@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
@@ -0,0 +1,201 @@
1
+ /**
2
+ * Hand-authored declarations for `@jarenjs/linq/migration` — the
3
+ * migration pen's type contract, on the line every pen keeps: the common
4
+ * path precisely typed, the exotic path honestly `unknown`, nothing ever
5
+ * a WRONG type.
6
+ *
7
+ * A transform is typed from the two model documents' phantoms. `from`
8
+ * gives the OLD shape of the named table (`InferMeta<typeof
9
+ * previous>[name]['doc']`), the value the callback is captured over;
10
+ * `to` gives the NEW shape, which the callback's result must SPELL — a
11
+ * member forgotten, mistyped or not in the new shape is a compile error,
12
+ * and the honest top (`UnknownExpr`, a `get()`) is admitted wherever a
13
+ * precise value is, because the runtime validator is the judge there.
14
+ * From a JSON snapshot the old shape is `unknown` and the value the
15
+ * honest top; the author annotates it (`(u: Expr<User>) => …`) from the
16
+ * declaration `jaren-db snapshot --types` writes, or keeps the previous
17
+ * model module beside the current one so the phantom is there. An
18
+ * assertion's row is typed by the members the two shapes SHARE (a
19
+ * precondition sees old rows, a postcondition new ones; what both agree
20
+ * on is what neither lies about), annotated when one shape is meant.
21
+ * Every claim here has a runtime twin in
22
+ * `test/linq/migration-pen.test.js` and a compile-level pin in
23
+ * `test/consumer/linq-migration.ts`.
24
+ */
25
+
26
+ import type { BoolExpr, DateTime, ExprBase, MemberExpr, UnknownExpr } from './index.js';
27
+ import type { Json } from './schema.js';
28
+ import type { ModelDocument, InferMeta } from './model.js';
29
+ import type { Externals, RuleDocument, RuleOut, ValueOf } from './jslt.js';
30
+
31
+ // ————— the document —————
32
+
33
+ export interface DdlStep { readonly kind: 'ddl'; readonly sql: string; readonly note?: string }
34
+ export interface SqlStep { readonly kind: 'sql'; readonly sql: string; readonly note?: string }
35
+ export interface JsltStep {
36
+ readonly kind: 'jslt';
37
+ readonly collection: string;
38
+ readonly stylesheet: readonly RuleDocument[];
39
+ /** A planner placeholder; the runner refuses it (`JD0021`). The pen never sets or clears it. */
40
+ readonly draft?: boolean;
41
+ readonly note?: string;
42
+ }
43
+ export interface QueryStep {
44
+ readonly kind: 'query';
45
+ readonly collection: string;
46
+ readonly assert: Json;
47
+ readonly expect?: 'empty' | 'ebv';
48
+ readonly note?: string;
49
+ }
50
+ export interface DeriveColumn {
51
+ readonly name: string;
52
+ readonly derive: 'geohash' | 'bbox' | 'vector';
53
+ readonly precision?: number;
54
+ readonly dims?: number;
55
+ readonly component?: 'w' | 's' | 'e' | 'n';
56
+ readonly segments: readonly object[];
57
+ }
58
+ export interface DeriveStep {
59
+ readonly kind: 'derive';
60
+ readonly collection: string;
61
+ readonly columns: readonly DeriveColumn[];
62
+ readonly note?: string;
63
+ }
64
+ export interface RebuildStep {
65
+ readonly kind: 'rebuild';
66
+ readonly table: string;
67
+ readonly create: readonly string[];
68
+ readonly copy: string;
69
+ readonly indexes: readonly string[];
70
+ readonly note?: string;
71
+ }
72
+ export type MigrationStep = DdlStep | SqlStep | JsltStep | QueryStep | DeriveStep | RebuildStep;
73
+
74
+ /** The `$migration` 0.1 document (MIGRATION-FORMAT §2). */
75
+ export interface MigrationDocument {
76
+ readonly $migration: '0.1';
77
+ readonly id: string;
78
+ readonly from: string;
79
+ readonly to: string;
80
+ readonly note?: string;
81
+ readonly steps: readonly MigrationStep[];
82
+ }
83
+
84
+ // ————— what a model document types —————
85
+
86
+ /** The entities and collections a model document declares; any string
87
+ * for a document the type cannot read (a JSON snapshot). */
88
+ export type DeclaredNames<M> = M extends ModelDocument<infer E, infer C>
89
+ ? (unknown extends E ? string : keyof E & string) | (unknown extends C ? string : keyof C & string)
90
+ : string;
91
+
92
+ /** The document shape of table `N` in a model — an entity's `doc`; the
93
+ * honest `unknown` for a collection, a JSON snapshot, or a name the
94
+ * model does not type. */
95
+ export type DocOf<M, N extends string> =
96
+ [InferMeta<M>] extends [never] ? unknown
97
+ : N extends keyof InferMeta<M>
98
+ ? (InferMeta<M>[N] extends { doc: infer D } ? D : unknown)
99
+ : unknown;
100
+
101
+ /** How a value of `T` is spelled in a transform's result: the value
102
+ * itself, an expression yielding it, the honest top, or — for an object
103
+ * — a literal spelling each member the same way; `unknown` admits
104
+ * anything. */
105
+ export type Spell<T> = SpellPresent<Exclude<T, undefined>> | (undefined extends T ? undefined : never);
106
+ type SpellPresent<T> =
107
+ unknown extends T ? unknown :
108
+ [T] extends [DateTime] ? string | ExprBase<string> | UnknownExpr :
109
+ [T] extends [readonly (infer E)[]] ? T | ExprBase<T> | UnknownExpr | readonly Spell<E>[] :
110
+ [T] extends [object] ? T | ExprBase<T> | UnknownExpr | { readonly [K in keyof T]: Spell<T[K]> } :
111
+ T | ExprBase<T> | UnknownExpr;
112
+
113
+ /** A rules array's verdict: a typed first rule must produce the new
114
+ * shape; a hand-written rule (`unknown` out) is the honest top. */
115
+ export type RulesFor<R extends readonly RuleDocument[], New> =
116
+ unknown extends RuleOut<R[0]> ? unknown : RuleOut<R[0]> extends New ? unknown : never;
117
+
118
+ /** Any stylesheet envelope: the JSLT pen's (phantoms and all) or a hand-written one. */
119
+ export type StylesheetLike = { readonly $jslt: '0.1'; readonly rules: readonly RuleDocument[] };
120
+
121
+ /** A stylesheet's verdict: a typed one must produce the new shape; an
122
+ * untyped or hand-written one is the honest top. */
123
+ export type SheetFor<S, New> = S extends { readonly __out: infer O }
124
+ ? (unknown extends O ? unknown : O extends New ? unknown : never)
125
+ : unknown;
126
+
127
+ export interface AssertOptions {
128
+ /** `'empty'` (the default, absent from the document): no row may
129
+ * satisfy the predicate — it names the violation; `'ebv'`: the matching
130
+ * rows are the witness. */
131
+ readonly expect?: 'empty' | 'ebv';
132
+ }
133
+
134
+ // ————— the builder —————
135
+
136
+ /** The migration under construction: immutable, every method a new
137
+ * builder; `.document`/`toJSON()` the deep-frozen document. */
138
+ export class Migration<From = unknown, To = unknown> {
139
+ private constructor();
140
+ /** One rendered DDL statement (`ddl`). */
141
+ ddl(sql: string, note?: string): Migration<From, To>;
142
+ /** One data statement spelled directly (`sql`, MIGRATION-FORMAT §9.4). */
143
+ sql(sql: string, note?: string): Migration<From, To>;
144
+ /** A `jslt` step: one root rule captured over the OLD row (`root`/`path`
145
+ * as externals), whose result spells the NEW row. Over a planned
146
+ * document it replaces the draft for `name`; otherwise it is appended
147
+ * for a table the target declares. */
148
+ transform<N extends DeclaredNames<To>, V extends ExprBase<unknown> = MemberExpr<DocOf<From, N>>>(
149
+ name: N,
150
+ rule: (row: V, x: Externals<{}, ValueOf<V>>) => Spell<DocOf<To, N>>,
151
+ ): Migration<From, To>;
152
+ /** A `stylesheet(…)` document — its output must be the new row when it
153
+ * is typed; a hand-written envelope is the honest top. A disposition or
154
+ * a mode table cannot ride in a `jslt` step (`JL0102`). */
155
+ transform<N extends DeclaredNames<To>, S extends StylesheetLike>(
156
+ name: N,
157
+ stylesheet: S & SheetFor<S, DocOf<To, N>>,
158
+ ): Migration<From, To>;
159
+ /** A rules array: a typed first rule must produce the new row; a
160
+ * hand-written rule is the honest top. */
161
+ transform<N extends DeclaredNames<To>, const R extends readonly RuleDocument[]>(
162
+ name: N,
163
+ rules: R & RulesFor<R, DocOf<To, N>>,
164
+ ): Migration<From, To>;
165
+ /** A `query` step over `name`'s rows: the predicate names the VIOLATION
166
+ * (`expect: 'empty'`, the default) or the witness (`'ebv'`); the row is
167
+ * the members the two shapes share, annotated when one shape is meant. */
168
+ assert<N extends DeclaredNames<To>, V extends ExprBase<unknown> = MemberExpr<DocOf<From, N> | DocOf<To, N>>>(
169
+ name: N,
170
+ predicate: (row: V) => BoolExpr | boolean,
171
+ options?: AssertOptions,
172
+ ): Migration<From, To>;
173
+ /** A query document over the rows, verbatim. */
174
+ assert<N extends DeclaredNames<To>>(name: N, query: Json, options?: AssertOptions): Migration<From, To>;
175
+ /** A backfill of stored derived columns (`derive`, §2.1). */
176
+ derive<N extends DeclaredNames<To>>(name: N, columns: readonly DeriveColumn[]): Migration<From, To>;
177
+ /** Any planner-emitted step, verbatim — the escape that keeps `rebuild` authorable. */
178
+ step(raw: MigrationStep): Migration<From, To>;
179
+ readonly document: MigrationDocument;
180
+ toJSON(): MigrationDocument;
181
+ }
182
+
183
+ export interface MigrationSpec<From, To> {
184
+ readonly id: string;
185
+ /** The model the store is at: a model document (the pen's or a JSON snapshot). */
186
+ readonly from: From;
187
+ /** The model the code carries. */
188
+ readonly to: To;
189
+ readonly note?: string;
190
+ }
191
+
192
+ /** A migration between two model documents; `from`/`to` are their shape hashes. */
193
+ export function defineMigration<From extends object, To extends object>(spec: MigrationSpec<From, To>): Migration<From, To>;
194
+
195
+ /** A planner's document, taken up so a typed `transform` replaces the
196
+ * draft it left; `from`/`to` type the transforms and are checked against
197
+ * the document's hashes (`JL0102` when they are not the planned models). */
198
+ export function fromPlanned<From = unknown, To = unknown>(
199
+ document: MigrationDocument | Json,
200
+ options?: { readonly from?: From; readonly to?: To },
201
+ ): Migration<From, To>;