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.
- package/README.md +37 -33
- package/dist/base64-D2gsioCY.js +42 -0
- package/dist/claims-BAf6c7is.js +48 -0
- package/dist/cli/_format-Cax5EsM9.js +101 -0
- package/dist/cli/bin.js +39 -6
- package/dist/cli/command-CK14fP91.js +502 -0
- package/dist/cli/compare-BmIWVEui.js +9 -0
- package/dist/cli/config-D9R0o1LH.js +1895 -0
- package/dist/cli/config-SSKSTUl2.js +2 -0
- package/dist/cli/db-DOBPt660.js +52 -0
- package/dist/cli/dist-B1MvLv-M.js +129 -0
- package/dist/cli/dist-CFgGknmZ.js +1112 -0
- package/dist/cli/dist-Du7VnEUG.js +621 -0
- package/dist/cli/doctor-BOym3mbL.js +2382 -0
- package/dist/cli/env-BZ0uy8XK.js +108 -0
- package/dist/cli/env-jIFUADLY.js +511 -0
- package/dist/cli/errors-4v4DTtda.js +56 -0
- package/dist/cli/fastest-levenshtein-CFN-lNDv.js +120 -0
- package/dist/cli/gen-Ccn_p90L.js +2008 -0
- package/dist/cli/gen-D5cLCULx.js +2 -0
- package/dist/cli/index.d.ts +295 -28
- package/dist/cli/index.js +184 -3
- package/dist/cli/init-ClnxRYBF.js +550 -0
- package/dist/cli/introspect-DxqfkVIv.js +81 -0
- package/dist/cli/io-k41_z-jT.js +24 -0
- package/dist/cli/json5-ChRycquj.js +787 -0
- package/dist/cli/jsonc-BUniUpOk.js +2 -0
- package/dist/cli/jsonc-D5Fu67jw.js +45 -0
- package/dist/cli/keys-ByKHnvP9.js +83 -0
- package/dist/cli/ohash-D7bG_EOb.js +277 -0
- package/dist/cli/openapi-8WHjxiTJ.js +66 -0
- package/dist/cli/project-B_GeXyHh.js +70 -0
- package/dist/cli/prompts-BNcNfAve.js +1142 -0
- package/dist/cli/prompts-BTYQGunc.js +2 -0
- package/dist/cli/read-sets-CMa29t9a.js +971 -0
- package/dist/cli/rolldown-runtime-BPOCksWG.js +24 -0
- package/dist/cli/run-CP20LKk_.js +347 -0
- package/dist/cli/seed-5J6eu_Xg.js +98 -0
- package/dist/cli/skills-LJJIhLFR.js +137 -0
- package/dist/cli/sql-D4VbqmXi.js +199 -0
- package/dist/cli/style-C0NFdJRL.js +29 -0
- package/dist/cli/toml-DB-MNnFs.js +424 -0
- package/dist/{version-Cqq1m3UY.js → cli/version-5mW_8sY1.js} +1 -1
- package/dist/cli/yaml-CYCbJ6et.js +2252 -0
- package/dist/client/index.d.ts +2 -2
- package/dist/client/index.js +15 -25
- package/dist/{compiler-CZ9nIuqy.d.ts → compiler-DB3aSFOA.d.ts} +2 -2
- package/dist/config/index.d.ts +4 -3
- package/dist/config/index.js +5 -3
- package/dist/config-BpxDfnbg.js +129 -0
- package/dist/{index-DOsjFvMf.d.ts → config-C1CYcm6o.d.ts} +49 -49
- package/dist/{config-ClDXmVtY.js → config-CbvFmGD8.js} +14 -137
- package/dist/{define-BXMYD9AY.js → define-Bh0AqTik.js} +221 -120
- package/dist/{define-e3zI4_4g.d.ts → define-CRS2MRV3.d.ts} +36 -31
- package/dist/edge/index.d.ts +9 -13
- package/dist/edge/index.js +51 -25
- package/dist/{entitlements-Dng-ctuT.d.ts → entitlements-Dm-FHpNH.d.ts} +2 -2
- package/dist/env/index.js +203 -1
- package/dist/{errors-Bl3rkOzo.js → errors-L0xK41y_.js} +1 -1
- package/dist/events/index.d.ts +1 -1
- package/dist/events/index.js +139 -1
- package/dist/{events-DOt3nSO-.d.ts → events-B21UOhvP.d.ts} +4 -4
- package/dist/{executor-CGdNQ27g.d.ts → executor-B5IoUxLE.d.ts} +2 -2
- package/dist/{executor-DeppvirK.js → executor-CVt6dD0B.js} +9 -4
- package/dist/{executor-BYXQ9AGn.d.ts → executor-CZ7ImRiD.d.ts} +2 -2
- package/dist/hono/index.d.ts +17 -24
- package/dist/hono/index.js +11 -11
- package/dist/{index-DuP14VHo.d.ts → index-528Ugmyp.d.ts} +30 -10
- package/dist/{index-Bw1bwtC0.d.ts → index-BAy4tsAP.d.ts} +28 -15
- package/dist/{index-CBDufH1M.d.ts → index-BBdvo-5d.d.ts} +24 -26
- package/dist/{index-DbxFr7XG.d.ts → index-BhHEC04r.d.ts} +9 -4
- package/dist/index-Cf-D2jk1.d.ts +50 -0
- package/dist/{index-Ciu5Xlml.d.ts → index-D5IfUIDh.d.ts} +6 -5
- package/dist/{index-K-3WM2Hp.d.ts → index-DFmOpBGC.d.ts} +13 -13
- package/dist/{index-D4v7sncu.d.ts → index-RlLXd8dL.d.ts} +13 -13
- package/dist/index.d.ts +17 -17
- package/dist/index.js +23 -14
- package/dist/{invalidate-DbxuL2jL.js → invalidate-CgxmRamI.js} +7 -1
- package/dist/jobs/index.d.ts +33 -26
- package/dist/jobs/index.js +44 -22
- package/dist/{json-schema-BpYqkCKf.js → json-schema-DP6V7cbr.js} +8 -3
- package/dist/lint/index.js +1 -1
- package/dist/list/index.d.ts +2 -2
- package/dist/list/index.js +131 -96
- package/dist/{live-DJyZMD6w.d.ts → live-BHakSWWo.d.ts} +26 -16
- package/dist/{live-D8rV1Ldw.js → live-CdJBOc4f.js} +13 -9
- package/dist/lookup-BaP5bI27.js +18 -0
- package/dist/mcp/index.d.ts +34 -27
- package/dist/mcp/index.js +59 -25
- package/dist/{mfa-TVia554c.d.ts → mfa-C7MNQ1Ob.d.ts} +1 -1
- package/dist/{mfa-CpLfJSde.js → mfa-byfjruR9.js} +190 -46
- package/dist/next/image/index.js +6 -3
- package/dist/next/index.d.ts +64 -48
- package/dist/next/index.js +63 -50
- package/dist/openapi/index.d.ts +1 -1
- package/dist/openapi/index.js +61 -38
- package/dist/orpc/index.d.ts +18 -21
- package/dist/orpc/index.js +12 -12
- package/dist/otel/index.d.ts +5 -5
- package/dist/otel/index.js +84 -63
- package/dist/{permdock-sql-CghlHPuH.js → permdock-sql-C4KFzLc9.js} +12 -7
- package/dist/permdock-sql-DImJULY-.d.ts +17 -0
- package/dist/{plugin-C4TR9J0Z.d.ts → plugin-bNhvJwRh.d.ts} +5 -4
- package/dist/plugins/actor/index.d.ts +1 -1
- package/dist/plugins/actor/index.js +1 -1
- package/dist/plugins/rules/index.d.ts +2 -2
- package/dist/plugins/rules/index.js +46 -16
- package/dist/plugins/soft-delete/index.d.ts +3 -3
- package/dist/plugins/soft-delete/index.js +4 -4
- package/dist/plugins/tenant/index.d.ts +3 -3
- package/dist/plugins/tenant/index.js +10 -4
- package/dist/plugins/timestamps/index.d.ts +1 -1
- package/dist/plugins/timestamps/index.js +2 -2
- package/dist/plugins/validation/index.d.ts +2 -2
- package/dist/plugins/validation/index.js +3 -3
- package/dist/pool-DFwEQwmN.d.ts +78 -0
- package/dist/postgres/index.d.ts +10 -5
- package/dist/postgres/index.js +37 -16
- package/dist/{postgrest-cAEQ_IQN.d.ts → postgrest-Bc-0Xw62.d.ts} +1 -1
- package/dist/{problem-BTkTtRV9.js → problem-BihjPR0t.js} +11 -5
- package/dist/{problem-DlgB0lYl.d.ts → problem-U8UEKccv.d.ts} +6 -4
- package/dist/query/index.d.ts +2 -2
- package/dist/query/index.js +2 -2
- package/dist/{query-ChvDbsDE.js → query-BMMSWbI7.js} +19 -19
- package/dist/react/index.d.ts +7 -7
- package/dist/react/index.js +2 -2
- package/dist/react/server.d.ts +6 -6
- package/dist/react/server.js +3 -3
- package/dist/react/session.d.ts +21 -2
- package/dist/react/session.js +19 -1
- package/dist/{react-C83BdBGt.js → react-CQHMaESR.js} +59 -55
- package/dist/{read-set-4lI3W_gZ.js → read-set-FWK8qQ58.js} +51 -16
- package/dist/realtime/index.d.ts +4 -3
- package/dist/realtime/index.js +19 -17
- package/dist/{index-CG69s15v.d.ts → refresh-BwYkyNOQ.d.ts} +7 -3
- package/dist/{resolve-CjHILk2w.d.ts → resolve-BAqQcwMW.d.ts} +17 -11
- package/dist/{resource-CgZa3YG_.d.ts → resource-BJcaIfxi.d.ts} +17 -8
- package/dist/{resource-BHEWmQJK.js → resource-My_y-Syh.js} +43 -21
- package/dist/{respond-Dne1ARSa.d.ts → respond-DgIbdrt8.d.ts} +39 -14
- package/dist/{result-DWXatkd6.js → result-Bj6yt33D.js} +2 -2
- package/dist/{result-CTkCZ6JA.d.ts → result-CqEsbgYs.d.ts} +16 -11
- package/dist/server/index.d.ts +38 -13
- package/dist/server/index.js +43 -14
- package/dist/{respond-DMcbQwfN.js → server-BA75B0mT.js} +151 -96
- package/dist/{shared-_6-uPL7E.js → shared-DnoCdMDr.js} +4 -3
- package/dist/{simplify-bwJpLnaS.js → simplify-Cqvfr9dj.js} +76 -39
- package/dist/sql/index.d.ts +139 -0
- package/dist/sql/index.js +1983 -0
- package/dist/{sql-DTjA1LPj.js → sql-B34HU2DI.js} +74 -17
- package/dist/ssr/index.d.ts +4 -4
- package/dist/ssr/index.js +2 -2
- package/dist/{standard-FUi3Z3-7.js → standard-BRyBGTtp.js} +2 -2
- package/dist/{standard-CyhRzctb.d.ts → standard-BsaCYQJc.d.ts} +1 -1
- package/dist/{stats-C5W-rBfR.js → stats-C_YxA2r1.js} +40 -14
- package/dist/storage/index.d.ts +4 -3
- package/dist/storage/index.js +548 -1
- package/dist/{tables-rZxRxNPW.js → tables-Cb-3_VWc.js} +19 -5
- package/dist/temporal-BwshQk0W.js +27 -0
- package/dist/temporal-required-CBNHT6ni.js +19 -0
- package/dist/testing/index.d.ts +25 -24
- package/dist/testing/index.js +165 -66
- package/dist/{types-C83v5SQz.d.ts → types-DONv9SHN.d.ts} +14 -11
- package/dist/version-Bmf7_FzM.js +4 -0
- package/dist/{view-D1s0wa0T.d.ts → view-B64o81wp.d.ts} +36 -6
- package/dist/{view-aOYizTeE.js → view-BrJI2LKp.js} +11 -2
- package/dist/webhooks/index.d.ts +19 -17
- package/dist/webhooks/index.js +1 -1
- package/dist/{webhooks-DMipjhSP.js → webhooks-Bh_Jf_-l.js} +45 -24
- package/package.json +50 -22
- package/schemas/config-v1.json +31 -1
- package/schemas/doctor-report-v1.json +17 -1
- package/schemas/snapshot-v2.json +35 -0
- package/skills/better-supabase/SKILL.md +77 -18
- package/skills/better-supabase/references/plugins.md +21 -22
- package/skills/better-supabase/references/troubleshooting.md +38 -18
- package/skills/better-supabase-api/SKILL.md +66 -18
- package/skills/better-supabase-api/references/adapters.md +64 -41
- package/skills/better-supabase-auth/SKILL.md +146 -0
- package/skills/better-supabase-auth/references/permdock.md +55 -0
- package/skills/better-supabase-testing/SKILL.md +68 -11
- package/dist/casing-da0uRTqt.js +0 -14
- package/dist/claims-CoTobNC-.js +0 -25
- package/dist/cli-DrSgDOQC.js +0 -6646
- package/dist/env-BEToab0I.js +0 -204
- package/dist/events-BuzTgn2D.js +0 -135
- package/dist/pool-R2m_DkXi.d.ts +0 -37
- package/dist/seed-CzecODcJ.js +0 -101
- package/dist/session-C3LxnQ0e.d.ts +0 -22
- package/dist/session-CqEwzVup.js +0 -20
- package/dist/storage-DuGn38fr.js +0 -527
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { n as dbError } from "./errors-
|
|
2
|
-
import { i as ok, n as err } from "./result-
|
|
3
|
-
import { t as validate } from "./standard-
|
|
4
|
-
import {
|
|
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
|
|
30
|
-
if (
|
|
31
|
-
const
|
|
32
|
-
return Number.isSafeInteger(
|
|
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
|
|
38
|
+
const issues = [];
|
|
35
39
|
const size = read("size", 50);
|
|
36
|
-
if (
|
|
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
|
-
|
|
44
|
-
|
|
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(
|
|
66
|
-
const meta =
|
|
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-
|
|
2
|
-
import { p as DbError, t as AsyncResult } from "./result-
|
|
3
|
-
import { I as StatsRecorder, P as DbStats, t as BetterSupabase, y as Db } from "./define-
|
|
4
|
-
import { h as RequestContext } from "./plugin-
|
|
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 {
|
|
7
|
-
import { o as ImpersonationOptions, t as Aal } from "./mfa-
|
|
8
|
-
import { a as ResolveAuthOptions, r as AuthState, t as AuthResolution } from "./resolve-
|
|
9
|
-
import { n as Bucket } from "./index-
|
|
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
|
|
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?:
|
|
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; `
|
|
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>(
|
|
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 {
|
|
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-
|
|
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 `
|
|
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
|
-
/**
|
|
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 `
|
|
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 `
|
|
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
|
|
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 `
|
|
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):
|
|
186
|
-
declare function toBetterResult<T>(result: Result<T>, api: BetterResultApi<T, DbError>):
|
|
187
|
-
declare function toBetterResult<T, E>(result: AsyncResult<T>, api: BetterResultApi<T, E>, mapError: (error: DbError) => E): Promise<
|
|
188
|
-
declare function toBetterResult<T>(result: AsyncResult<T>, api: BetterResultApi<T, unknown>): Promise<
|
|
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:
|
|
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,
|
|
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 };
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import { n as AnyModels, t as AnyFunctions } from "../types-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { _ as
|
|
7
|
-
import { a as
|
|
8
|
-
import { a as
|
|
9
|
-
import { n as
|
|
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(
|
|
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>(
|
|
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>(
|
|
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
|
-
|
|
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 };
|
package/dist/server/index.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as
|
|
3
|
-
import { a as
|
|
4
|
-
import { n as
|
|
5
|
-
import {
|
|
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
|
|
18
|
-
...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:
|
|
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(
|
|
53
|
+
* pipeline([withSupabase({ auth: 'user' }), withBetterSupabase(betterSupabase)()], (req, ctx) => ...)
|
|
49
54
|
* ```
|
|
50
55
|
*/
|
|
51
|
-
function withBetterSupabase(
|
|
56
|
+
function withBetterSupabase(betterSupabase) {
|
|
52
57
|
return defineMiddleware({
|
|
53
58
|
key: "db",
|
|
54
|
-
run: (_config) => (_req, ctx) => Promise.resolve({ db:
|
|
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(
|
|
66
|
+
function withBetterPostgres(betterSupabase) {
|
|
62
67
|
return defineMiddleware({
|
|
63
68
|
key: "sql",
|
|
64
|
-
run: (_config) => (_req, ctx) => Promise.resolve({ sql:
|
|
69
|
+
run: (_config) => (_req, ctx) => Promise.resolve({ sql: betterSupabase.connect(postgresExecutor(ctx.postgres), contextFromSupabase(ctx)) })
|
|
65
70
|
});
|
|
66
71
|
}
|
|
67
72
|
//#endregion
|
|
68
|
-
|
|
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 };
|