lanka 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/{LankaScenarioLocator-BGQHwf3n.d.ts → LankaScenarioLocator-CLkq4MaJ.d.ts} +1 -1
  2. package/dist/{LankaSharedStoreLocator-MvCpav5F.d.ts → LankaSharedStoreLocator-zS2kLu-S.d.ts} +21 -0
  3. package/dist/_extend/index.d.ts +4 -4
  4. package/dist/_extend/index.js +3 -3
  5. package/dist/_internal/index.d.ts +3 -3
  6. package/dist/{activeRuntime-FcsSJvUg.d.ts → activeRuntime-DT4gB16d.d.ts} +2 -2
  7. package/dist/bootstrap/index.d.ts +4 -4
  8. package/dist/bootstrap/index.js +5 -5
  9. package/dist/{chunk-RYFZCAQ3.js → chunk-63ST2UKP.js} +12 -12
  10. package/dist/chunk-63ST2UKP.js.map +1 -0
  11. package/dist/{chunk-Q3SOVBIJ.js → chunk-HZAIAGWS.js} +4 -4
  12. package/dist/{chunk-Q3SOVBIJ.js.map → chunk-HZAIAGWS.js.map} +1 -1
  13. package/dist/{chunk-FIR4XTBL.js → chunk-MYZQYOMD.js} +10 -12
  14. package/dist/chunk-MYZQYOMD.js.map +1 -0
  15. package/dist/{chunk-ILQNYQY5.js → chunk-UE2C76OR.js} +32 -18
  16. package/dist/chunk-UE2C76OR.js.map +1 -0
  17. package/dist/{chunk-EWVDJYCC.js → chunk-YXI4OQEV.js} +2 -6
  18. package/dist/chunk-YXI4OQEV.js.map +1 -0
  19. package/dist/{createLankaScope-Bc_vChRs.d.ts → createLankaScope-BiFxNQgl.d.ts} +1 -1
  20. package/dist/gateway/index.js +1 -2
  21. package/dist/gateway/index.js.map +1 -1
  22. package/dist/index.d.ts +4 -4
  23. package/dist/index.js +5 -5
  24. package/dist/locator/index.d.ts +6 -54
  25. package/dist/locator/index.js +1 -1
  26. package/dist/scenario/index.js +2 -2
  27. package/dist/viewmodel/index.js +4 -2
  28. package/dist/viewmodel/index.js.map +1 -1
  29. package/package.json +2 -2
  30. package/skills/lanka-core/SKILL.md +1 -1
  31. package/skills/lanka-core/reference.md +1 -1
  32. package/skills/lanka-packages/SKILL.md +1 -1
  33. package/dist/chunk-EWVDJYCC.js.map +0 -1
  34. package/dist/chunk-FIR4XTBL.js.map +0 -1
  35. package/dist/chunk-ILQNYQY5.js.map +0 -1
  36. package/dist/chunk-RYFZCAQ3.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/viewmodel/_abstractions/lanka-vm-environment/ALankaVMEnvironment.ts","../../src/viewmodel/_abstractions/lanka-vm/ALankaVM.ts","../../src/viewmodel/_internal/create-lanka-blind-spot-trap/createLankaBlindSpotTrap.ts","../../src/viewmodel/_internal/create-lanka-scenario-binder/createLankaScenarioBinder.ts","../../src/viewmodel/_internal/create-lanka-tracked-hook/createLankaTrackedHook.ts","../../src/viewmodel/_utils/resolve-lanka-dependency/resolveLankaDependency.ts","../../src/viewmodel/_factories/create-lanka-vm/createLankaVM.ts","../../src/viewmodel/_internal/create-lazy-lanka-hook/createLazyLankaHook.ts","../../src/viewmodel/_factories/create-lazy-lanka-vm/createLazyLankaVM.ts","../../src/viewmodel/_abstractions/lanka-stateless-vm/ALankaStatelessVM.ts","../../src/viewmodel/_factories/create-stateless-lanka-vm/createStatelessLankaVM.ts","../../src/viewmodel/_factories/create-lazy-stateless-lanka-vm/createLazyStatelessLankaVM.ts","../../src/viewmodel/_factories/create-shared-store-lanka-vm/createSharedStoreLankaVM.ts","../../src/viewmodel/_factories/create-lazy-shared-store-lanka-vm/createLazySharedStoreLankaVM.ts","../../src/viewmodel/_abstractions/lanka-shared-store-vm/ALankaSharedStoreVM.ts","../../src/viewmodel/_abstractions/lanka-shared-store/ALankaSharedStore.ts","../../src/viewmodel/_factories/create-lanka-shared-store/createLankaSharedStore.ts"],"sourcesContent":["/**\n * What every ViewModel is given, and the two moments it is told about.\n *\n * The three ViewModel shapes — stateful, stateless, over a shared store — differ\n * in where their state lives and in nothing else about this: each is handed a\n * data layer and a set of collaborators, and each is told when its scenarios are\n * bound and when they are about to be unbound.\n *\n * Stated once because a fifth hook added to two of the three is exactly the\n * divergence `skills/parity/SKILL.md` is written against, and three copies of a\n * default is how that starts.\n *\n * It is not a role and nothing extends it directly: the three bases do, and a\n * consumer extends one of them.\n */\nexport abstract class ALankaVMEnvironment<\n\tTGateways extends object = Record<string, never>,\n\tServices extends object = Record<string, never>,\n> {\n\t/** What `createGateways` answered: the data layer, kept apart from services. */\n\tprotected gateways!: TGateways;\n\n\t/** What `createServices` answered: everything that is not a gateway. */\n\tprotected services!: Services;\n\n\t/** The data layer, built once per ViewModel. */\n\tprotected createGateways(): TGateways {\n\t\treturn {} as TGateways;\n\t}\n\n\t/** Non-gateway collaborators, built once per ViewModel. */\n\tprotected createServices(): Services {\n\t\treturn {} as Services;\n\t}\n\n\t/** Runs after the scenarios are bound. */\n\tprotected onInit(): void {}\n\n\t/** Runs when the screen goes away, before the scenarios are unbound. */\n\tprotected onReset(): void {}\n}\n","import { ALankaVMEnvironment } from \"../lanka-vm-environment/ALankaVMEnvironment\";\nimport { create, StoreApi, UseBoundStore } from \"zustand\";\nimport { getLankaFlags } from \"../../../config/get-lanka-flags/getLankaFlags\";\nimport { createLankaBlindSpotTrap } from \"../../_internal/create-lanka-blind-spot-trap/createLankaBlindSpotTrap\";\nimport { createLankaScenarioBinder } from \"../../_internal/create-lanka-scenario-binder/createLankaScenarioBinder\";\nimport { createLankaTrackedHook } from \"../../_internal/create-lanka-tracked-hook/createLankaTrackedHook\";\nimport { ILankaScenarioVM } from \"../../../scenario/_interfaces/ILankaScenarioVM\";\nimport { lankaScenarioBootstrap } from \"../../../scenario/lanka-scenario-bootstrap/LankaScenarioBootstrap\";\nimport { lankaLogger } from \"../../../logger/lanka-logger/LankaLogger\";\nimport type { ILankaScenario } from \"../../../scenario/_interfaces/ILankaScenario\";\nimport type { ILankaVMContext } from \"../../_interfaces/ILankaVMContext\";\nimport type { TLankaVMEnhancer } from \"../../_types/TLankaVMEnhancer\";\nimport type { TLankaVMStateCreator } from \"../../_types/TLankaVMStateCreator\";\nimport type { TUnknownLankaScenarioBinding } from \"../../_types/TUnknownLankaScenarioBinding\";\n\n/**\n * A ViewModel written as a class: the state a screen reads, and the only place a\n * gateway is called from.\n *\n * This is the implementation of the role, and `createLankaVM` is the same thing\n * reached the other way — a subclass built from an options object. Neither style\n * can do what the other cannot, because there is nothing here to diverge from.\n *\n * The protected surface IS the functional context, member for member:\n * `set`, `get`, `gateways`, `services`, `trigger`. What the config supplies as a\n * value or a thunk, the class supplies by overriding a method of the same name —\n * `states`, `scenarioHandlers`, `enhancers`, `onInit`, `onReset` — with the two\n * dependency suppliers named `createGateways` and `createServices`, because\n * `gateways` and `services` already name what they answer.\n *\n * ```ts\n * class TodoVM extends ALankaVM<ITodoState, ITodoActions, ITodoGateways> {\n * \tprotected readonly name = \"TodoVM\";\n *\n * \tprotected states(): ITodoState {\n * \t\treturn { todos: [], isLoading: false };\n * \t}\n *\n * \tprotected createGateways(): ITodoGateways {\n * \t\treturn { todo: new TodoGateway() };\n * \t}\n *\n * \tprotected createActions(): ITodoActions {\n * \t\treturn {\n * \t\t\tload: async () => {\n * \t\t\t\tthis.set({ isLoading: true });\n * \t\t\t\tthis.set({ todos: await this.gateways.todo.list(), isLoading: false });\n * \t\t\t},\n * \t\t};\n * \t}\n * }\n *\n * export const useTodoVM = new TodoVM().build();\n * ```\n *\n * The access-tracking blind spot the functional style documents is the same one\n * here, and `enableAccessTrackingOptimization` is the same switch. A consumer\n * re-renders only for state keys it READ off the returned proxy; an action that\n * DERIVES a value reads the store through `get`, which the proxy never sees, so a\n * component whose only link to a key is such a getter never re-renders for it. In\n * development the mismatch announces itself by name rather than by a frozen\n * screen. Canon: `skills/parity/SKILL.md`.\n */\nexport abstract class ALankaVM<\n\tState extends object,\n\tActions extends object,\n\tTGateways extends object = Record<string, never>,\n\tServices extends object = Record<string, never>,\n> extends ALankaVMEnvironment<TGateways, Services> {\n\t/** Names the ViewModel in the logs, the scenario registry and the blind-spot warning. */\n\tprotected abstract readonly name: string;\n\n\t/**\n\t * Turn off when one broad consumer reads most fields, or when an action derives\n\t * what the screen shows — proxy tracking then costs more than it saves, and in\n\t * the second case it cannot see the read at all.\n\t */\n\tprotected readonly enableAccessTrackingOptimization: boolean = true;\n\n\t/** Writes state. Available from `createActions` onwards, never before. */\n\tprotected set!: StoreApi<State & Actions & ILankaScenarioVM>[\"setState\"];\n\n\t/** Reads state. The read a tracked hook cannot see — hence the switch above. */\n\tprotected get!: () => State & Actions & ILankaScenarioVM;\n\n\t/** Fires a scenario, which every ViewModel bound to it then hears. */\n\tprotected trigger = <TData>(scenario: ILankaScenario<TData>, data?: TData): void => {\n\t\tscenario.trigger(data);\n\t};\n\n\t/** The reactive fields the screen reads. */\n\tprotected states(): State {\n\t\treturn {} as State;\n\t}\n\n\t/** The scenarios this ViewModel listens to, unsubscribed for it on reset. */\n\tprotected scenarioHandlers(): TUnknownLankaScenarioBinding<\n\t\tState & Actions,\n\t\tTGateways,\n\t\tServices\n\t>[] {\n\t\treturn [];\n\t}\n\n\t/** Store middleware — `persist`, `lankaDevtools` — the last one applied outermost. */\n\tprotected enhancers(): TLankaVMEnhancer<State & Actions & ILankaScenarioVM>[] {\n\t\treturn [];\n\t}\n\n\t/** The actions the screen calls. Written against `this.set` and `this.get`. */\n\tprotected abstract createActions(): Actions;\n\n\t/**\n\t * The protected surface as an object, for the functional style.\n\t *\n\t * Assembled INSIDE the class because that is the only place `protected` can be\n\t * read — a context built from outside could carry only the public half, which is\n\t * the wrong half. Canon: `skills/parity/SKILL.md` section 3a.\n\t */\n\tprotected toStyleContext(): ILankaVMContext<\n\t\tState & Actions & ILankaScenarioVM,\n\t\tTGateways,\n\t\tServices\n\t> {\n\t\treturn {\n\t\t\tset: this.set,\n\t\t\tget: this.get,\n\t\t\tgateways: this.gateways,\n\t\t\tservices: this.services,\n\t\t\ttrigger: this.trigger,\n\t\t};\n\t}\n\n\t/** Builds the hook a screen calls. One store per call. */\n\tpublic build(): UseBoundStore<StoreApi<State & Actions & ILankaScenarioVM>> {\n\t\ttype TFullState = State & Actions & ILankaScenarioVM;\n\n\t\tlankaLogger.printViewModelLog(\"START Create VM\", this.name);\n\n\t\tconst blindSpot = createLankaBlindSpotTrap(\n\t\t\tthis.name,\n\t\t\tgetLankaFlags().isDevelopment === true,\n\t\t);\n\n\t\t// Asked once. Every call builds a fresh array, and this one used to be made\n\t\t// twice per ViewModel: once to bind the scenarios, once to decide whether to\n\t\t// register the ViewModel at all.\n\t\tconst bindings = this.scenarioHandlers();\n\n\t\tconst stateCreator: TLankaVMStateCreator<TFullState> = (set, get) => {\n\t\t\tthis.set = set;\n\t\t\tthis.get = blindSpot.observeGet(get);\n\t\t\tthis.gateways = this.createGateways();\n\t\t\tthis.services = this.createServices();\n\n\t\t\tconst actions = blindSpot.observeActions(this.createActions());\n\n\t\t\tconst { initializeScenario, resetScenario } = createLankaScenarioBinder({\n\t\t\t\tname: this.name,\n\t\t\t\tbindings,\n\t\t\t\tcontext: () => this.toStyleContext(),\n\t\t\t\tonInit: () => {\n\t\t\t\t\tthis.onInit();\n\t\t\t\t},\n\t\t\t\tonReset: () => {\n\t\t\t\t\tthis.onReset();\n\t\t\t\t},\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\t...this.states(),\n\t\t\t\t...actions,\n\t\t\t\tinitializeScenario,\n\t\t\t\tresetScenario,\n\t\t\t};\n\t\t};\n\n\t\tconst enhancedCreator = this.enhancers().reduce<TLankaVMStateCreator<TFullState>>(\n\t\t\t(creator, enhance) => enhance(creator),\n\t\t\tstateCreator,\n\t\t);\n\n\t\tconst store = create<TFullState>()(enhancedCreator);\n\n\t\tconst registerScenarioViewModel = (viewModel: ILankaScenarioVM): void => {\n\t\t\tif (bindings.length > 0) {\n\t\t\t\tlankaScenarioBootstrap.registerViewModel(viewModel, this.name);\n\t\t\t}\n\t\t};\n\n\t\tif (!this.enableAccessTrackingOptimization) {\n\t\t\tregisterScenarioViewModel(store.getState());\n\t\t\tlankaLogger.printViewModelLog(\"FINISH Create VM\", this.name);\n\n\t\t\treturn store;\n\t\t}\n\n\t\tconst useOptimizedViewModel = createLankaTrackedHook<TFullState>({\n\t\t\tsubscribe: (onChange) => store.subscribe(onChange),\n\t\t\treadState: () => store.getState(),\n\t\t\tonUntrackedChange: blindSpot.isArmed ? blindSpot.report : undefined,\n\t\t}) as UseBoundStore<StoreApi<TFullState>>;\n\n\t\tuseOptimizedViewModel.setState = store.setState;\n\t\tuseOptimizedViewModel.getState = store.getState;\n\t\tuseOptimizedViewModel.getInitialState = store.getInitialState;\n\t\tuseOptimizedViewModel.subscribe = store.subscribe;\n\n\t\tregisterScenarioViewModel(useOptimizedViewModel.getState());\n\n\t\tlankaLogger.printViewModelLog(\"FINISH Create VM\", this.name);\n\n\t\treturn useOptimizedViewModel;\n\t}\n}\n","export interface ILankaBlindSpotTrap {\n\t/** Whether the trap is armed. Everything below is inert when it is not. */\n\treadonly isArmed: boolean;\n\t/** Wraps `get` so reads made inside an action are attributed to it. */\n\tobserveGet: <TState>(get: () => TState) => () => TState;\n\t/** Wraps the actions so the trap knows which one is running. */\n\tobserveActions: <TActions extends object>(declared: TActions) => TActions;\n\t/** Reports a change that will not re-render, when the component reads the key. */\n\treport: (\n\t\ttrackedKeys: Set<string>,\n\t\tnext: Record<string, unknown>,\n\t\tprev: Record<string, unknown>,\n\t) => void;\n}\n\n/**\n * The blind spot: a key the component reads through a GETTER.\n *\n * Access tracking sees direct reads off the proxy. A key reached only inside a\n * derived getter is invisible to it, so a change to that key re-renders nothing\n * and the screen freezes with no error anywhere.\n *\n * The trap watches which keys each action reads through `get()`, and warns when\n * one of those changes without a tracked key changing with it.\n *\n * Development only: in production this is work on a hot path plus console noise\n * for somebody who does not write the code. Disarmed, every method is identity.\n */\nexport const createLankaBlindSpotTrap = (\n\tviewModelName: string,\n\tisArmed: boolean,\n): ILankaBlindSpotTrap => {\n\tif (!isArmed) {\n\t\treturn {\n\t\t\tisArmed: false,\n\t\t\tobserveGet: (get) => get,\n\t\t\tobserveActions: (declared) => declared,\n\t\t\treport: () => undefined,\n\t\t};\n\t}\n\n\t/** Action name → state keys it read through `get()`, past the proxy. */\n\tconst indirectReads = new Map<string, Set<string>>();\n\t/** Keys already warned about: a second warning adds nothing. */\n\tconst warnedKeys = new Set<string>();\n\tlet activeActionName: string | null = null;\n\n\treturn {\n\t\tisArmed: true,\n\n\t\tobserveGet<TState>(get: () => TState): () => TState {\n\t\t\treturn () => {\n\t\t\t\tconst state = get();\n\t\t\t\tconst actionName = activeActionName;\n\t\t\t\tif (actionName === null) return state;\n\n\t\t\t\treturn new Proxy(state as object, {\n\t\t\t\t\tget(target, prop, receiver) {\n\t\t\t\t\t\tif (typeof prop === \"string\") {\n\t\t\t\t\t\t\tlet keys = indirectReads.get(actionName);\n\t\t\t\t\t\t\tif (!keys) {\n\t\t\t\t\t\t\t\tkeys = new Set<string>();\n\t\t\t\t\t\t\t\tindirectReads.set(actionName, keys);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tkeys.add(prop);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn Reflect.get(target, prop, receiver) as unknown;\n\t\t\t\t\t},\n\t\t\t\t}) as TState;\n\t\t\t};\n\t\t},\n\n\t\tobserveActions<TActions extends object>(declared: TActions): TActions {\n\t\t\tconst observed = { ...declared } as Record<string, unknown>;\n\n\t\t\tfor (const [name, value] of Object.entries(declared)) {\n\t\t\t\tif (typeof value !== \"function\") continue;\n\n\t\t\t\tobserved[name] = (...args: unknown[]) => {\n\t\t\t\t\t// Restored rather than cleared: actions call each other, and clearing\n\t\t\t\t\t// would attribute the caller's later reads to nobody.\n\t\t\t\t\tconst previous = activeActionName;\n\t\t\t\t\tactiveActionName = name;\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn (value as (...a: unknown[]) => unknown)(...args);\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tactiveActionName = previous;\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn observed as TActions;\n\t\t},\n\n\t\treport(trackedKeys, next, prev): void {\n\t\t\tfor (const [changedKey, value] of Object.entries(next)) {\n\t\t\t\tif (Object.is(value, prev[changedKey])) continue;\n\t\t\t\tif (trackedKeys.has(changedKey) || warnedKeys.has(changedKey)) continue;\n\n\t\t\t\t// Not every untracked key is a fault: not reading what you do not need\n\t\t\t\t// is exactly what tracking exists for. The fault is a key the component\n\t\t\t\t// DOES read — through a getter taken off the proxy.\n\t\t\t\tconst viaGetter = [...trackedKeys].some((key) =>\n\t\t\t\t\tindirectReads.get(key)?.has(changedKey),\n\t\t\t\t);\n\t\t\t\tif (!viaGetter) continue;\n\n\t\t\t\twarnedKeys.add(changedKey);\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`[lanka] ${viewModelName}: key \"${changedKey}\" changed but no re-render will follow. ` +\n\t\t\t\t\t\t`The component reads it only through a getter, and tracking sees direct proxy reads only. ` +\n\t\t\t\t\t\t`Set enableAccessTrackingOptimization: false on this ViewModel — ` +\n\t\t\t\t\t\t`destructuring the key in the view \"for the side effect\" reads as dead code and will not survive a refactor.`,\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t};\n};\n","/**\n * A subscription option bag, as wide as the bus accepts.\n *\n * The binder passes it through and reads only `usedBy`; naming the rest here\n * would make this file a second declaration of the bus's options.\n */\nexport type TLankaScenarioBindingOptions = Record<string, unknown> & { usedBy?: string };\n\n/**\n * What the binder needs of a binding, and nothing more.\n *\n * Structural rather than the concrete `ILankaScenarioBinding`: three ViewModel\n * families declare their own binding type over their own context, and the binder\n * only ever calls `subscribe` and `handler`.\n */\nexport interface ILankaScenarioBindingLike<TContext, TData = unknown> {\n\tscenario: {\n\t\teventType: string;\n\t\tsubscribe: (\n\t\t\tcallback: (data?: TData) => void,\n\t\t\toptions?: TLankaScenarioBindingOptions,\n\t\t) => () => void;\n\t};\n\thandler: (context: TContext) => (data?: TData) => void;\n\toptions?: TLankaScenarioBindingOptions;\n}\n\nexport interface ILankaScenarioBinderConfig<TContext> {\n\t/** The ViewModel's name, reported to the bus as the subscriber. */\n\tname: string;\n\t/** What to bind. A ViewModel with none still gets a working binder. */\n\tbindings?: readonly ILankaScenarioBindingLike<TContext>[];\n\t/** The context handlers are built with, read at bind time. */\n\tcontext: () => TContext;\n\tonInit?: (context: TContext) => void;\n\tonReset?: (context: TContext) => void;\n}\n\nexport interface ILankaScenarioBinder {\n\t/** Whether the bindings are live. */\n\treadonly isInitialized: boolean;\n\t/** Subscribes every binding once. A second call does nothing. */\n\tinitializeScenario: () => void;\n\t/** Releases every subscription and allows a later re-initialisation. */\n\tresetScenario: () => void;\n}\n\n/**\n * The scenario lifetime of a ViewModel: bind once, release on reset.\n *\n * All three ViewModel families need exactly this, and all three had written it\n * out — two with an array plus a Set of seen event types, one with a Map. The\n * Map is the shape kept, because it does both jobs with one structure: the key\n * prevents a second subscription to the same event, and the value is the\n * function that releases THIS subscription.\n *\n * Releasing by callback identity, which an array invites, removes the first\n * entry carrying that callback rather than the caller's own — two handlers whose\n * closures compare equal cancel each other.\n */\nexport const createLankaScenarioBinder = <TContext>(\n\tconfig: ILankaScenarioBinderConfig<TContext>,\n): ILankaScenarioBinder => {\n\tconst subscriptions = new Map<string, () => void>();\n\tlet isInitialized = false;\n\n\treturn {\n\t\tget isInitialized(): boolean {\n\t\t\treturn isInitialized;\n\t\t},\n\n\t\tinitializeScenario(): void {\n\t\t\tif (isInitialized) return;\n\n\t\t\tconst context = config.context();\n\n\t\t\tfor (const binding of config.bindings ?? []) {\n\t\t\t\tconst key = binding.scenario.eventType;\n\t\t\t\tif (subscriptions.has(key)) continue;\n\n\t\t\t\tsubscriptions.set(\n\t\t\t\t\tkey,\n\t\t\t\t\tbinding.scenario.subscribe(binding.handler(context), {\n\t\t\t\t\t\tusedBy: config.name,\n\t\t\t\t\t\t...binding.options,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconfig.onInit?.(context);\n\t\t\tisInitialized = true;\n\t\t},\n\n\t\tresetScenario(): void {\n\t\t\tfor (const release of subscriptions.values()) release();\n\t\t\tsubscriptions.clear();\n\t\t\tisInitialized = false;\n\n\t\t\tconfig.onReset?.(config.context());\n\t\t},\n\t};\n};\n","import { useCallback, useRef, useSyncExternalStore } from \"react\";\n\nexport interface ILankaTrackedHookConfig<TState extends object> {\n\t/**\n\t * Subscribes to the source, reporting both states already in FULL shape.\n\t *\n\t * A shared-store ViewModel composes its full state from a store slice, so the\n\t * shaping happens here rather than inside the hook: the hook compares states,\n\t * it does not know how one is assembled.\n\t */\n\tsubscribe: (onChange: (next: TState, prev: TState) => void) => () => void;\n\t/** The current full state. */\n\treadState: () => TState;\n\t/**\n\t * Called when a change touched no tracked key, so no re-render will follow.\n\t *\n\t * The one seam the two ViewModel families differ on: only the plain factory\n\t * reports the blind spot, and only in development.\n\t */\n\tonUntrackedChange?: (\n\t\ttrackedKeys: Set<string>,\n\t\tnext: Record<string, unknown>,\n\t\tprev: Record<string, unknown>,\n\t) => void;\n}\n\nconst asRecord = (state: object): Record<string, unknown> => state as Record<string, unknown>;\n\n/**\n * The access-tracking hook every ViewModel factory renders through.\n *\n * Without a selector the component receives a Proxy that records which keys it\n * read; the next change re-renders only if one of THOSE keys moved. With a\n * selector the selector decides and tracking is bypassed.\n *\n * Both ViewModel families needed exactly this, and differed only in where the\n * state comes from — a store of their own, or a slice of a shared one. Those are\n * the two parameters above; the eighty lines below were copied.\n */\nexport const createLankaTrackedHook = <TState extends object>(\n\tconfig: ILankaTrackedHookConfig<TState>,\n) => {\n\treturn (selector?: (state: TState) => unknown): unknown => {\n\t\tconst selectorRef = useRef(selector);\n\t\tselectorRef.current = selector;\n\n\t\tconst trackedKeysRef = useRef<Set<string>>(new Set());\n\t\tconst trackedStateRef = useRef<TState | null>(null);\n\t\tconst trackedProxyRef = useRef<TState | null>(null);\n\n\t\t/**\n\t\t * Stable identity; the empty dependency list is deliberate.\n\t\t *\n\t\t * `useSyncExternalStore` keeps `subscribe` in an effect keyed on its\n\t\t * identity, so an inline arrow makes React tear the subscription down and\n\t\t * rebuild it on EVERY render of EVERY connected component — measured at 201\n\t\t * subscriptions for 200 renders. The body reads only refs and the\n\t\t * factory-scope config, never a prop or a render-scoped value, so there is\n\t\t * nothing for `[]` to capture stale.\n\t\t */\n\t\tconst subscribe = useCallback(\n\t\t\t(onStoreChange: () => void) =>\n\t\t\t\tconfig.subscribe((nextState, prevState) => {\n\t\t\t\t\tif (selectorRef.current) {\n\t\t\t\t\t\tonStoreChange();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst trackedKeys = trackedKeysRef.current;\n\t\t\t\t\tif (trackedKeys.size === 0) {\n\t\t\t\t\t\tonStoreChange();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst next = asRecord(nextState);\n\t\t\t\t\tconst prev = asRecord(prevState);\n\n\t\t\t\t\tfor (const key of trackedKeys) {\n\t\t\t\t\t\tif (!Object.is(next[key], prev[key])) {\n\t\t\t\t\t\t\tonStoreChange();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Reaching here means NO re-render will follow. If the changed key is\n\t\t\t\t\t// linked to the component through a getter it read, the screen froze.\n\t\t\t\t\tconfig.onUntrackedChange?.(trackedKeys, next, prev);\n\t\t\t\t}),\n\t\t\t[],\n\t\t);\n\n\t\treturn useSyncExternalStore(subscribe, readTracked, readUntracked);\n\n\t\tfunction readTracked(): unknown {\n\t\t\tconst state = config.readState();\n\t\t\tconst activeSelector = selectorRef.current;\n\n\t\t\tif (activeSelector) return activeSelector(state);\n\n\t\t\tif (trackedStateRef.current === state && trackedProxyRef.current) {\n\t\t\t\treturn trackedProxyRef.current;\n\t\t\t}\n\n\t\t\tconst trackedKeys = new Set<string>();\n\t\t\tconst proxyState = new Proxy(state, {\n\t\t\t\tget(target, prop, receiver) {\n\t\t\t\t\tif (typeof prop === \"string\") {\n\t\t\t\t\t\ttrackedKeys.add(prop);\n\t\t\t\t\t}\n\t\t\t\t\treturn Reflect.get(target, prop, receiver);\n\t\t\t\t},\n\t\t\t});\n\n\t\t\ttrackedKeysRef.current = trackedKeys;\n\t\t\ttrackedStateRef.current = state;\n\t\t\ttrackedProxyRef.current = proxyState;\n\n\t\t\treturn proxyState;\n\t\t}\n\n\t\t/**\n\t\t * The server snapshot: the state itself, never the Proxy.\n\t\t *\n\t\t * Tracking exists to skip renders a client would otherwise do; a server\n\t\t * renders once, and handing it a recording Proxy would only add work whose\n\t\t * result nothing reads.\n\t\t */\n\t\tfunction readUntracked(): unknown {\n\t\t\tconst state = config.readState();\n\t\t\tconst activeSelector = selectorRef.current;\n\n\t\t\treturn activeSelector ? activeSelector(state) : state;\n\t\t}\n\t};\n};\n","/**\n * A dependency bag given either directly or as a factory.\n *\n * The factory form exists so a ViewModel declared at module level does not\n * resolve its gateways at import time: the locator needs an active framework\n * instance, and a module body runs before one exists.\n */\nexport type TLankaDependencyBag<TBag extends object> = TBag | (() => TBag) | undefined;\n\n/**\n * Reads a dependency bag, whichever form it was declared in.\n *\n * All three ViewModel factories wrote this out twice each — once for gateways,\n * once for services — which is six copies of one three-line decision.\n */\nexport const resolveLankaDependency = <TBag extends object>(\n\tdeclared: TLankaDependencyBag<TBag>,\n): TBag => {\n\tif (typeof declared === \"function\") return declared();\n\treturn declared ?? ({} as TBag);\n};\n","import { StoreApi, UseBoundStore } from \"zustand\";\nimport { ALankaVM } from \"../../_abstractions/lanka-vm/ALankaVM\";\nimport { resolveLankaDependency } from \"../../_utils/resolve-lanka-dependency/resolveLankaDependency\";\nimport { ILankaScenarioVM } from \"../../../scenario/_interfaces/ILankaScenarioVM\";\nimport type { ILankaVMConfig } from \"../../_interfaces/ILankaVMConfig\";\n\n/**\n * The functional style of `ALankaVM`: a ViewModel declared as an options object.\n *\n * Everything it can do, the class can do, because this IS the class — the hooks a\n * subclass overrides arrive here as config fields of the same names, and the\n * protected surface arrives as the `ctx` every hook is handed. What a ViewModel is\n * and how it binds scenarios is documented once, on `ALankaVM`.\n *\n * ⚠️ ACCESS-TRACKING BLIND SPOT. A consumer re-renders only for state keys it READ\n * off the returned proxy. An action that DERIVES a value (`getSomeView()`) reads the\n * store through `get()`, which the proxy never sees — so a component whose only link\n * to a state key is such a getter will never re-render when that key changes.\n *\n * Set `enableAccessTrackingOptimization: false` on such a ViewModel. Do NOT patch it\n * in the view by destructuring the underlying keys for their side effect only: that\n * reads as dead code, so a refactor, an unused-variable cleanup or a lint autofix\n * removes it and the screen silently freezes again. `MeetingReportViewModel` carries\n * the worked example (its report toggles froze exactly that way, twice).\n *\n * In development the mismatch ANNOUNCES ITSELF: the framework sees that a key\n * changed, that no re-render will follow, and that the component reads that key\n * through a getter — and warns with the ViewModel and key names. \"Remember to\n * set the flag\" is not a mechanism.\n */\nexport function createLankaVM<State extends object, Actions extends object>(\n\tconfig: ILankaVMConfig<State, Actions, Record<string, never>, Record<string, never>>,\n): UseBoundStore<StoreApi<State & Actions & ILankaScenarioVM>>;\n\nexport function createLankaVM<\n\tState extends object,\n\tActions extends object,\n\tServices extends object,\n>(\n\tconfig: ILankaVMConfig<State, Actions, Record<string, never>, Services>,\n): UseBoundStore<StoreApi<State & Actions & ILankaScenarioVM>>;\n\nexport function createLankaVM<\n\tState extends object,\n\tActions extends object,\n\tTGateways extends object,\n>(\n\tconfig: ILankaVMConfig<State, Actions, TGateways, Record<string, never>>,\n): UseBoundStore<StoreApi<State & Actions & ILankaScenarioVM>>;\n\nexport function createLankaVM<\n\tState extends object,\n\tActions extends object,\n\tTGateways extends object,\n\tServices extends object,\n>(\n\tconfig: ILankaVMConfig<State, Actions, TGateways, Services>,\n): UseBoundStore<StoreApi<State & Actions & ILankaScenarioVM>>;\n\nexport function createLankaVM<\n\tState extends object,\n\tActions extends object,\n\tTGateways extends object = Record<string, never>,\n\tServices extends object = Record<string, never>,\n>(\n\tconfig: ILankaVMConfig<State, Actions, TGateways, Services>,\n): UseBoundStore<StoreApi<State & Actions & ILankaScenarioVM>> {\n\t/**\n\t * The bridge subclass lives here rather than in a shared helper because\n\t * `toStyleContext` is `protected`: only a class body deriving from `ALankaVM`\n\t * may read it. Canon: `skills/parity/SKILL.md` section 3a.\n\t */\n\tclass FunctionalVM extends ALankaVM<State, Actions, TGateways, Services> {\n\t\tprotected readonly name = config.name;\n\n\t\tprotected override readonly enableAccessTrackingOptimization =\n\t\t\tconfig.enableAccessTrackingOptimization ?? true;\n\n\t\tprotected override states(): State {\n\t\t\treturn config.states ?? ({} as State);\n\t\t}\n\n\t\tprotected override scenarioHandlers(): NonNullable<typeof config.scenarioHandlers> {\n\t\t\treturn config.scenarioHandlers ?? [];\n\t\t}\n\n\t\tprotected override enhancers(): NonNullable<typeof config.enhancers> {\n\t\t\treturn config.enhancers ?? [];\n\t\t}\n\n\t\tprotected override createGateways(): TGateways {\n\t\t\treturn resolveLankaDependency(config.gateways);\n\t\t}\n\n\t\tprotected override createServices(): Services {\n\t\t\treturn resolveLankaDependency(config.services);\n\t\t}\n\n\t\tprotected createActions(): Actions {\n\t\t\treturn config.createActions(this.toStyleContext());\n\t\t}\n\n\t\tprotected override onInit(): void {\n\t\t\tconfig.onInit?.(this.toStyleContext());\n\t\t}\n\n\t\tprotected override onReset(): void {\n\t\t\tconfig.onReset?.(this.toStyleContext());\n\t\t}\n\t}\n\n\treturn new FunctionalVM().build();\n}\n","import { lankaLogger } from \"../../../logger/lanka-logger/LankaLogger\";\n\n/**\n * What a lazy hook needs of the store behind it.\n *\n * Stated rather than cast: releasing a ViewModel means unsubscribing its\n * scenarios, so the mechanism does require this much — and every store it is\n * given has it, because `ILankaScenarioVM` is part of all three VM states.\n */\nexport interface ILankaReleasableStore {\n\tgetState: () => { resetScenario: () => void };\n}\n\n/** What every lazy factory is handed: a name for the log, and how to build. */\nexport interface ILankaLazyHookConfig<TStore> {\n\t/** The ViewModel's name, as the log line says it. */\n\tname: string;\n\t/** What the log calls this kind of ViewModel — `VM`, `slVM`, `ssVM`. */\n\tkind: string;\n\t/** Builds the real store. Called at most once until `release`. */\n\tcreate: () => TStore;\n}\n\n/** A lazily built store: everything the store is, plus `dispose`. */\nexport type TLazyLankaHook<TStore> = TStore & { dispose: () => void };\n\n/** The one store a lazy hook stands in front of, built at most once. */\ninterface ILankaLazySlot<TStore> {\n\tget: () => TStore;\n\trelease: () => void;\n}\n\n/**\n * Build once, release on demand: the state a lazy hook is made of.\n *\n * Separate from the forwarding below because they answer different questions —\n * WHEN the store exists, and WHERE a call goes. Read together they were one\n * function of fifty lines, which the composition canon calls what it is.\n */\nconst lazySlot = <TStore extends ILankaReleasableStore>(\n\tconfig: ILankaLazyHookConfig<TStore>,\n): ILankaLazySlot<TStore> => {\n\tlet store: TStore | null = null;\n\n\treturn {\n\t\tget: () => {\n\t\t\tif (!store) {\n\t\t\t\tlankaLogger.printViewModelLog(\n\t\t\t\t\t`LAZY: Creating ${config.kind} on first access`,\n\t\t\t\t\tconfig.name,\n\t\t\t\t);\n\t\t\t\tstore = config.create();\n\t\t\t}\n\t\t\treturn store;\n\t\t},\n\n\t\t/**\n\t\t * Releases the store. The next access builds a new one.\n\t\t *\n\t\t * Scenario subscriptions go first, through `resetScenario` — the same path\n\t\t * the between-tests reset uses. Dropping the reference without\n\t\t * unsubscribing would leave the bus holding handlers that write into a\n\t\t * discarded store.\n\t\t *\n\t\t * On a slot that never built, this does NOTHING: building a store in order\n\t\t * to destroy it is work with no result, and it would resurrect a ViewModel\n\t\t * a closed screen had just released.\n\t\t */\n\t\trelease: () => {\n\t\t\tif (!store) return;\n\t\t\tstore.getState().resetScenario();\n\t\t\tstore = null;\n\t\t},\n\t};\n};\n\n/**\n * How a member reaches the store: through a wrapper, always.\n *\n * The trap returns a FUNCTION for every member rather than the member itself, so\n * reading `useVM.setState` builds nothing and calling it builds the store. A trap\n * that resolved eagerly would end laziness the moment a devtool, a spread or a\n * debugger looked at the object — which is most of the ways an object is looked\n * at.\n *\n * `dispose` is the exception in both directions: it is not the store's, and it\n * must not build one.\n */\nconst forwardEveryMember =\n\t<TStore>(slot: ILankaLazySlot<TStore>) =>\n\t(_target: object, property: string | symbol): unknown => {\n\t\tif (property === \"dispose\") return slot.release;\n\n\t\treturn (...args: unknown[]) => {\n\t\t\tconst built = slot.get();\n\t\t\tconst member = (built as Record<string | symbol, unknown>)[property];\n\n\t\t\t// Every member of a zustand store is a method, and so is every one a\n\t\t\t// ViewModel adds — `getStoreState` included. A value member cannot be\n\t\t\t// classified without building the store first, which is the one thing a\n\t\t\t// property READ may not do, so it is handed back from the call instead:\n\t\t\t// `useVM.whatever()` gives the value.\n\t\t\treturn typeof member === \"function\"\n\t\t\t\t? (member as (...rest: unknown[]) => unknown).apply(built, args)\n\t\t\t\t: member;\n\t\t};\n\t};\n\n/**\n * The lazy half of every ViewModel factory, written once.\n *\n * Three factories used to carry this mechanism: build on first access, keep the\n * store, hand every member through, release on `dispose`. They differed in the\n * one line that builds — and, as it turned out, in which members they had\n * remembered to hand through.\n *\n * ## Why a Proxy rather than a list of members\n *\n * The three copies attached members BY HAND, and the three lists differed:\n * `getState` + `getInitialState` + `setState` + `subscribe` for the plain one,\n * `getState` alone for the stateless, `getState` + `getStoreState` for the\n * shared-store. Each list matched its own type, so nothing was broken — but the\n * plain one MIRRORS a zustand store, and a mirror is a promise to keep in step\n * with something somebody else releases. The day zustand adds a member, three\n * files have to hear about it.\n *\n * A Proxy cannot be incomplete. What the built store has, the lazy hook has, and\n * the type each factory declares is what narrows it back down to that variant's\n * contract — a lazy variant promises exactly what its eager twin promises, plus\n * `dispose`.\n */\nexport const createLazyLankaHook = <TStore extends ILankaReleasableStore>(\n\tconfig: ILankaLazyHookConfig<TStore>,\n): TLazyLankaHook<TStore> => {\n\tconst slot = lazySlot(config);\n\n\t// The hook itself: a function, so `useVM()` and `useVM(selector)` work before\n\t// anything is built.\n\tconst hook = (selector?: (state: unknown) => unknown): unknown => {\n\t\tconst built = slot.get() as unknown as (chosen?: unknown) => unknown;\n\t\treturn selector ? built(selector) : built();\n\t};\n\n\treturn new Proxy(hook, { get: forwardEveryMember(slot) }) as unknown as TLazyLankaHook<TStore>;\n};\n","import { ILankaScenarioVM } from \"../../../scenario/_interfaces/ILankaScenarioVM\";\nimport { createLazyLankaHook } from \"../../_internal/create-lazy-lanka-hook/createLazyLankaHook\";\nimport { createLankaVM } from \"../create-lanka-vm/createLankaVM\";\nimport type { ILankaVMConfig } from \"../../_interfaces/ILankaVMConfig\";\n\nexport function createLazyLankaVM<State extends object, Actions extends object>(\n\tconfig: ILankaVMConfig<State, Actions, Record<string, never>, Record<string, never>>,\n): TLazyLankaVM<\n\tReturnType<typeof createLankaVM<State, Actions, Record<string, never>, Record<string, never>>>,\n\tState & Actions & ILankaScenarioVM\n>;\n\nexport function createLazyLankaVM<\n\tState extends object,\n\tActions extends object,\n\tServices extends object,\n>(\n\tconfig: ILankaVMConfig<State, Actions, Record<string, never>, Services>,\n): TLazyLankaVM<\n\tReturnType<typeof createLankaVM<State, Actions, Record<string, never>, Services>>,\n\tState & Actions & ILankaScenarioVM\n>;\n\nexport function createLazyLankaVM<\n\tState extends object,\n\tActions extends object,\n\tTGateways extends object,\n>(\n\tconfig: ILankaVMConfig<State, Actions, TGateways, Record<string, never>>,\n): TLazyLankaVM<\n\tReturnType<typeof createLankaVM<State, Actions, TGateways, Record<string, never>>>,\n\tState & Actions & ILankaScenarioVM\n>;\n\nexport function createLazyLankaVM<\n\tState extends object,\n\tActions extends object,\n\tTGateways extends object,\n\tServices extends object,\n>(\n\tconfig: ILankaVMConfig<State, Actions, TGateways, Services>,\n): TLazyLankaVM<\n\tReturnType<typeof createLankaVM<State, Actions, TGateways, Services>>,\n\tState & Actions & ILankaScenarioVM\n>;\n\n/**\n * The lazy `createLankaVM`: nothing is built until a screen asks.\n *\n * For a ViewModel a session may never open — a settings screen, an admin panel,\n * a route behind a flag. The eager factory builds its store at module load, and\n * this one waits, which is the difference between paying for every screen the\n * application has and paying for the screens it shows.\n *\n * The mechanism is `createLazyLankaHook`, shared with the stateless and\n * shared-store variants, so all three hand through every member the store has\n * and release the same way. This file is the one line that says what gets built.\n */\nexport function createLazyLankaVM<\n\tState extends object,\n\tActions extends object,\n\tTGateways extends object = Record<string, never>,\n\tServices extends object = Record<string, never>,\n>(config: ILankaVMConfig<State, Actions, TGateways, Services>) {\n\treturn createLazyLankaHook({\n\t\tname: config.name,\n\t\tkind: \"VM\",\n\t\tcreate: () => createLankaVM(config),\n\t});\n}\n\n/**\n * A lazy ViewModel hook: everything an ordinary store does, plus `dispose`.\n */\nexport type TLazyLankaVM<TStore, TFullState> = TStore & {\n\tgetState: () => TFullState;\n\tdispose: () => void;\n};\n","import { ALankaVMEnvironment } from \"../lanka-vm-environment/ALankaVMEnvironment\";\nimport { ILankaScenarioVM } from \"../../../scenario/_interfaces/ILankaScenarioVM\";\nimport { lankaScenarioBootstrap } from \"../../../scenario/lanka-scenario-bootstrap/LankaScenarioBootstrap\";\nimport { lankaLogger } from \"../../../logger/lanka-logger/LankaLogger\";\nimport { createLankaScenarioBinder } from \"../../_internal/create-lanka-scenario-binder/createLankaScenarioBinder\";\nimport type { ILankaScenario } from \"../../../scenario/_interfaces/ILankaScenario\";\nimport type {\n\tILankaStatelessScenarioBinding,\n\tILankaStatelessVMContext,\n\tTLankaSetState,\n\tTLankaStatelessVMHook,\n} from \"../../_factories/create-stateless-lanka-vm/createStatelessLankaVM\";\n\n/**\n * A ViewModel that holds no reactive state: actions, and what they orchestrate.\n *\n * The second rung of the ladder in `core/README.md` written as a class. A screen\n * that reads nothing and only DOES things — a sign-out, a share sheet, a form\n * whose fields live in the form library — pays for a zustand store it never\n * reads; this is the same role without one.\n *\n * The protected surface IS the functional context, member for member: `set`,\n * `get`, `gateways`, `services`, `trigger`. What the config supplies as a value\n * or a thunk, the class supplies by overriding a method of the same name, with\n * the two dependency suppliers named `createGateways` and `createServices`\n * because `gateways` and `services` already name what they answer.\n *\n * ```ts\n * class SessionVM extends ALankaStatelessVM<ISessionActions, ISessionGateways> {\n * \tprotected readonly name = \"SessionVM\";\n *\n * \tprotected createGateways(): ISessionGateways {\n * \t\treturn { session: new SessionGateway() };\n * \t}\n *\n * \tprotected createActions(): ISessionActions {\n * \t\treturn {\n * \t\t\tsignOut: async () => {\n * \t\t\t\tawait this.gateways.session.signOut();\n * \t\t\t\tthis.trigger(sessionEnded);\n * \t\t\t},\n * \t\t};\n * \t}\n * }\n *\n * export const useSessionVM = new SessionVM().build();\n * ```\n *\n * Canon: `skills/parity/SKILL.md`.\n */\nexport abstract class ALankaStatelessVM<\n\tActions extends object,\n\tTGateways extends object = Record<string, never>,\n\tServices extends object = Record<string, never>,\n> extends ALankaVMEnvironment<TGateways, Services> {\n\t/** Names the ViewModel in the logs, the scenario registry and any warning. */\n\tprotected abstract readonly name: string;\n\n\t/** Writes state. Available from `createActions` onwards, never before. */\n\tprotected set!: TLankaSetState<Actions & ILankaScenarioVM>;\n\n\t/** Reads what the actions have written, including the actions themselves. */\n\tprotected get!: () => Actions & ILankaScenarioVM;\n\n\t/** Fires a scenario, which every ViewModel bound to it then hears. */\n\tprotected trigger = <TData>(scenario: ILankaScenario<TData>, data?: TData): void => {\n\t\tscenario.trigger(data);\n\t};\n\n\t/** The scenarios this ViewModel listens to, unsubscribed for it on reset. */\n\tprotected scenarioHandlers(): ILankaStatelessScenarioBinding<\n\t\tunknown,\n\t\tActions & ILankaScenarioVM,\n\t\tTGateways,\n\t\tServices\n\t>[] {\n\t\treturn [];\n\t}\n\n\t/** The actions the screen calls. Written against `this.set` and `this.get`. */\n\tprotected abstract createActions(): Actions;\n\n\t/**\n\t * The protected surface as an object, for the functional style.\n\t *\n\t * Assembled INSIDE the class because that is the only place `protected` can be\n\t * read. Canon: `skills/parity/SKILL.md` section 3a.\n\t */\n\tprotected toStyleContext(): ILankaStatelessVMContext<\n\t\tActions & ILankaScenarioVM,\n\t\tTGateways,\n\t\tServices\n\t> {\n\t\treturn {\n\t\t\tset: this.set,\n\t\t\tget: this.get,\n\t\t\tgateways: this.gateways,\n\t\t\tservices: this.services,\n\t\t\ttrigger: this.trigger,\n\t\t};\n\t}\n\n\t/** Builds the hook a screen calls. One ViewModel per call. */\n\tpublic build(): TLankaStatelessVMHook<Actions> {\n\t\ttype TFullState = Actions & ILankaScenarioVM;\n\n\t\tlankaLogger.printViewModelLog(\"START Create slVM\", this.name);\n\n\t\tlet state = {} as TFullState;\n\n\t\tthis.get = () => state;\n\t\tthis.set = (partial, replace) => {\n\t\t\tconst next =\n\t\t\t\ttypeof partial === \"function\"\n\t\t\t\t\t? (partial as (current: TFullState) => TFullState)(state)\n\t\t\t\t\t: partial;\n\n\t\t\tstate = replace ? (next as TFullState) : { ...state, ...next };\n\t\t};\n\n\t\tthis.gateways = this.createGateways();\n\t\tthis.services = this.createServices();\n\n\t\tconst actions = this.createActions();\n\t\tconst bindings = this.scenarioHandlers();\n\n\t\tconst { initializeScenario, resetScenario } = createLankaScenarioBinder({\n\t\t\tname: this.name,\n\t\t\tbindings,\n\t\t\tcontext: () => this.toStyleContext(),\n\t\t\tonInit: () => {\n\t\t\t\tthis.onInit();\n\t\t\t},\n\t\t\tonReset: () => {\n\t\t\t\tthis.onReset();\n\t\t\t},\n\t\t});\n\n\t\tstate = { ...state, ...actions, initializeScenario, resetScenario };\n\n\t\tif (bindings.length > 0) {\n\t\t\tlankaScenarioBootstrap.registerViewModel(state, this.name);\n\t\t}\n\n\t\tconst useStatelessViewModel = ((selector?: (full: TFullState) => unknown) =>\n\t\t\tselector ? selector(state) : state) as TLankaStatelessVMHook<Actions>;\n\n\t\tuseStatelessViewModel.getState = () => state;\n\n\t\tlankaLogger.printViewModelLog(\"FINISH Create slVM\", this.name);\n\n\t\treturn useStatelessViewModel;\n\t}\n}\n","import type { TLankaReplayRequest } from \"../../../scenario/event-bus/lanka-event-bus-instance/LankaEventBusInstance\";\nimport type { TLankaScenarioHandler } from \"../../_types/TLankaScenarioHandler\";\nimport { resolveLankaDependency } from \"../../_utils/resolve-lanka-dependency/resolveLankaDependency\";\nimport { ALankaStatelessVM } from \"../../_abstractions/lanka-stateless-vm/ALankaStatelessVM\";\nimport { ILankaScenario } from \"../../../scenario/_interfaces/ILankaScenario\";\nimport { ILankaScenarioVM } from \"../../../scenario/_interfaces/ILankaScenarioVM\";\n\nexport type TLankaSetState<TState> = (\n\tpartial: TState | Partial<TState> | ((state: TState) => TState | Partial<TState>),\n\treplace?: boolean,\n) => void;\n\nexport interface ILankaStatelessVMContext<\n\tTState,\n\tTGateways extends object,\n\tTServices extends object,\n> {\n\tset: TLankaSetState<TState>;\n\tget: () => TState;\n\tgateways: TGateways;\n\tservices: TServices;\n\ttrigger: <T>(scenario: ILankaScenario<T>, data?: T) => void;\n}\n\nexport interface ILankaStatelessScenarioBinding<\n\tTData,\n\tTState extends object,\n\tTGateways extends object,\n\tTServices extends object,\n> {\n\tscenario: ILankaScenario<TData>;\n\thandler: (\n\t\tctx: ILankaStatelessVMContext<TState, TGateways, TServices>,\n\t) => TLankaScenarioHandler<TData>;\n\toptions?: {\n\t\tpriority?: number;\n\t\treplay?: TLankaReplayRequest;\n\t\tusedBy?: string;\n\t};\n}\n\nexport type TLankaStatelessVMConfig<\n\tActions extends object,\n\tTGateways extends object = Record<string, never>,\n\tServices extends object = Record<string, never>,\n> = {\n\tname: string;\n\tcreateActions: (\n\t\tctx: ILankaStatelessVMContext<Actions & ILankaScenarioVM, TGateways, Services>,\n\t) => Actions;\n\tscenarioHandlers?: ILankaStatelessScenarioBinding<\n\t\tunknown,\n\t\tActions & ILankaScenarioVM,\n\t\tTGateways,\n\t\tServices\n\t>[];\n\tservices?: Services | (() => Services);\n\tgateways?: TGateways | (() => TGateways);\n\tonInit?: (\n\t\tctx: ILankaStatelessVMContext<Actions & ILankaScenarioVM, TGateways, Services>,\n\t) => void;\n\tonReset?: (\n\t\tctx: ILankaStatelessVMContext<Actions & ILankaScenarioVM, TGateways, Services>,\n\t) => void;\n};\n\nexport type TLankaStatelessVMHook<Actions extends object> = {\n\t<TSelected = Actions & ILankaScenarioVM>(\n\t\tselector?: (full: Actions & ILankaScenarioVM) => TSelected,\n\t): TSelected;\n\tgetState: () => Actions & ILankaScenarioVM;\n};\n\nexport function createStatelessLankaVM<Actions extends object>(\n\tconfig: TLankaStatelessVMConfig<Actions, Record<string, never>, Record<string, never>>,\n): TLankaStatelessVMHook<Actions>;\n\nexport function createStatelessLankaVM<Actions extends object, Services extends object>(\n\tconfig: TLankaStatelessVMConfig<Actions, Record<string, never>, Services>,\n): TLankaStatelessVMHook<Actions>;\n\nexport function createStatelessLankaVM<Actions extends object, TGateways extends object>(\n\tconfig: TLankaStatelessVMConfig<Actions, TGateways, Record<string, never>>,\n): TLankaStatelessVMHook<Actions>;\n\nexport function createStatelessLankaVM<\n\tActions extends object,\n\tTGateways extends object,\n\tServices extends object,\n>(config: TLankaStatelessVMConfig<Actions, TGateways, Services>): TLankaStatelessVMHook<Actions>;\n\n/**\n * The functional style of `ALankaStatelessVM`: actions declared as an options object.\n *\n * Same outward shape as the stateful factory — a hook-like function with\n * `getState` — and no zustand store under it, because a ViewModel that holds\n * nothing has nothing to subscribe to. What it is and how it binds scenarios is\n * documented once, on the class.\n */\nexport function createStatelessLankaVM<\n\tActions extends object,\n\tTGateways extends object = Record<string, never>,\n\tServices extends object = Record<string, never>,\n>(config: TLankaStatelessVMConfig<Actions, TGateways, Services>): TLankaStatelessVMHook<Actions> {\n\t/**\n\t * The bridge subclass lives here rather than in a shared helper because\n\t * `toStyleContext` is `protected`: only a class body deriving from\n\t * `ALankaStatelessVM` may read it. Canon: `skills/parity/SKILL.md` section 3a.\n\t */\n\tclass FunctionalStatelessVM extends ALankaStatelessVM<Actions, TGateways, Services> {\n\t\tprotected readonly name = config.name;\n\n\t\tprotected override scenarioHandlers(): NonNullable<typeof config.scenarioHandlers> {\n\t\t\treturn config.scenarioHandlers ?? [];\n\t\t}\n\n\t\tprotected override createGateways(): TGateways {\n\t\t\treturn resolveLankaDependency(config.gateways);\n\t\t}\n\n\t\tprotected override createServices(): Services {\n\t\t\treturn resolveLankaDependency(config.services);\n\t\t}\n\n\t\tprotected createActions(): Actions {\n\t\t\treturn config.createActions(this.toStyleContext());\n\t\t}\n\n\t\tprotected override onInit(): void {\n\t\t\tconfig.onInit?.(this.toStyleContext());\n\t\t}\n\n\t\tprotected override onReset(): void {\n\t\t\tconfig.onReset?.(this.toStyleContext());\n\t\t}\n\t}\n\n\treturn new FunctionalStatelessVM().build();\n}\n","import { ILankaScenarioVM } from \"../../../scenario/_interfaces/ILankaScenarioVM\";\nimport { createStatelessLankaVM } from \"../create-stateless-lanka-vm/createStatelessLankaVM\";\nimport type { ILankaVMConfig } from \"../../_interfaces/ILankaVMConfig\";\nimport { createLazyLankaHook } from \"../../_internal/create-lazy-lanka-hook/createLazyLankaHook\";\n\nexport type TLankaStatelessVMConfig<\n\tActions extends object,\n\tTGateways extends object = Record<string, never>,\n\tServices extends object = Record<string, never>,\n> = Omit<ILankaVMConfig<object, Actions, TGateways, Services>, \"states\"> & {\n\tstates?: never;\n};\n\ntype TLazyStatelessReturn<\n\tActions extends object,\n\tTGateways extends object,\n\tServices extends object,\n> = ReturnType<typeof createStatelessLankaVM<Actions, TGateways, Services>> & {\n\tgetState: () => Actions & ILankaScenarioVM;\n\tdispose: () => void;\n};\n\nexport function createLazyStatelessLankaVM<Actions extends object>(\n\tconfig: TLankaStatelessVMConfig<Actions, Record<string, never>, Record<string, never>>,\n): TLazyStatelessReturn<Actions, Record<string, never>, Record<string, never>>;\n\nexport function createLazyStatelessLankaVM<Actions extends object, Services extends object>(\n\tconfig: TLankaStatelessVMConfig<Actions, Record<string, never>, Services>,\n): TLazyStatelessReturn<Actions, Record<string, never>, Services>;\n\nexport function createLazyStatelessLankaVM<Actions extends object, TGateways extends object>(\n\tconfig: TLankaStatelessVMConfig<Actions, TGateways, Record<string, never>>,\n): TLazyStatelessReturn<Actions, TGateways, Record<string, never>>;\n\nexport function createLazyStatelessLankaVM<\n\tActions extends object,\n\tTGateways extends object,\n\tServices extends object,\n>(\n\tconfig: TLankaStatelessVMConfig<Actions, TGateways, Services>,\n): TLazyStatelessReturn<Actions, TGateways, Services>;\n\n/**\n * The lazy `createStatelessLankaVM`: nothing is built until a screen asks.\n *\n * The mechanism is `createLazyLankaHook` — build on first access, hand every\n * member through, release on `dispose` — and this file is the one line that says\n * WHICH ViewModel is built. It used to be a copy of that mechanism, and the copy\n * had forgotten `setState`, `subscribe` and `getInitialState`: typed as the whole\n * store, absent at runtime.\n */\nexport function createLazyStatelessLankaVM<\n\tActions extends object,\n\tTGateways extends object = Record<string, never>,\n\tServices extends object = Record<string, never>,\n>(config: TLankaStatelessVMConfig<Actions, TGateways, Services>) {\n\treturn createLazyLankaHook({\n\t\tname: config.name,\n\t\tkind: \"slVM\",\n\t\tcreate: () => createStatelessLankaVM(config),\n\t});\n}\n","import { useStore } from \"zustand\";\nimport { resolveLankaDependency } from \"../../_utils/resolve-lanka-dependency/resolveLankaDependency\";\nimport { createLankaScenarioBinder } from \"../../_internal/create-lanka-scenario-binder/createLankaScenarioBinder\";\nimport { createLankaTrackedHook } from \"../../_internal/create-lanka-tracked-hook/createLankaTrackedHook\";\nimport { ILankaScenarioVM } from \"../../../scenario/_interfaces/ILankaScenarioVM\";\nimport { lankaScenarioBootstrap } from \"../../../scenario/lanka-scenario-bootstrap/LankaScenarioBootstrap\";\nimport { lankaLogger } from \"../../../logger/lanka-logger/LankaLogger\";\nimport type {\n\tILankaSharedStoreVMConfig,\n\tTLankaSharedStoreVMHook,\n} from \"../../_interfaces/ILankaSharedStoreVMConfig\";\nimport type { ILankaSharedStoreVMContext } from \"../../_interfaces/ILankaSharedStoreVMContext\";\nimport { ALankaSharedStore } from \"../../_abstractions/lanka-shared-store/ALankaSharedStore\";\n\n/**\n * Factory for ViewModels backed by an external shared store instance.\n * Multiple ViewModels can be created on top of the same store instance.\n */\nexport function createSharedStoreLankaVM<\n\tStoreState extends object,\n\tActions extends object,\n\tStore extends ALankaSharedStore<StoreState>,\n>(\n\tconfig: ILankaSharedStoreVMConfig<\n\t\tStoreState,\n\t\tActions,\n\t\tStore,\n\t\tRecord<string, never>,\n\t\tRecord<string, never>\n\t>,\n): TLankaSharedStoreVMHook<StoreState, Actions>;\n\nexport function createSharedStoreLankaVM<\n\tStoreState extends object,\n\tActions extends object,\n\tStore extends ALankaSharedStore<StoreState>,\n\tServices extends object,\n>(\n\tconfig: ILankaSharedStoreVMConfig<StoreState, Actions, Store, Record<string, never>, Services>,\n): TLankaSharedStoreVMHook<StoreState, Actions>;\n\nexport function createSharedStoreLankaVM<\n\tStoreState extends object,\n\tActions extends object,\n\tStore extends ALankaSharedStore<StoreState>,\n\tTGateways extends object,\n>(\n\tconfig: ILankaSharedStoreVMConfig<StoreState, Actions, Store, TGateways, Record<string, never>>,\n): TLankaSharedStoreVMHook<StoreState, Actions>;\n\nexport function createSharedStoreLankaVM<\n\tStoreState extends object,\n\tActions extends object,\n\tStore extends ALankaSharedStore<StoreState>,\n\tTGateways extends object,\n\tServices extends object,\n>(\n\tconfig: ILankaSharedStoreVMConfig<StoreState, Actions, Store, TGateways, Services>,\n): TLankaSharedStoreVMHook<StoreState, Actions>;\n\nexport function createSharedStoreLankaVM<\n\tStoreState extends object,\n\tActions extends object,\n\tStore extends ALankaSharedStore<StoreState>,\n\tTGateways extends object = Record<string, never>,\n\tServices extends object = Record<string, never>,\n>(config: ILankaSharedStoreVMConfig<StoreState, Actions, Store, TGateways, Services>) {\n\tlankaLogger.printViewModelLog(\"START Create ssVM\", config.name);\n\n\ttype TFullState = StoreState & Actions & ILankaScenarioVM;\n\n\t/**\n\t * Unsubscribe functions, plus the event types already subscribed to.\n\t *\n\t * Two separate jobs, kept separate: the array releases subscriptions, the set\n\t * prevents subscribing to one event type twice.\n\t */\n\tlet actions = {} as Actions;\n\n\tconst gateways = resolveLankaDependency(config.gateways);\n\tconst services = resolveLankaDependency(config.services);\n\n\tlet lastStoreStateRef: StoreState | null = null;\n\tlet lastFullStateRef: TFullState | null = null;\n\n\tconst buildFullState = (storeState: StoreState): TFullState => {\n\t\tif (lastStoreStateRef === storeState && lastFullStateRef) {\n\t\t\treturn lastFullStateRef;\n\t\t}\n\n\t\tlastStoreStateRef = storeState;\n\t\tlastFullStateRef = {\n\t\t\t...storeState,\n\t\t\t...actions,\n\t\t\tinitializeScenario,\n\t\t\tresetScenario,\n\t\t};\n\n\t\treturn lastFullStateRef;\n\t};\n\n\tconst getFullState = (): TFullState => buildFullState(config.store.getState());\n\n\tconst ctx: ILankaSharedStoreVMContext<StoreState, TFullState, Store, TGateways, Services> = {\n\t\tset: (partial, replace) => config.store.setState(partial, replace),\n\t\tgetStore: () => config.store.getState(),\n\t\tget: () => getFullState(),\n\t\tstore: config.store,\n\t\tgateways,\n\t\tservices,\n\t\ttrigger: (scenario, data) => scenario.trigger(data),\n\t};\n\n\tconst { initializeScenario, resetScenario } = createLankaScenarioBinder({\n\t\tname: config.name,\n\t\tbindings: config.scenarioHandlers,\n\t\tcontext: () => ctx,\n\t\tonInit: config.onInit,\n\t\tonReset: config.onReset,\n\t});\n\n\tactions = config.createActions(ctx);\n\tlastStoreStateRef = null;\n\tlastFullStateRef = null;\n\tconst isAccessTrackingEnabled = config.enableAccessTrackingOptimization ?? true;\n\n\tconst useTrackedSharedStoreViewModel = createLankaTrackedHook<TFullState>({\n\t\tsubscribe: (onChange) =>\n\t\t\tconfig.store.subscribe((storeState, prevStoreState) => {\n\t\t\t\tonChange(buildFullState(storeState), buildFullState(prevStoreState));\n\t\t\t}),\n\t\treadState: getFullState,\n\t}) as TLankaSharedStoreVMHook<StoreState, Actions>;\n\n\tconst useUntrackedSharedStoreViewModel = ((selector?: (state: TFullState) => unknown) =>\n\t\tuseStore(config.store.getApi(), (storeState) => {\n\t\t\tconst fullState = buildFullState(storeState);\n\n\t\t\tif (selector) {\n\t\t\t\treturn selector(fullState);\n\t\t\t}\n\n\t\t\treturn fullState;\n\t\t})) as TLankaSharedStoreVMHook<StoreState, Actions>;\n\n\tconst useSharedStoreViewModel = isAccessTrackingEnabled\n\t\t? useTrackedSharedStoreViewModel\n\t\t: useUntrackedSharedStoreViewModel;\n\n\tuseSharedStoreViewModel.getState = () => getFullState();\n\tuseSharedStoreViewModel.getStoreState = () => config.store.getState();\n\n\tif (config.scenarioHandlers && config.scenarioHandlers.length > 0) {\n\t\tconst scenarioViewModel: ILankaScenarioVM = {\n\t\t\tinitializeScenario,\n\t\t\tresetScenario,\n\t\t};\n\t\tlankaScenarioBootstrap.registerViewModel(scenarioViewModel, config.name);\n\t}\n\n\tlankaLogger.printViewModelLog(\"FINISH Create ssVM\", config.name);\n\n\treturn useSharedStoreViewModel;\n}\n","import { ILankaScenarioVM } from \"../../../scenario/_interfaces/ILankaScenarioVM\";\nimport { ALankaSharedStore } from \"../../_abstractions/lanka-shared-store/ALankaSharedStore\";\nimport { createLazyLankaHook } from \"../../_internal/create-lazy-lanka-hook/createLazyLankaHook\";\nimport { createSharedStoreLankaVM } from \"../create-shared-store-lanka-vm/createSharedStoreLankaVM\";\nimport type { ILankaSharedStoreVMConfig } from \"../../_interfaces/ILankaSharedStoreVMConfig\";\n\n/**\n * What a lazy shared-store ViewModel is, in the type as well as at runtime.\n *\n * The overloads used to promise the eager factory's return and nothing else, so\n * `dispose` and `getStoreState` existed on the object and not in the type: a\n * consumer releasing a closed screen's ViewModel got a compile error for calling\n * something that was there.\n */\ntype TLazySharedStoreReturn<\n\tStoreState extends object,\n\tActions extends object,\n\tStore extends ALankaSharedStore<StoreState>,\n\tTGateways extends object,\n\tServices extends object,\n> = ReturnType<typeof createSharedStoreLankaVM<StoreState, Actions, Store, TGateways, Services>> & {\n\tgetState: () => StoreState & Actions & ILankaScenarioVM;\n\tgetStoreState: () => StoreState;\n\tdispose: () => void;\n};\n\nexport function createLazySharedStoreLankaVM<\n\tStoreState extends object,\n\tActions extends object,\n\tStore extends ALankaSharedStore<StoreState>,\n>(\n\tconfig: ILankaSharedStoreVMConfig<\n\t\tStoreState,\n\t\tActions,\n\t\tStore,\n\t\tRecord<string, never>,\n\t\tRecord<string, never>\n\t>,\n): TLazySharedStoreReturn<StoreState, Actions, Store, Record<string, never>, Record<string, never>>;\n\nexport function createLazySharedStoreLankaVM<\n\tStoreState extends object,\n\tActions extends object,\n\tStore extends ALankaSharedStore<StoreState>,\n\tTGateways extends object,\n>(\n\tconfig: ILankaSharedStoreVMConfig<StoreState, Actions, Store, TGateways, Record<string, never>>,\n): TLazySharedStoreReturn<StoreState, Actions, Store, TGateways, Record<string, never>>;\n\nexport function createLazySharedStoreLankaVM<\n\tStoreState extends object,\n\tActions extends object,\n\tStore extends ALankaSharedStore<StoreState>,\n\tTGateways extends object,\n\tServices extends object,\n>(\n\tconfig: ILankaSharedStoreVMConfig<StoreState, Actions, Store, TGateways, Services>,\n): TLazySharedStoreReturn<StoreState, Actions, Store, TGateways, Services>;\n\n/**\n * The lazy `createSharedStoreLankaVM`: nothing is built until a screen asks.\n *\n * The mechanism is `createLazyLankaHook`; this file is the one line that says\n * which ViewModel gets built. `dispose` releases THIS ViewModel's scenario\n * subscriptions and never the shared store — the store is shared, other\n * ViewModels stand on it, and taking its state away is not this one's decision.\n * That is the hook's behaviour, not a special case here: it resets the scenario\n * and drops its reference, and a shared store outlives both.\n */\nexport function createLazySharedStoreLankaVM<\n\tStoreState extends object,\n\tActions extends object,\n\tStore extends ALankaSharedStore<StoreState>,\n\tTGateways extends object = Record<string, never>,\n\tServices extends object = Record<string, never>,\n>(config: ILankaSharedStoreVMConfig<StoreState, Actions, Store, TGateways, Services>) {\n\treturn createLazyLankaHook({\n\t\tname: config.name,\n\t\tkind: \"ssVM\",\n\t\tcreate: () => createSharedStoreLankaVM(config),\n\t});\n}\n","import { ALankaVMEnvironment } from \"../lanka-vm-environment/ALankaVMEnvironment\";\nimport { createSharedStoreLankaVM } from \"../../_factories/create-shared-store-lanka-vm/createSharedStoreLankaVM\";\nimport type { ALankaSharedStore } from \"../lanka-shared-store/ALankaSharedStore\";\nimport type { ILankaScenarioVM } from \"../../../scenario/_interfaces/ILankaScenarioVM\";\nimport type { ILankaSharedStoreVMContext } from \"../../_interfaces/ILankaSharedStoreVMContext\";\nimport type {\n\tILankaSharedStoreScenarioBinding,\n\tTLankaSharedStoreVMHook,\n} from \"../../_interfaces/ILankaSharedStoreVMConfig\";\n\n/**\n * A ViewModel over a store several ViewModels share, written as a class.\n *\n * The third rung of the ladder in `core/README.md`: reach for it only when two\n * ViewModels must CO-EDIT one state — a list and the badge that counts it, a\n * form and the header that says it is dirty. What the class adds over the\n * stateful base is where the state lives: in the store it is given, so `set`\n * writes there and `getStore` reads it.\n *\n * ```ts\n * class BadgeVM extends ALankaSharedStoreVM<ISelection, IBadgeActions, TodoStore> {\n * \tprotected readonly name = \"BadgeVM\";\n *\n * \tpublic constructor(store: TodoStore) {\n * \t\tsuper(store);\n * \t}\n *\n * \tprotected createActions(): IBadgeActions {\n * \t\treturn { clear: () => this.set({ selectedId: null }) };\n * \t}\n * }\n * ```\n *\n * Unlike its two siblings this one is a thin adapter rather than the\n * implementation: the store, the tracked hook and the two memoised state\n * references are the factory's, and duplicating them here would be the second\n * implementation the parity canon exists to prevent. What it gives a class-style\n * consumer is the same protected surface under the same names.\n *\n * Canon: `skills/parity/SKILL.md`.\n */\nexport abstract class ALankaSharedStoreVM<\n\tStoreState extends object,\n\tActions extends object,\n\tStore extends ALankaSharedStore<StoreState>,\n\tTGateways extends object = Record<string, never>,\n\tServices extends object = Record<string, never>,\n> extends ALankaVMEnvironment<TGateways, Services> {\n\t/** Names the ViewModel in the logs and in the scenario registry. */\n\tprotected abstract readonly name: string;\n\n\t/** The store this ViewModel and its siblings share. */\n\tprotected readonly store: Store;\n\n\t/** Writes into the shared store, which every reader of it hears about. */\n\tprotected set!: ILankaSharedStoreVMContext<\n\t\tStoreState,\n\t\tStoreState & Actions & ILankaScenarioVM,\n\t\tStore,\n\t\tTGateways,\n\t\tServices\n\t>[\"set\"];\n\n\t/** Reads the store's own state, without this ViewModel's actions on top. */\n\tprotected getStore!: () => StoreState;\n\n\t/** Reads the store's state WITH the actions, which is what a screen sees. */\n\tprotected get!: () => StoreState & Actions & ILankaScenarioVM;\n\n\t/** Fires a scenario, which every ViewModel bound to it then hears. */\n\tprotected trigger!: ILankaSharedStoreVMContext<\n\t\tStoreState,\n\t\tStoreState & Actions & ILankaScenarioVM,\n\t\tStore,\n\t\tTGateways,\n\t\tServices\n\t>[\"trigger\"];\n\n\tpublic constructor(store: Store) {\n\t\tsuper();\n\t\tthis.store = store;\n\t}\n\n\t/**\n\t * Turn off when one broad consumer reads most fields of the store — proxy\n\t * tracking then costs more than it saves.\n\t */\n\tprotected readonly enableAccessTrackingOptimization: boolean = true;\n\n\t/** The scenarios this ViewModel listens to, unsubscribed for it on reset. */\n\tprotected scenarioHandlers(): ILankaSharedStoreScenarioBinding<\n\t\tunknown,\n\t\tStoreState,\n\t\tActions,\n\t\tStore,\n\t\tTGateways,\n\t\tServices\n\t>[] {\n\t\treturn [];\n\t}\n\n\t/** The actions the screen calls. Written against `this.set` and `this.get`. */\n\tprotected abstract createActions(): Actions;\n\n\t/** Builds the hook a screen calls. One ViewModel per call. */\n\tpublic build(): TLankaSharedStoreVMHook<StoreState, Actions> {\n\t\treturn createSharedStoreLankaVM<StoreState, Actions, Store, TGateways, Services>({\n\t\t\tname: this.name,\n\t\t\tstore: this.store,\n\t\t\tenableAccessTrackingOptimization: this.enableAccessTrackingOptimization,\n\t\t\tgateways: () => this.createGateways(),\n\t\t\tservices: () => this.createServices(),\n\t\t\tscenarioHandlers: this.scenarioHandlers(),\n\t\t\tcreateActions: (context) => {\n\t\t\t\t// The context arrives here and becomes the protected surface, under the\n\t\t\t\t// same names it carries: a consumer who switches styles moves the same\n\t\t\t\t// call from `set(...)` to `this.set(...)` and changes nothing else.\n\t\t\t\tthis.set = context.set;\n\t\t\t\tthis.getStore = context.getStore;\n\t\t\t\tthis.get = context.get;\n\t\t\t\tthis.gateways = context.gateways;\n\t\t\t\tthis.services = context.services;\n\t\t\t\tthis.trigger = context.trigger;\n\n\t\t\t\treturn this.createActions();\n\t\t\t},\n\t\t\tonInit: () => {\n\t\t\t\tthis.onInit();\n\t\t\t},\n\t\t\tonReset: () => {\n\t\t\t\tthis.onReset();\n\t\t\t},\n\t\t});\n\t}\n}\n","import { createStore, StoreApi } from \"zustand/vanilla\";\n\n/**\n * Base abstraction for shared feature stores.\n *\n * A store built on this class is resolved through the shared-store locator and\n * reused across several ViewModels.\n */\nexport abstract class ALankaSharedStore<TState extends object> {\n\tprivate readonly api: StoreApi<TState>;\n\tprivate readonly createInitialState: () => TState;\n\n\tprotected constructor(createInitialState: () => TState) {\n\t\tthis.createInitialState = createInitialState;\n\t\tthis.api = createStore<TState>()(() => this.createInitialState());\n\t}\n\n\tpublic getApi(): StoreApi<TState> {\n\t\treturn this.api;\n\t}\n\n\tpublic getState(): TState {\n\t\treturn this.api.getState();\n\t}\n\n\tpublic setState(\n\t\tpartial: TState | Partial<TState> | ((state: TState) => TState | Partial<TState>),\n\t\treplace?: boolean,\n\t): void {\n\t\tconst resolved = typeof partial === \"function\" ? partial(this.api.getState()) : partial;\n\n\t\tif (replace) {\n\t\t\tthis.api.setState(resolved as TState, true);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.api.setState(resolved);\n\t}\n\n\tpublic subscribe(listener: (state: TState, prevState: TState) => void) {\n\t\treturn this.api.subscribe(listener);\n\t}\n\n\t/**\n\t * Back to what the store was built with.\n\t *\n\t * Public, and it was not: while this was `protected` only a subclass could\n\t * reset, so the class style had a capability the functional one could not\n\t * reach — the asymmetry `skills/parity/SKILL.md` forbids. A shared store needs\n\t * explicit reset points (see the ladder in `core/README.md`), and the\n\t * application that owns them is outside the class either way.\n\t */\n\tpublic reset(): void {\n\t\tthis.api.setState(this.createInitialState(), true);\n\t}\n}\n","import { ALankaSharedStore } from \"../../_abstractions/lanka-shared-store/ALankaSharedStore\";\n\n/**\n * A shared store, without writing a class whose body is one function.\n *\n * A shared store is the third rung of the ladder in `core/README.md`: reach for\n * it only when several ViewModels must CO-EDIT one state. Most stores have no\n * behaviour of their own — the state and how to build it fresh is the whole\n * declaration — and this is the shape for those.\n *\n * One implementation: what comes back is an `ALankaSharedStore`, so a reset, a\n * subscription and the zustand api behave identically either way.\n */\nexport const createLankaSharedStore = <TState extends object>(\n\tcreateInitialState: () => TState,\n): ALankaSharedStore<TState> => {\n\tclass FunctionalSharedStore extends ALankaSharedStore<TState> {\n\t\tpublic constructor() {\n\t\t\tsuper(createInitialState);\n\t\t}\n\t}\n\n\treturn new FunctionalSharedStore();\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/viewmodel/_abstractions/lanka-vm-environment/ALankaVMEnvironment.ts","../../src/viewmodel/_abstractions/lanka-vm/ALankaVM.ts","../../src/viewmodel/_internal/create-lanka-blind-spot-trap/createLankaBlindSpotTrap.ts","../../src/viewmodel/_internal/create-lanka-scenario-binder/createLankaScenarioBinder.ts","../../src/viewmodel/_internal/create-lanka-tracked-hook/createLankaTrackedHook.ts","../../src/viewmodel/_utils/resolve-lanka-dependency/resolveLankaDependency.ts","../../src/viewmodel/_factories/create-lanka-vm/createLankaVM.ts","../../src/viewmodel/_internal/create-lazy-lanka-hook/createLazyLankaHook.ts","../../src/viewmodel/_factories/create-lazy-lanka-vm/createLazyLankaVM.ts","../../src/viewmodel/_abstractions/lanka-stateless-vm/ALankaStatelessVM.ts","../../src/viewmodel/_factories/create-stateless-lanka-vm/createStatelessLankaVM.ts","../../src/viewmodel/_factories/create-lazy-stateless-lanka-vm/createLazyStatelessLankaVM.ts","../../src/viewmodel/_factories/create-shared-store-lanka-vm/createSharedStoreLankaVM.ts","../../src/viewmodel/_factories/create-lazy-shared-store-lanka-vm/createLazySharedStoreLankaVM.ts","../../src/viewmodel/_abstractions/lanka-shared-store-vm/ALankaSharedStoreVM.ts","../../src/viewmodel/_abstractions/lanka-shared-store/ALankaSharedStore.ts","../../src/viewmodel/_factories/create-lanka-shared-store/createLankaSharedStore.ts"],"sourcesContent":["/**\n * What every ViewModel is given, and the two moments it is told about.\n *\n * The three ViewModel shapes — stateful, stateless, over a shared store — differ\n * in where their state lives and in nothing else about this: each is handed a\n * data layer and a set of collaborators, and each is told when its scenarios are\n * bound and when they are about to be unbound.\n *\n * Stated once because a fifth hook added to two of the three is exactly the\n * divergence `skills/parity/SKILL.md` is written against, and three copies of a\n * default is how that starts.\n *\n * It is not a role and nothing extends it directly: the three bases do, and a\n * consumer extends one of them.\n */\nexport abstract class ALankaVMEnvironment<\n\tTGateways extends object = Record<string, never>,\n\tServices extends object = Record<string, never>,\n> {\n\t/** What `createGateways` answered: the data layer, kept apart from services. */\n\tprotected gateways!: TGateways;\n\n\t/** What `createServices` answered: everything that is not a gateway. */\n\tprotected services!: Services;\n\n\t/** The data layer, built once per ViewModel. */\n\tprotected createGateways(): TGateways {\n\t\treturn {} as TGateways;\n\t}\n\n\t/** Non-gateway collaborators, built once per ViewModel. */\n\tprotected createServices(): Services {\n\t\treturn {} as Services;\n\t}\n\n\t/** Runs after the scenarios are bound. */\n\tprotected onInit(): void {}\n\n\t/** Runs when the screen goes away, before the scenarios are unbound. */\n\tprotected onReset(): void {}\n}\n","import { ALankaVMEnvironment } from \"../lanka-vm-environment/ALankaVMEnvironment\";\nimport { create, StoreApi, UseBoundStore } from \"zustand\";\nimport { getLankaFlags } from \"../../../config/get-lanka-flags/getLankaFlags\";\nimport { createLankaBlindSpotTrap } from \"../../_internal/create-lanka-blind-spot-trap/createLankaBlindSpotTrap\";\nimport { createLankaScenarioBinder } from \"../../_internal/create-lanka-scenario-binder/createLankaScenarioBinder\";\nimport { createLankaTrackedHook } from \"../../_internal/create-lanka-tracked-hook/createLankaTrackedHook\";\nimport { ILankaScenarioVM } from \"../../../scenario/_interfaces/ILankaScenarioVM\";\nimport { lankaScenarioBootstrap } from \"../../../scenario/lanka-scenario-bootstrap/LankaScenarioBootstrap\";\nimport { lankaLogger } from \"../../../logger/lanka-logger/LankaLogger\";\nimport type { ILankaScenario } from \"../../../scenario/_interfaces/ILankaScenario\";\nimport type { ILankaVMContext } from \"../../_interfaces/ILankaVMContext\";\nimport type { TLankaVMEnhancer } from \"../../_types/TLankaVMEnhancer\";\nimport type { TLankaVMStateCreator } from \"../../_types/TLankaVMStateCreator\";\nimport type { TUnknownLankaScenarioBinding } from \"../../_types/TUnknownLankaScenarioBinding\";\n\n/**\n * A ViewModel written as a class: the state a screen reads, and the only place a\n * gateway is called from.\n *\n * This is the implementation of the role, and `createLankaVM` is the same thing\n * reached the other way — a subclass built from an options object. Neither style\n * can do what the other cannot, because there is nothing here to diverge from.\n *\n * The protected surface IS the functional context, member for member:\n * `set`, `get`, `gateways`, `services`, `trigger`. What the config supplies as a\n * value or a thunk, the class supplies by overriding a method of the same name —\n * `states`, `scenarioHandlers`, `enhancers`, `onInit`, `onReset` — with the two\n * dependency suppliers named `createGateways` and `createServices`, because\n * `gateways` and `services` already name what they answer.\n *\n * ```ts\n * class TodoVM extends ALankaVM<ITodoState, ITodoActions, ITodoGateways> {\n * \tprotected readonly name = \"TodoVM\";\n *\n * \tprotected states(): ITodoState {\n * \t\treturn { todos: [], isLoading: false };\n * \t}\n *\n * \tprotected createGateways(): ITodoGateways {\n * \t\treturn { todo: new TodoGateway() };\n * \t}\n *\n * \tprotected createActions(): ITodoActions {\n * \t\treturn {\n * \t\t\tload: async () => {\n * \t\t\t\tthis.set({ isLoading: true });\n * \t\t\t\tthis.set({ todos: await this.gateways.todo.list(), isLoading: false });\n * \t\t\t},\n * \t\t};\n * \t}\n * }\n *\n * export const useTodoVM = new TodoVM().build();\n * ```\n *\n * The access-tracking blind spot the functional style documents is the same one\n * here, and `enableAccessTrackingOptimization` is the same switch. A consumer\n * re-renders only for state keys it READ off the returned proxy; an action that\n * DERIVES a value reads the store through `get`, which the proxy never sees, so a\n * component whose only link to a key is such a getter never re-renders for it. In\n * development the mismatch announces itself by name rather than by a frozen\n * screen. Canon: `skills/parity/SKILL.md`.\n */\nexport abstract class ALankaVM<\n\tState extends object,\n\tActions extends object,\n\tTGateways extends object = Record<string, never>,\n\tServices extends object = Record<string, never>,\n> extends ALankaVMEnvironment<TGateways, Services> {\n\t/** Names the ViewModel in the logs, the scenario registry and the blind-spot warning. */\n\tprotected abstract readonly name: string;\n\n\t/**\n\t * Turn off when one broad consumer reads most fields, or when an action derives\n\t * what the screen shows — proxy tracking then costs more than it saves, and in\n\t * the second case it cannot see the read at all.\n\t */\n\tprotected readonly enableAccessTrackingOptimization: boolean = true;\n\n\t/** Writes state. Available from `createActions` onwards, never before. */\n\tprotected set!: StoreApi<State & Actions & ILankaScenarioVM>[\"setState\"];\n\n\t/** Reads state. The read a tracked hook cannot see — hence the switch above. */\n\tprotected get!: () => State & Actions & ILankaScenarioVM;\n\n\t/** Fires a scenario, which every ViewModel bound to it then hears. */\n\tprotected trigger = <TData>(scenario: ILankaScenario<TData>, data?: TData): void => {\n\t\tscenario.trigger(data);\n\t};\n\n\t/** The reactive fields the screen reads. */\n\tprotected states(): State {\n\t\treturn {} as State;\n\t}\n\n\t/** The scenarios this ViewModel listens to, unsubscribed for it on reset. */\n\tprotected scenarioHandlers(): TUnknownLankaScenarioBinding<\n\t\tState & Actions,\n\t\tTGateways,\n\t\tServices\n\t>[] {\n\t\treturn [];\n\t}\n\n\t/** Store middleware — `persist`, `lankaDevtools` — the last one applied outermost. */\n\tprotected enhancers(): TLankaVMEnhancer<State & Actions & ILankaScenarioVM>[] {\n\t\treturn [];\n\t}\n\n\t/** The actions the screen calls. Written against `this.set` and `this.get`. */\n\tprotected abstract createActions(): Actions;\n\n\t/**\n\t * The protected surface as an object, for the functional style.\n\t *\n\t * Assembled INSIDE the class because that is the only place `protected` can be\n\t * read — a context built from outside could carry only the public half, which is\n\t * the wrong half. Canon: `skills/parity/SKILL.md` section 3a.\n\t */\n\tprotected toStyleContext(): ILankaVMContext<\n\t\tState & Actions & ILankaScenarioVM,\n\t\tTGateways,\n\t\tServices\n\t> {\n\t\treturn {\n\t\t\tset: this.set,\n\t\t\tget: this.get,\n\t\t\tgateways: this.gateways,\n\t\t\tservices: this.services,\n\t\t\ttrigger: this.trigger,\n\t\t};\n\t}\n\n\t/** Builds the hook a screen calls. One store per call. */\n\tpublic build(): UseBoundStore<StoreApi<State & Actions & ILankaScenarioVM>> {\n\t\ttype TFullState = State & Actions & ILankaScenarioVM;\n\n\t\tlankaLogger.printViewModelLog(\"START Create VM\", this.name);\n\n\t\tconst blindSpot = createLankaBlindSpotTrap(\n\t\t\tthis.name,\n\t\t\tgetLankaFlags().isDevelopment === true,\n\t\t);\n\n\t\t// Asked once. Every call builds a fresh array, and this one used to be made\n\t\t// twice per ViewModel: once to bind the scenarios, once to decide whether to\n\t\t// register the ViewModel at all.\n\t\tconst bindings = this.scenarioHandlers();\n\n\t\tconst stateCreator: TLankaVMStateCreator<TFullState> = (set, get) => {\n\t\t\tthis.set = set;\n\t\t\tthis.get = blindSpot.observeGet(get);\n\t\t\tthis.gateways = this.createGateways();\n\t\t\tthis.services = this.createServices();\n\n\t\t\tconst actions = blindSpot.observeActions(this.createActions());\n\n\t\t\tconst { initializeScenario, resetScenario } = createLankaScenarioBinder({\n\t\t\t\tname: this.name,\n\t\t\t\tbindings,\n\t\t\t\tcontext: () => this.toStyleContext(),\n\t\t\t\tonInit: () => {\n\t\t\t\t\tthis.onInit();\n\t\t\t\t},\n\t\t\t\tonReset: () => {\n\t\t\t\t\tthis.onReset();\n\t\t\t\t},\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\t...this.states(),\n\t\t\t\t...actions,\n\t\t\t\tinitializeScenario,\n\t\t\t\tresetScenario,\n\t\t\t};\n\t\t};\n\n\t\tconst enhancedCreator = this.enhancers().reduce<TLankaVMStateCreator<TFullState>>(\n\t\t\t(creator, enhance) => enhance(creator),\n\t\t\tstateCreator,\n\t\t);\n\n\t\tconst store = create<TFullState>()(enhancedCreator);\n\n\t\tconst registerScenarioViewModel = (viewModel: ILankaScenarioVM): void => {\n\t\t\tif (bindings.length > 0) {\n\t\t\t\tlankaScenarioBootstrap.registerViewModel(viewModel, this.name);\n\t\t\t}\n\t\t};\n\n\t\tif (!this.enableAccessTrackingOptimization) {\n\t\t\tregisterScenarioViewModel(store.getState());\n\t\t\tlankaLogger.printViewModelLog(\"FINISH Create VM\", this.name);\n\n\t\t\treturn store;\n\t\t}\n\n\t\tconst useOptimizedViewModel = createLankaTrackedHook<TFullState>({\n\t\t\tsubscribe: (onChange) => store.subscribe(onChange),\n\t\t\treadState: () => store.getState(),\n\t\t\tonUntrackedChange: blindSpot.isArmed ? blindSpot.report : undefined,\n\t\t}) as UseBoundStore<StoreApi<TFullState>>;\n\n\t\tuseOptimizedViewModel.setState = store.setState;\n\t\tuseOptimizedViewModel.getState = store.getState;\n\t\tuseOptimizedViewModel.getInitialState = store.getInitialState;\n\t\tuseOptimizedViewModel.subscribe = store.subscribe;\n\n\t\tregisterScenarioViewModel(useOptimizedViewModel.getState());\n\n\t\tlankaLogger.printViewModelLog(\"FINISH Create VM\", this.name);\n\n\t\treturn useOptimizedViewModel;\n\t}\n}\n","export interface ILankaBlindSpotTrap {\n\t/** Whether the trap is armed. Everything below is inert when it is not. */\n\treadonly isArmed: boolean;\n\t/** Wraps `get` so reads made inside an action are attributed to it. */\n\tobserveGet: <TState>(get: () => TState) => () => TState;\n\t/** Wraps the actions so the trap knows which one is running. */\n\tobserveActions: <TActions extends object>(declared: TActions) => TActions;\n\t/** Reports a change that will not re-render, when the component reads the key. */\n\treport: (\n\t\ttrackedKeys: Set<string>,\n\t\tnext: Record<string, unknown>,\n\t\tprev: Record<string, unknown>,\n\t) => void;\n}\n\n/**\n * The blind spot: a key the component reads through a GETTER.\n *\n * Access tracking sees direct reads off the proxy. A key reached only inside a\n * derived getter is invisible to it, so a change to that key re-renders nothing\n * and the screen freezes with no error anywhere.\n *\n * The trap watches which keys each action reads through `get()`, and warns when\n * one of those changes without a tracked key changing with it.\n *\n * Development only: in production this is work on a hot path plus console noise\n * for somebody who does not write the code. Disarmed, every method is identity.\n */\nexport const createLankaBlindSpotTrap = (\n\tviewModelName: string,\n\tisArmed: boolean,\n): ILankaBlindSpotTrap => {\n\tif (!isArmed) {\n\t\treturn {\n\t\t\tisArmed: false,\n\t\t\tobserveGet: (get) => get,\n\t\t\tobserveActions: (declared) => declared,\n\t\t\treport: () => undefined,\n\t\t};\n\t}\n\n\t/** Action name → state keys it read through `get()`, past the proxy. */\n\tconst indirectReads = new Map<string, Set<string>>();\n\t/** Keys already warned about: a second warning adds nothing. */\n\tconst warnedKeys = new Set<string>();\n\tlet activeActionName: string | null = null;\n\n\treturn {\n\t\tisArmed: true,\n\n\t\tobserveGet<TState>(get: () => TState): () => TState {\n\t\t\treturn () => {\n\t\t\t\tconst state = get();\n\t\t\t\tconst actionName = activeActionName;\n\t\t\t\tif (actionName === null) return state;\n\n\t\t\t\treturn new Proxy(state as object, {\n\t\t\t\t\tget(target, prop, receiver) {\n\t\t\t\t\t\tif (typeof prop === \"string\") {\n\t\t\t\t\t\t\tlet keys = indirectReads.get(actionName);\n\t\t\t\t\t\t\tif (!keys) {\n\t\t\t\t\t\t\t\tkeys = new Set<string>();\n\t\t\t\t\t\t\t\tindirectReads.set(actionName, keys);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tkeys.add(prop);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn Reflect.get(target, prop, receiver) as unknown;\n\t\t\t\t\t},\n\t\t\t\t}) as TState;\n\t\t\t};\n\t\t},\n\n\t\tobserveActions<TActions extends object>(declared: TActions): TActions {\n\t\t\tconst observed = { ...declared } as Record<string, unknown>;\n\n\t\t\tfor (const [name, value] of Object.entries(declared)) {\n\t\t\t\tif (typeof value !== \"function\") continue;\n\n\t\t\t\tobserved[name] = (...args: unknown[]) => {\n\t\t\t\t\t// Restored rather than cleared: actions call each other, and clearing\n\t\t\t\t\t// would attribute the caller's later reads to nobody.\n\t\t\t\t\tconst previous = activeActionName;\n\t\t\t\t\tactiveActionName = name;\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn (value as (...a: unknown[]) => unknown)(...args);\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tactiveActionName = previous;\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn observed as TActions;\n\t\t},\n\n\t\treport(trackedKeys, next, prev): void {\n\t\t\tfor (const [changedKey, value] of Object.entries(next)) {\n\t\t\t\tif (Object.is(value, prev[changedKey])) continue;\n\t\t\t\tif (trackedKeys.has(changedKey) || warnedKeys.has(changedKey)) continue;\n\n\t\t\t\t// Not every untracked key is a fault: not reading what you do not need\n\t\t\t\t// is exactly what tracking exists for. The fault is a key the component\n\t\t\t\t// DOES read — through a getter taken off the proxy.\n\t\t\t\tconst viaGetter = [...trackedKeys].some((key) =>\n\t\t\t\t\tindirectReads.get(key)?.has(changedKey),\n\t\t\t\t);\n\t\t\t\tif (!viaGetter) continue;\n\n\t\t\t\twarnedKeys.add(changedKey);\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`[lanka] ${viewModelName}: key \"${changedKey}\" changed but no re-render will follow. ` +\n\t\t\t\t\t\t`The component reads it only through a getter, and tracking sees direct proxy reads only. ` +\n\t\t\t\t\t\t`Set enableAccessTrackingOptimization: false on this ViewModel — ` +\n\t\t\t\t\t\t`destructuring the key in the view \"for the side effect\" reads as dead code and will not survive a refactor.`,\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t};\n};\n","/**\n * A subscription option bag, as wide as the bus accepts.\n *\n * The binder passes it through and reads only `usedBy`; naming the rest here\n * would make this file a second declaration of the bus's options.\n */\nexport type TLankaScenarioBindingOptions = Record<string, unknown> & { usedBy?: string };\n\n/**\n * What the binder needs of a binding, and nothing more.\n *\n * Structural rather than the concrete `ILankaScenarioBinding`: three ViewModel\n * families declare their own binding type over their own context, and the binder\n * only ever calls `subscribe` and `handler`.\n */\nexport interface ILankaScenarioBindingLike<TContext, TData = unknown> {\n\tscenario: {\n\t\teventType: string;\n\t\tsubscribe: (\n\t\t\tcallback: (data?: TData) => void,\n\t\t\toptions?: TLankaScenarioBindingOptions,\n\t\t) => () => void;\n\t};\n\thandler: (context: TContext) => (data?: TData) => void;\n\toptions?: TLankaScenarioBindingOptions;\n}\n\nexport interface ILankaScenarioBinderConfig<TContext> {\n\t/** The ViewModel's name, reported to the bus as the subscriber. */\n\tname: string;\n\t/** What to bind. A ViewModel with none still gets a working binder. */\n\tbindings?: readonly ILankaScenarioBindingLike<TContext>[];\n\t/** The context handlers are built with, read at bind time. */\n\tcontext: () => TContext;\n\tonInit?: (context: TContext) => void;\n\tonReset?: (context: TContext) => void;\n}\n\nexport interface ILankaScenarioBinder {\n\t/** Whether the bindings are live. */\n\treadonly isInitialized: boolean;\n\t/** Subscribes every binding once. A second call does nothing. */\n\tinitializeScenario: () => void;\n\t/** Releases every subscription and allows a later re-initialisation. */\n\tresetScenario: () => void;\n}\n\n/**\n * The scenario lifetime of a ViewModel: bind once, release on reset.\n *\n * All three ViewModel families need exactly this, and all three had written it\n * out — two with an array plus a Set of seen event types, one with a Map. The\n * Map is the shape kept, because it does both jobs with one structure: the key\n * prevents a second subscription to the same event, and the value is the\n * function that releases THIS subscription.\n *\n * Releasing by callback identity, which an array invites, removes the first\n * entry carrying that callback rather than the caller's own — two handlers whose\n * closures compare equal cancel each other.\n */\nexport const createLankaScenarioBinder = <TContext>(\n\tconfig: ILankaScenarioBinderConfig<TContext>,\n): ILankaScenarioBinder => {\n\tconst subscriptions = new Map<string, () => void>();\n\tlet isInitialized = false;\n\n\treturn {\n\t\tget isInitialized(): boolean {\n\t\t\treturn isInitialized;\n\t\t},\n\n\t\tinitializeScenario(): void {\n\t\t\tif (isInitialized) return;\n\n\t\t\tconst context = config.context();\n\n\t\t\tfor (const binding of config.bindings ?? []) {\n\t\t\t\tconst key = binding.scenario.eventType;\n\t\t\t\tif (subscriptions.has(key)) continue;\n\n\t\t\t\tsubscriptions.set(\n\t\t\t\t\tkey,\n\t\t\t\t\tbinding.scenario.subscribe(binding.handler(context), {\n\t\t\t\t\t\tusedBy: config.name,\n\t\t\t\t\t\t...binding.options,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconfig.onInit?.(context);\n\t\t\tisInitialized = true;\n\t\t},\n\n\t\tresetScenario(): void {\n\t\t\tfor (const release of subscriptions.values()) release();\n\t\t\tsubscriptions.clear();\n\t\t\tisInitialized = false;\n\n\t\t\tconfig.onReset?.(config.context());\n\t\t},\n\t};\n};\n","import { useCallback, useRef, useSyncExternalStore } from \"react\";\n\nexport interface ILankaTrackedHookConfig<TState extends object> {\n\t/**\n\t * Subscribes to the source, reporting both states already in FULL shape.\n\t *\n\t * A shared-store ViewModel composes its full state from a store slice, so the\n\t * shaping happens here rather than inside the hook: the hook compares states,\n\t * it does not know how one is assembled.\n\t */\n\tsubscribe: (onChange: (next: TState, prev: TState) => void) => () => void;\n\t/** The current full state. */\n\treadState: () => TState;\n\t/**\n\t * Called when a change touched no tracked key, so no re-render will follow.\n\t *\n\t * The one seam the two ViewModel families differ on: only the plain factory\n\t * reports the blind spot, and only in development.\n\t */\n\tonUntrackedChange?: (\n\t\ttrackedKeys: Set<string>,\n\t\tnext: Record<string, unknown>,\n\t\tprev: Record<string, unknown>,\n\t) => void;\n}\n\nconst asRecord = (state: object): Record<string, unknown> => state as Record<string, unknown>;\n\n/**\n * The access-tracking hook every ViewModel factory renders through.\n *\n * Without a selector the component receives a Proxy that records which keys it\n * read; the next change re-renders only if one of THOSE keys moved. With a\n * selector the selector decides and tracking is bypassed.\n *\n * Both ViewModel families needed exactly this, and differed only in where the\n * state comes from — a store of their own, or a slice of a shared one. Those are\n * the two parameters above; the eighty lines below were copied.\n */\nexport const createLankaTrackedHook = <TState extends object>(\n\tconfig: ILankaTrackedHookConfig<TState>,\n) => {\n\treturn (selector?: (state: TState) => unknown): unknown => {\n\t\tconst selectorRef = useRef(selector);\n\t\tselectorRef.current = selector;\n\n\t\tconst trackedKeysRef = useRef<Set<string>>(new Set());\n\t\tconst trackedStateRef = useRef<TState | null>(null);\n\t\tconst trackedProxyRef = useRef<TState | null>(null);\n\n\t\t/**\n\t\t * Stable identity; the empty dependency list is deliberate.\n\t\t *\n\t\t * `useSyncExternalStore` keeps `subscribe` in an effect keyed on its\n\t\t * identity, so an inline arrow makes React tear the subscription down and\n\t\t * rebuild it on EVERY render of EVERY connected component — measured at 201\n\t\t * subscriptions for 200 renders. The body reads only refs and the\n\t\t * factory-scope config, never a prop or a render-scoped value, so there is\n\t\t * nothing for `[]` to capture stale.\n\t\t */\n\t\tconst subscribe = useCallback(\n\t\t\t(onStoreChange: () => void) =>\n\t\t\t\tconfig.subscribe((nextState, prevState) => {\n\t\t\t\t\tif (selectorRef.current) {\n\t\t\t\t\t\tonStoreChange();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst trackedKeys = trackedKeysRef.current;\n\t\t\t\t\tif (trackedKeys.size === 0) {\n\t\t\t\t\t\tonStoreChange();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst next = asRecord(nextState);\n\t\t\t\t\tconst prev = asRecord(prevState);\n\n\t\t\t\t\tfor (const key of trackedKeys) {\n\t\t\t\t\t\tif (!Object.is(next[key], prev[key])) {\n\t\t\t\t\t\t\tonStoreChange();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Reaching here means NO re-render will follow. If the changed key is\n\t\t\t\t\t// linked to the component through a getter it read, the screen froze.\n\t\t\t\t\tconfig.onUntrackedChange?.(trackedKeys, next, prev);\n\t\t\t\t}),\n\t\t\t[],\n\t\t);\n\n\t\treturn useSyncExternalStore(subscribe, readTracked, readUntracked);\n\n\t\tfunction readTracked(): unknown {\n\t\t\tconst state = config.readState();\n\t\t\tconst activeSelector = selectorRef.current;\n\n\t\t\tif (activeSelector) return activeSelector(state);\n\n\t\t\tif (trackedStateRef.current === state && trackedProxyRef.current) {\n\t\t\t\treturn trackedProxyRef.current;\n\t\t\t}\n\n\t\t\tconst trackedKeys = new Set<string>();\n\t\t\tconst proxyState = new Proxy(state, {\n\t\t\t\tget(target, prop, receiver) {\n\t\t\t\t\tif (typeof prop === \"string\") {\n\t\t\t\t\t\ttrackedKeys.add(prop);\n\t\t\t\t\t}\n\t\t\t\t\treturn Reflect.get(target, prop, receiver);\n\t\t\t\t},\n\t\t\t});\n\n\t\t\ttrackedKeysRef.current = trackedKeys;\n\t\t\ttrackedStateRef.current = state;\n\t\t\ttrackedProxyRef.current = proxyState;\n\n\t\t\treturn proxyState;\n\t\t}\n\n\t\t/**\n\t\t * The server snapshot: the state itself, never the Proxy.\n\t\t *\n\t\t * Tracking exists to skip renders a client would otherwise do; a server\n\t\t * renders once, and handing it a recording Proxy would only add work whose\n\t\t * result nothing reads.\n\t\t */\n\t\tfunction readUntracked(): unknown {\n\t\t\tconst state = config.readState();\n\t\t\tconst activeSelector = selectorRef.current;\n\n\t\t\treturn activeSelector ? activeSelector(state) : state;\n\t\t}\n\t};\n};\n","/**\n * A dependency bag given either directly or as a factory.\n *\n * The factory form exists so a ViewModel declared at module level does not\n * resolve its gateways at import time: the locator needs an active framework\n * instance, and a module body runs before one exists.\n */\nexport type TLankaDependencyBag<TBag extends object> = TBag | (() => TBag) | undefined;\n\n/**\n * Reads a dependency bag, whichever form it was declared in.\n *\n * All three ViewModel factories wrote this out twice each — once for gateways,\n * once for services — which is six copies of one three-line decision.\n */\nexport const resolveLankaDependency = <TBag extends object>(\n\tdeclared: TLankaDependencyBag<TBag>,\n): TBag => {\n\tif (typeof declared === \"function\") return declared();\n\treturn declared ?? ({} as TBag);\n};\n","import { StoreApi, UseBoundStore } from \"zustand\";\nimport { ALankaVM } from \"../../_abstractions/lanka-vm/ALankaVM\";\nimport { resolveLankaDependency } from \"../../_utils/resolve-lanka-dependency/resolveLankaDependency\";\nimport { ILankaScenarioVM } from \"../../../scenario/_interfaces/ILankaScenarioVM\";\nimport type { ILankaVMConfig } from \"../../_interfaces/ILankaVMConfig\";\n\n/**\n * The functional style of `ALankaVM`: a ViewModel declared as an options object.\n *\n * Everything it can do, the class can do, because this IS the class — the hooks a\n * subclass overrides arrive here as config fields of the same names, and the\n * protected surface arrives as the `ctx` every hook is handed. What a ViewModel is\n * and how it binds scenarios is documented once, on `ALankaVM`.\n *\n * ⚠️ ACCESS-TRACKING BLIND SPOT. A consumer re-renders only for state keys it READ\n * off the returned proxy. An action that DERIVES a value (`getSomeView()`) reads the\n * store through `get()`, which the proxy never sees — so a component whose only link\n * to a state key is such a getter will never re-render when that key changes.\n *\n * Set `enableAccessTrackingOptimization: false` on such a ViewModel. Do NOT patch it\n * in the view by destructuring the underlying keys for their side effect only: that\n * reads as dead code, so a refactor, an unused-variable cleanup or a lint autofix\n * removes it and the screen silently freezes again. `MeetingReportViewModel` carries\n * the worked example (its report toggles froze exactly that way, twice).\n *\n * In development the mismatch ANNOUNCES ITSELF: the framework sees that a key\n * changed, that no re-render will follow, and that the component reads that key\n * through a getter — and warns with the ViewModel and key names. \"Remember to\n * set the flag\" is not a mechanism.\n */\nexport function createLankaVM<State extends object, Actions extends object>(\n\tconfig: ILankaVMConfig<State, Actions, Record<string, never>, Record<string, never>>,\n): UseBoundStore<StoreApi<State & Actions & ILankaScenarioVM>>;\n\nexport function createLankaVM<\n\tState extends object,\n\tActions extends object,\n\tServices extends object,\n>(\n\tconfig: ILankaVMConfig<State, Actions, Record<string, never>, Services>,\n): UseBoundStore<StoreApi<State & Actions & ILankaScenarioVM>>;\n\nexport function createLankaVM<\n\tState extends object,\n\tActions extends object,\n\tTGateways extends object,\n>(\n\tconfig: ILankaVMConfig<State, Actions, TGateways, Record<string, never>>,\n): UseBoundStore<StoreApi<State & Actions & ILankaScenarioVM>>;\n\nexport function createLankaVM<\n\tState extends object,\n\tActions extends object,\n\tTGateways extends object,\n\tServices extends object,\n>(\n\tconfig: ILankaVMConfig<State, Actions, TGateways, Services>,\n): UseBoundStore<StoreApi<State & Actions & ILankaScenarioVM>>;\n\nexport function createLankaVM<\n\tState extends object,\n\tActions extends object,\n\tTGateways extends object = Record<string, never>,\n\tServices extends object = Record<string, never>,\n>(\n\tconfig: ILankaVMConfig<State, Actions, TGateways, Services>,\n): UseBoundStore<StoreApi<State & Actions & ILankaScenarioVM>> {\n\t/**\n\t * The bridge subclass lives here rather than in a shared helper because\n\t * `toStyleContext` is `protected`: only a class body deriving from `ALankaVM`\n\t * may read it. Canon: `skills/parity/SKILL.md` section 3a.\n\t */\n\tclass FunctionalVM extends ALankaVM<State, Actions, TGateways, Services> {\n\t\tprotected readonly name = config.name;\n\n\t\tprotected override readonly enableAccessTrackingOptimization =\n\t\t\tconfig.enableAccessTrackingOptimization ?? true;\n\n\t\tprotected override states(): State {\n\t\t\treturn config.states ?? ({} as State);\n\t\t}\n\n\t\tprotected override scenarioHandlers(): NonNullable<typeof config.scenarioHandlers> {\n\t\t\treturn config.scenarioHandlers ?? [];\n\t\t}\n\n\t\tprotected override enhancers(): NonNullable<typeof config.enhancers> {\n\t\t\treturn config.enhancers ?? [];\n\t\t}\n\n\t\tprotected override createGateways(): TGateways {\n\t\t\treturn resolveLankaDependency(config.gateways);\n\t\t}\n\n\t\tprotected override createServices(): Services {\n\t\t\treturn resolveLankaDependency(config.services);\n\t\t}\n\n\t\tprotected createActions(): Actions {\n\t\t\treturn config.createActions(this.toStyleContext());\n\t\t}\n\n\t\tprotected override onInit(): void {\n\t\t\tconfig.onInit?.(this.toStyleContext());\n\t\t}\n\n\t\tprotected override onReset(): void {\n\t\t\tconfig.onReset?.(this.toStyleContext());\n\t\t}\n\t}\n\n\treturn new FunctionalVM().build();\n}\n","import { lankaLogger } from \"../../../logger/lanka-logger/LankaLogger\";\n\n/**\n * What a lazy hook needs of the store behind it.\n *\n * Stated rather than cast: releasing a ViewModel means unsubscribing its\n * scenarios, so the mechanism does require this much — and every store it is\n * given has it, because `ILankaScenarioVM` is part of all three VM states.\n */\nexport interface ILankaReleasableStore {\n\tgetState: () => { resetScenario: () => void };\n}\n\n/** What every lazy factory is handed: a name for the log, and how to build. */\nexport interface ILankaLazyHookConfig<TStore> {\n\t/** The ViewModel's name, as the log line says it. */\n\tname: string;\n\t/** What the log calls this kind of ViewModel — `VM`, `slVM`, `ssVM`. */\n\tkind: string;\n\t/** Builds the real store. Called at most once until `release`. */\n\tcreate: () => TStore;\n}\n\n/** A lazily built store: everything the store is, plus `dispose`. */\nexport type TLazyLankaHook<TStore> = TStore & { dispose: () => void };\n\n/** The one store a lazy hook stands in front of, built at most once. */\ninterface ILankaLazySlot<TStore> {\n\tget: () => TStore;\n\trelease: () => void;\n}\n\n/**\n * Build once, release on demand: the state a lazy hook is made of.\n *\n * Separate from the forwarding below because they answer different questions —\n * WHEN the store exists, and WHERE a call goes. Read together they were one\n * function of fifty lines, which the composition canon calls what it is.\n */\nconst lazySlot = <TStore extends ILankaReleasableStore>(\n\tconfig: ILankaLazyHookConfig<TStore>,\n): ILankaLazySlot<TStore> => {\n\tlet store: TStore | null = null;\n\n\treturn {\n\t\tget: () => {\n\t\t\tif (!store) {\n\t\t\t\tlankaLogger.printViewModelLog(\n\t\t\t\t\t`LAZY: Creating ${config.kind} on first access`,\n\t\t\t\t\tconfig.name,\n\t\t\t\t);\n\t\t\t\tstore = config.create();\n\t\t\t}\n\t\t\treturn store;\n\t\t},\n\n\t\t/**\n\t\t * Releases the store. The next access builds a new one.\n\t\t *\n\t\t * Scenario subscriptions go first, through `resetScenario` — the same path\n\t\t * the between-tests reset uses. Dropping the reference without\n\t\t * unsubscribing would leave the bus holding handlers that write into a\n\t\t * discarded store.\n\t\t *\n\t\t * On a slot that never built, this does NOTHING: building a store in order\n\t\t * to destroy it is work with no result, and it would resurrect a ViewModel\n\t\t * a closed screen had just released.\n\t\t */\n\t\trelease: () => {\n\t\t\tif (!store) return;\n\t\t\tstore.getState().resetScenario();\n\t\t\tstore = null;\n\t\t},\n\t};\n};\n\n/**\n * How a member reaches the store: through a wrapper, always.\n *\n * The trap returns a FUNCTION for every member rather than the member itself, so\n * reading `useVM.setState` builds nothing and calling it builds the store. A trap\n * that resolved eagerly would end laziness the moment a devtool, a spread or a\n * debugger looked at the object — which is most of the ways an object is looked\n * at.\n *\n * `dispose` is the exception in both directions: it is not the store's, and it\n * must not build one.\n *\n * ## The thenable trap\n *\n * `then` is answered with `undefined`, never with a wrapper, and that line is\n * load-bearing. `await` and `Promise.resolve` decide whether a value is a\n * promise by READING `.then` and checking it is callable: a trap that returns a\n * function for every name says yes to that question for an object that is not a\n * promise. The runtime then calls it as `then(resolve, reject)`, the wrapper\n * forwards to a store member that does not exist, gets `undefined`, and neither\n * callback is ever invoked — so the `await` hangs FOREVER, with no error and no\n * stack.\n *\n * That makes `await someLazyVM` and every `async` function that RETURNS one a\n * silent deadlock, which is a shape a test harness reaches for constantly:\n * `const vm = await load()` resolves a promise with the proxy, and resolution\n * adopts a thenable. It cost an afternoon in a consumer's suite, where nineteen\n * tests timed out at 30s each and named their own first line.\n *\n * `catch` and `finally` are excluded with it. They are not part of the\n * thenable check, but an object answering `then` alone while a caller treats it\n * as a promise is the more confusing half of the same mistake — and no zustand\n * store has a member by either name.\n */\nconst PROMISE_MEMBERS: ReadonlySet<string | symbol> = new Set([\"then\", \"catch\", \"finally\"]);\n\nconst forwardEveryMember =\n\t<TStore>(slot: ILankaLazySlot<TStore>) =>\n\t(_target: object, property: string | symbol): unknown => {\n\t\tif (property === \"dispose\") return slot.release;\n\t\tif (PROMISE_MEMBERS.has(property)) return undefined;\n\n\t\treturn (...args: unknown[]) => {\n\t\t\tconst built = slot.get();\n\t\t\tconst member = (built as Record<string | symbol, unknown>)[property];\n\n\t\t\t// Every member of a zustand store is a method, and so is every one a\n\t\t\t// ViewModel adds — `getStoreState` included. A value member cannot be\n\t\t\t// classified without building the store first, which is the one thing a\n\t\t\t// property READ may not do, so it is handed back from the call instead:\n\t\t\t// `useVM.whatever()` gives the value.\n\t\t\treturn typeof member === \"function\"\n\t\t\t\t? (member as (...rest: unknown[]) => unknown).apply(built, args)\n\t\t\t\t: member;\n\t\t};\n\t};\n\n/**\n * The lazy half of every ViewModel factory, written once.\n *\n * Three factories used to carry this mechanism: build on first access, keep the\n * store, hand every member through, release on `dispose`. They differed in the\n * one line that builds — and, as it turned out, in which members they had\n * remembered to hand through.\n *\n * ## Why a Proxy rather than a list of members\n *\n * The three copies attached members BY HAND, and the three lists differed:\n * `getState` + `getInitialState` + `setState` + `subscribe` for the plain one,\n * `getState` alone for the stateless, `getState` + `getStoreState` for the\n * shared-store. Each list matched its own type, so nothing was broken — but the\n * plain one MIRRORS a zustand store, and a mirror is a promise to keep in step\n * with something somebody else releases. The day zustand adds a member, three\n * files have to hear about it.\n *\n * A Proxy cannot be incomplete. What the built store has, the lazy hook has, and\n * the type each factory declares is what narrows it back down to that variant's\n * contract — a lazy variant promises exactly what its eager twin promises, plus\n * `dispose`.\n */\nexport const createLazyLankaHook = <TStore extends ILankaReleasableStore>(\n\tconfig: ILankaLazyHookConfig<TStore>,\n): TLazyLankaHook<TStore> => {\n\tconst slot = lazySlot(config);\n\n\t// The hook itself: a function, so `useVM()` and `useVM(selector)` work before\n\t// anything is built.\n\tconst hook = (selector?: (state: unknown) => unknown): unknown => {\n\t\tconst built = slot.get() as unknown as (chosen?: unknown) => unknown;\n\t\treturn selector ? built(selector) : built();\n\t};\n\n\treturn new Proxy(hook, { get: forwardEveryMember(slot) }) as unknown as TLazyLankaHook<TStore>;\n};\n","import { ILankaScenarioVM } from \"../../../scenario/_interfaces/ILankaScenarioVM\";\nimport { createLazyLankaHook } from \"../../_internal/create-lazy-lanka-hook/createLazyLankaHook\";\nimport { createLankaVM } from \"../create-lanka-vm/createLankaVM\";\nimport type { ILankaVMConfig } from \"../../_interfaces/ILankaVMConfig\";\n\nexport function createLazyLankaVM<State extends object, Actions extends object>(\n\tconfig: ILankaVMConfig<State, Actions, Record<string, never>, Record<string, never>>,\n): TLazyLankaVM<\n\tReturnType<typeof createLankaVM<State, Actions, Record<string, never>, Record<string, never>>>,\n\tState & Actions & ILankaScenarioVM\n>;\n\nexport function createLazyLankaVM<\n\tState extends object,\n\tActions extends object,\n\tServices extends object,\n>(\n\tconfig: ILankaVMConfig<State, Actions, Record<string, never>, Services>,\n): TLazyLankaVM<\n\tReturnType<typeof createLankaVM<State, Actions, Record<string, never>, Services>>,\n\tState & Actions & ILankaScenarioVM\n>;\n\nexport function createLazyLankaVM<\n\tState extends object,\n\tActions extends object,\n\tTGateways extends object,\n>(\n\tconfig: ILankaVMConfig<State, Actions, TGateways, Record<string, never>>,\n): TLazyLankaVM<\n\tReturnType<typeof createLankaVM<State, Actions, TGateways, Record<string, never>>>,\n\tState & Actions & ILankaScenarioVM\n>;\n\nexport function createLazyLankaVM<\n\tState extends object,\n\tActions extends object,\n\tTGateways extends object,\n\tServices extends object,\n>(\n\tconfig: ILankaVMConfig<State, Actions, TGateways, Services>,\n): TLazyLankaVM<\n\tReturnType<typeof createLankaVM<State, Actions, TGateways, Services>>,\n\tState & Actions & ILankaScenarioVM\n>;\n\n/**\n * The lazy `createLankaVM`: nothing is built until a screen asks.\n *\n * For a ViewModel a session may never open — a settings screen, an admin panel,\n * a route behind a flag. The eager factory builds its store at module load, and\n * this one waits, which is the difference between paying for every screen the\n * application has and paying for the screens it shows.\n *\n * The mechanism is `createLazyLankaHook`, shared with the stateless and\n * shared-store variants, so all three hand through every member the store has\n * and release the same way. This file is the one line that says what gets built.\n */\nexport function createLazyLankaVM<\n\tState extends object,\n\tActions extends object,\n\tTGateways extends object = Record<string, never>,\n\tServices extends object = Record<string, never>,\n>(config: ILankaVMConfig<State, Actions, TGateways, Services>) {\n\treturn createLazyLankaHook({\n\t\tname: config.name,\n\t\tkind: \"VM\",\n\t\tcreate: () => createLankaVM(config),\n\t});\n}\n\n/**\n * A lazy ViewModel hook: everything an ordinary store does, plus `dispose`.\n */\nexport type TLazyLankaVM<TStore, TFullState> = TStore & {\n\tgetState: () => TFullState;\n\tdispose: () => void;\n};\n","import { ALankaVMEnvironment } from \"../lanka-vm-environment/ALankaVMEnvironment\";\nimport { ILankaScenarioVM } from \"../../../scenario/_interfaces/ILankaScenarioVM\";\nimport { lankaScenarioBootstrap } from \"../../../scenario/lanka-scenario-bootstrap/LankaScenarioBootstrap\";\nimport { lankaLogger } from \"../../../logger/lanka-logger/LankaLogger\";\nimport { createLankaScenarioBinder } from \"../../_internal/create-lanka-scenario-binder/createLankaScenarioBinder\";\nimport type { ILankaScenario } from \"../../../scenario/_interfaces/ILankaScenario\";\nimport type {\n\tILankaStatelessScenarioBinding,\n\tILankaStatelessVMContext,\n\tTLankaSetState,\n\tTLankaStatelessVMHook,\n} from \"../../_factories/create-stateless-lanka-vm/createStatelessLankaVM\";\n\n/**\n * A ViewModel that holds no reactive state: actions, and what they orchestrate.\n *\n * The second rung of the ladder in `core/README.md` written as a class. A screen\n * that reads nothing and only DOES things — a sign-out, a share sheet, a form\n * whose fields live in the form library — pays for a zustand store it never\n * reads; this is the same role without one.\n *\n * The protected surface IS the functional context, member for member: `set`,\n * `get`, `gateways`, `services`, `trigger`. What the config supplies as a value\n * or a thunk, the class supplies by overriding a method of the same name, with\n * the two dependency suppliers named `createGateways` and `createServices`\n * because `gateways` and `services` already name what they answer.\n *\n * ```ts\n * class SessionVM extends ALankaStatelessVM<ISessionActions, ISessionGateways> {\n * \tprotected readonly name = \"SessionVM\";\n *\n * \tprotected createGateways(): ISessionGateways {\n * \t\treturn { session: new SessionGateway() };\n * \t}\n *\n * \tprotected createActions(): ISessionActions {\n * \t\treturn {\n * \t\t\tsignOut: async () => {\n * \t\t\t\tawait this.gateways.session.signOut();\n * \t\t\t\tthis.trigger(sessionEnded);\n * \t\t\t},\n * \t\t};\n * \t}\n * }\n *\n * export const useSessionVM = new SessionVM().build();\n * ```\n *\n * Canon: `skills/parity/SKILL.md`.\n */\nexport abstract class ALankaStatelessVM<\n\tActions extends object,\n\tTGateways extends object = Record<string, never>,\n\tServices extends object = Record<string, never>,\n> extends ALankaVMEnvironment<TGateways, Services> {\n\t/** Names the ViewModel in the logs, the scenario registry and any warning. */\n\tprotected abstract readonly name: string;\n\n\t/** Writes state. Available from `createActions` onwards, never before. */\n\tprotected set!: TLankaSetState<Actions & ILankaScenarioVM>;\n\n\t/** Reads what the actions have written, including the actions themselves. */\n\tprotected get!: () => Actions & ILankaScenarioVM;\n\n\t/** Fires a scenario, which every ViewModel bound to it then hears. */\n\tprotected trigger = <TData>(scenario: ILankaScenario<TData>, data?: TData): void => {\n\t\tscenario.trigger(data);\n\t};\n\n\t/** The scenarios this ViewModel listens to, unsubscribed for it on reset. */\n\tprotected scenarioHandlers(): ILankaStatelessScenarioBinding<\n\t\tunknown,\n\t\tActions & ILankaScenarioVM,\n\t\tTGateways,\n\t\tServices\n\t>[] {\n\t\treturn [];\n\t}\n\n\t/** The actions the screen calls. Written against `this.set` and `this.get`. */\n\tprotected abstract createActions(): Actions;\n\n\t/**\n\t * The protected surface as an object, for the functional style.\n\t *\n\t * Assembled INSIDE the class because that is the only place `protected` can be\n\t * read. Canon: `skills/parity/SKILL.md` section 3a.\n\t */\n\tprotected toStyleContext(): ILankaStatelessVMContext<\n\t\tActions & ILankaScenarioVM,\n\t\tTGateways,\n\t\tServices\n\t> {\n\t\treturn {\n\t\t\tset: this.set,\n\t\t\tget: this.get,\n\t\t\tgateways: this.gateways,\n\t\t\tservices: this.services,\n\t\t\ttrigger: this.trigger,\n\t\t};\n\t}\n\n\t/** Builds the hook a screen calls. One ViewModel per call. */\n\tpublic build(): TLankaStatelessVMHook<Actions> {\n\t\ttype TFullState = Actions & ILankaScenarioVM;\n\n\t\tlankaLogger.printViewModelLog(\"START Create slVM\", this.name);\n\n\t\tlet state = {} as TFullState;\n\n\t\tthis.get = () => state;\n\t\tthis.set = (partial, replace) => {\n\t\t\tconst next =\n\t\t\t\ttypeof partial === \"function\"\n\t\t\t\t\t? (partial as (current: TFullState) => TFullState)(state)\n\t\t\t\t\t: partial;\n\n\t\t\tstate = replace ? (next as TFullState) : { ...state, ...next };\n\t\t};\n\n\t\tthis.gateways = this.createGateways();\n\t\tthis.services = this.createServices();\n\n\t\tconst actions = this.createActions();\n\t\tconst bindings = this.scenarioHandlers();\n\n\t\tconst { initializeScenario, resetScenario } = createLankaScenarioBinder({\n\t\t\tname: this.name,\n\t\t\tbindings,\n\t\t\tcontext: () => this.toStyleContext(),\n\t\t\tonInit: () => {\n\t\t\t\tthis.onInit();\n\t\t\t},\n\t\t\tonReset: () => {\n\t\t\t\tthis.onReset();\n\t\t\t},\n\t\t});\n\n\t\tstate = { ...state, ...actions, initializeScenario, resetScenario };\n\n\t\tif (bindings.length > 0) {\n\t\t\tlankaScenarioBootstrap.registerViewModel(state, this.name);\n\t\t}\n\n\t\tconst useStatelessViewModel = ((selector?: (full: TFullState) => unknown) =>\n\t\t\tselector ? selector(state) : state) as TLankaStatelessVMHook<Actions>;\n\n\t\tuseStatelessViewModel.getState = () => state;\n\n\t\tlankaLogger.printViewModelLog(\"FINISH Create slVM\", this.name);\n\n\t\treturn useStatelessViewModel;\n\t}\n}\n","import type { TLankaReplayRequest } from \"../../../scenario/event-bus/lanka-event-bus-instance/LankaEventBusInstance\";\nimport type { TLankaScenarioHandler } from \"../../_types/TLankaScenarioHandler\";\nimport { resolveLankaDependency } from \"../../_utils/resolve-lanka-dependency/resolveLankaDependency\";\nimport { ALankaStatelessVM } from \"../../_abstractions/lanka-stateless-vm/ALankaStatelessVM\";\nimport { ILankaScenario } from \"../../../scenario/_interfaces/ILankaScenario\";\nimport { ILankaScenarioVM } from \"../../../scenario/_interfaces/ILankaScenarioVM\";\n\nexport type TLankaSetState<TState> = (\n\tpartial: TState | Partial<TState> | ((state: TState) => TState | Partial<TState>),\n\treplace?: boolean,\n) => void;\n\nexport interface ILankaStatelessVMContext<\n\tTState,\n\tTGateways extends object,\n\tTServices extends object,\n> {\n\tset: TLankaSetState<TState>;\n\tget: () => TState;\n\tgateways: TGateways;\n\tservices: TServices;\n\ttrigger: <T>(scenario: ILankaScenario<T>, data?: T) => void;\n}\n\nexport interface ILankaStatelessScenarioBinding<\n\tTData,\n\tTState extends object,\n\tTGateways extends object,\n\tTServices extends object,\n> {\n\tscenario: ILankaScenario<TData>;\n\thandler: (\n\t\tctx: ILankaStatelessVMContext<TState, TGateways, TServices>,\n\t) => TLankaScenarioHandler<TData>;\n\toptions?: {\n\t\tpriority?: number;\n\t\treplay?: TLankaReplayRequest;\n\t\tusedBy?: string;\n\t};\n}\n\nexport type TLankaStatelessVMConfig<\n\tActions extends object,\n\tTGateways extends object = Record<string, never>,\n\tServices extends object = Record<string, never>,\n> = {\n\tname: string;\n\tcreateActions: (\n\t\tctx: ILankaStatelessVMContext<Actions & ILankaScenarioVM, TGateways, Services>,\n\t) => Actions;\n\tscenarioHandlers?: ILankaStatelessScenarioBinding<\n\t\tunknown,\n\t\tActions & ILankaScenarioVM,\n\t\tTGateways,\n\t\tServices\n\t>[];\n\tservices?: Services | (() => Services);\n\tgateways?: TGateways | (() => TGateways);\n\tonInit?: (\n\t\tctx: ILankaStatelessVMContext<Actions & ILankaScenarioVM, TGateways, Services>,\n\t) => void;\n\tonReset?: (\n\t\tctx: ILankaStatelessVMContext<Actions & ILankaScenarioVM, TGateways, Services>,\n\t) => void;\n};\n\nexport type TLankaStatelessVMHook<Actions extends object> = {\n\t<TSelected = Actions & ILankaScenarioVM>(\n\t\tselector?: (full: Actions & ILankaScenarioVM) => TSelected,\n\t): TSelected;\n\tgetState: () => Actions & ILankaScenarioVM;\n};\n\nexport function createStatelessLankaVM<Actions extends object>(\n\tconfig: TLankaStatelessVMConfig<Actions, Record<string, never>, Record<string, never>>,\n): TLankaStatelessVMHook<Actions>;\n\nexport function createStatelessLankaVM<Actions extends object, Services extends object>(\n\tconfig: TLankaStatelessVMConfig<Actions, Record<string, never>, Services>,\n): TLankaStatelessVMHook<Actions>;\n\nexport function createStatelessLankaVM<Actions extends object, TGateways extends object>(\n\tconfig: TLankaStatelessVMConfig<Actions, TGateways, Record<string, never>>,\n): TLankaStatelessVMHook<Actions>;\n\nexport function createStatelessLankaVM<\n\tActions extends object,\n\tTGateways extends object,\n\tServices extends object,\n>(config: TLankaStatelessVMConfig<Actions, TGateways, Services>): TLankaStatelessVMHook<Actions>;\n\n/**\n * The functional style of `ALankaStatelessVM`: actions declared as an options object.\n *\n * Same outward shape as the stateful factory — a hook-like function with\n * `getState` — and no zustand store under it, because a ViewModel that holds\n * nothing has nothing to subscribe to. What it is and how it binds scenarios is\n * documented once, on the class.\n */\nexport function createStatelessLankaVM<\n\tActions extends object,\n\tTGateways extends object = Record<string, never>,\n\tServices extends object = Record<string, never>,\n>(config: TLankaStatelessVMConfig<Actions, TGateways, Services>): TLankaStatelessVMHook<Actions> {\n\t/**\n\t * The bridge subclass lives here rather than in a shared helper because\n\t * `toStyleContext` is `protected`: only a class body deriving from\n\t * `ALankaStatelessVM` may read it. Canon: `skills/parity/SKILL.md` section 3a.\n\t */\n\tclass FunctionalStatelessVM extends ALankaStatelessVM<Actions, TGateways, Services> {\n\t\tprotected readonly name = config.name;\n\n\t\tprotected override scenarioHandlers(): NonNullable<typeof config.scenarioHandlers> {\n\t\t\treturn config.scenarioHandlers ?? [];\n\t\t}\n\n\t\tprotected override createGateways(): TGateways {\n\t\t\treturn resolveLankaDependency(config.gateways);\n\t\t}\n\n\t\tprotected override createServices(): Services {\n\t\t\treturn resolveLankaDependency(config.services);\n\t\t}\n\n\t\tprotected createActions(): Actions {\n\t\t\treturn config.createActions(this.toStyleContext());\n\t\t}\n\n\t\tprotected override onInit(): void {\n\t\t\tconfig.onInit?.(this.toStyleContext());\n\t\t}\n\n\t\tprotected override onReset(): void {\n\t\t\tconfig.onReset?.(this.toStyleContext());\n\t\t}\n\t}\n\n\treturn new FunctionalStatelessVM().build();\n}\n","import { ILankaScenarioVM } from \"../../../scenario/_interfaces/ILankaScenarioVM\";\nimport { createStatelessLankaVM } from \"../create-stateless-lanka-vm/createStatelessLankaVM\";\nimport type { ILankaVMConfig } from \"../../_interfaces/ILankaVMConfig\";\nimport { createLazyLankaHook } from \"../../_internal/create-lazy-lanka-hook/createLazyLankaHook\";\n\nexport type TLankaStatelessVMConfig<\n\tActions extends object,\n\tTGateways extends object = Record<string, never>,\n\tServices extends object = Record<string, never>,\n> = Omit<ILankaVMConfig<object, Actions, TGateways, Services>, \"states\"> & {\n\tstates?: never;\n};\n\ntype TLazyStatelessReturn<\n\tActions extends object,\n\tTGateways extends object,\n\tServices extends object,\n> = ReturnType<typeof createStatelessLankaVM<Actions, TGateways, Services>> & {\n\tgetState: () => Actions & ILankaScenarioVM;\n\tdispose: () => void;\n};\n\nexport function createLazyStatelessLankaVM<Actions extends object>(\n\tconfig: TLankaStatelessVMConfig<Actions, Record<string, never>, Record<string, never>>,\n): TLazyStatelessReturn<Actions, Record<string, never>, Record<string, never>>;\n\nexport function createLazyStatelessLankaVM<Actions extends object, Services extends object>(\n\tconfig: TLankaStatelessVMConfig<Actions, Record<string, never>, Services>,\n): TLazyStatelessReturn<Actions, Record<string, never>, Services>;\n\nexport function createLazyStatelessLankaVM<Actions extends object, TGateways extends object>(\n\tconfig: TLankaStatelessVMConfig<Actions, TGateways, Record<string, never>>,\n): TLazyStatelessReturn<Actions, TGateways, Record<string, never>>;\n\nexport function createLazyStatelessLankaVM<\n\tActions extends object,\n\tTGateways extends object,\n\tServices extends object,\n>(\n\tconfig: TLankaStatelessVMConfig<Actions, TGateways, Services>,\n): TLazyStatelessReturn<Actions, TGateways, Services>;\n\n/**\n * The lazy `createStatelessLankaVM`: nothing is built until a screen asks.\n *\n * The mechanism is `createLazyLankaHook` — build on first access, hand every\n * member through, release on `dispose` — and this file is the one line that says\n * WHICH ViewModel is built. It used to be a copy of that mechanism, and the copy\n * had forgotten `setState`, `subscribe` and `getInitialState`: typed as the whole\n * store, absent at runtime.\n */\nexport function createLazyStatelessLankaVM<\n\tActions extends object,\n\tTGateways extends object = Record<string, never>,\n\tServices extends object = Record<string, never>,\n>(config: TLankaStatelessVMConfig<Actions, TGateways, Services>) {\n\treturn createLazyLankaHook({\n\t\tname: config.name,\n\t\tkind: \"slVM\",\n\t\tcreate: () => createStatelessLankaVM(config),\n\t});\n}\n","import { useStore } from \"zustand\";\nimport { resolveLankaDependency } from \"../../_utils/resolve-lanka-dependency/resolveLankaDependency\";\nimport { createLankaScenarioBinder } from \"../../_internal/create-lanka-scenario-binder/createLankaScenarioBinder\";\nimport { createLankaTrackedHook } from \"../../_internal/create-lanka-tracked-hook/createLankaTrackedHook\";\nimport { ILankaScenarioVM } from \"../../../scenario/_interfaces/ILankaScenarioVM\";\nimport { lankaScenarioBootstrap } from \"../../../scenario/lanka-scenario-bootstrap/LankaScenarioBootstrap\";\nimport { lankaLogger } from \"../../../logger/lanka-logger/LankaLogger\";\nimport type {\n\tILankaSharedStoreVMConfig,\n\tTLankaSharedStoreVMHook,\n} from \"../../_interfaces/ILankaSharedStoreVMConfig\";\nimport type { ILankaSharedStoreVMContext } from \"../../_interfaces/ILankaSharedStoreVMContext\";\nimport { ALankaSharedStore } from \"../../_abstractions/lanka-shared-store/ALankaSharedStore\";\n\n/**\n * Factory for ViewModels backed by an external shared store instance.\n * Multiple ViewModels can be created on top of the same store instance.\n */\nexport function createSharedStoreLankaVM<\n\tStoreState extends object,\n\tActions extends object,\n\tStore extends ALankaSharedStore<StoreState>,\n>(\n\tconfig: ILankaSharedStoreVMConfig<\n\t\tStoreState,\n\t\tActions,\n\t\tStore,\n\t\tRecord<string, never>,\n\t\tRecord<string, never>\n\t>,\n): TLankaSharedStoreVMHook<StoreState, Actions>;\n\nexport function createSharedStoreLankaVM<\n\tStoreState extends object,\n\tActions extends object,\n\tStore extends ALankaSharedStore<StoreState>,\n\tServices extends object,\n>(\n\tconfig: ILankaSharedStoreVMConfig<StoreState, Actions, Store, Record<string, never>, Services>,\n): TLankaSharedStoreVMHook<StoreState, Actions>;\n\nexport function createSharedStoreLankaVM<\n\tStoreState extends object,\n\tActions extends object,\n\tStore extends ALankaSharedStore<StoreState>,\n\tTGateways extends object,\n>(\n\tconfig: ILankaSharedStoreVMConfig<StoreState, Actions, Store, TGateways, Record<string, never>>,\n): TLankaSharedStoreVMHook<StoreState, Actions>;\n\nexport function createSharedStoreLankaVM<\n\tStoreState extends object,\n\tActions extends object,\n\tStore extends ALankaSharedStore<StoreState>,\n\tTGateways extends object,\n\tServices extends object,\n>(\n\tconfig: ILankaSharedStoreVMConfig<StoreState, Actions, Store, TGateways, Services>,\n): TLankaSharedStoreVMHook<StoreState, Actions>;\n\nexport function createSharedStoreLankaVM<\n\tStoreState extends object,\n\tActions extends object,\n\tStore extends ALankaSharedStore<StoreState>,\n\tTGateways extends object = Record<string, never>,\n\tServices extends object = Record<string, never>,\n>(config: ILankaSharedStoreVMConfig<StoreState, Actions, Store, TGateways, Services>) {\n\tlankaLogger.printViewModelLog(\"START Create ssVM\", config.name);\n\n\ttype TFullState = StoreState & Actions & ILankaScenarioVM;\n\n\t/**\n\t * Unsubscribe functions, plus the event types already subscribed to.\n\t *\n\t * Two separate jobs, kept separate: the array releases subscriptions, the set\n\t * prevents subscribing to one event type twice.\n\t */\n\tlet actions = {} as Actions;\n\n\tconst gateways = resolveLankaDependency(config.gateways);\n\tconst services = resolveLankaDependency(config.services);\n\n\tlet lastStoreStateRef: StoreState | null = null;\n\tlet lastFullStateRef: TFullState | null = null;\n\n\tconst buildFullState = (storeState: StoreState): TFullState => {\n\t\tif (lastStoreStateRef === storeState && lastFullStateRef) {\n\t\t\treturn lastFullStateRef;\n\t\t}\n\n\t\tlastStoreStateRef = storeState;\n\t\tlastFullStateRef = {\n\t\t\t...storeState,\n\t\t\t...actions,\n\t\t\tinitializeScenario,\n\t\t\tresetScenario,\n\t\t};\n\n\t\treturn lastFullStateRef;\n\t};\n\n\tconst getFullState = (): TFullState => buildFullState(config.store.getState());\n\n\tconst ctx: ILankaSharedStoreVMContext<StoreState, TFullState, Store, TGateways, Services> = {\n\t\tset: (partial, replace) => config.store.setState(partial, replace),\n\t\tgetStore: () => config.store.getState(),\n\t\tget: () => getFullState(),\n\t\tstore: config.store,\n\t\tgateways,\n\t\tservices,\n\t\ttrigger: (scenario, data) => scenario.trigger(data),\n\t};\n\n\tconst { initializeScenario, resetScenario } = createLankaScenarioBinder({\n\t\tname: config.name,\n\t\tbindings: config.scenarioHandlers,\n\t\tcontext: () => ctx,\n\t\tonInit: config.onInit,\n\t\tonReset: config.onReset,\n\t});\n\n\tactions = config.createActions(ctx);\n\tlastStoreStateRef = null;\n\tlastFullStateRef = null;\n\tconst isAccessTrackingEnabled = config.enableAccessTrackingOptimization ?? true;\n\n\tconst useTrackedSharedStoreViewModel = createLankaTrackedHook<TFullState>({\n\t\tsubscribe: (onChange) =>\n\t\t\tconfig.store.subscribe((storeState, prevStoreState) => {\n\t\t\t\tonChange(buildFullState(storeState), buildFullState(prevStoreState));\n\t\t\t}),\n\t\treadState: getFullState,\n\t}) as TLankaSharedStoreVMHook<StoreState, Actions>;\n\n\tconst useUntrackedSharedStoreViewModel = ((selector?: (state: TFullState) => unknown) =>\n\t\tuseStore(config.store.getApi(), (storeState) => {\n\t\t\tconst fullState = buildFullState(storeState);\n\n\t\t\tif (selector) {\n\t\t\t\treturn selector(fullState);\n\t\t\t}\n\n\t\t\treturn fullState;\n\t\t})) as TLankaSharedStoreVMHook<StoreState, Actions>;\n\n\tconst useSharedStoreViewModel = isAccessTrackingEnabled\n\t\t? useTrackedSharedStoreViewModel\n\t\t: useUntrackedSharedStoreViewModel;\n\n\tuseSharedStoreViewModel.getState = () => getFullState();\n\tuseSharedStoreViewModel.getStoreState = () => config.store.getState();\n\n\tif (config.scenarioHandlers && config.scenarioHandlers.length > 0) {\n\t\tconst scenarioViewModel: ILankaScenarioVM = {\n\t\t\tinitializeScenario,\n\t\t\tresetScenario,\n\t\t};\n\t\tlankaScenarioBootstrap.registerViewModel(scenarioViewModel, config.name);\n\t}\n\n\tlankaLogger.printViewModelLog(\"FINISH Create ssVM\", config.name);\n\n\treturn useSharedStoreViewModel;\n}\n","import { ILankaScenarioVM } from \"../../../scenario/_interfaces/ILankaScenarioVM\";\nimport { ALankaSharedStore } from \"../../_abstractions/lanka-shared-store/ALankaSharedStore\";\nimport { createLazyLankaHook } from \"../../_internal/create-lazy-lanka-hook/createLazyLankaHook\";\nimport { createSharedStoreLankaVM } from \"../create-shared-store-lanka-vm/createSharedStoreLankaVM\";\nimport type { ILankaSharedStoreVMConfig } from \"../../_interfaces/ILankaSharedStoreVMConfig\";\n\n/**\n * What a lazy shared-store ViewModel is, in the type as well as at runtime.\n *\n * The overloads used to promise the eager factory's return and nothing else, so\n * `dispose` and `getStoreState` existed on the object and not in the type: a\n * consumer releasing a closed screen's ViewModel got a compile error for calling\n * something that was there.\n */\ntype TLazySharedStoreReturn<\n\tStoreState extends object,\n\tActions extends object,\n\tStore extends ALankaSharedStore<StoreState>,\n\tTGateways extends object,\n\tServices extends object,\n> = ReturnType<typeof createSharedStoreLankaVM<StoreState, Actions, Store, TGateways, Services>> & {\n\tgetState: () => StoreState & Actions & ILankaScenarioVM;\n\tgetStoreState: () => StoreState;\n\tdispose: () => void;\n};\n\nexport function createLazySharedStoreLankaVM<\n\tStoreState extends object,\n\tActions extends object,\n\tStore extends ALankaSharedStore<StoreState>,\n>(\n\tconfig: ILankaSharedStoreVMConfig<\n\t\tStoreState,\n\t\tActions,\n\t\tStore,\n\t\tRecord<string, never>,\n\t\tRecord<string, never>\n\t>,\n): TLazySharedStoreReturn<StoreState, Actions, Store, Record<string, never>, Record<string, never>>;\n\nexport function createLazySharedStoreLankaVM<\n\tStoreState extends object,\n\tActions extends object,\n\tStore extends ALankaSharedStore<StoreState>,\n\tTGateways extends object,\n>(\n\tconfig: ILankaSharedStoreVMConfig<StoreState, Actions, Store, TGateways, Record<string, never>>,\n): TLazySharedStoreReturn<StoreState, Actions, Store, TGateways, Record<string, never>>;\n\nexport function createLazySharedStoreLankaVM<\n\tStoreState extends object,\n\tActions extends object,\n\tStore extends ALankaSharedStore<StoreState>,\n\tTGateways extends object,\n\tServices extends object,\n>(\n\tconfig: ILankaSharedStoreVMConfig<StoreState, Actions, Store, TGateways, Services>,\n): TLazySharedStoreReturn<StoreState, Actions, Store, TGateways, Services>;\n\n/**\n * The lazy `createSharedStoreLankaVM`: nothing is built until a screen asks.\n *\n * The mechanism is `createLazyLankaHook`; this file is the one line that says\n * which ViewModel gets built. `dispose` releases THIS ViewModel's scenario\n * subscriptions and never the shared store — the store is shared, other\n * ViewModels stand on it, and taking its state away is not this one's decision.\n * That is the hook's behaviour, not a special case here: it resets the scenario\n * and drops its reference, and a shared store outlives both.\n */\nexport function createLazySharedStoreLankaVM<\n\tStoreState extends object,\n\tActions extends object,\n\tStore extends ALankaSharedStore<StoreState>,\n\tTGateways extends object = Record<string, never>,\n\tServices extends object = Record<string, never>,\n>(config: ILankaSharedStoreVMConfig<StoreState, Actions, Store, TGateways, Services>) {\n\treturn createLazyLankaHook({\n\t\tname: config.name,\n\t\tkind: \"ssVM\",\n\t\tcreate: () => createSharedStoreLankaVM(config),\n\t});\n}\n","import { ALankaVMEnvironment } from \"../lanka-vm-environment/ALankaVMEnvironment\";\nimport { createSharedStoreLankaVM } from \"../../_factories/create-shared-store-lanka-vm/createSharedStoreLankaVM\";\nimport type { ALankaSharedStore } from \"../lanka-shared-store/ALankaSharedStore\";\nimport type { ILankaScenarioVM } from \"../../../scenario/_interfaces/ILankaScenarioVM\";\nimport type { ILankaSharedStoreVMContext } from \"../../_interfaces/ILankaSharedStoreVMContext\";\nimport type {\n\tILankaSharedStoreScenarioBinding,\n\tTLankaSharedStoreVMHook,\n} from \"../../_interfaces/ILankaSharedStoreVMConfig\";\n\n/**\n * A ViewModel over a store several ViewModels share, written as a class.\n *\n * The third rung of the ladder in `core/README.md`: reach for it only when two\n * ViewModels must CO-EDIT one state — a list and the badge that counts it, a\n * form and the header that says it is dirty. What the class adds over the\n * stateful base is where the state lives: in the store it is given, so `set`\n * writes there and `getStore` reads it.\n *\n * ```ts\n * class BadgeVM extends ALankaSharedStoreVM<ISelection, IBadgeActions, TodoStore> {\n * \tprotected readonly name = \"BadgeVM\";\n *\n * \tpublic constructor(store: TodoStore) {\n * \t\tsuper(store);\n * \t}\n *\n * \tprotected createActions(): IBadgeActions {\n * \t\treturn { clear: () => this.set({ selectedId: null }) };\n * \t}\n * }\n * ```\n *\n * Unlike its two siblings this one is a thin adapter rather than the\n * implementation: the store, the tracked hook and the two memoised state\n * references are the factory's, and duplicating them here would be the second\n * implementation the parity canon exists to prevent. What it gives a class-style\n * consumer is the same protected surface under the same names.\n *\n * Canon: `skills/parity/SKILL.md`.\n */\nexport abstract class ALankaSharedStoreVM<\n\tStoreState extends object,\n\tActions extends object,\n\tStore extends ALankaSharedStore<StoreState>,\n\tTGateways extends object = Record<string, never>,\n\tServices extends object = Record<string, never>,\n> extends ALankaVMEnvironment<TGateways, Services> {\n\t/** Names the ViewModel in the logs and in the scenario registry. */\n\tprotected abstract readonly name: string;\n\n\t/** The store this ViewModel and its siblings share. */\n\tprotected readonly store: Store;\n\n\t/** Writes into the shared store, which every reader of it hears about. */\n\tprotected set!: ILankaSharedStoreVMContext<\n\t\tStoreState,\n\t\tStoreState & Actions & ILankaScenarioVM,\n\t\tStore,\n\t\tTGateways,\n\t\tServices\n\t>[\"set\"];\n\n\t/** Reads the store's own state, without this ViewModel's actions on top. */\n\tprotected getStore!: () => StoreState;\n\n\t/** Reads the store's state WITH the actions, which is what a screen sees. */\n\tprotected get!: () => StoreState & Actions & ILankaScenarioVM;\n\n\t/** Fires a scenario, which every ViewModel bound to it then hears. */\n\tprotected trigger!: ILankaSharedStoreVMContext<\n\t\tStoreState,\n\t\tStoreState & Actions & ILankaScenarioVM,\n\t\tStore,\n\t\tTGateways,\n\t\tServices\n\t>[\"trigger\"];\n\n\tpublic constructor(store: Store) {\n\t\tsuper();\n\t\tthis.store = store;\n\t}\n\n\t/**\n\t * Turn off when one broad consumer reads most fields of the store — proxy\n\t * tracking then costs more than it saves.\n\t */\n\tprotected readonly enableAccessTrackingOptimization: boolean = true;\n\n\t/** The scenarios this ViewModel listens to, unsubscribed for it on reset. */\n\tprotected scenarioHandlers(): ILankaSharedStoreScenarioBinding<\n\t\tunknown,\n\t\tStoreState,\n\t\tActions,\n\t\tStore,\n\t\tTGateways,\n\t\tServices\n\t>[] {\n\t\treturn [];\n\t}\n\n\t/** The actions the screen calls. Written against `this.set` and `this.get`. */\n\tprotected abstract createActions(): Actions;\n\n\t/** Builds the hook a screen calls. One ViewModel per call. */\n\tpublic build(): TLankaSharedStoreVMHook<StoreState, Actions> {\n\t\treturn createSharedStoreLankaVM<StoreState, Actions, Store, TGateways, Services>({\n\t\t\tname: this.name,\n\t\t\tstore: this.store,\n\t\t\tenableAccessTrackingOptimization: this.enableAccessTrackingOptimization,\n\t\t\tgateways: () => this.createGateways(),\n\t\t\tservices: () => this.createServices(),\n\t\t\tscenarioHandlers: this.scenarioHandlers(),\n\t\t\tcreateActions: (context) => {\n\t\t\t\t// The context arrives here and becomes the protected surface, under the\n\t\t\t\t// same names it carries: a consumer who switches styles moves the same\n\t\t\t\t// call from `set(...)` to `this.set(...)` and changes nothing else.\n\t\t\t\tthis.set = context.set;\n\t\t\t\tthis.getStore = context.getStore;\n\t\t\t\tthis.get = context.get;\n\t\t\t\tthis.gateways = context.gateways;\n\t\t\t\tthis.services = context.services;\n\t\t\t\tthis.trigger = context.trigger;\n\n\t\t\t\treturn this.createActions();\n\t\t\t},\n\t\t\tonInit: () => {\n\t\t\t\tthis.onInit();\n\t\t\t},\n\t\t\tonReset: () => {\n\t\t\t\tthis.onReset();\n\t\t\t},\n\t\t});\n\t}\n}\n","import { createStore, StoreApi } from \"zustand/vanilla\";\n\n/**\n * Base abstraction for shared feature stores.\n *\n * A store built on this class is resolved through the shared-store locator and\n * reused across several ViewModels.\n */\nexport abstract class ALankaSharedStore<TState extends object> {\n\tprivate readonly api: StoreApi<TState>;\n\tprivate readonly createInitialState: () => TState;\n\n\tprotected constructor(createInitialState: () => TState) {\n\t\tthis.createInitialState = createInitialState;\n\t\tthis.api = createStore<TState>()(() => this.createInitialState());\n\t}\n\n\tpublic getApi(): StoreApi<TState> {\n\t\treturn this.api;\n\t}\n\n\tpublic getState(): TState {\n\t\treturn this.api.getState();\n\t}\n\n\tpublic setState(\n\t\tpartial: TState | Partial<TState> | ((state: TState) => TState | Partial<TState>),\n\t\treplace?: boolean,\n\t): void {\n\t\tconst resolved = typeof partial === \"function\" ? partial(this.api.getState()) : partial;\n\n\t\tif (replace) {\n\t\t\tthis.api.setState(resolved as TState, true);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.api.setState(resolved);\n\t}\n\n\tpublic subscribe(listener: (state: TState, prevState: TState) => void) {\n\t\treturn this.api.subscribe(listener);\n\t}\n\n\t/**\n\t * Back to what the store was built with.\n\t *\n\t * Public, and it was not: while this was `protected` only a subclass could\n\t * reset, so the class style had a capability the functional one could not\n\t * reach — the asymmetry `skills/parity/SKILL.md` forbids. A shared store needs\n\t * explicit reset points (see the ladder in `core/README.md`), and the\n\t * application that owns them is outside the class either way.\n\t */\n\tpublic reset(): void {\n\t\tthis.api.setState(this.createInitialState(), true);\n\t}\n}\n","import { ALankaSharedStore } from \"../../_abstractions/lanka-shared-store/ALankaSharedStore\";\n\n/**\n * A shared store, without writing a class whose body is one function.\n *\n * A shared store is the third rung of the ladder in `core/README.md`: reach for\n * it only when several ViewModels must CO-EDIT one state. Most stores have no\n * behaviour of their own — the state and how to build it fresh is the whole\n * declaration — and this is the shape for those.\n *\n * One implementation: what comes back is an `ALankaSharedStore`, so a reset, a\n * subscription and the zustand api behave identically either way.\n */\nexport const createLankaSharedStore = <TState extends object>(\n\tcreateInitialState: () => TState,\n): ALankaSharedStore<TState> => {\n\tclass FunctionalSharedStore extends ALankaSharedStore<TState> {\n\t\tpublic constructor() {\n\t\t\tsuper(createInitialState);\n\t\t}\n\t}\n\n\treturn new FunctionalSharedStore();\n};\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lanka",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "type": "module",
5
5
  "description": "core: Ten subsystems, two peer dependencies, five extension points.",
6
6
  "license": "MIT",
@@ -81,7 +81,7 @@
81
81
  "@standard-schema/spec": "^1.0.0"
82
82
  },
83
83
  "devDependencies": {
84
- "@lankajs/tool-testing": "^1.0.0"
84
+ "@lankajs/tool-testing": "^1.0.1"
85
85
  },
86
86
  "peerDependencies": {
87
87
  "react": "^19.2.0",
@@ -5,7 +5,7 @@ license: MIT
5
5
  metadata:
6
6
  author: lankajs
7
7
  package: lanka
8
- version: "1.0.0"
8
+ version: "1.0.1"
9
9
  ---
10
10
 
11
11
  # lanka — core
@@ -1,6 +1,6 @@
1
1
  <!-- Generated from core/GUIDE.md by scripts/skills.mjs. Edit the guide. -->
2
2
 
3
- > **`lanka@1.0.0`** — this document describes that version.
3
+ > **`lanka@1.0.1`** — this document describes that version.
4
4
  >
5
5
  > Install: `npm install lanka react zustand` (the peers are not optional; only npm adds a missing one for you).
6
6
  >
@@ -5,7 +5,7 @@ license: MIT
5
5
  metadata:
6
6
  author: lankajs
7
7
  package: lanka
8
- version: "1.0.0"
8
+ version: "1.0.1"
9
9
  ---
10
10
 
11
11
  # lanka — which package, and what it costs
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/scenario/event-bus/_facades/lanka-event-bus/lankaEventBus.ts","../src/scenario/_registries/lanka-scenario-vm-registry/LankaScenarioVMRegistry.ts","../src/scenario/_registries/lanka-scenarios-registry/LankaScenariosRegistry.ts","../src/scenario/_abstractions/lanka-scenario/ALankaScenario.ts","../../tools/testing/_fixtures/.lanka_di/Scenarios.ts"],"sourcesContent":["import { requireActiveRuntime } from \"../../../../_internal/active-runtime/activeRuntime\";\nimport type { ILankaEventLog } from \"../../../_interfaces/ILankaEventLog\";\nimport type { ILankaEventMetadata } from \"../../../_interfaces/ILankaEventMetadata\";\nimport type { TLankaEventBusMiddleware } from \"../../../_types/TLankaEventBusMiddleware\";\nimport type { LankaEventBusInstance } from \"../../lanka-event-bus-instance/LankaEventBusInstance\";\nimport type { TLankaReplayRequest } from \"../../lanka-event-bus-instance/LankaEventBusInstance\";\n\n/**\n * Ambient bus: the active instance's, reachable without holding it.\n *\n * Every member is one line of delegation and that is all this does. It exists\n * for callers that cannot hold an instance — a user-extended `ALankaScenario`,\n * the scenario bootstrap.\n *\n * An object rather than a class with a default instance, and the difference is\n * not cosmetic: this owns no state, so a second one would delegate to the same\n * runtime and be the same object under another name. Where an ambient DOES own\n * state — storage — the class is real and a second instance means something.\n *\n * Isolation belongs to the instance holder: `lanka.eventBus.dispatch(…)`. This\n * cannot offer it — by definition it serves the ONE active instance, so two\n * instances in one process share nothing through it.\n */\nconst bus = (): LankaEventBusInstance => requireActiveRuntime().eventBus;\n\nexport const lankaEventBus = Object.freeze({\n\tenableLogs: (): void => {\n\t\tbus().enableLogs();\n\t},\n\n\tdisableLogs: (): void => {\n\t\tbus().disableLogs();\n\t},\n\n\tregisterEvent: (eventType: string, metadata: ILankaEventMetadata): void => {\n\t\tbus().registerEvent(eventType, metadata);\n\t},\n\n\tgetRegisteredEvents: () => bus().getRegisteredEvents(),\n\n\tgetEventInfo: (eventType: string): ILankaEventMetadata | null => bus().getEventInfo(eventType),\n\n\tgetSubscriptions: (eventType: string): number => bus().getSubscriptions(eventType),\n\n\tsubscribe: <T>(\n\t\teventType: string,\n\t\tcallback: (data: T) => void,\n\t\toptions?: { priority?: number; replay?: TLankaReplayRequest; usedBy?: string },\n\t): (() => void) => bus().subscribe(eventType, callback, options),\n\n\tunsubscribe: <T>(eventType: string, callback: (data: T) => void): void => {\n\t\tbus().unsubscribe(eventType, callback);\n\t},\n\n\tdispatch: <T>(eventType: string, data?: T, usedBy?: string): void => {\n\t\tbus().dispatch(eventType, data, usedBy);\n\t},\n\n\taddMiddleware: <T>(middleware: TLankaEventBusMiddleware<T>): void => {\n\t\tbus().addMiddleware(middleware);\n\t},\n\n\tremoveMiddleware: <T>(middleware: TLankaEventBusMiddleware<T>): void => {\n\t\tbus().removeMiddleware(middleware);\n\t},\n\n\tgetEventLogs: (eventType?: string, limit = 100): ILankaEventLog[] =>\n\t\tbus().getEventLogs(eventType, limit),\n\n\tclearEvent: (eventType: string): void => {\n\t\tbus().clearEvent(eventType);\n\t},\n\n\tclearAllEvents: (): void => {\n\t\tbus().clearAllEvents();\n\t},\n\n\treset: (): void => {\n\t\tbus().reset();\n\t},\n});\n","import { requireActiveRuntime } from \"../../../_internal/active-runtime/activeRuntime\";\nimport { ILankaScenarioVM } from \"../../_interfaces/ILankaScenarioVM\";\n\n/**\n * The registry of ViewModels that use scenarios.\n *\n * They arrive by themselves: the factory registers a ViewModel when it declares\n * scenario handlers.\n */\nexport class LankaScenarioVMRegistry {\n\tprivate registeredViewModels: Set<ILankaScenarioVM> = new Set();\n\n\t/**\n\t * Public: the registry belongs to a framework instance rather than to the\n\t * module.\n\t */\n\tpublic constructor() {}\n\n\t/**\n\t * The active instance's registry, for callers that cannot hold one — the\n\t * static `LankaScenarioBootstrap`. Instance holders read `lanka.viewModels`.\n\t */\n\tpublic static getInstance(): LankaScenarioVMRegistry {\n\t\treturn requireActiveRuntime().viewModels;\n\t}\n\n\t/** Whether this ViewModel is already registered. */\n\tpublic isRegistered(viewModel: ILankaScenarioVM): boolean {\n\t\treturn this.registeredViewModels.has(viewModel);\n\t}\n\n\t/**\n\t * Registers a ViewModel.\n\t *\n\t * @returns `false` when it was already registered\n\t */\n\tpublic register(viewModel: ILankaScenarioVM): boolean {\n\t\tif (this.registeredViewModels.has(viewModel)) {\n\t\t\treturn false;\n\t\t}\n\t\tthis.registeredViewModels.add(viewModel);\n\t\treturn true;\n\t}\n\n\t/** Removes a ViewModel from the registry. */\n\tpublic unregister(viewModel: ILankaScenarioVM): void {\n\t\tthis.registeredViewModels.delete(viewModel);\n\t}\n\n\t/** Every registered ViewModel. */\n\tpublic getAllViewModels(): ILankaScenarioVM[] {\n\t\treturn Array.from(this.registeredViewModels);\n\t}\n\n\t/**\n\t * Clears every registered ViewModel. Required by tests.\n\t */\n\tpublic clear(): void {\n\t\tthis.registeredViewModels.clear();\n\t}\n\n\t/**\n\t * Unsubscribes every registered ViewModel from its scenarios and clears the\n\t * registry.\n\t *\n\t * Without it tests are not isolated: a subscription leaks from test to test.\n\t */\n\tpublic resetAll(): void {\n\t\tthis.registeredViewModels.forEach((vm) => {\n\t\t\ttry {\n\t\t\t\tvm.resetScenario();\n\t\t\t} catch {\n\t\t\t\t// One failing to reset is no reason to fail the rest.\n\t\t\t}\n\t\t});\n\t\tthis.clear();\n\t}\n}\n","import { requireActiveRuntime } from \"../../../_internal/active-runtime/activeRuntime\";\nimport { ILankaScenario } from \"../../_interfaces/ILankaScenario\";\nimport { ALankaScenario } from \"../../_abstractions/lanka-scenario/ALankaScenario\";\nimport { ILankaScenarioVM } from \"../../_interfaces/ILankaScenarioVM\";\nimport { LankaScenarioVMRegistry } from \"../lanka-scenario-vm-registry/LankaScenarioVMRegistry\";\nimport type { ILankaScenarioMetadata } from \"../../_interfaces/ILankaScenarioMetadata\";\n\n/**\n * The scenario registry: both those that registered themselves and those\n * registered by hand.\n *\n * `ALankaScenario` subclasses arrive here automatically unless they opted out.\n */\nexport class LankaScenariosRegistry {\n\tprivate registeredScenarios: Map<string, ILankaScenario<unknown>> = new Map();\n\tprivate scenarioMetadata: Map<string, ILankaScenarioMetadata> = new Map();\n\n\t/**\n\t * Public: the registry belongs to a framework instance rather than to the\n\t * module.\n\t */\n\tpublic constructor() {}\n\n\t/**\n\t * The active instance's registry, for callers that cannot hold one:\n\t * `ALankaScenario` (a base class the consumer extends) and the static\n\t * `LankaScenarioBootstrap`. Instance holders read `lanka.scenarios`.\n\t */\n\tpublic static getInstance(): LankaScenariosRegistry {\n\t\treturn requireActiveRuntime().scenarios;\n\t}\n\n\t/**\n\t * Registers a scenario by hand.\n\t *\n\t * @param scenario What to register\n\t * @returns `false` when it was already registered\n\t */\n\tpublic register(scenario: ILankaScenario<unknown>): boolean {\n\t\tif (this.registeredScenarios.has(scenario.name)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tthis.registeredScenarios.set(scenario.name, scenario);\n\t\tthis.scenarioMetadata.set(scenario.name, {\n\t\t\tscenario,\n\t\t\tname: scenario.name,\n\t\t\teventType: scenario.eventType,\n\t\t\tdataTypeName: scenario.dataTypeName,\n\t\t\tisRegistered: true,\n\t\t});\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Unregister a scenario\n\t * @param scenarioName Name of the scenario to unregister\n\t * @returns true if unregistered successfully, false if not found\n\t */\n\tpublic unregister(scenarioName: string): boolean {\n\t\tif (!this.registeredScenarios.has(scenarioName)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst metadata = this.scenarioMetadata.get(scenarioName);\n\t\tif (metadata) {\n\t\t\tmetadata.isRegistered = false;\n\t\t}\n\n\t\tthis.registeredScenarios.delete(scenarioName);\n\t\treturn true;\n\t}\n\n\t/**\n\t * Get metadata for a specific scenario\n\t * @param scenarioName Name of the scenario\n\t * @returns Scenario metadata or undefined if not found\n\t */\n\tpublic getMetadata(scenarioName: string): ILankaScenarioMetadata | undefined {\n\t\treturn this.scenarioMetadata.get(scenarioName);\n\t}\n\n\t/** Every registered scenario. */\n\tpublic getAllScenarios(): ILankaScenario<unknown>[] {\n\t\treturn Array.from(this.registeredScenarios.values());\n\t}\n\n\t/** Metadata of every scenario. */\n\tpublic getAllMetadata(): ILankaScenarioMetadata[] {\n\t\treturn Array.from(this.scenarioMetadata.values());\n\t}\n\n\t/** Whether a scenario with this name is registered. */\n\tpublic isRegistered(scenarioName: string): boolean {\n\t\treturn this.registeredScenarios.has(scenarioName);\n\t}\n\n\t/**\n\t * Collects every scenario that registered itself at construction.\n\t */\n\tpublic collectAutoRegisteredScenarios(): void {\n\t\t// Take those that registered themselves at construction.\n\t\tconst autoRegistered = ALankaScenario.getAutoRegisteredScenarios();\n\t\tautoRegistered.forEach((scenario) => {\n\t\t\tif (!this.registeredScenarios.has(scenario.name)) {\n\t\t\t\tthis.register(scenario);\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * A scenario by name.\n\t *\n\t * @returns `undefined` when there is none\n\t */\n\tpublic getScenarioByName(scenarioName: string): ILankaScenario<unknown> | undefined {\n\t\treturn this.registeredScenarios.get(scenarioName);\n\t}\n\n\t/** Every registered ViewModel. */\n\tpublic getAllViewModels(): ILankaScenarioVM[] {\n\t\treturn LankaScenarioVMRegistry.getInstance().getAllViewModels();\n\t}\n\n\t/**\n\t * Clears every registered scenario. Required by tests.\n\t */\n\tpublic clear(): void {\n\t\tthis.registeredScenarios.clear();\n\t\tthis.scenarioMetadata.clear();\n\t}\n}\n","import type { TLankaReplayRequest } from \"../../event-bus/lanka-event-bus-instance/LankaEventBusInstance\";\nimport { ILankaScenario } from \"../../_interfaces/ILankaScenario\";\nimport { LankaScenariosRegistry } from \"../../_registries/lanka-scenarios-registry/LankaScenariosRegistry\";\nimport { lankaLogger } from \"../../../logger/lanka-logger/LankaLogger\";\nimport { lankaEventBus } from \"../../event-bus/_facades/lanka-event-bus/lankaEventBus\";\n\n/**\n * The base of a scenario — a named unit of coordination over the event bus.\n *\n * A subclass declares `name`, `eventType` and `dataTypeName`, calls `trigger()`\n * when the event happens, and ViewModels subscribe to it and unsubscribe.\n *\n * Scenarios register THEMSELVES unless the subclass sets the static\n * `skipAutoRegistration`.\n *\n * ```ts\n * export class SessionUpdated extends ALankaScenario<TSession> {\n * readonly name = \"SessionUpdated\";\n * readonly eventType = \"session.updated\";\n * readonly dataTypeName = \"TSession\";\n * }\n * ```\n */\nexport abstract class ALankaScenario<TData = void> implements ILankaScenario<TData> {\n\tabstract readonly name: string;\n\tabstract readonly eventType: string;\n\tabstract readonly dataTypeName: string;\n\n\t/** A subclass sets this to opt out of self-registration. */\n\tstatic skipAutoRegistration?: boolean;\n\n\t/**\n\t * The self-registration pool.\n\t *\n\t * Class-level deliberately: a registry of DEFINITIONS, not runtime state. The\n\t * classes come from one barrel and both framework instances must see the same\n\t * list — splitting it would be divergence, not isolation.\n\t */\n\tprivate static autoRegisteredScenarios: Set<ALankaScenario<unknown>> = new Set();\n\n\t/** Registers the scenario itself unless the subclass opted out. */\n\tconstructor() {\n\t\t// The constructor comes from the actual class, that is the subclass.\n\t\tconst constructor = this.constructor as typeof ALankaScenario;\n\n\t\t// Register unless opted out.\n\t\tif (!constructor.skipAutoRegistration) {\n\t\t\tALankaScenario.autoRegisteredScenarios.add(this);\n\t\t}\n\t}\n\n\t/**\n\t * Every scenario that registered itself.\n\t *\n\t * @internal\n\t */\n\tpublic static getAutoRegisteredScenarios(): ALankaScenario<unknown>[] {\n\t\treturn Array.from(ALankaScenario.autoRegisteredScenarios);\n\t}\n\n\t/**\n\t * Clears the auto-registration pool. Required by tests.\n\t * @internal\n\t */\n\tpublic static clearAutoRegisteredScenarios(): void {\n\t\tALankaScenario.autoRegisteredScenarios.clear();\n\t}\n\n\t/**\n\t * Registers the scenario by hand.\n\t *\n\t * @returns `false` when it was already registered\n\t */\n\tpublic register(): boolean {\n\t\treturn LankaScenariosRegistry.getInstance().register(this);\n\t}\n\n\t/**\n\t * Removes the scenario from the registry.\n\t *\n\t * @returns `false` when it was not there\n\t */\n\tpublic unregister(): boolean {\n\t\treturn LankaScenariosRegistry.getInstance().unregister(this.name);\n\t}\n\n\ttrigger(data?: TData): void {\n\t\tlankaLogger.printScenarioLog(\"TRIGGER Scenario\", this.name, data);\n\t\tlankaEventBus.dispatch(this.eventType, data, this.name);\n\t}\n\n\t/**\n\t * Subscribes a handler and returns an unsubscribe function.\n\t *\n\t * Without the return, unsubscribing is possible only by callback identity, and\n\t * every ViewModel factory has to keep a map of references for it.\n\t */\n\tsubscribe(\n\t\tcallback: (data?: TData) => void,\n\t\toptions?: {\n\t\t\tpriority?: number;\n\t\t\treplay?: TLankaReplayRequest;\n\t\t\tusedBy?: string;\n\t\t},\n\t): () => void {\n\t\tlankaLogger.printScenarioLog(\"SUBSCRIBE Scenario\", this.name, this.dataTypeName);\n\t\treturn lankaEventBus.subscribe(this.eventType, callback, {\n\t\t\t...options,\n\t\t\tusedBy: options?.usedBy ?? this.name,\n\t\t});\n\t}\n}\n","/**\n * The scenarios this app publishes to `lanka`.\n *\n * Add one export line per class; the framework derives the locator from these\n * exports, so there is nothing else to register.\n *\n * @example export { SessionScenario } from \"../src/...\";\n */\nexport {};\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../tools/testing/_fixtures/.lanka_di/Gateways.ts","../src/locator/gateway/lanka-gateway-locator/LankaGatewayLocator.ts","../src/locator/scenario/lanka-scenario-locator/LankaScenarioLocator.ts","../src/locator/_factories/create-lanka-scope/createLankaScope.ts"],"sourcesContent":["/**\n * The gateways this app publishes to `lanka`.\n *\n * Add one export line per class; the framework derives the locator from these\n * exports, so there is nothing else to register.\n *\n * @example export { UserGateway } from \"../src/...\";\n */\nexport {};\n","import * as GatewaysModule from \"@lanka_di/Gateways\";\nimport type { ALankaGateway } from \"../../../gateway/_abstractions/lanka-gateway/ALankaGateway\";\nimport { ALankaLocator } from \"../../_abstractions/lanka-locator/ALankaLocator\";\nimport { findExportedClass } from \"../../_internal/findExportedClass\";\n\n/**\n * Resolves a gateway by property name (camelCase) or class name (PascalCase),\n * constructing it lazily and caching the instance.\n *\n * Adding a gateway takes one export line in `@lanka_di/Gateways`: types are\n * inferred and nothing is registered.\n */\nexport class LankaGatewayLocator extends ALankaLocator<ALankaGateway<unknown>> {\n\tconstructor() {\n\t\tsuper({\n\t\t\tfindClassByName: (gatewayName: string) =>\n\t\t\t\tfindExportedClass<ALankaGateway<unknown>>(GatewaysModule, gatewayName),\n\t\t\tnotFoundError: (gatewayName, propertyName) =>\n\t\t\t\t`Gateway \"${gatewayName}\" (accessed as \"${propertyName}\") not found. ` +\n\t\t\t\t`Make sure the gateway class extends ALankaGateway and is exported from lankaGateways.ts.`,\n\t\t});\n\t}\n}\n","import { LankaScenariosRegistry } from \"../../../scenario/_registries/lanka-scenarios-registry/LankaScenariosRegistry\";\nimport { ILankaScenario } from \"../../../scenario/_interfaces/ILankaScenario\";\nimport { ALankaScenario } from \"../../../scenario/_abstractions/lanka-scenario/ALankaScenario\";\nimport { ALankaLocator } from \"../../_abstractions/lanka-locator/ALankaLocator\";\n/**\n * Classes come from the consumer's barrel.\n *\n * Adding one is ONE export line: types are inferred, autocomplete works, and no\n * list has to be maintained.\n */\nimport * as ScenariosModule from \"@lanka_di/Scenarios\";\n\n/**\n * Resolves scenarios by property name (camelCase) or scenario name\n * (PascalCase).\n *\n * Looks in the registry, then in the self-registration pool, and failing both\n * constructs the scenario from the consumer's barrel on first use.\n */\nexport class LankaScenarioLocator extends ALankaLocator<ILankaScenario<unknown>> {\n\t/**\n\t * The registry is read LAZILY rather than in a field initialiser.\n\t *\n\t * The locator is constructed INSIDE `createLanka`, before the instance becomes\n\t * active. A field initialiser would ask for the active instance at that moment\n\t * and fail with \"no instance yet\" while the instance being created is on the\n\t * stack. Deferred reading resolves it: by the first scenario resolution an\n\t * active instance exists.\n\t */\n\tprivate get registry(): LankaScenariosRegistry {\n\t\treturn LankaScenariosRegistry.getInstance();\n\t}\n\n\tconstructor() {\n\t\tsuper({\n\t\t\tfindClassByName: (scenarioName: string) => {\n\t\t\t\t// By export key first: an instance name does not always survive minification.\n\t\t\t\tif (scenarioName in ScenariosModule) {\n\t\t\t\t\t// `as unknown` before the guards, exactly as in the singleton locator.\n\t\t\t\t\t// An EMPTY barrel — what the scaffolder writes, and what a new project\n\t\t\t\t\t// has until its first scenario — makes the module's keys `never`, so\n\t\t\t\t\t// an indexed access is `never` and reading `.prototype` off it does\n\t\t\t\t\t// not compile.\n\t\t\t\t\tconst ScenarioClass = ScenariosModule[\n\t\t\t\t\t\tscenarioName as keyof typeof ScenariosModule\n\t\t\t\t\t] as unknown;\n\t\t\t\t\tif (\n\t\t\t\t\t\ttypeof ScenarioClass === \"function\" &&\n\t\t\t\t\t\t\"prototype\" in ScenarioClass &&\n\t\t\t\t\t\tScenarioClass.prototype\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn ScenarioClass as new () => ILankaScenario<unknown>;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Fallback: look up by instance name.\n\t\t\t\tfor (const value of Object.values(ScenariosModule)) {\n\t\t\t\t\tif (typeof value === \"function\" && value.prototype) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst instance = new (value as new () => ALankaScenario<unknown>)();\n\t\t\t\t\t\t\tif (instance.name === scenarioName) {\n\t\t\t\t\t\t\t\treturn value as new () => ILankaScenario<unknown>;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// Not constructible — skip.\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn undefined;\n\t\t\t},\n\t\t\tgetInstanceByName: (scenarioName: string) => {\n\t\t\t\t// The registry first.\n\t\t\t\tconst registered = this.registry.getScenarioByName(scenarioName);\n\t\t\t\tif (registered) {\n\t\t\t\t\treturn registered;\n\t\t\t\t}\n\n\t\t\t\t// Then those that registered themselves.\n\t\t\t\tconst autoRegistered = ALankaScenario.getAutoRegisteredScenarios();\n\t\t\t\tconst scenario = autoRegistered.find((s) => s.name === scenarioName);\n\n\t\t\t\tif (scenario) {\n\t\t\t\t\tif (!this.registry.isRegistered(scenarioName)) {\n\t\t\t\t\t\tthis.registry.register(scenario);\n\t\t\t\t\t}\n\t\t\t\t\treturn scenario;\n\t\t\t\t}\n\n\t\t\t\t// Then finding the class by name and constructing it.\n\t\t\t\treturn undefined;\n\t\t\t},\n\t\t\tcreateInstance: (ScenarioClass) => {\n\t\t\t\tconst instance = new ScenarioClass();\n\t\t\t\tconst scenarioName = instance.name;\n\t\t\t\tif (!this.registry.isRegistered(scenarioName)) {\n\t\t\t\t\tthis.registry.register(instance);\n\t\t\t\t}\n\t\t\t\treturn instance;\n\t\t\t},\n\t\t\tnotFoundError: (scenarioName, propertyName) =>\n\t\t\t\t`Scenario \"${scenarioName}\" (accessed as \"${propertyName}\") not found. ` +\n\t\t\t\t`Make sure the scenario class extends ALankaScenario and has name=\"${scenarioName}\".`,\n\t\t});\n\t}\n}\n","import { caseConvert } from \"../../../_internal/case-convert/caseConvert\";\nimport { lankaLogger } from \"../../../logger/lanka-logger/LankaLogger\";\nimport type { LankaSingletonLocator } from \"../../singleton/lanka-singleton-locator/LankaSingletonLocator\";\n\n/**\n * A service lifetime other than \"as long as the application lives\".\n *\n * Everything resolved through `lankaSingletons.*` is a singleton for the life of\n * the app. Per-route, per-session and per-modal lifetimes otherwise rest on\n * discipline: every ViewModel calling `resetScenario()` and writing its own\n * `onReset`, in any of which it can be forgotten.\n *\n * A scope provides the same by construction: an object created in it goes away\n * with it, and nobody has to remember.\n *\n * ## What a scope does NOT do\n *\n * It does not shadow root objects and does not take them on close. It takes only\n * ITS OWN — the ones it created. A scope taking others' would be more dangerous\n * than no scopes at all: closing a screen would break the app.\n */\nexport interface ILankaScope {\n\t/** Resolves a service in this scope, creating it on first use. */\n\tresolve<TInstance>(propertyName: string): TInstance;\n\t/** Disposes everything this scope created and closes it. Idempotent. */\n\tdispose(): void;\n\t/** Whether the scope is closed. */\n\tisDisposed(): boolean;\n}\n\n/** A service may have a `dispose` — or may not. */\ninterface IMaybeDisposable {\n\tdispose?: () => void;\n}\n\nexport function createLankaScope(singletons: LankaSingletonLocator): ILankaScope {\n\tconst instances = new Map<string, unknown>();\n\tlet disposed = false;\n\n\treturn {\n\t\tresolve<TInstance>(propertyName: string): TInstance {\n\t\t\tif (disposed) {\n\t\t\t\t// Resolving from a closed scope is almost always a reference leaked from\n\t\t\t\t// an already-unmounted screen. Silently handing out an object would\n\t\t\t\t// extend the life of what was closed, invisibly.\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`The scope is closed: \"${propertyName}\" can no longer be resolved in it. ` +\n\t\t\t\t\t\t`This is usually a scope reference that outlived the screen that created it.`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst className = caseConvert(propertyName, \"pascalCase\");\n\t\t\tif (instances.has(className)) return instances.get(className) as TInstance;\n\n\t\t\t// The class comes from the root locator while the OBJECT is created here:\n\t\t\t// a scope is a different lifetime, not a different set of services.\n\t\t\tconst instance = singletons.createScopedInstance(className, propertyName);\n\t\t\tinstances.set(className, instance);\n\t\t\treturn instance as TInstance;\n\t\t},\n\n\t\tdispose(): void {\n\t\t\tif (disposed) return;\n\t\t\tdisposed = true;\n\n\t\t\tfor (const [name, instance] of instances) {\n\t\t\t\tconst disposable = instance as IMaybeDisposable;\n\t\t\t\tif (typeof disposable.dispose !== \"function\") continue;\n\t\t\t\ttry {\n\t\t\t\t\tdisposable.dispose();\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// One failure must not leave the rest alive: that is exactly what a\n\t\t\t\t\t// scope exists to prevent.\n\t\t\t\t\tlankaLogger.printBootstrapLog(\n\t\t\t\t\t\t`Failed to dispose \"${name}\" in the scope`,\n\t\t\t\t\t\terror instanceof Error ? error.message : String(error),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tinstances.clear();\n\t\t},\n\n\t\tisDisposed: () => disposed,\n\t};\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/_internal/case-convert/caseConvert.ts","../src/locator/_abstractions/lanka-locator/ALankaLocator.ts","../src/locator/_internal/findExportedClass.ts","../../tools/testing/_fixtures/.lanka_di/Singletons.ts","../src/locator/singleton/lanka-singleton-locator/LankaSingletonLocator.ts","../../tools/testing/_fixtures/.lanka_di/SharedStores.ts","../src/locator/shared-store/lanka-shared-store-locator/LankaSharedStoreLocator.ts"],"sourcesContent":["export function caseConvert(\n\tstr: string,\n\ttoCase: \"camelCase\" | \"kebabCase\" | \"snakeCase\" | \"pascalCase\" | \"titleCase\",\n): string {\n\tif (!str || typeof str !== \"string\") return str;\n\n\tconst words = str\n\t\t.replace(/([A-Z])/g, \" $1\")\n\t\t.trim()\n\t\t.split(/\\s+|_|-/)\n\t\t.filter((word) => word);\n\n\tswitch (toCase) {\n\t\tcase \"camelCase\":\n\t\t\treturn words\n\t\t\t\t.map((word, index) =>\n\t\t\t\t\tindex === 0\n\t\t\t\t\t\t? word.toLowerCase()\n\t\t\t\t\t\t: word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(),\n\t\t\t\t)\n\t\t\t\t.join(\"\");\n\t\tcase \"kebabCase\":\n\t\t\treturn words.map((word) => word.toLowerCase()).join(\"-\");\n\t\tcase \"snakeCase\":\n\t\t\treturn words.map((word) => word.toLowerCase()).join(\"_\");\n\t\tcase \"pascalCase\":\n\t\t\treturn words\n\t\t\t\t.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n\t\t\t\t.join(\"\");\n\t\tcase \"titleCase\":\n\t\t\treturn words\n\t\t\t\t.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n\t\t\t\t.join(\" \");\n\t\tdefault:\n\t\t\treturn str;\n\t}\n}\n","import type { ILankaLocator } from \"../../_interfaces/ILankaLocator\";\nimport { caseConvert } from \"../../../_internal/case-convert/caseConvert\";\n\n/**\n * Base locator configuration.\n */\nexport interface ILankaLocatorConfig<TInstance> {\n\t/** How to find a constructor by class name. */\n\tfindClassByName: (name: string) => (new () => TInstance) | undefined;\n\t/** How to create an object from a constructor. */\n\tcreateInstance?: (Class: new () => TInstance) => TInstance;\n\t/** Custom resolution by name, when the ordinary one is not enough. */\n\tgetInstanceByName?: (name: string) => TInstance | undefined;\n\t/** What to say when there is no such object. */\n\tnotFoundError?: (name: string, propertyName: string) => string;\n}\n\n/**\n * The locator base: resolves objects by property name (camelCase), translating\n * it into a class name (PascalCase).\n *\n * Handles what every locator shares — name translation, construction on first\n * use from the barrel's exports, and caching what was constructed.\n */\nexport abstract class ALankaLocator<TInstance> implements ILankaLocator<TInstance> {\n\tprotected readonly instanceCache: Map<string, TInstance> = new Map();\n\tprotected readonly registeredClasses: Map<string, new () => TInstance> = new Map();\n\tprotected readonly registeredInstances: Map<string, TInstance> = new Map();\n\tprotected readonly config: ILankaLocatorConfig<TInstance> & {\n\t\tcreateInstance: (Class: new () => TInstance) => TInstance;\n\t\tnotFoundError: (name: string, propertyName: string) => string;\n\t};\n\n\tprotected constructor(config: ILankaLocatorConfig<TInstance>) {\n\t\t// The defaults are applied AFTER the spread, so an explicit `undefined` —\n\t\t// which a caller forwarding its own optional config passes — falls back\n\t\t// instead of removing the only thing that can construct an instance.\n\t\tthis.config = {\n\t\t\t...config,\n\t\t\tcreateInstance: config.createInstance ?? ((Class) => new Class()),\n\t\t\tnotFoundError:\n\t\t\t\tconfig.notFoundError ??\n\t\t\t\t((name, propertyName) =>\n\t\t\t\t\t`Instance \"${name}\" (accessed as \"${propertyName}\") not found.`),\n\t\t};\n\t}\n\n\t/**\n\t * An object by class name.\n\t *\n\t * The cache first, then custom resolution when configured, and only then\n\t * construction.\n\t */\n\tprotected getInstanceByName(instanceName: string): TInstance | undefined {\n\t\tif (this.instanceCache.has(instanceName)) {\n\t\t\treturn this.instanceCache.get(instanceName);\n\t\t}\n\n\t\t// What was handed to us already built. Ahead of the barrel, and ahead of\n\t\t// custom resolution: a test's double must win over what the barrel exports.\n\t\tif (this.registeredInstances.has(instanceName)) {\n\t\t\treturn this.registeredInstances.get(instanceName);\n\t\t}\n\n\t\t// Custom resolution when configured.\n\t\tif (this.config.getInstanceByName) {\n\t\t\tconst instance = this.config.getInstanceByName(instanceName);\n\t\t\tif (instance) {\n\t\t\t\tthis.instanceCache.set(instanceName, instance);\n\t\t\t\treturn instance;\n\t\t\t}\n\t\t}\n\n\t\t// Otherwise find the class and construct.\n\t\tconst Class = this.config.findClassByName(instanceName);\n\t\tif (Class) {\n\t\t\tconst instance = this.config.createInstance(Class);\n\t\t\tthis.instanceCache.set(instanceName, instance);\n\t\t\treturn instance;\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * An object by property name (camelCase).\n\t *\n\t * Throws when there is none: a silent `undefined` would surface layers later.\n\t */\n\tpublic get(propertyName: string): TInstance {\n\t\tconst instanceName = caseConvert(propertyName, \"pascalCase\");\n\t\tconst instance = this.getInstanceByName(instanceName);\n\n\t\tif (!instance) {\n\t\t\tthrow new Error(this.config.notFoundError(instanceName, propertyName));\n\t\t}\n\n\t\treturn instance;\n\t}\n\n\t/**\n\t * Clears the instance cache. Required by tests.\n\t */\n\tpublic clearCache(): void {\n\t\tthis.instanceCache.clear();\n\t}\n\n\t// ── Registration by hand ─────────────────────────────────────────────────\n\t//\n\t// Every locator needs it, for the same two reasons: a test supplies a double,\n\t// and an application supplies an object it built itself. It lives here rather\n\t// than in each locator because three copies of four one-line methods are three\n\t// places for the cache invalidation to be forgotten.\n\n\t/**\n\t * Registers a class by hand, ahead of the consumer's barrel.\n\t *\n\t * The cache entry is dropped: what it holds was built from the previous class.\n\t */\n\tpublic register(className: string, Class: new () => TInstance): void {\n\t\tthis.registeredClasses.set(className, Class);\n\t\tthis.instanceCache.delete(className);\n\t}\n\n\t/**\n\t * Registers an already-built object by hand.\n\t *\n\t * It goes straight into the cache: there is nothing left to construct, and a\n\t * later lookup must not build a rival.\n\t */\n\tpublic registerInstance(className: string, instance: TInstance): void {\n\t\tthis.registeredInstances.set(className, instance);\n\t\tthis.instanceCache.set(className, instance);\n\t}\n\n\t/** Removes a class or object registered by hand, and what was built from it. */\n\tpublic unregister(className: string): void {\n\t\tthis.registeredClasses.delete(className);\n\t\tthis.registeredInstances.delete(className);\n\t\tthis.instanceCache.delete(className);\n\t}\n\n\t/** Whether this name resolves to anything the locator already holds. */\n\tpublic isRegistered(className: string): boolean {\n\t\treturn (\n\t\t\tthis.registeredClasses.has(className) ||\n\t\t\tthis.registeredInstances.has(className) ||\n\t\t\tthis.instanceCache.has(className)\n\t\t);\n\t}\n}\n","/**\n * Finds a class in a module's ES namespace by name.\n *\n * An ES namespace is an ordinary object and `module[name]` is enough. Walking\n * `Reflect.ownKeys`, reading property descriptors and wrapping field access in\n * `try/catch` guards against what does not happen.\n *\n * ## Why a fallback pass over `Class.name` is worse than useless\n *\n * It is written for the case where the export name was lost to minification. But\n * `Class.name`.\n *\n * minification loses `Class.name` too — so the fallback looks for something a\n * built bundle no longer has, creating an impression of protection where there\n * is none.\n *\n * Resolution still works when the export name differs from the class name, which\n * `locator.contract.test.ts` pins: the lookup is by EXPORT KEY, and that is what\n * the consumer writes in the barrel.\n */\nexport function findExportedClass<TInstance>(\n\tmodule: object,\n\texportName: string,\n): (new () => TInstance) | undefined {\n\t// `in` first, then indexing. An ES namespace answers `undefined` for a missing\n\t// key, but a mocked module does not: vitest returns a proxy that THROWS on an\n\t// unknown key.\n\tif (!(exportName in module)) return undefined;\n\n\tconst candidate = (module as Record<string, unknown>)[exportName];\n\n\t// `typeof === \"function\"` would also admit a plain function: it has a\n\t// `prototype` too. They cannot be told apart before calling, and that is a\n\t// deliberate boundary — the locator trusts the barrel, and `@lankajs/tool-di`\n\t// verifies the barrel.\n\treturn typeof candidate === \"function\" && candidate.prototype\n\t\t? (candidate as new () => TInstance)\n\t\t: undefined;\n}\n","/**\n * The singletons this app publishes to `lanka`.\n *\n * Add one export line per class; the framework derives the locator from these\n * exports, so there is nothing else to register.\n *\n * @example export { AnalyticsService } from \"../src/...\";\n */\nexport {};\n","import { ALankaLocator } from \"../../_abstractions/lanka-locator/ALankaLocator\";\nimport { findExportedClass } from \"../../_internal/findExportedClass\";\n/**\n * Classes come from the consumer's barrel.\n *\n * Adding one is ONE export line: types are inferred, autocomplete works, and no\n * list has to be maintained. A list maintained by hand is a list that eventually\n * falls behind the code.\n */\nimport * as SingletonsModule from \"@lanka_di/Singletons\";\n\n/**\n * LankaSingletonLocator configuration.\n */\nexport interface ILankaSingletonLocatorConfig {\n\t/** The module holding singleton classes — the consumer's barrel. */\n\tsingletonIndexModule?: Record<string, unknown>;\n}\n\n/**\n * Resolves singletons by property name (camelCase) or class name (PascalCase),\n * constructing them on first use and caching them.\n *\n * A class arrives either from the consumer's barrel or registered by hand — the\n * latter for tests and for objects that arrive already built.\n */\nexport class LankaSingletonLocator extends ALankaLocator<unknown> {\n\tprivate readonly singletonIndexModule?: Record<string, unknown>;\n\n\tconstructor(config?: ILankaSingletonLocatorConfig) {\n\t\tsuper({\n\t\t\tfindClassByName: (className: string) => {\n\t\t\t\t// Order: hand-registered first, then the application's barrel, then an\n\t\t\t\t// extra module if one was given.\n\t\t\t\t//\n\t\t\t\t// Each source is checked ONCE, by export key. A fallback pass over\n\t\t\t\t// `Class.name` looks for something a built bundle no longer has:\n\t\t\t\t// minification loses class names exactly as it loses export names.\n\t\t\t\tconst registered = this.registeredClasses.get(className);\n\t\t\t\tif (registered) return registered;\n\n\t\t\t\treturn (\n\t\t\t\t\tfindExportedClass<unknown>(SingletonsModule, className) ??\n\t\t\t\t\t(this.singletonIndexModule\n\t\t\t\t\t\t? findExportedClass<unknown>(this.singletonIndexModule, className)\n\t\t\t\t\t\t: undefined)\n\t\t\t\t);\n\t\t\t},\n\t\t\tcreateInstance: (Class) => {\n\t\t\t\treturn new Class();\n\t\t\t},\n\t\t\tnotFoundError: (className, propertyName) =>\n\t\t\t\t`Singleton \"${className}\" (accessed as \"${propertyName}\") not found. ` +\n\t\t\t\t`Make sure the class is exported from @lanka_di/Singletons.ts or registered via registerSingleton method.`,\n\t\t});\n\n\t\tthis.singletonIndexModule = config?.singletonIndexModule;\n\t}\n\n\t/**\n\t * Creates a NEW service object, bypassing the locator's cache.\n\t *\n\t * For scopes: they take the class from here and set the lifetime themselves.\n\t * The root cache is untouched — otherwise the first resolution inside a scope\n\t * would replace the application's root object.\n\t */\n\tpublic createScopedInstance(className: string, propertyName: string): unknown {\n\t\tconst Class = this.config.findClassByName(className);\n\t\tif (!Class) {\n\t\t\tthrow new Error(this.config.notFoundError(className, propertyName));\n\t\t}\n\t\treturn this.config.createInstance(Class);\n\t}\n}\n","/**\n * The shared stores this app publishes to `lanka`.\n *\n * Add one export line per class; the framework derives the locator from these\n * exports, so there is nothing else to register.\n *\n * @example export { UserSharedStore } from \"../src/...\";\n */\nexport {};\n","import { ALankaLocator } from \"../../_abstractions/lanka-locator/ALankaLocator\";\nimport { findExportedClass } from \"../../_internal/findExportedClass\";\nimport { ALankaSharedStore } from \"../../../viewmodel/_abstractions/lanka-shared-store/ALankaSharedStore\";\nimport * as SharedStoresModule from \"@lanka_di/SharedStores\";\n\ntype TSharedStoreState = object;\n\n/**\n * LankaSharedStoreLocator configuration.\n */\nexport interface ILankaSharedStoreLocatorConfig {\n\t/** The module holding shared store classes — the consumer's barrel. */\n\tsharedStoreIndexModule?: Record<string, unknown>;\n}\n\n/**\n * Resolves shared stores by property name (camelCase) or class name\n * (PascalCase), constructing them on first use and caching them.\n */\nexport class LankaSharedStoreLocator extends ALankaLocator<ALankaSharedStore<TSharedStoreState>> {\n\tprivate readonly sharedStoreIndexModule?: Record<string, unknown>;\n\n\tconstructor(config?: ILankaSharedStoreLocatorConfig) {\n\t\tsuper({\n\t\t\tfindClassByName: (className: string) => {\n\t\t\t\tconst registeredClass = this.registeredClasses.get(className);\n\t\t\t\tif (registeredClass) {\n\t\t\t\t\treturn registeredClass;\n\t\t\t\t}\n\n\t\t\t\treturn (\n\t\t\t\t\tfindExportedClass<ALankaSharedStore<TSharedStoreState>>(\n\t\t\t\t\t\tSharedStoresModule,\n\t\t\t\t\t\tclassName,\n\t\t\t\t\t) ??\n\t\t\t\t\t(this.sharedStoreIndexModule\n\t\t\t\t\t\t? findExportedClass<ALankaSharedStore<TSharedStoreState>>(\n\t\t\t\t\t\t\t\tthis.sharedStoreIndexModule,\n\t\t\t\t\t\t\t\tclassName,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t: undefined)\n\t\t\t\t);\n\t\t\t},\n\t\t\tcreateInstance: (Class) => {\n\t\t\t\treturn new Class();\n\t\t\t},\n\t\t\tnotFoundError: (className, propertyName) =>\n\t\t\t\t`SharedStore \"${className}\" (accessed as \"${propertyName}\") not found. ` +\n\t\t\t\t`Make sure the class extends ALankaSharedStore and is exported from @lanka_di/SharedStores.ts ` +\n\t\t\t\t`or registered via registerSharedStore method.`,\n\t\t});\n\n\t\tthis.sharedStoreIndexModule = config?.sharedStoreIndexModule;\n\t}\n}\n"],"mappings":"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","names":[]}