import { setupActions } from "../../actions/setupActions"; import { EmVer } from "../../emverLite/mod"; import { GenericManifest } from "../../manifest/ManifestTypes"; import { ExpectedExports } from "../../types"; import { once } from "../../util/once"; import { Migration } from "./Migration"; export class Migrations { private constructor( readonly manifest: GenericManifest, readonly migrations: Array>, ) {} private sortedMigrations = once(() => { const migrationsAsVersions = (this.migrations as Array>).map( (x) => [EmVer.parse(x.options.version), x] as const, ); migrationsAsVersions.sort((a, b) => a[0].compareForSort(b[0])); return migrationsAsVersions; }); private currentVersion = once(() => EmVer.parse(this.manifest.version)); static of>>( manifest: GenericManifest, ...migrations: EnsureUniqueId ) { return new Migrations(manifest, migrations as Array>); } async init({ effects, previousVersion, }: Parameters[0]) { if (!!previousVersion) { const previousVersionEmVer = EmVer.parse(previousVersion); for (const [_, migration] of this.sortedMigrations() .filter((x) => x[0].greaterThan(previousVersionEmVer)) .filter((x) => x[0].lessThanOrEqual(this.currentVersion()))) { await migration.up({ effects }); } } } async uninit({ effects, nextVersion, }: Parameters[0]) { if (!!nextVersion) { const nextVersionEmVer = EmVer.parse(nextVersion); const reversed = [...this.sortedMigrations()].reverse(); for (const [_, migration] of reversed .filter((x) => x[0].greaterThan(nextVersionEmVer)) .filter((x) => x[0].lessThanOrEqual(this.currentVersion()))) { await migration.down({ effects }); } } } } export function setupMigrations>>( manifest: GenericManifest, ...migrations: EnsureUniqueId ) { return Migrations.of(manifest, ...migrations); } // prettier-ignore export type EnsureUniqueId = B extends [] ? A : B extends [Migration, ...infer Rest] ? ( id extends ids ? "One of the ids are not unique"[] : EnsureUniqueId ) : "There exists a migration that is not a Migration"[]