UNPKG

@medamajs/compose

Version:

Composable state management extension for medama with support for hierarchical state layers, dynamic composition, and parallel state synchronization

216 lines 9.53 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.isComposite = exports.composeMedama = void 0; const const_1 = require("./const"); const forEachOnOwnNumerableProps_1 = require("./forEachOnOwnNumerableProps"); const jobQueue_1 = require("./jobQueue"); const modeManager_1 = require("./modeManager"); const traverseThroughPupils_1 = require("./traverseThroughPupils"); const { getReadWorkState, runWithReadModeOn, setSubscriptionMeansRequested, getRequestSubscriptionMeansState, resetReadWorkMode, } = (0, modeManager_1.createReadWorkModeManager)(); const { getUpdateWorkState, startUpdating, signalDeferredJobsToResolve, createConditionalDeferrer, resetUpdateWorkMode, } = (0, modeManager_1.createUpdateWorkModeManager)(); exports.composeMedama = ((layers, initState) => { const { addToQueue: addToStateQueue, processQueue: processStateQueue, resetQueue: resetStateQueue, } = (0, jobQueue_1.createJobQueue)(); const { deferOrRun: addToStateQueueAndSubscribeOrRun, reset: resetStateQueueSubscription } = createConditionalDeferrer(addToStateQueue, processStateQueue); const initReset = () => { resetStateQueue(); resetReadWorkMode(); resetUpdateWorkMode(); resetStateQueueSubscription(); }; initReset(); const pupilRecords = (0, forEachOnOwnNumerableProps_1.forEachOnOwnNumerableProps)(layers, (key, layer) => [key, layer]); const pupilMap = Object.fromEntries(pupilRecords); initState != null && pupilRecords.forEach(([key, { setState }]) => { key in initState && setState(initState[key]); }); let selectorStore = new WeakMap(); const readState = (compositeSelector) => { try { if (selectorStore.has(compositeSelector)) { const { getValue } = selectorStore.get(compositeSelector); return getValue(); } const { processLayer, getSubscriptionMeans } = createLayerProcessorWithSubscriptionMeans(); const isInitiator = !getReadWorkState(); const calculateResultFromLayers = () => (0, traverseThroughPupils_1.traverseThroughPupils)(pupilRecords, processLayer, !isInitiator && getRequestSubscriptionMeansState() ? (combinedLayers) => { combinedLayers[const_1._RELAY_SUBSCRIPTION_MEANS] = getSubscriptionMeans(); return compositeSelector(combinedLayers); } : compositeSelector); if (isInitiator) { const selectorRecord = createSelectorRecord(calculateResultFromLayers, addToStateQueueAndSubscribeOrRun, getSubscriptionMeans); selectorStore.set(compositeSelector, selectorRecord); setSubscriptionMeansRequested(); const { getValue } = selectorRecord; return getValue(); } return calculateResultFromLayers(); } catch (e) { initReset(); throw e; } }; const subscribeToState = (compositeSelector, subscription) => { try { readState(compositeSelector); let currentSelectorStoreRecord = selectorStore.get(compositeSelector); let unsubscribeHandle = null; let currentRevealedSubscriptionJob; const evaluateAndSubscribe = (subscriptionToReveal) => { startUpdating(); const { addSubscription, getValue } = currentSelectorStoreRecord; const possibleSubscriptionJob = subscriptionToReveal(getValue()); currentRevealedSubscriptionJob = typeof possibleSubscriptionJob === 'function' ? possibleSubscriptionJob : subscriptionToReveal; unsubscribeHandle = addSubscription(currentRevealedSubscriptionJob); signalDeferredJobsToResolve(); }; evaluateAndSubscribe(subscription); const unsubscribe = () => { unsubscribeHandle === null || unsubscribeHandle === void 0 ? void 0 : unsubscribeHandle(); unsubscribeHandle = null; }; const resubscribe = (subscriptionToResubscribe) => { unsubscribe(); evaluateAndSubscribe(subscriptionToResubscribe); }; const transfer = (selectorToTransferTo) => { unsubscribe(); readState(selectorToTransferTo); currentSelectorStoreRecord = selectorStore.get(selectorToTransferTo); evaluateAndSubscribe(currentRevealedSubscriptionJob); }; return { unsubscribe, resubscribe, transfer }; } catch (e) { initReset(); throw e; } }; const setState = (stateChange) => { try { const isUpdateInitiator = !getUpdateWorkState(); startUpdating(); const mergeToState = typeof stateChange === 'function' ? readState(stateChange) : stateChange; (0, forEachOnOwnNumerableProps_1.forEachOnOwnNumerableProps)(mergeToState, (key, toMerge) => { var _a; const { setState: setNestedState } = (_a = pupilMap[key]) !== null && _a !== void 0 ? _a : {}; setNestedState === null || setNestedState === void 0 ? void 0 : setNestedState(toMerge); }); return [mergeToState, isUpdateInitiator && signalDeferredJobsToResolve()][0]; } catch (e) { initReset(); throw e; } }; const resetState = (initState) => { initReset(); pupilRecords.forEach(([key, { resetState }]) => { resetState(initState === null || initState === void 0 ? void 0 : initState[key]); }); selectorStore = new WeakMap(); }; const addLayers = (layersToAdd, initState) => (0, exports.composeMedama)(Object.assign(Object.assign({}, layers), layersToAdd), initState); const deleteLayers = (layersToDelete) => { const nextLayers = Object.assign({}, layers); (Array.isArray(layersToDelete) ? layersToDelete : [layersToDelete]).forEach((layerK) => { delete nextLayers[layerK]; }); return (0, exports.composeMedama)(nextLayers); }; const pupil = { readState, subscribeToState, setState, resetState, addLayers, deleteLayers, }; return Object.assign(pupil, { pupil }); }); const createLayerProcessorWithSubscriptionMeans = () => { const subscriptionMeans = []; const processLayer = (key, layerState, subscribeToLayer, selectorIdentity, combinedLayers = Object.defineProperty(Object.create(null), const_1._COMPOSITE_STATE_SIGNATURE, { value: true, })) => { var _a; combinedLayers[key] = layerState; if (getRequestSubscriptionMeansState()) { if (const_1._RELAY_SUBSCRIPTION_MEANS in layerState) { (_a = layerState[const_1._RELAY_SUBSCRIPTION_MEANS]) === null || _a === void 0 ? void 0 : _a.forEach((chunk) => { subscriptionMeans.push(chunk); }); delete layerState[const_1._RELAY_SUBSCRIPTION_MEANS]; } else { subscriptionMeans.push((subscription) => subscribeToLayer(selectorIdentity, subscription).unsubscribe); } } return combinedLayers; }; const getSubscriptionMeans = () => subscriptionMeans; return { processLayer, getSubscriptionMeans }; }; const createSelectorRecord = (calculateResult, addToStateQueueAndSubscribeOrRun, getSubscriptionMeans) => { let unsubscribePoolFromLayers; let isRegistered = false; const registerTrigger = () => { if (isRegistered) return; const determineSubscriptionPoolExecution = () => { addToStateQueueAndSubscribeOrRun(selectorTrigger); }; const unsubscribeChunks = getSubscriptionMeans().map((subscribeToLayer) => subscribeToLayer(() => determineSubscriptionPoolExecution)); unsubscribePoolFromLayers = () => { unsubscribeChunks.forEach((unsubscribe) => { unsubscribe(); }); }; isRegistered = true; }; let memValue; let isToRecalculateValue = true; const runSelectorWithMemoization = () => { if (isToRecalculateValue) { runWithReadModeOn(() => { memValue = calculateResult(); }); isToRecalculateValue = false; } }; const jobs = new Set(); const selectorTrigger = () => { isToRecalculateValue = true; if (jobs.size === 0) { unsubscribePoolFromLayers(); isRegistered = false; return; } runSelectorWithMemoization(); jobs.forEach((job) => { job(memValue); }); }; const addSubscription = (subscriptionJob) => { jobs.add(subscriptionJob); return () => { jobs.delete(subscriptionJob); }; }; const getValue = () => { runSelectorWithMemoization(); registerTrigger(); return memValue; }; return { addSubscription, getValue }; }; const isComposite = (state) => const_1._COMPOSITE_STATE_SIGNATURE in state; exports.isComposite = isComposite; //# sourceMappingURL=composeMedama.js.map