okmodel 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. package/README.md +36 -18
  2. package/dist/adapters/pg/no-inflight-timeout.d.ts +17 -0
  3. package/dist/adapters/pg/postgres-extra.d.ts +22 -0
  4. package/dist/contracts/catalog/document.d.ts +19 -5
  5. package/dist/contracts/catalog/object.d.ts +2 -1
  6. package/dist/contracts/catalog/policy.d.ts +48 -0
  7. package/dist/contracts/catalog/types.d.ts +25 -1
  8. package/dist/contracts/catalog/view.d.ts +2 -0
  9. package/dist/contracts/internal.js +1 -1
  10. package/dist/contracts/location.d.ts +10 -0
  11. package/dist/dialects/pg/column.d.ts +13 -2
  12. package/dist/dialects/pg/ddl.d.ts +37 -1
  13. package/dist/dialects/pg/emit.d.ts +19 -1
  14. package/dist/dialects/pg/errors.d.ts +32 -1
  15. package/dist/dialects/pg/ext/citext.js +1 -1
  16. package/dist/dialects/pg/ext/index.js +1 -1
  17. package/dist/dialects/pg/ext/pg-trgm.js +1 -1
  18. package/dist/dialects/pg/filter-parse.d.ts +10 -3
  19. package/dist/dialects/pg/fn/index.js +10 -2
  20. package/dist/dialects/pg/index.d.ts +2 -1
  21. package/dist/dialects/pg/index.js +29 -17
  22. package/dist/dialects/pg/introspect.d.ts +7 -0
  23. package/dist/dialects/pg/model.d.ts +7 -2
  24. package/dist/dialects/pg/ops/or.d.ts +1 -1
  25. package/dist/dialects/pg/owner.d.ts +42 -0
  26. package/dist/dialects/pg/path-endpoint.d.ts +20 -0
  27. package/dist/dialects/pg/role/check.d.ts +3 -0
  28. package/dist/dialects/pg/role/index.d.ts +71 -6
  29. package/dist/dialects/pg/role/sql.d.ts +11 -0
  30. package/dist/dialects/pg/schema.d.ts +2 -0
  31. package/dist/dialects/pg/table.d.ts +25 -3
  32. package/dist/dialects/pg/temporal.d.ts +5 -76
  33. package/dist/dialects/pg/tenancy.d.ts +45 -3
  34. package/dist/dialects/pg/view/client.d.ts +19 -1
  35. package/dist/dialects/pg/view/index.d.ts +4 -0
  36. package/dist/dialects/pg/view/index.js +21 -178
  37. package/dist/dialects/pg/view/refresh.d.ts +24 -0
  38. package/dist/runtime/batch.d.ts +1 -1
  39. package/dist/runtime/client.d.ts +6 -1
  40. package/dist/runtime/conflict.d.ts +2 -1
  41. package/dist/runtime/drift.d.ts +9 -0
  42. package/dist/runtime/inflight.d.ts +14 -0
  43. package/dist/runtime/pg/bun.js +6 -5
  44. package/dist/runtime/pg/pg.js +5 -5
  45. package/dist/runtime/pg/pglite.js +6 -5
  46. package/dist/runtime/pg/postgresjs.js +5 -5
  47. package/dist/runtime/plan.d.ts +22 -1
  48. package/dist/runtime/predicate.d.ts +19 -0
  49. package/dist/runtime/safety/index.js +1 -1
  50. package/dist/runtime/tenancy/composite.d.ts +26 -0
  51. package/dist/runtime/tenancy/context.d.ts +16 -0
  52. package/dist/runtime/tenancy/index.d.ts +9 -5
  53. package/dist/runtime/tenancy/index.js +1508 -37
  54. package/dist/runtime/tenancy/path.d.ts +87 -0
  55. package/dist/runtime/tenancy/rls.d.ts +67 -0
  56. package/dist/runtime/tenancy/via.d.ts +22 -0
  57. package/dist/runtime/traits/index.js +17 -11
  58. package/dist/runtime/types.d.ts +13 -1
  59. package/dist/runtime/validate/index.js +4 -4
  60. package/dist/runtime/write.d.ts +1 -1
  61. package/dist/shared/09p049xa.js +702 -0
  62. package/dist/shared/{ykv7wh5b.js → 1f0xa3cb.js} +5 -5
  63. package/dist/shared/1nw1f3vs.js +23 -0
  64. package/dist/shared/{6p5k20sm.js → 1z04fa85.js} +21 -11
  65. package/dist/shared/{p7pfx624.js → 2cg3wnxc.js} +314 -65
  66. package/dist/shared/{dyj86cmj.js → 2jd1sn0e.js} +2 -2
  67. package/dist/shared/{qgvt8nx1.js → 2z7wv5tj.js} +21 -5
  68. package/dist/shared/{kyxb62mc.js → 31vm914h.js} +9 -1
  69. package/dist/shared/{sf8m6tfy.js → 32cnm7kn.js} +8 -3
  70. package/dist/shared/{t4tbsy9h.js → 358zsv4r.js} +1 -1
  71. package/dist/shared/{jdgqqx31.js → 3fqwmr09.js} +38 -14
  72. package/dist/shared/{922qbgnw.js → 3qnhc7w5.js} +16 -9
  73. package/dist/shared/{zvbjc949.js → 4az561fn.js} +1 -1
  74. package/dist/shared/{k3ted12y.js → 54tqkxja.js} +20 -2
  75. package/dist/shared/{k7cc9nzk.js → 5d8t84hg.js} +15 -3
  76. package/dist/shared/{fa9vt245.js → 5j36z8dn.js} +17 -6
  77. package/dist/shared/{1g0drakv.js → 5yv4k6a6.js} +1 -1
  78. package/dist/shared/8dqhth8c.js +12 -0
  79. package/dist/shared/8etn7d8w.js +62 -0
  80. package/dist/shared/{g516zdsb.js → 8x72s86k.js} +476 -30
  81. package/dist/shared/{nkc9sfqb.js → 929h19xp.js} +145 -7
  82. package/dist/shared/{gjthds9j.js → 9628a9xt.js} +1 -1
  83. package/dist/shared/{8xsbagad.js → 9s0ypp87.js} +88 -7
  84. package/dist/shared/{b066g80h.js → ag4c7516.js} +2 -2
  85. package/dist/shared/b3awxn7h.js +45 -0
  86. package/dist/shared/b4v57v3x.js +9 -0
  87. package/dist/shared/bdk4sty6.js +58 -0
  88. package/dist/shared/{s6gqfn5j.js → c58secgj.js} +125 -8
  89. package/dist/shared/{rrstp3kb.js → cgbamx3e.js} +2 -2
  90. package/dist/shared/d5azex6s.js +6 -0
  91. package/dist/shared/{5fqx9yh4.js → dk8v79p3.js} +3 -1
  92. package/dist/shared/{4m9fn52z.js → ed0b8k4s.js} +1 -1
  93. package/dist/shared/{z2rnngj4.js → ek2wt2dz.js} +8 -5
  94. package/dist/shared/{wxn4b7pp.js → f0f1n281.js} +59 -12
  95. package/dist/shared/{gdh9mrtp.js → g90m9b0g.js} +3 -2
  96. package/dist/shared/{tbszx8mz.js → gwn6v667.js} +2 -2
  97. package/dist/shared/{c8aghh05.js → h15jx9bc.js} +8 -2
  98. package/dist/shared/{3p4b1fg0.js → hazqqecq.js} +17 -93
  99. package/dist/shared/{4ef7mmqf.js → j3rkk835.js} +34 -11
  100. package/dist/shared/{bt9sfq0z.js → j60w0dvr.js} +56 -21
  101. package/dist/shared/{ycatkxmq.js → jgqj11w4.js} +1 -1
  102. package/dist/shared/k68eedmy.js +85 -0
  103. package/dist/shared/{szm0cksa.js → knmes2kh.js} +34 -6
  104. package/dist/shared/{ckjbyrt9.js → mb2ycs1p.js} +7 -9
  105. package/dist/shared/{tq9afp8d.js → n076ydsc.js} +1 -1
  106. package/dist/shared/{xhh1srw3.js → nx9hh281.js} +50 -32
  107. package/dist/shared/{kdkxh3kb.js → p248q79y.js} +58 -59
  108. package/dist/shared/{990a291j.js → p6bjzq9q.js} +14 -9
  109. package/dist/shared/{h4nqvjkp.js → pjr6xrm5.js} +2 -2
  110. package/dist/shared/pz6rj8ay.js +212 -0
  111. package/dist/shared/{5vdm4sgp.js → q3j1tq7a.js} +36 -23
  112. package/dist/shared/{8bwbwy8h.js → qq3899ht.js} +128 -18
  113. package/dist/shared/{dxjp14rk.js → r11n8grd.js} +2 -2
  114. package/dist/shared/r1fdd0f6.js +19 -0
  115. package/dist/shared/{8ktwd3rh.js → r3j8s5y0.js} +1 -1
  116. package/dist/shared/rhs3xe4k.js +7 -0
  117. package/dist/shared/{jsd07prz.js → rpycarcr.js} +6 -6
  118. package/dist/shared/{xsq7v6wp.js → sbdme3vy.js} +14 -2
  119. package/dist/shared/{xdpj5kkm.js → t3g0k88x.js} +775 -264
  120. package/dist/shared/{ayz64vzj.js → ttmg09vd.js} +708 -19
  121. package/dist/shared/{r6pj4fq2.js → venqrjna.js} +8 -4
  122. package/dist/shared/{fancm5pt.js → vjpnzwjz.js} +138 -15
  123. package/dist/shared/{9tgmr1gh.js → vmfkhszw.js} +44 -9
  124. package/dist/shared/{wqem4jed.js → wkme6tep.js} +11 -9
  125. package/dist/shared/{qy9rdq0g.js → wt5rzv1h.js} +15 -11
  126. package/dist/shared/wxr8cwns.js +6 -0
  127. package/dist/shared/{bzsjtd7c.js → wynzeggs.js} +19 -14
  128. package/dist/shared/x3jc53kg.js +220 -0
  129. package/dist/shared/{7p2wbz7f.js → x72jb7ad.js} +1 -1
  130. package/dist/shared/{fyqkk1m0.js → xq0mvhts.js} +10 -9
  131. package/dist/shared/xqve9598.js +53 -0
  132. package/dist/shared/{47xzb9fc.js → y2t3jktd.js} +2 -2
  133. package/dist/shared/{9x25fxhc.js → y34a8714.js} +1 -1
  134. package/dist/shared/{k7dwkhvq.js → y6jdds7g.js} +4 -1
  135. package/dist/shared/{h8ne16fq.js → ys0xzyaj.js} +1 -1
  136. package/dist/shared/{c9z5g0fm.js → ywr8hmey.js} +5 -2
  137. package/dist/shared/{g7ez901n.js → ywspezzx.js} +1 -1
  138. package/dist/shared/{9m80mkac.js → ze4hxsmy.js} +1 -1
  139. package/dist/shared/{fb00y8fp.js → zm0mafk4.js} +12 -6
  140. package/dist/shared/{y005b761.js → zy8r7qvz.js} +6 -2
  141. package/dist/tooling/cli.js +97 -24
  142. package/dist/tooling/migrate/apply.d.ts +14 -0
  143. package/dist/tooling/migrate/check.d.ts +3 -4
  144. package/dist/tooling/migrate/classify.d.ts +4 -0
  145. package/dist/tooling/migrate/commands.d.ts +1 -2
  146. package/dist/tooling/migrate/config.d.ts +3 -2
  147. package/dist/tooling/migrate/drift.d.ts +1 -1
  148. package/dist/tooling/migrate/estimate.d.ts +14 -1
  149. package/dist/tooling/migrate/files.d.ts +11 -1
  150. package/dist/tooling/migrate/index.js +17 -16
  151. package/dist/tooling/migrate/lint.d.ts +4 -4
  152. package/dist/tooling/migrate/lost.d.ts +28 -0
  153. package/dist/tooling/migrate/paths.d.ts +14 -0
  154. package/dist/tooling/migrate/plan.d.ts +10 -3
  155. package/dist/tooling/migrate/policy.d.ts +11 -0
  156. package/dist/tooling/migrate/runner.d.ts +25 -0
  157. package/dist/tooling/migrate/sandbox.d.ts +57 -0
  158. package/dist/tooling/migrate/sql-lex.d.ts +39 -0
  159. package/dist/tooling/migrate/text.d.ts +42 -0
  160. package/dist/tooling/node-version.d.ts +21 -0
  161. package/dist/tooling/testing/factories.d.ts +10 -0
  162. package/dist/tooling/testing/facts.d.ts +33 -5
  163. package/dist/tooling/testing/index.d.ts +1 -1
  164. package/dist/tooling/testing/index.js +3 -3
  165. package/dist/tooling/testing/isolation.d.ts +15 -8
  166. package/package.json +10 -6
  167. package/dist/shared/0v1g424p.js +0 -26
  168. package/dist/shared/r73pt594.js +0 -426
  169. package/dist/shared/rasvvzgz.js +0 -21
@@ -1,9 +1,10 @@
1
1
  import {
2
- isConnectionFailure
3
- } from "./tbszx8mz.js";
2
+ isConnectionSqlstate,
3
+ isConnectionErrno
4
+ } from "./gwn6v667.js";
4
5
  import {
5
6
  createClient
6
- } from "./bt9sfq0z.js";
7
+ } from "./j60w0dvr.js";
7
8
  import {
8
9
  OkmError2
9
10
  } from "./52szzakm.js";
@@ -330,7 +331,8 @@ async function openEndpoint(open, url, max, defaults, name, role, weight, probeM
330
331
  timer: undefined,
331
332
  current: 0,
332
333
  inflight: 0,
333
- latencyMs: null
334
+ latencyMs: null,
335
+ generation: 0
334
336
  };
335
337
  }
336
338
  async function detectPosition(endpoint) {
@@ -344,8 +346,11 @@ async function detectPosition(endpoint) {
344
346
  async function sample(handle, endpoint) {
345
347
  try {
346
348
  const sampled = await readPosition(handle, endpoint);
349
+ const reopened = endpoint.circuit === "open";
347
350
  endpoint.failures = 0;
348
351
  endpoint.circuit = "closed";
352
+ if (reopened)
353
+ endpoint.generation += 1;
349
354
  applySample(endpoint, sampled);
350
355
  } catch {
351
356
  endpoint.failures += 1;
@@ -514,6 +519,7 @@ function routePool(handle) {
514
519
  replicaRefused();
515
520
  const reason = options?.route === "primary" ? "constraint:primary" : "primary-required";
516
521
  tell(handle, { op: "write", endpoint: primary.name, reason });
522
+ await callGuard(primary);
517
523
  const result = await primary.pool.batch(statements, strip(options));
518
524
  await noteWrite(handle, primary.pool);
519
525
  return result;
@@ -554,6 +560,14 @@ function routePool(handle) {
554
560
  endpoint.pool.cancel?.();
555
561
  };
556
562
  }
563
+ const routed = pool;
564
+ routed.okmReadOnlyUnit = (text, params, prelude, options) => readOnlyUnit(handle, text, params, prelude, options);
565
+ routed.okmReadOnlyStream = (text, params, prelude, options) => readOnlyStream(handle, text, params, prelude, options);
566
+ routed.okmEndpoints = () => handle.endpoints.map((endpoint) => ({
567
+ name: endpoint.name,
568
+ generation: endpoint.generation,
569
+ pool: endpoint.pool
570
+ }));
557
571
  return pool;
558
572
  }
559
573
  function derive(schema, handle, router, shared, route) {
@@ -600,8 +614,82 @@ function force(handle, router, route) {
600
614
  }
601
615
  if (router.cancel !== undefined)
602
616
  pool.cancel = () => router.cancel();
617
+ const unit = router.okmReadOnlyUnit;
618
+ const stream = router.okmReadOnlyStream;
619
+ const forced = pool;
620
+ if (unit !== undefined) {
621
+ forced.okmReadOnlyUnit = (text, params, prelude, options) => unit(text, params, prelude, { ...options, route });
622
+ }
623
+ if (stream !== undefined) {
624
+ forced.okmReadOnlyStream = (text, params, prelude, options) => stream(text, params, prelude, { ...options, route });
625
+ }
603
626
  return pool;
604
627
  }
628
+ async function readOnlyUnit(handle, text, params, prelude, options) {
629
+ if (handle.closed)
630
+ closed();
631
+ const choice = await choose(handle, text, options?.route);
632
+ return attempt(handle, choice, async (endpoint) => {
633
+ if (endpoint.pool.reserve === undefined)
634
+ replicaReserve();
635
+ const conn = await endpoint.pool.reserve();
636
+ try {
637
+ await conn.execute("begin read only");
638
+ try {
639
+ await conn.execute(prelude.text, prelude.params);
640
+ const result = await conn.execute(text, params, strip(options));
641
+ await conn.execute("commit");
642
+ return result;
643
+ } catch (error) {
644
+ await conn.execute("rollback").catch(() => {
645
+ return;
646
+ });
647
+ throw error;
648
+ }
649
+ } finally {
650
+ await conn.release();
651
+ }
652
+ });
653
+ }
654
+ function readOnlyStream(handle, text, params, prelude, options) {
655
+ return async function* () {
656
+ if (handle.closed)
657
+ closed();
658
+ const choice = await choose(handle, text, options?.route);
659
+ tell(handle, { op: choice.op, endpoint: choice.endpoint.name, reason: choice.reason });
660
+ await callGuard(choice.endpoint);
661
+ if (choice.endpoint.pool.reserve === undefined)
662
+ replicaReserve();
663
+ const conn = await choice.endpoint.pool.reserve();
664
+ try {
665
+ await conn.execute("begin read only");
666
+ try {
667
+ await conn.execute(prelude.text, prelude.params);
668
+ await conn.execute(`declare okm_rls no scroll cursor for ${text}`, params);
669
+ for (;; ) {
670
+ const chunk = await conn.execute("fetch 64 from okm_rls");
671
+ if (chunk.rows.length === 0)
672
+ break;
673
+ yield chunk.rows;
674
+ }
675
+ await conn.execute("close okm_rls");
676
+ await conn.execute("commit");
677
+ } catch (error) {
678
+ await conn.execute("rollback").catch(() => {
679
+ return;
680
+ });
681
+ throw error;
682
+ }
683
+ } finally {
684
+ await conn.release();
685
+ }
686
+ }();
687
+ }
688
+ function replicaReserve() {
689
+ throw new OkmError2("OKM1111", "Row-level security needs a driver that can reserve a connection.", {
690
+ fix: { summary: "Use a Postgres driver that supports interactive transactions." }
691
+ });
692
+ }
605
693
  function classOf(text) {
606
694
  const head = text.trimStart().toLowerCase().replace(/\s+/g, " ");
607
695
  if (/^(begin|start transaction|commit|rollback|savepoint|release|set|reset)\b/.test(head)) {
@@ -611,7 +699,7 @@ function classOf(text) {
611
699
  return "lock";
612
700
  if (/\sfor (no key update|key share|update|share)\b/.test(head))
613
701
  return "lock";
614
- if (/^(insert|update|delete|with|create|alter|drop|truncate|grant|revoke|comment|vacuum|analyze|reindex|copy)\b/.test(head)) {
702
+ if (/^(insert|update|delete|refresh|with|create|alter|drop|truncate|grant|revoke|comment|vacuum|analyze|reindex|copy)\b/.test(head)) {
615
703
  return "write";
616
704
  }
617
705
  return "read";
@@ -625,7 +713,7 @@ async function choose(handle, text, route) {
625
713
  if (primary === undefined)
626
714
  throw new OkmError2("OKM1120", "A topology needs one primary URL.");
627
715
  if (text.trimStart().toLowerCase().startsWith("select current_setting")) {
628
- return { endpoint: primary, op: "read", reason: "primary-required" };
716
+ return { endpoint: primary, op: "read", reason: "primary-required", skipGuard: true };
629
717
  }
630
718
  if (route === "replica" && op !== "read")
631
719
  replicaRefused();
@@ -672,17 +760,67 @@ async function* readStream(handle, text, route, params, fallback) {
672
760
  async function attempt(handle, choice, run) {
673
761
  tell(handle, { op: choice.op, endpoint: choice.endpoint.name, reason: choice.reason });
674
762
  try {
763
+ if (choice.skipGuard !== true)
764
+ await callGuard(choice.endpoint);
675
765
  return await tracked(choice.endpoint, choice.op === "read", () => run(choice.endpoint));
676
766
  } catch (error) {
677
- if (choice.op !== "read" || !isConnectionFailure(error))
767
+ if (choice.op !== "read" || !isUnreachable(error))
678
768
  throw error;
769
+ choice.endpoint.generation += 1;
679
770
  const next = await retryOf(handle, choice);
680
771
  if (next === undefined)
681
772
  throw error;
682
773
  tell(handle, { op: "read", endpoint: next.endpoint.name, reason: next.reason });
774
+ if (choice.skipGuard !== true)
775
+ await callGuard(next.endpoint);
683
776
  return tracked(next.endpoint, true, () => run(next.endpoint));
684
777
  }
685
778
  }
779
+ function callGuard(endpoint) {
780
+ const guard = endpoint.pool.okmGuard;
781
+ if (guard === undefined)
782
+ return Promise.resolve();
783
+ return guard({
784
+ name: endpoint.name,
785
+ generation: endpoint.generation,
786
+ pool: endpoint.pool
787
+ });
788
+ }
789
+ var CHAIN_DEPTH = 8;
790
+ function isUnreachable(error) {
791
+ const seen = new Set;
792
+ const visit = (value, depth) => {
793
+ if (typeof value !== "object" || value === null || depth > CHAIN_DEPTH)
794
+ return false;
795
+ if (seen.has(value))
796
+ return false;
797
+ seen.add(value);
798
+ if (unreachableNode(value))
799
+ return true;
800
+ if (visit(Reflect.get(value, "cause"), depth + 1))
801
+ return true;
802
+ const errors = Reflect.get(value, "errors");
803
+ return Array.isArray(errors) && errors.some((item) => visit(item, depth + 1));
804
+ };
805
+ return visit(error, 0);
806
+ }
807
+ function unreachableNode(node) {
808
+ for (const key of ["sqlstate", "code", "errno"]) {
809
+ const code = Reflect.get(node, key);
810
+ if (typeof code !== "string" || code.length === 0)
811
+ continue;
812
+ if (isConnectionSqlstate(code) || isConnectionErrno(code))
813
+ return true;
814
+ if (code.startsWith("ERR_POSTGRES_CONNECTION_"))
815
+ return true;
816
+ if (code === "ERR_POSTGRES_IDLE_TIMEOUT" || code === "ERR_POSTGRES_LIFETIME_TIMEOUT") {
817
+ return true;
818
+ }
819
+ }
820
+ if (!(node instanceof Error))
821
+ return false;
822
+ return node.message.includes("ECONNREFUSED") || node.message.includes("ECONNRESET") || node.message.includes("CONNECTION_CLOSED") || node.message.includes("terminating connection") || node.message.includes("The pool is closed");
823
+ }
686
824
  async function tracked(endpoint, time, run) {
687
825
  const replica = endpoint.role === "replica";
688
826
  if (replica)
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  required
3
- } from "./c9z5g0fm.js";
3
+ } from "./ywr8hmey.js";
4
4
  import {
5
5
  rejected
6
6
  } from "./tmbdywx0.js";
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  creationOrder2
3
- } from "./8bwbwy8h.js";
3
+ } from "./qq3899ht.js";
4
4
  import {
5
5
  isDomain
6
- } from "./g7ez901n.js";
6
+ } from "./ywspezzx.js";
7
7
  import {
8
8
  quoteLiteral
9
9
  } from "./94ez8kzh.js";
10
10
  import {
11
11
  identityKey2
12
- } from "./t4tbsy9h.js";
12
+ } from "./358zsv4r.js";
13
13
  import {
14
14
  fitIdentifier2
15
15
  } from "./nfzc5z0w.js";
@@ -22,6 +22,7 @@ function renderCatalog(source, schema) {
22
22
  const folded = foldedKeys(source);
23
23
  const statements = [];
24
24
  const ordered = creationOrder2(source);
25
+ const created = uniqueBeforeForeignKey(ordered);
25
26
  for (const object of ordered) {
26
27
  if (object.kind !== "type" || object.owner === "ignored")
27
28
  continue;
@@ -29,8 +30,8 @@ function renderCatalog(source, schema) {
29
30
  if (sql !== undefined)
30
31
  statements.push(sql);
31
32
  }
32
- for (const object of ordered) {
33
- if (object.kind === "type" || object.kind === "function" || object.kind === "trigger" || object.kind === "view" || object.kind === "materializedView" || ownedByView(object)) {
33
+ for (const object of created) {
34
+ if (object.kind === "type" || object.kind === "function" || object.kind === "trigger" || object.kind === "view" || object.kind === "materializedView" || object.kind === "policy" || ownedByView(object)) {
34
35
  continue;
35
36
  }
36
37
  if (object.owner === "ignored")
@@ -46,6 +47,12 @@ function renderCatalog(source, schema) {
46
47
  if (sql !== undefined)
47
48
  statements.push(sql);
48
49
  }
50
+ for (const object of created) {
51
+ if (object.kind !== "policy" || object.owner === "ignored")
52
+ continue;
53
+ for (const step of policyCreatePlan(object, schema))
54
+ statements.push(step.sql);
55
+ }
49
56
  for (const kind of ["function", "trigger"]) {
50
57
  for (const object of ordered) {
51
58
  if (object.kind !== kind || object.owner === "ignored")
@@ -73,6 +80,48 @@ function renderCatalog(source, schema) {
73
80
  }
74
81
  return statements;
75
82
  }
83
+ function uniqueBeforeForeignKey(objects) {
84
+ const uniques = objects.filter((object) => object.kind === "constraint" && object.definition.constraintKind === "unique");
85
+ if (uniques.length === 0)
86
+ return objects;
87
+ const emitted = new Set;
88
+ const result = [];
89
+ for (const object of objects) {
90
+ if (emitted.has(object))
91
+ continue;
92
+ if (object.kind === "constraint" && object.definition.constraintKind === "foreignKey") {
93
+ const target = object.definition.references;
94
+ if (target !== undefined && !coveredByPrimary(objects, target.parent, target.columns)) {
95
+ const columns = target.columns.join("\x00");
96
+ for (const unique of uniques) {
97
+ if (emitted.has(unique))
98
+ continue;
99
+ if (!sameRef(unique.identity.parent, target.parent))
100
+ continue;
101
+ if (unique.definition.columns.join("\x00") !== columns)
102
+ continue;
103
+ result.push(unique);
104
+ emitted.add(unique);
105
+ }
106
+ }
107
+ }
108
+ result.push(object);
109
+ emitted.add(object);
110
+ }
111
+ return result;
112
+ }
113
+ function coveredByPrimary(objects, parent, columns) {
114
+ const key = columns.join("\x00");
115
+ return objects.some((object) => object.kind === "constraint" && object.definition.constraintKind === "primaryKey" && sameRef(object.identity.parent, parent) && object.definition.columns.join("\x00") === key);
116
+ }
117
+ function sameRef(left, right) {
118
+ if (left.name !== right.name || left.namespace.form !== right.namespace.form)
119
+ return false;
120
+ if (left.namespace.form === "static" && right.namespace.form === "static") {
121
+ return left.namespace.name === right.namespace.name;
122
+ }
123
+ return left.namespace.form === "template" && right.namespace.form === "template" ? left.namespace.pattern === right.namespace.pattern : false;
124
+ }
76
125
  function ownedByView(object) {
77
126
  if (object.kind !== "index")
78
127
  return false;
@@ -149,7 +198,39 @@ function functionSql(object, schema, replace) {
149
198
  }
150
199
  function viewSql(object, schema, replace) {
151
200
  const verb = replace ? "create or replace view" : "create view";
152
- return `${verb} ${qualify(schema, object.identity.name)} as ${object.definition.query}`;
201
+ const invoker = object.definition.securityInvoker === true ? " with (security_invoker = true)" : "";
202
+ return `${verb} ${qualify(schema, object.identity.name)}${invoker} as ${object.definition.query}`;
203
+ }
204
+ function policyCreatePlan(object, schema) {
205
+ const table = qualify(schema, object.identity.parent.name);
206
+ const name = quoteIdent(object.identity.name);
207
+ const command = object.definition.command === "all" ? "all" : "select";
208
+ const check = object.definition.command === "all" ? ` with check ${object.definition.expression}` : "";
209
+ const create = {
210
+ sql: `create policy ${name} on ${table} as permissive for ${command} using ${object.definition.expression}${check}`,
211
+ kind: "create-policy"
212
+ };
213
+ if (object.definition.command !== "all")
214
+ return [create];
215
+ return [
216
+ { sql: `alter table ${table} enable row level security`, kind: "enable-rls" },
217
+ { sql: `alter table ${table} force row level security`, kind: "enable-rls" },
218
+ create
219
+ ];
220
+ }
221
+ function policyDropPlan(object, schema) {
222
+ const table = qualify(schema, object.identity.parent.name);
223
+ const drop = {
224
+ sql: `drop policy ${quoteIdent(object.identity.name)} on ${table}`,
225
+ kind: "drop-policy"
226
+ };
227
+ if (object.definition.command !== "all")
228
+ return [drop];
229
+ return [
230
+ drop,
231
+ { sql: `alter table ${table} no force row level security`, kind: "disable-rls" },
232
+ { sql: `alter table ${table} disable row level security`, kind: "disable-rls" }
233
+ ];
153
234
  }
154
235
  function materializedViewSql(object, schema) {
155
236
  return `create materialized view ${qualify(schema, object.identity.name)} as ${object.definition.query} with no data`;
@@ -315,4 +396,4 @@ function qualify(schema, name) {
315
396
  return `${quoteIdent(schema)}.${quoteIdent(name)}`;
316
397
  }
317
398
 
318
- export { quoteIdent, renderCatalog, ownedByView, dropObjectSql, createObjectSql, functionSql, viewSql, refreshMaterializedViewSql, alterColumnSql, identitySequence, createTableSql, qualify };
399
+ export { quoteIdent, renderCatalog, uniqueBeforeForeignKey, ownedByView, dropObjectSql, createObjectSql, functionSql, viewSql, policyCreatePlan, policyDropPlan, refreshMaterializedViewSql, alterColumnSql, identitySequence, createTableSql, qualify };
@@ -2,10 +2,10 @@ import {
2
2
  DriverError2,
3
3
  outcomeUnknown2,
4
4
  mapDriverError2
5
- } from "./kyxb62mc.js";
5
+ } from "./31vm914h.js";
6
6
  import {
7
7
  isConnectionLost
8
- } from "./tbszx8mz.js";
8
+ } from "./gwn6v667.js";
9
9
 
10
10
  // src/adapters/pg/batch.ts
11
11
  var savepointIds = 0;
@@ -0,0 +1,45 @@
1
+ import {
2
+ isRecord,
3
+ orFail
4
+ } from "./2z7wv5tj.js";
5
+ import {
6
+ isOperator,
7
+ operatorName,
8
+ operatorValue
9
+ } from "./cn0n68ft.js";
10
+
11
+ // src/runtime/predicate.ts
12
+ function effectivePredicate(where) {
13
+ if (where === undefined)
14
+ return false;
15
+ if (isOperator(where)) {
16
+ const name = operatorName(where);
17
+ const value = operatorValue(where);
18
+ if (name === "or") {
19
+ if (!Array.isArray(value))
20
+ orFail(false);
21
+ if (value.length === 0)
22
+ return true;
23
+ for (const branch of value) {
24
+ if (!effectivePredicate(branch))
25
+ orFail(true);
26
+ }
27
+ return true;
28
+ }
29
+ if (name === "and") {
30
+ return Array.isArray(value) && value.some((part) => effectivePredicate(part));
31
+ }
32
+ if (name === "not")
33
+ return effectivePredicate(value);
34
+ return true;
35
+ }
36
+ if (!isRecord(where))
37
+ return true;
38
+ for (const key of Object.keys(where)) {
39
+ if (where[key] !== undefined)
40
+ return true;
41
+ }
42
+ return false;
43
+ }
44
+
45
+ export { effectivePredicate };
@@ -0,0 +1,9 @@
1
+ // src/runtime/inflight.ts
2
+ async function refuseUncancellableTimeout(pool, timeout) {
3
+ if (pool.capabilities.cancel === true || timeout === undefined || !(timeout > 0))
4
+ return;
5
+ const { noTimeout } = await import("./wxr8cwns.js");
6
+ noTimeout({ timeout });
7
+ }
8
+
9
+ export { refuseUncancellableTimeout };
@@ -0,0 +1,58 @@
1
+ import {
2
+ assertNamespace2,
3
+ normaliseEdges,
4
+ assertProvenance
5
+ } from "./358zsv4r.js";
6
+ import {
7
+ isReservedIdentifier2,
8
+ assertIdentifier2,
9
+ fitIdentifier2,
10
+ assertStoredText
11
+ } from "./nfzc5z0w.js";
12
+ import {
13
+ catalogError2
14
+ } from "./52szzakm.js";
15
+
16
+ // src/contracts/catalog/policy.ts
17
+ var BARE_IDENT = /^[a-z_][a-z0-9_$]*$/;
18
+ function policyIdent(name) {
19
+ if (BARE_IDENT.test(name) && !isReservedIdentifier2(name))
20
+ return name;
21
+ return `"${name.replaceAll('"', '""')}"`;
22
+ }
23
+ function tenantPolicyExpression(column, dataType) {
24
+ return `(${policyIdent(column)} = (NULLIF(current_setting('app.tenant'::text, true), ''::text))::${dataType})`;
25
+ }
26
+ function unscopedPolicyExpression() {
27
+ return `(current_setting('app.unscoped'::text, true) = 'on'::text)`;
28
+ }
29
+ function policyObject(input) {
30
+ assertNamespace2(input.parent.namespace);
31
+ assertIdentifier2(input.parent.name, "policy parent");
32
+ assertIdentifier2(input.name, "policy");
33
+ assertStoredText(input.expression, "policy expression");
34
+ if (input.command !== "all" && input.command !== "select") {
35
+ catalogError2("OKM1020", `Policy ${input.name} command is not supported.`);
36
+ }
37
+ assertProvenance(input.provenance);
38
+ const parent = {
39
+ kind: "table",
40
+ namespace: input.parent.namespace,
41
+ name: input.parent.name
42
+ };
43
+ const definition = {
44
+ command: input.command,
45
+ expression: input.expression,
46
+ force: input.force
47
+ };
48
+ return {
49
+ kind: "policy",
50
+ identity: { kind: "policy", parent: input.parent, name: fitIdentifier2(input.name) },
51
+ owner: input.owner ?? "managed",
52
+ definition,
53
+ dependencies: normaliseEdges([parent, ...input.dependencies ?? []]),
54
+ provenance: input.provenance
55
+ };
56
+ }
57
+
58
+ export { tenantPolicyExpression, unscopedPolicyExpression, policyObject };