okmodel 0.5.1 → 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 (155) hide show
  1. package/README.md +29 -14
  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 +5 -4
  19. package/dist/dialects/pg/fn/index.js +2 -2
  20. package/dist/dialects/pg/index.d.ts +2 -1
  21. package/dist/dialects/pg/index.js +23 -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/owner.d.ts +42 -0
  25. package/dist/dialects/pg/path-endpoint.d.ts +20 -0
  26. package/dist/dialects/pg/role/check.d.ts +3 -0
  27. package/dist/dialects/pg/role/index.d.ts +71 -6
  28. package/dist/dialects/pg/role/sql.d.ts +11 -0
  29. package/dist/dialects/pg/schema.d.ts +2 -0
  30. package/dist/dialects/pg/table.d.ts +25 -3
  31. package/dist/dialects/pg/tenancy.d.ts +45 -3
  32. package/dist/dialects/pg/view/client.d.ts +19 -1
  33. package/dist/dialects/pg/view/index.d.ts +4 -0
  34. package/dist/dialects/pg/view/index.js +21 -178
  35. package/dist/dialects/pg/view/refresh.d.ts +24 -0
  36. package/dist/runtime/batch.d.ts +1 -1
  37. package/dist/runtime/conflict.d.ts +2 -2
  38. package/dist/runtime/drift.d.ts +9 -0
  39. package/dist/runtime/inflight.d.ts +14 -0
  40. package/dist/runtime/pg/bun.js +4 -3
  41. package/dist/runtime/pg/pg.js +3 -3
  42. package/dist/runtime/pg/pglite.js +4 -3
  43. package/dist/runtime/pg/postgresjs.js +3 -3
  44. package/dist/runtime/plan.d.ts +18 -10
  45. package/dist/runtime/predicate.d.ts +19 -0
  46. package/dist/runtime/safety/index.js +1 -1
  47. package/dist/runtime/tenancy/composite.d.ts +26 -0
  48. package/dist/runtime/tenancy/context.d.ts +16 -0
  49. package/dist/runtime/tenancy/index.d.ts +9 -5
  50. package/dist/runtime/tenancy/index.js +1508 -37
  51. package/dist/runtime/tenancy/path.d.ts +87 -0
  52. package/dist/runtime/tenancy/rls.d.ts +67 -0
  53. package/dist/runtime/tenancy/via.d.ts +22 -0
  54. package/dist/runtime/traits/index.js +17 -11
  55. package/dist/runtime/types.d.ts +13 -1
  56. package/dist/runtime/validate/index.js +4 -4
  57. package/dist/runtime/write.d.ts +1 -1
  58. package/dist/shared/09p049xa.js +702 -0
  59. package/dist/shared/{6qd27mx0.js → 1f0xa3cb.js} +5 -5
  60. package/dist/shared/1nw1f3vs.js +23 -0
  61. package/dist/shared/{96qcj21c.js → 1z04fa85.js} +19 -9
  62. package/dist/shared/{qm7cdtvr.js → 2cg3wnxc.js} +296 -60
  63. package/dist/shared/{dyj86cmj.js → 2jd1sn0e.js} +2 -2
  64. package/dist/shared/{gbtcc2d7.js → 2z7wv5tj.js} +10 -35
  65. package/dist/shared/{k8v5v5wj.js → 32cnm7kn.js} +6 -1
  66. package/dist/shared/{t4tbsy9h.js → 358zsv4r.js} +1 -1
  67. package/dist/shared/{2pqx26h8.js → 3fqwmr09.js} +31 -22
  68. package/dist/shared/{zqrnhwsq.js → 3qnhc7w5.js} +16 -9
  69. package/dist/shared/{r2sp8hrc.js → 5d8t84hg.js} +12 -3
  70. package/dist/shared/{87jvvhnt.js → 5j36z8dn.js} +16 -5
  71. package/dist/shared/{1g0drakv.js → 5yv4k6a6.js} +1 -1
  72. package/dist/shared/8dqhth8c.js +12 -0
  73. package/dist/shared/8etn7d8w.js +62 -0
  74. package/dist/shared/{v36c5g6p.js → 8x72s86k.js} +400 -13
  75. package/dist/shared/{nxdp2ze3.js → 929h19xp.js} +107 -5
  76. package/dist/shared/{gjthds9j.js → 9628a9xt.js} +1 -1
  77. package/dist/shared/{8xsbagad.js → 9s0ypp87.js} +88 -7
  78. package/dist/shared/{efmy2gcg.js → ag4c7516.js} +1 -1
  79. package/dist/shared/b3awxn7h.js +45 -0
  80. package/dist/shared/b4v57v3x.js +9 -0
  81. package/dist/shared/bdk4sty6.js +58 -0
  82. package/dist/shared/{51mvgj8w.js → c58secgj.js} +100 -7
  83. package/dist/shared/d5azex6s.js +6 -0
  84. package/dist/shared/{5fqx9yh4.js → dk8v79p3.js} +3 -1
  85. package/dist/shared/{4m9fn52z.js → ed0b8k4s.js} +1 -1
  86. package/dist/shared/{z2rnngj4.js → ek2wt2dz.js} +8 -5
  87. package/dist/shared/{sycnx8gt.js → f0f1n281.js} +18 -8
  88. package/dist/shared/{f5cw5q5r.js → g90m9b0g.js} +2 -1
  89. package/dist/shared/{pf0d8f77.js → gwn6v667.js} +1 -1
  90. package/dist/shared/{8rsy3hxz.js → h15jx9bc.js} +1 -1
  91. package/dist/shared/{5enne4ma.js → hazqqecq.js} +17 -93
  92. package/dist/shared/{jwtxdj06.js → j3rkk835.js} +32 -9
  93. package/dist/shared/{hf22e0wt.js → j60w0dvr.js} +19 -18
  94. package/dist/shared/{ycatkxmq.js → jgqj11w4.js} +1 -1
  95. package/dist/shared/k68eedmy.js +85 -0
  96. package/dist/shared/{szm0cksa.js → knmes2kh.js} +34 -6
  97. package/dist/shared/{0t22wwh1.js → mb2ycs1p.js} +4 -2
  98. package/dist/shared/{cr74e96e.js → n076ydsc.js} +1 -1
  99. package/dist/shared/{cctw17hj.js → nx9hh281.js} +31 -28
  100. package/dist/shared/{gde73es6.js → p248q79y.js} +56 -55
  101. package/dist/shared/{janx09m5.js → p6bjzq9q.js} +11 -7
  102. package/dist/shared/{6rk2gen5.js → pjr6xrm5.js} +2 -2
  103. package/dist/shared/{wq9n6pwr.js → pz6rj8ay.js} +82 -9
  104. package/dist/shared/{caw8b9d8.js → q3j1tq7a.js} +35 -22
  105. package/dist/shared/{8bwbwy8h.js → qq3899ht.js} +128 -18
  106. package/dist/shared/{tm5ab8we.js → r11n8grd.js} +2 -2
  107. package/dist/shared/r1fdd0f6.js +19 -0
  108. package/dist/shared/{8ktwd3rh.js → r3j8s5y0.js} +1 -1
  109. package/dist/shared/rhs3xe4k.js +7 -0
  110. package/dist/shared/{ntneex2a.js → rpycarcr.js} +6 -6
  111. package/dist/shared/{aj2qxyhj.js → sbdme3vy.js} +14 -2
  112. package/dist/shared/{qv2ydck9.js → t3g0k88x.js} +638 -67
  113. package/dist/shared/{ga3sfy93.js → ttmg09vd.js} +535 -200
  114. package/dist/shared/{kfjp0gck.js → venqrjna.js} +8 -4
  115. package/dist/shared/{fancm5pt.js → vjpnzwjz.js} +138 -15
  116. package/dist/shared/{32zqc1dw.js → vmfkhszw.js} +31 -7
  117. package/dist/shared/{krxx77g0.js → wkme6tep.js} +10 -8
  118. package/dist/shared/{ps7a6h14.js → wt5rzv1h.js} +12 -8
  119. package/dist/shared/wxr8cwns.js +6 -0
  120. package/dist/shared/{6mnp99hx.js → wynzeggs.js} +16 -12
  121. package/dist/shared/x3jc53kg.js +220 -0
  122. package/dist/shared/{sdc7r2ww.js → xq0mvhts.js} +8 -8
  123. package/dist/shared/xqve9598.js +53 -0
  124. package/dist/shared/{47x8x9ze.js → y2t3jktd.js} +2 -2
  125. package/dist/shared/{9x25fxhc.js → y34a8714.js} +1 -1
  126. package/dist/shared/{k7dwkhvq.js → y6jdds7g.js} +4 -1
  127. package/dist/shared/{nkaxvt9q.js → ys0xzyaj.js} +1 -1
  128. package/dist/shared/{c9z5g0fm.js → ywr8hmey.js} +5 -2
  129. package/dist/shared/{g7ez901n.js → ywspezzx.js} +1 -1
  130. package/dist/shared/{9m80mkac.js → ze4hxsmy.js} +1 -1
  131. package/dist/shared/{r8x5qhd7.js → zm0mafk4.js} +10 -4
  132. package/dist/shared/{y005b761.js → zy8r7qvz.js} +6 -2
  133. package/dist/tooling/cli.js +41 -15
  134. package/dist/tooling/migrate/apply.d.ts +14 -0
  135. package/dist/tooling/migrate/check.d.ts +3 -4
  136. package/dist/tooling/migrate/classify.d.ts +4 -0
  137. package/dist/tooling/migrate/config.d.ts +3 -2
  138. package/dist/tooling/migrate/files.d.ts +11 -1
  139. package/dist/tooling/migrate/index.js +14 -14
  140. package/dist/tooling/migrate/lint.d.ts +1 -1
  141. package/dist/tooling/migrate/lost.d.ts +28 -0
  142. package/dist/tooling/migrate/paths.d.ts +14 -0
  143. package/dist/tooling/migrate/plan.d.ts +6 -3
  144. package/dist/tooling/migrate/runner.d.ts +25 -0
  145. package/dist/tooling/migrate/sandbox.d.ts +57 -0
  146. package/dist/tooling/migrate/sql-lex.d.ts +20 -3
  147. package/dist/tooling/migrate/text.d.ts +42 -0
  148. package/dist/tooling/node-version.d.ts +21 -0
  149. package/dist/tooling/testing/facts.d.ts +33 -5
  150. package/dist/tooling/testing/index.d.ts +1 -1
  151. package/dist/tooling/testing/index.js +3 -3
  152. package/dist/tooling/testing/isolation.d.ts +11 -5
  153. package/package.json +5 -2
  154. package/dist/shared/7zwwyh0v.js +0 -448
  155. package/dist/shared/q58y17hy.js +0 -21
@@ -2,10 +2,11 @@ import {
2
2
  readHandle,
3
3
  readCall,
4
4
  attachHttp
5
- } from "./hf22e0wt.js";
5
+ } from "./j60w0dvr.js";
6
6
  import {
7
7
  emitWhere,
8
8
  emitOrder,
9
+ refuseHidden,
9
10
  rejectKeys,
10
11
  readLimit,
11
12
  projectExpr,
@@ -15,7 +16,7 @@ import {
15
16
  list,
16
17
  isRecord,
17
18
  fail
18
- } from "./gbtcc2d7.js";
19
+ } from "./2z7wv5tj.js";
19
20
  import {
20
21
  OkmError2,
21
22
  throwNamed2
@@ -68,8 +69,11 @@ function plan(session, table, options, mods, view) {
68
69
  if (!isRecord(orderBy))
69
70
  fail("OKM1120", "orderBy must be an object of fields.");
70
71
  for (const field of Object.keys(orderBy)) {
71
- if (!spec.groups.some((column) => column.field === field)) {
72
- throwNamed2("OKM1120", field, spec.groups.map((column) => column.field), `aggregate() orders by a groupBy field. Accepted names: ${list(spec.groups.map((column) => column.field))}.`);
72
+ const column = indexed.columns.get(field);
73
+ if (column !== undefined)
74
+ refuseHidden(column);
75
+ if (!spec.groups.some((group) => group.field === field)) {
76
+ throwNamed2("OKM1120", field, spec.groups.map((group) => group.field), `aggregate() orders by a groupBy field. Accepted names: ${list(spec.groups.map((group) => group.field))}.`);
73
77
  }
74
78
  }
75
79
  }
@@ -2,28 +2,34 @@ import {
2
2
  roleObject,
3
3
  grantObject,
4
4
  defaultPrivilegeObject
5
- } from "./8bwbwy8h.js";
5
+ } from "./qq3899ht.js";
6
+ import {
7
+ columnPrivilege
8
+ } from "./ttmg09vd.js";
6
9
  import {
7
10
  quoteIdent
8
- } from "./8xsbagad.js";
11
+ } from "./9s0ypp87.js";
12
+ import {
13
+ policyObject
14
+ } from "./bdk4sty6.js";
9
15
  import {
10
16
  functionObject,
11
17
  triggerObject
12
- } from "./9x25fxhc.js";
18
+ } from "./y34a8714.js";
13
19
  import {
14
20
  normaliseViewQuery,
15
21
  viewObject,
16
22
  materializedViewObject,
17
23
  materializedViewIndex
18
- } from "./y005b761.js";
24
+ } from "./zy8r7qvz.js";
19
25
  import {
20
26
  extensionObject
21
- } from "./8ktwd3rh.js";
27
+ } from "./r3j8s5y0.js";
22
28
  import {
23
29
  catalog,
24
30
  enumType,
25
31
  domainType
26
- } from "./g7ez901n.js";
32
+ } from "./ywspezzx.js";
27
33
  import {
28
34
  staticNamespace2,
29
35
  identityKey2,
@@ -32,7 +38,7 @@ import {
32
38
  index3,
33
39
  constraint2,
34
40
  sequence2
35
- } from "./t4tbsy9h.js";
41
+ } from "./358zsv4r.js";
36
42
  import {
37
43
  referentialAction
38
44
  } from "./4e4c6vq2.js";
@@ -123,7 +129,8 @@ async function introspectSchema(runner, concrete, logical = "public", options) {
123
129
  triggers,
124
130
  functionDeps,
125
131
  views,
126
- viewDeps
132
+ viewDeps,
133
+ policies
127
134
  ] = await Promise.all([
128
135
  runner.query(TABLES, params),
129
136
  runner.query(COLUMNS, params),
@@ -137,7 +144,8 @@ async function introspectSchema(runner, concrete, logical = "public", options) {
137
144
  runner.query(TRIGGERS, params),
138
145
  runner.query(FUNCTION_DEPS, params),
139
146
  runner.query(VIEWS, params),
140
- runner.query(VIEW_DEPENDENCIES, params)
147
+ runner.query(VIEW_DEPENDENCIES, params),
148
+ runner.query(POLICIES, params)
141
149
  ]);
142
150
  const objects = [];
143
151
  const parents = new Map;
@@ -380,12 +388,38 @@ async function introspectSchema(runner, concrete, logical = "public", options) {
380
388
  const columns = printedColumns(text(row, "columns"));
381
389
  const query = normaliseViewQuery(text(row, "query"));
382
390
  const name = text(row, "name");
391
+ const invoker = kind === "view" && securityInvokerOption(text(row, "options"));
383
392
  if (kind === "materializedView") {
384
393
  objects.push(materializedViewObject({ namespace, name, columns, query, provenance }));
385
394
  } else {
386
- objects.push(viewObject({ namespace, name, columns, query, provenance }));
395
+ objects.push(viewObject({
396
+ namespace,
397
+ name,
398
+ columns,
399
+ query,
400
+ provenance,
401
+ ...invoker ? { securityInvoker: true } : {}
402
+ }));
387
403
  }
388
404
  }
405
+ for (const row of policies) {
406
+ const parentName = text(row, "table_name");
407
+ const parent = parents.get(parentName);
408
+ if (parent === undefined)
409
+ continue;
410
+ const command = policyCommand(text(row, "command"));
411
+ if (command === undefined || text(row, "enabled") !== "true")
412
+ continue;
413
+ objects.push(policyObject({
414
+ parent,
415
+ name: text(row, "name"),
416
+ command,
417
+ expression: text(row, "using_expr"),
418
+ force: text(row, "force") === "true",
419
+ provenance,
420
+ dependencies: [{ kind: "table", namespace, name: parentName }]
421
+ }));
422
+ }
389
423
  const viewEdges = viewDependencyEdges(viewDeps, namespace, objects);
390
424
  for (let index = 0;index < objects.length; index += 1) {
391
425
  const object = objects[index];
@@ -402,7 +436,8 @@ async function introspectSchema(runner, concrete, logical = "public", options) {
402
436
  columns: object.definition.columns,
403
437
  query: object.definition.query,
404
438
  provenance,
405
- dependencies
439
+ dependencies,
440
+ ...object.definition.securityInvoker === true ? { securityInvoker: true } : {}
406
441
  }) : materializedViewObject({
407
442
  namespace,
408
443
  name: object.identity.name,
@@ -413,7 +448,7 @@ async function introspectSchema(runner, concrete, logical = "public", options) {
413
448
  });
414
449
  }
415
450
  if (options?.managedRoles !== undefined) {
416
- objects.push(...await readPrivileges(runner, concrete, namespace, provenance, objects, options.managedRoles));
451
+ objects.push(...await readPrivileges(runner, concrete, logical, namespace, provenance, objects, options.managedRoles, options.reportingRole));
417
452
  }
418
453
  return catalog(objects);
419
454
  }
@@ -452,6 +487,30 @@ var FUNCTION_GRANTS = `select p.proname as name,
452
487
  select 1 from pg_depend d
453
488
  where d.classid = 'pg_proc'::regclass and d.objid = p.oid and d.deptype = 'e'
454
489
  )`;
490
+ var COLUMN_GRANTS = `select c.relname as name,
491
+ case c.relkind when 'v' then 'view' when 'm' then 'materializedView' else 'table' end as kind,
492
+ a.attname as column_name,
493
+ r.rolname as role, x.privilege_type as privilege
494
+ from pg_class c
495
+ join pg_namespace n on n.oid = c.relnamespace
496
+ join pg_attribute a on a.attrelid = c.oid and a.attnum > 0 and not a.attisdropped
497
+ cross join lateral aclexplode(a.attacl) as x
498
+ join pg_roles r on r.oid = x.grantee
499
+ where n.nspname = $1
500
+ and c.relkind in ('r', 'p', 'v', 'm')
501
+ and a.attacl is not null
502
+ and x.grantee <> 0
503
+ and x.grantee <> c.relowner`;
504
+ var SCHEMA_USAGE = `select 1 as ok
505
+ from pg_namespace n
506
+ cross join lateral aclexplode(n.nspacl) as a
507
+ where n.nspname = $1
508
+ and a.privilege_type = 'USAGE'
509
+ and (
510
+ a.grantee = 0
511
+ or a.grantee = (select oid from pg_roles where rolname = $2)
512
+ )
513
+ limit 1`;
455
514
  var DEFAULT_PRIVILEGES = `select owner_role.rolname as for_role, grantee.rolname as grantee,
456
515
  case d.defaclobjtype when 'S' then 'sequence' when 'f' then 'function' else 'table' end as object_kind,
457
516
  a.privilege_type as privilege
@@ -463,13 +522,15 @@ var DEFAULT_PRIVILEGES = `select owner_role.rolname as for_role, grantee.rolname
463
522
  where n.nspname = $1
464
523
  and d.defaclobjtype in ('r', 'S', 'f')
465
524
  and a.grantee <> 0`;
466
- async function readPrivileges(runner, concrete, namespace, provenance, built, managedRoles) {
525
+ async function readPrivileges(runner, concrete, logical, namespace, provenance, built, managedRoles, reportingRole) {
467
526
  const managed = new Set(managedRoles);
468
- const [roles, relations, functions, defaults] = await Promise.all([
527
+ const [roles, relations, functions, defaults, columns, usage] = await Promise.all([
469
528
  runner.query(ROLES, []),
470
529
  runner.query(RELATION_GRANTS, [concrete]),
471
530
  runner.query(FUNCTION_GRANTS, [concrete]),
472
- runner.query(DEFAULT_PRIVILEGES, [concrete])
531
+ runner.query(DEFAULT_PRIVILEGES, [concrete]),
532
+ runner.query(COLUMN_GRANTS, [concrete]),
533
+ reportingRole === undefined ? Promise.resolve([]) : runner.query(SCHEMA_USAGE, [concrete, reportingRole])
473
534
  ]);
474
535
  const objects = [];
475
536
  for (const row of roles) {
@@ -530,6 +591,42 @@ async function readPrivileges(runner, concrete, namespace, provenance, built, ma
530
591
  ]
531
592
  }));
532
593
  }
594
+ const grouped = new Map;
595
+ for (const row of columns) {
596
+ const privilege = text(row, "privilege").toUpperCase();
597
+ if (privilege !== "SELECT" && privilege !== "UPDATE")
598
+ continue;
599
+ const kind = grantKind(text(row, "kind"));
600
+ if (kind !== "table" && kind !== "view" && kind !== "materializedView")
601
+ continue;
602
+ const name = text(row, "name");
603
+ const role = text(row, "role");
604
+ const key = `${role}\x00${kind}\x00${name}\x00${privilege}`;
605
+ const current = grouped.get(key) ?? { role, kind, name, privilege, columns: [] };
606
+ current.columns.push(text(row, "column_name"));
607
+ grouped.set(key, current);
608
+ }
609
+ for (const group of grouped.values()) {
610
+ const target = built.find((object) => privilegeTarget(object) === `${group.kind}:${group.name}`);
611
+ if (target === undefined)
612
+ continue;
613
+ objects.push(grantObject({
614
+ role: group.role,
615
+ object: { kind: group.kind, namespace, name: group.name },
616
+ privilege: columnPrivilege(group.privilege, group.columns),
617
+ provenance,
618
+ dependencies: [{ kind: "role", name: group.role }, target.identity]
619
+ }));
620
+ }
621
+ if (usage.length > 0 && reportingRole !== undefined) {
622
+ objects.push(grantObject({
623
+ role: reportingRole,
624
+ object: { kind: "namespace", namespace, name: logical },
625
+ privilege: "USAGE",
626
+ provenance,
627
+ dependencies: [{ kind: "role", name: reportingRole }]
628
+ }));
629
+ }
533
630
  return objects;
534
631
  }
535
632
  function privilegeTarget(object) {
@@ -788,6 +885,7 @@ var TRIGGERS = `
788
885
  `;
789
886
  var VIEWS = `
790
887
  select c.relname as name, c.relkind as kind, pg_get_viewdef(c.oid, true) as query,
888
+ coalesce(array_to_string(c.reloptions, ','), '') as options,
791
889
  (
792
890
  select coalesce(string_agg(
793
891
  a.attname || '|' || format_type(a.atttypid, a.atttypmod),
@@ -821,6 +919,31 @@ var FUNCTION_DEPS = `
821
919
  and p.prokind = 'f'
822
920
  and p.prosrc = ''
823
921
  `;
922
+ var POLICIES = `
923
+ select c.relname as table_name,
924
+ p.polname as name,
925
+ p.polcmd as command,
926
+ coalesce(pg_get_expr(p.polqual, p.polrelid), '') as using_expr,
927
+ c.relforcerowsecurity::text as force,
928
+ c.relrowsecurity::text as enabled
929
+ from pg_policy p
930
+ join pg_class c on c.oid = p.polrelid
931
+ join pg_namespace n on n.oid = c.relnamespace
932
+ where n.nspname = $1
933
+ and c.relkind = 'r'
934
+ and ${CHILD}
935
+ and ${member("c.oid", "pg_class")}
936
+ `;
937
+ function securityInvokerOption(options) {
938
+ return options.split(",").some((item) => item === "security_invoker=true" || item === "security_invoker=on");
939
+ }
940
+ function policyCommand(command) {
941
+ if (command === "*")
942
+ return "all";
943
+ if (command === "r")
944
+ return "select";
945
+ return;
946
+ }
824
947
  function member(oid, classid) {
825
948
  return `not exists (
826
949
  select 1 from pg_depend member
@@ -9,7 +9,7 @@ import {
9
9
  isRecord,
10
10
  registerFailFix,
11
11
  fail
12
- } from "./gbtcc2d7.js";
12
+ } from "./2z7wv5tj.js";
13
13
  import {
14
14
  throwNamed2
15
15
  } from "./52szzakm.js";
@@ -112,11 +112,13 @@ function samePrimary(table, columns) {
112
112
  }
113
113
  function uniqueColumns(table, on, tenantKey) {
114
114
  const names = conflictNames(on);
115
+ const keys = keyList(tenantKey);
115
116
  for (const unique of table.model.uniques) {
116
- if (!same(unique, names))
117
+ const fields = fieldsOf(unique, names, keys);
118
+ if (fields === undefined)
117
119
  continue;
118
120
  const columns = [];
119
- for (const name of names) {
121
+ for (const name of fields) {
120
122
  const column = table.columns.get(name);
121
123
  if (column === undefined) {
122
124
  fail("OKM1104", `onConflict column ${name} is not on ${table.model.name}.`);
@@ -125,14 +127,14 @@ function uniqueColumns(table, on, tenantKey) {
125
127
  }
126
128
  return columns;
127
129
  }
128
- const accepted = acceptedConstraints(table.model, tenantKey);
129
- const implicit = tenantKey === undefined ? "" : ` The tenant key ${tenantKey} is part of each one and is not named here.`;
130
+ const accepted = acceptedConstraints(table.model, keys);
131
+ const implicit = keys.length === 0 ? "" : ` The tenant key ${keys.join(", ")} is part of each one and is not named here.`;
130
132
  throwNamed2("OKM1104", names.join(", "), accepted, `onConflict on ${table.model.name} names ${names.join(", ")}, which is not a unique constraint. Accepted: ${list(accepted)}.${implicit}`);
131
133
  }
132
- function acceptedConstraints(model, key) {
134
+ function acceptedConstraints(model, keys) {
133
135
  const shown = new Set;
134
136
  for (const fields of model.uniques) {
135
- const named = key === undefined ? fields : fields.filter((field) => field !== key);
137
+ const named = keys.length === 0 ? fields : fields.filter((field) => !keys.includes(field));
136
138
  if (named.length === 0)
137
139
  continue;
138
140
  shown.add(named.length > 1 ? `(${named.join(", ")})` : named.join(""));
@@ -166,6 +168,28 @@ function conflictNames(on) {
166
168
  }
167
169
  fail("OKM1104", "onConflict on must name a unique constraint's columns.");
168
170
  }
171
+ function fieldsOf(unique, names, tenantKeys) {
172
+ if (tenantKeys.some((key) => unique.includes(key))) {
173
+ const rest = [];
174
+ for (const field of unique) {
175
+ if (!tenantKeys.includes(field))
176
+ rest.push(field);
177
+ }
178
+ if (!same(rest, names))
179
+ return;
180
+ return unique;
181
+ }
182
+ if (!same(unique, names))
183
+ return;
184
+ return names;
185
+ }
186
+ function keyList(tenantKey) {
187
+ if (tenantKey === undefined)
188
+ return [];
189
+ if (typeof tenantKey === "string")
190
+ return [tenantKey];
191
+ return tenantKey;
192
+ }
169
193
  function same(unique, names) {
170
194
  if (unique.length !== names.length)
171
195
  return false;
@@ -62,13 +62,15 @@ class PoolSockets {
62
62
  }
63
63
  wake() {
64
64
  for (const socket of this.held)
65
- socket.ref();
65
+ if (socket.writable)
66
+ socket.ref();
66
67
  }
67
68
  park() {
68
69
  if (this.busy > 0 || this.listeners > 0)
69
70
  return;
70
71
  for (const socket of this.held)
71
- socket.unref();
72
+ if (socket.writable)
73
+ socket.unref();
72
74
  }
73
75
  }
74
76
  function driverOptions(config, state) {
@@ -117,7 +119,7 @@ function open2(config) {
117
119
  },
118
120
  async batch(statements, options) {
119
121
  return sockets.occupy(async () => {
120
- const { checkout } = await import("./caw8b9d8.js");
122
+ const { checkout } = await import("./r1fdd0f6.js");
121
123
  const connection = await checkout(held);
122
124
  try {
123
125
  return await connection.batch(statements, options);
@@ -129,12 +131,12 @@ function open2(config) {
129
131
  reserve() {
130
132
  const gate = sockets.busyGate();
131
133
  gate.enter();
132
- return import("./caw8b9d8.js").then((mod) => mod.holdCheckout(gate, () => mod.checkout(held)), (error) => {
134
+ return import("./r1fdd0f6.js").then((mod) => mod.holdCheckout(gate, () => mod.checkout(held)), (error) => {
133
135
  gate.leave();
134
136
  throw error;
135
137
  });
136
138
  },
137
- describe: (text, params) => sockets.occupy(() => import("./caw8b9d8.js").then((mod) => mod.describe(sql, text, params))),
139
+ describe: (text, params) => sockets.occupy(() => import("./r1fdd0f6.js").then((mod) => mod.describe(sql, text, params))),
138
140
  stream(text, params) {
139
141
  const gate = sockets.busyGate();
140
142
  return async function* () {
@@ -149,7 +151,7 @@ function open2(config) {
149
151
  listen(channel, onNotify) {
150
152
  const gate = sockets.listenerGate();
151
153
  gate.enter();
152
- return import("./caw8b9d8.js").then((mod) => mod.holdListener(gate, async () => {
154
+ return import("./r1fdd0f6.js").then((mod) => mod.holdListener(gate, async () => {
153
155
  const listening = await sql.listen(channel, onNotify);
154
156
  return async () => {
155
157
  await listening.unlisten();
@@ -219,7 +221,7 @@ class PgSession {
219
221
  onAbort();
220
222
  else
221
223
  watch.signal.addEventListener("abort", onAbort, { once: true });
222
- return import("./caw8b9d8.js").then((mod) => mod.watchQuery(pending, watch, onAbort, {
224
+ return import("./r1fdd0f6.js").then((mod) => mod.watchQuery(pending, watch, onAbort, {
223
225
  start,
224
226
  text,
225
227
  notices: this.notices,
@@ -271,7 +273,7 @@ class PgSession {
271
273
  }
272
274
  }
273
275
  async function* loadStream(sql, text, params) {
274
- const { stream } = await import("./caw8b9d8.js");
276
+ const { stream } = await import("./r1fdd0f6.js");
275
277
  yield* stream(sql, text, params);
276
278
  }
277
279
  function send(sql, text, params, named) {
@@ -1,22 +1,24 @@
1
1
  import {
2
2
  open2
3
- } from "./krxx77g0.js";
4
- import"./8bwbwy8h.js";
3
+ } from "./wkme6tep.js";
4
+ import"./qq3899ht.js";
5
5
  import"./n442h54c.js";
6
6
  import {
7
7
  assertRoleHealth
8
- } from "./szm0cksa.js";
9
- import"./fancm5pt.js";
8
+ } from "./knmes2kh.js";
9
+ import"./vjpnzwjz.js";
10
10
  import {
11
11
  errorDoc,
12
12
  openProject
13
- } from "./qv2ydck9.js";
13
+ } from "./t3g0k88x.js";
14
14
  import {
15
15
  omitManagedObjects,
16
+ sessionFailure,
17
+ finishQuiet,
16
18
  assertTargetPolicy,
17
19
  selectTarget
18
- } from "./ga3sfy93.js";
19
- import"./8xsbagad.js";
20
+ } from "./ttmg09vd.js";
21
+ import"./9s0ypp87.js";
20
22
  import {
21
23
  OkmError2
22
24
  } from "./52szzakm.js";
@@ -43,8 +45,10 @@ ${doc.fix}
43
45
  const pool = open2({ url: target.url, max: 1 });
44
46
  try {
45
47
  await assertRoleHealth(pool, opened.config.roles, objects);
48
+ } catch (error) {
49
+ throw sessionFailure(error) ?? error;
46
50
  } finally {
47
- await pool.close();
51
+ await finishQuiet(() => pool.close());
48
52
  }
49
53
  }
50
54
  return formatTriggers(objects);
@@ -0,0 +1,6 @@
1
+ import {
2
+ noTimeout2
3
+ } from "./8dqhth8c.js";
4
+ export {
5
+ noTimeout2 as noTimeout
6
+ };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  open2
3
- } from "./krxx77g0.js";
4
- import"./8bwbwy8h.js";
3
+ } from "./wkme6tep.js";
4
+ import"./qq3899ht.js";
5
5
  import"./n442h54c.js";
6
6
  import {
7
7
  CURRENT,
@@ -12,26 +12,28 @@ import {
12
12
  failedAt
13
13
  } from "./9yn6a2vd.js";
14
14
  import {
15
- loadMigrations,
16
15
  expandProvisioned,
17
16
  provisionHistoryIsKnown
18
- } from "./gde73es6.js";
19
- import"./szm0cksa.js";
20
- import"./fancm5pt.js";
17
+ } from "./p248q79y.js";
18
+ import"./knmes2kh.js";
19
+ import"./vjpnzwjz.js";
21
20
  import {
21
+ projectPath,
22
+ loadMigrations,
22
23
  loadConfig
23
- } from "./qv2ydck9.js";
24
+ } from "./t3g0k88x.js";
24
25
  import {
26
+ sessionFailure,
27
+ finishQuiet,
25
28
  assertTargetPolicy,
26
29
  listTargets
27
- } from "./ga3sfy93.js";
28
- import"./8xsbagad.js";
30
+ } from "./ttmg09vd.js";
31
+ import"./9s0ypp87.js";
29
32
  import {
30
33
  OkmError2
31
34
  } from "./52szzakm.js";
32
35
 
33
36
  // src/tooling/migrate/status.ts
34
- import { join } from "node:path";
35
37
  function describeStatus(migrations, history, recorded) {
36
38
  const known = new Set(migrations.map((migration) => migration.id));
37
39
  const done = expandProvisioned(migrations, new Set(history.map((row) => `${row.migrationId}:${String(row.stepIndex)}`)), history.map((row) => row.migrationId));
@@ -99,14 +101,16 @@ async function readTargetStatus(input) {
99
101
  protected: input.protected,
100
102
  backfills: await readBackfills(pool)
101
103
  };
104
+ } catch (error) {
105
+ throw sessionFailure(error) ?? error;
102
106
  } finally {
103
- await pool.close();
107
+ await finishQuiet(() => pool.close());
104
108
  }
105
109
  }
106
110
  async function statusProject(cwd, flags) {
107
111
  const config = await loadConfig(cwd);
108
112
  const targets = chosen(listTargets(config), flags.target);
109
- const migrations = loadMigrations(join(cwd, config.migrations ?? "migrations"));
113
+ const migrations = loadMigrations(projectPath(cwd, config.migrations ?? "migrations"));
110
114
  const rows = [];
111
115
  for (const target of targets) {
112
116
  rows.push(await readTargetStatus({