okmodel 0.3.0 → 0.5.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 (123) hide show
  1. package/README.md +263 -23
  2. package/dist/contracts/catalog/document.d.ts +26 -2
  3. package/dist/contracts/driver.d.ts +7 -0
  4. package/dist/dialects/pg/ext/citext.js +1 -1
  5. package/dist/dialects/pg/ext/index.js +1 -1
  6. package/dist/dialects/pg/ext/pg-trgm.js +1 -1
  7. package/dist/dialects/pg/index.js +3 -3
  8. package/dist/dialects/pg/introspect.d.ts +6 -0
  9. package/dist/dialects/pg/role/sql.d.ts +21 -4
  10. package/dist/dialects/pg/schema.d.ts +15 -6
  11. package/dist/dialects/pg/table.d.ts +17 -1
  12. package/dist/dialects/pg/view/index.d.ts +20 -6
  13. package/dist/dialects/pg/view/index.js +1 -1
  14. package/dist/dialects/pg/view/scratch.d.ts +2 -1
  15. package/dist/runtime/catalog-cache.d.ts +17 -0
  16. package/dist/runtime/compat-words.d.ts +23 -0
  17. package/dist/runtime/drift-detail.d.ts +20 -4
  18. package/dist/runtime/drift.d.ts +4 -2
  19. package/dist/runtime/pg/bun.d.ts +12 -7
  20. package/dist/runtime/pg/bun.js +5 -2
  21. package/dist/runtime/pg/pg.d.ts +12 -6
  22. package/dist/runtime/pg/pg.js +5 -2
  23. package/dist/runtime/pg/pglite.d.ts +11 -3
  24. package/dist/runtime/pg/pglite.js +5 -2
  25. package/dist/runtime/pg/postgresjs.d.ts +12 -6
  26. package/dist/runtime/pg/postgresjs.js +5 -2
  27. package/dist/runtime/plan.d.ts +3 -1
  28. package/dist/runtime/tenancy/index.js +1 -1
  29. package/dist/runtime/topology.d.ts +191 -0
  30. package/dist/runtime/traits/index.js +7 -6
  31. package/dist/runtime/types.d.ts +59 -2
  32. package/dist/runtime/validate/index.js +2 -2
  33. package/dist/shared/{x6wysh83.js → 3p4b1fg0.js} +3 -5
  34. package/dist/shared/{ty3v3hfk.js → 47xzb9fc.js} +2 -2
  35. package/dist/shared/{fs0ex00p.js → 4ef7mmqf.js} +2 -2
  36. package/dist/shared/{qybh48nd.js → 5fqx9yh4.js} +6 -2
  37. package/dist/shared/5mtf6cj3.js +94 -0
  38. package/dist/shared/{999ade2q.js → 5vdm4sgp.js} +1 -1
  39. package/dist/shared/{bqha5cg6.js → 6p5k20sm.js} +2 -2
  40. package/dist/shared/{t616ynfn.js → 8bwbwy8h.js} +71 -13
  41. package/dist/shared/{th14ygv2.js → 8ktwd3rh.js} +29 -1
  42. package/dist/shared/{wekze34d.js → 8xsbagad.js} +74 -2
  43. package/dist/shared/{bryqk9k9.js → 922qbgnw.js} +3 -3
  44. package/dist/shared/{meck53jv.js → 990a291j.js} +6 -5
  45. package/dist/shared/{jns2wx4t.js → 9tgmr1gh.js} +1 -1
  46. package/dist/shared/9yn6a2vd.js +11 -0
  47. package/dist/shared/{2ssqrv66.js → ayz64vzj.js} +1037 -181
  48. package/dist/shared/{k34e0xf2.js → bt9sfq0z.js} +16 -14
  49. package/dist/shared/{scwxrpx2.js → bzsjtd7c.js} +84 -15
  50. package/dist/shared/{m9tv7xn7.js → ckjbyrt9.js} +4 -4
  51. package/dist/shared/{ydaz1sv3.js → dxjp14rk.js} +10 -2
  52. package/dist/shared/{49ypnfwt.js → fancm5pt.js} +24 -229
  53. package/dist/shared/{6bazvqwm.js → fb00y8fp.js} +2 -2
  54. package/dist/shared/{1tfdfvhh.js → fyqkk1m0.js} +6 -4
  55. package/dist/shared/g516zdsb.js +905 -0
  56. package/dist/shared/{jkc6ws1p.js → g7ez901n.js} +83 -2
  57. package/dist/shared/{kgnc8grt.js → gdh9mrtp.js} +1 -1
  58. package/dist/shared/{p24x2334.js → h4nqvjkp.js} +5 -3
  59. package/dist/shared/{edwqqryd.js → h8ne16fq.js} +1 -1
  60. package/dist/shared/htnaj77v.js +17 -0
  61. package/dist/shared/jdgqqx31.js +72 -0
  62. package/dist/shared/{6w5j844a.js → jsd07prz.js} +2 -2
  63. package/dist/shared/{m78s7898.js → k7cc9nzk.js} +24 -7
  64. package/dist/shared/kdkxh3kb.js +758 -0
  65. package/dist/shared/nkc9sfqb.js +1161 -0
  66. package/dist/shared/{xva8v7qk.js → p7pfx624.js} +5 -5
  67. package/dist/shared/{xrfnq5k8.js → qgvt8nx1.js} +11 -2
  68. package/dist/shared/{ne02ng5c.js → qy9rdq0g.js} +9 -5
  69. package/dist/shared/{3ekj9x92.js → r6pj4fq2.js} +5 -3
  70. package/dist/shared/r73pt594.js +426 -0
  71. package/dist/shared/rasvvzgz.js +21 -0
  72. package/dist/shared/{01yr20s5.js → sf8m6tfy.js} +2 -2
  73. package/dist/shared/{hcmdtwgh.js → szm0cksa.js} +4 -1
  74. package/dist/shared/{axhk06q1.js → tq9afp8d.js} +1 -1
  75. package/dist/shared/{xw1d69vd.js → wqem4jed.js} +6 -6
  76. package/dist/shared/wxn4b7pp.js +252 -0
  77. package/dist/shared/xdpj5kkm.js +2203 -0
  78. package/dist/shared/xhh1srw3.js +589 -0
  79. package/dist/shared/{mt5wswjz.js → xsq7v6wp.js} +2 -2
  80. package/dist/shared/{7fvtrkwr.js → ycatkxmq.js} +1 -1
  81. package/dist/shared/ykv7wh5b.js +14 -0
  82. package/dist/shared/{fptpmvxp.js → z2rnngj4.js} +26 -21
  83. package/dist/tooling/cli.js +46 -17
  84. package/dist/tooling/migrate/apply.d.ts +61 -5
  85. package/dist/tooling/migrate/backfill.d.ts +136 -0
  86. package/dist/tooling/migrate/check.d.ts +65 -0
  87. package/dist/tooling/migrate/classify.d.ts +108 -0
  88. package/dist/tooling/migrate/commands.d.ts +2 -2
  89. package/dist/tooling/migrate/config.d.ts +22 -0
  90. package/dist/tooling/migrate/doctor.d.ts +3 -0
  91. package/dist/tooling/migrate/drift.d.ts +18 -2
  92. package/dist/tooling/migrate/estimate.d.ts +50 -0
  93. package/dist/tooling/migrate/extensions.d.ts +2 -0
  94. package/dist/tooling/migrate/files.d.ts +19 -0
  95. package/dist/tooling/migrate/index.d.ts +3 -2
  96. package/dist/tooling/migrate/index.js +69 -1
  97. package/dist/tooling/migrate/lint-rules.d.ts +51 -0
  98. package/dist/tooling/migrate/lint.d.ts +71 -0
  99. package/dist/tooling/migrate/managed.d.ts +1 -1
  100. package/dist/tooling/migrate/plan.d.ts +64 -9
  101. package/dist/tooling/migrate/project.d.ts +42 -7
  102. package/dist/tooling/migrate/provision.d.ts +18 -0
  103. package/dist/tooling/migrate/reference.d.ts +40 -0
  104. package/dist/tooling/migrate/runner.d.ts +108 -0
  105. package/dist/tooling/migrate/safe.d.ts +77 -0
  106. package/dist/tooling/migrate/seed.d.ts +20 -0
  107. package/dist/tooling/migrate/snapshot.d.ts +78 -0
  108. package/dist/tooling/migrate/status.d.ts +25 -6
  109. package/dist/tooling/testing/factories.d.ts +117 -0
  110. package/dist/tooling/testing/facts.d.ts +75 -0
  111. package/dist/tooling/testing/index.d.ts +89 -0
  112. package/dist/tooling/testing/index.js +8 -0
  113. package/dist/tooling/testing/isolation.d.ts +30 -0
  114. package/dist/tooling/testing/random.d.ts +40 -0
  115. package/dist/tooling/testing/record.d.ts +38 -0
  116. package/package.json +6 -2
  117. package/dist/shared/5nmdenb6.js +0 -1229
  118. package/dist/shared/dbjej1tw.js +0 -456
  119. package/dist/shared/g4f5kcx9.js +0 -37
  120. package/dist/shared/qbxzvwwc.js +0 -88
  121. package/dist/shared/zwmqxb0g.js +0 -79
  122. /package/dist/shared/{75xkjv0t.js → fa9vt245.js} +0 -0
  123. /package/dist/shared/{0jc3ffzf.js → zvbjc949.js} +0 -0
@@ -7,7 +7,7 @@ import {
7
7
  decodeResult,
8
8
  logicalIntent,
9
9
  appliedRules
10
- } from "./xrfnq5k8.js";
10
+ } from "./qgvt8nx1.js";
11
11
  import {
12
12
  OkmError2,
13
13
  safe2,
@@ -72,7 +72,7 @@ function openClient(session) {
72
72
  },
73
73
  close,
74
74
  connected: session.connected,
75
- tx: (...args) => import("./m78s7898.js").then((mod) => mod.tx(session, args)),
75
+ tx: (...args) => import("./k7cc9nzk.js").then((mod) => mod.tx(session, args)),
76
76
  batch: (ops, options) => batchHandle(session, ops, options),
77
77
  ...session.tx?.extras
78
78
  };
@@ -107,7 +107,7 @@ function tableApi(session, table, view, uses) {
107
107
  const api = {
108
108
  find(options = {}) {
109
109
  if ("lock" in options) {
110
- return lazyRead(session, () => import("./ydaz1sv3.js"), table, options, base, view);
110
+ return lazyRead(session, () => import("./dxjp14rk.js"), table, options, base, view);
111
111
  }
112
112
  return start(session, "find", table, options, base, view);
113
113
  },
@@ -121,10 +121,10 @@ function tableApi(session, table, view, uses) {
121
121
  return start(session, "exists", table, options, base, view);
122
122
  },
123
123
  page(options) {
124
- return lazyRead(session, () => import("./p24x2334.js"), table, options, base, view);
124
+ return lazyRead(session, () => import("./h4nqvjkp.js"), table, options, base, view);
125
125
  },
126
126
  aggregate(options = {}) {
127
- return lazyRead(session, () => import("./3ekj9x92.js"), table, options, base, view);
127
+ return lazyRead(session, () => import("./r6pj4fq2.js"), table, options, base, view);
128
128
  },
129
129
  insert(data, options = {}) {
130
130
  return writeHandle(session, "insert", table, data, options, mods);
@@ -154,13 +154,13 @@ function tableApi(session, table, view, uses) {
154
154
  return api;
155
155
  }
156
156
  function batchHandle(session, ops, options, replica) {
157
- return queryHandle(() => import("./mt5wswjz.js").then((mod) => mod.batch(session, ops, options, replica)), {
157
+ return queryHandle(() => import("./xsq7v6wp.js").then((mod) => mod.batch(session, ops, options, replica)), {
158
158
  replica: () => batchHandle(session, ops, options, true)
159
159
  });
160
160
  }
161
161
  var writers;
162
162
  function loadWrite() {
163
- writers ??= import("./xva8v7qk.js");
163
+ writers ??= import("./p7pfx624.js");
164
164
  return writers;
165
165
  }
166
166
  function queryHandle(run, extra) {
@@ -245,7 +245,7 @@ function lazyRead(session, load, table, options, mods, view) {
245
245
  });
246
246
  }
247
247
  async function decodeRows(plan, rows, table) {
248
- return plan.outputs.includes.length === 0 ? decodeResult(plan, rows, table) : (await import("./edwqqryd.js")).decodeIncluded(plan, rows, table);
248
+ return plan.outputs.includes.length === 0 ? decodeResult(plan, rows, table) : (await import("./h8ne16fq.js")).decodeIncluded(plan, rows, table);
249
249
  }
250
250
  function readHandle(session, table, call, mods, decode, extra) {
251
251
  let prepared;
@@ -320,7 +320,7 @@ function readHandle(session, table, call, mods, decode, extra) {
320
320
  }
321
321
  function streamLazy(session, call, prepare) {
322
322
  return async function* () {
323
- const { streamRows } = await import("./bryqk9k9.js");
323
+ const { streamRows } = await import("./922qbgnw.js");
324
324
  yield* streamRows(session, call, prepare, (error) => logged(session, error));
325
325
  }();
326
326
  }
@@ -357,7 +357,7 @@ function readCall(op, table, options, all, scope, model, schema, view) {
357
357
  };
358
358
  }
359
359
  async function checkServer(pool, schema, http, requireMeta, options, source) {
360
- const server = await import("./ty3v3hfk.js");
360
+ const server = await import("./47xzb9fc.js");
361
361
  let rows;
362
362
  try {
363
363
  const result = await pool.execute(server.versionQuery, undefined, options);
@@ -386,7 +386,7 @@ function errorFields(error) {
386
386
  var includeHooks;
387
387
  var operatorSql;
388
388
  function loadOperatorSql() {
389
- operatorSql ??= import("./axhk06q1.js").then(() => {
389
+ operatorSql ??= import("./tq9afp8d.js").then(() => {
390
390
  return;
391
391
  });
392
392
  return operatorSql;
@@ -394,7 +394,7 @@ function loadOperatorSql() {
394
394
  function hooksFor(call) {
395
395
  if (call.include === undefined)
396
396
  return Promise.resolve(undefined);
397
- includeHooks ??= import("./edwqqryd.js").then((mod) => mod.includeHooks);
397
+ includeHooks ??= import("./h8ne16fq.js").then((mod) => mod.includeHooks);
398
398
  return includeHooks;
399
399
  }
400
400
  function bindNow(schema, call) {
@@ -426,11 +426,13 @@ function attachHttp(http, error) {
426
426
  }
427
427
  function callOptions(input, statement) {
428
428
  const timeout = input.timeout ?? statement;
429
- if (input.signal === undefined && timeout === undefined)
429
+ const route = input.route;
430
+ if (input.signal === undefined && timeout === undefined && route === undefined)
430
431
  return;
431
432
  return {
432
433
  ...input.signal !== undefined ? { signal: input.signal } : {},
433
- ...timeout !== undefined ? { timeout } : {}
434
+ ...timeout !== undefined ? { timeout } : {},
435
+ ...route !== undefined ? { route } : {}
434
436
  };
435
437
  }
436
438
  function mapOptions(http, includeValues) {
@@ -1,17 +1,30 @@
1
1
  import {
2
2
  open2
3
- } from "./xw1d69vd.js";
4
- import"./t616ynfn.js";
3
+ } from "./wqem4jed.js";
4
+ import"./8bwbwy8h.js";
5
5
  import"./n442h54c.js";
6
6
  import {
7
- loadMigrations
8
- } from "./g4f5kcx9.js";
7
+ CURRENT,
8
+ BEHIND_EXPAND,
9
+ BEHIND_CONTRACT,
10
+ AHEAD_EXPAND,
11
+ AHEAD_CONTRACT,
12
+ failedAt
13
+ } from "./9yn6a2vd.js";
14
+ import {
15
+ loadMigrations,
16
+ expandProvisioned,
17
+ provisionHistoryIsKnown
18
+ } from "./kdkxh3kb.js";
19
+ import"./szm0cksa.js";
20
+ import"./fancm5pt.js";
9
21
  import {
10
22
  assertTargetPolicy,
11
23
  listTargets,
12
24
  loadConfig
13
- } from "./5nmdenb6.js";
14
- import"./2ssqrv66.js";
25
+ } from "./xdpj5kkm.js";
26
+ import"./ayz64vzj.js";
27
+ import"./8xsbagad.js";
15
28
  import {
16
29
  OkmError2
17
30
  } from "./52szzakm.js";
@@ -19,8 +32,8 @@ import {
19
32
  // src/tooling/migrate/status.ts
20
33
  import { join } from "node:path";
21
34
  function describeStatus(migrations, history, recorded) {
22
- const done = new Set(history.map((row) => `${row.migrationId}:${String(row.stepIndex)}`));
23
35
  const known = new Set(migrations.map((migration) => migration.id));
36
+ const done = expandProvisioned(migrations, new Set(history.map((row) => `${row.migrationId}:${String(row.stepIndex)}`)), history.map((row) => row.migrationId));
24
37
  for (const migration of migrations) {
25
38
  let have = 0;
26
39
  let missing = -1;
@@ -34,33 +47,33 @@ function describeStatus(migrations, history, recorded) {
34
47
  return {
35
48
  version: migration.id,
36
49
  catalogHash: recorded?.hash ?? "-",
37
- state: `failed at step ${String(missing)}`
50
+ state: failedAt(missing)
38
51
  };
39
52
  }
40
53
  }
41
- const extra = history.some((row) => !known.has(row.migrationId));
42
54
  const pending = migrations.filter((migration) => migration.steps.some((_, index) => !done.has(`${migration.id}:${String(index)}`)));
43
55
  const finished = lastComplete(migrations, done);
44
56
  const version = recorded?.version ?? finished ?? "-";
45
57
  const catalogHash = recorded?.hash ?? "-";
58
+ const extra = history.some((row) => !provisionHistoryIsKnown(row.migrationId, known));
46
59
  if (extra)
47
- return { version, catalogHash, state: "ahead" };
60
+ return { version, catalogHash, state: aheadState(history, known) };
48
61
  if (pending.length > 0) {
49
62
  const contract = pending.some((migration) => migration.steps.some((step) => step.class !== "expand"));
50
63
  return {
51
64
  version,
52
65
  catalogHash,
53
- state: contract ? "behind by contract" : "behind by expand"
66
+ state: contract ? BEHIND_CONTRACT : BEHIND_EXPAND
54
67
  };
55
68
  }
56
69
  const last = migrations.at(-1);
57
70
  if (last !== undefined && recorded !== undefined && recorded.hash !== last.catalogHash) {
58
- return { version, catalogHash, state: "ahead" };
71
+ return { version, catalogHash, state: aheadState(history, known) };
59
72
  }
60
73
  return {
61
74
  version: recorded?.version ?? last?.id ?? "-",
62
75
  catalogHash: recorded?.hash ?? last?.catalogHash ?? "-",
63
- state: "current"
76
+ state: CURRENT
64
77
  };
65
78
  }
66
79
  async function readTargetStatus(input) {
@@ -82,7 +95,8 @@ async function readTargetStatus(input) {
82
95
  version: described.version,
83
96
  catalogHash: described.catalogHash,
84
97
  state: described.state,
85
- protected: input.protected
98
+ protected: input.protected,
99
+ backfills: await readBackfills(pool)
86
100
  };
87
101
  } finally {
88
102
  await pool.close();
@@ -105,8 +119,17 @@ async function statusProject(cwd, flags) {
105
119
  }
106
120
  function formatStatus(rows) {
107
121
  const lines = ["target\tversion\tcatalog\tstate\tprotected"];
122
+ const backfills = [];
108
123
  for (const row of rows) {
109
124
  lines.push([row.target, row.version, row.catalogHash, row.state, row.protected ? "true" : "false"].join("\t"));
125
+ backfills.push(...row.backfills);
126
+ }
127
+ if (backfills.length > 0) {
128
+ lines.push("backfill");
129
+ lines.push("migration\tstep\trows\tkey\tstate");
130
+ for (const item of backfills) {
131
+ lines.push([item.migrationId, String(item.stepIndex), item.rows, item.lastKey, item.state].join("\t"));
132
+ }
110
133
  }
111
134
  return `${lines.join(`
112
135
  `)}
@@ -160,7 +183,33 @@ async function readHistory(pool) {
160
183
  rows.push({
161
184
  migrationId,
162
185
  stepIndex: Number(step),
163
- class: stepClass === "contract" || stepClass === "unclassified" ? stepClass : "expand"
186
+ class: storedClass(stepClass)
187
+ });
188
+ }
189
+ return rows;
190
+ }
191
+ async function readBackfills(pool) {
192
+ const present = await pool.execute("select to_regclass('okm_backfill') is not null");
193
+ if (!wireTrue(present.rows[0]?.[0] ?? null))
194
+ return [];
195
+ const result = await pool.execute(`select migration_id, step_index::text, rows_touched::text, last_key, state
196
+ from okm_backfill
197
+ where state <> 'done'
198
+ order by migration_id, step_index`);
199
+ const rows = [];
200
+ for (const row of result.rows) {
201
+ const migrationId = row[0];
202
+ const step = row[1];
203
+ const touched = row[2];
204
+ const state = row[4];
205
+ if (migrationId == null || step == null || touched == null || state == null)
206
+ continue;
207
+ rows.push({
208
+ migrationId,
209
+ stepIndex: Number(step),
210
+ rows: touched,
211
+ lastKey: row[3] ?? "-",
212
+ state
164
213
  });
165
214
  }
166
215
  return rows;
@@ -168,6 +217,26 @@ async function readHistory(pool) {
168
217
  function wireTrue(value) {
169
218
  return value === "t" || value === "true";
170
219
  }
220
+ function aheadState(history, known) {
221
+ let sawExtra = false;
222
+ let expandOnly = true;
223
+ for (const row of history) {
224
+ if (known.has(row.migrationId))
225
+ continue;
226
+ sawExtra = true;
227
+ if (row.class !== "expand")
228
+ expandOnly = false;
229
+ }
230
+ if (!sawExtra) {
231
+ expandOnly = history.length > 0 && history.every((row) => row.class === "expand");
232
+ }
233
+ return expandOnly ? AHEAD_EXPAND : AHEAD_CONTRACT;
234
+ }
235
+ function storedClass(value) {
236
+ if (value === "expand" || value === "contract" || value === "unclassified")
237
+ return value;
238
+ return "unclassified";
239
+ }
171
240
  export {
172
241
  statusProject
173
242
  };
@@ -1,9 +1,9 @@
1
- import {
2
- runWrite
3
- } from "./n4jqhpqz.js";
4
1
  import {
5
2
  stack
6
3
  } from "./672t5vym.js";
4
+ import {
5
+ runWrite
6
+ } from "./n4jqhpqz.js";
7
7
  import {
8
8
  withRowFilters,
9
9
  archiveRules,
@@ -14,7 +14,7 @@ import {
14
14
  isRecord,
15
15
  registerFailFix,
16
16
  fail
17
- } from "./xrfnq5k8.js";
17
+ } from "./qgvt8nx1.js";
18
18
  import {
19
19
  safetyInstalled,
20
20
  runSafety
@@ -3,10 +3,10 @@ import {
3
3
  readHandle,
4
4
  readCall,
5
5
  attachHttp
6
- } from "./k34e0xf2.js";
6
+ } from "./bt9sfq0z.js";
7
7
  import {
8
8
  fail
9
- } from "./xrfnq5k8.js";
9
+ } from "./qgvt8nx1.js";
10
10
  import {
11
11
  OkmError2,
12
12
  throwNamed2
@@ -27,6 +27,14 @@ function build(session, table, options, mods, view) {
27
27
  }
28
28
  function plan(session, table, options, mods, view) {
29
29
  const { lock, wait, ...rest } = options;
30
+ const forced = session.pool.forcedRoute;
31
+ if (rest.route === "replica" || forced === "replica") {
32
+ throw new OkmError2("OKM1840", "A locking read needs the primary.", {
33
+ fix: {
34
+ summary: "Run the operation on the primary. Writes, batch, locks, and tx() never go to a replica."
35
+ }
36
+ });
37
+ }
30
38
  if (session.tx === undefined) {
31
39
  throw new OkmError2("OKM1830", "A row lock needs a transaction. find was called outside tx().", {
32
40
  fix: { summary: "Move the find into tx(): the lock lasts until the transaction ends." }
@@ -2,13 +2,10 @@ import {
2
2
  roleObject,
3
3
  grantObject,
4
4
  defaultPrivilegeObject
5
- } from "./t616ynfn.js";
6
- import {
7
- planMigration
8
- } from "./2ssqrv66.js";
5
+ } from "./8bwbwy8h.js";
9
6
  import {
10
7
  quoteIdent
11
- } from "./wekze34d.js";
8
+ } from "./8xsbagad.js";
12
9
  import {
13
10
  functionObject,
14
11
  triggerObject
@@ -21,14 +18,12 @@ import {
21
18
  } from "./y005b761.js";
22
19
  import {
23
20
  extensionObject
24
- } from "./th14ygv2.js";
25
- import {
26
- catalog
27
- } from "./jkc6ws1p.js";
21
+ } from "./8ktwd3rh.js";
28
22
  import {
23
+ catalog,
29
24
  enumType,
30
25
  domainType
31
- } from "./qbxzvwwc.js";
26
+ } from "./g7ez901n.js";
32
27
  import {
33
28
  staticNamespace2,
34
29
  identityKey2,
@@ -41,12 +36,6 @@ import {
41
36
  import {
42
37
  referentialAction
43
38
  } from "./4e4c6vq2.js";
44
- import {
45
- OkmError2
46
- } from "./52szzakm.js";
47
-
48
- // src/tooling/migrate/drift.ts
49
- import postgres from "postgres";
50
39
 
51
40
  // src/dialects/pg/view/depend.ts
52
41
  function cellText(value) {
@@ -252,6 +241,7 @@ async function introspectSchema(runner, concrete, logical = "public", options) {
252
241
  const parent = parents.get(parentName) ?? { namespace, name: parentName };
253
242
  const kind = constraintKind(text(row, "contype"));
254
243
  const columns = list(text(row, "columns"));
244
+ const name = text(row, "name");
255
245
  const expression = kind === "check" ? checkExpression(text(row, "definition")) : "";
256
246
  const refTable = text(row, "ref_table");
257
247
  const refColumns = list(text(row, "ref_columns"));
@@ -261,8 +251,8 @@ async function introspectSchema(runner, concrete, logical = "public", options) {
261
251
  objects.push(constraint2({
262
252
  parent,
263
253
  constraintKind: kind,
264
- name: text(row, "name"),
265
- nameKey: kind === "primaryKey" ? "pkey" : columns.length > 0 ? columns.join("_") : "check",
254
+ name,
255
+ nameKey: constraintNameKey(kind, parentName, name, columns),
266
256
  columns,
267
257
  provenance,
268
258
  deferrable: flag(row, "deferrable"),
@@ -446,8 +436,9 @@ var RELATION_GRANTS = `select c.relname as name,
446
436
  select 1 from pg_depend d
447
437
  where d.classid = 'pg_class'::regclass and d.objid = c.oid and d.deptype = 'e'
448
438
  )`;
439
+ var FUNCTION_ARG_TYPES = "replace(oidvectortypes(p.proargtypes), ' ', '')";
449
440
  var FUNCTION_GRANTS = `select p.proname as name,
450
- replace(pg_get_function_identity_arguments(p.oid), ' ', '') as args,
441
+ ${FUNCTION_ARG_TYPES} as args,
451
442
  r.rolname as role, a.privilege_type as privilege
452
443
  from pg_proc p
453
444
  join pg_namespace n on n.oid = p.pronamespace
@@ -861,6 +852,19 @@ function partitionMethod(value) {
861
852
  return "hash";
862
853
  return;
863
854
  }
855
+ function constraintNameKey(kind, parent, name, columns) {
856
+ if (kind === "primaryKey")
857
+ return "pkey";
858
+ const tag = kind === "unique" ? "key" : kind === "foreignKey" ? "fkey" : "check";
859
+ const prefix = `${parent}_`;
860
+ const suffix = `_${tag}`;
861
+ if (name.startsWith(prefix) && name.endsWith(suffix) && name.length > prefix.length + suffix.length) {
862
+ return name.slice(prefix.length, -suffix.length);
863
+ }
864
+ if (columns.length > 0)
865
+ return columns.join("_");
866
+ return tag;
867
+ }
864
868
  function constraintKind(value) {
865
869
  if (value === "p")
866
870
  return "primaryKey";
@@ -910,213 +914,4 @@ function flag(row, key) {
910
914
  return value === true || value === "true" || value === "t";
911
915
  }
912
916
 
913
- // src/dialects/pg/view/scratch.ts
914
- var SCRATCH = "okm_view_seal";
915
- var VIEW_SHAPE = `
916
- select c.relname as name, c.relkind as kind, pg_get_viewdef(c.oid, true) as query,
917
- (
918
- select coalesce(string_agg(
919
- a.attname || '|' || format_type(a.atttypid, a.atttypmod),
920
- E'\\n' order by a.attnum
921
- ), '')
922
- from pg_attribute a
923
- where a.attrelid = c.oid and a.attnum > 0 and not a.attisdropped
924
- ) as columns
925
- from pg_class c
926
- join pg_namespace n on n.oid = c.relnamespace
927
- where n.nspname = $1 and c.relkind in ('v', 'm')
928
- `;
929
- async function sealViews(runner, source) {
930
- const views = source.objects.filter((object) => object.kind === "view" || object.kind === "materializedView");
931
- if (views.length === 0)
932
- return source;
933
- await dropScratch(runner);
934
- await runner.query(`create schema ${quoteIdent(SCRATCH)}`);
935
- try {
936
- await runner.query(`set search_path to ${quoteIdent(SCRATCH)}`);
937
- for (const object of source.objects) {
938
- if (object.kind !== "table")
939
- continue;
940
- await runner.query(stubTable(object, source));
941
- }
942
- await createViews(runner, views);
943
- const shapes = await runner.query(VIEW_SHAPE, [SCRATCH]);
944
- const deps = await runner.query(VIEW_DEPENDENCIES, [SCRATCH]);
945
- const edges = viewDependencyEdges(deps, PUBLIC, source.objects);
946
- const byName = new Map(shapes.map((row) => [cellText(row.name), row]));
947
- const next = source.objects.map((object) => {
948
- if (object.kind !== "view" && object.kind !== "materializedView")
949
- return object;
950
- const row = byName.get(object.identity.name);
951
- if (row === undefined) {
952
- throw new OkmError2("OKM1020", `View ${object.identity.name} was not created in the scratch schema.`, {
953
- fix: { summary: "The query has to run against the tables in this schema." }
954
- });
955
- }
956
- const columns = readColumns(object, cellText(row.columns));
957
- const query = normaliseViewQuery(cellText(row.query));
958
- const dependencies = edges.get(object.identity.name) ?? [];
959
- if (object.kind === "view") {
960
- return viewObject({
961
- namespace: object.identity.namespace,
962
- name: object.identity.name,
963
- columns,
964
- query,
965
- owner: object.owner,
966
- provenance: object.provenance,
967
- dependencies
968
- });
969
- }
970
- return materializedViewObject({
971
- namespace: object.identity.namespace,
972
- name: object.identity.name,
973
- columns,
974
- query,
975
- owner: object.owner,
976
- provenance: object.provenance,
977
- dependencies,
978
- ...object.definition.refresh !== undefined ? { refresh: object.definition.refresh } : {}
979
- });
980
- });
981
- return catalog(next);
982
- } finally {
983
- await runner.query("set search_path to public");
984
- await dropScratch(runner);
985
- }
986
- }
987
- async function createViews(runner, views) {
988
- const pending = [...views];
989
- let last = "";
990
- for (let pass = 0;pass < views.length && pending.length > 0; pass += 1) {
991
- const failed = [];
992
- let created = 0;
993
- for (const object of pending) {
994
- const sql = object.kind === "materializedView" ? `create materialized view ${quoteIdent(object.identity.name)} as ${object.definition.query} with no data` : `create view ${quoteIdent(object.identity.name)} as ${object.definition.query}`;
995
- try {
996
- await runner.query(sql);
997
- created += 1;
998
- } catch (error) {
999
- last = error instanceof Error ? error.message : String(error);
1000
- failed.push(object);
1001
- }
1002
- }
1003
- if (created === 0) {
1004
- throw new OkmError2("OKM1020", `View ${failed[0]?.identity.name ?? ""} could not be created. ${last}`, {
1005
- fix: { summary: "The query has to run against the tables in this schema." }
1006
- });
1007
- }
1008
- pending.length = 0;
1009
- pending.push(...failed);
1010
- }
1011
- }
1012
- function stubTable(object, source) {
1013
- const columns = source.objects.filter((item) => item.kind === "column" && item.identity.parent.name === object.identity.name);
1014
- const lines = columns.map((column) => `${quoteIdent(column.identity.name)} ${column.definition.dataType}`);
1015
- return `create table ${quoteIdent(object.identity.name)} (${lines.join(", ")})`;
1016
- }
1017
- function readColumns(object, printed) {
1018
- const live = printed.length === 0 ? [] : printed.split(`
1019
- `);
1020
- const declared = object.definition.columns;
1021
- if (live.length !== declared.length) {
1022
- throw mismatch(object.identity.name, declared.map((column) => column.name).join(", "), printed);
1023
- }
1024
- return declared.map((column, index) => {
1025
- const line = live[index] ?? "";
1026
- const splitAt = line.indexOf("|");
1027
- const name = splitAt < 0 ? line : line.slice(0, splitAt);
1028
- const type = splitAt < 0 ? "" : line.slice(splitAt + 1);
1029
- if (name !== column.name || type !== column.dataType) {
1030
- throw mismatch(object.identity.name, `${column.name}:${column.dataType}`, live[index] ?? "");
1031
- }
1032
- return column;
1033
- });
1034
- }
1035
- function mismatch(view, declared, live) {
1036
- return new OkmError2("OKM1020", `View ${view} declares ${declared} and the database has ${live}.`, { fix: { summary: "Declare the columns the query returns, in that order, with those types." } });
1037
- }
1038
- async function dropScratch(runner) {
1039
- const present = await runner.query(`select 1 as ok from pg_namespace where nspname = $1`, [
1040
- SCRATCH
1041
- ]);
1042
- if (present.length === 0)
1043
- return;
1044
- const rows = await runner.query(`
1045
- select c.relname as name, c.relkind as kind
1046
- from pg_class c
1047
- join pg_namespace n on n.oid = c.relnamespace
1048
- where n.nspname = $1 and c.relkind in ('v', 'm', 'r')
1049
- `, [SCRATCH]);
1050
- const views = rows.filter((row) => cellText(row.kind) === "v" || cellText(row.kind) === "m");
1051
- for (let pass = 0;pass < Math.max(views.length, 1); pass += 1) {
1052
- for (const row of views) {
1053
- const kind = cellText(row.kind) === "m" ? "materialized view" : "view";
1054
- try {
1055
- await runner.query(`drop ${kind} if exists ${quoteIdent(SCRATCH)}.${quoteIdent(cellText(row.name))}`);
1056
- } catch {}
1057
- }
1058
- }
1059
- for (const row of rows) {
1060
- if (cellText(row.kind) !== "r")
1061
- continue;
1062
- await runner.query(`drop table if exists ${quoteIdent(SCRATCH)}.${quoteIdent(cellText(row.name))}`);
1063
- }
1064
- await runner.query(`drop schema if exists ${quoteIdent(SCRATCH)}`);
1065
- }
1066
-
1067
- // src/tooling/migrate/drift.ts
1068
- async function assertAuthorDrift(url, author, roles) {
1069
- const sql = postgres(url, {
1070
- max: 1,
1071
- connect_timeout: 5,
1072
- idle_timeout: 1,
1073
- onnotice: () => {}
1074
- });
1075
- try {
1076
- const present = await sql`
1077
- select to_regclass('public.okm_meta')::text as reg
1078
- `;
1079
- if (present[0]?.reg == null)
1080
- return;
1081
- const runner = queryOf(sql);
1082
- const managed = managedRoleNames(roles);
1083
- const authorOnServer = await sealViews(runner, author);
1084
- const live = await introspectSchema(runner, "public", "public", managed === undefined ? undefined : { managedRoles: managed });
1085
- const plan = planMigration({ before: live, after: authorOnServer, name: "check" });
1086
- if (plan.steps.length === 0)
1087
- return;
1088
- throw new OkmError2("OKM1520", `The database differs from the schema.
1089
- ${plan.steps.map((step) => step.sql).join(`
1090
- `)}`, {
1091
- fix: {
1092
- summary: "Change the schema or the database so okm check reports no difference."
1093
- }
1094
- });
1095
- } finally {
1096
- await sql.end({ timeout: 5 });
1097
- }
1098
- }
1099
- function managedRoleNames(roles) {
1100
- if (roles === undefined)
1101
- return;
1102
- const names = new Set([roles.migration, roles.app]);
1103
- for (const role of roles.managed ?? [])
1104
- names.add(role.name);
1105
- return [...names];
1106
- }
1107
- function queryOf(sql) {
1108
- return {
1109
- async query(text, params) {
1110
- const rows = await sql.unsafe(text, params === undefined ? undefined : [...params]);
1111
- return rows.map((row) => {
1112
- const copy = {};
1113
- for (const [key, value] of Object.entries(row))
1114
- copy[key] = value;
1115
- return copy;
1116
- });
1117
- }
1118
- };
1119
- }
1120
- export {
1121
- assertAuthorDrift
1122
- };
917
+ export { cellText, VIEW_DEPENDENCIES, viewDependencyEdges, PUBLIC, introspectSchema, FUNCTION_ARG_TYPES };
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  send,
3
3
  connectClient
4
- } from "./bqha5cg6.js";
4
+ } from "./6p5k20sm.js";
5
5
  import {
6
6
  isConnectionLost
7
7
  } from "./tbszx8mz.js";
8
8
  import {
9
9
  WireSession
10
- } from "./0jc3ffzf.js";
10
+ } from "./zvbjc949.js";
11
11
  import {
12
12
  rejectClosed,
13
13
  runCall
@@ -1,10 +1,12 @@
1
- import"./t616ynfn.js";
1
+ import"./8bwbwy8h.js";
2
2
  import"./n442h54c.js";
3
+ import"./wqem4jed.js";
3
4
  import {
4
5
  listTargets,
5
6
  loadConfig
6
- } from "./5nmdenb6.js";
7
- import"./2ssqrv66.js";
7
+ } from "./xdpj5kkm.js";
8
+ import"./ayz64vzj.js";
9
+ import"./8xsbagad.js";
8
10
 
9
11
  // src/tooling/migrate/dev.ts
10
12
  import { mkdirSync } from "node:fs";
@@ -17,7 +19,7 @@ async function devProject(cwd) {
17
19
  `;
18
20
  const directory = join(cwd, config.out ?? ".okm", "dev-db");
19
21
  mkdirSync(directory, { recursive: true });
20
- const { open } = await import("./kgnc8grt.js");
22
+ const { open } = await import("./gdh9mrtp.js");
21
23
  const pool = await open({ dataDir: directory });
22
24
  try {
23
25
  await pool.execute("select 1");