diff --git a/packages/js/manifests/polywrap/scripts/templates/migrate-ts.mustache b/packages/js/manifests/polywrap/scripts/templates/migrate-ts.mustache index 7376923064..8817e13039 100644 --- a/packages/js/manifests/polywrap/scripts/templates/migrate-ts.mustache +++ b/packages/js/manifests/polywrap/scripts/templates/migrate-ts.mustache @@ -10,22 +10,8 @@ import { {{#latest}}{{type}}{{/latest}}Formats, latest{{#latest}}{{type}}{{/latest}}Format } from "."; - -{{#prevFormats}} -import { - migrate as migrate_{{tsVersion}}_to_{{#latest}}{{tsVersion}}{{/latest}} -} from "./migrators/{{version}}_to_{{#latest}}{{version}}{{/latest}}"; -{{/prevFormats}} - -type Migrator = { - [key in {{#latest}}{{type}}{{/latest}}Formats]?: (m: Any{{#latest}}{{type}}{{/latest}}) => {{#latest}}{{type}}{{/latest}}; -}; - -export const migrators: Migrator = { -{{#prevFormats}} - "{{version}}": migrate_{{tsVersion}}_to_{{#latest}}{{tsVersion}}{{/latest}}, -{{/prevFormats}} -}; +import { findShortestMigrationPath } from "../../migrations"; +import { migrators } from "./migrators"; export function migrate{{#latest}}{{type}}{{/latest}}( manifest: Any{{#latest}}{{type}}{{/latest}}, @@ -33,11 +19,6 @@ export function migrate{{#latest}}{{type}}{{/latest}}( ): {{#latest}}{{type}}{{/latest}} { let from = manifest.format as {{#latest}}{{type}}{{/latest}}Formats; - // HACK: Patch fix for backwards compatability - if(from === "0.1" && ("0.1.0" in migrators)) { - from = "0.1.0" as {{#latest}}{{type}}{{/latest}}Formats; - } - if (from === latest{{#latest}}{{type}}{{/latest}}Format) { return manifest as {{#latest}}{{type}}{{/latest}}; } @@ -46,17 +27,18 @@ export function migrate{{#latest}}{{type}}{{/latest}}( throw new Error(`Unrecognized {{#latest}}{{type}}{{/latest}}Format "${manifest.format}"`); } -{{#prevFormats.length}} - const migrator = migrators[from]; - if (!migrator) { + const migrationPath = findShortestMigrationPath(migrators, from, to); + if (!migrationPath) { throw new Error( - `Migrator from {{#latest}}{{type}}{{/latest}}Format "${from}" to "${to}" is not available` + `Migration path from {{#latest}}{{type}}{{/latest}}Format "${from}" to "${to}" is not available` ); } - return migrator(manifest); -{{/prevFormats.length}} -{{^prevFormats.length}} - throw new Error(`This should never happen, {{#latest}}{{type}}{{/latest}} migrators is empty. from: ${from}, to: ${to}`); -{{/prevFormats.length}} + let newManifest = manifest; + + for(const migrator of migrationPath){ + newManifest = migrator.migrate(newManifest) as Any{{#latest}}{{type}}{{/latest}}; + } + + return newManifest as {{#latest}}{{type}}{{/latest}}; } diff --git a/packages/js/manifests/polywrap/src/__tests__/migrations.spec.ts b/packages/js/manifests/polywrap/src/__tests__/migrations.spec.ts index 49445fc31c..4b9a8f0b1d 100644 --- a/packages/js/manifests/polywrap/src/__tests__/migrations.spec.ts +++ b/packages/js/manifests/polywrap/src/__tests__/migrations.spec.ts @@ -1,11 +1,70 @@ import { deserializeDeployManifest, deserializePolywrapManifest } from "../"; import fs from "fs"; +import { findShortestMigrationPath, Migrator } from "../migrations"; -describe("Polywrap Manifest Migrations", () => { - it("Should succesfully migrate from 0.1.0 to 0.2.0", async() => { - const manifestPath = __dirname + "/manifest/polywrap/migrations/polywrap-0.1.0.yaml"; - const expectedManifestPath = __dirname + "/manifest/polywrap/migrations/polywrap-0.2.0.yaml"; +describe("Manifest migration pathfinding", () => { + const migrators: Migrator[] = [ + { + from: "0.1.0", + to: "0.2.0", + migrate: (x) => x, + }, + { + from: "0.2.0", + to: "0.3.0", + migrate: (x) => x, + }, + { + from: "0.3.0", + to: "0.4.0", + migrate: (x) => x, + }, + { + from: "0.4.0", + to: "0.5.0", + migrate: (x) => x, + }, + { + from: "0.2.0", + to: "0.4.0", + migrate: (x) => x, + }, + ]; + + it("Should return undefined when no migration path exists", async () => { + const path = findShortestMigrationPath(migrators, "0.1.0", "0.6.0"); + + expect(path).toBeUndefined(); + + const reverseUnsupportedPath = findShortestMigrationPath( + migrators, + "0.2.0", + "0.1.0" + ); + + expect(reverseUnsupportedPath).toBeUndefined(); + }); + + it("Should return an empty array when from and to are the same", async () => { + const path = findShortestMigrationPath(migrators, "0.1.0", "0.1.0"); + + expect(path).toEqual([]); + }); + + it("Should return the shortest migration path", async () => { + const path = findShortestMigrationPath(migrators, "0.1.0", "0.5.0"); + + expect(path).toEqual([migrators[0], migrators[4], migrators[3]]); + }); +}); + +describe("Polywrap Project Manifest Migrations", () => { + it("Should succesfully migrate from 0.1.0 to 0.2.0", async () => { + const manifestPath = + __dirname + "/manifest/polywrap/migrations/polywrap-0.1.0.yaml"; + const expectedManifestPath = + __dirname + "/manifest/polywrap/migrations/polywrap-0.2.0.yaml"; const manifestFile = fs.readFileSync(manifestPath, "utf-8"); const expectedManifestFile = fs.readFileSync(expectedManifestPath, "utf-8"); @@ -18,9 +77,11 @@ describe("Polywrap Manifest Migrations", () => { }); describe("Polywrap Deploy Manifest Migrations", () => { - it("Should succesfully migrate from 0.1.0 to 0.2.0", async() => { - const manifestPath = __dirname + "/manifest/deploy/migrations/polywrap-0.1.0.yaml"; - const expectedManifestPath = __dirname + "/manifest/deploy/migrations/polywrap-0.2.0.yaml"; + it("Should succesfully migrate from 0.1.0 to 0.2.0", async () => { + const manifestPath = + __dirname + "/manifest/deploy/migrations/polywrap-0.1.0.yaml"; + const expectedManifestPath = + __dirname + "/manifest/deploy/migrations/polywrap-0.2.0.yaml"; const manifestFile = fs.readFileSync(manifestPath, "utf-8"); const expectedManifestFile = fs.readFileSync(expectedManifestPath, "utf-8"); @@ -30,4 +91,4 @@ describe("Polywrap Deploy Manifest Migrations", () => { expect(manifest).toEqual(expectedManifest); }); -}); \ No newline at end of file +}); diff --git a/packages/js/manifests/polywrap/src/formats/polywrap.app/migrate.ts b/packages/js/manifests/polywrap/src/formats/polywrap.app/migrate.ts index 9b162ac9de..f0b24e1abc 100644 --- a/packages/js/manifests/polywrap/src/formats/polywrap.app/migrate.ts +++ b/packages/js/manifests/polywrap/src/formats/polywrap.app/migrate.ts @@ -10,18 +10,8 @@ import { AppManifestFormats, latestAppManifestFormat } from "."; - -import { - migrate as migrate_0_1_0_to_0_2_0 -} from "./migrators/0.1.0_to_0.2.0"; - -type Migrator = { - [key in AppManifestFormats]?: (m: AnyAppManifest) => AppManifest; -}; - -export const migrators: Migrator = { - "0.1.0": migrate_0_1_0_to_0_2_0, -}; +import { findShortestMigrationPath } from "../../migrations"; +import { migrators } from "./migrators"; export function migrateAppManifest( manifest: AnyAppManifest, @@ -29,11 +19,6 @@ export function migrateAppManifest( ): AppManifest { let from = manifest.format as AppManifestFormats; - // HACK: Patch fix for backwards compatability - if(from === "0.1" && ("0.1.0" in migrators)) { - from = "0.1.0" as AppManifestFormats; - } - if (from === latestAppManifestFormat) { return manifest as AppManifest; } @@ -42,12 +27,18 @@ export function migrateAppManifest( throw new Error(`Unrecognized AppManifestFormat "${manifest.format}"`); } - const migrator = migrators[from]; - if (!migrator) { + const migrationPath = findShortestMigrationPath(migrators, from, to); + if (!migrationPath) { throw new Error( - `Migrator from AppManifestFormat "${from}" to "${to}" is not available` + `Migration path from AppManifestFormat "${from}" to "${to}" is not available` ); } - return migrator(manifest); + let newManifest = manifest; + + for(const migrator of migrationPath){ + newManifest = migrator.migrate(newManifest) as AnyAppManifest; + } + + return newManifest as AppManifest; } diff --git a/packages/js/manifests/polywrap/src/formats/polywrap.app/migrators/index.ts b/packages/js/manifests/polywrap/src/formats/polywrap.app/migrators/index.ts new file mode 100644 index 0000000000..2c882af9fa --- /dev/null +++ b/packages/js/manifests/polywrap/src/formats/polywrap.app/migrators/index.ts @@ -0,0 +1,15 @@ +import { Migrator } from "../../../migrations"; +import { migrate as migrate_0_1_0_to_0_2_0 } from "./0.1.0_to_0.2.0"; + +export const migrators: Migrator[] = [ + { + from: "0.1", + to: "0.2.0", + migrate: migrate_0_1_0_to_0_2_0 + }, + { + from: "0.1.0", + to: "0.2.0", + migrate: migrate_0_1_0_to_0_2_0 + } +]; \ No newline at end of file diff --git a/packages/js/manifests/polywrap/src/formats/polywrap.build/migrate.ts b/packages/js/manifests/polywrap/src/formats/polywrap.build/migrate.ts index 3fd31dfb03..acf48ffbec 100644 --- a/packages/js/manifests/polywrap/src/formats/polywrap.build/migrate.ts +++ b/packages/js/manifests/polywrap/src/formats/polywrap.build/migrate.ts @@ -10,14 +10,8 @@ import { BuildManifestFormats, latestBuildManifestFormat } from "."; - - -type Migrator = { - [key in BuildManifestFormats]?: (m: AnyBuildManifest) => BuildManifest; -}; - -export const migrators: Migrator = { -}; +import { findShortestMigrationPath } from "../../migrations"; +import { migrators } from "./migrators"; export function migrateBuildManifest( manifest: AnyBuildManifest, @@ -25,11 +19,6 @@ export function migrateBuildManifest( ): BuildManifest { let from = manifest.format as BuildManifestFormats; - // HACK: Patch fix for backwards compatability - if(from === "0.1" && ("0.1.0" in migrators)) { - from = "0.1.0" as BuildManifestFormats; - } - if (from === latestBuildManifestFormat) { return manifest as BuildManifest; } @@ -38,5 +27,18 @@ export function migrateBuildManifest( throw new Error(`Unrecognized BuildManifestFormat "${manifest.format}"`); } - throw new Error(`This should never happen, BuildManifest migrators is empty. from: ${from}, to: ${to}`); + const migrationPath = findShortestMigrationPath(migrators, from, to); + if (!migrationPath) { + throw new Error( + `Migration path from BuildManifestFormat "${from}" to "${to}" is not available` + ); + } + + let newManifest = manifest; + + for(const migrator of migrationPath){ + newManifest = migrator.migrate(newManifest) as AnyBuildManifest; + } + + return newManifest as BuildManifest; } diff --git a/packages/js/manifests/polywrap/src/formats/polywrap.build/migrators/index.ts b/packages/js/manifests/polywrap/src/formats/polywrap.build/migrators/index.ts new file mode 100644 index 0000000000..6fa0ce38a3 --- /dev/null +++ b/packages/js/manifests/polywrap/src/formats/polywrap.build/migrators/index.ts @@ -0,0 +1,3 @@ +import { Migrator } from "../../../migrations"; + +export const migrators: Migrator[] = []; diff --git a/packages/js/manifests/polywrap/src/formats/polywrap.deploy/migrate.ts b/packages/js/manifests/polywrap/src/formats/polywrap.deploy/migrate.ts index 8667f4ea10..7186f8edd5 100644 --- a/packages/js/manifests/polywrap/src/formats/polywrap.deploy/migrate.ts +++ b/packages/js/manifests/polywrap/src/formats/polywrap.deploy/migrate.ts @@ -10,18 +10,8 @@ import { DeployManifestFormats, latestDeployManifestFormat } from "."; - -import { - migrate as migrate_0_1_0_to_0_2_0 -} from "./migrators/0.1.0_to_0.2.0"; - -type Migrator = { - [key in DeployManifestFormats]?: (m: AnyDeployManifest) => DeployManifest; -}; - -export const migrators: Migrator = { - "0.1.0": migrate_0_1_0_to_0_2_0, -}; +import { findShortestMigrationPath } from "../../migrations"; +import { migrators } from "./migrators"; export function migrateDeployManifest( manifest: AnyDeployManifest, @@ -29,11 +19,6 @@ export function migrateDeployManifest( ): DeployManifest { let from = manifest.format as DeployManifestFormats; - // HACK: Patch fix for backwards compatability - if(from === "0.1" && ("0.1.0" in migrators)) { - from = "0.1.0" as DeployManifestFormats; - } - if (from === latestDeployManifestFormat) { return manifest as DeployManifest; } @@ -42,12 +27,18 @@ export function migrateDeployManifest( throw new Error(`Unrecognized DeployManifestFormat "${manifest.format}"`); } - const migrator = migrators[from]; - if (!migrator) { + const migrationPath = findShortestMigrationPath(migrators, from, to); + if (!migrationPath) { throw new Error( - `Migrator from DeployManifestFormat "${from}" to "${to}" is not available` + `Migration path from DeployManifestFormat "${from}" to "${to}" is not available` ); } - return migrator(manifest); + let newManifest = manifest; + + for(const migrator of migrationPath){ + newManifest = migrator.migrate(newManifest) as AnyDeployManifest; + } + + return newManifest as DeployManifest; } diff --git a/packages/js/manifests/polywrap/src/formats/polywrap.deploy/migrators/index.ts b/packages/js/manifests/polywrap/src/formats/polywrap.deploy/migrators/index.ts new file mode 100644 index 0000000000..2c882af9fa --- /dev/null +++ b/packages/js/manifests/polywrap/src/formats/polywrap.deploy/migrators/index.ts @@ -0,0 +1,15 @@ +import { Migrator } from "../../../migrations"; +import { migrate as migrate_0_1_0_to_0_2_0 } from "./0.1.0_to_0.2.0"; + +export const migrators: Migrator[] = [ + { + from: "0.1", + to: "0.2.0", + migrate: migrate_0_1_0_to_0_2_0 + }, + { + from: "0.1.0", + to: "0.2.0", + migrate: migrate_0_1_0_to_0_2_0 + } +]; \ No newline at end of file diff --git a/packages/js/manifests/polywrap/src/formats/polywrap.infra/migrate.ts b/packages/js/manifests/polywrap/src/formats/polywrap.infra/migrate.ts index d9aa2bc605..989982381f 100644 --- a/packages/js/manifests/polywrap/src/formats/polywrap.infra/migrate.ts +++ b/packages/js/manifests/polywrap/src/formats/polywrap.infra/migrate.ts @@ -10,14 +10,8 @@ import { InfraManifestFormats, latestInfraManifestFormat } from "."; - - -type Migrator = { - [key in InfraManifestFormats]?: (m: AnyInfraManifest) => InfraManifest; -}; - -export const migrators: Migrator = { -}; +import { findShortestMigrationPath } from "../../migrations"; +import { migrators } from "./migrators"; export function migrateInfraManifest( manifest: AnyInfraManifest, @@ -25,11 +19,6 @@ export function migrateInfraManifest( ): InfraManifest { let from = manifest.format as InfraManifestFormats; - // HACK: Patch fix for backwards compatability - if(from === "0.1" && ("0.1.0" in migrators)) { - from = "0.1.0" as InfraManifestFormats; - } - if (from === latestInfraManifestFormat) { return manifest as InfraManifest; } @@ -38,5 +27,18 @@ export function migrateInfraManifest( throw new Error(`Unrecognized InfraManifestFormat "${manifest.format}"`); } - throw new Error(`This should never happen, InfraManifest migrators is empty. from: ${from}, to: ${to}`); + const migrationPath = findShortestMigrationPath(migrators, from, to); + if (!migrationPath) { + throw new Error( + `Migration path from InfraManifestFormat "${from}" to "${to}" is not available` + ); + } + + let newManifest = manifest; + + for(const migrator of migrationPath){ + newManifest = migrator.migrate(newManifest) as AnyInfraManifest; + } + + return newManifest as InfraManifest; } diff --git a/packages/js/manifests/polywrap/src/formats/polywrap.infra/migrators/index.ts b/packages/js/manifests/polywrap/src/formats/polywrap.infra/migrators/index.ts new file mode 100644 index 0000000000..6fa0ce38a3 --- /dev/null +++ b/packages/js/manifests/polywrap/src/formats/polywrap.infra/migrators/index.ts @@ -0,0 +1,3 @@ +import { Migrator } from "../../../migrations"; + +export const migrators: Migrator[] = []; diff --git a/packages/js/manifests/polywrap/src/formats/polywrap.meta/migrate.ts b/packages/js/manifests/polywrap/src/formats/polywrap.meta/migrate.ts index cc1d82575a..170087ac42 100644 --- a/packages/js/manifests/polywrap/src/formats/polywrap.meta/migrate.ts +++ b/packages/js/manifests/polywrap/src/formats/polywrap.meta/migrate.ts @@ -10,14 +10,8 @@ import { MetaManifestFormats, latestMetaManifestFormat } from "."; - - -type Migrator = { - [key in MetaManifestFormats]?: (m: AnyMetaManifest) => MetaManifest; -}; - -export const migrators: Migrator = { -}; +import { findShortestMigrationPath } from "../../migrations"; +import { migrators } from "./migrators"; export function migrateMetaManifest( manifest: AnyMetaManifest, @@ -25,11 +19,6 @@ export function migrateMetaManifest( ): MetaManifest { let from = manifest.format as MetaManifestFormats; - // HACK: Patch fix for backwards compatability - if(from === "0.1" && ("0.1.0" in migrators)) { - from = "0.1.0" as MetaManifestFormats; - } - if (from === latestMetaManifestFormat) { return manifest as MetaManifest; } @@ -38,5 +27,18 @@ export function migrateMetaManifest( throw new Error(`Unrecognized MetaManifestFormat "${manifest.format}"`); } - throw new Error(`This should never happen, MetaManifest migrators is empty. from: ${from}, to: ${to}`); + const migrationPath = findShortestMigrationPath(migrators, from, to); + if (!migrationPath) { + throw new Error( + `Migration path from MetaManifestFormat "${from}" to "${to}" is not available` + ); + } + + let newManifest = manifest; + + for(const migrator of migrationPath){ + newManifest = migrator.migrate(newManifest) as AnyMetaManifest; + } + + return newManifest as MetaManifest; } diff --git a/packages/js/manifests/polywrap/src/formats/polywrap.meta/migrators/index.ts b/packages/js/manifests/polywrap/src/formats/polywrap.meta/migrators/index.ts new file mode 100644 index 0000000000..6fa0ce38a3 --- /dev/null +++ b/packages/js/manifests/polywrap/src/formats/polywrap.meta/migrators/index.ts @@ -0,0 +1,3 @@ +import { Migrator } from "../../../migrations"; + +export const migrators: Migrator[] = []; diff --git a/packages/js/manifests/polywrap/src/formats/polywrap.plugin/migrate.ts b/packages/js/manifests/polywrap/src/formats/polywrap.plugin/migrate.ts index b925557584..16e49bddbe 100644 --- a/packages/js/manifests/polywrap/src/formats/polywrap.plugin/migrate.ts +++ b/packages/js/manifests/polywrap/src/formats/polywrap.plugin/migrate.ts @@ -10,18 +10,8 @@ import { PluginManifestFormats, latestPluginManifestFormat } from "."; - -import { - migrate as migrate_0_1_0_to_0_2_0 -} from "./migrators/0.1.0_to_0.2.0"; - -type Migrator = { - [key in PluginManifestFormats]?: (m: AnyPluginManifest) => PluginManifest; -}; - -export const migrators: Migrator = { - "0.1.0": migrate_0_1_0_to_0_2_0, -}; +import { findShortestMigrationPath } from "../../migrations"; +import { migrators } from "./migrators"; export function migratePluginManifest( manifest: AnyPluginManifest, @@ -29,11 +19,6 @@ export function migratePluginManifest( ): PluginManifest { let from = manifest.format as PluginManifestFormats; - // HACK: Patch fix for backwards compatability - if(from === "0.1" && ("0.1.0" in migrators)) { - from = "0.1.0" as PluginManifestFormats; - } - if (from === latestPluginManifestFormat) { return manifest as PluginManifest; } @@ -42,12 +27,18 @@ export function migratePluginManifest( throw new Error(`Unrecognized PluginManifestFormat "${manifest.format}"`); } - const migrator = migrators[from]; - if (!migrator) { + const migrationPath = findShortestMigrationPath(migrators, from, to); + if (!migrationPath) { throw new Error( - `Migrator from PluginManifestFormat "${from}" to "${to}" is not available` + `Migration path from PluginManifestFormat "${from}" to "${to}" is not available` ); } - return migrator(manifest); + let newManifest = manifest; + + for(const migrator of migrationPath){ + newManifest = migrator.migrate(newManifest) as AnyPluginManifest; + } + + return newManifest as PluginManifest; } diff --git a/packages/js/manifests/polywrap/src/formats/polywrap.plugin/migrators/index.ts b/packages/js/manifests/polywrap/src/formats/polywrap.plugin/migrators/index.ts new file mode 100644 index 0000000000..2c882af9fa --- /dev/null +++ b/packages/js/manifests/polywrap/src/formats/polywrap.plugin/migrators/index.ts @@ -0,0 +1,15 @@ +import { Migrator } from "../../../migrations"; +import { migrate as migrate_0_1_0_to_0_2_0 } from "./0.1.0_to_0.2.0"; + +export const migrators: Migrator[] = [ + { + from: "0.1", + to: "0.2.0", + migrate: migrate_0_1_0_to_0_2_0 + }, + { + from: "0.1.0", + to: "0.2.0", + migrate: migrate_0_1_0_to_0_2_0 + } +]; \ No newline at end of file diff --git a/packages/js/manifests/polywrap/src/formats/polywrap.test/migrate.ts b/packages/js/manifests/polywrap/src/formats/polywrap.test/migrate.ts index bab7e2fbf4..6ba38c0066 100644 --- a/packages/js/manifests/polywrap/src/formats/polywrap.test/migrate.ts +++ b/packages/js/manifests/polywrap/src/formats/polywrap.test/migrate.ts @@ -10,14 +10,8 @@ import { PolywrapWorkflowFormats, latestPolywrapWorkflowFormat } from "."; - - -type Migrator = { - [key in PolywrapWorkflowFormats]?: (m: AnyPolywrapWorkflow) => PolywrapWorkflow; -}; - -export const migrators: Migrator = { -}; +import { findShortestMigrationPath } from "../../migrations"; +import { migrators } from "./migrators"; export function migratePolywrapWorkflow( manifest: AnyPolywrapWorkflow, @@ -25,11 +19,6 @@ export function migratePolywrapWorkflow( ): PolywrapWorkflow { let from = manifest.format as PolywrapWorkflowFormats; - // HACK: Patch fix for backwards compatability - if(from === "0.1" && ("0.1.0" in migrators)) { - from = "0.1.0" as PolywrapWorkflowFormats; - } - if (from === latestPolywrapWorkflowFormat) { return manifest as PolywrapWorkflow; } @@ -38,5 +27,18 @@ export function migratePolywrapWorkflow( throw new Error(`Unrecognized PolywrapWorkflowFormat "${manifest.format}"`); } - throw new Error(`This should never happen, PolywrapWorkflow migrators is empty. from: ${from}, to: ${to}`); + const migrationPath = findShortestMigrationPath(migrators, from, to); + if (!migrationPath) { + throw new Error( + `Migration path from PolywrapWorkflowFormat "${from}" to "${to}" is not available` + ); + } + + let newManifest = manifest; + + for(const migrator of migrationPath){ + newManifest = migrator.migrate(newManifest) as AnyPolywrapWorkflow; + } + + return newManifest as PolywrapWorkflow; } diff --git a/packages/js/manifests/polywrap/src/formats/polywrap.test/migrators/index.ts b/packages/js/manifests/polywrap/src/formats/polywrap.test/migrators/index.ts new file mode 100644 index 0000000000..6fa0ce38a3 --- /dev/null +++ b/packages/js/manifests/polywrap/src/formats/polywrap.test/migrators/index.ts @@ -0,0 +1,3 @@ +import { Migrator } from "../../../migrations"; + +export const migrators: Migrator[] = []; diff --git a/packages/js/manifests/polywrap/src/formats/polywrap/migrate.ts b/packages/js/manifests/polywrap/src/formats/polywrap/migrate.ts index ccce046445..45d4167a4c 100644 --- a/packages/js/manifests/polywrap/src/formats/polywrap/migrate.ts +++ b/packages/js/manifests/polywrap/src/formats/polywrap/migrate.ts @@ -10,18 +10,8 @@ import { PolywrapManifestFormats, latestPolywrapManifestFormat } from "."; - -import { - migrate as migrate_0_1_0_to_0_2_0 -} from "./migrators/0.1.0_to_0.2.0"; - -type Migrator = { - [key in PolywrapManifestFormats]?: (m: AnyPolywrapManifest) => PolywrapManifest; -}; - -export const migrators: Migrator = { - "0.1.0": migrate_0_1_0_to_0_2_0, -}; +import { findShortestMigrationPath } from "../../migrations"; +import { migrators } from "./migrators"; export function migratePolywrapManifest( manifest: AnyPolywrapManifest, @@ -29,11 +19,6 @@ export function migratePolywrapManifest( ): PolywrapManifest { let from = manifest.format as PolywrapManifestFormats; - // HACK: Patch fix for backwards compatability - if(from === "0.1" && ("0.1.0" in migrators)) { - from = "0.1.0" as PolywrapManifestFormats; - } - if (from === latestPolywrapManifestFormat) { return manifest as PolywrapManifest; } @@ -42,12 +27,18 @@ export function migratePolywrapManifest( throw new Error(`Unrecognized PolywrapManifestFormat "${manifest.format}"`); } - const migrator = migrators[from]; - if (!migrator) { + const migrationPath = findShortestMigrationPath(migrators, from, to); + if (!migrationPath) { throw new Error( - `Migrator from PolywrapManifestFormat "${from}" to "${to}" is not available` + `Migration path from PolywrapManifestFormat "${from}" to "${to}" is not available` ); } - return migrator(manifest); + let newManifest = manifest; + + for(const migrator of migrationPath){ + newManifest = migrator.migrate(newManifest) as AnyPolywrapManifest; + } + + return newManifest as PolywrapManifest; } diff --git a/packages/js/manifests/polywrap/src/formats/polywrap/migrators/index.ts b/packages/js/manifests/polywrap/src/formats/polywrap/migrators/index.ts new file mode 100644 index 0000000000..2c882af9fa --- /dev/null +++ b/packages/js/manifests/polywrap/src/formats/polywrap/migrators/index.ts @@ -0,0 +1,15 @@ +import { Migrator } from "../../../migrations"; +import { migrate as migrate_0_1_0_to_0_2_0 } from "./0.1.0_to_0.2.0"; + +export const migrators: Migrator[] = [ + { + from: "0.1", + to: "0.2.0", + migrate: migrate_0_1_0_to_0_2_0 + }, + { + from: "0.1.0", + to: "0.2.0", + migrate: migrate_0_1_0_to_0_2_0 + } +]; \ No newline at end of file diff --git a/packages/js/manifests/polywrap/src/migrations/findShortestMigrationPath.ts b/packages/js/manifests/polywrap/src/migrations/findShortestMigrationPath.ts new file mode 100644 index 0000000000..d97580d897 --- /dev/null +++ b/packages/js/manifests/polywrap/src/migrations/findShortestMigrationPath.ts @@ -0,0 +1,52 @@ +import { Migrator } from "./migration"; + +type MigrationWithSearchHistory = [Migrator, Migrator[]]; + +// A simple BFS intended to find the shortest migration path from one version to another +// Returns an array of migrations in the order they need to be performed to migrate from one version to another +export function findShortestMigrationPath( + nodes: Migrator[], + from: string, + to: string +): Migrator[] | undefined { + if (from === to) { + return []; + } + + const possibleStarts = nodes.filter((x) => x.from === from); + + if (!possibleStarts.length) { + return undefined; + } + + const visited = [...possibleStarts]; + + const queue: MigrationWithSearchHistory[] = possibleStarts.map((start) => [ + start, + [start], + ]); + + while (queue.length) { + const [node, path] = queue.shift() as MigrationWithSearchHistory; + + if (node.to === to) { + return path; + } + + const neighbours = nodes.filter( + (x) => !visited.includes(x) && x.from === node.to + ); + + for (const neighbour of neighbours) { + visited.push(neighbour); + + if (neighbour.to === to) { + return [...path, neighbour]; + } + + queue.push([neighbour, [...path, neighbour]]); + } + } + + return undefined; +} diff --git a/packages/js/manifests/polywrap/src/migrations/index.ts b/packages/js/manifests/polywrap/src/migrations/index.ts new file mode 100644 index 0000000000..712bb35572 --- /dev/null +++ b/packages/js/manifests/polywrap/src/migrations/index.ts @@ -0,0 +1,2 @@ +export * from "./findShortestMigrationPath"; +export * from "./migration"; diff --git a/packages/js/manifests/polywrap/src/migrations/migration.ts b/packages/js/manifests/polywrap/src/migrations/migration.ts new file mode 100644 index 0000000000..145ec43ff7 --- /dev/null +++ b/packages/js/manifests/polywrap/src/migrations/migration.ts @@ -0,0 +1,26 @@ +import { + AnyAppManifest, + AnyBuildManifest, + AnyDeployManifest, + AnyInfraManifest, + AnyMetaManifest, + AnyPluginManifest, + AnyPolywrapManifest, + AnyPolywrapWorkflow, +} from "../formats"; + +type AnyManifest = + | AnyPolywrapManifest + | AnyPluginManifest + | AnyAppManifest + | AnyInfraManifest + | AnyDeployManifest + | AnyBuildManifest + | AnyMetaManifest + | AnyPolywrapWorkflow; + +export type Migrator = { + from: string; + to: string; + migrate: (manifest: AnyManifest) => AnyManifest; +};