better-supabase 0.2.0 → 0.4.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 (190) hide show
  1. package/README.md +37 -33
  2. package/dist/base64-D2gsioCY.js +42 -0
  3. package/dist/claims-BAf6c7is.js +48 -0
  4. package/dist/cli/_format-Cax5EsM9.js +101 -0
  5. package/dist/cli/bin.js +39 -6
  6. package/dist/cli/command-CK14fP91.js +502 -0
  7. package/dist/cli/compare-BmIWVEui.js +9 -0
  8. package/dist/cli/config-D9R0o1LH.js +1895 -0
  9. package/dist/cli/config-SSKSTUl2.js +2 -0
  10. package/dist/cli/db-DOBPt660.js +52 -0
  11. package/dist/cli/dist-B1MvLv-M.js +129 -0
  12. package/dist/cli/dist-CFgGknmZ.js +1112 -0
  13. package/dist/cli/dist-Du7VnEUG.js +621 -0
  14. package/dist/cli/doctor-BOym3mbL.js +2382 -0
  15. package/dist/cli/env-BZ0uy8XK.js +108 -0
  16. package/dist/cli/env-jIFUADLY.js +511 -0
  17. package/dist/cli/errors-4v4DTtda.js +56 -0
  18. package/dist/cli/fastest-levenshtein-CFN-lNDv.js +120 -0
  19. package/dist/cli/gen-Ccn_p90L.js +2008 -0
  20. package/dist/cli/gen-D5cLCULx.js +2 -0
  21. package/dist/cli/index.d.ts +295 -28
  22. package/dist/cli/index.js +184 -3
  23. package/dist/cli/init-ClnxRYBF.js +550 -0
  24. package/dist/cli/introspect-DxqfkVIv.js +81 -0
  25. package/dist/cli/io-k41_z-jT.js +24 -0
  26. package/dist/cli/json5-ChRycquj.js +787 -0
  27. package/dist/cli/jsonc-BUniUpOk.js +2 -0
  28. package/dist/cli/jsonc-D5Fu67jw.js +45 -0
  29. package/dist/cli/keys-ByKHnvP9.js +83 -0
  30. package/dist/cli/ohash-D7bG_EOb.js +277 -0
  31. package/dist/cli/openapi-8WHjxiTJ.js +66 -0
  32. package/dist/cli/project-B_GeXyHh.js +70 -0
  33. package/dist/cli/prompts-BNcNfAve.js +1142 -0
  34. package/dist/cli/prompts-BTYQGunc.js +2 -0
  35. package/dist/cli/read-sets-CMa29t9a.js +971 -0
  36. package/dist/cli/rolldown-runtime-BPOCksWG.js +24 -0
  37. package/dist/cli/run-CP20LKk_.js +347 -0
  38. package/dist/cli/seed-5J6eu_Xg.js +98 -0
  39. package/dist/cli/skills-LJJIhLFR.js +137 -0
  40. package/dist/cli/sql-D4VbqmXi.js +199 -0
  41. package/dist/cli/style-C0NFdJRL.js +29 -0
  42. package/dist/cli/toml-DB-MNnFs.js +424 -0
  43. package/dist/{version-Cqq1m3UY.js → cli/version-5mW_8sY1.js} +1 -1
  44. package/dist/cli/yaml-CYCbJ6et.js +2252 -0
  45. package/dist/client/index.d.ts +2 -2
  46. package/dist/client/index.js +15 -25
  47. package/dist/{compiler-CZ9nIuqy.d.ts → compiler-DB3aSFOA.d.ts} +2 -2
  48. package/dist/config/index.d.ts +4 -3
  49. package/dist/config/index.js +5 -3
  50. package/dist/config-BpxDfnbg.js +129 -0
  51. package/dist/{index-DOsjFvMf.d.ts → config-C1CYcm6o.d.ts} +49 -49
  52. package/dist/{config-ClDXmVtY.js → config-CbvFmGD8.js} +14 -137
  53. package/dist/{define-BXMYD9AY.js → define-Bh0AqTik.js} +221 -120
  54. package/dist/{define-e3zI4_4g.d.ts → define-CRS2MRV3.d.ts} +36 -31
  55. package/dist/edge/index.d.ts +9 -13
  56. package/dist/edge/index.js +51 -25
  57. package/dist/{entitlements-Dng-ctuT.d.ts → entitlements-Dm-FHpNH.d.ts} +2 -2
  58. package/dist/env/index.js +203 -1
  59. package/dist/{errors-Bl3rkOzo.js → errors-L0xK41y_.js} +1 -1
  60. package/dist/events/index.d.ts +1 -1
  61. package/dist/events/index.js +139 -1
  62. package/dist/{events-DOt3nSO-.d.ts → events-B21UOhvP.d.ts} +4 -4
  63. package/dist/{executor-CGdNQ27g.d.ts → executor-B5IoUxLE.d.ts} +2 -2
  64. package/dist/{executor-DeppvirK.js → executor-CVt6dD0B.js} +9 -4
  65. package/dist/{executor-BYXQ9AGn.d.ts → executor-CZ7ImRiD.d.ts} +2 -2
  66. package/dist/hono/index.d.ts +17 -24
  67. package/dist/hono/index.js +11 -11
  68. package/dist/{index-DuP14VHo.d.ts → index-528Ugmyp.d.ts} +30 -10
  69. package/dist/{index-Bw1bwtC0.d.ts → index-BAy4tsAP.d.ts} +28 -15
  70. package/dist/{index-CBDufH1M.d.ts → index-BBdvo-5d.d.ts} +24 -26
  71. package/dist/{index-DbxFr7XG.d.ts → index-BhHEC04r.d.ts} +9 -4
  72. package/dist/index-Cf-D2jk1.d.ts +50 -0
  73. package/dist/{index-Ciu5Xlml.d.ts → index-D5IfUIDh.d.ts} +6 -5
  74. package/dist/{index-K-3WM2Hp.d.ts → index-DFmOpBGC.d.ts} +13 -13
  75. package/dist/{index-D4v7sncu.d.ts → index-RlLXd8dL.d.ts} +13 -13
  76. package/dist/index.d.ts +17 -17
  77. package/dist/index.js +23 -14
  78. package/dist/{invalidate-DbxuL2jL.js → invalidate-CgxmRamI.js} +7 -1
  79. package/dist/jobs/index.d.ts +33 -26
  80. package/dist/jobs/index.js +44 -22
  81. package/dist/{json-schema-BpYqkCKf.js → json-schema-DP6V7cbr.js} +8 -3
  82. package/dist/lint/index.js +1 -1
  83. package/dist/list/index.d.ts +2 -2
  84. package/dist/list/index.js +131 -96
  85. package/dist/{live-DJyZMD6w.d.ts → live-BHakSWWo.d.ts} +26 -16
  86. package/dist/{live-D8rV1Ldw.js → live-CdJBOc4f.js} +13 -9
  87. package/dist/lookup-BaP5bI27.js +18 -0
  88. package/dist/mcp/index.d.ts +34 -27
  89. package/dist/mcp/index.js +59 -25
  90. package/dist/{mfa-TVia554c.d.ts → mfa-C7MNQ1Ob.d.ts} +1 -1
  91. package/dist/{mfa-CpLfJSde.js → mfa-byfjruR9.js} +190 -46
  92. package/dist/next/image/index.js +6 -3
  93. package/dist/next/index.d.ts +64 -48
  94. package/dist/next/index.js +63 -50
  95. package/dist/openapi/index.d.ts +1 -1
  96. package/dist/openapi/index.js +61 -38
  97. package/dist/orpc/index.d.ts +18 -21
  98. package/dist/orpc/index.js +12 -12
  99. package/dist/otel/index.d.ts +5 -5
  100. package/dist/otel/index.js +84 -63
  101. package/dist/{permdock-sql-CghlHPuH.js → permdock-sql-C4KFzLc9.js} +12 -7
  102. package/dist/permdock-sql-DImJULY-.d.ts +17 -0
  103. package/dist/{plugin-C4TR9J0Z.d.ts → plugin-bNhvJwRh.d.ts} +5 -4
  104. package/dist/plugins/actor/index.d.ts +1 -1
  105. package/dist/plugins/actor/index.js +1 -1
  106. package/dist/plugins/rules/index.d.ts +2 -2
  107. package/dist/plugins/rules/index.js +46 -16
  108. package/dist/plugins/soft-delete/index.d.ts +3 -3
  109. package/dist/plugins/soft-delete/index.js +4 -4
  110. package/dist/plugins/tenant/index.d.ts +3 -3
  111. package/dist/plugins/tenant/index.js +10 -4
  112. package/dist/plugins/timestamps/index.d.ts +1 -1
  113. package/dist/plugins/timestamps/index.js +2 -2
  114. package/dist/plugins/validation/index.d.ts +2 -2
  115. package/dist/plugins/validation/index.js +3 -3
  116. package/dist/pool-DFwEQwmN.d.ts +78 -0
  117. package/dist/postgres/index.d.ts +10 -5
  118. package/dist/postgres/index.js +37 -16
  119. package/dist/{postgrest-cAEQ_IQN.d.ts → postgrest-Bc-0Xw62.d.ts} +1 -1
  120. package/dist/{problem-BTkTtRV9.js → problem-BihjPR0t.js} +11 -5
  121. package/dist/{problem-DlgB0lYl.d.ts → problem-U8UEKccv.d.ts} +6 -4
  122. package/dist/query/index.d.ts +2 -2
  123. package/dist/query/index.js +2 -2
  124. package/dist/{query-ChvDbsDE.js → query-BMMSWbI7.js} +19 -19
  125. package/dist/react/index.d.ts +7 -7
  126. package/dist/react/index.js +2 -2
  127. package/dist/react/server.d.ts +6 -6
  128. package/dist/react/server.js +3 -3
  129. package/dist/react/session.d.ts +21 -2
  130. package/dist/react/session.js +19 -1
  131. package/dist/{react-C83BdBGt.js → react-CQHMaESR.js} +59 -55
  132. package/dist/{read-set-4lI3W_gZ.js → read-set-FWK8qQ58.js} +51 -16
  133. package/dist/realtime/index.d.ts +4 -3
  134. package/dist/realtime/index.js +19 -17
  135. package/dist/{index-CG69s15v.d.ts → refresh-BwYkyNOQ.d.ts} +7 -3
  136. package/dist/{resolve-CjHILk2w.d.ts → resolve-BAqQcwMW.d.ts} +17 -11
  137. package/dist/{resource-CgZa3YG_.d.ts → resource-BJcaIfxi.d.ts} +17 -8
  138. package/dist/{resource-BHEWmQJK.js → resource-My_y-Syh.js} +43 -21
  139. package/dist/{respond-Dne1ARSa.d.ts → respond-DgIbdrt8.d.ts} +39 -14
  140. package/dist/{result-DWXatkd6.js → result-Bj6yt33D.js} +2 -2
  141. package/dist/{result-CTkCZ6JA.d.ts → result-CqEsbgYs.d.ts} +16 -11
  142. package/dist/server/index.d.ts +38 -13
  143. package/dist/server/index.js +43 -14
  144. package/dist/{respond-DMcbQwfN.js → server-BA75B0mT.js} +151 -96
  145. package/dist/{shared-_6-uPL7E.js → shared-DnoCdMDr.js} +4 -3
  146. package/dist/{simplify-bwJpLnaS.js → simplify-Cqvfr9dj.js} +76 -39
  147. package/dist/sql/index.d.ts +139 -0
  148. package/dist/sql/index.js +1983 -0
  149. package/dist/{sql-DTjA1LPj.js → sql-B34HU2DI.js} +74 -17
  150. package/dist/ssr/index.d.ts +4 -4
  151. package/dist/ssr/index.js +2 -2
  152. package/dist/{standard-FUi3Z3-7.js → standard-BRyBGTtp.js} +2 -2
  153. package/dist/{standard-CyhRzctb.d.ts → standard-BsaCYQJc.d.ts} +1 -1
  154. package/dist/{stats-C5W-rBfR.js → stats-C_YxA2r1.js} +40 -14
  155. package/dist/storage/index.d.ts +4 -3
  156. package/dist/storage/index.js +548 -1
  157. package/dist/{tables-rZxRxNPW.js → tables-Cb-3_VWc.js} +19 -5
  158. package/dist/temporal-BwshQk0W.js +27 -0
  159. package/dist/temporal-required-CBNHT6ni.js +19 -0
  160. package/dist/testing/index.d.ts +25 -24
  161. package/dist/testing/index.js +165 -66
  162. package/dist/{types-C83v5SQz.d.ts → types-DONv9SHN.d.ts} +14 -11
  163. package/dist/version-Bmf7_FzM.js +4 -0
  164. package/dist/{view-D1s0wa0T.d.ts → view-B64o81wp.d.ts} +36 -6
  165. package/dist/{view-aOYizTeE.js → view-BrJI2LKp.js} +11 -2
  166. package/dist/webhooks/index.d.ts +19 -17
  167. package/dist/webhooks/index.js +1 -1
  168. package/dist/{webhooks-DMipjhSP.js → webhooks-Bh_Jf_-l.js} +45 -24
  169. package/package.json +50 -22
  170. package/schemas/config-v1.json +31 -1
  171. package/schemas/doctor-report-v1.json +17 -1
  172. package/schemas/snapshot-v2.json +35 -0
  173. package/skills/better-supabase/SKILL.md +77 -18
  174. package/skills/better-supabase/references/plugins.md +21 -22
  175. package/skills/better-supabase/references/troubleshooting.md +38 -18
  176. package/skills/better-supabase-api/SKILL.md +66 -18
  177. package/skills/better-supabase-api/references/adapters.md +64 -41
  178. package/skills/better-supabase-auth/SKILL.md +146 -0
  179. package/skills/better-supabase-auth/references/permdock.md +55 -0
  180. package/skills/better-supabase-testing/SKILL.md +68 -11
  181. package/dist/casing-da0uRTqt.js +0 -14
  182. package/dist/claims-CoTobNC-.js +0 -25
  183. package/dist/cli-DrSgDOQC.js +0 -6646
  184. package/dist/env-BEToab0I.js +0 -204
  185. package/dist/events-BuzTgn2D.js +0 -135
  186. package/dist/pool-R2m_DkXi.d.ts +0 -37
  187. package/dist/seed-CzecODcJ.js +0 -101
  188. package/dist/session-C3LxnQ0e.d.ts +0 -22
  189. package/dist/session-CqEwzVup.js +0 -20
  190. package/dist/storage-DuGn38fr.js +0 -527
@@ -1,7 +1,7 @@
1
- import { n as dbError } from "./errors-Bl3rkOzo.js";
2
- import { i as ok, n as err } from "./result-DWXatkd6.js";
3
- import { t as validate } from "./standard-FUi3Z3-7.js";
4
- import { i as respond } from "./respond-DMcbQwfN.js";
1
+ import { n as dbError } from "./errors-L0xK41y_.js";
2
+ import { i as ok, n as err } from "./result-Bj6yt33D.js";
3
+ import { t as validate } from "./standard-BRyBGTtp.js";
4
+ import { s as respond } from "./server-BA75B0mT.js";
5
5
  //#region src/server/resource.ts
6
6
  const INTEGER = /* @__PURE__ */ new Set([
7
7
  "int2",
@@ -24,24 +24,44 @@ async function readBody(request) {
24
24
  } catch {}
25
25
  return err(dbError("invalid_request", "The request body must be a JSON object"));
26
26
  }
27
- function pageArgs(query, max) {
27
+ function pageArgs(query, max, pagination) {
28
+ const raw = (name) => {
29
+ const value = query instanceof URLSearchParams ? query.get(name) : query?.[name];
30
+ return value === null || value === "" ? void 0 : value;
31
+ };
28
32
  const read = (name, fallback) => {
29
- const raw = query instanceof URLSearchParams ? query.get(name) : query?.[name];
30
- if (raw === null || raw === void 0 || raw === "") return fallback;
31
- const value = Number(raw);
32
- return Number.isSafeInteger(value) && value >= 1 ? value : void 0;
33
+ const value = raw(name);
34
+ if (value === void 0) return fallback;
35
+ const number = Number(value);
36
+ return Number.isSafeInteger(number) && number >= 1 ? number : void 0;
33
37
  };
34
- const page = read("page", 1);
38
+ const issues = [];
35
39
  const size = read("size", 50);
36
- if (page === void 0 || size === void 0 || size > max) return err(dbError("validation", "Invalid page parameters", { issues: [...page === void 0 ? [{
37
- message: "Must be a positive integer",
38
- path: ["page"]
39
- }] : [], ...size === void 0 || size > max ? [{
40
+ if (size === void 0 || size > max) issues.push({
40
41
  message: `Must be between 1 and ${max}`,
41
42
  path: ["size"]
42
- }] : []] }));
43
- return ok({
44
- page,
43
+ });
44
+ const [used, unused] = pagination === "cursor" ? ["after", "page"] : ["page", "after"];
45
+ if (raw(unused) !== void 0) issues.push({
46
+ message: `This list pages with \`${used}\``,
47
+ path: [unused]
48
+ });
49
+ const page = read("page", 1);
50
+ if (pagination === "offset" && page === void 0) issues.push({
51
+ message: "Must be a positive integer",
52
+ path: ["page"]
53
+ });
54
+ const after = raw("after");
55
+ if (pagination === "cursor" && after !== void 0 && typeof after !== "string") issues.push({
56
+ message: "Must be text",
57
+ path: ["after"]
58
+ });
59
+ if (issues.length > 0 || size === void 0) return err(dbError("validation", "Invalid page parameters", { issues }));
60
+ return pagination === "cursor" ? ok({
61
+ after: typeof after === "string" ? after : null,
62
+ size
63
+ }) : ok({
64
+ page: page ?? 1,
45
65
  size
46
66
  });
47
67
  }
@@ -62,8 +82,8 @@ function notAllowed(allowed) {
62
82
  * `createOpenApi`: `GET/POST /<table>` and `GET/PATCH/DELETE /<table>/{id}`.
63
83
  * Shared by the HTTP adapters and the MCP table tools.
64
84
  */
65
- function defineResource(sb, table, options = {}) {
66
- const meta = sb.meta.tables[table];
85
+ function defineResource(betterSupabase, table, options = {}) {
86
+ const meta = betterSupabase.meta.tables[table];
67
87
  if (!meta) throw new TypeError(`Unknown table "${table}"`);
68
88
  if (options.list && options.list.table !== table) throw new TypeError(`The list query is for "${options.list.table}", not "${table}"`);
69
89
  const operations = options.operations ?? (meta.kind === "view" ? ["list", "get"] : [
@@ -78,6 +98,7 @@ function defineResource(sb, table, options = {}) {
78
98
  const extra = options.select === void 0 ? {} : { select: options.select };
79
99
  const maxPageSize = options.maxPageSize ?? 200;
80
100
  const list = options.list;
101
+ const pagination = list ? list.pagination ?? "offset" : options.pagination ?? "offset";
81
102
  const execute = async (db, operation, input = {}) => {
82
103
  const repository = db[table];
83
104
  if (!repository) throw new TypeError(`The db has no "${table}" repository`);
@@ -90,12 +111,12 @@ function defineResource(sb, table, options = {}) {
90
111
  if (!query.ok) return err(dbError("validation", "Invalid list query", { issues: query.issues }));
91
112
  return settled(list.run(db, query.value, extra));
92
113
  }
93
- const page = pageArgs(input.query, maxPageSize);
114
+ const page = pageArgs(input.query, maxPageSize, pagination);
94
115
  if (!page.ok) return page;
95
116
  return settled(repository.paginate({
96
117
  ...extra,
97
118
  ...page.data,
98
- count: "exact"
119
+ ..."page" in page.data ? { count: "exact" } : {}
99
120
  }));
100
121
  }
101
122
  case "get": {
@@ -160,6 +181,7 @@ function defineResource(sb, table, options = {}) {
160
181
  operations,
161
182
  keyParam,
162
183
  list,
184
+ pagination,
163
185
  maxPageSize,
164
186
  execute,
165
187
  handle(request, db, id, respondOptions = {}) {
@@ -1,12 +1,12 @@
1
- import { n as AnyModels, t as AnyFunctions } from "./types-C83v5SQz.js";
2
- import { p as DbError, t as AsyncResult } from "./result-CTkCZ6JA.js";
3
- import { I as StatsRecorder, P as DbStats, t as BetterSupabase, y as Db } from "./define-e3zI4_4g.js";
4
- import { h as RequestContext } from "./plugin-C4TR9J0Z.js";
1
+ import { n as AnyModels, t as AnyFunctions } from "./types-DONv9SHN.js";
2
+ import { p as DbError, t as AsyncResult } from "./result-CqEsbgYs.js";
3
+ import { I as StatsRecorder, P as DbStats, t as BetterSupabase, y as Db } from "./define-CRS2MRV3.js";
4
+ import { h as RequestContext } from "./plugin-bNhvJwRh.js";
5
5
  import { t as BetterSupabaseEnv } from "./index-Dy6kuF0P.js";
6
- import { r as SqlClaims, t as Postgres } from "./pool-R2m_DkXi.js";
7
- import { o as ImpersonationOptions, t as Aal } from "./mfa-TVia554c.js";
8
- import { a as ResolveAuthOptions, r as AuthState, t as AuthResolution } from "./resolve-CjHILk2w.js";
9
- import { n as Bucket } from "./index-DuP14VHo.js";
6
+ import { o as SqlClaims, t as BetterPostgres } from "./pool-DFwEQwmN.js";
7
+ import { o as ImpersonationOptions, t as Aal } from "./mfa-C7MNQ1Ob.js";
8
+ import { a as ResolveAuthOptions, r as AuthState, t as AuthResolution } from "./resolve-BAqQcwMW.js";
9
+ import { n as Bucket } from "./index-528Ugmyp.js";
10
10
  import { SupabaseClient } from "@supabase/supabase-js";
11
11
  //#region src/server/delete-account.d.ts
12
12
  interface DeleteAccountOptions {
@@ -40,7 +40,7 @@ interface ReplicaState {
40
40
  readonly pinned: boolean;
41
41
  /** This context wrote through its repositories (or called `pin()`). */
42
42
  readonly wrote: boolean;
43
- /** Sends later reads to the primary, e.g. after a write through `$client` or `$sql`. */
43
+ /** Sends later reads to the primary, e.g. after a write through `$client` or `ctx.sql`. */
44
44
  pin(): void;
45
45
  }
46
46
  //#endregion
@@ -49,8 +49,14 @@ interface ServerOptions {
49
49
  /** Defaults to `loadEnv()`. */
50
50
  readonly env?: BetterSupabaseEnv;
51
51
  /** Enables `ctx.sql` and `actingAs()`. */
52
- readonly postgres?: Postgres;
52
+ readonly postgres?: BetterPostgres;
53
53
  readonly auth?: Omit<ResolveAuthOptions, "env">;
54
+ /**
55
+ * Fetch the JWKS when the server is created, so the first request verifies
56
+ * its token without waiting for it. Applies when `env.jwksUrl` is set and
57
+ * `auth.jwks` is not. Defaults to true, except under `NODE_ENV=test`.
58
+ */
59
+ readonly prefetchJwks?: boolean;
54
60
  /**
55
61
  * Extra headers on the caller's PostgREST requests, readable in Postgres as
56
62
  * `current_setting('request.headers')` (channel, request id, client IP for audit).
@@ -98,6 +104,11 @@ interface BetterServer<M extends AnyModels, F extends AnyFunctions, E, C = unkno
98
104
  * cookie session only with `refresh: true`; send `ctx.resolution.apply(response)`.
99
105
  */
100
106
  context(request: Request, options?: ContextOptions): Promise<ServerContext<M, F, E, C, P>>;
107
+ /**
108
+ * The context for a resolution from `resolve(request)`, so one resolution
109
+ * can back several contexts without verifying the token again.
110
+ */
111
+ contextFromResolution(resolution: AuthResolution<C, P>, request: Request, options?: Omit<ContextOptions, "refresh">): ServerContext<M, F, E, C, P>;
101
112
  /** The context for an auth state resolved elsewhere (the proxy, a queue message). */
102
113
  contextFor(auth: AuthState<C, P>, options?: ContextOptions): ServerContext<M, F, E, C, P>;
103
114
  /** A stateless supabase-js client for an auth state, optionally with extra request headers. */
@@ -121,9 +132,9 @@ interface BetterServer<M extends AnyModels, F extends AnyFunctions, E, C = unkno
121
132
  }
122
133
  /**
123
134
  * Server-side entry point for APIs, jobs, MCP servers and framework
124
- * adapters. Holds the secrets; `sb` stays isomorphic.
135
+ * adapters. Holds the secrets; `betterSupabase` stays isomorphic.
125
136
  */
126
- declare function createServer<M extends AnyModels, D, F extends AnyFunctions, E, C = unknown, P = unknown>(sb: BetterSupabase<M, D, F, E, C, P>, options?: ServerOptions): BetterServer<M, F, E, C, P>;
137
+ declare function createServer<M extends AnyModels, D, F extends AnyFunctions, E, C = unknown, P = unknown>(betterSupabase: BetterSupabase<M, D, F, E, C, P>, options?: ServerOptions): BetterServer<M, F, E, C, P>;
127
138
  //#endregion
128
139
  //#region src/server/respond.d.ts
129
140
  type AuthKind = AuthState["kind"];
@@ -135,9 +146,23 @@ interface GuardOptions {
135
146
  * `required: 'aal2'` until the user verifies a second factor.
136
147
  */
137
148
  readonly aal?: Aal;
149
+ /**
150
+ * OAuth scopes a delegated token (an OAuth client or an `act` chain) needs.
151
+ * A missing one answers 403 with `error="insufficient_scope"`. The user's
152
+ * own session is not limited by scopes.
153
+ */
154
+ readonly scopes?: readonly string[];
155
+ }
156
+ /** Guard options for middleware and fetch handlers that resolve the caller themselves. */
157
+ interface MiddlewareOptions extends GuardOptions {
158
+ /**
159
+ * Refresh an expired cookie session and send the new cookies. Only for
160
+ * routes browsers call with cookies; bearer tokens never refresh.
161
+ */
162
+ readonly refresh?: boolean;
138
163
  }
139
164
  /** `undefined` when `auth` may pass; otherwise the 401/403 error to send. */
140
- declare function guard(auth: AuthState, allow?: GuardOptions["allow"], aal?: Aal): DbError | undefined;
165
+ declare function guard(auth: AuthState, allow?: GuardOptions["allow"], aal?: Aal, scopes?: readonly string[]): DbError | undefined;
141
166
  declare function isResult(value: unknown): value is {
142
167
  ok: boolean;
143
168
  data: unknown;
@@ -166,4 +191,4 @@ interface RespondOptions {
166
191
  /** A handler's value as a response: `Response` as is, data as JSON, errors as Problem Details. */
167
192
  declare function respond(run: () => unknown, options?: RespondOptions): Promise<Response>;
168
193
  //#endregion
169
- export { DeleteAccountResult as _, guard as a, settle as c, ServerContext as d, ServerOptions as f, DeleteAccountOptions as g, ReplicaState as h, Settled as i, BetterServer as l, PRIMARY_COOKIE as m, GuardOptions as n, isResult as o, createServer as p, RespondOptions as r, respond as s, AuthKind as t, ContextOptions as u };
194
+ export { DeleteAccountOptions as _, Settled as a, respond as c, ContextOptions as d, ServerContext as f, ReplicaState as g, PRIMARY_COOKIE as h, RespondOptions as i, settle as l, createServer as m, GuardOptions as n, guard as o, ServerOptions as p, MiddlewareOptions as r, isResult as s, AuthKind as t, BetterServer as u, DeleteAccountResult as v };
@@ -1,4 +1,4 @@
1
- import { n as dbError, r as dbErrorOf, t as DbException } from "./errors-Bl3rkOzo.js";
1
+ import { n as dbError, r as dbErrorOf, t as DbException } from "./errors-L0xK41y_.js";
2
2
  //#region src/core/result.ts
3
3
  const throwMappers = /* @__PURE__ */ new WeakMap();
4
4
  function inherit(from, next) {
@@ -49,7 +49,7 @@ var AsyncResult = class AsyncResult {
49
49
  /**
50
50
  * Resolves with the data, or rejects with a `DbException`. Pass `factory`
51
51
  * to throw your own error instead, e.g. an HTTP error for your framework;
52
- * without it, the mapper from `sb.mapError()` applies when one is set.
52
+ * without it, the mapper from `betterSupabase.mapError()` applies when one is set.
53
53
  */
54
54
  async orThrow(factory) {
55
55
  const result = await this.#promise;
@@ -7,9 +7,14 @@
7
7
  interface DbErrorKinds {
8
8
  not_found: Record<never, never>;
9
9
  unauthorized: Record<never, never>;
10
- /** `required`: the assurance level the route needs, when a second factor is missing. */
10
+ /**
11
+ * `required`: the assurance level the route needs, when a second factor is
12
+ * missing. `scopes`: the OAuth scopes the route needs, when a delegated
13
+ * token lacks one (`INSUFFICIENT_SCOPE`).
14
+ */
11
15
  forbidden: {
12
16
  required?: "aal1" | "aal2";
17
+ scopes?: readonly string[];
13
18
  };
14
19
  conflict: {
15
20
  constraint?: string;
@@ -119,7 +124,7 @@ type ErrorMapper = (raw: RawDbError, fallback: DbError) => DbError | undefined;
119
124
  declare function mapDbError(raw: RawDbError, mappers?: readonly ErrorMapper[]): DbError;
120
125
  //#endregion
121
126
  //#region src/core/result.d.ts
122
- /** Turns a `DbError` into the error `.orThrow()` throws; set with `sb.mapError()`. */
127
+ /** Turns a `DbError` into the error `.orThrow()` throws; set with `betterSupabase.mapError()`. */
123
128
  type ThrowMapper = (error: DbError) => unknown;
124
129
  type Ok<T> = {
125
130
  readonly ok: true;
@@ -148,7 +153,7 @@ declare class AsyncResult<T> implements PromiseLike<Result<T>> {
148
153
  /**
149
154
  * Resolves with the data, or rejects with a `DbException`. Pass `factory`
150
155
  * to throw your own error instead, e.g. an HTTP error for your framework;
151
- * without it, the mapper from `sb.mapError()` applies when one is set.
156
+ * without it, the mapper from `betterSupabase.mapError()` applies when one is set.
152
157
  */
153
158
  orThrow(factory?: (error: DbError) => unknown): Promise<T>;
154
159
  /** Resolves with the data, or `fallback` when the result is an error. */
@@ -158,7 +163,7 @@ declare class AsyncResult<T> implements PromiseLike<Result<T>> {
158
163
  andThen<U>(fn: (data: T) => PromiseLike<Result<U>>): AsyncResult<U>;
159
164
  }
160
165
  /** What `toBetterResult` returns: the `status`/`value`/`error` fields every better-result value has. */
161
- type BetterResultShape<T, E> = {
166
+ type BetterResultValue<T, E> = {
162
167
  readonly status: "ok";
163
168
  readonly value: T;
164
169
  } | {
@@ -173,7 +178,7 @@ interface BetterResultApi<T, E> {
173
178
  /**
174
179
  * Builds a better-result value with the `Result` namespace you pass, so
175
180
  * better-result stays your dependency. Errors go through `mapError`, or, for a
176
- * result from a `db` of `sb.mapError(fn)`, through `fn` (typed `unknown`).
181
+ * result from a `db` of `betterSupabase.mapError(fn)`, through `fn` (typed `unknown`).
177
182
  * The value is a real `Ok`/`Err`: cast it (`as Result<T, E>`) for its
178
183
  * methods in types; the cast itself is not checked against `T`.
179
184
  *
@@ -182,17 +187,17 @@ interface BetterResultApi<T, E> {
182
187
  * const customer = toBetterResult(await db.customers.findById(id), Result, toAppError);
183
188
  * ```
184
189
  */
185
- declare function toBetterResult<T, E>(result: Result<T>, api: BetterResultApi<T, E>, mapError: (error: DbError) => E): BetterResultShape<T, E>;
186
- declare function toBetterResult<T>(result: Result<T>, api: BetterResultApi<T, DbError>): BetterResultShape<T, DbError>;
187
- declare function toBetterResult<T, E>(result: AsyncResult<T>, api: BetterResultApi<T, E>, mapError: (error: DbError) => E): Promise<BetterResultShape<T, E>>;
188
- declare function toBetterResult<T>(result: AsyncResult<T>, api: BetterResultApi<T, unknown>): Promise<BetterResultShape<T, unknown>>;
190
+ declare function toBetterResult<T, E>(result: Result<T>, api: BetterResultApi<T, E>, mapError: (error: DbError) => E): BetterResultValue<T, E>;
191
+ declare function toBetterResult<T>(result: Result<T>, api: BetterResultApi<T, DbError>): BetterResultValue<T, DbError>;
192
+ declare function toBetterResult<T, E>(result: AsyncResult<T>, api: BetterResultApi<T, E>, mapError: (error: DbError) => E): Promise<BetterResultValue<T, E>>;
193
+ declare function toBetterResult<T>(result: AsyncResult<T>, api: BetterResultApi<T, unknown>): Promise<BetterResultValue<T, unknown>>;
189
194
  /**
190
195
  * Converts a better-result value back into a `Result`, by its `status`
191
196
  * field, so it works across better-result versions. A `DbError`, or an
192
197
  * error whose `cause` is one, is kept; others go through `mapError`
193
198
  * (default `toDbError`).
194
199
  */
195
- declare function fromBetterResult<T>(result: BetterResultShape<T, unknown>, mapError?: (error: unknown) => DbError): Result<T>;
200
+ declare function fromBetterResult<T>(result: BetterResultValue<T, unknown>, mapError?: (error: unknown) => DbError): Result<T>;
196
201
  declare function toDbError(cause: unknown): DbError;
197
202
  //#endregion
198
- export { isConflict as C, statusOf as D, mapDbError as E, isCheck as S, isForeignKey as T, DbException as _, Ok as a, ValidationIssue as b, err as c, toBetterResult as d, toDbError as f, DbErrorOf as g, DbErrorKinds as h, Err as i, fromBetterResult as l, DbErrorKind as m, BetterResultApi as n, Result as o, DbError as p, BetterResultShape as r, ThrowMapper as s, AsyncResult as t, ok as u, ErrorMapper as v, isDbError as w, dbError as x, RawDbError as y };
203
+ export { isConflict as C, statusOf as D, mapDbError as E, isCheck as S, isForeignKey as T, DbException as _, Ok as a, ValidationIssue as b, err as c, toBetterResult as d, toDbError as f, DbErrorOf as g, DbErrorKinds as h, Err as i, fromBetterResult as l, DbErrorKind as m, BetterResultApi as n, Result as o, DbError as p, BetterResultValue as r, ThrowMapper as s, AsyncResult as t, ok as u, ErrorMapper as v, isDbError as w, dbError as x, RawDbError as y };
@@ -1,12 +1,14 @@
1
- import { n as AnyModels, t as AnyFunctions } from "../types-C83v5SQz.js";
2
- import { t as BetterSupabase, y as Db } from "../define-e3zI4_4g.js";
3
- import { h as RequestContext } from "../plugin-C4TR9J0Z.js";
4
- import { a as checkAal, c as impersonatorOf, i as amrOf, n as AmrEntry, o as ImpersonationOptions, r as aalOf, s as Impersonator, t as Aal } from "../mfa-TVia554c.js";
5
- import { _ as readSession, a as ResolveAuthOptions, b as writeSession, c as clientIp, d as CookieOptions, f as CookieRecord, i as InvalidReason, l as resolveAuth, m as StoredSession, n as AuthResolver, o as ResolvedState, p as CookieWrite, r as AuthState, s as authContext, t as AuthResolution, u as AUTH_CACHE_HEADERS, y as sessionCookieName } from "../resolve-CjHILk2w.js";
6
- import { _ as DeleteAccountResult, a as guard, c as settle, d as ServerContext, f as ServerOptions, g as DeleteAccountOptions, h as ReplicaState, i as Settled, l as BetterServer, m as PRIMARY_COOKIE, n as GuardOptions, o as isResult, p as createServer, r as RespondOptions, s as respond, t as AuthKind, u as ContextOptions } from "../respond-Dne1ARSa.js";
7
- import { a as defineResource, i as ResourceRouteOptions, n as ResourceInput, r as ResourceList, t as ResourceHandler } from "../resource-CgZa3YG_.js";
8
- import { a as ProblemResponseOptions, c as problemResponse, i as ProblemOptions, l as toProblem, n as PROBLEM_TYPE_BASE, o as fromProblem, r as ProblemDetails, s as isProblem, t as PROBLEM_CONTENT_TYPE } from "../problem-DlgB0lYl.js";
9
- import { n as RefreshOutcome, r as refreshSession } from "../index-CG69s15v.js";
1
+ import { n as AnyModels, t as AnyFunctions } from "../types-DONv9SHN.js";
2
+ import { p as DbError } from "../result-CqEsbgYs.js";
3
+ import { t as BetterSupabase, y as Db } from "../define-CRS2MRV3.js";
4
+ import { h as RequestContext } from "../plugin-bNhvJwRh.js";
5
+ import { a as checkAal, c as impersonatorOf, i as amrOf, n as AmrEntry, o as ImpersonationOptions, r as aalOf, s as Impersonator, t as Aal } from "../mfa-C7MNQ1Ob.js";
6
+ import { _ as readSession, a as ResolveAuthOptions, b as writeSession, c as clientIp, d as CookieOptions, f as CookieRecord, i as InvalidReason, l as resolveAuth, m as StoredSession, n as AuthResolver, o as ResolvedState, p as CookieWrite, r as AuthState, s as authContext, t as AuthResolution, u as AUTH_CACHE_HEADERS, y as sessionCookieName } from "../resolve-BAqQcwMW.js";
7
+ import { _ as DeleteAccountOptions, a as Settled, c as respond, d as ContextOptions, f as ServerContext, g as ReplicaState, h as PRIMARY_COOKIE, i as RespondOptions, l as settle, m as createServer, n as GuardOptions, o as guard, p as ServerOptions, r as MiddlewareOptions, s as isResult, t as AuthKind, u as BetterServer, v as DeleteAccountResult } from "../respond-DgIbdrt8.js";
8
+ import { a as ResourceRouteOptions, i as ResourcePagination, n as ResourceInput, o as defineResource, r as ResourceList, t as ResourceHandler } from "../resource-BJcaIfxi.js";
9
+ import { a as ProblemResponseOptions, c as problemResponse, i as ProblemOptions, l as toProblem, n as PROBLEM_TYPE_BASE, o as fromProblem, r as ProblemDetails, s as isProblem, t as PROBLEM_CONTENT_TYPE } from "../problem-U8UEKccv.js";
10
+ import { a as SessionDelegation, i as SessionActor, n as toSession, r as ActClaim, t as AuthSession } from "../view-B64o81wp.js";
11
+ import { n as RefreshOutcome, r as refreshSession } from "../refresh-BwYkyNOQ.js";
10
12
  import { SupabaseClient } from "@supabase/supabase-js";
11
13
  import { Middleware } from "@supabase/middleware";
12
14
  import { AuthMode, JWTClaims, UserClaims } from "@supabase/server";
@@ -25,18 +27,41 @@ export declare function contextFromSupabase(ctx: SupabaseAuthContext): RequestCo
25
27
  * `ctx.supabase` (the caller-scoped client from `withSupabase`).
26
28
  *
27
29
  * ```ts
28
- * pipeline([withSupabase({ auth: 'user' }), withBetterSupabase(sb)()], (req, ctx) => ...)
30
+ * pipeline([withSupabase({ auth: 'user' }), withBetterSupabase(betterSupabase)()], (req, ctx) => ...)
29
31
  * ```
30
32
  */
31
- export declare function withBetterSupabase<M extends AnyModels, D, F extends AnyFunctions, E>(sb: BetterSupabase<M, D, F, E>): Middleware<"db", void, SupabaseAuthContext & {
33
+ export declare function withBetterSupabase<M extends AnyModels, D, F extends AnyFunctions, E>(betterSupabase: BetterSupabase<M, D, F, E>): Middleware<"db", void, SupabaseAuthContext & {
32
34
  readonly supabase: SupabaseClient;
33
35
  }, Db<M, F, E, SupabaseClient>>;
34
36
  /**
35
37
  * Entry contributing `ctx.sql`: repositories over `ctx.postgres` from
36
38
  * `withPostgresClient`, which runs each query as the caller with RLS.
37
39
  */
38
- export declare function withBetterPostgres<M extends AnyModels, D, F extends AnyFunctions, E>(sb: BetterSupabase<M, D, F, E>): Middleware<"sql", void, SupabaseAuthContext & {
40
+ export declare function withBetterPostgres<M extends AnyModels, D, F extends AnyFunctions, E>(betterSupabase: BetterSupabase<M, D, F, E>): Middleware<"sql", void, SupabaseAuthContext & {
39
41
  readonly postgres: PostgresApi;
40
42
  }, Db<M, F, E, undefined>>;
41
43
  //#endregion
42
- export { AUTH_CACHE_HEADERS, type Aal, type AmrEntry, type AuthKind, type AuthResolution, type AuthResolver, type AuthState, type BetterServer, type ContextOptions, type CookieOptions, type CookieRecord, type CookieWrite, type DeleteAccountOptions, type DeleteAccountResult, type GuardOptions, type ImpersonationOptions, type Impersonator, type InvalidReason, PRIMARY_COOKIE, PROBLEM_CONTENT_TYPE, PROBLEM_TYPE_BASE, type ProblemDetails, type ProblemOptions, type ProblemResponseOptions, type RefreshOutcome, type ReplicaState, type ResolveAuthOptions, type ResolvedState, type ResourceHandler, type ResourceInput, type ResourceList, type ResourceRouteOptions, type RespondOptions, type ServerContext, type ServerOptions, type Settled, type StoredSession, type SupabaseAuthContext, aalOf, amrOf, authContext, checkAal, clientIp, createServer, defineResource, fromProblem, guard, impersonatorOf, isProblem, isResult, problemResponse, readSession, refreshSession, resolveAuth, respond, sessionCookieName, settle, toProblem, writeSession };
44
+ //#region src/auth/revocation.d.ts
45
+ /** A client that can read `auth.sessions`, such as `createPostgres().admin`. */
46
+ interface SessionLookup {
47
+ queryRaw<T = Record<string, unknown>>(text: string, params?: unknown[]): Promise<T[]>;
48
+ }
49
+ /**
50
+ * `undefined` when the user token's session still exists in `auth.sessions`;
51
+ * otherwise an `unauthorized` error with code `SESSION_REVOKED`. A verified
52
+ * access token stays valid until it expires, even after sign-out; call this
53
+ * before sensitive actions (deleting the account, changing the email) to
54
+ * reject tokens of ended sessions. It costs one query, so nothing calls it
55
+ * by default. Non-user callers pass: `guard` decides about them.
56
+ */
57
+ export declare function checkSession(sql: SessionLookup, auth: {
58
+ readonly kind: "user";
59
+ readonly claims: {
60
+ readonly sub?: unknown;
61
+ readonly session_id?: unknown;
62
+ };
63
+ } | {
64
+ readonly kind: string;
65
+ }): Promise<DbError | undefined>;
66
+ //#endregion
67
+ export { AUTH_CACHE_HEADERS, type Aal, type ActClaim, type AmrEntry, type AuthKind, type AuthResolution, type AuthResolver, type AuthSession, type AuthState, type BetterServer, type ContextOptions, type CookieOptions, type CookieRecord, type CookieWrite, type DeleteAccountOptions, type DeleteAccountResult, type GuardOptions, type ImpersonationOptions, type Impersonator, type InvalidReason, type MiddlewareOptions, PRIMARY_COOKIE, PROBLEM_CONTENT_TYPE, PROBLEM_TYPE_BASE, type ProblemDetails, type ProblemOptions, type ProblemResponseOptions, type RefreshOutcome, type ReplicaState, type ResolveAuthOptions, type ResolvedState, type ResourceHandler, type ResourceInput, type ResourceList, type ResourcePagination, type ResourceRouteOptions, type RespondOptions, type ServerContext, type ServerOptions, type SessionActor, type SessionDelegation, type SessionLookup, type Settled, type StoredSession, type SupabaseAuthContext, aalOf, amrOf, authContext, checkAal, clientIp, createServer, defineResource, fromProblem, guard, impersonatorOf, isProblem, isResult, problemResponse, readSession, refreshSession, resolveAuth, respond, sessionCookieName, settle, toProblem, toSession, writeSession };
@@ -1,8 +1,10 @@
1
- import { a as problemResponse, i as isProblem, n as PROBLEM_TYPE_BASE, o as toProblem, r as fromProblem, t as PROBLEM_CONTENT_TYPE } from "../problem-BTkTtRV9.js";
2
- import { a as settle, i as respond, n as guard, o as createServer, r as isResult, u as PRIMARY_COOKIE } from "../respond-DMcbQwfN.js";
3
- import { a as clientIp, f as sessionCookieName, g as impersonatorOf, i as authContext, m as refreshSession, n as amrOf, o as resolveAuth, p as writeSession, r as checkAal, s as AUTH_CACHE_HEADERS, t as aalOf, u as readSession } from "../mfa-CpLfJSde.js";
4
- import { n as postgresExecutor } from "../executor-DeppvirK.js";
5
- import { t as defineResource } from "../resource-BHEWmQJK.js";
1
+ import { n as dbError } from "../errors-L0xK41y_.js";
2
+ import { a as problemResponse, i as isProblem, n as PROBLEM_TYPE_BASE, o as toProblem, r as fromProblem, t as PROBLEM_CONTENT_TYPE } from "../problem-BihjPR0t.js";
3
+ import { a as guard, c as settle, o as isResult, s as respond, t as createServer, u as PRIMARY_COOKIE } from "../server-BA75B0mT.js";
4
+ import { a as clientIp, c as AUTH_CACHE_HEADERS, d as readSession, h as refreshSession, i as authContext, m as writeSession, n as amrOf, p as sessionCookieName, r as checkAal, s as resolveAuth, t as aalOf, y as impersonatorOf } from "../mfa-byfjruR9.js";
5
+ import { n as postgresExecutor } from "../executor-CVt6dD0B.js";
6
+ import { t as toSession } from "../view-BrJI2LKp.js";
7
+ import { t as defineResource } from "../resource-My_y-Syh.js";
6
8
  import { defineMiddleware } from "@supabase/middleware";
7
9
  //#region src/server/middleware.ts
8
10
  /** Repository context from a `@supabase/server` context. */
@@ -14,8 +16,8 @@ function contextFromSupabase(ctx) {
14
16
  actor: {
15
17
  id: ctx.userClaims.id,
16
18
  kind: "user",
17
- ...ctx.userClaims.role !== void 0 ? { role: ctx.userClaims.role } : {},
18
- ...ctx.userClaims.email !== void 0 ? { email: ctx.userClaims.email } : {}
19
+ ...ctx.userClaims.role === void 0 ? {} : { role: ctx.userClaims.role },
20
+ ...ctx.userClaims.email === void 0 ? {} : { email: ctx.userClaims.email }
19
21
  },
20
22
  claims: ctx.jwtClaims ?? {}
21
23
  };
@@ -29,7 +31,10 @@ function contextFromSupabase(ctx) {
29
31
  };
30
32
  case "publishable":
31
33
  case "none": break;
32
- default: return ctx.authMode;
34
+ default: {
35
+ const unknown = ctx.authMode;
36
+ throw new TypeError(`contextFromSupabase: unknown auth mode "${String(unknown)}"`);
37
+ }
33
38
  }
34
39
  return {
35
40
  actor: {
@@ -45,24 +50,48 @@ function contextFromSupabase(ctx) {
45
50
  * `ctx.supabase` (the caller-scoped client from `withSupabase`).
46
51
  *
47
52
  * ```ts
48
- * pipeline([withSupabase({ auth: 'user' }), withBetterSupabase(sb)()], (req, ctx) => ...)
53
+ * pipeline([withSupabase({ auth: 'user' }), withBetterSupabase(betterSupabase)()], (req, ctx) => ...)
49
54
  * ```
50
55
  */
51
- function withBetterSupabase(sb) {
56
+ function withBetterSupabase(betterSupabase) {
52
57
  return defineMiddleware({
53
58
  key: "db",
54
- run: (_config) => (_req, ctx) => Promise.resolve({ db: sb.connect(ctx.supabase, contextFromSupabase(ctx)) })
59
+ run: (_config) => (_req, ctx) => Promise.resolve({ db: betterSupabase.connect(ctx.supabase, contextFromSupabase(ctx)) })
55
60
  });
56
61
  }
57
62
  /**
58
63
  * Entry contributing `ctx.sql`: repositories over `ctx.postgres` from
59
64
  * `withPostgresClient`, which runs each query as the caller with RLS.
60
65
  */
61
- function withBetterPostgres(sb) {
66
+ function withBetterPostgres(betterSupabase) {
62
67
  return defineMiddleware({
63
68
  key: "sql",
64
- run: (_config) => (_req, ctx) => Promise.resolve({ sql: sb.connect(postgresExecutor(ctx.postgres), contextFromSupabase(ctx)) })
69
+ run: (_config) => (_req, ctx) => Promise.resolve({ sql: betterSupabase.connect(postgresExecutor(ctx.postgres), contextFromSupabase(ctx)) })
65
70
  });
66
71
  }
67
72
  //#endregion
68
- export { AUTH_CACHE_HEADERS, PRIMARY_COOKIE, PROBLEM_CONTENT_TYPE, PROBLEM_TYPE_BASE, aalOf, amrOf, authContext, checkAal, clientIp, contextFromSupabase, createServer, defineResource, fromProblem, guard, impersonatorOf, isProblem, isResult, problemResponse, readSession, refreshSession, resolveAuth, respond, sessionCookieName, settle, toProblem, withBetterPostgres, withBetterSupabase, writeSession };
73
+ //#region src/auth/revocation.ts
74
+ const UUID = /^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/i;
75
+ const ACTIVE = `select exists (
76
+ select 1 from auth.sessions s
77
+ where s.id = $1::uuid and s.user_id = $2::uuid
78
+ and (s.not_after is null or s.not_after > now())
79
+ ) as active`;
80
+ /**
81
+ * `undefined` when the user token's session still exists in `auth.sessions`;
82
+ * otherwise an `unauthorized` error with code `SESSION_REVOKED`. A verified
83
+ * access token stays valid until it expires, even after sign-out; call this
84
+ * before sensitive actions (deleting the account, changing the email) to
85
+ * reject tokens of ended sessions. It costs one query, so nothing calls it
86
+ * by default. Non-user callers pass: `guard` decides about them.
87
+ */
88
+ async function checkSession(sql, auth) {
89
+ if (auth.kind !== "user" || !("claims" in auth)) return void 0;
90
+ const { sub, session_id: sessionId } = auth.claims;
91
+ const revoked = dbError("unauthorized", "This session has ended", { code: "SESSION_REVOKED" });
92
+ if (typeof sessionId !== "string" || typeof sub !== "string" || !UUID.test(sessionId) || !UUID.test(sub)) return revoked;
93
+ const [row] = await sql.queryRaw(ACTIVE, [sessionId, sub]);
94
+ return row?.active === true ? void 0 : revoked;
95
+ }
96
+ //#endregion
97
+ export { AUTH_CACHE_HEADERS, PRIMARY_COOKIE, PROBLEM_CONTENT_TYPE, PROBLEM_TYPE_BASE, aalOf, amrOf, authContext, checkAal, checkSession, clientIp, contextFromSupabase, createServer, defineResource, fromProblem, guard, impersonatorOf, isProblem, isResult, problemResponse, readSession, refreshSession, resolveAuth, respond, sessionCookieName, settle, toProblem, toSession, withBetterPostgres, withBetterSupabase, writeSession };