okmodel 0.2.1 → 0.4.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 +882 -48
- package/dist/contracts/catalog/document.d.ts +6 -2
- package/dist/contracts/catalog/enum.d.ts +31 -4
- package/dist/contracts/catalog/extension.d.ts +61 -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 +164 -10
- package/dist/contracts/catalog/view.d.ts +73 -0
- package/dist/dialects/pg/column.d.ts +3 -1
- 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/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.js +104 -19
- package/dist/dialects/pg/introspect.d.ts +10 -1
- package/dist/dialects/pg/operators.d.ts +8 -1
- 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 +51 -0
- package/dist/dialects/pg/table.d.ts +24 -1
- package/dist/dialects/pg/tenancy.d.ts +9 -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 +22 -0
- package/dist/dialects/pg/where.d.ts +2 -2
- package/dist/runtime/catalog-cache.d.ts +17 -0
- package/dist/runtime/compat-words.d.ts +23 -0
- package/dist/runtime/drift-detail.d.ts +20 -4
- package/dist/runtime/drift.d.ts +4 -2
- package/dist/runtime/pg/bun.js +3 -3
- package/dist/runtime/pg/pg.js +3 -3
- package/dist/runtime/pg/pglite.js +3 -3
- package/dist/runtime/pg/postgresjs.js +3 -3
- package/dist/runtime/tenancy/index.js +6 -3
- package/dist/runtime/traits/index.d.ts +7 -2
- package/dist/runtime/traits/index.js +151 -13
- package/dist/runtime/types.d.ts +2 -0
- package/dist/runtime/validate/index.js +4 -4
- package/dist/shared/{xkz8g6by.js → 1g0drakv.js} +2 -2
- package/dist/shared/2321avmn.js +418 -0
- package/dist/shared/{7mht49yd.js → 3p4b1fg0.js} +57 -18
- package/dist/shared/41kv2xdm.js +318 -0
- package/dist/shared/{97g2jnrw.js → 4ef7mmqf.js} +3 -3
- package/dist/shared/{sacqha1y.js → 4m9fn52z.js} +2 -2
- package/dist/shared/5mtf6cj3.js +94 -0
- package/dist/shared/{1dp5knt7.js → 5vdm4sgp.js} +2 -2
- package/dist/shared/{a1gdp7j9.js → 6693j9rs.js} +1 -1
- package/dist/shared/{38crxbgn.js → 6p5k20sm.js} +3 -3
- package/dist/shared/7nk68fj8.js +751 -0
- package/dist/shared/84ptn35q.js +71 -0
- package/dist/shared/{d2whjz4k.js → 8jb4ymh2.js} +581 -28
- package/dist/shared/8ktwd3rh.js +97 -0
- package/dist/shared/94ez8kzh.js +19 -0
- package/dist/shared/{3a5ne750.js → 9m80mkac.js} +2 -2
- package/dist/shared/9x25fxhc.js +150 -0
- package/dist/shared/9yn6a2vd.js +11 -0
- package/dist/shared/ady1ms74.js +72 -0
- package/dist/shared/{4jzzghr6.js → awrsqrn7.js} +6 -6
- package/dist/shared/{4b9da9d7.js → axhk06q1.js} +19 -1
- package/dist/shared/{d04j53v8.js → c5g81ngb.js} +82 -14
- package/dist/shared/{n47rd821.js → c8aghh05.js} +1 -1
- package/dist/shared/{dd4f8mnx.js → c9z5g0fm.js} +4 -2
- package/dist/shared/{ps43134h.js → dyj86cmj.js} +4 -4
- package/dist/shared/{0qkxbm1f.js → fa9vt245.js} +1 -1
- package/dist/shared/{qa5dsc7z.js → fb00y8fp.js} +3 -3
- package/dist/shared/{qxa0yb9j.js → g7ez901n.js} +30 -1
- package/dist/shared/{py3nh7jy.js → gdh9mrtp.js} +2 -2
- package/dist/shared/{yw5c610b.js → gjthds9j.js} +2 -2
- package/dist/shared/hcmdtwgh.js +102 -0
- package/dist/shared/hqjsxnz7.js +13 -0
- package/dist/shared/htnaj77v.js +17 -0
- package/dist/shared/{v18jva5b.js → jgxzjzcz.js} +1 -1
- package/dist/shared/{x9v1qgeb.js → jsd07prz.js} +3 -3
- package/dist/shared/{g9f0zqce.js → kafaa5zv.js} +1 -1
- package/dist/shared/kj680nxv.js +19 -0
- package/dist/shared/{mxmcdsh5.js → kkzwp3d2.js} +9 -9
- package/dist/shared/{g1b5zzj9.js → n0dgs0pb.js} +1 -1
- package/dist/shared/n5y9zyj1.js +2431 -0
- package/dist/shared/{zt8y0wzb.js → n7mcc1gk.js} +1 -1
- package/dist/shared/{ge03bfca.js → nxb42q7h.js} +2 -2
- package/dist/shared/q6zsyh31.js +2192 -0
- package/dist/shared/{sfh4pk75.js → q795afwa.js} +26 -21
- package/dist/shared/{10tjenmd.js → qn0srwwq.js} +1 -1
- package/dist/shared/s4mb6a4b.js +545 -0
- package/dist/shared/{ytg3xf9p.js → sf8m6tfy.js} +3 -3
- package/dist/shared/{zd93g3rq.js → sr5ms7b3.js} +1 -1
- package/dist/shared/{xatfg0gn.js → tmbdywx0.js} +4 -19
- package/dist/shared/tny2t3sm.js +100 -0
- package/dist/shared/{e7a268fy.js → v7tpnhnz.js} +1 -1
- package/dist/shared/{ecdzej21.js → wqem4jed.js} +7 -7
- package/dist/shared/xghkt7a9.js +1144 -0
- package/dist/shared/y005b761.js +112 -0
- package/dist/shared/ycatkxmq.js +84 -0
- package/dist/shared/ygem90rn.js +900 -0
- package/dist/shared/{eaxwrgby.js → yjw02enp.js} +6 -3
- package/dist/shared/{mrq77sgw.js → zg24x0hm.js} +1 -1
- package/dist/shared/{cstgkzdx.js → zvbjc949.js} +1 -1
- package/dist/tooling/cli.js +66 -13
- package/dist/tooling/migrate/apply.d.ts +75 -5
- package/dist/tooling/migrate/backfill.d.ts +136 -0
- package/dist/tooling/migrate/check.d.ts +65 -0
- package/dist/tooling/migrate/classify.d.ts +108 -0
- package/dist/tooling/migrate/commands.d.ts +2 -1
- package/dist/tooling/migrate/config.d.ts +30 -0
- package/dist/tooling/migrate/doctor.d.ts +28 -0
- package/dist/tooling/migrate/drift.d.ts +35 -0
- package/dist/tooling/migrate/estimate.d.ts +50 -0
- package/dist/tooling/migrate/ext.d.ts +17 -0
- package/dist/tooling/migrate/extensions.d.ts +53 -0
- package/dist/tooling/migrate/files.d.ts +12 -0
- package/dist/tooling/migrate/index.d.ts +3 -2
- package/dist/tooling/migrate/index.js +67 -1
- package/dist/tooling/migrate/lint-rules.d.ts +51 -0
- package/dist/tooling/migrate/lint.d.ts +71 -0
- package/dist/tooling/migrate/managed.d.ts +17 -0
- package/dist/tooling/migrate/plan.d.ts +78 -10
- package/dist/tooling/migrate/project.d.ts +64 -5
- package/dist/tooling/migrate/provision.d.ts +18 -0
- package/dist/tooling/migrate/reference.d.ts +40 -0
- package/dist/tooling/migrate/runner.d.ts +108 -0
- package/dist/tooling/migrate/safe.d.ts +77 -0
- package/dist/tooling/migrate/seed.d.ts +20 -0
- package/dist/tooling/migrate/snapshot.d.ts +78 -0
- package/dist/tooling/migrate/status.d.ts +25 -6
- package/dist/tooling/migrate/type-name.d.ts +19 -0
- package/dist/tooling/testing/factories.d.ts +117 -0
- package/dist/tooling/testing/facts.d.ts +72 -0
- package/dist/tooling/testing/index.d.ts +89 -0
- package/dist/tooling/testing/index.js +8 -0
- package/dist/tooling/testing/isolation.d.ts +30 -0
- package/dist/tooling/testing/random.d.ts +40 -0
- package/dist/tooling/testing/record.d.ts +38 -0
- package/package.json +26 -2
- package/dist/shared/5z4q2zda.js +0 -2073
- package/dist/shared/eqmtn1bj.js +0 -399
- package/dist/shared/rtnaqre0.js +0 -37
- package/dist/shared/zwmqxb0g.js +0 -79
- package/dist/shared/{m9tv7xn7.js → radd3z4g.js} +3 -3
- /package/dist/shared/{9k6vetvf.js → rrstp3kb.js} +0 -0
|
@@ -7,6 +7,15 @@
|
|
|
7
7
|
* and `pg_get_constraintdef`, which is the database's normalised text (D128).
|
|
8
8
|
*/
|
|
9
9
|
import type { Catalog } from "../../contracts/catalog/types.js";
|
|
10
|
+
/** Which cluster roles the catalog owns. */
|
|
11
|
+
export type IntrospectOptions = {
|
|
12
|
+
/**
|
|
13
|
+
* Role names this catalog creates and alters.
|
|
14
|
+
*
|
|
15
|
+
* When omitted, roles, grants, and default privileges are not read.
|
|
16
|
+
*/
|
|
17
|
+
readonly managedRoles?: readonly string[];
|
|
18
|
+
};
|
|
10
19
|
/** A connection that can run one query. Parameters are `$1`, `$2`, … */
|
|
11
20
|
export type CatalogQuery = {
|
|
12
21
|
/**
|
|
@@ -29,7 +38,7 @@ export type CatalogQuery = {
|
|
|
29
38
|
* @param logical - Namespace stored on the catalog identities
|
|
30
39
|
* @returns A checked catalog
|
|
31
40
|
*/
|
|
32
|
-
export declare function introspectSchema(runner: CatalogQuery, concrete: string, logical?: string): Promise<Catalog>;
|
|
41
|
+
export declare function introspectSchema(runner: CatalogQuery, concrete: string, logical?: string, options?: IntrospectOptions): Promise<Catalog>;
|
|
33
42
|
/**
|
|
34
43
|
* Applies one expression as a check and reads Postgres's reprint.
|
|
35
44
|
*
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
declare const brand: unique symbol;
|
|
8
8
|
declare const RUNTIME: unique symbol;
|
|
9
9
|
/** Operator names the read path compiles. */
|
|
10
|
-
export type OperatorName = "eq" | "lt" | "lte" | "gt" | "gte" | "between" | "startsWith" | "contains" | "endsWith" | "like" | "ilike" | "inList" | "notIn" | "not" | "or" | "and" | "has" | "none" | "every" | "inc" | "containedBy" | "overlaps" | "hasKey" | "hasAnyKey" | "path" | "matches" | "json.set" | "arr.append" | "arr.remove";
|
|
10
|
+
export type OperatorName = "eq" | "lt" | "lte" | "gt" | "gte" | "between" | "startsWith" | "contains" | "endsWith" | "like" | "ilike" | "inList" | "notIn" | "not" | "or" | "and" | "has" | "none" | "every" | "inc" | "containedBy" | "overlaps" | "hasKey" | "hasAnyKey" | "path" | "matches" | "similar" | "wordSimilar" | "json.set" | "arr.append" | "arr.remove";
|
|
11
11
|
/** A tagged operator. `value` is the operand the helper stored. */
|
|
12
12
|
export type Tagged<Name extends OperatorName, V> = {
|
|
13
13
|
readonly [brand]: Name;
|
|
@@ -48,6 +48,13 @@ export type MatchValue = {
|
|
|
48
48
|
};
|
|
49
49
|
/** `@@` against a tsvector column. */
|
|
50
50
|
export type Matches = Tagged<"matches", MatchValue>;
|
|
51
|
+
/** Text stored on a `pg_trgm` operator. `schema` is the extension's install schema. */
|
|
52
|
+
export type TrigramQuery = {
|
|
53
|
+
readonly query: string;
|
|
54
|
+
readonly schema: string;
|
|
55
|
+
};
|
|
56
|
+
/** `pg_trgm` `%` or `<%`. */
|
|
57
|
+
export type Trigram<Name extends "similar" | "wordSimilar"> = Tagged<Name, TrigramQuery>;
|
|
51
58
|
/** `jsonb_set` path and the new value. */
|
|
52
59
|
export type JsonSetValue<V> = {
|
|
53
60
|
readonly path: readonly string[];
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Role checks for `okm doctor` and apply preflight.
|
|
3
|
+
*
|
|
4
|
+
* Both run before any catalog statement. `connect()` does not call them.
|
|
5
|
+
*/
|
|
6
|
+
import type { DriverPool } from "../../../contracts/driver.js";
|
|
7
|
+
import type { CatalogObject } from "../../../contracts/catalog/types.js";
|
|
8
|
+
import type { RolesInput } from "./index.js";
|
|
9
|
+
/** A pool or a reserved connection. Both can run one statement. */
|
|
10
|
+
type Runner = Pick<DriverPool, "execute">;
|
|
11
|
+
/**
|
|
12
|
+
* Checks named roles, `CREATEROLE`, and the application role's privileges.
|
|
13
|
+
*
|
|
14
|
+
* A missing external role is reported. A managed role that is absent is not:
|
|
15
|
+
* the plan creates it. OKM1825 is raised only when the object exists and the
|
|
16
|
+
* privilege is missing.
|
|
17
|
+
*
|
|
18
|
+
* @param runner - Database connection
|
|
19
|
+
* @param roles - `defineConfig({ roles })`
|
|
20
|
+
* @param objects - Catalog, including grants
|
|
21
|
+
*/
|
|
22
|
+
export declare function assertRoleHealth(runner: Runner, roles: RolesInput, objects: readonly CatalogObject[]): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Refuses to apply role changes when the acting role lacks `CREATEROLE`.
|
|
25
|
+
*
|
|
26
|
+
* @param runner - Database connection
|
|
27
|
+
* @param role - The role that will run `CREATE ROLE` or `ALTER ROLE`
|
|
28
|
+
*/
|
|
29
|
+
export declare function assertCreateRole(runner: Runner, role: string): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Reads `current_user`.
|
|
32
|
+
*
|
|
33
|
+
* @param runner - Database connection
|
|
34
|
+
* @returns The role this session is acting as
|
|
35
|
+
*/
|
|
36
|
+
export declare function currentUser(runner: Runner): Promise<string>;
|
|
37
|
+
/**
|
|
38
|
+
* Reports whether `pg_roles` has the name.
|
|
39
|
+
*
|
|
40
|
+
* @param runner - Database connection
|
|
41
|
+
* @param name - Role name
|
|
42
|
+
* @returns `true` when the role exists
|
|
43
|
+
*/
|
|
44
|
+
export declare function roleExists(runner: Runner, name: string): Promise<boolean>;
|
|
45
|
+
export {};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `roles: { migration, app }`.
|
|
3
|
+
*
|
|
4
|
+
* The object contributes role, grant, and default-privilege records. `schema()`
|
|
5
|
+
* does not import this module. Tooling calls {@link attachRoles} when the
|
|
6
|
+
* config names roles.
|
|
7
|
+
*/
|
|
8
|
+
import type { Catalog, CatalogObject } from "../../../contracts/catalog/types.js";
|
|
9
|
+
/** A role the plan creates and alters. It is never dropped. */
|
|
10
|
+
export type ManagedRole = {
|
|
11
|
+
readonly name: string;
|
|
12
|
+
/** `LOGIN` when true. The default is `NOLOGIN`. */
|
|
13
|
+
readonly login?: boolean;
|
|
14
|
+
/** `INHERIT` when not `false`. */
|
|
15
|
+
readonly inherit?: boolean;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Roles named by `defineConfig`.
|
|
19
|
+
*
|
|
20
|
+
* A string is external: it must already exist. A name listed in `managed` is
|
|
21
|
+
* created when `pg_roles` does not have it.
|
|
22
|
+
*/
|
|
23
|
+
export type RolesInput = {
|
|
24
|
+
/** Role that runs migrations. */
|
|
25
|
+
readonly migration: string;
|
|
26
|
+
/** Role the application connects as. */
|
|
27
|
+
readonly app: string;
|
|
28
|
+
/** Roles this catalog creates and alters. */
|
|
29
|
+
readonly managed?: readonly ManagedRole[];
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Adds role, grant, and default-privilege objects to a catalog.
|
|
33
|
+
*
|
|
34
|
+
* Grants and default privileges are for {@link RolesInput.app} on every
|
|
35
|
+
* managed table, view, materialized view, sequence, and function. Fine-grained
|
|
36
|
+
* grants are not accepted here.
|
|
37
|
+
*
|
|
38
|
+
* @param source - Catalog from `schema()`
|
|
39
|
+
* @param input - Migration role, application role, and managed roles
|
|
40
|
+
* @returns A catalog that includes those objects
|
|
41
|
+
*/
|
|
42
|
+
export declare function attachRoles(source: Catalog, input: RolesInput): Catalog;
|
|
43
|
+
/**
|
|
44
|
+
* Catalog records for one `roles` configuration.
|
|
45
|
+
*
|
|
46
|
+
* @param input - Migration role, application role, and managed roles
|
|
47
|
+
* @param built - Objects already in the catalog
|
|
48
|
+
* @returns Role, grant, and default-privilege records
|
|
49
|
+
*/
|
|
50
|
+
export declare function contributeRoles(input: RolesInput, built: readonly CatalogObject[]): readonly CatalogObject[];
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQL for roles, grants, and default privileges.
|
|
3
|
+
*
|
|
4
|
+
* The plan calls these. `SET ROLE` is not one of them: the runner issues it
|
|
5
|
+
* once, outside the plan (D119).
|
|
6
|
+
*/
|
|
7
|
+
import type { CatalogObject } from "../../../contracts/catalog/types.js";
|
|
8
|
+
/** Statements the planner inserts around the rest of the catalog. */
|
|
9
|
+
export type PrivilegeSql = {
|
|
10
|
+
/** Revokes, run while the objects still exist. */
|
|
11
|
+
readonly revoke: readonly PrivilegeStatement[];
|
|
12
|
+
/** Role creates, role alters, and default privileges. Before new tables. */
|
|
13
|
+
readonly prepare: readonly PrivilegeStatement[];
|
|
14
|
+
/** Grants on objects that exist, or that this plan creates first. */
|
|
15
|
+
readonly grant: readonly PrivilegeStatement[];
|
|
16
|
+
};
|
|
17
|
+
/** One privilege statement and the planner kind it is. */
|
|
18
|
+
export type PrivilegeStatement = {
|
|
19
|
+
readonly sql: string;
|
|
20
|
+
readonly kind: "revoke" | "revoke-default" | "create-role" | "alter-role" | "grant-default" | "grant";
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Diffs role, grant, and default-privilege objects into SQL.
|
|
24
|
+
*
|
|
25
|
+
* A role is created only when it is managed and absent. It is altered only
|
|
26
|
+
* when both sides are managed. It is never dropped. Grants and default
|
|
27
|
+
* privileges are revoked and granted. None of the statements use
|
|
28
|
+
* `IF NOT EXISTS`.
|
|
29
|
+
*
|
|
30
|
+
* @param before - Previous catalog objects
|
|
31
|
+
* @param after - Next catalog objects
|
|
32
|
+
* @param schema - Concrete schema name
|
|
33
|
+
* @param recreated - Identity keys this plan drops and creates. Postgres drops
|
|
34
|
+
* grants with the object, so those grants are issued again after it exists
|
|
35
|
+
* @returns Statements in three groups
|
|
36
|
+
*/
|
|
37
|
+
export declare function privilegeSql(before: readonly CatalogObject[], after: readonly CatalogObject[], schema: string, recreated?: ReadonlySet<string>): PrivilegeSql;
|
|
38
|
+
/**
|
|
39
|
+
* Role name in `create role`, when the statement is one.
|
|
40
|
+
*
|
|
41
|
+
* @param sql - One plan statement
|
|
42
|
+
* @returns The role, or `undefined` when the statement is not `CREATE ROLE`
|
|
43
|
+
*/
|
|
44
|
+
export declare function createdRoleName(sql: string): string | undefined;
|
|
45
|
+
/**
|
|
46
|
+
* Reports whether a statement creates or alters a role.
|
|
47
|
+
*
|
|
48
|
+
* @param sql - One plan statement
|
|
49
|
+
* @returns `true` for `CREATE ROLE` and `ALTER ROLE`
|
|
50
|
+
*/
|
|
51
|
+
export declare function changesRole(sql: string): boolean;
|
|
@@ -28,6 +28,13 @@ export type IndexCall = {
|
|
|
28
28
|
* Absent on an ordinary index.
|
|
29
29
|
*/
|
|
30
30
|
readonly predicate?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Raw index tail an extension may set on the call.
|
|
33
|
+
*
|
|
34
|
+
* A `using …` tail is the extension's index method. The core factory does
|
|
35
|
+
* not read it. `compileIndexes` copies the field onto the catalog index.
|
|
36
|
+
*/
|
|
37
|
+
readonly expression?: string;
|
|
31
38
|
/**
|
|
32
39
|
* Marks the index unique.
|
|
33
40
|
*
|
|
@@ -105,7 +112,13 @@ export type TableOptions<TColumns> = {
|
|
|
105
112
|
*/
|
|
106
113
|
readonly presets?: PresetMap<RowFrom<TColumns>>;
|
|
107
114
|
readonly policies?: unknown;
|
|
108
|
-
|
|
115
|
+
/**
|
|
116
|
+
* Rows the application requires to exist.
|
|
117
|
+
*
|
|
118
|
+
* Apply inserts a row when its key is missing. It does not update or delete.
|
|
119
|
+
* The rows stay on the schema. They are not a diff in the catalog.
|
|
120
|
+
*/
|
|
121
|
+
readonly reference?: ReferenceOption;
|
|
109
122
|
/** `one` and `many`. Other relation kinds stay reserved. */
|
|
110
123
|
readonly relations?: unknown;
|
|
111
124
|
};
|
|
@@ -200,6 +213,16 @@ export type InsertFrom<TColumns> = {
|
|
|
200
213
|
export type UpdateFrom<TColumns, TKey extends string = never> = {
|
|
201
214
|
readonly [K in keyof TColumns as K extends TKey ? never : ColumnUpdateOf<TColumns[K]> extends never ? never : K]: ColumnUpdateOf<TColumns[K]>;
|
|
202
215
|
};
|
|
216
|
+
/**
|
|
217
|
+
* Rows declared with the table option `reference`.
|
|
218
|
+
*
|
|
219
|
+
* `key` is one column name or several, in constraint order. `rows` are the
|
|
220
|
+
* values apply inserts when that key is absent.
|
|
221
|
+
*/
|
|
222
|
+
export type ReferenceOption = {
|
|
223
|
+
readonly key: string | readonly string[];
|
|
224
|
+
readonly rows: readonly Readonly<Record<string, string | number | boolean | null>>[];
|
|
225
|
+
};
|
|
203
226
|
/**
|
|
204
227
|
* Declares a table.
|
|
205
228
|
*
|
|
@@ -81,6 +81,15 @@ export type ColumnTenancy = {
|
|
|
81
81
|
* @param ctx - Names, scope, and the table map
|
|
82
82
|
*/
|
|
83
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;
|
|
84
93
|
missing(table: string): never;
|
|
85
94
|
};
|
|
86
95
|
/**
|
|
@@ -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;
|