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.
Files changed (148) hide show
  1. package/README.md +882 -48
  2. package/dist/contracts/catalog/document.d.ts +6 -2
  3. package/dist/contracts/catalog/enum.d.ts +31 -4
  4. package/dist/contracts/catalog/extension.d.ts +61 -0
  5. package/dist/contracts/catalog/privilege.d.ts +64 -0
  6. package/dist/contracts/catalog/routine.d.ts +56 -0
  7. package/dist/contracts/catalog/types.d.ts +164 -10
  8. package/dist/contracts/catalog/view.d.ts +73 -0
  9. package/dist/dialects/pg/column.d.ts +3 -1
  10. package/dist/dialects/pg/ddl.d.ts +65 -1
  11. package/dist/dialects/pg/enum.d.ts +10 -8
  12. package/dist/dialects/pg/ext/citext.d.ts +14 -0
  13. package/dist/dialects/pg/ext/citext.js +11 -0
  14. package/dist/dialects/pg/ext/index.d.ts +52 -0
  15. package/dist/dialects/pg/ext/index.js +6 -0
  16. package/dist/dialects/pg/ext/pg-trgm.d.ts +53 -0
  17. package/dist/dialects/pg/ext/pg-trgm.js +42 -0
  18. package/dist/dialects/pg/fn/index.d.ts +107 -0
  19. package/dist/dialects/pg/fn/index.js +175 -0
  20. package/dist/dialects/pg/fn/touch.d.ts +14 -0
  21. package/dist/dialects/pg/index.js +104 -19
  22. package/dist/dialects/pg/introspect.d.ts +10 -1
  23. package/dist/dialects/pg/operators.d.ts +8 -1
  24. package/dist/dialects/pg/role/check.d.ts +45 -0
  25. package/dist/dialects/pg/role/index.d.ts +50 -0
  26. package/dist/dialects/pg/role/sql.d.ts +51 -0
  27. package/dist/dialects/pg/table.d.ts +24 -1
  28. package/dist/dialects/pg/tenancy.d.ts +9 -0
  29. package/dist/dialects/pg/view/client.d.ts +30 -0
  30. package/dist/dialects/pg/view/depend.d.ts +35 -0
  31. package/dist/dialects/pg/view/index.d.ts +114 -0
  32. package/dist/dialects/pg/view/index.js +289 -0
  33. package/dist/dialects/pg/view/scratch.d.ts +22 -0
  34. package/dist/dialects/pg/where.d.ts +2 -2
  35. package/dist/runtime/catalog-cache.d.ts +17 -0
  36. package/dist/runtime/compat-words.d.ts +23 -0
  37. package/dist/runtime/drift-detail.d.ts +20 -4
  38. package/dist/runtime/drift.d.ts +4 -2
  39. package/dist/runtime/pg/bun.js +3 -3
  40. package/dist/runtime/pg/pg.js +3 -3
  41. package/dist/runtime/pg/pglite.js +3 -3
  42. package/dist/runtime/pg/postgresjs.js +3 -3
  43. package/dist/runtime/tenancy/index.js +6 -3
  44. package/dist/runtime/traits/index.d.ts +7 -2
  45. package/dist/runtime/traits/index.js +151 -13
  46. package/dist/runtime/types.d.ts +2 -0
  47. package/dist/runtime/validate/index.js +4 -4
  48. package/dist/shared/{xkz8g6by.js → 1g0drakv.js} +2 -2
  49. package/dist/shared/2321avmn.js +418 -0
  50. package/dist/shared/{7mht49yd.js → 3p4b1fg0.js} +57 -18
  51. package/dist/shared/41kv2xdm.js +318 -0
  52. package/dist/shared/{97g2jnrw.js → 4ef7mmqf.js} +3 -3
  53. package/dist/shared/{sacqha1y.js → 4m9fn52z.js} +2 -2
  54. package/dist/shared/5mtf6cj3.js +94 -0
  55. package/dist/shared/{1dp5knt7.js → 5vdm4sgp.js} +2 -2
  56. package/dist/shared/{a1gdp7j9.js → 6693j9rs.js} +1 -1
  57. package/dist/shared/{38crxbgn.js → 6p5k20sm.js} +3 -3
  58. package/dist/shared/7nk68fj8.js +751 -0
  59. package/dist/shared/84ptn35q.js +71 -0
  60. package/dist/shared/{d2whjz4k.js → 8jb4ymh2.js} +581 -28
  61. package/dist/shared/8ktwd3rh.js +97 -0
  62. package/dist/shared/94ez8kzh.js +19 -0
  63. package/dist/shared/{3a5ne750.js → 9m80mkac.js} +2 -2
  64. package/dist/shared/9x25fxhc.js +150 -0
  65. package/dist/shared/9yn6a2vd.js +11 -0
  66. package/dist/shared/ady1ms74.js +72 -0
  67. package/dist/shared/{4jzzghr6.js → awrsqrn7.js} +6 -6
  68. package/dist/shared/{4b9da9d7.js → axhk06q1.js} +19 -1
  69. package/dist/shared/{d04j53v8.js → c5g81ngb.js} +82 -14
  70. package/dist/shared/{n47rd821.js → c8aghh05.js} +1 -1
  71. package/dist/shared/{dd4f8mnx.js → c9z5g0fm.js} +4 -2
  72. package/dist/shared/{ps43134h.js → dyj86cmj.js} +4 -4
  73. package/dist/shared/{0qkxbm1f.js → fa9vt245.js} +1 -1
  74. package/dist/shared/{qa5dsc7z.js → fb00y8fp.js} +3 -3
  75. package/dist/shared/{qxa0yb9j.js → g7ez901n.js} +30 -1
  76. package/dist/shared/{py3nh7jy.js → gdh9mrtp.js} +2 -2
  77. package/dist/shared/{yw5c610b.js → gjthds9j.js} +2 -2
  78. package/dist/shared/hcmdtwgh.js +102 -0
  79. package/dist/shared/hqjsxnz7.js +13 -0
  80. package/dist/shared/htnaj77v.js +17 -0
  81. package/dist/shared/{v18jva5b.js → jgxzjzcz.js} +1 -1
  82. package/dist/shared/{x9v1qgeb.js → jsd07prz.js} +3 -3
  83. package/dist/shared/{g9f0zqce.js → kafaa5zv.js} +1 -1
  84. package/dist/shared/kj680nxv.js +19 -0
  85. package/dist/shared/{mxmcdsh5.js → kkzwp3d2.js} +9 -9
  86. package/dist/shared/{g1b5zzj9.js → n0dgs0pb.js} +1 -1
  87. package/dist/shared/n5y9zyj1.js +2431 -0
  88. package/dist/shared/{zt8y0wzb.js → n7mcc1gk.js} +1 -1
  89. package/dist/shared/{ge03bfca.js → nxb42q7h.js} +2 -2
  90. package/dist/shared/q6zsyh31.js +2192 -0
  91. package/dist/shared/{sfh4pk75.js → q795afwa.js} +26 -21
  92. package/dist/shared/{10tjenmd.js → qn0srwwq.js} +1 -1
  93. package/dist/shared/s4mb6a4b.js +545 -0
  94. package/dist/shared/{ytg3xf9p.js → sf8m6tfy.js} +3 -3
  95. package/dist/shared/{zd93g3rq.js → sr5ms7b3.js} +1 -1
  96. package/dist/shared/{xatfg0gn.js → tmbdywx0.js} +4 -19
  97. package/dist/shared/tny2t3sm.js +100 -0
  98. package/dist/shared/{e7a268fy.js → v7tpnhnz.js} +1 -1
  99. package/dist/shared/{ecdzej21.js → wqem4jed.js} +7 -7
  100. package/dist/shared/xghkt7a9.js +1144 -0
  101. package/dist/shared/y005b761.js +112 -0
  102. package/dist/shared/ycatkxmq.js +84 -0
  103. package/dist/shared/ygem90rn.js +900 -0
  104. package/dist/shared/{eaxwrgby.js → yjw02enp.js} +6 -3
  105. package/dist/shared/{mrq77sgw.js → zg24x0hm.js} +1 -1
  106. package/dist/shared/{cstgkzdx.js → zvbjc949.js} +1 -1
  107. package/dist/tooling/cli.js +66 -13
  108. package/dist/tooling/migrate/apply.d.ts +75 -5
  109. package/dist/tooling/migrate/backfill.d.ts +136 -0
  110. package/dist/tooling/migrate/check.d.ts +65 -0
  111. package/dist/tooling/migrate/classify.d.ts +108 -0
  112. package/dist/tooling/migrate/commands.d.ts +2 -1
  113. package/dist/tooling/migrate/config.d.ts +30 -0
  114. package/dist/tooling/migrate/doctor.d.ts +28 -0
  115. package/dist/tooling/migrate/drift.d.ts +35 -0
  116. package/dist/tooling/migrate/estimate.d.ts +50 -0
  117. package/dist/tooling/migrate/ext.d.ts +17 -0
  118. package/dist/tooling/migrate/extensions.d.ts +53 -0
  119. package/dist/tooling/migrate/files.d.ts +12 -0
  120. package/dist/tooling/migrate/index.d.ts +3 -2
  121. package/dist/tooling/migrate/index.js +67 -1
  122. package/dist/tooling/migrate/lint-rules.d.ts +51 -0
  123. package/dist/tooling/migrate/lint.d.ts +71 -0
  124. package/dist/tooling/migrate/managed.d.ts +17 -0
  125. package/dist/tooling/migrate/plan.d.ts +78 -10
  126. package/dist/tooling/migrate/project.d.ts +64 -5
  127. package/dist/tooling/migrate/provision.d.ts +18 -0
  128. package/dist/tooling/migrate/reference.d.ts +40 -0
  129. package/dist/tooling/migrate/runner.d.ts +108 -0
  130. package/dist/tooling/migrate/safe.d.ts +77 -0
  131. package/dist/tooling/migrate/seed.d.ts +20 -0
  132. package/dist/tooling/migrate/snapshot.d.ts +78 -0
  133. package/dist/tooling/migrate/status.d.ts +25 -6
  134. package/dist/tooling/migrate/type-name.d.ts +19 -0
  135. package/dist/tooling/testing/factories.d.ts +117 -0
  136. package/dist/tooling/testing/facts.d.ts +72 -0
  137. package/dist/tooling/testing/index.d.ts +89 -0
  138. package/dist/tooling/testing/index.js +8 -0
  139. package/dist/tooling/testing/isolation.d.ts +30 -0
  140. package/dist/tooling/testing/random.d.ts +40 -0
  141. package/dist/tooling/testing/record.d.ts +38 -0
  142. package/package.json +26 -2
  143. package/dist/shared/5z4q2zda.js +0 -2073
  144. package/dist/shared/eqmtn1bj.js +0 -399
  145. package/dist/shared/rtnaqre0.js +0 -37
  146. package/dist/shared/zwmqxb0g.js +0 -79
  147. package/dist/shared/{m9tv7xn7.js → radd3z4g.js} +3 -3
  148. /package/dist/shared/{9k6vetvf.js → rrstp3kb.js} +0 -0
@@ -35,8 +35,12 @@ export declare function renameColumn(source: Catalog, change: {
35
35
  /**
36
36
  * Renames a table without renaming its constraints or indexes.
37
37
  *
38
- * Column, index, and constraint parents move to the new name. Expression text
39
- * that names the table is rewritten. Constraint and index names stay.
38
+ * Column, index, constraint, and trigger parents move to the new name, and
39
+ * edges that pointed at those objects move with them. Expression text that
40
+ * names the table is rewritten. Constraint and index names stay. A grant on
41
+ * the table, or on an identity sequence named `{table}_{column}_seq`, follows
42
+ * the name the schema will use. The planner emits the `RENAME` for a default
43
+ * name; a custom name is left as it is.
40
44
  *
41
45
  * @param source - Catalog document
42
46
  * @param change - Namespace, current table name, and the new name
@@ -1,10 +1,10 @@
1
1
  /**
2
- * Enum catalog objects.
2
+ * Enum and domain catalog objects.
3
3
  *
4
- * Kind `type`, identity `(namespace, name)`. The definition is the ordered
5
- * label list and nothing else: domains are not catalog objects.
4
+ * Kind `type`, identity `(namespace, name)`. An enum definition is the ordered
5
+ * label list. A domain definition is the base type and the check.
6
6
  */
7
- import type { Namespace, ObjectIdentity, Owner, Provenance, TypeObject } from "./types.js";
7
+ import type { DomainDefinition, Namespace, ObjectIdentity, Owner, Provenance, TypeDefinition, TypeObject } from "./types.js";
8
8
  /** Input for {@link enumType}. */
9
9
  export type EnumTypeInput = {
10
10
  readonly namespace: Namespace;
@@ -25,6 +25,33 @@ export type EnumTypeInput = {
25
25
  * @returns A type envelope
26
26
  */
27
27
  export declare function enumType(input: EnumTypeInput): TypeObject;
28
+ /** Input for {@link domainType}. */
29
+ export type DomainTypeInput = {
30
+ readonly namespace: Namespace;
31
+ readonly name: string;
32
+ readonly base: string;
33
+ readonly check: string;
34
+ readonly owner?: Owner;
35
+ readonly provenance: Provenance;
36
+ readonly dependencies?: readonly ObjectIdentity[];
37
+ };
38
+ /**
39
+ * Builds a domain type object.
40
+ *
41
+ * The definition is the base type and the check. An empty base or an empty
42
+ * check is OKM1020.
43
+ *
44
+ * @param input - Namespace, name, base type, and check
45
+ * @returns A type envelope
46
+ */
47
+ export declare function domainType(input: DomainTypeInput): TypeObject;
48
+ /**
49
+ * Reports whether a type definition is a domain.
50
+ *
51
+ * @param definition - Enum labels or a domain base and check
52
+ * @returns `true` when the definition has a base type
53
+ */
54
+ export declare function isDomain(definition: TypeDefinition): definition is DomainDefinition;
28
55
  /**
29
56
  * Reports whether two label lists are the same text in the same order.
30
57
  *
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Extension catalog objects.
3
+ *
4
+ * The factory stores the record. It does not parse a document and it does
5
+ * not plan SQL. Those stay in the document chunk and in tooling.
6
+ */
7
+ import type { Catalog, ExtensionObject, ObjectIdentity, Owner, Provenance } from "./types.js";
8
+ /** Input for {@link extensionObject}. */
9
+ export type ExtensionInput = {
10
+ readonly name: string;
11
+ readonly schema: string;
12
+ readonly relocatable?: boolean;
13
+ readonly version?: string;
14
+ readonly owner?: Owner;
15
+ readonly provenance: Provenance;
16
+ readonly dependencies?: readonly ObjectIdentity[];
17
+ };
18
+ /**
19
+ * Builds an extension record.
20
+ *
21
+ * @param input - Name, install schema, and optional version pin
22
+ * @returns The catalog object
23
+ */
24
+ export declare function extensionObject(input: ExtensionInput): ExtensionObject;
25
+ /**
26
+ * Reports whether a version is an exact pin (`1.6`), not a floor or an omission.
27
+ *
28
+ * @param version - Declared or installed version
29
+ * @returns `true` when every component is a decimal integer
30
+ */
31
+ export declare function isExactVersion(version: string | undefined): version is string;
32
+ /**
33
+ * Compares two exact versions. A shorter tail is zero.
34
+ *
35
+ * @param left - Exact version
36
+ * @param right - Exact version
37
+ * @returns Negative when `left` is older, positive when it is newer
38
+ */
39
+ export declare function compareExtensionVersions(left: string, right: string): number;
40
+ /**
41
+ * Reports whether two extension records are the same migration.
42
+ *
43
+ * An unpinned or floor declaration matches any installed version. Schema and
44
+ * `relocatable` still have to match.
45
+ *
46
+ * @param before - Previous record
47
+ * @param after - Declared record
48
+ * @returns `true` when no `ALTER EXTENSION` is required
49
+ */
50
+ export declare function sameExtensionDefinition(before: ExtensionObject, after: ExtensionObject): boolean;
51
+ /**
52
+ * Drops a version when the other side of a diff does not pin an exact one.
53
+ *
54
+ * Serialization then compares the rest of the record. Exact pins on both
55
+ * sides are left as written.
56
+ *
57
+ * @param source - Catalog being compared
58
+ * @param other - The other catalog
59
+ * @returns `source`, or a copy with those versions removed
60
+ */
61
+ export declare function alignExtensionVersions(source: Catalog, other: Catalog): Catalog;
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Role, grant, and default-privilege records.
3
+ *
4
+ * The factories store the envelope. SQL, introspection, and the doctor
5
+ * checks live in the dialect and in tooling.
6
+ */
7
+ import type { DefaultPrivilegeObject, GrantObject, GrantObjectRef, Namespace, ObjectIdentity, Owner, Provenance, RoleObject } from "./types.js";
8
+ /** Input for {@link roleObject}. */
9
+ export type RoleInput = {
10
+ readonly name: string;
11
+ readonly login?: boolean;
12
+ readonly inherit?: boolean;
13
+ readonly owner?: Owner;
14
+ readonly provenance: Provenance;
15
+ readonly dependencies?: readonly ObjectIdentity[];
16
+ };
17
+ /** Input for {@link grantObject}. */
18
+ export type GrantInput = {
19
+ readonly role: string;
20
+ readonly object: GrantObjectRef;
21
+ readonly privilege: string;
22
+ readonly owner?: Owner;
23
+ readonly provenance: Provenance;
24
+ readonly dependencies?: readonly ObjectIdentity[];
25
+ };
26
+ /** Input for {@link defaultPrivilegeObject}. */
27
+ export type DefaultPrivilegeInput = {
28
+ readonly forRole: string;
29
+ readonly namespace: Namespace;
30
+ readonly objectKind: string;
31
+ readonly grantee: string;
32
+ readonly privilege: string;
33
+ readonly owner?: Owner;
34
+ readonly provenance: Provenance;
35
+ readonly dependencies?: readonly ObjectIdentity[];
36
+ };
37
+ /**
38
+ * Builds a role record.
39
+ *
40
+ * The name is an identifier. The grant key is not.
41
+ *
42
+ * @param input - Name, login, and inherit
43
+ * @returns The catalog object
44
+ */
45
+ export declare function roleObject(input: RoleInput): RoleObject;
46
+ /**
47
+ * Builds a grant record.
48
+ *
49
+ * Identity is `(role, object, privilege)`. It is not checked against the
50
+ * 63-byte identifier limit (D119).
51
+ *
52
+ * @param input - Grantee, object, and one privilege
53
+ * @returns The catalog object
54
+ */
55
+ export declare function grantObject(input: GrantInput): GrantObject;
56
+ /**
57
+ * Builds a default-privilege record.
58
+ *
59
+ * Identity is `(forRole, namespace, objectKind, grantee, privilege)`.
60
+ *
61
+ * @param input - Creating role, schema, object kind, grantee, and privilege
62
+ * @returns The catalog object
63
+ */
64
+ export declare function defaultPrivilegeObject(input: DefaultPrivilegeInput): DefaultPrivilegeObject;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Function and trigger catalog objects.
3
+ *
4
+ * The factories store the record. They do not plan SQL. DDL stays in the
5
+ * dialect, and `fn()` / `trigger()` stay on `okmodel/fn`.
6
+ */
7
+ import type { FunctionArgument, FunctionLanguage, FunctionObject, FunctionSecurity, FunctionVolatility, Namespace, ObjectIdentity, ObjectRef, Owner, Provenance, TriggerCall, TriggerEvent, TriggerLevel, TriggerObject, TriggerTiming } from "./types.js";
8
+ /** Input for {@link functionObject}. */
9
+ export type FunctionInput = {
10
+ readonly namespace?: Namespace;
11
+ readonly name: string;
12
+ readonly arguments?: readonly FunctionArgument[];
13
+ readonly returns: string;
14
+ readonly language: FunctionLanguage;
15
+ readonly volatility?: FunctionVolatility;
16
+ readonly security?: FunctionSecurity;
17
+ readonly searchPath?: string;
18
+ readonly body: string;
19
+ readonly atomic?: boolean;
20
+ readonly owner?: Owner;
21
+ readonly provenance: Provenance;
22
+ readonly dependencies?: readonly ObjectIdentity[];
23
+ };
24
+ /** Input for {@link triggerObject}. */
25
+ export type TriggerInput = {
26
+ readonly parent: ObjectRef;
27
+ readonly name: string;
28
+ readonly timing: TriggerTiming;
29
+ readonly events: readonly TriggerEvent[];
30
+ readonly level: TriggerLevel;
31
+ readonly calls: TriggerCall;
32
+ readonly updateOf?: readonly string[];
33
+ readonly when?: string;
34
+ readonly owner?: Owner;
35
+ readonly provenance: Provenance;
36
+ readonly dependencies?: readonly ObjectIdentity[];
37
+ };
38
+ /**
39
+ * Builds a function record.
40
+ *
41
+ * Argument types are the identity. Names live only in the definition.
42
+ *
43
+ * @param input - Signature, language, and body
44
+ * @returns The catalog object
45
+ */
46
+ export declare function functionObject(input: FunctionInput): FunctionObject;
47
+ /**
48
+ * Builds a trigger record.
49
+ *
50
+ * Dependencies are the table, the function, and each `UPDATE OF` column.
51
+ * Events are stored in a fixed order.
52
+ *
53
+ * @param input - Timing, events, and the function it calls
54
+ * @returns The catalog object
55
+ */
56
+ export declare function triggerObject(input: TriggerInput): TriggerObject;
@@ -14,7 +14,7 @@ export type Owner = (typeof OWNERS)[number];
14
14
  * Object kinds from spec section 5.7.
15
15
  *
16
16
  * Built in this layer: table, column, index, constraint, sequence, and type.
17
- * A type object is an enum: ordered labels, and no other form.
17
+ * A type object is an enum (ordered labels) or a domain (base type and check).
18
18
  */
19
19
  export declare const OBJECT_KINDS: readonly ["table", "column", "index", "constraint", "sequence", "view", "materializedView", "type", "function", "trigger", "policy", "extension", "role", "grant", "defaultPrivilege"];
20
20
  /** A catalog object kind. */
@@ -100,9 +100,15 @@ export type GrantIdentity = {
100
100
  readonly object: GrantObjectRef;
101
101
  readonly privilege: string;
102
102
  };
103
- /** What a grant attaches to. `namespace` is the schema itself. */
103
+ /**
104
+ * What a grant attaches to.
105
+ *
106
+ * `namespace` is the schema itself. A function's `name` is `name(argTypes)`
107
+ * so overloads stay distinct without a second field. The key is not a stored
108
+ * identifier (D119).
109
+ */
104
110
  export type GrantObjectRef = {
105
- readonly kind: "table" | "sequence" | "namespace";
111
+ readonly kind: "table" | "view" | "materializedView" | "sequence" | "function" | "namespace";
106
112
  readonly namespace: Namespace;
107
113
  readonly name: string;
108
114
  };
@@ -130,6 +136,19 @@ export type ExtensionIdentity = {
130
136
  readonly kind: "extension";
131
137
  readonly name: string;
132
138
  };
139
+ /**
140
+ * Canonical extension record.
141
+ *
142
+ * `version` is an exact pin (`1.6`) or a floor (`>=0.7`). Absent means
143
+ * unpinned: the installed version is information and drift ignores it.
144
+ */
145
+ export type ExtensionDefinition = {
146
+ /** Schema the extension is installed in. */
147
+ readonly schema: string;
148
+ /** Whether `ALTER EXTENSION … SET SCHEMA` is allowed. */
149
+ readonly relocatable: boolean;
150
+ readonly version?: string;
151
+ };
133
152
  /** Stable identity. The variant depends on the kind. */
134
153
  export type ObjectIdentity = NamespaceIdentity | AnchoredIdentity | FunctionIdentity | GrantIdentity | DefaultPrivilegeIdentity | RoleIdentity | ExtensionIdentity;
135
154
  /**
@@ -237,11 +256,22 @@ export type ConstraintDefinition = {
237
256
  * Enum definition.
238
257
  *
239
258
  * `labels` is the stored order. That order is part of the catalog hash.
240
- * Domains are not represented here.
241
259
  */
242
- export type TypeDefinition = {
260
+ export type EnumDefinition = {
243
261
  readonly labels: readonly string[];
244
262
  };
263
+ /**
264
+ * Domain definition.
265
+ *
266
+ * `base` is the Postgres type the domain is created over. `check` is the
267
+ * domain check, stored as written. A later base type is refused (OKM1020).
268
+ */
269
+ export type DomainDefinition = {
270
+ readonly base: string;
271
+ readonly check: string;
272
+ };
273
+ /** A catalog type: an enum or a domain. */
274
+ export type TypeDefinition = EnumDefinition | DomainDefinition;
245
275
  /** Sequence definition. Start and increment are decimal integers. */
246
276
  export type SequenceDefinition = {
247
277
  readonly dataType: "smallint" | "integer" | "bigint";
@@ -283,13 +313,137 @@ export type TypeObject = CatalogEnvelope<"type", NamespaceIdentity & {
283
313
  readonly kind: "type";
284
314
  }, TypeDefinition>;
285
315
  /**
286
- * One built catalog object.
316
+ * An extension.
317
+ *
318
+ * The record is identity, schema, relocatable, and version. Core stores it
319
+ * and does not interpret it. The extension object produces it.
320
+ */
321
+ export type ExtensionObject = CatalogEnvelope<"extension", ExtensionIdentity, ExtensionDefinition>;
322
+ /** One function language. */
323
+ export type FunctionLanguage = "sql" | "plpgsql";
324
+ /** One volatility. */
325
+ export type FunctionVolatility = "volatile" | "stable" | "immutable";
326
+ /** `SECURITY INVOKER` or `SECURITY DEFINER`. */
327
+ export type FunctionSecurity = "invoker" | "definer";
328
+ /** One argument. The name is not part of the identity. */
329
+ export type FunctionArgument = {
330
+ readonly name: string;
331
+ readonly type: string;
332
+ };
333
+ /**
334
+ * Function definition.
335
+ *
336
+ * The body of a plpgsql or plain SQL function is the source Postgres stores
337
+ * (`prosrc`). A `LANGUAGE sql` body that starts with `BEGIN ATOMIC` is marked
338
+ * `atomic`: Postgres reprints that body and leaves `prosrc` empty.
339
+ */
340
+ export type FunctionDefinition = {
341
+ readonly arguments: readonly FunctionArgument[];
342
+ readonly returns: string;
343
+ readonly language: FunctionLanguage;
344
+ readonly volatility: FunctionVolatility;
345
+ readonly security: FunctionSecurity;
346
+ readonly body: string;
347
+ readonly searchPath?: string;
348
+ readonly atomic?: true;
349
+ };
350
+ /** One trigger timing. */
351
+ export type TriggerTiming = "before" | "after" | "instead";
352
+ /** One trigger event. Stored order is insert, update, delete, truncate. */
353
+ export type TriggerEvent = "insert" | "update" | "delete" | "truncate";
354
+ /** One trigger level. */
355
+ export type TriggerLevel = "row" | "statement";
356
+ /** The function a trigger calls. Argument types keep an overload distinct. */
357
+ export type TriggerCall = {
358
+ readonly namespace: Namespace;
359
+ readonly name: string;
360
+ readonly argTypes: readonly string[];
361
+ };
362
+ /**
363
+ * Trigger definition.
287
364
  *
288
- * Views, functions, triggers, extensions, roles, grants, and default
289
- * privileges use {@link CatalogEnvelope} when they are built. They are not
290
- * part of this union yet.
365
+ * `updateOf` lists SQL column names for `UPDATE OF`. `when` is the predicate
366
+ * text. The table and the function are dependency edges.
367
+ */
368
+ export type TriggerDefinition = {
369
+ readonly timing: TriggerTiming;
370
+ readonly events: readonly TriggerEvent[];
371
+ readonly level: TriggerLevel;
372
+ readonly calls: TriggerCall;
373
+ readonly updateOf?: readonly string[];
374
+ readonly when?: string;
375
+ };
376
+ /** A function. Identity is `(schema, name, argTypes[])`. */
377
+ export type FunctionObject = CatalogEnvelope<"function", FunctionIdentity, FunctionDefinition>;
378
+ /** A trigger. Identity is `(table, name)`. */
379
+ export type TriggerObject = CatalogEnvelope<"trigger", AnchoredIdentity & {
380
+ readonly kind: "trigger";
381
+ }, TriggerDefinition>;
382
+ /** One output column of a view or materialized view. */
383
+ export type ViewColumn = {
384
+ readonly name: string;
385
+ readonly dataType: string;
386
+ };
387
+ /**
388
+ * View definition.
389
+ *
390
+ * `query` is the server reprint when one has been read (`pg_get_viewdef`),
391
+ * and the author's SQL until then. Column dependencies are separate edges.
392
+ */
393
+ export type ViewDefinition = {
394
+ readonly columns: readonly ViewColumn[];
395
+ readonly query: string;
396
+ };
397
+ /**
398
+ * Materialized view definition.
399
+ *
400
+ * There is no replace. `refresh` is the populate mode. Postgres does not
401
+ * store it; introspection leaves it unset.
402
+ */
403
+ export type MaterializedViewDefinition = {
404
+ readonly columns: readonly ViewColumn[];
405
+ readonly query: string;
406
+ readonly refresh?: "concurrently";
407
+ };
408
+ /** A view. Identity is `(namespace, name)`. */
409
+ export type ViewObject = CatalogEnvelope<"view", NamespaceIdentity & {
410
+ readonly kind: "view";
411
+ }, ViewDefinition>;
412
+ /** A materialized view. Identity is `(namespace, name)`. */
413
+ export type MaterializedViewObject = CatalogEnvelope<"materializedView", NamespaceIdentity & {
414
+ readonly kind: "materializedView";
415
+ }, MaterializedViewDefinition>;
416
+ /**
417
+ * Role definition.
418
+ *
419
+ * Only `login` and `inherit` are altered in place. A password is not stored.
420
+ */
421
+ export type RoleDefinition = {
422
+ readonly login: boolean;
423
+ readonly inherit: boolean;
424
+ };
425
+ /**
426
+ * Grant definition.
427
+ *
428
+ * The privilege is the identity. `GRANT OPTION` is not in this version.
429
+ */
430
+ export type GrantDefinition = Record<string, never>;
431
+ /**
432
+ * Default-privilege definition.
433
+ *
434
+ * The key is the identity. The statement is `ALTER DEFAULT PRIVILEGES`.
435
+ */
436
+ export type DefaultPrivilegeDefinition = Record<string, never>;
437
+ /** A role. Identity is the name. Roles are never dropped (D119). */
438
+ export type RoleObject = CatalogEnvelope<"role", RoleIdentity, RoleDefinition>;
439
+ /** A grant. Identity is `(role, object, privilege)`. */
440
+ export type GrantObject = CatalogEnvelope<"grant", GrantIdentity, GrantDefinition>;
441
+ /** A default privilege. Identity is `(forRole, namespace, objectKind, grantee, privilege)`. */
442
+ export type DefaultPrivilegeObject = CatalogEnvelope<"defaultPrivilege", DefaultPrivilegeIdentity, DefaultPrivilegeDefinition>;
443
+ /**
444
+ * One built catalog object.
291
445
  */
292
- export type CatalogObject = TableObject | ColumnObject | IndexObject | ConstraintObject | SequenceObject | TypeObject;
446
+ export type CatalogObject = TableObject | ColumnObject | IndexObject | ConstraintObject | SequenceObject | TypeObject | ExtensionObject | FunctionObject | TriggerObject | ViewObject | MaterializedViewObject | RoleObject | GrantObject | DefaultPrivilegeObject;
293
447
  /** Format version stored in the serialized catalog. */
294
448
  export declare const CATALOG_VERSION = 1;
295
449
  /** A catalog document. Object order is identity-key order. */
@@ -0,0 +1,73 @@
1
+ /**
2
+ * View and materialized view catalog objects.
3
+ *
4
+ * The factories store the record. They do not plan SQL. DDL stays in the
5
+ * dialect, and `view()` / `materializedView()` stay on `okmodel/view`.
6
+ */
7
+ import type { IndexObject, MaterializedViewObject, Namespace, ObjectIdentity, ObjectRef, Owner, Provenance, ViewColumn, ViewObject } from "./types.js";
8
+ /** Input for {@link viewObject}. */
9
+ export type ViewInput = {
10
+ readonly namespace?: Namespace;
11
+ readonly name: string;
12
+ readonly columns: readonly ViewColumn[];
13
+ readonly query: string;
14
+ readonly owner?: Owner;
15
+ readonly provenance: Provenance;
16
+ readonly dependencies?: readonly ObjectIdentity[];
17
+ };
18
+ /** Input for {@link materializedViewObject}. */
19
+ export type MaterializedViewInput = ViewInput & {
20
+ readonly refresh?: "concurrently";
21
+ };
22
+ /** Input for {@link materializedViewIndex}. */
23
+ export type MaterializedViewIndexInput = {
24
+ readonly parent: ObjectRef;
25
+ readonly name?: string;
26
+ readonly columns: readonly string[];
27
+ readonly unique?: boolean;
28
+ readonly nameKey?: string;
29
+ readonly expression?: string;
30
+ readonly predicate?: string;
31
+ readonly owner?: Owner;
32
+ readonly provenance: Provenance;
33
+ /** Retargeted edges. Omitted edges depend on the materialized view. */
34
+ readonly dependencies?: readonly ObjectIdentity[];
35
+ };
36
+ /**
37
+ * Trims a view query and drops one trailing semicolon.
38
+ *
39
+ * `pg_get_viewdef` and the author's SQL both go through this before they are
40
+ * stored, so two reads of the same reprint compare equal.
41
+ *
42
+ * @param query - Author SQL or a server reprint
43
+ * @returns The stored query text
44
+ */
45
+ export declare function normaliseViewQuery(query: string): string;
46
+ /**
47
+ * Builds a view record.
48
+ *
49
+ * Identity is `(namespace, name)`. Columns stay in declaration order.
50
+ *
51
+ * @param input - Columns, query, and dependency edges
52
+ * @returns The catalog object
53
+ */
54
+ export declare function viewObject(input: ViewInput): ViewObject;
55
+ /**
56
+ * Builds a materialized view record.
57
+ *
58
+ * `refresh` is stored only for `"concurrently"`. The object has no replace.
59
+ *
60
+ * @param input - Columns, query, populate mode, and dependency edges
61
+ * @returns The catalog object
62
+ */
63
+ export declare function materializedViewObject(input: MaterializedViewInput): MaterializedViewObject;
64
+ /**
65
+ * Builds an index owned by a materialized view.
66
+ *
67
+ * The edge points at the view, not at a table. View output columns are not
68
+ * catalog objects, so the index does not depend on column identities.
69
+ *
70
+ * @param input - Parent view, columns, and uniqueness
71
+ * @returns An index envelope
72
+ */
73
+ export declare function materializedViewIndex(input: MaterializedViewIndexInput): IndexObject;
@@ -4,7 +4,7 @@
4
4
  * Modifiers allocate a new builder when called. Importing this module does
5
5
  * not build a codec table. `.validate()` stores rules and does not run them.
6
6
  */
7
- import { type ReferentialAction } from "../../contracts/catalog/types.js";
7
+ import { type CatalogObject, type Namespace, type Provenance, type ReferentialAction } from "../../contracts/catalog/types.js";
8
8
  import { type ClientFill } from "../../contracts/generator.js";
9
9
  /** Flags that decide the row, insert, and update shapes of one column. */
10
10
  export type ColumnFlags = {
@@ -221,6 +221,7 @@ export type ColumnState<TValue> = {
221
221
  readonly domain: {
222
222
  readonly base: string;
223
223
  readonly check: string;
224
+ readonly emit?: (namespace: Namespace, provenance: Provenance, objects: CatalogObject[]) => void;
224
225
  } | undefined;
225
226
  readonly primaryKey: boolean;
226
227
  readonly typeLabel: string | undefined;
@@ -264,6 +265,7 @@ export type OpenColumn<TValue> = {
264
265
  readonly domain?: {
265
266
  readonly base: string;
266
267
  readonly check: string;
268
+ readonly emit?: (namespace: Namespace, provenance: Provenance, objects: CatalogObject[]) => void;
267
269
  };
268
270
  readonly primaryKey?: boolean;
269
271
  readonly typeLabel?: string;
@@ -4,7 +4,7 @@
4
4
  * Planning and scratch comparison both render through here, so a statement
5
5
  * has one spelling.
6
6
  */
7
- import type { Catalog, CatalogObject, ColumnObject, SequenceObject, TableObject } from "../../contracts/catalog/types.js";
7
+ import type { Catalog, CatalogObject, ColumnObject, FunctionObject, MaterializedViewObject, SequenceObject, TableObject, ViewObject } from "../../contracts/catalog/types.js";
8
8
  /**
9
9
  * Quotes one identifier.
10
10
  *
@@ -23,6 +23,15 @@ export declare function quoteIdent(name: string): string;
23
23
  * @returns SQL statements
24
24
  */
25
25
  export declare function renderCatalog(source: Catalog, schema: string): readonly string[];
26
+ /**
27
+ * Reports whether an index belongs to a view or a materialized view.
28
+ *
29
+ * Those indexes are created after the view, not with the tables.
30
+ *
31
+ * @param object - Catalog object
32
+ * @returns `true` when an index edge points at a view
33
+ */
34
+ export declare function ownedByView(object: CatalogObject): boolean;
26
35
  /**
27
36
  * SQL that drops one object.
28
37
  *
@@ -42,6 +51,53 @@ export declare function dropObjectSql(object: CatalogObject, schema: string): st
42
51
  * @returns The statement
43
52
  */
44
53
  export declare function createObjectSql(object: CatalogObject, schema: string): string | undefined;
54
+ /**
55
+ * `CREATE` or `CREATE OR REPLACE` for one function.
56
+ *
57
+ * A compatible signature change uses replace. The body is the stored source,
58
+ * or the `BEGIN ATOMIC` block when the function is atomic.
59
+ *
60
+ * @param object - Function to render
61
+ * @param schema - Concrete schema name
62
+ * @param replace - `CREATE OR REPLACE` when true
63
+ * @returns The statement
64
+ */
65
+ export declare function functionSql(object: FunctionObject, schema: string, replace: boolean): string;
66
+ /**
67
+ * `CREATE` or `CREATE OR REPLACE` for one view.
68
+ *
69
+ * Appending columns is replace. The query is the stored text.
70
+ *
71
+ * @param object - View to render
72
+ * @param schema - Concrete schema name
73
+ * @param replace - `CREATE OR REPLACE` when true
74
+ * @returns The statement
75
+ */
76
+ export declare function viewSql(object: ViewObject, schema: string, replace: boolean): string;
77
+ /**
78
+ * `CREATE MATERIALIZED VIEW ... WITH NO DATA`.
79
+ *
80
+ * Populate is a separate planned step. This statement does not read the table.
81
+ *
82
+ * @param object - Materialized view to render
83
+ * @param schema - Concrete schema name
84
+ * @returns The statement
85
+ */
86
+ export declare function materializedViewSql(object: MaterializedViewObject, schema: string): string;
87
+ /**
88
+ * `REFRESH MATERIALIZED VIEW`.
89
+ *
90
+ * A view created `WITH NO DATA` is empty, and Postgres rejects `CONCURRENTLY`
91
+ * until it has been populated once. The plan's populate step passes
92
+ * `populated: false`. A later refresh uses `CONCURRENTLY` when the declaration
93
+ * asked for it.
94
+ *
95
+ * @param object - Materialized view to refresh
96
+ * @param schema - Concrete schema name
97
+ * @param populated - `true` when the view already holds rows
98
+ * @returns The statement
99
+ */
100
+ export declare function refreshMaterializedViewSql(object: MaterializedViewObject, schema: string, populated?: boolean): string;
45
101
  /**
46
102
  * In-place column changes: type, nullability, and default.
47
103
  *
@@ -68,3 +124,11 @@ export declare function identitySequence(sequence: SequenceObject, source: Catal
68
124
  * @returns The statement
69
125
  */
70
126
  export declare function createTableSql(tableObject: TableObject, source: Catalog, schema: string): string;
127
+ /**
128
+ * Quotes a schema-qualified name.
129
+ *
130
+ * @param schema - Concrete schema name
131
+ * @param name - Object name
132
+ * @returns `"schema"."name"`
133
+ */
134
+ export declare function qualify(schema: string, name: string): string;