okmodel 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (228) hide show
  1. package/README.md +727 -37
  2. package/dist/adapters/capabilities.d.ts +34 -0
  3. package/dist/adapters/pg/bunsql-extra.d.ts +17 -0
  4. package/dist/adapters/pg/bunsql.d.ts +60 -0
  5. package/dist/adapters/pg/call.d.ts +2 -12
  6. package/dist/adapters/pg/nodepostgres-extra.d.ts +18 -0
  7. package/dist/adapters/pg/nodepostgres.d.ts +57 -0
  8. package/dist/adapters/pg/postgres-extra.d.ts +50 -1
  9. package/dist/adapters/pg/postgresjs.d.ts +0 -4
  10. package/dist/adapters/pg/session.d.ts +94 -0
  11. package/dist/adapters/pg/watch.d.ts +18 -0
  12. package/dist/contracts/catalog/enum.d.ts +31 -4
  13. package/dist/contracts/catalog/extension.d.ts +61 -0
  14. package/dist/contracts/catalog/object.d.ts +1 -0
  15. package/dist/contracts/catalog/privilege.d.ts +64 -0
  16. package/dist/contracts/catalog/routine.d.ts +56 -0
  17. package/dist/contracts/catalog/types.d.ts +179 -18
  18. package/dist/contracts/catalog/view.d.ts +73 -0
  19. package/dist/contracts/connection.d.ts +13 -0
  20. package/dist/contracts/driver.d.ts +18 -5
  21. package/dist/contracts/error.d.ts +17 -1
  22. package/dist/contracts/generator.d.ts +63 -0
  23. package/dist/contracts/index.d.ts +2 -2
  24. package/dist/contracts/index.js +1 -1
  25. package/dist/contracts/internal.js +11 -9
  26. package/dist/contracts/location.d.ts +24 -0
  27. package/dist/contracts/rows.d.ts +15 -0
  28. package/dist/dialects/pg/archive-bind.d.ts +22 -0
  29. package/dist/dialects/pg/column.d.ts +129 -10
  30. package/dist/dialects/pg/compile.d.ts +1 -0
  31. package/dist/dialects/pg/custom.d.ts +6 -0
  32. package/dist/dialects/pg/ddl.d.ts +65 -1
  33. package/dist/dialects/pg/enum.d.ts +10 -8
  34. package/dist/dialects/pg/ext/citext.d.ts +14 -0
  35. package/dist/dialects/pg/ext/citext.js +11 -0
  36. package/dist/dialects/pg/ext/index.d.ts +52 -0
  37. package/dist/dialects/pg/ext/index.js +6 -0
  38. package/dist/dialects/pg/ext/pg-trgm.d.ts +53 -0
  39. package/dist/dialects/pg/ext/pg-trgm.js +42 -0
  40. package/dist/dialects/pg/filter-parse.d.ts +19 -0
  41. package/dist/dialects/pg/filters.d.ts +19 -0
  42. package/dist/dialects/pg/fn/index.d.ts +107 -0
  43. package/dist/dialects/pg/fn/index.js +175 -0
  44. package/dist/dialects/pg/fn/touch.d.ts +14 -0
  45. package/dist/dialects/pg/index.d.ts +11 -2
  46. package/dist/dialects/pg/index.js +243 -1062
  47. package/dist/dialects/pg/introspect.d.ts +10 -1
  48. package/dist/dialects/pg/keys.d.ts +19 -3
  49. package/dist/dialects/pg/model.d.ts +223 -2
  50. package/dist/dialects/pg/operator-fit.d.ts +86 -0
  51. package/dist/dialects/pg/operators.d.ts +46 -1
  52. package/dist/dialects/pg/ops/arr-append.d.ts +9 -0
  53. package/dist/dialects/pg/ops/arr-ns.d.ts +7 -0
  54. package/dist/dialects/pg/ops/arr-remove.d.ts +9 -0
  55. package/dist/dialects/pg/ops/containedBy.d.ts +9 -0
  56. package/dist/dialects/pg/ops/contains.d.ts +8 -4
  57. package/dist/dialects/pg/ops/hasAnyKey.d.ts +8 -0
  58. package/dist/dialects/pg/ops/hasKey.d.ts +8 -0
  59. package/dist/dialects/pg/ops/json-ns.d.ts +6 -0
  60. package/dist/dialects/pg/ops/json-set.d.ts +12 -0
  61. package/dist/dialects/pg/ops/matches.d.ts +16 -0
  62. package/dist/dialects/pg/ops/overlaps.d.ts +9 -0
  63. package/dist/dialects/pg/ops/path.d.ts +13 -0
  64. package/dist/dialects/pg/preset.d.ts +76 -0
  65. package/dist/dialects/pg/relations.d.ts +59 -2
  66. package/dist/dialects/pg/role/check.d.ts +45 -0
  67. package/dist/dialects/pg/role/index.d.ts +50 -0
  68. package/dist/dialects/pg/role/sql.d.ts +44 -0
  69. package/dist/dialects/pg/schema.d.ts +109 -5
  70. package/dist/dialects/pg/table.d.ts +137 -11
  71. package/dist/dialects/pg/temporal.d.ts +9 -7
  72. package/dist/dialects/pg/tenancy.d.ts +103 -0
  73. package/dist/dialects/pg/through.d.ts +21 -0
  74. package/dist/dialects/pg/trait.d.ts +141 -0
  75. package/dist/dialects/pg/view/client.d.ts +30 -0
  76. package/dist/dialects/pg/view/depend.d.ts +35 -0
  77. package/dist/dialects/pg/view/index.d.ts +114 -0
  78. package/dist/dialects/pg/view/index.js +289 -0
  79. package/dist/dialects/pg/view/scratch.d.ts +21 -0
  80. package/dist/dialects/pg/where.d.ts +37 -0
  81. package/dist/runtime/aggregate.d.ts +25 -0
  82. package/dist/runtime/archive-handle.d.ts +18 -0
  83. package/dist/runtime/archive-rules.d.ts +12 -0
  84. package/dist/runtime/archive.d.ts +73 -0
  85. package/dist/runtime/batch.d.ts +20 -0
  86. package/dist/runtime/client.d.ts +114 -5
  87. package/dist/runtime/conflict.d.ts +2 -1
  88. package/dist/runtime/exposure.d.ts +27 -0
  89. package/dist/runtime/hookm.d.ts +39 -0
  90. package/dist/runtime/ids/index.d.ts +11 -0
  91. package/dist/runtime/ids/index.js +193 -0
  92. package/dist/runtime/ids/okid-extended.d.ts +19 -0
  93. package/dist/runtime/ids/okid-generator.d.ts +21 -0
  94. package/dist/runtime/ids/okid-shared.d.ts +89 -0
  95. package/dist/runtime/ids/okid.d.ts +24 -0
  96. package/dist/runtime/ids/uuid.d.ts +21 -0
  97. package/dist/runtime/lock.d.ts +22 -0
  98. package/dist/runtime/operator-sql.d.ts +8 -0
  99. package/dist/runtime/page.d.ts +25 -0
  100. package/dist/runtime/pg/bun.d.ts +30 -0
  101. package/dist/runtime/pg/bun.js +52 -0
  102. package/dist/runtime/pg/pg.d.ts +29 -0
  103. package/dist/runtime/pg/pg.js +52 -0
  104. package/dist/runtime/pg/pglite.js +16 -17
  105. package/dist/runtime/pg/postgresjs.js +14 -24
  106. package/dist/runtime/plan.d.ts +146 -7
  107. package/dist/runtime/preset-stack.d.ts +17 -0
  108. package/dist/runtime/presets.d.ts +48 -0
  109. package/dist/runtime/read-stream.d.ts +26 -0
  110. package/dist/runtime/safety/index.d.ts +159 -0
  111. package/dist/runtime/safety/index.js +294 -0
  112. package/dist/runtime/safety-hook.d.ts +42 -0
  113. package/dist/runtime/server-check.d.ts +34 -0
  114. package/dist/runtime/tenancy/index.d.ts +37 -0
  115. package/dist/runtime/tenancy/index.js +368 -0
  116. package/dist/runtime/trait-read.d.ts +30 -0
  117. package/dist/runtime/traits/index.d.ts +133 -0
  118. package/dist/runtime/traits/index.js +646 -0
  119. package/dist/runtime/transaction.d.ts +19 -0
  120. package/dist/runtime/tx.d.ts +22 -7
  121. package/dist/runtime/types.d.ts +376 -27
  122. package/dist/runtime/validate/bind.d.ts +11 -0
  123. package/dist/runtime/validate/closed.d.ts +16 -0
  124. package/dist/runtime/validate/engine.d.ts +41 -0
  125. package/dist/runtime/validate/hook.d.ts +17 -0
  126. package/dist/runtime/validate/index.d.ts +21 -0
  127. package/dist/runtime/validate/index.js +175 -0
  128. package/dist/runtime/validate/load.d.ts +13 -0
  129. package/dist/runtime/validate/places.d.ts +41 -0
  130. package/dist/runtime/validate/rules.d.ts +108 -0
  131. package/dist/runtime/validate/surface.d.ts +102 -0
  132. package/dist/runtime/write.d.ts +30 -5
  133. package/dist/shared/01yr20s5.js +149 -0
  134. package/dist/shared/0jc3ffzf.js +154 -0
  135. package/dist/shared/0v1g424p.js +26 -0
  136. package/dist/shared/1g0drakv.js +225 -0
  137. package/dist/shared/{kprcwaha.js → 1tfdfvhh.js} +5 -3
  138. package/dist/shared/{05w44d8g.js → 2ssqrv66.js} +767 -715
  139. package/dist/shared/3ekj9x92.js +210 -0
  140. package/dist/shared/49ypnfwt.js +1122 -0
  141. package/dist/shared/4e4c6vq2.js +62 -0
  142. package/dist/shared/4m9fn52z.js +70 -0
  143. package/dist/shared/{ycwz42az.js → 52szzakm.js} +6 -26
  144. package/dist/shared/5nmdenb6.js +1229 -0
  145. package/dist/shared/672t5vym.js +12 -0
  146. package/dist/shared/6bazvqwm.js +86 -0
  147. package/dist/shared/6w5j844a.js +201 -0
  148. package/dist/shared/{fgqgsb5z.js → 75xkjv0t.js} +2 -2
  149. package/dist/shared/7fvtrkwr.js +84 -0
  150. package/dist/shared/7m88x3e9.js +45 -0
  151. package/dist/shared/{mtkwv8wx.js → 7p2wbz7f.js} +1 -1
  152. package/dist/shared/83eaefwr.js +10 -0
  153. package/dist/shared/94ez8kzh.js +19 -0
  154. package/dist/shared/96ps4g1z.js +32 -0
  155. package/dist/shared/{xqbhg6cn.js → 999ade2q.js} +95 -10
  156. package/dist/shared/9m80mkac.js +158 -0
  157. package/dist/shared/9x25fxhc.js +150 -0
  158. package/dist/shared/a5sxz52y.js +13 -0
  159. package/dist/shared/axhk06q1.js +156 -0
  160. package/dist/shared/{dynq16vb.js → b066g80h.js} +8 -6
  161. package/dist/shared/bqha5cg6.js +229 -0
  162. package/dist/shared/bryqk9k9.js +31 -0
  163. package/dist/shared/c8aghh05.js +442 -0
  164. package/dist/shared/c9z5g0fm.js +309 -0
  165. package/dist/shared/{m3ypagh5.js → dbjej1tw.js} +124 -15
  166. package/dist/shared/dyj86cmj.js +69 -0
  167. package/dist/shared/e6wg00wd.js +164 -0
  168. package/dist/shared/{hadrfb9h.js → edwqqryd.js} +17 -14
  169. package/dist/shared/{qk3hxfja.js → fptpmvxp.js} +5 -5
  170. package/dist/shared/fs0ex00p.js +76 -0
  171. package/dist/shared/{jjb7yht9.js → g4f5kcx9.js} +3 -3
  172. package/dist/shared/gjthds9j.js +48 -0
  173. package/dist/shared/hcmdtwgh.js +102 -0
  174. package/dist/shared/{g5fhqmwe.js → jkc6ws1p.js} +6 -56
  175. package/dist/shared/{yd1kzwn2.js → jns2wx4t.js} +55 -12
  176. package/dist/shared/k34e0xf2.js +450 -0
  177. package/dist/shared/k3ted12y.js +33 -0
  178. package/dist/shared/k7dwkhvq.js +31 -0
  179. package/dist/shared/{8b04d28c.js → kgnc8grt.js} +2 -2
  180. package/dist/shared/{hd293j9g.js → kyxb62mc.js} +14 -2
  181. package/dist/shared/m78s7898.js +376 -0
  182. package/dist/shared/m9tv7xn7.js +404 -0
  183. package/dist/shared/meck53jv.js +99 -0
  184. package/dist/shared/mt5wswjz.js +90 -0
  185. package/dist/shared/n0dgs0pb.js +75 -0
  186. package/dist/shared/n442h54c.js +14 -0
  187. package/dist/shared/n4jqhpqz.js +27 -0
  188. package/dist/shared/n7mcc1gk.js +132 -0
  189. package/dist/shared/ne02ng5c.js +68 -0
  190. package/dist/shared/{mkjmqjv4.js → nfzc5z0w.js} +2 -104
  191. package/dist/shared/nsva2a6b.js +42 -0
  192. package/dist/shared/p24x2334.js +195 -0
  193. package/dist/shared/qbxzvwwc.js +88 -0
  194. package/dist/shared/{w8samvk1.js → qybh48nd.js} +1 -1
  195. package/dist/shared/r6nwkxnt.js +86 -0
  196. package/dist/shared/{xy79j5hq.js → rrstp3kb.js} +25 -36
  197. package/dist/shared/rwmrejjz.js +26 -0
  198. package/dist/shared/{zhc5vmgf.js → s6gqfn5j.js} +2 -2
  199. package/dist/shared/{523ft3e8.js → scwxrpx2.js} +7 -5
  200. package/dist/shared/{j5cn2963.js → t4tbsy9h.js} +13 -64
  201. package/dist/shared/{y9m15dfv.js → t616ynfn.js} +544 -32
  202. package/dist/shared/{ngk8gj61.js → tbszx8mz.js} +15 -1
  203. package/dist/shared/th14ygv2.js +69 -0
  204. package/dist/shared/tmbdywx0.js +178 -0
  205. package/dist/shared/ty3v3hfk.js +64 -0
  206. package/dist/shared/wekze34d.js +246 -0
  207. package/dist/shared/x6wysh83.js +1132 -0
  208. package/dist/shared/{rgs0st28.js → xrfnq5k8.js} +237 -434
  209. package/dist/shared/{x5x59srr.js → xva8v7qk.js} +416 -83
  210. package/dist/shared/{dkn3y60a.js → xw1d69vd.js} +76 -112
  211. package/dist/shared/y005b761.js +112 -0
  212. package/dist/shared/ydaz1sv3.js +55 -0
  213. package/dist/shared/{p0cbr3g2.js → zwmqxb0g.js} +1 -1
  214. package/dist/tooling/cli.js +40 -12
  215. package/dist/tooling/migrate/apply.d.ts +16 -0
  216. package/dist/tooling/migrate/commands.d.ts +12 -1
  217. package/dist/tooling/migrate/config.d.ts +8 -0
  218. package/dist/tooling/migrate/doctor.d.ts +25 -0
  219. package/dist/tooling/migrate/drift.d.ts +19 -0
  220. package/dist/tooling/migrate/engine.d.ts +36 -0
  221. package/dist/tooling/migrate/ext.d.ts +17 -0
  222. package/dist/tooling/migrate/extensions.d.ts +51 -0
  223. package/dist/tooling/migrate/managed.d.ts +17 -0
  224. package/dist/tooling/migrate/plan.d.ts +14 -1
  225. package/dist/tooling/migrate/project.d.ts +25 -1
  226. package/dist/tooling/migrate/type-name.d.ts +19 -0
  227. package/package.json +61 -4
  228. package/dist/shared/gk7cs7sp.js +0 -566
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Preset types and the names a preset may not take (spec section 6.2, D41, D125).
3
+ *
4
+ * A preset is a named, typed refinement of a table: `tasks.pending()`. It gets
5
+ * a builder with one additive method, `where`, and returns that builder. The
6
+ * builder has no method that removes or replaces a predicate, so a preset can
7
+ * only narrow what the caller, tenancy, and the active set already allow.
8
+ *
9
+ * Only types and one list live here. The code that runs presets loads on the
10
+ * first call (`runtime/presets.ts`).
11
+ */
12
+ import type { Or } from "./operators.js";
13
+ import type { FieldWhere } from "./where.js";
14
+ /**
15
+ * What a preset receives.
16
+ *
17
+ * Every method adds. There is no method that removes or replaces a predicate
18
+ * (D125, D126), and the tenant and active-set predicates are not in the
19
+ * builder at all: the planner puts them around it.
20
+ *
21
+ * @typeParam Row - The table's row
22
+ */
23
+ export type PresetQuery<Row> = {
24
+ /**
25
+ * Adds a predicate, joined with the others by AND.
26
+ *
27
+ * Earlier predicates stay, whether the caller's, another preset's, or this
28
+ * preset's own.
29
+ *
30
+ * @param filter - Fields and operators, or `or(...)`
31
+ * @returns The same builder
32
+ */
33
+ where(filter: FieldWhere<Row> | Or<FieldWhere<Row>>): PresetQuery<Row>;
34
+ };
35
+ /**
36
+ * One preset: the builder first, then the preset's own typed arguments.
37
+ *
38
+ * @typeParam Row - The table's row
39
+ */
40
+ export type Preset<Row> = (q: PresetQuery<Row>, ...args: never[]) => PresetQuery<Row>;
41
+ /**
42
+ * Names a preset may not take (OKM1040).
43
+ *
44
+ * The first group are client methods. The second is reserved for later
45
+ * releases. `then` would make a table handle look like a promise.
46
+ */
47
+ export type ReservedPreset = "find" | "one" | "page" | "aggregate" | "count" | "exists" | "insert" | "update" | "delete" | "archive" | "restore" | "withArchived" | "onlyArchived" | "then" | "lock" | "watch" | "subscribe" | "stream" | "inspect" | "explain" | "with" | "for" | "as";
48
+ /**
49
+ * The `presets` option. A reserved name is a type error here, and OKM1040 when
50
+ * the schema is used.
51
+ *
52
+ * @typeParam Row - The table's row
53
+ */
54
+ export type PresetMap<Row> = {
55
+ readonly [name: string]: Preset<Row>;
56
+ } & {
57
+ readonly [N in ReservedPreset]?: never;
58
+ };
59
+ /** Names {@link ReservedPreset} lists, for the runtime check. */
60
+ export declare const RESERVED_PRESETS: ReadonlySet<string>;
61
+ /**
62
+ * Throws OKM1040 when a preset name is a client method or reserved.
63
+ *
64
+ * @param names - Preset names from one table or one trait
65
+ * @param where - What defines them, for the message: `table tasks` or `trait softDelete`
66
+ */
67
+ export declare function checkPresetNames(names: Iterable<string>, where: string): void;
68
+ /**
69
+ * Throws OKM1040 for a preset name defined by two sources.
70
+ *
71
+ * @param name - The preset name
72
+ * @param table - Table that ends up with both
73
+ * @param first - What defined it first: `table tasks` or `trait softDelete`
74
+ * @param second - What defines it again
75
+ */
76
+ export declare function duplicatePreset(name: string, table: string, first: string, second: string): never;
@@ -1,9 +1,11 @@
1
1
  /**
2
- * `one` and `many` relations.
2
+ * `one`, `many`, and `manyThrough` relations.
3
3
  *
4
4
  * They name a table. `schema()` resolves the foreign key. An ambiguous key
5
- * is OKM1021. `manyThrough` arrives in 0.2. `morph` stays reserved.
5
+ * is OKM1021. `manyThrough` names the join table as well and carries its own
6
+ * resolver, so a schema without one does not pay for it. `morph` stays reserved.
6
7
  */
8
+ import type { RelationModel } from "./model.js";
7
9
  /** A to-one relation. `field` is the local foreign key when the table has several. */
8
10
  export type OneRelation<TTable extends string = string> = {
9
11
  readonly kind: "one";
@@ -16,6 +18,46 @@ export type ManyRelation<TTable extends string = string> = {
16
18
  readonly table: TTable;
17
19
  readonly field: string | undefined;
18
20
  };
21
+ /** A foreign key `schema()` resolved, as a relation resolver sees it. */
22
+ export type RelationEdge = {
23
+ readonly fromTable: string;
24
+ readonly fromField: string;
25
+ readonly toTable: string;
26
+ /** Local SQL names, one column or a composite key. */
27
+ readonly local: readonly string[];
28
+ /** Referenced SQL names, in the same order. */
29
+ readonly remote: readonly string[];
30
+ };
31
+ /** What a relation's own resolver reads from `schema()`. */
32
+ export type RelationScope = {
33
+ /** The table that declares the relation. */
34
+ readonly owner: string;
35
+ /** The relation name. */
36
+ readonly name: string;
37
+ readonly edges: readonly RelationEdge[];
38
+ /** Every table name in the schema, sorted. */
39
+ readonly tables: readonly string[];
40
+ };
41
+ /**
42
+ * A to-many relation through a join table.
43
+ *
44
+ * It is a {@link ManyRelation} to the types, so `include`, `has`, `none`, and
45
+ * `every` read it as one. `resolve` is what `schema()` calls in place of the
46
+ * foreign-key search that `many` uses.
47
+ */
48
+ export type ManyThroughRelation<TTable extends string = string> = ManyRelation<TTable> & {
49
+ /** The join table. */
50
+ readonly through: string;
51
+ /** Turns this declaration into a resolved model. */
52
+ readonly resolve: (scope: RelationScope) => RelationModel;
53
+ };
54
+ /** Join-table foreign keys, named only when more than one points at a table. */
55
+ export type ThroughKeys = {
56
+ /** The join table field that references the declaring table. */
57
+ readonly from?: string;
58
+ /** The join table field that references the related table. */
59
+ readonly to?: string;
60
+ };
19
61
  /** A relation `table()` stores. */
20
62
  export type RelationCall = OneRelation | ManyRelation;
21
63
  /**
@@ -43,3 +85,18 @@ export declare function many<const TTable extends string>(table: TTable, field?:
43
85
  * @returns `true` for `one` and `many`
44
86
  */
45
87
  export declare function isRelationCall(value: unknown): value is RelationCall;
88
+ /**
89
+ * Declares a to-many relation through a join table.
90
+ *
91
+ * The join table has one foreign key to the declaring table and one to the
92
+ * related table. Name `from` and `to` when a table has more than one. Tenancy
93
+ * and archivable apply to the join rows and to the related rows alike.
94
+ *
95
+ * @typeParam TTable - Related table
96
+ * @param table - Related table name
97
+ * @param options - The join table, and its foreign-key fields when ambiguous
98
+ * @returns The relation `schema()` resolves
99
+ */
100
+ export declare function manyThrough<const TTable extends string>(table: TTable, options: {
101
+ readonly through: string;
102
+ } & ThroughKeys): ManyThroughRelation<TTable>;
@@ -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,44 @@
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 string[];
12
+ /** Role creates, role alters, and default privileges. Before new tables. */
13
+ readonly prepare: readonly string[];
14
+ /** Grants on objects that exist, or that this plan creates first. */
15
+ readonly grant: readonly string[];
16
+ };
17
+ /**
18
+ * Diffs role, grant, and default-privilege objects into SQL.
19
+ *
20
+ * A role is created only when it is managed and absent. It is altered only
21
+ * when both sides are managed. It is never dropped. Grants and default
22
+ * privileges are revoked and granted. None of the statements use
23
+ * `IF NOT EXISTS`.
24
+ *
25
+ * @param before - Previous catalog objects
26
+ * @param after - Next catalog objects
27
+ * @param schema - Concrete schema name
28
+ * @returns Statements in three groups
29
+ */
30
+ export declare function privilegeSql(before: readonly CatalogObject[], after: readonly CatalogObject[], schema: string): PrivilegeSql;
31
+ /**
32
+ * Role name in `create role`, when the statement is one.
33
+ *
34
+ * @param sql - One plan statement
35
+ * @returns The role, or `undefined` when the statement is not `CREATE ROLE`
36
+ */
37
+ export declare function createdRoleName(sql: string): string | undefined;
38
+ /**
39
+ * Reports whether a statement creates or alters a role.
40
+ *
41
+ * @param sql - One plan statement
42
+ * @returns `true` for `CREATE ROLE` and `ALTER ROLE`
43
+ */
44
+ export declare function changesRole(sql: string): boolean;
@@ -4,8 +4,11 @@
4
4
  * Work happens here, not in `table()` and not at import.
5
5
  */
6
6
  import type { Catalog } from "../../contracts/catalog/types.js";
7
- import { type TableModel } from "./model.js";
8
- import { type AnyTable } from "./table.js";
7
+ import { type ClientGenerator } from "../../contracts/generator.js";
8
+ import { type SchemaHook, type TableModel } from "./model.js";
9
+ import type { FieldsOfList, HasArchive, PresetsOfList, Trait } from "./trait.js";
10
+ import { type ColumnTenancy, type TenantFields } from "./tenancy.js";
11
+ import { type AnyTable, type InsertFrom, type RowFrom, type UpdateFrom } from "./table.js";
9
12
  /** Codec defaults from spec section 6.6. */
10
13
  export type SchemaCodecs = {
11
14
  readonly bigint: "string" | "number" | "bigint";
@@ -33,8 +36,28 @@ export type SchemaInput<TTables extends readonly AnyTable[]> = {
33
36
  readonly timestamps?: SchemaCodecs["timestamps"];
34
37
  };
35
38
  readonly types?: "emitted" | "inferred";
36
- readonly traits?: unknown;
37
- readonly tenancy?: unknown;
39
+ /**
40
+ * What a bare `t.id()` means.
41
+ *
42
+ * `"uuidv7"` and `"uuidv4"` are database defaults. A client generator is
43
+ * filled on insert and stays out of the catalog. A column option wins.
44
+ */
45
+ readonly defaults?: {
46
+ readonly id?: "uuidv7" | "uuidv4" | ClientGenerator<string>;
47
+ };
48
+ /**
49
+ * Traits applied to every table.
50
+ *
51
+ * A table opts out with `omitDefaults` and a reason. A table's own `traits`
52
+ * are added as well.
53
+ */
54
+ readonly traits?: readonly Trait[];
55
+ /**
56
+ * Column tenancy.
57
+ *
58
+ * Every table gains the key unless it passes `global("reason")`.
59
+ */
60
+ readonly tenancy?: ColumnTenancy;
38
61
  readonly validation?: unknown;
39
62
  readonly extensions?: unknown;
40
63
  readonly functions?: unknown;
@@ -59,11 +82,68 @@ export type BuiltSchema<TTables extends readonly AnyTable[]> = {
59
82
  readonly codecs: SchemaCodecs;
60
83
  readonly requires: SchemaRequires | undefined;
61
84
  readonly tables: TTables;
85
+ /**
86
+ * Schema traits, when the call passed a non-empty list.
87
+ *
88
+ * Omitted otherwise, so a schema that uses no traits does not carry the key.
89
+ */
90
+ readonly traits?: readonly Trait[];
91
+ /**
92
+ * Column tenancy, when the call passed it.
93
+ *
94
+ * Omitted otherwise, so a schema with no tenancy does not carry the key.
95
+ */
96
+ readonly tenancy?: ColumnTenancy;
62
97
  /** Query model. Built once, beside the catalog document. */
63
98
  readonly model: {
64
99
  readonly [T in TTables[number] as T["~name"]]: TableModel;
65
100
  };
66
101
  };
102
+ /**
103
+ * A schema whose tenant tables carry the tenant key on the row.
104
+ *
105
+ * A table marked `~global` keeps its own type. No tenancy leaves the schema
106
+ * type unchanged.
107
+ *
108
+ * @typeParam S - Schema type before tenancy
109
+ * @typeParam TTables - Tables in declaration order
110
+ * @typeParam TTenancy - Column tenancy, or `undefined`
111
+ */
112
+ export type TenancySchema<S, TTables extends readonly AnyTable[], TTenancy> = TTenancy extends ColumnTenancy ? Omit<S, "~byName"> & {
113
+ readonly tenancy: TTenancy;
114
+ readonly "~byName": {
115
+ readonly [T in TTables[number] as T["~name"]]: T extends {
116
+ readonly "~global": string;
117
+ } ? T : T & {
118
+ readonly "~row": RowFrom<TenantFields<TTenancy["key"]>>;
119
+ readonly "~insert": InsertFrom<TenantFields<TTenancy["key"]>>;
120
+ readonly "~update": UpdateFrom<TenantFields<TTenancy["key"]>>;
121
+ };
122
+ };
123
+ } : S;
124
+ /**
125
+ * A schema whose default traits are part of every table's row type.
126
+ *
127
+ * A table with `omitDefaults` keeps its own type. An empty trait list does not
128
+ * change the schema type.
129
+ *
130
+ * @typeParam TTables - Tables in declaration order
131
+ * @typeParam TTraits - Schema default traits
132
+ */
133
+ export type SchemaWithTraits<TTables extends readonly AnyTable[], TTraits extends readonly {
134
+ readonly fields: Readonly<Record<string, object>>;
135
+ }[]> = [keyof FieldsOfList<TTraits> | keyof PresetsOfList<TTraits>] extends [never] ? BuiltSchema<TTables> : Omit<BuiltSchema<TTables>, "~byName"> & {
136
+ readonly "~byName": {
137
+ readonly [T in TTables[number] as T["~name"]]: ApplySchemaTraits<T, FieldsOfList<TTraits>, TTraits>;
138
+ };
139
+ };
140
+ type ApplySchemaTraits<TTable, TFields, TTraits> = TTable extends {
141
+ readonly "~omitDefaults": true;
142
+ } ? TTable : TTable & {
143
+ readonly "~row": RowFrom<TFields>;
144
+ readonly "~insert": InsertFrom<TFields>;
145
+ readonly "~update": UpdateFrom<TFields>;
146
+ } & HasArchive<TTraits> & PresetsOfList<TTraits>;
67
147
  /**
68
148
  * Compiles tables into a catalog.
69
149
  *
@@ -74,4 +154,28 @@ export type BuiltSchema<TTables extends readonly AnyTable[]> = {
74
154
  * @param config - Tables, casing, codecs, and the row-type mode
75
155
  * @returns The schema and its catalog
76
156
  */
77
- export declare function schema<const TTables extends readonly AnyTable[]>(config: SchemaInput<TTables>): BuiltSchema<TTables>;
157
+ export declare function schema<const TTables extends readonly AnyTable[], const TTraits extends readonly {
158
+ readonly fields: Readonly<Record<string, object>>;
159
+ }[], const TTenancy extends ColumnTenancy | undefined = undefined, const TValidation = undefined>(config: Omit<SchemaInput<TTables>, "traits" | "tenancy" | "validation"> & {
160
+ readonly traits: TTraits;
161
+ readonly tenancy?: TTenancy;
162
+ readonly validation?: TValidation;
163
+ }): [TValidation] extends [undefined] ? TenancySchema<SchemaWithTraits<TTables, TTraits>, TTables, TTenancy> : TenancySchema<SchemaWithTraits<TTables, TTraits>, TTables, TTenancy> & {
164
+ readonly "~validation": TValidation;
165
+ };
166
+ export declare function schema<const TTables extends readonly AnyTable[], const TTenancy extends ColumnTenancy | undefined = undefined, const TValidation = undefined>(config: Omit<SchemaInput<TTables>, "tenancy" | "validation"> & {
167
+ readonly tenancy?: TTenancy;
168
+ readonly validation?: TValidation;
169
+ }): [TValidation] extends [undefined] ? TenancySchema<BuiltSchema<TTables>, TTables, TTenancy> : TenancySchema<BuiltSchema<TTables>, TTables, TTenancy> & {
170
+ readonly "~validation": TValidation;
171
+ };
172
+ /**
173
+ * Registers a hook from an opt-in module.
174
+ *
175
+ * Core does not import that module. A featureless app never calls this, so
176
+ * the module that loads the validation engine stays out of its graph.
177
+ *
178
+ * @param hook - Called for the client and for each table
179
+ */
180
+ export declare function addSchemaHook(hook: SchemaHook): void;
181
+ export {};
@@ -6,6 +6,8 @@
6
6
  */
7
7
  import { type ColumnInsertOf, type ColumnRowOf, type ColumnUpdateOf } from "./column.js";
8
8
  import { type RelationCall } from "./relations.js";
9
+ import type { PresetMap } from "./preset.js";
10
+ import { type FieldsOfList, type HasArchive, type PresetsOfList, type Trait } from "./trait.js";
9
11
  /**
10
12
  * A column as seen by `indexes` and `checks`.
11
13
  *
@@ -20,6 +22,19 @@ export type ColumnHandle = {
20
22
  export type IndexCall = {
21
23
  readonly columns: readonly string[];
22
24
  readonly isUnique: boolean;
25
+ /**
26
+ * Partial-index predicate, stored as the catalog wrote it.
27
+ *
28
+ * Absent on an ordinary index.
29
+ */
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;
23
38
  /**
24
39
  * Marks the index unique.
25
40
  *
@@ -52,16 +67,50 @@ export type TableOptions<TColumns> = {
52
67
  readonly unique?: {
53
68
  readonly [name: string]: readonly (keyof TColumns & string)[];
54
69
  };
70
+ /**
71
+ * Composite primary key, in column order.
72
+ *
73
+ * A single-column key can use this or `.primaryKey()` on the column.
74
+ * One table has one primary key.
75
+ */
76
+ readonly primaryKey?: readonly (keyof TColumns & string)[];
55
77
  readonly sqlName?: string;
56
78
  readonly renamedFrom?: string;
57
79
  readonly comment?: string;
58
80
  readonly validate?: unknown;
59
81
  readonly validation?: unknown;
60
- readonly traits?: unknown;
61
- readonly omitDefaults?: unknown;
62
- readonly tenancy?: unknown;
82
+ /**
83
+ * Traits added to this table.
84
+ *
85
+ * Schema default traits are added as well, unless `omitDefaults` is set.
86
+ */
87
+ readonly traits?: readonly Trait[];
88
+ /**
89
+ * Skip schema default traits.
90
+ *
91
+ * The value is the reason. An empty reason is rejected when the schema is built.
92
+ */
93
+ readonly omitDefaults?: string;
94
+ /**
95
+ * Opts this table out of schema tenancy.
96
+ *
97
+ * `global("reason")` is the opt-out. `{ via }` arrives later.
98
+ */
99
+ readonly tenancy?: {
100
+ readonly kind: "global";
101
+ readonly reason: string;
102
+ } | {
103
+ readonly via: string;
104
+ };
63
105
  readonly computed?: unknown;
64
- readonly presets?: unknown;
106
+ /**
107
+ * Named, typed refinements called as `tasks.pending()`.
108
+ *
109
+ * A preset gets a builder and its own arguments and returns the builder.
110
+ * The builder only adds predicates. A name that is a client method or is
111
+ * reserved is OKM1040.
112
+ */
113
+ readonly presets?: PresetMap<RowFrom<TColumns>>;
65
114
  readonly policies?: unknown;
66
115
  readonly reference?: unknown;
67
116
  /** `one` and `many`. Other relation kinds stay reserved. */
@@ -85,16 +134,39 @@ export type Handles<TColumns> = {
85
134
  * @typeParam TColumns - Column builders
86
135
  * @typeParam TRelations - Relations declared on this table
87
136
  */
88
- export type Table<TName extends string, TColumns, TRelations extends Readonly<Record<string, RelationCall>> = Readonly<Record<string, never>>> = {
137
+ export type Table<TName extends string, TColumns, TRelations extends Readonly<Record<string, RelationCall>> = Readonly<Record<string, never>>, TKey extends string = never, TOptions = object> = {
89
138
  readonly "~name": TName;
90
139
  readonly "~columns": TColumns;
91
140
  readonly "~row": RowFrom<TColumns>;
92
141
  readonly "~insert": InsertFrom<TColumns>;
93
- readonly "~update": UpdateFrom<TColumns>;
142
+ readonly "~update": UpdateFrom<TColumns, TKey>;
94
143
  readonly "~relations": TRelations;
95
144
  readonly name: TName;
96
145
  readonly columns: TColumns;
97
- readonly options?: TableOptions<TColumns>;
146
+ readonly options?: TOptions;
147
+ /**
148
+ * Allowlisted client filters.
149
+ *
150
+ * A hidden field in `allow`, `sort`, or `relations` throws OKM1123 here.
151
+ * `parse` loads the parser on first use.
152
+ *
153
+ * @param spec - Fields, operators, and sorts the caller may send
154
+ * @returns A parser for one request object
155
+ */
156
+ filters(spec: FilterSpec): {
157
+ parse(query: unknown): Promise<ParsedFilters>;
158
+ };
159
+ };
160
+ /** What {@link Table.filters} accepts. */
161
+ export type FilterSpec = {
162
+ readonly allow?: Readonly<Record<string, readonly string[]>>;
163
+ readonly sort?: readonly string[];
164
+ readonly relations?: Readonly<Record<string, readonly string[]>>;
165
+ };
166
+ /** `where` and `orderBy` a caller can spread into `find`. */
167
+ export type ParsedFilters = {
168
+ readonly where: Readonly<Record<string, unknown>>;
169
+ readonly orderBy?: Readonly<Record<string, "asc" | "desc">>;
98
170
  };
99
171
  /**
100
172
  * Any table `schema()` can compile.
@@ -108,6 +180,8 @@ export type AnyTable = {
108
180
  readonly name: string;
109
181
  readonly columns: Readonly<Record<string, object>>;
110
182
  readonly options?: object;
183
+ /** `file.ts:line` of the `table()` call. Not part of the catalog hash. */
184
+ readonly source?: string;
111
185
  };
112
186
  /**
113
187
  * Row shape. Hidden columns are omitted.
@@ -130,8 +204,8 @@ export type InsertFrom<TColumns> = {
130
204
  *
131
205
  * @typeParam TColumns - Column builders
132
206
  */
133
- export type UpdateFrom<TColumns> = {
134
- readonly [K in keyof TColumns as ColumnUpdateOf<TColumns[K]> extends never ? never : K]: ColumnUpdateOf<TColumns[K]>;
207
+ export type UpdateFrom<TColumns, TKey extends string = never> = {
208
+ readonly [K in keyof TColumns as K extends TKey ? never : ColumnUpdateOf<TColumns[K]> extends never ? never : K]: ColumnUpdateOf<TColumns[K]>;
135
209
  };
136
210
  /**
137
211
  * Declares a table.
@@ -145,8 +219,8 @@ export type UpdateFrom<TColumns> = {
145
219
  * @param options - Indexes, checks, unique constraints, and names
146
220
  * @returns The table
147
221
  */
148
- export declare function table<const TName extends string, const TColumns extends Readonly<Record<string, object>>>(name: TName, columns: TColumns): Table<TName, TColumns, Readonly<Record<string, never>>>;
149
- export declare function table<const TName extends string, const TColumns extends Readonly<Record<string, object>>, const TOptions extends TableOptions<TColumns>>(name: TName, columns: TColumns, options: TOptions): Table<TName, TColumns, RelationsOf<TOptions>>;
222
+ export declare function table<const TName extends string, const TColumns extends Readonly<Record<string, object>>>(name: TName, columns: TColumns): Table<TName, TColumns, Readonly<Record<string, never>>, never>;
223
+ export declare function table<const TName extends string, const TColumns extends Readonly<Record<string, object>>, const TOptions extends TableOptions<TColumns>>(name: TName, columns: TColumns, options: TOptions): DeclaredTable<TName, TColumns, TOptions>;
150
224
  /**
151
225
  * Relation map stored on a table.
152
226
  *
@@ -158,6 +232,58 @@ export declare function table<const TName extends string, const TColumns extends
158
232
  type RelationsOf<TOptions> = TOptions extends {
159
233
  readonly relations: infer R;
160
234
  } ? R extends Readonly<Record<string, RelationCall>> ? R : Readonly<Record<string, never>> : Readonly<Record<string, never>>;
235
+ /**
236
+ * Column names listed in a table's `primaryKey` option.
237
+ *
238
+ * Absent when the option is omitted, so a table without it does not change
239
+ * its update shape.
240
+ *
241
+ * @typeParam TOptions - Options argument
242
+ */
243
+ type PrimaryOf<TOptions> = TOptions extends {
244
+ readonly primaryKey: infer K;
245
+ } ? K extends readonly (infer F)[] ? Extract<F, string> : never : never;
246
+ /**
247
+ * Table type callers see, including trait fields and an opt-out of schema traits.
248
+ *
249
+ * @typeParam TName - Table name
250
+ * @typeParam TColumns - Column builders
251
+ * @typeParam TOptions - Options argument
252
+ */
253
+ type DeclaredTable<TName extends string, TColumns, TOptions> = Table<TName, TColumns, RelationsOf<TOptions>, PrimaryOf<TOptions>, NoInfer<TOptions>> & TraitShapes<TColumns, TOptions> & ArchiveFlag<TOptions> & PresetFlag<TOptions> & OmitFlag<TOptions> & GlobalFlag<TOptions>;
254
+ type ArchiveFlag<TOptions> = TOptions extends {
255
+ readonly traits: infer TTraits;
256
+ } ? HasArchive<TTraits> : unknown;
257
+ /** `{ "~presets" }` from the table's own `presets` and its traits' presets, when there are any. */
258
+ type PresetFlag<TOptions> = (TOptions extends {
259
+ readonly presets: infer TPresets;
260
+ } ? {
261
+ readonly "~presets": TPresets;
262
+ } : unknown) & (TOptions extends {
263
+ readonly traits: infer TTraits;
264
+ } ? PresetsOfList<TTraits> : unknown);
265
+ type OmitFlag<TOptions> = TOptions extends {
266
+ readonly omitDefaults: string;
267
+ } ? {
268
+ readonly "~omitDefaults": true;
269
+ } : unknown;
270
+ type GlobalFlag<TOptions> = TOptions extends {
271
+ readonly tenancy: {
272
+ readonly kind: "global";
273
+ readonly reason: infer TReason;
274
+ };
275
+ } ? {
276
+ readonly "~global": TReason;
277
+ } : unknown;
278
+ type TraitShapes<TColumns, TOptions> = TOptions extends {
279
+ readonly traits: infer TTraits;
280
+ } ? TTraits extends readonly {
281
+ readonly fields: Readonly<Record<string, object>>;
282
+ }[] ? keyof FieldsOfList<TTraits> extends never ? unknown : {
283
+ readonly "~row": RowFrom<TColumns> & RowFrom<FieldsOfList<TTraits>>;
284
+ readonly "~insert": InsertFrom<TColumns> & InsertFrom<FieldsOfList<TTraits>>;
285
+ readonly "~update": UpdateFrom<TColumns, PrimaryOf<TOptions>> & UpdateFrom<FieldsOfList<TTraits>>;
286
+ } : unknown : unknown;
161
287
  /**
162
288
  * Declares an index from column handles.
163
289
  *