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
@@ -1,32 +1,38 @@
1
1
  import {
2
- lankaScenarioBootstrap
3
- } from "./chunk-B7EYIAW7.js";
4
- import {
5
- LankaGatewayLocator,
6
- LankaScenarioLocator,
7
2
  createLankaScope
8
- } from "./chunk-5MAQVBI2.js";
3
+ } from "./chunk-SBITVBF7.js";
4
+ import {
5
+ LankaGatewayLocator
6
+ } from "./chunk-BMF4TM2Z.js";
7
+ import {
8
+ LankaScenarioLocator
9
+ } from "./chunk-42CWYVZJ.js";
10
+ import {
11
+ lankaScenarioBootstrap
12
+ } from "./chunk-MKKMTLOY.js";
9
13
  import {
10
14
  LankaScenarioVMRegistry,
11
15
  LankaScenariosRegistry
12
- } from "./chunk-O5ROO7QF.js";
16
+ } from "./chunk-NWEHOMTS.js";
13
17
  import {
14
18
  createLankaHost
15
19
  } from "./chunk-XESL274R.js";
16
20
  import {
17
21
  createInFlightCounter
18
- } from "./chunk-UJEC7H6K.js";
22
+ } from "./chunk-BHQ2SQ7P.js";
23
+ import {
24
+ LankaSharedStoreLocator
25
+ } from "./chunk-3R2NO47A.js";
19
26
  import {
20
- LankaSharedStoreLocator,
21
27
  LankaSingletonLocator
22
- } from "./chunk-UE2C76OR.js";
28
+ } from "./chunk-24MUFFHF.js";
23
29
  import {
24
30
  lankaLogger
25
- } from "./chunk-C2HP7CRD.js";
31
+ } from "./chunk-FII3PW2G.js";
26
32
  import {
27
33
  getActiveRuntime,
28
- setActiveRuntime
29
- } from "./chunk-BGVDPDX4.js";
34
+ setActiveLankaRuntime
35
+ } from "./chunk-XGMXT4XZ.js";
30
36
 
31
37
  // src/scenario/event-bus/lanka-event-bus-instance/LankaEventBusInstance.ts
32
38
  var isThenable = (value) => typeof value?.then === "function";
@@ -538,7 +544,7 @@ function createLanka(config) {
538
544
  return bootstrapped;
539
545
  },
540
546
  activate() {
541
- setActiveRuntime(instance);
547
+ setActiveLankaRuntime(instance);
542
548
  },
543
549
  dispose() {
544
550
  teardown();
@@ -572,7 +578,7 @@ function createLanka(config) {
572
578
  locators.sharedStores.clearCache();
573
579
  scenarioState.bootstrapped = false;
574
580
  scenarioState.initialized = /* @__PURE__ */ new WeakSet();
575
- if (getActiveRuntime() === instance) setActiveRuntime(null);
581
+ if (getActiveRuntime() === instance) setActiveLankaRuntime(null);
576
582
  }
577
583
  const plugins = createLankaPluginRegistry(instance);
578
584
  instance.activate();
@@ -729,4 +735,4 @@ export {
729
735
  resetActiveLanka,
730
736
  ALankaPlugin
731
737
  };
732
- //# sourceMappingURL=chunk-UBGXDTXC.js.map
738
+ //# sourceMappingURL=chunk-SO7D5E7O.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/scenario/event-bus/lanka-event-bus-instance/LankaEventBusInstance.ts","../src/bootstrap/_internal/create-lanka-plugin-registry/createLankaPluginRegistry.ts","../src/bootstrap/_factories/create-lanka/createLanka.ts","../src/bootstrap/start-lanka/startLanka.ts","../src/bootstrap/reset-active-lanka/resetActiveLanka.ts","../src/bootstrap/_abstractions/lanka-plugin/ALankaPlugin.ts"],"sourcesContent":["import { ILankaEventMetadata } from \"../../_interfaces/ILankaEventMetadata\";\nimport { ILankaEventLog } from \"../../_interfaces/ILankaEventLog\";\nimport {\n\tTLankaEventBusDecision,\n\tTLankaEventBusMiddleware,\n} from \"../../_types/TLankaEventBusMiddleware\";\nimport { TLankaEventBusObserver } from \"../../_types/TLankaEventBusObserver\";\nimport { ILankaEventBusOutcome } from \"../../_interfaces/ILankaEventBusOutcome\";\nimport { lankaLogger } from \"../../../logger/lanka-logger/LankaLogger\";\n\n/**\n * Whether a handler's return value is something that can still reject.\n *\n * Duck-typed rather than `instanceof Promise`, because the promise a handler\n * returns need not be THIS realm's: a jsdom test, a native module and a bundled\n * polyfill each bring their own, and `instanceof` answers false for all of them.\n * An `instanceof` check here would work everywhere except the places most likely\n * to need it.\n */\nconst isThenable = (value: unknown): value is PromiseLike<unknown> =>\n\ttypeof (value as PromiseLike<unknown> | null)?.then === \"function\";\n\n/** One subscription: the callback plus everything the bus knows about it. */\ntype TSubscriptionEntry<T = unknown> = {\n\tcallback: (data: T) => void;\n\tpriority: number;\n\t/**\n\t * How many recent values this subscriber asks to be replayed on subscribe.\n\t *\n\t * A number rather than a flag: \"the whole buffer\" can be a hundred events in a\n\t * row, which is almost never what \"give me the current state\" means.\n\t */\n\treplayCount: number;\n};\n\n/** State of one registered event type. */\ntype TEventState = {\n\tmeta: ILankaEventMetadata;\n\tlogs: ILankaEventLog[];\n\tbuffer: unknown[];\n\tsubs: TSubscriptionEntry[];\n};\n\n/**\n * How many recent values to replay to a new subscriber.\n *\n * `true` is kept and means \"the last one\".\n */\nexport type TLankaReplayRequest = boolean | \"last\" | number;\n\nfunction resolveReplayCount(request: TLankaReplayRequest | undefined): number {\n\tif (request === undefined || request === false) return 0;\n\tif (request === true || request === \"last\") return 1;\n\treturn Math.max(0, Math.trunc(request));\n}\n\nfunction maxReplayDepth(subs: readonly TSubscriptionEntry[]): number {\n\tlet depth = 0;\n\tfor (const entry of subs) if (entry.replayCount > depth) depth = entry.replayCount;\n\treturn depth;\n}\n\n// -----------------------------------------------------------------------------\n// Bus implementation\n// -----------------------------------------------------------------------------\n\nexport class LankaEventBusInstance {\n\t/** Event registry and per-event state — private to each instance. */\n\tprivate registry: Map<string, TEventState> = new Map();\n\n\t/** Middleware registered on this instance. */\n\tprivate middlewares: TLankaEventBusMiddleware<unknown>[] = [];\n\n\t/**\n\t * What is watching the OUTCOME of each dispatch — see `TLankaEventBusObserver`.\n\t *\n\t * An array rather than a set for one reason: `dispatch` reads `.length` on\n\t * every event, and that check is what keeps an unobserved bus paying nothing.\n\t */\n\tprivate observers: TLankaEventBusObserver[] = [];\n\n\t/** Default maximum number of logs kept per event type. */\n\tprivate defaultMaxLogs = 100;\n\n\t/** Internal timers for replay batching (avoid multiple replays in the same tick). */\n\tprivate pendingReplayTimers: Map<string, ReturnType<typeof setTimeout>> = new Map();\n\n\t/** Whether event logging is enabled. */\n\tprivate isEnableLogs = false;\n\n\t/**\n\t * How many events this bus has logged, ever — the order records are read in.\n\t *\n\t * Incremented only while logging is on, which is off by default, so a bus\n\t * nobody is inspecting pays nothing for it.\n\t */\n\tprivate dispatchCount = 0;\n\n\t// -------------------------------------------------------------------------\n\t// Configuration\n\t// -------------------------------------------------------------------------\n\n\t/** Configures the bus, e.g. logging. Called once at application start. */\n\tpublic enableLogs(): void {\n\t\tthis.isEnableLogs = true;\n\t}\n\tpublic disableLogs(): void {\n\t\tthis.isEnableLogs = false;\n\t}\n\n\t// -------------------------------------------------------------------------\n\t// Internal\n\t// -------------------------------------------------------------------------\n\n\t/**\n\t * Ensures the event is registered, registering it if not.\n\t *\n\t * @param eventType Event type\n\t * @param usedBy Who uses it — for the inspector and for finding an owner\n\t */\n\tprivate ensureEvent(eventType: string, usedBy?: string): TEventState {\n\t\tlet state = this.registry.get(eventType);\n\t\tif (!state) {\n\t\t\tconst meta: ILankaEventMetadata = {\n\t\t\t\tdataType: \"any\",\n\t\t\t\tdescription: `Auto-registered event: ${eventType}`,\n\t\t\t\tusedBy: usedBy ? [usedBy] : [],\n\t\t\t\tpriority: 0,\n\t\t\t\tmaxLogs: this.defaultMaxLogs,\n\t\t\t};\n\t\t\tstate = {\n\t\t\t\tmeta,\n\t\t\t\tlogs: [],\n\t\t\t\tbuffer: [],\n\t\t\t\tsubs: [],\n\t\t\t};\n\t\t\tthis.registry.set(eventType, state);\n\t\t} else if (usedBy) {\n\t\t\tconst meta = state.meta;\n\t\t\tmeta.usedBy = [...new Set([...(meta.usedBy ?? []), usedBy])];\n\t\t}\n\t\treturn state;\n\t}\n\n\t// -------------------------------------------------------------------------\n\t// Public surface\n\t// -------------------------------------------------------------------------\n\n\t/**\n\t * Declares an event explicitly, together with its metadata.\n\t *\n\t * @param eventType Event type\n\t * @param metadata What is known about the event and what it is allowed\n\t */\n\tpublic registerEvent(eventType: string, metadata: ILankaEventMetadata): void {\n\t\t// MERGE, never recreate the state.\n\t\t//\n\t\t// Writing `subs: []` here means a call after anyone subscribed silently\n\t\t// drops every subscriber. Bootstrap order (register before ViewModels\n\t\t// initialise) hides it, but that is a coincidence, not an invariant: any\n\t\t// lazy event registration breaks it, and the only symptom is that nothing\n\t\t// works.\n\t\tconst existing = this.registry.get(eventType);\n\t\tconst meta: ILankaEventMetadata = {\n\t\t\tdataType: metadata.dataType ?? existing?.meta.dataType ?? \"any\",\n\t\t\tdescription:\n\t\t\t\tmetadata.description ??\n\t\t\t\texisting?.meta.description ??\n\t\t\t\t`Registered event: ${eventType}`,\n\t\t\t// `usedBy` lists everyone using the event and exists precisely to be\n\t\t\t// complete. Replacing it would erase half.\n\t\t\tusedBy: [...new Set([...(existing?.meta.usedBy ?? []), ...(metadata.usedBy ?? [])])],\n\t\t\tschema: metadata.schema ?? existing?.meta.schema,\n\t\t\tpriority: metadata.priority ?? existing?.meta.priority ?? 0,\n\t\t\tmaxLogs: metadata.maxLogs ?? existing?.meta.maxLogs ?? this.defaultMaxLogs,\n\t\t\treplay: metadata.replay ?? existing?.meta.replay,\n\t\t};\n\n\t\tif (existing) {\n\t\t\texisting.meta = meta;\n\t\t\treturn;\n\t\t}\n\n\t\tthis.registry.set(eventType, { meta, logs: [], buffer: [], subs: [] });\n\t}\n\n\t/** Every registered event with its metadata. */\n\tpublic getRegisteredEvents() {\n\t\treturn Array.from(this.registry.entries())\n\t\t\t.map(([eventType, state]) => ({\n\t\t\t\teventType,\n\t\t\t\tmetadata: state.meta,\n\t\t\t}))\n\t\t\t.sort((a, b) => a.eventType.localeCompare(b.eventType));\n\t}\n\n\t/** Metadata of one event type. */\n\tpublic getEventInfo(eventType: string): ILankaEventMetadata | null {\n\t\treturn this.registry.get(eventType)?.meta ?? null;\n\t}\n\n\t/** How many live subscriptions this event has. */\n\t/**\n\t * How many values sit in the event's buffer.\n\t *\n\t * Exists for the test: \"the buffer stays empty until someone asks for replay\"\n\t * is a claim about MEMORY, and nothing but asking can check it.\n\t */\n\tpublic getBufferedCount(eventType: string): number {\n\t\treturn this.registry.get(eventType)?.buffer.length ?? 0;\n\t}\n\n\tpublic getSubscriptions(eventType: string): number {\n\t\treturn this.registry.get(eventType)?.subs.length ?? 0;\n\t}\n\n\t/**\n\t * Subscribes a handler to an event type.\n\t *\n\t * @param eventType Event type\n\t * @param callback What to run on dispatch\n\t * @param options Subscription options:\n\t * - `priority` — execution order, higher runs earlier;\n\t * - `replay` — receive what was dispatched before subscribing;\n\t * - `usedBy` — who subscribed, for the inspector.\n\t */\n\tpublic subscribe<T>(\n\t\teventType: string,\n\t\tcallback: (data: T) => 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\tconst state = this.ensureEvent(eventType, options?.usedBy);\n\t\tconst prio = options?.priority ?? state.meta.priority ?? 0;\n\t\tconst entry: TSubscriptionEntry<unknown> = {\n\t\t\tcallback: callback as unknown as (data: unknown) => void,\n\t\t\tpriority: prio,\n\t\t\treplayCount: resolveReplayCount(options?.replay),\n\t\t};\n\n\t\tconst subs = state.subs;\n\t\tlet low = 0,\n\t\t\thigh = subs.length;\n\t\twhile (low < high) {\n\t\t\tconst mid = (low + high) >>> 1;\n\t\t\tif (subs[mid].priority < prio) high = mid;\n\t\t\telse low = mid + 1;\n\t\t}\n\t\tsubs.splice(low, 0, entry);\n\n\t\tif (options?.replay) this.scheduleBatchedReplay(eventType, state);\n\n\t\t// The returned function removes EXACTLY this record, not the first one with\n\t\t// the same callback: by callback, two subscriptions of one function are\n\t\t// indistinguishable.\n\t\treturn () => {\n\t\t\tconst at = state.subs.indexOf(entry);\n\t\t\tif (at !== -1) state.subs.splice(at, 1);\n\t\t};\n\t}\n\n\t/**\n\t * Removes a handler from an event type.\n\t *\n\t * @param eventType Event type\n\t * @param callback A previously subscribed handler\n\t */\n\tpublic unsubscribe<T>(eventType: string, callback: (data: T) => void): void {\n\t\tconst state = this.registry.get(eventType);\n\t\tif (!state) return;\n\t\tconst subs = state.subs;\n\t\tfor (let i = 0; i < subs.length; i++) {\n\t\t\tif (subs[i].callback === callback) {\n\t\t\t\tsubs.splice(i, 1);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Dispatches an event: the middleware chain first, then subscribers.\n\t *\n\t * @param eventType Event type\n\t * @param data Payload\n\t * @param usedBy Who dispatched — recorded in the metadata\n\t */\n\tpublic dispatch<T>(eventType: string, data?: T, usedBy?: string): void {\n\t\tconst state = this.ensureEvent(eventType, usedBy);\n\t\tconst { meta, subs, buffer } = state;\n\n\t\t// Payload shape check\n\t\tif (meta.schema && data !== undefined && !meta.schema(data)) {\n\t\t\tlankaLogger.printScenarioLog(`Invalid data for event \"${eventType}\":`, data);\n\t\t\tthis.report({ eventType, outcome: \"invalid\", subscribers: subs.length });\n\t\t\treturn;\n\t\t}\n\n\t\tthis.logEvent(state, eventType, data);\n\n\t\tconst deliver = (): void => {\n\t\t\t// Iterate a COPY. A subscriber may unsubscribe inside its own handler —\n\t\t\t// \"waited for the session, then unsubscribed\" is a routine pattern — and\n\t\t\t// `unsubscribe` splices this same array, so iterating the original skips\n\t\t\t// a neighbour silently.\n\t\t\t//\n\t\t\t// The deliberate side effect: subscribing DURING delivery waits for the\n\t\t\t// next event. Otherwise delivery order would depend on subscription\n\t\t\t// timing, which is undefined.\n\t\t\tfor (const entry of [...subs]) {\n\t\t\t\ttry {\n\t\t\t\t\t// A handler is typed `(data) => void`, and TypeScript assigns a\n\t\t\t\t\t// `Promise<void>` to a void return position — so `async () => { await\n\t\t\t\t\t// refetch(); }` is a handler that compiles with nothing to warn about,\n\t\t\t\t\t// and \"refetch when the stream reconnects\" is the common shape rather\n\t\t\t\t\t// than an exotic one.\n\t\t\t\t\t//\n\t\t\t\t\t// Its failure arrives a microtask after this loop has finished, where\n\t\t\t\t\t// the `catch` below cannot reach it: on node's default an unhandled\n\t\t\t\t\t// rejection ends the PROCESS, and ends it inside whatever ran next.\n\t\t\t\t\t// The promise this bus already makes — one subscriber cannot take a\n\t\t\t\t\t// dispatch down with it — has to cover that handler too, or it only\n\t\t\t\t\t// holds for the handlers that happen to be synchronous.\n\t\t\t\t\tconst settled: unknown = entry.callback(data);\n\n\t\t\t\t\tif (isThenable(settled)) {\n\t\t\t\t\t\tsettled.then(undefined, (err: unknown) => {\n\t\t\t\t\t\t\tlankaLogger.printScenarioLog(\n\t\t\t\t\t\t\t\t`Error dispatching event \"${eventType}\":`,\n\t\t\t\t\t\t\t\terr,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} catch (err) {\n\t\t\t\t\tlankaLogger.printScenarioLog(`Error dispatching event \"${eventType}\":`, err);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\t// Every middleware RETURNS a decision. A `next()`-based shape means not\n\t\t// calling it makes the event vanish silently.\n\t\t//\n\t\t// An exception is the same case as \"did not call next\": it also stops\n\t\t// delivery, so it is handled the same way and names itself in the log,\n\t\t// instead of surfacing and breaking whoever dispatched.\n\t\tfor (const middleware of [...this.middlewares]) {\n\t\t\tlet decision: TLankaEventBusDecision;\n\t\t\ttry {\n\t\t\t\tdecision = middleware(eventType, data);\n\t\t\t} catch (err) {\n\t\t\t\tdecision = { stop: err instanceof Error ? err.message : String(err) };\n\t\t\t}\n\n\t\t\tif (decision !== \"pass\") {\n\t\t\t\tthis.markStopped(state, decision.stop);\n\t\t\t\tlankaLogger.printScenarioLog(\n\t\t\t\t\t`Event \"${eventType}\" stopped by middleware:`,\n\t\t\t\t\tdecision.stop,\n\t\t\t\t);\n\t\t\t\t// The one place that knows WHICH middleware stopped it. A middleware\n\t\t\t\t// cannot learn this about a middleware after itself, which is why an\n\t\t\t\t// inspector needed an observer rather than a sixth middleware.\n\t\t\t\tthis.report({\n\t\t\t\t\teventType,\n\t\t\t\t\toutcome: \"stopped\",\n\t\t\t\t\tsubscribers: subs.length,\n\t\t\t\t\tstoppedBy: decision.stop,\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// AFTER the chain, and that ordering is the guarantee.\n\t\t//\n\t\t// The buffer used to be filled before the middlewares ran, so an event the\n\t\t// chain STOPPED still sat in it — and the next subscriber asking for replay\n\t\t// received a payload no subscriber had been allowed to see, with nothing in\n\t\t// the bus log recording that delivery. Middleware is how an application\n\t\t// gates an event (an authorisation check, a privacy filter, a feature\n\t\t// flag); a gate the framework routes around is not a gate.\n\t\t//\n\t\t// The buffer exists ONLY on demand and holds exactly what the greediest\n\t\t// subscriber asked for. Buffering every payload unconditionally holds up to\n\t\t// a hundred payloads per event type until the end of the session — in an app\n\t\t// where user data arrives over SSE, that is personal data kept in memory\n\t\t// with no consumer.\n\t\tconst depth = Math.max(resolveReplayCount(meta.replay), maxReplayDepth(subs));\n\t\tif (depth > 0) {\n\t\t\tbuffer.push(data);\n\t\t\twhile (buffer.length > depth) buffer.shift();\n\t\t} else if (buffer.length > 0) {\n\t\t\t// The last replay asker unsubscribed — nothing left to hold.\n\t\t\tbuffer.length = 0;\n\t\t}\n\n\t\tdeliver();\n\t\tthis.report({ eventType, outcome: \"delivered\", subscribers: subs.length });\n\t}\n\n\t/** Adds middleware to the shared chain. */\n\tpublic addMiddleware<T>(mw: TLankaEventBusMiddleware<T>): void {\n\t\tthis.middlewares.push(mw as unknown as TLankaEventBusMiddleware<unknown>);\n\t}\n\n\t/** Removes previously added middleware. */\n\tpublic removeMiddleware<T>(mw: TLankaEventBusMiddleware<T>): void {\n\t\tconst i = this.middlewares.indexOf(mw as unknown as TLankaEventBusMiddleware<unknown>);\n\t\tif (i !== -1) this.middlewares.splice(i, 1);\n\t}\n\n\t/**\n\t * Watches what became of each dispatch. An extension point — the sixth.\n\t *\n\t * An observer never decides: its return value is ignored, and a throw from it\n\t * is logged rather than surfaced. A diagnostic tool that could stop an event\n\t * would make \"I disabled the inspector and it started working\" a sentence\n\t * somebody says.\n\t */\n\tpublic addObserver(observer: TLankaEventBusObserver): void {\n\t\tthis.observers.push(observer);\n\t}\n\n\t/** Removes a previously added observer. */\n\tpublic removeObserver(observer: TLankaEventBusObserver): void {\n\t\tconst i = this.observers.indexOf(observer);\n\t\tif (i !== -1) this.observers.splice(i, 1);\n\t}\n\n\t/**\n\t * Log of dispatched events, oldest first, `limit` most recent kept.\n\t *\n\t * ## Why the records are sorted rather than concatenated\n\t *\n\t * They are held per event TYPE, so that each type keeps its own `maxLogs`\n\t * and a chatty event cannot push a quiet one's history out. Concatenating\n\t * those lists puts every record of one type before every record of the next,\n\t * and `slice(-limit)` then answers the tail of whichever type the registry\n\t * happened to hold last — not the most recent events at all. On a bus with\n\t * one event type nothing looked wrong; on a real one the log was a\n\t * chronology that had never been in chronological order.\n\t *\n\t * @param eventType Limit to one type\n\t * @param limit How many recent records to return\n\t */\n\tpublic getEventLogs(eventType?: string, limit = 100): ILankaEventLog[] {\n\t\tif (eventType) {\n\t\t\treturn this.registry.get(eventType)?.logs.slice(-limit) ?? [];\n\t\t}\n\t\tconst all: ILankaEventLog[] = [];\n\t\tfor (const { logs } of this.registry.values()) all.push(...logs);\n\t\t// By `sequence`, not by `timestamp`: a timestamp has millisecond\n\t\t// resolution and a burst — an SSE storm, bootstrap — dispatches many\n\t\t// events inside one, so sorting by it would leave those in the order the\n\t\t// concatenation happened to produce, which is the defect itself.\n\t\tall.sort((left, right) => (left.sequence ?? 0) - (right.sequence ?? 0));\n\t\treturn all.slice(-limit);\n\t}\n\n\t/** Removes an event together with its subscriptions, log and buffer. */\n\tpublic clearEvent(eventType: string): void {\n\t\tthis.registry.delete(eventType);\n\t\tconst t = this.pendingReplayTimers.get(eventType);\n\t\tif (t) {\n\t\t\tclearTimeout(t);\n\t\t\tthis.pendingReplayTimers.delete(eventType);\n\t\t}\n\t}\n\n\t/** Removes every event and any scheduled replays. */\n\tpublic clearAllEvents(): void {\n\t\tthis.registry.clear();\n\t\tfor (const t of this.pendingReplayTimers.values()) clearTimeout(t);\n\t\tthis.pendingReplayTimers.clear();\n\t}\n\n\t/** Full bus reset: events, middleware and observers. */\n\tpublic reset(): void {\n\t\tthis.clearAllEvents();\n\t\tthis.middlewares = [];\n\t\tthis.observers = [];\n\t\tthis.isEnableLogs = false;\n\t}\n\n\t// -------------------------------------------------------------------------\n\t// Internal helpers\n\t// -------------------------------------------------------------------------\n\n\t/**\n\t * Tells the observers what became of a dispatch.\n\t *\n\t * The empty-list check is the whole reason a bus nobody watches pays nothing\n\t * for this: `dispatch` is a hot path, and an iteration over an empty array on\n\t * every event would be a cost paid by every application for a feature almost\n\t * none of them installs. Measured in `LankaEventBusInstance.bench.ts`.\n\t *\n\t * An observer that throws is logged and the next one still runs — the same\n\t * treatment a subscriber gets, and for the same reason: a diagnostic tool must\n\t * not be able to break the application it is diagnosing.\n\t */\n\tprivate report(outcome: ILankaEventBusOutcome): void {\n\t\tif (this.observers.length === 0) return;\n\n\t\tfor (const observer of [...this.observers]) {\n\t\t\ttry {\n\t\t\t\tobserver(outcome);\n\t\t\t} catch (err) {\n\t\t\t\tlankaLogger.printScenarioLog(\n\t\t\t\t\t`Event bus observer failed for \"${outcome.eventType}\":`,\n\t\t\t\t\terr,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Marks the last log record with the reason it was stopped.\n\t *\n\t * Writes where `logEvent` just put the event: a stop is not a separate\n\t * occurrence but this one's outcome.\n\t */\n\tprivate markStopped(state: TEventState, reason: string): void {\n\t\tconst last = state.logs.at(-1);\n\t\tif (last) last.stoppedBy = reason;\n\t}\n\n\t/** Add an event log entry for debugging/auditing. */\n\tprivate logEvent(state: TEventState, eventType: string, data: unknown): void {\n\t\tif (this.isEnableLogs) {\n\t\t\tconst cap = state.meta.maxLogs ?? this.defaultMaxLogs;\n\t\t\tconst logs = state.logs;\n\t\t\tthis.dispatchCount += 1;\n\t\t\tconst log: ILankaEventLog = {\n\t\t\t\teventType,\n\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t\tdata,\n\t\t\t\tsequence: this.dispatchCount,\n\t\t\t};\n\t\t\tlog.stackTrace = new Error().stack;\n\t\t\tlogs.push(log);\n\t\t\tif (logs.length > cap) logs.shift();\n\t\t}\n\t}\n\n\t/**\n\t * Schedules replay for late subscribers that asked for it.\n\t *\n\t * Replays are batched into one tick: otherwise ten subscriptions to one event\n\t * would make ten separate passes over the same buffer.\n\t */\n\tprivate scheduleBatchedReplay(eventType: string, state: TEventState): void {\n\t\tif (this.pendingReplayTimers.has(eventType)) return;\n\n\t\tconst timer = setTimeout(() => {\n\t\t\tthis.pendingReplayTimers.delete(eventType);\n\t\t\tconst { buffer, subs } = state;\n\t\t\tif (!buffer.length) return;\n\n\t\t\tconst needReplay = subs.filter((s) => s.replayCount > 0);\n\t\t\tif (!needReplay.length) return;\n\n\t\t\tfor (const entry of needReplay) {\n\t\t\t\t// Each gets what IT asked for, not what the buffer happens to hold.\n\t\t\t\tfor (const payload of buffer.slice(-entry.replayCount)) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tentry.callback(payload);\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tlankaLogger.printScenarioLog(\n\t\t\t\t\t\t\t`Error dispatching event \"${eventType}\" (replay):`,\n\t\t\t\t\t\t\terr,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Replay is an event of subscribing, not a property of the subscriber: it\n\t\t\t// does not happen a second time.\n\t\t\tfor (const entry of needReplay) entry.replayCount = 0;\n\t\t}, 0);\n\n\t\tthis.pendingReplayTimers.set(eventType, timer);\n\t}\n}\n","import type { ILankaPlugin } from \"../../ILankaPlugin\";\nimport type { ILankaInstance } from \"../../_factories/create-lanka/createLanka\";\n\nexport interface ILankaPluginRegistry {\n\t/** Installs a plugin and returns the function that removes it. */\n\tuse: (plugin: ILankaPlugin) => () => void;\n\t/** Removes every plugin, newest first is NOT guaranteed — see `removeAll`. */\n\tremoveAll: () => void;\n}\n\n/**\n * The plugins installed on one framework instance.\n *\n * Owns three decisions that are easy to get subtly wrong and impossible to see\n * from the outside: a duplicate is refused, removal is idempotent, and removing\n * all of them iterates a COPY of the values.\n */\nexport const createLankaPluginRegistry = (instance: ILankaInstance): ILankaPluginRegistry => {\n\tconst removers = new Map<string, () => void>();\n\n\treturn {\n\t\tuse(plugin: ILankaPlugin): () => void {\n\t\t\tif (removers.has(plugin.name)) {\n\t\t\t\t// Rejected LOUDLY: two copies of a retry policy double the request\n\t\t\t\t// count, and that shows up only as backend load — much later, and to\n\t\t\t\t// somebody else.\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Plugin \"${plugin.name}\" is already registered on this lanka instance. ` +\n\t\t\t\t\t\t\"Registering twice almost always means two copies of one policy.\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst uninstall = plugin.install(instance);\n\n\t\t\tconst remove = (): void => {\n\t\t\t\t// Idempotent: a caller may hold the remover and also dispose the\n\t\t\t\t// instance, and uninstalling twice is how a plugin's own teardown ends\n\t\t\t\t// up running against a framework that is already gone.\n\t\t\t\tif (!removers.has(plugin.name)) return;\n\t\t\t\tremovers.delete(plugin.name);\n\t\t\t\tuninstall?.();\n\t\t\t};\n\n\t\t\tremovers.set(plugin.name, remove);\n\t\t\treturn remove;\n\t\t},\n\n\t\tremoveAll(): void {\n\t\t\t// A COPY: each remover deletes its own entry, and mutating the map being\n\t\t\t// iterated skips every second plugin.\n\t\t\tfor (const remove of [...removers.values()]) remove();\n\t\t\tremovers.clear();\n\t\t},\n\t};\n};\n","import { LankaEventBusInstance } from \"../../../scenario/event-bus/lanka-event-bus-instance/LankaEventBusInstance\";\nimport { createLankaPluginRegistry } from \"../../_internal/create-lanka-plugin-registry/createLankaPluginRegistry\";\nimport { LankaScenariosRegistry } from \"../../../scenario/_registries/lanka-scenarios-registry/LankaScenariosRegistry\";\nimport { LankaScenarioVMRegistry } from \"../../../scenario/_registries/lanka-scenario-vm-registry/LankaScenarioVMRegistry\";\nimport { lankaScenarioBootstrap } from \"../../../scenario/lanka-scenario-bootstrap/LankaScenarioBootstrap\";\nimport { LankaGatewayLocator } from \"../../../locator/gateway/lanka-gateway-locator/LankaGatewayLocator\";\nimport { LankaScenarioLocator } from \"../../../locator/scenario/lanka-scenario-locator/LankaScenarioLocator\";\nimport { LankaSingletonLocator } from \"../../../locator/singleton/lanka-singleton-locator/LankaSingletonLocator\";\nimport { LankaSharedStoreLocator } from \"../../../locator/shared-store/lanka-shared-store-locator/LankaSharedStoreLocator\";\nimport { createInFlightCounter } from \"../../../gateway/inflight/lankaHttpInFlight\";\nimport { lankaLogger } from \"../../../logger/lanka-logger/LankaLogger\";\nimport {\n\tgetActiveRuntime,\n\tsetActiveLankaRuntime,\n} from \"../../../_internal/active-runtime/activeRuntime\";\nimport { createLankaScope } from \"../../../locator/_factories/create-lanka-scope/createLankaScope\";\nimport type { ILankaScope } from \"../../../locator/_factories/create-lanka-scope/createLankaScope\";\nimport type { ILankaPlugin } from \"../../ILankaPlugin\";\nimport type { ILankaRuntime } from \"../../../_internal/active-runtime/activeRuntime\";\nimport type { ILankaFlags } from \"../../../config/_interfaces/ILankaFlags\";\nimport type { ILankaHost } from \"../../../config/_interfaces/ILankaHost\";\nimport type { ILankaRuntimeConfig } from \"../../../config/_interfaces/ILankaRuntimeConfig\";\nimport type { ILankaScenarioVM } from \"../../../scenario/_interfaces/ILankaScenarioVM\";\nimport type { TLankaRequestMiddleware } from \"../../../gateway/request/lankaRequestMiddleware\";\n\n/**\n * A framework instance: all framework state in one object.\n *\n * What instance-scoped state buys: two apps in one process (micro-frontends,\n * Storybook beside the app) no longer share a bus, locator caches and mock mode;\n * SSR does not reuse state between different users' requests; and test isolation\n * rests on construction rather than on a global `beforeEach` reaching into\n * internal registries.\n *\n * **Ambient facades** — `lankaEventBus.dispatch`, `lankaSingletons.foo`,\n * `getLankaFlags()`, `lankaHttpInFlight` — resolve THE ONE active instance\n * (`internal/activeRuntime.ts`). Isolation belongs to whoever holds an instance;\n * a facade cannot offer it.\n *\n * One thing stays at module level deliberately: `ALankaScenario` collects\n * constructed scenarios into a static pool. That is a REGISTRY OF DEFINITIONS,\n * not runtime state — the classes come from one `@lanka_di/Scenarios` barrel and\n * both instances must see the same list. Splitting it would be divergence.\n */\nexport interface ILankaInstance extends ILankaRuntime {\n\t/**\n\t * Adds a wrapper around every request. Returns a function that removes it.\n\t *\n\t * This is how `@lankajs/plugin-http` installs retry, the idempotency key, the\n\t * CSRF header and auth refresh.\n\t */\n\tuseRequestMiddleware(middleware: TLankaRequestMiddleware): () => void;\n\t/** Default timeout for every request of this instance. */\n\tsetRequestTimeout(timeoutMs: number | undefined): void;\n\t/** Resolves a service in the root scope — for the instance's whole lifetime. */\n\tresolve<TInstance>(propertyName: string): TInstance;\n\t/**\n\t * Creates a scope: a lifetime shorter than the application's.\n\t *\n\t * An object created in a scope goes away with it.\n\t */\n\tcreateScope(): ILankaScope;\n\t/**\n\t * Registers a plugin. Returns a function that removes it.\n\t *\n\t * The fifth and last extension point. An extension point declared before\n\t * anything plugs into it describes an imagined need while costing real\n\t * support, so this one arrived with the FIRST plugin.\n\t */\n\tuse(plugin: ILankaPlugin): () => void;\n\t/** Runs services and the scenario layer. Idempotent. */\n\tbootstrap(config?: ILankaBootstrapConfig): Promise<void>;\n\t/** Has bootstrap already run? */\n\tisBootstrapped(): boolean;\n\t/** Makes this instance the one ambient facades resolve to. */\n\tactivate(): void;\n\t/**\n\t * Removes subscriptions, clears registries and, if this instance was active,\n\t * clears the pointer. Returns the framework to its pre-bootstrap state.\n\t */\n\tdispose(): void;\n}\n\nexport interface ILankaInstanceConfig {\n\thost: ILankaHost;\n\tflags?: ILankaFlags;\n}\n\nexport interface ILankaServiceConfig {\n\tname?: string;\n\tinit: () => void | Promise<void>;\n\tsync?: boolean;\n\tpriority?: number;\n\t/**\n\t * A failure of this service does not abort bootstrap.\n\t *\n\t * Without the flag one failed service takes the WHOLE phase with it: the async\n\t * phase because of `Promise.all`, the sync phase because later tasks never run.\n\t * Wrapping the failure in a swallowing `try/catch` is worse still — the app\n\t * starts with a partially executed plan and does not know it.\n\t */\n\toptional?: boolean;\n\t/**\n\t * How long to wait for the service. Overrunning counts as a failure.\n\t *\n\t * Without a deadline a service that never settles holds bootstrap forever and\n\t * the app never paints its first screen. Failing is more honest than waiting:\n\t * an optional service is skipped, a required one names itself.\n\t */\n\ttimeoutMs?: number;\n}\n\nexport interface ILankaScenarioBootstrapConfig {\n\tsync?: boolean;\n\tpriority?: number;\n}\n\nexport interface ILankaBootstrapConfig {\n\tservices?: ILankaServiceConfig[];\n\tscenarios?: ILankaScenarioBootstrapConfig;\n}\n\n/**\n * Config merge: patch over previous, flags over flags.\n *\n * Lives HERE rather than in `config/lankaConfig` because the rule belongs to\n * whoever holds the config — the instance. Importing it from the config module\n * would pull that module into EVERY test's graph through the test kit, and any\n * test that partially mocks the config module would break the suite with \"No\n * export is defined on the mock\".\n */\nfunction mergeLankaConfig(\n\tprevious: ILankaRuntimeConfig,\n\tpatch: ILankaRuntimeConfig,\n): ILankaRuntimeConfig {\n\treturn {\n\t\t// `host` is read field by field: `setConfig({ host: undefined })` through a\n\t\t// spread would leave the instance with no host, and every request URL would\n\t\t// then carry the string \"undefined\". Flags stay a spread — there both\n\t\t// absent and undefined mean \"not set\", so nothing can be lost.\n\t\thost: patch.host ?? previous.host,\n\t\tflags: { ...previous.flags, ...patch.flags },\n\t};\n}\n\ntype TExecutionTask = {\n\tname: string;\n\tpriority: number;\n\toptional: boolean;\n\ttimeoutMs?: number;\n\texecute: () => void | Promise<void>;\n};\n\n/**\n * Creates an instance and makes it active.\n *\n * Activating on creation is the deliberate default: there is almost always one\n * app and the facades must work immediately. A second instance takes the\n * pointer — the last one created serves the facades. Callers needing another\n * order call `activate()` explicitly.\n */\nexport function createLanka(config: ILankaInstanceConfig): ILankaInstance {\n\tlet runtimeConfig: ILankaRuntimeConfig = mergeLankaConfig(\n\t\t{},\n\t\t{ host: config.host, flags: config.flags },\n\t);\n\tlet bootstrapped = false;\n\tlet bootstrapping: Promise<void> | null = null; // the plan in flight, joined by later callers\n\n\tconst eventBus = new LankaEventBusInstance();\n\tconst scenarios = new LankaScenariosRegistry();\n\tconst viewModels = new LankaScenarioVMRegistry();\n\tconst inFlight = createInFlightCounter();\n\tconst scenarioState = {\n\t\tbootstrapped: false,\n\t\tinitialized: new WeakSet<ILankaScenarioVM>(),\n\t};\n\tconst scopes = new Set<ILankaScope>();\n\tconst requestMiddleware: TLankaRequestMiddleware[] = [];\n\tlet requestTimeoutMs: number | undefined;\n\n\tconst locators = {\n\t\tgateways: new LankaGatewayLocator(),\n\t\tscenarios: new LankaScenarioLocator(),\n\t\tsingletons: new LankaSingletonLocator(),\n\t\tsharedStores: new LankaSharedStoreLocator(),\n\t};\n\n\tconst instance: ILankaInstance = {\n\t\teventBus,\n\t\tscenarios,\n\t\tviewModels,\n\t\tinFlight,\n\t\tlocators,\n\t\tscenarioState,\n\t\trequestMiddleware,\n\t\tget requestTimeoutMs() {\n\t\t\treturn requestTimeoutMs;\n\t\t},\n\t\tuseRequestMiddleware(middleware: TLankaRequestMiddleware): () => void {\n\t\t\trequestMiddleware.push(middleware);\n\t\t\treturn () => {\n\t\t\t\tconst at = requestMiddleware.indexOf(middleware);\n\t\t\t\tif (at !== -1) requestMiddleware.splice(at, 1);\n\t\t\t};\n\t\t},\n\t\tsetRequestTimeout(timeoutMs: number | undefined): void {\n\t\t\trequestTimeoutMs = timeoutMs;\n\t\t},\n\t\tresolve<TInstance>(propertyName: string): TInstance {\n\t\t\treturn locators.singletons.get(propertyName) as TInstance;\n\t\t},\n\t\tuse(plugin: ILankaPlugin): () => void {\n\t\t\treturn plugins.use(plugin);\n\t\t},\n\t\tcreateScope(): ILankaScope {\n\t\t\tconst scope = createLankaScope(locators.singletons);\n\t\t\tscopes.add(scope);\n\t\t\treturn scope;\n\t\t},\n\t\tget config() {\n\t\t\treturn runtimeConfig;\n\t\t},\n\t\tsetConfig(patch: ILankaRuntimeConfig): void {\n\t\t\truntimeConfig = mergeLankaConfig(runtimeConfig, patch);\n\t\t},\n\t\tgetFlags(): ILankaFlags {\n\t\t\treturn runtimeConfig.flags ?? {};\n\t\t},\n\t\tisBootstrapped(): boolean {\n\t\t\treturn bootstrapped;\n\t\t},\n\t\tactivate(): void {\n\t\t\tsetActiveLankaRuntime(instance);\n\t\t},\n\t\tdispose(): void {\n\t\t\tteardown();\n\t\t\trequestMiddleware.length = 0;\n\t\t\trequestTimeoutMs = undefined;\n\t\t\tbootstrapped = false;\n\t\t},\n\t\tbootstrap(bootstrapConfig: ILankaBootstrapConfig = {}): Promise<void> {\n\t\t\tif (bootstrapped) {\n\t\t\t\tlankaLogger.printBootstrapLog(\"LANKA ALREADY BOOTSTRAPPED\");\n\t\t\t\treturn Promise.resolve();\n\t\t\t}\n\t\t\t// One run, shared: the flag flips when the plan has FINISHED, so two\n\t\t\t// callers arriving before that — two routes, StrictMode mounting twice —\n\t\t\t// both read \"not bootstrapped\" and every service ran twice.\n\t\t\tbootstrapping ??= runBootstrap(instance, bootstrapConfig, () => {\n\t\t\t\tbootstrapped = true;\n\t\t\t}).finally(() => {\n\t\t\t\tbootstrapping = null;\n\t\t\t});\n\t\t\treturn bootstrapping;\n\t\t},\n\t};\n\n\t/**\n\t * Tears the instance down, in the ONE order that works.\n\t *\n\t * Scopes close FIRST: they hold objects built from this instance's classes, so\n\t * disposing without them would leave alive exactly what a scope exists to\n\t * remove. Plugins go AFTER scopes and BEFORE the registries: removing them\n\t * earlier would leave the objects being disposed with half a framework — no\n\t * middleware, but still expecting it.\n\t */\n\tfunction teardown(): void {\n\t\tfor (const scope of scopes) scope.dispose();\n\t\tscopes.clear();\n\n\t\tplugins.removeAll();\n\n\t\tviewModels.resetAll();\n\t\tscenarios.clear();\n\t\teventBus.reset();\n\n\t\tlocators.gateways.clearCache();\n\t\tlocators.scenarios.clearCache();\n\t\tlocators.singletons.clearCache();\n\t\tlocators.sharedStores.clearCache();\n\n\t\tscenarioState.bootstrapped = false;\n\t\tscenarioState.initialized = new WeakSet<ILankaScenarioVM>();\n\n\t\tif (getActiveRuntime() === instance) setActiveLankaRuntime(null);\n\t}\n\n\tconst plugins = createLankaPluginRegistry(instance);\n\n\tinstance.activate();\n\t// EVERY new instance adopts the declared ViewModels: a screen file creates\n\t// them at module level, and neither import order nor test number may decide\n\t// whether the framework knows about them.\n\tlankaScenarioBootstrap.adoptDeclaredViewModels();\n\n\treturn instance;\n}\n\nfunction createExecutionPlan(config: ILankaBootstrapConfig) {\n\tconst syncTasks: TExecutionTask[] = [];\n\tconst asyncTasks: TExecutionTask[] = [];\n\tconst postAsyncTasks: TExecutionTask[] = [];\n\n\tconfig.services?.forEach((service, index) => {\n\t\tconst task: TExecutionTask = {\n\t\t\tname: service.name || `Service-${index + 1}`,\n\t\t\tpriority: service.priority ?? 0,\n\t\t\toptional: service.optional ?? false,\n\t\t\ttimeoutMs: service.timeoutMs,\n\t\t\texecute: service.init,\n\t\t};\n\n\t\tif (service.sync) syncTasks.push(task);\n\t\telse asyncTasks.push(task);\n\t});\n\n\t// Field by field rather than a spread over defaults: a caller forwarding its\n\t// own optional config passes `{ sync: undefined }`, and a spread would put that\n\t// over `sync: true` — moving the whole scenario layer out of the sync phase\n\t// because somebody did not set a variable.\n\tconst scenarioSync = config.scenarios?.sync ?? true;\n\tconst scenarioTask: TExecutionTask = {\n\t\tname: \"LankaScenarioBootstrap\",\n\t\tpriority: config.scenarios?.priority ?? 0,\n\t\t// The scenario layer is required: without it nothing subscribed to it\n\t\t// works, and continuing silently would start an app where half the screens\n\t\t// never update.\n\t\toptional: false,\n\t\texecute: () => {\n\t\t\tlankaScenarioBootstrap.bootstrap();\n\t\t},\n\t};\n\n\tif (scenarioSync) syncTasks.push(scenarioTask);\n\telse postAsyncTasks.push(scenarioTask);\n\n\tsyncTasks.sort((a, b) => b.priority - a.priority);\n\n\treturn { syncTasks, asyncTasks, postAsyncTasks };\n}\n\n/**\n * One bootstrap, start to finish: the three phases in the one order that works,\n * then `markDone` — which the instance uses to flip its flag, and only then.\n *\n * Outside `createLanka` because it closes over nothing the instance holds: the\n * flag it must flip arrives as a callback, and everything else it needs it is\n * handed. That keeps the factory readable as the object it builds.\n */\nasync function runBootstrap(\n\tinstance: ILankaInstance,\n\tconfig: ILankaBootstrapConfig,\n\tmarkDone: () => void,\n): Promise<void> {\n\tinstance.activate();\n\tlankaLogger.printBootstrapLog(\"LANKA BOOTSTRAP START\");\n\n\tconst plan = createExecutionPlan(config);\n\tawait runSequential(plan.syncTasks, \"SYNC TASKS\");\n\tawait runParallel(plan.asyncTasks, \"ASYNC TASKS\");\n\tawait runSequential(plan.postAsyncTasks, \"POST-ASYNC TASKS (lankaScenarios)\");\n\n\tmarkDone();\n\tlankaLogger.printBootstrapLog(\"LANKA BOOTSTRAP FINISH\");\n}\n\n/**\n * Runs a task under its deadline.\n *\n * A race against a timer rather than an `AbortSignal`: a service is an arbitrary\n * application function and cannot be cancelled. The deadline bounds the WAIT,\n * not the work — hung work continues in the background, bootstrap stops waiting.\n */\nasync function runWithDeadline(task: TExecutionTask): Promise<void> {\n\tif (task.timeoutMs === undefined) {\n\t\tawait task.execute();\n\t\treturn;\n\t}\n\n\tlet timer: ReturnType<typeof setTimeout> | undefined;\n\ttry {\n\t\tawait Promise.race([\n\t\t\tPromise.resolve(task.execute()),\n\t\t\tnew Promise<never>((_resolve, reject) => {\n\t\t\t\ttimer = setTimeout(\n\t\t\t\t\t() =>\n\t\t\t\t\t\treject(\n\t\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t\t`Service \"${task.name}\" did not finish within ${String(task.timeoutMs)}ms`,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t\ttask.timeoutMs,\n\t\t\t\t);\n\t\t\t}),\n\t\t]);\n\t} finally {\n\t\tif (timer !== undefined) clearTimeout(timer);\n\t}\n}\n\n/**\n * One task's failure: swallow and log, or abort the plan.\n *\n * The TASK's flag decides, not a blanket tolerance in the runner — otherwise\n * `optional` would mean nothing.\n */\nfunction handleTaskFailure(task: TExecutionTask, phaseName: string, error: unknown): void {\n\tlankaLogger.printBootstrapLog(`[${phaseName}] ERROR IN ${task.name}`, formatError(error));\n\tif (!task.optional) throw error;\n\tlankaLogger.printBootstrapLog(`[${phaseName}] SKIPPED (optional): ${task.name}`);\n}\n\nasync function runSequential(tasks: TExecutionTask[], phaseName: string): Promise<void> {\n\tif (tasks.length === 0) return;\n\n\tfor (const task of tasks) {\n\t\ttry {\n\t\t\tlankaLogger.printBootstrapLog(\n\t\t\t\t`[${phaseName}] EXECUTING: ${task.name} (Priority: ${String(task.priority)})`,\n\t\t\t);\n\t\t\tawait runWithDeadline(task);\n\t\t} catch (error) {\n\t\t\thandleTaskFailure(task, phaseName, error);\n\t\t}\n\t}\n}\n\nasync function runParallel(tasks: TExecutionTask[], phaseName: string): Promise<void> {\n\tif (tasks.length === 0) return;\n\n\tlankaLogger.printBootstrapLog(\n\t\t`[${phaseName}] EXECUTING ${String(tasks.length)} TASKS IN PARALLEL`,\n\t);\n\n\t// `allSettled`, not `all`: `all` rejects on the first failure, so an optional\n\t// service would take down required ones that were still running. Outcomes are\n\t// examined after everything has finished.\n\tconst outcomes = await Promise.allSettled(\n\t\ttasks.map(async (task) => {\n\t\t\tlankaLogger.printBootstrapLog(`[${phaseName}] EXECUTING: ${task.name}`);\n\t\t\tawait runWithDeadline(task);\n\t\t}),\n\t);\n\n\tfor (const [index, outcome] of outcomes.entries()) {\n\t\tif (outcome.status === \"rejected\") {\n\t\t\thandleTaskFailure(tasks[index], phaseName, outcome.reason);\n\t\t}\n\t}\n}\n\nfunction formatError(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n","import { createLanka } from \"../_factories/create-lanka/createLanka\";\nimport { createLankaHost } from \"../../config/_factories/create-lanka-host/createLankaHost\";\nimport type { ILankaHost } from \"../../config/_interfaces/ILankaHost\";\nimport type { ILankaInstance } from \"../_factories/create-lanka/createLanka\";\nimport type { TLankaStartConfig } from \"../_types/TLankaStartConfig\";\n\n/** The host as given, or one built from the base URL. */\nconst hostOf = (config: TLankaStartConfig): ILankaHost =>\n\tconfig.host ?? createLankaHost({ apiBaseUrl: config.apiBaseUrl, ...config.messages });\n\n/**\n * A started framework, in one call.\n *\n * ```ts\n * const lanka = await startLanka({ apiBaseUrl: \"https://api.example.com\" });\n * const sameOrigin = await startLanka(); // nothing to configure yet\n * ```\n *\n * ## What it saves, and what it does not hide\n *\n * `createLanka` already activates the instance it returns, and `bootstrap` already\n * brings up the scenario layer — so an application's whole start-up was two calls\n * and a `for` loop over its plugins. This is those, in the order that works, and\n * nothing else: what comes back is the same `ILankaInstance`, with every method\n * it always had.\n *\n * The order matters and is the reason this exists rather than a paragraph in a\n * guide. Plugins install BEFORE bootstrap, because a plugin that adds a\n * bootstrap service after the plan is built adds it to nothing; and bootstrap is\n * awaited, because a screen rendered against a half-started framework fails in\n * the layer it reaches first rather than where the mistake was.\n *\n * An application that needs something between those steps — registering a\n * singleton whose construction reads a service's result, say — writes the two\n * calls out and keeps this one for the next project.\n */\nexport const startLanka = async (config: TLankaStartConfig = {}): Promise<ILankaInstance> => {\n\tconst lanka = createLanka({ host: hostOf(config), flags: config.flags });\n\n\tfor (const plugin of config.plugins ?? []) lanka.use(plugin);\n\n\tawait lanka.bootstrap({ services: config.services, scenarios: config.scenarios });\n\n\treturn lanka;\n};\n","import { getActiveRuntime } from \"../../_internal/active-runtime/activeRuntime\";\nimport type { ILankaScenarioVM } from \"../../scenario/_interfaces/ILankaScenarioVM\";\n\n/**\n * Resets the active instance, if there is one.\n *\n * What the test kit needs between cases. Silent when there is no instance:\n * \"reset nothing\" is not an error, and the setup file runs before EVERY test,\n * including those that never bootstrap the framework.\n */\nexport function resetActiveLanka(): void {\n\tconst active = getActiveRuntime();\n\tif (!active) return;\n\n\tactive.viewModels.resetAll();\n\tactive.scenarios.clear();\n\tactive.eventBus.clearAllEvents();\n\tactive.scenarioState.bootstrapped = false;\n\tactive.scenarioState.initialized = new WeakSet<ILankaScenarioVM>();\n}\n","import type { ILankaInstance } from \"../../_factories/create-lanka/createLanka\";\nimport type { ILankaPlugin } from \"../../ILankaPlugin\";\n\n/**\n * A plugin, written as a class.\n *\n * The functional style is a function returning `{ name, install }`, and it is\n * what the framework's own five plugins use — a plugin is a value handed to\n * `use()`, and the ecosystem writes those as `react()`, `pinia()`,\n * `tsconfigPaths()`.\n *\n * This is the same contract for an application that keeps its plugins as\n * classes: `name` is a field, `install` is a method, and `uninstall` is the\n * teardown the framework calls on removal and on dispose. Nothing above can\n * tell which style wrote it — `use()` sees `ILankaPlugin` either way.\n */\nexport abstract class ALankaPlugin implements ILankaPlugin {\n\tpublic abstract readonly name: string;\n\n\t/** Everything this plugin puts in place. Return nothing if there is nothing to undo. */\n\tprotected abstract onInstall(lanka: ILankaInstance): void;\n\n\t/**\n\t * Removes what `onInstall` put in place.\n\t *\n\t * A default that does nothing rather than an abstract member: an abstract one\n\t * would break every existing subclass the day it was added, and most plugins\n\t * genuinely have nothing to undo.\n\t */\n\tprotected onUninstall(): void {\n\t\t/* Nothing to undo unless a subclass says otherwise. */\n\t}\n\n\tpublic install(lanka: ILankaInstance): () => void {\n\t\tthis.onInstall(lanka);\n\n\t\treturn () => {\n\t\t\tthis.onUninstall();\n\t\t};\n\t}\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,17 @@
1
+ // src/viewmodel/_internal/lanka-blind-spot-registry/lankaBlindSpotRegistry.ts
2
+ var traps = /* @__PURE__ */ new WeakMap();
3
+ var lankaBlindSpotRegistry = {
4
+ /** Remembers the trap built for one ViewModel. Disarmed traps are not kept. */
5
+ remember(viewModel, trap) {
6
+ if (trap.isArmed) traps.set(viewModel, trap);
7
+ },
8
+ /** The trap for this ViewModel, if it has one. */
9
+ of(viewModel) {
10
+ return traps.get(viewModel);
11
+ }
12
+ };
13
+
14
+ export {
15
+ lankaBlindSpotRegistry
16
+ };
17
+ //# sourceMappingURL=chunk-UDP6IXDS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/viewmodel/_internal/lanka-blind-spot-registry/lankaBlindSpotRegistry.ts"],"sourcesContent":["import type { ILankaBlindSpotTrap } from \"../create-lanka-blind-spot-trap/createLankaBlindSpotTrap\";\n\n/**\n * A ViewModel → its blind-spot trap, for whoever is doing the reading.\n *\n * ## Why the trap is not on the port\n *\n * The blind spot is a DEVELOPMENT diagnostic of this framework: a key the screen\n * reaches only through a derived getter changes, no re-render follows, and the\n * warning names the ViewModel and the key. Whoever can see that a render was\n * skipped is the binding — so the binding has to be able to reach the trap.\n *\n * Putting it on `ILankaReadableVM` would have been the short way and is the\n * wrong one: the port is what every binding implements against and what a\n * third-party author reads as the contract. A member that is empty in production\n * and framework-internal in development is not part of a contract; it is core\n * talking to itself past the interface.\n *\n * So the lookup is here, exported through `lanka/extend` by way of\n * `createLankaAccessTracker`, and a binding never names it. A ViewModel with no\n * trap — production, or a shape that has no blind spot to report — simply is not\n * in the map, and the tracker reports nothing.\n *\n * ## A WeakMap and not a property\n *\n * A ViewModel is a module-level object an application creates and never\n * disposes, and the trap must not outlive it — which a `Map` keyed by name would\n * guarantee it did. It is also not a property because the object a screen holds\n * is the store, and the store's members are a surface somebody's devtools walks.\n */\nconst traps = new WeakMap<object, ILankaBlindSpotTrap>();\n\nexport const lankaBlindSpotRegistry = {\n\t/** Remembers the trap built for one ViewModel. Disarmed traps are not kept. */\n\tremember(viewModel: object, trap: ILankaBlindSpotTrap): void {\n\t\tif (trap.isArmed) traps.set(viewModel, trap);\n\t},\n\n\t/** The trap for this ViewModel, if it has one. */\n\tof(viewModel: object): ILankaBlindSpotTrap | undefined {\n\t\treturn traps.get(viewModel);\n\t},\n};\n"],"mappings":";AA8BA,IAAM,QAAQ,oBAAI,QAAqC;AAEhD,IAAM,yBAAyB;AAAA;AAAA,EAErC,SAAS,WAAmB,MAAiC;AAC5D,QAAI,KAAK,QAAS,OAAM,IAAI,WAAW,IAAI;AAAA,EAC5C;AAAA;AAAA,EAGA,GAAG,WAAoD;AACtD,WAAO,MAAM,IAAI,SAAS;AAAA,EAC3B;AACD;","names":[]}
@@ -1,15 +1,28 @@
1
1
  // src/_internal/active-runtime/activeRuntime.ts
2
2
  var active = null;
3
3
  var resolveRuntime = null;
4
- function setActiveRuntime(runtime) {
4
+ var resolveScope = null;
5
+ function setActiveLankaRuntime(runtime) {
5
6
  active = runtime;
6
7
  }
7
8
  function setLankaRuntimeResolver(resolver) {
8
9
  resolveRuntime = resolver;
9
10
  }
11
+ function getLankaProcessRuntime() {
12
+ return active;
13
+ }
10
14
  function getActiveRuntime() {
11
15
  return resolveRuntime ? resolveRuntime() : active;
12
16
  }
17
+ function setLankaScopeResolver(resolver) {
18
+ resolveScope = resolver;
19
+ }
20
+ function hasLankaScopeResolver() {
21
+ return resolveScope !== null;
22
+ }
23
+ function getActiveLankaScope() {
24
+ return resolveScope ? resolveScope() : null;
25
+ }
13
26
  function requireActiveRuntime() {
14
27
  const runtime = resolveRuntime ? resolveRuntime() : active;
15
28
  if (!runtime) {
@@ -21,9 +34,13 @@ function requireActiveRuntime() {
21
34
  }
22
35
 
23
36
  export {
24
- setActiveRuntime,
37
+ setActiveLankaRuntime,
25
38
  setLankaRuntimeResolver,
39
+ getLankaProcessRuntime,
26
40
  getActiveRuntime,
41
+ setLankaScopeResolver,
42
+ hasLankaScopeResolver,
43
+ getActiveLankaScope,
27
44
  requireActiveRuntime
28
45
  };
29
- //# sourceMappingURL=chunk-BGVDPDX4.js.map
46
+ //# sourceMappingURL=chunk-XGMXT4XZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/_internal/active-runtime/activeRuntime.ts"],"sourcesContent":["import type { LankaEventBusInstance } from \"../../scenario/event-bus/lanka-event-bus-instance/LankaEventBusInstance\";\nimport type { LankaScenariosRegistry } from \"../../scenario/_registries/lanka-scenarios-registry/LankaScenariosRegistry\";\nimport type { LankaScenarioVMRegistry } from \"../../scenario/_registries/lanka-scenario-vm-registry/LankaScenarioVMRegistry\";\nimport type { ILankaRuntimeConfig } from \"../../config/_interfaces/ILankaRuntimeConfig\";\nimport type { ILankaInFlightCounter } from \"../../gateway/inflight/lankaHttpInFlight\";\nimport type { ILankaScenarioVM } from \"../../scenario/_interfaces/ILankaScenarioVM\";\nimport type { TLankaRequestMiddleware } from \"../../gateway/request/lankaRequestMiddleware\";\nimport type { LankaGatewayLocator } from \"../../locator/gateway/lanka-gateway-locator/LankaGatewayLocator\";\nimport type { LankaScenarioLocator } from \"../../locator/scenario/lanka-scenario-locator/LankaScenarioLocator\";\nimport type { LankaSingletonLocator } from \"../../locator/singleton/lanka-singleton-locator/LankaSingletonLocator\";\nimport type { LankaSharedStoreLocator } from \"../../locator/shared-store/lanka-shared-store-locator/LankaSharedStoreLocator\";\n\n/**\n * The pointer to the framework instance that ambient facades resolve to.\n *\n * ## Why this module is separate and imports no value\n *\n * Framework state belongs to an instance (`createLanka`), but the callers of\n * `lankaEventBus.dispatch`, `getLankaFlags()`, `lankaSingletons.foo`, `lankaHttpInFlight` —\n * the ambient facades cannot hold one — a user-extended `ALankaScenario`, the\n * static `LankaScenarioBootstrap` — so they ask which instance is active.\n *\n * The module is dependency-free DELIBERATELY: every import here is `import type`\n * and disappears at compile time. Otherwise there would be a cycle\n * `createLanka → locator → gateway → config → createLanka`, and module\n * evaluation order would start deciding what ends up `undefined`.\n *\n * This is still a global pointer. Real isolation belongs to whoever holds an\n * instance: their own bus, registries and counter. The facades serve ONE active\n * instance — exactly what an application with one needs.\n */\nexport interface ILankaRuntime {\n\treadonly eventBus: LankaEventBusInstance;\n\treadonly scenarios: LankaScenariosRegistry;\n\treadonly viewModels: LankaScenarioVMRegistry;\n\treadonly inFlight: ILankaInFlightCounter;\n\t/**\n\t * Request wrappers, in registration order: the first wraps them all.\n\t *\n\t * An array, not a set: order carries meaning — retry must sit outside request\n\t * signing, or the second attempt goes out unsigned.\n\t */\n\treadonly requestMiddleware: readonly TLankaRequestMiddleware[];\n\t/** Default response deadline. `undefined` means no limit. */\n\treadonly requestTimeoutMs: number | undefined;\n\treadonly locators: {\n\t\treadonly gateways: LankaGatewayLocator;\n\t\treadonly scenarios: LankaScenarioLocator;\n\t\treadonly singletons: LankaSingletonLocator;\n\t\treadonly sharedStores: LankaSharedStoreLocator;\n\t};\n\treadonly config: ILankaRuntimeConfig;\n\t/**\n\t * Bootstrap state of the scenario layer.\n\t *\n\t * A mutable object rather than contract fields: `LankaScenarioBootstrap` is an\n\t * ambient facade and must write here without holding an instance.\n\t */\n\treadonly scenarioState: {\n\t\tbootstrapped: boolean;\n\t\tinitialized: WeakSet<ILankaScenarioVM>;\n\t};\n\tsetConfig(patch: ILankaRuntimeConfig): void;\n\tgetFlags(): NonNullable<ILankaRuntimeConfig[\"flags\"]>;\n}\n\n/**\n * How \"which instance is active\" is answered.\n *\n * A strategy, because the answer depends on where the code runs. In a browser\n * there is one instance per document and a module-level pointer IS the answer. In\n * a server process there is one instance per REQUEST, and a module-level pointer\n * is the bug: the last request to start would answer for all of them.\n */\nexport type TLankaRuntimeResolver = () => ILankaRuntime | null;\n\n/**\n * How \"which SCOPE is this\" is answered, which is a different question.\n *\n * `TLankaRuntimeResolver` answers which framework INSTANCE serves a call, and on\n * a server that is one per request. This answers which unit of work the call\n * belongs to, and the two are not interchangeable: `runInLankaServerScope`\n * creates its instance INSIDE the scope, and `createLanka` activates every\n * instance it builds — so the process pointer and the scope's runtime are the\n * same object during a request, and nothing downstream can tell \"inside a\n * scope\" from \"after one ended\".\n *\n * That distinction is what a per-scope lifetime needs. Without it a call made\n * outside every request resolves against the LAST request's runtime and is\n * handed the last stranger's state, which is the failure a scope exists to\n * abolish.\n *\n * Core ships no resolver here either, and knows only that the question exists.\n */\nexport type TLankaScopeResolver = () => object | null;\n\nlet active: ILankaRuntime | null = null;\nlet resolveRuntime: TLankaRuntimeResolver | null = null;\nlet resolveScope: TLankaScopeResolver | null = null;\n\nexport function setActiveLankaRuntime(runtime: ILankaRuntime | null): void {\n\tactive = runtime;\n}\n\n/**\n * Replaces the strategy, or restores the default one with `null`.\n *\n * The installed resolver is the WHOLE answer — the module-level pointer is not\n * consulted behind it. That is deliberate: a fallback would turn \"this ran\n * outside a request\" from a loud error into one request quietly reading another\n * request's instance, which is the failure this seam exists to make impossible.\n *\n * Core ships no resolver and knows of none. What installs one is a package that\n * knows the shape of a request; core knows only that the question has more than\n * one answer.\n */\nexport function setLankaRuntimeResolver(resolver: TLankaRuntimeResolver | null): void {\n\tresolveRuntime = resolver;\n}\n\n/**\n * The PROCESS's own instance, read without asking the strategy.\n *\n * `getActiveRuntime` consults the installed resolver and is the answer for\n * almost everything. This is the one question it cannot answer: what a call\n * would have resolved to if nobody had installed a resolver at all.\n *\n * It exists for a resolver that wants to DEFER. A server's resolver answers from\n * its request scope, and a process that also holds an ambient instance — a\n * worker with a cache, a dev server between reloads, a suite between cases —\n * has a right answer outside every scope that the resolver cannot see. Without\n * this, the first request in such a process makes every later ambient call fail\n * for the life of it.\n *\n * Not a fallback inside `getActiveRuntime`, deliberately: a resolver that wants\n * to defer says so, and one that wants a call outside its scope to fail loudly\n * goes on failing loudly. The choice belongs to whoever knows what a scope is.\n */\nexport function getLankaProcessRuntime(): ILankaRuntime | null {\n\treturn active;\n}\n\nexport function getActiveRuntime(): ILankaRuntime | null {\n\treturn resolveRuntime ? resolveRuntime() : active;\n}\n\n/**\n * Installs the strategy that says which unit of work a call belongs to.\n *\n * Installed by whoever knows what a scope IS — `@lankajs/host` wraps a request\n * in `AsyncLocalStorage` and answers from its store. A browser installs none,\n * and that is the right answer there: a tab is one scope for its whole life.\n */\nexport function setLankaScopeResolver(resolver: TLankaScopeResolver | null): void {\n\tresolveScope = resolver;\n}\n\n/** Whether anything at all knows how to answer \"which scope\". */\nexport function hasLankaScopeResolver(): boolean {\n\treturn resolveScope !== null;\n}\n\n/**\n * The current unit of work, or `null`.\n *\n * `null` means two different things and the caller has to tell them apart with\n * `hasLankaScopeResolver`: with no resolver installed there are no scopes and a\n * process-wide lifetime is correct; with one installed it means this call ran\n * OUTSIDE every scope, which on a server is a mistake worth failing on.\n */\nexport function getActiveLankaScope(): object | null {\n\treturn resolveScope ? resolveScope() : null;\n}\n\n/**\n * The active instance, or a loud failure.\n *\n * No fallback, deliberately, for the same reason `getLankaHost` has none: an\n * instance created silently on the fly would mean subscriptions went to one bus\n * and events to another, and the divergence would surface three layers away.\n */\nexport function requireActiveRuntime(): ILankaRuntime {\n\t// The strategy is read here rather than through `getActiveRuntime()`: this is\n\t// the hottest path in the framework — every ambient facade, every request,\n\t// every dispatch — and a call that only forwards is a call that shows up in\n\t// `perf/`.\n\tconst runtime = resolveRuntime ? resolveRuntime() : active;\n\n\tif (!runtime) {\n\t\tthrow new Error(\n\t\t\tresolveRuntime\n\t\t\t\t? \"lanka has no instance for this call. A runtime resolver is installed and \" +\n\t\t\t\t\t\t\"answered with none, which on a server means the code ran outside a \" +\n\t\t\t\t\t\t\"request scope — start one, or do this work inside it.\"\n\t\t\t\t: \"lanka used before an instance existed. Call createLanka({ host }) and \" +\n\t\t\t\t\t\t\"activate it.\",\n\t\t);\n\t}\n\n\treturn runtime;\n}\n"],"mappings":";AAgGA,IAAI,SAA+B;AACnC,IAAI,iBAA+C;AACnD,IAAI,eAA2C;AAExC,SAAS,sBAAsB,SAAqC;AAC1E,WAAS;AACV;AAcO,SAAS,wBAAwB,UAA8C;AACrF,mBAAiB;AAClB;AAoBO,SAAS,yBAA+C;AAC9D,SAAO;AACR;AAEO,SAAS,mBAAyC;AACxD,SAAO,iBAAiB,eAAe,IAAI;AAC5C;AASO,SAAS,sBAAsB,UAA4C;AACjF,iBAAe;AAChB;AAGO,SAAS,wBAAiC;AAChD,SAAO,iBAAiB;AACzB;AAUO,SAAS,sBAAqC;AACpD,SAAO,eAAe,aAAa,IAAI;AACxC;AASO,SAAS,uBAAsC;AAKrD,QAAM,UAAU,iBAAiB,eAAe,IAAI;AAEpD,MAAI,CAAC,SAAS;AACb,UAAM,IAAI;AAAA,MACT,iBACG,2MAGA;AAAA,IAEJ;AAAA,EACD;AAEA,SAAO;AACR;","names":[]}
@@ -3,11 +3,11 @@ import {
3
3
  } from "../chunk-XESL274R.js";
4
4
  import {
5
5
  getLankaHost
6
- } from "../chunk-RKYKK6MN.js";
6
+ } from "../chunk-RUMUFHSL.js";
7
7
  import {
8
8
  getLankaFlags
9
- } from "../chunk-D27MREPB.js";
10
- import "../chunk-BGVDPDX4.js";
9
+ } from "../chunk-7DQUF2QR.js";
10
+ import "../chunk-XGMXT4XZ.js";
11
11
  export {
12
12
  createLankaHost,
13
13
  getLankaFlags,
@@ -1,5 +1,5 @@
1
- import { I as ILankaScope } from './createLankaScope-BiFxNQgl.js';
2
- import { I as ILankaRuntime } from './activeRuntime-BYd2D6Lx.js';
1
+ import { I as ILankaScope } from './createLankaScope-CVoV0EwO.js';
2
+ import { I as ILankaRuntime } from './activeRuntime-ByucLPhj.js';
3
3
  import { a as ILankaHost, I as ILankaFlags } from './ILankaRuntimeConfig-Vl436GWK.js';
4
4
  import { T as TLankaRequestMiddleware } from './lankaRequestMiddleware-DAC5kCb7.js';
5
5
 
@@ -1,4 +1,4 @@
1
- import { b as LankaSingletonLocator } from './LankaSharedStoreLocator-zS2kLu-S.js';
1
+ import { LankaSingletonLocator } from './locator/singleton/lanka-singleton-locator/LankaSingletonLocator.js';
2
2
 
3
3
  /**
4
4
  * A service lifetime other than "as long as the application lives".
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  createLankaApiError,
3
3
  handleLankaApiError
4
- } from "../chunk-NDCJBO47.js";
4
+ } from "../chunk-O5EUTNR6.js";
5
5
  import "../chunk-J5LA3Q6D.js";
6
6
  import {
7
7
  LankaError
8
8
  } from "../chunk-G32H73QY.js";
9
- import "../chunk-RKYKK6MN.js";
10
- import "../chunk-BGVDPDX4.js";
9
+ import "../chunk-RUMUFHSL.js";
10
+ import "../chunk-XGMXT4XZ.js";
11
11
 
12
12
  // src/errors/read-lanka-field-errors/readLankaFieldErrors.ts
13
13
  var NONE = Object.freeze([]);
@@ -7,26 +7,26 @@ import {
7
7
  } from "../chunk-YR4MZXMU.js";
8
8
  import {
9
9
  lankaHttpInFlight
10
- } from "../chunk-UJEC7H6K.js";
10
+ } from "../chunk-BHQ2SQ7P.js";
11
11
  import {
12
12
  handleLankaApiError
13
- } from "../chunk-NDCJBO47.js";
13
+ } from "../chunk-O5EUTNR6.js";
14
14
  import "../chunk-J5LA3Q6D.js";
15
15
  import {
16
16
  LankaError
17
17
  } from "../chunk-G32H73QY.js";
18
18
  import {
19
19
  getLankaHost
20
- } from "../chunk-RKYKK6MN.js";
20
+ } from "../chunk-RUMUFHSL.js";
21
21
  import {
22
22
  lankaLogger
23
- } from "../chunk-C2HP7CRD.js";
23
+ } from "../chunk-FII3PW2G.js";
24
24
  import {
25
25
  getLankaFlags
26
- } from "../chunk-D27MREPB.js";
26
+ } from "../chunk-7DQUF2QR.js";
27
27
  import {
28
28
  getActiveRuntime
29
- } from "../chunk-BGVDPDX4.js";
29
+ } from "../chunk-XGMXT4XZ.js";
30
30
 
31
31
  // src/gateway/request/_abstractions/lanka-request/ALankaRequest.ts
32
32
  function classifyTransportError(error, timedOut) {
package/dist/index.d.ts CHANGED
@@ -1,21 +1,26 @@
1
- export { I as ILankaBootstrapConfig, a as ILankaInstance, b as ILankaInstanceConfig, c as ILankaPlugin, d as ILankaScenarioBootstrapConfig, e as ILankaServiceConfig, f as createLanka } from './createLanka-NrlvN-WQ.js';
1
+ export { I as ILankaBootstrapConfig, a as ILankaInstance, b as ILankaInstanceConfig, c as ILankaPlugin, d as ILankaScenarioBootstrapConfig, e as ILankaServiceConfig, f as createLanka } from './createLanka-DvUGu9Hl.js';
2
2
  export { ALankaPlugin, ILankaStartOptions, TLankaStartConfig, resetActiveLanka, startLanka } from './bootstrap/index.js';
3
3
  export { ILankaRoleFactory, ILankaRoleOpening, TLankaRoleOpener, defineLankaRole } from './role/index.js';
4
4
  export { ILankaHostConfig, createLankaHost, getLankaFlags, getLankaHost } from './config/index.js';
5
5
  export { I as ILankaFlags, a as ILankaHost, b as ILankaRuntimeConfig } from './ILankaRuntimeConfig-Vl436GWK.js';
6
- export { I as ILankaLocatorConfig } from './LankaSharedStoreLocator-zS2kLu-S.js';
6
+ export { I as ILankaLocatorConfig } from './ALankaLocator-BUCCz0Q5.js';
7
7
  export { lankaLogger } from './logger/index.js';
8
8
  export { I as ILankaErrorInit, L as LankaError, T as TLankaErrorKind } from './LankaError-D6RWNyLM.js';
9
- import './createLankaScope-BiFxNQgl.js';
10
- import './activeRuntime-BYd2D6Lx.js';
11
- import './ILankaScenarioVM-DpKFL3iE.js';
12
- import './LankaScenarioLocator-CAENLhDO.js';
13
- import './ILankaScenarioMetadata-Dj4GCqmX.js';
9
+ import './createLankaScope-CVoV0EwO.js';
10
+ import './locator/singleton/lanka-singleton-locator/LankaSingletonLocator.js';
11
+ import './activeRuntime-ByucLPhj.js';
12
+ import './ILankaScenario-DQd9ZfUw.js';
13
+ import './LankaScenarioVMRegistry-DySAOaj2.js';
14
+ import './ILankaScenarioVM-DKwjbIRq.js';
15
+ import './ILankaScenarioMetadata-BsDp0Bzm.js';
16
+ import './lankaHttpInFlight-Bk1eIuSx.js';
17
+ import './lankaRequestMiddleware-DAC5kCb7.js';
18
+ import './locator/gateway/lanka-gateway-locator/LankaGatewayLocator.js';
14
19
  import './ALankaGateway-BrVPaZN5.js';
15
20
  import './lankaStandardValidator-BUFnysK0.js';
16
21
  import '@standard-schema/spec';
17
22
  import './ILankaFieldError-D5931-vT.js';
18
- import './lankaHttpInFlight-Bk1eIuSx.js';
19
- import './lankaRequestMiddleware-DAC5kCb7.js';
23
+ import './locator/scenario/lanka-scenario-locator/LankaScenarioLocator.js';
24
+ import './locator/shared-store/lanka-shared-store-locator/LankaSharedStoreLocator.js';
20
25
  import './ALankaSharedStore-B7uepuuk.js';
21
26
  import 'zustand/vanilla';
package/dist/index.js CHANGED
@@ -6,28 +6,33 @@ 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-SO7D5E7O.js";
10
+ import "./chunk-SBITVBF7.js";
11
+ import "./chunk-BMF4TM2Z.js";
12
+ import "./chunk-42CWYVZJ.js";
13
+ import "./chunk-MKKMTLOY.js";
14
+ import "./chunk-NWEHOMTS.js";
13
15
  import {
14
16
  createLankaHost
15
17
  } from "./chunk-XESL274R.js";
16
- import "./chunk-UJEC7H6K.js";
18
+ import "./chunk-BHQ2SQ7P.js";
17
19
  import {
18
20
  LankaError
19
21
  } from "./chunk-G32H73QY.js";
20
22
  import {
21
23
  getLankaHost
22
- } from "./chunk-RKYKK6MN.js";
23
- import "./chunk-UE2C76OR.js";
24
+ } from "./chunk-RUMUFHSL.js";
25
+ import "./chunk-3R2NO47A.js";
26
+ import "./chunk-24MUFFHF.js";
27
+ import "./chunk-JZJ6GXX3.js";
28
+ import "./chunk-N3275IPH.js";
24
29
  import {
25
30
  lankaLogger
26
- } from "./chunk-C2HP7CRD.js";
31
+ } from "./chunk-FII3PW2G.js";
27
32
  import {
28
33
  getLankaFlags
29
- } from "./chunk-D27MREPB.js";
30
- import "./chunk-BGVDPDX4.js";
34
+ } from "./chunk-7DQUF2QR.js";
35
+ import "./chunk-XGMXT4XZ.js";
31
36
  export {
32
37
  ALankaPlugin,
33
38
  LankaError,
@@ -0,0 +1,18 @@
1
+ import { A as ALankaGateway } from '../../../ALankaGateway-BrVPaZN5.js';
2
+ import { A as ALankaLocator } from '../../../ALankaLocator-BUCCz0Q5.js';
3
+ import '../../../lankaStandardValidator-BUFnysK0.js';
4
+ import '@standard-schema/spec';
5
+ import '../../../ILankaFieldError-D5931-vT.js';
6
+
7
+ /**
8
+ * Resolves a gateway by property name (camelCase) or class name (PascalCase),
9
+ * constructing it lazily and caching the instance.
10
+ *
11
+ * Adding a gateway takes one export line in `@lanka_di/Gateways`: types are
12
+ * inferred and nothing is registered.
13
+ */
14
+ declare class LankaGatewayLocator extends ALankaLocator<ALankaGateway<unknown>> {
15
+ constructor();
16
+ }
17
+
18
+ export { LankaGatewayLocator };
@@ -0,0 +1,9 @@
1
+ import {
2
+ LankaGatewayLocator
3
+ } from "../../../chunk-BMF4TM2Z.js";
4
+ import "../../../chunk-JZJ6GXX3.js";
5
+ import "../../../chunk-N3275IPH.js";
6
+ export {
7
+ LankaGatewayLocator
8
+ };
9
+ //# sourceMappingURL=LankaGatewayLocator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1,11 +1,13 @@
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-CVoV0EwO.js';
2
+ export { a as ILankaLocator, I as ILankaLocatorConfig } from '../ALankaLocator-BUCCz0Q5.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';
6
6
  import * as SingletonsModule from '@lanka_di/Singletons';
7
7
  import * as SharedStoresModule from '@lanka_di/SharedStores';
8
8
  import { A as ALankaSharedStore } from '../ALankaSharedStore-B7uepuuk.js';
9
+ export { ILankaSharedStoreLocatorConfig } from './shared-store/lanka-shared-store-locator/LankaSharedStoreLocator.js';
10
+ export { ILankaSingletonLocatorConfig } from './singleton/lanka-singleton-locator/LankaSingletonLocator.js';
9
11
  import '../lankaStandardValidator-BUFnysK0.js';
10
12
  import '@standard-schema/spec';
11
13
  import '../ILankaFieldError-D5931-vT.js';
@@ -2,11 +2,14 @@ import {
2
2
  createLankaLocatorProxy,
3
3
  lankaSharedStores,
4
4
  lankaSingletons
5
- } from "../chunk-DTO27QFR.js";
6
- import "../chunk-UE2C76OR.js";
5
+ } from "../chunk-H5TIUKRK.js";
6
+ import "../chunk-3R2NO47A.js";
7
+ import "../chunk-24MUFFHF.js";
8
+ import "../chunk-JZJ6GXX3.js";
9
+ import "../chunk-N3275IPH.js";
7
10
  import {
8
11
  requireActiveRuntime
9
- } from "../chunk-BGVDPDX4.js";
12
+ } from "../chunk-XGMXT4XZ.js";
10
13
 
11
14
  // src/locator/gateway/_facades/lanka-gateways/lankaGateways.ts
12
15
  var gatewayLocator = {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/locator/gateway/_facades/lanka-gateways/lankaGateways.ts","../../src/locator/scenario/_facades/lanka-scenarios/lankaScenarios.ts","../../src/locator/singleton/_abstractions/lanka-singleton/ALankaSingleton.ts","../../src/locator/singleton/_factories/create-lanka-singleton/createLankaSingleton.ts"],"sourcesContent":["import { requireActiveRuntime } from \"../../../../_internal/active-runtime/activeRuntime\";\nimport type { ILankaLocator } from \"../../../_interfaces/ILankaLocator\";\nimport type { TLankaGateways } from \"../../_types/TLankaGateways\";\nimport { createLankaLocatorProxy } from \"../../../_factories/create-lanka-locator-proxy/createLankaLocatorProxy\";\nimport type { ALankaGateway } from \"../../../../gateway/_abstractions/lanka-gateway/ALankaGateway\";\n\n/**\n * The locator comes from the active instance rather than being created here.\n *\n * The cache of resolved objects is state, and module-level state would let two\n * frameworks in one process resolve the same gateway. The proxy stays at module\n * level because it has hundreds of call sites; only the cache moved.\n */\nconst gatewayLocator: ILankaLocator<ALankaGateway<unknown>> = {\n\tget: (propertyName: string) => requireActiveRuntime().locators.gateways.get(propertyName),\n};\n\n/**\n * Access to every gateway at once.\n *\n * An `ALankaGateway` subclass appears here by itself. The property is camelCase,\n * the gateway name is PascalCase.\n *\n * ```ts\n * import { lankaGateways } from \"lanka\";\n *\n * const user = await lankaGateways.userGateway.getById(1);\n * const list = await lankaGateways.companyGateway.getList({ page: 1 });\n * ```\n */\nexport const lankaGateways = createLankaLocatorProxy<ALankaGateway<unknown>, TLankaGateways>({\n\tlocator: gatewayLocator,\n\tprotectedProperties: [\"clearCache\"],\n\terrorPrefix: \"Cannot access gateway\",\n});\n","import { requireActiveRuntime } from \"../../../../_internal/active-runtime/activeRuntime\";\nimport type { ILankaLocator } from \"../../../_interfaces/ILankaLocator\";\nimport { createLankaLocatorProxy } from \"../../../_factories/create-lanka-locator-proxy/createLankaLocatorProxy\";\nimport type { ILankaScenario } from \"../../../../scenario/_interfaces/ILankaScenario\";\nimport { TLankaScenarios } from \"../../_types/TLankaScenarios\";\n\n/**\n * The locator comes from the active instance rather than being created here.\n *\n * The cache of resolved objects is state, and module-level state would let two\n * frameworks in one process resolve the same scenario. The proxy stays at module\n * level because it has hundreds of call sites; only the cache moved.\n */\nconst scenarioLocator: ILankaLocator<ILankaScenario<unknown>> = {\n\tget: (propertyName: string) => requireActiveRuntime().locators.scenarios.get(propertyName),\n};\n\n/**\n * Access to every scenario at once.\n *\n * An `ALankaScenario` subclass appears here by itself. The property is camelCase,\n * the scenario name is PascalCase.\n *\n * ```ts\n * import { lankaScenarios } from \"lanka\";\n *\n * lankaScenarios.sessionUpdated.trigger({ user });\n * lankaScenarios.usersListRefresh.trigger({ reason: \"create\" });\n *\n * lankaScenarios.usersListRefresh.subscribe((data) => { ... });\n * ```\n */\nexport const lankaScenarios = createLankaLocatorProxy<ILankaScenario<unknown>, TLankaScenarios>({\n\tlocator: scenarioLocator,\n\terrorPrefix: \"Cannot access scenario\",\n});\n","/**\n * The singleton marker: \"this class is published by the application in\n * `lankaSingletons`\".\n *\n * ## Why a marker when the class is exported anyway\n *\n * The other three locators have one: a gateway extends `ALankaGateway`, a\n * scenario has a `name`, a store extends `ALankaSharedStore`. Without a marker\n * the selection is \"anything that is a function with a prototype\", so a stray\n * export in the barrel — a helper, a companion class, an accidental re-export —\n * becomes part of the public `lankaSingletons.*`, and a typo in a name is caught\n * at runtime on first use, far from where it was made.\n *\n * ## A base class rather than a field\n *\n * A marker field can be put on anything, an object included, and the type would\n * again stop telling a class from a non-class. Inheritance also gives TypeScript\n * something it can select on in a mapped type.\n *\n * The class is empty deliberately: all it carries is the statement \"I am meant\n * for the locator\".\n */\nexport abstract class ALankaSingleton {\n\t/**\n\t * A runtime check, for the locator, which cannot see types.\n\t *\n\t * Looks at the prototype chain rather than the name: names are lost to\n\t * minification, and a name check would work only until the build.\n\t */\n\tstatic is(candidate: unknown): boolean {\n\t\tif (typeof candidate !== \"function\") return false;\n\n\t\tlet proto: unknown = Object.getPrototypeOf(candidate) as unknown;\n\t\twhile (typeof proto === \"function\") {\n\t\t\tif (proto === ALankaSingleton) return true;\n\t\t\tproto = Object.getPrototypeOf(proto) as unknown;\n\t\t}\n\t\treturn false;\n\t}\n}\n","import { ALankaSingleton } from \"../../_abstractions/lanka-singleton/ALankaSingleton\";\n\n/**\n * The functional style of `ALankaSingleton`: a singleton declared by a function.\n *\n * A singleton is a role — an application writes many — and this is the same role\n * the class style declares by extending the marker. What comes back IS a subclass\n * of `ALankaSingleton`, so the locator discovers it in the consumer's barrel,\n * builds it on first use and caches it, exactly as it does a hand-written class.\n *\n * ```ts\n * export const PlaygroundClock = createLankaSingleton(() => ({\n * \tnow: () => Date.now(),\n * }));\n * ```\n *\n * The result is exported under a PascalCase name because it is a class: the\n * locator resolves `lankaSingletons.playgroundClock` by that export name, and a\n * camelCase one would read as the instance while being the constructor.\n *\n * The builder runs at first resolution, not here — a singleton declared in a\n * module body must not touch a runtime that does not exist yet. Canon:\n * `skills/parity/SKILL.md`.\n */\nexport const createLankaSingleton = <TInstance extends object>(\n\tbuild: () => TInstance,\n): new () => TInstance => {\n\tclass FunctionalSingleton extends ALankaSingleton {\n\t\tpublic constructor() {\n\t\t\tsuper();\n\n\t\t\t// A constructor answering an object is what makes the two styles one\n\t\t\t// implementation: the locator constructs a marked class either way, and\n\t\t\t// what it gets back is what the builder returned.\n\t\t\treturn build();\n\t\t}\n\t}\n\n\treturn FunctionalSingleton as unknown as new () => TInstance;\n};\n"],"mappings":";;;;;;;;;;;AAaA,IAAM,iBAAwD;AAAA,EAC7D,KAAK,CAAC,iBAAyB,qBAAqB,EAAE,SAAS,SAAS,IAAI,YAAY;AACzF;AAeO,IAAM,gBAAgB,wBAAgE;AAAA,EAC5F,SAAS;AAAA,EACT,qBAAqB,CAAC,YAAY;AAAA,EAClC,aAAa;AACd,CAAC;;;ACrBD,IAAM,kBAA0D;AAAA,EAC/D,KAAK,CAAC,iBAAyB,qBAAqB,EAAE,SAAS,UAAU,IAAI,YAAY;AAC1F;AAiBO,IAAM,iBAAiB,wBAAkE;AAAA,EAC/F,SAAS;AAAA,EACT,aAAa;AACd,CAAC;;;ACbM,IAAe,kBAAf,MAAe,iBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOrC,OAAO,GAAG,WAA6B;AACtC,QAAI,OAAO,cAAc,WAAY,QAAO;AAE5C,QAAI,QAAiB,OAAO,eAAe,SAAS;AACpD,WAAO,OAAO,UAAU,YAAY;AACnC,UAAI,UAAU,iBAAiB,QAAO;AACtC,cAAQ,OAAO,eAAe,KAAK;AAAA,IACpC;AACA,WAAO;AAAA,EACR;AACD;;;ACfO,IAAM,uBAAuB,CACnC,UACyB;AAAA,EACzB,MAAM,4BAA4B,gBAAgB;AAAA,IAC1C,cAAc;AACpB,YAAM;AAKN,aAAO,MAAM;AAAA,IACd;AAAA,EACD;AAEA,SAAO;AACR;","names":[]}
1
+ {"version":3,"sources":["../../src/locator/gateway/_facades/lanka-gateways/lankaGateways.ts","../../src/locator/scenario/_facades/lanka-scenarios/lankaScenarios.ts","../../src/locator/singleton/_abstractions/lanka-singleton/ALankaSingleton.ts","../../src/locator/singleton/_factories/create-lanka-singleton/createLankaSingleton.ts"],"sourcesContent":["import { requireActiveRuntime } from \"../../../../_internal/active-runtime/activeRuntime\";\nimport type { ILankaLocator } from \"../../../_interfaces/ILankaLocator\";\nimport type { TLankaGateways } from \"../../_types/TLankaGateways\";\nimport { createLankaLocatorProxy } from \"../../../_factories/create-lanka-locator-proxy/createLankaLocatorProxy\";\nimport type { ALankaGateway } from \"../../../../gateway/_abstractions/lanka-gateway/ALankaGateway\";\n\n/**\n * The locator comes from the active instance rather than being created here.\n *\n * The cache of resolved objects is state, and module-level state would let two\n * frameworks in one process resolve the same gateway. The proxy stays at module\n * level because it has hundreds of call sites; only the cache moved.\n */\nconst gatewayLocator: ILankaLocator<ALankaGateway<unknown>> = {\n\tget: (propertyName: string) => requireActiveRuntime().locators.gateways.get(propertyName),\n};\n\n/**\n * Access to every gateway at once.\n *\n * An `ALankaGateway` subclass appears here by itself. The property is camelCase,\n * the gateway name is PascalCase.\n *\n * ```ts\n * import { lankaGateways } from \"lanka\";\n *\n * const user = await lankaGateways.userGateway.getById(1);\n * const list = await lankaGateways.companyGateway.getList({ page: 1 });\n * ```\n */\nexport const lankaGateways = createLankaLocatorProxy<ALankaGateway<unknown>, TLankaGateways>({\n\tlocator: gatewayLocator,\n\tprotectedProperties: [\"clearCache\"],\n\terrorPrefix: \"Cannot access gateway\",\n});\n","import { requireActiveRuntime } from \"../../../../_internal/active-runtime/activeRuntime\";\nimport type { ILankaLocator } from \"../../../_interfaces/ILankaLocator\";\nimport { createLankaLocatorProxy } from \"../../../_factories/create-lanka-locator-proxy/createLankaLocatorProxy\";\nimport type { ILankaScenario } from \"../../../../scenario/_interfaces/ILankaScenario\";\nimport { TLankaScenarios } from \"../../_types/TLankaScenarios\";\n\n/**\n * The locator comes from the active instance rather than being created here.\n *\n * The cache of resolved objects is state, and module-level state would let two\n * frameworks in one process resolve the same scenario. The proxy stays at module\n * level because it has hundreds of call sites; only the cache moved.\n */\nconst scenarioLocator: ILankaLocator<ILankaScenario<unknown>> = {\n\tget: (propertyName: string) => requireActiveRuntime().locators.scenarios.get(propertyName),\n};\n\n/**\n * Access to every scenario at once.\n *\n * An `ALankaScenario` subclass appears here by itself. The property is camelCase,\n * the scenario name is PascalCase.\n *\n * ```ts\n * import { lankaScenarios } from \"lanka\";\n *\n * lankaScenarios.sessionUpdated.trigger({ user });\n * lankaScenarios.usersListRefresh.trigger({ reason: \"create\" });\n *\n * lankaScenarios.usersListRefresh.subscribe((data) => { ... });\n * ```\n */\nexport const lankaScenarios = createLankaLocatorProxy<ILankaScenario<unknown>, TLankaScenarios>({\n\tlocator: scenarioLocator,\n\terrorPrefix: \"Cannot access scenario\",\n});\n","/**\n * The singleton marker: \"this class is published by the application in\n * `lankaSingletons`\".\n *\n * ## Why a marker when the class is exported anyway\n *\n * The other three locators have one: a gateway extends `ALankaGateway`, a\n * scenario has a `name`, a store extends `ALankaSharedStore`. Without a marker\n * the selection is \"anything that is a function with a prototype\", so a stray\n * export in the barrel — a helper, a companion class, an accidental re-export —\n * becomes part of the public `lankaSingletons.*`, and a typo in a name is caught\n * at runtime on first use, far from where it was made.\n *\n * ## A base class rather than a field\n *\n * A marker field can be put on anything, an object included, and the type would\n * again stop telling a class from a non-class. Inheritance also gives TypeScript\n * something it can select on in a mapped type.\n *\n * The class is empty deliberately: all it carries is the statement \"I am meant\n * for the locator\".\n */\nexport abstract class ALankaSingleton {\n\t/**\n\t * A runtime check, for the locator, which cannot see types.\n\t *\n\t * Looks at the prototype chain rather than the name: names are lost to\n\t * minification, and a name check would work only until the build.\n\t */\n\tstatic is(candidate: unknown): boolean {\n\t\tif (typeof candidate !== \"function\") return false;\n\n\t\tlet proto: unknown = Object.getPrototypeOf(candidate) as unknown;\n\t\twhile (typeof proto === \"function\") {\n\t\t\tif (proto === ALankaSingleton) return true;\n\t\t\tproto = Object.getPrototypeOf(proto) as unknown;\n\t\t}\n\t\treturn false;\n\t}\n}\n","import { ALankaSingleton } from \"../../_abstractions/lanka-singleton/ALankaSingleton\";\n\n/**\n * The functional style of `ALankaSingleton`: a singleton declared by a function.\n *\n * A singleton is a role — an application writes many — and this is the same role\n * the class style declares by extending the marker. What comes back IS a subclass\n * of `ALankaSingleton`, so the locator discovers it in the consumer's barrel,\n * builds it on first use and caches it, exactly as it does a hand-written class.\n *\n * ```ts\n * export const PlaygroundClock = createLankaSingleton(() => ({\n * \tnow: () => Date.now(),\n * }));\n * ```\n *\n * The result is exported under a PascalCase name because it is a class: the\n * locator resolves `lankaSingletons.playgroundClock` by that export name, and a\n * camelCase one would read as the instance while being the constructor.\n *\n * The builder runs at first resolution, not here — a singleton declared in a\n * module body must not touch a runtime that does not exist yet. Canon:\n * `skills/parity/SKILL.md`.\n */\nexport const createLankaSingleton = <TInstance extends object>(\n\tbuild: () => TInstance,\n): new () => TInstance => {\n\tclass FunctionalSingleton extends ALankaSingleton {\n\t\tpublic constructor() {\n\t\t\tsuper();\n\n\t\t\t// A constructor answering an object is what makes the two styles one\n\t\t\t// implementation: the locator constructs a marked class either way, and\n\t\t\t// what it gets back is what the builder returned.\n\t\t\treturn build();\n\t\t}\n\t}\n\n\treturn FunctionalSingleton as unknown as new () => TInstance;\n};\n"],"mappings":";;;;;;;;;;;;;;AAaA,IAAM,iBAAwD;AAAA,EAC7D,KAAK,CAAC,iBAAyB,qBAAqB,EAAE,SAAS,SAAS,IAAI,YAAY;AACzF;AAeO,IAAM,gBAAgB,wBAAgE;AAAA,EAC5F,SAAS;AAAA,EACT,qBAAqB,CAAC,YAAY;AAAA,EAClC,aAAa;AACd,CAAC;;;ACrBD,IAAM,kBAA0D;AAAA,EAC/D,KAAK,CAAC,iBAAyB,qBAAqB,EAAE,SAAS,UAAU,IAAI,YAAY;AAC1F;AAiBO,IAAM,iBAAiB,wBAAkE;AAAA,EAC/F,SAAS;AAAA,EACT,aAAa;AACd,CAAC;;;ACbM,IAAe,kBAAf,MAAe,iBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOrC,OAAO,GAAG,WAA6B;AACtC,QAAI,OAAO,cAAc,WAAY,QAAO;AAE5C,QAAI,QAAiB,OAAO,eAAe,SAAS;AACpD,WAAO,OAAO,UAAU,YAAY;AACnC,UAAI,UAAU,iBAAiB,QAAO;AACtC,cAAQ,OAAO,eAAe,KAAK;AAAA,IACpC;AACA,WAAO;AAAA,EACR;AACD;;;ACfO,IAAM,uBAAuB,CACnC,UACyB;AAAA,EACzB,MAAM,4BAA4B,gBAAgB;AAAA,IAC1C,cAAc;AACpB,YAAM;AAKN,aAAO,MAAM;AAAA,IACd;AAAA,EACD;AAEA,SAAO;AACR;","names":[]}