feat: conditionally use transactions
This commit is contained in:
61
.vscode/launch.json
vendored
61
.vscode/launch.json
vendored
@@ -33,54 +33,39 @@
|
|||||||
"cwd": "${workspaceFolder}"
|
"cwd": "${workspaceFolder}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "node",
|
"type": "node-terminal",
|
||||||
"request": "launch",
|
"command": "ts-node src/bin/migrate.ts migrate",
|
||||||
"name": "Migrate CLI - create",
|
|
||||||
"runtimeArgs": [
|
|
||||||
"-r",
|
|
||||||
"ts-node/register"
|
|
||||||
],
|
|
||||||
"args": [
|
|
||||||
"src/bin/migrate.ts",
|
|
||||||
"migrate:create",
|
|
||||||
"second"
|
|
||||||
],
|
|
||||||
"env": {
|
|
||||||
"PAYLOAD_CONFIG_PATH": "test/migrations-cli/config.ts"
|
|
||||||
},
|
|
||||||
"outputCapture": "std",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "node",
|
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"name": "Migrate CLI - migrate",
|
"name": "Migrate CLI - migrate",
|
||||||
"runtimeArgs": [
|
|
||||||
"-r",
|
|
||||||
"ts-node/register"
|
|
||||||
],
|
|
||||||
"args": [
|
|
||||||
"src/bin/migrate.ts",
|
|
||||||
"migrate",
|
|
||||||
],
|
|
||||||
"env": {
|
"env": {
|
||||||
"PAYLOAD_CONFIG_PATH": "test/migrations-cli/config.ts"
|
"PAYLOAD_CONFIG_PATH": "test/migrations-cli/config.ts",
|
||||||
|
"PAYLOAD_DATABASE": "postgres",
|
||||||
|
"PAYLOAD_DROP_DATABASE": "true",
|
||||||
},
|
},
|
||||||
"outputCapture": "std",
|
"outputCapture": "std",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "node",
|
"type": "node-terminal",
|
||||||
|
"command": "ts-node src/bin/migrate.ts migrate:status",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"name": "Migrate CLI - status",
|
"name": "Migrate CLI - status",
|
||||||
"runtimeArgs": [
|
|
||||||
"-r",
|
|
||||||
"ts-node/register"
|
|
||||||
],
|
|
||||||
"args": [
|
|
||||||
"src/bin/migrate.ts",
|
|
||||||
"migrate:status",
|
|
||||||
],
|
|
||||||
"env": {
|
"env": {
|
||||||
"PAYLOAD_CONFIG_PATH": "test/migrations-cli/config.ts"
|
"PAYLOAD_CONFIG_PATH": "test/migrations-cli/config.ts",
|
||||||
|
"PAYLOAD_DATABASE": "postgres",
|
||||||
|
"PAYLOAD_DROP_DATABASE": "true",
|
||||||
|
},
|
||||||
|
"outputCapture": "std",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "node-terminal",
|
||||||
|
"command": "ts-node src/bin/migrate.ts migrate:create yass",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "Migrate CLI - create",
|
||||||
|
"env": {
|
||||||
|
// "PAYLOAD_CONFIG_PATH": "test/migrations-cli/config.ts",
|
||||||
|
"PAYLOAD_CONFIG_PATH": "test/postgres/config.ts",
|
||||||
|
"PAYLOAD_DATABASE": "postgres",
|
||||||
|
// "PAYLOAD_DROP_DATABASE": "true",
|
||||||
},
|
},
|
||||||
"outputCapture": "std",
|
"outputCapture": "std",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -12,11 +12,11 @@ import prompts from 'prompts';
|
|||||||
import { buildTable } from './schema/build';
|
import { buildTable } from './schema/build';
|
||||||
import type { GenericEnum, GenericRelation, GenericTable, PostgresAdapter } from './types';
|
import type { GenericEnum, GenericRelation, GenericTable, PostgresAdapter } from './types';
|
||||||
|
|
||||||
const migrationTemplate = `
|
const migrationTemplate = (upSQL?: string) => `
|
||||||
import payload, { Payload } from 'payload';
|
import payload, { Payload } from 'payload';
|
||||||
|
|
||||||
export async function up(payload: Payload): Promise<void> {
|
export async function up(payload: Payload): Promise<void> {
|
||||||
await payload.db.db.execute(\`{{SQL}}\`);
|
${upSQL ? `await payload.db.db.execute(\`${upSQL}\`);` : '// Migration code'}
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function down(payload: Payload): Promise<void> {
|
export async function down(payload: Payload): Promise<void> {
|
||||||
@@ -50,7 +50,7 @@ export const createMigration: CreateMigration = async function createMigration(
|
|||||||
const drizzleJsonBefore = generateDrizzleJson(JSON.parse(snapshotJSON));
|
const drizzleJsonBefore = generateDrizzleJson(JSON.parse(snapshotJSON));
|
||||||
const drizzleJsonAfter = generateDrizzleJson(this.schema, drizzleJsonBefore.id);
|
const drizzleJsonAfter = generateDrizzleJson(this.schema, drizzleJsonBefore.id);
|
||||||
const sqlStatements = await generateMigration(drizzleJsonBefore, drizzleJsonAfter);
|
const sqlStatements = await generateMigration(drizzleJsonBefore, drizzleJsonAfter);
|
||||||
fs.writeFileSync(filePath, migrationTemplate.replace('{{SQL}}', sqlStatements.join('\n')));
|
fs.writeFileSync(filePath, migrationTemplate(sqlStatements.length ? sqlStatements?.join('\n') : undefined));
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// Get the most recent migration schema from the file system
|
// Get the most recent migration schema from the file system
|
||||||
|
|||||||
@@ -7,9 +7,13 @@ import { migrateStatus } from './migrations/migrateStatus';
|
|||||||
import { migrateDown } from './migrations/migrateDown';
|
import { migrateDown } from './migrations/migrateDown';
|
||||||
import { migrateRefresh } from './migrations/migrateRefresh';
|
import { migrateRefresh } from './migrations/migrateRefresh';
|
||||||
import { migrateReset } from './migrations/migrateReset';
|
import { migrateReset } from './migrations/migrateReset';
|
||||||
import { DatabaseAdapter } from './types';
|
import { BeginTransaction, CommitTransaction, DatabaseAdapter, RollbackTransaction } from './types';
|
||||||
import { createMigration } from './migrations/createMigration';
|
import { createMigration } from './migrations/createMigration';
|
||||||
|
|
||||||
|
const beginTransaction: BeginTransaction = async () => null;
|
||||||
|
const rollbackTransaction: RollbackTransaction = async () => null;
|
||||||
|
const commitTransaction: CommitTransaction = async () => null;
|
||||||
|
|
||||||
export function createDatabaseAdapter<T extends DatabaseAdapter>(args: MarkOptional<T,
|
export function createDatabaseAdapter<T extends DatabaseAdapter>(args: MarkOptional<T,
|
||||||
| 'transaction'
|
| 'transaction'
|
||||||
| 'migrate'
|
| 'migrate'
|
||||||
@@ -19,7 +23,8 @@ export function createDatabaseAdapter<T extends DatabaseAdapter>(args: MarkOptio
|
|||||||
| 'migrateRefresh'
|
| 'migrateRefresh'
|
||||||
| 'migrateReset'
|
| 'migrateReset'
|
||||||
| 'migrateFresh'
|
| 'migrateFresh'
|
||||||
| 'migrationDir'>): T {
|
| 'migrationDir'
|
||||||
|
>): T {
|
||||||
// Need to implement DB Webpack config extensions here
|
// Need to implement DB Webpack config extensions here
|
||||||
if (args.webpack) {
|
if (args.webpack) {
|
||||||
const existingWebpackConfig = args.payload.config.admin.webpack ? args.payload.config.admin.webpack : (webpackConfig) => webpackConfig;
|
const existingWebpackConfig = args.payload.config.admin.webpack ? args.payload.config.admin.webpack : (webpackConfig) => webpackConfig;
|
||||||
@@ -39,6 +44,12 @@ export function createDatabaseAdapter<T extends DatabaseAdapter>(args: MarkOptio
|
|||||||
migrateRefresh,
|
migrateRefresh,
|
||||||
migrateReset,
|
migrateReset,
|
||||||
migrateFresh: async () => null,
|
migrateFresh: async () => null,
|
||||||
|
|
||||||
|
// Default 'null' transaction functions
|
||||||
|
beginTransaction,
|
||||||
|
commitTransaction,
|
||||||
|
rollbackTransaction,
|
||||||
|
|
||||||
...args,
|
...args,
|
||||||
} as T;
|
} as T;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export async function getMigrations({
|
|||||||
const existingMigrations = migrationQuery.docs as unknown as MigrationData[];
|
const existingMigrations = migrationQuery.docs as unknown as MigrationData[];
|
||||||
|
|
||||||
// Get the highest batch number from existing migrations
|
// Get the highest batch number from existing migrations
|
||||||
const latestBatch = existingMigrations?.[0]?.batch || 0;
|
const latestBatch = Number(existingMigrations?.[0]?.batch) || 0;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
existingMigrations,
|
existingMigrations,
|
||||||
|
|||||||
@@ -21,10 +21,11 @@ export async function migrate(this: DatabaseAdapter): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const start = Date.now();
|
const start = Date.now();
|
||||||
let transactionID;
|
let transactionID: string | number | undefined;
|
||||||
|
|
||||||
|
payload.logger.info({ msg: `Migrating: ${migration.name}` });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
payload.logger.info({ msg: `Migrating: ${migration.name}` });
|
|
||||||
transactionID = await this.beginTransaction();
|
transactionID = await this.beginTransaction();
|
||||||
await migration.up({ payload });
|
await migration.up({ payload });
|
||||||
payload.logger.info({ msg: `Migrated: ${migration.name} (${Date.now() - start}ms)` });
|
payload.logger.info({ msg: `Migrated: ${migration.name} (${Date.now() - start}ms)` });
|
||||||
@@ -34,9 +35,7 @@ export async function migrate(this: DatabaseAdapter): Promise<void> {
|
|||||||
name: migration.name,
|
name: migration.name,
|
||||||
batch: newBatch,
|
batch: newBatch,
|
||||||
},
|
},
|
||||||
req: {
|
...(transactionID && { req: { transactionID } as PayloadRequest }),
|
||||||
transactionID,
|
|
||||||
} as PayloadRequest,
|
|
||||||
});
|
});
|
||||||
await this.commitTransaction(transactionID);
|
await this.commitTransaction(transactionID);
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ export const readMigrationFiles = async ({
|
|||||||
const files = fs
|
const files = fs
|
||||||
.readdirSync(payload.db.migrationDir)
|
.readdirSync(payload.db.migrationDir)
|
||||||
.sort()
|
.sort()
|
||||||
|
.filter((f) => f.endsWith('.ts'))
|
||||||
.map((file) => {
|
.map((file) => {
|
||||||
return path.resolve(payload.db.migrationDir, file);
|
return path.resolve(payload.db.migrationDir, file);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,52 +1,3 @@
|
|||||||
/* eslint-disable no-console */
|
import { buildConfigWithDefaults } from '../buildConfigWithDefaults';
|
||||||
|
|
||||||
import path from 'path';
|
export default buildConfigWithDefaults({});
|
||||||
import { buildConfig } from '../buildConfig';
|
|
||||||
import { CollectionConfig } from '../../types';
|
|
||||||
import { mongooseAdapter } from '../../src/mongoose';
|
|
||||||
import payload from '../../src';
|
|
||||||
|
|
||||||
const Users: CollectionConfig = {
|
|
||||||
slug: 'users',
|
|
||||||
auth: true,
|
|
||||||
fields: [
|
|
||||||
{
|
|
||||||
name: 'custom',
|
|
||||||
type: 'text',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'checkbox',
|
|
||||||
type: 'checkbox',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
// // @ts-expect-error partial
|
|
||||||
// const mockAdapter: DatabaseAdapter = {
|
|
||||||
// // payload: undefined,
|
|
||||||
// migrationDir: path.resolve(__dirname, '.migrations'),
|
|
||||||
// migrateStatus: async () => console.log('TODO: migrateStatus not implemented.'),
|
|
||||||
// createMigration: async (): Promise<void> =>
|
|
||||||
// console.log('TODO: createMigration not implemented.'),
|
|
||||||
// migrate: async (): Promise<void> => console.log('TODO: migrate not implemented.'),
|
|
||||||
// migrateDown: async (): Promise<void> =>
|
|
||||||
// console.log('TODO: migrateDown not implemented.'),
|
|
||||||
// migrateRefresh: async (): Promise<void> =>
|
|
||||||
// console.log('TODO: migrateRefresh not implemented.'),
|
|
||||||
// migrateReset: async (): Promise<void> =>
|
|
||||||
// console.log('TODO: migrateReset not implemented.'),
|
|
||||||
// migrateFresh: async (): Promise<void> =>
|
|
||||||
// console.log('TODO: migrateFresh not implemented.'),
|
|
||||||
// };
|
|
||||||
|
|
||||||
export default buildConfig({
|
|
||||||
serverURL: 'http://localhost:3000',
|
|
||||||
admin: {
|
|
||||||
user: Users.slug,
|
|
||||||
},
|
|
||||||
collections: [Users],
|
|
||||||
typescript: {
|
|
||||||
outputFile: path.resolve(__dirname, 'payload-types.ts'),
|
|
||||||
},
|
|
||||||
db: mongooseAdapter({ payload, url: 'mongodb://127.0.0.1:27017/migrations-cli-test' }),
|
|
||||||
});
|
|
||||||
|
|||||||
Reference in New Issue
Block a user