okmodel 0.1.1 → 0.2.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.
- package/README.md +32 -16
- package/dist/adapters/capabilities.d.ts +34 -0
- package/dist/adapters/pg/bunsql-extra.d.ts +17 -0
- package/dist/adapters/pg/bunsql.d.ts +60 -0
- package/dist/adapters/pg/call.d.ts +2 -12
- package/dist/adapters/pg/nodepostgres-extra.d.ts +18 -0
- package/dist/adapters/pg/nodepostgres.d.ts +57 -0
- package/dist/adapters/pg/postgres-extra.d.ts +50 -1
- package/dist/adapters/pg/postgresjs.d.ts +0 -4
- package/dist/adapters/pg/session.d.ts +94 -0
- package/dist/adapters/pg/watch.d.ts +18 -0
- package/dist/contracts/catalog/object.d.ts +1 -0
- package/dist/contracts/catalog/types.d.ts +15 -8
- package/dist/contracts/connection.d.ts +13 -0
- package/dist/contracts/driver.d.ts +18 -5
- package/dist/contracts/error.d.ts +17 -1
- package/dist/contracts/generator.d.ts +63 -0
- package/dist/contracts/index.d.ts +2 -2
- package/dist/contracts/index.js +1 -1
- package/dist/contracts/internal.js +11 -9
- package/dist/contracts/location.d.ts +24 -0
- package/dist/contracts/rows.d.ts +15 -0
- package/dist/dialects/pg/archive-bind.d.ts +22 -0
- package/dist/dialects/pg/column.d.ts +126 -9
- package/dist/dialects/pg/compile.d.ts +1 -0
- package/dist/dialects/pg/custom.d.ts +6 -0
- package/dist/dialects/pg/filter-parse.d.ts +19 -0
- package/dist/dialects/pg/filters.d.ts +19 -0
- package/dist/dialects/pg/index.d.ts +11 -2
- package/dist/dialects/pg/index.js +159 -1063
- package/dist/dialects/pg/keys.d.ts +19 -3
- package/dist/dialects/pg/model.d.ts +223 -2
- package/dist/dialects/pg/operator-fit.d.ts +86 -0
- package/dist/dialects/pg/operators.d.ts +39 -1
- package/dist/dialects/pg/ops/arr-append.d.ts +9 -0
- package/dist/dialects/pg/ops/arr-ns.d.ts +7 -0
- package/dist/dialects/pg/ops/arr-remove.d.ts +9 -0
- package/dist/dialects/pg/ops/containedBy.d.ts +9 -0
- package/dist/dialects/pg/ops/contains.d.ts +8 -4
- package/dist/dialects/pg/ops/hasAnyKey.d.ts +8 -0
- package/dist/dialects/pg/ops/hasKey.d.ts +8 -0
- package/dist/dialects/pg/ops/json-ns.d.ts +6 -0
- package/dist/dialects/pg/ops/json-set.d.ts +12 -0
- package/dist/dialects/pg/ops/matches.d.ts +16 -0
- package/dist/dialects/pg/ops/overlaps.d.ts +9 -0
- package/dist/dialects/pg/ops/path.d.ts +13 -0
- package/dist/dialects/pg/preset.d.ts +76 -0
- package/dist/dialects/pg/relations.d.ts +59 -2
- package/dist/dialects/pg/schema.d.ts +109 -5
- package/dist/dialects/pg/table.d.ts +130 -11
- package/dist/dialects/pg/temporal.d.ts +9 -7
- package/dist/dialects/pg/tenancy.d.ts +94 -0
- package/dist/dialects/pg/through.d.ts +21 -0
- package/dist/dialects/pg/trait.d.ts +141 -0
- package/dist/dialects/pg/where.d.ts +37 -0
- package/dist/runtime/aggregate.d.ts +25 -0
- package/dist/runtime/archive-handle.d.ts +18 -0
- package/dist/runtime/archive-rules.d.ts +12 -0
- package/dist/runtime/archive.d.ts +73 -0
- package/dist/runtime/batch.d.ts +20 -0
- package/dist/runtime/client.d.ts +114 -5
- package/dist/runtime/conflict.d.ts +2 -1
- package/dist/runtime/exposure.d.ts +27 -0
- package/dist/runtime/hookm.d.ts +39 -0
- package/dist/runtime/ids/index.d.ts +11 -0
- package/dist/runtime/ids/index.js +193 -0
- package/dist/runtime/ids/okid-extended.d.ts +19 -0
- package/dist/runtime/ids/okid-generator.d.ts +21 -0
- package/dist/runtime/ids/okid-shared.d.ts +89 -0
- package/dist/runtime/ids/okid.d.ts +24 -0
- package/dist/runtime/ids/uuid.d.ts +21 -0
- package/dist/runtime/lock.d.ts +22 -0
- package/dist/runtime/operator-sql.d.ts +8 -0
- package/dist/runtime/page.d.ts +25 -0
- package/dist/runtime/pg/bun.d.ts +30 -0
- package/dist/runtime/pg/bun.js +52 -0
- package/dist/runtime/pg/pg.d.ts +29 -0
- package/dist/runtime/pg/pg.js +52 -0
- package/dist/runtime/pg/pglite.js +16 -17
- package/dist/runtime/pg/postgresjs.js +14 -24
- package/dist/runtime/plan.d.ts +146 -7
- package/dist/runtime/preset-stack.d.ts +17 -0
- package/dist/runtime/presets.d.ts +48 -0
- package/dist/runtime/read-stream.d.ts +26 -0
- package/dist/runtime/safety/index.d.ts +159 -0
- package/dist/runtime/safety/index.js +294 -0
- package/dist/runtime/safety-hook.d.ts +42 -0
- package/dist/runtime/server-check.d.ts +34 -0
- package/dist/runtime/tenancy/index.d.ts +37 -0
- package/dist/runtime/tenancy/index.js +365 -0
- package/dist/runtime/trait-read.d.ts +30 -0
- package/dist/runtime/traits/index.d.ts +128 -0
- package/dist/runtime/traits/index.js +509 -0
- package/dist/runtime/transaction.d.ts +19 -0
- package/dist/runtime/tx.d.ts +22 -7
- package/dist/runtime/types.d.ts +376 -27
- package/dist/runtime/validate/bind.d.ts +11 -0
- package/dist/runtime/validate/closed.d.ts +16 -0
- package/dist/runtime/validate/engine.d.ts +41 -0
- package/dist/runtime/validate/hook.d.ts +17 -0
- package/dist/runtime/validate/index.d.ts +21 -0
- package/dist/runtime/validate/index.js +175 -0
- package/dist/runtime/validate/load.d.ts +13 -0
- package/dist/runtime/validate/places.d.ts +41 -0
- package/dist/runtime/validate/rules.d.ts +108 -0
- package/dist/runtime/validate/surface.d.ts +102 -0
- package/dist/runtime/write.d.ts +30 -5
- package/dist/shared/{fgqgsb5z.js → 0qkxbm1f.js} +2 -2
- package/dist/shared/0v1g424p.js +26 -0
- package/dist/shared/10tjenmd.js +210 -0
- package/dist/shared/{xqbhg6cn.js → 1dp5knt7.js} +95 -10
- package/dist/shared/38crxbgn.js +229 -0
- package/dist/shared/3a5ne750.js +158 -0
- package/dist/shared/4b9da9d7.js +138 -0
- package/dist/shared/4e4c6vq2.js +62 -0
- package/dist/shared/{x5x59srr.js → 4jzzghr6.js} +416 -83
- package/dist/shared/{ycwz42az.js → 52szzakm.js} +6 -26
- package/dist/shared/{05w44d8g.js → 5z4q2zda.js} +567 -18
- package/dist/shared/672t5vym.js +12 -0
- package/dist/shared/7m88x3e9.js +45 -0
- package/dist/shared/7mht49yd.js +1091 -0
- package/dist/shared/{mtkwv8wx.js → 7p2wbz7f.js} +1 -1
- package/dist/shared/83eaefwr.js +10 -0
- package/dist/shared/96ps4g1z.js +32 -0
- package/dist/shared/97g2jnrw.js +76 -0
- package/dist/shared/{xy79j5hq.js → 9k6vetvf.js} +25 -36
- package/dist/shared/{w8samvk1.js → a1gdp7j9.js} +1 -1
- package/dist/shared/a5sxz52y.js +13 -0
- package/dist/shared/{dynq16vb.js → b066g80h.js} +8 -6
- package/dist/shared/cstgkzdx.js +154 -0
- package/dist/shared/{523ft3e8.js → d04j53v8.js} +6 -5
- package/dist/shared/{y9m15dfv.js → d2whjz4k.js} +15 -9
- package/dist/shared/dd4f8mnx.js +307 -0
- package/dist/shared/e6wg00wd.js +164 -0
- package/dist/shared/e7a268fy.js +195 -0
- package/dist/shared/{kprcwaha.js → eaxwrgby.js} +4 -3
- package/dist/shared/{dkn3y60a.js → ecdzej21.js} +76 -112
- package/dist/shared/{hadrfb9h.js → edwqqryd.js} +17 -14
- package/dist/shared/{m3ypagh5.js → eqmtn1bj.js} +57 -5
- package/dist/shared/g1b5zzj9.js +75 -0
- package/dist/shared/g9f0zqce.js +376 -0
- package/dist/shared/ge03bfca.js +64 -0
- package/dist/shared/{yd1kzwn2.js → jns2wx4t.js} +55 -12
- package/dist/shared/k3ted12y.js +33 -0
- package/dist/shared/k7dwkhvq.js +31 -0
- package/dist/shared/{hd293j9g.js → kyxb62mc.js} +14 -2
- package/dist/shared/m9tv7xn7.js +404 -0
- package/dist/shared/mrq77sgw.js +55 -0
- package/dist/shared/mxmcdsh5.js +450 -0
- package/dist/shared/n442h54c.js +14 -0
- package/dist/shared/n47rd821.js +442 -0
- package/dist/shared/n4jqhpqz.js +27 -0
- package/dist/shared/{mkjmqjv4.js → nfzc5z0w.js} +2 -104
- package/dist/shared/nsva2a6b.js +42 -0
- package/dist/shared/ps43134h.js +69 -0
- package/dist/shared/{8b04d28c.js → py3nh7jy.js} +2 -2
- package/dist/shared/qa5dsc7z.js +86 -0
- package/dist/shared/{g5fhqmwe.js → qxa0yb9j.js} +6 -4
- package/dist/shared/r6nwkxnt.js +86 -0
- package/dist/shared/{jjb7yht9.js → rtnaqre0.js} +3 -3
- package/dist/shared/rwmrejjz.js +26 -0
- package/dist/shared/{zhc5vmgf.js → s6gqfn5j.js} +2 -2
- package/dist/shared/sacqha1y.js +70 -0
- package/dist/shared/{qk3hxfja.js → sfh4pk75.js} +5 -5
- package/dist/shared/{j5cn2963.js → t4tbsy9h.js} +13 -64
- package/dist/shared/{ngk8gj61.js → tbszx8mz.js} +15 -1
- package/dist/shared/v18jva5b.js +90 -0
- package/dist/shared/x9v1qgeb.js +201 -0
- package/dist/shared/xatfg0gn.js +193 -0
- package/dist/shared/xkz8g6by.js +225 -0
- package/dist/shared/{rgs0st28.js → xrfnq5k8.js} +237 -434
- package/dist/shared/ytg3xf9p.js +149 -0
- package/dist/shared/yw5c610b.js +48 -0
- package/dist/shared/zd93g3rq.js +31 -0
- package/dist/shared/zt8y0wzb.js +132 -0
- package/dist/shared/{p0cbr3g2.js → zwmqxb0g.js} +1 -1
- package/dist/tooling/cli.js +14 -10
- package/dist/tooling/migrate/commands.d.ts +10 -0
- package/dist/tooling/migrate/engine.d.ts +36 -0
- package/package.json +41 -4
- package/dist/shared/gk7cs7sp.js +0 -566
|
@@ -1,36 +1,23 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DriverError2
|
|
3
|
-
} from "../../shared/
|
|
3
|
+
} from "../../shared/kyxb62mc.js";
|
|
4
4
|
import {
|
|
5
5
|
open2
|
|
6
|
-
} from "../../shared/
|
|
7
|
-
import {
|
|
8
|
-
createClient
|
|
9
|
-
} from "../../shared/rgs0st28.js";
|
|
6
|
+
} from "../../shared/ecdzej21.js";
|
|
10
7
|
import {
|
|
11
8
|
POSTGRESJS_CAPABILITIES,
|
|
12
9
|
readCapability2,
|
|
13
10
|
hasCapability2
|
|
14
|
-
} from "../../shared/
|
|
11
|
+
} from "../../shared/9k6vetvf.js";
|
|
12
|
+
import {
|
|
13
|
+
createClient
|
|
14
|
+
} from "../../shared/mxmcdsh5.js";
|
|
15
15
|
|
|
16
16
|
// src/runtime/pg/postgresjs.ts
|
|
17
17
|
function connect(target, options) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
http: options.errors?.http,
|
|
22
|
-
includeValues: options.errors?.includeValues,
|
|
23
|
-
logger: options.logger,
|
|
24
|
-
signal: options.signal,
|
|
25
|
-
timeout: options.timeout,
|
|
26
|
-
catalog: options.catalog,
|
|
27
|
-
catalogDir: options.catalogDir,
|
|
28
|
-
requireMeta: options.requireMeta
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
const url = target;
|
|
32
|
-
const pool = open2({
|
|
33
|
-
url,
|
|
18
|
+
const owned = !isPool(target);
|
|
19
|
+
const pool = isPool(target) ? target : open2({
|
|
20
|
+
url: target,
|
|
34
21
|
...options.max !== undefined ? { max: options.max } : {},
|
|
35
22
|
...options.timeouts !== undefined ? { timeouts: options.timeouts } : {},
|
|
36
23
|
...options.prepared !== undefined ? { prepared: options.prepared } : {},
|
|
@@ -38,15 +25,18 @@ function connect(target, options) {
|
|
|
38
25
|
...options.ssl !== undefined ? { ssl: options.ssl } : {}
|
|
39
26
|
});
|
|
40
27
|
return createClient(options.schema, pool, {
|
|
41
|
-
ownsPool:
|
|
28
|
+
ownsPool: owned,
|
|
42
29
|
http: options.errors?.http,
|
|
43
30
|
includeValues: options.errors?.includeValues,
|
|
44
31
|
logger: options.logger,
|
|
45
32
|
signal: options.signal,
|
|
46
33
|
timeout: options.timeout,
|
|
34
|
+
timeouts: options.timeouts,
|
|
35
|
+
hookm: options.hookm,
|
|
47
36
|
catalog: options.catalog,
|
|
48
37
|
catalogDir: options.catalogDir,
|
|
49
|
-
requireMeta: options.requireMeta
|
|
38
|
+
requireMeta: options.requireMeta,
|
|
39
|
+
generators: options.generators
|
|
50
40
|
});
|
|
51
41
|
}
|
|
52
42
|
function isPool(target) {
|
package/dist/runtime/plan.d.ts
CHANGED
|
@@ -5,11 +5,26 @@
|
|
|
5
5
|
* Identifiers come from the catalog model. Values are parameters.
|
|
6
6
|
*/
|
|
7
7
|
import { type QueryCode } from "../contracts/error.js";
|
|
8
|
+
import { type OperatorName } from "../dialects/pg/operators.js";
|
|
8
9
|
import { type ColumnModel, type QuerySchema, type RelationModel, type TableModel } from "../dialects/pg/model.js";
|
|
9
10
|
/** A read the caller asked for. */
|
|
10
|
-
export type ReadOp = "find" | "one" | "count" | "exists";
|
|
11
|
+
export type ReadOp = "find" | "one" | "count" | "exists" | "aggregate";
|
|
11
12
|
/** Routing constraint chosen before execute. */
|
|
12
13
|
export type RouteConstraint = "auto" | "primary" | "replica";
|
|
14
|
+
/**
|
|
15
|
+
* Tenant scope for one call.
|
|
16
|
+
*
|
|
17
|
+
* The value is a parameter. The cache key records `tenant` or `unscoped`, not the value.
|
|
18
|
+
*/
|
|
19
|
+
export type CallScope = {
|
|
20
|
+
readonly value: string;
|
|
21
|
+
} | {
|
|
22
|
+
readonly unscoped: string;
|
|
23
|
+
};
|
|
24
|
+
/** Writes one more `where` condition after the tenant and active-set predicates. */
|
|
25
|
+
export type Keyset = (sink: Sink, alias: string) => void;
|
|
26
|
+
/** Writes the whole statement of a read the planner does not know. */
|
|
27
|
+
export type ReadBuild = (schema: QuerySchema, table: Indexed, sink: Sink, outputs: Built | undefined, call: ReadCall) => void;
|
|
13
28
|
/** One read call. `all` is the `.all(reason)` escape for an unbounded read. */
|
|
14
29
|
export type ReadCall = {
|
|
15
30
|
readonly op: ReadOp;
|
|
@@ -20,7 +35,57 @@ export type ReadCall = {
|
|
|
20
35
|
readonly limit?: unknown;
|
|
21
36
|
readonly include?: unknown;
|
|
22
37
|
readonly all?: string;
|
|
38
|
+
/** The `after` cursor of a `page`. The condition joins the others with `and`. */
|
|
39
|
+
readonly after?: Keyset;
|
|
40
|
+
/** Set by `aggregate`. It writes the statement and the safety predicates stay in `emitWhere`. */
|
|
41
|
+
readonly build?: ReadBuild;
|
|
42
|
+
/** Writes the end of the statement, after `limit`. A row lock sets it. */
|
|
43
|
+
readonly tail?: (sink: Sink) => void;
|
|
44
|
+
/** The caller's `signal` and `timeout`. They never enter the plan or its key. */
|
|
45
|
+
readonly signal?: AbortSignal;
|
|
46
|
+
readonly timeout?: number;
|
|
47
|
+
/** Set by `for()` or `unscoped()`. Absent on a schema with no tenancy. */
|
|
48
|
+
readonly scope?: CallScope;
|
|
49
|
+
/** Inspect lines from the tenancy object. Absent when the schema has no tenancy. */
|
|
50
|
+
readonly tenancyRules?: readonly AppliedRule[];
|
|
51
|
+
/** `withArchived` or `onlyArchived`. Absent means the active set. */
|
|
52
|
+
readonly archive?: ArchiveView;
|
|
53
|
+
/** Inspect lines for the archive set and for presets. Absent when neither applies. */
|
|
54
|
+
readonly ruleLines?: readonly AppliedRule[];
|
|
23
55
|
};
|
|
56
|
+
/** How an archivable read or write chooses rows. Absent means the active set. */
|
|
57
|
+
export type ArchiveView = "with" | "only";
|
|
58
|
+
/**
|
|
59
|
+
* Runs `fn` with a tenant scope and an archive visibility visible to {@link emitWhere}.
|
|
60
|
+
*
|
|
61
|
+
* Restores both, including when `fn` throws. Sync callers finish the statement
|
|
62
|
+
* before the first await.
|
|
63
|
+
*
|
|
64
|
+
* @param scope - Tenant value or an unscoped reason
|
|
65
|
+
* @param view - `with` or `only`. `undefined` is the active set
|
|
66
|
+
* @param fn - Statement builder
|
|
67
|
+
* @returns Whatever `fn` returns
|
|
68
|
+
*/
|
|
69
|
+
export declare function withRowFilters<T>(scope: CallScope | undefined, view: ArchiveView | undefined, fn: () => T): T;
|
|
70
|
+
type ArchiveInspect = (model: TableModel | undefined, view: ArchiveView | undefined) => readonly AppliedRule[] | undefined;
|
|
71
|
+
/**
|
|
72
|
+
* Installs the phrase recorder `archivable()` owns.
|
|
73
|
+
*
|
|
74
|
+
* A featureless schema never calls this, so the phrases stay out of startup.
|
|
75
|
+
*
|
|
76
|
+
* @param fn - Builds the lines for one table
|
|
77
|
+
*/
|
|
78
|
+
export declare function installArchiveInspect(fn: ArchiveInspect): void;
|
|
79
|
+
/**
|
|
80
|
+
* Inspect lines for one archivable table.
|
|
81
|
+
*
|
|
82
|
+
* Absent when the trait was not installed, or the table is not archivable.
|
|
83
|
+
*
|
|
84
|
+
* @param model - Table model
|
|
85
|
+
* @param view - `with` or `only`. `undefined` is the active set
|
|
86
|
+
* @returns The lines, or `undefined`
|
|
87
|
+
*/
|
|
88
|
+
export declare function archiveRules(model: TableModel | undefined, view: ArchiveView | undefined): readonly AppliedRule[] | undefined;
|
|
24
89
|
/** Where a decoded value sits. */
|
|
25
90
|
export type ScalarOut = {
|
|
26
91
|
readonly key: string;
|
|
@@ -68,6 +133,8 @@ export type AppliedRule = {
|
|
|
68
133
|
readonly rule: string;
|
|
69
134
|
readonly contribution: string;
|
|
70
135
|
readonly provenance: string;
|
|
136
|
+
/** `file.ts:line` where the rule or the table was defined. */
|
|
137
|
+
readonly source?: string;
|
|
71
138
|
};
|
|
72
139
|
export type Indexed = {
|
|
73
140
|
readonly model: TableModel;
|
|
@@ -81,13 +148,49 @@ export type Sink = {
|
|
|
81
148
|
mark(token: string): void;
|
|
82
149
|
};
|
|
83
150
|
/**
|
|
84
|
-
*
|
|
151
|
+
* Option names `find`, `one`, `count`, and `exists` accept.
|
|
152
|
+
*
|
|
153
|
+
* @param op - The read
|
|
154
|
+
* @returns Names in a stable order
|
|
155
|
+
*/
|
|
156
|
+
export declare function readOptionNames(op: ReadOp): readonly string[];
|
|
157
|
+
/** 0.2 operator SQL. Absent until that module has been imported. */
|
|
158
|
+
type OperatorEmit = (column: ColumnModel, ref: string, name: OperatorName, value: unknown, sink: Sink) => void;
|
|
159
|
+
/**
|
|
160
|
+
* Installs the 0.2 operator compiler.
|
|
85
161
|
*
|
|
86
|
-
*
|
|
162
|
+
* Called when `operator-sql` loads. A second install replaces the first.
|
|
87
163
|
*
|
|
88
|
-
* @param
|
|
164
|
+
* @param emit - Compiler for containment, keys, paths, and matches
|
|
89
165
|
*/
|
|
90
|
-
export declare function
|
|
166
|
+
export declare function installOperatorSql(emit: OperatorEmit): void;
|
|
167
|
+
/**
|
|
168
|
+
* Reports whether planning this read has to load the 0.2 operator module first.
|
|
169
|
+
*
|
|
170
|
+
* Equality, comparisons, and text patterns plan without it.
|
|
171
|
+
*
|
|
172
|
+
* @param schema - Connected schema
|
|
173
|
+
* @param call - The read
|
|
174
|
+
* @returns `true` when {@link installOperatorSql} has not run and the read needs it
|
|
175
|
+
*/
|
|
176
|
+
export declare function readNeedsOperatorSql(schema: QuerySchema, call: ReadCall): boolean;
|
|
177
|
+
/**
|
|
178
|
+
* Writes `<table> <alias> where <link to parent>` for a to-many relation.
|
|
179
|
+
*
|
|
180
|
+
* A `manyThrough` relation reads the join table and joins the related table.
|
|
181
|
+
* The caller adds the related table's own predicates after it.
|
|
182
|
+
*/
|
|
183
|
+
export declare function emitRelationFrom(schema: QuerySchema, relation: RelationModel, child: Indexed, sink: Sink, parent: string, alias: string, depth: number): void;
|
|
184
|
+
/**
|
|
185
|
+
* Runs registered safety rules before planning.
|
|
186
|
+
*
|
|
187
|
+
* Nothing runs until `okmodel/safety` has registered a rule. The startup
|
|
188
|
+
* graph pays for the check, not for the registry.
|
|
189
|
+
*
|
|
190
|
+
* @param schema - Connected schema
|
|
191
|
+
* @param call - The read
|
|
192
|
+
*/
|
|
193
|
+
export declare function verifyRead(schema: QuerySchema, call: ReadCall): void;
|
|
91
194
|
/**
|
|
92
195
|
* Binds a call: shape key and parameters, no SQL.
|
|
93
196
|
*
|
|
@@ -133,12 +236,15 @@ export declare function logicalIntent(call: ReadCall): {
|
|
|
133
236
|
/**
|
|
134
237
|
* Rules for inspection, including the caller filter when one was passed.
|
|
135
238
|
*
|
|
239
|
+
* Catalog rules carry `source` when the table recorded one.
|
|
240
|
+
*
|
|
136
241
|
* @param call - The read
|
|
242
|
+
* @param source - `file.ts:line` of the table, when `table()` recorded it
|
|
137
243
|
* @returns Provenance-tagged rules
|
|
138
244
|
*/
|
|
139
|
-
export declare function appliedRules(call: ReadCall): readonly AppliedRule[];
|
|
245
|
+
export declare function appliedRules(call: ReadCall, source?: string): readonly AppliedRule[];
|
|
140
246
|
export declare function emitJoin(sink: Sink, parent: string, child: string, relation: RelationModel): void;
|
|
141
|
-
export declare function emitWhere(schema: QuerySchema, table: Indexed, where: unknown, sink: Sink, alias: string, depth: number, appended?: boolean): void;
|
|
247
|
+
export declare function emitWhere(schema: QuerySchema, table: Indexed, where: unknown, sink: Sink, alias: string, depth: number, appended?: boolean, extra?: Keyset): void;
|
|
142
248
|
export declare function emitOrder(table: Indexed, orderBy: unknown, sink: Sink, alias: string): void;
|
|
143
249
|
export declare function emitPrimaryOrder(table: Indexed, sink: Sink, alias: string): void;
|
|
144
250
|
export type ParsedInclude = {
|
|
@@ -154,8 +260,24 @@ export type ParsedInclude = {
|
|
|
154
260
|
readonly nested: readonly ParsedInclude[];
|
|
155
261
|
};
|
|
156
262
|
export declare function selectedColumns(table: Indexed, select: unknown): readonly ColumnModel[];
|
|
263
|
+
export declare function parseOrder(field: string, value: unknown): {
|
|
264
|
+
readonly dir: "asc" | "desc";
|
|
265
|
+
readonly nulls: "first" | "last";
|
|
266
|
+
};
|
|
157
267
|
export declare function rejectKeys(value: Readonly<Record<string, unknown>>, accepted: readonly string[], where: string): void;
|
|
158
268
|
export declare function readLimit(value: unknown): number;
|
|
269
|
+
/**
|
|
270
|
+
* Lets an object through only when the column's codec takes it (OKM1121).
|
|
271
|
+
*
|
|
272
|
+
* A column whose codec takes only scalars has no `accepts`, so every object is
|
|
273
|
+
* refused for it. A bare object in a `where` is refused for every column; the
|
|
274
|
+
* operators and `eq` are the explicit forms (D125).
|
|
275
|
+
*
|
|
276
|
+
* @param column - Target column
|
|
277
|
+
* @param value - The object
|
|
278
|
+
* @param bare - Whether the object sits in a `where` without `eq`
|
|
279
|
+
*/
|
|
280
|
+
export declare function takeObject(column: ColumnModel, value: object, bare?: boolean): void;
|
|
159
281
|
export declare function projectExpr(sql: string, dataType: string): string;
|
|
160
282
|
export declare function jsonExpr(sql: string, dataType: string): string;
|
|
161
283
|
export declare function decodeRow(outputs: Outputs, row: readonly (string | null)[]): Record<string, unknown>;
|
|
@@ -164,4 +286,21 @@ export declare function indexes(schema: QuerySchema): ReadonlyMap<string, Indexe
|
|
|
164
286
|
export declare function quote(name: string): string;
|
|
165
287
|
export declare function list(names: readonly string[]): string;
|
|
166
288
|
export declare function isRecord(value: unknown): value is Record<string, unknown>;
|
|
289
|
+
/**
|
|
290
|
+
* Records the fix text for a code thrown from a chunk that loads on first use.
|
|
291
|
+
*
|
|
292
|
+
* A read does not carry the write, conflict, or include sentences. The module
|
|
293
|
+
* that throws the code registers the same sentence before it can throw.
|
|
294
|
+
*
|
|
295
|
+
* @param code - Spec code
|
|
296
|
+
* @param summary - Fix sentence `fail` attaches
|
|
297
|
+
*/
|
|
298
|
+
export declare function registerFailFix(code: QueryCode, summary: string): void;
|
|
299
|
+
/**
|
|
300
|
+
* Throws an {@link OkmError} for a query the planner rejects.
|
|
301
|
+
*
|
|
302
|
+
* @param code - Spec code
|
|
303
|
+
* @param message - What failed
|
|
304
|
+
*/
|
|
167
305
|
export declare function fail(code: QueryCode, message: string): never;
|
|
306
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Puts preset filters after a caller's filter.
|
|
3
|
+
*
|
|
4
|
+
* Kept apart from the presets module so a write or an archive that uses no
|
|
5
|
+
* preset does not load the code that runs them.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Joins a caller's `where` and the filters presets added, with AND.
|
|
9
|
+
*
|
|
10
|
+
* The planner reads the result like any `where`, so the tenant predicate and
|
|
11
|
+
* the active set are written around it and cannot be dropped by a preset.
|
|
12
|
+
*
|
|
13
|
+
* @param where - The caller's `where`, when there is one
|
|
14
|
+
* @param presets - Filters the presets added, in call order. Absent or empty adds nothing
|
|
15
|
+
* @returns The same `where`, or one that also holds the preset filters
|
|
16
|
+
*/
|
|
17
|
+
export declare function stack(where: unknown, presets: readonly unknown[] | undefined): unknown;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runs the presets chained on a table handle.
|
|
3
|
+
*
|
|
4
|
+
* Loaded on the first call that uses a preset. A schema with no preset, and a
|
|
5
|
+
* call that chains none, never load this file.
|
|
6
|
+
*
|
|
7
|
+
* A preset gets a builder with one method, `where`, which adds a filter. The
|
|
8
|
+
* filters join the caller's with AND (`stack`), and the planner writes the
|
|
9
|
+
* tenant predicate and the active set around the result, so no preset can
|
|
10
|
+
* remove either one (D125, D126).
|
|
11
|
+
*/
|
|
12
|
+
import type { PresetUse, QuerySchema } from "../dialects/pg/model.js";
|
|
13
|
+
import type { AppliedRule, ReadCall } from "./plan.js";
|
|
14
|
+
/** The filters a chain of presets added, and the inspect lines that name them. */
|
|
15
|
+
export type Resolved = {
|
|
16
|
+
readonly wheres: readonly unknown[];
|
|
17
|
+
readonly rules: readonly AppliedRule[];
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Fails on a preset name that is a client method or reserved.
|
|
21
|
+
*
|
|
22
|
+
* Runs when the client connects, for every table that has presets, so a bad
|
|
23
|
+
* name fails before the first query and not at the first preset call.
|
|
24
|
+
*
|
|
25
|
+
* @param schema - Connected schema
|
|
26
|
+
*/
|
|
27
|
+
export declare function checkSchema(schema: QuerySchema): void;
|
|
28
|
+
/**
|
|
29
|
+
* Runs the chained presets and collects what each one added.
|
|
30
|
+
*
|
|
31
|
+
* @param schema - Connected schema
|
|
32
|
+
* @param table - Table the chain is on
|
|
33
|
+
* @param uses - The last preset call in the chain
|
|
34
|
+
* @returns The filters, in call order, and one `preset` rule per call
|
|
35
|
+
*/
|
|
36
|
+
export declare function resolve(schema: QuerySchema, table: string, uses: PresetUse): Resolved;
|
|
37
|
+
/**
|
|
38
|
+
* Applies the chained presets to a read.
|
|
39
|
+
*
|
|
40
|
+
* The caller's `where` stays first. The call keeps its tenant and active-set
|
|
41
|
+
* rules, and gains one `preset` rule per call for `inspect()`.
|
|
42
|
+
*
|
|
43
|
+
* @param schema - Connected schema
|
|
44
|
+
* @param call - The read as the caller wrote it
|
|
45
|
+
* @param uses - Presets chained on the handle
|
|
46
|
+
* @returns The same read with the presets' filters stacked after its `where`
|
|
47
|
+
*/
|
|
48
|
+
export declare function refine(schema: QuerySchema, call: ReadCall, uses: PresetUse): ReadCall;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-side read cursor.
|
|
3
|
+
*
|
|
4
|
+
* Loaded the first time `.stream()` is iterated. A find that is only awaited
|
|
5
|
+
* does not load it.
|
|
6
|
+
*/
|
|
7
|
+
import type { DriverPool } from "../contracts/driver.js";
|
|
8
|
+
import { OkmError, type ErrorStatuses } from "../contracts/error.js";
|
|
9
|
+
import { type Plan, type ReadCall } from "./plan.js";
|
|
10
|
+
/**
|
|
11
|
+
* Yields decoded rows from the driver's stream.
|
|
12
|
+
*
|
|
13
|
+
* @param session - Connected pool and HTTP statuses
|
|
14
|
+
* @param call - The read being streamed
|
|
15
|
+
* @param prepare - Compiles the statement on first use
|
|
16
|
+
* @param log - Attaches the session logger and returns the error
|
|
17
|
+
* @returns One row at a time
|
|
18
|
+
*/
|
|
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>;
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Final safety verification (`okmodel/safety`).
|
|
3
|
+
*
|
|
4
|
+
* A registry and a property harness. Later steps register the rules they own.
|
|
5
|
+
* This module does not hard-code those rules, and the application startup
|
|
6
|
+
* graph does not import it.
|
|
7
|
+
*/
|
|
8
|
+
import { OkmError } from "../../contracts/error.js";
|
|
9
|
+
import { type SafetyContribution, type SafetyHatch } from "../safety-hook.js";
|
|
10
|
+
export type { SafetyContribution, SafetyHatch };
|
|
11
|
+
/** What one registered rule sees. */
|
|
12
|
+
export type SafetyInput = {
|
|
13
|
+
/** Contributions the pipeline recorded, including the caller. */
|
|
14
|
+
readonly contributions: readonly SafetyContribution[];
|
|
15
|
+
/**
|
|
16
|
+
* Contributions recorded before a later step ran.
|
|
17
|
+
*
|
|
18
|
+
* One that is missing from {@link SafetyInput.contributions} is `dropped`.
|
|
19
|
+
*/
|
|
20
|
+
readonly recorded?: readonly SafetyContribution[];
|
|
21
|
+
/** Escape hatches with a reason. A blank reason is itself a violation. */
|
|
22
|
+
readonly hatches?: readonly SafetyHatch[];
|
|
23
|
+
};
|
|
24
|
+
/** One broken rule. */
|
|
25
|
+
export type SafetyViolation = {
|
|
26
|
+
readonly rule: string;
|
|
27
|
+
readonly contribution: string;
|
|
28
|
+
/** `file.ts:line` of the rule, when it was recorded. */
|
|
29
|
+
readonly source?: string;
|
|
30
|
+
readonly detail: string;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* A rule a later step registers.
|
|
34
|
+
*
|
|
35
|
+
* `check` returns violations. It does not throw. The registry sorts them.
|
|
36
|
+
*/
|
|
37
|
+
export type SafetyRule = {
|
|
38
|
+
readonly name: string;
|
|
39
|
+
/** Who added the rule. */
|
|
40
|
+
readonly contribution: string;
|
|
41
|
+
/**
|
|
42
|
+
* `file.ts:line`.
|
|
43
|
+
*
|
|
44
|
+
* {@link registerRule} records the caller when this is omitted.
|
|
45
|
+
*/
|
|
46
|
+
readonly source?: string;
|
|
47
|
+
/**
|
|
48
|
+
* @param input - Contributions and hatches for one query
|
|
49
|
+
* @returns Violations. Empty when the rule holds
|
|
50
|
+
*/
|
|
51
|
+
check(input: SafetyInput): readonly SafetyViolation[];
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* OKM1190. `violations` is every broken rule, in stable order.
|
|
55
|
+
*
|
|
56
|
+
* `rule` and `contribution` repeat the first of that list.
|
|
57
|
+
*/
|
|
58
|
+
export declare class SafetyError extends OkmError {
|
|
59
|
+
/** Rule name of the first violation. */
|
|
60
|
+
readonly rule: string;
|
|
61
|
+
/** Contribution of the first violation. */
|
|
62
|
+
readonly contribution: string;
|
|
63
|
+
/** Every violation, sorted. */
|
|
64
|
+
readonly violations: readonly SafetyViolation[];
|
|
65
|
+
/**
|
|
66
|
+
* @param violations - Broken rules, already in stable order
|
|
67
|
+
*/
|
|
68
|
+
constructor(violations: readonly SafetyViolation[]);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Registers one rule and installs the read-path hook.
|
|
72
|
+
*
|
|
73
|
+
* The returned function removes that rule. The hook is cleared when no rules
|
|
74
|
+
* remain, so a query does not call into this module.
|
|
75
|
+
*
|
|
76
|
+
* @param rule - The check. A missing `source` is the caller's file and line
|
|
77
|
+
* @returns Removes this registration
|
|
78
|
+
*/
|
|
79
|
+
/**
|
|
80
|
+
* Registers the field-exposure rule.
|
|
81
|
+
*
|
|
82
|
+
* A contribution that shows a hidden field, reveals a sensitive value, or
|
|
83
|
+
* sets a guarded field without `{ allow }` is OKM1190. The package does not
|
|
84
|
+
* register it on import (`sideEffects` is false). Call this once.
|
|
85
|
+
*
|
|
86
|
+
* The contribution text is the whole subject the rule can see. P21's input
|
|
87
|
+
* has no schema and no query, so the planner phrases the verdict
|
|
88
|
+
* (`excluded`, `redacted`, `absent`, `allowed`) and a leak is the words
|
|
89
|
+
* `shown`, `revealed`, or `set`.
|
|
90
|
+
*
|
|
91
|
+
* @returns Removes this registration
|
|
92
|
+
*/
|
|
93
|
+
export declare function registerFieldExposure(): () => void;
|
|
94
|
+
/**
|
|
95
|
+
* Registers the timestamps rule.
|
|
96
|
+
*
|
|
97
|
+
* A contribution that sets `createdAt` or `updatedAt` from input is OKM1190.
|
|
98
|
+
* `{ allow }` does not permit it. The planner records `set by timestamps`
|
|
99
|
+
* or `kept`. The package does not register the rule on import.
|
|
100
|
+
*
|
|
101
|
+
* @returns Removes this registration
|
|
102
|
+
*/
|
|
103
|
+
/**
|
|
104
|
+
* Registers the column-tenancy rule.
|
|
105
|
+
*
|
|
106
|
+
* A contribution that sets the tenant key from input is OKM1190. `{ allow }`
|
|
107
|
+
* does not permit it. The planner throws the same code even when this rule
|
|
108
|
+
* is not registered. The package does not register the rule on import.
|
|
109
|
+
*
|
|
110
|
+
* @returns Removes this registration
|
|
111
|
+
*/
|
|
112
|
+
export declare function registerTenancy(): () => void;
|
|
113
|
+
export declare function registerTimestamps(): () => void;
|
|
114
|
+
/**
|
|
115
|
+
* Registers the archive rule.
|
|
116
|
+
*
|
|
117
|
+
* A contribution that drops the active set, or skips a named cascade, is
|
|
118
|
+
* OKM1190. The planner records `active set`, `with archived`, `only archived`,
|
|
119
|
+
* and `cascade <table>`. The package does not register the rule on import.
|
|
120
|
+
*
|
|
121
|
+
* @returns Removes this registration
|
|
122
|
+
*/
|
|
123
|
+
export declare function registerArchive(): () => void;
|
|
124
|
+
/**
|
|
125
|
+
* Registers the presets rule.
|
|
126
|
+
*
|
|
127
|
+
* A preset only adds predicates. A contribution that says a preset `removed`
|
|
128
|
+
* or `replaced` one (the caller's, the tenant's, or the active set) is
|
|
129
|
+
* OKM1190. The builder has no such method, so the planner never records the
|
|
130
|
+
* words; the rule keeps the contract checkable if a later builder grows one.
|
|
131
|
+
* The package does not register the rule on import.
|
|
132
|
+
*
|
|
133
|
+
* @returns Removes this registration
|
|
134
|
+
*/
|
|
135
|
+
export declare function registerPresets(): () => void;
|
|
136
|
+
export declare function registerRule(rule: SafetyRule): () => void;
|
|
137
|
+
/**
|
|
138
|
+
* Runs the registered rules.
|
|
139
|
+
*
|
|
140
|
+
* @param input - Contributions, an optional earlier recording, and hatches
|
|
141
|
+
* @returns Violations in stable order. Empty when every rule holds
|
|
142
|
+
*/
|
|
143
|
+
export declare function review(input: SafetyInput): readonly SafetyViolation[];
|
|
144
|
+
/**
|
|
145
|
+
* Throws OKM1190 when {@link review} finds a violation.
|
|
146
|
+
*
|
|
147
|
+
* @param input - Contributions, an optional earlier recording, and hatches
|
|
148
|
+
*/
|
|
149
|
+
export declare function verify(input: SafetyInput): void;
|
|
150
|
+
/**
|
|
151
|
+
* Checks each case, then again with the registered rules reversed.
|
|
152
|
+
*
|
|
153
|
+
* The two verdicts must match. A later step copies this, registers its rule,
|
|
154
|
+
* and passes its cases. Rule order is not part of the verdict.
|
|
155
|
+
*
|
|
156
|
+
* @param cases - Subjects to check
|
|
157
|
+
* @returns Violations for each case, in case order
|
|
158
|
+
*/
|
|
159
|
+
export declare function safetyProperty(cases: readonly SafetyInput[]): readonly (readonly SafetyViolation[])[];
|