UNPKG

@adpt/core

Version:
129 lines 4.18 kB
"use strict"; /* * Copyright 2018-2019 Unbounded Systems, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const debug_1 = tslib_1.__importDefault(require("debug")); const util = tslib_1.__importStar(require("util")); const ld = tslib_1.__importStar(require("lodash")); const utils_1 = require("@adpt/utils"); const error_1 = require("./error"); const jsx_1 = require("./jsx"); const debugState = debug_1.default("adapt:state"); function namespaceToKey(ns) { return JSON.stringify(ns); } function keyToNamespace(key) { try { return JSON.parse(key); } catch (e) { if (ld.isError(e)) { throw new Error("Illegal key: " + e.message); } else { throw new Error("Illegal key"); } } } function createStateStore(json) { const ret = new StateStoreImpl(); if (json != null) { const init = JSON.parse(json); for (const key in init) { if (!init.hasOwnProperty(key)) continue; const ns = keyToNamespace(key); const val = init[key]; if (ld.isObject(val)) { ret.setElementState(ns, val); } else if (init[key] === undefined) { //Do nothing } else { throw new Error(`Illegal state in store json: ${key} => ${util.inspect(init[key])}`); } } } return ret; } exports.createStateStore = createStateStore; class StateStoreImpl { constructor() { this.states = new Map(); } setElementState(elem, data) { const key = namespaceToKey(elem); if (debugState.enabled) { const prev = this.states.get(key); const diff = utils_1.diffObjects(prev, data); if (diff) debugState(`State change for ${elem}:\n${diff}`); } if (data === undefined) { this.states.delete(key); } else { this.states.set(key, data); } } elementState(elem) { return this.states.get(namespaceToKey(elem)); } serialize() { const ret = {}; this.states.forEach((elem, key) => { ret[key] = elem; }); return JSON.stringify(ret); } } async function applyStateUpdates(path, store, props, updaters) { if (updaters.length === 0) return false; const prev = store.elementState(path); if (prev === undefined) { throw new error_1.InternalError(`previous Component state should have been initialized`); } let newState = prev; for (const updater of updaters) { // Copy current state so updater can't modify newState // https://github.com/Microsoft/TypeScript/pull/13288 const u = await updater(Object.assign({}, newState), props); newState = Object.assign({}, newState, u); } if (ld.isEqual(prev, newState)) return false; store.setElementState(path, newState); return true; } exports.applyStateUpdates = applyStateUpdates; function stateNamespaceForPath(path) { const elem = ld.last(path); if (!elem) return []; if (!jsx_1.isElementImpl(elem)) throw new Error("Elements must inherit from ElementImpl"); if (jsx_1.isMountedElement(elem)) { return elem.stateNamespace; } else { throw new Error("Cannot compute state namespace for path with unmounted elements" + util.inspect(path)); } } exports.stateNamespaceForPath = stateNamespaceForPath; //# sourceMappingURL=state.js.map