Add very primitive migration engine

This commit is contained in:
Kacper Donat 2020-01-26 17:24:08 +01:00
parent 253b206a39
commit b06a89350f
5 changed files with 68 additions and 8 deletions

View File

@ -17,6 +17,8 @@ import PortalVue from 'portal-vue';
import VueDragscroll from 'vue-dragscroll';
import { Workbox } from "workbox-window";
import { migrate } from "./store/migrations";
Vue.use(Vuex);
Vue.use(PortalVue);
Vue.use(VueDragscroll);
@ -25,6 +27,8 @@ Vue.prototype.$isTouch = 'ontouchstart' in window || navigator.msMaxTouchPoints
// async dependencies
(async function () {
await migrate("vuex");
const [ components, { default: store } ] = await Promise.all([
import('./components'),
import('./store'),

View File

@ -1,6 +1,6 @@
import Vue from 'vue'
import { Component, Prop } from 'vue-property-decorator'
import { namespace, State } from "vuex-class";
import { namespace, State, Mutation } from "vuex-class";
import { Favourite } from "../store/favourites";
import { SavedState } from "../store/root";
import { Stop } from "../model";
@ -12,9 +12,10 @@ import { Favourites } from "../store";
export class FavouritesComponent extends Vue {
@Favourites.State favourites: Favourite[];
@Favourites.Mutation remove: (fav: Favourite) => void;
@Mutation('replace') setStops: (stops: Stop[]) => void;
choose(favourite: Favourite) {
this.$store.dispatch('load', favourite.state);
this.setStops(favourite.stops);
}
}
@ -22,11 +23,7 @@ function createFavouriteEntry(name: string, stops: Stop[]): Favourite {
return {
id: uuid.v4(),
name,
stops,
state: {
version: 1,
stops: stops.map(stop => stop.id),
},
stops
}
}

View File

@ -7,7 +7,6 @@ export interface Favourite {
id: string;
name: string;
stops: Stop[];
state: SavedState;
}
export interface FavouritesState {

View File

@ -0,0 +1,56 @@
import { distinct } from "../utils";
import urls from "../urls";
import * as uuid from "uuid";
type Migration = {
name: string,
key: string,
up: (state: any) => Promise<any>;
}
const migrations: Migration[] = [
{
name: "202001261540_full_stop_in_state",
key: "vuex",
up: async state => {
const current = state.favourites.favourites;
const ids = current
.map(favourite => favourite.state.stops)
.reduce((cur, acc) => [ ...cur, ...acc ])
.filter(distinct)
;
const stops = await (await fetch(urls.prepare(urls.stops.all, { id: ids }))).json();
const lookup = stops.reduce((lookup, stop) => ({ ...lookup, [stop.id]: stop }), {});
return {
...state,
favourites: {
...state.favourites,
favourites: state.favourites.favourites.map(favourite => ({
id: favourite.id || uuid.v4(),
name: favourite.name,
stops: favourite.stops || favourite.state.stops.map(id => lookup[id]).filter(distinct),
}))
}
}
}
}
];
export async function migrate(key: string) {
const current = JSON.parse(window.localStorage.getItem('migrations')) || [];
const state = JSON.parse(window.localStorage.getItem(key)) || {};
const result = await migrations
.filter(migration => migration.key == key)
.filter(migration => !current.includes(migration.name))
.reduce(async (state, migration) => {
current.push(migration.name);
return await migration.up(state)
}, state);
window.localStorage.setItem('migrations', JSON.stringify(current));
window.localStorage.setItem(key, JSON.stringify(result));
}

View File

@ -63,3 +63,7 @@ export function get(object: any, path: string): any {
return object[segments.shift()];
}
export function distinct<T>(value: T, index: number, array: T[]) {
return array.indexOf(value) === index;
}