padloc/packages/core/src/migrations.ts

94 lines
2.9 KiB
TypeScript

import { Err, ErrorCode } from "./error";
export interface Migration {
from: string;
to: string;
transforms: {
[kind: string]: {
up: (inp: any, kind?: string) => any;
down: (inp: any, kind?: string) => any;
};
};
}
export const MIGRATIONS: Migration[] = [
{
from: "3.0.14",
to: "3.1.0",
transforms: {
account: {
up: ({ mainVault, orgs, ...rest }: any) => ({
mainVault: { id: mainVault },
orgs: orgs.map((org: any) => ({
id: org,
})),
...rest,
}),
down: ({ mainVault, orgs, ...rest }: any) => ({
mainVault: mainVault.id,
orgs: orgs.map((org: any) => org.id),
...rest,
}),
},
all: {
up: (raw: any, kind?: string) => ({ kind, ...raw }),
down: ({ kind, ...rest }) => rest,
},
},
},
];
export const EARLIEST_VERSION = MIGRATIONS[0].from;
export const LATEST_VERSION = MIGRATIONS[MIGRATIONS.length - 1].to;
function norm(version: string = EARLIEST_VERSION): string {
return version
.split(".")
.map((part) => part.padStart(3, "0"))
.join();
}
export function upgrade(kind: string, raw: any, version: string = LATEST_VERSION): any {
if (norm(raw.version) > norm(LATEST_VERSION)) {
throw new Err(
ErrorCode.UNSUPPORTED_VERSION,
"An object could not be decoded because it was encoded with a newer version of Padloc. " +
"Please update to the latest version to fix this problem!"
);
}
const migration = MIGRATIONS.find(
(m) => norm(m.from) >= norm(raw.version || EARLIEST_VERSION) && norm(m.to) <= norm(version)
);
if (migration) {
let transform = migration.transforms["all"];
raw = transform ? transform.up(raw, kind) : raw;
transform = migration.transforms[kind];
raw = transform ? transform.up(raw, kind) : raw;
raw.version = migration.to;
return upgrade(kind, raw, version);
} else {
raw.version = version;
return raw;
}
}
export function downgrade(kind: string, raw: any, version: string = LATEST_VERSION): any {
const migration = MIGRATIONS.reverse().find(
(m) => norm(m.to) <= norm(raw.version || LATEST_VERSION) && norm(m.from) >= norm(version)
);
if (migration) {
let transform = migration.transforms[kind];
raw = transform ? transform.down(raw, kind) : raw;
transform = migration.transforms["all"];
raw = transform ? transform.down(raw, kind) : raw;
raw.version = migration.from;
return downgrade(kind, raw, version);
} else {
raw.version = norm(version) > norm(LATEST_VERSION) ? LATEST_VERSION : version;
return raw;
}
}