lanka 1.3.0 → 2.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 (91) hide show
  1. package/README.md +1 -1
  2. package/dist/{LankaSharedStoreLocator-zS2kLu-S.d.ts → ALankaLocator-BUCCz0Q5.d.ts} +1 -47
  3. package/dist/ILankaReadableVM-BoPzHEPV.d.ts +72 -0
  4. package/dist/{ILankaScenarioVM-DpKFL3iE.d.ts → ILankaScenario-DQd9ZfUw.d.ts} +1 -30
  5. package/dist/{ILankaScenarioMetadata-Dj4GCqmX.d.ts → ILankaScenarioMetadata-BsDp0Bzm.d.ts} +1 -1
  6. package/dist/ILankaScenarioVM-DKwjbIRq.d.ts +30 -0
  7. package/dist/{LankaScenarioLocator-CAENLhDO.d.ts → LankaScenarioVMRegistry-DySAOaj2.d.ts} +4 -37
  8. package/dist/_extend/index.d.ts +235 -7
  9. package/dist/_extend/index.js +152 -12
  10. package/dist/_extend/index.js.map +1 -1
  11. package/dist/_internal/index.d.ts +13 -8
  12. package/dist/_internal/index.js +9 -3
  13. package/dist/_internal/index.js.map +1 -1
  14. package/dist/{activeRuntime-BYd2D6Lx.d.ts → activeRuntime-ByucLPhj.d.ts} +55 -4
  15. package/dist/bootstrap/index.d.ts +15 -10
  16. package/dist/bootstrap/index.js +14 -9
  17. package/dist/chunk-24MUFFHF.js +43 -0
  18. package/dist/chunk-24MUFFHF.js.map +1 -0
  19. package/dist/chunk-3R2NO47A.js +35 -0
  20. package/dist/chunk-3R2NO47A.js.map +1 -0
  21. package/dist/{chunk-5MAQVBI2.js → chunk-42CWYVZJ.js} +44 -61
  22. package/dist/chunk-42CWYVZJ.js.map +1 -0
  23. package/dist/{chunk-D27MREPB.js → chunk-7DQUF2QR.js} +2 -2
  24. package/dist/{chunk-UJEC7H6K.js → chunk-BHQ2SQ7P.js} +2 -2
  25. package/dist/chunk-BMF4TM2Z.js +22 -0
  26. package/dist/chunk-BMF4TM2Z.js.map +1 -0
  27. package/dist/{chunk-C2HP7CRD.js → chunk-FII3PW2G.js} +2 -2
  28. package/dist/{chunk-DTO27QFR.js → chunk-H5TIUKRK.js} +2 -2
  29. package/dist/chunk-JZJ6GXX3.js +12 -0
  30. package/dist/chunk-JZJ6GXX3.js.map +1 -0
  31. package/dist/{chunk-B7EYIAW7.js → chunk-MKKMTLOY.js} +47 -13
  32. package/dist/chunk-MKKMTLOY.js.map +1 -0
  33. package/dist/{chunk-UE2C76OR.js → chunk-N3275IPH.js} +2 -69
  34. package/dist/chunk-N3275IPH.js.map +1 -0
  35. package/dist/{chunk-O5ROO7QF.js → chunk-NWEHOMTS.js} +3 -3
  36. package/dist/{chunk-NDCJBO47.js → chunk-O5EUTNR6.js} +2 -2
  37. package/dist/{chunk-RKYKK6MN.js → chunk-RUMUFHSL.js} +2 -2
  38. package/dist/chunk-SBITVBF7.js +49 -0
  39. package/dist/chunk-SBITVBF7.js.map +1 -0
  40. package/dist/{chunk-UBGXDTXC.js → chunk-SO7D5E7O.js} +22 -16
  41. package/dist/chunk-SO7D5E7O.js.map +1 -0
  42. package/dist/chunk-UDP6IXDS.js +17 -0
  43. package/dist/chunk-UDP6IXDS.js.map +1 -0
  44. package/dist/{chunk-BGVDPDX4.js → chunk-XGMXT4XZ.js} +20 -3
  45. package/dist/chunk-XGMXT4XZ.js.map +1 -0
  46. package/dist/config/index.js +3 -3
  47. package/dist/{createLanka-NrlvN-WQ.d.ts → createLanka-DvUGu9Hl.d.ts} +2 -2
  48. package/dist/{createLankaScope-BiFxNQgl.d.ts → createLankaScope-CVoV0EwO.d.ts} +1 -1
  49. package/dist/errors/index.js +3 -3
  50. package/dist/gateway/index.js +6 -6
  51. package/dist/index.d.ts +14 -9
  52. package/dist/index.js +15 -10
  53. package/dist/locator/gateway/lanka-gateway-locator/LankaGatewayLocator.d.ts +18 -0
  54. package/dist/locator/gateway/lanka-gateway-locator/LankaGatewayLocator.js +9 -0
  55. package/dist/locator/gateway/lanka-gateway-locator/LankaGatewayLocator.js.map +1 -0
  56. package/dist/locator/index.d.ts +4 -2
  57. package/dist/locator/index.js +6 -3
  58. package/dist/locator/index.js.map +1 -1
  59. package/dist/locator/scenario/lanka-scenario-locator/LankaScenarioLocator.d.ts +60 -0
  60. package/dist/locator/scenario/lanka-scenario-locator/LankaScenarioLocator.js +12 -0
  61. package/dist/locator/scenario/lanka-scenario-locator/LankaScenarioLocator.js.map +1 -0
  62. package/dist/locator/shared-store/lanka-shared-store-locator/LankaSharedStoreLocator.d.ts +22 -0
  63. package/dist/locator/shared-store/lanka-shared-store-locator/LankaSharedStoreLocator.js +9 -0
  64. package/dist/locator/shared-store/lanka-shared-store-locator/LankaSharedStoreLocator.js.map +1 -0
  65. package/dist/locator/singleton/lanka-singleton-locator/LankaSingletonLocator.d.ts +30 -0
  66. package/dist/locator/singleton/lanka-singleton-locator/LankaSingletonLocator.js +9 -0
  67. package/dist/locator/singleton/lanka-singleton-locator/LankaSingletonLocator.js.map +1 -0
  68. package/dist/logger/index.js +3 -3
  69. package/dist/mock/index.js +3 -3
  70. package/dist/scenario/index.d.ts +29 -3
  71. package/dist/scenario/index.js +5 -5
  72. package/dist/stream/index.d.ts +17 -12
  73. package/dist/viewmodel/index.d.ts +139 -28
  74. package/dist/viewmodel/index.js +95 -126
  75. package/dist/viewmodel/index.js.map +1 -1
  76. package/package.json +3 -4
  77. package/skills/lanka-core/SKILL.md +18 -16
  78. package/skills/lanka-core/reference.md +135 -58
  79. package/skills/lanka-packages/SKILL.md +94 -22
  80. package/dist/chunk-5MAQVBI2.js.map +0 -1
  81. package/dist/chunk-B7EYIAW7.js.map +0 -1
  82. package/dist/chunk-BGVDPDX4.js.map +0 -1
  83. package/dist/chunk-UBGXDTXC.js.map +0 -1
  84. package/dist/chunk-UE2C76OR.js.map +0 -1
  85. /package/dist/{chunk-D27MREPB.js.map → chunk-7DQUF2QR.js.map} +0 -0
  86. /package/dist/{chunk-UJEC7H6K.js.map → chunk-BHQ2SQ7P.js.map} +0 -0
  87. /package/dist/{chunk-C2HP7CRD.js.map → chunk-FII3PW2G.js.map} +0 -0
  88. /package/dist/{chunk-DTO27QFR.js.map → chunk-H5TIUKRK.js.map} +0 -0
  89. /package/dist/{chunk-O5ROO7QF.js.map → chunk-NWEHOMTS.js.map} +0 -0
  90. /package/dist/{chunk-NDCJBO47.js.map → chunk-O5EUTNR6.js.map} +0 -0
  91. /package/dist/{chunk-RKYKK6MN.js.map → chunk-RUMUFHSL.js.map} +0 -0
@@ -0,0 +1,60 @@
1
+ import { I as ILankaScenario } from '../../../ILankaScenario-DQd9ZfUw.js';
2
+ import { A as ALankaLocator } from '../../../ALankaLocator-BUCCz0Q5.js';
3
+
4
+ /**
5
+ * Resolves scenarios by property name (camelCase) or scenario name
6
+ * (PascalCase).
7
+ *
8
+ * Looks in the registry, then in the self-registration pool, and failing both
9
+ * constructs the scenario from the consumer's barrel on first use.
10
+ */
11
+ declare class LankaScenarioLocator extends ALankaLocator<ILankaScenario<unknown>> {
12
+ /**
13
+ * The registry is read LAZILY rather than in a field initialiser.
14
+ *
15
+ * The locator is constructed INSIDE `createLanka`, before the instance becomes
16
+ * active. A field initialiser would ask for the active instance at that moment
17
+ * and fail with "no instance yet" while the instance being created is on the
18
+ * stack. Deferred reading resolves it: by the first scenario resolution an
19
+ * active instance exists.
20
+ */
21
+ private get registry();
22
+ /**
23
+ * Every constructible class the consumer's barrel exports.
24
+ *
25
+ * Published so that this file stays the ONE module in the framework that reads
26
+ * `@lanka_di/Scenarios`. `LankaScenarioBootstrap` used to read it too, and
27
+ * that second reader is what made `lanka/scenario` — the entry a consumer's
28
+ * scenario class imports `ALankaScenario` from — part of the import cycle the
29
+ * inversion creates. A bundler is free to order the chunks behind that entry
30
+ * however it likes, and when it put the barrel first the consumer's class
31
+ * extended `undefined`. `lanka/locator` carries the cycle instead, and no
32
+ * scenario class imports it.
33
+ *
34
+ * Not a filter on "is a scenario": an export that is not a function has no
35
+ * chance of being one, and anything further is decided by CONSTRUCTING it,
36
+ * which is the caller's job and the only honest test.
37
+ *
38
+ * ## Why the values are widened to `unknown` first
39
+ *
40
+ * A type predicate has to be assignable to the type it narrows, and the type
41
+ * of what this reads is the CONSUMER'S — whatever their `Scenarios` barrel
42
+ * happens to export. A real scenario class is `typeof TheirScenario`, which
43
+ * carries the statics `ALankaScenario` declares, and `new () => ILankaScenario`
44
+ * has none of them: the predicate is not assignable to it, and the file does
45
+ * not compile in any project whose barrel has a scenario in it.
46
+ *
47
+ * It compiled here for one reason: this repository's fixture barrel says
48
+ * `export {}`, so `Object.values` is `never[]` and every predicate is
49
+ * vacuously assignable. `_playgrounds/node` is where it failed, because that
50
+ * is a barrel with a real class in it — the same blind spot, in the same
51
+ * shape, as the empty probe barrels that let the 2.0.0 chunk cycle ship.
52
+ *
53
+ * `unknown` is also what this honestly knows. The framework cannot see a
54
+ * consumer's types; it sees exports and asks whether each is a function.
55
+ */
56
+ getDeclaredScenarioClasses(): readonly (new () => ILankaScenario<unknown>)[];
57
+ constructor();
58
+ }
59
+
60
+ export { LankaScenarioLocator };
@@ -0,0 +1,12 @@
1
+ import {
2
+ LankaScenarioLocator
3
+ } from "../../../chunk-42CWYVZJ.js";
4
+ import "../../../chunk-NWEHOMTS.js";
5
+ import "../../../chunk-N3275IPH.js";
6
+ import "../../../chunk-FII3PW2G.js";
7
+ import "../../../chunk-7DQUF2QR.js";
8
+ import "../../../chunk-XGMXT4XZ.js";
9
+ export {
10
+ LankaScenarioLocator
11
+ };
12
+ //# sourceMappingURL=LankaScenarioLocator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,22 @@
1
+ import { A as ALankaLocator } from '../../../ALankaLocator-BUCCz0Q5.js';
2
+ import { A as ALankaSharedStore } from '../../../ALankaSharedStore-B7uepuuk.js';
3
+ import 'zustand/vanilla';
4
+
5
+ type TSharedStoreState = object;
6
+ /**
7
+ * LankaSharedStoreLocator configuration.
8
+ */
9
+ interface ILankaSharedStoreLocatorConfig {
10
+ /** The module holding shared store classes — the consumer's barrel. */
11
+ sharedStoreIndexModule?: Record<string, unknown>;
12
+ }
13
+ /**
14
+ * Resolves shared stores by property name (camelCase) or class name
15
+ * (PascalCase), constructing them on first use and caching them.
16
+ */
17
+ declare class LankaSharedStoreLocator extends ALankaLocator<ALankaSharedStore<TSharedStoreState>> {
18
+ private readonly sharedStoreIndexModule?;
19
+ constructor(config?: ILankaSharedStoreLocatorConfig);
20
+ }
21
+
22
+ export { type ILankaSharedStoreLocatorConfig, LankaSharedStoreLocator };
@@ -0,0 +1,9 @@
1
+ import {
2
+ LankaSharedStoreLocator
3
+ } from "../../../chunk-3R2NO47A.js";
4
+ import "../../../chunk-JZJ6GXX3.js";
5
+ import "../../../chunk-N3275IPH.js";
6
+ export {
7
+ LankaSharedStoreLocator
8
+ };
9
+ //# sourceMappingURL=LankaSharedStoreLocator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,30 @@
1
+ import { A as ALankaLocator } from '../../../ALankaLocator-BUCCz0Q5.js';
2
+
3
+ /**
4
+ * LankaSingletonLocator configuration.
5
+ */
6
+ interface ILankaSingletonLocatorConfig {
7
+ /** The module holding singleton classes — the consumer's barrel. */
8
+ singletonIndexModule?: Record<string, unknown>;
9
+ }
10
+ /**
11
+ * Resolves singletons by property name (camelCase) or class name (PascalCase),
12
+ * constructing them on first use and caching them.
13
+ *
14
+ * A class arrives either from the consumer's barrel or registered by hand — the
15
+ * latter for tests and for objects that arrive already built.
16
+ */
17
+ declare class LankaSingletonLocator extends ALankaLocator<unknown> {
18
+ private readonly singletonIndexModule?;
19
+ constructor(config?: ILankaSingletonLocatorConfig);
20
+ /**
21
+ * Creates a NEW service object, bypassing the locator's cache.
22
+ *
23
+ * For scopes: they take the class from here and set the lifetime themselves.
24
+ * The root cache is untouched — otherwise the first resolution inside a scope
25
+ * would replace the application's root object.
26
+ */
27
+ createScopedInstance(className: string, propertyName: string): unknown;
28
+ }
29
+
30
+ export { type ILankaSingletonLocatorConfig, LankaSingletonLocator };
@@ -0,0 +1,9 @@
1
+ import {
2
+ LankaSingletonLocator
3
+ } from "../../../chunk-24MUFFHF.js";
4
+ import "../../../chunk-JZJ6GXX3.js";
5
+ import "../../../chunk-N3275IPH.js";
6
+ export {
7
+ LankaSingletonLocator
8
+ };
9
+ //# sourceMappingURL=LankaSingletonLocator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -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) => {
@@ -1,6 +1,7 @@
1
- import { a as ILankaScenario, T as TLankaReplayRequest, b as ILankaEventMetadata, c as TLankaEventBusMiddleware, d as TLankaEventBusObserver, e as ILankaEventLog, I as ILankaScenarioVM } from '../ILankaScenarioVM-DpKFL3iE.js';
2
- export { f as ILankaEventBusOutcome, g as TLankaEventBusDecision } from '../ILankaScenarioVM-DpKFL3iE.js';
3
- export { I as ILankaScenarioMetadata } from '../ILankaScenarioMetadata-Dj4GCqmX.js';
1
+ import { I as ILankaScenario, T as TLankaReplayRequest, a as ILankaEventMetadata, b as TLankaEventBusMiddleware, c as TLankaEventBusObserver, d as ILankaEventLog } from '../ILankaScenario-DQd9ZfUw.js';
2
+ export { e as ILankaEventBusOutcome, f as TLankaEventBusDecision } from '../ILankaScenario-DQd9ZfUw.js';
3
+ import { I as ILankaScenarioVM } from '../ILankaScenarioVM-DKwjbIRq.js';
4
+ export { I as ILankaScenarioMetadata } from '../ILankaScenarioMetadata-BsDp0Bzm.js';
4
5
 
5
6
  /**
6
7
  * The base of a scenario — a named unit of coordination over the event bus.
@@ -223,6 +224,31 @@ declare class LankaScenarioBootstrap {
223
224
  * registry already holds.
224
225
  */
225
226
  adoptDeclaredViewModels(): void;
227
+ /**
228
+ * Whether the ViewModel being built belongs to ONE scope.
229
+ *
230
+ * A module-level ViewModel is declared once and adopted by every instance
231
+ * ever created, which is what `declaredViewModels` is for and why it is never
232
+ * drained. A SCOPED one is the opposite: it belongs to the request that built
233
+ * it and to nothing after.
234
+ *
235
+ * Declaring one would be the defect this flag exists to prevent, and it is
236
+ * worth spelling out because nothing would look wrong. The array grows by an
237
+ * entry per request for the life of the process, and request N+1 ADOPTS
238
+ * request N's ViewModel — subscribing it to N+1's scenarios, so a dispatch
239
+ * runs N's handlers against N's gateways and writes into N's store. Every
240
+ * suite stays green and the leak is one user seeing another's board.
241
+ */
242
+ private isBuildingScoped;
243
+ /**
244
+ * Runs `build` with its declarations kept OUT of the process-wide list.
245
+ *
246
+ * Called by `resolveLankaVM` and by nothing else. A narrow seam rather than a
247
+ * parameter on every factory: the nine ways to build a ViewModel would each
248
+ * have to carry a flag through to `registerViewModel`, and eight of them have
249
+ * no business knowing what a scope is.
250
+ */
251
+ buildScoped<TBuilt>(build: () => TBuilt): TBuilt;
226
252
  registerViewModel(viewModel: ILankaScenarioVM, name?: string): void;
227
253
  private attachViewModel;
228
254
  /**
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  lankaScenarioBootstrap
3
- } from "../chunk-B7EYIAW7.js";
3
+ } from "../chunk-MKKMTLOY.js";
4
4
  import {
5
5
  ALankaScenario,
6
6
  lankaEventBus
7
- } from "../chunk-O5ROO7QF.js";
8
- import "../chunk-C2HP7CRD.js";
9
- import "../chunk-D27MREPB.js";
10
- import "../chunk-BGVDPDX4.js";
7
+ } from "../chunk-NWEHOMTS.js";
8
+ import "../chunk-FII3PW2G.js";
9
+ import "../chunk-7DQUF2QR.js";
10
+ import "../chunk-XGMXT4XZ.js";
11
11
 
12
12
  // src/scenario/_factories/create-lanka-scenario/createLankaScenario.ts
13
13
  var createLankaScenario = (config) => {
@@ -1,19 +1,24 @@
1
- import { c as ILankaPlugin } from '../createLanka-NrlvN-WQ.js';
2
- import '../createLankaScope-BiFxNQgl.js';
3
- import '../LankaSharedStoreLocator-zS2kLu-S.js';
4
- import '../ALankaSharedStore-B7uepuuk.js';
5
- import 'zustand/vanilla';
6
- import '../activeRuntime-BYd2D6Lx.js';
7
- import '../ILankaScenarioVM-DpKFL3iE.js';
8
- import '../LankaScenarioLocator-CAENLhDO.js';
9
- import '../ILankaScenarioMetadata-Dj4GCqmX.js';
1
+ import { c as ILankaPlugin } from '../createLanka-DvUGu9Hl.js';
2
+ import '../createLankaScope-CVoV0EwO.js';
3
+ import '../locator/singleton/lanka-singleton-locator/LankaSingletonLocator.js';
4
+ import '../ALankaLocator-BUCCz0Q5.js';
5
+ import '../activeRuntime-ByucLPhj.js';
6
+ import '../ILankaScenario-DQd9ZfUw.js';
7
+ import '../LankaScenarioVMRegistry-DySAOaj2.js';
8
+ import '../ILankaScenarioVM-DKwjbIRq.js';
9
+ import '../ILankaScenarioMetadata-BsDp0Bzm.js';
10
+ import '../ILankaRuntimeConfig-Vl436GWK.js';
11
+ import '../lankaHttpInFlight-Bk1eIuSx.js';
12
+ import '../lankaRequestMiddleware-DAC5kCb7.js';
13
+ import '../locator/gateway/lanka-gateway-locator/LankaGatewayLocator.js';
10
14
  import '../ALankaGateway-BrVPaZN5.js';
11
15
  import '../lankaStandardValidator-BUFnysK0.js';
12
16
  import '@standard-schema/spec';
13
17
  import '../ILankaFieldError-D5931-vT.js';
14
- import '../ILankaRuntimeConfig-Vl436GWK.js';
15
- import '../lankaHttpInFlight-Bk1eIuSx.js';
16
- import '../lankaRequestMiddleware-DAC5kCb7.js';
18
+ import '../locator/scenario/lanka-scenario-locator/LankaScenarioLocator.js';
19
+ import '../locator/shared-store/lanka-shared-store-locator/LankaSharedStoreLocator.js';
20
+ import '../ALankaSharedStore-B7uepuuk.js';
21
+ import 'zustand/vanilla';
17
22
 
18
23
  /**
19
24
  * What a subscriber is handed when a named event arrives.
@@ -1,8 +1,28 @@
1
- import { StoreApi, StateCreator, UseBoundStore } from 'zustand';
2
- import { a as ILankaScenario, T as TLankaReplayRequest, I as ILankaScenarioVM } from '../ILankaScenarioVM-DpKFL3iE.js';
1
+ import { I as ILankaReadableVM } from '../ILankaReadableVM-BoPzHEPV.js';
2
+ import { I as ILankaScenarioVM } from '../ILankaScenarioVM-DKwjbIRq.js';
3
+ import { StoreApi, StateCreator } from 'zustand';
4
+ import { I as ILankaScenario, T as TLankaReplayRequest } from '../ILankaScenario-DQd9ZfUw.js';
3
5
  import { A as ALankaSharedStore } from '../ALankaSharedStore-B7uepuuk.js';
4
6
  import { StoreApi as StoreApi$1 } from 'zustand/vanilla';
5
7
 
8
+ /**
9
+ * A ViewModel that can also be written to from outside.
10
+ *
11
+ * The reading half plus the two members a host needs: the state a screen starts
12
+ * from, and a way to make server data that first state — which is what
13
+ * `hydrateLankaVM` does and the only reason writing is published at all.
14
+ *
15
+ * A view binding takes `ILankaReadableVM` instead. The narrower type is not
16
+ * politeness: a binding holding this one could write during a render, which is
17
+ * the defect no framework's scheduler survives.
18
+ */
19
+ interface ILankaVM<TState extends object> extends ILankaReadableVM<TState> {
20
+ /** The state the ViewModel was built with, before anything wrote to it. */
21
+ getInitialState(): TState;
22
+ /** Writes state. Partial by default; `replace` swaps the whole object. */
23
+ setState(partial: TState | Partial<TState> | ((state: TState) => TState | Partial<TState>), replace?: false): void;
24
+ }
25
+
6
26
  interface ILankaVMContext<TState, TGateways extends object, TServices extends object> {
7
27
  set: StoreApi<TState>["setState"];
8
28
  get: () => TState;
@@ -122,10 +142,10 @@ interface ILankaVMConfig<State extends object, Actions extends object, TGateways
122
142
  * through a getter — and warns with the ViewModel and key names. "Remember to
123
143
  * set the flag" is not a mechanism.
124
144
  */
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>>;
145
+ declare function createLankaVM<State extends object, Actions extends object>(config: ILankaVMConfig<State, Actions, Record<string, never>, Record<string, never>>): ILankaVM<State & Actions & ILankaScenarioVM>;
146
+ declare function createLankaVM<State extends object, Actions extends object, Services extends object>(config: ILankaVMConfig<State, Actions, Record<string, never>, Services>): ILankaVM<State & Actions & ILankaScenarioVM>;
147
+ declare function createLankaVM<State extends object, Actions extends object, TGateways extends object>(config: ILankaVMConfig<State, Actions, TGateways, Record<string, never>>): ILankaVM<State & Actions & ILankaScenarioVM>;
148
+ 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
149
 
130
150
  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
151
  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 +186,18 @@ type TLankaStatelessVMConfig$1<Actions extends object, TGateways extends object
166
186
  onInit?: (ctx: ILankaStatelessVMContext<Actions & ILankaScenarioVM, TGateways, Services>) => void;
167
187
  onReset?: (ctx: ILankaStatelessVMContext<Actions & ILankaScenarioVM, TGateways, Services>) => void;
168
188
  };
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>;
189
+ /**
190
+ * @deprecated since 2.0.0 - use ILankaReadableVM, which is what a stateless
191
+ * ViewModel now IS: `createStatelessLankaVM` answers a readable ViewModel rather
192
+ * than a React hook, so the word "Hook" in this name no longer describes
193
+ * anything. The alias is kept because a published name is never removed, and it
194
+ * resolves to exactly the type the factory returns.
195
+ */
196
+ type TLankaStatelessVMHook<Actions extends object> = ILankaReadableVM<Actions & ILankaScenarioVM>;
197
+ declare function createStatelessLankaVM<Actions extends object>(config: TLankaStatelessVMConfig$1<Actions, Record<string, never>, Record<string, never>>): ILankaReadableVM<Actions & ILankaScenarioVM>;
198
+ declare function createStatelessLankaVM<Actions extends object, Services extends object>(config: TLankaStatelessVMConfig$1<Actions, Record<string, never>, Services>): ILankaReadableVM<Actions & ILankaScenarioVM>;
199
+ declare function createStatelessLankaVM<Actions extends object, TGateways extends object>(config: TLankaStatelessVMConfig$1<Actions, TGateways, Record<string, never>>): ILankaReadableVM<Actions & ILankaScenarioVM>;
200
+ declare function createStatelessLankaVM<Actions extends object, TGateways extends object, Services extends object>(config: TLankaStatelessVMConfig$1<Actions, TGateways, Services>): ILankaReadableVM<Actions & ILankaScenarioVM>;
177
201
 
178
202
  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
203
  states?: never;
@@ -197,11 +221,25 @@ interface ILankaSharedStoreVMContext<TStoreState extends object, TFullState exte
197
221
  trigger: <T>(scenario: ILankaScenario<T>, data?: T) => void;
198
222
  }
199
223
 
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;
224
+ /**
225
+ * A ViewModel over a store somebody else owns.
226
+ *
227
+ * The port, plus the one member the shape genuinely adds: the SLICE, without the
228
+ * actions and scenario members composed onto it. A screen reads `getState`; code
229
+ * that has to reason about what is actually persisted — a hydration, a devtools
230
+ * panel, a second ViewModel over the same store — reads `getStoreState`.
231
+ */
232
+ interface ILankaSharedStoreVM<TStoreState extends object, TActions extends object> extends ILankaReadableVM<TStoreState & TActions & ILankaScenarioVM> {
233
+ /** The shared store's own state, without this ViewModel's actions on top. */
203
234
  getStoreState: () => TStoreState;
204
- };
235
+ }
236
+ /**
237
+ * @deprecated since 2.0.0 - use ILankaSharedStoreVM, which is the same type
238
+ * under a name that is still true: `createSharedStoreLankaVM` answers a readable
239
+ * ViewModel rather than a React hook. The alias is kept because a published name
240
+ * is never removed.
241
+ */
242
+ type TLankaSharedStoreVMHook<TStoreState extends object, TActions extends object> = ILankaSharedStoreVM<TStoreState, TActions>;
205
243
  interface ILankaSharedStoreScenarioBinding<TData, TStoreState extends object, TActions extends object, TStore extends ALankaSharedStore<TStoreState>, TGateways extends object, TServices extends object> {
206
244
  scenario: ILankaScenario<TData>;
207
245
  /**
@@ -235,10 +273,10 @@ interface ILankaSharedStoreVMConfig<TStoreState extends object, TActions extends
235
273
  * Factory for ViewModels backed by an external shared store instance.
236
274
  * Multiple ViewModels can be created on top of the same store instance.
237
275
  */
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>;
276
+ 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>;
277
+ 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>;
278
+ 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>;
279
+ 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
280
 
243
281
  /**
244
282
  * What a lazy shared-store ViewModel is, in the type as well as at runtime.
@@ -386,7 +424,7 @@ declare abstract class ALankaVM<State extends object, Actions extends object, TG
386
424
  */
387
425
  protected readonly enableAccessTrackingOptimization: boolean;
388
426
  /** Writes state. Available from `createActions` onwards, never before. */
389
- protected set: StoreApi<State & Actions & ILankaScenarioVM>["setState"];
427
+ protected set: StoreApi$1<State & Actions & ILankaScenarioVM>["setState"];
390
428
  /** Reads state. The read a tracked hook cannot see — hence the switch above. */
391
429
  protected get: () => State & Actions & ILankaScenarioVM;
392
430
  /** Fires a scenario, which every ViewModel bound to it then hears. */
@@ -413,8 +451,16 @@ declare abstract class ALankaVM<State extends object, Actions extends object, TG
413
451
  * the wrong half. Canon: `skills/parity/SKILL.md` section 3a.
414
452
  */
415
453
  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>>;
454
+ /**
455
+ * Builds the ViewModel a screen reads. One store per call.
456
+ *
457
+ * What comes back is a STORE, not a hook: `getState`, `subscribe`, `setState`,
458
+ * plus the name and the tracking flag. A screen reaches it through its
459
+ * framework's binding — `useLankaVM(todoVM)` from `@lankajs/react`,
460
+ * `@lankajs/vue` and the rest of the shelf — and a program with no framework
461
+ * at all reads `getState()` and `subscribe()` directly.
462
+ */
463
+ build(): ILankaVM<State & Actions & ILankaScenarioVM>;
418
464
  }
419
465
 
420
466
  /**
@@ -482,8 +528,13 @@ declare abstract class ALankaStatelessVM<Actions extends object, TGateways exten
482
528
  * read. Canon: `skills/parity/SKILL.md` section 3a.
483
529
  */
484
530
  protected toStyleContext(): ILankaStatelessVMContext<Actions & ILankaScenarioVM, TGateways, Services>;
485
- /** Builds the hook a screen calls. One ViewModel per call. */
486
- build(): TLankaStatelessVMHook<Actions>;
531
+ /**
532
+ * Builds the ViewModel a screen reads. One per call.
533
+ *
534
+ * What comes back answers the read half of the port and nothing more: there
535
+ * is no store to write to from outside, because there is no state to write.
536
+ */
537
+ build(): ILankaReadableVM<Actions & ILankaScenarioVM>;
487
538
  }
488
539
 
489
540
  /**
@@ -559,8 +610,68 @@ declare abstract class ALankaSharedStoreVM<StoreState extends object, Actions ex
559
610
  */
560
611
  declare const createLankaSharedStore: <TState extends object>(createInitialState: () => TState) => ALankaSharedStore<TState>;
561
612
 
613
+ /**
614
+ * Keeps a selection's IDENTITY while nothing in it moved.
615
+ *
616
+ * ```ts
617
+ * const hold = createLankaShallowHold<{ title: string; status: string }>();
618
+ *
619
+ * // in any binding on the shelf
620
+ * const view = useLankaVM(missionVM, (state) => hold({
621
+ * title: state.title,
622
+ * status: state.status,
623
+ * }));
624
+ * ```
625
+ *
626
+ * ## What it is for
627
+ *
628
+ * A selector narrows what a reader depends on, and a selector that BUILDS its
629
+ * answer — `(state) => ({ a: state.a })`, `(state) => rows.filter(…)`, the shape
630
+ * a consumer reaches for first — cannot say so. Every binding compares the new
631
+ * selection with the last one by identity, and a fresh object is never identical
632
+ * to anything, so the reader wakes for every change in the ViewModel including
633
+ * the keys the selector exists to ignore. This is the comparison that makes the
634
+ * selection mean something.
635
+ *
636
+ * A selector answering a PRIMITIVE never needed it, which is what makes the cost
637
+ * quiet: the shape that is free and the shape that repaints on everything look
638
+ * the same on the page.
639
+ *
640
+ * ## Why it is in core and not in a binding
641
+ *
642
+ * It was `useLankaShallow` in `@lankajs/react` and nowhere else, and that made it
643
+ * a CAPABILITY one member of the shelf had and four did not. An idiom is a
644
+ * spelling; this changes which notifications reach a reader, and it encodes a
645
+ * policy — one level deep, own keys, `Object.is` — that five packages inventing
646
+ * separately would answer five ways. `skills/parity/SKILL.md` 3c: a binding that
647
+ * needs more than the port gives it has found something that belongs in core, for
648
+ * everybody.
649
+ *
650
+ * `useLankaShallow` keeps working and is now React's spelling over this. It has
651
+ * to exist there and cannot exist here: a React component re-runs the hook on
652
+ * every render, so the holding has to survive a render while the SELECTOR stays
653
+ * the current one — which is a `useRef`, and a ref is not something core can
654
+ * have.
655
+ *
656
+ * ## Why it holds a value and not a selector
657
+ *
658
+ * `createLankaShallowSelector(selector)` was the other shape and it cannot serve
659
+ * React: the wrapper would be rebuilt whenever the selector's identity moved, and
660
+ * an inline arrow is a new function every render, so the holding would reset
661
+ * before it ever held anything. Taking the VALUE puts the state in the only place
662
+ * every framework can keep it, and the extra line at a call site is the price of
663
+ * one name that works in all five rather than two that each work in some.
664
+ *
665
+ * ## One level, and it says so by failing
666
+ *
667
+ * Deeper would mean walking a state of unknown size on every read, which is the
668
+ * cost a reader took a selector to avoid. A selection with a nested object wants
669
+ * a selector that picks the leaves.
670
+ */
671
+ declare const createLankaShallowHold: <TValue>() => ((next: TValue) => TValue);
672
+
562
673
  type TLankaVMStateCreator<TFullState> = StateCreator<TFullState, TLankaAnyMutators, TLankaAnyMutators>;
563
674
 
564
675
  type TLankaSharedStoreSetState<TState extends object> = (partial: TState | Partial<TState> | ((state: TState) => TState | Partial<TState>), replace?: boolean) => void;
565
676
 
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 };
677
+ 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 };