okmodel 0.5.0 → 0.6.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 +36 -18
- package/dist/adapters/pg/no-inflight-timeout.d.ts +17 -0
- package/dist/adapters/pg/postgres-extra.d.ts +22 -0
- package/dist/contracts/catalog/document.d.ts +19 -5
- package/dist/contracts/catalog/object.d.ts +2 -1
- package/dist/contracts/catalog/policy.d.ts +48 -0
- package/dist/contracts/catalog/types.d.ts +25 -1
- package/dist/contracts/catalog/view.d.ts +2 -0
- package/dist/contracts/internal.js +1 -1
- package/dist/contracts/location.d.ts +10 -0
- package/dist/dialects/pg/column.d.ts +13 -2
- package/dist/dialects/pg/ddl.d.ts +37 -1
- package/dist/dialects/pg/emit.d.ts +19 -1
- package/dist/dialects/pg/errors.d.ts +32 -1
- package/dist/dialects/pg/ext/citext.js +1 -1
- package/dist/dialects/pg/ext/index.js +1 -1
- package/dist/dialects/pg/ext/pg-trgm.js +1 -1
- package/dist/dialects/pg/filter-parse.d.ts +10 -3
- package/dist/dialects/pg/fn/index.js +10 -2
- package/dist/dialects/pg/index.d.ts +2 -1
- package/dist/dialects/pg/index.js +29 -17
- package/dist/dialects/pg/introspect.d.ts +7 -0
- package/dist/dialects/pg/model.d.ts +7 -2
- package/dist/dialects/pg/ops/or.d.ts +1 -1
- package/dist/dialects/pg/owner.d.ts +42 -0
- package/dist/dialects/pg/path-endpoint.d.ts +20 -0
- package/dist/dialects/pg/role/check.d.ts +3 -0
- package/dist/dialects/pg/role/index.d.ts +71 -6
- package/dist/dialects/pg/role/sql.d.ts +11 -0
- package/dist/dialects/pg/schema.d.ts +2 -0
- package/dist/dialects/pg/table.d.ts +25 -3
- package/dist/dialects/pg/temporal.d.ts +5 -76
- package/dist/dialects/pg/tenancy.d.ts +45 -3
- package/dist/dialects/pg/view/client.d.ts +19 -1
- package/dist/dialects/pg/view/index.d.ts +4 -0
- package/dist/dialects/pg/view/index.js +21 -178
- package/dist/dialects/pg/view/refresh.d.ts +24 -0
- package/dist/runtime/batch.d.ts +1 -1
- package/dist/runtime/client.d.ts +6 -1
- package/dist/runtime/conflict.d.ts +2 -1
- package/dist/runtime/drift.d.ts +9 -0
- package/dist/runtime/inflight.d.ts +14 -0
- package/dist/runtime/pg/bun.js +6 -5
- package/dist/runtime/pg/pg.js +5 -5
- package/dist/runtime/pg/pglite.js +6 -5
- package/dist/runtime/pg/postgresjs.js +5 -5
- package/dist/runtime/plan.d.ts +22 -1
- package/dist/runtime/predicate.d.ts +19 -0
- package/dist/runtime/safety/index.js +1 -1
- package/dist/runtime/tenancy/composite.d.ts +26 -0
- package/dist/runtime/tenancy/context.d.ts +16 -0
- package/dist/runtime/tenancy/index.d.ts +9 -5
- package/dist/runtime/tenancy/index.js +1508 -37
- package/dist/runtime/tenancy/path.d.ts +87 -0
- package/dist/runtime/tenancy/rls.d.ts +67 -0
- package/dist/runtime/tenancy/via.d.ts +22 -0
- package/dist/runtime/traits/index.js +17 -11
- package/dist/runtime/types.d.ts +13 -1
- package/dist/runtime/validate/index.js +4 -4
- package/dist/runtime/write.d.ts +1 -1
- package/dist/shared/09p049xa.js +702 -0
- package/dist/shared/{ykv7wh5b.js → 1f0xa3cb.js} +5 -5
- package/dist/shared/1nw1f3vs.js +23 -0
- package/dist/shared/{6p5k20sm.js → 1z04fa85.js} +21 -11
- package/dist/shared/{p7pfx624.js → 2cg3wnxc.js} +314 -65
- package/dist/shared/{dyj86cmj.js → 2jd1sn0e.js} +2 -2
- package/dist/shared/{qgvt8nx1.js → 2z7wv5tj.js} +21 -5
- package/dist/shared/{kyxb62mc.js → 31vm914h.js} +9 -1
- package/dist/shared/{sf8m6tfy.js → 32cnm7kn.js} +8 -3
- package/dist/shared/{t4tbsy9h.js → 358zsv4r.js} +1 -1
- package/dist/shared/{jdgqqx31.js → 3fqwmr09.js} +38 -14
- package/dist/shared/{922qbgnw.js → 3qnhc7w5.js} +16 -9
- package/dist/shared/{zvbjc949.js → 4az561fn.js} +1 -1
- package/dist/shared/{k3ted12y.js → 54tqkxja.js} +20 -2
- package/dist/shared/{k7cc9nzk.js → 5d8t84hg.js} +15 -3
- package/dist/shared/{fa9vt245.js → 5j36z8dn.js} +17 -6
- package/dist/shared/{1g0drakv.js → 5yv4k6a6.js} +1 -1
- package/dist/shared/8dqhth8c.js +12 -0
- package/dist/shared/8etn7d8w.js +62 -0
- package/dist/shared/{g516zdsb.js → 8x72s86k.js} +476 -30
- package/dist/shared/{nkc9sfqb.js → 929h19xp.js} +145 -7
- package/dist/shared/{gjthds9j.js → 9628a9xt.js} +1 -1
- package/dist/shared/{8xsbagad.js → 9s0ypp87.js} +88 -7
- package/dist/shared/{b066g80h.js → ag4c7516.js} +2 -2
- package/dist/shared/b3awxn7h.js +45 -0
- package/dist/shared/b4v57v3x.js +9 -0
- package/dist/shared/bdk4sty6.js +58 -0
- package/dist/shared/{s6gqfn5j.js → c58secgj.js} +125 -8
- package/dist/shared/{rrstp3kb.js → cgbamx3e.js} +2 -2
- package/dist/shared/d5azex6s.js +6 -0
- package/dist/shared/{5fqx9yh4.js → dk8v79p3.js} +3 -1
- package/dist/shared/{4m9fn52z.js → ed0b8k4s.js} +1 -1
- package/dist/shared/{z2rnngj4.js → ek2wt2dz.js} +8 -5
- package/dist/shared/{wxn4b7pp.js → f0f1n281.js} +59 -12
- package/dist/shared/{gdh9mrtp.js → g90m9b0g.js} +3 -2
- package/dist/shared/{tbszx8mz.js → gwn6v667.js} +2 -2
- package/dist/shared/{c8aghh05.js → h15jx9bc.js} +8 -2
- package/dist/shared/{3p4b1fg0.js → hazqqecq.js} +17 -93
- package/dist/shared/{4ef7mmqf.js → j3rkk835.js} +34 -11
- package/dist/shared/{bt9sfq0z.js → j60w0dvr.js} +56 -21
- package/dist/shared/{ycatkxmq.js → jgqj11w4.js} +1 -1
- package/dist/shared/k68eedmy.js +85 -0
- package/dist/shared/{szm0cksa.js → knmes2kh.js} +34 -6
- package/dist/shared/{ckjbyrt9.js → mb2ycs1p.js} +7 -9
- package/dist/shared/{tq9afp8d.js → n076ydsc.js} +1 -1
- package/dist/shared/{xhh1srw3.js → nx9hh281.js} +50 -32
- package/dist/shared/{kdkxh3kb.js → p248q79y.js} +58 -59
- package/dist/shared/{990a291j.js → p6bjzq9q.js} +14 -9
- package/dist/shared/{h4nqvjkp.js → pjr6xrm5.js} +2 -2
- package/dist/shared/pz6rj8ay.js +212 -0
- package/dist/shared/{5vdm4sgp.js → q3j1tq7a.js} +36 -23
- package/dist/shared/{8bwbwy8h.js → qq3899ht.js} +128 -18
- package/dist/shared/{dxjp14rk.js → r11n8grd.js} +2 -2
- package/dist/shared/r1fdd0f6.js +19 -0
- package/dist/shared/{8ktwd3rh.js → r3j8s5y0.js} +1 -1
- package/dist/shared/rhs3xe4k.js +7 -0
- package/dist/shared/{jsd07prz.js → rpycarcr.js} +6 -6
- package/dist/shared/{xsq7v6wp.js → sbdme3vy.js} +14 -2
- package/dist/shared/{xdpj5kkm.js → t3g0k88x.js} +775 -264
- package/dist/shared/{ayz64vzj.js → ttmg09vd.js} +708 -19
- package/dist/shared/{r6pj4fq2.js → venqrjna.js} +8 -4
- package/dist/shared/{fancm5pt.js → vjpnzwjz.js} +138 -15
- package/dist/shared/{9tgmr1gh.js → vmfkhszw.js} +44 -9
- package/dist/shared/{wqem4jed.js → wkme6tep.js} +11 -9
- package/dist/shared/{qy9rdq0g.js → wt5rzv1h.js} +15 -11
- package/dist/shared/wxr8cwns.js +6 -0
- package/dist/shared/{bzsjtd7c.js → wynzeggs.js} +19 -14
- package/dist/shared/x3jc53kg.js +220 -0
- package/dist/shared/{7p2wbz7f.js → x72jb7ad.js} +1 -1
- package/dist/shared/{fyqkk1m0.js → xq0mvhts.js} +10 -9
- package/dist/shared/xqve9598.js +53 -0
- package/dist/shared/{47xzb9fc.js → y2t3jktd.js} +2 -2
- package/dist/shared/{9x25fxhc.js → y34a8714.js} +1 -1
- package/dist/shared/{k7dwkhvq.js → y6jdds7g.js} +4 -1
- package/dist/shared/{h8ne16fq.js → ys0xzyaj.js} +1 -1
- package/dist/shared/{c9z5g0fm.js → ywr8hmey.js} +5 -2
- package/dist/shared/{g7ez901n.js → ywspezzx.js} +1 -1
- package/dist/shared/{9m80mkac.js → ze4hxsmy.js} +1 -1
- package/dist/shared/{fb00y8fp.js → zm0mafk4.js} +12 -6
- package/dist/shared/{y005b761.js → zy8r7qvz.js} +6 -2
- package/dist/tooling/cli.js +97 -24
- package/dist/tooling/migrate/apply.d.ts +14 -0
- package/dist/tooling/migrate/check.d.ts +3 -4
- package/dist/tooling/migrate/classify.d.ts +4 -0
- package/dist/tooling/migrate/commands.d.ts +1 -2
- package/dist/tooling/migrate/config.d.ts +3 -2
- package/dist/tooling/migrate/drift.d.ts +1 -1
- package/dist/tooling/migrate/estimate.d.ts +14 -1
- package/dist/tooling/migrate/files.d.ts +11 -1
- package/dist/tooling/migrate/index.js +17 -16
- package/dist/tooling/migrate/lint.d.ts +4 -4
- package/dist/tooling/migrate/lost.d.ts +28 -0
- package/dist/tooling/migrate/paths.d.ts +14 -0
- package/dist/tooling/migrate/plan.d.ts +10 -3
- package/dist/tooling/migrate/policy.d.ts +11 -0
- package/dist/tooling/migrate/runner.d.ts +25 -0
- package/dist/tooling/migrate/sandbox.d.ts +57 -0
- package/dist/tooling/migrate/sql-lex.d.ts +39 -0
- package/dist/tooling/migrate/text.d.ts +42 -0
- package/dist/tooling/node-version.d.ts +21 -0
- package/dist/tooling/testing/factories.d.ts +10 -0
- package/dist/tooling/testing/facts.d.ts +33 -5
- package/dist/tooling/testing/index.d.ts +1 -1
- package/dist/tooling/testing/index.js +3 -3
- package/dist/tooling/testing/isolation.d.ts +15 -8
- package/package.json +10 -6
- package/dist/shared/0v1g424p.js +0 -26
- package/dist/shared/r73pt594.js +0 -426
- package/dist/shared/rasvvzgz.js +0 -21
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
functionObject,
|
|
3
3
|
triggerObject
|
|
4
|
-
} from "../../../shared/
|
|
4
|
+
} from "../../../shared/y34a8714.js";
|
|
5
5
|
import {
|
|
6
6
|
staticNamespace2
|
|
7
|
-
} from "../../../shared/
|
|
7
|
+
} from "../../../shared/358zsv4r.js";
|
|
8
|
+
import {
|
|
9
|
+
assertIdentifier2
|
|
10
|
+
} from "../../../shared/nfzc5z0w.js";
|
|
8
11
|
import {
|
|
9
12
|
OkmError2
|
|
10
13
|
} from "../../../shared/52szzakm.js";
|
|
@@ -26,6 +29,11 @@ function fn(name, options) {
|
|
|
26
29
|
fix: { summary: "Set search_path on the function to the schemas it is allowed to see." }
|
|
27
30
|
});
|
|
28
31
|
}
|
|
32
|
+
if (options.searchPath !== undefined && options.searchPath.trim().length > 0) {
|
|
33
|
+
for (const part of options.searchPath.split(",")) {
|
|
34
|
+
assertIdentifier2(part.trim(), `function ${name} search_path`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
29
37
|
const argTypes = (options.arguments ?? []).map((argument) => argument.type);
|
|
30
38
|
const schema = options.schema ?? "public";
|
|
31
39
|
return {
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
* Each builder is a separate export so a bundle can keep only the ones it calls.
|
|
6
6
|
*/
|
|
7
7
|
export { schema, type BuiltSchema, type SchemaCodecs, type SchemaInput, type SchemaRequires, } from "./schema.js";
|
|
8
|
-
export {
|
|
8
|
+
export { withOwner, type DeclaredOwner } from "./owner.js";
|
|
9
|
+
export { index, sql, table, type AnyTable, type ColumnHandle, type IndexCall, type SqlText, type SqlValue, type FilterOperator, type Table, type TableOptions, } from "./table.js";
|
|
9
10
|
export type { PresetQuery } from "./preset.js";
|
|
10
11
|
export { custom } from "./custom.js";
|
|
11
12
|
export { ColumnBuilder } from "./column.js";
|
|
@@ -2,7 +2,10 @@ import {
|
|
|
2
2
|
jsonReplacer2,
|
|
3
3
|
json2,
|
|
4
4
|
jsonb2
|
|
5
|
-
} from "../../shared/
|
|
5
|
+
} from "../../shared/9628a9xt.js";
|
|
6
|
+
import {
|
|
7
|
+
withOwner2
|
|
8
|
+
} from "../../shared/xqve9598.js";
|
|
6
9
|
import {
|
|
7
10
|
encodeInstant,
|
|
8
11
|
decodeInstant,
|
|
@@ -14,25 +17,22 @@ import {
|
|
|
14
17
|
time2,
|
|
15
18
|
timetz2,
|
|
16
19
|
interval2
|
|
17
|
-
} from "../../shared/
|
|
20
|
+
} from "../../shared/5yv4k6a6.js";
|
|
18
21
|
import {
|
|
19
|
-
one2,
|
|
20
|
-
many2,
|
|
21
|
-
manyThrough2,
|
|
22
22
|
schema2
|
|
23
|
-
} from "../../shared/
|
|
23
|
+
} from "../../shared/hazqqecq.js";
|
|
24
24
|
import {
|
|
25
25
|
domainType
|
|
26
|
-
} from "../../shared/
|
|
26
|
+
} from "../../shared/ywspezzx.js";
|
|
27
|
+
import {
|
|
28
|
+
one2,
|
|
29
|
+
many2,
|
|
30
|
+
manyThrough2
|
|
31
|
+
} from "../../shared/k68eedmy.js";
|
|
27
32
|
import {
|
|
28
33
|
id2,
|
|
29
34
|
uuid2
|
|
30
|
-
} from "../../shared/
|
|
31
|
-
import {
|
|
32
|
-
table2,
|
|
33
|
-
index2,
|
|
34
|
-
sql2
|
|
35
|
-
} from "../../shared/jsd07prz.js";
|
|
35
|
+
} from "../../shared/2jd1sn0e.js";
|
|
36
36
|
import {
|
|
37
37
|
text2,
|
|
38
38
|
varchar2,
|
|
@@ -40,13 +40,18 @@ import {
|
|
|
40
40
|
citext2,
|
|
41
41
|
encodeText,
|
|
42
42
|
decodeText
|
|
43
|
-
} from "../../shared/
|
|
43
|
+
} from "../../shared/ed0b8k4s.js";
|
|
44
|
+
import {
|
|
45
|
+
table2,
|
|
46
|
+
index2,
|
|
47
|
+
sql2
|
|
48
|
+
} from "../../shared/rpycarcr.js";
|
|
44
49
|
import {
|
|
45
50
|
ColumnBuilder2,
|
|
46
51
|
required,
|
|
47
52
|
openColumn,
|
|
48
53
|
formatType
|
|
49
|
-
} from "../../shared/
|
|
54
|
+
} from "../../shared/ywr8hmey.js";
|
|
50
55
|
import {
|
|
51
56
|
definition,
|
|
52
57
|
rejected
|
|
@@ -54,11 +59,12 @@ import {
|
|
|
54
59
|
import {
|
|
55
60
|
sameNamespace2,
|
|
56
61
|
compareText
|
|
57
|
-
} from "../../shared/
|
|
62
|
+
} from "../../shared/358zsv4r.js";
|
|
58
63
|
import {
|
|
59
64
|
tag
|
|
60
65
|
} from "../../shared/cn0n68ft.js";
|
|
61
66
|
import {
|
|
67
|
+
OkmError2,
|
|
62
68
|
catalogError2
|
|
63
69
|
} from "../../shared/52szzakm.js";
|
|
64
70
|
var __defProp = Object.defineProperty;
|
|
@@ -909,6 +915,11 @@ function notIn(values) {
|
|
|
909
915
|
}
|
|
910
916
|
// src/dialects/pg/ops/or.ts
|
|
911
917
|
function or(branches) {
|
|
918
|
+
if (arguments.length !== 1 || !Array.isArray(branches)) {
|
|
919
|
+
throw new OkmError2("OKM1121", "Pass an array: or([a, b]).", {
|
|
920
|
+
fix: { summary: "Pass an array: or([a, b])." }
|
|
921
|
+
});
|
|
922
|
+
}
|
|
912
923
|
return tag("or", branches);
|
|
913
924
|
}
|
|
914
925
|
// src/dialects/pg/ops/overlaps.ts
|
|
@@ -998,5 +1009,6 @@ export {
|
|
|
998
1009
|
tstzrange,
|
|
999
1010
|
tsvector,
|
|
1000
1011
|
uuid2 as uuid,
|
|
1001
|
-
varchar2 as varchar
|
|
1012
|
+
varchar2 as varchar,
|
|
1013
|
+
withOwner2 as withOwner
|
|
1002
1014
|
};
|
|
@@ -15,6 +15,13 @@ export type IntrospectOptions = {
|
|
|
15
15
|
* When omitted, roles, grants, and default privileges are not read.
|
|
16
16
|
*/
|
|
17
17
|
readonly managedRoles?: readonly string[];
|
|
18
|
+
/**
|
|
19
|
+
* Read-only role.
|
|
20
|
+
*
|
|
21
|
+
* Schema `USAGE` is read for this role only. Other roles keep the schema
|
|
22
|
+
* privileges they already have.
|
|
23
|
+
*/
|
|
24
|
+
readonly reportingRole?: string;
|
|
18
25
|
};
|
|
19
26
|
/** A connection that can run one query. Parameters are `$1`, `$2`, … */
|
|
20
27
|
export type CatalogQuery = {
|
|
@@ -21,8 +21,13 @@ export type ColumnModel = {
|
|
|
21
21
|
* call a codec it does not need.
|
|
22
22
|
*/
|
|
23
23
|
readonly decode: ((wire: string) => unknown) | undefined;
|
|
24
|
-
/**
|
|
25
|
-
|
|
24
|
+
/**
|
|
25
|
+
* Excluded from a default select. Named selects still return it. Includes never return it.
|
|
26
|
+
*
|
|
27
|
+
* `"filter"` is still excluded, and `where` and `orderBy` may name it.
|
|
28
|
+
* `true` is excluded and refused there (OKM1120).
|
|
29
|
+
*/
|
|
30
|
+
readonly hidden: boolean | "filter";
|
|
26
31
|
/**
|
|
27
32
|
* Redacted in logs, errors, and `inspect()`.
|
|
28
33
|
*
|
|
@@ -3,7 +3,7 @@ import { type Or } from "../operators.js";
|
|
|
3
3
|
* Disjunction of where objects.
|
|
4
4
|
*
|
|
5
5
|
* @typeParam V - One branch
|
|
6
|
-
* @param branches - Where objects, or-ed
|
|
6
|
+
* @param branches - Where objects, or-ed. One array: `or([a, b])`
|
|
7
7
|
* @returns A tagged operator
|
|
8
8
|
*/
|
|
9
9
|
export declare function or<const V>(branches: readonly V[]): Or<V>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Table ownership marks (`external` and `ignored`).
|
|
3
|
+
*
|
|
4
|
+
* The mark lives on the table value, not in `table()` options. `schema()` does
|
|
5
|
+
* not read it, so a featureless app does not load this module. Tooling stamps
|
|
6
|
+
* the catalog before it plans.
|
|
7
|
+
*/
|
|
8
|
+
import type { Catalog, Owner } from "../../contracts/catalog/types.js";
|
|
9
|
+
import type { AnyTable } from "./table.js";
|
|
10
|
+
/** Owners a declaration may set. `managed` stays the default. */
|
|
11
|
+
export type DeclaredOwner = Exclude<Owner, "managed">;
|
|
12
|
+
/**
|
|
13
|
+
* Marks a table `external` or `ignored`.
|
|
14
|
+
*
|
|
15
|
+
* `external` is known and queryable, and a plan never creates, alters, or
|
|
16
|
+
* drops it. `ignored` is invisible to diffs, plans, and `okm check`. The
|
|
17
|
+
* table stays on the schema, so the client can still name it.
|
|
18
|
+
*
|
|
19
|
+
* @param table - A `table()` value
|
|
20
|
+
* @param owner - `external` or `ignored`
|
|
21
|
+
* @returns The same table
|
|
22
|
+
*/
|
|
23
|
+
export declare function withOwner<T extends AnyTable>(table: T, owner: DeclaredOwner): T;
|
|
24
|
+
/**
|
|
25
|
+
* Reads the mark {@link withOwner} stored.
|
|
26
|
+
*
|
|
27
|
+
* @param table - A table value
|
|
28
|
+
* @returns The mark, or `undefined` when the table is managed
|
|
29
|
+
*/
|
|
30
|
+
export declare function tableOwner(table: object): DeclaredOwner | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Copies `owner` onto a table and the objects that belong to it.
|
|
33
|
+
*
|
|
34
|
+
* Columns, indexes, constraints, triggers, policies, and sequences that
|
|
35
|
+
* depend on the table follow the table. A catalog with no marks is returned
|
|
36
|
+
* as itself.
|
|
37
|
+
*
|
|
38
|
+
* @param source - Catalog from `schema()`
|
|
39
|
+
* @param marks - SQL table name to owner
|
|
40
|
+
* @returns The catalog planning and drift should read
|
|
41
|
+
*/
|
|
42
|
+
export declare function stampOwnership(source: Catalog, marks: ReadonlyMap<string, DeclaredOwner>): Catalog;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Marks the table a path ends on.
|
|
3
|
+
*
|
|
4
|
+
* The symbol lives here so a column-only app and a featureless app do not
|
|
5
|
+
* load it. `archivable()` reads it. Compile hashes named fields, so the mark
|
|
6
|
+
* stays out of the catalog.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Property set on the tenant table a path ends on.
|
|
10
|
+
*
|
|
11
|
+
* An options spread does not copy it. The rewrite sets it on the table object.
|
|
12
|
+
*/
|
|
13
|
+
export declare const pathEndpoint: unique symbol;
|
|
14
|
+
/**
|
|
15
|
+
* Records that `table` is the end of a path.
|
|
16
|
+
*
|
|
17
|
+
* @param table - The rewritten tenant table
|
|
18
|
+
* @returns The same table, marked
|
|
19
|
+
*/
|
|
20
|
+
export declare function markPathEndpoint<T extends object>(table: T): T;
|
|
@@ -23,6 +23,9 @@ export declare function assertRoleHealth(runner: Runner, roles: RolesInput, obje
|
|
|
23
23
|
/**
|
|
24
24
|
* Refuses to apply role changes when the acting role lacks `CREATEROLE`.
|
|
25
25
|
*
|
|
26
|
+
* A superuser can create roles when `rolcreaterole` is false, so `rolsuper`
|
|
27
|
+
* satisfies the same check.
|
|
28
|
+
*
|
|
26
29
|
* @param runner - Database connection
|
|
27
30
|
* @param role - The role that will run `CREATE ROLE` or `ALTER ROLE`
|
|
28
31
|
*/
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `roles: { migration, app }`.
|
|
2
|
+
* `roles: { migration, app, reporting? }`.
|
|
3
3
|
*
|
|
4
4
|
* The object contributes role, grant, and default-privilege records. `schema()`
|
|
5
5
|
* does not import this module. Tooling calls {@link attachRoles} when the
|
|
6
6
|
* config names roles.
|
|
7
7
|
*/
|
|
8
8
|
import type { Catalog, CatalogObject } from "../../../contracts/catalog/types.js";
|
|
9
|
+
import { OkmError } from "../../../contracts/error.js";
|
|
9
10
|
/** A role the plan creates and alters. It is never dropped. */
|
|
10
11
|
export type ManagedRole = {
|
|
11
12
|
readonly name: string;
|
|
@@ -14,37 +15,101 @@ export type ManagedRole = {
|
|
|
14
15
|
/** `INHERIT` when not `false`. */
|
|
15
16
|
readonly inherit?: boolean;
|
|
16
17
|
};
|
|
18
|
+
/**
|
|
19
|
+
* One column grant.
|
|
20
|
+
*
|
|
21
|
+
* `on` is the table, view, or materialized view name. `select` and `update`
|
|
22
|
+
* name columns. A hidden column is included only when it is listed here.
|
|
23
|
+
*/
|
|
24
|
+
export type ColumnGrantInput = {
|
|
25
|
+
/** Role that receives the privilege. */
|
|
26
|
+
readonly role: string;
|
|
27
|
+
/** Table, view, or materialized view. */
|
|
28
|
+
readonly on: string;
|
|
29
|
+
/** Columns granted `SELECT`. */
|
|
30
|
+
readonly select?: readonly string[];
|
|
31
|
+
/** Columns granted `UPDATE`. */
|
|
32
|
+
readonly update?: readonly string[];
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Why a `roles` declaration was refused.
|
|
36
|
+
*
|
|
37
|
+
* `reporting_distinct` means the reporting role is the migration or
|
|
38
|
+
* application role. `reporting_write` means that role was granted a write.
|
|
39
|
+
*/
|
|
40
|
+
export type RoleDeclarationReason = "reporting_distinct" | "reporting_write";
|
|
41
|
+
/**
|
|
42
|
+
* A `roles` declaration this version refuses.
|
|
43
|
+
*
|
|
44
|
+
* The kind stays `invalid`. No new OKM code: OKM1825 is a missing privilege
|
|
45
|
+
* at doctor time, and OKM1060 is a column definition.
|
|
46
|
+
*/
|
|
47
|
+
export declare class RoleDeclarationError extends OkmError {
|
|
48
|
+
/** Which rule refused the declaration. */
|
|
49
|
+
readonly reason: RoleDeclarationReason;
|
|
50
|
+
/**
|
|
51
|
+
* @param reason - Which rule failed
|
|
52
|
+
* @param message - What the author should change
|
|
53
|
+
*/
|
|
54
|
+
constructor(reason: RoleDeclarationReason, message: string);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Columns of one table, for the reporting role's hidden-column rule.
|
|
58
|
+
*
|
|
59
|
+
* `hidden` is true for `.hidden()` and for `hidden({ filterable: true })`.
|
|
60
|
+
*/
|
|
61
|
+
export type TableExposure = {
|
|
62
|
+
/** SQL table name. */
|
|
63
|
+
readonly table: string;
|
|
64
|
+
/** Field name and SQL name. `hidden` is left out of the reporting role. */
|
|
65
|
+
readonly columns: readonly {
|
|
66
|
+
readonly field: string;
|
|
67
|
+
readonly sql: string;
|
|
68
|
+
readonly hidden: boolean;
|
|
69
|
+
}[];
|
|
70
|
+
};
|
|
17
71
|
/**
|
|
18
72
|
* Roles named by `defineConfig`.
|
|
19
73
|
*
|
|
20
74
|
* A string is external: it must already exist. A name listed in `managed` is
|
|
21
|
-
* created when `pg_roles` does not have it.
|
|
75
|
+
* created when `pg_roles` does not have it. `reporting` receives select only.
|
|
22
76
|
*/
|
|
23
77
|
export type RolesInput = {
|
|
24
78
|
/** Role that runs migrations. */
|
|
25
79
|
readonly migration: string;
|
|
26
80
|
/** Role the application connects as. */
|
|
27
81
|
readonly app: string;
|
|
82
|
+
/**
|
|
83
|
+
* Read-only role.
|
|
84
|
+
*
|
|
85
|
+
* Select on tables, views, and materialized views, usage on schemas, and
|
|
86
|
+
* default privileges for later tables. No write and no execute.
|
|
87
|
+
*/
|
|
88
|
+
readonly reporting?: string;
|
|
28
89
|
/** Roles this catalog creates and alters. */
|
|
29
90
|
readonly managed?: readonly ManagedRole[];
|
|
91
|
+
/** Column `SELECT` or `UPDATE` grants. */
|
|
92
|
+
readonly columns?: readonly ColumnGrantInput[];
|
|
30
93
|
};
|
|
31
94
|
/**
|
|
32
95
|
* Adds role, grant, and default-privilege objects to a catalog.
|
|
33
96
|
*
|
|
34
97
|
* Grants and default privileges are for {@link RolesInput.app} on every
|
|
35
|
-
* managed table, view, materialized view, sequence, and function.
|
|
36
|
-
* grants are
|
|
98
|
+
* managed table, view, materialized view, sequence, and function. Column
|
|
99
|
+
* grants and the reporting role are added when `input` names them.
|
|
37
100
|
*
|
|
38
101
|
* @param source - Catalog from `schema()`
|
|
39
102
|
* @param input - Migration role, application role, and managed roles
|
|
103
|
+
* @param exposure - Hidden columns. Omitted when no table hides one
|
|
40
104
|
* @returns A catalog that includes those objects
|
|
41
105
|
*/
|
|
42
|
-
export declare function attachRoles(source: Catalog, input: RolesInput): Catalog;
|
|
106
|
+
export declare function attachRoles(source: Catalog, input: RolesInput, exposure?: readonly TableExposure[]): Catalog;
|
|
43
107
|
/**
|
|
44
108
|
* Catalog records for one `roles` configuration.
|
|
45
109
|
*
|
|
46
110
|
* @param input - Migration role, application role, and managed roles
|
|
47
111
|
* @param built - Objects already in the catalog
|
|
112
|
+
* @param exposure - Hidden columns. Omitted when no table hides one
|
|
48
113
|
* @returns Role, grant, and default-privilege records
|
|
49
114
|
*/
|
|
50
|
-
export declare function contributeRoles(input: RolesInput, built: readonly CatalogObject[]): readonly CatalogObject[];
|
|
115
|
+
export declare function contributeRoles(input: RolesInput, built: readonly CatalogObject[], exposure?: readonly TableExposure[]): readonly CatalogObject[];
|
|
@@ -19,6 +19,17 @@ export type PrivilegeStatement = {
|
|
|
19
19
|
readonly sql: string;
|
|
20
20
|
readonly kind: "revoke" | "revoke-default" | "create-role" | "alter-role" | "grant-default" | "grant";
|
|
21
21
|
};
|
|
22
|
+
/**
|
|
23
|
+
* Privilege name for a column grant.
|
|
24
|
+
*
|
|
25
|
+
* Columns are sorted so the identity is stable. The catalog stores this
|
|
26
|
+
* string. It does not grow the grant type.
|
|
27
|
+
*
|
|
28
|
+
* @param name - `SELECT` or `UPDATE`
|
|
29
|
+
* @param columns - SQL column names
|
|
30
|
+
* @returns `SELECT(email,name)`
|
|
31
|
+
*/
|
|
32
|
+
export declare function columnPrivilege(name: string, columns: readonly string[]): string;
|
|
22
33
|
/**
|
|
23
34
|
* Diffs role, grant, and default-privilege objects into SQL.
|
|
24
35
|
*
|
|
@@ -114,6 +114,8 @@ export type TenancySchema<S, TTables extends readonly AnyTable[], TTenancy> = TT
|
|
|
114
114
|
readonly "~byName": {
|
|
115
115
|
readonly [T in TTables[number] as T["~name"]]: T extends {
|
|
116
116
|
readonly "~global": string;
|
|
117
|
+
} ? T : T extends {
|
|
118
|
+
readonly "~path": string;
|
|
117
119
|
} ? T : T & {
|
|
118
120
|
readonly "~row": RowFrom<TenantFields<TTenancy["key"]>>;
|
|
119
121
|
readonly "~insert": InsertFrom<TenantFields<TTenancy["key"]>>;
|
|
@@ -154,7 +154,8 @@ export type Table<TName extends string, TColumns, TRelations extends Readonly<Re
|
|
|
154
154
|
* Allowlisted client filters.
|
|
155
155
|
*
|
|
156
156
|
* A hidden field in `allow`, `sort`, or `relations` throws OKM1123 here.
|
|
157
|
-
* `parse` loads the parser on first use.
|
|
157
|
+
* `parse` loads the parser on first use. An operator outside
|
|
158
|
+
* {@link FilterOperator} is not assignable.
|
|
158
159
|
*
|
|
159
160
|
* @param spec - Fields, operators, and sorts the caller may send
|
|
160
161
|
* @returns A parser for one request object
|
|
@@ -163,10 +164,23 @@ export type Table<TName extends string, TColumns, TRelations extends Readonly<Re
|
|
|
163
164
|
parse(query: unknown): Promise<ParsedFilters>;
|
|
164
165
|
};
|
|
165
166
|
};
|
|
167
|
+
/**
|
|
168
|
+
* Operators `filters().parse` applies.
|
|
169
|
+
*
|
|
170
|
+
* `path`, `matches`, `similar`, `wordSimilar`, boolean trees, relation
|
|
171
|
+
* quantifiers, and write operators are not in this list. A caller cannot
|
|
172
|
+
* name them in `allow`.
|
|
173
|
+
*/
|
|
174
|
+
export type FilterOperator = "eq" | "in" | "inList" | "notIn" | "lt" | "lte" | "gt" | "gte" | "between" | "startsWith" | "endsWith" | "contains" | "like" | "ilike" | "not" | "containedBy" | "overlaps" | "hasKey" | "hasAnyKey";
|
|
166
175
|
/** What {@link Table.filters} accepts. */
|
|
167
176
|
export type FilterSpec = {
|
|
168
|
-
readonly allow?: Readonly<Record<string, readonly
|
|
177
|
+
readonly allow?: Readonly<Record<string, readonly FilterOperator[]>>;
|
|
169
178
|
readonly sort?: readonly string[];
|
|
179
|
+
/**
|
|
180
|
+
* Relation name to the fields a caller may filter.
|
|
181
|
+
*
|
|
182
|
+
* `parse` turns `{ list: { name: { startsWith: "a" } } }` into `has`.
|
|
183
|
+
*/
|
|
170
184
|
readonly relations?: Readonly<Record<string, readonly string[]>>;
|
|
171
185
|
};
|
|
172
186
|
/** `where` and `orderBy` a caller can spread into `find`. */
|
|
@@ -266,7 +280,7 @@ type PrimaryOf<TOptions> = TOptions extends {
|
|
|
266
280
|
* @typeParam TColumns - Column builders
|
|
267
281
|
* @typeParam TOptions - Options argument
|
|
268
282
|
*/
|
|
269
|
-
type DeclaredTable<TName extends string, TColumns, TOptions> = Table<TName, TColumns, RelationsOf<TOptions>, PrimaryOf<TOptions>, NoInfer<TOptions>> & TraitShapes<TColumns, TOptions> & ArchiveFlag<TOptions> & PresetFlag<TOptions> & OmitFlag<TOptions> & GlobalFlag<TOptions>;
|
|
283
|
+
type DeclaredTable<TName extends string, TColumns, TOptions> = Table<TName, TColumns, RelationsOf<TOptions>, PrimaryOf<TOptions>, NoInfer<TOptions>> & TraitShapes<TColumns, TOptions> & ArchiveFlag<TOptions> & PresetFlag<TOptions> & OmitFlag<TOptions> & GlobalFlag<TOptions> & PathFlag<TOptions>;
|
|
270
284
|
type ArchiveFlag<TOptions> = TOptions extends {
|
|
271
285
|
readonly traits: infer TTraits;
|
|
272
286
|
} ? HasArchive<TTraits> : unknown;
|
|
@@ -291,6 +305,14 @@ type GlobalFlag<TOptions> = TOptions extends {
|
|
|
291
305
|
} ? {
|
|
292
306
|
readonly "~global": TReason;
|
|
293
307
|
} : unknown;
|
|
308
|
+
/** A path table keeps its own columns. The schema type does not add the tenant key. */
|
|
309
|
+
type PathFlag<TOptions> = TOptions extends {
|
|
310
|
+
readonly tenancy: {
|
|
311
|
+
readonly via: infer TVia extends string;
|
|
312
|
+
};
|
|
313
|
+
} ? {
|
|
314
|
+
readonly "~path": TVia;
|
|
315
|
+
} : unknown;
|
|
294
316
|
type TraitShapes<TColumns, TOptions> = TOptions extends {
|
|
295
317
|
readonly traits: infer TTraits;
|
|
296
318
|
} ? TTraits extends readonly {
|
|
@@ -114,100 +114,29 @@ export declare function decodeDuration(wire: string): Temporal.Duration;
|
|
|
114
114
|
*/
|
|
115
115
|
export declare function intervalFields(fields: string): string;
|
|
116
116
|
/**
|
|
117
|
-
*
|
|
118
|
-
* TypeScript
|
|
117
|
+
* Empty names so `Temporal.Instant` and the other codec types merge with
|
|
118
|
+
* TypeScript's Temporal lib and with `temporal-polyfill`. Method signatures
|
|
119
|
+
* live in `temporal.local.d.ts` for this repository's typecheck only. They
|
|
120
|
+
* are not shipped: a second `toString` or `var Temporal` conflicts with those
|
|
121
|
+
* libraries (QA-L2).
|
|
119
122
|
*/
|
|
120
123
|
declare global {
|
|
121
124
|
/** Instant, plain date-time, date, time, and duration. */
|
|
122
125
|
namespace Temporal {
|
|
123
126
|
/** UTC instant. */
|
|
124
127
|
interface Instant {
|
|
125
|
-
/**
|
|
126
|
-
* @param options - Fractional digits to keep
|
|
127
|
-
* @returns ISO-8601 text
|
|
128
|
-
*/
|
|
129
|
-
toString(options?: {
|
|
130
|
-
readonly fractionalSecondDigits?: number;
|
|
131
|
-
}): string;
|
|
132
128
|
}
|
|
133
129
|
/** Date and time without a zone. */
|
|
134
130
|
interface PlainDateTime {
|
|
135
|
-
/**
|
|
136
|
-
* @param options - Fractional digits to keep
|
|
137
|
-
* @returns ISO-8601 text
|
|
138
|
-
*/
|
|
139
|
-
toString(options?: {
|
|
140
|
-
readonly fractionalSecondDigits?: number;
|
|
141
|
-
}): string;
|
|
142
131
|
}
|
|
143
132
|
/** Calendar date. */
|
|
144
133
|
interface PlainDate {
|
|
145
|
-
/**
|
|
146
|
-
* @returns `YYYY-MM-DD`
|
|
147
|
-
*/
|
|
148
|
-
toString(): string;
|
|
149
|
-
/**
|
|
150
|
-
* @param duration - Days to add
|
|
151
|
-
* @returns A later or earlier date
|
|
152
|
-
*/
|
|
153
|
-
add(duration: {
|
|
154
|
-
readonly days: number;
|
|
155
|
-
}): Temporal.PlainDate;
|
|
156
134
|
}
|
|
157
135
|
/** Time of day. */
|
|
158
136
|
interface PlainTime {
|
|
159
|
-
/**
|
|
160
|
-
* @param options - Fractional digits to keep
|
|
161
|
-
* @returns Time text
|
|
162
|
-
*/
|
|
163
|
-
toString(options?: {
|
|
164
|
-
readonly fractionalSecondDigits?: number;
|
|
165
|
-
}): string;
|
|
166
137
|
}
|
|
167
138
|
/** ISO-8601 duration. */
|
|
168
139
|
interface Duration {
|
|
169
|
-
/**
|
|
170
|
-
* @returns ISO-8601 duration text
|
|
171
|
-
*/
|
|
172
|
-
toString(): string;
|
|
173
140
|
}
|
|
174
141
|
}
|
|
175
|
-
/** Temporal constructors used by the codecs. */
|
|
176
|
-
var Temporal: {
|
|
177
|
-
readonly Instant: {
|
|
178
|
-
/**
|
|
179
|
-
* @param item - ISO-8601 instant
|
|
180
|
-
* @returns An instant
|
|
181
|
-
*/
|
|
182
|
-
from(item: string): Temporal.Instant;
|
|
183
|
-
};
|
|
184
|
-
readonly PlainDateTime: {
|
|
185
|
-
/**
|
|
186
|
-
* @param item - ISO-8601 date-time
|
|
187
|
-
* @returns A plain date-time
|
|
188
|
-
*/
|
|
189
|
-
from(item: string): Temporal.PlainDateTime;
|
|
190
|
-
};
|
|
191
|
-
readonly PlainDate: {
|
|
192
|
-
/**
|
|
193
|
-
* @param item - `YYYY-MM-DD`
|
|
194
|
-
* @returns A date
|
|
195
|
-
*/
|
|
196
|
-
from(item: string): Temporal.PlainDate;
|
|
197
|
-
};
|
|
198
|
-
readonly PlainTime: {
|
|
199
|
-
/**
|
|
200
|
-
* @param item - Time text
|
|
201
|
-
* @returns A time
|
|
202
|
-
*/
|
|
203
|
-
from(item: string): Temporal.PlainTime;
|
|
204
|
-
};
|
|
205
|
-
readonly Duration: {
|
|
206
|
-
/**
|
|
207
|
-
* @param item - ISO-8601 duration, or numeric fields
|
|
208
|
-
* @returns A duration
|
|
209
|
-
*/
|
|
210
|
-
from(item: string | Readonly<Record<string, number>>): Temporal.Duration;
|
|
211
|
-
};
|
|
212
|
-
};
|
|
213
142
|
}
|
|
@@ -16,9 +16,15 @@ import type { AnyTable } from "./table.js";
|
|
|
16
16
|
export type TenantFields<Key extends string> = {
|
|
17
17
|
readonly [K in Key]: ColumnBuilder<string, FlagTrue<PlainFlags, "guarded">>;
|
|
18
18
|
};
|
|
19
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* One tenant value, or a reason for leaving the scope. The value is not a cache key.
|
|
21
|
+
*
|
|
22
|
+
* `values` is set when the tenant is several keys. `value` stays the first key,
|
|
23
|
+
* which is what a single-key scope already stored.
|
|
24
|
+
*/
|
|
20
25
|
export type TenantCall = {
|
|
21
26
|
readonly value: string;
|
|
27
|
+
readonly values?: Readonly<Record<string, string>>;
|
|
22
28
|
} | {
|
|
23
29
|
readonly unscoped: string;
|
|
24
30
|
};
|
|
@@ -49,10 +55,45 @@ export type TenancyRule = {
|
|
|
49
55
|
*/
|
|
50
56
|
export type ColumnTenancy = {
|
|
51
57
|
readonly key: string;
|
|
58
|
+
/** Every tenant field, in declaration order. One entry for column tenancy. */
|
|
59
|
+
readonly keys?: readonly string[];
|
|
52
60
|
readonly type: "uuid";
|
|
53
|
-
readonly strategy:
|
|
61
|
+
readonly strategy: string;
|
|
54
62
|
/** Tables with the tenant column, widened uniques, and composite references. */
|
|
55
63
|
rewrite(tables: readonly AnyTable[]): readonly AnyTable[];
|
|
64
|
+
/** Path table: isolation follows a relation instead of a tenant column. */
|
|
65
|
+
isPath?(table: string): boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Steps from a path table to the tenant table.
|
|
68
|
+
*
|
|
69
|
+
* Absent when `table` has its own tenant column.
|
|
70
|
+
*/
|
|
71
|
+
pathOf?(table: string): readonly {
|
|
72
|
+
readonly child: string;
|
|
73
|
+
readonly parent: string;
|
|
74
|
+
readonly localField: string;
|
|
75
|
+
readonly remoteField: string;
|
|
76
|
+
}[] | undefined;
|
|
77
|
+
/**
|
|
78
|
+
* Writes a locking `EXISTS` for an insert into a path table.
|
|
79
|
+
*
|
|
80
|
+
* @returns `false` when `table` is not a path table
|
|
81
|
+
*/
|
|
82
|
+
lockPredicate?(input: {
|
|
83
|
+
readonly table: string;
|
|
84
|
+
readonly fieldSql: (field: string) => string | undefined;
|
|
85
|
+
readonly encode: ((value: unknown) => string) | undefined;
|
|
86
|
+
readonly alias: string;
|
|
87
|
+
readonly appended: boolean;
|
|
88
|
+
readonly scope: TenantCall | undefined;
|
|
89
|
+
readonly sink: TenancyText;
|
|
90
|
+
}): boolean;
|
|
91
|
+
/**
|
|
92
|
+
* Checks a path update's new parent in the same statement.
|
|
93
|
+
*
|
|
94
|
+
* A column-tenant table ignores it.
|
|
95
|
+
*/
|
|
96
|
+
noteParent?(table: string, set: Readonly<Record<string, unknown>>, sink: TenancyText, scope: TenantCall | undefined, fieldSql: (field: string) => string | undefined): void;
|
|
56
97
|
/** The guarded uuid column, for emitted row types. */
|
|
57
98
|
column(): object;
|
|
58
99
|
predicate(input: {
|
|
@@ -95,7 +136,8 @@ export type ColumnTenancy = {
|
|
|
95
136
|
/**
|
|
96
137
|
* Reads `schema({ tenancy })`.
|
|
97
138
|
*
|
|
98
|
-
* Omitted stays `undefined`. Anything else must
|
|
139
|
+
* Omitted stays `undefined`. Anything else must carry `rewrite`. The strategy
|
|
140
|
+
* name stays on the object from `okmodel/tenancy`. This file does not list them.
|
|
99
141
|
*
|
|
100
142
|
* @param value - The option the caller passed
|
|
101
143
|
* @returns The tenancy object, or `undefined`
|