better-supabase 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -31
- package/dist/base64-CQeB1eSf.js +42 -0
- package/dist/claims-CoTobNC-.js +25 -0
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.js +4 -14
- package/dist/{compiler-DL18ukPe.d.ts → compiler-2zqGzxVZ.d.ts} +2 -2
- package/dist/config/index.d.ts +4 -3
- package/dist/config/index.js +5 -3
- package/dist/config-Be4GwsqI.js +129 -0
- package/dist/{index-BD6wKthp.d.ts → config-C1CYcm6o.d.ts} +75 -54
- package/dist/{config-D-aR2ZoN.js → config-DOsGYSiT.js} +14 -136
- package/dist/{define-QGkq04oe.js → define-DF341GDj.js} +133 -110
- package/dist/{define-CTfWw-SS.d.ts → define-DUbydmJa.d.ts} +32 -14
- package/dist/edge/index.d.ts +4 -4
- package/dist/edge/index.js +4 -4
- package/dist/entitlements-CTEBm7IB.js +20 -0
- package/dist/entitlements-DvJXoI02.d.ts +42 -0
- package/dist/env/index.js +203 -1
- package/dist/events/index.d.ts +1 -1
- package/dist/events/index.js +139 -1
- package/dist/{events-2OJsVG_d.d.ts → events-Do8jXh4D.d.ts} +3 -3
- package/dist/{executor-Bje4suQF.d.ts → executor-B26lgbHD.d.ts} +2 -2
- package/dist/{executor-Ceq60hPM.js → executor-C57jx2pn.js} +7 -2
- package/dist/{executor-Bazhgsgq.d.ts → executor-DynmIWhq.d.ts} +2 -2
- package/dist/guards-BnzDvFrz.js +10 -0
- package/dist/hono/index.d.ts +5 -5
- package/dist/hono/index.js +4 -4
- package/dist/{index-Hf8PP9sP.d.ts → index-BNsABq7P.d.ts} +17 -13
- package/dist/{index-JXHBuS53.d.ts → index-CADlNHK-.d.ts} +27 -14
- package/dist/{index-Nxo3TJcm.d.ts → index-CTTMS6_1.d.ts} +27 -8
- package/dist/index-Cf-D2jk1.d.ts +50 -0
- package/dist/{index-Dup-nSe9.d.ts → index-CriFFJ_p.d.ts} +4 -4
- package/dist/{index-DQVvHzjW.d.ts → index-GV77NpRP.d.ts} +5 -4
- package/dist/{index-Sw43J8HG.d.ts → index-UJ-LUxtI.d.ts} +6 -6
- package/dist/{index-cEeweTeM.d.ts → index-kpgopLNv.d.ts} +4 -3
- package/dist/{index-DRid0qIv.d.ts → index-qriRM9cZ.d.ts} +7 -2
- package/dist/index.d.ts +13 -13
- package/dist/index.js +18 -8
- package/dist/jobs/index.d.ts +25 -24
- package/dist/jobs/index.js +19 -12
- package/dist/{json-schema-BbwO2mZg.js → json-schema--aOXAGfU.js} +9 -3
- package/dist/lint/index.js +1 -1
- package/dist/list/index.d.ts +2 -2
- package/dist/list/index.js +128 -93
- package/dist/{live-6b9i72Ux.d.ts → live-QE3UPbGm.d.ts} +27 -6
- package/dist/logger-glM28NVN.js +21 -0
- package/dist/mcp/index.d.ts +59 -15
- package/dist/mcp/index.js +229 -67
- package/dist/{mfa-CpogP66z.js → mfa-BxoR1RkN.js} +97 -22
- package/dist/{mfa-TVia554c.d.ts → mfa-x3V3vGh-.d.ts} +1 -1
- package/dist/next/index.d.ts +51 -38
- package/dist/next/index.js +31 -25
- package/dist/openapi/index.d.ts +1 -1
- package/dist/openapi/index.js +58 -35
- package/dist/orpc/index.d.ts +6 -6
- package/dist/orpc/index.js +3 -3
- package/dist/otel/index.d.ts +3 -3
- package/dist/otel/index.js +5 -3
- package/dist/{template-BeOGnynM.js → permdock-sql-Bta_G0v-.js} +32 -3
- package/dist/permdock-sql-DImJULY-.d.ts +17 -0
- package/dist/{plugin-HvGqCurB.d.ts → plugin-DVRB8qNE.d.ts} +5 -4
- package/dist/plugins/actor/index.d.ts +1 -1
- package/dist/plugins/rules/index.d.ts +4 -3
- package/dist/plugins/rules/index.js +8 -15
- package/dist/plugins/soft-delete/index.d.ts +3 -3
- package/dist/plugins/soft-delete/index.js +2 -2
- package/dist/plugins/tenant/index.d.ts +10 -4
- package/dist/plugins/tenant/index.js +15 -13
- package/dist/plugins/timestamps/index.d.ts +1 -1
- package/dist/plugins/timestamps/index.js +1 -1
- package/dist/plugins/validation/index.d.ts +2 -2
- package/dist/pool-B9qsLyFR.d.ts +71 -0
- package/dist/postgres/index.d.ts +10 -5
- package/dist/postgres/index.js +36 -16
- package/dist/{postgrest-Dm-vhY6R.d.ts → postgrest-DmBlevh-.d.ts} +1 -1
- package/dist/{problem-DPu6Fh-t.js → problem-CGt1ADix.js} +14 -8
- package/dist/{problem-DlgB0lYl.d.ts → problem-Z2RTQjZD.d.ts} +6 -4
- package/dist/query/index.d.ts +2 -2
- package/dist/query/index.js +1 -1
- package/dist/{query-ChvDbsDE.js → query-BdKLTPlj.js} +2 -2
- package/dist/react/index.d.ts +7 -7
- package/dist/react/index.js +3 -3
- package/dist/react/server.d.ts +5 -5
- package/dist/react/server.js +1 -1
- package/dist/react/session.d.ts +21 -2
- package/dist/react/session.js +19 -1
- package/dist/{react-CrOvrnIP.js → react-DNBYNazu.js} +28 -23
- package/dist/{read-set-DhX2d04c.js → read-set-D0qBcboM.js} +3 -3
- package/dist/realtime/index.d.ts +4 -2
- package/dist/realtime/index.js +30 -14
- package/dist/{resolve-DW8h9NPm.d.ts → resolve-BRciX2jK.d.ts} +25 -9
- package/dist/{resource-SkPTRJDD.d.ts → resource-CwVgiI5q.d.ts} +16 -7
- package/dist/{resource-CYiu6Ygi.js → resource-D30rp0GN.js} +38 -16
- package/dist/{respond-4-dhoV7x.js → respond-C44EZAJo.js} +38 -19
- package/dist/{respond-PoTpy5DT.d.ts → respond-DAkPIdTH.d.ts} +23 -17
- package/dist/{result-CTkCZ6JA.d.ts → result-c2OYgCV2.d.ts} +13 -8
- package/dist/server/index.d.ts +35 -10
- package/dist/server/index.js +38 -9
- package/dist/{simplify-oHiDKRVQ.js → simplify-LakqK1vH.js} +22 -28
- package/dist/{spec-pins-t6sPaHvl.js → spec-pins-C3oc-Tdp.js} +1 -1
- package/dist/{spec-pins-CJPVghHy.d.ts → spec-pins-CqorWDnO.d.ts} +1 -1
- package/dist/sql/index.d.ts +139 -0
- package/dist/sql/index.js +1983 -0
- package/dist/{sql-M8l3fnS0.js → sql-BIgk12ew.js} +72 -16
- package/dist/ssr/index.d.ts +5 -5
- package/dist/ssr/index.js +3 -3
- package/dist/{standard-CyhRzctb.d.ts → standard-eudBiRk1.d.ts} +1 -1
- package/dist/{stats-3iy8u3_P.js → stats-D78UQ8Yu.js} +8 -7
- package/dist/storage/index.d.ts +4 -2
- package/dist/storage/index.js +530 -1
- package/dist/{tables-rZxRxNPW.js → tables-Dhha3BXM.js} +5 -5
- package/dist/temporal-BwshQk0W.js +27 -0
- package/dist/temporal-required-CMxeSVPo.js +19 -0
- package/dist/testing/index.d.ts +49 -16
- package/dist/testing/index.js +233 -66
- package/dist/{types-C2fslP1z.d.ts → types-DONv9SHN.d.ts} +68 -12
- package/dist/{version-Cqq1m3UY.js → version-BfpG2gks.js} +1 -1
- package/dist/view-3Po_PVlr.d.ts +79 -0
- package/dist/{view-B6F9QbG-.js → view-wZ-9qIUz.js} +12 -2
- package/dist/webhooks/index.d.ts +19 -17
- package/dist/webhooks/index.js +1 -1
- package/dist/{webhooks-DbMTJJX2.js → webhooks-CAIFQSTM.js} +12 -10
- package/package.json +30 -30
- package/schemas/config-v1.json +80 -5
- package/schemas/doctor-report-v1.json +18 -1
- package/schemas/snapshot-v2.json +39 -0
- package/skills/better-supabase/SKILL.md +23 -11
- package/skills/better-supabase/references/plugins.md +28 -16
- package/skills/better-supabase/references/troubleshooting.md +15 -15
- package/skills/better-supabase-api/SKILL.md +9 -9
- package/skills/better-supabase-api/references/adapters.md +30 -25
- package/skills/better-supabase-testing/SKILL.md +15 -11
- package/bin/better-supabase.js +0 -3
- package/dist/casing-da0uRTqt.js +0 -14
- package/dist/cli/bin.d.ts +0 -1
- package/dist/cli/bin.js +0 -15
- package/dist/cli/index.d.ts +0 -226
- package/dist/cli/index.js +0 -3
- package/dist/cli-CoByWYja.js +0 -6472
- package/dist/entitlements-BBg61DQZ.d.ts +0 -20
- package/dist/entitlements-BC_khwRy.js +0 -17
- package/dist/env-BEToab0I.js +0 -204
- package/dist/events-BuzTgn2D.js +0 -135
- package/dist/pool-BFeqzwQS.d.ts +0 -37
- package/dist/seed-CzecODcJ.js +0 -101
- package/dist/session-C3osL21k.d.ts +0 -21
- package/dist/session-CD-3orO_.js +0 -19
- package/dist/storage-BWXVUXGk.js +0 -461
- package/dist/view-B0ltUmTi.d.ts +0 -43
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { n as dbError, t as DbException } from "./errors-Bl3rkOzo.js";
|
|
2
|
-
import { a as invalidRequest, c as needsDecoding, o as decodeRows, r as IrBuilder, s as encodeValue } from "./simplify-
|
|
3
|
-
import {
|
|
2
|
+
import { a as invalidRequest, c as needsDecoding, o as decodeRows, r as IrBuilder, s as encodeValue } from "./simplify-LakqK1vH.js";
|
|
3
|
+
import { n as nowInstant } from "./temporal-BwshQk0W.js";
|
|
4
|
+
import { i as or, n as column, r as not, t as and } from "./types-6cYK9pbJ.js";
|
|
4
5
|
import { i as ok, n as err, o as toDbError, s as withErrorMapper, t as AsyncResult } from "./result-DWXatkd6.js";
|
|
5
|
-
import { t as invalidationTargets } from "./tables-
|
|
6
|
+
import { t as invalidationTargets } from "./tables-Dhha3BXM.js";
|
|
7
|
+
import { t as consoleLogger } from "./logger-glM28NVN.js";
|
|
6
8
|
import { r as orderPlugins } from "./plugin-BqR6wKMB.js";
|
|
7
|
-
import { a as postgrestExecutor, n as StatsRecorder, r as recordStats } from "./stats-
|
|
8
|
-
import { d as isQuerySpec, f as specTables, n as checkParams, o as isReadSet, r as containsPlaceholder, t as bindParams, u as createSpecs } from "./read-set-
|
|
9
|
+
import { a as postgrestExecutor, n as StatsRecorder, r as recordStats } from "./stats-D78UQ8Yu.js";
|
|
10
|
+
import { d as isQuerySpec, f as specTables, n as checkParams, o as isReadSet, r as containsPlaceholder, t as bindParams, u as createSpecs } from "./read-set-D0qBcboM.js";
|
|
11
|
+
import { a as toBase64Url, t as base64ToText } from "./base64-CQeB1eSf.js";
|
|
9
12
|
import { t as validate } from "./standard-FUi3Z3-7.js";
|
|
10
13
|
//#region src/core/batch.ts
|
|
11
14
|
/**
|
|
@@ -91,26 +94,6 @@ function memoryCache() {
|
|
|
91
94
|
};
|
|
92
95
|
}
|
|
93
96
|
//#endregion
|
|
94
|
-
//#region src/core/logger.ts
|
|
95
|
-
const log = (method) => (message, fields) => {
|
|
96
|
-
if (fields === void 0) console[method](`better-supabase: ${message}`);
|
|
97
|
-
else console[method](`better-supabase: ${message}`, fields);
|
|
98
|
-
};
|
|
99
|
-
/** The default: `console`, with a `better-supabase:` prefix. */
|
|
100
|
-
const consoleLogger = {
|
|
101
|
-
debug: log("debug"),
|
|
102
|
-
info: log("info"),
|
|
103
|
-
warn: log("warn"),
|
|
104
|
-
error: log("error")
|
|
105
|
-
};
|
|
106
|
-
const noop = () => {};
|
|
107
|
-
const silentLogger = {
|
|
108
|
-
debug: noop,
|
|
109
|
-
info: noop,
|
|
110
|
-
warn: noop,
|
|
111
|
-
error: noop
|
|
112
|
-
};
|
|
113
|
-
//#endregion
|
|
114
97
|
//#region src/core/events.ts
|
|
115
98
|
/**
|
|
116
99
|
* Observers only: a handler that throws is reported to the logger and never
|
|
@@ -148,27 +131,13 @@ var EventHub = class {
|
|
|
148
131
|
};
|
|
149
132
|
//#endregion
|
|
150
133
|
//#region src/core/cursor.ts
|
|
151
|
-
const encoder = new TextEncoder();
|
|
152
|
-
const decoder = new TextDecoder();
|
|
153
|
-
function toBase64Url(bytes) {
|
|
154
|
-
let binary = "";
|
|
155
|
-
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
156
|
-
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
157
|
-
}
|
|
158
|
-
function fromBase64Url(text) {
|
|
159
|
-
const base64 = text.replace(/-/g, "+").replace(/_/g, "/");
|
|
160
|
-
const binary = atob(base64 + "=".repeat((4 - base64.length % 4) % 4));
|
|
161
|
-
const bytes = new Uint8Array(binary.length);
|
|
162
|
-
for (let index = 0; index < binary.length; index += 1) bytes[index] = binary.charCodeAt(index);
|
|
163
|
-
return bytes;
|
|
164
|
-
}
|
|
165
134
|
/** Opaque, URL-safe keyset cursor. */
|
|
166
135
|
function encodeCursor(values) {
|
|
167
|
-
return toBase64Url(
|
|
136
|
+
return toBase64Url(JSON.stringify(values));
|
|
168
137
|
}
|
|
169
138
|
function decodeCursor(cursor) {
|
|
170
139
|
try {
|
|
171
|
-
const parsed = JSON.parse(
|
|
140
|
+
const parsed = JSON.parse(base64ToText(cursor));
|
|
172
141
|
return Array.isArray(parsed) ? parsed : void 0;
|
|
173
142
|
} catch {
|
|
174
143
|
return;
|
|
@@ -208,7 +177,7 @@ function optionsOf(args) {
|
|
|
208
177
|
return options;
|
|
209
178
|
}
|
|
210
179
|
function signalOf(args) {
|
|
211
|
-
const signal = args?.signal;
|
|
180
|
+
const signal = args?.["signal"];
|
|
212
181
|
return signal instanceof AbortSignal ? signal : void 0;
|
|
213
182
|
}
|
|
214
183
|
function mutationKind(op) {
|
|
@@ -252,10 +221,16 @@ var OperationRunner = class {
|
|
|
252
221
|
} : { errorMappers: runtime.errorMappers };
|
|
253
222
|
const executed = await runtime.executor.execute(current, context);
|
|
254
223
|
const selection = current.kind === "select" ? current.selection : current.returning;
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
224
|
+
let result = executed;
|
|
225
|
+
if (executed.ok && selection && needsDecoding(selection)) try {
|
|
226
|
+
result = ok({
|
|
227
|
+
...executed.data,
|
|
228
|
+
rows: decodeRows(selection, executed.data.rows)
|
|
229
|
+
});
|
|
230
|
+
} catch (cause) {
|
|
231
|
+
if (cause instanceof DbException) return this.fail(op.table, cause.error);
|
|
232
|
+
throw cause;
|
|
233
|
+
}
|
|
259
234
|
const rows = result.ok ? result.data.rows.length : 0;
|
|
260
235
|
const truncated = current.kind === "select" && current.limit === void 0 && current.single === void 0 && !current.head && rows >= runtime.maxRows;
|
|
261
236
|
if (truncated && !runtime.truncatedTables.has(op.table.key)) {
|
|
@@ -315,21 +290,21 @@ var OperationRunner = class {
|
|
|
315
290
|
/** Creates the runtime repository object for one table. */
|
|
316
291
|
function createRepository(runner, table) {
|
|
317
292
|
const { builder } = runner.runtime;
|
|
318
|
-
const selection = (args) => builder.selection(table, args?.select, args?.include);
|
|
293
|
+
const selection = (args) => builder.selection(table, args?.["select"], args?.["include"]);
|
|
319
294
|
const selectOp = (args, patch = {}) => ({
|
|
320
295
|
kind: "select",
|
|
321
296
|
table,
|
|
322
297
|
selection: selection(args),
|
|
323
|
-
where: builder.where(table, args?.where),
|
|
324
|
-
orderBy: builder.orderBy(table, args?.orderBy),
|
|
325
|
-
limit: typeof args?.limit === "number" ? args
|
|
326
|
-
offset: typeof args?.offset === "number" ? args
|
|
298
|
+
where: builder.where(table, args?.["where"]),
|
|
299
|
+
orderBy: builder.orderBy(table, args?.["orderBy"]),
|
|
300
|
+
limit: typeof args?.["limit"] === "number" ? args["limit"] : void 0,
|
|
301
|
+
offset: typeof args?.["offset"] === "number" ? args["offset"] : void 0,
|
|
327
302
|
count: void 0,
|
|
328
303
|
head: false,
|
|
329
304
|
single: void 0,
|
|
330
305
|
...patch
|
|
331
306
|
});
|
|
332
|
-
const returning = (args) => args?.returning === false ? void 0 : selection(args);
|
|
307
|
+
const returning = (args) => args?.["returning"] === false ? void 0 : selection(args);
|
|
333
308
|
const run = (op, args) => runner.run(op, optionsOf(args), signalOf(args));
|
|
334
309
|
const notFound = () => runner.fail(table, dbError("not_found", `No ${table.key} row matched`));
|
|
335
310
|
const base = {
|
|
@@ -358,7 +333,7 @@ function createRepository(runner, table) {
|
|
|
358
333
|
findUnique(args) {
|
|
359
334
|
return AsyncResult.from(async () => {
|
|
360
335
|
const op = selectOp(args, {
|
|
361
|
-
where: builder.uniqueKey(table, args
|
|
336
|
+
where: builder.uniqueKey(table, args["where"]),
|
|
362
337
|
limit: 1
|
|
363
338
|
});
|
|
364
339
|
const result = await run(op, args);
|
|
@@ -379,8 +354,8 @@ function createRepository(runner, table) {
|
|
|
379
354
|
},
|
|
380
355
|
count(args) {
|
|
381
356
|
return AsyncResult.from(async () => {
|
|
382
|
-
const mode = args?.mode;
|
|
383
|
-
const op = selectOp({ where: args?.where }, {
|
|
357
|
+
const mode = args?.["mode"];
|
|
358
|
+
const op = selectOp({ where: args?.["where"] }, {
|
|
384
359
|
selection: {
|
|
385
360
|
columns: [],
|
|
386
361
|
includes: []
|
|
@@ -395,28 +370,28 @@ function createRepository(runner, table) {
|
|
|
395
370
|
aggregate(args) {
|
|
396
371
|
return AsyncResult.from(async () => {
|
|
397
372
|
const aggregation = builder.aggregation(table, args);
|
|
398
|
-
const orderBy = builder.orderBy(table, args
|
|
373
|
+
const orderBy = builder.orderBy(table, args["orderBy"]);
|
|
399
374
|
const grouped = new Set(aggregation.columns.map((c) => c.column));
|
|
400
375
|
const loose = orderBy.find((term) => !grouped.has(term.column));
|
|
401
376
|
if (loose) return runner.fail(table, dbError("invalid_request", `aggregate on "${table.key}" can only sort by groupBy columns, not "${loose.column}"`));
|
|
402
377
|
const op = selectOp({
|
|
403
|
-
where: args
|
|
404
|
-
limit: args
|
|
405
|
-
offset: args
|
|
378
|
+
where: args["where"],
|
|
379
|
+
limit: args["limit"],
|
|
380
|
+
offset: args["offset"]
|
|
406
381
|
}, {
|
|
407
382
|
selection: aggregation,
|
|
408
383
|
orderBy
|
|
409
384
|
});
|
|
410
385
|
const result = await run(op, args);
|
|
411
386
|
if (!result.ok) return result;
|
|
412
|
-
if (args
|
|
387
|
+
if (args["groupBy"] !== void 0) return ok(result.data.rows);
|
|
413
388
|
return ok(result.data.rows[0] ?? decodeRows(aggregation, [{}])[0] ?? {});
|
|
414
389
|
});
|
|
415
390
|
},
|
|
416
391
|
exists(args) {
|
|
417
392
|
return AsyncResult.from(async () => {
|
|
418
393
|
const columns = table.primaryKey.slice(0, 1).map((alias) => builder.selectColumn(table, alias));
|
|
419
|
-
const op = selectOp({ where: args?.where }, {
|
|
394
|
+
const op = selectOp({ where: args?.["where"] }, {
|
|
420
395
|
selection: {
|
|
421
396
|
columns,
|
|
422
397
|
includes: []
|
|
@@ -435,21 +410,21 @@ function createRepository(runner, table) {
|
|
|
435
410
|
const op = insertOp([data], args, void 0);
|
|
436
411
|
const result = await run(op, args);
|
|
437
412
|
if (!result.ok) return result;
|
|
438
|
-
return ok(args?.returning === false ? null : result.data.rows[0] ?? null);
|
|
413
|
+
return ok(args?.["returning"] === false ? null : result.data.rows[0] ?? null);
|
|
439
414
|
});
|
|
440
415
|
},
|
|
441
416
|
createMany(rows, args) {
|
|
442
417
|
return AsyncResult.from(async () => {
|
|
443
|
-
if (rows.length === 0) return ok(args?.returning === false ? { count: 0 } : []);
|
|
418
|
+
if (rows.length === 0) return ok(args?.["returning"] === false ? { count: 0 } : []);
|
|
444
419
|
const result = await run(insertOp(rows, args, void 0), args);
|
|
445
420
|
if (!result.ok) return result;
|
|
446
|
-
return ok(args?.returning === false ? { count: result.data.count ?? rows.length } : result.data.rows);
|
|
421
|
+
return ok(args?.["returning"] === false ? { count: result.data.count ?? rows.length } : result.data.rows);
|
|
447
422
|
});
|
|
448
423
|
},
|
|
449
424
|
update(id, patch, args) {
|
|
450
425
|
return AsyncResult.from(async () => {
|
|
451
426
|
const key = builder.primaryKey(table, id);
|
|
452
|
-
const expect = args?.expect ? builder.where(table, args
|
|
427
|
+
const expect = args?.["expect"] ? builder.where(table, args["expect"]) : void 0;
|
|
453
428
|
const op = {
|
|
454
429
|
kind: "update",
|
|
455
430
|
table,
|
|
@@ -481,8 +456,8 @@ function createRepository(runner, table) {
|
|
|
481
456
|
const op = {
|
|
482
457
|
kind: "update",
|
|
483
458
|
table,
|
|
484
|
-
set: builder.row(table, args
|
|
485
|
-
where: builder.where(table, args
|
|
459
|
+
set: builder.row(table, args["data"], "update"),
|
|
460
|
+
where: builder.where(table, args["where"]),
|
|
486
461
|
returning: void 0
|
|
487
462
|
};
|
|
488
463
|
const result = await run(op, args);
|
|
@@ -491,19 +466,19 @@ function createRepository(runner, table) {
|
|
|
491
466
|
},
|
|
492
467
|
upsert(data, args) {
|
|
493
468
|
return AsyncResult.from(async () => {
|
|
494
|
-
const op = insertOp([data], args, conflictColumns(args?.onConflict));
|
|
469
|
+
const op = insertOp([data], args, conflictColumns(args?.["onConflict"]));
|
|
495
470
|
const result = await run(op, args);
|
|
496
471
|
if (!result.ok) return result;
|
|
497
|
-
return ok(args?.returning === false ? null : result.data.rows[0] ?? null);
|
|
472
|
+
return ok(args?.["returning"] === false ? null : result.data.rows[0] ?? null);
|
|
498
473
|
});
|
|
499
474
|
},
|
|
500
475
|
upsertMany(rows, args) {
|
|
501
476
|
return AsyncResult.from(async () => {
|
|
502
|
-
if (rows.length === 0) return ok(args?.returning === false ? { count: 0 } : []);
|
|
503
|
-
const op = insertOp(rows, args, conflictColumns(args?.onConflict));
|
|
477
|
+
if (rows.length === 0) return ok(args?.["returning"] === false ? { count: 0 } : []);
|
|
478
|
+
const op = insertOp(rows, args, conflictColumns(args?.["onConflict"]));
|
|
504
479
|
const result = await run(op, args);
|
|
505
480
|
if (!result.ok) return result;
|
|
506
|
-
return ok(args?.returning === false ? { count: result.data.count ?? rows.length } : result.data.rows);
|
|
481
|
+
return ok(args?.["returning"] === false ? { count: result.data.count ?? rows.length } : result.data.rows);
|
|
507
482
|
});
|
|
508
483
|
},
|
|
509
484
|
delete(id, args) {
|
|
@@ -521,7 +496,7 @@ function createRepository(runner, table) {
|
|
|
521
496
|
},
|
|
522
497
|
deleteMany(args) {
|
|
523
498
|
return AsyncResult.from(async () => {
|
|
524
|
-
const where = builder.where(table, args
|
|
499
|
+
const where = builder.where(table, args["where"]);
|
|
525
500
|
if (!where) return runner.fail(table, dbError("invalid_request", "deleteMany needs a non-empty \"where\""));
|
|
526
501
|
const result = await run({
|
|
527
502
|
kind: "delete",
|
|
@@ -534,14 +509,15 @@ function createRepository(runner, table) {
|
|
|
534
509
|
}
|
|
535
510
|
};
|
|
536
511
|
function insertOp(rows, args, conflict) {
|
|
512
|
+
const built = rows.map((row) => builder.row(table, row));
|
|
537
513
|
return {
|
|
538
514
|
kind: "insert",
|
|
539
515
|
table,
|
|
540
|
-
rows:
|
|
516
|
+
rows: conflict && built.length > 1 ? byKey(built, conflict) : built,
|
|
541
517
|
returning: returning(args),
|
|
542
518
|
onConflict: conflict ? {
|
|
543
519
|
columns: conflict,
|
|
544
|
-
action: args?.ignoreDuplicates === true ? "ignore" : "update"
|
|
520
|
+
action: args?.["ignoreDuplicates"] === true ? "ignore" : "update"
|
|
545
521
|
} : void 0,
|
|
546
522
|
defaultToNull: false
|
|
547
523
|
};
|
|
@@ -557,11 +533,11 @@ function createRepository(runner, table) {
|
|
|
557
533
|
return invalidRequest(`Invalid onConflict on "${table.key}"`, table.key);
|
|
558
534
|
}
|
|
559
535
|
async function offsetPage(args) {
|
|
560
|
-
const size = Number(args
|
|
536
|
+
const size = Number(args["size"]);
|
|
561
537
|
if (!Number.isInteger(size) || size < 1) return runner.fail(table, dbError("invalid_request", "\"size\" must be a positive integer"));
|
|
562
|
-
const number = args
|
|
538
|
+
const number = args["page"] === void 0 ? 1 : Number(args["page"]);
|
|
563
539
|
if (!Number.isInteger(number) || number < 1) return runner.fail(table, dbError("invalid_request", "\"page\" must be a positive integer"));
|
|
564
|
-
const count = args
|
|
540
|
+
const count = args["count"];
|
|
565
541
|
const op = selectOp(args, {
|
|
566
542
|
limit: size + 1,
|
|
567
543
|
offset: (number - 1) * size,
|
|
@@ -583,19 +559,19 @@ function createRepository(runner, table) {
|
|
|
583
559
|
});
|
|
584
560
|
}
|
|
585
561
|
async function cursorPage(args) {
|
|
586
|
-
const size = Number(args
|
|
562
|
+
const size = Number(args["size"]);
|
|
587
563
|
if (!Number.isInteger(size) || size < 1) return runner.fail(table, dbError("invalid_request", "\"size\" must be a positive integer"));
|
|
588
|
-
const orderBy = withTieBreaker(builder.orderBy(table, args
|
|
564
|
+
const orderBy = withTieBreaker(builder.orderBy(table, args["orderBy"]));
|
|
589
565
|
const { selection: withSort, added } = ensureColumns(selection(args), orderBy);
|
|
590
566
|
let after;
|
|
591
|
-
if (typeof args
|
|
592
|
-
const values = decodeCursor(args
|
|
567
|
+
if (typeof args["after"] === "string") {
|
|
568
|
+
const values = decodeCursor(args["after"]);
|
|
593
569
|
if (!values || values.length !== orderBy.length) return runner.fail(table, dbError("invalid_request", "Invalid cursor"));
|
|
594
|
-
after = keysetCondition(orderBy, values);
|
|
570
|
+
after = keysetCondition(orderBy, values, (name) => Object.values(table.columns).find((meta) => meta.db === name)?.nullable ?? true);
|
|
595
571
|
}
|
|
596
572
|
const op = selectOp(args, {
|
|
597
573
|
selection: withSort,
|
|
598
|
-
where: and(builder.where(table, args
|
|
574
|
+
where: and(builder.where(table, args["where"]), after),
|
|
599
575
|
orderBy,
|
|
600
576
|
limit: size + 1,
|
|
601
577
|
offset: void 0
|
|
@@ -653,24 +629,47 @@ function strip(row, keys) {
|
|
|
653
629
|
for (const key of keys) delete copy[key];
|
|
654
630
|
return copy;
|
|
655
631
|
}
|
|
656
|
-
/**
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
632
|
+
/**
|
|
633
|
+
* Rows in conflict-key order, so concurrent upserts lock the same rows in
|
|
634
|
+
* the same order instead of deadlocking.
|
|
635
|
+
*/
|
|
636
|
+
function byKey(rows, columns) {
|
|
637
|
+
const compare = (left, right) => {
|
|
638
|
+
if (left === right) return 0;
|
|
639
|
+
if (left === null || left === void 0) return 1;
|
|
640
|
+
if (right === null || right === void 0) return -1;
|
|
641
|
+
if (typeof left === "number" && typeof right === "number") return left - right;
|
|
642
|
+
if (typeof left === "bigint" && typeof right === "bigint") return left < right ? -1 : 1;
|
|
643
|
+
const a = String(left);
|
|
644
|
+
const b = String(right);
|
|
645
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
646
|
+
};
|
|
647
|
+
return [...rows].sort((left, right) => {
|
|
648
|
+
for (const column of columns) {
|
|
649
|
+
const order = compare(left[column], right[column]);
|
|
650
|
+
if (order !== 0) return order;
|
|
651
|
+
}
|
|
652
|
+
return 0;
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
/**
|
|
656
|
+
* The rows after the cursor `values` in `orderBy` order, as an OR of ANDs:
|
|
657
|
+
* `a > x or (a = x and b > y)`. The SQL compiler sends that shape as the row
|
|
658
|
+
* comparison `(a, b) > (x, y)`. Nulls sort where Postgres puts them: last
|
|
659
|
+
* for `asc`, first for `desc`, unless the term says otherwise.
|
|
660
|
+
*/
|
|
661
|
+
function keysetCondition(orderBy, values, nullable) {
|
|
662
|
+
const isNull = (name) => column(name, "is", null);
|
|
663
|
+
const branches = orderBy.flatMap((term, index) => {
|
|
664
|
+
const value = values[index];
|
|
665
|
+
const nullsFirst = (term.nulls ?? (term.direction === "desc" ? "first" : "last")) === "first";
|
|
666
|
+
const after = column(term.column, term.direction === "asc" ? "gt" : "lt", value);
|
|
667
|
+
const step = value === null ? nullsFirst ? not(isNull(term.column)) : void 0 : nullsFirst || !nullable(term.column) ? after : or(after, isNull(term.column));
|
|
668
|
+
if (!step) return [];
|
|
669
|
+
const equal = orderBy.slice(0, index).map((prev, prevIndex) => values[prevIndex] === null ? isNull(prev.column) : column(prev.column, "eq", values[prevIndex]));
|
|
670
|
+
return [and(...equal, step) ?? step];
|
|
672
671
|
});
|
|
673
|
-
return or(...branches);
|
|
672
|
+
return branches.length > 0 ? or(...branches) : column(orderBy[0]?.column ?? "", "in", []);
|
|
674
673
|
}
|
|
675
674
|
//#endregion
|
|
676
675
|
//#region src/core/search.ts
|
|
@@ -707,6 +706,10 @@ var BetterSupabase = class BetterSupabase {
|
|
|
707
706
|
get claimsSchema() {
|
|
708
707
|
return this.options.claims;
|
|
709
708
|
}
|
|
709
|
+
/** The schema set by `userMetadata()`; its output types `session.profile`. */
|
|
710
|
+
get userMetadataSchema() {
|
|
711
|
+
return this.options.userMetadata;
|
|
712
|
+
}
|
|
710
713
|
/**
|
|
711
714
|
* Returns a new instance whose servers validate verified JWT claims (custom
|
|
712
715
|
* access token hook output) with `schema`, and whose sessions are typed by it.
|
|
@@ -723,6 +726,24 @@ var BetterSupabase = class BetterSupabase {
|
|
|
723
726
|
}, this.events);
|
|
724
727
|
}
|
|
725
728
|
/**
|
|
729
|
+
* Returns a new instance whose sessions parse `user_metadata` with
|
|
730
|
+
* `schema` into a typed `session.profile`. Users can change their metadata
|
|
731
|
+
* with `auth.updateUser()`, so a failure only leaves `profile` undefined
|
|
732
|
+
* (with one warning), and no authorization code reads it. It is for
|
|
733
|
+
* display only: roles, memberships, the tenant and entitlements come from
|
|
734
|
+
* the verified claims, never from `profile`.
|
|
735
|
+
*
|
|
736
|
+
* ```ts
|
|
737
|
+
* const sb = defineSupabase(schema).userMetadata(z.object({ display_name: z.string() }));
|
|
738
|
+
* ```
|
|
739
|
+
*/
|
|
740
|
+
userMetadata(schema) {
|
|
741
|
+
return new BetterSupabase(this.schema, this.plugins, {
|
|
742
|
+
...this.options,
|
|
743
|
+
userMetadata: schema
|
|
744
|
+
}, this.events);
|
|
745
|
+
}
|
|
746
|
+
/**
|
|
726
747
|
* Returns a new instance whose `.orThrow()` throws `mapper(error)` instead
|
|
727
748
|
* of a `DbException`, and whose results `toBetterResult` maps the same way.
|
|
728
749
|
* Results themselves keep their `DbError`.
|
|
@@ -793,7 +814,9 @@ var BetterSupabase = class BetterSupabase {
|
|
|
793
814
|
const invalidate = (target) => {
|
|
794
815
|
try {
|
|
795
816
|
const pending = adapter.invalidate(target);
|
|
796
|
-
if (pending) pending.catch((cause) =>
|
|
817
|
+
if (pending) pending.catch((cause) => {
|
|
818
|
+
report(cause, target.table);
|
|
819
|
+
});
|
|
797
820
|
} catch (cause) {
|
|
798
821
|
report(cause, target.table);
|
|
799
822
|
}
|
|
@@ -828,7 +851,7 @@ var BetterSupabase = class BetterSupabase {
|
|
|
828
851
|
context,
|
|
829
852
|
events,
|
|
830
853
|
errorMappers,
|
|
831
|
-
now: this.options.now ??
|
|
854
|
+
now: this.options.now ?? nowInstant,
|
|
832
855
|
maxRows: this.options.maxRows ?? 1e3,
|
|
833
856
|
truncatedTables: this.#truncatedTables
|
|
834
857
|
});
|
|
@@ -982,15 +1005,15 @@ var BetterSupabase = class BetterSupabase {
|
|
|
982
1005
|
const rows = entry.rows ?? [];
|
|
983
1006
|
const result = await runSpec(this.#db(client, {
|
|
984
1007
|
name: "read-set",
|
|
985
|
-
execute:
|
|
1008
|
+
execute: (op) => {
|
|
986
1009
|
if (op.kind === "select" && op.single) {
|
|
987
|
-
if (rows.length > 1) return err(dbError("multiple_rows", `Expected one ${op.table.key} row`));
|
|
988
|
-
if (rows.length === 0 && op.single === "one") return err(dbError("not_found", `No ${op.table.key} row matched`));
|
|
1010
|
+
if (rows.length > 1) return Promise.resolve(err(dbError("multiple_rows", `Expected one ${op.table.key} row`)));
|
|
1011
|
+
if (rows.length === 0 && op.single === "one") return Promise.resolve(err(dbError("not_found", `No ${op.table.key} row matched`)));
|
|
989
1012
|
}
|
|
990
|
-
return ok({
|
|
1013
|
+
return Promise.resolve(ok({
|
|
991
1014
|
rows,
|
|
992
1015
|
count: entry.count ?? null
|
|
993
|
-
});
|
|
1016
|
+
}));
|
|
994
1017
|
}
|
|
995
1018
|
}, context, [], new StatsRecorder(), new EventHub(this.events.logger)), spec, void 0);
|
|
996
1019
|
if (!result.ok) return result;
|
|
@@ -1011,7 +1034,7 @@ var BetterSupabase = class BetterSupabase {
|
|
|
1011
1034
|
repository[name] = method;
|
|
1012
1035
|
}
|
|
1013
1036
|
}
|
|
1014
|
-
repository
|
|
1037
|
+
repository["extend"] = (build) => ({
|
|
1015
1038
|
...repository,
|
|
1016
1039
|
...build(repository)
|
|
1017
1040
|
});
|
|
@@ -1065,4 +1088,4 @@ function defineSupabase(schema, options) {
|
|
|
1065
1088
|
return new BetterSupabase(schema, [], options);
|
|
1066
1089
|
}
|
|
1067
1090
|
//#endregion
|
|
1068
|
-
export { EventHub as a,
|
|
1091
|
+
export { EventHub as a, rowKey as c, encodeCursor as i, rpcCacheTargets as l, defineSupabase as n, cacheTargetOf as o, decodeCursor as r, memoryCache as s, BetterSupabase as t };
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
import { g as
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { a as
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
1
|
+
/// <reference lib="esnext.temporal" />
|
|
2
|
+
import { A as SchemaMeta, C as PrimaryKeyValue, D as Relations, E as RelationTypes, I as UniqueKeyName, L as UniqueWhere, N as TableKey, O as Row, P as TableMeta, R as Update, g as Insert, j as Simplify, k as Schema, n as AnyModels, t as AnyFunctions } from "./types-DONv9SHN.js";
|
|
3
|
+
import { g as Operation, l as CountMode, r as Executor } from "./executor-DynmIWhq.js";
|
|
4
|
+
import { p as DbError, s as ThrowMapper, t as AsyncResult, v as ErrorMapper } from "./result-c2OYgCV2.js";
|
|
5
|
+
import { a as EventHub, f as Logger, i as EventHandler, o as EventName, s as MutationNotice, u as RpcNotice } from "./events-Do8jXh4D.js";
|
|
6
|
+
import { a as ExtensionOf, g as WithExtension, h as RequestContext, n as AnyPlugin, r as ApplyExtension } from "./plugin-DVRB8qNE.js";
|
|
7
|
+
import { t as StandardSchemaV1 } from "./standard-eudBiRk1.js";
|
|
8
|
+
import { i as PostgrestPlan } from "./postgrest-DmBlevh-.js";
|
|
8
9
|
//#region src/ir/args.d.ts
|
|
9
10
|
interface BaseOps<V> {
|
|
10
11
|
readonly eq?: V;
|
|
@@ -147,7 +148,7 @@ interface AggregateArgs<M extends AnyModels, T extends keyof M> {
|
|
|
147
148
|
type SelectPart<M extends AnyModels, T extends keyof M, A> = A extends {
|
|
148
149
|
readonly select: readonly (infer K)[];
|
|
149
150
|
} ? Pick<Row<M, T>, Extract<K, keyof Row<M, T>>> : Row<M, T>;
|
|
150
|
-
type RelationPayload<M extends AnyModels, R, V> = R extends
|
|
151
|
+
type RelationPayload<M extends AnyModels, R, V> = R extends RelationTypes ? R["kind"] extends "many" ? Payload<M, Extract<R["table"], keyof M>, V extends true ? unknown : V>[] : R["nullable"] extends true ? Payload<M, Extract<R["table"], keyof M>, V extends true ? unknown : V> | null : Payload<M, Extract<R["table"], keyof M>, V extends true ? unknown : V> : never;
|
|
151
152
|
type IncludePart<M extends AnyModels, T extends keyof M, A> = A extends {
|
|
152
153
|
readonly include: infer I;
|
|
153
154
|
} ? { -readonly [R in keyof I & keyof Relations<M, T>]: RelationPayload<M, Relations<M, T>[R], I[R]>; } & CountPart<I> & ([keyof I & MeasureKey] extends [never] ? unknown : RelationMeasures<M, T, I>) : unknown;
|
|
@@ -551,7 +552,7 @@ declare function explainPostgrest(op: Operation): PostgrestPlan;
|
|
|
551
552
|
//#region src/core/define.d.ts
|
|
552
553
|
interface DefineSupabaseOptions {
|
|
553
554
|
/** Clock used by plugins (timestamps, soft delete). */
|
|
554
|
-
readonly now?: () =>
|
|
555
|
+
readonly now?: () => Temporal.Instant;
|
|
555
556
|
/** Extra error mappers, run before plugin mappers. */
|
|
556
557
|
readonly errors?: readonly ErrorMapper[];
|
|
557
558
|
/** Receives errors from event handlers, hooks and cache adapters. Defaults to `console`. */
|
|
@@ -562,6 +563,8 @@ interface DefineSupabaseOptions {
|
|
|
562
563
|
readonly throwAs?: ThrowMapper;
|
|
563
564
|
/** Validates verified JWT claims on the server. Prefer `sb.claims()`, which also types them. */
|
|
564
565
|
readonly claims?: StandardSchemaV1;
|
|
566
|
+
/** Parses `user_metadata` into `session.profile`. Prefer `sb.userMetadata()`, which also types it. */
|
|
567
|
+
readonly userMetadata?: StandardSchemaV1;
|
|
565
568
|
/**
|
|
566
569
|
* PostgREST's `db-max-rows`: the most rows one read returns. An unbounded
|
|
567
570
|
* `findMany` that returns this many sets `truncated` on the `query` event
|
|
@@ -586,7 +589,7 @@ interface RpcDefinition {
|
|
|
586
589
|
* The isomorphic definition of your data layer: schema plus plugins. Holds no
|
|
587
590
|
* secrets and no connection; `connect()` binds it to a client per request.
|
|
588
591
|
*/
|
|
589
|
-
declare class BetterSupabase<M extends AnyModels = AnyModels, D = unknown, F extends AnyFunctions = AnyFunctions, E = unknown, C = unknown> {
|
|
592
|
+
declare class BetterSupabase<M extends AnyModels = AnyModels, D = unknown, F extends AnyFunctions = AnyFunctions, E = unknown, C = unknown, P = unknown> {
|
|
590
593
|
#private;
|
|
591
594
|
readonly schema: Schema<M, D, F>;
|
|
592
595
|
readonly plugins: readonly AnyPlugin[];
|
|
@@ -596,6 +599,8 @@ declare class BetterSupabase<M extends AnyModels = AnyModels, D = unknown, F ext
|
|
|
596
599
|
get meta(): SchemaMeta;
|
|
597
600
|
/** The schema set by `claims()`; its output types `session.claims`. */
|
|
598
601
|
get claimsSchema(): StandardSchemaV1<unknown, C> | undefined;
|
|
602
|
+
/** The schema set by `userMetadata()`; its output types `session.profile`. */
|
|
603
|
+
get userMetadataSchema(): StandardSchemaV1<unknown, P> | undefined;
|
|
599
604
|
/**
|
|
600
605
|
* Returns a new instance whose servers validate verified JWT claims (custom
|
|
601
606
|
* access token hook output) with `schema`, and whose sessions are typed by it.
|
|
@@ -605,7 +610,20 @@ declare class BetterSupabase<M extends AnyModels = AnyModels, D = unknown, F ext
|
|
|
605
610
|
* const sb = defineSupabase(schema).claims(z.object({ tenant_id: z.uuid() }));
|
|
606
611
|
* ```
|
|
607
612
|
*/
|
|
608
|
-
claims<S extends StandardSchemaV1>(schema: S): BetterSupabase<M, D, F, E, StandardSchemaV1.InferOutput<S
|
|
613
|
+
claims<S extends StandardSchemaV1>(schema: S): BetterSupabase<M, D, F, E, StandardSchemaV1.InferOutput<S>, P>;
|
|
614
|
+
/**
|
|
615
|
+
* Returns a new instance whose sessions parse `user_metadata` with
|
|
616
|
+
* `schema` into a typed `session.profile`. Users can change their metadata
|
|
617
|
+
* with `auth.updateUser()`, so a failure only leaves `profile` undefined
|
|
618
|
+
* (with one warning), and no authorization code reads it. It is for
|
|
619
|
+
* display only: roles, memberships, the tenant and entitlements come from
|
|
620
|
+
* the verified claims, never from `profile`.
|
|
621
|
+
*
|
|
622
|
+
* ```ts
|
|
623
|
+
* const sb = defineSupabase(schema).userMetadata(z.object({ display_name: z.string() }));
|
|
624
|
+
* ```
|
|
625
|
+
*/
|
|
626
|
+
userMetadata<S extends StandardSchemaV1>(schema: S): BetterSupabase<M, D, F, E, C, StandardSchemaV1.InferOutput<S>>;
|
|
609
627
|
/**
|
|
610
628
|
* Returns a new instance whose `.orThrow()` throws `mapper(error)` instead
|
|
611
629
|
* of a `DbException`, and whose results `toBetterResult` maps the same way.
|
|
@@ -615,7 +633,7 @@ declare class BetterSupabase<M extends AnyModels = AnyModels, D = unknown, F ext
|
|
|
615
633
|
* const sb = defineSupabase(schema).mapError((error) => new AppError(error));
|
|
616
634
|
* ```
|
|
617
635
|
*/
|
|
618
|
-
mapError(mapper: (error: DbError) => unknown): BetterSupabase<M, D, F, E, C>;
|
|
636
|
+
mapError(mapper: (error: DbError) => unknown): BetterSupabase<M, D, F, E, C, P>;
|
|
619
637
|
/**
|
|
620
638
|
* Builds serializable `QuerySpec`s with the same arguments and result types
|
|
621
639
|
* as the repository: `sb.spec.customers.findMany({ select: ['id'] })`.
|
|
@@ -624,7 +642,7 @@ declare class BetterSupabase<M extends AnyModels = AnyModels, D = unknown, F ext
|
|
|
624
642
|
/** App keys of every table a spec reads; mutations of any of them make it stale. */
|
|
625
643
|
tablesOf(spec: QuerySpec): string[];
|
|
626
644
|
/** Returns a new instance with the plugin appended. */
|
|
627
|
-
use<
|
|
645
|
+
use<Q extends AnyPlugin>(plugin: Q): BetterSupabase<M, D, F, WithExtension<E, ExtensionOf<Q>>, C, P>;
|
|
628
646
|
/**
|
|
629
647
|
* Declares the tables an RPC writes, so cache adapters and live queries
|
|
630
648
|
* invalidate them after it succeeds.
|
|
@@ -635,7 +653,7 @@ declare class BetterSupabase<M extends AnyModels = AnyModels, D = unknown, F ext
|
|
|
635
653
|
*/
|
|
636
654
|
defineRpc(name: Extract<keyof F, string>, options: {
|
|
637
655
|
readonly invalidates: readonly TableKey<M>[];
|
|
638
|
-
}): BetterSupabase<M, D, F, E, C>;
|
|
656
|
+
}): BetterSupabase<M, D, F, E, C, P>;
|
|
639
657
|
/** Observes queries, mutations, errors, auth and refreshes. */
|
|
640
658
|
on<K extends EventName>(name: K, handler: EventHandler<K>): () => void;
|
|
641
659
|
/**
|
package/dist/edge/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as BetterSupabase } from "../define-
|
|
3
|
-
import { d as ServerContext, f as ServerOptions, l as BetterServer, n as GuardOptions } from "../respond-
|
|
4
|
-
import {
|
|
1
|
+
import { N as TableKey, n as AnyModels, t as AnyFunctions } from "../types-DONv9SHN.js";
|
|
2
|
+
import { t as BetterSupabase } from "../define-DUbydmJa.js";
|
|
3
|
+
import { d as ServerContext, f as ServerOptions, l as BetterServer, n as GuardOptions } from "../respond-DAkPIdTH.js";
|
|
4
|
+
import { a as ResourceRouteOptions } from "../resource-CwVgiI5q.js";
|
|
5
5
|
//#region src/edge/index.d.ts
|
|
6
6
|
export interface CorsOptions {
|
|
7
7
|
/** Allowed origins, or `*`. Defaults to `*`. */
|
package/dist/edge/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { n as dbError } from "../errors-Bl3rkOzo.js";
|
|
2
|
-
import { a as problemResponse } from "../problem-
|
|
3
|
-
import { i as respond, n as guard, o as createServer, s as extendServer, t as defaultExpose } from "../respond-
|
|
4
|
-
import { t as defineResource } from "../resource-
|
|
2
|
+
import { a as problemResponse } from "../problem-CGt1ADix.js";
|
|
3
|
+
import { i as respond, n as guard, o as createServer, s as extendServer, t as defaultExpose } from "../respond-C44EZAJo.js";
|
|
4
|
+
import { t as defineResource } from "../resource-D30rp0GN.js";
|
|
5
5
|
//#region src/edge/index.ts
|
|
6
6
|
const SUPABASE_CORS_HEADERS = [
|
|
7
7
|
"authorization",
|
|
@@ -54,7 +54,7 @@ function createEdge(sb, options = {}) {
|
|
|
54
54
|
});
|
|
55
55
|
const ctx = await server.context(request, { refresh: handlerOptions.refresh ?? false });
|
|
56
56
|
const instance = new URL(request.url).pathname;
|
|
57
|
-
const denied = guard(ctx.auth, handlerOptions.allow, handlerOptions.aal);
|
|
57
|
+
const denied = guard(ctx.auth, handlerOptions.allow, handlerOptions.aal, handlerOptions.scopes);
|
|
58
58
|
let response;
|
|
59
59
|
try {
|
|
60
60
|
response = denied ? problemResponse(denied, {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//#region src/auth/entitlements.ts
|
|
2
|
+
/**
|
|
3
|
+
* Whether the session's plan-features claim grants `key` in `tenantId`.
|
|
4
|
+
* `claim` is `config.claims.features` (default `features`), the claim
|
|
5
|
+
* `better_supabase.feature_claims()` fills. The claim is as fresh as the
|
|
6
|
+
* token: enforce it in RLS with `better_supabase.has_entitlement()`, and
|
|
7
|
+
* refresh the session after checkout.
|
|
8
|
+
*/
|
|
9
|
+
function hasEntitlement(session, tenantId, key, claim = "features") {
|
|
10
|
+
if (session.kind !== "user") return false;
|
|
11
|
+
const claims = session.claims;
|
|
12
|
+
if (!isRecord(claims)) return false;
|
|
13
|
+
const features = claims[claim];
|
|
14
|
+
if (!isRecord(features) || !Object.hasOwn(features, tenantId)) return false;
|
|
15
|
+
const keys = features[tenantId];
|
|
16
|
+
return Array.isArray(keys) && keys.includes(key);
|
|
17
|
+
}
|
|
18
|
+
const isRecord = (value) => typeof value === "object" && value !== null;
|
|
19
|
+
//#endregion
|
|
20
|
+
export { hasEntitlement as t };
|