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
|
@@ -32,6 +32,18 @@ function scalarKind(column) {
|
|
|
32
32
|
if (column.type === "record" || column.type === "void") return { kind: "unknown" };
|
|
33
33
|
return { kind: "string" };
|
|
34
34
|
}
|
|
35
|
+
/** App names of the columns that plugins fill from the table's flags. */
|
|
36
|
+
function managedColumns(table) {
|
|
37
|
+
const { timestamps, actor, softDelete } = table.flags;
|
|
38
|
+
return new Set([
|
|
39
|
+
timestamps?.createdAt,
|
|
40
|
+
timestamps?.updatedAt,
|
|
41
|
+
actor?.createdBy,
|
|
42
|
+
actor?.updatedBy,
|
|
43
|
+
actor?.impersonatedBy,
|
|
44
|
+
softDelete
|
|
45
|
+
].filter((name) => name !== void 0));
|
|
46
|
+
}
|
|
35
47
|
/**
|
|
36
48
|
* The generated row type of a field (its element type for arrays). Storage
|
|
37
49
|
* path columns validate as strings and are cast to their `StoragePath` brand.
|
|
@@ -43,6 +55,7 @@ function rowType(table, plan) {
|
|
|
43
55
|
/** The fields a variant accepts; read-only columns are left out of writes. */
|
|
44
56
|
function fieldsFor(table, variant, input) {
|
|
45
57
|
const fields = [];
|
|
58
|
+
const managed = managedColumns(table);
|
|
46
59
|
for (const [name, column] of Object.entries(table.columns)) {
|
|
47
60
|
if (variant === "Insert" && (column.generated || column.insertable === false)) continue;
|
|
48
61
|
if (variant === "Update" && (column.generated || column.updatable === false)) continue;
|
|
@@ -52,7 +65,8 @@ function fieldsFor(table, variant, input) {
|
|
|
52
65
|
scalar: scalarKind(column),
|
|
53
66
|
nullable: column.nullable,
|
|
54
67
|
optional: variant === "Update" || variant === "Insert" && (column.nullable || column.hasDefault),
|
|
55
|
-
customJson: Boolean(column.json && input.config.json[`${table.name}.${column.db}`])
|
|
68
|
+
customJson: Boolean(column.json && input.config.json[`${table.name}.${column.db}`]),
|
|
69
|
+
managed: managed.has(name)
|
|
56
70
|
});
|
|
57
71
|
}
|
|
58
72
|
return fields;
|
|
@@ -130,6 +144,13 @@ function scalar(kind) {
|
|
|
130
144
|
}
|
|
131
145
|
}
|
|
132
146
|
function property(plan) {
|
|
147
|
+
const schema = nullable(plan);
|
|
148
|
+
return plan.managed ? {
|
|
149
|
+
...schema,
|
|
150
|
+
readOnly: true
|
|
151
|
+
} : schema;
|
|
152
|
+
}
|
|
153
|
+
function nullable(plan) {
|
|
133
154
|
let schema = scalar(plan.scalar);
|
|
134
155
|
if (plan.column.array) schema = {
|
|
135
156
|
type: "array",
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { t as cloneValue } from "./clone-BfgmLU90.js";
|
|
2
|
+
import { n as nowInstant } from "./temporal-CVlIV2DZ.js";
|
|
3
|
+
//#region src/core/kit-events.ts
|
|
4
|
+
/**
|
|
5
|
+
* Fixed OpenTelemetry attribute names for kit work, so dashboards and
|
|
6
|
+
* queries can rely on them.
|
|
7
|
+
*/
|
|
8
|
+
const KIT_ATTRIBUTES = {
|
|
9
|
+
event: "better_supabase.kit.event",
|
|
10
|
+
tenant: "better_supabase.tenant",
|
|
11
|
+
actor: "better_supabase.actor.id",
|
|
12
|
+
supportSessionId: "better_supabase.support.session_id",
|
|
13
|
+
orgId: "better_supabase.org.id",
|
|
14
|
+
invitationId: "better_supabase.invitation.id",
|
|
15
|
+
notificationType: "better_supabase.notification.type",
|
|
16
|
+
webhookEndpointId: "better_supabase.webhook.endpoint_id"
|
|
17
|
+
};
|
|
18
|
+
/** The `KIT_ATTRIBUTES` an event carries. */
|
|
19
|
+
function kitEventAttributes(event) {
|
|
20
|
+
const attributes = { [KIT_ATTRIBUTES.event]: event.type };
|
|
21
|
+
if (event.tenant) attributes[KIT_ATTRIBUTES.tenant] = event.tenant;
|
|
22
|
+
if (event.actorId) attributes[KIT_ATTRIBUTES.actor] = event.actorId;
|
|
23
|
+
const data = Object.fromEntries(Object.entries(event.data));
|
|
24
|
+
const add = (key, value) => {
|
|
25
|
+
if (typeof value === "string" && value.length > 0) attributes[key] = value;
|
|
26
|
+
};
|
|
27
|
+
add(KIT_ATTRIBUTES.supportSessionId, data["sessionId"]);
|
|
28
|
+
add(KIT_ATTRIBUTES.orgId, data["organizationId"]);
|
|
29
|
+
add(KIT_ATTRIBUTES.invitationId, data["invitationId"]);
|
|
30
|
+
add(KIT_ATTRIBUTES.notificationType, data["type"]);
|
|
31
|
+
add(KIT_ATTRIBUTES.webhookEndpointId, data["endpointId"]);
|
|
32
|
+
return attributes;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Emits a kit event on `events` with a copy of `data`. Does nothing without
|
|
36
|
+
* a `kit` handler, so kits call it unconditionally.
|
|
37
|
+
*/
|
|
38
|
+
function emitKitEvent(events, type, data, meta = {}) {
|
|
39
|
+
if (!events.has("kit")) return;
|
|
40
|
+
const event = {
|
|
41
|
+
...meta,
|
|
42
|
+
type,
|
|
43
|
+
data: cloneValue(data),
|
|
44
|
+
time: nowInstant()
|
|
45
|
+
};
|
|
46
|
+
events.emit("kit", event);
|
|
47
|
+
}
|
|
48
|
+
const matches = (pattern, type) => pattern.endsWith(".*") ? type.startsWith(pattern.slice(0, -1)) : pattern === type;
|
|
49
|
+
/**
|
|
50
|
+
* Listens to the kit events that match `pattern` (`'support.started'` or
|
|
51
|
+
* `'support.*'`). Returns a function that stops listening.
|
|
52
|
+
*/
|
|
53
|
+
function onKitEvent(betterSupabase, pattern, handler) {
|
|
54
|
+
return betterSupabase.events.on("kit", (event) => {
|
|
55
|
+
if (!matches(pattern, event.type)) return;
|
|
56
|
+
handler(event);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
//#endregion
|
|
60
|
+
export { onKitEvent as i, emitKitEvent as n, kitEventAttributes as r, KIT_ATTRIBUTES as t };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { t as SqlClient } from "./executor-Cghdstwu.js";
|
|
2
|
+
//#region src/core/kit-transport.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Calls a kit function as the current user and resolves with its result.
|
|
5
|
+
* Rejects with the raw database error (a `pg` error or a PostgREST error
|
|
6
|
+
* object), which the kit maps to a `DbError`.
|
|
7
|
+
*/
|
|
8
|
+
interface KitTransport {
|
|
9
|
+
call(schema: string, fn: string, args: Readonly<Record<string, unknown>>): Promise<unknown>;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Calls the functions over Postgres, as the user `client` runs as:
|
|
13
|
+
* `sqlTransport(postgres.asUser(ctx.auth.claims))`. Works for any schema.
|
|
14
|
+
*/
|
|
15
|
+
declare function sqlTransport(client: SqlClient): KitTransport;
|
|
16
|
+
interface RpcResponse {
|
|
17
|
+
readonly data: unknown;
|
|
18
|
+
readonly error: unknown;
|
|
19
|
+
}
|
|
20
|
+
/** The part of a supabase-js client `rpcTransport` uses. */
|
|
21
|
+
interface RpcClient {
|
|
22
|
+
schema(name: string): {
|
|
23
|
+
rpc(fn: string, args: Record<string, unknown>): PromiseLike<RpcResponse>;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Calls the functions over the Data API with the user's session. The kit
|
|
28
|
+
* schema must be exposed (`[api] schemas` in `config.toml`), or the modules
|
|
29
|
+
* installed in `public` (`kits.<module>.schema`).
|
|
30
|
+
*/
|
|
31
|
+
declare function rpcTransport(client: RpcClient): KitTransport;
|
|
32
|
+
//#endregion
|
|
33
|
+
export { sqlTransport as i, RpcClient as n, rpcTransport as r, KitTransport as t };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { r as sqlIdent } from "./template-TxrGI5jR.js";
|
|
2
|
+
//#region src/core/kit-transport.ts
|
|
3
|
+
/**
|
|
4
|
+
* Calls the functions over Postgres, as the user `client` runs as:
|
|
5
|
+
* `sqlTransport(postgres.asUser(ctx.auth.claims))`. Works for any schema.
|
|
6
|
+
*/
|
|
7
|
+
function sqlTransport(client) {
|
|
8
|
+
return { async call(schema, fn, args) {
|
|
9
|
+
const entries = Object.entries(args).filter(([, value]) => value !== void 0);
|
|
10
|
+
const params = entries.map(([, value]) => value !== null && typeof value === "object" && !Array.isArray(value) ? JSON.stringify(value) : value);
|
|
11
|
+
const list = entries.map(([name], index) => `${sqlIdent(name)} => $${String(index + 1)}`).join(", ");
|
|
12
|
+
const [row] = await client.queryRaw(`select ${sqlIdent(schema)}.${sqlIdent(fn)}(${list}) as value`, params);
|
|
13
|
+
return row?.value ?? null;
|
|
14
|
+
} };
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Calls the functions over the Data API with the user's session. The kit
|
|
18
|
+
* schema must be exposed (`[api] schemas` in `config.toml`), or the modules
|
|
19
|
+
* installed in `public` (`kits.<module>.schema`).
|
|
20
|
+
*/
|
|
21
|
+
function rpcTransport(client) {
|
|
22
|
+
return { async call(schema, fn, args) {
|
|
23
|
+
const defined = Object.fromEntries(Object.entries(args).filter(([, value]) => value !== void 0));
|
|
24
|
+
const { data, error } = await client.schema(schema).rpc(fn, defined);
|
|
25
|
+
if (error) {
|
|
26
|
+
const message = typeof error === "object" && "message" in error ? String(error.message) : String(error);
|
|
27
|
+
throw Object.assign(new Error(message), error);
|
|
28
|
+
}
|
|
29
|
+
return data;
|
|
30
|
+
} };
|
|
31
|
+
}
|
|
32
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
33
|
+
/** The Postgres or PostgREST error a transport rejected with, if it is one. */
|
|
34
|
+
function rawError(cause) {
|
|
35
|
+
if (!isRecord(cause)) return void 0;
|
|
36
|
+
const field = (key) => {
|
|
37
|
+
const value = cause[key];
|
|
38
|
+
return typeof value === "string" ? value : void 0;
|
|
39
|
+
};
|
|
40
|
+
if (field("code") === void 0) return void 0;
|
|
41
|
+
const raw = {};
|
|
42
|
+
for (const key of [
|
|
43
|
+
"message",
|
|
44
|
+
"code",
|
|
45
|
+
"details",
|
|
46
|
+
"hint",
|
|
47
|
+
"constraint"
|
|
48
|
+
]) {
|
|
49
|
+
const value = field(key);
|
|
50
|
+
if (value !== void 0) raw[key] = value;
|
|
51
|
+
}
|
|
52
|
+
return raw;
|
|
53
|
+
}
|
|
54
|
+
//#endregion
|
|
55
|
+
export { rpcTransport as n, sqlTransport as r, rawError as t };
|
|
@@ -9,14 +9,16 @@ function resolveJsonSchema(source) {
|
|
|
9
9
|
return jsonSchema.input({ target: "draft-2020-12" });
|
|
10
10
|
}
|
|
11
11
|
function entitlementsOf(config = {}) {
|
|
12
|
-
const customer = config.customer
|
|
13
|
-
const dot = customer
|
|
14
|
-
if (dot <= 0) throw new TypeError(`entitlements.customer must be "table.column", got "${customer}"`);
|
|
12
|
+
const customer = config.customer;
|
|
13
|
+
const dot = customer?.lastIndexOf(".") ?? -1;
|
|
14
|
+
if (customer !== void 0 && dot <= 0) throw new TypeError(`entitlements.customer must be "table.column", got "${customer}"`);
|
|
15
15
|
return {
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
...customer === void 0 ? {} : {
|
|
17
|
+
table: customer.slice(0, dot),
|
|
18
|
+
column: customer.slice(dot + 1)
|
|
19
|
+
},
|
|
18
20
|
key: config.key ?? "id",
|
|
19
|
-
permdock: config.permdock === false ? false : { scope: config.permdock
|
|
21
|
+
permdock: config.permdock === false ? false : config.permdock?.scope === void 0 ? {} : { scope: config.permdock.scope }
|
|
20
22
|
};
|
|
21
23
|
}
|
|
22
24
|
function vectorSearchOf(config = {}) {
|
|
@@ -86,7 +88,8 @@ function resolveConfig(config, root) {
|
|
|
86
88
|
tenant: pick(config.plugins?.tenant, { column: "organization_id" }),
|
|
87
89
|
actor: pick(config.plugins?.actor, {
|
|
88
90
|
createdBy: "created_by",
|
|
89
|
-
updatedBy: "updated_by"
|
|
91
|
+
updatedBy: "updated_by",
|
|
92
|
+
impersonatedBy: "impersonated_by"
|
|
90
93
|
})
|
|
91
94
|
},
|
|
92
95
|
claims: {
|
|
@@ -95,7 +98,10 @@ function resolveConfig(config, root) {
|
|
|
95
98
|
},
|
|
96
99
|
buckets: config.buckets ?? {},
|
|
97
100
|
topics: config.topics ?? {},
|
|
98
|
-
realtime: {
|
|
101
|
+
realtime: {
|
|
102
|
+
tables: config.realtime?.tables ?? [],
|
|
103
|
+
global: config.realtime?.global ?? []
|
|
104
|
+
},
|
|
99
105
|
entitlements: entitlementsOf(config.entitlements),
|
|
100
106
|
permdock: {
|
|
101
107
|
manifest: config.permdock?.manifest ?? "permdock.manifest.json",
|
|
@@ -108,6 +114,7 @@ function resolveConfig(config, root) {
|
|
|
108
114
|
testsDir: config.sql?.testsDir ?? "supabase/tests",
|
|
109
115
|
kit: config.sql?.kit ?? []
|
|
110
116
|
},
|
|
117
|
+
kits: config.kits ?? {},
|
|
111
118
|
seed: {
|
|
112
119
|
entry: config.seed?.entry ?? "supabase/seed.ts",
|
|
113
120
|
output: config.seed?.output ?? "supabase/seeds/000_better_supabase.sql"
|
|
@@ -126,4 +133,25 @@ function resolveConfig(config, root) {
|
|
|
126
133
|
};
|
|
127
134
|
}
|
|
128
135
|
//#endregion
|
|
129
|
-
|
|
136
|
+
//#region src/config/kits.ts
|
|
137
|
+
/** URL tenancy: the tenant comes from the request (a slug), not a stored setting. */
|
|
138
|
+
const DEFAULT_ACTIVE_TENANT = "resolver";
|
|
139
|
+
const KIT_SCHEMA = "better_supabase";
|
|
140
|
+
function resolveKitModule(config = {}) {
|
|
141
|
+
return {
|
|
142
|
+
mode: config.mode ?? "managed",
|
|
143
|
+
schema: config.schema ?? KIT_SCHEMA,
|
|
144
|
+
tables: config.tables ?? {},
|
|
145
|
+
columns: config.columns ?? {},
|
|
146
|
+
...config.idType === void 0 ? {} : { idType: config.idType },
|
|
147
|
+
permissions: config.permissions ?? {},
|
|
148
|
+
options: config.options ?? {},
|
|
149
|
+
hooks: {
|
|
150
|
+
schema: config.hooks?.schema ?? "public",
|
|
151
|
+
functions: config.hooks?.functions ?? {}
|
|
152
|
+
},
|
|
153
|
+
events: config.events ?? true
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
//#endregion
|
|
157
|
+
export { resolveConfig as a, defineConfig as i, resolveKitModule as n, resolveJsonSchema as o, CONFIG_SCHEMA_URL as r, DEFAULT_ACTIVE_TENANT as t };
|
package/dist/list/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as ListPage, c as ListParsers, d as ListQueryInput, f as ListSearchParams, g as defineListQuery, h as UNSET, i as ListExtra, l as ListQuery, m as ParserSpec, n as FacetInfo, o as ListPagination, p as OpenApiParameter, r as ListDefinition, s as ListParseResult, t as FacetCounts, u as ListQueryConfig } from "../index-
|
|
1
|
+
import { a as ListPage, c as ListParsers, d as ListQueryInput, f as ListSearchParams, g as defineListQuery, h as UNSET, i as ListExtra, l as ListQuery, m as ParserSpec, n as FacetInfo, o as ListPagination, p as OpenApiParameter, r as ListDefinition, s as ListParseResult, t as FacetCounts, u as ListQueryConfig } from "../index-fag8VJZ2.js";
|
|
2
2
|
export { type FacetCounts, type FacetInfo, type ListDefinition, type ListExtra, type ListPage, type ListPagination, type ListParseResult, type ListParsers, type ListQuery, type ListQueryConfig, type ListQueryInput, type ListSearchParams, type OpenApiParameter, type ParserSpec, UNSET, defineListQuery };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { Z as QuerySpec, t as BetterSupabase } from "./define-
|
|
4
|
-
import {
|
|
1
|
+
import { P as TableKey, S as PermdockTopicPolicy, j as SchemaMeta, k as Row, n as AnyFunctions, r as AnyModels } from "./types-Dnf_wRDz.js";
|
|
2
|
+
import { _ as DbError, a as AsyncResult, u as Result, w as ValidationIssue } from "./executor-BunPOO-k.js";
|
|
3
|
+
import { Z as QuerySpec, t as BetterSupabase } from "./define-Bp_BZa5h.js";
|
|
4
|
+
import { n as PermdockCatalog } from "./permdock-sql-C2Inc6Xc.js";
|
|
5
5
|
import { n as TemplateValues, t as TemplateParams } from "./template-mbvlysOo.js";
|
|
6
6
|
import { RealtimeChannel, SupabaseClient } from "@supabase/supabase-js";
|
|
7
7
|
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
@@ -41,7 +41,8 @@ interface TopicOptions<E extends EventSchemas> {
|
|
|
41
41
|
readonly permdock?: PermdockTopicPolicy;
|
|
42
42
|
/**
|
|
43
43
|
* PermDock's `permissions.catalog.json`. With it, a `permdock` policy
|
|
44
|
-
* naming a permission
|
|
44
|
+
* naming a permission without `rowConditions: false` (including one the
|
|
45
|
+
* catalog doesn't list) throws.
|
|
45
46
|
*/
|
|
46
47
|
readonly catalog?: PermdockCatalog;
|
|
47
48
|
/** Let clients broadcast on the topic, not only receive. Defaults to `false`. */
|
package/dist/mcp/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as BetterSupabase } from "../define-
|
|
3
|
-
import { f as ServerContext, n as GuardOptions, p as ServerOptions, u as BetterServer } from "../respond-
|
|
4
|
-
import {
|
|
1
|
+
import { P as TableKey, n as AnyFunctions, r as AnyModels } from "../types-Dnf_wRDz.js";
|
|
2
|
+
import { t as BetterSupabase } from "../define-Bp_BZa5h.js";
|
|
3
|
+
import { f as ServerContext, n as GuardOptions, p as ServerOptions, u as BetterServer } from "../respond-BR1fJWOB.js";
|
|
4
|
+
import { i as ResourceOperation } from "../index-C7f8cOBM.js";
|
|
5
|
+
import { a as ResourceRouteOptions } from "../resource-DNRFP7KR.js";
|
|
5
6
|
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
6
7
|
//#region src/mcp/mcp.d.ts
|
|
7
8
|
export declare const MCP_PROTOCOL_VERSION: string;
|
|
@@ -38,7 +39,7 @@ interface McpTool<M extends AnyModels, F extends AnyFunctions, E, C = unknown, P
|
|
|
38
39
|
/** What the `authorize` and `visible` hooks see of a tool. */
|
|
39
40
|
interface ToolRef {
|
|
40
41
|
readonly info: ToolInfo;
|
|
41
|
-
/** The tool's `meta`, e.g. a PermDock permission. `
|
|
42
|
+
/** The tool's `meta`, e.g. a PermDock permission. For table tools, the resource's `meta` for that operation. */
|
|
42
43
|
readonly meta: unknown;
|
|
43
44
|
}
|
|
44
45
|
/** The outcome of `authorize`. `scopes` turns a refusal into an OAuth challenge. */
|
|
@@ -66,8 +67,17 @@ interface ToolDefinition<M extends AnyModels, F extends AnyFunctions, E, I, C =
|
|
|
66
67
|
readonly meta?: unknown;
|
|
67
68
|
run(args: I, ctx: ToolContext<M, F, E, C, P>): unknown;
|
|
68
69
|
}
|
|
69
|
-
|
|
70
|
-
|
|
70
|
+
/** A table's tools: the REST resource options, plus `meta` per operation for `authorize` and `visible`. */
|
|
71
|
+
type ToolResourceOptions<M extends AnyModels, T extends TableKey<M>> = ResourceRouteOptions<M, T> & {
|
|
72
|
+
/**
|
|
73
|
+
* Opaque data per operation, e.g. a PermDock permission, passed to
|
|
74
|
+
* `authorize` and `visible` as the table tool's `meta`. Never sent to
|
|
75
|
+
* clients. An operation without an entry gets `undefined`.
|
|
76
|
+
*/
|
|
77
|
+
readonly meta?: { readonly [K in ResourceOperation]?: unknown; };
|
|
78
|
+
};
|
|
79
|
+
type ToolResources<M extends AnyModels> = { readonly [T in TableKey<M>]?: ToolResourceOptions<M, T> | true; };
|
|
80
|
+
interface McpOptions<M extends AnyModels, F extends AnyFunctions, E, C = unknown, P = unknown> extends ServerOptions, Omit<GuardOptions, "scopes"> {
|
|
71
81
|
readonly name: string;
|
|
72
82
|
readonly version: string;
|
|
73
83
|
readonly title?: string;
|
|
@@ -88,7 +98,14 @@ interface McpOptions<M extends AnyModels, F extends AnyFunctions, E, C = unknown
|
|
|
88
98
|
* `insufficient_scope` challenges. `offline_access` is left out: refresh
|
|
89
99
|
* tokens are between the client and the authorization server.
|
|
90
100
|
*/
|
|
101
|
+
readonly advertisedScopes?: readonly string[];
|
|
102
|
+
/** @deprecated Use `advertisedScopes`; `requiredScopes` is what `guard` enforces. */
|
|
91
103
|
readonly scopes?: readonly string[];
|
|
104
|
+
/**
|
|
105
|
+
* Scopes a delegated token (an OAuth client or an `act` chain) needs to call
|
|
106
|
+
* the server at all. A missing one answers 403 `insufficient_scope`.
|
|
107
|
+
*/
|
|
108
|
+
readonly requiredScopes?: readonly string[];
|
|
92
109
|
/** Origins allowed to call the server (DNS rebinding protection). Defaults to any. */
|
|
93
110
|
readonly allowedOrigins?: readonly string[];
|
|
94
111
|
/**
|
|
@@ -146,4 +163,4 @@ export declare function defineTool<M extends AnyModels, F extends AnyFunctions,
|
|
|
146
163
|
*/
|
|
147
164
|
export declare function createMcp<M extends AnyModels, D, F extends AnyFunctions, E, C = unknown, P = unknown>(betterSupabase: BetterSupabase<M, D, F, E, C, P>, options: McpOptions<M, F, E, C, P>): BetterMcp<M, F, E, C, P>;
|
|
148
165
|
//#endregion
|
|
149
|
-
export type { BetterMcp, GuardOptions, McpOptions, McpTool, ResourceRouteOptions, ToolAnnotations, ToolContext, ToolDecision, ToolDefinition, ToolInfo, ToolRef, ToolResources, ToolResult };
|
|
166
|
+
export type { BetterMcp, GuardOptions, McpOptions, McpTool, ResourceRouteOptions, ToolAnnotations, ToolContext, ToolDecision, ToolDefinition, ToolInfo, ToolRef, ToolResourceOptions, ToolResources, ToolResult };
|
package/dist/mcp/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { n as dbError } from "../errors-
|
|
1
|
+
import { n as dbError } from "../errors-DtwXa6b8.js";
|
|
2
2
|
import { t as base64ToText } from "../base64-D2gsioCY.js";
|
|
3
|
-
import { t as validate } from "../standard-
|
|
4
|
-
import { o as toProblem } from "../problem-
|
|
3
|
+
import { t as validate } from "../standard-D7r6dMUu.js";
|
|
4
|
+
import { a as problemResponse, o as toProblem } from "../problem-BW1KhzSG.js";
|
|
5
5
|
import { t as SPEC_PINS } from "../spec-pins-C3oc-Tdp.js";
|
|
6
|
-
import { t as buildJsonSchema } from "../json-schema-
|
|
7
|
-
import { a as guard,
|
|
8
|
-
import { t as defineResource } from "../resource-
|
|
6
|
+
import { t as buildJsonSchema } from "../json-schema-m1fiwKgN.js";
|
|
7
|
+
import { a as withExtra, d as guard, g as jsonResponse, h as jsonReplacer, m as settle, n as createServer, r as extendServer, u as defaultExpose } from "../server-B1mZ7CgQ.js";
|
|
8
|
+
import { t as defineResource } from "../resource-mqfJW4YF.js";
|
|
9
9
|
import { fromSupabaseUrl, unauthorizedResponse } from "@supabase/server/oauth-protected-resource";
|
|
10
10
|
//#region src/mcp/mcp.ts
|
|
11
11
|
const MCP_PROTOCOL_VERSION = SPEC_PINS.mcp;
|
|
@@ -215,7 +215,7 @@ function textResult(value, isError = false) {
|
|
|
215
215
|
return {
|
|
216
216
|
content: [{
|
|
217
217
|
type: "text",
|
|
218
|
-
text: typeof value === "string" ? value : JSON.stringify(value ?? null)
|
|
218
|
+
text: typeof value === "string" ? value : JSON.stringify(value ?? null, jsonReplacer)
|
|
219
219
|
}],
|
|
220
220
|
...structured ? { structuredContent: structured } : {},
|
|
221
221
|
...isError ? { isError: true } : {}
|
|
@@ -258,11 +258,14 @@ function createMcp(betterSupabase, options) {
|
|
|
258
258
|
const isVisible = async (tool, ctx) => !options.visible || options.visible(ctx, tool);
|
|
259
259
|
for (const [table, raw] of Object.entries(options.resources ?? {})) {
|
|
260
260
|
if (!raw) continue;
|
|
261
|
-
const
|
|
261
|
+
const key = table;
|
|
262
|
+
const entry = raw;
|
|
263
|
+
const { meta, ...route } = entry === true ? {} : entry;
|
|
264
|
+
const resource = defineResource(betterSupabase, key, route);
|
|
262
265
|
for (const { info, operation } of tableTools(resource, defs)) {
|
|
263
266
|
const ref = {
|
|
264
267
|
info,
|
|
265
|
-
meta:
|
|
268
|
+
meta: meta?.[operation]
|
|
266
269
|
};
|
|
267
270
|
register({
|
|
268
271
|
...ref,
|
|
@@ -338,7 +341,7 @@ function createMcp(betterSupabase, options) {
|
|
|
338
341
|
const outcome = await invoke(name, args, ctx);
|
|
339
342
|
return isRefusal(outcome) ? failure(dbError("forbidden", outcome.refusal)) : outcome;
|
|
340
343
|
};
|
|
341
|
-
const scopes = (options.scopes ?? []).filter((scope) => scope !== "offline_access");
|
|
344
|
+
const scopes = (options.advertisedScopes ?? options.scopes ?? []).filter((scope) => scope !== "offline_access");
|
|
342
345
|
const serverInfo = {
|
|
343
346
|
name: options.name,
|
|
344
347
|
version: options.version,
|
|
@@ -362,6 +365,12 @@ function createMcp(betterSupabase, options) {
|
|
|
362
365
|
response.headers.set("www-authenticate", challenge);
|
|
363
366
|
return response;
|
|
364
367
|
};
|
|
368
|
+
/** A missing second factor is no scope problem, and an outage is not the caller's fault. */
|
|
369
|
+
const refuse = (request, denied) => {
|
|
370
|
+
if (denied.kind === "unauthorized") return unauthorized(request);
|
|
371
|
+
if (denied.kind !== "forbidden") return problemResponse(denied, { expose });
|
|
372
|
+
return denied.code === "INSUFFICIENT_AAL" ? rpcError(null, INVALID_REQUEST, denied.message, 403) : forbidden(request, denied.message, denied.scopes);
|
|
373
|
+
};
|
|
365
374
|
const unsupportedVersion = (id, requested) => rpcError(id, UNSUPPORTED_PROTOCOL_VERSION, "Unsupported protocol version", 400, {
|
|
366
375
|
supported: [...SUPPORTED_VERSIONS],
|
|
367
376
|
requested
|
|
@@ -391,9 +400,9 @@ function createMcp(betterSupabase, options) {
|
|
|
391
400
|
});
|
|
392
401
|
const header = request.headers.get("mcp-protocol-version");
|
|
393
402
|
if (header && !SUPPORTED_VERSIONS.includes(header)) return unsupportedVersion(null, header);
|
|
394
|
-
const ctx = await server.context(request);
|
|
395
|
-
const denied = guard(ctx.auth, options.allow, options.aal);
|
|
396
|
-
if (denied) return
|
|
403
|
+
const ctx = await server.context(request, { cookies: false });
|
|
404
|
+
const denied = guard(ctx.auth, options.allow, options.aal, options.requiredScopes);
|
|
405
|
+
if (denied) return refuse(request, denied);
|
|
397
406
|
let message;
|
|
398
407
|
try {
|
|
399
408
|
message = await request.json();
|
|
@@ -412,7 +421,7 @@ function createMcp(betterSupabase, options) {
|
|
|
412
421
|
request,
|
|
413
422
|
signal: request.signal
|
|
414
423
|
});
|
|
415
|
-
const reply = (result) =>
|
|
424
|
+
const reply = (result) => jsonResponse({
|
|
416
425
|
jsonrpc: "2.0",
|
|
417
426
|
id: message.id,
|
|
418
427
|
result: modern ? {
|
|
@@ -1,18 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
//#region src/auth/impersonation.d.ts
|
|
3
|
-
/** The admin acting as the user, from the RFC 8693 `act` claim. */
|
|
4
|
-
interface Impersonator {
|
|
5
|
-
readonly id: string;
|
|
6
|
-
readonly reason?: string;
|
|
7
|
-
}
|
|
8
|
-
/** `actingAs(userId, claims, { actor, reason })`: who acts, and why (recorded by the audit module). */
|
|
9
|
-
interface ImpersonationOptions {
|
|
10
|
-
readonly actor: string;
|
|
11
|
-
readonly reason: string;
|
|
12
|
-
}
|
|
13
|
-
/** The impersonator in `claims.act`, or `undefined` for a normal session. */
|
|
14
|
-
declare function impersonatorOf(claims: Readonly<Record<string, unknown>>): Impersonator | undefined;
|
|
15
|
-
//#endregion
|
|
1
|
+
import { _ as DbError } from "./executor-BunPOO-k.js";
|
|
16
2
|
//#region src/auth/mfa.d.ts
|
|
17
3
|
/** Authenticator assurance level: `aal2` once a second factor is verified in this session. */
|
|
18
4
|
type Aal = "aal1" | "aal2";
|
|
@@ -41,4 +27,4 @@ declare function checkAal(auth: {
|
|
|
41
27
|
readonly kind: string;
|
|
42
28
|
}, required: Aal): DbError | undefined;
|
|
43
29
|
//#endregion
|
|
44
|
-
export { checkAal as a,
|
|
30
|
+
export { checkAal as a, amrOf as i, AmrEntry as n, aalOf as r, Aal as t };
|
package/dist/next/index.d.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { n as
|
|
2
|
-
import {
|
|
3
|
-
import { B as ReadSet, P as DbStats, Z as QuerySpec, l as CacheAdapter, t as BetterSupabase } from "../define-
|
|
4
|
-
import { n as
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { n as toSession, t as AuthSession } from "../view-
|
|
8
|
-
import { r as LiveCountSeed, t as CountRunner } from "../live-
|
|
9
|
-
import { n as
|
|
1
|
+
import { n as AnyFunctions, r as AnyModels } from "../types-Dnf_wRDz.js";
|
|
2
|
+
import { _ as DbError } from "../executor-BunPOO-k.js";
|
|
3
|
+
import { B as ReadSet, P as DbStats, Z as QuerySpec, l as CacheAdapter, t as BetterSupabase } from "../define-Bp_BZa5h.js";
|
|
4
|
+
import { n as Impersonator, o as AuthState } from "../impersonation-BmePsuxz.js";
|
|
5
|
+
import { C as SupportOptions, D as supportSessions, E as SupportStartRequest, T as SupportSessions, b as ActiveSupport, d as ContextOptions, f as ServerContext, n as GuardOptions, p as ServerOptions, t as AuthKind, u as BetterServer, w as SupportPolicy } from "../respond-BR1fJWOB.js";
|
|
6
|
+
import { n as AmrEntry, t as Aal } from "../mfa-Cu96oJdw.js";
|
|
7
|
+
import { n as toSession, t as AuthSession } from "../view-CbgObAeb.js";
|
|
8
|
+
import { r as LiveCountSeed, t as CountRunner } from "../live-D9W2M5aO.js";
|
|
9
|
+
import { n as supportOf, t as SupportView } from "../support-view-B8SlToQX.js";
|
|
10
|
+
import { n as MembershipClaim, r as hasEntitlement, t as EntitlementKey } from "../entitlements-BiJZ4t49.js";
|
|
10
11
|
import { NextRequest } from "next/server.js";
|
|
11
12
|
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
12
13
|
//#region src/next/collector.d.ts
|
|
@@ -149,7 +150,27 @@ interface BetterNext<M extends AnyModels, F extends AnyFunctions, E, C = unknown
|
|
|
149
150
|
* `expectDbBudget`. Answers 404 unless `debug` is on.
|
|
150
151
|
*/
|
|
151
152
|
debugRoute(): (request: Request) => Promise<Response>;
|
|
153
|
+
/**
|
|
154
|
+
* Starts a support session for the signed-in admin and sets its cookie,
|
|
155
|
+
* so the admin's next requests render as the target. Call it from a
|
|
156
|
+
* server action.
|
|
157
|
+
*/
|
|
158
|
+
startSupport(request: SupportStartRequest): Promise<ActionResult<SupportStarted>>;
|
|
159
|
+
/** Ends the admin's support session and clears its cookie. Call it from a server action. */
|
|
160
|
+
stopSupport(): Promise<ActionResult<{
|
|
161
|
+
readonly ended: boolean;
|
|
162
|
+
}>>;
|
|
163
|
+
}
|
|
164
|
+
/** What `startSupport` returns: plain data, safe across the action boundary. */
|
|
165
|
+
interface SupportStarted {
|
|
166
|
+
readonly sessionId: string;
|
|
167
|
+
readonly targetUserId: string;
|
|
168
|
+
readonly readOnly: boolean;
|
|
169
|
+
/** ISO 8601. */
|
|
170
|
+
readonly expiresAt: string;
|
|
152
171
|
}
|
|
172
|
+
/** The tag `bs.cached()` adds to entries rendered in a support session. */
|
|
173
|
+
export declare function supportTag(sessionId: string): string;
|
|
153
174
|
interface SessionStaleOptions {
|
|
154
175
|
/** Below this, the result would not be prefetched anyway. Defaults to 30. */
|
|
155
176
|
readonly min?: number;
|
|
@@ -223,4 +244,4 @@ export declare function shouldRefresh(request: Request): boolean;
|
|
|
223
244
|
*/
|
|
224
245
|
export declare function createNext<M extends AnyModels, D, F extends AnyFunctions, E, C = unknown, P = unknown>(betterSupabase: BetterSupabase<M, D, F, E, C, P>, options?: NextOptions): BetterNext<M, F, E, C, P>;
|
|
225
246
|
//#endregion
|
|
226
|
-
export { type Aal, type ActionOptions, type ActionResult, type AmrEntry, type AuthKind, type AuthSession, type BetterNext, type CachedContext, type CachedOptions, type DbBudget, type DbStats, type EntitlementKey, type GuardOptions, type Impersonator, type LiveCountSeed, type MembershipClaim, type NextDebugOptions, type NextOptions, type ProxyOptions, type RequireAalOptions, type SessionStaleOptions, hasEntitlement, toSession };
|
|
247
|
+
export { type Aal, type ActionOptions, type ActionResult, type ActiveSupport, type AmrEntry, type AuthKind, type AuthSession, type BetterNext, type CachedContext, type CachedOptions, type DbBudget, type DbStats, type EntitlementKey, type GuardOptions, type Impersonator, type LiveCountSeed, type MembershipClaim, type NextDebugOptions, type NextOptions, type ProxyOptions, type RequireAalOptions, type SessionStaleOptions, type SupportOptions, type SupportPolicy, type SupportSessions, type SupportStartRequest, type SupportStarted, type SupportView, hasEntitlement, supportOf, supportSessions, toSession };
|