okmodel 0.5.0 → 0.6.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 (169) hide show
  1. package/README.md +36 -18
  2. package/dist/adapters/pg/no-inflight-timeout.d.ts +17 -0
  3. package/dist/adapters/pg/postgres-extra.d.ts +22 -0
  4. package/dist/contracts/catalog/document.d.ts +19 -5
  5. package/dist/contracts/catalog/object.d.ts +2 -1
  6. package/dist/contracts/catalog/policy.d.ts +48 -0
  7. package/dist/contracts/catalog/types.d.ts +25 -1
  8. package/dist/contracts/catalog/view.d.ts +2 -0
  9. package/dist/contracts/internal.js +1 -1
  10. package/dist/contracts/location.d.ts +10 -0
  11. package/dist/dialects/pg/column.d.ts +13 -2
  12. package/dist/dialects/pg/ddl.d.ts +37 -1
  13. package/dist/dialects/pg/emit.d.ts +19 -1
  14. package/dist/dialects/pg/errors.d.ts +32 -1
  15. package/dist/dialects/pg/ext/citext.js +1 -1
  16. package/dist/dialects/pg/ext/index.js +1 -1
  17. package/dist/dialects/pg/ext/pg-trgm.js +1 -1
  18. package/dist/dialects/pg/filter-parse.d.ts +10 -3
  19. package/dist/dialects/pg/fn/index.js +10 -2
  20. package/dist/dialects/pg/index.d.ts +2 -1
  21. package/dist/dialects/pg/index.js +29 -17
  22. package/dist/dialects/pg/introspect.d.ts +7 -0
  23. package/dist/dialects/pg/model.d.ts +7 -2
  24. package/dist/dialects/pg/ops/or.d.ts +1 -1
  25. package/dist/dialects/pg/owner.d.ts +42 -0
  26. package/dist/dialects/pg/path-endpoint.d.ts +20 -0
  27. package/dist/dialects/pg/role/check.d.ts +3 -0
  28. package/dist/dialects/pg/role/index.d.ts +71 -6
  29. package/dist/dialects/pg/role/sql.d.ts +11 -0
  30. package/dist/dialects/pg/schema.d.ts +2 -0
  31. package/dist/dialects/pg/table.d.ts +25 -3
  32. package/dist/dialects/pg/temporal.d.ts +5 -76
  33. package/dist/dialects/pg/tenancy.d.ts +45 -3
  34. package/dist/dialects/pg/view/client.d.ts +19 -1
  35. package/dist/dialects/pg/view/index.d.ts +4 -0
  36. package/dist/dialects/pg/view/index.js +21 -178
  37. package/dist/dialects/pg/view/refresh.d.ts +24 -0
  38. package/dist/runtime/batch.d.ts +1 -1
  39. package/dist/runtime/client.d.ts +6 -1
  40. package/dist/runtime/conflict.d.ts +2 -1
  41. package/dist/runtime/drift.d.ts +9 -0
  42. package/dist/runtime/inflight.d.ts +14 -0
  43. package/dist/runtime/pg/bun.js +6 -5
  44. package/dist/runtime/pg/pg.js +5 -5
  45. package/dist/runtime/pg/pglite.js +6 -5
  46. package/dist/runtime/pg/postgresjs.js +5 -5
  47. package/dist/runtime/plan.d.ts +22 -1
  48. package/dist/runtime/predicate.d.ts +19 -0
  49. package/dist/runtime/safety/index.js +1 -1
  50. package/dist/runtime/tenancy/composite.d.ts +26 -0
  51. package/dist/runtime/tenancy/context.d.ts +16 -0
  52. package/dist/runtime/tenancy/index.d.ts +9 -5
  53. package/dist/runtime/tenancy/index.js +1508 -37
  54. package/dist/runtime/tenancy/path.d.ts +87 -0
  55. package/dist/runtime/tenancy/rls.d.ts +67 -0
  56. package/dist/runtime/tenancy/via.d.ts +22 -0
  57. package/dist/runtime/traits/index.js +17 -11
  58. package/dist/runtime/types.d.ts +13 -1
  59. package/dist/runtime/validate/index.js +4 -4
  60. package/dist/runtime/write.d.ts +1 -1
  61. package/dist/shared/09p049xa.js +702 -0
  62. package/dist/shared/{ykv7wh5b.js → 1f0xa3cb.js} +5 -5
  63. package/dist/shared/1nw1f3vs.js +23 -0
  64. package/dist/shared/{6p5k20sm.js → 1z04fa85.js} +21 -11
  65. package/dist/shared/{p7pfx624.js → 2cg3wnxc.js} +314 -65
  66. package/dist/shared/{dyj86cmj.js → 2jd1sn0e.js} +2 -2
  67. package/dist/shared/{qgvt8nx1.js → 2z7wv5tj.js} +21 -5
  68. package/dist/shared/{kyxb62mc.js → 31vm914h.js} +9 -1
  69. package/dist/shared/{sf8m6tfy.js → 32cnm7kn.js} +8 -3
  70. package/dist/shared/{t4tbsy9h.js → 358zsv4r.js} +1 -1
  71. package/dist/shared/{jdgqqx31.js → 3fqwmr09.js} +38 -14
  72. package/dist/shared/{922qbgnw.js → 3qnhc7w5.js} +16 -9
  73. package/dist/shared/{zvbjc949.js → 4az561fn.js} +1 -1
  74. package/dist/shared/{k3ted12y.js → 54tqkxja.js} +20 -2
  75. package/dist/shared/{k7cc9nzk.js → 5d8t84hg.js} +15 -3
  76. package/dist/shared/{fa9vt245.js → 5j36z8dn.js} +17 -6
  77. package/dist/shared/{1g0drakv.js → 5yv4k6a6.js} +1 -1
  78. package/dist/shared/8dqhth8c.js +12 -0
  79. package/dist/shared/8etn7d8w.js +62 -0
  80. package/dist/shared/{g516zdsb.js → 8x72s86k.js} +476 -30
  81. package/dist/shared/{nkc9sfqb.js → 929h19xp.js} +145 -7
  82. package/dist/shared/{gjthds9j.js → 9628a9xt.js} +1 -1
  83. package/dist/shared/{8xsbagad.js → 9s0ypp87.js} +88 -7
  84. package/dist/shared/{b066g80h.js → ag4c7516.js} +2 -2
  85. package/dist/shared/b3awxn7h.js +45 -0
  86. package/dist/shared/b4v57v3x.js +9 -0
  87. package/dist/shared/bdk4sty6.js +58 -0
  88. package/dist/shared/{s6gqfn5j.js → c58secgj.js} +125 -8
  89. package/dist/shared/{rrstp3kb.js → cgbamx3e.js} +2 -2
  90. package/dist/shared/d5azex6s.js +6 -0
  91. package/dist/shared/{5fqx9yh4.js → dk8v79p3.js} +3 -1
  92. package/dist/shared/{4m9fn52z.js → ed0b8k4s.js} +1 -1
  93. package/dist/shared/{z2rnngj4.js → ek2wt2dz.js} +8 -5
  94. package/dist/shared/{wxn4b7pp.js → f0f1n281.js} +59 -12
  95. package/dist/shared/{gdh9mrtp.js → g90m9b0g.js} +3 -2
  96. package/dist/shared/{tbszx8mz.js → gwn6v667.js} +2 -2
  97. package/dist/shared/{c8aghh05.js → h15jx9bc.js} +8 -2
  98. package/dist/shared/{3p4b1fg0.js → hazqqecq.js} +17 -93
  99. package/dist/shared/{4ef7mmqf.js → j3rkk835.js} +34 -11
  100. package/dist/shared/{bt9sfq0z.js → j60w0dvr.js} +56 -21
  101. package/dist/shared/{ycatkxmq.js → jgqj11w4.js} +1 -1
  102. package/dist/shared/k68eedmy.js +85 -0
  103. package/dist/shared/{szm0cksa.js → knmes2kh.js} +34 -6
  104. package/dist/shared/{ckjbyrt9.js → mb2ycs1p.js} +7 -9
  105. package/dist/shared/{tq9afp8d.js → n076ydsc.js} +1 -1
  106. package/dist/shared/{xhh1srw3.js → nx9hh281.js} +50 -32
  107. package/dist/shared/{kdkxh3kb.js → p248q79y.js} +58 -59
  108. package/dist/shared/{990a291j.js → p6bjzq9q.js} +14 -9
  109. package/dist/shared/{h4nqvjkp.js → pjr6xrm5.js} +2 -2
  110. package/dist/shared/pz6rj8ay.js +212 -0
  111. package/dist/shared/{5vdm4sgp.js → q3j1tq7a.js} +36 -23
  112. package/dist/shared/{8bwbwy8h.js → qq3899ht.js} +128 -18
  113. package/dist/shared/{dxjp14rk.js → r11n8grd.js} +2 -2
  114. package/dist/shared/r1fdd0f6.js +19 -0
  115. package/dist/shared/{8ktwd3rh.js → r3j8s5y0.js} +1 -1
  116. package/dist/shared/rhs3xe4k.js +7 -0
  117. package/dist/shared/{jsd07prz.js → rpycarcr.js} +6 -6
  118. package/dist/shared/{xsq7v6wp.js → sbdme3vy.js} +14 -2
  119. package/dist/shared/{xdpj5kkm.js → t3g0k88x.js} +775 -264
  120. package/dist/shared/{ayz64vzj.js → ttmg09vd.js} +708 -19
  121. package/dist/shared/{r6pj4fq2.js → venqrjna.js} +8 -4
  122. package/dist/shared/{fancm5pt.js → vjpnzwjz.js} +138 -15
  123. package/dist/shared/{9tgmr1gh.js → vmfkhszw.js} +44 -9
  124. package/dist/shared/{wqem4jed.js → wkme6tep.js} +11 -9
  125. package/dist/shared/{qy9rdq0g.js → wt5rzv1h.js} +15 -11
  126. package/dist/shared/wxr8cwns.js +6 -0
  127. package/dist/shared/{bzsjtd7c.js → wynzeggs.js} +19 -14
  128. package/dist/shared/x3jc53kg.js +220 -0
  129. package/dist/shared/{7p2wbz7f.js → x72jb7ad.js} +1 -1
  130. package/dist/shared/{fyqkk1m0.js → xq0mvhts.js} +10 -9
  131. package/dist/shared/xqve9598.js +53 -0
  132. package/dist/shared/{47xzb9fc.js → y2t3jktd.js} +2 -2
  133. package/dist/shared/{9x25fxhc.js → y34a8714.js} +1 -1
  134. package/dist/shared/{k7dwkhvq.js → y6jdds7g.js} +4 -1
  135. package/dist/shared/{h8ne16fq.js → ys0xzyaj.js} +1 -1
  136. package/dist/shared/{c9z5g0fm.js → ywr8hmey.js} +5 -2
  137. package/dist/shared/{g7ez901n.js → ywspezzx.js} +1 -1
  138. package/dist/shared/{9m80mkac.js → ze4hxsmy.js} +1 -1
  139. package/dist/shared/{fb00y8fp.js → zm0mafk4.js} +12 -6
  140. package/dist/shared/{y005b761.js → zy8r7qvz.js} +6 -2
  141. package/dist/tooling/cli.js +97 -24
  142. package/dist/tooling/migrate/apply.d.ts +14 -0
  143. package/dist/tooling/migrate/check.d.ts +3 -4
  144. package/dist/tooling/migrate/classify.d.ts +4 -0
  145. package/dist/tooling/migrate/commands.d.ts +1 -2
  146. package/dist/tooling/migrate/config.d.ts +3 -2
  147. package/dist/tooling/migrate/drift.d.ts +1 -1
  148. package/dist/tooling/migrate/estimate.d.ts +14 -1
  149. package/dist/tooling/migrate/files.d.ts +11 -1
  150. package/dist/tooling/migrate/index.js +17 -16
  151. package/dist/tooling/migrate/lint.d.ts +4 -4
  152. package/dist/tooling/migrate/lost.d.ts +28 -0
  153. package/dist/tooling/migrate/paths.d.ts +14 -0
  154. package/dist/tooling/migrate/plan.d.ts +10 -3
  155. package/dist/tooling/migrate/policy.d.ts +11 -0
  156. package/dist/tooling/migrate/runner.d.ts +25 -0
  157. package/dist/tooling/migrate/sandbox.d.ts +57 -0
  158. package/dist/tooling/migrate/sql-lex.d.ts +39 -0
  159. package/dist/tooling/migrate/text.d.ts +42 -0
  160. package/dist/tooling/node-version.d.ts +21 -0
  161. package/dist/tooling/testing/factories.d.ts +10 -0
  162. package/dist/tooling/testing/facts.d.ts +33 -5
  163. package/dist/tooling/testing/index.d.ts +1 -1
  164. package/dist/tooling/testing/index.js +3 -3
  165. package/dist/tooling/testing/isolation.d.ts +15 -8
  166. package/package.json +10 -6
  167. package/dist/shared/0v1g424p.js +0 -26
  168. package/dist/shared/r73pt594.js +0 -426
  169. package/dist/shared/rasvvzgz.js +0 -21
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  isConnectionSqlstate,
3
3
  isConnectionFailure
4
- } from "./tbszx8mz.js";
4
+ } from "./gwn6v667.js";
5
5
  import {
6
6
  OkmError2,
7
7
  stripRowValues,
@@ -9,19 +9,21 @@ import {
9
9
  } from "./52szzakm.js";
10
10
 
11
11
  // src/dialects/pg/errors.ts
12
- function mapPostgresError(error, options) {
12
+ function mapPostgresError2(error, options) {
13
13
  if (error instanceof OkmError2)
14
14
  return error;
15
15
  if (!isDriverError(error))
16
16
  return OkmError2.from(error);
17
17
  const kind = kindOf(error);
18
18
  const columns = columnsOf(error);
19
- const fieldReason = kind === "not_null" ? "not_null" : reasonOf(kind, error.table, error.constraint);
19
+ const hint = hintOf(error, kind);
20
+ const fieldReason = hint?.reason ?? (kind === "not_null" ? "not_null" : reasonOf(kind, error.table, error.constraint, columns, options?.schema));
20
21
  const values = options?.includeValues === true ? valuesOf(error.detail, columns) : undefined;
21
22
  const code = kind === "outcome_unknown" ? "OKM1401" : kind;
22
23
  return new OkmError2(code, summaryOf(kind, error, columns, fieldReason), {
23
24
  kind,
24
25
  fieldReason,
26
+ ...hint !== undefined ? { fix: hint.fix } : {},
25
27
  ...error.table !== undefined ? { table: error.table } : {},
26
28
  ...columns.length > 0 ? { columns } : {},
27
29
  ...error.constraint !== undefined ? { constraint: error.constraint } : {},
@@ -32,6 +34,12 @@ function mapPostgresError(error, options) {
32
34
  ...options?.http !== undefined ? { http: options.http } : {}
33
35
  });
34
36
  }
37
+ var TLS_CODE = /^(ERR_TLS_|ERR_POSTGRES_TLS_|SELF_SIGNED_CERT_|DEPTH_ZERO_SELF_SIGNED_CERT$|UNABLE_TO_VERIFY_LEAF_SIGNATURE$)/;
38
+ function isTlsFailure(error) {
39
+ const cause = error.cause;
40
+ const code = typeof cause === "object" && cause !== null ? Reflect.get(cause, "code") : undefined;
41
+ return typeof code === "string" && TLS_CODE.test(code);
42
+ }
35
43
  function isDriverError(error) {
36
44
  if (!(error instanceof Error) || error.name !== "DriverError")
37
45
  return false;
@@ -47,10 +55,54 @@ function kindOf(error) {
47
55
  if (mapped !== undefined)
48
56
  return mapped;
49
57
  }
50
- if (isConnectionFailure(error))
58
+ if (isTlsFailure(error) || isConnectionFailure(error))
51
59
  return "unavailable";
52
60
  return "driver";
53
61
  }
62
+ var MIGRATE_FIX = {
63
+ summary: "Run okm migrate apply so the object exists, then check okm migrate status. The reason names the missing object."
64
+ };
65
+ var TLS_FIX = {
66
+ summary: "Check sslmode in the connection URL against the server certificate: use require, verify-ca, or verify-full with the CA the certificate chains to. For node-postgres, add uselibpqcompat=true so sslmode follows libpq."
67
+ };
68
+ function hintOf(error, kind) {
69
+ if (error.sqlstate === "42P01")
70
+ return { reason: "undefined_table", fix: MIGRATE_FIX };
71
+ if (error.sqlstate === "42703")
72
+ return { reason: "undefined_column", fix: MIGRATE_FIX };
73
+ const refresh = refreshHint(error);
74
+ if (refresh !== undefined)
75
+ return refresh;
76
+ if (kind === "unavailable" && error.sqlstate === undefined && isTlsFailure(error)) {
77
+ return { reason: "tls", fix: TLS_FIX };
78
+ }
79
+ return;
80
+ }
81
+ function refreshHint(error) {
82
+ if (error.sqlstate === "0A000" && error.message.includes("materialized view is not populated")) {
83
+ return {
84
+ reason: "not_populated",
85
+ fix: { summary: "Refresh once without CONCURRENTLY so the view is populated." }
86
+ };
87
+ }
88
+ if (error.sqlstate === "55000" && error.message.includes("cannot refresh materialized view") && error.message.includes("concurrently")) {
89
+ return {
90
+ reason: "no_unique_index",
91
+ fix: {
92
+ summary: "Add a unique index with no WHERE clause, or refresh without CONCURRENTLY."
93
+ }
94
+ };
95
+ }
96
+ if (error.sqlstate === "42501" && error.message.includes("materialized view")) {
97
+ return {
98
+ reason: "not_owner",
99
+ fix: {
100
+ summary: "Refresh runs as the owner, the migration role. Connect as that role and call refresh(), or run REFRESH MATERIALIZED VIEW as that role. The application role is not the owner."
101
+ }
102
+ };
103
+ }
104
+ return;
105
+ }
54
106
  function kindFromSqlstate(sqlstate) {
55
107
  switch (sqlstate) {
56
108
  case "23505":
@@ -88,7 +140,15 @@ function kindFromSqlstate(sqlstate) {
88
140
  return;
89
141
  }
90
142
  }
91
- function reasonOf(kind, table, constraint) {
143
+ function reasonOf(kind, table, constraint, columns, schema) {
144
+ if (schema !== undefined && schema.catalog !== undefined && table !== undefined) {
145
+ const matched = matchObject(schema.catalog, table, constraint, columns);
146
+ if (matched !== undefined)
147
+ return reasonFromObject(schema, table, matched, columns);
148
+ }
149
+ return reasonFromName(kind, table, constraint);
150
+ }
151
+ function reasonFromName(kind, table, constraint) {
92
152
  if (constraint === undefined || constraint.length === 0)
93
153
  return kind;
94
154
  if (table !== undefined) {
@@ -104,6 +164,61 @@ function reasonOf(kind, table, constraint) {
104
164
  }
105
165
  return constraint;
106
166
  }
167
+ function matchObject(catalog, table, constraint, columns) {
168
+ const rows = [];
169
+ for (const object of catalog.objects) {
170
+ if (object.kind !== "constraint" && object.kind !== "index")
171
+ continue;
172
+ if (object.identity.parent.name !== table)
173
+ continue;
174
+ rows.push(object);
175
+ }
176
+ if (columns.length > 0) {
177
+ const key = columns.join(",");
178
+ const hits = rows.filter((object) => object.definition.columns.join(",") === key);
179
+ if (constraint !== undefined) {
180
+ const named = hits.find((object) => object.identity.name === constraint);
181
+ if (named !== undefined)
182
+ return named;
183
+ }
184
+ const only = hits.length === 1 ? hits[0] : undefined;
185
+ if (only !== undefined)
186
+ return only;
187
+ }
188
+ if (constraint === undefined)
189
+ return;
190
+ return rows.find((object) => object.identity.name === constraint);
191
+ }
192
+ function reasonFromObject(schema, table, object, columns) {
193
+ if (object.kind === "index")
194
+ return object.identity.name;
195
+ const nameKey = object.definition.nameKey;
196
+ if (columns.length === 0)
197
+ return nameKey;
198
+ const sqlKey = object.definition.columns.join("_");
199
+ if (nameKey !== sqlKey || object.definition.columns.length < 2)
200
+ return nameKey;
201
+ return fieldKey(schema, table, object.definition.columns) ?? nameKey;
202
+ }
203
+ function fieldKey(schema, table, columns) {
204
+ let model;
205
+ for (const item of Object.values(schema.model)) {
206
+ if (item.sql === table) {
207
+ model = item;
208
+ break;
209
+ }
210
+ }
211
+ if (model === undefined)
212
+ return;
213
+ const fields = [];
214
+ for (const column of columns) {
215
+ const found = model.columns.find((item) => item.sql === column);
216
+ if (found === undefined)
217
+ return;
218
+ fields.push(found.field);
219
+ }
220
+ return fields.join("_");
221
+ }
107
222
  function nameKeyOf(rest) {
108
223
  const tags = ["_fkey", "_check", "_key"];
109
224
  for (const tag of tags) {
@@ -188,6 +303,9 @@ function unquote(name) {
188
303
  }
189
304
  function summaryOf(kind, error, columns, fieldReason) {
190
305
  const label = labelOf(kind);
306
+ if (kind === "driver" && fieldReason === "not_owner") {
307
+ return "The application role cannot refresh a materialized view. Refresh runs as the owner, the migration role.";
308
+ }
191
309
  if (kind === "driver")
192
310
  return stripRowValues(error.message);
193
311
  const where = place(error.table, columns);
@@ -252,6 +370,5 @@ function labelOf(kind) {
252
370
  return "Driver error";
253
371
  }
254
372
  }
255
- export {
256
- mapPostgresError
257
- };
373
+
374
+ export { mapPostgresError2 };
@@ -41,7 +41,7 @@ function hasCapability2(flags, name) {
41
41
  // src/adapters/failure.ts
42
42
  var loading;
43
43
  function driverErrors() {
44
- loading ??= import("./7p2wbz7f.js");
44
+ loading ??= import("./x72jb7ad.js");
45
45
  return loading;
46
46
  }
47
47
  function rejectClosed(message = "The pool is closed.") {
@@ -83,7 +83,7 @@ function runCall(closed, options, fn) {
83
83
  if (options === undefined || !needsWatch(options))
84
84
  return fn(undefined);
85
85
  const watched = options;
86
- return import("./k3ted12y.js").then(({ openWatch }) => {
86
+ return import("./54tqkxja.js").then(({ openWatch }) => {
87
87
  const watch = openWatch(watched);
88
88
  return fn(watch).finally(() => {
89
89
  watch.finish();
@@ -0,0 +1,6 @@
1
+ import {
2
+ mapPostgresError2
3
+ } from "./c58secgj.js";
4
+ export {
5
+ mapPostgresError2 as mapPostgresError
6
+ };
@@ -7,9 +7,11 @@ import {
7
7
  startupCatalog2,
8
8
  startupHash2,
9
9
  loadTrustedCatalog2,
10
+ catalogFileText2,
10
11
  parseCatalog2
11
- } from "./8bwbwy8h.js";
12
+ } from "./qq3899ht.js";
12
13
  export {
14
+ catalogFileText2 as catalogFileText,
13
15
  catalogHash2 as catalogHash,
14
16
  creationOrder2 as creationOrder,
15
17
  loadTrustedCatalog2 as loadTrustedCatalog,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  required
3
- } from "./c9z5g0fm.js";
3
+ } from "./ywr8hmey.js";
4
4
  import {
5
5
  definition,
6
6
  rejected
@@ -1,3 +1,6 @@
1
+ import {
2
+ catalogFileText2
3
+ } from "./qq3899ht.js";
1
4
  import {
2
5
  OkmError2
3
6
  } from "./52szzakm.js";
@@ -11,7 +14,7 @@ async function assertCompatible(pool, schema, recordedHash, source, options) {
11
14
  if (code.artifact !== undefined) {
12
15
  const artifact = code.artifact;
13
16
  await loadOnce(`text\x00${artifact.hash}`, async () => {
14
- const { loadTrustedCatalog } = await import("./5fqx9yh4.js");
17
+ const { loadTrustedCatalog } = await import("./dk8v79p3.js");
15
18
  loadTrustedCatalog(artifact.text, artifact.hash);
16
19
  });
17
20
  } else if (code.fromFile) {
@@ -25,7 +28,7 @@ async function assertCompatible(pool, schema, recordedHash, source, options) {
25
28
  }
26
29
  });
27
30
  }
28
- const { loadTrustedCatalog } = await import("./5fqx9yh4.js");
31
+ const { loadTrustedCatalog } = await import("./dk8v79p3.js");
29
32
  loadTrustedCatalog(text, code.hash);
30
33
  });
31
34
  }
@@ -39,7 +42,7 @@ async function codeHash(schema, source) {
39
42
  const listed = await readHashFile(source.catalogDir);
40
43
  if (listed !== undefined)
41
44
  return { hash: listed, fromFile: true };
42
- const { catalogHash } = await import("./5fqx9yh4.js");
45
+ const { catalogHash } = await import("./dk8v79p3.js");
43
46
  return { hash: catalogHash(schemaCatalog(schema)), fromFile: false };
44
47
  }
45
48
  function schemaCatalog(schema) {
@@ -57,12 +60,12 @@ async function readHashFile(catalogDir) {
57
60
  const text = await readText(`${artifactDir(catalogDir)}/catalog.hash`);
58
61
  if (text === undefined)
59
62
  return;
60
- const hash = text.trim();
63
+ const hash = catalogFileText2(text, "catalog.hash").trim();
61
64
  return hash.length === 0 ? undefined : hash;
62
65
  }
63
66
  function artifactDir(catalogDir) {
64
67
  if (catalogDir !== undefined)
65
- return catalogDir.replace(/\/$/, "");
68
+ return catalogDir.replace(/[/\\]+$/, "");
66
69
  const cwd = globalThis.process?.cwd?.() ?? ".";
67
70
  return `${cwd}/.okm`;
68
71
  }
@@ -4,22 +4,26 @@ import {
4
4
  viewDependencyEdges,
5
5
  PUBLIC,
6
6
  introspectSchema
7
- } from "./fancm5pt.js";
7
+ } from "./vjpnzwjz.js";
8
8
  import {
9
- planMigration
10
- } from "./ayz64vzj.js";
9
+ planMigration,
10
+ sessionFailure,
11
+ finishQuiet,
12
+ assertDirectConnection,
13
+ assertStableBackend
14
+ } from "./ttmg09vd.js";
11
15
  import {
12
16
  quoteIdent,
13
17
  createObjectSql
14
- } from "./8xsbagad.js";
18
+ } from "./9s0ypp87.js";
15
19
  import {
16
20
  normaliseViewQuery,
17
21
  viewObject,
18
22
  materializedViewObject
19
- } from "./y005b761.js";
23
+ } from "./zy8r7qvz.js";
20
24
  import {
21
25
  catalog
22
- } from "./g7ez901n.js";
26
+ } from "./ywspezzx.js";
23
27
  import {
24
28
  OkmError2
25
29
  } from "./52szzakm.js";
@@ -49,8 +53,11 @@ async function sealViews(runner, source) {
49
53
  return source;
50
54
  await dropScratch(runner);
51
55
  await runner.query(`create schema ${quoteIdent(SCRATCH)}`);
56
+ const previous = await runner.query(`select current_setting('search_path') as path`);
57
+ const saved = cellText(previous[0]?.path);
58
+ const path = await scratchSearchPath(runner, source);
52
59
  try {
53
- await runner.query(`set search_path to ${quoteIdent(SCRATCH)}`);
60
+ await runner.query(`select set_config('search_path', $1, false)`, [path]);
54
61
  await createObjects(runner, source, "type");
55
62
  for (const object of source.objects) {
56
63
  if (object.kind !== "table")
@@ -83,7 +90,8 @@ async function sealViews(runner, source) {
83
90
  query,
84
91
  owner: object.owner,
85
92
  provenance: object.provenance,
86
- dependencies
93
+ dependencies,
94
+ ...object.definition.securityInvoker === true ? { securityInvoker: true } : {}
87
95
  });
88
96
  }
89
97
  return materializedViewObject({
@@ -99,10 +107,37 @@ async function sealViews(runner, source) {
99
107
  });
100
108
  return catalog(next);
101
109
  } finally {
102
- await runner.query("set search_path to public");
110
+ await runner.query(`select set_config('search_path', $1, false)`, [saved]).catch(() => {
111
+ return;
112
+ });
103
113
  await dropScratch(runner);
104
114
  }
105
115
  }
116
+ async function scratchSearchPath(runner, source) {
117
+ const names = new Set;
118
+ for (const object of source.objects) {
119
+ if (object.kind !== "column")
120
+ continue;
121
+ const bare = object.definition.dataType.split(".").pop()?.replace(/\(.*$/, "").replace(/\[\]$/, "").trim().toLowerCase();
122
+ if (bare !== undefined && bare.length > 0)
123
+ names.add(bare);
124
+ }
125
+ const extra = [];
126
+ if (names.size > 0) {
127
+ const rows = await runner.query(`select distinct n.nspname as schema
128
+ from pg_type t
129
+ join pg_namespace n on n.oid = t.typnamespace
130
+ where t.typname = any(string_to_array($1, E'\\x1f'))
131
+ and n.nspname not in ('pg_catalog', 'information_schema', 'pg_toast')`, [[...names].join("\x1F")]);
132
+ for (const row of rows) {
133
+ const schema = cellText(row.schema);
134
+ if (schema.length > 0 && schema !== "public" && schema !== SCRATCH)
135
+ extra.push(schema);
136
+ }
137
+ }
138
+ extra.sort();
139
+ return [SCRATCH, ...extra, "public"].map((name) => quoteIdent(name)).join(", ");
140
+ }
106
141
  async function createObjects(runner, source, kind) {
107
142
  for (const object of source.objects) {
108
143
  if (object.kind !== kind)
@@ -193,7 +228,8 @@ async function dropScratch(runner) {
193
228
  }
194
229
 
195
230
  // src/tooling/migrate/drift.ts
196
- async function assertAuthorDrift2(url, author, roles) {
231
+ async function assertAuthorDrift2(url, author, roles, allowPooler = false) {
232
+ assertDirectConnection(url, allowPooler);
197
233
  const sql = postgres(url, {
198
234
  max: 1,
199
235
  connect_timeout: 5,
@@ -201,6 +237,10 @@ async function assertAuthorDrift2(url, author, roles) {
201
237
  onnotice: () => {}
202
238
  });
203
239
  try {
240
+ await assertStableBackend(async () => {
241
+ const rows = await sql`select pg_backend_pid()::text as pid`;
242
+ return rows[0]?.pid ?? "";
243
+ }, allowPooler);
204
244
  const present = await sql`
205
245
  select to_regclass('public.okm_meta')::text as reg
206
246
  `;
@@ -219,8 +259,10 @@ ${plan.steps.map((step) => step.sql).join(`
219
259
  summary: "Change the schema or the database so okm check reports no difference."
220
260
  }
221
261
  });
262
+ } catch (error) {
263
+ throw sessionFailure(error) ?? error;
222
264
  } finally {
223
- await sql.end({ timeout: 5 });
265
+ await finishQuiet(() => sql.end({ timeout: 5 }));
224
266
  }
225
267
  }
226
268
  function catalogQuery2(sql) {
@@ -238,12 +280,17 @@ function catalogQuery2(sql) {
238
280
  }
239
281
  function managedRoleOptions2(roles) {
240
282
  const names = managedRoleNames(roles);
241
- return names === undefined ? undefined : { managedRoles: names };
283
+ return names === undefined ? undefined : {
284
+ managedRoles: names,
285
+ ...roles?.reporting !== undefined ? { reportingRole: roles.reporting } : {}
286
+ };
242
287
  }
243
288
  function managedRoleNames(roles) {
244
289
  if (roles === undefined)
245
290
  return;
246
291
  const names = new Set([roles.migration, roles.app]);
292
+ if (roles.reporting !== undefined)
293
+ names.add(roles.reporting);
247
294
  for (const role of roles.managed ?? [])
248
295
  names.add(role.name);
249
296
  return [...names];
@@ -1,11 +1,12 @@
1
1
  import {
2
2
  open3
3
- } from "./fa9vt245.js";
3
+ } from "./5j36z8dn.js";
4
+ import"./8dqhth8c.js";
4
5
  import {
5
6
  PGLITE_CAPABILITIES,
6
7
  readCapability2,
7
8
  hasCapability2
8
- } from "./rrstp3kb.js";
9
+ } from "./cgbamx3e.js";
9
10
  export {
10
11
  PGLITE_CAPABILITIES as capabilities,
11
12
  hasCapability2 as hasCapability,
@@ -28,7 +28,7 @@ function isConnectionFailure(error) {
28
28
  if (!(error instanceof Error))
29
29
  return false;
30
30
  const message = error.message;
31
- return message.includes("ECONNREFUSED") || message.includes("ECONNRESET") || message.includes("CONNECTION_CLOSED") || message.includes("terminating connection") || message.includes("The pool is closed");
31
+ return message.includes("ECONNREFUSED") || message.includes("ECONNRESET") || message.includes("CONNECT") || message.includes("terminating connection") || message.includes("The pool is closed");
32
32
  }
33
33
  function isConnectionLost(error) {
34
34
  if (isConnectionFailure(error))
@@ -51,4 +51,4 @@ function readCode(error, key) {
51
51
  return typeof value === "string" && value.length > 0 ? value : undefined;
52
52
  }
53
53
 
54
- export { isConnectionSqlstate, isConnectionFailure, isConnectionLost };
54
+ export { isConnectionSqlstate, isConnectionErrno, isConnectionFailure, isConnectionLost };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  validationGate
3
- } from "./9m80mkac.js";
3
+ } from "./ze4hxsmy.js";
4
4
  import {
5
5
  isOperator
6
6
  } from "./cn0n68ft.js";
@@ -422,6 +422,12 @@ function isRecord(value) {
422
422
  function failShape(message) {
423
423
  throw new OkmError2("OKM1121", message, { kind: "invalid" });
424
424
  }
425
+ function failedMessage(first) {
426
+ if (first === undefined)
427
+ return "Validation failed.";
428
+ const field = first.path.length === 0 ? "$row" : first.path.join(".");
429
+ return `Validation failed: ${field} ${first.message}`;
430
+ }
425
431
  function throwIssues(issues) {
426
432
  const columns = [];
427
433
  for (const issue of issues) {
@@ -429,7 +435,7 @@ function throwIssues(issues) {
429
435
  if (typeof field === "string" && !columns.includes(field))
430
436
  columns.push(field);
431
437
  }
432
- throw new OkmError2("OKM1200", "Validation failed.", {
438
+ throw new OkmError2("OKM1200", failedMessage(issues[0]), {
433
439
  kind: "invalid",
434
440
  ...columns.length > 0 ? { columns } : {},
435
441
  issues,
@@ -2,23 +2,23 @@ import {
2
2
  catalog,
3
3
  enumType,
4
4
  sameEnumLabels
5
- } from "./g7ez901n.js";
5
+ } from "./ywspezzx.js";
6
6
  import {
7
- snakeCase,
8
- emittedTypeName,
9
- rejectLater
10
- } from "./jsd07prz.js";
11
- import {
12
- withLocation
13
- } from "./k7dwkhvq.js";
7
+ isRelationCall
8
+ } from "./k68eedmy.js";
14
9
  import {
15
10
  encodeText,
16
11
  decodeText
17
- } from "./4m9fn52z.js";
12
+ } from "./ed0b8k4s.js";
13
+ import {
14
+ snakeCase,
15
+ emittedTypeName,
16
+ rejectLater
17
+ } from "./rpycarcr.js";
18
18
  import {
19
19
  ColumnBuilder2,
20
20
  formatType
21
- } from "./c9z5g0fm.js";
21
+ } from "./ywr8hmey.js";
22
22
  import {
23
23
  definition,
24
24
  unavailable
@@ -26,6 +26,9 @@ import {
26
26
  import {
27
27
  quoteLiteral
28
28
  } from "./94ez8kzh.js";
29
+ import {
30
+ withLocation
31
+ } from "./y6jdds7g.js";
29
32
  import {
30
33
  staticNamespace2,
31
34
  table3,
@@ -34,7 +37,7 @@ import {
34
37
  constraint2,
35
38
  sequence2,
36
39
  compareText
37
- } from "./t4tbsy9h.js";
40
+ } from "./358zsv4r.js";
38
41
  import {
39
42
  assertIdentifier2,
40
43
  fitIdentifier2,
@@ -49,85 +52,6 @@ import {
49
52
  readClientGenerator
50
53
  } from "./rwmrejjz.js";
51
54
 
52
- // src/dialects/pg/through.ts
53
- var emit = (planner, schema, relation, child, sink, parent, alias, depth) => {
54
- const through = relation.through;
55
- const join = through === undefined ? undefined : planner.indexes(schema).get(through.table);
56
- if (through === undefined || join === undefined) {
57
- return catalogError2("OKM1020", `Relation ${relation.name} names a join table that is not in the schema.`);
58
- }
59
- const { quote } = planner;
60
- const joinAlias = `j${alias}`;
61
- sink.mark(`via:${through.table}`);
62
- sink.text(`${quote(join.model.sql)} ${joinAlias} join ${quote(child.model.sql)} ${alias} on `);
63
- for (let index = 0;index < through.local.length; index += 1) {
64
- const local = through.local[index];
65
- const remote = through.remote[index];
66
- if (local === undefined || remote === undefined)
67
- continue;
68
- if (index > 0)
69
- sink.text(" and ");
70
- sink.text(`${alias}.${quote(remote)} = ${joinAlias}.${quote(local)}`);
71
- }
72
- sink.text(" where ");
73
- planner.join(sink, parent, joinAlias, relation);
74
- planner.where(schema, join, undefined, sink, joinAlias, depth + 1, true);
75
- };
76
- function resolveThrough(scope, table, through, from, to) {
77
- for (const name of [table, through]) {
78
- if (!scope.tables.includes(name)) {
79
- throwNamed2("OKM1020", name, scope.tables, `Relation ${scope.owner}.${scope.name} names ${name}, which is not in the schema. Accepted names: ${scope.tables.join(", ")}.`);
80
- }
81
- }
82
- const toOwner = pick(scope, through, scope.owner, from, `${scope.owner}.${scope.name}`, "from");
83
- const toTable = pick(scope, through, table, to, `${scope.owner}.${scope.name}`, "to");
84
- if (toOwner === toTable) {
85
- catalogError2("OKM1021", `Relation ${scope.owner}.${scope.name} uses ${toOwner.fromField} on ${through} for both ends. Pass from and to.`);
86
- }
87
- return {
88
- name: scope.name,
89
- kind: "many",
90
- table,
91
- local: toOwner.remote,
92
- remote: toOwner.local,
93
- through: { table: through, local: toTable.local, remote: toTable.remote, emit }
94
- };
95
- }
96
- function pick(scope, through, target, field, label, end) {
97
- const matches = scope.edges.filter((edge) => edge.fromTable === through && edge.toTable === target && (field === undefined || edge.fromField === field));
98
- const [only] = matches;
99
- if (matches.length === 1 && only !== undefined)
100
- return only;
101
- const fields = matches.map((edge) => edge.fromField).sort();
102
- catalogError2("OKM1021", `Relation ${label} through ${through} is ambiguous at ${end}. Accepted columns: ${fields.length === 0 ? "(none)" : fields.join(", ")}.`);
103
- }
104
-
105
- // src/dialects/pg/relations.ts
106
- function one2(table, field) {
107
- return { kind: "one", table, field };
108
- }
109
- function many2(table, field) {
110
- return { kind: "many", table, field };
111
- }
112
- function isRelationCall(value) {
113
- if (typeof value !== "object" || value === null)
114
- return false;
115
- if (!("kind" in value) || !("table" in value))
116
- return false;
117
- const kind = value.kind;
118
- return (kind === "one" || kind === "many") && typeof value.table === "string";
119
- }
120
- function manyThrough2(table, options) {
121
- const { through, from, to } = options;
122
- return {
123
- kind: "many",
124
- table,
125
- field: undefined,
126
- through,
127
- resolve: (scope) => resolveThrough(scope, table, through, from, to)
128
- };
129
- }
130
-
131
55
  // src/dialects/pg/compile.ts
132
56
  function compileColumn(builder, input) {
133
57
  const state = builder.state;
@@ -212,7 +136,7 @@ function readTenancy(value) {
212
136
  definition("schema() tenancy must be columnTenancy() from okmodel/tenancy.");
213
137
  }
214
138
  const record = value;
215
- if (record.strategy !== "column" || typeof record.rewrite !== "function") {
139
+ if (typeof record.rewrite !== "function") {
216
140
  definition("schema() tenancy must be columnTenancy() from okmodel/tenancy.");
217
141
  }
218
142
  return value;
@@ -557,7 +481,7 @@ function compileTable(item, namespace, casing, codecs, requires, idDefault, jobs
557
481
  references: column.state.references,
558
482
  encode: column.state.encode,
559
483
  decode: decode === decodeText ? undefined : decode,
560
- hidden: column.state.hidden,
484
+ hidden: column.state.filterable === true ? "filter" : column.state.hidden,
561
485
  sensitive: column.state.sensitive,
562
486
  guarded: column.state.guarded,
563
487
  writable: column.state.guarded !== true && column.state.omitWrite !== true && column.state.generated === undefined,
@@ -1127,4 +1051,4 @@ function list(names) {
1127
1051
  return names.length === 0 ? "(none)" : names.join(", ");
1128
1052
  }
1129
1053
 
1130
- export { one2, many2, manyThrough2, schema2, addSchemaHook };
1054
+ export { schema2, addSchemaHook };