@jarenjs/linq 0.49.2 → 0.66.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/ARCHITECTURE.md +227 -0
  2. package/README.md +650 -17
  3. package/docs/APP-PEN.md +1143 -0
  4. package/docs/CONTRACT-PEN.md +1221 -0
  5. package/docs/DB-CLIENT.md +882 -0
  6. package/docs/FLOW-PEN.md +1033 -0
  7. package/docs/FORMS-PEN.md +940 -0
  8. package/docs/JSLT-PEN.md +955 -0
  9. package/docs/LINQ-FORMAT.md +778 -383
  10. package/docs/MIGRATION-PEN.md +781 -0
  11. package/docs/MODEL-PEN.md +1092 -0
  12. package/docs/QUERY-PEN.md +1724 -0
  13. package/docs/SCHEMA-PEN.md +1218 -0
  14. package/package.json +57 -4
  15. package/src/app/action.js +251 -0
  16. package/src/app/capture.js +63 -0
  17. package/src/app/define.js +255 -0
  18. package/src/app/index.js +20 -0
  19. package/src/app/patch.js +277 -0
  20. package/src/app/sub.js +106 -0
  21. package/src/async.js +377 -75
  22. package/src/capture-root.js +82 -0
  23. package/src/concurrency.js +48 -11
  24. package/src/contract/define.js +282 -0
  25. package/src/contract/http.js +247 -0
  26. package/src/contract/index.js +23 -0
  27. package/src/contract/operation.js +338 -0
  28. package/src/db/handle.js +89 -0
  29. package/src/db/include.js +351 -0
  30. package/src/db/index.js +24 -0
  31. package/src/db/ledger.js +195 -0
  32. package/src/db/live.js +43 -0
  33. package/src/db/membership.js +37 -0
  34. package/src/db/open.js +130 -0
  35. package/src/document.js +143 -13
  36. package/src/effect.js +65 -0
  37. package/src/errors.js +78 -6
  38. package/src/expression.js +463 -36
  39. package/src/federate.js +531 -0
  40. package/src/flow/capture.js +33 -0
  41. package/src/flow/dag.js +316 -0
  42. package/src/flow/fsm.js +323 -0
  43. package/src/flow/index.js +22 -0
  44. package/src/forms/index.js +43 -0
  45. package/src/forms/rules.js +170 -0
  46. package/src/forms/submit.js +177 -0
  47. package/src/index.js +5 -2
  48. package/src/jslt/body.js +226 -0
  49. package/src/jslt/index.js +18 -0
  50. package/src/jslt/rules.js +202 -0
  51. package/src/json-boundary.js +90 -0
  52. package/src/migration/define.js +318 -0
  53. package/src/migration/index.js +15 -0
  54. package/src/migration/steps.js +244 -0
  55. package/src/model/collection.js +273 -0
  56. package/src/model/define.js +125 -0
  57. package/src/model/entity.js +307 -0
  58. package/src/model/index.js +47 -0
  59. package/src/model/relation.js +85 -0
  60. package/src/provider.js +137 -20
  61. package/src/schema/brand.js +31 -0
  62. package/src/schema/builders.js +526 -0
  63. package/src/schema/check.js +29 -0
  64. package/src/schema/emit.js +394 -0
  65. package/src/schema/factories.js +239 -0
  66. package/src/schema/index.js +37 -0
  67. package/src/schema-of.js +24 -0
  68. package/src/sequence.js +233 -103
  69. package/src/sources.js +10 -3
  70. package/types/app.d.ts +293 -0
  71. package/types/contract.d.ts +468 -0
  72. package/types/db.d.ts +359 -0
  73. package/types/flow.d.ts +285 -0
  74. package/types/forms.d.ts +253 -0
  75. package/types/index.d.ts +296 -26
  76. package/types/jslt.d.ts +193 -0
  77. package/types/migration.d.ts +201 -0
  78. package/types/model.d.ts +526 -0
  79. package/types/schema.d.ts +494 -0
package/types/app.d.ts ADDED
@@ -0,0 +1,293 @@
1
+ /**
2
+ * Hand-authored declarations for `@jarenjs/linq/app` — the app pen's
3
+ * type contract, kept to the same line as `index.d.ts`: the common path
4
+ * is precisely typed, the exotic path is honestly `unknown`, nothing is
5
+ * ever a WRONG type.
6
+ *
7
+ * `AppDocument<State, Actions>` carries the state shape and the ACTION
8
+ * NAMES as phantoms, both read off the declarations themselves — the
9
+ * keys of `actions` are literal, so `ActionsOf<typeof app>` is the union
10
+ * a `bind<Names>()` is checked against and `bind<Names>('nope')` does
11
+ * not compile, before it is `JL0102` and long before the loop's
12
+ * `JA2001`.
13
+ *
14
+ * The honest limits, both of them TypeScript's own (a function's type
15
+ * arguments are all-or-none, and a sibling member's inferred type cannot
16
+ * contextually type a callback beside it):
17
+ *
18
+ * - an action's `s` is typed by ANNOTATION — `action((s: Expr<State>, x)
19
+ * => …)` — because `action()` is evaluated before `defineApp()` sees
20
+ * the `state` builder. What `defineApp({ state })` types is the
21
+ * DOCUMENT (`StateOf<typeof app>`), which is what a host reading
22
+ * `app.getState()` needs. `x.payload` needs no annotation:
23
+ * `action(fn, { payload })` declares it on the same call.
24
+ * - `bind()`'s action name is checked by annotating the call —
25
+ * `bind<Action>('todo/add')` — where `Action` is the union the author
26
+ * declared or `ActionsOf<>` read back. `defineApp()` checks the other
27
+ * direction at run time over the whole view, which is the half a type
28
+ * cannot reach: a view is a compiled stylesheet by then.
29
+ *
30
+ * Every claim here has a runtime twin in `test/linq/app-pen.test.js` and
31
+ * a compile-level pin in `test/consumer/linq-app.ts`; APP-PEN.md is the
32
+ * normative mapping table.
33
+ */
34
+
35
+ import type { Expr, MemberExpr, UnknownExpr } from './index.js';
36
+ import type { BuilderLike, Infer, Json, JsonSchema } from './schema.js';
37
+
38
+ type AnyBuilder = BuilderLike<any, any, any>;
39
+
40
+ /** `Expr<any>`/`Expr<unknown>` would pick a wrong arm; the honest top instead. */
41
+ type ValueExpr<T> = MemberExpr<T>;
42
+
43
+ // ————— the action scope —————
44
+
45
+ /**
46
+ * APP-FORMAT §3.1's default `$event` slice, plus one member per field
47
+ * the binding requested. Every value is a JSON primitive by
48
+ * construction: `$event` MUST survive `JSON.stringify`, the same
49
+ * invariant as state.
50
+ */
51
+ export type EventSlice<Fields extends string = never> =
52
+ & { readonly type: unknown; readonly value: unknown; readonly checked: unknown; readonly key: unknown }
53
+ & { readonly [K in Fields]: unknown };
54
+
55
+ /**
56
+ * The two externals §3.1 binds beside the state — and the whole ambient
57
+ * vocabulary an action has.
58
+ */
59
+ export interface ActionScope<Payload = unknown, Fields extends string = never> {
60
+ /** The dispatch payload (a binding's `with`), `null` when absent. */
61
+ readonly payload: ValueExpr<Payload>;
62
+ /** The serializable event slice, `null` for a programmatic dispatch. */
63
+ readonly event: Expr<EventSlice<Fields>>;
64
+ }
65
+
66
+ /** A patch path: a lambda over the state, or an RFC 6901 pointer. The
67
+ * lambda sees the SAME scope the action does, so a computed index may
68
+ * read `$payload` — annotate it (`(c: Expr<State>, y: ActionScope<P>)`)
69
+ * exactly as an action's own callback is annotated. */
70
+ export type PatchPath<State = unknown, Payload = unknown> =
71
+ | ((state: ValueExpr<State>, externals: ActionScope<Payload>) => unknown)
72
+ | string;
73
+
74
+ /** One RFC 6902 operation of a transition's `patch` (§3.2). */
75
+ export interface PatchOp {
76
+ readonly op: 'add' | 'replace' | 'remove' | 'move' | 'copy' | 'test';
77
+ readonly from?: unknown;
78
+ readonly path: unknown;
79
+ readonly value?: unknown;
80
+ }
81
+
82
+ /** One effect invocation (§5.1). */
83
+ export interface EffectDeclaration<Run extends string = string> {
84
+ readonly run: Run;
85
+ readonly with?: unknown;
86
+ }
87
+
88
+ /** A transition object (§3.2), as the action's capture spells it. */
89
+ export interface Transition {
90
+ readonly state?: unknown;
91
+ readonly patch?: readonly PatchOp[];
92
+ readonly effects?: readonly EffectDeclaration[];
93
+ }
94
+
95
+ /** One captured action document, carrying its payload type as a phantom. */
96
+ export interface ActionDeclaration<Payload = unknown> {
97
+ readonly __payload: Payload;
98
+ readonly document: Json;
99
+ }
100
+
101
+ // ————— bindings and subscriptions —————
102
+
103
+ /** §4's object binding form. */
104
+ export interface Binding<Names extends string = string> {
105
+ readonly action: Names;
106
+ readonly with?: unknown;
107
+ readonly event?: readonly string[];
108
+ readonly preventDefault?: boolean;
109
+ readonly stopPropagation?: boolean;
110
+ }
111
+
112
+ /** One subscription entry (§5.3). */
113
+ export interface SubDeclaration<Run extends string = string> {
114
+ readonly run: Run;
115
+ readonly with?: Json;
116
+ readonly when?: Json;
117
+ readonly withQuery?: Json;
118
+ readonly key?: Json;
119
+ readonly for?: Json;
120
+ }
121
+
122
+ /** What a subscription's `withQuery`/`key` binds under a `for` fan-out. */
123
+ export interface FanScope<Item = unknown> {
124
+ /** The item this instance was fanned out over (`$item`). */
125
+ readonly item: ValueExpr<Item>;
126
+ }
127
+
128
+ /** A subscription member: a callback over the state, or a query document. */
129
+ export type SubRule<State, Externals> =
130
+ | ((state: ValueExpr<State>, externals: Externals) => unknown)
131
+ | { readonly [keyword: string]: unknown }
132
+ | string;
133
+
134
+ // ————— the document —————
135
+
136
+ /**
137
+ * A `jaren-app` 0.1 document as the pen writes it, carrying the state
138
+ * shape and the declared action names as phantoms.
139
+ */
140
+ export interface AppDocument<State = unknown, Actions extends string = string> {
141
+ readonly __state: State;
142
+ readonly __actions: Actions;
143
+ readonly $app: '0.1';
144
+ readonly state?: Json;
145
+ readonly view: unknown;
146
+ readonly actions?: { readonly [name: string]: Json };
147
+ readonly subs?: readonly SubDeclaration[];
148
+ }
149
+
150
+ /**
151
+ * What `defineApp()` answers: the document, and the state's schema
152
+ * beside it — never merged, because the format has no slot for one.
153
+ *
154
+ * `Schema` is the third phantom because the SLOT is not always filled:
155
+ * `defineApp()` answers `null` for a plain-JSON state with no `schema`
156
+ * beside it, and a `JsonSchema | boolean` for the two overloads that
157
+ * were given a builder. Carrying that per overload is what lets the one
158
+ * line every consumer writes —
159
+ * `new JarenValidator().compile(stateSchema)` — compile without a narrow
160
+ * on the overloads that can never answer `null`. It defaults to the
161
+ * whole union, so `AppResult<State, Actions>` still names any result.
162
+ */
163
+ export interface AppResult<
164
+ State = unknown,
165
+ Actions extends string = string,
166
+ Schema extends JsonSchema | boolean | null = JsonSchema | boolean | null,
167
+ > {
168
+ readonly document: AppDocument<State, Actions>;
169
+ readonly stateSchema: Schema;
170
+ }
171
+
172
+ /** The state an app document describes — what `app.getState()` answers. */
173
+ export type StateOf<A> = A extends AppResult<infer S, any, any> ? S
174
+ : A extends AppDocument<infer S, any> ? S : never;
175
+ /** The action names an app declares — what a `bind<>()` is checked against. */
176
+ export type ActionsOf<A> = A extends AppResult<any, infer N, any> ? N
177
+ : A extends AppDocument<any, infer N> ? N : never;
178
+
179
+ // ————— the surface —————
180
+
181
+ /**
182
+ * One action document (§3): a callback captured over the state, `$event`
183
+ * and `$payload`, whose result is a transition. Annotate `s` to type it
184
+ * (`(s: Expr<State>, x) => …`); `payload` and `event` are TYPES only —
185
+ * the format carries no schema for either.
186
+ */
187
+ export function action<State = unknown>(
188
+ fn: (state: ValueExpr<State>, externals: ActionScope<unknown, never>) => unknown,
189
+ ): ActionDeclaration<unknown>;
190
+ export function action<
191
+ B extends AnyBuilder, const Fields extends readonly string[] = [], State = unknown,
192
+ >(
193
+ fn: (state: ValueExpr<State>, externals: ActionScope<Infer<B>, Fields[number]>) => unknown,
194
+ options: { readonly payload: B; readonly event?: Fields },
195
+ ): ActionDeclaration<Infer<B>>;
196
+ export function action<const Fields extends readonly string[], State = unknown>(
197
+ fn: (state: ValueExpr<State>, externals: ActionScope<unknown, Fields[number]>) => unknown,
198
+ options: { readonly event: Fields },
199
+ ): ActionDeclaration<unknown>;
200
+
201
+ /** A transition object (§3.2), in the order the runtime applies it. */
202
+ export function transition(spec: {
203
+ readonly state?: unknown;
204
+ readonly patch?: readonly PatchOp[];
205
+ readonly effects?: readonly EffectDeclaration[];
206
+ }): Transition;
207
+
208
+ /** One effect invocation (§5.1). Its props are a value in the ACTION's
209
+ * own scope: one document, one capture. */
210
+ export function effect<const Run extends string>(
211
+ run: Run, props?: unknown): EffectDeclaration<Run>;
212
+
213
+ /** `{ "op": "add", "path", "value" }` — sets a member, or REPLACES an
214
+ * array when the path names one; `append()` is the array insert. */
215
+ export function add<State = unknown, Payload = unknown>(
216
+ path: PatchPath<State, Payload>, value: unknown): PatchOp;
217
+ /** `{ "op": "add", "path": "<path>/-", "value" }` — RFC 6902's array append. */
218
+ export function append<State = unknown, Payload = unknown>(
219
+ path: PatchPath<State, Payload>, value: unknown): PatchOp;
220
+ /** `{ "op": "replace", "path", "value" }` — and the op an array ELEMENT needs. */
221
+ export function replace<State = unknown, Payload = unknown>(
222
+ path: PatchPath<State, Payload>, value: unknown): PatchOp;
223
+ /** `{ "op": "remove", "path" }`. */
224
+ export function remove<State = unknown, Payload = unknown>(
225
+ path: PatchPath<State, Payload>): PatchOp;
226
+ /** `{ "op": "move", "from", "path" }`. */
227
+ export function move<State = unknown, Payload = unknown>(
228
+ from: PatchPath<State, Payload>, path: PatchPath<State, Payload>): PatchOp;
229
+ /** `{ "op": "copy", "from", "path" }`. */
230
+ export function copy<State = unknown, Payload = unknown>(
231
+ from: PatchPath<State, Payload>, path: PatchPath<State, Payload>): PatchOp;
232
+ /** `{ "op": "test", "path", "value" }` — a failing test aborts the transition. */
233
+ export function test<State = unknown, Payload = unknown>(
234
+ path: PatchPath<State, Payload>, value: unknown): PatchOp;
235
+
236
+ /**
237
+ * One event binding (§4). Annotate the call with the declared action
238
+ * names — `bind<Action>('todo/add')` — and a name the app does not
239
+ * declare stops compiling.
240
+ */
241
+ export function bind<Names extends string = string>(
242
+ name: Names,
243
+ options?: {
244
+ readonly payload?: unknown;
245
+ readonly event?: readonly string[];
246
+ readonly preventDefault?: boolean;
247
+ readonly stopPropagation?: boolean;
248
+ },
249
+ ): Binding<Names>;
250
+
251
+ /** One subscription entry (§5.3). `with` is verbatim data and never
252
+ * restarts; `withQuery`/`key`/`for` are queries and make it dynamic. */
253
+ export function sub<const Run extends string, State = unknown, Item = unknown>(
254
+ run: Run,
255
+ options?: {
256
+ readonly with?: Json;
257
+ readonly when?: SubRule<State, Record<string, never>>;
258
+ readonly withQuery?: SubRule<State, FanScope<Item>>;
259
+ readonly key?: SubRule<State, FanScope<Item>>;
260
+ readonly for?: SubRule<State, Record<string, never>>;
261
+ },
262
+ ): SubDeclaration<Run>;
263
+
264
+ /**
265
+ * Write a `jaren-app` 0.1 document (§2) and the JSON Schema of its
266
+ * state. The initial state comes from the state builder's `default()`s
267
+ * unless `initial` names one; a required member that declares neither is
268
+ * `JL0102`.
269
+ */
270
+ export function defineApp<
271
+ B extends AnyBuilder, const A extends Record<string, ActionDeclaration<any>> = {},
272
+ >(spec: {
273
+ readonly state: B;
274
+ readonly initial?: Infer<B>;
275
+ readonly view: unknown;
276
+ readonly actions?: A;
277
+ readonly subs?: readonly SubDeclaration[];
278
+ }): AppResult<Infer<B>, keyof A & string, JsonSchema | boolean>;
279
+ export function defineApp<
280
+ B extends AnyBuilder, const A extends Record<string, ActionDeclaration<any>> = {},
281
+ >(spec: {
282
+ readonly state?: Json;
283
+ readonly schema: B;
284
+ readonly view: unknown;
285
+ readonly actions?: A;
286
+ readonly subs?: readonly SubDeclaration[];
287
+ }): AppResult<Infer<B>, keyof A & string, JsonSchema | boolean>;
288
+ export function defineApp<const A extends Record<string, ActionDeclaration<any>> = {}>(spec: {
289
+ readonly state?: Json;
290
+ readonly view: unknown;
291
+ readonly actions?: A;
292
+ readonly subs?: readonly SubDeclaration[];
293
+ }): AppResult<unknown, keyof A & string, null>;