lanka 1.0.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +5 -3
  2. package/dist/{ALankaGateway-ExlRGT3D.d.ts → ALankaGateway-CkW1LbKE.d.ts} +50 -4
  3. package/dist/{ILankaScenarioMetadata-Bu-yggTZ.d.ts → ILankaScenarioMetadata-GoWWNEQL.d.ts} +1 -1
  4. package/dist/{ILankaScenarioVM-DuCyPoyT.d.ts → ILankaScenarioVM-DUsI-fSc.d.ts} +116 -3
  5. package/dist/{LankaScenarioLocator-CLkq4MaJ.d.ts → LankaScenarioLocator-D86TIwiu.d.ts} +10 -5
  6. package/dist/_extend/index.d.ts +4 -4
  7. package/dist/_extend/index.js +2 -2
  8. package/dist/_internal/index.d.ts +5 -5
  9. package/dist/{activeRuntime-DT4gB16d.d.ts → activeRuntime-B336NU5I.d.ts} +2 -2
  10. package/dist/bootstrap/index.d.ts +13 -144
  11. package/dist/bootstrap/index.js +4 -4
  12. package/dist/{chunk-MYZQYOMD.js → chunk-5MAQVBI2.js} +20 -15
  13. package/dist/chunk-5MAQVBI2.js.map +1 -0
  14. package/dist/chunk-D5WKKEIR.js +54 -0
  15. package/dist/chunk-D5WKKEIR.js.map +1 -0
  16. package/dist/{chunk-63ST2UKP.js → chunk-LMKLLEHA.js} +103 -17
  17. package/dist/chunk-LMKLLEHA.js.map +1 -0
  18. package/dist/{chunk-YXI4OQEV.js → chunk-O5ROO7QF.js} +27 -4
  19. package/dist/chunk-O5ROO7QF.js.map +1 -0
  20. package/dist/{chunk-HZAIAGWS.js → chunk-UGXSGQPW.js} +6 -2
  21. package/dist/chunk-UGXSGQPW.js.map +1 -0
  22. package/dist/createLanka-DI1CSy2Q.d.ts +139 -0
  23. package/dist/gateway/index.d.ts +77 -67
  24. package/dist/gateway/index.js +50 -54
  25. package/dist/gateway/index.js.map +1 -1
  26. package/dist/index.d.ts +7 -6
  27. package/dist/index.js +4 -4
  28. package/dist/locator/index.d.ts +1 -1
  29. package/dist/scenario/index.d.ts +6 -4
  30. package/dist/scenario/index.js +2 -2
  31. package/dist/stream/index.d.ts +386 -0
  32. package/dist/stream/index.js +287 -0
  33. package/dist/stream/index.js.map +1 -0
  34. package/dist/validation/index.js +4 -48
  35. package/dist/validation/index.js.map +1 -1
  36. package/dist/viewmodel/index.d.ts +1 -1
  37. package/dist/viewmodel/index.js +2 -2
  38. package/package.json +7 -3
  39. package/skills/lanka-core/SKILL.md +1 -1
  40. package/skills/lanka-core/reference.md +110 -17
  41. package/skills/lanka-packages/SKILL.md +1 -1
  42. package/dist/chunk-63ST2UKP.js.map +0 -1
  43. package/dist/chunk-HZAIAGWS.js.map +0 -1
  44. package/dist/chunk-MYZQYOMD.js.map +0 -1
  45. package/dist/chunk-YXI4OQEV.js.map +0 -1
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  **◆ core** · Core
4
4
 
5
- > Ten subsystems, two peer dependencies, five extension points.
5
+ > Twelve subsystems, two peer dependencies, five extension points.
6
6
 
7
7
  One, unscoped. Everything depends on it; it depends on nothing.
8
8
 
@@ -16,7 +16,8 @@ One, unscoped. Everything depends on it; it depends on nothing.
16
16
  | --- | --- | --- |
17
17
  | `useRequestMiddleware(mw)` | wrap every request | yes |
18
18
  | `inFlight.subscribe(fn)` | observe the number of requests on the wire | yes |
19
- | `lankaEventBus.addMiddleware` | intercept bus events | yes |
19
+ | `lankaEventBus.addMiddleware` | intercept bus events, and stop one | yes |
20
+ | `lankaEventBus.addObserver` | hear what became of each dispatch | yes |
20
21
  | `LankaLogger sinks` | where log output goes | yes |
21
22
  | `use(plugin)` | register a whole plugin | yes |
22
23
 
@@ -46,6 +47,7 @@ the seal on `internal`, and catches a subsystem added as a folder and forgotten
46
47
  - `src/mock/`
47
48
  - `src/errors/`
48
49
  - `src/scenario/`
50
+ - `src/stream/`
49
51
  - `src/viewmodel/`
50
52
  - `src/logger/`
51
53
  - `src/internal/` — **not exported.** Refactored without a major.
@@ -226,7 +228,7 @@ to rename.
226
228
 
227
229
  `ViewModel` shortens to `VM` in class, factory and type names: `ALankaVM` and
228
230
  `createLankaVM` are written in every screen file — the same ViewModel reached from
229
- either style, one of the nine roles `skills/parity/SKILL.md` governs.
231
+ either style, one of the roles `skills/parity/SKILL.md` governs.
230
232
 
231
233
  Three names stay bare — `isRecord`, `getStringField`, `generateUuid`. They are pure
232
234
  utilities over ordinary values; a collision there is resolved at the import site, which
@@ -1,5 +1,34 @@
1
1
  import { I as ILankaValidator } from './lankaStandardValidator-CL-r-zEV.js';
2
2
 
3
+ /**
4
+ * `RequestInit`, with the body a JSON API actually sends.
5
+ *
6
+ * `RequestInit["body"]` is `BodyInit | null` — a string, a `FormData`, a blob,
7
+ * bytes. It is what `fetch` accepts and it is NOT what a gateway method writes:
8
+ * every one of them writes `body: { name, email }`, an object, and lets the
9
+ * transport encode it.
10
+ *
11
+ * The framework's transport has always encoded that object. The TYPE never
12
+ * admitted it, and the cost was not a cast at the call site — it was a fork. A
13
+ * consumer could not write `body: { … }` against `RequestInit`, so they declared
14
+ * their own options type; declaring it made every shipped transport
15
+ * unassignable, because those were fixed to `RequestInit`; so they wrote a
16
+ * transport too, and with it a base URL, a CSRF header and an auth refresh the
17
+ * framework already had. One wrong type produced a re-implementation of three
18
+ * packages.
19
+ *
20
+ * `unknown` rather than a union of the encodable shapes: the transport decides
21
+ * by INSPECTING the value, and a type listing what it accepts would have to be
22
+ * kept in step with that inspection by hand. What is not a `BodyInit` is JSON —
23
+ * that is the whole rule, and it needs no enumeration.
24
+ */
25
+ type TLankaRequestInit = Omit<RequestInit, "body"> & {
26
+ /**
27
+ * Anything. A `BodyInit` travels as given; everything else is encoded as JSON.
28
+ */
29
+ body?: unknown;
30
+ };
31
+
3
32
  /**
4
33
  * Transport options plus what core controls.
5
34
  *
@@ -26,7 +55,7 @@ type TLankaExecuteOptions<TOptions> = TOptions & {
26
55
  * is how development without a backend works, and a request that ignored it
27
56
  * would silently disable mock mode for the gateway holding it.
28
57
  */
29
- interface ILankaRequest<TOptions = RequestInit> {
58
+ interface ILankaRequest<TOptions = TLankaRequestInit> {
30
59
  /**
31
60
  * Sends the request and returns the value the caller asked for.
32
61
  *
@@ -68,7 +97,15 @@ interface IALankaGatewayConfig<TOptions> {
68
97
  * reads it.
69
98
  */
70
99
  queryParamsHandler?: TLankaQueryBuilder;
71
- /** Validation service (DI). May be replaced for tests / migration. */
100
+ /**
101
+ * The validator a method checks a response body with. Defaults to
102
+ * `lankaStandardValidator`.
103
+ *
104
+ * Reachable as `this.validationService` in a class and as
105
+ * `validationService` in the functional context. A test hands one that
106
+ * records what it was asked; a migration hands one that accepts a shape the
107
+ * new schema does not yet.
108
+ */
72
109
  validationService?: ILankaValidator;
73
110
  /**
74
111
  * Enable mock mode. If undefined, reads from infrastructure flags (isMockMode).
@@ -77,9 +114,18 @@ interface IALankaGatewayConfig<TOptions> {
77
114
  useMock?: boolean;
78
115
  }
79
116
 
80
- declare abstract class ALankaGateway<TOptions = RequestInit> {
117
+ declare abstract class ALankaGateway<TOptions = TLankaRequestInit> {
81
118
  protected requestExecutor: ILankaRequest<TOptions>;
82
119
  protected queryParamsHandler: TLankaQueryBuilder;
120
+ /**
121
+ * The validator a method checks a response body with.
122
+ *
123
+ * `config.validationService` when one was given, the Standard Schema port
124
+ * otherwise. It used to be accepted by the config and read by nothing: a
125
+ * consumer handing a test double to the gateway got the real validator and no
126
+ * error, which is the worst kind of ignored option — it looks honoured.
127
+ */
128
+ protected readonly validationService: ILankaValidator;
83
129
  protected readonly useMock: boolean;
84
130
  protected readonly basePath: string;
85
131
  protected constructor(config: IALankaGatewayConfig<TOptions>);
@@ -119,4 +165,4 @@ declare abstract class ALankaGateway<TOptions = RequestInit> {
119
165
  protected setQueryParamsHandler(handler: TLankaQueryBuilder): void;
120
166
  }
121
167
 
122
- export { ALankaGateway as A, type IALankaGatewayConfig as I, type TLankaExecuteOptions as T, type ILankaRequest as a, type TLankaQueryBuilder as b, type TLankaQueryParams as c };
168
+ export { ALankaGateway as A, type IALankaGatewayConfig as I, type TLankaExecuteOptions as T, type TLankaRequestInit as a, type ILankaRequest as b, type TLankaQueryBuilder as c, type TLankaQueryParams as d };
@@ -1,4 +1,4 @@
1
- import { a as ILankaScenario } from './ILankaScenarioVM-DuCyPoyT.js';
1
+ import { a as ILankaScenario } from './ILankaScenarioVM-DUsI-fSc.js';
2
2
 
3
3
  /**
4
4
  * Metadata about a registered scenario
@@ -35,6 +35,17 @@ interface ILankaEventLog {
35
35
  eventType: string;
36
36
  /** ISO timestamp of when the event was dispatched. */
37
37
  timestamp: string;
38
+ /**
39
+ * Where this record falls in the order the bus saw events, counting from one.
40
+ *
41
+ * What `getEventLogs()` orders by, and the reason it can: a timestamp has
42
+ * millisecond resolution, and a burst dispatches many events inside one, so
43
+ * two records of one millisecond cannot be told apart by their time.
44
+ *
45
+ * Optional because a record built by anything other than the bus has no
46
+ * place in that order.
47
+ */
48
+ sequence?: number;
38
49
  /** The payload data of the event. */
39
50
  data: unknown;
40
51
  /** Optional captured stack trace (if enabled). */
@@ -77,6 +88,60 @@ type TLankaEventBusDecision = "pass" | {
77
88
  */
78
89
  type TLankaEventBusMiddleware<T> = (eventType: string, data: T) => TLankaEventBusDecision;
79
90
 
91
+ /**
92
+ * What became of one dispatch, after the whole chain has run.
93
+ *
94
+ * The counterpart of `TLankaEventBusDecision`: a middleware RETURNS a decision,
95
+ * and the bus REPORTS an outcome. The two are deliberately symmetrical, and the
96
+ * asymmetry that matters is that an outcome cannot change anything.
97
+ */
98
+ interface ILankaEventBusOutcome {
99
+ eventType: string;
100
+ /**
101
+ * Delivered to the subscribers, stopped by a middleware, or refused by the
102
+ * event's own schema.
103
+ *
104
+ * A union rather than an `enum`: a fourth outcome is then additive, which
105
+ * `skills/surface/SKILL.md` §6d.5 is about.
106
+ */
107
+ outcome: "delivered" | "stopped" | "invalid";
108
+ /**
109
+ * How many subscribers the event had when it was dispatched.
110
+ *
111
+ * The AUDIENCE, not the recipients: "three subscribers never heard it" is the
112
+ * sentence a stopped event needs, and a count that went to zero on a stop
113
+ * could not say it.
114
+ */
115
+ subscribers: number;
116
+ /** The reason a middleware gave, when one stopped it. */
117
+ stoppedBy?: string;
118
+ }
119
+
120
+ /**
121
+ * Something watching what became of each dispatch.
122
+ *
123
+ * ## Why this is not a middleware
124
+ *
125
+ * A middleware runs in a CHAIN and sees only what happened before it. The first
126
+ * one registered — which is what a diagnostic tool ends up being, since it is
127
+ * installed at bootstrap — cannot see a later middleware's decision to stop an
128
+ * event, so "which middleware stopped it" was a question nothing could answer.
129
+ * `@lankajs/plugin-devtools` carried a `stoppedBy` field that no code path ever
130
+ * filled, and its guide documented it.
131
+ *
132
+ * An observer runs ONCE per dispatch, after the chain, and its return value is
133
+ * ignored — it cannot decide anything. That is what keeps a diagnostic tool
134
+ * incapable of changing what it diagnoses, by construction rather than by
135
+ * discipline.
136
+ *
137
+ * ## Why the parameter is one object
138
+ *
139
+ * `skills/surface/SKILL.md` §6d.9: a callback's parameters are one object, so
140
+ * the day the bus learns to report how long delivery took, nobody's handler
141
+ * silently receives a different third argument.
142
+ */
143
+ type TLankaEventBusObserver = (outcome: ILankaEventBusOutcome) => void;
144
+
80
145
  /**
81
146
  * How many recent values to replay to a new subscriber.
82
147
  *
@@ -88,12 +153,26 @@ declare class LankaEventBusInstance {
88
153
  private registry;
89
154
  /** Middleware registered on this instance. */
90
155
  private middlewares;
156
+ /**
157
+ * What is watching the OUTCOME of each dispatch — see `TLankaEventBusObserver`.
158
+ *
159
+ * An array rather than a set for one reason: `dispatch` reads `.length` on
160
+ * every event, and that check is what keeps an unobserved bus paying nothing.
161
+ */
162
+ private observers;
91
163
  /** Default maximum number of logs kept per event type. */
92
164
  private defaultMaxLogs;
93
165
  /** Internal timers for replay batching (avoid multiple replays in the same tick). */
94
166
  private pendingReplayTimers;
95
167
  /** Whether event logging is enabled. */
96
168
  private isEnableLogs;
169
+ /**
170
+ * How many events this bus has logged, ever — the order records are read in.
171
+ *
172
+ * Incremented only while logging is on, which is off by default, so a bus
173
+ * nobody is inspecting pays nothing for it.
174
+ */
175
+ private dispatchCount;
97
176
  /** Configures the bus, e.g. logging. Called once at application start. */
98
177
  enableLogs(): void;
99
178
  disableLogs(): void;
@@ -162,7 +241,28 @@ declare class LankaEventBusInstance {
162
241
  /** Removes previously added middleware. */
163
242
  removeMiddleware<T>(mw: TLankaEventBusMiddleware<T>): void;
164
243
  /**
165
- * Log of dispatched events.
244
+ * Watches what became of each dispatch. An extension point — the sixth.
245
+ *
246
+ * An observer never decides: its return value is ignored, and a throw from it
247
+ * is logged rather than surfaced. A diagnostic tool that could stop an event
248
+ * would make "I disabled the inspector and it started working" a sentence
249
+ * somebody says.
250
+ */
251
+ addObserver(observer: TLankaEventBusObserver): void;
252
+ /** Removes a previously added observer. */
253
+ removeObserver(observer: TLankaEventBusObserver): void;
254
+ /**
255
+ * Log of dispatched events, oldest first, `limit` most recent kept.
256
+ *
257
+ * ## Why the records are sorted rather than concatenated
258
+ *
259
+ * They are held per event TYPE, so that each type keeps its own `maxLogs`
260
+ * and a chatty event cannot push a quiet one's history out. Concatenating
261
+ * those lists puts every record of one type before every record of the next,
262
+ * and `slice(-limit)` then answers the tail of whichever type the registry
263
+ * happened to hold last — not the most recent events at all. On a bus with
264
+ * one event type nothing looked wrong; on a real one the log was a
265
+ * chronology that had never been in chronological order.
166
266
  *
167
267
  * @param eventType Limit to one type
168
268
  * @param limit How many recent records to return
@@ -172,8 +272,21 @@ declare class LankaEventBusInstance {
172
272
  clearEvent(eventType: string): void;
173
273
  /** Removes every event and any scheduled replays. */
174
274
  clearAllEvents(): void;
175
- /** Full bus reset: events and middleware. */
275
+ /** Full bus reset: events, middleware and observers. */
176
276
  reset(): void;
277
+ /**
278
+ * Tells the observers what became of a dispatch.
279
+ *
280
+ * The empty-list check is the whole reason a bus nobody watches pays nothing
281
+ * for this: `dispatch` is a hot path, and an iteration over an empty array on
282
+ * every event would be a cost paid by every application for a feature almost
283
+ * none of them installs. Measured in `LankaEventBusInstance.bench.ts`.
284
+ *
285
+ * An observer that throws is logged and the next one still runs — the same
286
+ * treatment a subscriber gets, and for the same reason: a diagnostic tool must
287
+ * not be able to break the application it is diagnosing.
288
+ */
289
+ private report;
177
290
  /**
178
291
  * Marks the last log record with the reason it was stopped.
179
292
  *
@@ -257,4 +370,4 @@ interface ILankaScenarioVM {
257
370
  resetScenario(): void;
258
371
  }
259
372
 
260
- export { type ILankaScenarioVM as I, LankaEventBusInstance as L, type TLankaReplayRequest as T, type ILankaScenario as a, type ILankaEventMetadata as b, type TLankaEventBusMiddleware as c, type ILankaEventLog as d, type TLankaEventBusDecision as e };
373
+ export { type ILankaScenarioVM as I, LankaEventBusInstance as L, type TLankaReplayRequest as T, type ILankaScenario as a, type ILankaEventMetadata as b, type TLankaEventBusMiddleware as c, type TLankaEventBusObserver as d, type ILankaEventLog as e, type ILankaEventBusOutcome as f, type TLankaEventBusDecision as g };
@@ -1,6 +1,6 @@
1
- import { a as ILankaScenario, I as ILankaScenarioVM } from './ILankaScenarioVM-DuCyPoyT.js';
2
- import { I as ILankaScenarioMetadata } from './ILankaScenarioMetadata-Bu-yggTZ.js';
3
- import { A as ALankaGateway } from './ALankaGateway-ExlRGT3D.js';
1
+ import { a as ILankaScenario, I as ILankaScenarioVM } from './ILankaScenarioVM-DUsI-fSc.js';
2
+ import { I as ILankaScenarioMetadata } from './ILankaScenarioMetadata-GoWWNEQL.js';
3
+ import { A as ALankaGateway } from './ALankaGateway-CkW1LbKE.js';
4
4
  import { A as ALankaLocator } from './LankaSharedStoreLocator-zS2kLu-S.js';
5
5
 
6
6
  /**
@@ -31,7 +31,8 @@ declare class LankaScenariosRegistry {
31
31
  */
32
32
  register(scenario: ILankaScenario<unknown>): boolean;
33
33
  /**
34
- * Unregister a scenario
34
+ * Removes a scenario, calling its `cleanup` if it declared one.
35
+ *
35
36
  * @param scenarioName Name of the scenario to unregister
36
37
  * @returns true if unregistered successfully, false if not found
37
38
  */
@@ -61,7 +62,11 @@ declare class LankaScenariosRegistry {
61
62
  /** Every registered ViewModel. */
62
63
  getAllViewModels(): ILankaScenarioVM[];
63
64
  /**
64
- * Clears every registered scenario. Required by tests.
65
+ * Removes every scenario, calling each one's `cleanup`.
66
+ *
67
+ * What `dispose()` and the between-tests reset go through: `initialize` ran
68
+ * for every scenario at bootstrap, and this is the one moment its mirror
69
+ * image can run for all of them.
65
70
  */
66
71
  clear(): void;
67
72
  }
@@ -1,11 +1,11 @@
1
- export { L as LankaGatewayLocator, a as LankaScenarioLocator, b as LankaScenarioVMRegistry, c as LankaScenariosRegistry } from '../LankaScenarioLocator-CLkq4MaJ.js';
1
+ export { L as LankaGatewayLocator, a as LankaScenarioLocator, b as LankaScenarioVMRegistry, c as LankaScenariosRegistry } from '../LankaScenarioLocator-D86TIwiu.js';
2
2
  import { a as ILankaLocator } from '../LankaSharedStoreLocator-zS2kLu-S.js';
3
3
  export { A as ALankaLocator, L as LankaSharedStoreLocator, b as LankaSingletonLocator } from '../LankaSharedStoreLocator-zS2kLu-S.js';
4
4
  export { c as createLankaScope } from '../createLankaScope-BiFxNQgl.js';
5
5
  export { c as composeLankaRequestMiddleware } from '../lankaRequestMiddleware-DAC5kCb7.js';
6
- import '../ILankaScenarioVM-DuCyPoyT.js';
7
- import '../ILankaScenarioMetadata-Bu-yggTZ.js';
8
- import '../ALankaGateway-ExlRGT3D.js';
6
+ import '../ILankaScenarioVM-DUsI-fSc.js';
7
+ import '../ILankaScenarioMetadata-GoWWNEQL.js';
8
+ import '../ALankaGateway-CkW1LbKE.js';
9
9
  import '../lankaStandardValidator-CL-r-zEV.js';
10
10
  import '@standard-schema/spec';
11
11
  import '../ALankaSharedStore-B7uepuuk.js';
@@ -2,11 +2,11 @@ import {
2
2
  LankaGatewayLocator,
3
3
  LankaScenarioLocator,
4
4
  createLankaScope
5
- } from "../chunk-MYZQYOMD.js";
5
+ } from "../chunk-5MAQVBI2.js";
6
6
  import {
7
7
  LankaScenarioVMRegistry,
8
8
  LankaScenariosRegistry
9
- } from "../chunk-YXI4OQEV.js";
9
+ } from "../chunk-O5ROO7QF.js";
10
10
  import {
11
11
  composeLankaRequestMiddleware
12
12
  } from "../chunk-YR4MZXMU.js";
@@ -1,8 +1,8 @@
1
- export { I as ILankaRuntime, T as TLankaRuntimeResolver, s as setLankaRuntimeResolver } from '../activeRuntime-DT4gB16d.js';
2
- import '../ILankaScenarioVM-DuCyPoyT.js';
3
- import '../LankaScenarioLocator-CLkq4MaJ.js';
4
- import '../ILankaScenarioMetadata-Bu-yggTZ.js';
5
- import '../ALankaGateway-ExlRGT3D.js';
1
+ export { I as ILankaRuntime, T as TLankaRuntimeResolver, s as setLankaRuntimeResolver } from '../activeRuntime-B336NU5I.js';
2
+ import '../ILankaScenarioVM-DUsI-fSc.js';
3
+ import '../LankaScenarioLocator-D86TIwiu.js';
4
+ import '../ILankaScenarioMetadata-GoWWNEQL.js';
5
+ import '../ALankaGateway-CkW1LbKE.js';
6
6
  import '../lankaStandardValidator-CL-r-zEV.js';
7
7
  import '@standard-schema/spec';
8
8
  import '../LankaSharedStoreLocator-zS2kLu-S.js';
@@ -1,5 +1,5 @@
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-CLkq4MaJ.js';
1
+ import { L as LankaEventBusInstance, I as ILankaScenarioVM } from './ILankaScenarioVM-DUsI-fSc.js';
2
+ import { c as LankaScenariosRegistry, b as LankaScenarioVMRegistry, L as LankaGatewayLocator, a as LankaScenarioLocator } from './LankaScenarioLocator-D86TIwiu.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';
@@ -1,150 +1,19 @@
1
- import { I as ILankaScope } from '../createLankaScope-BiFxNQgl.js';
2
- import { I as ILankaRuntime } from '../activeRuntime-DT4gB16d.js';
3
- import { a as ILankaHost, I as ILankaFlags } from '../ILankaRuntimeConfig-Vl436GWK.js';
4
- import { T as TLankaRequestMiddleware } from '../lankaRequestMiddleware-DAC5kCb7.js';
1
+ import { c as ILankaPlugin, e as ILankaServiceConfig, I as ILankaBootstrapConfig, a as ILankaInstance } from '../createLanka-DI1CSy2Q.js';
2
+ export { b as ILankaInstanceConfig, d as ILankaScenarioBootstrapConfig, f as createLanka } from '../createLanka-DI1CSy2Q.js';
3
+ import { I as ILankaFlags, a as ILankaHost } from '../ILankaRuntimeConfig-Vl436GWK.js';
4
+ export { I as ILankaScope } from '../createLankaScope-BiFxNQgl.js';
5
+ import '../activeRuntime-B336NU5I.js';
6
+ import '../ILankaScenarioVM-DUsI-fSc.js';
7
+ import '../LankaScenarioLocator-D86TIwiu.js';
8
+ import '../ILankaScenarioMetadata-GoWWNEQL.js';
9
+ import '../ALankaGateway-CkW1LbKE.js';
10
+ import '../lankaStandardValidator-CL-r-zEV.js';
11
+ import '@standard-schema/spec';
5
12
  import '../LankaSharedStoreLocator-zS2kLu-S.js';
6
13
  import '../ALankaSharedStore-B7uepuuk.js';
7
14
  import 'zustand/vanilla';
8
- import '../ILankaScenarioVM-DuCyPoyT.js';
9
- import '../LankaScenarioLocator-CLkq4MaJ.js';
10
- import '../ILankaScenarioMetadata-Bu-yggTZ.js';
11
- import '../ALankaGateway-ExlRGT3D.js';
12
- import '../lankaStandardValidator-CL-r-zEV.js';
13
- import '@standard-schema/spec';
14
15
  import '../lankaHttpInFlight-Bk1eIuSx.js';
15
-
16
- /**
17
- * A plugin is an extension core knows by SHAPE rather than by name.
18
- *
19
- * ## Plugin versus module
20
- *
21
- * A module is called by the application (`app → module`) and core does not know
22
- * it exists. A plugin sits on the path core itself walks (`app → core → plugin`).
23
- * The test question: does core need a hook for this to work? No — then it is a
24
- * module, and making it a plugin costs more, because the hook has to be supported
25
- * forever.
26
- *
27
- * ## Why `install` receives the instance
28
- *
29
- * So a plugin has no private route to the framework. Everything it can do comes
30
- * from the instance it was given, which means two instances in one process (a
31
- * test beside the app) do not share its configuration.
32
- */
33
- interface ILankaPlugin {
34
- /**
35
- * The name the plugin is recognised by. Registering the same name twice is
36
- * rejected: two copies of a retry policy would silently double the request
37
- * count.
38
- */
39
- readonly name: string;
40
- /**
41
- * Installation. The returned function removes everything the plugin installed
42
- * and is called when the plugin is removed and when the instance is disposed.
43
- */
44
- install: (lanka: ILankaInstance) => (() => void) | void;
45
- }
46
-
47
- /**
48
- * A framework instance: all framework state in one object.
49
- *
50
- * What instance-scoped state buys: two apps in one process (micro-frontends,
51
- * Storybook beside the app) no longer share a bus, locator caches and mock mode;
52
- * SSR does not reuse state between different users' requests; and test isolation
53
- * rests on construction rather than on a global `beforeEach` reaching into
54
- * internal registries.
55
- *
56
- * **Ambient facades** — `lankaEventBus.dispatch`, `lankaSingletons.foo`,
57
- * `getLankaFlags()`, `lankaHttpInFlight` — resolve THE ONE active instance
58
- * (`internal/activeRuntime.ts`). Isolation belongs to whoever holds an instance;
59
- * a facade cannot offer it.
60
- *
61
- * One thing stays at module level deliberately: `ALankaScenario` collects
62
- * constructed scenarios into a static pool. That is a REGISTRY OF DEFINITIONS,
63
- * not runtime state — the classes come from one `@lanka_di/Scenarios` barrel and
64
- * both instances must see the same list. Splitting it would be divergence.
65
- */
66
- interface ILankaInstance extends ILankaRuntime {
67
- /**
68
- * Adds a wrapper around every request. Returns a function that removes it.
69
- *
70
- * This is how `@lankajs/plugin-http` installs retry, the idempotency key, the
71
- * CSRF header and auth refresh.
72
- */
73
- useRequestMiddleware(middleware: TLankaRequestMiddleware): () => void;
74
- /** Default timeout for every request of this instance. */
75
- setRequestTimeout(timeoutMs: number | undefined): void;
76
- /** Resolves a service in the root scope — for the instance's whole lifetime. */
77
- resolve<TInstance>(propertyName: string): TInstance;
78
- /**
79
- * Creates a scope: a lifetime shorter than the application's.
80
- *
81
- * An object created in a scope goes away with it.
82
- */
83
- createScope(): ILankaScope;
84
- /**
85
- * Registers a plugin. Returns a function that removes it.
86
- *
87
- * The fifth and last extension point. An extension point declared before
88
- * anything plugs into it describes an imagined need while costing real
89
- * support, so this one arrived with the FIRST plugin.
90
- */
91
- use(plugin: ILankaPlugin): () => void;
92
- /** Runs services and the scenario layer. Idempotent. */
93
- bootstrap(config?: ILankaBootstrapConfig): Promise<void>;
94
- /** Has bootstrap already run? */
95
- isBootstrapped(): boolean;
96
- /** Makes this instance the one ambient facades resolve to. */
97
- activate(): void;
98
- /**
99
- * Removes subscriptions, clears registries and, if this instance was active,
100
- * clears the pointer. Returns the framework to its pre-bootstrap state.
101
- */
102
- dispose(): void;
103
- }
104
- interface ILankaInstanceConfig {
105
- host: ILankaHost;
106
- flags?: ILankaFlags;
107
- }
108
- interface ILankaServiceConfig {
109
- name?: string;
110
- init: () => void | Promise<void>;
111
- sync?: boolean;
112
- priority?: number;
113
- /**
114
- * A failure of this service does not abort bootstrap.
115
- *
116
- * Without the flag one failed service takes the WHOLE phase with it: the async
117
- * phase because of `Promise.all`, the sync phase because later tasks never run.
118
- * Wrapping the failure in a swallowing `try/catch` is worse still — the app
119
- * starts with a partially executed plan and does not know it.
120
- */
121
- optional?: boolean;
122
- /**
123
- * How long to wait for the service. Overrunning counts as a failure.
124
- *
125
- * Without a deadline a service that never settles holds bootstrap forever and
126
- * the app never paints its first screen. Failing is more honest than waiting:
127
- * an optional service is skipped, a required one names itself.
128
- */
129
- timeoutMs?: number;
130
- }
131
- interface ILankaScenarioBootstrapConfig {
132
- sync?: boolean;
133
- priority?: number;
134
- }
135
- interface ILankaBootstrapConfig {
136
- services?: ILankaServiceConfig[];
137
- scenarios?: ILankaScenarioBootstrapConfig;
138
- }
139
- /**
140
- * Creates an instance and makes it active.
141
- *
142
- * Activating on creation is the deliberate default: there is almost always one
143
- * app and the facades must work immediately. A second instance takes the
144
- * pointer — the last one created serves the facades. Callers needing another
145
- * order call `activate()` explicitly.
146
- */
147
- declare function createLanka(config: ILankaInstanceConfig): ILankaInstance;
16
+ import '../lankaRequestMiddleware-DAC5kCb7.js';
148
17
 
149
18
  /** What `startLanka` takes beyond the host, all of it optional. */
150
19
  interface ILankaStartOptions {
@@ -239,4 +108,4 @@ declare abstract class ALankaPlugin implements ILankaPlugin {
239
108
  install(lanka: ILankaInstance): () => void;
240
109
  }
241
110
 
242
- export { ALankaPlugin, type ILankaBootstrapConfig, type ILankaInstance, type ILankaInstanceConfig, type ILankaPlugin, type ILankaScenarioBootstrapConfig, ILankaScope, type ILankaServiceConfig, type ILankaStartOptions, type TLankaStartConfig, createLanka, resetActiveLanka, startLanka };
111
+ export { ALankaPlugin, ILankaBootstrapConfig, ILankaInstance, ILankaPlugin, ILankaServiceConfig, type ILankaStartOptions, type TLankaStartConfig, resetActiveLanka, startLanka };
@@ -3,10 +3,10 @@ import {
3
3
  createLanka,
4
4
  resetActiveLanka,
5
5
  startLanka
6
- } from "../chunk-63ST2UKP.js";
7
- import "../chunk-HZAIAGWS.js";
8
- import "../chunk-MYZQYOMD.js";
9
- import "../chunk-YXI4OQEV.js";
6
+ } from "../chunk-LMKLLEHA.js";
7
+ import "../chunk-UGXSGQPW.js";
8
+ import "../chunk-5MAQVBI2.js";
9
+ import "../chunk-O5ROO7QF.js";
10
10
  import "../chunk-XESL274R.js";
11
11
  import "../chunk-UJEC7H6K.js";
12
12
  import "../chunk-UE2C76OR.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  ALankaScenario,
3
3
  LankaScenariosRegistry
4
- } from "./chunk-YXI4OQEV.js";
4
+ } from "./chunk-O5ROO7QF.js";
5
5
  import {
6
6
  ALankaLocator,
7
7
  caseConvert,
@@ -24,6 +24,23 @@ var LankaGatewayLocator = class extends ALankaLocator {
24
24
 
25
25
  // src/locator/scenario/lanka-scenario-locator/LankaScenarioLocator.ts
26
26
  import * as ScenariosModule from "@lanka_di/Scenarios";
27
+ var findScenarioClassByInstanceName = (scenarioName) => {
28
+ const pooled = ALankaScenario.getAutoRegisteredScenarios();
29
+ for (const value of Object.values(ScenariosModule)) {
30
+ if (typeof value !== "function" || !value.prototype) continue;
31
+ const Class = value;
32
+ const instance = pooled.find((scenario) => scenario.constructor === Class) ?? construct(Class);
33
+ if (instance?.name === scenarioName) return Class;
34
+ }
35
+ return void 0;
36
+ };
37
+ var construct = (Class) => {
38
+ try {
39
+ return new Class();
40
+ } catch {
41
+ return void 0;
42
+ }
43
+ };
27
44
  var LankaScenarioLocator = class extends ALankaLocator {
28
45
  /**
29
46
  * The registry is read LAZILY rather than in a field initialiser.
@@ -46,19 +63,7 @@ var LankaScenarioLocator = class extends ALankaLocator {
46
63
  return ScenarioClass;
47
64
  }
48
65
  }
49
- for (const value of Object.values(ScenariosModule)) {
50
- if (typeof value === "function" && value.prototype) {
51
- try {
52
- const instance = new value();
53
- if (instance.name === scenarioName) {
54
- return value;
55
- }
56
- } catch {
57
- continue;
58
- }
59
- }
60
- }
61
- return void 0;
66
+ return findScenarioClassByInstanceName(scenarioName);
62
67
  },
63
68
  getInstanceByName: (scenarioName) => {
64
69
  const registered = this.registry.getScenarioByName(scenarioName);
@@ -131,4 +136,4 @@ export {
131
136
  LankaScenarioLocator,
132
137
  createLankaScope
133
138
  };
134
- //# sourceMappingURL=chunk-MYZQYOMD.js.map
139
+ //# sourceMappingURL=chunk-5MAQVBI2.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 * The barrel's class whose INSTANCE carries this name, when the export key does\n * not.\n *\n * A pooled instance answers for its class without constructing another: the\n * pool is never drained, so a lookup that constructed every class on every miss\n * grew it by the whole barrel each time a bad name was asked for. Only a class\n * the pool has never seen is constructed here — once, and it joins the pool.\n */\nconst findScenarioClassByInstanceName = (\n\tscenarioName: string,\n): (new () => ILankaScenario<unknown>) | undefined => {\n\tconst pooled = ALankaScenario.getAutoRegisteredScenarios();\n\n\tfor (const value of Object.values(ScenariosModule)) {\n\t\tif (typeof value !== \"function\" || !value.prototype) continue;\n\n\t\tconst Class = value as new () => ALankaScenario<unknown>;\n\t\tconst instance =\n\t\t\tpooled.find((scenario) => scenario.constructor === Class) ?? construct(Class);\n\t\tif (instance?.name === scenarioName) return Class;\n\t}\n\n\treturn undefined;\n};\n\n/** A new instance, or `undefined` for an export that is not constructible. */\nconst construct = (\n\tClass: new () => ALankaScenario<unknown>,\n): ALankaScenario<unknown> | undefined => {\n\ttry {\n\t\treturn new Class();\n\t} catch {\n\t\treturn undefined;\n\t}\n};\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\treturn findScenarioClassByInstanceName(scenarioName);\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":[]}