From 2498e3e1d3778fdc784b9a7edaa5443050726b9b Mon Sep 17 00:00:00 2001 From: Greg Fodor <gfodor@gmail.com> Date: Fri, 9 Mar 2018 18:32:07 -0800 Subject: [PATCH] Added store --- src/storage/store.js | 77 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 src/storage/store.js diff --git a/src/storage/store.js b/src/storage/store.js new file mode 100644 index 000000000..e4b814396 --- /dev/null +++ b/src/storage/store.js @@ -0,0 +1,77 @@ +import uuid from "uuid/v4"; +import { Validator } from "jsonschema"; + +const LOCAL_STORE_KEY = "___mozilla_hubs"; +const STORE_STATE_CACHE_KEY = Symbol(); +const validator = new Validator(); + +// Durable (via local-storage) schema-enforced state that is meant to be consumed via forward data flow. +// (Think flux but with way less incidental complexity, at least for now :)) +const SCHEMA = { + id: "/MozillaHubsStore", + + definitions: { + profile: { + type: "object", + additionalProperties: false, + properties: { + display_name: { type: "string", pattern: "^[A-Za-z0-9-]{3,32}$" }, + } + } + }, + + type: "object", + + properties: { + id: { type: "string", pattern: "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$" }, + profile: { "$ref": "#/definitions/profile" }, + }, + + additionalProperties: false +} + +export default class Store { + subscribers = new Set(); + + constructor() { + if (localStorage.getItem(LOCAL_STORE_KEY) === null) { + localStorage.setItem(LOCAL_STORE_KEY, JSON.stringify({ id: uuid() })); + } + } + + get state() { + if (!this.hasOwnProperty(STORE_STATE_CACHE_KEY)) { + this[STORE_STATE_CACHE_KEY] = JSON.parse(localStorage.getItem(LOCAL_STORE_KEY)); + } + + return this[STORE_STATE_CACHE_KEY]; + } + + subscribe(subscriber) { + this.subscribers.add(subscriber); + } + + update(newState) { + if (newState.id) { + console.error("Store id is immutable."); + return; + } + + const finalState = { ...this.state, ...newState }; + const isValid = validator.validate(finalState, SCHEMA).valid; + + if (!isValid) { + console.warn(`Write of ${JSON.stringify(finalState)} to store failed schema validation.`) + return; + } + + localStorage.setItem(LOCAL_STORE_KEY, JSON.stringify(finalState)); + delete this[STORE_STATE_CACHE_KEY]; + + for (const subscriber of this.subscribers) { + subscriber(); + } + + return finalState; + } +} -- GitLab