mirror of
https://github.com/p-stream/p-stream.git
synced 2026-04-21 07:32:25 +00:00
helper methods in versioned store
This commit is contained in:
parent
ff1c0d65d6
commit
7096e544f4
2 changed files with 139 additions and 87 deletions
|
|
@ -32,7 +32,6 @@ version 0
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// TODO implement the store into the rest of the codebase
|
|
||||||
export const VideoProgressStore = versionedStoreBuilder()
|
export const VideoProgressStore = versionedStoreBuilder()
|
||||||
.setKey('video-progress')
|
.setKey('video-progress')
|
||||||
.addVersion({
|
.addVersion({
|
||||||
|
|
|
||||||
|
|
@ -1,90 +1,109 @@
|
||||||
function buildStoreObject(data) {
|
function buildStoreObject(d) {
|
||||||
return {
|
const data = {
|
||||||
versions: data.versions,
|
versions: d.versions,
|
||||||
currentVersion: data.maxVersion,
|
currentVersion: d.maxVersion,
|
||||||
id: data.storageString,
|
id: d.storageString,
|
||||||
update(obj) {
|
|
||||||
if (!obj)
|
|
||||||
throw new Error("object to update is not an object");
|
|
||||||
|
|
||||||
// repeat until object fully updated
|
|
||||||
while (obj["--version"] !== this.currentVersion) {
|
|
||||||
// get version
|
|
||||||
let version = obj["--version"] || 0;
|
|
||||||
if (version.constructor !== Number || version < 0)
|
|
||||||
version = -42; // invalid on purpose so it will reset
|
|
||||||
else {
|
|
||||||
version = (version+1).toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if version exists
|
|
||||||
if (!this.versions[version]) {
|
|
||||||
console.error(`Version not found for storage item in store ${this.id}, resetting`);
|
|
||||||
obj = null;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// update object
|
|
||||||
obj = this.versions[version].update(obj);
|
|
||||||
console.log(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if resulting obj is null, use latest version as init object
|
|
||||||
if (obj === null) {
|
|
||||||
console.error(`Storage item for store ${this.id} has been reset due to faulty updates`);
|
|
||||||
return this.versions[this.currentVersion.toString()].init();
|
|
||||||
}
|
|
||||||
|
|
||||||
// updates succesful, return
|
|
||||||
return obj;
|
|
||||||
},
|
|
||||||
|
|
||||||
/*
|
|
||||||
* get a instance of a stored item
|
|
||||||
* will be migrated to the latest version on fetch
|
|
||||||
* call .save() on it put the new modified data back
|
|
||||||
*/
|
|
||||||
get() {
|
|
||||||
// get from storage api
|
|
||||||
const store = this;
|
|
||||||
let data = localStorage.getItem(this.id);
|
|
||||||
|
|
||||||
// parse json if item exists
|
|
||||||
if (data) {
|
|
||||||
try {
|
|
||||||
data = JSON.parse(data);
|
|
||||||
if (!data.constructor) {
|
|
||||||
console.error(`Storage item for store ${this.id} has not constructor`)
|
|
||||||
throw new Error("storage item has no constructor")
|
|
||||||
}
|
|
||||||
if (data.constructor !== Object) {
|
|
||||||
console.error(`Storage item for store ${this.id} is not an object`)
|
|
||||||
throw new Error("storage item is not an object")
|
|
||||||
}
|
|
||||||
} catch (_) {
|
|
||||||
// if errored, set to null so it generates new one, see below
|
|
||||||
console.error(`Failed to parse storage item for store ${this.id}`)
|
|
||||||
data = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if item doesnt exist, generate from version init
|
|
||||||
if (!data) {
|
|
||||||
data = this.versions[this.currentVersion.toString()].init();
|
|
||||||
}
|
|
||||||
|
|
||||||
// update the data if needed
|
|
||||||
data = this.update(data);
|
|
||||||
|
|
||||||
// add a save object to return value
|
|
||||||
data.save = function save() {
|
|
||||||
localStorage.setItem(store.id, JSON.stringify(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
// return data
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function update(obj) {
|
||||||
|
if (!obj)
|
||||||
|
throw new Error("object to update is not an object");
|
||||||
|
|
||||||
|
// repeat until object fully updated
|
||||||
|
if (obj["--version"] === undefined)
|
||||||
|
obj["--version"] = 0;
|
||||||
|
while (obj["--version"] !== this.currentVersion) {
|
||||||
|
// get version
|
||||||
|
let version = obj["--version"] || 0;
|
||||||
|
if (version.constructor !== Number || version < 0)
|
||||||
|
version = -42; // invalid on purpose so it will reset
|
||||||
|
else {
|
||||||
|
version = (version+1).toString()
|
||||||
|
}
|
||||||
|
console.log(this, version);
|
||||||
|
|
||||||
|
// check if version exists
|
||||||
|
if (!this.versions[version]) {
|
||||||
|
console.error(`Version not found for storage item in store ${this.id}, resetting`);
|
||||||
|
obj = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update object
|
||||||
|
obj = this.versions[version].update(obj);
|
||||||
|
console.log(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if resulting obj is null, use latest version as init object
|
||||||
|
if (obj === null) {
|
||||||
|
console.error(`Storage item for store ${this.id} has been reset due to faulty updates`);
|
||||||
|
return this.versions[this.currentVersion.toString()].init();
|
||||||
|
}
|
||||||
|
|
||||||
|
// updates succesful, return
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
function get() {
|
||||||
|
// get from storage api
|
||||||
|
const store = this;
|
||||||
|
let data = localStorage.getItem(this.id);
|
||||||
|
|
||||||
|
// parse json if item exists
|
||||||
|
if (data) {
|
||||||
|
try {
|
||||||
|
data = JSON.parse(data);
|
||||||
|
if (!data.constructor) {
|
||||||
|
console.error(`Storage item for store ${this.id} has not constructor`)
|
||||||
|
throw new Error("storage item has no constructor")
|
||||||
|
}
|
||||||
|
if (data.constructor !== Object) {
|
||||||
|
console.error(`Storage item for store ${this.id} is not an object`)
|
||||||
|
throw new Error("storage item is not an object")
|
||||||
|
}
|
||||||
|
} catch (_) {
|
||||||
|
// if errored, set to null so it generates new one, see below
|
||||||
|
console.error(`Failed to parse storage item for store ${this.id}`)
|
||||||
|
data = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if item doesnt exist, generate from version init
|
||||||
|
if (!data) {
|
||||||
|
data = this.versions[this.currentVersion.toString()].init();
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the data if needed
|
||||||
|
data = this.update(data);
|
||||||
|
|
||||||
|
// add a save object to return value
|
||||||
|
data.save = function save() {
|
||||||
|
localStorage.setItem(store.id, JSON.stringify(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
// add instance helpers
|
||||||
|
Object.entries(d.instanceHelpers).forEach(([name, helper]) => {
|
||||||
|
if (data[name] !== undefined)
|
||||||
|
throw new Error(`helper name: ${name} on instance of store ${this.id} is reserved`)
|
||||||
|
data[name] = helper.bind(data);
|
||||||
|
})
|
||||||
|
|
||||||
|
// return data
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add functions to store
|
||||||
|
data.get = get.bind(data);
|
||||||
|
data.update = update.bind(data);
|
||||||
|
|
||||||
|
// add static helpers
|
||||||
|
Object.entries(d.staticHelpers).forEach(([name, helper]) => {
|
||||||
|
if (data[name] !== undefined)
|
||||||
|
throw new Error(`helper name: ${name} on store ${data.id} is reserved`)
|
||||||
|
data[name] = helper.bind({});
|
||||||
|
})
|
||||||
|
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -99,6 +118,8 @@ export function versionedStoreBuilder() {
|
||||||
maxVersion: 0,
|
maxVersion: 0,
|
||||||
versions: {},
|
versions: {},
|
||||||
storageString: null,
|
storageString: null,
|
||||||
|
instanceHelpers: {},
|
||||||
|
staticHelpers: {},
|
||||||
},
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -147,6 +168,38 @@ export function versionedStoreBuilder() {
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* register a instance or static helper to the store
|
||||||
|
*
|
||||||
|
* name: name of the helper function
|
||||||
|
* helper: function to execute, the 'this' context is the current storage item (type is instance)
|
||||||
|
* type: "instance" or "static". instance is put on the storage item when you store.get() it, static is on the store
|
||||||
|
*/
|
||||||
|
registerHelper({ name, helper, type }) {
|
||||||
|
// type
|
||||||
|
if (!type)
|
||||||
|
type = "instance"
|
||||||
|
|
||||||
|
// input checking
|
||||||
|
if (!name || name.constructor !== String) {
|
||||||
|
throw new Error("helper name is not a string")
|
||||||
|
}
|
||||||
|
if (!helper || helper.constructor !== Function) {
|
||||||
|
throw new Error("helper function is not a function")
|
||||||
|
}
|
||||||
|
if (!["instance", "static"].includes(type)) {
|
||||||
|
throw new Error("helper type must be either 'instance' or 'static'")
|
||||||
|
}
|
||||||
|
|
||||||
|
// register helper
|
||||||
|
if (type === "instance")
|
||||||
|
this._data.instanceHelpers[name] = helper
|
||||||
|
else if (type === "static")
|
||||||
|
this._data.staticHelpers[name] = helper
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* returns function store based on what has been set
|
* returns function store based on what has been set
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue