queue/source/migrations/migrations.ts

118 lines
2.9 KiB
TypeScript

import browser from "webextension-polyfill";
import {migrate, type Migration} from "@holllo/migration-helper";
import {createValue} from "@holllo/webextension-storage";
import type {ItemKeyPrefix} from "../item/item.js";
/** The Queue Item type for versions `<0.3.0`. */
export type QueueItemPre030 = {
added: Date;
id: number;
text: string;
url: string;
};
/** The Queue Item type for versions `>=0.3.0 <1.0.0`. */
export type QueueItem030 = {
sortIndex: number;
} & QueueItemPre030;
/** The Queue Item type for versions `>=1.0.0`. */
export type QueueItem100 = {
dateAdded: Date;
id: number;
text: string | undefined;
url: string;
};
/** All migrations for Queue storage. */
export const dataMigrations: Array<Migration<string>> = [
{
version: "0.1.7",
async migrate(data: Record<string, any>) {
const migrated: Record<string, any> = {
version: "0.1.7",
};
const items = (data.queue as QueueItemPre030[]) ?? [];
for (const item of items) {
const key = `qi${item.id}`;
migrated[key] = item;
}
return migrated;
},
},
{
version: "0.3.0",
async migrate(data: Record<string, any>) {
const migrated: Record<string, any> = {
version: "0.3.0",
};
for (const [key, value] of Object.entries<QueueItemPre030>(data)) {
if (key.startsWith("qi")) {
const item: QueueItem030 = {
sortIndex: value.id,
...value,
};
migrated[key] = item;
}
}
return migrated;
},
},
{
version: "1.0.0",
async migrate(data: Record<string, any>) {
const migrated: Record<string, any> = {
version: "1.0.0",
};
for (const [key, value] of Object.entries<QueueItem030>(data)) {
if (key.startsWith("qi")) {
const item: QueueItem100 = {
dateAdded: new Date(value.added),
id: value.id,
text: value.text === "" ? undefined : value.text,
url: value.url,
};
const prefix: ItemKeyPrefix = "item-";
migrated[`${prefix}${item.id}`] = item;
}
}
return migrated;
},
},
];
/** Run the migrations and apply the result to storage. */
export async function runMigrations(): Promise<void> {
const manifest = browser.runtime.getManifest();
const version = await createValue<string>({
deserialize: (input) => input,
serialize: (input) => input,
key: "version",
storage: browser.storage.sync,
value: manifest.version,
});
// Only when the current data version is lower than the manifest version
// should the migrations run.
if (version.value >= manifest.version) {
return;
}
const migrated = await migrate(
await browser.storage.sync.get(),
version.value,
dataMigrations,
);
await browser.storage.sync.clear();
await browser.storage.sync.set(migrated as Record<string, any>);
}