From 79f9ef2481886a700b59bda255f31d41c34b2343 Mon Sep 17 00:00:00 2001 From: Elliot DeNolf Date: Thu, 14 Sep 2023 14:23:17 -0400 Subject: [PATCH] chore: migration improvements (#3335) * chore: better migrationDir handling * chore: add .migrations to gitignore * chore: migration cli debugging * docs: stub out each migration command --- .gitignore | 1 + .migrations/drizzle-snapshot.json | 935 ------------------ .vscode/launch.json | 42 +- docs/database/overview.mdx | 81 ++ packages/db-mongodb/src/index.ts | 2 +- packages/db-postgres/src/index.ts | 1 + packages/payload/src/bin/index.ts | 9 +- packages/payload/src/bin/migrate.ts | 24 +- .../payload/src/database/createAdapter.ts | 4 +- .../src/database/migrations/migrateDown.ts | 6 +- .../src/database/migrations/migrateReset.ts | 4 +- .../src/database/migrations/migrateStatus.ts | 5 + .../database/migrations/readMigrationFiles.ts | 7 +- 13 files changed, 155 insertions(+), 966 deletions(-) delete mode 100644 .migrations/drizzle-snapshot.json diff --git a/.gitignore b/.gitignore index c0253c0ca..267459bd1 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ dist .idea test-results .devcontainer +.migrations # Created by https://www.toptal.com/developers/gitignore/api/node,macos,windows,webstorm,sublimetext,visualstudiocode # Edit at https://www.toptal.com/developers/gitignore?templates=node,macos,windows,webstorm,sublimetext,visualstudiocode diff --git a/.migrations/drizzle-snapshot.json b/.migrations/drizzle-snapshot.json deleted file mode 100644 index 0828d88da..000000000 --- a/.migrations/drizzle-snapshot.json +++ /dev/null @@ -1,935 +0,0 @@ -{ - "id": "4ae32e6a-885c-4034-ac10-923edac1ff6b", - "prevId": "00000000-0000-0000-0000-000000000000", - "version": "5", - "dialect": "pg", - "tables": { - "posts_my_array_my_sub_array": { - "name": "posts_my_array_my_sub_array", - "schema": "", - "columns": { - "_order": { - "name": "_order", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "_parent_id": { - "name": "_parent_id", - "type": "varchar", - "primaryKey": false, - "notNull": true - }, - "id": { - "name": "id", - "type": "varchar", - "primaryKey": true, - "notNull": true - }, - "sub_sub_field": { - "name": "sub_sub_field", - "type": "varchar", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "posts_my_array_my_sub_array__parent_id_posts_my_array_id_fk": { - "name": "posts_my_array_my_sub_array__parent_id_posts_my_array_id_fk", - "tableFrom": "posts_my_array_my_sub_array", - "tableTo": "posts_my_array", - "columnsFrom": [ - "_parent_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "posts_my_array": { - "name": "posts_my_array", - "schema": "", - "columns": { - "_order": { - "name": "_order", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "_parent_id": { - "name": "_parent_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "id": { - "name": "id", - "type": "varchar", - "primaryKey": true, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "posts_my_array__parent_id_posts_id_fk": { - "name": "posts_my_array__parent_id_posts_id_fk", - "tableFrom": "posts_my_array", - "tableTo": "posts", - "columnsFrom": [ - "_parent_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "posts_my_array_locales": { - "name": "posts_my_array_locales", - "schema": "", - "columns": { - "sub_field": { - "name": "sub_field", - "type": "varchar", - "primaryKey": false, - "notNull": false - }, - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "_locale": { - "name": "_locale", - "type": "_locales", - "primaryKey": false, - "notNull": true - }, - "_parent_id": { - "name": "_parent_id", - "type": "varchar", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "posts_my_array_locales__parent_id_posts_my_array_id_fk": { - "name": "posts_my_array_locales__parent_id_posts_my_array_id_fk", - "tableFrom": "posts_my_array_locales", - "tableTo": "posts_my_array", - "columnsFrom": [ - "_parent_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "posts_block1": { - "name": "posts_block1", - "schema": "", - "columns": { - "_order": { - "name": "_order", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "_path": { - "name": "_path", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "_parent_id": { - "name": "_parent_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "id": { - "name": "id", - "type": "varchar", - "primaryKey": true, - "notNull": true - }, - "non_localized_text": { - "name": "non_localized_text", - "type": "varchar", - "primaryKey": false, - "notNull": false - }, - "block_name": { - "name": "block_name", - "type": "varchar", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "posts_block1__parent_id_posts_id_fk": { - "name": "posts_block1__parent_id_posts_id_fk", - "tableFrom": "posts_block1", - "tableTo": "posts", - "columnsFrom": [ - "_parent_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "posts_block1_locales": { - "name": "posts_block1_locales", - "schema": "", - "columns": { - "localized_text": { - "name": "localized_text", - "type": "varchar", - "primaryKey": false, - "notNull": false - }, - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "_locale": { - "name": "_locale", - "type": "_locales", - "primaryKey": false, - "notNull": true - }, - "_parent_id": { - "name": "_parent_id", - "type": "varchar", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "posts_block1_locales__parent_id_posts_block1_id_fk": { - "name": "posts_block1_locales__parent_id_posts_block1_id_fk", - "tableFrom": "posts_block1_locales", - "tableTo": "posts_block1", - "columnsFrom": [ - "_parent_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "posts_block2_block_array": { - "name": "posts_block2_block_array", - "schema": "", - "columns": { - "_order": { - "name": "_order", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "_parent_id": { - "name": "_parent_id", - "type": "varchar", - "primaryKey": false, - "notNull": true - }, - "id": { - "name": "id", - "type": "varchar", - "primaryKey": true, - "notNull": true - }, - "sub_block_array": { - "name": "sub_block_array", - "type": "varchar", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "posts_block2_block_array__parent_id_posts_block2_id_fk": { - "name": "posts_block2_block_array__parent_id_posts_block2_id_fk", - "tableFrom": "posts_block2_block_array", - "tableTo": "posts_block2", - "columnsFrom": [ - "_parent_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "posts_block2": { - "name": "posts_block2", - "schema": "", - "columns": { - "_order": { - "name": "_order", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "_path": { - "name": "_path", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "_parent_id": { - "name": "_parent_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "id": { - "name": "id", - "type": "varchar", - "primaryKey": true, - "notNull": true - }, - "number": { - "name": "number", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "block_name": { - "name": "block_name", - "type": "varchar", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "posts_block2__parent_id_posts_id_fk": { - "name": "posts_block2__parent_id_posts_id_fk", - "tableFrom": "posts_block2", - "tableTo": "posts", - "columnsFrom": [ - "_parent_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "posts_my_group_group_array": { - "name": "posts_my_group_group_array", - "schema": "", - "columns": { - "_order": { - "name": "_order", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "_parent_id": { - "name": "_parent_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "id": { - "name": "id", - "type": "varchar", - "primaryKey": true, - "notNull": true - }, - "group_array_text": { - "name": "group_array_text", - "type": "varchar", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "posts_my_group_group_array__parent_id_posts_id_fk": { - "name": "posts_my_group_group_array__parent_id_posts_id_fk", - "tableFrom": "posts_my_group_group_array", - "tableTo": "posts", - "columnsFrom": [ - "_parent_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "posts": { - "name": "posts", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "my_group_sub_field": { - "name": "my_group_sub_field", - "type": "varchar", - "primaryKey": false, - "notNull": false - }, - "my_group_sub_group_sub_sub_field": { - "name": "my_group_sub_group_sub_sub_field", - "type": "varchar", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "posts_locales": { - "name": "posts_locales", - "schema": "", - "columns": { - "title": { - "name": "title", - "type": "varchar", - "primaryKey": false, - "notNull": false - }, - "number": { - "name": "number", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "my_group_sub_field_localized": { - "name": "my_group_sub_field_localized", - "type": "varchar", - "primaryKey": false, - "notNull": false - }, - "my_group_sub_group_sub_sub_field_localized": { - "name": "my_group_sub_group_sub_sub_field_localized", - "type": "varchar", - "primaryKey": false, - "notNull": false - }, - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "_locale": { - "name": "_locale", - "type": "_locales", - "primaryKey": false, - "notNull": true - }, - "_parent_id": { - "name": "_parent_id", - "type": "integer", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "posts_locales__parent_id_posts_id_fk": { - "name": "posts_locales__parent_id_posts_id_fk", - "tableFrom": "posts_locales", - "tableTo": "posts", - "columnsFrom": [ - "_parent_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "posts_relationships": { - "name": "posts_relationships", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "parent_id": { - "name": "parent_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "path": { - "name": "path", - "type": "varchar", - "primaryKey": false, - "notNull": true - }, - "order": { - "name": "order", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "pages_id": { - "name": "pages_id", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "people_id": { - "name": "people_id", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "posts_id": { - "name": "posts_id", - "type": "integer", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "posts_relationships_parent_id_posts_id_fk": { - "name": "posts_relationships_parent_id_posts_id_fk", - "tableFrom": "posts_relationships", - "tableTo": "posts", - "columnsFrom": [ - "parent_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "posts_relationships_pages_id_pages_id_fk": { - "name": "posts_relationships_pages_id_pages_id_fk", - "tableFrom": "posts_relationships", - "tableTo": "pages", - "columnsFrom": [ - "pages_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "posts_relationships_people_id_people_id_fk": { - "name": "posts_relationships_people_id_people_id_fk", - "tableFrom": "posts_relationships", - "tableTo": "people", - "columnsFrom": [ - "people_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "posts_relationships_posts_id_posts_id_fk": { - "name": "posts_relationships_posts_id_posts_id_fk", - "tableFrom": "posts_relationships", - "tableTo": "posts", - "columnsFrom": [ - "posts_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "pages": { - "name": "pages", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "slug": { - "name": "slug", - "type": "varchar", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "people": { - "name": "people", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "full_name": { - "name": "full_name", - "type": "varchar", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "users": { - "name": "users", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "email": { - "name": "email", - "type": "varchar", - "primaryKey": false, - "notNull": false - }, - "reset_password_token": { - "name": "reset_password_token", - "type": "varchar", - "primaryKey": false, - "notNull": false - }, - "salt": { - "name": "salt", - "type": "varchar", - "primaryKey": false, - "notNull": false - }, - "hash": { - "name": "hash", - "type": "varchar", - "primaryKey": false, - "notNull": false - }, - "login_attempts": { - "name": "login_attempts", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "email_idx": { - "name": "email_idx", - "columns": [ - "email" - ], - "isUnique": true - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "payload_preferences": { - "name": "payload_preferences", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "key": { - "name": "key", - "type": "varchar", - "primaryKey": false, - "notNull": false - }, - "value": { - "name": "value", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "payload_preferences_relationships": { - "name": "payload_preferences_relationships", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "parent_id": { - "name": "parent_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "path": { - "name": "path", - "type": "varchar", - "primaryKey": false, - "notNull": true - }, - "order": { - "name": "order", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "users_id": { - "name": "users_id", - "type": "integer", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "payload_preferences_relationships_parent_id_payload_preferences_id_fk": { - "name": "payload_preferences_relationships_parent_id_payload_preferences_id_fk", - "tableFrom": "payload_preferences_relationships", - "tableTo": "payload_preferences", - "columnsFrom": [ - "parent_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "payload_preferences_relationships_users_id_users_id_fk": { - "name": "payload_preferences_relationships_users_id_users_id_fk", - "tableFrom": "payload_preferences_relationships", - "tableTo": "users", - "columnsFrom": [ - "users_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "payload_migrations": { - "name": "payload_migrations", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "serial", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "varchar", - "primaryKey": false, - "notNull": false - }, - "batch": { - "name": "batch", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "schema": { - "name": "schema", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - } - }, - "enums": { - "_locales": { - "name": "_locales", - "values": { - "en": "en", - "es": "es" - } - } - }, - "schemas": {}, - "_meta": { - "schemas": {}, - "tables": {}, - "columns": {} - } -} diff --git a/.vscode/launch.json b/.vscode/launch.json index 6cd7d7fae..f6a20bf1c 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -31,10 +31,11 @@ "type": "node-terminal" }, { - "command": "ts-node src/bin/migrate.ts migrate", + "command": "ts-node ./packages/payload/src/bin/index.ts migrate", "env": { "PAYLOAD_CONFIG_PATH": "test/migrations-cli/config.ts", - "PAYLOAD_DATABASE": "postgres" + "PAYLOAD_DATABASE": "mongoose", + "DISABLE_SWC": "true" // SWC messes up debugging the bin scripts // "PAYLOAD_DROP_DATABASE": "true", }, "name": "Migrate CLI - migrate", @@ -43,10 +44,11 @@ "type": "node-terminal" }, { - "command": "ts-node src/bin/migrate.ts migrate:status", + "command": "ts-node ./packages/payload/src/bin/index.ts migrate:status", "env": { "PAYLOAD_CONFIG_PATH": "test/migrations-cli/config.ts", - "PAYLOAD_DATABASE": "postgres" + "PAYLOAD_DATABASE": "mongoose", + "DISABLE_SWC": "true" // SWC messes up debugging the bin scripts // "PAYLOAD_DROP_DATABASE": "true", }, "name": "Migrate CLI - status", @@ -55,11 +57,11 @@ "type": "node-terminal" }, { - "command": "ts-node src/bin/migrate.ts migrate:create yass", + "command": "ts-node ./packages/payload/src/bin/index.ts migrate:create yass", "env": { - // "PAYLOAD_CONFIG_PATH": "test/migrations-cli/config.ts", - "PAYLOAD_CONFIG_PATH": "test/postgres/config.ts", - "PAYLOAD_DATABASE": "postgres" + "PAYLOAD_CONFIG_PATH": "test/migrations-cli/config.ts", + "PAYLOAD_DATABASE": "mongoose", + "DISABLE_SWC": "true" // SWC messes up debugging the bin scripts // "PAYLOAD_DROP_DATABASE": "true", }, "name": "Migrate CLI - create", @@ -68,11 +70,11 @@ "type": "node-terminal" }, { - "command": "ts-node src/bin/migrate.ts migrate:down", + "command": "ts-node ./packages/payload/src/bin/index.ts migrate:down", "env": { - // "PAYLOAD_CONFIG_PATH": "test/migrations-cli/config.ts", - "PAYLOAD_CONFIG_PATH": "test/postgres/config.ts", - "PAYLOAD_DATABASE": "postgres" + "PAYLOAD_CONFIG_PATH": "test/migrations-cli/config.ts", + "PAYLOAD_DATABASE": "mongoose", + "DISABLE_SWC": "true" // SWC messes up debugging the bin scripts // "PAYLOAD_DROP_DATABASE": "true", }, "name": "Migrate CLI - down", @@ -81,11 +83,11 @@ "type": "node-terminal" }, { - "command": "ts-node src/bin/migrate.ts migrate:reset", + "command": "ts-node ./packages/payload/src/bin/index.ts migrate:reset", "env": { - // "PAYLOAD_CONFIG_PATH": "test/migrations-cli/config.ts", - "PAYLOAD_CONFIG_PATH": "test/postgres/config.ts", - "PAYLOAD_DATABASE": "postgres" + "PAYLOAD_CONFIG_PATH": "test/migrations-cli/config.ts", + "PAYLOAD_DATABASE": "mongoose", + "DISABLE_SWC": "true" // SWC messes up debugging the bin scripts // "PAYLOAD_DROP_DATABASE": "true", }, "name": "Migrate CLI - reset", @@ -94,11 +96,11 @@ "type": "node-terminal" }, { - "command": "ts-node src/bin/migrate.ts migrate:refresh", + "command": "ts-node ./packages/payload/src/bin/index.ts migrate:refresh", "env": { - // "PAYLOAD_CONFIG_PATH": "test/migrations-cli/config.ts", - "PAYLOAD_CONFIG_PATH": "test/postgres/config.ts", - "PAYLOAD_DATABASE": "postgres" + "PAYLOAD_CONFIG_PATH": "test/migrations-cli/config.ts", + "PAYLOAD_DATABASE": "mongoose", + "DISABLE_SWC": "true" // SWC messes up debugging the bin scripts // "PAYLOAD_DROP_DATABASE": "true", }, "name": "Migrate CLI - refresh", diff --git a/docs/database/overview.mdx b/docs/database/overview.mdx index d6e18c653..d0c90d572 100644 --- a/docs/database/overview.mdx +++ b/docs/database/overview.mdx @@ -84,3 +84,84 @@ The following functions can be used for managing transactions: `payload.db.rollbackTransaction` - Takes the identifier for the transaction, discards any changes. ## Migrations + +Payload's migrations are accessible via the `payload` command in your project directory. + +Available commands: + +- [`migrate`](#migrate) - Performs any migrations that have not yet been run. +- [`migrate:status`](#migrate:status) - Checks the status of migrations. +- [`migrate:down`](#migrate:down) - Reverts the last batch of migrations. +- [`migrate:refresh`](#migrate:refresh) - Rolls back all migrations and runs them again. +- [`migrate:reset`](#migrate:reset) - Rolls back all migrations. +- [`migrate:create`](#migrate:create) - Creates new migration file in migrations directory. + +### Migrate + +The `migrate` command will run any migrations that have not yet been run. This command is run automatically when you start your Payload server. + +`payload migrate` + +Example output: + +```text +TODO: add example output +``` + +### Migrate:status + +The `migrate:status` command will check the status of migrations. + +`payload migrate:status` + +Example output: + +```text +``` + +### Migrate:down + +Revert the last batch of migrations. + +`payload migrate:down` + +Example output: + +```text +``` + +### Migrate:refresh + +Roll back all migrations and run them again. + +`payload migrate:refresh` + +Example output: + +```text +``` + +### Migrate:reset + +Roll back all migrations. + +`payload migrate:reset` + +Example output: + +```text +``` + +### Migrate:create + +Create a new migration file in the migrations directory. + +`payload migrate:create` + +Example output: + +```text +Migration created at .migrations/20230912_131129_first.ts +``` + + diff --git a/packages/db-mongodb/src/index.ts b/packages/db-mongodb/src/index.ts index 7cdf0539d..8133eb28e 100644 --- a/packages/db-mongodb/src/index.ts +++ b/packages/db-mongodb/src/index.ts @@ -92,7 +92,7 @@ export function mongooseAdapter({ findVersions, globals: undefined, init, - migrationDir, + ...(migrationDir && { migrationDir }), mongoMemoryServer: undefined, payload, queryDrafts, diff --git a/packages/db-postgres/src/index.ts b/packages/db-postgres/src/index.ts index bbf461596..a59a0574a 100644 --- a/packages/db-postgres/src/index.ts +++ b/packages/db-postgres/src/index.ts @@ -45,6 +45,7 @@ export function postgresAdapter(args: Args): PostgresAdapterResult { beginTransaction, rollbackTransaction, commitTransaction, + ...(args.migrationDir && { migrationDir: args.migrationDir }), queryDrafts, findOne, find, diff --git a/packages/payload/src/bin/index.ts b/packages/payload/src/bin/index.ts index d2c4cbf29..e7f3bcd85 100755 --- a/packages/payload/src/bin/index.ts +++ b/packages/payload/src/bin/index.ts @@ -36,9 +36,12 @@ if (tsConfig?.config?.compilerOptions?.paths) { } } -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore - bad @swc/register types -swcRegister(swcOptions) +// Allow disabling SWC for debugging +if (process.env.DISABLE_SWC !== 'true') { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore - bad @swc/register types + swcRegister(swcOptions) +} const { build } = require('./build') diff --git a/packages/payload/src/bin/migrate.ts b/packages/payload/src/bin/migrate.ts index 873322bd6..11c7404cf 100644 --- a/packages/payload/src/bin/migrate.ts +++ b/packages/payload/src/bin/migrate.ts @@ -1,5 +1,17 @@ import payload from '..' +const availableCommands = [ + 'migrate', + 'migrate:create', + 'migrate:down', + 'migrate:refresh', + 'migrate:reset', + 'migrate:status', + 'migration:fresh', +] + +const availableCommandsMsg = `Available commands: ${availableCommands.join(', ')}` + export const migrate = async (args: string[]): Promise => { // Barebones instance to access database adapter await payload.init({ @@ -13,6 +25,13 @@ export const migrate = async (args: string[]): Promise => { throw new Error('No database adapter found') } + if (!args.length) { + payload.logger.error({ + msg: `No migration command provided. ${availableCommandsMsg}`, + }) + process.exit(1) + } + switch (args[0]) { case 'migrate': await adapter.migrate() @@ -41,7 +60,10 @@ export const migrate = async (args: string[]): Promise => { break default: - throw new Error(`Unknown migration command: ${args[0]}`) + payload.logger.error({ + msg: `Unknown migration command: ${args[0]}. ${availableCommandsMsg}`, + }) + process.exit(1) } } diff --git a/packages/payload/src/database/createAdapter.ts b/packages/payload/src/database/createAdapter.ts index eb92990bd..3c07fd531 100644 --- a/packages/payload/src/database/createAdapter.ts +++ b/packages/payload/src/database/createAdapter.ts @@ -55,11 +55,13 @@ export function createDatabaseAdapter( migrateFresh: async () => null, migrateRefresh, migrateReset, - migrateStatus, rollbackTransaction, transaction, ...args, + + // Ensure migrationDir is set + migrationDir: args.migrationDir || '.migrations', } as T } diff --git a/packages/payload/src/database/migrations/migrateDown.ts b/packages/payload/src/database/migrations/migrateDown.ts index a93784aa4..56e404d86 100644 --- a/packages/payload/src/database/migrations/migrateDown.ts +++ b/packages/payload/src/database/migrations/migrateDown.ts @@ -34,10 +34,12 @@ export async function migrateDown(this: DatabaseAdapter): Promise { let transactionID try { - payload.logger.info({ msg: `Migrating: ${migrationFile.name}` }) + payload.logger.info({ msg: `Migrating down: ${migrationFile.name}` }) transactionID = await this.beginTransaction() await migrationFile.down({ payload }) - payload.logger.info({ msg: `Migrated: ${migrationFile.name} (${Date.now() - start}ms)` }) + payload.logger.info({ + msg: `Migrated down: ${migrationFile.name} (${Date.now() - start}ms)`, + }) // Waiting for implementation here await payload.delete({ collection: 'payload-migrations', diff --git a/packages/payload/src/database/migrations/migrateReset.ts b/packages/payload/src/database/migrations/migrateReset.ts index 9487a1942..f28bb2993 100644 --- a/packages/payload/src/database/migrations/migrateReset.ts +++ b/packages/payload/src/database/migrations/migrateReset.ts @@ -25,7 +25,7 @@ export async function migrateReset(this: DatabaseAdapter): Promise { (existing) => existing.name === migration.name, ) if (existingMigration) { - payload.logger.info({ msg: `Migrating: ${migration.name}` }) + payload.logger.info({ msg: `Migrating down: ${migration.name}` }) try { const start = Date.now() transactionID = await this.beginTransaction() @@ -40,7 +40,7 @@ export async function migrateReset(this: DatabaseAdapter): Promise { }, }) await this.commitTransaction(transactionID) - payload.logger.info({ msg: `Migrated: ${migration.name} (${Date.now() - start}ms)` }) + payload.logger.info({ msg: `Migrated down: ${migration.name} (${Date.now() - start}ms)` }) } catch (err: unknown) { await this.rollbackTransaction(transactionID) payload.logger.error({ err, msg: `Error running migration ${migration.name}` }) diff --git a/packages/payload/src/database/migrations/migrateStatus.ts b/packages/payload/src/database/migrations/migrateStatus.ts index aa9e95062..7969c16a8 100644 --- a/packages/payload/src/database/migrations/migrateStatus.ts +++ b/packages/payload/src/database/migrations/migrateStatus.ts @@ -8,6 +8,11 @@ import { readMigrationFiles } from './readMigrationFiles' export async function migrateStatus(this: DatabaseAdapter): Promise { const { payload } = this const migrationFiles = await readMigrationFiles({ payload }) + + payload.logger.debug({ + msg: `Found ${migrationFiles.length} migration files.`, + }) + const { existingMigrations } = await getMigrations({ payload }) if (!migrationFiles.length) { diff --git a/packages/payload/src/database/migrations/readMigrationFiles.ts b/packages/payload/src/database/migrations/readMigrationFiles.ts index 14465cd33..0fe06f397 100644 --- a/packages/payload/src/database/migrations/readMigrationFiles.ts +++ b/packages/payload/src/database/migrations/readMigrationFiles.ts @@ -12,7 +12,12 @@ export const readMigrationFiles = async ({ }: { payload: Payload }): Promise => { - if (!fs.existsSync(payload.db.migrationDir)) return [] + if (!fs.existsSync(payload.db.migrationDir)) { + payload.logger.debug({ + msg: `No migration directory found at ${payload.db.migrationDir}`, + }) + return [] + } const files = fs .readdirSync(payload.db.migrationDir)