better-supabase 0.2.0 → 0.3.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 (139) hide show
  1. package/README.md +34 -31
  2. package/dist/base64-CQeB1eSf.js +42 -0
  3. package/dist/client/index.d.ts +1 -1
  4. package/dist/client/index.js +4 -14
  5. package/dist/{compiler-CZ9nIuqy.d.ts → compiler-2zqGzxVZ.d.ts} +2 -2
  6. package/dist/config/index.d.ts +4 -3
  7. package/dist/config/index.js +5 -3
  8. package/dist/config-Be4GwsqI.js +129 -0
  9. package/dist/{index-DOsjFvMf.d.ts → config-C1CYcm6o.d.ts} +49 -49
  10. package/dist/{config-ClDXmVtY.js → config-DOsGYSiT.js} +14 -137
  11. package/dist/{define-BXMYD9AY.js → define-DF341GDj.js} +71 -51
  12. package/dist/{define-e3zI4_4g.d.ts → define-DUbydmJa.d.ts} +10 -9
  13. package/dist/edge/index.d.ts +4 -4
  14. package/dist/edge/index.js +4 -4
  15. package/dist/{entitlements-Dng-ctuT.d.ts → entitlements-DvJXoI02.d.ts} +1 -1
  16. package/dist/env/index.js +203 -1
  17. package/dist/events/index.d.ts +1 -1
  18. package/dist/events/index.js +139 -1
  19. package/dist/{events-DOt3nSO-.d.ts → events-Do8jXh4D.d.ts} +3 -3
  20. package/dist/{executor-BYXQ9AGn.d.ts → executor-B26lgbHD.d.ts} +2 -2
  21. package/dist/{executor-DeppvirK.js → executor-C57jx2pn.js} +7 -2
  22. package/dist/{executor-CGdNQ27g.d.ts → executor-DynmIWhq.d.ts} +2 -2
  23. package/dist/hono/index.d.ts +5 -5
  24. package/dist/hono/index.js +4 -4
  25. package/dist/{index-CBDufH1M.d.ts → index-BNsABq7P.d.ts} +8 -8
  26. package/dist/{index-Bw1bwtC0.d.ts → index-CADlNHK-.d.ts} +27 -14
  27. package/dist/{index-DuP14VHo.d.ts → index-CTTMS6_1.d.ts} +19 -8
  28. package/dist/index-Cf-D2jk1.d.ts +50 -0
  29. package/dist/{index-K-3WM2Hp.d.ts → index-CriFFJ_p.d.ts} +4 -4
  30. package/dist/{index-Ciu5Xlml.d.ts → index-GV77NpRP.d.ts} +5 -4
  31. package/dist/{index-D4v7sncu.d.ts → index-UJ-LUxtI.d.ts} +3 -3
  32. package/dist/{index-CG69s15v.d.ts → index-kpgopLNv.d.ts} +4 -3
  33. package/dist/{index-DbxFr7XG.d.ts → index-qriRM9cZ.d.ts} +7 -2
  34. package/dist/index.d.ts +12 -12
  35. package/dist/index.js +16 -7
  36. package/dist/jobs/index.d.ts +25 -24
  37. package/dist/jobs/index.js +16 -10
  38. package/dist/{json-schema-BpYqkCKf.js → json-schema--aOXAGfU.js} +7 -2
  39. package/dist/lint/index.js +1 -1
  40. package/dist/list/index.d.ts +2 -2
  41. package/dist/list/index.js +128 -93
  42. package/dist/{live-DJyZMD6w.d.ts → live-QE3UPbGm.d.ts} +16 -6
  43. package/dist/mcp/index.d.ts +24 -17
  44. package/dist/mcp/index.js +41 -12
  45. package/dist/{mfa-CpLfJSde.js → mfa-BxoR1RkN.js} +74 -19
  46. package/dist/{mfa-TVia554c.d.ts → mfa-x3V3vGh-.d.ts} +1 -1
  47. package/dist/next/index.d.ts +39 -26
  48. package/dist/next/index.js +28 -23
  49. package/dist/openapi/index.d.ts +1 -1
  50. package/dist/openapi/index.js +57 -34
  51. package/dist/orpc/index.d.ts +6 -6
  52. package/dist/orpc/index.js +3 -3
  53. package/dist/otel/index.d.ts +2 -2
  54. package/dist/otel/index.js +4 -2
  55. package/dist/{permdock-sql-CghlHPuH.js → permdock-sql-Bta_G0v-.js} +11 -6
  56. package/dist/permdock-sql-DImJULY-.d.ts +17 -0
  57. package/dist/{plugin-C4TR9J0Z.d.ts → plugin-DVRB8qNE.d.ts} +5 -4
  58. package/dist/plugins/actor/index.d.ts +1 -1
  59. package/dist/plugins/rules/index.d.ts +2 -2
  60. package/dist/plugins/rules/index.js +4 -4
  61. package/dist/plugins/soft-delete/index.d.ts +3 -3
  62. package/dist/plugins/soft-delete/index.js +2 -2
  63. package/dist/plugins/tenant/index.d.ts +2 -2
  64. package/dist/plugins/timestamps/index.d.ts +1 -1
  65. package/dist/plugins/timestamps/index.js +1 -1
  66. package/dist/plugins/validation/index.d.ts +2 -2
  67. package/dist/pool-B9qsLyFR.d.ts +71 -0
  68. package/dist/postgres/index.d.ts +10 -5
  69. package/dist/postgres/index.js +36 -16
  70. package/dist/{postgrest-cAEQ_IQN.d.ts → postgrest-DmBlevh-.d.ts} +1 -1
  71. package/dist/{problem-BTkTtRV9.js → problem-CGt1ADix.js} +10 -4
  72. package/dist/{problem-DlgB0lYl.d.ts → problem-Z2RTQjZD.d.ts} +6 -4
  73. package/dist/query/index.d.ts +2 -2
  74. package/dist/query/index.js +1 -1
  75. package/dist/{query-ChvDbsDE.js → query-BdKLTPlj.js} +2 -2
  76. package/dist/react/index.d.ts +7 -7
  77. package/dist/react/index.js +2 -2
  78. package/dist/react/server.d.ts +3 -3
  79. package/dist/react/server.js +1 -1
  80. package/dist/react/session.d.ts +21 -2
  81. package/dist/react/session.js +19 -1
  82. package/dist/{react-C83BdBGt.js → react-DNBYNazu.js} +20 -16
  83. package/dist/{read-set-4lI3W_gZ.js → read-set-D0qBcboM.js} +3 -3
  84. package/dist/realtime/index.d.ts +4 -3
  85. package/dist/realtime/index.js +7 -6
  86. package/dist/{resolve-CjHILk2w.d.ts → resolve-BRciX2jK.d.ts} +6 -5
  87. package/dist/{resource-CgZa3YG_.d.ts → resource-CwVgiI5q.d.ts} +16 -7
  88. package/dist/{resource-BHEWmQJK.js → resource-D30rp0GN.js} +38 -16
  89. package/dist/{respond-DMcbQwfN.js → respond-C44EZAJo.js} +35 -19
  90. package/dist/{respond-Dne1ARSa.d.ts → respond-DAkPIdTH.d.ts} +15 -9
  91. package/dist/{result-CTkCZ6JA.d.ts → result-c2OYgCV2.d.ts} +13 -8
  92. package/dist/server/index.d.ts +35 -10
  93. package/dist/server/index.js +38 -9
  94. package/dist/{simplify-bwJpLnaS.js → simplify-LakqK1vH.js} +10 -16
  95. package/dist/sql/index.d.ts +139 -0
  96. package/dist/sql/index.js +1983 -0
  97. package/dist/{sql-DTjA1LPj.js → sql-BIgk12ew.js} +72 -16
  98. package/dist/ssr/index.d.ts +4 -4
  99. package/dist/ssr/index.js +2 -2
  100. package/dist/{standard-CyhRzctb.d.ts → standard-eudBiRk1.d.ts} +1 -1
  101. package/dist/{stats-C5W-rBfR.js → stats-D78UQ8Yu.js} +8 -7
  102. package/dist/storage/index.d.ts +4 -3
  103. package/dist/storage/index.js +530 -1
  104. package/dist/{tables-rZxRxNPW.js → tables-Dhha3BXM.js} +5 -5
  105. package/dist/temporal-BwshQk0W.js +27 -0
  106. package/dist/temporal-required-CMxeSVPo.js +19 -0
  107. package/dist/testing/index.d.ts +13 -11
  108. package/dist/testing/index.js +128 -29
  109. package/dist/{types-C83v5SQz.d.ts → types-DONv9SHN.d.ts} +14 -11
  110. package/dist/{version-Cqq1m3UY.js → version-BfpG2gks.js} +1 -1
  111. package/dist/{view-D1s0wa0T.d.ts → view-3Po_PVlr.d.ts} +34 -4
  112. package/dist/{view-aOYizTeE.js → view-wZ-9qIUz.js} +11 -2
  113. package/dist/webhooks/index.d.ts +18 -16
  114. package/dist/webhooks/index.js +1 -1
  115. package/dist/{webhooks-DMipjhSP.js → webhooks-CAIFQSTM.js} +11 -9
  116. package/package.json +24 -28
  117. package/schemas/config-v1.json +31 -1
  118. package/schemas/doctor-report-v1.json +17 -1
  119. package/schemas/snapshot-v2.json +35 -0
  120. package/skills/better-supabase/SKILL.md +23 -11
  121. package/skills/better-supabase/references/plugins.md +21 -18
  122. package/skills/better-supabase/references/troubleshooting.md +15 -15
  123. package/skills/better-supabase-api/SKILL.md +7 -7
  124. package/skills/better-supabase-api/references/adapters.md +30 -25
  125. package/skills/better-supabase-testing/SKILL.md +11 -8
  126. package/bin/better-supabase.js +0 -4
  127. package/dist/casing-da0uRTqt.js +0 -14
  128. package/dist/cli/bin.d.ts +0 -1
  129. package/dist/cli/bin.js +0 -15
  130. package/dist/cli/index.d.ts +0 -226
  131. package/dist/cli/index.js +0 -3
  132. package/dist/cli-DrSgDOQC.js +0 -6646
  133. package/dist/env-BEToab0I.js +0 -204
  134. package/dist/events-BuzTgn2D.js +0 -135
  135. package/dist/pool-R2m_DkXi.d.ts +0 -37
  136. package/dist/seed-CzecODcJ.js +0 -101
  137. package/dist/session-C3LxnQ0e.d.ts +0 -22
  138. package/dist/session-CqEwzVup.js +0 -20
  139. package/dist/storage-DuGn38fr.js +0 -527
@@ -1,9 +1,9 @@
1
1
  import { i as tenantClaimPaths, n as claimAt, r as claimsOf } from "./claims-CoTobNC-.js";
2
2
  import { t as invalidateTables } from "./invalidate-DbxuL2jL.js";
3
3
  import { n as liveQuery, t as liveCount } from "./live-D8rV1Ldw.js";
4
- import { n as useSession } from "./session-CqEwzVup.js";
4
+ import { useSession } from "./react/session.js";
5
5
  import { createContext, createElement, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
6
- //#region src/react/index.ts
6
+ //#region src/react/hooks.ts
7
7
  const BrowserContext = createContext(null);
8
8
  const LOADING = {
9
9
  status: "loading",
@@ -91,9 +91,9 @@ function useBroadcast(topic, values, handlers, options) {
91
91
  const userId = auth.user?.id ?? null;
92
92
  if (options?.invalidate && !queryClient) throw new Error("better-supabase: useBroadcast({ invalidate }) needs <BetterSupabaseProvider queryClient={...}>");
93
93
  useEffect(() => {
94
- if (!name || auth.status === "loading") return void 0;
94
+ if (!name || auth.status === "loading") return;
95
95
  const matched = topic.match(name);
96
- if (!matched) return void 0;
96
+ if (!matched) return;
97
97
  const forward = (payload, message) => {
98
98
  const current = latest.current;
99
99
  const table = current.handlers;
@@ -153,7 +153,7 @@ function useLiveQuery(spec, options = {}) {
153
153
  const userId = auth.user?.id ?? null;
154
154
  const debounceMs = options.debounceMs;
155
155
  useEffect(() => {
156
- if (!key || !queryClient || auth.status === "loading") return void 0;
156
+ if (!key || !queryClient || auth.status === "loading") return;
157
157
  const live = liveQuery(browser.sb, browser.supabase, JSON.parse(key), {
158
158
  onChange: (tables) => void invalidateTables(queryClient, tables),
159
159
  onStatus: setStatus,
@@ -202,19 +202,23 @@ function useLiveCount(source, options = {}) {
202
202
  const debounceMs = options.debounceMs;
203
203
  const hasInitial = initial !== void 0;
204
204
  useEffect(() => {
205
- if (!key || auth.status === "loading") return void 0;
205
+ if (!key || auth.status === "loading") return;
206
206
  const live = liveCount(browser.sb, browser.supabase, browser.db, JSON.parse(key), {
207
207
  immediate: !hasInitial,
208
- onCount: (count) => setState({
209
- key,
210
- count,
211
- error: void 0
212
- }),
213
- onError: (error) => setState((previous) => ({
214
- key,
215
- count: previous.key === key ? previous.count : void 0,
216
- error
217
- })),
208
+ onCount: (count) => {
209
+ setState({
210
+ key,
211
+ count,
212
+ error: void 0
213
+ });
214
+ },
215
+ onError: (error) => {
216
+ setState((previous) => ({
217
+ key,
218
+ count: previous.key === key ? previous.count : void 0,
219
+ error
220
+ }));
221
+ },
218
222
  onStatus: setStatus,
219
223
  ...tenant === void 0 ? {} : { tenant },
220
224
  ...debounceMs === void 0 ? {} : { debounceMs }
@@ -1,5 +1,5 @@
1
- import { r as IrBuilder, u as tableMeta } from "./simplify-bwJpLnaS.js";
2
- import { n as touchedTables } from "./tables-rZxRxNPW.js";
1
+ import { r as IrBuilder, u as tableMeta } from "./simplify-LakqK1vH.js";
2
+ import { n as touchedTables } from "./tables-Dhha3BXM.js";
3
3
  //#region src/core/spec.ts
4
4
  const READ_METHODS = [
5
5
  "findMany",
@@ -87,7 +87,7 @@ const TYPE = /^(?:[a-z_][a-z0-9_]*\.)?[a-z_][a-z0-9_]*(?:\[\])?$/;
87
87
  /** `jsonb_build_object` takes at most 100 arguments. */
88
88
  const MAX_ENTRIES = 50;
89
89
  /** Placeholders are `NUL bs:<name> NUL`: no real parameter value holds a NUL. */
90
- const NUL = String.fromCharCode(0);
90
+ const NUL = "\0";
91
91
  const SENTINEL = new RegExp(`${NUL}bs:([a-z_][a-z0-9_]*)${NUL}`, "gi");
92
92
  const EXACT = new RegExp(`^${NUL}bs:([a-z_][a-z0-9_]*)${NUL}$`, "i");
93
93
  function sentinel(name) {
@@ -1,4 +1,5 @@
1
- import { x as PermdockTopicPolicy } from "../types-C83v5SQz.js";
1
+ import { x as PermdockTopicPolicy } from "../types-DONv9SHN.js";
2
+ import { t as PermdockCatalog } from "../permdock-sql-DImJULY-.js";
2
3
  import { n as TemplateValues, t as TemplateParams } from "../template-mbvlysOo.js";
3
- import { C as defineTopic, S as TriggerOptions, _ as TopicEvent, a as LiveSource, b as TopicOptions, c as liveQuery, d as RealtimeClient, f as RowChange, g as Topic, h as SubscriptionStatus, i as LiveQueryOptions, l as liveTopic, m as Subscription, n as LiveCountOptions, o as LiveSubscription, p as SubscribeOptions, r as LiveCountSeed, s as liveCount, t as CountRunner, u as EventSchemas, v as TopicHandlers, w as rowChange, x as TopicPayload, y as TopicMessage } from "../live-DJyZMD6w.js";
4
- export { type CountRunner, EventSchemas, type LiveCountOptions, type LiveCountSeed, type LiveQueryOptions, type LiveSource, type LiveSubscription, type PermdockTopicPolicy, RealtimeClient, RowChange, SubscribeOptions, Subscription, SubscriptionStatus, type TemplateParams, type TemplateValues, Topic, TopicEvent, TopicHandlers, TopicMessage, TopicOptions, TopicPayload, TriggerOptions, defineTopic, liveCount, liveQuery, liveTopic, rowChange };
4
+ import { C as defineTopic, S as TriggerOptions, _ as TopicEvent, a as LiveSource, b as TopicOptions, c as liveQuery, d as RealtimeClient, f as RowChange, g as Topic, h as SubscriptionStatus, i as LiveQueryOptions, l as liveTopic, m as Subscription, n as LiveCountOptions, o as LiveSubscription, p as SubscribeOptions, r as LiveCountSeed, s as liveCount, t as CountRunner, u as EventSchemas, v as TopicHandlers, w as rowChange, x as TopicPayload, y as TopicMessage } from "../live-QE3UPbGm.js";
5
+ export { type CountRunner, type EventSchemas, type LiveCountOptions, type LiveCountSeed, type LiveQueryOptions, type LiveSource, type LiveSubscription, type PermdockCatalog, type PermdockTopicPolicy, type RealtimeClient, type RowChange, type SubscribeOptions, type Subscription, type SubscriptionStatus, type TemplateParams, type TemplateValues, type Topic, type TopicEvent, type TopicHandlers, type TopicMessage, type TopicOptions, type TopicPayload, type TriggerOptions, defineTopic, liveCount, liveQuery, liveTopic, rowChange };
@@ -3,9 +3,9 @@ import { i as ok, n as err, t as AsyncResult } from "../result-DWXatkd6.js";
3
3
  import { i as tenantClaimPaths } from "../claims-CoTobNC-.js";
4
4
  import { n as liveQuery, r as liveTopic, t as liveCount } from "../live-D8rV1Ldw.js";
5
5
  import { s as toApp } from "../shared-_6-uPL7E.js";
6
- import { a as sqlString, i as sqlIdent, n as parseTemplate, r as slug, t as permdockCheck } from "../permdock-sql-CghlHPuH.js";
6
+ import { a as sqlIdent, i as slug, o as sqlString, r as parseTemplate, t as permdockCheck } from "../permdock-sql-Bta_G0v-.js";
7
7
  import { REALTIME_SUBSCRIBE_STATES } from "@supabase/supabase-js";
8
- //#region src/realtime/index.ts
8
+ //#region src/realtime/topic.ts
9
9
  const VALUE = /^[\w.@+=-]+$/;
10
10
  function validateValue(_name, value) {
11
11
  return VALUE.test(value) ? void 0 : "contains characters topics do not allow";
@@ -55,7 +55,7 @@ function sendError(status, message) {
55
55
  */
56
56
  function defineTopic(template, options = {}) {
57
57
  const parsed = parseTemplate(template, ":", validateValue);
58
- const literal = template.replace(/\{[^}]+\}/g, " ");
58
+ const literal = template.replaceAll(/\{[^}]+\}/g, " ");
59
59
  const name = slug(options.name ?? literal) || "topic";
60
60
  const isPrivate = options.private ?? true;
61
61
  const schemas = options.events ?? {};
@@ -71,10 +71,10 @@ function defineTopic(template, options = {}) {
71
71
  if (!permdock) return void 0;
72
72
  const where = `defineTopic(${template})`;
73
73
  const id = permdock.scope === "global" ? void 0 : `split_part((select realtime.topic()), ':', ${String(permdock.segment ?? segment(tenantParam ?? "orgId", "PermDock"))})`;
74
- const receive = permdockCheck(where, permdock, permdock.receive, id);
74
+ const receive = permdockCheck(where, permdock, permdock.receive, id, options.catalog);
75
75
  return {
76
76
  receive,
77
- send: permdock.send === void 0 ? receive : permdockCheck(where, permdock, permdock.send, id)
77
+ send: permdock.send === void 0 ? receive : permdockCheck(where, permdock, permdock.send, id, options.catalog)
78
78
  };
79
79
  })();
80
80
  if (!permdock && tenantParam && (options.tenant || parsed.params.includes(tenantParam))) {
@@ -131,7 +131,7 @@ function defineTopic(template, options = {}) {
131
131
  if (!db) throw new TypeError(`defineTopic: no column for {${param}} on "${table}"`);
132
132
  return `rec.${sqlIdent(db)}::text`;
133
133
  });
134
- const schema = trigger.functionSchema ?? "public";
134
+ const schema = trigger.functionSchema ?? "better_supabase";
135
135
  const fn = `${sqlIdent(schema)}.${sqlIdent(`bs_broadcast_${name}_${slug(meta.name)}`)}`;
136
136
  const triggerName = sqlIdent(`bs_broadcast_${name}`);
137
137
  const target = `${sqlIdent(meta.schema)}.${sqlIdent(meta.name)}`;
@@ -142,6 +142,7 @@ function defineTopic(template, options = {}) {
142
142
  ]).join(" or ");
143
143
  return [
144
144
  `-- better-supabase: broadcast ${meta.name} changes to ${template}`,
145
+ `create schema if not exists ${sqlIdent(schema)};`,
145
146
  `create or replace function ${fn}()`,
146
147
  "returns trigger",
147
148
  "language plpgsql",
@@ -1,7 +1,7 @@
1
- import { p as DbError } from "./result-CTkCZ6JA.js";
2
- import { f as Logger, l as RefreshEvent } from "./events-DOt3nSO-.js";
3
- import { h as RequestContext } from "./plugin-C4TR9J0Z.js";
4
- import { t as StandardSchemaV1 } from "./standard-CyhRzctb.js";
1
+ import { p as DbError } from "./result-c2OYgCV2.js";
2
+ import { f as Logger, l as RefreshEvent } from "./events-Do8jXh4D.js";
3
+ import { h as RequestContext } from "./plugin-DVRB8qNE.js";
4
+ import { t as StandardSchemaV1 } from "./standard-eudBiRk1.js";
5
5
  import { t as BetterSupabaseEnv } from "./index-Dy6kuF0P.js";
6
6
  import { CookieOptions } from "@supabase/ssr";
7
7
  import { JWTClaims, SupabaseEnv, UserClaims } from "@supabase/server";
@@ -76,7 +76,7 @@ type AuthState<C = unknown, P = unknown> = {
76
76
  readonly reason: InvalidReason;
77
77
  readonly error: DbError;
78
78
  };
79
- type InvalidReason = "token" | "claims";
79
+ type InvalidReason = "token" | "claims" | "actor";
80
80
  /**
81
81
  * What an `AuthResolver` returns. `reason` may be left out of an `invalid`
82
82
  * state; it then counts as `token`.
@@ -140,6 +140,7 @@ interface ResolveAuthOptions {
140
140
  /** Called after every refresh attempt (metrics, logging). */
141
141
  readonly onRefresh?: (event: RefreshEvent) => void;
142
142
  readonly fetch?: typeof fetch;
143
+ /** Epoch milliseconds, the unit JWT `exp` and `iat` math needs. */
143
144
  readonly now?: () => number;
144
145
  }
145
146
  interface AuthResolution<C = unknown, P = unknown> {
@@ -1,13 +1,14 @@
1
- import { N as TableKey, P as TableMeta, R as Update, _ as Insert, n as AnyModels, t as AnyFunctions } from "./types-C83v5SQz.js";
2
- import { b as ValidationIssue, o as Result } from "./result-CTkCZ6JA.js";
3
- import { t as BetterSupabase, xt as SelectArg } from "./define-e3zI4_4g.js";
4
- import { r as RespondOptions } from "./respond-Dne1ARSa.js";
5
- import { i as ResourceOperation } from "./index-DbxFr7XG.js";
1
+ import { N as TableKey, P as TableMeta, R as Update, g as Insert, n as AnyModels, t as AnyFunctions } from "./types-DONv9SHN.js";
2
+ import { b as ValidationIssue, o as Result } from "./result-c2OYgCV2.js";
3
+ import { t as BetterSupabase, xt as SelectArg } from "./define-DUbydmJa.js";
4
+ import { r as RespondOptions } from "./respond-DAkPIdTH.js";
5
+ import { i as ResourceOperation } from "./index-qriRM9cZ.js";
6
6
  import { StandardSchemaV1 } from "@standard-schema/spec";
7
7
  //#region src/server/resource.d.ts
8
8
  /** What a resource needs from `defineListQuery`. */
9
9
  interface ResourceList {
10
10
  readonly table: string;
11
+ readonly pagination?: ResourcePagination;
11
12
  readonly openapi: readonly unknown[];
12
13
  readonly jsonSchema: Readonly<Record<string, unknown>>;
13
14
  parse(input: never): {
@@ -31,9 +32,16 @@ interface ResourceRouteOptions<M extends AnyModels, T extends TableKey<M>> {
31
32
  readonly create?: StandardSchemaV1<unknown, Insert<M, T>>;
32
33
  readonly update?: StandardSchemaV1<unknown, Update<M, T>>;
33
34
  };
34
- /** Largest page for the default `page`/`size` list. Defaults to 200. */
35
+ /**
36
+ * Paging of the default list: `offset` (`page` and `size`) or `cursor`
37
+ * (`after` and `size`, keyset). A `list` query brings its own. Defaults
38
+ * to `offset`.
39
+ */
40
+ readonly pagination?: ResourcePagination;
41
+ /** Largest page for the default list. Defaults to 200. */
35
42
  readonly maxPageSize?: number;
36
43
  }
44
+ type ResourcePagination = "offset" | "cursor";
37
45
  interface ResourceInput {
38
46
  /** Primary key value; strings are converted for integer keys. */
39
47
  readonly id?: unknown;
@@ -49,6 +57,7 @@ interface ResourceHandler {
49
57
  /** Name of the key parameter, or `undefined` for tables without a single-column key. */
50
58
  readonly keyParam: string | undefined;
51
59
  readonly list: ResourceList | undefined;
60
+ readonly pagination: ResourcePagination;
52
61
  readonly maxPageSize: number;
53
62
  /** Runs one operation as whoever `db` is bound to. Resolves to a `Result`. */
54
63
  execute(db: object, operation: ResourceOperation, input?: ResourceInput): Promise<Result<unknown>>;
@@ -62,4 +71,4 @@ interface ResourceHandler {
62
71
  */
63
72
  declare function defineResource<M extends AnyModels, D, F extends AnyFunctions, E, T extends TableKey<M>>(sb: BetterSupabase<M, D, F, E>, table: T, options?: ResourceRouteOptions<M, T>): ResourceHandler;
64
73
  //#endregion
65
- export { defineResource as a, ResourceRouteOptions as i, ResourceInput as n, ResourceList as r, ResourceHandler as t };
74
+ export { ResourceRouteOptions as a, ResourcePagination as i, ResourceInput as n, defineResource as o, ResourceList as r, ResourceHandler as t };
@@ -1,7 +1,7 @@
1
1
  import { n as dbError } from "./errors-Bl3rkOzo.js";
2
2
  import { i as ok, n as err } from "./result-DWXatkd6.js";
3
3
  import { t as validate } from "./standard-FUi3Z3-7.js";
4
- import { i as respond } from "./respond-DMcbQwfN.js";
4
+ import { i as respond } from "./respond-C44EZAJo.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
  }
@@ -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,10 +1,11 @@
1
1
  import { n as dbError, o as isDbError, r as dbErrorOf } from "./errors-Bl3rkOzo.js";
2
2
  import { i as ok, n as err, o as toDbError, t as AsyncResult } from "./result-DWXatkd6.js";
3
- import { a as postgrestExecutor, n as StatsRecorder } from "./stats-C5W-rBfR.js";
4
- import { a as problemResponse } from "./problem-BTkTtRV9.js";
5
- import { i as loadEnv } from "./env-BEToab0I.js";
6
- import { h as actClaim, i as authContext, o as resolveAuth, r as checkAal } from "./mfa-CpLfJSde.js";
7
- import { n as postgresExecutor } from "./executor-DeppvirK.js";
3
+ import { a as postgrestExecutor, n as StatsRecorder } from "./stats-D78UQ8Yu.js";
4
+ import { a as problemResponse } from "./problem-CGt1ADix.js";
5
+ import { loadEnv } from "./env/index.js";
6
+ import { _ as actClaim, g as delegationOf, h as actorOf, i as authContext, o as resolveAuth, r as checkAal } from "./mfa-BxoR1RkN.js";
7
+ import { n as postgresExecutor } from "./executor-C57jx2pn.js";
8
+ import { parseCookieHeader, serializeCookieHeader } from "@supabase/ssr";
8
9
  import { createClient } from "@supabase/supabase-js";
9
10
  //#region src/server/replicas.ts
10
11
  /** Cookie holding the epoch ms until which reads stay on the primary. */
@@ -29,19 +30,18 @@ function replicaState(pinnedUntil = 0, now = Date.now()) {
29
30
  /** `bs-primary-until` from a `cookie` header, or 0. */
30
31
  function pinnedUntil(cookieHeader) {
31
32
  if (!cookieHeader) return 0;
32
- for (const part of cookieHeader.split(";")) {
33
- const [name, value] = part.trim().split("=", 2);
34
- if (name === "bs-primary-until") {
35
- const until = Number(value);
36
- return Number.isFinite(until) ? until : 0;
37
- }
38
- }
39
- return 0;
33
+ const value = parseCookieHeader(cookieHeader).find((cookie) => cookie.name === PRIMARY_COOKIE)?.value;
34
+ const until = Number(value);
35
+ return value !== void 0 && Number.isFinite(until) ? until : 0;
40
36
  }
41
37
  /** A `Set-Cookie` value keeping the next requests on the primary for `pinMs`. */
42
38
  function primaryCookie(pinMs, now = Date.now()) {
43
- const seconds = Math.max(1, Math.ceil(pinMs / 1e3));
44
- return `${PRIMARY_COOKIE}=${String(now + pinMs)}; Path=/; Max-Age=${String(seconds)}; HttpOnly; SameSite=Lax`;
39
+ return serializeCookieHeader(PRIMARY_COOKIE, String(now + pinMs), {
40
+ path: "/",
41
+ maxAge: Math.max(1, Math.ceil(pinMs / 1e3)),
42
+ httpOnly: true,
43
+ sameSite: "lax"
44
+ });
45
45
  }
46
46
  /**
47
47
  * Reads go to `replica` until the context is pinned; writes, and every read
@@ -248,7 +248,7 @@ function createServer(sb, options = {}) {
248
248
  return replica;
249
249
  },
250
250
  get sql() {
251
- if (!options.postgres || !sqlClaims) return void 0;
251
+ if (!options.postgres || !sqlClaims) return;
252
252
  sql ??= sqlFor(sqlClaims, context, recorder);
253
253
  return sql;
254
254
  },
@@ -264,7 +264,7 @@ function createServer(sb, options = {}) {
264
264
  ...claims ? { claims } : {},
265
265
  ...userMetadata ? { userMetadata } : {},
266
266
  env: env(),
267
- ...resolveOptions.refresh !== void 0 ? { refresh: resolveOptions.refresh } : {},
267
+ ...resolveOptions.refresh === void 0 ? {} : { refresh: resolveOptions.refresh },
268
268
  onRefresh: (event) => {
269
269
  options.auth?.onRefresh?.(event);
270
270
  sb.events.emit("refresh", event);
@@ -329,10 +329,26 @@ function createServer(sb, options = {}) {
329
329
  }
330
330
  //#endregion
331
331
  //#region src/server/respond.ts
332
+ /** The scopes a delegated user token lacks; empty for the user's own session. */
333
+ function missingScopes(auth, required) {
334
+ if (required.length === 0) return [];
335
+ const outcome = actorOf(auth.claims);
336
+ if (!outcome.ok || !outcome.actor) return [];
337
+ const granted = new Set(delegationOf(auth.claims)?.scopes);
338
+ return required.filter((scope) => !granted.has(scope));
339
+ }
332
340
  /** `undefined` when `auth` may pass; otherwise the 401/403 error to send. */
333
- function guard(auth, allow = ["user"], aal = "aal1") {
341
+ function guard(auth, allow = ["user"], aal = "aal1", scopes = []) {
334
342
  if (auth.kind === "invalid") return auth.error;
335
- if (allow.includes(auth.kind)) return checkAal(auth, aal);
343
+ if (allow.includes(auth.kind)) {
344
+ const denied = checkAal(auth, aal);
345
+ if (denied || auth.kind !== "user") return denied;
346
+ const missing = missingScopes(auth, scopes);
347
+ return missing.length > 0 ? dbError("forbidden", `The token lacks the scope ${missing.join(" ")}`, {
348
+ code: "INSUFFICIENT_SCOPE",
349
+ scopes
350
+ }) : void 0;
351
+ }
336
352
  return auth.kind === "anon" ? dbError("unauthorized", "Sign in to continue", { code: "MISSING_CREDENTIALS" }) : dbError("forbidden", `A ${auth.kind} caller is not allowed here`);
337
353
  }
338
354
  function isResult(value) {
@@ -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-c2OYgCV2.js";
3
+ import { I as StatsRecorder, P as DbStats, t as BetterSupabase, y as Db } from "./define-DUbydmJa.js";
4
+ import { h as RequestContext } from "./plugin-DVRB8qNE.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, r as Postgres } from "./pool-B9qsLyFR.js";
7
+ import { o as ImpersonationOptions, t as Aal } from "./mfa-x3V3vGh-.js";
8
+ import { a as ResolveAuthOptions, r as AuthState, t as AuthResolution } from "./resolve-BRciX2jK.js";
9
+ import { n as Bucket } from "./index-CTTMS6_1.js";
10
10
  import { SupabaseClient } from "@supabase/supabase-js";
11
11
  //#region src/server/delete-account.d.ts
12
12
  interface DeleteAccountOptions {
@@ -135,9 +135,15 @@ interface GuardOptions {
135
135
  * `required: 'aal2'` until the user verifies a second factor.
136
136
  */
137
137
  readonly aal?: Aal;
138
+ /**
139
+ * OAuth scopes a delegated token (an OAuth client or an `act` chain) needs.
140
+ * A missing one answers 403 with `error="insufficient_scope"`. The user's
141
+ * own session is not limited by scopes.
142
+ */
143
+ readonly scopes?: readonly string[];
138
144
  }
139
145
  /** `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;
146
+ declare function guard(auth: AuthState, allow?: GuardOptions["allow"], aal?: Aal, scopes?: readonly string[]): DbError | undefined;
141
147
  declare function isResult(value: unknown): value is {
142
148
  ok: boolean;
143
149
  data: unknown;
@@ -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;
@@ -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
  } | {
@@ -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-c2OYgCV2.js";
3
+ import { t as BetterSupabase, y as Db } from "../define-DUbydmJa.js";
4
+ import { h as RequestContext } from "../plugin-DVRB8qNE.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-x3V3vGh-.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-BRciX2jK.js";
7
+ 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-DAkPIdTH.js";
8
+ import { a as ResourceRouteOptions, i as ResourcePagination, n as ResourceInput, o as defineResource, r as ResourceList, t as ResourceHandler } from "../resource-CwVgiI5q.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-Z2RTQjZD.js";
10
+ import { a as SessionDelegation, i as SessionActor, n as toSession, r as ActClaim, t as AuthSession } from "../view-3Po_PVlr.js";
11
+ import { n as RefreshOutcome, r as refreshSession } from "../index-kpgopLNv.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";
@@ -39,4 +41,27 @@ export declare function withBetterPostgres<M extends AnyModels, D, F extends Any
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, 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 };