1
Fork 0
migration-helper/source/migration-helper.ts

52 lines
1.5 KiB
TypeScript
Raw Normal View History

2022-03-03 13:40:38 +00:00
/**
* A {@link Migration} contains a target version and a migrate function.
*
* The version is used to determine whether the migration has yet to be applied
* or if it needs to be skipped, see {@link SkipMigrationFn} for details.
*
* The migrate function should take the data you pass through {@link migrate}
* and modify it to your needs.
*/
2023-05-08 10:23:28 +00:00
export type Migration<V, A = any, B = any> = {
2022-03-03 13:40:38 +00:00
version: V;
2023-05-08 10:23:28 +00:00
migrate: (data: A) => Promise<B>;
2022-03-03 13:40:38 +00:00
};
/**
* A function that determines if a {@link Migration} should be skipped.
*
* The first argument will be the version of the current {@link Migration} being
* tested, while the second argument will be the version passed into
* {@link migrate}.
*
2022-03-03 21:17:04 +00:00
* If left undefined, `a <= b` will be used. This works for {@link Date dates},
2022-03-03 13:40:38 +00:00
* {@link Number numbers} and {@link String strings}. So if you want to use a
* different type for versioning you should create your own function.
*/
export type SkipMigrationFn<V> = (a: V, b: V) => boolean;
/**
* Migrate some data to the specified version.
*
* See {@link Migration} and {@link SkipMigrationFn} for details on creating
* migrations and a custom skip function.
*/
export async function migrate<V>(
data: unknown,
version: V,
migrations: Array<Migration<V>>,
2022-03-03 21:17:04 +00:00
skip: SkipMigrationFn<V> = (a, b) => a <= b,
2022-03-03 13:40:38 +00:00
): Promise<unknown> {
let migratedData = data;
for (const migration of migrations) {
if (skip(migration.version, version)) {
continue;
}
2022-03-03 14:01:06 +00:00
migratedData = await migration.migrate(migratedData);
2022-03-03 13:40:38 +00:00
}
return migratedData;
}