better-supabase 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. package/README.md +2 -0
  2. package/dist/channel-FQW-CnGR.d.ts +70 -0
  3. package/dist/cli/bin.js +1 -1
  4. package/dist/cli/codemod-DqV7612m.js +388 -0
  5. package/dist/cli/{config-D9R0o1LH.js → config-CPVpXP5I.js} +78 -8
  6. package/dist/cli/{config-SSKSTUl2.js → config-dtoekM0v.js} +1 -1
  7. package/dist/cli/{read-sets-CMa29t9a.js → diff-SjkO5rNr.js} +1 -220
  8. package/dist/cli/{dist-CFgGknmZ.js → dist-DBPdlPYK.js} +4 -4
  9. package/dist/cli/{dist-B1MvLv-M.js → dist-DreZ24Sz.js} +1 -1
  10. package/dist/cli/{dist-Du7VnEUG.js → dist-xn4wlboc.js} +112 -1
  11. package/dist/cli/{doctor-BOym3mbL.js → doctor-L7Z8mYTx.js} +531 -50
  12. package/dist/cli/{env-BZ0uy8XK.js → env-DmKv_G4A.js} +1 -1
  13. package/dist/cli/gen-BJc9vdyu.js +2 -0
  14. package/dist/cli/{gen-Ccn_p90L.js → gen-C2osRcr5.js} +283 -87
  15. package/dist/cli/index.d.ts +1 -1
  16. package/dist/cli/index.js +4 -4
  17. package/dist/cli/{init-ClnxRYBF.js → init-Saf5-R9T.js} +2 -2
  18. package/dist/cli/{introspect-DxqfkVIv.js → introspect--H7oGmcd.js} +2 -2
  19. package/dist/cli/{openapi-8WHjxiTJ.js → openapi-Cp5Fyta-.js} +1 -1
  20. package/dist/cli/read-sets-BfMQcKy8.js +289 -0
  21. package/dist/cli/{run-CP20LKk_.js → run-BKR2W_79.js} +16 -12
  22. package/dist/cli/{seed-5J6eu_Xg.js → seed-CUlqWh-8.js} +1 -1
  23. package/dist/cli/sql-DzPbfngx.js +348 -0
  24. package/dist/cli/{version-5mW_8sY1.js → version-BDJuO0UR.js} +1 -1
  25. package/dist/client/index.d.ts +1 -1
  26. package/dist/client/index.js +3 -10
  27. package/dist/clone-BfgmLU90.js +21 -0
  28. package/dist/{compiler-DB3aSFOA.d.ts → compiler-BXH_aZ7N.d.ts} +2 -2
  29. package/dist/config/index.d.ts +4 -4
  30. package/dist/config/index.js +4 -4
  31. package/dist/{config-CbvFmGD8.js → config-DreERlKo.js} +1 -1
  32. package/dist/{config-C1CYcm6o.d.ts → config-T_ejwyd3.d.ts} +176 -11
  33. package/dist/{define-CRS2MRV3.d.ts → define-Bp_BZa5h.d.ts} +11 -7
  34. package/dist/{define-Bh0AqTik.js → define-cNKzqwL_.js} +202 -16
  35. package/dist/edge/index.d.ts +16 -5
  36. package/dist/edge/index.js +10 -7
  37. package/dist/{entitlements-Dm-FHpNH.d.ts → entitlements-DUxU4oHe.d.ts} +1 -1
  38. package/dist/env/index.d.ts +2 -2
  39. package/dist/env/index.js +34 -1
  40. package/dist/{errors-L0xK41y_.js → errors-DtwXa6b8.js} +1 -0
  41. package/dist/events/index.d.ts +3 -2
  42. package/dist/events/index.js +65 -12
  43. package/dist/events-aIO7vsIk.d.ts +230 -0
  44. package/dist/{result-CqEsbgYs.d.ts → executor-BunPOO-k.d.ts} +200 -1
  45. package/dist/{executor-CZ7ImRiD.d.ts → executor-Cghdstwu.d.ts} +1 -2
  46. package/dist/{executor-CVt6dD0B.js → executor-XycESQPH.js} +3 -3
  47. package/dist/hono/index.d.ts +17 -6
  48. package/dist/hono/index.js +40 -5
  49. package/dist/impersonation-VfaGc4Q_.js +41 -0
  50. package/dist/{index-BBdvo-5d.d.ts → index-BGdgBPdf.d.ts} +49 -6
  51. package/dist/{index-BhHEC04r.d.ts → index-C7f8cOBM.d.ts} +2 -2
  52. package/dist/{index-Dy6kuF0P.d.ts → index-CLg87OBW.d.ts} +6 -1
  53. package/dist/{index-D5IfUIDh.d.ts → index-DOESKG27.d.ts} +33 -8
  54. package/dist/{index-DFmOpBGC.d.ts → index-DgILJRXj.d.ts} +35 -9
  55. package/dist/{index-RlLXd8dL.d.ts → index-DmXSxbLi.d.ts} +4 -4
  56. package/dist/{index-Cf-D2jk1.d.ts → index-Dxn2a5cw.d.ts} +2 -2
  57. package/dist/{index-528Ugmyp.d.ts → index-SaTsEfGP.d.ts} +76 -8
  58. package/dist/{index-BAy4tsAP.d.ts → index-fag8VJZ2.d.ts} +3 -4
  59. package/dist/index.d.ts +30 -13
  60. package/dist/index.js +10 -9
  61. package/dist/jobs/index.d.ts +147 -101
  62. package/dist/jobs/index.js +744 -237
  63. package/dist/{json-schema-DP6V7cbr.js → json-schema-m1fiwKgN.js} +22 -1
  64. package/dist/kit-events-CTFDfSwb.js +60 -0
  65. package/dist/kit-transport-B82k1djG.d.ts +33 -0
  66. package/dist/kit-transport-DJlHQUBU.js +55 -0
  67. package/dist/{config-BpxDfnbg.js → kits-CGLLrNPd.js} +37 -9
  68. package/dist/list/index.d.ts +1 -1
  69. package/dist/{live-BHakSWWo.d.ts → live-D9W2M5aO.d.ts} +6 -5
  70. package/dist/mcp/index.d.ts +25 -8
  71. package/dist/mcp/index.js +23 -14
  72. package/dist/{mfa-C7MNQ1Ob.d.ts → mfa-CusDgPaD.d.ts} +5 -1
  73. package/dist/next/index.d.ts +31 -10
  74. package/dist/next/index.js +136 -27
  75. package/dist/notifications/index.d.ts +162 -0
  76. package/dist/notifications/index.js +264 -0
  77. package/dist/openapi/index.d.ts +1 -1
  78. package/dist/openapi/index.js +2 -2
  79. package/dist/orgs/index.d.ts +132 -0
  80. package/dist/orgs/index.js +245 -0
  81. package/dist/orpc/index.d.ts +28 -8
  82. package/dist/orpc/index.js +16 -3
  83. package/dist/otel/index.d.ts +21 -2
  84. package/dist/otel/index.js +50 -9
  85. package/dist/permdock-sql-C2Inc6Xc.d.ts +29 -0
  86. package/dist/permdock-sql-DgOfeixi.js +51 -0
  87. package/dist/plugin-DwARMuQp.js +59 -0
  88. package/dist/{plugin-bNhvJwRh.d.ts → plugin-o144f322.d.ts} +17 -5
  89. package/dist/plugins/actor/index.d.ts +5 -2
  90. package/dist/plugins/actor/index.js +22 -8
  91. package/dist/plugins/rules/index.d.ts +2 -2
  92. package/dist/plugins/rules/index.js +15 -10
  93. package/dist/plugins/soft-delete/index.d.ts +3 -3
  94. package/dist/plugins/soft-delete/index.js +14 -5
  95. package/dist/plugins/tenant/index.d.ts +2 -2
  96. package/dist/plugins/tenant/index.js +38 -20
  97. package/dist/plugins/timestamps/index.d.ts +1 -1
  98. package/dist/plugins/timestamps/index.js +4 -3
  99. package/dist/plugins/validation/index.d.ts +2 -2
  100. package/dist/plugins/validation/index.js +26 -6
  101. package/dist/{pool-DFwEQwmN.d.ts → pool-C9voM4Kw.d.ts} +17 -6
  102. package/dist/postgres/index.d.ts +5 -5
  103. package/dist/postgres/index.js +20 -11
  104. package/dist/{postgrest-Bc-0Xw62.d.ts → postgrest-CruYKAvV.d.ts} +1 -1
  105. package/dist/{problem-BihjPR0t.js → problem-BW1KhzSG.js} +2 -1
  106. package/dist/{problem-U8UEKccv.d.ts → problem-Blxe8S31.d.ts} +1 -1
  107. package/dist/query/index.d.ts +2 -2
  108. package/dist/query/index.js +3 -3
  109. package/dist/{query-BMMSWbI7.js → query-CCbo44lG.js} +2 -2
  110. package/dist/queue-BYUCjr59.d.ts +252 -0
  111. package/dist/react/index.d.ts +8 -7
  112. package/dist/react/index.js +4 -3
  113. package/dist/react/server.d.ts +14 -3
  114. package/dist/react/server.js +10 -2
  115. package/dist/react/session.d.ts +7 -1
  116. package/dist/react/session.js +9 -1
  117. package/dist/{react-CQHMaESR.js → react-C_s7kiNz.js} +103 -11
  118. package/dist/{read-set-FWK8qQ58.js → read-set-DQFt1N_Y.js} +22 -1
  119. package/dist/realtime/index.d.ts +3 -3
  120. package/dist/realtime/index.js +5 -4
  121. package/dist/{refresh-BwYkyNOQ.d.ts → refresh-BTrQ_ZTp.d.ts} +1 -1
  122. package/dist/{resolve-BAqQcwMW.d.ts → resolve-C15TJq77.d.ts} +11 -5
  123. package/dist/{resource-My_y-Syh.js → resource-CRxxwkQq.js} +22 -7
  124. package/dist/{resource-BJcaIfxi.d.ts → resource-D8iqWMr-.d.ts} +5 -5
  125. package/dist/respond-D2OQl62-.d.ts +371 -0
  126. package/dist/{result-Bj6yt33D.js → result-BKiliPY7.js} +1 -1
  127. package/dist/server/index.d.ts +14 -12
  128. package/dist/server/index.js +11 -17
  129. package/dist/{server-BA75B0mT.js → server-Csx2sRjg.js} +251 -34
  130. package/dist/{shared-DnoCdMDr.js → shared-D1dRUrAg.js} +16 -2
  131. package/dist/signers-Cc6r98SW.d.ts +162 -0
  132. package/dist/{simplify-Cqvfr9dj.js → simplify-_0oUKqCd.js} +4 -115
  133. package/dist/sql/index.d.ts +247 -10
  134. package/dist/sql/index.js +8590 -779
  135. package/dist/{sql-B34HU2DI.js → sql-Coh6n4cC.js} +9 -2
  136. package/dist/ssr/index.d.ts +4 -4
  137. package/dist/ssr/index.js +1 -2
  138. package/dist/{standard-BRyBGTtp.js → standard-D7r6dMUu.js} +6 -3
  139. package/dist/{standard-BsaCYQJc.d.ts → standard-J4YgMOLm.d.ts} +1 -1
  140. package/dist/{stats-C_YxA2r1.js → stats-Bqob3WqT.js} +4 -4
  141. package/dist/storage/index.d.ts +4 -4
  142. package/dist/storage/index.js +155 -26
  143. package/dist/support-DT-OhSxD.d.ts +88 -0
  144. package/dist/support-Dk6vdmEw.js +291 -0
  145. package/dist/support-view-Da5peKFg.d.ts +17 -0
  146. package/dist/support-view-g4YLBeqX.js +18 -0
  147. package/dist/{permdock-sql-C4KFzLc9.js → template-TxrGI5jR.js} +2 -31
  148. package/dist/{temporal-BwshQk0W.js → temporal-CVlIV2DZ.js} +17 -4
  149. package/dist/{temporal-required-CBNHT6ni.js → temporal-required-CAt4Dc9Z.js} +2 -2
  150. package/dist/testing/index.d.ts +100 -10
  151. package/dist/testing/index.js +336 -8
  152. package/dist/{types-DONv9SHN.d.ts → types-Dnf_wRDz.d.ts} +26 -3
  153. package/dist/user-change-CHFEUro1.js +49 -0
  154. package/dist/{webhooks-Bh_Jf_-l.js → verify-Ce49ETPz.js} +5 -5
  155. package/dist/{version-Bmf7_FzM.js → version-DM_Roffb.js} +1 -1
  156. package/dist/{view-B64o81wp.d.ts → view-BEf0diC5.d.ts} +8 -3
  157. package/dist/{mfa-byfjruR9.js → view-Bq64ki8-.js} +95 -38
  158. package/dist/webhooks/index.d.ts +135 -4
  159. package/dist/webhooks/index.js +588 -2
  160. package/dist/wire-D2dT86vi.js +35 -0
  161. package/package.json +16 -8
  162. package/schemas/config-v1.json +131 -1
  163. package/schemas/doctor-report-v1.json +10 -0
  164. package/skills/better-supabase/SKILL.md +9 -6
  165. package/skills/better-supabase/references/plugins.md +6 -3
  166. package/skills/better-supabase/references/troubleshooting.md +1 -0
  167. package/skills/better-supabase-api/SKILL.md +9 -2
  168. package/skills/better-supabase-api/references/adapters.md +11 -8
  169. package/skills/better-supabase-auth/SKILL.md +3 -0
  170. package/skills/better-supabase-auth/references/permdock.md +56 -11
  171. package/dist/cli/gen-D5cLCULx.js +0 -2
  172. package/dist/cli/sql-D4VbqmXi.js +0 -199
  173. package/dist/events-B21UOhvP.d.ts +0 -84
  174. package/dist/executor-B5IoUxLE.d.ts +0 -195
  175. package/dist/invalidate-CgxmRamI.js +0 -24
  176. package/dist/permdock-sql-DImJULY-.d.ts +0 -17
  177. package/dist/plugin-BqR6wKMB.js +0 -23
  178. package/dist/respond-DgIbdrt8.d.ts +0 -194
  179. package/dist/view-BrJI2LKp.js +0 -45
@@ -0,0 +1,51 @@
1
+ import { i as sqlString, r as sqlIdent } from "./template-TxrGI5jR.js";
2
+ //#region src/core/permdock-sql.ts
3
+ const SCOPE = /^[a-z][a-z0-9_]*$/;
4
+ /** PermDock's default `rls.schema`, a schema the Data API does not expose. */
5
+ const PERMDOCK_SCHEMA = "permdock";
6
+ /** PermDock splits a key with row conditions into `key#1`, `key#2`, ...: those need its own policies. */
7
+ const SPLIT_KEY = /#\d+$/;
8
+ function permdockKeyStatus(catalog, key) {
9
+ const entry = catalog.permissions.find((permission) => permission.key === key);
10
+ if (!entry) return "missing";
11
+ if (entry.rowConditions === true) return "row-conditions";
12
+ if (entry.rowConditions === false) return "scope-only";
13
+ return "no-flag";
14
+ }
15
+ const REGENERATE = "Regenerate permissions.catalog.json with a current `permdock catalog`, which writes rowConditions for every permission.";
16
+ /**
17
+ * The SQL condition for one PermDock permission key. `id` is the text
18
+ * expression holding the scope id; it is compared as text, so a malformed
19
+ * path never raises a cast error.
20
+ *
21
+ * The helpers check role and scope, not a permission's row conditions, so
22
+ * the condition is only correct for permissions whose grants have none
23
+ * beyond the scope. `#n` keys are refused. With a catalog, only keys it marks
24
+ * `rowConditions: false` are accepted: `true`, a missing flag and a key the
25
+ * catalog doesn't list are refused.
26
+ */
27
+ function permdockCheck(where, target, key, id, catalog) {
28
+ if (key === "") throw new TypeError(`${where}: a PermDock permission key is empty`);
29
+ if (SPLIT_KEY.test(key)) throw new TypeError(`${where}: "${key}" is one part of a permission PermDock splits by row condition. Use PermDock's generated policies for it.`);
30
+ if (catalog) {
31
+ const status = permdockKeyStatus(catalog, key);
32
+ switch (status) {
33
+ case "scope-only": break;
34
+ case "row-conditions": throw new TypeError(`${where}: "${key}" has row conditions in PermDock's catalog (rowConditions: true), which the SQL helpers don't check. Use PermDock's generated policies for it.`);
35
+ case "no-flag": throw new TypeError(`${where}: "${key}" has no rowConditions flag in PermDock's catalog, so whether the SQL helpers check it fully is unknown. ${REGENERATE}`);
36
+ case "missing": throw new TypeError(`${where}: "${key}" is not in PermDock's catalog. ${REGENERATE}`);
37
+ default: return status;
38
+ }
39
+ }
40
+ const schema = sqlIdent(target.schema ?? "permdock");
41
+ if (target.scope === "global") return `(select ${schema}.permdock_has(${sqlString(key)}))`;
42
+ if (!SCOPE.test(target.scope)) throw new TypeError(`${where}: invalid PermDock scope "${target.scope}"`);
43
+ if (id === void 0) throw new TypeError(`${where}: scope "${target.scope}" needs a segment`);
44
+ return `${id} in (select t.id::text from ${schema}.${sqlIdent(`permitted_${target.scope}_ids`)}(${sqlString(key)}) as t(id))`;
45
+ }
46
+ /** The keys a bucket or topic PermDock policy names. */
47
+ function permdockKeys(policy) {
48
+ return Object.values(policy.permdock).filter((key) => typeof key === "string");
49
+ }
50
+ //#endregion
51
+ export { permdockKeys as i, permdockCheck as n, permdockKeyStatus as r, PERMDOCK_SCHEMA as t };
@@ -0,0 +1,59 @@
1
+ //#region src/core/plugin.ts
2
+ const PLUGIN_API_VERSION = 1;
3
+ const RANK = {
4
+ pre: 0,
5
+ normal: 1,
6
+ post: 2
7
+ };
8
+ /**
9
+ * `rules()` checks the query as the caller wrote it, so it runs before every
10
+ * other `pre` plugin (soft delete turns deletes into updates, tenant adds
11
+ * filters).
12
+ */
13
+ function rankOf(plugin) {
14
+ return plugin.name === "rules" ? -1 : RANK[plugin.enforce ?? "normal"];
15
+ }
16
+ /**
17
+ * Plugins in hook order: `rules`, then `pre`, then unmarked in `use()` order,
18
+ * then `post`.
19
+ */
20
+ function orderPlugins(plugins) {
21
+ return plugins.map((plugin, index) => ({
22
+ plugin,
23
+ index
24
+ })).sort((a, b) => rankOf(a.plugin) - rankOf(b.plugin) || a.index - b.index).map(({ plugin }) => plugin);
25
+ }
26
+ /** Identity helper that fixes `apiVersion` and infers the plugin types. */
27
+ function definePlugin(plugin) {
28
+ return {
29
+ ...plugin,
30
+ apiVersion: 1
31
+ };
32
+ }
33
+ /** Tenants that `tenant()` resolved from claims, per connection context. */
34
+ const resolvedTenants = /* @__PURE__ */ new WeakMap();
35
+ /** Records the tenant a plugin resolved for `context`, so mutation notices carry it. */
36
+ function recordTenant(context, tenant) {
37
+ resolvedTenants.set(context, tenant);
38
+ }
39
+ /** `context.tenant`, else the tenant a plugin resolved for this connection. */
40
+ function tenantOf(context) {
41
+ return context.tenant ?? resolvedTenants.get(context);
42
+ }
43
+ /**
44
+ * A symbol key, so JSON, claims and spread request data can't set it, while
45
+ * `$with` copies it to the derived context.
46
+ */
47
+ const ALL_TENANTS = Symbol("better-supabase.allTenants");
48
+ /** `context`, marked so `tenant()` and tenant buckets skip their tenant scope. */
49
+ function allTenantsContext(context) {
50
+ return {
51
+ ...context,
52
+ [ALL_TENANTS]: true
53
+ };
54
+ }
55
+ function spansAllTenants(context) {
56
+ return Object.hasOwn(context, ALL_TENANTS);
57
+ }
58
+ //#endregion
59
+ export { recordTenant as a, orderPlugins as i, allTenantsContext as n, spansAllTenants as o, definePlugin as r, tenantOf as s, PLUGIN_API_VERSION as t };
@@ -1,7 +1,6 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { A as SchemaMeta, P as TableMeta, n as AnyModels } from "./types-DONv9SHN.js";
3
- import { g as Operation, h as MutationOp, r as Executor } from "./executor-B5IoUxLE.js";
4
- import { v as ErrorMapper } from "./result-CqEsbgYs.js";
2
+ import { F as TableMeta, j as SchemaMeta, r as AnyModels } from "./types-Dnf_wRDz.js";
3
+ import { H as MutationOp, S as ErrorMapper, U as Operation, r as Executor } from "./executor-BunPOO-k.js";
5
4
  //#region src/core/plugin.d.ts
6
5
  /** Who is making the request. */
7
6
  interface Actor {
@@ -32,11 +31,24 @@ interface HookArgs {
32
31
  readonly now: () => Temporal.Instant;
33
32
  }
34
33
  type MutationKind = "insert" | "upsert" | "update" | "delete";
34
+ /** What the caller asked for: `softDelete` is a `delete` that a plugin turned into an update. */
35
+ type MutationIntent = MutationKind | "softDelete";
35
36
  interface MutationEvent {
36
37
  readonly table: TableMeta;
38
+ /** The statement that ran. */
37
39
  readonly kind: MutationKind;
38
- /** App-cased rows returned by the mutation. */
40
+ /** What the caller asked for; differs from `kind` when a plugin rewrote the mutation. */
41
+ readonly intent?: MutationIntent;
42
+ /** App-cased rows returned by the mutation. A copy: changing it never changes the result. */
39
43
  readonly rows: readonly Readonly<Record<string, unknown>>[];
44
+ /**
45
+ * App-cased primary keys of the changed rows, when they are known: from
46
+ * the returned rows, or from a `where` on the primary key when nothing is
47
+ * returned (soft deletes, `returning: false`).
48
+ */
49
+ readonly keys?: readonly Readonly<Record<string, unknown>>[];
50
+ /** The tenant of the write: `context.tenant`, or the one `tenant()` resolved. */
51
+ readonly tenant?: string;
40
52
  readonly context: RequestContext;
41
53
  }
42
54
  /** Runtime handle passed to `Plugin.repository`. */
@@ -116,4 +128,4 @@ declare function definePlugin<const Name extends string, Ext extends RepositoryE
116
128
  readonly apiVersion?: 1;
117
129
  }): Plugin<Name, Ext>;
118
130
  //#endregion
119
- export { definePlugin as _, ExtensionOf as a, MutationEvent as c, PLUGIN_API_VERSION as d, Plugin as f, WithExtension as g, RequestContext as h, CallOptions as i, MutationKind as l, RepositoryExtension as m, AnyPlugin as n, HasFlag as o, RepositoryApi as p, ApplyExtension as r, HookArgs as s, Actor as t, NoExtension as u };
131
+ export { WithExtension as _, ExtensionOf as a, MutationEvent as c, NoExtension as d, PLUGIN_API_VERSION as f, RequestContext as g, RepositoryExtension as h, CallOptions as i, MutationIntent as l, RepositoryApi as m, AnyPlugin as n, HasFlag as o, Plugin as p, ApplyExtension as r, HookArgs as s, Actor as t, MutationKind as u, definePlugin as v };
@@ -1,4 +1,4 @@
1
- import { f as Plugin, h as RequestContext } from "../../plugin-bNhvJwRh.js";
1
+ import { g as RequestContext, p as Plugin } from "../../plugin-o144f322.js";
2
2
  //#region src/plugins/actor/index.d.ts
3
3
  export interface ActorOptions {
4
4
  /** Custom actor id resolution. Defaults to `context.actor.id` for users and services. */
@@ -7,7 +7,10 @@ export interface ActorOptions {
7
7
  /**
8
8
  * Stamps the columns generated as `Flags.actor`: `createdBy` on insert and
9
9
  * `updatedBy` on insert and update. Soft deletes are updates, so they record
10
- * who deleted the row. Without an actor (anonymous requests) nothing is set.
10
+ * who deleted the row. `impersonatedBy` gets `context.actor.impersonator` on
11
+ * an impersonated insert or update and is left alone otherwise, so a user's
12
+ * own update keeps the stamp, like the SQL kit's `track_actor`. Without an
13
+ * actor (anonymous requests) nothing is set.
11
14
  */
12
15
  export declare function actor(options?: ActorOptions): Plugin<"actor">;
13
16
  //#endregion
@@ -1,5 +1,5 @@
1
- import { n as definePlugin } from "../../plugin-BqR6wKMB.js";
2
- import { i as insertsOnly, l as withDefault, t as dbName } from "../../shared-DnoCdMDr.js";
1
+ import { r as definePlugin } from "../../plugin-DwARMuQp.js";
2
+ import { a as insertsOnly, i as guardManaged, t as dbName, u as withDefault } from "../../shared-D1dRUrAg.js";
3
3
  //#region src/plugins/actor/index.ts
4
4
  function defaultActor(context) {
5
5
  const actor = context.actor;
@@ -8,30 +8,44 @@ function defaultActor(context) {
8
8
  /**
9
9
  * Stamps the columns generated as `Flags.actor`: `createdBy` on insert and
10
10
  * `updatedBy` on insert and update. Soft deletes are updates, so they record
11
- * who deleted the row. Without an actor (anonymous requests) nothing is set.
11
+ * who deleted the row. `impersonatedBy` gets `context.actor.impersonator` on
12
+ * an impersonated insert or update and is left alone otherwise, so a user's
13
+ * own update keeps the stamp, like the SQL kit's `track_actor`. Without an
14
+ * actor (anonymous requests) nothing is set.
12
15
  */
13
16
  function actor(options = {}) {
14
17
  const resolve = options.resolve ?? defaultActor;
15
18
  return definePlugin({
16
19
  name: "actor",
17
- beforeMutation(op, { table, context }) {
20
+ beforeMutation(op, { table, context, options }) {
18
21
  const flags = table.flags.actor;
19
22
  if (!flags) return op;
20
- const id = resolve(context);
21
- if (id === void 0) return op;
22
23
  const created = dbName(table, flags.createdBy);
23
24
  const updated = dbName(table, flags.updatedBy);
25
+ const impersonated = dbName(table, flags.impersonatedBy);
26
+ guardManaged(op, [
27
+ created,
28
+ updated,
29
+ impersonated
30
+ ], "actor", options);
31
+ const id = resolve(context);
32
+ if (id === void 0) return op;
33
+ const impersonator = context.actor?.impersonator;
34
+ const stamp = (row) => {
35
+ const stamped = withDefault(row, updated, id);
36
+ return impersonator === void 0 ? stamped : withDefault(stamped, impersonated, impersonator);
37
+ };
24
38
  switch (op.kind) {
25
39
  case "insert": {
26
40
  const stampCreated = insertsOnly(op);
27
41
  return {
28
42
  ...op,
29
- rows: op.rows.map((row) => withDefault(stampCreated ? withDefault(row, created, id) : row, updated, id))
43
+ rows: op.rows.map((row) => stamp(stampCreated ? withDefault(row, created, id) : row))
30
44
  };
31
45
  }
32
46
  case "update": return {
33
47
  ...op,
34
- set: withDefault(op.set, updated, id)
48
+ set: stamp(op.set)
35
49
  };
36
50
  case "delete": return op;
37
51
  default: return op;
@@ -1,5 +1,5 @@
1
- import { g as Operation } from "../../executor-B5IoUxLE.js";
2
- import { f as Plugin, m as RepositoryExtension } from "../../plugin-bNhvJwRh.js";
1
+ import { U as Operation } from "../../executor-BunPOO-k.js";
2
+ import { h as RepositoryExtension, p as Plugin } from "../../plugin-o144f322.js";
3
3
  //#region src/plugins/rules/index.d.ts
4
4
  export type RuleLevel = "off" | "warn" | "error";
5
5
  /** A level, or a level with the rule's option: `['error', 500]`. */
@@ -1,7 +1,7 @@
1
- import { n as dbError, t as DbException } from "../../errors-L0xK41y_.js";
1
+ import { n as dbError, t as DbException } from "../../errors-DtwXa6b8.js";
2
2
  import { t as lookupOf } from "../../lookup-BaP5bI27.js";
3
- import { n as definePlugin } from "../../plugin-BqR6wKMB.js";
4
- import { n as claimAt, r as claimsOf } from "../../claims-BAf6c7is.js";
3
+ import { r as definePlugin } from "../../plugin-DwARMuQp.js";
4
+ import { i as tenantClaimPaths, n as claimAt, r as claimsOf } from "../../claims-BAf6c7is.js";
5
5
  //#region src/plugins/rules/index.ts
6
6
  /** Catches data-exposure and correctness mistakes; everything else off. */
7
7
  function safe() {
@@ -121,8 +121,12 @@ function checks(rules) {
121
121
  const maxLimit = optionOf(rules.maxLimit, 1e3);
122
122
  const maxDepth = optionOf(rules.maxIncludeDepth, 3);
123
123
  return {
124
- noUnboundedFindMany: (op) => op.kind === "select" && op.single === void 0 && !op.head && op.limit === void 0 ? "findMany without limit reads every visible row" : void 0,
125
- maxLimit: (op) => op.kind === "select" && op.limit !== void 0 && op.limit > maxLimit ? `limit ${op.limit} is above the maximum of ${maxLimit}` : void 0,
124
+ noUnboundedFindMany: (op) => op.kind === "select" && op.single === void 0 && !op.head && op.limit === void 0 && op.selection.aggregate === void 0 ? "findMany without limit reads every visible row" : void 0,
125
+ maxLimit: (op) => {
126
+ if (op.kind !== "select" || op.limit === void 0) return;
127
+ const limit = op.lookAhead === true ? op.limit - 1 : op.limit;
128
+ return limit > maxLimit ? `limit ${limit} is above the maximum of ${maxLimit}` : void 0;
129
+ },
126
130
  requireOrderByForCursor: (op) => op.kind === "select" && !op.head && op.orderBy.length === 0 && (op.offset !== void 0 || op.limit !== void 0 && op.limit > 1) ? "paging without orderBy returns rows in no stable order" : void 0,
127
131
  maxIncludeDepth: (op) => {
128
132
  const max = maxDepth;
@@ -132,14 +136,15 @@ function checks(rules) {
132
136
  },
133
137
  requireTenantContext: (op, { context, schema }) => {
134
138
  if (!op.table.flags.tenant || context.actor?.kind === "service") return;
135
- const claim = optionOf(rules.requireTenantContext, claimsOf(schema).tenant);
136
- return context.tenant === void 0 && claimAt(context.claims, claim) === void 0 ? `"${op.table.key}" is tenant-scoped but the request has no tenant (context.tenant or claim "${claim}")` : void 0;
139
+ if (typeof context.tenant === "string") return;
140
+ const claim = optionOf(rules.requireTenantContext, void 0);
141
+ const paths = claim === void 0 ? tenantClaimPaths(claimsOf(schema).tenant) : [claim];
142
+ return paths.some((path) => claimAt(context.claims, path) !== void 0) ? void 0 : `"${op.table.key}" is tenant-scoped but the request has no tenant (context.tenant or claim ${paths.map((path) => `"${path}"`).join(" or ")})`;
137
143
  },
138
144
  noAdminInBrowser: (_op, { context }) => context.actor?.kind === "service" && isBrowser() ? "a service-role connection is running in a browser" : void 0,
139
145
  noSensitiveSelect: (op, { options }) => {
140
- if (options["sensitive"] === true) return;
141
- const selection = op.kind === "select" ? op.selection : op.returning;
142
- const columns = selection ? sensitiveColumns(selection, op.table) : [];
146
+ if (options["sensitive"] === true || op.kind !== "select") return;
147
+ const columns = sensitiveColumns(op.selection, op.table);
143
148
  return columns.length > 0 ? `reads sensitive column(s) ${columns.join(", ")}; pass { sensitive: true } to allow` : void 0;
144
149
  },
145
150
  noDeleteManyWithoutWhere: (op) => op.kind === "delete" && op.where === void 0 ? "delete without where removes every visible row" : void 0,
@@ -1,6 +1,6 @@
1
- import { C as PrimaryKeyValue } from "../../types-DONv9SHN.js";
2
- import { t as AsyncResult } from "../../result-CqEsbgYs.js";
3
- import { f as Plugin, m as RepositoryExtension, o as HasFlag } from "../../plugin-bNhvJwRh.js";
1
+ import { w as PrimaryKeyValue } from "../../types-Dnf_wRDz.js";
2
+ import { a as AsyncResult } from "../../executor-BunPOO-k.js";
3
+ import { h as RepositoryExtension, o as HasFlag, p as Plugin } from "../../plugin-o144f322.js";
4
4
  //#region src/plugins/soft-delete/index.d.ts
5
5
  export interface SoftDeleteFindArgs {
6
6
  /** Include soft-deleted rows of the queried table. */
@@ -1,8 +1,8 @@
1
1
  import { t as and } from "../../types-6cYK9pbJ.js";
2
- import { i as ok, t as AsyncResult } from "../../result-Bj6yt33D.js";
3
- import { n as definePlugin } from "../../plugin-BqR6wKMB.js";
2
+ import { i as ok, t as AsyncResult } from "../../result-BKiliPY7.js";
3
+ import { r as definePlugin } from "../../plugin-DwARMuQp.js";
4
4
  import { n as scopeOperation } from "../../scope-CDHcS7dE.js";
5
- import { a as isNotNull, o as isNull, t as dbName } from "../../shared-DnoCdMDr.js";
5
+ import { a as insertsOnly, i as guardManaged, o as isNotNull, s as isNull, t as dbName, u as withDefault } from "../../shared-D1dRUrAg.js";
6
6
  //#region src/plugins/soft-delete/index.ts
7
7
  function deletedColumn(table) {
8
8
  return dbName(table, table.flags.softDelete);
@@ -39,9 +39,17 @@ function softDelete() {
39
39
  };
40
40
  },
41
41
  beforeMutation(op, { table, options, now }) {
42
- if (op.kind !== "delete" || options["hard"] === true) return op;
43
42
  const column = deletedColumn(table);
44
43
  if (!column) return op;
44
+ guardManaged(op, [column], "softDelete", options);
45
+ if (op.kind === "insert") {
46
+ if (insertsOnly(op)) return op;
47
+ return {
48
+ ...op,
49
+ rows: op.rows.map((row) => withDefault(row, column, null))
50
+ };
51
+ }
52
+ if (op.kind !== "delete" || options["hard"] === true) return op;
45
53
  return {
46
54
  kind: "update",
47
55
  table,
@@ -58,7 +66,8 @@ function softDelete() {
58
66
  const result = await update(key, { [flag]: null }, {
59
67
  ...args,
60
68
  withDeleted: true,
61
- returning: false
69
+ returning: false,
70
+ override: true
62
71
  });
63
72
  return result.ok ? ok(void 0) : result;
64
73
  }) };
@@ -1,5 +1,5 @@
1
- import { A as SchemaMeta } from "../../types-DONv9SHN.js";
2
- import { f as Plugin, h as RequestContext, m as RepositoryExtension, o as HasFlag } from "../../plugin-bNhvJwRh.js";
1
+ import { j as SchemaMeta } from "../../types-Dnf_wRDz.js";
2
+ import { g as RequestContext, h as RepositoryExtension, o as HasFlag, p as Plugin } from "../../plugin-o144f322.js";
3
3
  //#region src/plugins/tenant/index.d.ts
4
4
  /**
5
5
  * Dotted paths to the string claims of `C` (up to three levels), e.g.
@@ -1,8 +1,8 @@
1
- import { n as dbError, t as DbException } from "../../errors-L0xK41y_.js";
2
- import { n as definePlugin } from "../../plugin-BqR6wKMB.js";
1
+ import { n as dbError, t as DbException } from "../../errors-DtwXa6b8.js";
2
+ import { a as recordTenant, o as spansAllTenants, r as definePlugin } from "../../plugin-DwARMuQp.js";
3
3
  import { n as scopeOperation } from "../../scope-CDHcS7dE.js";
4
4
  import { i as tenantClaimPaths, n as claimAt, r as claimsOf } from "../../claims-BAf6c7is.js";
5
- import { n as equals, r as forbidden, t as dbName } from "../../shared-DnoCdMDr.js";
5
+ import { a as insertsOnly, n as equals, r as forbidden, t as dbName } from "../../shared-D1dRUrAg.js";
6
6
  //#region src/plugins/tenant/index.ts
7
7
  /**
8
8
  * The tenant for a request: `context.tenant`, then the configured claim.
@@ -18,6 +18,11 @@ function resolveTenant(context, options = {}, schema) {
18
18
  if (value !== void 0) return value;
19
19
  }
20
20
  }
21
+ /** Tenant columns may be numeric; the resolved tenant is always a string. */
22
+ function sameTenant(value, id) {
23
+ if (value === id) return true;
24
+ return (typeof value === "number" || typeof value === "bigint") && String(value) === id;
25
+ }
21
26
  function tenantColumn(table) {
22
27
  return dbName(table, table.flags.tenant);
23
28
  }
@@ -32,21 +37,32 @@ function tenant(options = {}) {
32
37
  const onMissing = options.onMissing ?? "error";
33
38
  /** A context is fixed for a connection, so its tenant is resolved once. */
34
39
  const resolved = /* @__PURE__ */ new WeakMap();
35
- const current = (table, context, schema) => {
40
+ const resolvedFor = (context, schema) => {
36
41
  let id = resolved.get(context);
37
42
  if (id === void 0 && !resolved.has(context)) {
38
43
  id = resolveTenant(context, options, schema);
39
44
  resolved.set(context, id);
45
+ if (id !== void 0) recordTenant(context, id);
40
46
  }
41
- if (id === void 0 && onMissing === "error" && tenantColumn(table)) throw new DbException(dbError("forbidden", `No tenant in the request context for "${table.key}"`));
47
+ return id;
48
+ };
49
+ const missing = (table) => {
50
+ throw new DbException(dbError("forbidden", `No tenant in the request context for "${table.key}"`));
51
+ };
52
+ const current = (table, context, schema) => {
53
+ const id = resolvedFor(context, schema);
54
+ if (id === void 0 && onMissing === "error" && tenantColumn(table)) missing(table);
42
55
  return id;
43
56
  };
44
57
  return definePlugin({
45
58
  name: "tenant",
46
59
  transformQuery(op, { context, schema, options: call }) {
47
- if (call["allTenants"] === true) return op;
48
- const id = current(op.table, context, schema);
49
- if (id === void 0) return op;
60
+ if (call["allTenants"] === true || spansAllTenants(context)) return op;
61
+ const id = resolvedFor(context, schema);
62
+ if (id === void 0) {
63
+ if (onMissing === "error") scopeOperation(op, (table) => tenantColumn(table) ? missing(table) : void 0);
64
+ return op;
65
+ }
50
66
  return scopeOperation(op, (table) => {
51
67
  const column = tenantColumn(table);
52
68
  return column ? equals(column, id) : void 0;
@@ -54,22 +70,24 @@ function tenant(options = {}) {
54
70
  },
55
71
  beforeMutation(op, { table, context, schema, options: call }) {
56
72
  const column = tenantColumn(table);
57
- if (!column || call["allTenants"] === true) return op;
73
+ if (!column || call["allTenants"] === true || spansAllTenants(context)) return op;
58
74
  const id = current(table, context, schema);
59
75
  if (id === void 0) return op;
60
76
  switch (op.kind) {
61
- case "insert": return {
62
- ...op,
63
- rows: op.rows.map((row) => {
64
- if (column in row && row[column] !== id) forbidden(`Cannot write a ${table.key} row for another tenant`);
65
- return {
66
- ...row,
67
- [column]: id
68
- };
69
- })
70
- };
77
+ case "insert":
78
+ if (!insertsOnly(op) && !op.onConflict?.columns.includes(column)) forbidden(`An upsert on ${table.key} that updates on conflict needs the tenant column "${column}" in its conflict target`);
79
+ return {
80
+ ...op,
81
+ rows: op.rows.map((row) => {
82
+ if (column in row && !sameTenant(row[column], id)) forbidden(`Cannot write a ${table.key} row for another tenant`);
83
+ return {
84
+ ...row,
85
+ [column]: id
86
+ };
87
+ })
88
+ };
71
89
  case "update":
72
- if (column in op.set && op.set[column] !== id) forbidden(`Cannot move a ${table.key} row to another tenant`);
90
+ if (column in op.set && !sameTenant(op.set[column], id)) forbidden(`Cannot move a ${table.key} row to another tenant`);
73
91
  return op;
74
92
  case "delete": return op;
75
93
  default: return op;
@@ -1,4 +1,4 @@
1
- import { f as Plugin } from "../../plugin-bNhvJwRh.js";
1
+ import { p as Plugin } from "../../plugin-o144f322.js";
2
2
  //#region src/plugins/timestamps/index.d.ts
3
3
  /**
4
4
  * Stamps the columns generated as `Flags.timestamps`: `createdAt` on insert,
@@ -1,5 +1,5 @@
1
- import { n as definePlugin } from "../../plugin-BqR6wKMB.js";
2
- import { i as insertsOnly, l as withDefault, t as dbName } from "../../shared-DnoCdMDr.js";
1
+ import { r as definePlugin } from "../../plugin-DwARMuQp.js";
2
+ import { a as insertsOnly, i as guardManaged, t as dbName, u as withDefault } from "../../shared-D1dRUrAg.js";
3
3
  //#region src/plugins/timestamps/index.ts
4
4
  /**
5
5
  * Stamps the columns generated as `Flags.timestamps`: `createdAt` on insert,
@@ -9,11 +9,12 @@ import { i as insertsOnly, l as withDefault, t as dbName } from "../../shared-Dn
9
9
  function timestamps() {
10
10
  return definePlugin({
11
11
  name: "timestamps",
12
- beforeMutation(op, { table, now }) {
12
+ beforeMutation(op, { table, now, options }) {
13
13
  const flags = table.flags.timestamps;
14
14
  if (!flags) return op;
15
15
  const created = dbName(table, flags.createdAt);
16
16
  const updated = dbName(table, flags.updatedAt);
17
+ guardManaged(op, [created, updated], "timestamps", options);
17
18
  const stamp = now().toString();
18
19
  switch (op.kind) {
19
20
  case "insert": {
@@ -1,5 +1,5 @@
1
- import { f as Plugin } from "../../plugin-bNhvJwRh.js";
2
- import { t as StandardSchemaV1 } from "../../standard-BsaCYQJc.js";
1
+ import { p as Plugin } from "../../plugin-o144f322.js";
2
+ import { t as StandardSchemaV1 } from "../../standard-J4YgMOLm.js";
3
3
  //#region src/plugins/validation/index.d.ts
4
4
  export interface TableValidators {
5
5
  /** Validates inserts and upserts, with app-cased keys. */
@@ -1,13 +1,33 @@
1
- import { n as dbError, t as DbException } from "../../errors-L0xK41y_.js";
2
- import { n as definePlugin } from "../../plugin-BqR6wKMB.js";
3
- import { t as validate } from "../../standard-BRyBGTtp.js";
4
- import { c as toDb, s as toApp } from "../../shared-DnoCdMDr.js";
1
+ import { n as dbError, t as DbException } from "../../errors-DtwXa6b8.js";
2
+ import { n as decodeValue, r as encodeValue } from "../../wire-D2dT86vi.js";
3
+ import { r as definePlugin } from "../../plugin-DwARMuQp.js";
4
+ import { t as validate } from "../../standard-D7r6dMUu.js";
5
+ import { c as toApp, l as toDb } from "../../shared-D1dRUrAg.js";
5
6
  //#region src/plugins/validation/index.ts
7
+ /**
8
+ * Rows reach plugins in wire form (ISO text, decimal text), while generated
9
+ * validators expect the column codecs' app values (Temporal, `bigint`).
10
+ */
11
+ function decoded(table, row) {
12
+ const app = toApp(table, row);
13
+ for (const [name, value] of Object.entries(app)) {
14
+ const codec = table.columns[name]?.codec;
15
+ if (codec === void 0 || typeof value !== "string") continue;
16
+ try {
17
+ app[name] = decodeValue(codec, value);
18
+ } catch {}
19
+ }
20
+ return app;
21
+ }
22
+ function encoded(row) {
23
+ for (const [name, value] of Object.entries(row)) row[name] = encodeValue(value);
24
+ return row;
25
+ }
6
26
  async function check(schema, table, row, label, index) {
7
- const result = await validate(schema, toApp(table, row), label);
27
+ const result = await validate(schema, decoded(table, row), label);
8
28
  if (result.ok) {
9
29
  const output = result.data;
10
- return typeof output === "object" && output !== null ? toDb(table, output) : { ...row };
30
+ return typeof output === "object" && output !== null ? encoded(toDb(table, output)) : { ...row };
11
31
  }
12
32
  const error = result.error;
13
33
  if (index === void 0 || error.kind !== "validation") throw new DbException(error);
@@ -1,5 +1,5 @@
1
- import { r as Executor } from "./executor-B5IoUxLE.js";
2
- import { t as SqlClient } from "./executor-CZ7ImRiD.js";
1
+ import { r as Executor } from "./executor-BunPOO-k.js";
2
+ import { t as SqlClient } from "./executor-Cghdstwu.js";
3
3
  //#region src/postgres/pool.d.ts
4
4
  /** The part of a `pg` pool client `createPostgres` uses. */
5
5
  interface PgPoolClient {
@@ -48,11 +48,22 @@ interface SqlClaims {
48
48
  readonly role?: string;
49
49
  readonly [claim: string]: unknown;
50
50
  }
51
+ /** What every transaction of a user session sets besides the claims and role. */
52
+ interface SessionOptions {
53
+ /**
54
+ * Transaction-local settings, e.g. `{ 'better_supabase.tenant': id }`.
55
+ * Names need a dot (custom settings); `role` and `request.jwt.claims` are
56
+ * set from the claims.
57
+ */
58
+ readonly settings?: Readonly<Record<string, string>>;
59
+ /** Runs every transaction with `begin read only`: writes fail with 25006. */
60
+ readonly readOnly?: boolean;
61
+ }
51
62
  interface BetterPostgres {
52
63
  /** Connects as the connection-string role. On Supabase that bypasses RLS. */
53
64
  readonly admin: SqlClient;
54
65
  /** Runs every query as the given user, with RLS, like PostgREST does. */
55
- asUser(claims: SqlClaims): SqlClient;
66
+ asUser(claims: SqlClaims, options?: SessionOptions): SqlClient;
56
67
  /** Runs every query as `anon`. */
57
68
  readonly anon: SqlClient;
58
69
  /**
@@ -60,11 +71,11 @@ interface BetterPostgres {
60
71
  * `createServer` calls it for `ctx.sql`, so only apps that pass `postgres`
61
72
  * bundle the SQL compiler.
62
73
  */
63
- executorFor(claims: SqlClaims): Executor;
74
+ executorFor(claims: SqlClaims, options?: SessionOptions): Executor;
64
75
  /** Runs `fn` in one transaction. Pass claims to run it as a user. */
65
76
  transaction<T>(fn: (client: SqlClient) => Promise<T>, options?: {
66
77
  readonly claims?: SqlClaims;
67
- }): Promise<T>;
78
+ } & SessionOptions): Promise<T>;
68
79
  end(): Promise<void>;
69
80
  [Symbol.asyncDispose](): Promise<void>;
70
81
  }
@@ -75,4 +86,4 @@ interface BetterPostgres {
75
86
  */
76
87
  declare function createPostgres(options?: PostgresOptions): BetterPostgres;
77
88
  //#endregion
78
- export { PostgresTimeouts as a, PostgresOptions as i, PgPool as n, SqlClaims as o, PgPoolClient as r, createPostgres as s, BetterPostgres as t };
89
+ export { PostgresTimeouts as a, createPostgres as c, PostgresOptions as i, PgPool as n, SessionOptions as o, PgPoolClient as r, SqlClaims as s, BetterPostgres as t };
@@ -1,7 +1,7 @@
1
- import { g as Operation } from "../executor-B5IoUxLE.js";
2
- import { n as fromPgError, r as postgresExecutor, t as SqlClient } from "../executor-CZ7ImRiD.js";
3
- import { a as PostgresTimeouts, i as PostgresOptions, n as PgPool, o as SqlClaims, r as PgPoolClient, s as createPostgres, t as BetterPostgres } from "../pool-DFwEQwmN.js";
4
- import { t as Compiler } from "../compiler-DB3aSFOA.js";
1
+ import { U as Operation } from "../executor-BunPOO-k.js";
2
+ import { n as fromPgError, r as postgresExecutor, t as SqlClient } from "../executor-Cghdstwu.js";
3
+ import { a as PostgresTimeouts, c as createPostgres, i as PostgresOptions, n as PgPool, o as SessionOptions, r as PgPoolClient, s as SqlClaims, t as BetterPostgres } from "../pool-C9voM4Kw.js";
4
+ import { t as Compiler } from "../compiler-BXH_aZ7N.js";
5
5
  //#region src/compile/sql.d.ts
6
6
  interface SqlQuery {
7
7
  readonly text: string;
@@ -30,4 +30,4 @@ export declare function compileSql(op: Operation): SqlPlan;
30
30
  //#region src/postgres/compiler.d.ts
31
31
  export declare const sqlCompiler: Compiler<SqlPlan>;
32
32
  //#endregion
33
- export { type BetterPostgres, type PgPool, type PgPoolClient, type PostgresOptions, type PostgresTimeouts, type SqlClaims, type SqlClient, type SqlPlan, type SqlQuery, createPostgres, fromPgError, postgresExecutor };
33
+ export { type BetterPostgres, type PgPool, type PgPoolClient, type PostgresOptions, type PostgresTimeouts, type SessionOptions, type SqlClaims, type SqlClient, type SqlPlan, type SqlQuery, createPostgres, fromPgError, postgresExecutor };