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
@@ -2,7 +2,7 @@
2
2
  * Enum and domain columns.
3
3
  *
4
4
  * The catalog column type is the type name. Compile records a dependency on
5
- * the enum, and `schema()` stores that enum as a catalog type.
5
+ * the type, and the column's `emit` adds that type when the catalog is built.
6
6
  */
7
7
  import { type ColumnBuilder, type ColumnFlags, type PlainFlags } from "./column.js";
8
8
  /**
@@ -17,14 +17,16 @@ import { type ColumnBuilder, type ColumnFlags, type PlainFlags } from "./column.
17
17
  */
18
18
  export declare function enumColumn<const TValues extends readonly string[]>(name: string, values: TValues): ColumnBuilder<TValues[number], PlainFlags>;
19
19
  /**
20
- * A named domain over a scalar column.
20
+ * A named domain over a column type.
21
21
  *
22
- * Domains are not catalog objects in this version. Calling the builder fails
23
- * with OKM1061 until 0.3, when a domain becomes a `type` subkind (D141).
22
+ * The TypeScript row type and the codec are the base column's. The catalog
23
+ * column type is the domain name, and the domain is a `type` object (D141).
24
+ * An enum base is OKM1060. Changing the base type of an existing domain is
25
+ * OKM1020 when the plan is built.
24
26
  *
25
27
  * @param name - Domain name
26
- * @param base - Scalar column the domain is based on
27
- * @param check - Domain check expression
28
- * @returns A domain column with the base codec, once 0.3 supports it
28
+ * @param base - Column the domain is based on
29
+ * @param check - Domain check expression, stored as written
30
+ * @returns A domain column
29
31
  */
30
- export declare function domain<TValue, TFlags extends ColumnFlags>(_name: string, _base: ColumnBuilder<TValue, TFlags>, _check: string): ColumnBuilder<TValue, PlainFlags>;
32
+ export declare function domain<TValue, TFlags extends ColumnFlags>(name: string, base: ColumnBuilder<TValue, TFlags>, check: string): ColumnBuilder<TValue, TFlags>;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * The `citext` extension.
3
+ *
4
+ * Case-insensitive equality is the column's ordinary `eq` once the type is
5
+ * `citext`. This module declares the extension so that column can build.
6
+ */
7
+ import { type Extension, type ExtensionOptions } from "./index.js";
8
+ /**
9
+ * Declares `citext`.
10
+ *
11
+ * @param options - Schema and version pin. The version differs by Postgres major, so the default is unpinned.
12
+ * @returns The extension object
13
+ */
14
+ export declare function citext(options?: ExtensionOptions): Extension;
@@ -0,0 +1,11 @@
1
+ import {
2
+ extension2
3
+ } from "../../../shared/ycatkxmq.js";
4
+
5
+ // src/dialects/pg/ext/citext.ts
6
+ function citext(options = {}) {
7
+ return extension2("citext", options);
8
+ }
9
+ export {
10
+ citext
11
+ };
@@ -0,0 +1,52 @@
1
+ /**
2
+ * `okmodel/ext`.
3
+ *
4
+ * `extension()` returns an object that produces its own catalog record.
5
+ * Duplicate and undeclared-use checks run here. Core only asks each declared
6
+ * object for its records.
7
+ */
8
+ import type { ExtensionObject } from "../../../contracts/catalog/types.js";
9
+ /** Options on {@link extension}. */
10
+ export type ExtensionOptions = {
11
+ /** Exact pin (`1.6`) or a floor (`>=0.7`). Omitted means unpinned. */
12
+ readonly version?: string;
13
+ /** Install schema. The default is `public`. */
14
+ readonly schema?: string;
15
+ /**
16
+ * Whether the extension may move.
17
+ *
18
+ * The default is `true`. A move of a non-relocatable extension is OKM1814.
19
+ */
20
+ readonly relocatable?: boolean;
21
+ };
22
+ /**
23
+ * One declared extension.
24
+ *
25
+ * Methods on a built-in, such as `pgTrgm.similar`, are the typed API. They
26
+ * are not stored in the catalog record.
27
+ */
28
+ export type Extension = {
29
+ readonly name: string;
30
+ readonly schema: string;
31
+ readonly relocatable: boolean;
32
+ readonly version?: string;
33
+ /**
34
+ * Catalog records for this declaration.
35
+ *
36
+ * @param peers - The `schema({ extensions })` list
37
+ * @param built - Objects the schema has already staged
38
+ * @returns The extension record
39
+ */
40
+ contribute(peers: unknown, built: unknown): readonly ExtensionObject[];
41
+ };
42
+ /**
43
+ * Declares an extension by name.
44
+ *
45
+ * A bare declaration has the full lifecycle and no typed operators. Built-ins
46
+ * wrap this and add their own methods.
47
+ *
48
+ * @param name - Extension name, such as `citext` or `vector`
49
+ * @param options - Schema, version pin, and whether it may move
50
+ * @returns The definition object `schema({ extensions })` stores
51
+ */
52
+ export declare function extension(name: string, options?: ExtensionOptions): Extension;
@@ -0,0 +1,6 @@
1
+ import {
2
+ extension2
3
+ } from "../../../shared/ycatkxmq.js";
4
+ export {
5
+ extension2 as extension
6
+ };
@@ -0,0 +1,53 @@
1
+ /**
2
+ * The `pg_trgm` extension.
3
+ *
4
+ * `similar` and `wordSimilar` are where-operators. Their SQL lives in the
5
+ * lazy operator module. Index methods set the catalog `expression` to a
6
+ * `using …` tail; the core index factory does not grow a `using` field.
7
+ */
8
+ import { type Tagged } from "../operators.js";
9
+ import type { IndexCall } from "../table.js";
10
+ import { type Extension, type ExtensionOptions } from "./index.js";
11
+ /** Operand stored on a trigram operator. */
12
+ export type TrigramQuery = {
13
+ readonly query: string;
14
+ readonly schema: string;
15
+ };
16
+ /** `pg_trgm` plus its operators and index methods. */
17
+ export type PgTrgm = Extension & {
18
+ /**
19
+ * `column % query`.
20
+ *
21
+ * @param query - The text to compare
22
+ * @returns A tagged where-operator
23
+ */
24
+ similar(query: string): Tagged<"similar", TrigramQuery>;
25
+ /**
26
+ * `column <% query`.
27
+ *
28
+ * @param query - The text to compare
29
+ * @returns A tagged where-operator
30
+ */
31
+ wordSimilar(query: string): Tagged<"wordSimilar", TrigramQuery>;
32
+ /**
33
+ * A GIN index with `gin_trgm_ops`.
34
+ *
35
+ * @param column - SQL column name
36
+ * @returns An index call whose expression is the `using` tail
37
+ */
38
+ gin(column: string): IndexCall;
39
+ /**
40
+ * A GiST index with `gist_trgm_ops`.
41
+ *
42
+ * @param column - SQL column name
43
+ * @returns An index call whose expression is the `using` tail
44
+ */
45
+ gist(column: string): IndexCall;
46
+ };
47
+ /**
48
+ * Declares `pg_trgm`.
49
+ *
50
+ * @param options - Schema and version pin
51
+ * @returns The extension object and its operators
52
+ */
53
+ export declare function pgTrgm(options?: ExtensionOptions): PgTrgm;
@@ -0,0 +1,42 @@
1
+ import {
2
+ extension2
3
+ } from "../../../shared/ycatkxmq.js";
4
+ import {
5
+ tag
6
+ } from "../../../shared/cn0n68ft.js";
7
+
8
+ // src/dialects/pg/ext/pg-trgm.ts
9
+ function pgTrgm(options = {}) {
10
+ const declared = extension2("pg_trgm", options);
11
+ const schema = declared.schema;
12
+ return {
13
+ ...declared,
14
+ similar(query) {
15
+ return tag("similar", { query, schema });
16
+ },
17
+ wordSimilar(query) {
18
+ return tag("wordSimilar", { query, schema });
19
+ },
20
+ gin(column) {
21
+ return usingIndex(column, "gin", "gin_trgm_ops");
22
+ },
23
+ gist(column) {
24
+ return usingIndex(column, "gist", "gist_trgm_ops");
25
+ }
26
+ };
27
+ }
28
+ function usingIndex(column, method, opclass) {
29
+ const quoted = `"${column.replaceAll('"', '""')}"`;
30
+ const call = {
31
+ columns: [column],
32
+ isUnique: false,
33
+ expression: `using ${method} (${quoted} ${opclass})`,
34
+ unique() {
35
+ return call;
36
+ }
37
+ };
38
+ return call;
39
+ }
40
+ export {
41
+ pgTrgm
42
+ };
@@ -0,0 +1,107 @@
1
+ /**
2
+ * `okmodel/fn`.
3
+ *
4
+ * `fn()` and `trigger()` return objects that produce their own catalog
5
+ * records. `schema()` only asks each declared object for those records.
6
+ */
7
+ import type { CatalogObject, FunctionLanguage, FunctionSecurity, FunctionVolatility, TriggerEvent, TriggerLevel, TriggerTiming } from "../../../contracts/catalog/types.js";
8
+ import type { AnyTable, SqlText } from "../table.js";
9
+ /** One argument of {@link fn}. */
10
+ export type FunctionArgumentInput = {
11
+ readonly name: string;
12
+ readonly type: string;
13
+ };
14
+ /**
15
+ * A table, or one column of a table.
16
+ *
17
+ * A table is an object dependency. `{ table, column }` is a column dependency.
18
+ * `column` is the SQL name.
19
+ */
20
+ export type DependsOn = AnyTable | {
21
+ readonly table: AnyTable;
22
+ readonly column: string;
23
+ };
24
+ /** Options for {@link fn}. */
25
+ export type FunctionOptions = {
26
+ readonly arguments?: readonly FunctionArgumentInput[];
27
+ readonly returns: string;
28
+ readonly language: FunctionLanguage;
29
+ readonly volatility?: FunctionVolatility;
30
+ readonly security?: FunctionSecurity;
31
+ /** Required when `security` is `"definer"` (OKM1823). */
32
+ readonly searchPath?: string;
33
+ readonly body: SqlText | string;
34
+ /**
35
+ * Tables and columns the body uses.
36
+ *
37
+ * Required for plpgsql (OKM1824). Omitted for `LANGUAGE sql` that begins
38
+ * with `BEGIN ATOMIC`; those edges are read from `pg_depend`.
39
+ */
40
+ readonly dependsOn?: readonly DependsOn[];
41
+ /** Schema. The default is `public`. */
42
+ readonly schema?: string;
43
+ };
44
+ /**
45
+ * One declared function.
46
+ *
47
+ * `contribute` builds the catalog record. Overloads differ by argument types.
48
+ */
49
+ export type Routine = {
50
+ readonly name: string;
51
+ readonly schema: string;
52
+ readonly argTypes: readonly string[];
53
+ /**
54
+ * Catalog record for this declaration.
55
+ *
56
+ * @param peers - The `schema({ functions })` list
57
+ * @param built - Objects the schema has already staged
58
+ * @returns The function record
59
+ */
60
+ contribute(peers: unknown, built: unknown): readonly CatalogObject[];
61
+ };
62
+ /** Options for {@link trigger}. */
63
+ export type TriggerOptions = {
64
+ readonly on: AnyTable;
65
+ readonly timing: TriggerTiming;
66
+ readonly events: readonly TriggerEvent[];
67
+ readonly level: TriggerLevel;
68
+ /** `UPDATE OF` columns. SQL names. Each one is a column dependency. */
69
+ readonly updateOf?: readonly string[];
70
+ readonly when?: SqlText | string;
71
+ readonly calls: Routine;
72
+ };
73
+ /**
74
+ * One declared trigger.
75
+ *
76
+ * Identity is `(table, name)`.
77
+ */
78
+ export type TriggerDeclaration = {
79
+ readonly name: string;
80
+ /**
81
+ * Catalog record for this declaration.
82
+ *
83
+ * @param peers - The `schema({ triggers })` list
84
+ * @param built - Objects the schema has already staged
85
+ * @returns The trigger record
86
+ */
87
+ contribute(peers: unknown, built: unknown): readonly CatalogObject[];
88
+ };
89
+ /**
90
+ * Declares a function.
91
+ *
92
+ * plpgsql without `dependsOn` is OKM1824. `security: "definer"` without
93
+ * `searchPath` is OKM1823.
94
+ *
95
+ * @param name - Function name
96
+ * @param options - Signature, language, body, and dependencies
97
+ * @returns The definition object `schema({ functions })` stores
98
+ */
99
+ export declare function fn(name: string, options: FunctionOptions): Routine;
100
+ /**
101
+ * Declares a trigger.
102
+ *
103
+ * @param name - Trigger name, unique on its table
104
+ * @param options - Table, timing, events, and the function it calls
105
+ * @returns The definition object `schema({ triggers })` stores
106
+ */
107
+ export declare function trigger(name: string, options: TriggerOptions): TriggerDeclaration;
@@ -0,0 +1,175 @@
1
+ import {
2
+ functionObject,
3
+ triggerObject
4
+ } from "../../../shared/9x25fxhc.js";
5
+ import {
6
+ staticNamespace2
7
+ } from "../../../shared/t4tbsy9h.js";
8
+ import {
9
+ OkmError2
10
+ } from "../../../shared/52szzakm.js";
11
+
12
+ // src/dialects/pg/fn/index.ts
13
+ function fn(name, options) {
14
+ const language = options.language;
15
+ const body = bodyText(options.body);
16
+ const atomic = language === "sql" && /^\s*begin\s+atomic\b/i.test(body);
17
+ if (language === "plpgsql" && options.dependsOn === undefined) {
18
+ throw new OkmError2("OKM1824", `Function ${name} is plpgsql and has no dependsOn. Postgres does not record dependencies inside the body.`, {
19
+ fix: {
20
+ summary: "List dependsOn. LANGUAGE sql with BEGIN ATOMIC is inferred and does not need the list."
21
+ }
22
+ });
23
+ }
24
+ if (options.security === "definer" && (options.searchPath === undefined || options.searchPath.trim().length === 0)) {
25
+ throw new OkmError2("OKM1823", `Function ${name} is security definer and has no search_path.`, {
26
+ fix: { summary: "Set search_path on the function to the schemas it is allowed to see." }
27
+ });
28
+ }
29
+ const argTypes = (options.arguments ?? []).map((argument) => argument.type);
30
+ const schema = options.schema ?? "public";
31
+ return {
32
+ name,
33
+ schema,
34
+ argTypes,
35
+ contribute(peers, built) {
36
+ assertPeers(peers, "functions");
37
+ const namespace = staticNamespace2(schema);
38
+ const provenance = { origin: "file", name };
39
+ return [
40
+ functionObject({
41
+ namespace,
42
+ name,
43
+ ...options.arguments !== undefined ? { arguments: options.arguments } : {},
44
+ returns: options.returns,
45
+ language,
46
+ ...options.volatility !== undefined ? { volatility: options.volatility } : {},
47
+ ...options.security !== undefined ? { security: options.security } : {},
48
+ ...options.searchPath !== undefined ? { searchPath: options.searchPath } : {},
49
+ body,
50
+ ...atomic ? { atomic: true } : {},
51
+ provenance,
52
+ dependencies: dependencyEdges(options.dependsOn, built)
53
+ })
54
+ ];
55
+ }
56
+ };
57
+ }
58
+ function trigger(name, options) {
59
+ return {
60
+ name,
61
+ contribute(peers, built) {
62
+ assertPeers(peers, "triggers");
63
+ const parent = tableRef(options.on, built);
64
+ const namespace = staticNamespace2(options.calls.schema);
65
+ const calls = {
66
+ namespace,
67
+ name: options.calls.name,
68
+ argTypes: options.calls.argTypes
69
+ };
70
+ if (!hasIdentity(built, { kind: "function", ...calls })) {
71
+ throw new OkmError2("OKM1020", `Trigger ${name} calls ${options.calls.name}, which is not in the catalog.`, { fix: { summary: "List the function in schema({ functions }) before the trigger." } });
72
+ }
73
+ for (const column of options.updateOf ?? []) {
74
+ if (!hasIdentity(built, { kind: "column", parent, name: column })) {
75
+ throw new OkmError2("OKM1020", `Trigger ${name} names column ${column}, which ${parent.name} does not have.`, { fix: { summary: "Name a column of the table the trigger is on." } });
76
+ }
77
+ }
78
+ return [
79
+ triggerObject({
80
+ parent,
81
+ name,
82
+ timing: options.timing,
83
+ events: options.events,
84
+ level: options.level,
85
+ calls,
86
+ ...options.updateOf !== undefined ? { updateOf: options.updateOf } : {},
87
+ ...options.when !== undefined ? { when: bodyText(options.when) } : {},
88
+ provenance: { origin: "file", name }
89
+ })
90
+ ];
91
+ }
92
+ };
93
+ }
94
+ function bodyText(body) {
95
+ return typeof body === "string" ? body : body.text;
96
+ }
97
+ function assertPeers(peers, option) {
98
+ if (!Array.isArray(peers)) {
99
+ throw new OkmError2("OKM1020", `schema({ ${option} }) must be a list.`, {
100
+ fix: { summary: `Pass an array to schema({ ${option} }).` }
101
+ });
102
+ }
103
+ }
104
+ function dependencyEdges(dependsOn, built) {
105
+ if (dependsOn === undefined)
106
+ return [];
107
+ return dependsOn.map((item) => {
108
+ if ("column" in item && "table" in item) {
109
+ const parent = tableRef(item.table, built);
110
+ const edge = { kind: "column", parent, name: item.column };
111
+ if (!hasIdentity(built, edge)) {
112
+ throw new OkmError2("OKM1020", `dependsOn names column ${item.column}, which ${parent.name} does not have.`, { fix: { summary: "Name a column of a table in this schema." } });
113
+ }
114
+ return edge;
115
+ }
116
+ const parent = tableRef(item, built);
117
+ return { kind: "table", namespace: parent.namespace, name: parent.name };
118
+ });
119
+ }
120
+ function tableRef(table, built) {
121
+ if (!Array.isArray(built)) {
122
+ throw new OkmError2("OKM1020", `Table ${table.name} is not in the catalog.`, {
123
+ fix: { summary: "List the table in schema({ tables })." }
124
+ });
125
+ }
126
+ for (const object of built) {
127
+ if (!isRecord(object) || object.kind !== "table")
128
+ continue;
129
+ const identity = object.identity;
130
+ const provenance = object.provenance;
131
+ if (!isRecord(identity) || !isRecord(provenance))
132
+ continue;
133
+ if (provenance.origin === "file" && provenance.name === table.name && typeof identity.name === "string") {
134
+ const namespace = identity.namespace;
135
+ if (isRecord(namespace) && namespace.form === "static" && typeof namespace.name === "string") {
136
+ return { namespace: staticNamespace2(namespace.name), name: identity.name };
137
+ }
138
+ }
139
+ }
140
+ throw new OkmError2("OKM1020", `Table ${table.name} is not in the catalog.`, {
141
+ fix: { summary: "List the table in schema({ tables })." }
142
+ });
143
+ }
144
+ function hasIdentity(built, identity) {
145
+ if (!Array.isArray(built))
146
+ return false;
147
+ for (const object of built) {
148
+ if (!isRecord(object) || !isRecord(object.identity))
149
+ continue;
150
+ if (same(object.identity, identity))
151
+ return true;
152
+ }
153
+ return false;
154
+ }
155
+ function same(left, right) {
156
+ if (left.kind !== right.kind)
157
+ return false;
158
+ if (right.kind === "function") {
159
+ return left.name === right.name && JSON.stringify(left.argTypes) === JSON.stringify(right.argTypes);
160
+ }
161
+ if (right.kind === "column") {
162
+ const parent = left.parent;
163
+ return left.name === right.name && isRecord(parent) && parent.name === right.parent.name;
164
+ }
165
+ if (right.kind === "table")
166
+ return left.name === right.name;
167
+ return false;
168
+ }
169
+ function isRecord(value) {
170
+ return typeof value === "object" && value !== null;
171
+ }
172
+ export {
173
+ fn,
174
+ trigger
175
+ };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * The trigger and function `timestamps({ enforce: "trigger" })` contributes.
3
+ *
4
+ * One function per updated-column SQL name. One trigger per table. Provenance
5
+ * is the timestamps trait. The body writes `new.<column> = now()`.
6
+ */
7
+ import type { CatalogObject } from "../../../contracts/catalog/types.js";
8
+ /**
9
+ * Catalog records for tables that carry the timestamps trait.
10
+ *
11
+ * @param built - Objects already staged, including columns
12
+ * @returns The function and one trigger per table, or nothing when no table opted in
13
+ */
14
+ export declare function timestampRecords(built: unknown): readonly CatalogObject[];
@@ -2,7 +2,7 @@ import {
2
2
  jsonReplacer2,
3
3
  json2,
4
4
  jsonb2
5
- } from "../../shared/yw5c610b.js";
5
+ } from "../../shared/gjthds9j.js";
6
6
  import {
7
7
  encodeInstant,
8
8
  decodeInstant,
@@ -14,17 +14,25 @@ import {
14
14
  time2,
15
15
  timetz2,
16
16
  interval2
17
- } from "../../shared/xkz8g6by.js";
18
- import {
19
- id2,
20
- uuid2
21
- } from "../../shared/ps43134h.js";
17
+ } from "../../shared/1g0drakv.js";
22
18
  import {
23
19
  one2,
24
20
  many2,
25
21
  manyThrough2,
26
22
  schema2
27
- } from "../../shared/7mht49yd.js";
23
+ } from "../../shared/3p4b1fg0.js";
24
+ import {
25
+ domainType
26
+ } from "../../shared/g7ez901n.js";
27
+ import {
28
+ id2,
29
+ uuid2
30
+ } from "../../shared/dyj86cmj.js";
31
+ import {
32
+ table2,
33
+ index2,
34
+ sql2
35
+ } from "../../shared/jsd07prz.js";
28
36
  import {
29
37
  text2,
30
38
  varchar2,
@@ -32,25 +40,27 @@ import {
32
40
  citext2,
33
41
  encodeText,
34
42
  decodeText
35
- } from "../../shared/sacqha1y.js";
36
- import {
37
- table2,
38
- index2,
39
- sql2
40
- } from "../../shared/x9v1qgeb.js";
43
+ } from "../../shared/4m9fn52z.js";
41
44
  import {
42
45
  ColumnBuilder2,
43
46
  required,
44
- openColumn
45
- } from "../../shared/dd4f8mnx.js";
47
+ openColumn,
48
+ formatType
49
+ } from "../../shared/c9z5g0fm.js";
46
50
  import {
47
51
  definition,
48
- unavailable,
49
52
  rejected
50
- } from "../../shared/xatfg0gn.js";
53
+ } from "../../shared/tmbdywx0.js";
54
+ import {
55
+ sameNamespace2,
56
+ compareText
57
+ } from "../../shared/t4tbsy9h.js";
51
58
  import {
52
59
  tag
53
60
  } from "../../shared/cn0n68ft.js";
61
+ import {
62
+ catalogError2
63
+ } from "../../shared/52szzakm.js";
54
64
  var __defProp = Object.defineProperty;
55
65
  var __returnValue = (v) => v;
56
66
  function __exportSetter(name, newValue) {
@@ -664,8 +674,83 @@ function enumColumn(name, values) {
664
674
  sqlForm: "quote"
665
675
  });
666
676
  }
667
- function domain(_name, _base, _check) {
668
- unavailable("t.domain() is not available yet. It arrives in 0.3.");
677
+ function domain(name, base, check) {
678
+ if (name.length === 0)
679
+ definition("domain name must be a non-empty type name.");
680
+ if (check.length === 0)
681
+ definition("domain check must be a non-empty expression.");
682
+ if (base.state.enumLabels !== undefined) {
683
+ definition("A domain cannot use an enum as its base in this version. Use a scalar column type.");
684
+ }
685
+ const baseSql = canonicalBase(formatType(base.state.baseType, base.state.dims));
686
+ const extension = base.state.extension;
687
+ const inner = base.state.baseType;
688
+ const nested = base.state.domain !== undefined;
689
+ return new ColumnBuilder2({
690
+ ...base.state,
691
+ baseType: name,
692
+ dims: 0,
693
+ typeDependency: name,
694
+ enumLabels: undefined,
695
+ domain: {
696
+ base: baseSql,
697
+ check,
698
+ emit(namespace, provenance, objects) {
699
+ base.state.domain?.emit?.(namespace, provenance, objects);
700
+ const dependencies = [];
701
+ if (extension !== undefined)
702
+ dependencies.push({ kind: "extension", name: extension });
703
+ if (nested)
704
+ dependencies.push({ kind: "type", namespace, name: inner });
705
+ const built = domainType({
706
+ namespace,
707
+ name,
708
+ base: baseSql,
709
+ check,
710
+ provenance,
711
+ ...dependencies.length > 0 ? { dependencies } : {}
712
+ });
713
+ const index = objects.findIndex((object) => object.kind === "type" && object.identity.name === name && sameNamespace2(object.identity.namespace, namespace));
714
+ const previous = index >= 0 ? objects[index] : undefined;
715
+ if (previous !== undefined && previous.kind === "type") {
716
+ const definition = previous.definition;
717
+ if (!("base" in definition) || definition.base !== baseSql || definition.check !== check) {
718
+ catalogError2("OKM1020", `Domain ${name} is ${"base" in definition ? definition.base : "an enum"} on ${previous.provenance.name} and ${baseSql} on ${provenance.name}. One domain has one base and one check.`);
719
+ }
720
+ if (compareText(provenance.name, previous.provenance.name) < 0)
721
+ objects[index] = built;
722
+ return;
723
+ }
724
+ objects.push(built);
725
+ }
726
+ }
727
+ });
728
+ }
729
+ function canonicalBase(typeName) {
730
+ const bracket = typeName.indexOf("[");
731
+ const scalar = bracket === -1 ? typeName : typeName.slice(0, bracket);
732
+ const suffix = bracket === -1 ? "" : typeName.slice(bracket);
733
+ return canonicalScalar(scalar) + suffix;
734
+ }
735
+ function canonicalScalar(typeName) {
736
+ const varchar = /^varchar\((\d+)\)$/.exec(typeName);
737
+ if (varchar !== null)
738
+ return `character varying(${varchar[1] ?? ""})`;
739
+ const fixed = /^char\((\d+)\)$/.exec(typeName);
740
+ if (fixed !== null)
741
+ return `character(${fixed[1] ?? ""})`;
742
+ const timed = /^(timestamptz|timestamp|timetz|time)(\(\d+\))?$/.exec(typeName);
743
+ if (timed === null)
744
+ return typeName;
745
+ const name = timed[1];
746
+ const precision = timed[2] ?? "";
747
+ if (name === "timestamptz")
748
+ return `timestamp${precision} with time zone`;
749
+ if (name === "timestamp")
750
+ return `timestamp${precision} without time zone`;
751
+ if (name === "timetz")
752
+ return `time${precision} with time zone`;
753
+ return `time${precision} without time zone`;
669
754
  }
670
755
  // src/dialects/pg/namespace.ts
671
756
  var t = {