lanka 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +242 -0
  3. package/dist/ALankaGateway-ExlRGT3D.d.ts +122 -0
  4. package/dist/ALankaSharedStore-B7uepuuk.d.ts +29 -0
  5. package/dist/ILankaApiError-zI_2bNs0.d.ts +16 -0
  6. package/dist/ILankaRuntimeConfig-Vl436GWK.d.ts +62 -0
  7. package/dist/ILankaScenarioMetadata-Bu-yggTZ.d.ts +14 -0
  8. package/dist/ILankaScenarioVM-DuCyPoyT.d.ts +260 -0
  9. package/dist/LankaError-B1HtuIkw.d.ts +86 -0
  10. package/dist/LankaScenarioLocator-BGQHwf3n.d.ts +144 -0
  11. package/dist/LankaSharedStoreLocator-MvCpav5F.d.ts +126 -0
  12. package/dist/TLankaErrorHandler-Yfqtdh1M.d.ts +3 -0
  13. package/dist/_extend/index.d.ts +34 -0
  14. package/dist/_extend/index.js +36 -0
  15. package/dist/_extend/index.js.map +1 -0
  16. package/dist/_internal/index.d.ts +43 -0
  17. package/dist/_internal/index.js +34 -0
  18. package/dist/_internal/index.js.map +1 -0
  19. package/dist/activeRuntime-FcsSJvUg.d.ts +84 -0
  20. package/dist/bootstrap/index.d.ts +242 -0
  21. package/dist/bootstrap/index.js +22 -0
  22. package/dist/bootstrap/index.js.map +1 -0
  23. package/dist/chunk-73IVH3C6.js +52 -0
  24. package/dist/chunk-73IVH3C6.js.map +1 -0
  25. package/dist/chunk-BGVDPDX4.js +29 -0
  26. package/dist/chunk-BGVDPDX4.js.map +1 -0
  27. package/dist/chunk-C2HP7CRD.js +224 -0
  28. package/dist/chunk-C2HP7CRD.js.map +1 -0
  29. package/dist/chunk-D27MREPB.js +13 -0
  30. package/dist/chunk-D27MREPB.js.map +1 -0
  31. package/dist/chunk-DTO27QFR.js +59 -0
  32. package/dist/chunk-DTO27QFR.js.map +1 -0
  33. package/dist/chunk-EWVDJYCC.js +296 -0
  34. package/dist/chunk-EWVDJYCC.js.map +1 -0
  35. package/dist/chunk-FIR4XTBL.js +136 -0
  36. package/dist/chunk-FIR4XTBL.js.map +1 -0
  37. package/dist/chunk-ILQNYQY5.js +200 -0
  38. package/dist/chunk-ILQNYQY5.js.map +1 -0
  39. package/dist/chunk-J5LA3Q6D.js +14 -0
  40. package/dist/chunk-J5LA3Q6D.js.map +1 -0
  41. package/dist/chunk-MDZ42XRH.js +10 -0
  42. package/dist/chunk-MDZ42XRH.js.map +1 -0
  43. package/dist/chunk-Q3SOVBIJ.js +176 -0
  44. package/dist/chunk-Q3SOVBIJ.js.map +1 -0
  45. package/dist/chunk-Q7QESSYF.js +49 -0
  46. package/dist/chunk-Q7QESSYF.js.map +1 -0
  47. package/dist/chunk-RKYKK6MN.js +19 -0
  48. package/dist/chunk-RKYKK6MN.js.map +1 -0
  49. package/dist/chunk-RYFZCAQ3.js +637 -0
  50. package/dist/chunk-RYFZCAQ3.js.map +1 -0
  51. package/dist/chunk-UJEC7H6K.js +39 -0
  52. package/dist/chunk-UJEC7H6K.js.map +1 -0
  53. package/dist/chunk-XESL274R.js +23 -0
  54. package/dist/chunk-XESL274R.js.map +1 -0
  55. package/dist/chunk-YR4MZXMU.js +13 -0
  56. package/dist/chunk-YR4MZXMU.js.map +1 -0
  57. package/dist/config/index.d.ts +63 -0
  58. package/dist/config/index.js +16 -0
  59. package/dist/config/index.js.map +1 -0
  60. package/dist/createLankaScope-Bc_vChRs.d.ts +30 -0
  61. package/dist/errors/index.d.ts +37 -0
  62. package/dist/errors/index.js +16 -0
  63. package/dist/errors/index.js.map +1 -0
  64. package/dist/gateway/index.d.ts +258 -0
  65. package/dist/gateway/index.js +438 -0
  66. package/dist/gateway/index.js.map +1 -0
  67. package/dist/index.d.ts +20 -0
  68. package/dist/index.js +43 -0
  69. package/dist/index.js.map +1 -0
  70. package/dist/lankaHttpInFlight-Bk1eIuSx.d.ts +43 -0
  71. package/dist/lankaRequestMiddleware-DAC5kCb7.d.ts +62 -0
  72. package/dist/lankaStandardValidator-CL-r-zEV.d.ts +34 -0
  73. package/dist/locator/index.d.ts +282 -0
  74. package/dist/locator/index.js +67 -0
  75. package/dist/locator/index.js.map +1 -0
  76. package/dist/logger/index.d.ts +146 -0
  77. package/dist/logger/index.js +11 -0
  78. package/dist/logger/index.js.map +1 -0
  79. package/dist/mock/index.d.ts +16 -0
  80. package/dist/mock/index.js +58 -0
  81. package/dist/mock/index.js.map +1 -0
  82. package/dist/role/index.d.ts +48 -0
  83. package/dist/role/index.js +7 -0
  84. package/dist/role/index.js.map +1 -0
  85. package/dist/scenario/index.d.ts +204 -0
  86. package/dist/scenario/index.js +28 -0
  87. package/dist/scenario/index.js.map +1 -0
  88. package/dist/validation/index.d.ts +18 -0
  89. package/dist/validation/index.js +53 -0
  90. package/dist/validation/index.js.map +1 -0
  91. package/dist/viewmodel/index.d.ts +478 -0
  92. package/dist/viewmodel/index.js +701 -0
  93. package/dist/viewmodel/index.js.map +1 -0
  94. package/package.json +99 -0
  95. package/skills/lanka-core/SKILL.md +241 -0
  96. package/skills/lanka-core/reference.md +1090 -0
  97. package/skills/lanka-packages/SKILL.md +70 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 lankajs contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,242 @@
1
+ # lanka
2
+
3
+ **◆ core** · Core
4
+
5
+ > Ten subsystems, two peer dependencies, five extension points.
6
+
7
+ One, unscoped. Everything depends on it; it depends on nothing.
8
+
9
+ **Runs in:** the browser, node and React Native — everywhere.
10
+
11
+ **How to use it:** [GUIDE.md](./GUIDE.md) — the user guide, with examples. **How to change it:** [SKILL.md](./SKILL.md).
12
+
13
+ ## Extension points core declares
14
+
15
+ | Point | What it gives | Available |
16
+ | --- | --- | --- |
17
+ | `useRequestMiddleware(mw)` | wrap every request | yes |
18
+ | `inFlight.subscribe(fn)` | observe the number of requests on the wire | yes |
19
+ | `lankaEventBus.addMiddleware` | intercept bus events | yes |
20
+ | `LankaLogger sinks` | where log output goes | yes |
21
+ | `use(plugin)` | register a whole plugin | yes |
22
+
23
+ The list is closed on purpose. Each point is a public contract for the lifetime of a
24
+ major version, so anything that can be a module must be a module.
25
+
26
+ ## Subsystems
27
+
28
+ Flat, with no intermediate `Layers/`: **folder = subpath in `exports` = line in this list.**
29
+
30
+ Each subsystem is exported through its BARREL (`index.ts`), so public is exactly what the
31
+ barrel lists, moving a file inside a subsystem is not a breaking change, and a consumer's
32
+ import reads `lanka/gateway`.
33
+
34
+ `internal/` is not in the map — that is what may be refactored without a major. Hence the
35
+ rule: a primitive a neighbouring package needs has two honest exits, becoming public here
36
+ or moving to the neighbour. `src/publicSurface.test.ts` checks the map, the barrels and
37
+ the seal on `internal`, and catches a subsystem added as a folder and forgotten in
38
+ `exports`.
39
+
40
+ - `src/bootstrap/`
41
+ - `src/role/`
42
+ - `src/config/`
43
+ - `src/locator/`
44
+ - `src/gateway/`
45
+ - `src/validation/`
46
+ - `src/mock/`
47
+ - `src/errors/`
48
+ - `src/scenario/`
49
+ - `src/viewmodel/`
50
+ - `src/logger/`
51
+ - `src/internal/` — **not exported.** Refactored without a major.
52
+
53
+ ## Instance
54
+
55
+ ```ts
56
+ const lanka = createLanka({ host, flags });
57
+ await lanka.bootstrap({ services });
58
+ ```
59
+
60
+ The instance owns all framework state: the bus, the scenario registries, four locator
61
+ caches, the config and the in-flight request counter. Module-level state made three
62
+ things impossible, none of which looked like a bug: two apps in one process shared a
63
+ bus, SSR reused state between different users' requests, and test isolation rested on a
64
+ global `beforeEach` reaching into internal registries.
65
+
66
+ **Ambient facades** — `lankaEventBus.dispatch`, `lankaSingletons.foo`, `getLankaFlags()`,
67
+ `lankaHttpInFlight` — resolve THE ONE active instance (`internal/activeRuntime.ts`).
68
+ They exist for callers that cannot hold an instance: a user-extended `ALankaScenario`,
69
+ the static `LankaScenarioBootstrap`, a module package with no instance in scope.
70
+ Isolation belongs to the instance holder; a facade cannot offer it.
71
+
72
+ One thing stays at module level deliberately: `ALankaScenario` collects constructed
73
+ scenarios into a static pool. That is not runtime state but a REGISTRY OF DEFINITIONS —
74
+ the classes come from one `@lanka_di/Scenarios` barrel and both instances must see the
75
+ same list. Splitting it would be divergence, not isolation.
76
+
77
+ ## Failure
78
+
79
+ `LankaError` carries a TAGGED kind: `network` · `timeout` · `aborted` · `http` · `schema` ·
80
+ `domain`. Six rather than one, because each demands something different of the interface:
81
+ a network failure invites a retry, an aborted request is not shown at all (the user left),
82
+ a schema break is reported as a break rather than as the user's fault.
83
+
84
+ The kind is assigned where the failure is born: in `ALankaRequest.execute`, the single
85
+ point every request passes through.
86
+
87
+ Parsing a particular response body format is NOT here: which JSON the backend sends is
88
+ policy, and policy lives in `@lankajs/plugin-http`.
89
+
90
+ ## Host contract
91
+
92
+ ```ts
93
+ interface ILankaHost {
94
+ apiBaseUrl: string;
95
+ httpErrorMessage(status: number): string;
96
+ networkErrorMessage(): string;
97
+ timeoutErrorMessage(): string;
98
+ }
99
+ ```
100
+
101
+ All required, and that is the choice: a forgotten field is a compile error in the one
102
+ place it can be passed, rather than a wrong-language string in the interface or an
103
+ `undefined` inside a request URL. `ALankaGateway.endpoint()` prefixes with `apiBaseUrl`.
104
+
105
+ ### Request middleware shape
106
+
107
+ **Request middleware is a WRAPPER, not a set of hooks.** The `(ctx, next) => …` shape,
108
+ because retry cannot be expressed with `onRequest`/`onResponse`/`onError`: `onError` can
109
+ replace an error but cannot run the request again — and retry plus auth refresh are the
110
+ two main abilities of a request-policy plugin. Registered first wraps the rest.
111
+
112
+ The objection to `next()` that holds for the event bus does not carry over: there a
113
+ middleware that skips `next` SILENCES the event, here it returns a value instead of a
114
+ request, and the caller sees it.
115
+
116
+ **Cancellation and timeout.** `execute` takes `signal` and `timeoutMs`; the default
117
+ timeout is per instance. The framework combines the caller's signal and its own timer
118
+ into ONE signal and still distinguishes who aborted: a timed-out request yields `timeout`
119
+ and is shown, a caller-aborted one yields `aborted` and stays silent. `AbortSignal` does
120
+ not distinguish them — it has one `abort` for everyone.
121
+
122
+ ## Response body validation
123
+
124
+ The port accepts ANY schema implementing Standard Schema: zod 4, valibot, arktype. An
125
+ abstraction typed by its single implementation is not an abstraction; the proof is a
126
+ second implementation passing the same assertions, and it is in the tests.
127
+
128
+ There are no adapter classes: a schema describes itself. The app chooses the library —
129
+ `@lankajs/zod`, `@lankajs/valibot`, or neither, working with schemas directly.
130
+
131
+ An async schema is rejected LOUDLY. Standard Schema allows `validate` to return a
132
+ promise, a synchronous port cannot await it, and answering "fine" would let unvalidated
133
+ data through — a check that cannot fail reporting success.
134
+
135
+ ## Lifetime
136
+
137
+ `lanka.createScope()` gives a lifetime shorter than the application's: an object created
138
+ in a scope goes away with it.
139
+
140
+ A scope takes only ITS OWN objects. One that took others' would be more dangerous than no
141
+ scopes at all: closing a screen would break the app. Resolving from a closed scope is
142
+ rejected loudly — it is almost always a reference that outlived its screen.
143
+
144
+ A lazy ViewModel has `dispose()` for the same reason: it subscribes to scenarios on first
145
+ use, and without explicit disposal the subscription outlives the screen that created it.
146
+
147
+ ## Access-tracking blind spot
148
+
149
+ A consumer re-renders only for keys it READ through the proxy. An action computing a
150
+ value via `get()` reads state past the proxy — so a component whose only link to a key
151
+ goes through such a getter never re-renders: the screen freezes and there is no error.
152
+
153
+ It cannot be fixed in the view: destructuring "for the side effect" reads as dead code and
154
+ the next refactor or lint autofix removes it. The fix is
155
+ `enableAccessTrackingOptimization: false`, and so that nobody has to remember it, in
156
+ development the mismatch announces itself: the framework sees that a key changed, that no
157
+ re-render will follow, and that the component reads that key through a getter — and warns
158
+ with the ViewModel and key names.
159
+
160
+ The trap stays silent on healthy code: not reading what you do not need is the work
161
+ tracking exists for.
162
+
163
+ ## Event bus
164
+
165
+ **Buffering on request only.** Buffer depth is the maximum of what the event declares
166
+ (`registerEvent({ replay: N })`) and what subscribers ask for; when the last asker
167
+ unsubscribes the buffer is cleared. Buffering every payload unconditionally holds
168
+ personal data in memory with no consumer at all.
169
+
170
+ **`replay` counts values:** `false | "last" | N`, where `true` means "last".
171
+
172
+ **`subscribe` returns an unsubscribe.** It removes EXACTLY that subscription: by callback,
173
+ two subscriptions of one function are indistinguishable.
174
+
175
+ **Delivery iterates a COPY of the subscriber list.** A subscriber may unsubscribe inside
176
+ its own handler, and unsubscribing splices the same array, so iterating the original
177
+ skipped a neighbour silently. The deliberate side effect: subscribing during delivery
178
+ waits for the next event.
179
+
180
+ **`registerEvent` merges metadata** instead of recreating state; recreating dropped every
181
+ subscriber silently.
182
+
183
+ **Middleware returns a decision** — `"pass"` or `{ stop: reason }`. A `next()`-based shape
184
+ means not calling it makes the event vanish SILENTLY: a mechanism that exists for
185
+ observability would be its own blind spot. A stop is written to the event log and is
186
+ visible to the inspector. An exception in middleware is treated the same way.
187
+
188
+ ## Which of the three carries a connection
189
+
190
+ The framework ships a ViewModel, a scenario and a shared store, and the hardest
191
+ question is not how any of them works but which one a connection belongs to. The
192
+ ladder, in order — take the first rung that fits and stop:
193
+
194
+ 1. **One ViewModel owns the state.** Start here always. A screen with a question
195
+ about its own data has no connection to carry.
196
+ 2. **Another must REACT — a scenario.** It carries a fact (`GapCompleted`), not a
197
+ command, and each side decides what the fact means for its own state. Nobody
198
+ imports anybody: that is the whole reason the layer exists.
199
+ 3. **Several must CO-EDIT one state — one shared store.** Only when scenarios have
200
+ turned into synchronisation: the same value written in three ViewModels, kept in
201
+ step by hand, racing on a slow answer. Keep the store scoped to the feature and
202
+ give it explicit reset points.
203
+ 4. **The store became a bus — the feature boundary is wrong.** A shared store that
204
+ everything reads is global state with extra steps. Split the feature and hand
205
+ cross-feature connections back to scenarios.
206
+
207
+ The rungs are not styles to pick between. Each costs more than the one above: a
208
+ scenario is a name in two files, a shared store is a lifetime somebody has to own.
209
+
210
+ `no-viewmodel-to-viewmodel` in `@lankajs/tool-eslint` enforces the only hard part —
211
+ that rung 1 never reaches sideways — and the core playground runs rungs 2 and 3
212
+ beside each other: a scenario writes into a ViewModel that never heard of the
213
+ trigger, and two ViewModels share one selection through `PlaygroundTodoStore`.
214
+
215
+ ## Naming rule
216
+
217
+ **Anything the consumer writes in their own code carries the framework name.**
218
+ `ALankaGateway`, `ALankaScenario`, `createLankaVM`, `lankaEventBus`, `LankaLogger`,
219
+ `lankaSingletons`.
220
+
221
+ Two reasons, the second the stronger one. A reader of an unfamiliar file can see where
222
+ `ALankaGateway` came from; `AGateway` says nothing. And the framework does not squat
223
+ popular names — `Logger`, `EventBus`, `Storage`, `Singletons`, `Scenarios` are exactly
224
+ the names an app wants for ITS own things, and a library that takes them forces the app
225
+ to rename.
226
+
227
+ `ViewModel` shortens to `VM` in class, factory and type names: `ALankaVM` and
228
+ `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.
230
+
231
+ Three names stay bare — `isRecord`, `getStringField`, `generateUuid`. They are pure
232
+ utilities over ordinary values; a collision there is resolved at the import site, which
233
+ is not available for a class that gets EXTENDED.
234
+
235
+ The rule is executed by `core/src/brand.test.ts`, not stated in a document.
236
+
237
+ `.lanka_di` barrel names (`Gateways.ts`, `Scenarios.ts`, …) are NOT branded: those files
238
+ belong to the consumer and the folder already says whose they are.
239
+
240
+ ---
241
+
242
+ Repository map: [../README.md](../README.md)
@@ -0,0 +1,122 @@
1
+ import { I as ILankaValidator } from './lankaStandardValidator-CL-r-zEV.js';
2
+
3
+ /**
4
+ * Transport options plus what core controls.
5
+ *
6
+ * `signal` and `timeoutMs` are taken out and never reach the transport as given:
7
+ * core combines them into one signal and passes that.
8
+ */
9
+ type TLankaExecuteOptions<TOptions> = TOptions & {
10
+ signal?: AbortSignal;
11
+ timeoutMs?: number;
12
+ };
13
+
14
+ /**
15
+ * What a gateway needs of a request: one method that sends and returns a value.
16
+ *
17
+ * The port, so a consumer can supply their OWN request rather than inheriting
18
+ * from ours. `ALankaRequest` implements it and remains the convenient way in —
19
+ * it brings middleware composition, deadline resolution, in-flight accounting
20
+ * and failure classification — but a consumer with a different transport story
21
+ * (a native bridge, an offline queue, a test double that never touches the
22
+ * network) needs none of that and should not have to extend a class to be
23
+ * accepted.
24
+ *
25
+ * `mockHandler` is part of the contract rather than an implementation detail: it
26
+ * is how development without a backend works, and a request that ignored it
27
+ * would silently disable mock mode for the gateway holding it.
28
+ */
29
+ interface ILankaRequest<TOptions = RequestInit> {
30
+ /**
31
+ * Sends the request and returns the value the caller asked for.
32
+ *
33
+ * Rejects with a `LankaError` carrying a kind — `http`, `network`, `timeout`,
34
+ * `aborted`, `schema` — because the kind is what a caller branches on: a
35
+ * timeout is shown, a cancellation is not, and only a network failure invites
36
+ * a retry.
37
+ */
38
+ execute<TReturn = Response>(endpoint: string, options?: TLankaExecuteOptions<TOptions>, mockHandler?: () => Promise<TReturn>): Promise<TReturn>;
39
+ }
40
+
41
+ type TLankaQueryParams = string | number | boolean | null | undefined | TLankaQueryParams[] | {
42
+ [key: string]: TLankaQueryParams;
43
+ };
44
+
45
+ type TLankaQueryBuilder = (params: Record<string, TLankaQueryParams>) => URLSearchParams;
46
+
47
+ interface IALankaGatewayConfig<TOptions> {
48
+ /**
49
+ * The request this gateway sends through. Defaults to `LankaFetchJsonRequest`.
50
+ *
51
+ * Each request kind has its own logic — one answers a parsed JSON body, another
52
+ * the raw `Response`, another uploads multipart — and JSON over `fetch` is what
53
+ * almost every gateway wants. So it is supplied when the gateway is NOT
54
+ * ordinary, and omitted otherwise.
55
+ *
56
+ * Typed as the PORT: `ALankaRequest` is the convenient implementation, not a
57
+ * requirement. A consumer with their own transport story supplies their own,
58
+ * and a test supplies one that never leaves the process.
59
+ */
60
+ request?: ILankaRequest<TOptions>;
61
+ /** Base API path for this gateway, e.g. "/admin/company" */
62
+ basePath?: string;
63
+ /**
64
+ * Serialises query parameters for every request of this gateway.
65
+ *
66
+ * An error-body handler does NOT belong here: it is given to the request —
67
+ * `new LankaFetchJsonRequest({ errorHandler })` — which is the only layer that
68
+ * reads it.
69
+ */
70
+ queryParamsHandler?: TLankaQueryBuilder;
71
+ /** Validation service (DI). May be replaced for tests / migration. */
72
+ validationService?: ILankaValidator;
73
+ /**
74
+ * Enable mock mode. If undefined, reads from infrastructure flags (isMockMode).
75
+ * If true, mock handlers passed to request methods will be used instead of real requests.
76
+ */
77
+ useMock?: boolean;
78
+ }
79
+
80
+ declare abstract class ALankaGateway<TOptions = RequestInit> {
81
+ protected requestExecutor: ILankaRequest<TOptions>;
82
+ protected queryParamsHandler: TLankaQueryBuilder;
83
+ protected readonly useMock: boolean;
84
+ protected readonly basePath: string;
85
+ protected constructor(config: IALankaGatewayConfig<TOptions>);
86
+ /**
87
+ * Resolves endpoint for request.
88
+ * - Absolute paths (starting with "/") are returned as-is
89
+ * - Relative paths are joined with basePath
90
+ * - Query-only strings like "?a=1" are attached to basePath
91
+ */
92
+ protected endpoint(path?: string): string;
93
+ /**
94
+ * Joins `basePath` and the method path.
95
+ */
96
+ private resolvePath;
97
+ /**
98
+ * Prefixes the API base URL from the host contract.
99
+ *
100
+ * Here rather than in every consumer: otherwise each consumer knows the URL
101
+ * and the framework does not, and a realtime plugin would have to know a
102
+ * specific application's build.
103
+ *
104
+ * Declaring the field and not using it would be worse than not declaring it: a
105
+ * declaration nothing is built from is a second truth, free to diverge from
106
+ * the first.
107
+ *
108
+ * An absolute URL never reaches here — `endpoint()` filters it out before the
109
+ * join.
110
+ */
111
+ private withApiBase;
112
+ protected buildQueryParams<T extends object>(params: T): URLSearchParams;
113
+ protected request<TReturn = unknown>(path: string, options?: TLankaExecuteOptions<TOptions>, mockHandler?: () => Promise<TReturn>): Promise<TReturn>;
114
+ /**
115
+ * Allows to replace request implementation at runtime (e.g. feature flags / tests).
116
+ * If you prefer static customization - override `request()` in a subclass.
117
+ */
118
+ protected setRequest(request: ILankaRequest<TOptions>): void;
119
+ protected setQueryParamsHandler(handler: TLankaQueryBuilder): void;
120
+ }
121
+
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 };
@@ -0,0 +1,29 @@
1
+ import { StoreApi } from 'zustand/vanilla';
2
+
3
+ /**
4
+ * Base abstraction for shared feature stores.
5
+ *
6
+ * A store built on this class is resolved through the shared-store locator and
7
+ * reused across several ViewModels.
8
+ */
9
+ declare abstract class ALankaSharedStore<TState extends object> {
10
+ private readonly api;
11
+ private readonly createInitialState;
12
+ protected constructor(createInitialState: () => TState);
13
+ getApi(): StoreApi<TState>;
14
+ getState(): TState;
15
+ setState(partial: TState | Partial<TState> | ((state: TState) => TState | Partial<TState>), replace?: boolean): void;
16
+ subscribe(listener: (state: TState, prevState: TState) => void): () => void;
17
+ /**
18
+ * Back to what the store was built with.
19
+ *
20
+ * Public, and it was not: while this was `protected` only a subclass could
21
+ * reset, so the class style had a capability the functional one could not
22
+ * reach — the asymmetry `skills/parity/SKILL.md` forbids. A shared store needs
23
+ * explicit reset points (see the ladder in `core/README.md`), and the
24
+ * application that owns them is outside the class either way.
25
+ */
26
+ reset(): void;
27
+ }
28
+
29
+ export { ALankaSharedStore as A };
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Structural API-error shape read by consumer code.
3
+ *
4
+ * `status` is OPTIONAL: a network drop and an aborted request carry no status,
5
+ * and three of the six `LankaError` kinds have none.
6
+ *
7
+ * `LankaError` implements this interface, so consumers may read `status` and
8
+ * `errors` off any thrown framework error.
9
+ */
10
+ interface ILankaApiError {
11
+ status?: number;
12
+ errors?: string[];
13
+ message?: string;
14
+ }
15
+
16
+ export type { ILankaApiError as I };
@@ -0,0 +1,62 @@
1
+ interface ILankaFlags {
2
+ isMockMode?: boolean;
3
+ loggerEnabled?: boolean;
4
+ loggerGateway?: boolean;
5
+ loggerScenario?: boolean;
6
+ loggerViewModel?: boolean;
7
+ loggerView?: boolean;
8
+ loggerBootstrap?: boolean;
9
+ /** Comes from `import.meta.env.PROD` — silences all log output. */
10
+ isProduction?: boolean;
11
+ /** Comes from `import.meta.env.DEV` — enables development-only behaviour. */
12
+ isDevelopment?: boolean;
13
+ }
14
+
15
+ /**
16
+ * What the package needs from the HOSTING application and cannot know itself.
17
+ *
18
+ * A package cannot import its consumer, and should not: these are product
19
+ * decisions belonging to whoever owns the screens and the session.
20
+ *
21
+ * The fields are REQUIRED, and that is the point. None has a sensible default —
22
+ * a missing message factory would mean a wrong-language string in the interface,
23
+ * a missing base URL an `undefined` inside a request path. So omitting one is a
24
+ * TYPE ERROR in the app's own barrel rather than a surprise at runtime.
25
+ */
26
+ interface ILankaHost {
27
+ /**
28
+ * What to show when a response carried a status but no message.
29
+ *
30
+ * ONE method rather than a map of seven: which statuses the app has copy for,
31
+ * and what it says for the rest, is the app's business. The package knows only
32
+ * that it has a number and needs a sentence.
33
+ */
34
+ httpErrorMessage(status: number): string;
35
+ /**
36
+ * API base URL — where the framework calls.
37
+ *
38
+ * In the contract because otherwise each consumer would know the URL and the
39
+ * framework would not, making `@lankajs/plugin-sse` impossible: it would
40
+ * have to know a specific application's build.
41
+ *
42
+ * Without a trailing slash — `ALankaGateway.endpoint()` normalises it.
43
+ */
44
+ apiBaseUrl: string;
45
+ /**
46
+ * What to say when the request never reached the server.
47
+ *
48
+ * `LankaError` separates `network` from `timeout` because the interface needs
49
+ * different things from them. How the app phrases each is not the framework's
50
+ * to guess.
51
+ */
52
+ networkErrorMessage(): string;
53
+ /** What to say when it arrived but no response came. */
54
+ timeoutErrorMessage(): string;
55
+ }
56
+
57
+ interface ILankaRuntimeConfig {
58
+ flags?: ILankaFlags;
59
+ host?: ILankaHost;
60
+ }
61
+
62
+ export type { ILankaFlags as I, ILankaHost as a, ILankaRuntimeConfig as b };
@@ -0,0 +1,14 @@
1
+ import { a as ILankaScenario } from './ILankaScenarioVM-DuCyPoyT.js';
2
+
3
+ /**
4
+ * Metadata about a registered scenario
5
+ */
6
+ interface ILankaScenarioMetadata {
7
+ scenario: ILankaScenario<unknown>;
8
+ name: string;
9
+ eventType: string;
10
+ dataTypeName: string;
11
+ isRegistered: boolean;
12
+ }
13
+
14
+ export type { ILankaScenarioMetadata as I };