respond-framework
Version:
create as fast you think
120 lines (111 loc) • 5.33 kB
JavaScript
;
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.