UNPKG

respond-framework

Version:
120 lines (111 loc) 5.33 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _createSeed = require("./helpers/createSeed.js"); var _createSettings = require("./helpers/createSettings.js"); var _nestSettings = require("./helpers/nestSettings.js"); var _nestAtBranch = require("./helpers/nestAtBranch.js"); var _deterministicCounter = require("../../helpers/deterministicCounter.js"); var _constants = require("../../helpers/constants.js"); const build = ({ respond, state }) => { const { system, top, branches } = respond; const { replayState, seed, baseState } = system; const depth = []; const { configs, settings } = createConfigsAndSettings(top, branches, depth, replayState); state = replayState.status === 'session' ? state : baseState.replayTools ??= {}; // assign to baseState to override previous replayTools state that would otherwise be assigned in hydrateModules that runs after at the end of createModule state.configs = configs; state.settings = settings; replayState.settings ??= (0, _nestSettings.nestAllSettings)(configs, settings); // replayState.settings is generated by tapping reload, eg while focusing a particular module; it will then be saved to test files and brought back when those tests are played or via sessionStorage on refreshes; however on first visit, it won't exist, so we need to generate the full settings tree with default settings, as if the top level module is the focusedBranch const nextSeed = system.seed = { __counterRef: (0, _deterministicCounter.createCounterRef)(seed) }; if (_constants.isProd) return; depth.forEach(createDbWithSeed(nextSeed, seed)); // depth-first so parent modules' createSeed function can operate on existing seeds from child modules }; var _default = exports.default = build; const createConfigsAndSettings = (top, branches, depth, replayState) => { const { branch: focusedBranch, settings: input } = replayState; const configs = {}; const settings = {}; const branch = input?.settingsBranchDependency ?? focusedBranch; // settings with a module start higher than the branch where they get their ancestor replays from const nested = (0, _nestAtBranch.default)(branch, input); // input is provided starting at the given module, but we need to traverse from the top to gather possible parent replays createAllSettingsBreadth(top, nested, branches, depth, focusedBranch, configs, settings); return { configs, settings }; }; const createAllSettingsBreadth = (mod, input, branches, depth, fb, configs, settings, replays = { config: {}, settings: {} }) => { if (mod.db) { replays = mod.db.replays ?? mod.replays ?? {}; // db won't exist in production client-side replays.db = mod.db; replays.db.branchAbsolute = mod.branchAbsolute; // callDatabase uses this to determine inherited db's *actual* absolute branch replays.settings = (0, _createSettings.default)(replays.config, input); } else if (mod.replays) { mod.replays.db = replays.db; // db inherited (but not replays) replays = mod.replays; replays.settings = (0, _createSettings.default)(mod.replays.config, input); } configs[mod.branchAbsolute] = replays.config; settings[mod.branchAbsolute] = replays.settings; // replays + db inherited if no mod.db/replays const state = branches[mod.branch]; // branch might be outside focused module tree if (state) Object.getPrototypeOf(state).replays = state.respond.replays = replays; // now, by a sharing a reference, child modules who didn't have replays will have BOTH the correct top-down inherited settings + bottom-up merged db/seed depth.unshift([mod, replays]); for (const k of mod.moduleKeys) { if (k === 'replayTools') continue; createAllSettingsBreadth(mod[k], input?.[k], branches, depth, fb, configs, settings, replays); } }; const createDbWithSeed = (nextSeed, seed, shared = {}) => ([mod, replays]) => { if (!mod.db) return; // only modules that have actual replays and therefore db/seed data const b = mod.branchAbsolute; const { db = {}, settings = {}, createSeed = _createSeed.default, ...options } = replays; nextSeed[b] = {}; db.tableNames.forEach(k => mergeTable(nextSeed[b], seed?.[b], shared, k, db[k])); if (!seed) createSeed(settings, options, db); }; const mergeTable = (nextSeed, seed, shared, key, table) => { if (table.share === false) { table.docs ??= {}; table.docs = seed ? Object.assign(table.docs, seed[k]) : table.docs; nextSeed[k] = table.docs; return; } const k = table.shareKey ?? key; const docs = shared[k]?.docs; table.docs = seed ? docs ? Object.assign(docs, seed[k]) : seed[k] // seed[k] will contain the same docs, but we must link the object reference so they continue to update together (note: seed only exists for hmr + session satuses) : docs ?? {}; nextSeed[k] = table.docs; shared[k] = table; }; // Collections with the same name will share `docs` object, and ancestor modules // will receive collections created in child modules even if they don't themselves have it. // This is to ensure docs sharing will jump over intermediary modules that don't require // the given table, and so by the end `state.respond.replays.db` will contain all collections.