okmodel 0.6.0 → 0.7.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.
- package/README.md +100 -1131
- package/dist/adapters/capabilities.d.ts +3 -0
- package/dist/adapters/failure.d.ts +13 -2
- package/dist/adapters/lazy-errors.d.ts +22 -0
- package/dist/adapters/pg/bunsql-extra.d.ts +54 -3
- package/dist/adapters/pg/bunsql.d.ts +14 -1
- package/dist/adapters/pg/cursor.d.ts +17 -0
- package/dist/adapters/pg/no-inflight-timeout.d.ts +11 -8
- package/dist/adapters/pg/nodepostgres-extra.d.ts +22 -1
- package/dist/adapters/pg/nodepostgres.d.ts +12 -0
- package/dist/adapters/pg/pglite-wire.d.ts +24 -0
- package/dist/adapters/pg/pglite.d.ts +10 -0
- package/dist/adapters/pg/postgres-extra.d.ts +27 -11
- package/dist/adapters/pg/reserved.d.ts +42 -0
- package/dist/adapters/pg/session.d.ts +0 -18
- package/dist/contracts/connection.d.ts +7 -6
- package/dist/dialects/pg/floor.d.ts +68 -0
- package/dist/dialects/pg/index.d.ts +6 -1
- package/dist/dialects/pg/index.js +49 -159
- package/dist/dialects/pg/keys.d.ts +11 -8
- package/dist/dialects/pg/model.d.ts +40 -0
- package/dist/dialects/pg/morph.d.ts +43 -0
- package/dist/dialects/pg/operator-fit.d.ts +2 -2
- package/dist/dialects/pg/operators.d.ts +14 -7
- package/dist/dialects/pg/ops/bucket.d.ts +65 -0
- package/dist/dialects/pg/ops/inc.d.ts +2 -2
- package/dist/dialects/pg/ops/matches.d.ts +9 -12
- package/dist/dialects/pg/ops/relevance.d.ts +13 -0
- package/dist/dialects/pg/ops/search-query.d.ts +22 -0
- package/dist/dialects/pg/ops/window.d.ts +103 -0
- package/dist/dialects/pg/preset.d.ts +1 -1
- package/dist/dialects/pg/relations.d.ts +100 -3
- package/dist/dialects/pg/schema.d.ts +31 -3
- package/dist/dialects/pg/view/index.js +1 -1
- package/dist/runtime/aggregate.d.ts +8 -2
- package/dist/runtime/bucket-group.d.ts +70 -0
- package/dist/runtime/conflict.d.ts +22 -4
- package/dist/runtime/include.d.ts +0 -8
- package/dist/runtime/inflight.d.ts +1 -1
- package/dist/runtime/page.d.ts +4 -1
- package/dist/runtime/pg/bun.js +12 -6
- package/dist/runtime/pg/pg.js +5 -5
- package/dist/runtime/pg/pglite.d.ts +1 -0
- package/dist/runtime/pg/pglite.js +9 -9
- package/dist/runtime/pg/postgresjs.js +5 -5
- package/dist/runtime/plan.d.ts +95 -5
- package/dist/runtime/read-stream.d.ts +13 -16
- package/dist/runtime/result-name.d.ts +17 -0
- package/dist/runtime/server-check.d.ts +3 -3
- package/dist/runtime/sort-bind.d.ts +21 -0
- package/dist/runtime/sort.d.ts +56 -0
- package/dist/runtime/sync.d.ts +70 -0
- package/dist/runtime/tenancy/index.js +7 -5
- package/dist/runtime/text-search.d.ts +20 -0
- package/dist/runtime/traits/index.d.ts +80 -0
- package/dist/runtime/traits/index.js +175 -11
- package/dist/runtime/tree.d.ts +38 -0
- package/dist/runtime/types.d.ts +218 -22
- package/dist/runtime/validate/index.js +2 -2
- package/dist/runtime/version.d.ts +39 -0
- package/dist/runtime/window.d.ts +21 -0
- package/dist/runtime/write.d.ts +54 -2
- package/dist/shared/{wkme6tep.js → 14vx95q4.js} +8 -16
- package/dist/shared/1est4ezg.js +313 -0
- package/dist/shared/{4az561fn.js → 1qa0qajz.js} +8 -23
- package/dist/shared/{2cg3wnxc.js → 1w508jbr.js} +593 -130
- package/dist/shared/2c13q96h.js +18 -0
- package/dist/shared/{b4v57v3x.js → 2d3xq4ps.js} +2 -2
- package/dist/shared/{1nw1f3vs.js → 2shdbn8q.js} +7 -7
- package/dist/shared/3v7t1yrv.js +208 -0
- package/dist/shared/{x3jc53kg.js → 5e3tf63j.js} +2 -2
- package/dist/shared/5fe3kbsh.js +10 -0
- package/dist/shared/5v3xf80k.js +37 -0
- package/dist/shared/{c58secgj.js → 63qtkrca.js} +38 -4
- package/dist/shared/{2z7wv5tj.js → 67txcrcw.js} +55 -34
- package/dist/shared/79dt02vc.js +12 -0
- package/dist/shared/{8x72s86k.js → 7k9grvf6.js} +10 -4
- package/dist/shared/7kms6fvj.js +20 -0
- package/dist/shared/7mnme5tn.js +8 -0
- package/dist/shared/7n7ddwt4.js +6 -0
- package/dist/shared/{5j36z8dn.js → 81ebdx9p.js} +39 -70
- package/dist/shared/{knmes2kh.js → 8skf0cam.js} +1 -1
- package/dist/shared/9a4ae4p8.js +31 -0
- package/dist/shared/9y3mmmh1.js +436 -0
- package/dist/shared/ab9gmbwy.js +213 -0
- package/dist/shared/{f0f1n281.js → ax7qv55k.js} +2 -2
- package/dist/shared/{g90m9b0g.js → aytqh5y2.js} +6 -5
- package/dist/shared/{vjpnzwjz.js → b5pftnn2.js} +1 -1
- package/dist/shared/{ag4c7516.js → b76b8d95.js} +2 -2
- package/dist/shared/{vmfkhszw.js → bg3rym3g.js} +33 -26
- package/dist/shared/{mb2ycs1p.js → bm22fvzr.js} +15 -15
- package/dist/shared/{q3j1tq7a.js → bz84tkzm.js} +148 -23
- package/dist/shared/{31vm914h.js → cm3w0ywp.js} +15 -16
- package/dist/shared/cn957f8d.js +179 -0
- package/dist/shared/{gwn6v667.js → cnkky55j.js} +25 -14
- package/dist/shared/{ys0xzyaj.js → dkxgzaqd.js} +224 -19
- package/dist/shared/dzj09cye.js +10 -0
- package/dist/shared/exn3sd90.js +359 -0
- package/dist/shared/g6evj1j3.js +66 -0
- package/dist/shared/ga9j92qj.js +25 -0
- package/dist/shared/{t3g0k88x.js → gs74dbj5.js} +16 -12
- package/dist/shared/gzaveazc.js +285 -0
- package/dist/shared/{2jd1sn0e.js → hyh73qk6.js} +1 -1
- package/dist/shared/{r1fdd0f6.js → je4axnm8.js} +5 -2
- package/dist/shared/{1f0xa3cb.js → jvd0mqag.js} +3 -3
- package/dist/shared/jznfax0y.js +155 -0
- package/dist/shared/{cgbamx3e.js → kb2sdhfb.js} +7 -4
- package/dist/shared/{wt5rzv1h.js → kr0jzbw2.js} +5 -5
- package/dist/shared/{p6bjzq9q.js → ktz42yez.js} +12 -4
- package/dist/shared/{p248q79y.js → m6p12kbr.js} +2 -2
- package/dist/shared/{r6nwkxnt.js → m7n9h2a5.js} +4 -4
- package/dist/shared/{672t5vym.js → mss6ctgv.js} +2 -2
- package/dist/shared/{929h19xp.js → mtaszv5a.js} +40 -10
- package/dist/shared/{b3awxn7h.js → n816peh1.js} +1 -1
- package/dist/shared/nbw1z4yd.js +18 -0
- package/dist/shared/{nx9hh281.js → p6qc5gcp.js} +12 -11
- package/dist/shared/{pjr6xrm5.js → pbp1ss85.js} +20 -17
- package/dist/shared/pt94kz7f.js +6 -0
- package/dist/shared/q5c6ngn3.js +13 -0
- package/dist/shared/{xq0mvhts.js → rs73fca9.js} +4 -4
- package/dist/shared/{r11n8grd.js → sfz1ksn6.js} +7 -4
- package/dist/shared/{wynzeggs.js → svncdeh5.js} +6 -6
- package/dist/shared/{j60w0dvr.js → tbrvgw6z.js} +57 -38
- package/dist/shared/te5as7z7.js +622 -0
- package/dist/shared/{ttmg09vd.js → tsvww22q.js} +1 -1
- package/dist/shared/{y2t3jktd.js → ttsqgp4p.js} +19 -12
- package/dist/shared/{x72jb7ad.js → v8g1vgv8.js} +1 -1
- package/dist/shared/{sbdme3vy.js → vb6qfyve.js} +60 -10
- package/dist/shared/{5d8t84hg.js → vczs8gd4.js} +14 -14
- package/dist/shared/{5yv4k6a6.js → vqrjpcqn.js} +144 -2
- package/dist/shared/{3fqwmr09.js → w72kgg4q.js} +4 -4
- package/dist/shared/{1z04fa85.js → w79hsckn.js} +12 -57
- package/dist/shared/{09p049xa.js → wa07eas9.js} +42 -14
- package/dist/shared/{32cnm7kn.js → x933k9a3.js} +74 -38
- package/dist/shared/{n076ydsc.js → xhfsfkgk.js} +62 -28
- package/dist/shared/xjk7hnn5.js +272 -0
- package/dist/shared/{hazqqecq.js → xnxsed62.js} +50 -21
- package/dist/shared/y6njgyda.js +249 -0
- package/dist/shared/{8etn7d8w.js → z7s6fpxv.js} +1 -1
- package/dist/shared/{n7mcc1gk.js → zchaghkf.js} +4 -3
- package/dist/shared/zm0ptry0.js +40 -0
- package/dist/shared/{nsva2a6b.js → znm0bpp5.js} +3 -0
- package/dist/shared/zp9fmend.js +145 -0
- package/dist/tooling/cli.js +11 -11
- package/dist/tooling/migrate/engine.d.ts +3 -2
- package/dist/tooling/migrate/index.js +7 -7
- package/dist/tooling/testing/index.js +1 -1
- package/package.json +4 -2
- package/dist/shared/3qnhc7w5.js +0 -38
- package/dist/shared/7m88x3e9.js +0 -45
- package/dist/shared/8dqhth8c.js +0 -12
- package/dist/shared/d5azex6s.js +0 -6
- package/dist/shared/j3rkk835.js +0 -99
- package/dist/shared/k68eedmy.js +0 -85
- package/dist/shared/venqrjna.js +0 -216
- package/dist/shared/wxr8cwns.js +0 -6
- package/dist/shared/zm0mafk4.js +0 -92
package/dist/runtime/plan.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { type QueryCode } from "../contracts/error.js";
|
|
|
8
8
|
import { type OperatorName } from "../dialects/pg/operators.js";
|
|
9
9
|
import { type ColumnModel, type QuerySchema, type RelationModel, type TableModel } from "../dialects/pg/model.js";
|
|
10
10
|
/** A read the caller asked for. */
|
|
11
|
-
export type ReadOp = "find" | "one" | "count" | "exists" | "aggregate";
|
|
11
|
+
export type ReadOp = "find" | "one" | "count" | "exists" | "aggregate" | "descendants" | "ancestors";
|
|
12
12
|
/** Routing constraint chosen before execute. */
|
|
13
13
|
export type RouteConstraint = "auto" | "primary" | "replica";
|
|
14
14
|
/**
|
|
@@ -25,7 +25,7 @@ export type CallScope = {
|
|
|
25
25
|
/** Writes one more `where` condition after the tenant and active-set predicates. */
|
|
26
26
|
export type Keyset = (sink: Sink, alias: string) => void;
|
|
27
27
|
/** Writes the whole statement of a read the planner does not know. */
|
|
28
|
-
export type ReadBuild = (schema: QuerySchema, table: Indexed, sink: Sink, outputs: Built | undefined, call: ReadCall) => void;
|
|
28
|
+
export type ReadBuild = (schema: QuerySchema, table: Indexed, sink: Sink, outputs: Built | undefined, call: ReadCall, hooks?: IncludeHooks) => void;
|
|
29
29
|
/** One read call. `all` is the `.all(reason)` escape for an unbounded read. */
|
|
30
30
|
export type ReadCall = {
|
|
31
31
|
readonly op: ReadOp;
|
|
@@ -35,6 +35,8 @@ export type ReadCall = {
|
|
|
35
35
|
readonly orderBy?: unknown;
|
|
36
36
|
readonly limit?: unknown;
|
|
37
37
|
readonly include?: unknown;
|
|
38
|
+
/** `find` and `count`. Rewritten to `matches` and `relevance` before SQL. */
|
|
39
|
+
readonly search?: unknown;
|
|
38
40
|
readonly all?: string;
|
|
39
41
|
/** The `after` cursor of a `page`. The condition joins the others with `and`. */
|
|
40
42
|
readonly after?: Keyset;
|
|
@@ -47,6 +49,15 @@ export type ReadCall = {
|
|
|
47
49
|
readonly timeout?: number;
|
|
48
50
|
/** `"primary"` or `"replica"`. Absent means the router classifies the statement. */
|
|
49
51
|
readonly route?: "primary" | "replica";
|
|
52
|
+
/**
|
|
53
|
+
* Endpoint a `.stream()` already chose.
|
|
54
|
+
*
|
|
55
|
+
* The first batch leaves `name` empty and the router fills it. Later batches
|
|
56
|
+
* pass the same object so they stay on that endpoint.
|
|
57
|
+
*/
|
|
58
|
+
readonly pin?: {
|
|
59
|
+
name?: string;
|
|
60
|
+
};
|
|
50
61
|
/** Set by `for()` or `unscoped()`. Absent on a schema with no tenancy. */
|
|
51
62
|
readonly scope?: CallScope;
|
|
52
63
|
/** Inspect lines from the tenancy object. Absent when the schema has no tenancy. */
|
|
@@ -95,6 +106,11 @@ export type ScalarOut = {
|
|
|
95
106
|
readonly at: number;
|
|
96
107
|
readonly decode: ((wire: string) => unknown) | undefined;
|
|
97
108
|
};
|
|
109
|
+
/** One target inside a morph include's JSON value. */
|
|
110
|
+
export type MorphOut = {
|
|
111
|
+
readonly type: string;
|
|
112
|
+
readonly fields: readonly ScalarOut[];
|
|
113
|
+
};
|
|
98
114
|
/** A nested include. `at` is a root column for `one` and the JSON column for `many`. */
|
|
99
115
|
export type IncludeOut = {
|
|
100
116
|
readonly name: string;
|
|
@@ -102,6 +118,15 @@ export type IncludeOut = {
|
|
|
102
118
|
readonly at: number;
|
|
103
119
|
readonly fields: readonly ScalarOut[];
|
|
104
120
|
readonly nested: readonly IncludeOut[];
|
|
121
|
+
/**
|
|
122
|
+
* Set when the include is a morph.
|
|
123
|
+
*
|
|
124
|
+
* The column at `at` is one JSON array, `[type, ...fields]`, or null.
|
|
125
|
+
*/
|
|
126
|
+
readonly morph?: {
|
|
127
|
+
readonly typeKey: string;
|
|
128
|
+
readonly targets: readonly MorphOut[];
|
|
129
|
+
};
|
|
105
130
|
};
|
|
106
131
|
/** Columns and includes in statement order. */
|
|
107
132
|
export type Outputs = {
|
|
@@ -114,6 +139,13 @@ export type IncludeHooks = {
|
|
|
114
139
|
read(schema: QuerySchema, table: Indexed, include: unknown, all: string | undefined): readonly ParsedInclude[];
|
|
115
140
|
select(include: ParsedInclude, alias: string, sink: Sink, outputs: Built | undefined, column: number): number;
|
|
116
141
|
join(schema: QuerySchema, include: ParsedInclude, sink: Sink, parentAlias: string, alias: string, depth: number): void;
|
|
142
|
+
/**
|
|
143
|
+
* Reports whether an include's `where` or `orderBy` needs the operator compiler.
|
|
144
|
+
*
|
|
145
|
+
* The root check does not walk includes. This does, and only after the
|
|
146
|
+
* include planner has loaded.
|
|
147
|
+
*/
|
|
148
|
+
needsOperator(schema: QuerySchema, call: ReadCall): boolean;
|
|
117
149
|
};
|
|
118
150
|
export type Built = {
|
|
119
151
|
fields: ScalarOut[];
|
|
@@ -157,8 +189,13 @@ export type Sink = {
|
|
|
157
189
|
* @returns Names in a stable order
|
|
158
190
|
*/
|
|
159
191
|
export declare function readOptionNames(op: ReadOp): readonly string[];
|
|
160
|
-
/**
|
|
161
|
-
|
|
192
|
+
/**
|
|
193
|
+
* 0.2 operator SQL. Absent until that module has been imported.
|
|
194
|
+
*
|
|
195
|
+
* `order` is set when the operator is an `orderBy` value. `relevance` writes
|
|
196
|
+
* its direction there; the same operator in `where` is refused by that module.
|
|
197
|
+
*/
|
|
198
|
+
type OperatorEmit = (column: ColumnModel, ref: string, name: OperatorName, value: unknown, sink: Sink, order?: true) => void;
|
|
162
199
|
/**
|
|
163
200
|
* Installs the 0.2 operator compiler.
|
|
164
201
|
*
|
|
@@ -177,6 +214,16 @@ export declare function installOperatorSql(emit: OperatorEmit): void;
|
|
|
177
214
|
* @returns `true` when {@link installOperatorSql} has not run and the read needs it
|
|
178
215
|
*/
|
|
179
216
|
export declare function readNeedsOperatorSql(schema: QuerySchema, call: ReadCall): boolean;
|
|
217
|
+
/**
|
|
218
|
+
* Reports whether `orderBy` holds a `relevance` value.
|
|
219
|
+
*
|
|
220
|
+
* Called before the operator compiler has loaded. The include planner uses it
|
|
221
|
+
* for a related table.
|
|
222
|
+
*
|
|
223
|
+
* @param orderBy - The caller's order
|
|
224
|
+
* @returns `true` when a value is `relevance`
|
|
225
|
+
*/
|
|
226
|
+
export declare function orderHasRelevance(orderBy: unknown): boolean;
|
|
180
227
|
/**
|
|
181
228
|
* Writes `<table> <alias> where <link to parent>` for a to-many relation.
|
|
182
229
|
*
|
|
@@ -184,6 +231,18 @@ export declare function readNeedsOperatorSql(schema: QuerySchema, call: ReadCall
|
|
|
184
231
|
* The caller adds the related table's own predicates after it.
|
|
185
232
|
*/
|
|
186
233
|
export declare function emitRelationFrom(schema: QuerySchema, relation: RelationModel, child: Indexed, sink: Sink, parent: string, alias: string, depth: number): void;
|
|
234
|
+
/**
|
|
235
|
+
* Reports whether a filter needs the operator compiler.
|
|
236
|
+
*
|
|
237
|
+
* Equality and text patterns do not. The include planner calls this for a
|
|
238
|
+
* related table.
|
|
239
|
+
*
|
|
240
|
+
* @param table - The table the filter reads
|
|
241
|
+
* @param value - A `where` value
|
|
242
|
+
* @param key - The field, when `value` is that field's operand
|
|
243
|
+
* @returns `true` when the operator compiler has to load
|
|
244
|
+
*/
|
|
245
|
+
export declare function needsOperatorSql(table: Indexed, value: unknown, key?: string): boolean;
|
|
187
246
|
/**
|
|
188
247
|
* Runs registered safety rules before planning.
|
|
189
248
|
*
|
|
@@ -259,6 +318,15 @@ export declare function emitPrimaryOrder(table: Indexed, sink: Sink, alias: stri
|
|
|
259
318
|
* @param column - The field the caller named
|
|
260
319
|
*/
|
|
261
320
|
export declare function refuseHidden(column: ColumnModel): void;
|
|
321
|
+
export declare function emitLimit(call: ReadCall, sink: Sink): void;
|
|
322
|
+
/** One target branch of a morph include. */
|
|
323
|
+
export type ParsedMorphTarget = {
|
|
324
|
+
readonly type: string;
|
|
325
|
+
readonly table: string;
|
|
326
|
+
readonly sql: string;
|
|
327
|
+
readonly keySql: string;
|
|
328
|
+
readonly columns: readonly ColumnModel[];
|
|
329
|
+
};
|
|
262
330
|
export type ParsedInclude = {
|
|
263
331
|
readonly name: string;
|
|
264
332
|
readonly relation: RelationModel;
|
|
@@ -270,13 +338,35 @@ export type ParsedInclude = {
|
|
|
270
338
|
/** Index in the projected list that is null when the related row is missing. */
|
|
271
339
|
readonly anchor: number;
|
|
272
340
|
readonly nested: readonly ParsedInclude[];
|
|
341
|
+
/**
|
|
342
|
+
* Set when the include is a morph.
|
|
343
|
+
*
|
|
344
|
+
* Absent on every other include, so a normal include does not carry it.
|
|
345
|
+
*/
|
|
346
|
+
readonly morphTo?: {
|
|
347
|
+
readonly typeKey: string;
|
|
348
|
+
readonly typeSql: string;
|
|
349
|
+
readonly idSql: string;
|
|
350
|
+
readonly targets: readonly ParsedMorphTarget[];
|
|
351
|
+
};
|
|
273
352
|
};
|
|
274
353
|
export declare function selectedColumns(table: Indexed, select: unknown): readonly ColumnModel[];
|
|
275
354
|
export declare function parseOrder(field: string, value: unknown): {
|
|
276
355
|
readonly dir: "asc" | "desc";
|
|
277
356
|
readonly nulls: "first" | "last";
|
|
278
357
|
};
|
|
279
|
-
|
|
358
|
+
/**
|
|
359
|
+
* Refuses a key that `accepted` does not list.
|
|
360
|
+
*
|
|
361
|
+
* A read passes `search`. `one` and `exists` then say to use `find` or
|
|
362
|
+
* `count`, instead of the generic option list.
|
|
363
|
+
*
|
|
364
|
+
* @param value - Caller options
|
|
365
|
+
* @param accepted - Names this call allows
|
|
366
|
+
* @param where - The call, named in the error
|
|
367
|
+
* @param search - When set, a rejected `search` key uses the read message
|
|
368
|
+
*/
|
|
369
|
+
export declare function rejectKeys(value: Readonly<Record<string, unknown>>, accepted: readonly string[], where: string, search?: true): void;
|
|
280
370
|
export declare function readLimit(value: unknown): number;
|
|
281
371
|
/**
|
|
282
372
|
* Lets an object through only when the column's codec takes it (OKM1121).
|
|
@@ -1,26 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Keyset batches for `.stream()` (spec §10).
|
|
3
3
|
*
|
|
4
4
|
* Loaded the first time `.stream()` is iterated. A find that is only awaited
|
|
5
|
-
* does not load it.
|
|
5
|
+
* does not load it. Each batch is one finished `page` query: fetch, yield,
|
|
6
|
+
* then fetch the next. A `break` does not hold a connection. A server cursor
|
|
7
|
+
* is not used, so the driver `stream` flag is not read.
|
|
6
8
|
*/
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
9
|
-
import { type
|
|
9
|
+
import { OkmError } from "../contracts/error.js";
|
|
10
|
+
import { type Mods, type Session } from "./client.js";
|
|
11
|
+
import { type ArchiveView, type ReadCall } from "./plan.js";
|
|
10
12
|
/**
|
|
11
|
-
* Yields decoded rows
|
|
13
|
+
* Yields decoded rows, one keyset batch at a time.
|
|
12
14
|
*
|
|
13
15
|
* @param session - Connected pool and HTTP statuses
|
|
14
|
-
* @param call - The
|
|
15
|
-
* @param
|
|
16
|
+
* @param call - The find being streamed
|
|
17
|
+
* @param mods - `.all` reason and presets
|
|
18
|
+
* @param view - Archive visibility
|
|
19
|
+
* @param batchOptions - `{ batch }`, or omitted for {@link DEFAULT_BATCH}
|
|
16
20
|
* @param log - Attaches the session logger and returns the error
|
|
17
21
|
* @returns One row at a time
|
|
18
22
|
*/
|
|
19
|
-
export declare function streamRows(session:
|
|
20
|
-
readonly connected: Promise<void>;
|
|
21
|
-
readonly pool: DriverPool;
|
|
22
|
-
readonly http: ErrorStatuses | undefined;
|
|
23
|
-
}, call: ReadCall, prepare: () => Promise<{
|
|
24
|
-
readonly plan: Plan;
|
|
25
|
-
readonly params: readonly (string | null)[];
|
|
26
|
-
}>, log: (error: OkmError) => OkmError): AsyncIterable<unknown>;
|
|
23
|
+
export declare function streamRows(session: Session, call: ReadCall, mods: Mods, view: ArchiveView | undefined, batchOptions: object | undefined, log: (error: OkmError) => OkmError): AsyncIterable<unknown>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Result keys a caller chooses.
|
|
3
|
+
*
|
|
4
|
+
* Loaded with the bucket chunk and the window chunk (D258). The startup
|
|
5
|
+
* graph does not import it.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Refuses a result key that would shadow or replace a prototype property.
|
|
9
|
+
*
|
|
10
|
+
* Assigning `__proto__` replaces that object's prototype when the value is an
|
|
11
|
+
* object. The other names shadow methods on the row. `then` makes the row a
|
|
12
|
+
* thenable. The check runs before any SQL.
|
|
13
|
+
*
|
|
14
|
+
* @param name - The result key
|
|
15
|
+
* @param where - The call, such as `rowNumber as` or `bucket as`
|
|
16
|
+
*/
|
|
17
|
+
export declare function refusePrototypeKey(name: string, where: string): void;
|
|
@@ -17,11 +17,11 @@ export declare const versionQuery = "select current_setting('server_version_num'
|
|
|
17
17
|
/**
|
|
18
18
|
* Accepts the `server_version_num` row, or throws OKM1801, OKM1520, OKM1802, or OKM1803.
|
|
19
19
|
*
|
|
20
|
-
* A declared
|
|
21
|
-
*
|
|
20
|
+
* A declared floor is the minimum. With no floor, the minimum is 15.
|
|
21
|
+
* A major below 15 is refused when the schema is built.
|
|
22
22
|
*
|
|
23
23
|
* @param pool - Connection that ran the version query
|
|
24
|
-
* @param schema - Schema whose
|
|
24
|
+
* @param schema - Schema whose floor is the declared minimum
|
|
25
25
|
* @param rows - `server_version_num`, `version()`, and the `okm_meta` hash
|
|
26
26
|
* @param http - Status overrides from `connect`
|
|
27
27
|
* @param requireMeta - When true, a missing hash is OKM1520
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unique index `sortable()` adds.
|
|
3
|
+
*
|
|
4
|
+
* Tenancy has already widened uniques (D168), so this index names the tenant
|
|
5
|
+
* keys itself. The move and insert SQL load later, on the first call.
|
|
6
|
+
*/
|
|
7
|
+
import type { AnyTable } from "../dialects/pg/table.js";
|
|
8
|
+
/**
|
|
9
|
+
* Adds the position unique index on tables this trait applies to.
|
|
10
|
+
*
|
|
11
|
+
* A path table is refused: the tenant key is not a column, so the index could
|
|
12
|
+
* not keep two tenants from sharing a position.
|
|
13
|
+
*
|
|
14
|
+
* @param self - The trait object `schema()` stored
|
|
15
|
+
* @param tables - Tables after the tenancy rewrite
|
|
16
|
+
* @param casing - Schema casing
|
|
17
|
+
* @param schemaTraits - Traits from `schema()`, when any were passed
|
|
18
|
+
* @param group - Field that splits the order, when `sortable` was given one
|
|
19
|
+
* @returns Tables with the index on the ones this trait applies to
|
|
20
|
+
*/
|
|
21
|
+
export declare function rewriteSortable(self: object, tables: readonly AnyTable[], casing: "snake" | undefined, schemaTraits: readonly object[] | undefined, group: string | undefined): readonly AnyTable[];
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Position assignment and `move`.
|
|
3
|
+
*
|
|
4
|
+
* Loaded on the first insert or move of a `sortable()` table. Positions are
|
|
5
|
+
* dense positive integers, unique inside the group (and the tenant). The
|
|
6
|
+
* advisory lock is its own statement. The next statement reads positions.
|
|
7
|
+
* Under READ COMMITTED a statement's snapshot is taken when it starts, which
|
|
8
|
+
* is before a lock in that same statement is granted, so a commit that landed
|
|
9
|
+
* while this transaction waited would be invisible.
|
|
10
|
+
*/
|
|
11
|
+
import type { Statement } from "../contracts/driver.js";
|
|
12
|
+
import type { ColumnModel, QuerySchema } from "../dialects/pg/model.js";
|
|
13
|
+
import { type ArchiveView, type CallScope, type Indexed } from "./plan.js";
|
|
14
|
+
import { type RunHost } from "./tx.js";
|
|
15
|
+
type Host = RunHost & {
|
|
16
|
+
readonly schema: QuerySchema;
|
|
17
|
+
readonly scope?: CallScope;
|
|
18
|
+
readonly connected?: Promise<void>;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Inserts rows at the end of their group.
|
|
22
|
+
*
|
|
23
|
+
* The lock statement runs first. The insert then takes `max(position) + n`
|
|
24
|
+
* from a snapshot taken after that lock is held. A writer that bypasses these
|
|
25
|
+
* statements can still race; the unique index rejects a duplicate.
|
|
26
|
+
*
|
|
27
|
+
* @param table - Target table
|
|
28
|
+
* @param columns - Columns the insert already decided to write
|
|
29
|
+
* @param rows - Stamped rows, in call order
|
|
30
|
+
* @param group - Group field, when the trait has one
|
|
31
|
+
* @param tenantFields - Tenant fields stored on this table
|
|
32
|
+
* @returns The lock, then the insert without `returning`
|
|
33
|
+
*/
|
|
34
|
+
export declare function insertAtEnd(table: Indexed, columns: readonly ColumnModel[], rows: readonly Record<string, unknown>[], group: string | undefined, tenantFields: readonly string[] | undefined): {
|
|
35
|
+
readonly lock: Statement;
|
|
36
|
+
readonly text: string;
|
|
37
|
+
readonly params: (string | null)[];
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Moves one row before or after another in the same group.
|
|
41
|
+
*
|
|
42
|
+
* The result is `{ position }` after the move. A missing id is `not_found`.
|
|
43
|
+
* An anchor in another group is OKM1120 and writes nothing. The same id on
|
|
44
|
+
* both sides leaves the row where it is.
|
|
45
|
+
*
|
|
46
|
+
* @param host - Pool and schema
|
|
47
|
+
* @param tableName - Table the trait is on
|
|
48
|
+
* @param id - Primary key of the row to move, without the tenant key
|
|
49
|
+
* @param place - `{ before }` or `{ after }`, the anchor's primary key
|
|
50
|
+
* @param view - Archive visibility, when the handle narrowed it
|
|
51
|
+
* @returns The row's position after the move
|
|
52
|
+
*/
|
|
53
|
+
export declare function move(host: Host, tableName: string, id: unknown, place: unknown, view: ArchiveView | undefined): Promise<{
|
|
54
|
+
readonly position: number;
|
|
55
|
+
}>;
|
|
56
|
+
export {};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `sync` (spec §11, §13 tool 10).
|
|
3
|
+
*
|
|
4
|
+
* One transaction sets a to-many relation to an exact set of ids. The first
|
|
5
|
+
* statement locks the parent row. The write is a second statement, so a sync
|
|
6
|
+
* that waited for that lock sees the links the previous sync committed. A join table
|
|
7
|
+
* gains and loses link rows. A one-to-many sets or clears a nullable foreign
|
|
8
|
+
* key and leaves the related row in place. A link that would have to delete
|
|
9
|
+
* that row is refused. Duplicate ids count once. An id that is not in the
|
|
10
|
+
* related table, or a parent id that is not in this table, writes nothing and
|
|
11
|
+
* throws `not_found`. The parent row is locked, so two syncs of the same id
|
|
12
|
+
* run one after the other.
|
|
13
|
+
*
|
|
14
|
+
* Loaded on the first call.
|
|
15
|
+
*/
|
|
16
|
+
import type { Statement } from "../contracts/driver.js";
|
|
17
|
+
import type { PresetUse } from "../dialects/pg/model.js";
|
|
18
|
+
import { type Mods as ReadMods, type Session } from "./client.js";
|
|
19
|
+
import { type ArchiveView } from "./plan.js";
|
|
20
|
+
type Mods = {
|
|
21
|
+
readonly expect?: number;
|
|
22
|
+
readonly archive?: ArchiveView | undefined;
|
|
23
|
+
readonly uses?: PresetUse | undefined;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Runs one `sync`.
|
|
27
|
+
*
|
|
28
|
+
* @param session - Client session
|
|
29
|
+
* @param table - Table that owns the relation
|
|
30
|
+
* @param id - Primary key of that row
|
|
31
|
+
* @param relation - To-many relation name
|
|
32
|
+
* @param ids - Related primary keys the relation should hold
|
|
33
|
+
* @param options - `expect`, `signal`, and `timeout`
|
|
34
|
+
* @param mods - Chained `expect`, archive visibility, and presets
|
|
35
|
+
* @returns The ids whose links were added or removed
|
|
36
|
+
*/
|
|
37
|
+
export declare function execute(session: Session, table: string, id: unknown, relation: unknown, ids: unknown, options: object | undefined, mods: Mods): Promise<{
|
|
38
|
+
readonly added: readonly unknown[];
|
|
39
|
+
readonly removed: readonly unknown[];
|
|
40
|
+
}>;
|
|
41
|
+
/**
|
|
42
|
+
* The statement `sync` would run.
|
|
43
|
+
*
|
|
44
|
+
* @param session - Client session
|
|
45
|
+
* @param table - Table that owns the relation
|
|
46
|
+
* @param id - Primary key of that row
|
|
47
|
+
* @param relation - To-many relation name
|
|
48
|
+
* @param ids - Related primary keys the relation should hold
|
|
49
|
+
* @param options - `expect`, `signal`, and `timeout`
|
|
50
|
+
* @param mods - Chained `expect`, archive visibility, and presets
|
|
51
|
+
* @returns One statement
|
|
52
|
+
*/
|
|
53
|
+
export declare function explain(session: Session, table: string, id: unknown, relation: unknown, ids: unknown, options: object | undefined, mods: Mods): Promise<{
|
|
54
|
+
readonly statements: readonly Statement[];
|
|
55
|
+
}>;
|
|
56
|
+
/**
|
|
57
|
+
* The handle for one `sync`.
|
|
58
|
+
*
|
|
59
|
+
* Await runs the change. `sql` shows the lock and the write. `expect` lives on
|
|
60
|
+
* the outer handle, which calls this again with `mods.expect` set.
|
|
61
|
+
*
|
|
62
|
+
* @param session - Client session
|
|
63
|
+
* @param table - Table that owns the relation
|
|
64
|
+
* @param input - `id`, `relation`, `ids`, and `options`
|
|
65
|
+
* @param mods - Presets, plus `expect` when the outer handle chained it
|
|
66
|
+
* @param view - Archive view. The same value a read on this handle uses
|
|
67
|
+
* @returns A handle. The value is `{ added, removed }`
|
|
68
|
+
*/
|
|
69
|
+
export declare function build(session: Session, table: string, input: object, mods: ReadMods, view: ArchiveView | undefined): Promise<unknown> & Record<string, unknown>;
|
|
70
|
+
export {};
|
|
@@ -8,10 +8,10 @@ import {
|
|
|
8
8
|
} from "../../shared/bdk4sty6.js";
|
|
9
9
|
import {
|
|
10
10
|
isRelationCall
|
|
11
|
-
} from "../../shared/
|
|
11
|
+
} from "../../shared/exn3sd90.js";
|
|
12
12
|
import {
|
|
13
13
|
uuid2
|
|
14
|
-
} from "../../shared/
|
|
14
|
+
} from "../../shared/hyh73qk6.js";
|
|
15
15
|
import {
|
|
16
16
|
index2,
|
|
17
17
|
snakeCase
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
} from "../../shared/94ez8kzh.js";
|
|
29
29
|
import {
|
|
30
30
|
quote
|
|
31
|
-
} from "../../shared/
|
|
31
|
+
} from "../../shared/67txcrcw.js";
|
|
32
32
|
import {
|
|
33
33
|
assertIdentifier2
|
|
34
34
|
} from "../../shared/nfzc5z0w.js";
|
|
@@ -233,7 +233,8 @@ function rewriteTenant(keys, keyColumns, item, tables, kind, tenants, exemptions
|
|
|
233
233
|
...options,
|
|
234
234
|
...primaryKey !== undefined ? { primaryKey } : {},
|
|
235
235
|
...Object.keys(unique).length > 0 ? { unique } : {},
|
|
236
|
-
...indexes !== undefined ? { indexes } : {}
|
|
236
|
+
...indexes !== undefined ? { indexes } : {},
|
|
237
|
+
tenantKeys: keys
|
|
237
238
|
}
|
|
238
239
|
};
|
|
239
240
|
return declared !== undefined && declared.length > 0 ? markPathEndpoint(rewritten) : rewritten;
|
|
@@ -1667,7 +1668,8 @@ function rewriteTenant2(key, column, item, tables, kind, tenants, exemptions, ex
|
|
|
1667
1668
|
...options,
|
|
1668
1669
|
...primaryKey !== undefined ? { primaryKey } : {},
|
|
1669
1670
|
...Object.keys(unique).length > 0 ? { unique } : {},
|
|
1670
|
-
...indexes !== undefined ? { indexes } : {}
|
|
1671
|
+
...indexes !== undefined ? { indexes } : {},
|
|
1672
|
+
tenantKeys: [key]
|
|
1671
1673
|
}
|
|
1672
1674
|
};
|
|
1673
1675
|
return noted !== undefined && noted.length > 0 ? markPathEndpoint(rewritten) : rewritten;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `search` on `find` and `count`.
|
|
3
|
+
*
|
|
4
|
+
* Loaded on the first call that passes `search`. It rewrites the call into
|
|
5
|
+
* `matches` and, when `find` has no `orderBy`, `relevance` plus the primary
|
|
6
|
+
* key. The SQL compiler is the one those helpers already use.
|
|
7
|
+
*/
|
|
8
|
+
import type { QuerySchema } from "../dialects/pg/model.js";
|
|
9
|
+
import { type ReadCall } from "./plan.js";
|
|
10
|
+
/**
|
|
11
|
+
* Rewrites `search` into `matches` and `relevance`.
|
|
12
|
+
*
|
|
13
|
+
* `count` keeps the caller's order, which it does not emit. An explicit
|
|
14
|
+
* `orderBy` on `find` replaces the automatic ranking.
|
|
15
|
+
*
|
|
16
|
+
* @param schema - Connected schema
|
|
17
|
+
* @param call - The read, with `search` set
|
|
18
|
+
* @returns The same read, without `search`
|
|
19
|
+
*/
|
|
20
|
+
export declare function applyTextSearch(schema: QuerySchema, call: ReadCall): ReadCall;
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* does not import it does not load these columns.
|
|
6
6
|
*/
|
|
7
7
|
import { type PresetMap } from "../../dialects/pg/preset.js";
|
|
8
|
+
import type { QuerySchema, SchemaHookCtx } from "../../dialects/pg/model.js";
|
|
8
9
|
import type { AnyTable, RowFrom } from "../../dialects/pg/table.js";
|
|
9
10
|
import { attachArchive } from "../archive-handle.js";
|
|
10
11
|
import { type Trait, type TraitContext, type TraitModel } from "../../dialects/pg/trait.js";
|
|
@@ -131,3 +132,82 @@ export declare function archivable(options?: ArchivableOptions): {
|
|
|
131
132
|
rewrite(tables: readonly AnyTable[], casing: "snake" | undefined, schemaTraits: readonly object[] | undefined): readonly AnyTable[];
|
|
132
133
|
hook: typeof attachArchive;
|
|
133
134
|
};
|
|
135
|
+
/**
|
|
136
|
+
* Adds `version` and checks it on every update.
|
|
137
|
+
*
|
|
138
|
+
* The column starts at 1. An update passes the version it read and the write
|
|
139
|
+
* bumps it. A stale version is category `conflict` and changes nothing.
|
|
140
|
+
* Input cannot set `version`.
|
|
141
|
+
*
|
|
142
|
+
* @returns The versioned trait
|
|
143
|
+
*/
|
|
144
|
+
export declare function versioned(): {
|
|
145
|
+
readonly name: string;
|
|
146
|
+
readonly fields: {
|
|
147
|
+
readonly version: import("../../dialects/pg/column.js").ColumnBuilder<number, import("../../dialects/pg/column.js").FlagTrue<import("../../dialects/pg/column.js").FlagTrue<import("../../dialects/pg/column.js").PlainFlags, "hasDefault">, "guarded">>;
|
|
148
|
+
};
|
|
149
|
+
readonly touch?: readonly "version"[];
|
|
150
|
+
readonly sealed?: readonly "version"[];
|
|
151
|
+
apply(model: TraitModel, ctx: TraitContext): void;
|
|
152
|
+
contribute(peers: unknown, built: unknown): readonly unknown[];
|
|
153
|
+
};
|
|
154
|
+
/**
|
|
155
|
+
* Adds `position` and `move`.
|
|
156
|
+
*
|
|
157
|
+
* New rows go at the end of the group. `move` places a row before or after
|
|
158
|
+
* another in that group. `find` and `page` order by `position` when the
|
|
159
|
+
* caller does not pass `orderBy`. Input cannot set `position`.
|
|
160
|
+
*
|
|
161
|
+
* @param groupBy - Column that splits the order. Omit it for one list
|
|
162
|
+
* @returns The sortable trait
|
|
163
|
+
*/
|
|
164
|
+
export declare function sortable(groupBy?: string): {
|
|
165
|
+
name: string;
|
|
166
|
+
fields: {
|
|
167
|
+
readonly position: import("../../dialects/pg/column.js").ColumnBuilder<number, import("../../dialects/pg/column.js").FlagTrue<import("../../dialects/pg/column.js").PlainFlags, "guarded">>;
|
|
168
|
+
};
|
|
169
|
+
touch?: readonly "position"[];
|
|
170
|
+
sealed?: readonly "position"[];
|
|
171
|
+
contribute(peers: unknown, built: unknown): readonly unknown[];
|
|
172
|
+
group?: string;
|
|
173
|
+
"~sort": true;
|
|
174
|
+
apply(model: TraitModel, ctx: TraitContext): void;
|
|
175
|
+
/**
|
|
176
|
+
* Adds the unique position index after tenancy has widened uniques.
|
|
177
|
+
*
|
|
178
|
+
* @param tables - Tables after the tenancy rewrite
|
|
179
|
+
* @param casing - Schema casing
|
|
180
|
+
* @param schemaTraits - Traits from `schema()`, when any were passed
|
|
181
|
+
* @returns The rewritten tables
|
|
182
|
+
*/
|
|
183
|
+
rewrite(tables: readonly AnyTable[], casing: "snake" | undefined, schemaTraits: readonly object[] | undefined): readonly AnyTable[];
|
|
184
|
+
hook: typeof attachSort;
|
|
185
|
+
};
|
|
186
|
+
/**
|
|
187
|
+
* Adds `move` and the default position order on a sortable table.
|
|
188
|
+
*
|
|
189
|
+
* @param target - The table handle being built
|
|
190
|
+
* @param ctx - Table name and the session
|
|
191
|
+
*/
|
|
192
|
+
declare function attachSort(target: Record<string, unknown>, ctx: SchemaHookCtx): void;
|
|
193
|
+
declare module "../types.js" {
|
|
194
|
+
interface TableExtras<S extends QuerySchema, K extends keyof S["~byName"] & string> {
|
|
195
|
+
/**
|
|
196
|
+
* Moves one row before or after another in the same group.
|
|
197
|
+
*
|
|
198
|
+
* The result is the row's position after the move. A missing id is
|
|
199
|
+
* `not_found`. An anchor in another group is OKM1120.
|
|
200
|
+
*
|
|
201
|
+
* @param id - Primary key of the row to move, without the tenant key
|
|
202
|
+
* @param place - `{ before }` or `{ after }`, the anchor's primary key
|
|
203
|
+
* @returns The position after the move
|
|
204
|
+
*/
|
|
205
|
+
move(id: unknown, place: {
|
|
206
|
+
readonly before: unknown;
|
|
207
|
+
} | {
|
|
208
|
+
readonly after: unknown;
|
|
209
|
+
}): Promise<{
|
|
210
|
+
readonly position: number;
|
|
211
|
+
}>;
|
|
212
|
+
}
|
|
213
|
+
}
|