Add a system to create migrations for existing storage.

This commit is contained in:
Bauke 2020-11-26 18:21:00 +01:00
parent e4e52ae5f7
commit f00b4161c3
Signed by: Bauke
GPG Key ID: C1C0F29952BCF558
4 changed files with 84 additions and 8 deletions

View File

@ -4,12 +4,14 @@ import {
getManifest,
getNextQItem,
getSettings,
migrate,
newQItemID,
QItem,
QMessage,
removeQItem,
saveSettings,
updateBadge
updateBadge,
versionAsNumber
} from '.';
let timeoutID: number | null = null;
@ -61,17 +63,28 @@ browser.runtime.onMessage.addListener(async (request: QMessage<unknown>) => {
browser.runtime.onInstalled.addListener(async () => {
const manifest = getManifest();
const settings = await getSettings();
const versionGotUpdated =
versionAsNumber(manifest.version) > versionAsNumber(settings.latestVersion);
if (versionGotUpdated) {
// Set the previous sync storage data in the local storage as a backup.
const previous = await browser.storage.sync.get();
await browser.storage.local.clear();
await browser.storage.local.set(previous);
// Then migrate the sync storage data and update it.
const next = migrate(settings.latestVersion, previous);
next.latestVersion = manifest.version;
next.versionGotUpdated = versionGotUpdated;
await browser.storage.sync.clear();
await browser.storage.sync.set(next);
}
// Open the options page when:
// * The extension is first installed or is updated.
// * In development, for convenience.
if (
manifest.version !== settings.latestVersion ||
manifest.nodeEnv === 'development'
) {
settings.latestVersion = manifest.version;
settings.versionGotUpdated = true;
await saveSettings(settings);
if (versionGotUpdated || manifest.nodeEnv === 'development') {
await openOptionsPage();
}
});

View File

@ -73,5 +73,14 @@ export async function updateBadge(settings?: Settings): Promise<void> {
]);
}
/**
* Returns a version string as a number by removing the periods.
* @param version
*/
export function versionAsNumber(version: string): number {
return Number(version.replace(/\./g, ''));
}
export * from './components';
export * from './migrations';
export * from './settings';

View File

@ -0,0 +1,24 @@
import {Migration, QItem} from '../..';
export const migration_2020_11_26: Migration = {
date: new Date('2020-11-26T14:32:00.000Z'),
version: '0.1.7',
upgrade
};
/**
* This upgrades the sync settings to use 'qi<ID>'-named objects for QItems instead
* of them being in an array.
* Relevant commit: a668da05a179851b2a1117ef2d6aa9cef48d4964
*/
function upgrade(previous: Record<string, any>): Record<string, any> {
const items: QItem[] = previous.queue ?? [];
const next: Record<string, any> = previous;
delete next.queue;
for (const item of items) {
next['qi' + item.id.toString()] = item;
}
return next;
}

View File

@ -0,0 +1,30 @@
import {log, versionAsNumber} from '../..';
import {migration_2020_11_26} from './2020-11-26';
export type Migration = {
date: Date;
version: string;
upgrade: (previous: Record<string, any>) => Record<string, any>;
};
const migrations: Migration[] = [migration_2020_11_26];
export function migrate(
latestVersion: string,
previous: Record<string, any>
): Record<string, any> {
let next = previous;
for (const migration of migrations) {
// If the saved version is >= the version from the migration, we've already
// handled it previously, so skip it.
if (versionAsNumber(latestVersion) >= versionAsNumber(migration.version)) {
continue;
}
log(`Running migration ${migration.date.toISOString()}`);
next = migration.upgrade(previous);
}
return next;
}