lanka 1.3.0 → 2.0.0

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 (63) hide show
  1. package/README.md +1 -1
  2. package/dist/ILankaReadableVM-BoPzHEPV.d.ts +72 -0
  3. package/dist/{LankaScenarioLocator-CAENLhDO.d.ts → LankaScenarioLocator-Dki2Es3O.d.ts} +2 -2
  4. package/dist/{LankaSharedStoreLocator-zS2kLu-S.d.ts → LankaSharedStoreLocator-jsz_gnUm.d.ts} +1 -1
  5. package/dist/_extend/index.d.ts +228 -5
  6. package/dist/_extend/index.js +137 -8
  7. package/dist/_extend/index.js.map +1 -1
  8. package/dist/_internal/index.d.ts +3 -3
  9. package/dist/_internal/index.js +9 -3
  10. package/dist/_internal/index.js.map +1 -1
  11. package/dist/{activeRuntime-BYd2D6Lx.d.ts → activeRuntime-BO-qY0yY.d.ts} +50 -3
  12. package/dist/bootstrap/index.d.ts +6 -6
  13. package/dist/bootstrap/index.js +7 -8
  14. package/dist/{chunk-D27MREPB.js → chunk-7DQUF2QR.js} +2 -2
  15. package/dist/{chunk-UJEC7H6K.js → chunk-BHQ2SQ7P.js} +2 -2
  16. package/dist/chunk-EYDMBI5T.js +550 -0
  17. package/dist/chunk-EYDMBI5T.js.map +1 -0
  18. package/dist/{chunk-C2HP7CRD.js → chunk-FII3PW2G.js} +2 -2
  19. package/dist/{chunk-DTO27QFR.js → chunk-H5TIUKRK.js} +2 -2
  20. package/dist/{chunk-NDCJBO47.js → chunk-O5EUTNR6.js} +2 -2
  21. package/dist/{chunk-RKYKK6MN.js → chunk-RUMUFHSL.js} +2 -2
  22. package/dist/{chunk-UBGXDTXC.js → chunk-SZVNPK24.js} +11 -13
  23. package/dist/chunk-SZVNPK24.js.map +1 -0
  24. package/dist/chunk-UDP6IXDS.js +17 -0
  25. package/dist/chunk-UDP6IXDS.js.map +1 -0
  26. package/dist/{chunk-5MAQVBI2.js → chunk-UMPSR4US.js} +3 -3
  27. package/dist/{chunk-BGVDPDX4.js → chunk-XGMXT4XZ.js} +20 -3
  28. package/dist/chunk-XGMXT4XZ.js.map +1 -0
  29. package/dist/config/index.js +3 -3
  30. package/dist/{createLanka-NrlvN-WQ.d.ts → createLanka-x4oSMs7P.d.ts} +2 -2
  31. package/dist/{createLankaScope-BiFxNQgl.d.ts → createLankaScope-DomNbEvb.d.ts} +1 -1
  32. package/dist/errors/index.js +3 -3
  33. package/dist/gateway/index.js +9 -9
  34. package/dist/index.d.ts +5 -5
  35. package/dist/index.js +8 -9
  36. package/dist/locator/index.d.ts +2 -2
  37. package/dist/locator/index.js +2 -2
  38. package/dist/logger/index.js +3 -3
  39. package/dist/mock/index.js +3 -3
  40. package/dist/scenario/index.d.ts +25 -0
  41. package/dist/scenario/index.js +6 -8
  42. package/dist/scenario/index.js.map +1 -1
  43. package/dist/stream/index.d.ts +5 -5
  44. package/dist/viewmodel/index.d.ts +137 -27
  45. package/dist/viewmodel/index.js +94 -126
  46. package/dist/viewmodel/index.js.map +1 -1
  47. package/package.json +3 -4
  48. package/skills/lanka-core/SKILL.md +18 -16
  49. package/skills/lanka-core/reference.md +135 -58
  50. package/skills/lanka-packages/SKILL.md +94 -22
  51. package/dist/chunk-B7EYIAW7.js +0 -216
  52. package/dist/chunk-B7EYIAW7.js.map +0 -1
  53. package/dist/chunk-BGVDPDX4.js.map +0 -1
  54. package/dist/chunk-O5ROO7QF.js +0 -315
  55. package/dist/chunk-O5ROO7QF.js.map +0 -1
  56. package/dist/chunk-UBGXDTXC.js.map +0 -1
  57. /package/dist/{chunk-D27MREPB.js.map → chunk-7DQUF2QR.js.map} +0 -0
  58. /package/dist/{chunk-UJEC7H6K.js.map → chunk-BHQ2SQ7P.js.map} +0 -0
  59. /package/dist/{chunk-C2HP7CRD.js.map → chunk-FII3PW2G.js.map} +0 -0
  60. /package/dist/{chunk-DTO27QFR.js.map → chunk-H5TIUKRK.js.map} +0 -0
  61. /package/dist/{chunk-NDCJBO47.js.map → chunk-O5EUTNR6.js.map} +0 -0
  62. /package/dist/{chunk-RKYKK6MN.js.map → chunk-RUMUFHSL.js.map} +0 -0
  63. /package/dist/{chunk-5MAQVBI2.js.map → chunk-UMPSR4US.js.map} +0 -0
package/dist/index.js CHANGED
@@ -6,28 +6,27 @@ import {
6
6
  createLanka,
7
7
  resetActiveLanka,
8
8
  startLanka
9
- } from "./chunk-UBGXDTXC.js";
10
- import "./chunk-B7EYIAW7.js";
11
- import "./chunk-5MAQVBI2.js";
12
- import "./chunk-O5ROO7QF.js";
9
+ } from "./chunk-SZVNPK24.js";
10
+ import "./chunk-UMPSR4US.js";
11
+ import "./chunk-EYDMBI5T.js";
13
12
  import {
14
13
  createLankaHost
15
14
  } from "./chunk-XESL274R.js";
16
- import "./chunk-UJEC7H6K.js";
15
+ import "./chunk-BHQ2SQ7P.js";
17
16
  import {
18
17
  LankaError
19
18
  } from "./chunk-G32H73QY.js";
20
19
  import {
21
20
  getLankaHost
22
- } from "./chunk-RKYKK6MN.js";
21
+ } from "./chunk-RUMUFHSL.js";
23
22
  import "./chunk-UE2C76OR.js";
24
23
  import {
25
24
  lankaLogger
26
- } from "./chunk-C2HP7CRD.js";
25
+ } from "./chunk-FII3PW2G.js";
27
26
  import {
28
27
  getLankaFlags
29
- } from "./chunk-D27MREPB.js";
30
- import "./chunk-BGVDPDX4.js";
28
+ } from "./chunk-7DQUF2QR.js";
29
+ import "./chunk-XGMXT4XZ.js";
31
30
  export {
32
31
  ALankaPlugin,
33
32
  LankaError,
@@ -1,5 +1,5 @@
1
- export { I as ILankaScope } from '../createLankaScope-BiFxNQgl.js';
2
- export { a as ILankaLocator, I as ILankaLocatorConfig, c as ILankaSharedStoreLocatorConfig, d as ILankaSingletonLocatorConfig } from '../LankaSharedStoreLocator-zS2kLu-S.js';
1
+ export { I as ILankaScope } from '../createLankaScope-DomNbEvb.js';
2
+ export { b as ILankaLocator, I as ILankaLocatorConfig, c as ILankaSharedStoreLocatorConfig, d as ILankaSingletonLocatorConfig } from '../LankaSharedStoreLocator-jsz_gnUm.js';
3
3
  import * as GatewaysModule from '@lanka_di/Gateways';
4
4
  import { A as ALankaGateway } from '../ALankaGateway-BrVPaZN5.js';
5
5
  import * as ScenariosModule from '@lanka_di/Scenarios';
@@ -2,11 +2,11 @@ import {
2
2
  createLankaLocatorProxy,
3
3
  lankaSharedStores,
4
4
  lankaSingletons
5
- } from "../chunk-DTO27QFR.js";
5
+ } from "../chunk-H5TIUKRK.js";
6
6
  import "../chunk-UE2C76OR.js";
7
7
  import {
8
8
  requireActiveRuntime
9
- } from "../chunk-BGVDPDX4.js";
9
+ } from "../chunk-XGMXT4XZ.js";
10
10
 
11
11
  // src/locator/gateway/_facades/lanka-gateways/lankaGateways.ts
12
12
  var gatewayLocator = {
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  LankaLogger,
3
3
  lankaLogger
4
- } from "../chunk-C2HP7CRD.js";
5
- import "../chunk-D27MREPB.js";
6
- import "../chunk-BGVDPDX4.js";
4
+ } from "../chunk-FII3PW2G.js";
5
+ import "../chunk-7DQUF2QR.js";
6
+ import "../chunk-XGMXT4XZ.js";
7
7
  export {
8
8
  LankaLogger,
9
9
  lankaLogger
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  lankaLogger
3
- } from "../chunk-C2HP7CRD.js";
3
+ } from "../chunk-FII3PW2G.js";
4
4
  import {
5
5
  getLankaFlags
6
- } from "../chunk-D27MREPB.js";
7
- import "../chunk-BGVDPDX4.js";
6
+ } from "../chunk-7DQUF2QR.js";
7
+ import "../chunk-XGMXT4XZ.js";
8
8
 
9
9
  // src/_internal/sleep.ts
10
10
  var sleep = (ms = 300) => {
@@ -223,6 +223,31 @@ declare class LankaScenarioBootstrap {
223
223
  * registry already holds.
224
224
  */
225
225
  adoptDeclaredViewModels(): void;
226
+ /**
227
+ * Whether the ViewModel being built belongs to ONE scope.
228
+ *
229
+ * A module-level ViewModel is declared once and adopted by every instance
230
+ * ever created, which is what `declaredViewModels` is for and why it is never
231
+ * drained. A SCOPED one is the opposite: it belongs to the request that built
232
+ * it and to nothing after.
233
+ *
234
+ * Declaring one would be the defect this flag exists to prevent, and it is
235
+ * worth spelling out because nothing would look wrong. The array grows by an
236
+ * entry per request for the life of the process, and request N+1 ADOPTS
237
+ * request N's ViewModel — subscribing it to N+1's scenarios, so a dispatch
238
+ * runs N's handlers against N's gateways and writes into N's store. Every
239
+ * suite stays green and the leak is one user seeing another's board.
240
+ */
241
+ private isBuildingScoped;
242
+ /**
243
+ * Runs `build` with its declarations kept OUT of the process-wide list.
244
+ *
245
+ * Called by `resolveLankaVM` and by nothing else. A narrow seam rather than a
246
+ * parameter on every factory: the nine ways to build a ViewModel would each
247
+ * have to carry a flag through to `registerViewModel`, and eight of them have
248
+ * no business knowing what a scope is.
249
+ */
250
+ buildScoped<TBuilt>(build: () => TBuilt): TBuilt;
226
251
  registerViewModel(viewModel: ILankaScenarioVM, name?: string): void;
227
252
  private attachViewModel;
228
253
  /**
@@ -1,13 +1,11 @@
1
- import {
2
- lankaScenarioBootstrap
3
- } from "../chunk-B7EYIAW7.js";
4
1
  import {
5
2
  ALankaScenario,
6
- lankaEventBus
7
- } from "../chunk-O5ROO7QF.js";
8
- import "../chunk-C2HP7CRD.js";
9
- import "../chunk-D27MREPB.js";
10
- import "../chunk-BGVDPDX4.js";
3
+ lankaEventBus,
4
+ lankaScenarioBootstrap
5
+ } from "../chunk-EYDMBI5T.js";
6
+ import "../chunk-FII3PW2G.js";
7
+ import "../chunk-7DQUF2QR.js";
8
+ import "../chunk-XGMXT4XZ.js";
11
9
 
12
10
  // src/scenario/_factories/create-lanka-scenario/createLankaScenario.ts
13
11
  var createLankaScenario = (config) => {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/scenario/_factories/create-lanka-scenario/createLankaScenario.ts"],"sourcesContent":["import { ALankaScenario } from \"../../_abstractions/lanka-scenario/ALankaScenario\";\nimport type { ILankaScenario } from \"../../_interfaces/ILankaScenario\";\n\n/** What a scenario is: three names and nothing else. */\nexport interface ILankaScenarioConfig {\n\t/** The scenario's name, and the key it is found by. */\n\tname: string;\n\t/** The event type on the bus. */\n\teventType: string;\n\t/** The event data's type name — for the bus metadata. */\n\tdataTypeName: string;\n\t/** Opts out of self-registration, as `skipAutoRegistration` does on a class. */\n\tskipAutoRegistration?: boolean;\n}\n\n/**\n * A scenario, without writing a class whose body is data.\n *\n * The class style is right where a scenario has behaviour — an `initialize` that\n * warms something, a `cleanup` that lets go. Most have neither: in the two\n * applications this framework grew out of, every scenario is a class holding\n * three `readonly` fields and nothing else.\n *\n * One implementation: this builds a subclass of `ALankaScenario`, so\n * self-registration, `trigger` and `subscribe` are the same code either way.\n */\nexport const createLankaScenario = <TData = void>(\n\tconfig: ILankaScenarioConfig,\n): ILankaScenario<TData> => {\n\tclass FunctionalScenario extends ALankaScenario<TData> {\n\t\tpublic static override skipAutoRegistration = config.skipAutoRegistration ?? false;\n\n\t\tpublic readonly name = config.name;\n\t\tpublic readonly eventType = config.eventType;\n\t\tpublic readonly dataTypeName = config.dataTypeName;\n\t}\n\n\treturn new FunctionalScenario();\n};\n"],"mappings":";;;;;;;;;;;;AA0BO,IAAM,sBAAsB,CAClC,WAC2B;AAAA,EAC3B,MAAM,2BAA2B,eAAsB;AAAA,IACtD,OAAuB,uBAAuB,OAAO,wBAAwB;AAAA,IAE7D,OAAO,OAAO;AAAA,IACd,YAAY,OAAO;AAAA,IACnB,eAAe,OAAO;AAAA,EACvC;AAEA,SAAO,IAAI,mBAAmB;AAC/B;","names":[]}
1
+ {"version":3,"sources":["../../src/scenario/_factories/create-lanka-scenario/createLankaScenario.ts"],"sourcesContent":["import { ALankaScenario } from \"../../_abstractions/lanka-scenario/ALankaScenario\";\nimport type { ILankaScenario } from \"../../_interfaces/ILankaScenario\";\n\n/** What a scenario is: three names and nothing else. */\nexport interface ILankaScenarioConfig {\n\t/** The scenario's name, and the key it is found by. */\n\tname: string;\n\t/** The event type on the bus. */\n\teventType: string;\n\t/** The event data's type name — for the bus metadata. */\n\tdataTypeName: string;\n\t/** Opts out of self-registration, as `skipAutoRegistration` does on a class. */\n\tskipAutoRegistration?: boolean;\n}\n\n/**\n * A scenario, without writing a class whose body is data.\n *\n * The class style is right where a scenario has behaviour — an `initialize` that\n * warms something, a `cleanup` that lets go. Most have neither: in the two\n * applications this framework grew out of, every scenario is a class holding\n * three `readonly` fields and nothing else.\n *\n * One implementation: this builds a subclass of `ALankaScenario`, so\n * self-registration, `trigger` and `subscribe` are the same code either way.\n */\nexport const createLankaScenario = <TData = void>(\n\tconfig: ILankaScenarioConfig,\n): ILankaScenario<TData> => {\n\tclass FunctionalScenario extends ALankaScenario<TData> {\n\t\tpublic static override skipAutoRegistration = config.skipAutoRegistration ?? false;\n\n\t\tpublic readonly name = config.name;\n\t\tpublic readonly eventType = config.eventType;\n\t\tpublic readonly dataTypeName = config.dataTypeName;\n\t}\n\n\treturn new FunctionalScenario();\n};\n"],"mappings":";;;;;;;;;;AA0BO,IAAM,sBAAsB,CAClC,WAC2B;AAAA,EAC3B,MAAM,2BAA2B,eAAsB;AAAA,IACtD,OAAuB,uBAAuB,OAAO,wBAAwB;AAAA,IAE7D,OAAO,OAAO;AAAA,IACd,YAAY,OAAO;AAAA,IACnB,eAAe,OAAO;AAAA,EACvC;AAEA,SAAO,IAAI,mBAAmB;AAC/B;","names":[]}
@@ -1,11 +1,11 @@
1
- import { c as ILankaPlugin } from '../createLanka-NrlvN-WQ.js';
2
- import '../createLankaScope-BiFxNQgl.js';
3
- import '../LankaSharedStoreLocator-zS2kLu-S.js';
1
+ import { c as ILankaPlugin } from '../createLanka-x4oSMs7P.js';
2
+ import '../createLankaScope-DomNbEvb.js';
3
+ import '../LankaSharedStoreLocator-jsz_gnUm.js';
4
4
  import '../ALankaSharedStore-B7uepuuk.js';
5
5
  import 'zustand/vanilla';
6
- import '../activeRuntime-BYd2D6Lx.js';
6
+ import '../activeRuntime-BO-qY0yY.js';
7
7
  import '../ILankaScenarioVM-DpKFL3iE.js';
8
- import '../LankaScenarioLocator-CAENLhDO.js';
8
+ import '../LankaScenarioLocator-Dki2Es3O.js';
9
9
  import '../ILankaScenarioMetadata-Dj4GCqmX.js';
10
10
  import '../ALankaGateway-BrVPaZN5.js';
11
11
  import '../lankaStandardValidator-BUFnysK0.js';
@@ -1,8 +1,27 @@
1
- import { StoreApi, StateCreator, UseBoundStore } from 'zustand';
1
+ import { I as ILankaReadableVM } from '../ILankaReadableVM-BoPzHEPV.js';
2
2
  import { a as ILankaScenario, T as TLankaReplayRequest, I as ILankaScenarioVM } from '../ILankaScenarioVM-DpKFL3iE.js';
3
+ import { StoreApi, StateCreator } from 'zustand';
3
4
  import { A as ALankaSharedStore } from '../ALankaSharedStore-B7uepuuk.js';
4
5
  import { StoreApi as StoreApi$1 } from 'zustand/vanilla';
5
6
 
7
+ /**
8
+ * A ViewModel that can also be written to from outside.
9
+ *
10
+ * The reading half plus the two members a host needs: the state a screen starts
11
+ * from, and a way to make server data that first state — which is what
12
+ * `hydrateLankaVM` does and the only reason writing is published at all.
13
+ *
14
+ * A view binding takes `ILankaReadableVM` instead. The narrower type is not
15
+ * politeness: a binding holding this one could write during a render, which is
16
+ * the defect no framework's scheduler survives.
17
+ */
18
+ interface ILankaVM<TState extends object> extends ILankaReadableVM<TState> {
19
+ /** The state the ViewModel was built with, before anything wrote to it. */
20
+ getInitialState(): TState;
21
+ /** Writes state. Partial by default; `replace` swaps the whole object. */
22
+ setState(partial: TState | Partial<TState> | ((state: TState) => TState | Partial<TState>), replace?: false): void;
23
+ }
24
+
6
25
  interface ILankaVMContext<TState, TGateways extends object, TServices extends object> {
7
26
  set: StoreApi<TState>["setState"];
8
27
  get: () => TState;
@@ -122,10 +141,10 @@ interface ILankaVMConfig<State extends object, Actions extends object, TGateways
122
141
  * through a getter — and warns with the ViewModel and key names. "Remember to
123
142
  * set the flag" is not a mechanism.
124
143
  */
125
- declare function createLankaVM<State extends object, Actions extends object>(config: ILankaVMConfig<State, Actions, Record<string, never>, Record<string, never>>): UseBoundStore<StoreApi<State & Actions & ILankaScenarioVM>>;
126
- declare function createLankaVM<State extends object, Actions extends object, Services extends object>(config: ILankaVMConfig<State, Actions, Record<string, never>, Services>): UseBoundStore<StoreApi<State & Actions & ILankaScenarioVM>>;
127
- declare function createLankaVM<State extends object, Actions extends object, TGateways extends object>(config: ILankaVMConfig<State, Actions, TGateways, Record<string, never>>): UseBoundStore<StoreApi<State & Actions & ILankaScenarioVM>>;
128
- declare function createLankaVM<State extends object, Actions extends object, TGateways extends object, Services extends object>(config: ILankaVMConfig<State, Actions, TGateways, Services>): UseBoundStore<StoreApi<State & Actions & ILankaScenarioVM>>;
144
+ declare function createLankaVM<State extends object, Actions extends object>(config: ILankaVMConfig<State, Actions, Record<string, never>, Record<string, never>>): ILankaVM<State & Actions & ILankaScenarioVM>;
145
+ declare function createLankaVM<State extends object, Actions extends object, Services extends object>(config: ILankaVMConfig<State, Actions, Record<string, never>, Services>): ILankaVM<State & Actions & ILankaScenarioVM>;
146
+ declare function createLankaVM<State extends object, Actions extends object, TGateways extends object>(config: ILankaVMConfig<State, Actions, TGateways, Record<string, never>>): ILankaVM<State & Actions & ILankaScenarioVM>;
147
+ declare function createLankaVM<State extends object, Actions extends object, TGateways extends object, Services extends object>(config: ILankaVMConfig<State, Actions, TGateways, Services>): ILankaVM<State & Actions & ILankaScenarioVM>;
129
148
 
130
149
  declare function createLazyLankaVM<State extends object, Actions extends object>(config: ILankaVMConfig<State, Actions, Record<string, never>, Record<string, never>>): TLazyLankaVM<ReturnType<typeof createLankaVM<State, Actions, Record<string, never>, Record<string, never>>>, State & Actions & ILankaScenarioVM>;
131
150
  declare function createLazyLankaVM<State extends object, Actions extends object, Services extends object>(config: ILankaVMConfig<State, Actions, Record<string, never>, Services>): TLazyLankaVM<ReturnType<typeof createLankaVM<State, Actions, Record<string, never>, Services>>, State & Actions & ILankaScenarioVM>;
@@ -166,14 +185,18 @@ type TLankaStatelessVMConfig$1<Actions extends object, TGateways extends object
166
185
  onInit?: (ctx: ILankaStatelessVMContext<Actions & ILankaScenarioVM, TGateways, Services>) => void;
167
186
  onReset?: (ctx: ILankaStatelessVMContext<Actions & ILankaScenarioVM, TGateways, Services>) => void;
168
187
  };
169
- type TLankaStatelessVMHook<Actions extends object> = {
170
- <TSelected = Actions & ILankaScenarioVM>(selector?: (full: Actions & ILankaScenarioVM) => TSelected): TSelected;
171
- getState: () => Actions & ILankaScenarioVM;
172
- };
173
- declare function createStatelessLankaVM<Actions extends object>(config: TLankaStatelessVMConfig$1<Actions, Record<string, never>, Record<string, never>>): TLankaStatelessVMHook<Actions>;
174
- declare function createStatelessLankaVM<Actions extends object, Services extends object>(config: TLankaStatelessVMConfig$1<Actions, Record<string, never>, Services>): TLankaStatelessVMHook<Actions>;
175
- declare function createStatelessLankaVM<Actions extends object, TGateways extends object>(config: TLankaStatelessVMConfig$1<Actions, TGateways, Record<string, never>>): TLankaStatelessVMHook<Actions>;
176
- declare function createStatelessLankaVM<Actions extends object, TGateways extends object, Services extends object>(config: TLankaStatelessVMConfig$1<Actions, TGateways, Services>): TLankaStatelessVMHook<Actions>;
188
+ /**
189
+ * @deprecated since 2.0.0 - use ILankaReadableVM, which is what a stateless
190
+ * ViewModel now IS: `createStatelessLankaVM` answers a readable ViewModel rather
191
+ * than a React hook, so the word "Hook" in this name no longer describes
192
+ * anything. The alias is kept because a published name is never removed, and it
193
+ * resolves to exactly the type the factory returns.
194
+ */
195
+ type TLankaStatelessVMHook<Actions extends object> = ILankaReadableVM<Actions & ILankaScenarioVM>;
196
+ declare function createStatelessLankaVM<Actions extends object>(config: TLankaStatelessVMConfig$1<Actions, Record<string, never>, Record<string, never>>): ILankaReadableVM<Actions & ILankaScenarioVM>;
197
+ declare function createStatelessLankaVM<Actions extends object, Services extends object>(config: TLankaStatelessVMConfig$1<Actions, Record<string, never>, Services>): ILankaReadableVM<Actions & ILankaScenarioVM>;
198
+ declare function createStatelessLankaVM<Actions extends object, TGateways extends object>(config: TLankaStatelessVMConfig$1<Actions, TGateways, Record<string, never>>): ILankaReadableVM<Actions & ILankaScenarioVM>;
199
+ declare function createStatelessLankaVM<Actions extends object, TGateways extends object, Services extends object>(config: TLankaStatelessVMConfig$1<Actions, TGateways, Services>): ILankaReadableVM<Actions & ILankaScenarioVM>;
177
200
 
178
201
  type TLankaStatelessVMConfig<Actions extends object, TGateways extends object = Record<string, never>, Services extends object = Record<string, never>> = Omit<ILankaVMConfig<object, Actions, TGateways, Services>, "states"> & {
179
202
  states?: never;
@@ -197,11 +220,25 @@ interface ILankaSharedStoreVMContext<TStoreState extends object, TFullState exte
197
220
  trigger: <T>(scenario: ILankaScenario<T>, data?: T) => void;
198
221
  }
199
222
 
200
- type TLankaSharedStoreVMHook<TStoreState extends object, TActions extends object> = {
201
- <TSelected = TStoreState & TActions & ILankaScenarioVM>(selector?: (full: TStoreState & TActions & ILankaScenarioVM) => TSelected): TSelected;
202
- getState: () => TStoreState & TActions & ILankaScenarioVM;
223
+ /**
224
+ * A ViewModel over a store somebody else owns.
225
+ *
226
+ * The port, plus the one member the shape genuinely adds: the SLICE, without the
227
+ * actions and scenario members composed onto it. A screen reads `getState`; code
228
+ * that has to reason about what is actually persisted — a hydration, a devtools
229
+ * panel, a second ViewModel over the same store — reads `getStoreState`.
230
+ */
231
+ interface ILankaSharedStoreVM<TStoreState extends object, TActions extends object> extends ILankaReadableVM<TStoreState & TActions & ILankaScenarioVM> {
232
+ /** The shared store's own state, without this ViewModel's actions on top. */
203
233
  getStoreState: () => TStoreState;
204
- };
234
+ }
235
+ /**
236
+ * @deprecated since 2.0.0 - use ILankaSharedStoreVM, which is the same type
237
+ * under a name that is still true: `createSharedStoreLankaVM` answers a readable
238
+ * ViewModel rather than a React hook. The alias is kept because a published name
239
+ * is never removed.
240
+ */
241
+ type TLankaSharedStoreVMHook<TStoreState extends object, TActions extends object> = ILankaSharedStoreVM<TStoreState, TActions>;
205
242
  interface ILankaSharedStoreScenarioBinding<TData, TStoreState extends object, TActions extends object, TStore extends ALankaSharedStore<TStoreState>, TGateways extends object, TServices extends object> {
206
243
  scenario: ILankaScenario<TData>;
207
244
  /**
@@ -235,10 +272,10 @@ interface ILankaSharedStoreVMConfig<TStoreState extends object, TActions extends
235
272
  * Factory for ViewModels backed by an external shared store instance.
236
273
  * Multiple ViewModels can be created on top of the same store instance.
237
274
  */
238
- declare function createSharedStoreLankaVM<StoreState extends object, Actions extends object, Store extends ALankaSharedStore<StoreState>>(config: ILankaSharedStoreVMConfig<StoreState, Actions, Store, Record<string, never>, Record<string, never>>): TLankaSharedStoreVMHook<StoreState, Actions>;
239
- declare function createSharedStoreLankaVM<StoreState extends object, Actions extends object, Store extends ALankaSharedStore<StoreState>, Services extends object>(config: ILankaSharedStoreVMConfig<StoreState, Actions, Store, Record<string, never>, Services>): TLankaSharedStoreVMHook<StoreState, Actions>;
240
- declare function createSharedStoreLankaVM<StoreState extends object, Actions extends object, Store extends ALankaSharedStore<StoreState>, TGateways extends object>(config: ILankaSharedStoreVMConfig<StoreState, Actions, Store, TGateways, Record<string, never>>): TLankaSharedStoreVMHook<StoreState, Actions>;
241
- declare function createSharedStoreLankaVM<StoreState extends object, Actions extends object, Store extends ALankaSharedStore<StoreState>, TGateways extends object, Services extends object>(config: ILankaSharedStoreVMConfig<StoreState, Actions, Store, TGateways, Services>): TLankaSharedStoreVMHook<StoreState, Actions>;
275
+ declare function createSharedStoreLankaVM<StoreState extends object, Actions extends object, Store extends ALankaSharedStore<StoreState>>(config: ILankaSharedStoreVMConfig<StoreState, Actions, Store, Record<string, never>, Record<string, never>>): ILankaSharedStoreVM<StoreState, Actions>;
276
+ declare function createSharedStoreLankaVM<StoreState extends object, Actions extends object, Store extends ALankaSharedStore<StoreState>, Services extends object>(config: ILankaSharedStoreVMConfig<StoreState, Actions, Store, Record<string, never>, Services>): ILankaSharedStoreVM<StoreState, Actions>;
277
+ declare function createSharedStoreLankaVM<StoreState extends object, Actions extends object, Store extends ALankaSharedStore<StoreState>, TGateways extends object>(config: ILankaSharedStoreVMConfig<StoreState, Actions, Store, TGateways, Record<string, never>>): ILankaSharedStoreVM<StoreState, Actions>;
278
+ declare function createSharedStoreLankaVM<StoreState extends object, Actions extends object, Store extends ALankaSharedStore<StoreState>, TGateways extends object, Services extends object>(config: ILankaSharedStoreVMConfig<StoreState, Actions, Store, TGateways, Services>): ILankaSharedStoreVM<StoreState, Actions>;
242
279
 
243
280
  /**
244
281
  * What a lazy shared-store ViewModel is, in the type as well as at runtime.
@@ -386,7 +423,7 @@ declare abstract class ALankaVM<State extends object, Actions extends object, TG
386
423
  */
387
424
  protected readonly enableAccessTrackingOptimization: boolean;
388
425
  /** Writes state. Available from `createActions` onwards, never before. */
389
- protected set: StoreApi<State & Actions & ILankaScenarioVM>["setState"];
426
+ protected set: StoreApi$1<State & Actions & ILankaScenarioVM>["setState"];
390
427
  /** Reads state. The read a tracked hook cannot see — hence the switch above. */
391
428
  protected get: () => State & Actions & ILankaScenarioVM;
392
429
  /** Fires a scenario, which every ViewModel bound to it then hears. */
@@ -413,8 +450,16 @@ declare abstract class ALankaVM<State extends object, Actions extends object, TG
413
450
  * the wrong half. Canon: `skills/parity/SKILL.md` section 3a.
414
451
  */
415
452
  protected toStyleContext(): ILankaVMContext<State & Actions & ILankaScenarioVM, TGateways, Services>;
416
- /** Builds the hook a screen calls. One store per call. */
417
- build(): UseBoundStore<StoreApi<State & Actions & ILankaScenarioVM>>;
453
+ /**
454
+ * Builds the ViewModel a screen reads. One store per call.
455
+ *
456
+ * What comes back is a STORE, not a hook: `getState`, `subscribe`, `setState`,
457
+ * plus the name and the tracking flag. A screen reaches it through its
458
+ * framework's binding — `useLankaVM(todoVM)` from `@lankajs/react`,
459
+ * `@lankajs/vue` and the rest of the shelf — and a program with no framework
460
+ * at all reads `getState()` and `subscribe()` directly.
461
+ */
462
+ build(): ILankaVM<State & Actions & ILankaScenarioVM>;
418
463
  }
419
464
 
420
465
  /**
@@ -482,8 +527,13 @@ declare abstract class ALankaStatelessVM<Actions extends object, TGateways exten
482
527
  * read. Canon: `skills/parity/SKILL.md` section 3a.
483
528
  */
484
529
  protected toStyleContext(): ILankaStatelessVMContext<Actions & ILankaScenarioVM, TGateways, Services>;
485
- /** Builds the hook a screen calls. One ViewModel per call. */
486
- build(): TLankaStatelessVMHook<Actions>;
530
+ /**
531
+ * Builds the ViewModel a screen reads. One per call.
532
+ *
533
+ * What comes back answers the read half of the port and nothing more: there
534
+ * is no store to write to from outside, because there is no state to write.
535
+ */
536
+ build(): ILankaReadableVM<Actions & ILankaScenarioVM>;
487
537
  }
488
538
 
489
539
  /**
@@ -559,8 +609,68 @@ declare abstract class ALankaSharedStoreVM<StoreState extends object, Actions ex
559
609
  */
560
610
  declare const createLankaSharedStore: <TState extends object>(createInitialState: () => TState) => ALankaSharedStore<TState>;
561
611
 
612
+ /**
613
+ * Keeps a selection's IDENTITY while nothing in it moved.
614
+ *
615
+ * ```ts
616
+ * const hold = createLankaShallowHold<{ title: string; status: string }>();
617
+ *
618
+ * // in any binding on the shelf
619
+ * const view = useLankaVM(missionVM, (state) => hold({
620
+ * title: state.title,
621
+ * status: state.status,
622
+ * }));
623
+ * ```
624
+ *
625
+ * ## What it is for
626
+ *
627
+ * A selector narrows what a reader depends on, and a selector that BUILDS its
628
+ * answer — `(state) => ({ a: state.a })`, `(state) => rows.filter(…)`, the shape
629
+ * a consumer reaches for first — cannot say so. Every binding compares the new
630
+ * selection with the last one by identity, and a fresh object is never identical
631
+ * to anything, so the reader wakes for every change in the ViewModel including
632
+ * the keys the selector exists to ignore. This is the comparison that makes the
633
+ * selection mean something.
634
+ *
635
+ * A selector answering a PRIMITIVE never needed it, which is what makes the cost
636
+ * quiet: the shape that is free and the shape that repaints on everything look
637
+ * the same on the page.
638
+ *
639
+ * ## Why it is in core and not in a binding
640
+ *
641
+ * It was `useLankaShallow` in `@lankajs/react` and nowhere else, and that made it
642
+ * a CAPABILITY one member of the shelf had and four did not. An idiom is a
643
+ * spelling; this changes which notifications reach a reader, and it encodes a
644
+ * policy — one level deep, own keys, `Object.is` — that five packages inventing
645
+ * separately would answer five ways. `skills/parity/SKILL.md` 3c: a binding that
646
+ * needs more than the port gives it has found something that belongs in core, for
647
+ * everybody.
648
+ *
649
+ * `useLankaShallow` keeps working and is now React's spelling over this. It has
650
+ * to exist there and cannot exist here: a React component re-runs the hook on
651
+ * every render, so the holding has to survive a render while the SELECTOR stays
652
+ * the current one — which is a `useRef`, and a ref is not something core can
653
+ * have.
654
+ *
655
+ * ## Why it holds a value and not a selector
656
+ *
657
+ * `createLankaShallowSelector(selector)` was the other shape and it cannot serve
658
+ * React: the wrapper would be rebuilt whenever the selector's identity moved, and
659
+ * an inline arrow is a new function every render, so the holding would reset
660
+ * before it ever held anything. Taking the VALUE puts the state in the only place
661
+ * every framework can keep it, and the extra line at a call site is the price of
662
+ * one name that works in all five rather than two that each work in some.
663
+ *
664
+ * ## One level, and it says so by failing
665
+ *
666
+ * Deeper would mean walking a state of unknown size on every read, which is the
667
+ * cost a reader took a selector to avoid. A selection with a nested object wants
668
+ * a selector that picks the leaves.
669
+ */
670
+ declare const createLankaShallowHold: <TValue>() => ((next: TValue) => TValue);
671
+
562
672
  type TLankaVMStateCreator<TFullState> = StateCreator<TFullState, TLankaAnyMutators, TLankaAnyMutators>;
563
673
 
564
674
  type TLankaSharedStoreSetState<TState extends object> = (partial: TState | Partial<TState> | ((state: TState) => TState | Partial<TState>), replace?: boolean) => void;
565
675
 
566
- export { ALankaSharedStore, ALankaSharedStoreVM, ALankaStatelessVM, ALankaVM, type ILankaScenarioBinding, type ILankaSharedStoreScenarioBinding, type ILankaSharedStoreVMConfig, type ILankaSharedStoreVMContext, type ILankaStatelessScenarioBinding, type ILankaStatelessVMContext, type ILankaVMConfig, type ILankaVMContext, type TLankaAnyMutators, type TLankaSetState, type TLankaSharedStoreSetState, type TLankaSharedStoreVMHook, type TLankaStatelessVMConfig$1 as TLankaStatelessVMConfig, type TLankaStatelessVMHook, type TLankaVMEnhancer, type TLankaVMStateCreator, type TLazyLankaVM, type TUnknownLankaScenarioBinding, createLankaSharedStore, createLankaVM, createLazyLankaVM, createLazySharedStoreLankaVM, createLazyStatelessLankaVM, createSharedStoreLankaVM, createStatelessLankaVM };
676
+ export { ALankaSharedStore, ALankaSharedStoreVM, ALankaStatelessVM, ALankaVM, ILankaReadableVM, type ILankaScenarioBinding, type ILankaSharedStoreScenarioBinding, type ILankaSharedStoreVM, type ILankaSharedStoreVMConfig, type ILankaSharedStoreVMContext, type ILankaStatelessScenarioBinding, type ILankaStatelessVMContext, type ILankaVM, type ILankaVMConfig, type ILankaVMContext, type TLankaAnyMutators, type TLankaSetState, type TLankaSharedStoreSetState, type TLankaSharedStoreVMHook, type TLankaStatelessVMConfig$1 as TLankaStatelessVMConfig, type TLankaStatelessVMHook, type TLankaVMEnhancer, type TLankaVMStateCreator, type TLazyLankaVM, type TUnknownLankaScenarioBinding, createLankaShallowHold, createLankaSharedStore, createLankaVM, createLazyLankaVM, createLazySharedStoreLankaVM, createLazyStatelessLankaVM, createSharedStoreLankaVM, createStatelessLankaVM };