UNPKG

@modern-js-reduck/store

Version:

The meta-framework suite designed from scratch for frontend-focused modern web development.

97 lines (96 loc) 3.26 kB
import { _ as _object_spread } from "@swc/helpers/_/_object_spread"; import mountModel from "./mountModel"; import { combineSubscribe } from "./subscribe"; import { getComputedDepModels, isModel } from "../utils/misc"; function createUseModel(context) { function useModel(...args) { const flattenedArgs = Array.isArray(args[0]) ? [ ...args[0], ...args.slice(1) ] : args; flattenedArgs.forEach((model) => { if (isModel(model)) { mountModel(context, model); } }); const { getState, getActions, actualModels, subscribe } = parseModelParams(context, flattenedArgs); const computedArr = actualModels.map((m) => { const { modelDesc: { computed } } = context.apis.getModel(m); return computed; }); const computedDepModels = getComputedDepModels(computedArr); computedDepModels.forEach((model) => { if (isModel(model)) { mountModel(context, model); } }); let [state, actions] = [ getState(), getActions() ]; ({ state, actions } = context.pluginCore.invokePipeline("useModel", { state, actions }, { models: actualModels, mountedModels: actualModels.map((model) => context.apis.getModel(model)) })); return [ state, actions, subscribe ]; } return useModel; } const parseModelParams = (context, _models) => { const models = Array.isArray(_models) ? _models : [ _models ]; const actualModels = []; const selectors = []; for (const model of models) { if (isModel(model)) { actualModels.push(model); } else { selectors.push(model); } } const [stateSelector, actionSelector] = selectors; if (actualModels.length > 1) { actualModels.forEach((m) => { if (Object.prototype.toString.call(context.apis.getModel(m).state) !== "[object Object]") { throw new Error(`You cant use multiple model one of which's state is primitive data`); } }); } const getStateWithComputed = (model) => { const { state, modelDesc: { computed } } = context.apis.getModel(model); let computedState; if (computed) { computedState = Object.keys(computed).reduce((curState, computedKey) => { curState[computedKey] = state[computedKey]; return curState; }, {}); return _object_spread({}, state, computedState); } return state; }; const finalStateSelector = (...models2) => { if (stateSelector) { return stateSelector(...actualModels.map((model) => getStateWithComputed(model))); } if (models2.length === 1) { return getStateWithComputed(models2[0]); } return models2.reduce((res, model) => _object_spread({}, res, getStateWithComputed(model)), {}); }; const finalActionSelector = actionSelector || ((...actions) => actions.reduce((res, action) => Object.assign(res, action), {})); return { getState: () => finalStateSelector(...actualModels), getActions: () => finalActionSelector(...actualModels.map((model) => context.apis.getModel(model).actions)), subscribe: (handler) => combineSubscribe(context, ...actualModels.map((model) => context.apis.getModelSubscribe(model)))(handler), actualModels }; }; export { createUseModel };