okmodel 0.1.1 → 0.3.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 +727 -37
- 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/enum.d.ts +31 -4
- package/dist/contracts/catalog/extension.d.ts +61 -0
- package/dist/contracts/catalog/object.d.ts +1 -0
- package/dist/contracts/catalog/privilege.d.ts +64 -0
- package/dist/contracts/catalog/routine.d.ts +56 -0
- package/dist/contracts/catalog/types.d.ts +179 -18
- package/dist/contracts/catalog/view.d.ts +73 -0
- 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 +129 -10
- package/dist/dialects/pg/compile.d.ts +1 -0
- package/dist/dialects/pg/custom.d.ts +6 -0
- package/dist/dialects/pg/ddl.d.ts +65 -1
- package/dist/dialects/pg/enum.d.ts +10 -8
- package/dist/dialects/pg/ext/citext.d.ts +14 -0
- package/dist/dialects/pg/ext/citext.js +11 -0
- package/dist/dialects/pg/ext/index.d.ts +52 -0
- package/dist/dialects/pg/ext/index.js +6 -0
- package/dist/dialects/pg/ext/pg-trgm.d.ts +53 -0
- package/dist/dialects/pg/ext/pg-trgm.js +42 -0
- package/dist/dialects/pg/filter-parse.d.ts +19 -0
- package/dist/dialects/pg/filters.d.ts +19 -0
- package/dist/dialects/pg/fn/index.d.ts +107 -0
- package/dist/dialects/pg/fn/index.js +175 -0
- package/dist/dialects/pg/fn/touch.d.ts +14 -0
- package/dist/dialects/pg/index.d.ts +11 -2
- package/dist/dialects/pg/index.js +243 -1062
- package/dist/dialects/pg/introspect.d.ts +10 -1
- 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 +46 -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/role/check.d.ts +45 -0
- package/dist/dialects/pg/role/index.d.ts +50 -0
- package/dist/dialects/pg/role/sql.d.ts +44 -0
- package/dist/dialects/pg/schema.d.ts +109 -5
- package/dist/dialects/pg/table.d.ts +137 -11
- package/dist/dialects/pg/temporal.d.ts +9 -7
- package/dist/dialects/pg/tenancy.d.ts +103 -0
- package/dist/dialects/pg/through.d.ts +21 -0
- package/dist/dialects/pg/trait.d.ts +141 -0
- package/dist/dialects/pg/view/client.d.ts +30 -0
- package/dist/dialects/pg/view/depend.d.ts +35 -0
- package/dist/dialects/pg/view/index.d.ts +114 -0
- package/dist/dialects/pg/view/index.js +289 -0
- package/dist/dialects/pg/view/scratch.d.ts +21 -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 +368 -0
- package/dist/runtime/trait-read.d.ts +30 -0
- package/dist/runtime/traits/index.d.ts +133 -0
- package/dist/runtime/traits/index.js +646 -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/01yr20s5.js +149 -0
- package/dist/shared/0jc3ffzf.js +154 -0
- package/dist/shared/0v1g424p.js +26 -0
- package/dist/shared/1g0drakv.js +225 -0
- package/dist/shared/{kprcwaha.js → 1tfdfvhh.js} +5 -3
- package/dist/shared/{05w44d8g.js → 2ssqrv66.js} +767 -715
- package/dist/shared/3ekj9x92.js +210 -0
- package/dist/shared/49ypnfwt.js +1122 -0
- package/dist/shared/4e4c6vq2.js +62 -0
- package/dist/shared/4m9fn52z.js +70 -0
- package/dist/shared/{ycwz42az.js → 52szzakm.js} +6 -26
- package/dist/shared/5nmdenb6.js +1229 -0
- package/dist/shared/672t5vym.js +12 -0
- package/dist/shared/6bazvqwm.js +86 -0
- package/dist/shared/6w5j844a.js +201 -0
- package/dist/shared/{fgqgsb5z.js → 75xkjv0t.js} +2 -2
- package/dist/shared/7fvtrkwr.js +84 -0
- package/dist/shared/7m88x3e9.js +45 -0
- package/dist/shared/{mtkwv8wx.js → 7p2wbz7f.js} +1 -1
- package/dist/shared/83eaefwr.js +10 -0
- package/dist/shared/94ez8kzh.js +19 -0
- package/dist/shared/96ps4g1z.js +32 -0
- package/dist/shared/{xqbhg6cn.js → 999ade2q.js} +95 -10
- package/dist/shared/9m80mkac.js +158 -0
- package/dist/shared/9x25fxhc.js +150 -0
- package/dist/shared/a5sxz52y.js +13 -0
- package/dist/shared/axhk06q1.js +156 -0
- package/dist/shared/{dynq16vb.js → b066g80h.js} +8 -6
- package/dist/shared/bqha5cg6.js +229 -0
- package/dist/shared/bryqk9k9.js +31 -0
- package/dist/shared/c8aghh05.js +442 -0
- package/dist/shared/c9z5g0fm.js +309 -0
- package/dist/shared/{m3ypagh5.js → dbjej1tw.js} +124 -15
- package/dist/shared/dyj86cmj.js +69 -0
- package/dist/shared/e6wg00wd.js +164 -0
- package/dist/shared/{hadrfb9h.js → edwqqryd.js} +17 -14
- package/dist/shared/{qk3hxfja.js → fptpmvxp.js} +5 -5
- package/dist/shared/fs0ex00p.js +76 -0
- package/dist/shared/{jjb7yht9.js → g4f5kcx9.js} +3 -3
- package/dist/shared/gjthds9j.js +48 -0
- package/dist/shared/hcmdtwgh.js +102 -0
- package/dist/shared/{g5fhqmwe.js → jkc6ws1p.js} +6 -56
- package/dist/shared/{yd1kzwn2.js → jns2wx4t.js} +55 -12
- package/dist/shared/k34e0xf2.js +450 -0
- package/dist/shared/k3ted12y.js +33 -0
- package/dist/shared/k7dwkhvq.js +31 -0
- package/dist/shared/{8b04d28c.js → kgnc8grt.js} +2 -2
- package/dist/shared/{hd293j9g.js → kyxb62mc.js} +14 -2
- package/dist/shared/m78s7898.js +376 -0
- package/dist/shared/m9tv7xn7.js +404 -0
- package/dist/shared/meck53jv.js +99 -0
- package/dist/shared/mt5wswjz.js +90 -0
- package/dist/shared/n0dgs0pb.js +75 -0
- package/dist/shared/n442h54c.js +14 -0
- package/dist/shared/n4jqhpqz.js +27 -0
- package/dist/shared/n7mcc1gk.js +132 -0
- package/dist/shared/ne02ng5c.js +68 -0
- package/dist/shared/{mkjmqjv4.js → nfzc5z0w.js} +2 -104
- package/dist/shared/nsva2a6b.js +42 -0
- package/dist/shared/p24x2334.js +195 -0
- package/dist/shared/qbxzvwwc.js +88 -0
- package/dist/shared/{w8samvk1.js → qybh48nd.js} +1 -1
- package/dist/shared/r6nwkxnt.js +86 -0
- package/dist/shared/{xy79j5hq.js → rrstp3kb.js} +25 -36
- package/dist/shared/rwmrejjz.js +26 -0
- package/dist/shared/{zhc5vmgf.js → s6gqfn5j.js} +2 -2
- package/dist/shared/{523ft3e8.js → scwxrpx2.js} +7 -5
- package/dist/shared/{j5cn2963.js → t4tbsy9h.js} +13 -64
- package/dist/shared/{y9m15dfv.js → t616ynfn.js} +544 -32
- package/dist/shared/{ngk8gj61.js → tbszx8mz.js} +15 -1
- package/dist/shared/th14ygv2.js +69 -0
- package/dist/shared/tmbdywx0.js +178 -0
- package/dist/shared/ty3v3hfk.js +64 -0
- package/dist/shared/wekze34d.js +246 -0
- package/dist/shared/x6wysh83.js +1132 -0
- package/dist/shared/{rgs0st28.js → xrfnq5k8.js} +237 -434
- package/dist/shared/{x5x59srr.js → xva8v7qk.js} +416 -83
- package/dist/shared/{dkn3y60a.js → xw1d69vd.js} +76 -112
- package/dist/shared/y005b761.js +112 -0
- package/dist/shared/ydaz1sv3.js +55 -0
- package/dist/shared/{p0cbr3g2.js → zwmqxb0g.js} +1 -1
- package/dist/tooling/cli.js +40 -12
- package/dist/tooling/migrate/apply.d.ts +16 -0
- package/dist/tooling/migrate/commands.d.ts +12 -1
- package/dist/tooling/migrate/config.d.ts +8 -0
- package/dist/tooling/migrate/doctor.d.ts +25 -0
- package/dist/tooling/migrate/drift.d.ts +19 -0
- package/dist/tooling/migrate/engine.d.ts +36 -0
- package/dist/tooling/migrate/ext.d.ts +17 -0
- package/dist/tooling/migrate/extensions.d.ts +51 -0
- package/dist/tooling/migrate/managed.d.ts +17 -0
- package/dist/tooling/migrate/plan.d.ts +14 -1
- package/dist/tooling/migrate/project.d.ts +25 -1
- package/dist/tooling/migrate/type-name.d.ts +19 -0
- package/package.json +61 -4
- package/dist/shared/gk7cs7sp.js +0 -566
|
@@ -86,21 +86,23 @@ export declare function encodeTimeZone(value: TimeWithOffset, precision?: TimePr
|
|
|
86
86
|
/**
|
|
87
87
|
* Decodes a time with offset.
|
|
88
88
|
*
|
|
89
|
-
* @param wire - Time text plus an offset
|
|
90
|
-
* @returns Time and offset
|
|
89
|
+
* @param wire - Time text plus an offset, `±HH` as Postgres sends it or `±HH:MM`
|
|
90
|
+
* @returns Time and offset, the offset as `±HH:MM`
|
|
91
91
|
*/
|
|
92
92
|
export declare function decodeTimeZone(wire: string): TimeWithOffset;
|
|
93
93
|
/**
|
|
94
94
|
* Encodes a duration as an ISO-8601 duration.
|
|
95
95
|
*
|
|
96
96
|
* @param value - Duration
|
|
97
|
-
* @returns ISO-8601 text Postgres accepts for interval
|
|
97
|
+
* @returns ISO-8601 text Postgres accepts for interval, with a sign on each field when negative
|
|
98
98
|
*/
|
|
99
99
|
export declare function encodeDuration(value: Temporal.Duration): string;
|
|
100
100
|
/**
|
|
101
|
-
* Decodes an
|
|
101
|
+
* Decodes an interval as Postgres sends it: `1 year 2 mons 3 days 04:05:06.5`,
|
|
102
|
+
* `01:30:00`, or an ISO-8601 duration. A part may carry a sign. Parts of
|
|
103
|
+
* different signs (`1 day -01:00:00`) cannot be one `Temporal.Duration`.
|
|
102
104
|
*
|
|
103
|
-
* @param wire -
|
|
105
|
+
* @param wire - Interval text
|
|
104
106
|
* @returns A duration
|
|
105
107
|
*/
|
|
106
108
|
export declare function decodeDuration(wire: string): Temporal.Duration;
|
|
@@ -202,10 +204,10 @@ declare global {
|
|
|
202
204
|
};
|
|
203
205
|
readonly Duration: {
|
|
204
206
|
/**
|
|
205
|
-
* @param item - ISO-8601 duration
|
|
207
|
+
* @param item - ISO-8601 duration, or numeric fields
|
|
206
208
|
* @returns A duration
|
|
207
209
|
*/
|
|
208
|
-
from(item: string): Temporal.Duration;
|
|
210
|
+
from(item: string | Readonly<Record<string, number>>): Temporal.Duration;
|
|
209
211
|
};
|
|
210
212
|
};
|
|
211
213
|
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The tenancy object `schema()` calls once.
|
|
3
|
+
*
|
|
4
|
+
* The methods live on the value `columnTenancy()` returns from `okmodel/tenancy`.
|
|
5
|
+
* This file only names them. An application that never imports that subpath
|
|
6
|
+
* does not load them.
|
|
7
|
+
*/
|
|
8
|
+
import type { ColumnBuilder, FlagTrue, PlainFlags } from "./column.js";
|
|
9
|
+
import type { SchemaHookCtx } from "./model.js";
|
|
10
|
+
import type { AnyTable } from "./table.js";
|
|
11
|
+
/**
|
|
12
|
+
* A guarded uuid column, one per tenant table.
|
|
13
|
+
*
|
|
14
|
+
* Insert and update omit it. The client fills it from the scope.
|
|
15
|
+
*/
|
|
16
|
+
export type TenantFields<Key extends string> = {
|
|
17
|
+
readonly [K in Key]: ColumnBuilder<string, FlagTrue<PlainFlags, "guarded">>;
|
|
18
|
+
};
|
|
19
|
+
/** One tenant value, or a reason for leaving the scope. The value is not a cache key. */
|
|
20
|
+
export type TenantCall = {
|
|
21
|
+
readonly value: string;
|
|
22
|
+
} | {
|
|
23
|
+
readonly unscoped: string;
|
|
24
|
+
};
|
|
25
|
+
/** Text the scope predicate writes. The planner's sink has these methods. */
|
|
26
|
+
export type TenancyText = {
|
|
27
|
+
text(value: string): void;
|
|
28
|
+
param(encoded: string): void;
|
|
29
|
+
mark(token: string): void;
|
|
30
|
+
};
|
|
31
|
+
/** `for()` and `unscoped()` plus the table names the root client keeps. */
|
|
32
|
+
export type TenancyClient = {
|
|
33
|
+
readonly names: readonly string[];
|
|
34
|
+
readonly for?: (input: unknown) => unknown;
|
|
35
|
+
readonly unscoped?: (reason: string) => unknown;
|
|
36
|
+
};
|
|
37
|
+
/** One inspect rule the tenancy object recorded. */
|
|
38
|
+
export type TenancyRule = {
|
|
39
|
+
readonly rule: string;
|
|
40
|
+
readonly contribution: string;
|
|
41
|
+
readonly provenance: string;
|
|
42
|
+
readonly source?: string;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Column tenancy passed to `schema({ tenancy })`.
|
|
46
|
+
*
|
|
47
|
+
* `columnTenancy()` from `okmodel/tenancy` builds it. `rewrite` runs once,
|
|
48
|
+
* before compile. The other methods are the planner and the client.
|
|
49
|
+
*/
|
|
50
|
+
export type ColumnTenancy = {
|
|
51
|
+
readonly key: string;
|
|
52
|
+
readonly type: "uuid";
|
|
53
|
+
readonly strategy: "column";
|
|
54
|
+
/** Tables with the tenant column, widened uniques, and composite references. */
|
|
55
|
+
rewrite(tables: readonly AnyTable[]): readonly AnyTable[];
|
|
56
|
+
/** The guarded uuid column, for emitted row types. */
|
|
57
|
+
column(): object;
|
|
58
|
+
predicate(input: {
|
|
59
|
+
readonly table: string;
|
|
60
|
+
readonly fieldSql: (field: string) => string | undefined;
|
|
61
|
+
readonly encode: ((value: unknown) => string) | undefined;
|
|
62
|
+
readonly alias: string;
|
|
63
|
+
readonly appended: boolean;
|
|
64
|
+
readonly scope: TenantCall | undefined;
|
|
65
|
+
readonly sink: TenancyText;
|
|
66
|
+
}): boolean;
|
|
67
|
+
guard(table: string, field: string, kind: "where" | "insert" | "update"): void;
|
|
68
|
+
stamp(table: string, rows: Record<string, unknown>[], scope: TenantCall | undefined): void;
|
|
69
|
+
client(input: {
|
|
70
|
+
readonly names: readonly string[];
|
|
71
|
+
readonly scoped: boolean;
|
|
72
|
+
readonly open: (scope: TenantCall) => unknown;
|
|
73
|
+
}): TenancyClient;
|
|
74
|
+
rules(table: string, source: string | undefined, scope: TenantCall | undefined): readonly TenancyRule[];
|
|
75
|
+
/**
|
|
76
|
+
* Attaches `for()` and `unscoped()` on the root client.
|
|
77
|
+
*
|
|
78
|
+
* The same hook archivable uses for its table methods.
|
|
79
|
+
*
|
|
80
|
+
* @param target - The client object
|
|
81
|
+
* @param ctx - Names, scope, and the table map
|
|
82
|
+
*/
|
|
83
|
+
hook(target: Record<string, unknown>, ctx: SchemaHookCtx): void;
|
|
84
|
+
/**
|
|
85
|
+
* Treats a view that exposes the tenant key as tenant-scoped.
|
|
86
|
+
*
|
|
87
|
+
* The predicate then applies to reads of that view. A view that does not
|
|
88
|
+
* expose the key is refused earlier (OKM1820) unless it is `global`.
|
|
89
|
+
*
|
|
90
|
+
* @param name - Client name of the view
|
|
91
|
+
*/
|
|
92
|
+
scopeView(name: string): void;
|
|
93
|
+
missing(table: string): never;
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Reads `schema({ tenancy })`.
|
|
97
|
+
*
|
|
98
|
+
* Omitted stays `undefined`. Anything else must be `columnTenancy()`.
|
|
99
|
+
*
|
|
100
|
+
* @param value - The option the caller passed
|
|
101
|
+
* @returns The tenancy object, or `undefined`
|
|
102
|
+
*/
|
|
103
|
+
export declare function readTenancy(value: unknown): ColumnTenancy | undefined;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolver and emitter of a `manyThrough` relation.
|
|
3
|
+
*
|
|
4
|
+
* The relation object carries both. `schema()` calls the resolver, and the
|
|
5
|
+
* planner calls the emitter with its own helpers, so a schema that has no
|
|
6
|
+
* `manyThrough` ships none of this. A join row or target in another tenant or
|
|
7
|
+
* archived never shows: the same planner predicates apply to both tables.
|
|
8
|
+
*/
|
|
9
|
+
import type { RelationScope } from "./relations.js";
|
|
10
|
+
import type { RelationModel } from "./model.js";
|
|
11
|
+
/**
|
|
12
|
+
* Resolves a `manyThrough` declaration against the schema's foreign keys.
|
|
13
|
+
*
|
|
14
|
+
* @param scope - What `schema()` knows
|
|
15
|
+
* @param table - Related table name
|
|
16
|
+
* @param through - Join table name
|
|
17
|
+
* @param from - Join table field that references the declaring table, when ambiguous
|
|
18
|
+
* @param to - Join table field that references the related table, when ambiguous
|
|
19
|
+
* @returns The resolved relation, carrying its emitter
|
|
20
|
+
*/
|
|
21
|
+
export declare function resolveThrough(scope: RelationScope, table: string, through: string, from: string | undefined, to: string | undefined): RelationModel;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trait values `schema()` applies.
|
|
3
|
+
*
|
|
4
|
+
* The timestamp columns and their clock live in `okmodel/traits`. This module
|
|
5
|
+
* only reads the object a schema passes in, so an application that never
|
|
6
|
+
* imports a trait does not load that code.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Columns an archivable trait asks `schema()` to keep.
|
|
10
|
+
*
|
|
11
|
+
* `at` and `id` are field names. `cascade` names child tables archived and
|
|
12
|
+
* restored with the row. The trait's rewrite makes uniques partial and checks
|
|
13
|
+
* the cascade. Absent means the table is not archivable.
|
|
14
|
+
*/
|
|
15
|
+
export type ArchiveRequest = {
|
|
16
|
+
readonly at: string;
|
|
17
|
+
readonly id: string;
|
|
18
|
+
readonly cascade: readonly string[];
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Columns `schema()` passes to {@link Trait.apply}.
|
|
22
|
+
*
|
|
23
|
+
* `columns` starts as the table's own fields. `apply` adds the trait's fields
|
|
24
|
+
* or throws OKM1012 when a name is already there. `archive` is set by
|
|
25
|
+
* `archivable()` and read once, after every trait has applied.
|
|
26
|
+
*/
|
|
27
|
+
export type TraitModel = {
|
|
28
|
+
columns: Record<string, object>;
|
|
29
|
+
archive?: ArchiveRequest;
|
|
30
|
+
/**
|
|
31
|
+
* Presets collected so far: the table's own first, then each trait's.
|
|
32
|
+
*
|
|
33
|
+
* Starts as the table's own object. A trait copies it before adding, so the
|
|
34
|
+
* author's object is never changed.
|
|
35
|
+
*/
|
|
36
|
+
presets?: Readonly<Record<string, unknown>> | undefined;
|
|
37
|
+
/** Trait that added each preset. A name missing here is the table's own. */
|
|
38
|
+
presetFrom?: Record<string, string>;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* The table `apply` is adding columns to.
|
|
42
|
+
*/
|
|
43
|
+
export type TraitContext = {
|
|
44
|
+
readonly table: string;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Columns and write rules a trait contributes.
|
|
48
|
+
*
|
|
49
|
+
* `fields` are real columns. `touch` columns are set to `now()` on update.
|
|
50
|
+
* `sealed` columns cannot be set from input, including `{ allow }`.
|
|
51
|
+
* A touched column is sealed. `apply` is the trait's own merge. `schema()`
|
|
52
|
+
* only calls it.
|
|
53
|
+
*/
|
|
54
|
+
export type Trait = {
|
|
55
|
+
readonly name: string;
|
|
56
|
+
readonly fields: Readonly<Record<string, object>>;
|
|
57
|
+
readonly touch?: readonly string[];
|
|
58
|
+
readonly sealed?: readonly string[];
|
|
59
|
+
/** Presets the trait adds to every table it applies to. */
|
|
60
|
+
readonly presets?: Readonly<Record<string, unknown>>;
|
|
61
|
+
/**
|
|
62
|
+
* Adds this trait's columns to one table.
|
|
63
|
+
*
|
|
64
|
+
* @param model - Columns collected so far
|
|
65
|
+
* @param ctx - Table name, for OKM1012
|
|
66
|
+
*/
|
|
67
|
+
apply(model: TraitModel, ctx: TraitContext): void;
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Field maps of every trait in a list, as one object.
|
|
71
|
+
*
|
|
72
|
+
* An empty list contributes no fields. The field types stay on the value
|
|
73
|
+
* `trait()` returned; this reads them back.
|
|
74
|
+
*
|
|
75
|
+
* @typeParam TTraits - Trait list
|
|
76
|
+
*/
|
|
77
|
+
export type FieldsOfList<TTraits> = TTraits extends readonly [] ? Record<never, never> : TTraits extends readonly (infer TItem)[] ? UnionToIntersection<TItem extends {
|
|
78
|
+
readonly fields: infer TFields;
|
|
79
|
+
} ? TFields : Record<never, never>> : Record<never, never>;
|
|
80
|
+
/**
|
|
81
|
+
* `{ "~archive": true }` when a trait list includes `archivable()`.
|
|
82
|
+
*
|
|
83
|
+
* An empty match contributes `unknown`, so a table without the trait does
|
|
84
|
+
* not gain the key.
|
|
85
|
+
*
|
|
86
|
+
* @typeParam TTraits - Trait list, or a single trait object
|
|
87
|
+
*/
|
|
88
|
+
export type HasArchive<TTraits> = [
|
|
89
|
+
Extract<TTraits extends readonly (infer TItem)[] ? TItem : TTraits, {
|
|
90
|
+
readonly "~archive": true;
|
|
91
|
+
}>
|
|
92
|
+
] extends [never] ? unknown : {
|
|
93
|
+
readonly "~archive": true;
|
|
94
|
+
};
|
|
95
|
+
/** The `presets` maps of a trait list, as a union. Empty when no trait has any. */
|
|
96
|
+
type TraitPresetUnion<TTraits> = TTraits extends readonly (infer TItem)[] ? TItem extends {
|
|
97
|
+
readonly presets: infer TPresets;
|
|
98
|
+
} ? TPresets : never : never;
|
|
99
|
+
/**
|
|
100
|
+
* `{ "~presets": ... }` when a trait list adds presets, joined into one map.
|
|
101
|
+
*
|
|
102
|
+
* Nothing is added otherwise, so a table without trait presets keeps its type.
|
|
103
|
+
*
|
|
104
|
+
* @typeParam TTraits - Trait list
|
|
105
|
+
*/
|
|
106
|
+
export type PresetsOfList<TTraits> = [TraitPresetUnion<TTraits>] extends [never] ? unknown : {
|
|
107
|
+
readonly "~presets": UnionToIntersection<TraitPresetUnion<TTraits>>;
|
|
108
|
+
};
|
|
109
|
+
type UnionToIntersection<TUnion> = (TUnion extends unknown ? (argument: TUnion) => void : never) extends (argument: infer TIntersection) => void ? TIntersection : never;
|
|
110
|
+
/** A trait object before `trait()` attaches `apply`. */
|
|
111
|
+
type CheckedTrait = {
|
|
112
|
+
readonly name: string;
|
|
113
|
+
readonly fields: Readonly<Record<string, object>>;
|
|
114
|
+
readonly touch?: readonly string[];
|
|
115
|
+
readonly sealed?: readonly string[];
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Checks one trait object.
|
|
119
|
+
*
|
|
120
|
+
* `methods` and `requires` are part of the type and rejected until the
|
|
121
|
+
* prompt that implements them.
|
|
122
|
+
*
|
|
123
|
+
* @param value - One entry of a traits list
|
|
124
|
+
* @param where - `schema()` or the table name, for the error
|
|
125
|
+
* @returns The same object when it is a trait
|
|
126
|
+
*/
|
|
127
|
+
export declare function checkTrait(value: unknown, where: string): CheckedTrait;
|
|
128
|
+
/**
|
|
129
|
+
* Trait field builders that apply to one table, in catalog order.
|
|
130
|
+
*
|
|
131
|
+
* `emitRowTypes` uses this. `schema()` has already rejected a conflict.
|
|
132
|
+
*
|
|
133
|
+
* @param schemaTraits - Traits stored on the built schema
|
|
134
|
+
* @param options - This table's `traits` and `omitDefaults`
|
|
135
|
+
* @returns Field name and builder pairs. Empty when the table has no traits
|
|
136
|
+
*/
|
|
137
|
+
export declare function contributedFields(schemaTraits: readonly Trait[] | undefined, options: {
|
|
138
|
+
readonly traits?: readonly Trait[];
|
|
139
|
+
readonly omitDefaults?: string;
|
|
140
|
+
} | undefined): readonly (readonly [string, object])[];
|
|
141
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read model and client hook for a declared view.
|
|
3
|
+
*
|
|
4
|
+
* `schema()` calls `install` and the client calls `hook`. Neither path is
|
|
5
|
+
* imported by a featureless app. Writes are not copied onto the handle.
|
|
6
|
+
*/
|
|
7
|
+
import type { ColumnTenancy } from "../tenancy.js";
|
|
8
|
+
import type { SchemaHook, TableModel } from "../model.js";
|
|
9
|
+
import { type AnyTable } from "../table.js";
|
|
10
|
+
/** What `schema()` passes when it binds a view. */
|
|
11
|
+
export type ViewInstall = (model: {
|
|
12
|
+
[name: string]: TableModel;
|
|
13
|
+
}, tenancy: ColumnTenancy | undefined, tables: readonly AnyTable[], casing: "snake" | undefined, scoped: Set<string>) => void;
|
|
14
|
+
/**
|
|
15
|
+
* Client name, read model, and the hook that moves the handle under `views`.
|
|
16
|
+
*
|
|
17
|
+
* @param name - SQL name of the view
|
|
18
|
+
* @param columns - Declared output columns
|
|
19
|
+
* @param query - Author SQL
|
|
20
|
+
* @param tenancy - `global("reason")`, when the view opts out
|
|
21
|
+
* @returns Methods stored on the declaration
|
|
22
|
+
*/
|
|
23
|
+
export declare function viewClient(name: string, columns: readonly {
|
|
24
|
+
readonly name: string;
|
|
25
|
+
readonly type: string;
|
|
26
|
+
}[], query: string, tenancy: unknown): {
|
|
27
|
+
readonly field: string;
|
|
28
|
+
readonly install: ViewInstall;
|
|
29
|
+
readonly hook: SchemaHook;
|
|
30
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Column dependencies of a view, read from `pg_depend`.
|
|
3
|
+
*
|
|
4
|
+
* Postgres records them on the view's rewrite rule. The edge is column
|
|
5
|
+
* granularity when that column is a catalog object.
|
|
6
|
+
*/
|
|
7
|
+
import type { CatalogObject, Namespace, ObjectIdentity } from "../../../contracts/catalog/types.js";
|
|
8
|
+
/**
|
|
9
|
+
* Reads a query cell as text.
|
|
10
|
+
*
|
|
11
|
+
* @param value - A driver cell
|
|
12
|
+
* @returns The string, or empty when the cell is not a scalar
|
|
13
|
+
*/
|
|
14
|
+
export declare function cellText(value: unknown): string;
|
|
15
|
+
/**
|
|
16
|
+
* `pg_depend` rows for views and materialized views in one schema.
|
|
17
|
+
*
|
|
18
|
+
* `$1` is the concrete schema name. `refobjsubid > 0` keeps column edges.
|
|
19
|
+
*/
|
|
20
|
+
export declare const VIEW_DEPENDENCIES = "\n select v.relname as view, t.relname as table, a.attname as column\n from pg_depend d\n join pg_rewrite r on r.oid = d.objid and d.classid = 'pg_rewrite'::regclass\n join pg_class v on v.oid = r.ev_class\n join pg_class t on t.oid = d.refobjid and d.refclassid = 'pg_class'::regclass\n join pg_attribute a on a.attrelid = t.oid and a.attnum = d.refobjsubid\n join pg_namespace n on n.oid = v.relnamespace\n where n.nspname = $1\n and v.relkind in ('v', 'm')\n and d.refobjsubid > 0\n and v.oid <> t.oid\n and t.relkind in ('r', 'p', 'v', 'm')\n";
|
|
21
|
+
/**
|
|
22
|
+
* Turns dependency rows into edges that exist in `objects`.
|
|
23
|
+
*
|
|
24
|
+
* A table column becomes a column edge. A view that is itself a catalog
|
|
25
|
+
* object becomes an object edge. Anything else is omitted: the catalog
|
|
26
|
+
* refuses an edge whose target is missing.
|
|
27
|
+
*
|
|
28
|
+
* @param rows - Rows from {@link VIEW_DEPENDENCIES}
|
|
29
|
+
* @param namespace - Logical namespace stored on the edges
|
|
30
|
+
* @param objects - Catalog the edges must point into
|
|
31
|
+
* @returns Edges keyed by view name
|
|
32
|
+
*/
|
|
33
|
+
export declare function viewDependencyEdges(rows: readonly Readonly<Record<string, unknown>>[], namespace: Namespace, objects: readonly CatalogObject[]): Map<string, ObjectIdentity[]>;
|
|
34
|
+
/** Logical public namespace. Tests and the default schema use it. */
|
|
35
|
+
export declare const PUBLIC: Namespace;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `okmodel/view`.
|
|
3
|
+
*
|
|
4
|
+
* `view()` and `materializedView()` return objects that produce their own
|
|
5
|
+
* catalog records. `schema()` only asks each declared object for those records.
|
|
6
|
+
* DDL, diffing, and scratch verification stay out of this module's callers
|
|
7
|
+
* until a plan or a check loads them.
|
|
8
|
+
*/
|
|
9
|
+
import type { CatalogObject } from "../../../contracts/catalog/types.js";
|
|
10
|
+
import type { SchemaHook } from "../model.js";
|
|
11
|
+
import type { SqlText } from "../table.js";
|
|
12
|
+
import { type ViewInstall } from "./client.js";
|
|
13
|
+
/** One declared output column. `type` is the Postgres type name. */
|
|
14
|
+
export type ViewColumnInput = {
|
|
15
|
+
readonly name: string;
|
|
16
|
+
readonly type: string;
|
|
17
|
+
};
|
|
18
|
+
/** Options for {@link view}. */
|
|
19
|
+
export type ViewOptions = {
|
|
20
|
+
readonly columns: readonly ViewColumnInput[];
|
|
21
|
+
readonly query: SqlText | string;
|
|
22
|
+
/** Schema. The default is `public`. */
|
|
23
|
+
readonly schema?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Opts the view out of tenancy.
|
|
26
|
+
*
|
|
27
|
+
* A view that reads a tenant table and does not expose the tenant key is
|
|
28
|
+
* OKM1820 unless this is `global("reason")`.
|
|
29
|
+
*/
|
|
30
|
+
readonly tenancy?: unknown;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* One declared view.
|
|
34
|
+
*
|
|
35
|
+
* `contribute` builds the catalog record. Column dependencies are filled
|
|
36
|
+
* from `pg_depend` by scratch verification, not at this call.
|
|
37
|
+
*/
|
|
38
|
+
export type ViewDeclaration = {
|
|
39
|
+
readonly name: string;
|
|
40
|
+
readonly schema: string;
|
|
41
|
+
/**
|
|
42
|
+
* Catalog record for this declaration.
|
|
43
|
+
*
|
|
44
|
+
* @param peers - The `schema({ views })` list
|
|
45
|
+
* @param built - Objects the schema has already staged
|
|
46
|
+
* @returns The view record
|
|
47
|
+
*/
|
|
48
|
+
contribute(peers: unknown, built: unknown): readonly CatalogObject[];
|
|
49
|
+
/** Publishes the read model. `schema()` calls it. */
|
|
50
|
+
install: ViewInstall;
|
|
51
|
+
/** Moves the read handle under `db.views`. */
|
|
52
|
+
hook: SchemaHook;
|
|
53
|
+
};
|
|
54
|
+
/** One index owned by a materialized view. */
|
|
55
|
+
export type MaterializedViewIndexInput = {
|
|
56
|
+
readonly name?: string;
|
|
57
|
+
readonly columns: readonly string[];
|
|
58
|
+
readonly unique?: boolean;
|
|
59
|
+
};
|
|
60
|
+
/** Options for {@link materializedView}. */
|
|
61
|
+
export type MaterializedViewOptions = ViewOptions & {
|
|
62
|
+
readonly indexes?: readonly MaterializedViewIndexInput[];
|
|
63
|
+
/**
|
|
64
|
+
* Populate mode.
|
|
65
|
+
*
|
|
66
|
+
* `"concurrently"` plans `REFRESH MATERIALIZED VIEW CONCURRENTLY` and
|
|
67
|
+
* requires a unique index (OKM1822). Omitted still populates, without
|
|
68
|
+
* `CONCURRENTLY`.
|
|
69
|
+
*/
|
|
70
|
+
readonly refresh?: "concurrently";
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* One declared materialized view.
|
|
74
|
+
*
|
|
75
|
+
* Identity is `(namespace, name)`. Indexes are separate catalog objects.
|
|
76
|
+
*/
|
|
77
|
+
export type MaterializedViewDeclaration = {
|
|
78
|
+
readonly name: string;
|
|
79
|
+
readonly schema: string;
|
|
80
|
+
/**
|
|
81
|
+
* Catalog records for this declaration.
|
|
82
|
+
*
|
|
83
|
+
* @param peers - The `schema({ views })` list
|
|
84
|
+
* @param built - Objects the schema has already staged
|
|
85
|
+
* @returns The materialized view and its indexes
|
|
86
|
+
*/
|
|
87
|
+
contribute(peers: unknown, built: unknown): readonly CatalogObject[];
|
|
88
|
+
/** Publishes the read model. `schema()` calls it. */
|
|
89
|
+
install: ViewInstall;
|
|
90
|
+
/** Moves the read handle under `db.views`. */
|
|
91
|
+
hook: SchemaHook;
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* Declares a view as SQL with output columns.
|
|
95
|
+
*
|
|
96
|
+
* The query is stored as written. A scratch database reads `pg_depend` and
|
|
97
|
+
* `pg_get_viewdef` before a plan treats the body as canonical.
|
|
98
|
+
*
|
|
99
|
+
* @param name - View name
|
|
100
|
+
* @param options - Columns and query
|
|
101
|
+
* @returns The definition object `schema({ views })` stores
|
|
102
|
+
*/
|
|
103
|
+
export declare function view(name: string, options: ViewOptions): ViewDeclaration;
|
|
104
|
+
/**
|
|
105
|
+
* Declares a materialized view.
|
|
106
|
+
*
|
|
107
|
+
* Creation is `WITH NO DATA`. Populate is a later plan step. `refresh:
|
|
108
|
+
* "concurrently"` without a unique index is OKM1822.
|
|
109
|
+
*
|
|
110
|
+
* @param name - Materialized view name
|
|
111
|
+
* @param options - Columns, query, indexes, and refresh mode
|
|
112
|
+
* @returns The definition object `schema({ views })` stores
|
|
113
|
+
*/
|
|
114
|
+
export declare function materializedView(name: string, options: MaterializedViewOptions): MaterializedViewDeclaration;
|