From f8e13f0d6679198a3dba74eaf70f76ccd23c18ff Mon Sep 17 00:00:00 2001 From: Joakim Carlstein Date: Tue, 19 Dec 2023 10:25:06 +0100 Subject: [PATCH] docs: add some basic documentation for the storage plugin api --- .../docs/reference/migration-types.mdx | 93 +++++++++++++++++++ .../docs/reference/storage-plugin-api.mdx | 86 +++++++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 docs/src/content/docs/reference/migration-types.mdx create mode 100644 docs/src/content/docs/reference/storage-plugin-api.mdx diff --git a/docs/src/content/docs/reference/migration-types.mdx b/docs/src/content/docs/reference/migration-types.mdx new file mode 100644 index 0000000..b47f5c0 --- /dev/null +++ b/docs/src/content/docs/reference/migration-types.mdx @@ -0,0 +1,93 @@ +--- +title: Migration Types +--- + +import Link from '@components/Link.astro'; + +These are common TypeScript types for migration files used by plugins. + +## `MigrationMetadata` + +```ts +type MigrationMetadata = { + /** + * The name of the migration file + * + * @example 20210901123456000_create_users_table.js + */ + name: string; + /** + * The directory where the migration file is located, relative to the current working directory + * + * @example migrations + */ + directory: string; + /** + * The full absolute path to the migration file + * + * @example /home/user/project/migrations/20210901123456000_create_users_table.js + */ + filePath: string; + /** + * The relative path to the migration file, relative to the current working directory + * + * @example migrations/20210901123456000_create_users_table.js + */ + relativeFilePath: string; + /** + * The current working directory (the same as process.cwd()) + */ + cwd: string; + /** + * The extension of the migration file, with a leading period + * + * @example .js + */ + extension: string; +}; +``` + +## `MigrationMetadataFinished` + +```ts +type MigrationMetadataFinished = MigrationMetadata & { + status: 'done' | 'failed' | 'skipped' | 'pending'; + /** + * The duration of the migration in milliseconds + */ + duration: number; + /** + * The error that occurred during the migration, if `status` is `"failed"` + */ + error?: Error; +}; +``` + +## `MigrationHistoryEntry` + +```ts +type MigrationHistoryEntry = { + /** + * The name of the migration. + * + * @example 20210901123456000_create_users_table.js + */ + name: string; + /** + * The date when the migration was executed. + */ + date: Date; + /** + * The status of the migration. + * + * As an entry is only added to the history after the migration has finished, this will always be either `"done"` or `"failed"`. + */ + status: 'done' | 'failed'; + /** + * The error that occurred during the migration, if `status` is `"failed"` + * + * This should be a plain object, as it is serialized when passed to the storage plugin's `onError` method. + */ + error?: Record; +}; +``` diff --git a/docs/src/content/docs/reference/storage-plugin-api.mdx b/docs/src/content/docs/reference/storage-plugin-api.mdx new file mode 100644 index 0000000..5840fe9 --- /dev/null +++ b/docs/src/content/docs/reference/storage-plugin-api.mdx @@ -0,0 +1,86 @@ +--- +title: Storage Plugin API +--- + +import Link from '@components/Link.astro'; + +When writing a storage plugin, you will need to implement the following interface: + +```ts +type EmigrateStorage = { + initializeStorage(): Promise; +}; +``` + +Where `Storage` is the following interface: + +```ts +type Storage = { + /** + * Acquire a lock on the given migrations. + * + * To best support concurrent migrations (e.g. when multiple services are deployed at the same time and want to migrate the same database) + * the plugin should try to lock all migrations at once (i.e. in a transaction) and ignore migrations that are already locked (or done). + * The successfully locked migrations should be returned and are the migrations that will be executed. + * + * If one of the migrations to lock is in a failed state, the plugin should throw an error to abort the migration attempt. + * + * @returns The migrations that were successfully locked. + */ + lock(migrations: MigrationMetadata[]): Promise; + /** + * The unlock method is called after all migrations have been executed or when the process is interrupted (e.g. by a SIGTERM or SIGINT signal). + * + * Depending on the plugin implementation, the unlock method is usually a no-op for already succeeded or failed migrations. + * + * @param migrations The previously successfully locked migrations that should now be unlocked. + */ + unlock(migrations: MigrationMetadata[]): Promise; + + /** + * Remove a migration from the history. + * + * This is used to remove a migration from the history which is needed for failed migrations to be re-executed. + * + * @param migration The migration that should be removed from the history. + */ + remove(migration: MigrationMetadata): Promise; + /** + * Get the history of previously executed migrations. + * + * For failed migrations, the error property should be set. + * Emigrate will not sort the history entries, so the plugin should return the entries in the order they were executed. + * The order doesn't affect the execution of migrations, but it does affect the order in which the history is displayed in the CLI. + * Migrations that have not yet been executed will always be run in alphabetical order. + * + * The history has two purposes: + * 1. To determine which migrations have already been executed. + * 2. To list the migration history in the CLI. + */ + getHistory(): AsyncIterable; + /** + * Called when a migration has been successfully executed. + * + * @param migration The name of the migration that should be marked as done. + */ + onSuccess(migration: MigrationMetadataFinished): Promise; + /** + * Called when a migration has failed. + * + * The passed error will be serialized so it's easily storable it in the history. + * If the original Error instance is needed it's available as the `error` property on the finished migration. + * + * @param migration The name of the migration that should be marked as failed. + * @param error The error that caused the migration to fail. Serialized for easy storage. + */ + onError(migration: MigrationMetadataFinished, error: SerializedError): Promise; + /** + * Called when the command is finished or aborted (e.g. by a SIGTERM or SIGINT signal). + * + * Use this to clean up any resources like database connections or file handles. + */ + end(): Promise; +}; +``` + +See the Migration Types page for more information about the `MigrationMetadata`, `MigrationMetadataFinished`, and `MigrationHistoryEntry` types.