better-supabase 0.4.0 → 0.5.1
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 +135 -16
- package/dist/actor-DaJjqD5R.d.ts +43 -0
- package/dist/channel-FQW-CnGR.d.ts +70 -0
- package/dist/cli/bin.js +1 -1
- package/dist/cli/codemod-DqV7612m.js +388 -0
- package/dist/cli/{config-D9R0o1LH.js → config-CPVpXP5I.js} +78 -8
- package/dist/cli/{config-SSKSTUl2.js → config-dtoekM0v.js} +1 -1
- package/dist/cli/{read-sets-CMa29t9a.js → diff-SjkO5rNr.js} +1 -220
- package/dist/cli/{dist-CFgGknmZ.js → dist-DBPdlPYK.js} +4 -4
- package/dist/cli/{dist-B1MvLv-M.js → dist-DreZ24Sz.js} +1 -1
- package/dist/cli/{dist-Du7VnEUG.js → dist-xn4wlboc.js} +112 -1
- package/dist/cli/{doctor-BOym3mbL.js → doctor-C_A-KEAz.js} +533 -50
- package/dist/cli/{env-BZ0uy8XK.js → env-DmKv_G4A.js} +1 -1
- package/dist/cli/gen-CIdSQZad.js +2 -0
- package/dist/cli/{gen-Ccn_p90L.js → gen-CjElD1Vw.js} +321 -88
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.js +4 -4
- package/dist/cli/{init-ClnxRYBF.js → init-DMa6M7hV.js} +2 -2
- package/dist/cli/{introspect-DxqfkVIv.js → introspect-BKlaIu_M.js} +2 -2
- package/dist/cli/{openapi-8WHjxiTJ.js → openapi-Cp5Fyta-.js} +1 -1
- package/dist/cli/read-sets-VQcPgxU9.js +436 -0
- package/dist/cli/{run-CP20LKk_.js → run-Bo_NLT5n.js} +16 -12
- package/dist/cli/{seed-5J6eu_Xg.js → seed-CUlqWh-8.js} +1 -1
- package/dist/cli/sql-CVx-1O8G.js +373 -0
- package/dist/cli/{version-5mW_8sY1.js → version-BCtlgDQx.js} +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.js +3 -10
- package/dist/clone-BfgmLU90.js +21 -0
- package/dist/{compiler-DB3aSFOA.d.ts → compiler-BXH_aZ7N.d.ts} +2 -2
- package/dist/config/index.d.ts +4 -4
- package/dist/config/index.js +4 -4
- package/dist/{config-C1CYcm6o.d.ts → config-Bv7gvfzC.d.ts} +185 -11
- package/dist/{config-CbvFmGD8.js → config-DreERlKo.js} +1 -1
- package/dist/{define-CRS2MRV3.d.ts → define-Bp_BZa5h.d.ts} +11 -7
- package/dist/{define-Bh0AqTik.js → define-cNKzqwL_.js} +202 -16
- package/dist/edge/index.d.ts +16 -5
- package/dist/edge/index.js +10 -7
- package/dist/{entitlements-Dm-FHpNH.d.ts → entitlements-BiJZ4t49.d.ts} +1 -1
- package/dist/env/index.d.ts +2 -2
- package/dist/env/index.js +34 -1
- package/dist/{errors-L0xK41y_.js → errors-DtwXa6b8.js} +1 -0
- package/dist/events/index.d.ts +3 -2
- package/dist/events/index.js +65 -12
- package/dist/events-aIO7vsIk.d.ts +230 -0
- package/dist/{result-CqEsbgYs.d.ts → executor-BunPOO-k.d.ts} +200 -1
- package/dist/{executor-CZ7ImRiD.d.ts → executor-Cghdstwu.d.ts} +1 -2
- package/dist/{executor-CVt6dD0B.js → executor-XycESQPH.js} +3 -3
- package/dist/hono/index.d.ts +17 -6
- package/dist/hono/index.js +40 -5
- package/dist/impersonation-BgSHAYLf.js +133 -0
- package/dist/{resolve-BAqQcwMW.d.ts → impersonation-BmePsuxz.d.ts} +36 -6
- package/dist/{index-BhHEC04r.d.ts → index-C7f8cOBM.d.ts} +2 -2
- package/dist/{index-Dy6kuF0P.d.ts → index-CLg87OBW.d.ts} +6 -1
- package/dist/{index-Cf-D2jk1.d.ts → index-CWMDdEr4.d.ts} +2 -2
- package/dist/{index-D5IfUIDh.d.ts → index-DOESKG27.d.ts} +33 -8
- package/dist/{index-DFmOpBGC.d.ts → index-DgILJRXj.d.ts} +35 -9
- package/dist/{index-RlLXd8dL.d.ts → index-DmXSxbLi.d.ts} +4 -4
- package/dist/{index-BBdvo-5d.d.ts → index-Dp2VDwog.d.ts} +49 -6
- package/dist/{index-528Ugmyp.d.ts → index-SaTsEfGP.d.ts} +76 -8
- package/dist/{index-BAy4tsAP.d.ts → index-fag8VJZ2.d.ts} +3 -4
- package/dist/index.d.ts +30 -13
- package/dist/index.js +10 -9
- package/dist/jobs/index.d.ts +147 -101
- package/dist/jobs/index.js +744 -237
- package/dist/{json-schema-DP6V7cbr.js → json-schema-m1fiwKgN.js} +22 -1
- package/dist/kit-events-CTFDfSwb.js +60 -0
- package/dist/kit-transport-B82k1djG.d.ts +33 -0
- package/dist/kit-transport-DJlHQUBU.js +55 -0
- package/dist/{config-BpxDfnbg.js → kits-CGLLrNPd.js} +37 -9
- package/dist/list/index.d.ts +1 -1
- package/dist/{live-BHakSWWo.d.ts → live-D9W2M5aO.d.ts} +6 -5
- package/dist/mcp/index.d.ts +25 -8
- package/dist/mcp/index.js +23 -14
- package/dist/{mfa-C7MNQ1Ob.d.ts → mfa-Cu96oJdw.d.ts} +2 -16
- package/dist/next/index.d.ts +31 -10
- package/dist/next/index.js +136 -27
- package/dist/notifications/index.d.ts +162 -0
- package/dist/notifications/index.js +264 -0
- package/dist/openapi/index.d.ts +1 -1
- package/dist/openapi/index.js +2 -2
- package/dist/orgs/index.d.ts +132 -0
- package/dist/orgs/index.js +245 -0
- package/dist/orpc/index.d.ts +28 -8
- package/dist/orpc/index.js +16 -3
- package/dist/otel/index.d.ts +21 -2
- package/dist/otel/index.js +50 -9
- package/dist/permdock-sql-C2Inc6Xc.d.ts +29 -0
- package/dist/permdock-sql-DgOfeixi.js +51 -0
- package/dist/plugin-DwARMuQp.js +59 -0
- package/dist/{plugin-bNhvJwRh.d.ts → plugin-o144f322.d.ts} +17 -5
- package/dist/plugins/actor/index.d.ts +5 -2
- package/dist/plugins/actor/index.js +22 -8
- package/dist/plugins/rules/index.d.ts +2 -2
- package/dist/plugins/rules/index.js +15 -10
- package/dist/plugins/soft-delete/index.d.ts +3 -3
- package/dist/plugins/soft-delete/index.js +14 -5
- package/dist/plugins/tenant/index.d.ts +2 -2
- package/dist/plugins/tenant/index.js +38 -20
- package/dist/plugins/timestamps/index.d.ts +1 -1
- package/dist/plugins/timestamps/index.js +4 -3
- package/dist/plugins/validation/index.d.ts +2 -2
- package/dist/plugins/validation/index.js +26 -6
- package/dist/{pool-DFwEQwmN.d.ts → pool-C9voM4Kw.d.ts} +17 -6
- package/dist/postgres/index.d.ts +5 -5
- package/dist/postgres/index.js +20 -11
- package/dist/{postgrest-Bc-0Xw62.d.ts → postgrest-CruYKAvV.d.ts} +1 -1
- package/dist/{problem-BihjPR0t.js → problem-BW1KhzSG.js} +2 -1
- package/dist/{problem-U8UEKccv.d.ts → problem-Blxe8S31.d.ts} +1 -1
- package/dist/query/index.d.ts +2 -2
- package/dist/query/index.js +3 -3
- package/dist/{query-BMMSWbI7.js → query-CCbo44lG.js} +2 -2
- package/dist/queue-BYUCjr59.d.ts +252 -0
- package/dist/react/index.d.ts +8 -7
- package/dist/react/index.js +4 -3
- package/dist/react/server.d.ts +14 -3
- package/dist/react/server.js +10 -2
- package/dist/react/session.d.ts +7 -1
- package/dist/react/session.js +9 -1
- package/dist/{react-CQHMaESR.js → react-C_s7kiNz.js} +103 -11
- package/dist/{read-set-FWK8qQ58.js → read-set-DQFt1N_Y.js} +22 -1
- package/dist/realtime/index.d.ts +3 -3
- package/dist/realtime/index.js +5 -4
- package/dist/{refresh-BwYkyNOQ.d.ts → refresh-CFPX0Qft.d.ts} +1 -1
- package/dist/{resource-BJcaIfxi.d.ts → resource-DNRFP7KR.d.ts} +5 -5
- package/dist/{resource-My_y-Syh.js → resource-mqfJW4YF.js} +22 -7
- package/dist/respond-BR1fJWOB.d.ts +377 -0
- package/dist/{result-Bj6yt33D.js → result-BKiliPY7.js} +1 -1
- package/dist/server/index.d.ts +15 -12
- package/dist/server/index.js +11 -17
- package/dist/{server-BA75B0mT.js → server-B1mZ7CgQ.js} +259 -37
- package/dist/{shared-DnoCdMDr.js → shared-D1dRUrAg.js} +16 -2
- package/dist/signers-Cc6r98SW.d.ts +162 -0
- package/dist/{simplify-Cqvfr9dj.js → simplify-_0oUKqCd.js} +4 -115
- package/dist/sql/index.d.ts +283 -11
- package/dist/sql/index.js +8705 -775
- package/dist/{sql-B34HU2DI.js → sql-Coh6n4cC.js} +9 -2
- package/dist/ssr/index.d.ts +4 -4
- package/dist/ssr/index.js +1 -2
- package/dist/{standard-BRyBGTtp.js → standard-D7r6dMUu.js} +6 -3
- package/dist/{standard-BsaCYQJc.d.ts → standard-J4YgMOLm.d.ts} +1 -1
- package/dist/{stats-C_YxA2r1.js → stats-Bqob3WqT.js} +4 -4
- package/dist/storage/index.d.ts +4 -4
- package/dist/storage/index.js +155 -26
- package/dist/support-CEPwlw2G.d.ts +89 -0
- package/dist/support-view-B8SlToQX.d.ts +17 -0
- package/dist/support-view-g4YLBeqX.js +18 -0
- package/dist/support-wHnK6zp-.js +293 -0
- package/dist/{permdock-sql-C4KFzLc9.js → template-TxrGI5jR.js} +2 -31
- package/dist/{temporal-BwshQk0W.js → temporal-CVlIV2DZ.js} +17 -4
- package/dist/{temporal-required-CBNHT6ni.js → temporal-required-CAt4Dc9Z.js} +2 -2
- package/dist/testing/index.d.ts +132 -10
- package/dist/testing/index.js +476 -8
- package/dist/{types-DONv9SHN.d.ts → types-Dnf_wRDz.d.ts} +26 -3
- package/dist/user-change-CHFEUro1.js +49 -0
- package/dist/{webhooks-Bh_Jf_-l.js → verify-Ce49ETPz.js} +5 -5
- package/dist/{version-Bmf7_FzM.js → version-DOYTYwHP.js} +1 -1
- package/dist/{mfa-byfjruR9.js → view-Bn6HNKUe.js} +97 -98
- package/dist/{view-B64o81wp.d.ts → view-CbgObAeb.d.ts} +22 -31
- package/dist/webhooks/index.d.ts +135 -4
- package/dist/webhooks/index.js +588 -2
- package/dist/wire-D2dT86vi.js +35 -0
- package/package.json +27 -19
- package/schemas/config-v1.json +131 -1
- package/schemas/doctor-report-v1.json +11 -0
- package/skills/better-supabase/SKILL.md +9 -6
- package/skills/better-supabase/references/plugins.md +6 -3
- package/skills/better-supabase/references/troubleshooting.md +1 -0
- package/skills/better-supabase-api/SKILL.md +9 -2
- package/skills/better-supabase-api/references/adapters.md +11 -8
- package/skills/better-supabase-auth/SKILL.md +18 -7
- package/skills/better-supabase-auth/references/permdock.md +78 -11
- package/dist/cli/gen-D5cLCULx.js +0 -2
- package/dist/cli/sql-D4VbqmXi.js +0 -199
- package/dist/events-B21UOhvP.d.ts +0 -84
- package/dist/executor-B5IoUxLE.d.ts +0 -195
- package/dist/invalidate-CgxmRamI.js +0 -24
- package/dist/permdock-sql-DImJULY-.d.ts +0 -17
- package/dist/plugin-BqR6wKMB.js +0 -23
- package/dist/respond-DgIbdrt8.d.ts +0 -194
- package/dist/view-BrJI2LKp.js +0 -45
|
@@ -1,87 +1,9 @@
|
|
|
1
|
-
import { n as dbError } from "./errors-
|
|
1
|
+
import { n as dbError } from "./errors-DtwXa6b8.js";
|
|
2
2
|
import { t as consoleLogger } from "./logger-glM28NVN.js";
|
|
3
3
|
import { n as decodeJwtPayload } from "./base64-D2gsioCY.js";
|
|
4
|
+
import { a as delegationOf, i as actorOf, n as impersonatorOf, r as userContext } from "./impersonation-BgSHAYLf.js";
|
|
4
5
|
import { DEFAULT_COOKIE_OPTIONS, createChunks, isChunkLike, parseCookieHeader, serializeCookieHeader, stringFromBase64URL, stringToBase64URL } from "@supabase/ssr";
|
|
5
6
|
import { extractCredentials, verifyCredentials } from "@supabase/server/core";
|
|
6
|
-
//#region src/auth/impersonation.ts
|
|
7
|
-
/** The `act` claim for an impersonated session. */
|
|
8
|
-
function actClaim(options) {
|
|
9
|
-
return {
|
|
10
|
-
sub: options.actor,
|
|
11
|
-
reason: options.reason
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
/** The impersonator in `claims.act`, or `undefined` for a normal session. */
|
|
15
|
-
function impersonatorOf(claims) {
|
|
16
|
-
const act = claims["act"];
|
|
17
|
-
if (typeof act !== "object" || act === null) return void 0;
|
|
18
|
-
const { sub, reason } = act;
|
|
19
|
-
if (typeof sub !== "string" || sub === "") return void 0;
|
|
20
|
-
return typeof reason === "string" ? {
|
|
21
|
-
id: sub,
|
|
22
|
-
reason
|
|
23
|
-
} : { id: sub };
|
|
24
|
-
}
|
|
25
|
-
//#endregion
|
|
26
|
-
//#region src/auth/actor.ts
|
|
27
|
-
function isRecord(value) {
|
|
28
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
29
|
-
}
|
|
30
|
-
function copyAct(level) {
|
|
31
|
-
const entries = Object.entries(level).map(([key, value]) => [key, key === "act" && isRecord(value) ? copyAct(value) : value]);
|
|
32
|
-
return Object.fromEntries(entries);
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Reads only `act` and `client_id`, the way PermDock's `actorOf` does. An
|
|
36
|
-
* `act` that is not a chain of objects each with a non-empty `sub` is
|
|
37
|
-
* `{ ok: false }`: the session must not pass as the user alone.
|
|
38
|
-
*/
|
|
39
|
-
function actorOf(claims) {
|
|
40
|
-
const outer = claims["act"];
|
|
41
|
-
if (outer !== void 0) {
|
|
42
|
-
let level = outer;
|
|
43
|
-
while (level !== void 0) {
|
|
44
|
-
if (!isRecord(level)) return {
|
|
45
|
-
ok: false,
|
|
46
|
-
reason: "invalid-chain"
|
|
47
|
-
};
|
|
48
|
-
const sub = level["sub"];
|
|
49
|
-
if (typeof sub !== "string" || sub === "") return {
|
|
50
|
-
ok: false,
|
|
51
|
-
reason: "invalid-chain"
|
|
52
|
-
};
|
|
53
|
-
level = level["act"];
|
|
54
|
-
}
|
|
55
|
-
if (!isRecord(outer) || typeof outer["sub"] !== "string") return {
|
|
56
|
-
ok: false,
|
|
57
|
-
reason: "invalid-chain"
|
|
58
|
-
};
|
|
59
|
-
return {
|
|
60
|
-
ok: true,
|
|
61
|
-
actor: {
|
|
62
|
-
id: outer["sub"],
|
|
63
|
-
kind: "oauth-client",
|
|
64
|
-
chain: copyAct(outer)
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
const client = claims["client_id"];
|
|
69
|
-
if (typeof client === "string" && client !== "") return {
|
|
70
|
-
ok: true,
|
|
71
|
-
actor: {
|
|
72
|
-
id: client,
|
|
73
|
-
kind: "oauth-client"
|
|
74
|
-
}
|
|
75
|
-
};
|
|
76
|
-
return { ok: true };
|
|
77
|
-
}
|
|
78
|
-
/** The OAuth `scope` claim (a space-separated string or a list); `undefined` when empty. */
|
|
79
|
-
function delegationOf(claims) {
|
|
80
|
-
const scope = claims["scope"];
|
|
81
|
-
const scopes = typeof scope === "string" ? scope.split(/\s+/u).filter(Boolean) : Array.isArray(scope) ? scope.filter((item) => typeof item === "string") : [];
|
|
82
|
-
return scopes.length > 0 ? { scopes } : void 0;
|
|
83
|
-
}
|
|
84
|
-
//#endregion
|
|
85
7
|
//#region src/auth/refresh.ts
|
|
86
8
|
/**
|
|
87
9
|
* How long a finished refresh is reused for requests still carrying the old
|
|
@@ -284,7 +206,7 @@ function serverEnv(options) {
|
|
|
284
206
|
url: env.url,
|
|
285
207
|
publishableKeys: { default: env.publishableKey },
|
|
286
208
|
secretKeys: env.secretKeys ?? (env.secretKey ? { default: env.secretKey } : {}),
|
|
287
|
-
jwks: options.jwks ?? env.jwksUrl
|
|
209
|
+
jwks: options.jwks ?? env.jwks ?? env.jwksUrl
|
|
288
210
|
};
|
|
289
211
|
}
|
|
290
212
|
const MEMO_SIZE = 256;
|
|
@@ -295,7 +217,7 @@ let memoByJwks = /* @__PURE__ */ new WeakMap();
|
|
|
295
217
|
* and island resolves the same token again; this skips the signature check.
|
|
296
218
|
*/
|
|
297
219
|
function memoFor(options) {
|
|
298
|
-
const jwks = options.jwks;
|
|
220
|
+
const jwks = options.jwks ?? options.env.jwks;
|
|
299
221
|
if (jwks && typeof jwks === "object" && !(jwks instanceof URL)) {
|
|
300
222
|
let memo = memoByJwks.get(jwks);
|
|
301
223
|
if (!memo) memoByJwks.set(jwks, memo = /* @__PURE__ */ new Map());
|
|
@@ -311,6 +233,42 @@ function memoFor(options) {
|
|
|
311
233
|
if (!memo) memoByUrl.set(key, memo = /* @__PURE__ */ new Map());
|
|
312
234
|
return memo;
|
|
313
235
|
}
|
|
236
|
+
function sameJson(a, b) {
|
|
237
|
+
if (a === b) return true;
|
|
238
|
+
if (typeof a !== "object" || typeof b !== "object" || !a || !b) return false;
|
|
239
|
+
if (Array.isArray(a) !== Array.isArray(b)) return false;
|
|
240
|
+
const left = Object.entries(a);
|
|
241
|
+
const right = new Map(Object.entries(b));
|
|
242
|
+
return left.length === right.size && left.every(([key, value]) => right.has(key) && sameJson(value, right.get(key)));
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Records a token that `@supabase/server` verified for this request, so the
|
|
246
|
+
* next `resolveAuth` with these options doesn't verify it again. Only when
|
|
247
|
+
* `claims` is the token's own payload, it hasn't expired, and its `iss` and
|
|
248
|
+
* `aud` pass the checks these options would apply; otherwise returns false
|
|
249
|
+
* and the token is verified as usual.
|
|
250
|
+
*/
|
|
251
|
+
function rememberVerified(options, verified) {
|
|
252
|
+
const { token, claims, user } = verified;
|
|
253
|
+
const now = Math.floor((options.now ?? Date.now)() / 1e3);
|
|
254
|
+
const expiresAt = typeof claims.exp === "number" ? claims.exp : null;
|
|
255
|
+
if (expiresAt === null || expiresAt <= now) return false;
|
|
256
|
+
if (!sameJson(decodeJwtPayload(token), claims)) return false;
|
|
257
|
+
const issuers = [options.issuer ?? `${options.env.url}/auth/v1`].flat();
|
|
258
|
+
if (typeof claims.iss !== "string" || !issuers.includes(claims.iss)) return false;
|
|
259
|
+
const audiences = [options.audience ?? "authenticated"].flat();
|
|
260
|
+
const aud = claims.aud;
|
|
261
|
+
const given = Array.isArray(aud) ? aud : [aud];
|
|
262
|
+
if (!audiences.some((audience) => given.includes(audience))) return false;
|
|
263
|
+
remember(memoFor(options), token, {
|
|
264
|
+
kind: "user",
|
|
265
|
+
token,
|
|
266
|
+
claims,
|
|
267
|
+
user,
|
|
268
|
+
expiresAt
|
|
269
|
+
}, expiresAt);
|
|
270
|
+
return true;
|
|
271
|
+
}
|
|
314
272
|
function remembered(memo, token, now) {
|
|
315
273
|
const hit = memo.get(token);
|
|
316
274
|
if (!hit) return void 0;
|
|
@@ -385,7 +343,7 @@ async function checkClaims(state, options) {
|
|
|
385
343
|
if (!actorOf(state.claims).ok) return {
|
|
386
344
|
kind: "invalid",
|
|
387
345
|
reason: "actor",
|
|
388
|
-
error: dbError("unauthorized", "The token's act claim is not a chain of actors with a sub", { code: "ACTOR_INVALID" })
|
|
346
|
+
error: dbError("unauthorized", "The token's act claim is not a chain of actors with a sub, or has a kind other than support or impersonation", { code: "ACTOR_INVALID" })
|
|
389
347
|
};
|
|
390
348
|
if (!options.claims) return state;
|
|
391
349
|
let outcome = options.claims["~standard"].validate(state.claims);
|
|
@@ -444,7 +402,7 @@ function base64url(text) {
|
|
|
444
402
|
* fetch it as before.
|
|
445
403
|
*/
|
|
446
404
|
function prefetchJwks(options) {
|
|
447
|
-
if (options.jwks !== void 0) return Promise.resolve();
|
|
405
|
+
if (options.jwks !== void 0 || options.env.jwks !== void 0) return Promise.resolve();
|
|
448
406
|
return verifyCredentials({
|
|
449
407
|
token: PREFETCH_TOKEN,
|
|
450
408
|
apikey: null
|
|
@@ -546,6 +504,10 @@ async function resolveAuth(request, options) {
|
|
|
546
504
|
token: null,
|
|
547
505
|
apikey: credentials.apikey
|
|
548
506
|
}, options.secret === true ? ["secret"] : options.secret.map((name) => `secret:${name}`), options, "bearer"), cookies);
|
|
507
|
+
if (options.cookies === false) return resolution({
|
|
508
|
+
kind: "anon",
|
|
509
|
+
reason: "none"
|
|
510
|
+
}, cookies);
|
|
549
511
|
const name = options.cookie?.name ?? sessionCookieName(options.env.url);
|
|
550
512
|
const session = readSession(cookies(), name);
|
|
551
513
|
if (!session) {
|
|
@@ -611,19 +573,7 @@ async function resolveAuth(request, options) {
|
|
|
611
573
|
/** The repository context (`actor`, `claims`) for an auth state. */
|
|
612
574
|
function authContext(auth) {
|
|
613
575
|
switch (auth.kind) {
|
|
614
|
-
case "user":
|
|
615
|
-
const impersonator = impersonatorOf(auth.claims);
|
|
616
|
-
return {
|
|
617
|
-
actor: {
|
|
618
|
-
id: auth.user.id,
|
|
619
|
-
kind: "user",
|
|
620
|
-
...auth.user.role === void 0 ? {} : { role: auth.user.role },
|
|
621
|
-
...auth.user.email === void 0 ? {} : { email: auth.user.email },
|
|
622
|
-
...impersonator ? { impersonator: impersonator.id } : {}
|
|
623
|
-
},
|
|
624
|
-
claims: auth.claims
|
|
625
|
-
};
|
|
626
|
-
}
|
|
576
|
+
case "user": return userContext(auth.user, auth.claims);
|
|
627
577
|
case "service": return {
|
|
628
578
|
actor: {
|
|
629
579
|
id: `service:${auth.keyName}`,
|
|
@@ -682,4 +632,53 @@ function checkAal(auth, required) {
|
|
|
682
632
|
});
|
|
683
633
|
}
|
|
684
634
|
//#endregion
|
|
685
|
-
|
|
635
|
+
//#region src/auth/view.ts
|
|
636
|
+
/** Whether the token belongs to an anonymous user (`signInAnonymously()`). */
|
|
637
|
+
function isAnonymousUser(claims) {
|
|
638
|
+
return "is_anonymous" in claims && claims.is_anonymous === true;
|
|
639
|
+
}
|
|
640
|
+
/** Drops the token from an `AuthState`, leaving only serializable fields. */
|
|
641
|
+
function toSession(auth) {
|
|
642
|
+
switch (auth.kind) {
|
|
643
|
+
case "user": {
|
|
644
|
+
const impersonator = impersonatorOf(auth.claims);
|
|
645
|
+
const outcome = actorOf(auth.claims);
|
|
646
|
+
const actor = outcome.ok ? outcome.actor : void 0;
|
|
647
|
+
const client = actor?.kind === "oauth-client" ? actor : void 0;
|
|
648
|
+
const scopes = client ? delegationOf(auth.claims)?.scopes : void 0;
|
|
649
|
+
const delegation = client && (scopes || client.chain) ? {
|
|
650
|
+
scopes: scopes ?? [],
|
|
651
|
+
...client.chain ? { chain: client.chain } : {}
|
|
652
|
+
} : void 0;
|
|
653
|
+
return {
|
|
654
|
+
kind: "user",
|
|
655
|
+
user: auth.user,
|
|
656
|
+
claims: auth.claims,
|
|
657
|
+
expiresAt: auth.expiresAt,
|
|
658
|
+
...auth.profile === void 0 ? {} : { profile: auth.profile },
|
|
659
|
+
aal: aalOf(auth.claims),
|
|
660
|
+
anonymous: isAnonymousUser(auth.claims),
|
|
661
|
+
amr: amrOf(auth.claims),
|
|
662
|
+
...impersonator ? { impersonator } : {},
|
|
663
|
+
...actor ? { actor } : {},
|
|
664
|
+
...delegation ? { delegation } : {}
|
|
665
|
+
};
|
|
666
|
+
}
|
|
667
|
+
case "service": return {
|
|
668
|
+
kind: "service",
|
|
669
|
+
keyName: auth.keyName
|
|
670
|
+
};
|
|
671
|
+
case "anon": return {
|
|
672
|
+
kind: "anon",
|
|
673
|
+
reason: auth.reason
|
|
674
|
+
};
|
|
675
|
+
case "invalid": return {
|
|
676
|
+
kind: "invalid",
|
|
677
|
+
reason: auth.reason,
|
|
678
|
+
error: auth.error
|
|
679
|
+
};
|
|
680
|
+
default: return auth;
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
//#endregion
|
|
684
|
+
export { writeSession as _, checkAal as a, prefetchJwks as c, AUTH_CACHE_HEADERS as d, applyCookieWrites as f, sessionCookieName as g, serializeCookie as h, amrOf as i, rememberVerified as l, readSession as m, toSession as n, authContext as o, parseCookies as p, aalOf as r, clientIp as s, isAnonymousUser as t, resolveAuth as u, refreshSession as v };
|
|
@@ -1,30 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as
|
|
3
|
-
import {
|
|
1
|
+
import { _ as DbError } from "./executor-BunPOO-k.js";
|
|
2
|
+
import { n as Impersonator, o as AuthState, s as InvalidReason } from "./impersonation-BmePsuxz.js";
|
|
3
|
+
import { n as AmrEntry, t as Aal } from "./mfa-Cu96oJdw.js";
|
|
4
|
+
import { n as SessionActor, r as SessionDelegation } from "./actor-DaJjqD5R.js";
|
|
4
5
|
import { JWTClaims, UserClaims } from "@supabase/server";
|
|
5
|
-
//#region src/auth/actor.d.ts
|
|
6
|
-
/** One level of an RFC 8693 `act` chain: who acts, and who acted before it. */
|
|
7
|
-
interface ActClaim {
|
|
8
|
-
readonly sub: string;
|
|
9
|
-
readonly act?: ActClaim;
|
|
10
|
-
readonly [claim: string]: unknown;
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* The app acting for the user: the outermost `sub` of an RFC 8693 `act`
|
|
14
|
-
* chain (prior actors stay on `chain`), else the OAuth `client_id` of a
|
|
15
|
-
* Supabase OAuth server token.
|
|
16
|
-
*/
|
|
17
|
-
interface SessionActor {
|
|
18
|
-
readonly id: string;
|
|
19
|
-
readonly kind: "oauth-client";
|
|
20
|
-
readonly chain?: ActClaim;
|
|
21
|
-
}
|
|
22
|
-
/** What the user delegated to the actor: the token's OAuth `scope`. */
|
|
23
|
-
interface SessionDelegation {
|
|
24
|
-
readonly scopes: readonly string[];
|
|
25
|
-
readonly chain?: ActClaim;
|
|
26
|
-
}
|
|
27
|
-
//#endregion
|
|
28
6
|
//#region src/auth/view.d.ts
|
|
29
7
|
/**
|
|
30
8
|
* The verified caller as plain data: no token, no clients. Safe to return
|
|
@@ -48,16 +26,29 @@ type AuthSession<C = unknown, P = unknown> = {
|
|
|
48
26
|
readonly profile?: P;
|
|
49
27
|
/** `aal2` once the user verified a second factor in this session. */
|
|
50
28
|
readonly aal: Aal;
|
|
29
|
+
/**
|
|
30
|
+
* Signed in with `signInAnonymously()` (the `is_anonymous` claim). Guards
|
|
31
|
+
* refuse these users unless `allow` lists `'anonymous'`; `'anon'` means
|
|
32
|
+
* no session and never admits them.
|
|
33
|
+
*/
|
|
34
|
+
readonly anonymous: boolean;
|
|
51
35
|
/** How the user signed in (`password`, `totp`, `sso/saml`, ...). */
|
|
52
36
|
readonly amr: readonly AmrEntry[];
|
|
53
|
-
/**
|
|
37
|
+
/**
|
|
38
|
+
* Set when an admin acts as this user in a support session or an
|
|
39
|
+
* impersonated session (`act.kind`), for a banner. Matches `actor`.
|
|
40
|
+
*/
|
|
54
41
|
readonly impersonator?: Impersonator;
|
|
55
42
|
/**
|
|
56
|
-
*
|
|
57
|
-
*
|
|
43
|
+
* Who acts for the user: an OAuth client or agent (`client_id`, or an
|
|
44
|
+
* `act` chain without `kind`), a support session or an impersonated
|
|
45
|
+
* session, as PermDock's `actorOf` reads it.
|
|
58
46
|
*/
|
|
59
47
|
readonly actor?: SessionActor;
|
|
60
|
-
/**
|
|
48
|
+
/**
|
|
49
|
+
* The scopes the user granted an `oauth-client` actor, plus its `act`
|
|
50
|
+
* chain. Never set for a support or impersonated session.
|
|
51
|
+
*/
|
|
61
52
|
readonly delegation?: SessionDelegation;
|
|
62
53
|
} | {
|
|
63
54
|
readonly kind: "service";
|
|
@@ -76,4 +67,4 @@ type AnonReason = Extract<AuthState, {
|
|
|
76
67
|
/** Drops the token from an `AuthState`, leaving only serializable fields. */
|
|
77
68
|
declare function toSession<C, P>(auth: AuthState<C, P>): AuthSession<C, P>;
|
|
78
69
|
//#endregion
|
|
79
|
-
export {
|
|
70
|
+
export { toSession as n, AuthSession as t };
|
package/dist/webhooks/index.d.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
/// <reference lib="esnext.temporal" />
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { P as TableKey, k as Row, n as AnyFunctions, r as AnyModels } from "../types-Dnf_wRDz.js";
|
|
3
|
+
import { S as ErrorMapper, a as AsyncResult, u as Result } from "../executor-BunPOO-k.js";
|
|
4
|
+
import { a as EventHub } from "../events-aIO7vsIk.js";
|
|
5
|
+
import { t as BetterSupabase } from "../define-Bp_BZa5h.js";
|
|
6
|
+
import { g as RequestContext } from "../plugin-o144f322.js";
|
|
7
|
+
import { r as EventSink } from "../index-DOESKG27.js";
|
|
8
|
+
import { i as sqlTransport, n as RpcClient, r as rpcTransport, t as KitTransport } from "../kit-transport-B82k1djG.js";
|
|
9
|
+
import { _ as PublicUrlOptions, a as hmacSigner, b as publicUrl, c as WebhookSecretStore, d as WebhookPolicyError, f as WebhookRequest, g as AllowUrl, h as fetchTransport, i as WebhookSigner, l as sqlSecretStore, m as WebhookTransport, n as StandardWebhooksOptions, o as standardWebhooks, p as WebhookResponse, r as WebhookSignInput, s as RotateSecretOptions, t as HmacSignerOptions, u as FetchTransportOptions, v as ResolveHost, y as isPublicAddress } from "../signers-Cc6r98SW.js";
|
|
5
10
|
//#region src/webhooks/verify.d.ts
|
|
6
11
|
interface VerifiedWebhook<T = unknown> {
|
|
7
12
|
readonly id: string;
|
|
@@ -73,6 +78,8 @@ interface AuthHooks {
|
|
|
73
78
|
readonly site_url: string;
|
|
74
79
|
readonly token_new: string;
|
|
75
80
|
readonly token_hash_new: string;
|
|
81
|
+
/** Auth adds fields over time (`old_email`, `factor_type`, ...). */
|
|
82
|
+
readonly [key: string]: unknown;
|
|
76
83
|
};
|
|
77
84
|
};
|
|
78
85
|
output: Record<never, never>;
|
|
@@ -151,4 +158,128 @@ export declare function isDatabaseWebhook(value: unknown): value is DatabaseWebh
|
|
|
151
158
|
*/
|
|
152
159
|
export declare function databaseChange<M extends AnyModels, D, F extends AnyFunctions, E, T extends TableKey<M>>(betterSupabase: BetterSupabase<M, D, F, E>, table: T, payload: unknown): DatabaseChange<Row<M, T>> | null;
|
|
153
160
|
//#endregion
|
|
154
|
-
|
|
161
|
+
//#region src/webhooks/outgoing.d.ts
|
|
162
|
+
/** One claimed delivery, as `shouldDeliver`, `transform` and `headers` see it. */
|
|
163
|
+
interface WebhookDelivery {
|
|
164
|
+
readonly id: string;
|
|
165
|
+
readonly endpointId: string;
|
|
166
|
+
readonly url: string;
|
|
167
|
+
readonly type: string;
|
|
168
|
+
readonly payload: unknown;
|
|
169
|
+
/** 1 on the first try. Counted when the delivery is claimed. */
|
|
170
|
+
readonly attempt: number;
|
|
171
|
+
readonly tenant: string | null;
|
|
172
|
+
readonly eventId: string | null;
|
|
173
|
+
readonly runId: string | null;
|
|
174
|
+
readonly createdAt: Temporal.Instant;
|
|
175
|
+
}
|
|
176
|
+
interface RetryPolicy {
|
|
177
|
+
/** Attempts before a delivery is dead-lettered. Defaults to 8. */
|
|
178
|
+
readonly maxAttempts?: number;
|
|
179
|
+
/**
|
|
180
|
+
* Seconds before the next attempt. Defaults to 5 seconds, 5 minutes, 30
|
|
181
|
+
* minutes, 2 hours, 5 hours, then 10 hours, each with full jitter. A
|
|
182
|
+
* receiver's `Retry-After` wins when it asks for longer, up to a day.
|
|
183
|
+
*/
|
|
184
|
+
readonly backoff?: (attempt: number) => number;
|
|
185
|
+
/** Statuses worth retrying. Defaults to 408, 429 and 5xx; network errors always retry. */
|
|
186
|
+
readonly retryable?: (status: number) => boolean;
|
|
187
|
+
}
|
|
188
|
+
interface WebhooksOptions {
|
|
189
|
+
/** `sqlTransport(postgres.admin)` for the worker, or the user's connection to manage. */
|
|
190
|
+
readonly transport: KitTransport;
|
|
191
|
+
/** `kits.webhooks-out.schema`. Defaults to `better_supabase`. */
|
|
192
|
+
readonly schema?: string;
|
|
193
|
+
/** Defaults to `fetchTransport({ allowUrl })`. */
|
|
194
|
+
readonly http?: WebhookTransport;
|
|
195
|
+
/** Used by the default `http`. Defaults to `publicUrl()`. */
|
|
196
|
+
readonly allowUrl?: AllowUrl;
|
|
197
|
+
/** Defaults to `standardWebhooks()`. */
|
|
198
|
+
readonly signer?: WebhookSigner;
|
|
199
|
+
/** Defaults to `sqlSecretStore(transport)`. */
|
|
200
|
+
readonly secrets?: WebhookSecretStore;
|
|
201
|
+
readonly retry?: RetryPolicy;
|
|
202
|
+
/** Return `false` (or throw) to cancel a delivery instead of sending it. */
|
|
203
|
+
readonly shouldDeliver?: (delivery: WebhookDelivery) => boolean | Promise<boolean>;
|
|
204
|
+
/**
|
|
205
|
+
* The JSON body. Defaults to the Standard Webhooks envelope,
|
|
206
|
+
* `{ type, timestamp, data }`.
|
|
207
|
+
*/
|
|
208
|
+
readonly transform?: (delivery: WebhookDelivery) => unknown;
|
|
209
|
+
/** Extra headers, e.g. an `idempotency-key`. */
|
|
210
|
+
readonly headers?: (delivery: WebhookDelivery) => Readonly<Record<string, string>>;
|
|
211
|
+
/** Characters of the response body kept in the log. Defaults to 2000. */
|
|
212
|
+
readonly responseBodyLimit?: number;
|
|
213
|
+
/** `betterSupabase.events`, for `webhook.*` kit events. */
|
|
214
|
+
readonly events?: EventHub;
|
|
215
|
+
readonly context?: RequestContext;
|
|
216
|
+
readonly errorMappers?: readonly ErrorMapper[];
|
|
217
|
+
}
|
|
218
|
+
interface PublishInput {
|
|
219
|
+
readonly type: string;
|
|
220
|
+
readonly data: unknown;
|
|
221
|
+
readonly tenant?: string;
|
|
222
|
+
/** With an id, publishing it again never queues a second delivery. */
|
|
223
|
+
readonly id?: string;
|
|
224
|
+
}
|
|
225
|
+
interface DispatchInput {
|
|
226
|
+
readonly endpointId: string;
|
|
227
|
+
readonly type: string;
|
|
228
|
+
readonly data: unknown;
|
|
229
|
+
/** An external run id stored with the delivery, e.g. a workflow run. */
|
|
230
|
+
readonly runId?: string;
|
|
231
|
+
readonly eventId?: string;
|
|
232
|
+
}
|
|
233
|
+
interface DeliverWebhooksOptions {
|
|
234
|
+
/** Deliveries per claim. Defaults to 25. */
|
|
235
|
+
readonly batch?: number;
|
|
236
|
+
/**
|
|
237
|
+
* Requests in flight at once. Defaults to 10, so a batch of 25 at the
|
|
238
|
+
* 10-second timeout finishes well inside the lease.
|
|
239
|
+
*/
|
|
240
|
+
readonly concurrency?: number;
|
|
241
|
+
/** How long a claim holds a delivery. Defaults to `'2 minutes'`. */
|
|
242
|
+
readonly lease?: string;
|
|
243
|
+
readonly budgetMs?: number;
|
|
244
|
+
}
|
|
245
|
+
interface DeliverWebhooksResult {
|
|
246
|
+
readonly succeeded: number;
|
|
247
|
+
/** Failed attempts that will retry. */
|
|
248
|
+
readonly retrying: number;
|
|
249
|
+
/** Deliveries that ran out of attempts or can't succeed. */
|
|
250
|
+
readonly dead: number;
|
|
251
|
+
readonly canceled: number;
|
|
252
|
+
/** Endpoints disabled after failing for `disableAfter`. */
|
|
253
|
+
readonly disabled: number;
|
|
254
|
+
}
|
|
255
|
+
interface WebhooksRouteOptions extends DeliverWebhooksOptions {
|
|
256
|
+
readonly secret: string | undefined;
|
|
257
|
+
readonly onError?: (error: unknown) => void;
|
|
258
|
+
}
|
|
259
|
+
interface Webhooks {
|
|
260
|
+
/** Queues the event for each subscribed endpoint; returns how many. */
|
|
261
|
+
publish(event: PublishInput): AsyncResult<number>;
|
|
262
|
+
/** Sends to one endpoint outside its subscriptions; returns the delivery id. */
|
|
263
|
+
dispatch(input: DispatchInput): AsyncResult<string>;
|
|
264
|
+
/** Queues a finished delivery again. */
|
|
265
|
+
redeliver(deliveryId: string): AsyncResult<string>;
|
|
266
|
+
/** A new signing secret, returned once. */
|
|
267
|
+
rotateSecret(endpointId: string, options?: RotateSecretOptions): AsyncResult<string>;
|
|
268
|
+
/** Sends due deliveries. Run it from a cron route or a job. */
|
|
269
|
+
deliver(options?: DeliverWebhooksOptions): Promise<DeliverWebhooksResult>;
|
|
270
|
+
/** A `GET`/`POST` handler for Vercel Cron that runs `deliver` behind a bearer secret. */
|
|
271
|
+
deliverRoute(options: WebhooksRouteOptions): (request: Request) => Promise<Response>;
|
|
272
|
+
/**
|
|
273
|
+
* An `EventSink` that publishes CloudEvents, e.g. from the outbox relay.
|
|
274
|
+
* Endpoints subscribe to unprefixed types, so it removes `typePrefix`
|
|
275
|
+
* (`dev.better-supabase` by default, the relay's default) and the dot.
|
|
276
|
+
*/
|
|
277
|
+
sink(options?: WebhookSinkOptions): EventSink;
|
|
278
|
+
}
|
|
279
|
+
interface WebhookSinkOptions {
|
|
280
|
+
/** The relay's `typePrefix`. */
|
|
281
|
+
readonly typePrefix?: string;
|
|
282
|
+
}
|
|
283
|
+
export declare function createWebhooks(options: WebhooksOptions): Webhooks;
|
|
284
|
+
//#endregion
|
|
285
|
+
export { type AllowUrl, type AuthHookError, type AuthHookKind, type AuthHooks, type DatabaseChange, type DatabaseWebhookPayload, type DeliverWebhooksOptions, type DeliverWebhooksResult, type DispatchInput, type FetchTransportOptions, type HmacSignerOptions, type KitTransport, type PublicUrlOptions, type PublishInput, type ResolveHost, type RetryPolicy, type RotateSecretOptions, type RpcClient, type StandardWebhooksOptions, type VerifiedWebhook, type VerifyOptions, type WebhookDelivery, type WebhookInput, WebhookPolicyError, type WebhookRequest, type WebhookResponse, type WebhookSecretStore, type WebhookSignInput, type WebhookSigner, type WebhookSinkOptions, type WebhookTransport, type Webhooks, type WebhooksOptions, type WebhooksRouteOptions, fetchTransport, hmacSigner, isPublicAddress, publicUrl, rpcTransport, sqlSecretStore, sqlTransport, standardWebhooks };
|