okmodel 0.9.0 → 0.9.1

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 (175) hide show
  1. package/README.md +9 -1
  2. package/dist/adapters/pg/bunsql-extra.d.ts +5 -5
  3. package/dist/adapters/pg/bunsql.d.ts +6 -2
  4. package/dist/adapters/pg/nodepostgres.d.ts +16 -1
  5. package/dist/adapters/pg/postgres-extra.d.ts +3 -17
  6. package/dist/adapters/pg/postgresjs.d.ts +2 -1
  7. package/dist/contracts/driver.d.ts +3 -2
  8. package/dist/contracts/error.d.ts +1 -1
  9. package/dist/dialects/pg/errors.d.ts +2 -0
  10. package/dist/dialects/pg/ext/fuzzystrmatch.js +1 -1
  11. package/dist/dialects/pg/ext/hstore.js +1 -1
  12. package/dist/dialects/pg/ext/ltree.js +1 -1
  13. package/dist/dialects/pg/ext/pgcrypto.js +1 -1
  14. package/dist/dialects/pg/ext/unaccent.js +1 -1
  15. package/dist/dialects/pg/filters.d.ts +2 -2
  16. package/dist/dialects/pg/fn/index.js +1 -1
  17. package/dist/dialects/pg/index.js +3 -3
  18. package/dist/dialects/pg/introspect.d.ts +12 -0
  19. package/dist/dialects/pg/view/index.js +2 -2
  20. package/dist/runtime/param-limit.d.ts +20 -0
  21. package/dist/runtime/pg/bun.js +3 -3
  22. package/dist/runtime/pg/neon.js +3 -3
  23. package/dist/runtime/pg/pg.js +3 -3
  24. package/dist/runtime/pg/pglite.js +2 -2
  25. package/dist/runtime/pg/postgresjs.js +10 -10
  26. package/dist/runtime/tenancy/index.js +1 -1
  27. package/dist/runtime/traits/index.js +2 -2
  28. package/dist/runtime/validate/index.js +2 -2
  29. package/dist/runtime/write.d.ts +1 -1
  30. package/dist/shared/{5kyb3tqx.js → 1h5h1rf5.js} +1 -1
  31. package/dist/shared/{4vbf83xx.js → 2vcnpf0n.js} +1 -1
  32. package/dist/shared/{8n688yjg.js → 3ap5hxvj.js} +2 -1
  33. package/dist/shared/{wvtjg5m3.js → 3d7a80fq.js} +1 -1
  34. package/dist/shared/{bphrgwz9.js → 3dr444ny.js} +57 -78
  35. package/dist/shared/{yvabyg9k.js → 3vvpcphd.js} +7 -6
  36. package/dist/shared/{760ppr76.js → 4a3mmhhe.js} +2 -2
  37. package/dist/shared/{90sg0w5a.js → 4pkz5nvw.js} +65 -10
  38. package/dist/shared/{mazpbcdj.js → 4te76xc5.js} +1 -1
  39. package/dist/shared/{xwhdcrm4.js → 60y4ahmw.js} +1 -1
  40. package/dist/shared/{9dtgn1z2.js → 63qjmhnp.js} +100 -17
  41. package/dist/shared/{s7he5e5d.js → 67w3kn71.js} +1 -1
  42. package/dist/shared/{n306gqkd.js → 6vfvsdkt.js} +9 -7
  43. package/dist/shared/{jpybhf98.js → 6xqvesa5.js} +1 -1
  44. package/dist/shared/{n5whk3mt.js → 8gdbty5v.js} +8 -8
  45. package/dist/shared/{ccsmhv9r.js → 8ma6drzr.js} +194 -31
  46. package/dist/shared/{3456242y.js → 8p2bgye0.js} +110 -18
  47. package/dist/shared/{ebhz8vh6.js → 8qwqrxed.js} +11 -3
  48. package/dist/shared/{ss2kv2rs.js → 8v7vzpgt.js} +10 -7
  49. package/dist/shared/{8qzkd9f3.js → ak61ye1f.js} +3 -3
  50. package/dist/shared/{6nae0spm.js → bdekbvmt.js} +69 -7
  51. package/dist/shared/{tw1nvvfj.js → bxjq6xqv.js} +2 -2
  52. package/dist/shared/{rbxt795q.js → c7dqd3gk.js} +81 -41
  53. package/dist/shared/ddh72ym5.js +20 -0
  54. package/dist/shared/e1c55v04.js +10 -0
  55. package/dist/shared/{8jesqsrk.js → ekhq3ytz.js} +1 -1
  56. package/dist/shared/{7ba5h6pb.js → esy4dyxe.js} +5 -5
  57. package/dist/shared/{gcefca6p.js → f9t9g54z.js} +22 -9
  58. package/dist/shared/fkjne6gx.js +8 -0
  59. package/dist/shared/{ds229x4r.js → fne90dvz.js} +4 -1
  60. package/dist/shared/{cexb7z6b.js → gr9sn4za.js} +1 -1
  61. package/dist/shared/{mvmm3xpb.js → gzgfsspx.js} +1 -1
  62. package/dist/shared/{fdsz3w80.js → hgt69zjf.js} +2 -2
  63. package/dist/shared/{dd5pmnky.js → jvxcp1qk.js} +70 -86
  64. package/dist/shared/{yybhre6n.js → k73e8n9d.js} +3 -3
  65. package/dist/shared/{mgaq2sd3.js → kzgrcy8s.js} +8 -7
  66. package/dist/shared/{myk8fswx.js → mz48rs74.js} +14 -3
  67. package/dist/shared/{62b603gr.js → n6je5b28.js} +10 -23
  68. package/dist/shared/{2szgv6yj.js → ns35jqz0.js} +71 -45
  69. package/dist/shared/{xtsydxjg.js → nstwgzn8.js} +1 -1
  70. package/dist/shared/{stfa9xcw.js → py2zrrm6.js} +7 -6
  71. package/dist/shared/{9dr2qnx7.js → qqm3ze6q.js} +1 -1
  72. package/dist/shared/{cf8zdz5p.js → rcjm0yn7.js} +27 -34
  73. package/dist/shared/{ckz05z15.js → rged92v6.js} +7 -4
  74. package/dist/shared/{qvwwp1mp.js → rw4tpcd0.js} +30 -21
  75. package/dist/shared/{bsek72fg.js → s5qe47a6.js} +3 -0
  76. package/dist/shared/{1d9q9cv2.js → smxzjz60.js} +2 -2
  77. package/dist/shared/{c3mvnq7a.js → th5rnaxw.js} +1 -1
  78. package/dist/shared/{1mxm04fy.js → tyqapcgk.js} +71 -8
  79. package/dist/shared/{zdqf8k5d.js → vsna85qf.js} +1 -1
  80. package/dist/shared/{63qtkrca.js → vy47ryqa.js} +55 -5
  81. package/dist/shared/{xv8qj97g.js → wbdh9qbg.js} +3 -1
  82. package/dist/shared/{2zdxkt7b.js → wp7y8q3y.js} +41 -9
  83. package/dist/shared/{pg4ezgyf.js → xbd9xs6p.js} +2 -2
  84. package/dist/shared/{npdftanb.js → xbvz446k.js} +16 -13
  85. package/dist/shared/{aksb89mn.js → y6tfjk9q.js} +2 -2
  86. package/dist/shared/{3bb7wsqt.js → ycnft340.js} +1 -1
  87. package/dist/shared/{z7s6fpxv.js → ymenf259.js} +1 -1
  88. package/dist/shared/{71n0jmhc.js → ysdw2fg3.js} +10 -2
  89. package/dist/shared/{xqacq37x.js → zecrwdk9.js} +1 -1
  90. package/dist/shared/{3t6kw83m.js → zm2rzqba.js} +2 -1
  91. package/dist/tooling/cli.js +122 -44
  92. package/dist/tooling/driver-run.js +107 -24
  93. package/dist/tooling/github/comment.d.ts +8 -2
  94. package/dist/tooling/migrate/apply.d.ts +17 -2
  95. package/dist/tooling/migrate/drift.d.ts +12 -0
  96. package/dist/tooling/migrate/driver-url.d.ts +17 -0
  97. package/dist/tooling/migrate/index.js +9 -7
  98. package/dist/tooling/migrate/policy.d.ts +17 -5
  99. package/dist/tooling/migrate/pooler-probe.d.ts +23 -0
  100. package/dist/tooling/migrate/pull.d.ts +3 -0
  101. package/dist/tooling/migrate/runner.d.ts +24 -1
  102. package/dist/tooling/shared/{0j0jtse1.js → 09a6vsys.js} +1 -1
  103. package/dist/tooling/shared/{68tf18v4.js → 0v9ptnxp.js} +8 -8
  104. package/dist/tooling/shared/{qartgazh.js → 0wtzps9p.js} +6 -6
  105. package/dist/tooling/shared/{1800eymw.js → 0yhf1db4.js} +6 -6
  106. package/dist/tooling/shared/{s6qha57m.js → 19msgrsc.js} +2 -2
  107. package/dist/tooling/shared/{3yn79q5m.js → 1fwfm5m3.js} +1 -1
  108. package/dist/tooling/shared/{hfq3n3bd.js → 2jdn09e2.js} +55 -5
  109. package/dist/tooling/shared/{v6j1ep6w.js → 2qrte2ct.js} +5 -5
  110. package/dist/tooling/shared/{yb4kd19s.js → 2v4nwnkb.js} +1 -1
  111. package/dist/tooling/shared/{ezqn88nj.js → 33z39trp.js} +106 -23
  112. package/dist/tooling/shared/{0r05zhyq.js → 353vnw9z.js} +5 -5
  113. package/dist/tooling/shared/{m4hhb8aa.js → 390kry9g.js} +2 -2
  114. package/dist/tooling/shared/{rcywj2w8.js → 3f6etb9z.js} +18 -31
  115. package/dist/tooling/shared/{9wsnsvbf.js → 3t2cqmsx.js} +1 -1
  116. package/dist/tooling/shared/{5zrzffnk.js → 4dzvjtpy.js} +1 -1
  117. package/dist/tooling/shared/{am04v8na.js → 4ec0nxvw.js} +10 -10
  118. package/dist/tooling/shared/{04svnxxj.js → 4tg2bn41.js} +59 -78
  119. package/dist/tooling/shared/{829fjxyw.js → 5rah55z0.js} +2 -2
  120. package/dist/tooling/shared/{c0xevn1h.js → 804w1t69.js} +4 -4
  121. package/dist/tooling/shared/{dhatassp.js → 8g0m0rvd.js} +6 -6
  122. package/dist/tooling/shared/{zx3v9phv.js → 8msbtw5s.js} +1 -1
  123. package/dist/tooling/shared/{7pxncnzs.js → 8t22h3h7.js} +2 -2
  124. package/dist/tooling/shared/{wbwq1jsa.js → 91c59b7b.js} +2 -2
  125. package/dist/tooling/shared/{a2xe04bm.js → adk9k6va.js} +1 -1
  126. package/dist/tooling/shared/{w17sj05d.js → ajjd5cwz.js} +2 -2
  127. package/dist/tooling/shared/{35zemrmf.js → angjck01.js} +1 -1
  128. package/dist/tooling/shared/{jsjjz875.js → asnnc3v5.js} +1 -1
  129. package/dist/tooling/shared/{5bmksndh.js → bj1kyqc8.js} +2 -2
  130. package/dist/tooling/shared/{kbqnrs1x.js → bt3tjemb.js} +11 -3
  131. package/dist/tooling/shared/{vwr2y833.js → chk2bh4f.js} +2 -2
  132. package/dist/tooling/shared/{ybdew6j7.js → ckq4z5ax.js} +5 -2
  133. package/dist/tooling/shared/{3rmaz3pq.js → d3rhb24q.js} +1 -1
  134. package/dist/tooling/shared/{mw5npye0.js → d8q00vxg.js} +4 -4
  135. package/dist/tooling/shared/{j664qjrt.js → dx188rxs.js} +2 -2
  136. package/dist/tooling/shared/{8yr7ges1.js → efq6p9df.js} +35 -42
  137. package/dist/tooling/shared/{yhp829bx.js → en6rwzq0.js} +3 -3
  138. package/dist/tooling/shared/{f77nnfqy.js → f2r5g0fs.js} +2 -2
  139. package/dist/tooling/shared/{zs9aymcp.js → f4gep0nk.js} +1 -1
  140. package/dist/tooling/shared/{kz715295.js → f8a010fm.js} +13 -11
  141. package/dist/tooling/shared/{w5d89rb4.js → fdsek6pa.js} +1 -1
  142. package/dist/tooling/shared/fvmrxsd1.js +8 -0
  143. package/dist/tooling/shared/{jpgmjsx3.js → g3xybeqf.js} +4 -3
  144. package/dist/tooling/shared/{wezxf3h8.js → gefmpwsa.js} +1 -1
  145. package/dist/tooling/shared/{jr2nmr81.js → gjj71hfh.js} +23 -20
  146. package/dist/tooling/shared/{9sfbtwsk.js → jgzt69pa.js} +5 -5
  147. package/dist/tooling/shared/{a4pzghha.js → jm30k2ca.js} +10 -8
  148. package/dist/tooling/shared/{shjs0379.js → kayqzpbk.js} +6 -3
  149. package/dist/tooling/shared/{tcwpjvxe.js → kvw1672d.js} +1 -1
  150. package/dist/tooling/shared/{stebqyyd.js → mr1kcgpw.js} +3 -3
  151. package/dist/tooling/shared/{tpssp7ac.js → mwbdf409.js} +1 -1
  152. package/dist/tooling/shared/{fh07z1dt.js → ns9207v3.js} +1 -1
  153. package/dist/tooling/shared/{5p8km5jb.js → p6tjv97k.js} +3 -3
  154. package/dist/tooling/shared/{ytk1tjs0.js → p73evwf0.js} +1 -1
  155. package/dist/tooling/shared/{8m5znpdt.js → phc1nc4g.js} +1 -1
  156. package/dist/tooling/shared/{asgr07mp.js → ppybjw50.js} +79 -16
  157. package/dist/tooling/shared/{t4xveemq.js → qdrn8ghn.js} +5 -4
  158. package/dist/tooling/shared/rd8h01ta.js +20 -0
  159. package/dist/tooling/shared/{7aews1zg.js → rwg8y90m.js} +3 -3
  160. package/dist/tooling/shared/{5x3pf400.js → ry2f3w8p.js} +3 -3
  161. package/dist/tooling/shared/{m3xt8b1h.js → ryc5sa58.js} +8 -8
  162. package/dist/tooling/shared/{57btdkgm.js → ss87qxwv.js} +2 -2
  163. package/dist/tooling/shared/{6vk28rjp.js → vg68k11z.js} +3 -3
  164. package/dist/tooling/shared/{62fxpc1p.js → vms9dta5.js} +73 -89
  165. package/dist/tooling/shared/{gqwevek4.js → xchpnbdv.js} +1 -1
  166. package/dist/tooling/shared/{t6zjeake.js → xn6p01fh.js} +5 -5
  167. package/dist/tooling/shared/{7b3xp9gc.js → xwr6q618.js} +3 -3
  168. package/dist/tooling/shared/{yfedr1zb.js → xx3gmq94.js} +1 -1
  169. package/dist/tooling/shared/{9qr9rkbh.js → y2bd7yfx.js} +21 -13
  170. package/dist/tooling/shared/{nxq95eb6.js → y4gq9rbe.js} +11 -11
  171. package/dist/tooling/shared/{76pv6qff.js → y4vwft92.js} +2 -2
  172. package/dist/tooling/shared/{sjwkt1pg.js → yz68xcmc.js} +1 -1
  173. package/dist/tooling/testing/factories.d.ts +1 -3
  174. package/dist/tooling/testing/index.js +1 -1
  175. package/package.json +2 -1
@@ -4,10 +4,10 @@ import {
4
4
  import {
5
5
  viewGlobalReason,
6
6
  viewMentions
7
- } from "./760ppr76.js";
7
+ } from "./4a3mmhhe.js";
8
8
  import {
9
9
  createClient
10
- } from "./npdftanb.js";
10
+ } from "./xbvz446k.js";
11
11
  import {
12
12
  OkmError2
13
13
  } from "./52szzakm.js";
@@ -189,29 +189,30 @@ function bindFactories(host, definitions) {
189
189
  }
190
190
  return bound;
191
191
  }
192
- async function insertRow(host, table, overrides, children, inherited) {
193
- if (host.creating.has(table)) {
192
+ async function insertRow(host, table, overrides, children, inherited, creating) {
193
+ const inflight = creating ?? new Set;
194
+ if (inflight.has(table)) {
194
195
  throw new OkmError2("invalid", `Factory cycle at ${table}.`, {
195
196
  fix: { summary: "A ref() points back at a row that is still being created." }
196
197
  });
197
198
  }
198
- host.creating.add(table);
199
+ inflight.add(table);
199
200
  try {
200
- return await insertPrepared(host, table, overrides, children, inherited);
201
+ return await insertPrepared(host, table, overrides, children, inherited, inflight);
201
202
  } finally {
202
- host.creating.delete(table);
203
+ inflight.delete(table);
203
204
  }
204
205
  }
205
- async function insertPrepared(host, table, overrides, children, inherited) {
206
+ async function insertPrepared(host, table, overrides, children, inherited, creating) {
206
207
  const facts = requireTable(host, table);
207
208
  const defined = host.definitions.get(table)?.(context(host)) ?? {};
208
209
  const merged = { ...defined, ...overrides };
209
- const key = host.schema.tenancy?.key;
210
- const taken = takeTenant(merged, facts.tenant ? key : undefined);
210
+ const keys = tenantKeyNames(host);
211
+ const taken = takeTenant(merged, facts.tenant ? keys : []);
211
212
  const requested = taken.tenant ?? inherited;
212
213
  const tenant = facts.tenant ? requested ?? host.rng.uuid() : undefined;
213
- const resolved = await resolveRefs(host, taken.rest, tenant);
214
- await fillRequired(host, facts, resolved, tenant);
214
+ const resolved = await resolveRefs(host, taken.rest, tenant, creating);
215
+ await fillRequired(host, facts, resolved, tenant, creating);
215
216
  const row = await writeRow(host, facts, resolved, tenant);
216
217
  host.cache.set(cacheKey(table, facts.tenant ? tenant : undefined), row);
217
218
  host.created.set(table, (host.created.get(table) ?? 0) + 1);
@@ -227,7 +228,7 @@ async function insertPrepared(host, table, overrides, children, inherited) {
227
228
  }
228
229
  const link = linkFields(host, facts, requireTable(host, child), row);
229
230
  for (let index = 0;index < count; index += 1) {
230
- await insertRow(host, child, link, undefined, tenant);
231
+ await insertRow(host, child, link, undefined, tenant, creating);
231
232
  }
232
233
  }
233
234
  }
@@ -276,20 +277,26 @@ function context(host) {
276
277
  }
277
278
  };
278
279
  }
279
- function takeTenant(row, key) {
280
- if (key === undefined || !Object.hasOwn(row, key))
280
+ function takeTenant(row, keys) {
281
+ if (keys.length === 0)
281
282
  return { tenant: undefined, rest: row };
282
- const value = row[key];
283
283
  const rest = { ...row };
284
- delete rest[key];
285
- if (typeof value !== "string" || value.length === 0) {
286
- throw new OkmError2("invalid", `${key} must be a uuid string.`, {
287
- fix: { summary: `Pass create({ ${key} }) the tenant uuid.` }
288
- });
284
+ let tenant;
285
+ for (const key of keys) {
286
+ if (!Object.hasOwn(rest, key))
287
+ continue;
288
+ const value = rest[key];
289
+ delete rest[key];
290
+ if (typeof value !== "string" || value.length === 0) {
291
+ throw new OkmError2("invalid", `${key} must be a uuid string.`, {
292
+ fix: { summary: `Pass create({ ${key} }) the tenant uuid.` }
293
+ });
294
+ }
295
+ tenant ??= value;
289
296
  }
290
- return { tenant: value, rest };
297
+ return { tenant, rest };
291
298
  }
292
- async function resolveRefs(host, row, tenant) {
299
+ async function resolveRefs(host, row, tenant, creating) {
293
300
  const resolved = {};
294
301
  for (const field of Object.keys(row)) {
295
302
  const value = row[field];
@@ -298,18 +305,18 @@ async function resolveRefs(host, row, tenant) {
298
305
  resolved[field] = value;
299
306
  continue;
300
307
  }
301
- resolved[field] = primaryValue(await referenced(host, target, tenant), requireTable(host, target), host.schema.tenancy?.key);
308
+ resolved[field] = primaryValue(await referenced(host, target, tenant, creating), requireTable(host, target), tenantKeyNames(host));
302
309
  }
303
310
  return resolved;
304
311
  }
305
- async function fillRequired(host, facts, row, tenant) {
312
+ async function fillRequired(host, facts, row, tenant, creating) {
306
313
  for (const column of facts.columns) {
307
314
  if (!isRequired(column) || Object.hasOwn(row, column.field))
308
315
  continue;
309
316
  const foreign = facts.foreignKeys.find((key) => key.columns.includes(column.sql));
310
317
  if (foreign !== undefined) {
311
318
  const target = factsBySql(host, foreign.target);
312
- const parent = await referenced(host, target.name, tenant);
319
+ const parent = await referenced(host, target.name, tenant, creating);
313
320
  assignForeign(host, facts, foreign, parent, row);
314
321
  if (Object.hasOwn(row, column.field))
315
322
  continue;
@@ -319,7 +326,7 @@ async function fillRequired(host, facts, row, tenant) {
319
326
  }
320
327
  function assignForeign(host, child, foreign, parent, row) {
321
328
  const target = factsBySql(host, foreign.target);
322
- const key = host.schema.tenancy?.key;
329
+ const keys = new Set(tenantKeyNames(host));
323
330
  for (let index = 0;index < foreign.columns.length; index += 1) {
324
331
  const childSql = foreign.columns[index];
325
332
  const parentSql = foreign.targetColumns[index];
@@ -327,25 +334,36 @@ function assignForeign(host, child, foreign, parent, row) {
327
334
  continue;
328
335
  const field = fieldOf(child, childSql);
329
336
  const source = fieldOf(target, parentSql);
330
- if (field === undefined || source === undefined || field === key)
337
+ if (field === undefined || source === undefined || keys.has(field))
331
338
  continue;
332
339
  if (!Object.hasOwn(row, field))
333
340
  row[field] = parent[source];
334
341
  }
335
342
  }
336
- async function referenced(host, table, tenant) {
343
+ async function referenced(host, table, tenant, creating) {
337
344
  const facts = requireTable(host, table);
338
345
  const scope = facts.tenant ? tenant : undefined;
339
346
  const cached = host.cache.get(cacheKey(table, scope));
340
347
  if (cached !== undefined)
341
348
  return cached;
342
- return insertRow(host, table, scope === undefined ? undefined : tenantOverride(host, scope), undefined, scope);
349
+ return insertRow(host, table, scope === undefined ? undefined : tenantOverride(host, scope), undefined, scope, creating);
343
350
  }
344
351
  function tenantOverride(host, tenant) {
345
- const key = host.schema.tenancy?.key;
346
- if (key === undefined)
352
+ const keys = tenantKeyNames(host);
353
+ if (keys.length === 0)
347
354
  return;
348
- return { [key]: tenant };
355
+ const overrides = {};
356
+ for (const key of keys)
357
+ overrides[key] = tenant;
358
+ return overrides;
359
+ }
360
+ function tenantKeyNames(host) {
361
+ const tenancy = host.schema.tenancy;
362
+ if (tenancy === undefined)
363
+ return [];
364
+ if (tenancy.keys !== undefined && tenancy.keys.length > 0)
365
+ return tenancy.keys;
366
+ return [tenancy.key];
349
367
  }
350
368
  function linkFields(host, parent, child, row) {
351
369
  const many = parent.relations.find((relation) => relation.kind === "many" && relation.table === child.name);
@@ -366,7 +384,7 @@ function linkFields(host, parent, child, row) {
366
384
  });
367
385
  }
368
386
  function paired(host, child, parent, childSql, parentSql, row) {
369
- const key = host.schema.tenancy?.key;
387
+ const keys = new Set(tenantKeyNames(host));
370
388
  const linked = {};
371
389
  for (let index = 0;index < childSql.length; index += 1) {
372
390
  const childName = childSql[index];
@@ -375,7 +393,7 @@ function paired(host, child, parent, childSql, parentSql, row) {
375
393
  continue;
376
394
  const field = fieldOf(child, childName);
377
395
  const source = fieldOf(parent, parentName);
378
- if (field === undefined || source === undefined || field === key)
396
+ if (field === undefined || source === undefined || keys.has(field))
379
397
  continue;
380
398
  linked[field] = row[source];
381
399
  }
@@ -463,8 +481,9 @@ function enumLabels(catalog, dataType) {
463
481
  }
464
482
  return;
465
483
  }
466
- function primaryValue(row, facts, tenantKey) {
467
- const fields = facts.primary.filter((field) => field !== tenantKey);
484
+ function primaryValue(row, facts, tenantKeys) {
485
+ const skip = new Set(tenantKeys);
486
+ const fields = facts.primary.filter((field) => !skip.has(field));
468
487
  if (fields.length !== 1) {
469
488
  throw new OkmError2("invalid", `ref(${facts.name}) needs a single primary key.`, {
470
489
  fix: { summary: "Set the foreign-key columns in the factory." }
@@ -590,16 +609,18 @@ async function isolation(host) {
590
609
  }
591
610
  }
592
611
  async function checkTable(host, facts, tenantA, tenantB) {
593
- const key = host.schema.tenancy?.key;
594
- if (key === undefined)
595
- return;
596
612
  const keys = tenantKeys(host);
613
+ if (keys.length === 0)
614
+ return;
597
615
  if (host.definitions.size > 0 && !host.definitions.has(facts.name)) {
598
616
  throw new OkmError2("invalid", `Factory ${facts.name} is missing.`, {
599
617
  fix: { summary: `Add ${facts.name} to factories().` }
600
618
  });
601
619
  }
602
- const row = await insertRow(host, facts.name, { [key]: tenantB }, undefined, tenantB);
620
+ const overrides = {};
621
+ for (const key of keys)
622
+ overrides[key] = tenantB;
623
+ const row = await insertRow(host, facts.name, overrides, undefined, tenantB);
603
624
  const where = primaryWhere(facts, row, keys);
604
625
  const client = openTenant(host, tenantA);
605
626
  const handle = tableHandle2(client, facts.name);
@@ -762,7 +783,14 @@ async function checkFlips(host, facts, keys, tenantA, tenantB) {
762
783
  continue;
763
784
  values[flipped] = tenantB;
764
785
  const client = openTenant(host, values);
765
- const stored = await tableHandle2(client, facts.name).insert(data);
786
+ let stored;
787
+ try {
788
+ stored = await tableHandle2(client, facts.name).insert(data);
789
+ } catch (error) {
790
+ if (error instanceof OkmError2 && error.kind === "foreign_key")
791
+ continue;
792
+ throw error;
793
+ }
766
794
  if (!isRow2(stored))
767
795
  continue;
768
796
  const where = primaryWhere(facts, stored, keys);
@@ -863,9 +891,8 @@ async function checkView(host, view, keys, tenantA, tenantB) {
863
891
  for (const tenant of [tenantA, tenantB]) {
864
892
  for (const name of sources) {
865
893
  const facts = requireFacts(host, name);
866
- const key = keys[0];
867
894
  const overrides = markerFor(view, facts, keys, tenant);
868
- if (key !== undefined)
895
+ for (const key of keys)
869
896
  overrides[key] = tenant;
870
897
  const row = await insertRow(host, name, overrides, undefined, tenant);
871
898
  if (tenant === tenantB)
@@ -1317,7 +1344,6 @@ async function testing2(schema, options) {
1317
1344
  facts,
1318
1345
  rng: rng(seed),
1319
1346
  cache: new Map,
1320
- creating: new Set,
1321
1347
  created: new Map,
1322
1348
  definitions: new Map
1323
1349
  };
@@ -3,7 +3,7 @@ import {
3
3
  readHandle,
4
4
  readCall,
5
5
  attachHttp
6
- } from "./npdftanb.js";
6
+ } from "./xbvz446k.js";
7
7
  import {
8
8
  emitWhere,
9
9
  emitOrder,
@@ -1,18 +1,19 @@
1
1
  import {
2
2
  open2
3
- } from "./dd5pmnky.js";
3
+ } from "./jvxcp1qk.js";
4
4
  import"./12z7aznj.js";
5
5
  import"./n442h54c.js";
6
6
  import"./fk9vef30.js";
7
7
  import {
8
8
  openProject
9
- } from "./2zdxkt7b.js";
9
+ } from "./wp7y8q3y.js";
10
10
  import {
11
+ driverUrl,
11
12
  sessionFailure,
12
13
  finishQuiet,
13
14
  assertTargetPolicy,
14
15
  selectTarget
15
- } from "./6nae0spm.js";
16
+ } from "./bdekbvmt.js";
16
17
  import {
17
18
  isExactVersion,
18
19
  compareExtensionVersions
@@ -41,7 +42,7 @@ var TYPES = `
41
42
  where e.extname = $1
42
43
  and d.deptype = 'e'
43
44
  and d.classid = 'pg_type'::regclass
44
- and t.typtype in ('b', 'e', 'd')
45
+ and t.typtype in ('b', 'e', 'd', 'c')
45
46
  order by t.typname
46
47
  `;
47
48
  var FUNCTIONS = `
@@ -312,7 +313,7 @@ async function extProject(cwd, command, flags) {
312
313
  const opened = await openProject(cwd);
313
314
  const target = selectTarget(opened.config, flags.target);
314
315
  assertTargetPolicy(target, "check", flags.allowProtected);
315
- const pool = open2({ url: target.url, max: 1 });
316
+ const pool = open2({ url: driverUrl(target.url), max: 1 });
316
317
  try {
317
318
  if (command === "list")
318
319
  return formatList(await readExtensions(pool));
@@ -424,7 +425,7 @@ async function withServer(cwd, flags, body) {
424
425
  const opened = await openProject(cwd);
425
426
  const target = selectTarget(opened.config, flags.target);
426
427
  assertTargetPolicy(target, "check", flags.allowProtected);
427
- const pool = open2({ url: target.url, max: 1 });
428
+ const pool = open2({ url: driverUrl(target.url), max: 1 });
428
429
  try {
429
430
  return await body(pool);
430
431
  } catch (error) {
@@ -17,7 +17,7 @@ import {
17
17
  snakeCase,
18
18
  emittedTypeName,
19
19
  rejectLater
20
- } from "./gcefca6p.js";
20
+ } from "./f9t9g54z.js";
21
21
  import {
22
22
  ColumnBuilder2,
23
23
  formatType
@@ -4,8 +4,8 @@ import {
4
4
  import {
5
5
  send2,
6
6
  reserve,
7
- park
8
- } from "./62b603gr.js";
7
+ releaseReserved
8
+ } from "./n6je5b28.js";
9
9
  import {
10
10
  resetSession2,
11
11
  refuseWhenLost2
@@ -62,19 +62,13 @@ function lostQuery(error) {
62
62
  function socketClosed(error) {
63
63
  if (!(error instanceof Error))
64
64
  return false;
65
- if (error.message === "Connection closed")
65
+ if (bunClosed(error.message))
66
66
  return true;
67
- return error.cause instanceof Error && error.cause.message === "Connection closed";
67
+ return error.cause instanceof Error && bunClosed(error.cause.message);
68
68
  }
69
- async function listen(sql, parked, closed, channel, onNotify) {
69
+ async function listen(sql, closed, channel, onNotify) {
70
70
  if (closed)
71
71
  return rejectClosed();
72
- const pending = parked.splice(0);
73
- for (const reserved of pending) {
74
- const done = reserved.release();
75
- if (done instanceof Promise)
76
- await done;
77
- }
78
72
  const subscription = await sql.listen(channel, onNotify);
79
73
  return async () => {
80
74
  await subscription.unlisten();
@@ -84,7 +78,7 @@ async function checkout(held) {
84
78
  const { counters, isClosed } = held;
85
79
  if (isClosed())
86
80
  return rejectClosed();
87
- const reserved = await takeOpen(held) ?? await reserve(held.sql, held.acquireMs, counters);
81
+ const reserved = await reserve(held.sql, held.acquireMs, counters);
88
82
  counters.reserved += 1;
89
83
  const session = new WireSession((text, params) => send2(reserved, text, params), held.notices, isClosed, false, () => {
90
84
  counters.reservedBusy += 1;
@@ -140,20 +134,33 @@ async function checkout(held) {
140
134
  try {
141
135
  if (!lost.on)
142
136
  await reset(session, reserved);
143
- } catch (error) {
144
- if (lostQuery(error) || reportsClosed(reserved))
145
- lost.on = true;
146
- else
147
- throw error;
137
+ else if (session.depth() > 0 && !reportsClosed(reserved)) {
138
+ await reserved.unsafe("ROLLBACK").catch(() => {
139
+ return;
140
+ });
141
+ session.abandon();
142
+ }
143
+ } catch {
144
+ lost.on = true;
148
145
  } finally {
149
146
  counters.reserved = Math.max(0, counters.reserved - 1);
150
147
  if (lost.on) {
151
148
  try {
152
149
  reserved.release();
153
150
  } catch {}
154
- await flushClosed(held.sql);
155
- } else
156
- await park(held.parked, reserved);
151
+ if (counters.reserved === 0)
152
+ await flushClosed(held.sql);
153
+ } else {
154
+ try {
155
+ await releaseReserved(reserved);
156
+ } catch {
157
+ try {
158
+ reserved.release();
159
+ } catch {}
160
+ if (counters.reserved === 0)
161
+ await flushClosed(held.sql);
162
+ }
163
+ }
157
164
  }
158
165
  }
159
166
  };
@@ -161,20 +168,6 @@ async function checkout(held) {
161
168
  function reportsClosed(reserved) {
162
169
  return Reflect.get(reserved, "closed") === true;
163
170
  }
164
- async function takeOpen(held) {
165
- while (held.parked.length > 0) {
166
- const next = held.parked.pop();
167
- if (next === undefined)
168
- return;
169
- if (!reportsClosed(next))
170
- return next;
171
- try {
172
- next.release();
173
- } catch {}
174
- await flushClosed(held.sql);
175
- }
176
- return;
177
- }
178
171
  async function flushClosed(sql) {
179
172
  for (let attempt = 0;attempt < 3; attempt += 1) {
180
173
  try {
@@ -1,14 +1,17 @@
1
1
  import {
2
2
  assertAuthorDrift2,
3
+ sealDomainChecks2,
3
4
  catalogQuery2,
4
5
  managedRoleOptions2
5
- } from "./90sg0w5a.js";
6
- import"./myk8fswx.js";
7
- import"./6nae0spm.js";
6
+ } from "./4pkz5nvw.js";
7
+ import"./e1c55v04.js";
8
+ import"./mz48rs74.js";
9
+ import"./bdekbvmt.js";
8
10
  import"./fk9vef30.js";
9
11
  import"./12z7aznj.js";
10
12
  export {
11
13
  assertAuthorDrift2 as assertAuthorDrift,
12
14
  catalogQuery2 as catalogQuery,
13
- managedRoleOptions2 as managedRoleOptions
15
+ managedRoleOptions2 as managedRoleOptions,
16
+ sealDomainChecks2 as sealDomainChecks
14
17
  };
@@ -6,31 +6,35 @@ import {
6
6
  } from "./fk9vef30.js";
7
7
  import"./n442h54c.js";
8
8
  import"./cm3w0ywp.js";
9
- import"./dd5pmnky.js";
9
+ import"./jvxcp1qk.js";
10
10
  import {
11
11
  watchReserved2
12
- } from "./bphrgwz9.js";
13
- import {
14
- ensureMigrationTables2
15
- } from "./ccsmhv9r.js";
12
+ } from "./3dr444ny.js";
16
13
  import {
17
14
  sealViews,
18
15
  catalogQuery2,
19
16
  managedRoleOptions2
20
- } from "./90sg0w5a.js";
17
+ } from "./4pkz5nvw.js";
18
+ import {
19
+ ensureMigrationTables2
20
+ } from "./8ma6drzr.js";
21
21
  import {
22
22
  assumeRole,
23
23
  grantSchema,
24
+ ownSchema,
24
25
  assertSchemaUsageLanded,
25
26
  catalogsEqual,
26
27
  snapshotDifference
27
- } from "./3456242y.js";
28
+ } from "./8p2bgye0.js";
28
29
  import {
29
30
  roleExists
30
- } from "./jpybhf98.js";
31
+ } from "./6xqvesa5.js";
32
+ import {
33
+ probeStableBackend
34
+ } from "./e1c55v04.js";
31
35
  import {
32
36
  introspectSchema
33
- } from "./myk8fswx.js";
37
+ } from "./mz48rs74.js";
34
38
  import {
35
39
  projectPath,
36
40
  loadSnapshots,
@@ -44,22 +48,23 @@ import {
44
48
  hasError,
45
49
  lintRefusal,
46
50
  openProject
47
- } from "./2zdxkt7b.js";
51
+ } from "./wp7y8q3y.js";
48
52
  import {
53
+ driverUrl,
49
54
  sqlStatements,
50
55
  transactionControl,
51
56
  canonicalTypeName,
52
57
  createdRoleName,
53
58
  createRoleOnce,
59
+ changesRole,
54
60
  classOf,
55
61
  strictestClass,
56
62
  planMigration,
57
63
  sessionFailure,
58
64
  finishQuiet,
59
65
  assertDirectConnection,
60
- assertStableBackend,
61
66
  selectTarget
62
- } from "./6nae0spm.js";
67
+ } from "./bdekbvmt.js";
63
68
  import {
64
69
  isConnectionLost
65
70
  } from "./cnkky55j.js";
@@ -154,7 +159,7 @@ function retargetSteps(steps, schema, source = "public") {
154
159
  }));
155
160
  }
156
161
  async function inCheckTransaction(url, scratch, config, allowPooler, run) {
157
- const sql = postgres(url, {
162
+ const sql = postgres(driverUrl(url), {
158
163
  max: 1,
159
164
  connect_timeout: 5,
160
165
  idle_timeout: 1,
@@ -174,7 +179,7 @@ async function inCheckTransaction(url, scratch, config, allowPooler, run) {
174
179
  let rolledBack = false;
175
180
  let xid = "";
176
181
  try {
177
- await assertStableBackend(async () => {
182
+ await probeStableBackend(url, async () => {
178
183
  const rows = await reserved.unsafe("select pg_backend_pid()::text as pid");
179
184
  const pid = cell(rows[0], "pid");
180
185
  return pid ?? "";
@@ -273,7 +278,7 @@ function closedError() {
273
278
  return Object.assign(new Error("CONNECTION_CLOSED"), { code: "CONNECTION_CLOSED" });
274
279
  }
275
280
  async function dropScratch(url, scratch) {
276
- const sql = postgres(url, {
281
+ const sql = postgres(driverUrl(url), {
277
282
  max: 1,
278
283
  connect_timeout: 5,
279
284
  idle_timeout: 1,
@@ -322,6 +327,9 @@ async function runSteps(sql, connection, scratch, migrationRole, migration, sess
322
327
  if (prepared.sql.length === 0)
323
328
  continue;
324
329
  try {
330
+ if (migrationRole !== undefined && !changesRole(step.sql) && session.setRole !== migrationRole && await roleExists(connection, migrationRole)) {
331
+ await assumeRole(connection, migrationRole, session);
332
+ }
325
333
  const created = createdRoleName(step.sql);
326
334
  const existed = created !== undefined && await roleExists(connection, created);
327
335
  if (step.backfill !== undefined) {
@@ -332,17 +340,18 @@ async function runSteps(sql, connection, scratch, migrationRole, migration, sess
332
340
  } else if (!existed) {
333
341
  await sql.unsafe(createRoleOnce(prepared.sql.replace(/;\s*$/, "")));
334
342
  }
335
- if (created !== undefined && created === migrationRole) {
336
- if (!existed) {
337
- await grantSchema(connection, scratch, created);
338
- await connection.execute(`grant select, insert, update on okm_meta, okm_history, okm_backfill to ${quoteIdent2(created)}`);
339
- }
340
- await assumeRole(connection, created, session);
343
+ if (created !== undefined && created === migrationRole && !existed) {
344
+ await grantSchema(connection, scratch, created);
345
+ await ownSchema(connection, scratch, created);
346
+ await connection.execute(`grant select, insert, update on okm_meta, okm_history, okm_backfill to ${quoteIdent2(created)}`);
341
347
  }
342
348
  } catch (error) {
343
349
  throw failStep(migration.id, index, error);
344
350
  }
345
351
  }
352
+ if (migrationRole !== undefined && session.setRole !== migrationRole && await roleExists(connection, migrationRole)) {
353
+ await assumeRole(connection, migrationRole, session);
354
+ }
346
355
  }
347
356
  function prepareCheckSql(sql) {
348
357
  const parts = sqlStatements(sql);
@@ -54,6 +54,9 @@ function scanLiteral(literal, state) {
54
54
  for (let index = 0;index < literal.length; index += 1) {
55
55
  const char = literal[index] ?? "";
56
56
  const code = literal.charCodeAt(index);
57
+ if (char === "\\") {
58
+ fragmentError("A fragment cannot include a backslash.", "Pass the value as an interpolation.");
59
+ }
57
60
  if (state.quote !== undefined) {
58
61
  if (char !== state.quote)
59
62
  continue;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  emitSqlSelect,
3
3
  decodeSqlNumber
4
- } from "./3bb7wsqt.js";
4
+ } from "./ycnft340.js";
5
5
  import {
6
6
  refusePrototypeKey
7
7
  } from "./a62rb2da.js";
@@ -10,7 +10,7 @@ import {
10
10
  } from "./9a4ae4p8.js";
11
11
  import {
12
12
  readSelectFragment
13
- } from "./bsek72fg.js";
13
+ } from "./s5qe47a6.js";
14
14
  import {
15
15
  emitWhere,
16
16
  emitOrder,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  build2,
3
3
  identityColumn2
4
- } from "./s7he5e5d.js";
4
+ } from "./67w3kn71.js";
5
5
  export {
6
6
  build2 as build,
7
7
  identityColumn2 as identityColumn