lanka 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{LankaScenarioLocator-BGQHwf3n.d.ts → LankaScenarioLocator-CLkq4MaJ.d.ts} +1 -1
- package/dist/{LankaSharedStoreLocator-MvCpav5F.d.ts → LankaSharedStoreLocator-zS2kLu-S.d.ts} +21 -0
- package/dist/_extend/index.d.ts +4 -4
- package/dist/_extend/index.js +3 -3
- package/dist/_internal/index.d.ts +3 -3
- package/dist/{activeRuntime-FcsSJvUg.d.ts → activeRuntime-DT4gB16d.d.ts} +2 -2
- package/dist/bootstrap/index.d.ts +4 -4
- package/dist/bootstrap/index.js +5 -5
- package/dist/{chunk-RYFZCAQ3.js → chunk-63ST2UKP.js} +12 -12
- package/dist/chunk-63ST2UKP.js.map +1 -0
- package/dist/{chunk-Q3SOVBIJ.js → chunk-HZAIAGWS.js} +4 -4
- package/dist/{chunk-Q3SOVBIJ.js.map → chunk-HZAIAGWS.js.map} +1 -1
- package/dist/{chunk-FIR4XTBL.js → chunk-MYZQYOMD.js} +10 -12
- package/dist/chunk-MYZQYOMD.js.map +1 -0
- package/dist/{chunk-ILQNYQY5.js → chunk-UE2C76OR.js} +32 -18
- package/dist/chunk-UE2C76OR.js.map +1 -0
- package/dist/{chunk-EWVDJYCC.js → chunk-YXI4OQEV.js} +2 -6
- package/dist/chunk-YXI4OQEV.js.map +1 -0
- package/dist/{createLankaScope-Bc_vChRs.d.ts → createLankaScope-BiFxNQgl.d.ts} +1 -1
- package/dist/gateway/index.js +1 -2
- package/dist/gateway/index.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +5 -5
- package/dist/locator/index.d.ts +6 -54
- package/dist/locator/index.js +1 -1
- package/dist/scenario/index.js +2 -2
- package/dist/viewmodel/index.js +4 -2
- package/dist/viewmodel/index.js.map +1 -1
- package/package.json +2 -2
- package/skills/lanka-core/SKILL.md +1 -1
- package/skills/lanka-core/reference.md +1 -1
- package/skills/lanka-packages/SKILL.md +1 -1
- package/dist/chunk-EWVDJYCC.js.map +0 -1
- package/dist/chunk-FIR4XTBL.js.map +0 -1
- package/dist/chunk-ILQNYQY5.js.map +0 -1
- package/dist/chunk-RYFZCAQ3.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { a as ILankaScenario, I as ILankaScenarioVM } from './ILankaScenarioVM-DuCyPoyT.js';
|
|
2
2
|
import { I as ILankaScenarioMetadata } from './ILankaScenarioMetadata-Bu-yggTZ.js';
|
|
3
3
|
import { A as ALankaGateway } from './ALankaGateway-ExlRGT3D.js';
|
|
4
|
-
import { A as ALankaLocator } from './LankaSharedStoreLocator-
|
|
4
|
+
import { A as ALankaLocator } from './LankaSharedStoreLocator-zS2kLu-S.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* The scenario registry: both those that registered themselves and those
|
package/dist/{LankaSharedStoreLocator-MvCpav5F.d.ts → LankaSharedStoreLocator-zS2kLu-S.d.ts}
RENAMED
|
@@ -43,6 +43,27 @@ declare abstract class ALankaLocator<TInstance> implements ILankaLocator<TInstan
|
|
|
43
43
|
notFoundError: (name: string, propertyName: string) => string;
|
|
44
44
|
};
|
|
45
45
|
protected constructor(config: ILankaLocatorConfig<TInstance>);
|
|
46
|
+
/**
|
|
47
|
+
* The class a name resolves to: hand-registered FIRST, then the consumer's
|
|
48
|
+
* barrel.
|
|
49
|
+
*
|
|
50
|
+
* One owner for both callers, and that is the whole point of it existing.
|
|
51
|
+
* `registeredClasses` used to be read inside each locator's own
|
|
52
|
+
* `findClassByName`, and only two of the four did it — singletons and shared
|
|
53
|
+
* stores worked, gateways and scenarios silently dropped the class. Moving the
|
|
54
|
+
* read into `getInstanceByName` fixed those two and broke a third path:
|
|
55
|
+
* `LankaSingletonLocator.createScopedInstance` calls `findClassByName`
|
|
56
|
+
* directly, so a registered class stopped resolving inside a scope. Ten tests
|
|
57
|
+
* said so.
|
|
58
|
+
*
|
|
59
|
+
* Both callers go through here now. A fourth caller added later gets the
|
|
60
|
+
* precedence for free instead of having to remember it.
|
|
61
|
+
*
|
|
62
|
+
* The precedence itself matches `registeredInstances` below: what a caller
|
|
63
|
+
* handed over wins over what the barrel happens to export under that name,
|
|
64
|
+
* because the caller is usually a test substituting a double.
|
|
65
|
+
*/
|
|
66
|
+
protected classFor(instanceName: string): (new () => TInstance) | undefined;
|
|
46
67
|
/**
|
|
47
68
|
* An object by class name.
|
|
48
69
|
*
|
package/dist/_extend/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { L as LankaGatewayLocator, a as LankaScenarioLocator, b as LankaScenarioVMRegistry, c as LankaScenariosRegistry } from '../LankaScenarioLocator-
|
|
2
|
-
import { a as ILankaLocator } from '../LankaSharedStoreLocator-
|
|
3
|
-
export { A as ALankaLocator, L as LankaSharedStoreLocator, b as LankaSingletonLocator } from '../LankaSharedStoreLocator-
|
|
4
|
-
export { c as createLankaScope } from '../createLankaScope-
|
|
1
|
+
export { L as LankaGatewayLocator, a as LankaScenarioLocator, b as LankaScenarioVMRegistry, c as LankaScenariosRegistry } from '../LankaScenarioLocator-CLkq4MaJ.js';
|
|
2
|
+
import { a as ILankaLocator } from '../LankaSharedStoreLocator-zS2kLu-S.js';
|
|
3
|
+
export { A as ALankaLocator, L as LankaSharedStoreLocator, b as LankaSingletonLocator } from '../LankaSharedStoreLocator-zS2kLu-S.js';
|
|
4
|
+
export { c as createLankaScope } from '../createLankaScope-BiFxNQgl.js';
|
|
5
5
|
export { c as composeLankaRequestMiddleware } from '../lankaRequestMiddleware-DAC5kCb7.js';
|
|
6
6
|
import '../ILankaScenarioVM-DuCyPoyT.js';
|
|
7
7
|
import '../ILankaScenarioMetadata-Bu-yggTZ.js';
|
package/dist/_extend/index.js
CHANGED
|
@@ -2,11 +2,11 @@ import {
|
|
|
2
2
|
LankaGatewayLocator,
|
|
3
3
|
LankaScenarioLocator,
|
|
4
4
|
createLankaScope
|
|
5
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-MYZQYOMD.js";
|
|
6
6
|
import {
|
|
7
7
|
LankaScenarioVMRegistry,
|
|
8
8
|
LankaScenariosRegistry
|
|
9
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-YXI4OQEV.js";
|
|
10
10
|
import {
|
|
11
11
|
composeLankaRequestMiddleware
|
|
12
12
|
} from "../chunk-YR4MZXMU.js";
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
ALankaLocator,
|
|
18
18
|
LankaSharedStoreLocator,
|
|
19
19
|
LankaSingletonLocator
|
|
20
|
-
} from "../chunk-
|
|
20
|
+
} from "../chunk-UE2C76OR.js";
|
|
21
21
|
import "../chunk-C2HP7CRD.js";
|
|
22
22
|
import "../chunk-D27MREPB.js";
|
|
23
23
|
import "../chunk-BGVDPDX4.js";
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
export { I as ILankaRuntime, T as TLankaRuntimeResolver, s as setLankaRuntimeResolver } from '../activeRuntime-
|
|
1
|
+
export { I as ILankaRuntime, T as TLankaRuntimeResolver, s as setLankaRuntimeResolver } from '../activeRuntime-DT4gB16d.js';
|
|
2
2
|
import '../ILankaScenarioVM-DuCyPoyT.js';
|
|
3
|
-
import '../LankaScenarioLocator-
|
|
3
|
+
import '../LankaScenarioLocator-CLkq4MaJ.js';
|
|
4
4
|
import '../ILankaScenarioMetadata-Bu-yggTZ.js';
|
|
5
5
|
import '../ALankaGateway-ExlRGT3D.js';
|
|
6
6
|
import '../lankaStandardValidator-CL-r-zEV.js';
|
|
7
7
|
import '@standard-schema/spec';
|
|
8
|
-
import '../LankaSharedStoreLocator-
|
|
8
|
+
import '../LankaSharedStoreLocator-zS2kLu-S.js';
|
|
9
9
|
import '../ALankaSharedStore-B7uepuuk.js';
|
|
10
10
|
import 'zustand/vanilla';
|
|
11
11
|
import '../ILankaRuntimeConfig-Vl436GWK.js';
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { L as LankaEventBusInstance, I as ILankaScenarioVM } from './ILankaScenarioVM-DuCyPoyT.js';
|
|
2
|
-
import { c as LankaScenariosRegistry, b as LankaScenarioVMRegistry, L as LankaGatewayLocator, a as LankaScenarioLocator } from './LankaScenarioLocator-
|
|
2
|
+
import { c as LankaScenariosRegistry, b as LankaScenarioVMRegistry, L as LankaGatewayLocator, a as LankaScenarioLocator } from './LankaScenarioLocator-CLkq4MaJ.js';
|
|
3
3
|
import { b as ILankaRuntimeConfig } from './ILankaRuntimeConfig-Vl436GWK.js';
|
|
4
4
|
import { I as ILankaInFlightCounter } from './lankaHttpInFlight-Bk1eIuSx.js';
|
|
5
5
|
import { T as TLankaRequestMiddleware } from './lankaRequestMiddleware-DAC5kCb7.js';
|
|
6
|
-
import { b as LankaSingletonLocator, L as LankaSharedStoreLocator } from './LankaSharedStoreLocator-
|
|
6
|
+
import { b as LankaSingletonLocator, L as LankaSharedStoreLocator } from './LankaSharedStoreLocator-zS2kLu-S.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* The pointer to the framework instance that ambient facades resolve to.
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { I as ILankaScope } from '../createLankaScope-
|
|
2
|
-
import { I as ILankaRuntime } from '../activeRuntime-
|
|
1
|
+
import { I as ILankaScope } from '../createLankaScope-BiFxNQgl.js';
|
|
2
|
+
import { I as ILankaRuntime } from '../activeRuntime-DT4gB16d.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
|
-
import '../LankaSharedStoreLocator-
|
|
5
|
+
import '../LankaSharedStoreLocator-zS2kLu-S.js';
|
|
6
6
|
import '../ALankaSharedStore-B7uepuuk.js';
|
|
7
7
|
import 'zustand/vanilla';
|
|
8
8
|
import '../ILankaScenarioVM-DuCyPoyT.js';
|
|
9
|
-
import '../LankaScenarioLocator-
|
|
9
|
+
import '../LankaScenarioLocator-CLkq4MaJ.js';
|
|
10
10
|
import '../ILankaScenarioMetadata-Bu-yggTZ.js';
|
|
11
11
|
import '../ALankaGateway-ExlRGT3D.js';
|
|
12
12
|
import '../lankaStandardValidator-CL-r-zEV.js';
|
package/dist/bootstrap/index.js
CHANGED
|
@@ -3,13 +3,13 @@ import {
|
|
|
3
3
|
createLanka,
|
|
4
4
|
resetActiveLanka,
|
|
5
5
|
startLanka
|
|
6
|
-
} from "../chunk-
|
|
7
|
-
import "../chunk-
|
|
8
|
-
import "../chunk-
|
|
9
|
-
import "../chunk-
|
|
6
|
+
} from "../chunk-63ST2UKP.js";
|
|
7
|
+
import "../chunk-HZAIAGWS.js";
|
|
8
|
+
import "../chunk-MYZQYOMD.js";
|
|
9
|
+
import "../chunk-YXI4OQEV.js";
|
|
10
10
|
import "../chunk-XESL274R.js";
|
|
11
11
|
import "../chunk-UJEC7H6K.js";
|
|
12
|
-
import "../chunk-
|
|
12
|
+
import "../chunk-UE2C76OR.js";
|
|
13
13
|
import "../chunk-C2HP7CRD.js";
|
|
14
14
|
import "../chunk-D27MREPB.js";
|
|
15
15
|
import "../chunk-BGVDPDX4.js";
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
lankaScenarioBootstrap
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-HZAIAGWS.js";
|
|
4
4
|
import {
|
|
5
5
|
LankaGatewayLocator,
|
|
6
6
|
LankaScenarioLocator,
|
|
7
7
|
createLankaScope
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-MYZQYOMD.js";
|
|
9
9
|
import {
|
|
10
10
|
LankaScenarioVMRegistry,
|
|
11
11
|
LankaScenariosRegistry
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-YXI4OQEV.js";
|
|
13
13
|
import {
|
|
14
14
|
createLankaHost
|
|
15
15
|
} from "./chunk-XESL274R.js";
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
import {
|
|
20
20
|
LankaSharedStoreLocator,
|
|
21
21
|
LankaSingletonLocator
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-UE2C76OR.js";
|
|
23
23
|
import {
|
|
24
24
|
lankaLogger
|
|
25
25
|
} from "./chunk-C2HP7CRD.js";
|
|
@@ -208,13 +208,6 @@ var LankaEventBusInstance = class {
|
|
|
208
208
|
return;
|
|
209
209
|
}
|
|
210
210
|
this.logEvent(state, eventType, data);
|
|
211
|
-
const depth = Math.max(resolveReplayCount(meta.replay), maxReplayDepth(subs));
|
|
212
|
-
if (depth > 0) {
|
|
213
|
-
buffer.push(data);
|
|
214
|
-
while (buffer.length > depth) buffer.shift();
|
|
215
|
-
} else if (buffer.length > 0) {
|
|
216
|
-
buffer.length = 0;
|
|
217
|
-
}
|
|
218
211
|
const deliver = () => {
|
|
219
212
|
for (const entry of [...subs]) {
|
|
220
213
|
try {
|
|
@@ -240,6 +233,13 @@ var LankaEventBusInstance = class {
|
|
|
240
233
|
return;
|
|
241
234
|
}
|
|
242
235
|
}
|
|
236
|
+
const depth = Math.max(resolveReplayCount(meta.replay), maxReplayDepth(subs));
|
|
237
|
+
if (depth > 0) {
|
|
238
|
+
buffer.push(data);
|
|
239
|
+
while (buffer.length > depth) buffer.shift();
|
|
240
|
+
} else if (buffer.length > 0) {
|
|
241
|
+
buffer.length = 0;
|
|
242
|
+
}
|
|
243
243
|
deliver();
|
|
244
244
|
}
|
|
245
245
|
/** Adds middleware to the shared chain. */
|
|
@@ -634,4 +634,4 @@ export {
|
|
|
634
634
|
resetActiveLanka,
|
|
635
635
|
ALankaPlugin
|
|
636
636
|
};
|
|
637
|
-
//# sourceMappingURL=chunk-
|
|
637
|
+
//# sourceMappingURL=chunk-63ST2UKP.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 { lankaLogger } from \"../../../logger/lanka-logger/LankaLogger\";\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/** 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// 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\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\tentry.callback(data);\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\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}\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 * Log of dispatched events.\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\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 and middleware. */\n\tpublic reset(): void {\n\t\tthis.clearAllEvents();\n\t\tthis.middlewares = [];\n\t\tthis.isEnableLogs = false;\n\t}\n\n\t// -------------------------------------------------------------------------\n\t// Internal helpers\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\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};\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\tsetActiveRuntime,\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\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\tsetActiveRuntime(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\tasync bootstrap(bootstrapConfig: ILankaBootstrapConfig = {}): Promise<void> {\n\t\t\tif (bootstrapped) {\n\t\t\t\tlankaLogger.printBootstrapLog(\"LANKA ALREADY BOOTSTRAPPED\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tinstance.activate();\n\t\t\tlankaLogger.printBootstrapLog(\"LANKA BOOTSTRAP START\");\n\n\t\t\tconst plan = createExecutionPlan(bootstrapConfig);\n\n\t\t\tawait runSequential(plan.syncTasks, \"SYNC TASKS\");\n\t\t\tawait runParallel(plan.asyncTasks, \"ASYNC TASKS\");\n\t\t\tawait runSequential(plan.postAsyncTasks, \"POST-ASYNC TASKS (lankaScenarios)\");\n\n\t\t\tbootstrapped = true;\n\t\t\tlankaLogger.printBootstrapLog(\"LANKA BOOTSTRAP FINISH\");\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) setActiveRuntime(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 * 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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCA,SAAS,mBAAmB,SAAkD;AAC7E,MAAI,YAAY,UAAa,YAAY,MAAO,QAAO;AACvD,MAAI,YAAY,QAAQ,YAAY,OAAQ,QAAO;AACnD,SAAO,KAAK,IAAI,GAAG,KAAK,MAAM,OAAO,CAAC;AACvC;AAEA,SAAS,eAAe,MAA6C;AACpE,MAAI,QAAQ;AACZ,aAAW,SAAS,KAAM,KAAI,MAAM,cAAc,MAAO,SAAQ,MAAM;AACvE,SAAO;AACR;AAMO,IAAM,wBAAN,MAA4B;AAAA;AAAA,EAE1B,WAAqC,oBAAI,IAAI;AAAA;AAAA,EAG7C,cAAmD,CAAC;AAAA;AAAA,EAGpD,iBAAiB;AAAA;AAAA,EAGjB,sBAAkE,oBAAI,IAAI;AAAA;AAAA,EAG1E,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA,EAOhB,aAAmB;AACzB,SAAK,eAAe;AAAA,EACrB;AAAA,EACO,cAAoB;AAC1B,SAAK,eAAe;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYQ,YAAY,WAAmB,QAA8B;AACpE,QAAI,QAAQ,KAAK,SAAS,IAAI,SAAS;AACvC,QAAI,CAAC,OAAO;AACX,YAAM,OAA4B;AAAA,QACjC,UAAU;AAAA,QACV,aAAa,0BAA0B,SAAS;AAAA,QAChD,QAAQ,SAAS,CAAC,MAAM,IAAI,CAAC;AAAA,QAC7B,UAAU;AAAA,QACV,SAAS,KAAK;AAAA,MACf;AACA,cAAQ;AAAA,QACP;AAAA,QACA,MAAM,CAAC;AAAA,QACP,QAAQ,CAAC;AAAA,QACT,MAAM,CAAC;AAAA,MACR;AACA,WAAK,SAAS,IAAI,WAAW,KAAK;AAAA,IACnC,WAAW,QAAQ;AAClB,YAAM,OAAO,MAAM;AACnB,WAAK,SAAS,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAI,KAAK,UAAU,CAAC,GAAI,MAAM,CAAC,CAAC;AAAA,IAC5D;AACA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYO,cAAc,WAAmB,UAAqC;AAQ5E,UAAM,WAAW,KAAK,SAAS,IAAI,SAAS;AAC5C,UAAM,OAA4B;AAAA,MACjC,UAAU,SAAS,YAAY,UAAU,KAAK,YAAY;AAAA,MAC1D,aACC,SAAS,eACT,UAAU,KAAK,eACf,qBAAqB,SAAS;AAAA;AAAA;AAAA,MAG/B,QAAQ,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAI,UAAU,KAAK,UAAU,CAAC,GAAI,GAAI,SAAS,UAAU,CAAC,CAAE,CAAC,CAAC;AAAA,MACnF,QAAQ,SAAS,UAAU,UAAU,KAAK;AAAA,MAC1C,UAAU,SAAS,YAAY,UAAU,KAAK,YAAY;AAAA,MAC1D,SAAS,SAAS,WAAW,UAAU,KAAK,WAAW,KAAK;AAAA,MAC5D,QAAQ,SAAS,UAAU,UAAU,KAAK;AAAA,IAC3C;AAEA,QAAI,UAAU;AACb,eAAS,OAAO;AAChB;AAAA,IACD;AAEA,SAAK,SAAS,IAAI,WAAW,EAAE,MAAM,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC;AAAA,EACtE;AAAA;AAAA,EAGO,sBAAsB;AAC5B,WAAO,MAAM,KAAK,KAAK,SAAS,QAAQ,CAAC,EACvC,IAAI,CAAC,CAAC,WAAW,KAAK,OAAO;AAAA,MAC7B;AAAA,MACA,UAAU,MAAM;AAAA,IACjB,EAAE,EACD,KAAK,CAAC,GAAG,MAAM,EAAE,UAAU,cAAc,EAAE,SAAS,CAAC;AAAA,EACxD;AAAA;AAAA,EAGO,aAAa,WAA+C;AAClE,WAAO,KAAK,SAAS,IAAI,SAAS,GAAG,QAAQ;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASO,iBAAiB,WAA2B;AAClD,WAAO,KAAK,SAAS,IAAI,SAAS,GAAG,OAAO,UAAU;AAAA,EACvD;AAAA,EAEO,iBAAiB,WAA2B;AAClD,WAAO,KAAK,SAAS,IAAI,SAAS,GAAG,KAAK,UAAU;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYO,UACN,WACA,UACA,SAKa;AACb,UAAM,QAAQ,KAAK,YAAY,WAAW,SAAS,MAAM;AACzD,UAAM,OAAO,SAAS,YAAY,MAAM,KAAK,YAAY;AACzD,UAAM,QAAqC;AAAA,MAC1C;AAAA,MACA,UAAU;AAAA,MACV,aAAa,mBAAmB,SAAS,MAAM;AAAA,IAChD;AAEA,UAAM,OAAO,MAAM;AACnB,QAAI,MAAM,GACT,OAAO,KAAK;AACb,WAAO,MAAM,MAAM;AAClB,YAAM,MAAO,MAAM,SAAU;AAC7B,UAAI,KAAK,GAAG,EAAE,WAAW,KAAM,QAAO;AAAA,UACjC,OAAM,MAAM;AAAA,IAClB;AACA,SAAK,OAAO,KAAK,GAAG,KAAK;AAEzB,QAAI,SAAS,OAAQ,MAAK,sBAAsB,WAAW,KAAK;AAKhE,WAAO,MAAM;AACZ,YAAM,KAAK,MAAM,KAAK,QAAQ,KAAK;AACnC,UAAI,OAAO,GAAI,OAAM,KAAK,OAAO,IAAI,CAAC;AAAA,IACvC;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,YAAe,WAAmB,UAAmC;AAC3E,UAAM,QAAQ,KAAK,SAAS,IAAI,SAAS;AACzC,QAAI,CAAC,MAAO;AACZ,UAAM,OAAO,MAAM;AACnB,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACrC,UAAI,KAAK,CAAC,EAAE,aAAa,UAAU;AAClC,aAAK,OAAO,GAAG,CAAC;AAChB;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASO,SAAY,WAAmB,MAAU,QAAuB;AACtE,UAAM,QAAQ,KAAK,YAAY,WAAW,MAAM;AAChD,UAAM,EAAE,MAAM,MAAM,OAAO,IAAI;AAG/B,QAAI,KAAK,UAAU,SAAS,UAAa,CAAC,KAAK,OAAO,IAAI,GAAG;AAC5D,kBAAY,iBAAiB,2BAA2B,SAAS,MAAM,IAAI;AAC3E;AAAA,IACD;AAEA,SAAK,SAAS,OAAO,WAAW,IAAI;AAEpC,UAAM,UAAU,MAAY;AAS3B,iBAAW,SAAS,CAAC,GAAG,IAAI,GAAG;AAC9B,YAAI;AACH,gBAAM,SAAS,IAAI;AAAA,QACpB,SAAS,KAAK;AACb,sBAAY,iBAAiB,4BAA4B,SAAS,MAAM,GAAG;AAAA,QAC5E;AAAA,MACD;AAAA,IACD;AAQA,eAAW,cAAc,CAAC,GAAG,KAAK,WAAW,GAAG;AAC/C,UAAI;AACJ,UAAI;AACH,mBAAW,WAAW,WAAW,IAAI;AAAA,MACtC,SAAS,KAAK;AACb,mBAAW,EAAE,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE;AAAA,MACrE;AAEA,UAAI,aAAa,QAAQ;AACxB,aAAK,YAAY,OAAO,SAAS,IAAI;AACrC,oBAAY;AAAA,UACX,UAAU,SAAS;AAAA,UACnB,SAAS;AAAA,QACV;AACA;AAAA,MACD;AAAA,IACD;AAgBA,UAAM,QAAQ,KAAK,IAAI,mBAAmB,KAAK,MAAM,GAAG,eAAe,IAAI,CAAC;AAC5E,QAAI,QAAQ,GAAG;AACd,aAAO,KAAK,IAAI;AAChB,aAAO,OAAO,SAAS,MAAO,QAAO,MAAM;AAAA,IAC5C,WAAW,OAAO,SAAS,GAAG;AAE7B,aAAO,SAAS;AAAA,IACjB;AAEA,YAAQ;AAAA,EACT;AAAA;AAAA,EAGO,cAAiB,IAAuC;AAC9D,SAAK,YAAY,KAAK,EAAkD;AAAA,EACzE;AAAA;AAAA,EAGO,iBAAoB,IAAuC;AACjE,UAAM,IAAI,KAAK,YAAY,QAAQ,EAAkD;AACrF,QAAI,MAAM,GAAI,MAAK,YAAY,OAAO,GAAG,CAAC;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,aAAa,WAAoB,QAAQ,KAAuB;AACtE,QAAI,WAAW;AACd,aAAO,KAAK,SAAS,IAAI,SAAS,GAAG,KAAK,MAAM,CAAC,KAAK,KAAK,CAAC;AAAA,IAC7D;AACA,UAAM,MAAwB,CAAC;AAC/B,eAAW,EAAE,KAAK,KAAK,KAAK,SAAS,OAAO,EAAG,KAAI,KAAK,GAAG,IAAI;AAC/D,WAAO,IAAI,MAAM,CAAC,KAAK;AAAA,EACxB;AAAA;AAAA,EAGO,WAAW,WAAyB;AAC1C,SAAK,SAAS,OAAO,SAAS;AAC9B,UAAM,IAAI,KAAK,oBAAoB,IAAI,SAAS;AAChD,QAAI,GAAG;AACN,mBAAa,CAAC;AACd,WAAK,oBAAoB,OAAO,SAAS;AAAA,IAC1C;AAAA,EACD;AAAA;AAAA,EAGO,iBAAuB;AAC7B,SAAK,SAAS,MAAM;AACpB,eAAW,KAAK,KAAK,oBAAoB,OAAO,EAAG,cAAa,CAAC;AACjE,SAAK,oBAAoB,MAAM;AAAA,EAChC;AAAA;AAAA,EAGO,QAAc;AACpB,SAAK,eAAe;AACpB,SAAK,cAAc,CAAC;AACpB,SAAK,eAAe;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYQ,YAAY,OAAoB,QAAsB;AAC7D,UAAM,OAAO,MAAM,KAAK,GAAG,EAAE;AAC7B,QAAI,KAAM,MAAK,YAAY;AAAA,EAC5B;AAAA;AAAA,EAGQ,SAAS,OAAoB,WAAmB,MAAqB;AAC5E,QAAI,KAAK,cAAc;AACtB,YAAM,MAAM,MAAM,KAAK,WAAW,KAAK;AACvC,YAAM,OAAO,MAAM;AACnB,YAAM,MAAsB;AAAA,QAC3B;AAAA,QACA,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,QAClC;AAAA,MACD;AACA,UAAI,aAAa,IAAI,MAAM,EAAE;AAC7B,WAAK,KAAK,GAAG;AACb,UAAI,KAAK,SAAS,IAAK,MAAK,MAAM;AAAA,IACnC;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,sBAAsB,WAAmB,OAA0B;AAC1E,QAAI,KAAK,oBAAoB,IAAI,SAAS,EAAG;AAE7C,UAAM,QAAQ,WAAW,MAAM;AAC9B,WAAK,oBAAoB,OAAO,SAAS;AACzC,YAAM,EAAE,QAAQ,KAAK,IAAI;AACzB,UAAI,CAAC,OAAO,OAAQ;AAEpB,YAAM,aAAa,KAAK,OAAO,CAAC,MAAM,EAAE,cAAc,CAAC;AACvD,UAAI,CAAC,WAAW,OAAQ;AAExB,iBAAW,SAAS,YAAY;AAE/B,mBAAW,WAAW,OAAO,MAAM,CAAC,MAAM,WAAW,GAAG;AACvD,cAAI;AACH,kBAAM,SAAS,OAAO;AAAA,UACvB,SAAS,KAAK;AACb,wBAAY;AAAA,cACX,4BAA4B,SAAS;AAAA,cACrC;AAAA,YACD;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAIA,iBAAW,SAAS,WAAY,OAAM,cAAc;AAAA,IACrD,GAAG,CAAC;AAEJ,SAAK,oBAAoB,IAAI,WAAW,KAAK;AAAA,EAC9C;AACD;;;ACzbO,IAAM,4BAA4B,CAAC,aAAmD;AAC5F,QAAM,WAAW,oBAAI,IAAwB;AAE7C,SAAO;AAAA,IACN,IAAI,QAAkC;AACrC,UAAI,SAAS,IAAI,OAAO,IAAI,GAAG;AAI9B,cAAM,IAAI;AAAA,UACT,WAAW,OAAO,IAAI;AAAA,QAEvB;AAAA,MACD;AAEA,YAAM,YAAY,OAAO,QAAQ,QAAQ;AAEzC,YAAM,SAAS,MAAY;AAI1B,YAAI,CAAC,SAAS,IAAI,OAAO,IAAI,EAAG;AAChC,iBAAS,OAAO,OAAO,IAAI;AAC3B,oBAAY;AAAA,MACb;AAEA,eAAS,IAAI,OAAO,MAAM,MAAM;AAChC,aAAO;AAAA,IACR;AAAA,IAEA,YAAkB;AAGjB,iBAAW,UAAU,CAAC,GAAG,SAAS,OAAO,CAAC,EAAG,QAAO;AACpD,eAAS,MAAM;AAAA,IAChB;AAAA,EACD;AACD;;;AC6EA,SAAS,iBACR,UACA,OACsB;AACtB,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA,IAKN,MAAM,MAAM,QAAQ,SAAS;AAAA,IAC7B,OAAO,EAAE,GAAG,SAAS,OAAO,GAAG,MAAM,MAAM;AAAA,EAC5C;AACD;AAkBO,SAAS,YAAY,QAA8C;AACzE,MAAI,gBAAqC;AAAA,IACxC,CAAC;AAAA,IACD,EAAE,MAAM,OAAO,MAAM,OAAO,OAAO,MAAM;AAAA,EAC1C;AACA,MAAI,eAAe;AAEnB,QAAM,WAAW,IAAI,sBAAsB;AAC3C,QAAM,YAAY,IAAI,uBAAuB;AAC7C,QAAM,aAAa,IAAI,wBAAwB;AAC/C,QAAM,WAAW,sBAAsB;AACvC,QAAM,gBAAgB;AAAA,IACrB,cAAc;AAAA,IACd,aAAa,oBAAI,QAA0B;AAAA,EAC5C;AACA,QAAM,SAAS,oBAAI,IAAiB;AACpC,QAAM,oBAA+C,CAAC;AACtD,MAAI;AAEJ,QAAM,WAAW;AAAA,IAChB,UAAU,IAAI,oBAAoB;AAAA,IAClC,WAAW,IAAI,qBAAqB;AAAA,IACpC,YAAY,IAAI,sBAAsB;AAAA,IACtC,cAAc,IAAI,wBAAwB;AAAA,EAC3C;AAEA,QAAM,WAA2B;AAAA,IAChC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,IAAI,mBAAmB;AACtB,aAAO;AAAA,IACR;AAAA,IACA,qBAAqB,YAAiD;AACrE,wBAAkB,KAAK,UAAU;AACjC,aAAO,MAAM;AACZ,cAAM,KAAK,kBAAkB,QAAQ,UAAU;AAC/C,YAAI,OAAO,GAAI,mBAAkB,OAAO,IAAI,CAAC;AAAA,MAC9C;AAAA,IACD;AAAA,IACA,kBAAkB,WAAqC;AACtD,yBAAmB;AAAA,IACpB;AAAA,IACA,QAAmB,cAAiC;AACnD,aAAO,SAAS,WAAW,IAAI,YAAY;AAAA,IAC5C;AAAA,IACA,IAAI,QAAkC;AACrC,aAAO,QAAQ,IAAI,MAAM;AAAA,IAC1B;AAAA,IACA,cAA2B;AAC1B,YAAM,QAAQ,iBAAiB,SAAS,UAAU;AAClD,aAAO,IAAI,KAAK;AAChB,aAAO;AAAA,IACR;AAAA,IACA,IAAI,SAAS;AACZ,aAAO;AAAA,IACR;AAAA,IACA,UAAU,OAAkC;AAC3C,sBAAgB,iBAAiB,eAAe,KAAK;AAAA,IACtD;AAAA,IACA,WAAwB;AACvB,aAAO,cAAc,SAAS,CAAC;AAAA,IAChC;AAAA,IACA,iBAA0B;AACzB,aAAO;AAAA,IACR;AAAA,IACA,WAAiB;AAChB,uBAAiB,QAAQ;AAAA,IAC1B;AAAA,IACA,UAAgB;AACf,eAAS;AACT,wBAAkB,SAAS;AAC3B,yBAAmB;AACnB,qBAAe;AAAA,IAChB;AAAA,IACA,MAAM,UAAU,kBAAyC,CAAC,GAAkB;AAC3E,UAAI,cAAc;AACjB,oBAAY,kBAAkB,4BAA4B;AAC1D;AAAA,MACD;AACA,eAAS,SAAS;AAClB,kBAAY,kBAAkB,uBAAuB;AAErD,YAAM,OAAO,oBAAoB,eAAe;AAEhD,YAAM,cAAc,KAAK,WAAW,YAAY;AAChD,YAAM,YAAY,KAAK,YAAY,aAAa;AAChD,YAAM,cAAc,KAAK,gBAAgB,mCAAmC;AAE5E,qBAAe;AACf,kBAAY,kBAAkB,wBAAwB;AAAA,IACvD;AAAA,EACD;AAWA,WAAS,WAAiB;AACzB,eAAW,SAAS,OAAQ,OAAM,QAAQ;AAC1C,WAAO,MAAM;AAEb,YAAQ,UAAU;AAElB,eAAW,SAAS;AACpB,cAAU,MAAM;AAChB,aAAS,MAAM;AAEf,aAAS,SAAS,WAAW;AAC7B,aAAS,UAAU,WAAW;AAC9B,aAAS,WAAW,WAAW;AAC/B,aAAS,aAAa,WAAW;AAEjC,kBAAc,eAAe;AAC7B,kBAAc,cAAc,oBAAI,QAA0B;AAE1D,QAAI,iBAAiB,MAAM,SAAU,kBAAiB,IAAI;AAAA,EAC3D;AAEA,QAAM,UAAU,0BAA0B,QAAQ;AAElD,WAAS,SAAS;AAIlB,yBAAuB,wBAAwB;AAE/C,SAAO;AACR;AAEA,SAAS,oBAAoB,QAA+B;AAC3D,QAAM,YAA8B,CAAC;AACrC,QAAM,aAA+B,CAAC;AACtC,QAAM,iBAAmC,CAAC;AAE1C,SAAO,UAAU,QAAQ,CAAC,SAAS,UAAU;AAC5C,UAAM,OAAuB;AAAA,MAC5B,MAAM,QAAQ,QAAQ,WAAW,QAAQ,CAAC;AAAA,MAC1C,UAAU,QAAQ,YAAY;AAAA,MAC9B,UAAU,QAAQ,YAAY;AAAA,MAC9B,WAAW,QAAQ;AAAA,MACnB,SAAS,QAAQ;AAAA,IAClB;AAEA,QAAI,QAAQ,KAAM,WAAU,KAAK,IAAI;AAAA,QAChC,YAAW,KAAK,IAAI;AAAA,EAC1B,CAAC;AAMD,QAAM,eAAe,OAAO,WAAW,QAAQ;AAC/C,QAAM,eAA+B;AAAA,IACpC,MAAM;AAAA,IACN,UAAU,OAAO,WAAW,YAAY;AAAA;AAAA;AAAA;AAAA,IAIxC,UAAU;AAAA,IACV,SAAS,MAAM;AACd,6BAAuB,UAAU;AAAA,IAClC;AAAA,EACD;AAEA,MAAI,aAAc,WAAU,KAAK,YAAY;AAAA,MACxC,gBAAe,KAAK,YAAY;AAErC,YAAU,KAAK,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,QAAQ;AAEhD,SAAO,EAAE,WAAW,YAAY,eAAe;AAChD;AASA,eAAe,gBAAgB,MAAqC;AACnE,MAAI,KAAK,cAAc,QAAW;AACjC,UAAM,KAAK,QAAQ;AACnB;AAAA,EACD;AAEA,MAAI;AACJ,MAAI;AACH,UAAM,QAAQ,KAAK;AAAA,MAClB,QAAQ,QAAQ,KAAK,QAAQ,CAAC;AAAA,MAC9B,IAAI,QAAe,CAAC,UAAU,WAAW;AACxC,gBAAQ;AAAA,UACP,MACC;AAAA,YACC,IAAI;AAAA,cACH,YAAY,KAAK,IAAI,2BAA2B,OAAO,KAAK,SAAS,CAAC;AAAA,YACvE;AAAA,UACD;AAAA,UACD,KAAK;AAAA,QACN;AAAA,MACD,CAAC;AAAA,IACF,CAAC;AAAA,EACF,UAAE;AACD,QAAI,UAAU,OAAW,cAAa,KAAK;AAAA,EAC5C;AACD;AAQA,SAAS,kBAAkB,MAAsB,WAAmB,OAAsB;AACzF,cAAY,kBAAkB,IAAI,SAAS,cAAc,KAAK,IAAI,IAAI,YAAY,KAAK,CAAC;AACxF,MAAI,CAAC,KAAK,SAAU,OAAM;AAC1B,cAAY,kBAAkB,IAAI,SAAS,yBAAyB,KAAK,IAAI,EAAE;AAChF;AAEA,eAAe,cAAc,OAAyB,WAAkC;AACvF,MAAI,MAAM,WAAW,EAAG;AAExB,aAAW,QAAQ,OAAO;AACzB,QAAI;AACH,kBAAY;AAAA,QACX,IAAI,SAAS,gBAAgB,KAAK,IAAI,eAAe,OAAO,KAAK,QAAQ,CAAC;AAAA,MAC3E;AACA,YAAM,gBAAgB,IAAI;AAAA,IAC3B,SAAS,OAAO;AACf,wBAAkB,MAAM,WAAW,KAAK;AAAA,IACzC;AAAA,EACD;AACD;AAEA,eAAe,YAAY,OAAyB,WAAkC;AACrF,MAAI,MAAM,WAAW,EAAG;AAExB,cAAY;AAAA,IACX,IAAI,SAAS,eAAe,OAAO,MAAM,MAAM,CAAC;AAAA,EACjD;AAKA,QAAM,WAAW,MAAM,QAAQ;AAAA,IAC9B,MAAM,IAAI,OAAO,SAAS;AACzB,kBAAY,kBAAkB,IAAI,SAAS,gBAAgB,KAAK,IAAI,EAAE;AACtE,YAAM,gBAAgB,IAAI;AAAA,IAC3B,CAAC;AAAA,EACF;AAEA,aAAW,CAAC,OAAO,OAAO,KAAK,SAAS,QAAQ,GAAG;AAClD,QAAI,QAAQ,WAAW,YAAY;AAClC,wBAAkB,MAAM,KAAK,GAAG,WAAW,QAAQ,MAAM;AAAA,IAC1D;AAAA,EACD;AACD;AAEA,SAAS,YAAY,OAAwB;AAC5C,SAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC7D;;;ACvaA,IAAM,SAAS,CAAC,WACf,OAAO,QAAQ,gBAAgB,EAAE,YAAY,OAAO,YAAY,GAAG,OAAO,SAAS,CAAC;AA4B9E,IAAM,aAAa,OAAO,SAA4B,CAAC,MAA+B;AAC5F,QAAM,QAAQ,YAAY,EAAE,MAAM,OAAO,MAAM,GAAG,OAAO,OAAO,MAAM,CAAC;AAEvE,aAAW,UAAU,OAAO,WAAW,CAAC,EAAG,OAAM,IAAI,MAAM;AAE3D,QAAM,MAAM,UAAU,EAAE,UAAU,OAAO,UAAU,WAAW,OAAO,UAAU,CAAC;AAEhF,SAAO;AACR;;;AClCO,SAAS,mBAAyB;AACxC,QAAM,SAAS,iBAAiB;AAChC,MAAI,CAAC,OAAQ;AAEb,SAAO,WAAW,SAAS;AAC3B,SAAO,UAAU,MAAM;AACvB,SAAO,SAAS,eAAe;AAC/B,SAAO,cAAc,eAAe;AACpC,SAAO,cAAc,cAAc,oBAAI,QAA0B;AAClE;;;ACHO,IAAe,eAAf,MAAoD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAahD,cAAoB;AAAA,EAE9B;AAAA,EAEO,QAAQ,OAAmC;AACjD,SAAK,UAAU,KAAK;AAEpB,WAAO,MAAM;AACZ,WAAK,YAAY;AAAA,IAClB;AAAA,EACD;AACD;","names":[]}
|
|
@@ -2,9 +2,8 @@ import {
|
|
|
2
2
|
ALankaScenario,
|
|
3
3
|
LankaScenarioVMRegistry,
|
|
4
4
|
LankaScenariosRegistry,
|
|
5
|
-
Scenarios_exports,
|
|
6
5
|
lankaEventBus
|
|
7
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-YXI4OQEV.js";
|
|
8
7
|
import {
|
|
9
8
|
lankaLogger
|
|
10
9
|
} from "./chunk-C2HP7CRD.js";
|
|
@@ -14,6 +13,7 @@ import {
|
|
|
14
13
|
} from "./chunk-BGVDPDX4.js";
|
|
15
14
|
|
|
16
15
|
// src/scenario/lanka-scenario-bootstrap/LankaScenarioBootstrap.ts
|
|
16
|
+
import * as ScenariosModule from "@lanka_di/Scenarios";
|
|
17
17
|
var LankaScenarioBootstrap = class {
|
|
18
18
|
/**
|
|
19
19
|
* The bootstrapped flag and the set of initialised VMs live on the INSTANCE.
|
|
@@ -29,7 +29,7 @@ var LankaScenarioBootstrap = class {
|
|
|
29
29
|
return this.state.bootstrapped;
|
|
30
30
|
}
|
|
31
31
|
forceInstantiateAllScenarios() {
|
|
32
|
-
for (const exported of Object.values(
|
|
32
|
+
for (const exported of Object.values(ScenariosModule)) {
|
|
33
33
|
if (typeof exported !== "function") continue;
|
|
34
34
|
try {
|
|
35
35
|
new exported();
|
|
@@ -173,4 +173,4 @@ var lankaScenarioBootstrap = new LankaScenarioBootstrap();
|
|
|
173
173
|
export {
|
|
174
174
|
lankaScenarioBootstrap
|
|
175
175
|
};
|
|
176
|
-
//# sourceMappingURL=chunk-
|
|
176
|
+
//# sourceMappingURL=chunk-HZAIAGWS.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/scenario/lanka-scenario-bootstrap/LankaScenarioBootstrap.ts"],"sourcesContent":["import type { ILankaScenario } from \"../_interfaces/ILankaScenario\";\nimport type { ILankaScenarioVM } from \"../_interfaces/ILankaScenarioVM\";\nimport { LankaScenariosRegistry } from \"../_registries/lanka-scenarios-registry/LankaScenariosRegistry\";\nimport { LankaScenarioVMRegistry } from \"../_registries/lanka-scenario-vm-registry/LankaScenarioVMRegistry\";\nimport { ALankaScenario } from \"../_abstractions/lanka-scenario/ALankaScenario\";\nimport { lankaLogger } from \"../../logger/lanka-logger/LankaLogger\";\n\n/**\n * Brings up the scenario layer — deliberately React-free.\n *\n * Two jobs: declare every scenario's events on the bus as early as possible,\n * before the first ViewModel exists; and let a ViewModel raise its own\n * subscriptions at construction.\n *\n * Called from the application entry point before ViewModels are imported.\n */\n\n// The barrel of every scenario class: what keeps bootstrap in step with the list.\nimport * as ScenariosModule from \"@lanka_di/Scenarios\";\nimport { lankaEventBus } from \"../event-bus/_facades/lanka-event-bus/lankaEventBus\";\nimport {\n\tgetActiveRuntime,\n\trequireActiveRuntime,\n} from \"../../_internal/active-runtime/activeRuntime\";\n\n/**\n * Bootstrapping the scenario layer, for callers with no instance in hand.\n *\n * An ordinary class with an ordinary instance: the declared-ViewModel list below\n * is deliberately shared across instances — every test builds a new framework and\n * module-level ViewModels are declared once — so the single instance IS the\n * shared list, and a second one would be a second list nobody adopts.\n */\nexport class LankaScenarioBootstrap {\n\t/**\n\t * The bootstrapped flag and the set of initialised VMs live on the INSTANCE.\n\t *\n\t * As static fields, a second framework in the same process would exit\n\t * `bootstrap()` on someone else's flag — never starting at all, with no symptom\n\t * except that no scenario works.\n\t */\n\tprivate get state() {\n\t\treturn requireActiveRuntime().scenarioState;\n\t}\n\n\tpublic isScenarioLayerBootstrapped(): boolean {\n\t\treturn this.state.bootstrapped;\n\t}\n\n\tprivate forceInstantiateAllScenarios(): void {\n\t\tfor (const exported of Object.values(ScenariosModule)) {\n\t\t\t// Only class constructors are relevant.\n\t\t\tif (typeof exported !== \"function\") continue;\n\n\t\t\ttry {\n\t\t\t\t// Constructing an ALankaScenario subclass puts it into the\n\t\t\t\t// self-registration pool — see ALankaScenario.\n\t\t\t\tnew (exported as unknown as new () => unknown)();\n\t\t\t} catch {\n\t\t\t\t// Not every export is constructible; skip those.\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate registerScenarioEvents(scenarios: ILankaScenario<unknown>[]): void {\n\t\tconst registeredEventTypes = new Set<string>();\n\n\t\tscenarios.forEach((scenario) => {\n\t\t\tif (!registeredEventTypes.has(scenario.eventType)) {\n\t\t\t\tregisteredEventTypes.add(scenario.eventType);\n\n\t\t\t\tlankaLogger.printScenarioLog(\"REGISTER SCENARIO EVENT\", scenario.name);\n\t\t\t\tlankaEventBus.registerEvent(scenario.eventType, {\n\t\t\t\t\tdataType: scenario.dataTypeName,\n\t\t\t\t\tdescription: `Scenario: ${scenario.name}`,\n\t\t\t\t\tusedBy: [scenario.name],\n\t\t\t\t\tpriority: 0,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (scenario.initialize) {\n\t\t\t\tlankaLogger.printScenarioLog(\"INITIALIZE SCENARIO\", scenario.name);\n\t\t\t\tscenario.initialize();\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate initializeAlreadyCreatedViewModels(): void {\n\t\tconst viewModels = LankaScenarioVMRegistry.getInstance().getAllViewModels();\n\t\tviewModels.forEach((vm) => {\n\t\t\tif (!this.state.initialized.has(vm)) {\n\t\t\t\tthis.state.initialized.add(vm);\n\t\t\t\tvm.initializeScenario();\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Brings up the scenario layer.\n\t *\n\t * Constructs the scenario classes so they can be collected, declares their\n\t * events on the bus, calls `initialize()` where present, and initialises\n\t * ViewModels that already exist — which happens in tests and under unusual\n\t * import order.\n\t *\n\t * Idempotent.\n\t */\n\tpublic bootstrap(): void {\n\t\tif (this.state.bootstrapped) return;\n\n\t\tlankaLogger.printScenarioLog(\"BOOTSTRAP SCENARIOS START\");\n\n\t\t// Instances must exist, or the registry has nothing to collect.\n\t\tthis.forceInstantiateAllScenarios();\n\n\t\tconst registry = LankaScenariosRegistry.getInstance();\n\t\tregistry.collectAutoRegisteredScenarios();\n\n\t\tconst scenarios = registry.getAllScenarios();\n\t\tthis.registerScenarioEvents(scenarios);\n\n\t\tthis.state.bootstrapped = true;\n\n\t\t// Some ViewModels may predate bootstrap — in tests, or under unusual import\n\t\t// order; initialise them now.\n\t\tthis.initializeAlreadyCreatedViewModels();\n\n\t\tlankaLogger.printScenarioLog(\"BOOTSTRAP SCENARIOS FINISH\");\n\t}\n\n\t/**\n\t * Called by a ViewModel factory when the ViewModel declares scenario handlers.\n\t *\n\t * Registers the ViewModel and, if the layer is already up, initialises it\n\t * immediately. Duplicate registration and duplicate initialisation are\n\t * impossible.\n\t *\n\t * @param viewModel What to register\n\t * @param name Name for the log\n\t */\n\t/**\n\t * ViewModels DECLARED in this process.\n\t *\n\t * Module-level deliberately, the same case as the scenario pool: a registry of\n\t * DEFINITIONS, not runtime state. Splitting it between instances would be\n\t * divergence, not isolation — the classes come from the same modules and both\n\t * instances must see one list.\n\t *\n\t * Two reasons it exists:\n\t *\n\t * 1. Declaring a ViewModel is a declaration, not work. A screen file creates it\n\t * at module level, and import order decides whether that happens before or\n\t * after `createLanka()`. Requiring a live instance at declaration time\n\t * requires an import order the consumer does not control.\n\t * 2. Instances come one after another: every test creates its own. The list is\n\t * NOT drained by the first — otherwise the second instance would know no\n\t * module-level ViewModel and its `dispose()` would not remove their\n\t * subscriptions, so a test would receive events the previous one subscribed\n\t * to.\n\t */\n\tprivate readonly declaredViewModels: { viewModel: ILankaScenarioVM; name?: string }[] = [];\n\n\t/** Registers everything declared into a NEW instance. Called by `createLanka`. */\n\tpublic adoptDeclaredViewModels(): void {\n\t\tfor (const { viewModel, name } of [...this.declaredViewModels]) {\n\t\t\tthis.attachViewModel(viewModel, name);\n\t\t}\n\t}\n\n\tpublic registerViewModel(viewModel: ILankaScenarioVM, name?: string): void {\n\t\tconst isKnown = this.declaredViewModels.some(\n\t\t\t(declared) => declared.viewModel === viewModel,\n\t\t);\n\t\tif (!isKnown) this.declaredViewModels.push({ viewModel, name });\n\n\t\t// No instance yet: the declaration came before bootstrap, and whoever\n\t\t// bootstraps will pick it up.\n\t\tif (!getActiveRuntime()) return;\n\n\t\tthis.attachViewModel(viewModel, name);\n\t}\n\n\tprivate attachViewModel(viewModel: ILankaScenarioVM, name?: string): void {\n\t\tconst registry = LankaScenarioVMRegistry.getInstance();\n\n\t\t// Already registered — nothing to do.\n\t\tif (registry.isRegistered(viewModel)) {\n\t\t\tif (name) {\n\t\t\t\tlankaLogger.printViewModelLog(\"VM Already Registered (skipped)\", name);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Register it.\n\t\tregistry.register(viewModel);\n\n\t\tif (name) {\n\t\t\tlankaLogger.printViewModelLog(\"Register Scenario VM\", name);\n\t\t}\n\n\t\t// The layer is already up — initialise it now rather than at the next\n\t\t// bootstrap.\n\t\tif (this.state.bootstrapped) {\n\t\t\tif (!this.state.initialized.has(viewModel)) {\n\t\t\t\tthis.state.initialized.add(viewModel);\n\t\t\t\tviewModel.initializeScenario();\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Resets the whole scenario layer. Without it tests are not isolated.\n\t *\n\t * Clears the self-registration list, the scenario registry with its metadata,\n\t * the ViewModel registry together with all their subscriptions, and the bus —\n\t * events and\n\t * middleware.\n\t */\n\tpublic reset(): void {\n\t\tALankaScenario.clearAutoRegisteredScenarios();\n\t\tLankaScenariosRegistry.getInstance().clear();\n\t\tLankaScenarioVMRegistry.getInstance().resetAll();\n\t\tlankaEventBus.clearAllEvents();\n\t\tthis.state.bootstrapped = false;\n\t\tthis.state.initialized = new WeakSet<ILankaScenarioVM>();\n\t}\n}\n\n/** The one every caller wants. */\nexport const lankaScenarioBootstrap = new LankaScenarioBootstrap();\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/scenario/lanka-scenario-bootstrap/LankaScenarioBootstrap.ts"],"sourcesContent":["import type { ILankaScenario } from \"../_interfaces/ILankaScenario\";\nimport type { ILankaScenarioVM } from \"../_interfaces/ILankaScenarioVM\";\nimport { LankaScenariosRegistry } from \"../_registries/lanka-scenarios-registry/LankaScenariosRegistry\";\nimport { LankaScenarioVMRegistry } from \"../_registries/lanka-scenario-vm-registry/LankaScenarioVMRegistry\";\nimport { ALankaScenario } from \"../_abstractions/lanka-scenario/ALankaScenario\";\nimport { lankaLogger } from \"../../logger/lanka-logger/LankaLogger\";\n\n/**\n * Brings up the scenario layer — deliberately React-free.\n *\n * Two jobs: declare every scenario's events on the bus as early as possible,\n * before the first ViewModel exists; and let a ViewModel raise its own\n * subscriptions at construction.\n *\n * Called from the application entry point before ViewModels are imported.\n */\n\n// The barrel of every scenario class: what keeps bootstrap in step with the list.\nimport * as ScenariosModule from \"@lanka_di/Scenarios\";\nimport { lankaEventBus } from \"../event-bus/_facades/lanka-event-bus/lankaEventBus\";\nimport {\n\tgetActiveRuntime,\n\trequireActiveRuntime,\n} from \"../../_internal/active-runtime/activeRuntime\";\n\n/**\n * Bootstrapping the scenario layer, for callers with no instance in hand.\n *\n * An ordinary class with an ordinary instance: the declared-ViewModel list below\n * is deliberately shared across instances — every test builds a new framework and\n * module-level ViewModels are declared once — so the single instance IS the\n * shared list, and a second one would be a second list nobody adopts.\n */\nexport class LankaScenarioBootstrap {\n\t/**\n\t * The bootstrapped flag and the set of initialised VMs live on the INSTANCE.\n\t *\n\t * As static fields, a second framework in the same process would exit\n\t * `bootstrap()` on someone else's flag — never starting at all, with no symptom\n\t * except that no scenario works.\n\t */\n\tprivate get state() {\n\t\treturn requireActiveRuntime().scenarioState;\n\t}\n\n\tpublic isScenarioLayerBootstrapped(): boolean {\n\t\treturn this.state.bootstrapped;\n\t}\n\n\tprivate forceInstantiateAllScenarios(): void {\n\t\tfor (const exported of Object.values(ScenariosModule)) {\n\t\t\t// Only class constructors are relevant.\n\t\t\tif (typeof exported !== \"function\") continue;\n\n\t\t\ttry {\n\t\t\t\t// Constructing an ALankaScenario subclass puts it into the\n\t\t\t\t// self-registration pool — see ALankaScenario.\n\t\t\t\tnew (exported as unknown as new () => unknown)();\n\t\t\t} catch {\n\t\t\t\t// Not every export is constructible; skip those.\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate registerScenarioEvents(scenarios: ILankaScenario<unknown>[]): void {\n\t\tconst registeredEventTypes = new Set<string>();\n\n\t\tscenarios.forEach((scenario) => {\n\t\t\tif (!registeredEventTypes.has(scenario.eventType)) {\n\t\t\t\tregisteredEventTypes.add(scenario.eventType);\n\n\t\t\t\tlankaLogger.printScenarioLog(\"REGISTER SCENARIO EVENT\", scenario.name);\n\t\t\t\tlankaEventBus.registerEvent(scenario.eventType, {\n\t\t\t\t\tdataType: scenario.dataTypeName,\n\t\t\t\t\tdescription: `Scenario: ${scenario.name}`,\n\t\t\t\t\tusedBy: [scenario.name],\n\t\t\t\t\tpriority: 0,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (scenario.initialize) {\n\t\t\t\tlankaLogger.printScenarioLog(\"INITIALIZE SCENARIO\", scenario.name);\n\t\t\t\tscenario.initialize();\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate initializeAlreadyCreatedViewModels(): void {\n\t\tconst viewModels = LankaScenarioVMRegistry.getInstance().getAllViewModels();\n\t\tviewModels.forEach((vm) => {\n\t\t\tif (!this.state.initialized.has(vm)) {\n\t\t\t\tthis.state.initialized.add(vm);\n\t\t\t\tvm.initializeScenario();\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Brings up the scenario layer.\n\t *\n\t * Constructs the scenario classes so they can be collected, declares their\n\t * events on the bus, calls `initialize()` where present, and initialises\n\t * ViewModels that already exist — which happens in tests and under unusual\n\t * import order.\n\t *\n\t * Idempotent.\n\t */\n\tpublic bootstrap(): void {\n\t\tif (this.state.bootstrapped) return;\n\n\t\tlankaLogger.printScenarioLog(\"BOOTSTRAP SCENARIOS START\");\n\n\t\t// Instances must exist, or the registry has nothing to collect.\n\t\tthis.forceInstantiateAllScenarios();\n\n\t\tconst registry = LankaScenariosRegistry.getInstance();\n\t\tregistry.collectAutoRegisteredScenarios();\n\n\t\tconst scenarios = registry.getAllScenarios();\n\t\tthis.registerScenarioEvents(scenarios);\n\n\t\tthis.state.bootstrapped = true;\n\n\t\t// Some ViewModels may predate bootstrap — in tests, or under unusual import\n\t\t// order; initialise them now.\n\t\tthis.initializeAlreadyCreatedViewModels();\n\n\t\tlankaLogger.printScenarioLog(\"BOOTSTRAP SCENARIOS FINISH\");\n\t}\n\n\t/**\n\t * Called by a ViewModel factory when the ViewModel declares scenario handlers.\n\t *\n\t * Registers the ViewModel and, if the layer is already up, initialises it\n\t * immediately. Duplicate registration and duplicate initialisation are\n\t * impossible.\n\t *\n\t * @param viewModel What to register\n\t * @param name Name for the log\n\t */\n\t/**\n\t * ViewModels DECLARED in this process.\n\t *\n\t * Module-level deliberately, the same case as the scenario pool: a registry of\n\t * DEFINITIONS, not runtime state. Splitting it between instances would be\n\t * divergence, not isolation — the classes come from the same modules and both\n\t * instances must see one list.\n\t *\n\t * Two reasons it exists:\n\t *\n\t * 1. Declaring a ViewModel is a declaration, not work. A screen file creates it\n\t * at module level, and import order decides whether that happens before or\n\t * after `createLanka()`. Requiring a live instance at declaration time\n\t * requires an import order the consumer does not control.\n\t * 2. Instances come one after another: every test creates its own. The list is\n\t * NOT drained by the first — otherwise the second instance would know no\n\t * module-level ViewModel and its `dispose()` would not remove their\n\t * subscriptions, so a test would receive events the previous one subscribed\n\t * to.\n\t */\n\tprivate readonly declaredViewModels: { viewModel: ILankaScenarioVM; name?: string }[] = [];\n\n\t/** Registers everything declared into a NEW instance. Called by `createLanka`. */\n\tpublic adoptDeclaredViewModels(): void {\n\t\tfor (const { viewModel, name } of [...this.declaredViewModels]) {\n\t\t\tthis.attachViewModel(viewModel, name);\n\t\t}\n\t}\n\n\tpublic registerViewModel(viewModel: ILankaScenarioVM, name?: string): void {\n\t\tconst isKnown = this.declaredViewModels.some(\n\t\t\t(declared) => declared.viewModel === viewModel,\n\t\t);\n\t\tif (!isKnown) this.declaredViewModels.push({ viewModel, name });\n\n\t\t// No instance yet: the declaration came before bootstrap, and whoever\n\t\t// bootstraps will pick it up.\n\t\tif (!getActiveRuntime()) return;\n\n\t\tthis.attachViewModel(viewModel, name);\n\t}\n\n\tprivate attachViewModel(viewModel: ILankaScenarioVM, name?: string): void {\n\t\tconst registry = LankaScenarioVMRegistry.getInstance();\n\n\t\t// Already registered — nothing to do.\n\t\tif (registry.isRegistered(viewModel)) {\n\t\t\tif (name) {\n\t\t\t\tlankaLogger.printViewModelLog(\"VM Already Registered (skipped)\", name);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Register it.\n\t\tregistry.register(viewModel);\n\n\t\tif (name) {\n\t\t\tlankaLogger.printViewModelLog(\"Register Scenario VM\", name);\n\t\t}\n\n\t\t// The layer is already up — initialise it now rather than at the next\n\t\t// bootstrap.\n\t\tif (this.state.bootstrapped) {\n\t\t\tif (!this.state.initialized.has(viewModel)) {\n\t\t\t\tthis.state.initialized.add(viewModel);\n\t\t\t\tviewModel.initializeScenario();\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Resets the whole scenario layer. Without it tests are not isolated.\n\t *\n\t * Clears the self-registration list, the scenario registry with its metadata,\n\t * the ViewModel registry together with all their subscriptions, and the bus —\n\t * events and\n\t * middleware.\n\t */\n\tpublic reset(): void {\n\t\tALankaScenario.clearAutoRegisteredScenarios();\n\t\tLankaScenariosRegistry.getInstance().clear();\n\t\tLankaScenarioVMRegistry.getInstance().resetAll();\n\t\tlankaEventBus.clearAllEvents();\n\t\tthis.state.bootstrapped = false;\n\t\tthis.state.initialized = new WeakSet<ILankaScenarioVM>();\n\t}\n}\n\n/** The one every caller wants. */\nexport const lankaScenarioBootstrap = new LankaScenarioBootstrap();\n"],"mappings":"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","names":[]}
|
|
@@ -1,31 +1,29 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ALankaScenario,
|
|
3
|
-
LankaScenariosRegistry
|
|
4
|
-
|
|
5
|
-
} from "./chunk-EWVDJYCC.js";
|
|
3
|
+
LankaScenariosRegistry
|
|
4
|
+
} from "./chunk-YXI4OQEV.js";
|
|
6
5
|
import {
|
|
7
6
|
ALankaLocator,
|
|
8
7
|
caseConvert,
|
|
9
8
|
findExportedClass
|
|
10
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-UE2C76OR.js";
|
|
11
10
|
import {
|
|
12
11
|
lankaLogger
|
|
13
12
|
} from "./chunk-C2HP7CRD.js";
|
|
14
13
|
|
|
15
|
-
// ../tools/testing/_fixtures/.lanka_di/Gateways.ts
|
|
16
|
-
var Gateways_exports = {};
|
|
17
|
-
|
|
18
14
|
// src/locator/gateway/lanka-gateway-locator/LankaGatewayLocator.ts
|
|
15
|
+
import * as GatewaysModule from "@lanka_di/Gateways";
|
|
19
16
|
var LankaGatewayLocator = class extends ALankaLocator {
|
|
20
17
|
constructor() {
|
|
21
18
|
super({
|
|
22
|
-
findClassByName: (gatewayName) => findExportedClass(
|
|
19
|
+
findClassByName: (gatewayName) => findExportedClass(GatewaysModule, gatewayName),
|
|
23
20
|
notFoundError: (gatewayName, propertyName) => `Gateway "${gatewayName}" (accessed as "${propertyName}") not found. Make sure the gateway class extends ALankaGateway and is exported from lankaGateways.ts.`
|
|
24
21
|
});
|
|
25
22
|
}
|
|
26
23
|
};
|
|
27
24
|
|
|
28
25
|
// src/locator/scenario/lanka-scenario-locator/LankaScenarioLocator.ts
|
|
26
|
+
import * as ScenariosModule from "@lanka_di/Scenarios";
|
|
29
27
|
var LankaScenarioLocator = class extends ALankaLocator {
|
|
30
28
|
/**
|
|
31
29
|
* The registry is read LAZILY rather than in a field initialiser.
|
|
@@ -42,13 +40,13 @@ var LankaScenarioLocator = class extends ALankaLocator {
|
|
|
42
40
|
constructor() {
|
|
43
41
|
super({
|
|
44
42
|
findClassByName: (scenarioName) => {
|
|
45
|
-
if (scenarioName in
|
|
46
|
-
const ScenarioClass =
|
|
43
|
+
if (scenarioName in ScenariosModule) {
|
|
44
|
+
const ScenarioClass = ScenariosModule[scenarioName];
|
|
47
45
|
if (typeof ScenarioClass === "function" && "prototype" in ScenarioClass && ScenarioClass.prototype) {
|
|
48
46
|
return ScenarioClass;
|
|
49
47
|
}
|
|
50
48
|
}
|
|
51
|
-
for (const value of Object.values(
|
|
49
|
+
for (const value of Object.values(ScenariosModule)) {
|
|
52
50
|
if (typeof value === "function" && value.prototype) {
|
|
53
51
|
try {
|
|
54
52
|
const instance = new value();
|
|
@@ -133,4 +131,4 @@ export {
|
|
|
133
131
|
LankaScenarioLocator,
|
|
134
132
|
createLankaScope
|
|
135
133
|
};
|
|
136
|
-
//# sourceMappingURL=chunk-
|
|
134
|
+
//# sourceMappingURL=chunk-MYZQYOMD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/locator/gateway/lanka-gateway-locator/LankaGatewayLocator.ts","../src/locator/scenario/lanka-scenario-locator/LankaScenarioLocator.ts","../src/locator/_factories/create-lanka-scope/createLankaScope.ts"],"sourcesContent":["import * as GatewaysModule from \"@lanka_di/Gateways\";\nimport type { ALankaGateway } from \"../../../gateway/_abstractions/lanka-gateway/ALankaGateway\";\nimport { ALankaLocator } from \"../../_abstractions/lanka-locator/ALankaLocator\";\nimport { findExportedClass } from \"../../_internal/find-exported-class/findExportedClass\";\n\n/**\n * Resolves a gateway by property name (camelCase) or class name (PascalCase),\n * constructing it lazily and caching the instance.\n *\n * Adding a gateway takes one export line in `@lanka_di/Gateways`: types are\n * inferred and nothing is registered.\n */\nexport class LankaGatewayLocator extends ALankaLocator<ALankaGateway<unknown>> {\n\tconstructor() {\n\t\tsuper({\n\t\t\tfindClassByName: (gatewayName: string) =>\n\t\t\t\tfindExportedClass<ALankaGateway<unknown>>(GatewaysModule, gatewayName),\n\t\t\tnotFoundError: (gatewayName, propertyName) =>\n\t\t\t\t`Gateway \"${gatewayName}\" (accessed as \"${propertyName}\") not found. ` +\n\t\t\t\t`Make sure the gateway class extends ALankaGateway and is exported from lankaGateways.ts.`,\n\t\t});\n\t}\n}\n","import { LankaScenariosRegistry } from \"../../../scenario/_registries/lanka-scenarios-registry/LankaScenariosRegistry\";\nimport { ILankaScenario } from \"../../../scenario/_interfaces/ILankaScenario\";\nimport { ALankaScenario } from \"../../../scenario/_abstractions/lanka-scenario/ALankaScenario\";\nimport { ALankaLocator } from \"../../_abstractions/lanka-locator/ALankaLocator\";\n/**\n * Classes come from the consumer's barrel.\n *\n * Adding one is ONE export line: types are inferred, autocomplete works, and no\n * list has to be maintained.\n */\nimport * as ScenariosModule from \"@lanka_di/Scenarios\";\n\n/**\n * Resolves scenarios by property name (camelCase) or scenario name\n * (PascalCase).\n *\n * Looks in the registry, then in the self-registration pool, and failing both\n * constructs the scenario from the consumer's barrel on first use.\n */\nexport class LankaScenarioLocator extends ALankaLocator<ILankaScenario<unknown>> {\n\t/**\n\t * The registry is read LAZILY rather than in a field initialiser.\n\t *\n\t * The locator is constructed INSIDE `createLanka`, before the instance becomes\n\t * active. A field initialiser would ask for the active instance at that moment\n\t * and fail with \"no instance yet\" while the instance being created is on the\n\t * stack. Deferred reading resolves it: by the first scenario resolution an\n\t * active instance exists.\n\t */\n\tprivate get registry(): LankaScenariosRegistry {\n\t\treturn LankaScenariosRegistry.getInstance();\n\t}\n\n\tconstructor() {\n\t\tsuper({\n\t\t\tfindClassByName: (scenarioName: string) => {\n\t\t\t\t// By export key first: an instance name does not always survive minification.\n\t\t\t\tif (scenarioName in ScenariosModule) {\n\t\t\t\t\t// `as unknown` before the guards, exactly as in the singleton locator.\n\t\t\t\t\t// An EMPTY barrel — what the scaffolder writes, and what a new project\n\t\t\t\t\t// has until its first scenario — makes the module's keys `never`, so\n\t\t\t\t\t// an indexed access is `never` and reading `.prototype` off it does\n\t\t\t\t\t// not compile.\n\t\t\t\t\tconst ScenarioClass = ScenariosModule[\n\t\t\t\t\t\tscenarioName as keyof typeof ScenariosModule\n\t\t\t\t\t] as unknown;\n\t\t\t\t\tif (\n\t\t\t\t\t\ttypeof ScenarioClass === \"function\" &&\n\t\t\t\t\t\t\"prototype\" in ScenarioClass &&\n\t\t\t\t\t\tScenarioClass.prototype\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn ScenarioClass as new () => ILankaScenario<unknown>;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Fallback: look up by instance name.\n\t\t\t\tfor (const value of Object.values(ScenariosModule)) {\n\t\t\t\t\tif (typeof value === \"function\" && value.prototype) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst instance = new (value as new () => ALankaScenario<unknown>)();\n\t\t\t\t\t\t\tif (instance.name === scenarioName) {\n\t\t\t\t\t\t\t\treturn value as new () => ILankaScenario<unknown>;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// Not constructible — skip.\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn undefined;\n\t\t\t},\n\t\t\tgetInstanceByName: (scenarioName: string) => {\n\t\t\t\t// The registry first.\n\t\t\t\tconst registered = this.registry.getScenarioByName(scenarioName);\n\t\t\t\tif (registered) {\n\t\t\t\t\treturn registered;\n\t\t\t\t}\n\n\t\t\t\t// Then those that registered themselves.\n\t\t\t\tconst autoRegistered = ALankaScenario.getAutoRegisteredScenarios();\n\t\t\t\tconst scenario = autoRegistered.find((s) => s.name === scenarioName);\n\n\t\t\t\tif (scenario) {\n\t\t\t\t\tif (!this.registry.isRegistered(scenarioName)) {\n\t\t\t\t\t\tthis.registry.register(scenario);\n\t\t\t\t\t}\n\t\t\t\t\treturn scenario;\n\t\t\t\t}\n\n\t\t\t\t// Then finding the class by name and constructing it.\n\t\t\t\treturn undefined;\n\t\t\t},\n\t\t\tcreateInstance: (ScenarioClass) => {\n\t\t\t\tconst instance = new ScenarioClass();\n\t\t\t\tconst scenarioName = instance.name;\n\t\t\t\tif (!this.registry.isRegistered(scenarioName)) {\n\t\t\t\t\tthis.registry.register(instance);\n\t\t\t\t}\n\t\t\t\treturn instance;\n\t\t\t},\n\t\t\tnotFoundError: (scenarioName, propertyName) =>\n\t\t\t\t`Scenario \"${scenarioName}\" (accessed as \"${propertyName}\") not found. ` +\n\t\t\t\t`Make sure the scenario class extends ALankaScenario and has name=\"${scenarioName}\".`,\n\t\t});\n\t}\n}\n","import { caseConvert } from \"../../../_internal/case-convert/caseConvert\";\nimport { lankaLogger } from \"../../../logger/lanka-logger/LankaLogger\";\nimport type { LankaSingletonLocator } from \"../../singleton/lanka-singleton-locator/LankaSingletonLocator\";\n\n/**\n * A service lifetime other than \"as long as the application lives\".\n *\n * Everything resolved through `lankaSingletons.*` is a singleton for the life of\n * the app. Per-route, per-session and per-modal lifetimes otherwise rest on\n * discipline: every ViewModel calling `resetScenario()` and writing its own\n * `onReset`, in any of which it can be forgotten.\n *\n * A scope provides the same by construction: an object created in it goes away\n * with it, and nobody has to remember.\n *\n * ## What a scope does NOT do\n *\n * It does not shadow root objects and does not take them on close. It takes only\n * ITS OWN — the ones it created. A scope taking others' would be more dangerous\n * than no scopes at all: closing a screen would break the app.\n */\nexport interface ILankaScope {\n\t/** Resolves a service in this scope, creating it on first use. */\n\tresolve<TInstance>(propertyName: string): TInstance;\n\t/** Disposes everything this scope created and closes it. Idempotent. */\n\tdispose(): void;\n\t/** Whether the scope is closed. */\n\tisDisposed(): boolean;\n}\n\n/** A service may have a `dispose` — or may not. */\ninterface IMaybeDisposable {\n\tdispose?: () => void;\n}\n\nexport function createLankaScope(singletons: LankaSingletonLocator): ILankaScope {\n\tconst instances = new Map<string, unknown>();\n\tlet disposed = false;\n\n\treturn {\n\t\tresolve<TInstance>(propertyName: string): TInstance {\n\t\t\tif (disposed) {\n\t\t\t\t// Resolving from a closed scope is almost always a reference leaked from\n\t\t\t\t// an already-unmounted screen. Silently handing out an object would\n\t\t\t\t// extend the life of what was closed, invisibly.\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`The scope is closed: \"${propertyName}\" can no longer be resolved in it. ` +\n\t\t\t\t\t\t`This is usually a scope reference that outlived the screen that created it.`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst className = caseConvert(propertyName, \"pascalCase\");\n\t\t\tif (instances.has(className)) return instances.get(className) as TInstance;\n\n\t\t\t// The class comes from the root locator while the OBJECT is created here:\n\t\t\t// a scope is a different lifetime, not a different set of services.\n\t\t\tconst instance = singletons.createScopedInstance(className, propertyName);\n\t\t\tinstances.set(className, instance);\n\t\t\treturn instance as TInstance;\n\t\t},\n\n\t\tdispose(): void {\n\t\t\tif (disposed) return;\n\t\t\tdisposed = true;\n\n\t\t\tfor (const [name, instance] of instances) {\n\t\t\t\tconst disposable = instance as IMaybeDisposable;\n\t\t\t\tif (typeof disposable.dispose !== \"function\") continue;\n\t\t\t\ttry {\n\t\t\t\t\tdisposable.dispose();\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// One failure must not leave the rest alive: that is exactly what a\n\t\t\t\t\t// scope exists to prevent.\n\t\t\t\t\tlankaLogger.printBootstrapLog(\n\t\t\t\t\t\t`Failed to dispose \"${name}\" in the scope`,\n\t\t\t\t\t\terror instanceof Error ? error.message : String(error),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tinstances.clear();\n\t\t},\n\n\t\tisDisposed: () => disposed,\n\t};\n}\n"],"mappings":"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","names":[]}
|
|
@@ -33,6 +33,29 @@ var ALankaLocator = class {
|
|
|
33
33
|
notFoundError: config.notFoundError ?? ((name, propertyName) => `Instance "${name}" (accessed as "${propertyName}") not found.`)
|
|
34
34
|
};
|
|
35
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* The class a name resolves to: hand-registered FIRST, then the consumer's
|
|
38
|
+
* barrel.
|
|
39
|
+
*
|
|
40
|
+
* One owner for both callers, and that is the whole point of it existing.
|
|
41
|
+
* `registeredClasses` used to be read inside each locator's own
|
|
42
|
+
* `findClassByName`, and only two of the four did it — singletons and shared
|
|
43
|
+
* stores worked, gateways and scenarios silently dropped the class. Moving the
|
|
44
|
+
* read into `getInstanceByName` fixed those two and broke a third path:
|
|
45
|
+
* `LankaSingletonLocator.createScopedInstance` calls `findClassByName`
|
|
46
|
+
* directly, so a registered class stopped resolving inside a scope. Ten tests
|
|
47
|
+
* said so.
|
|
48
|
+
*
|
|
49
|
+
* Both callers go through here now. A fourth caller added later gets the
|
|
50
|
+
* precedence for free instead of having to remember it.
|
|
51
|
+
*
|
|
52
|
+
* The precedence itself matches `registeredInstances` below: what a caller
|
|
53
|
+
* handed over wins over what the barrel happens to export under that name,
|
|
54
|
+
* because the caller is usually a test substituting a double.
|
|
55
|
+
*/
|
|
56
|
+
classFor(instanceName) {
|
|
57
|
+
return this.registeredClasses.get(instanceName) ?? this.config.findClassByName(instanceName);
|
|
58
|
+
}
|
|
36
59
|
/**
|
|
37
60
|
* An object by class name.
|
|
38
61
|
*
|
|
@@ -53,7 +76,7 @@ var ALankaLocator = class {
|
|
|
53
76
|
return instance;
|
|
54
77
|
}
|
|
55
78
|
}
|
|
56
|
-
const Class = this.
|
|
79
|
+
const Class = this.classFor(instanceName);
|
|
57
80
|
if (Class) {
|
|
58
81
|
const instance = this.config.createInstance(Class);
|
|
59
82
|
this.instanceCache.set(instanceName, instance);
|
|
@@ -117,25 +140,22 @@ var ALankaLocator = class {
|
|
|
117
140
|
}
|
|
118
141
|
};
|
|
119
142
|
|
|
120
|
-
// src/locator/_internal/findExportedClass.ts
|
|
143
|
+
// src/locator/_internal/find-exported-class/findExportedClass.ts
|
|
121
144
|
function findExportedClass(module, exportName) {
|
|
122
145
|
if (!(exportName in module)) return void 0;
|
|
146
|
+
if (!Object.hasOwn(module, exportName)) return void 0;
|
|
123
147
|
const candidate = module[exportName];
|
|
124
148
|
return typeof candidate === "function" && candidate.prototype ? candidate : void 0;
|
|
125
149
|
}
|
|
126
150
|
|
|
127
|
-
// ../tools/testing/_fixtures/.lanka_di/Singletons.ts
|
|
128
|
-
var Singletons_exports = {};
|
|
129
|
-
|
|
130
151
|
// src/locator/singleton/lanka-singleton-locator/LankaSingletonLocator.ts
|
|
152
|
+
import * as SingletonsModule from "@lanka_di/Singletons";
|
|
131
153
|
var LankaSingletonLocator = class extends ALankaLocator {
|
|
132
154
|
singletonIndexModule;
|
|
133
155
|
constructor(config) {
|
|
134
156
|
super({
|
|
135
157
|
findClassByName: (className) => {
|
|
136
|
-
|
|
137
|
-
if (registered) return registered;
|
|
138
|
-
return findExportedClass(Singletons_exports, className) ?? (this.singletonIndexModule ? findExportedClass(this.singletonIndexModule, className) : void 0);
|
|
158
|
+
return findExportedClass(SingletonsModule, className) ?? (this.singletonIndexModule ? findExportedClass(this.singletonIndexModule, className) : void 0);
|
|
139
159
|
},
|
|
140
160
|
createInstance: (Class) => {
|
|
141
161
|
return new Class();
|
|
@@ -152,7 +172,7 @@ var LankaSingletonLocator = class extends ALankaLocator {
|
|
|
152
172
|
* would replace the application's root object.
|
|
153
173
|
*/
|
|
154
174
|
createScopedInstance(className, propertyName) {
|
|
155
|
-
const Class = this.
|
|
175
|
+
const Class = this.classFor(className);
|
|
156
176
|
if (!Class) {
|
|
157
177
|
throw new Error(this.config.notFoundError(className, propertyName));
|
|
158
178
|
}
|
|
@@ -160,21 +180,15 @@ var LankaSingletonLocator = class extends ALankaLocator {
|
|
|
160
180
|
}
|
|
161
181
|
};
|
|
162
182
|
|
|
163
|
-
// ../tools/testing/_fixtures/.lanka_di/SharedStores.ts
|
|
164
|
-
var SharedStores_exports = {};
|
|
165
|
-
|
|
166
183
|
// src/locator/shared-store/lanka-shared-store-locator/LankaSharedStoreLocator.ts
|
|
184
|
+
import * as SharedStoresModule from "@lanka_di/SharedStores";
|
|
167
185
|
var LankaSharedStoreLocator = class extends ALankaLocator {
|
|
168
186
|
sharedStoreIndexModule;
|
|
169
187
|
constructor(config) {
|
|
170
188
|
super({
|
|
171
189
|
findClassByName: (className) => {
|
|
172
|
-
const registeredClass = this.registeredClasses.get(className);
|
|
173
|
-
if (registeredClass) {
|
|
174
|
-
return registeredClass;
|
|
175
|
-
}
|
|
176
190
|
return findExportedClass(
|
|
177
|
-
|
|
191
|
+
SharedStoresModule,
|
|
178
192
|
className
|
|
179
193
|
) ?? (this.sharedStoreIndexModule ? findExportedClass(
|
|
180
194
|
this.sharedStoreIndexModule,
|
|
@@ -197,4 +211,4 @@ export {
|
|
|
197
211
|
LankaSingletonLocator,
|
|
198
212
|
LankaSharedStoreLocator
|
|
199
213
|
};
|
|
200
|
-
//# sourceMappingURL=chunk-
|
|
214
|
+
//# sourceMappingURL=chunk-UE2C76OR.js.map
|