better-supabase 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -33
- package/dist/base64-D2gsioCY.js +42 -0
- package/dist/claims-BAf6c7is.js +48 -0
- package/dist/cli/_format-Cax5EsM9.js +101 -0
- package/dist/cli/bin.js +39 -6
- package/dist/cli/command-CK14fP91.js +502 -0
- package/dist/cli/compare-BmIWVEui.js +9 -0
- package/dist/cli/config-D9R0o1LH.js +1895 -0
- package/dist/cli/config-SSKSTUl2.js +2 -0
- package/dist/cli/db-DOBPt660.js +52 -0
- package/dist/cli/dist-B1MvLv-M.js +129 -0
- package/dist/cli/dist-CFgGknmZ.js +1112 -0
- package/dist/cli/dist-Du7VnEUG.js +621 -0
- package/dist/cli/doctor-BOym3mbL.js +2382 -0
- package/dist/cli/env-BZ0uy8XK.js +108 -0
- package/dist/cli/env-jIFUADLY.js +511 -0
- package/dist/cli/errors-4v4DTtda.js +56 -0
- package/dist/cli/fastest-levenshtein-CFN-lNDv.js +120 -0
- package/dist/cli/gen-Ccn_p90L.js +2008 -0
- package/dist/cli/gen-D5cLCULx.js +2 -0
- package/dist/cli/index.d.ts +295 -28
- package/dist/cli/index.js +184 -3
- package/dist/cli/init-ClnxRYBF.js +550 -0
- package/dist/cli/introspect-DxqfkVIv.js +81 -0
- package/dist/cli/io-k41_z-jT.js +24 -0
- package/dist/cli/json5-ChRycquj.js +787 -0
- package/dist/cli/jsonc-BUniUpOk.js +2 -0
- package/dist/cli/jsonc-D5Fu67jw.js +45 -0
- package/dist/cli/keys-ByKHnvP9.js +83 -0
- package/dist/cli/ohash-D7bG_EOb.js +277 -0
- package/dist/cli/openapi-8WHjxiTJ.js +66 -0
- package/dist/cli/project-B_GeXyHh.js +70 -0
- package/dist/cli/prompts-BNcNfAve.js +1142 -0
- package/dist/cli/prompts-BTYQGunc.js +2 -0
- package/dist/cli/read-sets-CMa29t9a.js +971 -0
- package/dist/cli/rolldown-runtime-BPOCksWG.js +24 -0
- package/dist/cli/run-CP20LKk_.js +347 -0
- package/dist/cli/seed-5J6eu_Xg.js +98 -0
- package/dist/cli/skills-LJJIhLFR.js +137 -0
- package/dist/cli/sql-D4VbqmXi.js +199 -0
- package/dist/cli/style-C0NFdJRL.js +29 -0
- package/dist/cli/toml-DB-MNnFs.js +424 -0
- package/dist/{version-Cqq1m3UY.js → cli/version-5mW_8sY1.js} +1 -1
- package/dist/cli/yaml-CYCbJ6et.js +2252 -0
- package/dist/client/index.d.ts +2 -2
- package/dist/client/index.js +15 -25
- package/dist/{compiler-CZ9nIuqy.d.ts → compiler-DB3aSFOA.d.ts} +2 -2
- package/dist/config/index.d.ts +4 -3
- package/dist/config/index.js +5 -3
- package/dist/config-BpxDfnbg.js +129 -0
- package/dist/{index-DOsjFvMf.d.ts → config-C1CYcm6o.d.ts} +49 -49
- package/dist/{config-ClDXmVtY.js → config-CbvFmGD8.js} +14 -137
- package/dist/{define-BXMYD9AY.js → define-Bh0AqTik.js} +221 -120
- package/dist/{define-e3zI4_4g.d.ts → define-CRS2MRV3.d.ts} +36 -31
- package/dist/edge/index.d.ts +9 -13
- package/dist/edge/index.js +51 -25
- package/dist/{entitlements-Dng-ctuT.d.ts → entitlements-Dm-FHpNH.d.ts} +2 -2
- package/dist/env/index.js +203 -1
- package/dist/{errors-Bl3rkOzo.js → errors-L0xK41y_.js} +1 -1
- package/dist/events/index.d.ts +1 -1
- package/dist/events/index.js +139 -1
- package/dist/{events-DOt3nSO-.d.ts → events-B21UOhvP.d.ts} +4 -4
- package/dist/{executor-CGdNQ27g.d.ts → executor-B5IoUxLE.d.ts} +2 -2
- package/dist/{executor-DeppvirK.js → executor-CVt6dD0B.js} +9 -4
- package/dist/{executor-BYXQ9AGn.d.ts → executor-CZ7ImRiD.d.ts} +2 -2
- package/dist/hono/index.d.ts +17 -24
- package/dist/hono/index.js +11 -11
- package/dist/{index-DuP14VHo.d.ts → index-528Ugmyp.d.ts} +30 -10
- package/dist/{index-Bw1bwtC0.d.ts → index-BAy4tsAP.d.ts} +28 -15
- package/dist/{index-CBDufH1M.d.ts → index-BBdvo-5d.d.ts} +24 -26
- package/dist/{index-DbxFr7XG.d.ts → index-BhHEC04r.d.ts} +9 -4
- package/dist/index-Cf-D2jk1.d.ts +50 -0
- package/dist/{index-Ciu5Xlml.d.ts → index-D5IfUIDh.d.ts} +6 -5
- package/dist/{index-K-3WM2Hp.d.ts → index-DFmOpBGC.d.ts} +13 -13
- package/dist/{index-D4v7sncu.d.ts → index-RlLXd8dL.d.ts} +13 -13
- package/dist/index.d.ts +17 -17
- package/dist/index.js +23 -14
- package/dist/{invalidate-DbxuL2jL.js → invalidate-CgxmRamI.js} +7 -1
- package/dist/jobs/index.d.ts +33 -26
- package/dist/jobs/index.js +44 -22
- package/dist/{json-schema-BpYqkCKf.js → json-schema-DP6V7cbr.js} +8 -3
- package/dist/lint/index.js +1 -1
- package/dist/list/index.d.ts +2 -2
- package/dist/list/index.js +131 -96
- package/dist/{live-DJyZMD6w.d.ts → live-BHakSWWo.d.ts} +26 -16
- package/dist/{live-D8rV1Ldw.js → live-CdJBOc4f.js} +13 -9
- package/dist/lookup-BaP5bI27.js +18 -0
- package/dist/mcp/index.d.ts +34 -27
- package/dist/mcp/index.js +59 -25
- package/dist/{mfa-TVia554c.d.ts → mfa-C7MNQ1Ob.d.ts} +1 -1
- package/dist/{mfa-CpLfJSde.js → mfa-byfjruR9.js} +190 -46
- package/dist/next/image/index.js +6 -3
- package/dist/next/index.d.ts +64 -48
- package/dist/next/index.js +63 -50
- package/dist/openapi/index.d.ts +1 -1
- package/dist/openapi/index.js +61 -38
- package/dist/orpc/index.d.ts +18 -21
- package/dist/orpc/index.js +12 -12
- package/dist/otel/index.d.ts +5 -5
- package/dist/otel/index.js +84 -63
- package/dist/{permdock-sql-CghlHPuH.js → permdock-sql-C4KFzLc9.js} +12 -7
- package/dist/permdock-sql-DImJULY-.d.ts +17 -0
- package/dist/{plugin-C4TR9J0Z.d.ts → plugin-bNhvJwRh.d.ts} +5 -4
- package/dist/plugins/actor/index.d.ts +1 -1
- package/dist/plugins/actor/index.js +1 -1
- package/dist/plugins/rules/index.d.ts +2 -2
- package/dist/plugins/rules/index.js +46 -16
- package/dist/plugins/soft-delete/index.d.ts +3 -3
- package/dist/plugins/soft-delete/index.js +4 -4
- package/dist/plugins/tenant/index.d.ts +3 -3
- package/dist/plugins/tenant/index.js +10 -4
- package/dist/plugins/timestamps/index.d.ts +1 -1
- package/dist/plugins/timestamps/index.js +2 -2
- package/dist/plugins/validation/index.d.ts +2 -2
- package/dist/plugins/validation/index.js +3 -3
- package/dist/pool-DFwEQwmN.d.ts +78 -0
- package/dist/postgres/index.d.ts +10 -5
- package/dist/postgres/index.js +37 -16
- package/dist/{postgrest-cAEQ_IQN.d.ts → postgrest-Bc-0Xw62.d.ts} +1 -1
- package/dist/{problem-BTkTtRV9.js → problem-BihjPR0t.js} +11 -5
- package/dist/{problem-DlgB0lYl.d.ts → problem-U8UEKccv.d.ts} +6 -4
- package/dist/query/index.d.ts +2 -2
- package/dist/query/index.js +2 -2
- package/dist/{query-ChvDbsDE.js → query-BMMSWbI7.js} +19 -19
- package/dist/react/index.d.ts +7 -7
- package/dist/react/index.js +2 -2
- package/dist/react/server.d.ts +6 -6
- package/dist/react/server.js +3 -3
- package/dist/react/session.d.ts +21 -2
- package/dist/react/session.js +19 -1
- package/dist/{react-C83BdBGt.js → react-CQHMaESR.js} +59 -55
- package/dist/{read-set-4lI3W_gZ.js → read-set-FWK8qQ58.js} +51 -16
- package/dist/realtime/index.d.ts +4 -3
- package/dist/realtime/index.js +19 -17
- package/dist/{index-CG69s15v.d.ts → refresh-BwYkyNOQ.d.ts} +7 -3
- package/dist/{resolve-CjHILk2w.d.ts → resolve-BAqQcwMW.d.ts} +17 -11
- package/dist/{resource-CgZa3YG_.d.ts → resource-BJcaIfxi.d.ts} +17 -8
- package/dist/{resource-BHEWmQJK.js → resource-My_y-Syh.js} +43 -21
- package/dist/{respond-Dne1ARSa.d.ts → respond-DgIbdrt8.d.ts} +39 -14
- package/dist/{result-DWXatkd6.js → result-Bj6yt33D.js} +2 -2
- package/dist/{result-CTkCZ6JA.d.ts → result-CqEsbgYs.d.ts} +16 -11
- package/dist/server/index.d.ts +38 -13
- package/dist/server/index.js +43 -14
- package/dist/{respond-DMcbQwfN.js → server-BA75B0mT.js} +151 -96
- package/dist/{shared-_6-uPL7E.js → shared-DnoCdMDr.js} +4 -3
- package/dist/{simplify-bwJpLnaS.js → simplify-Cqvfr9dj.js} +76 -39
- package/dist/sql/index.d.ts +139 -0
- package/dist/sql/index.js +1983 -0
- package/dist/{sql-DTjA1LPj.js → sql-B34HU2DI.js} +74 -17
- package/dist/ssr/index.d.ts +4 -4
- package/dist/ssr/index.js +2 -2
- package/dist/{standard-FUi3Z3-7.js → standard-BRyBGTtp.js} +2 -2
- package/dist/{standard-CyhRzctb.d.ts → standard-BsaCYQJc.d.ts} +1 -1
- package/dist/{stats-C5W-rBfR.js → stats-C_YxA2r1.js} +40 -14
- package/dist/storage/index.d.ts +4 -3
- package/dist/storage/index.js +548 -1
- package/dist/{tables-rZxRxNPW.js → tables-Cb-3_VWc.js} +19 -5
- package/dist/temporal-BwshQk0W.js +27 -0
- package/dist/temporal-required-CBNHT6ni.js +19 -0
- package/dist/testing/index.d.ts +25 -24
- package/dist/testing/index.js +165 -66
- package/dist/{types-C83v5SQz.d.ts → types-DONv9SHN.d.ts} +14 -11
- package/dist/version-Bmf7_FzM.js +4 -0
- package/dist/{view-D1s0wa0T.d.ts → view-B64o81wp.d.ts} +36 -6
- package/dist/{view-aOYizTeE.js → view-BrJI2LKp.js} +11 -2
- package/dist/webhooks/index.d.ts +19 -17
- package/dist/webhooks/index.js +1 -1
- package/dist/{webhooks-DMipjhSP.js → webhooks-Bh_Jf_-l.js} +45 -24
- package/package.json +50 -22
- package/schemas/config-v1.json +31 -1
- package/schemas/doctor-report-v1.json +17 -1
- package/schemas/snapshot-v2.json +35 -0
- package/skills/better-supabase/SKILL.md +77 -18
- package/skills/better-supabase/references/plugins.md +21 -22
- package/skills/better-supabase/references/troubleshooting.md +38 -18
- package/skills/better-supabase-api/SKILL.md +66 -18
- package/skills/better-supabase-api/references/adapters.md +64 -41
- package/skills/better-supabase-auth/SKILL.md +146 -0
- package/skills/better-supabase-auth/references/permdock.md +55 -0
- package/skills/better-supabase-testing/SKILL.md +68 -11
- package/dist/casing-da0uRTqt.js +0 -14
- package/dist/claims-CoTobNC-.js +0 -25
- package/dist/cli-DrSgDOQC.js +0 -6646
- package/dist/env-BEToab0I.js +0 -204
- package/dist/events-BuzTgn2D.js +0 -135
- package/dist/pool-R2m_DkXi.d.ts +0 -37
- package/dist/seed-CzecODcJ.js +0 -101
- package/dist/session-C3LxnQ0e.d.ts +0 -22
- package/dist/session-CqEwzVup.js +0 -20
- package/dist/storage-DuGn38fr.js +0 -527
|
@@ -1,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-B5IoUxLE.js";
|
|
4
|
+
import { p as DbError, s as ThrowMapper, t as AsyncResult, v as ErrorMapper } from "./result-CqEsbgYs.js";
|
|
5
|
+
import { a as EventHub, f as Logger, i as EventHandler, o as EventName, s as MutationNotice, u as RpcNotice } from "./events-B21UOhvP.js";
|
|
6
|
+
import { a as ExtensionOf, g as WithExtension, h as RequestContext, n as AnyPlugin, r as ApplyExtension } from "./plugin-bNhvJwRh.js";
|
|
7
|
+
import { t as StandardSchemaV1 } from "./standard-BsaCYQJc.js";
|
|
8
|
+
import { i as PostgrestPlan } from "./postgrest-Bc-0Xw62.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;
|
|
@@ -177,13 +178,17 @@ type AggregateResult<M extends AnyModels, T extends keyof M, A> = A extends {
|
|
|
177
178
|
readonly groupBy: readonly unknown[];
|
|
178
179
|
} ? AggregateRow<M, T, A>[] : AggregateRow<M, T, A>;
|
|
179
180
|
/** The row type returned for read arguments `A` on table `T`. */
|
|
180
|
-
type Payload<M extends AnyModels, T extends keyof M, A> =
|
|
181
|
+
type Payload<M extends AnyModels, T extends keyof M, A> = A extends {
|
|
182
|
+
readonly include: unknown;
|
|
183
|
+
} ? Simplify<SelectPart<M, T, A> & IncludePart<M, T, A>> : A extends {
|
|
184
|
+
readonly select: readonly unknown[];
|
|
185
|
+
} ? Simplify<SelectPart<M, T, A>> : Row<M, T>;
|
|
181
186
|
//#endregion
|
|
182
187
|
//#region src/core/spec.d.ts
|
|
183
188
|
type ReadMethod = "findMany" | "findFirst" | "findUnique" | "findById" | "count" | "aggregate" | "exists" | "paginate";
|
|
184
189
|
declare const resultType: unique symbol;
|
|
185
190
|
/**
|
|
186
|
-
* A read, described as plain JSON: build it with `
|
|
191
|
+
* A read, described as plain JSON: build it with `betterSupabase.spec`, run it with
|
|
187
192
|
* `db.$run(spec)`, send it from a Server Component to the client, or hand it
|
|
188
193
|
* to `/query` and `/next`. Args never carry a `signal`.
|
|
189
194
|
*/
|
|
@@ -268,7 +273,7 @@ interface ReadSetOptions<P extends ReadSetParamTypes> {
|
|
|
268
273
|
*
|
|
269
274
|
* ```ts
|
|
270
275
|
* export const appChrome = defineReadSet(
|
|
271
|
-
*
|
|
276
|
+
* betterSupabase,
|
|
272
277
|
* 'app_chrome',
|
|
273
278
|
* { params: { userId: 'uuid' } },
|
|
274
279
|
* (s, p) => ({
|
|
@@ -281,7 +286,7 @@ interface ReadSetOptions<P extends ReadSetParamTypes> {
|
|
|
281
286
|
* `p` holds placeholders, not values: pass them straight into `where` (or
|
|
282
287
|
* `in`), where the function reads them from its `p jsonb` argument.
|
|
283
288
|
*/
|
|
284
|
-
declare function defineReadSet<M extends AnyModels, D, F extends AnyFunctions, E, const N extends string, const P extends ReadSetParamTypes, const S extends Readonly<Record<string, QuerySpec>>>(
|
|
289
|
+
declare function defineReadSet<M extends AnyModels, D, F extends AnyFunctions, E, const N extends string, const P extends ReadSetParamTypes, const S extends Readonly<Record<string, QuerySpec>>>(betterSupabase: BetterSupabase<M, D, F, E>, name: N, options: ReadSetOptions<P>, build: (specs: Specs<M, E>, params: ReadSetParams<P>) => S): ReadSet<N, P, S>;
|
|
285
290
|
declare function isReadSet(value: unknown): value is ReadSet;
|
|
286
291
|
/** App keys of every table the set reads. */
|
|
287
292
|
declare function readSetTables(set: ReadSet, meta?: SchemaMeta): string[];
|
|
@@ -384,7 +389,7 @@ type PageOf<M extends AnyModels, T extends keyof M, A> = A extends {
|
|
|
384
389
|
readonly after: unknown;
|
|
385
390
|
} ? CursorPage<Payload<M, T, A>> : OffsetPage<Payload<M, T, A>>;
|
|
386
391
|
interface Repository<M extends AnyModels, T extends TableKey<M>, E = unknown> {
|
|
387
|
-
readonly $
|
|
392
|
+
readonly $tableName: T;
|
|
388
393
|
readonly $meta: TableMeta;
|
|
389
394
|
findMany<const A extends FindManyArgs<M, T> & FindExt<E, M, T>>(args?: A): AsyncResult<Payload<M, T, A>[]>;
|
|
390
395
|
findFirst<const A extends FindFirstArgs<M, T> & FindExt<E, M, T>>(args?: A): AsyncResult<Payload<M, T, A> | null>;
|
|
@@ -470,7 +475,7 @@ interface DbHelpers<M extends AnyModels, F extends AnyFunctions, E, C> {
|
|
|
470
475
|
$table<T extends TableKey<M>>(name: T): RepositoryOf<M, T, E>;
|
|
471
476
|
/** Calls, waves, tables and time for everything run through this `db`. */
|
|
472
477
|
$stats(): DbStats;
|
|
473
|
-
/** Runs a `QuerySpec` built with `
|
|
478
|
+
/** Runs a `QuerySpec` built with `betterSupabase.spec`. */
|
|
474
479
|
$run<S extends QuerySpec<TableKey<M>>>(spec: S, options?: {
|
|
475
480
|
readonly signal?: AbortSignal;
|
|
476
481
|
}): AsyncResult<InferResult<S>>;
|
|
@@ -515,7 +520,7 @@ interface CacheTarget {
|
|
|
515
520
|
/**
|
|
516
521
|
* Invalidates cached reads after a mutation. First-party adapters:
|
|
517
522
|
* `nextCache()` (Next.js cache tags) and `queryCache(client)` (TanStack
|
|
518
|
-
* Query). Attach one with `
|
|
523
|
+
* Query). Attach one with `betterSupabase.cache(adapter)`; prove custom ones with
|
|
519
524
|
* `testCacheAdapter`.
|
|
520
525
|
*/
|
|
521
526
|
interface CacheAdapter {
|
|
@@ -549,20 +554,20 @@ declare function postgrestExecutor(client: PostgrestClientLike): Executor;
|
|
|
549
554
|
declare function explainPostgrest(op: Operation): PostgrestPlan;
|
|
550
555
|
//#endregion
|
|
551
556
|
//#region src/core/define.d.ts
|
|
552
|
-
interface
|
|
557
|
+
interface SupabaseOptions {
|
|
553
558
|
/** Clock used by plugins (timestamps, soft delete). */
|
|
554
|
-
readonly now?: () =>
|
|
559
|
+
readonly now?: () => Temporal.Instant;
|
|
555
560
|
/** Extra error mappers, run before plugin mappers. */
|
|
556
561
|
readonly errors?: readonly ErrorMapper[];
|
|
557
562
|
/** Receives errors from event handlers, hooks and cache adapters. Defaults to `console`. */
|
|
558
563
|
readonly logger?: Logger;
|
|
559
|
-
/** RPCs that change tables, keyed by function name. Prefer `
|
|
564
|
+
/** RPCs that change tables, keyed by function name. Prefer `betterSupabase.defineRpc()`. */
|
|
560
565
|
readonly rpc?: Readonly<Record<string, RpcDefinition>>;
|
|
561
|
-
/** Builds the error `.orThrow()` throws. Prefer `
|
|
566
|
+
/** Builds the error `.orThrow()` throws. Prefer `betterSupabase.mapError()`. */
|
|
562
567
|
readonly throwAs?: ThrowMapper;
|
|
563
|
-
/** Validates verified JWT claims on the server. Prefer `
|
|
568
|
+
/** Validates verified JWT claims on the server. Prefer `betterSupabase.claims()`, which also types them. */
|
|
564
569
|
readonly claims?: StandardSchemaV1;
|
|
565
|
-
/** Parses `user_metadata` into `session.profile`. Prefer `
|
|
570
|
+
/** Parses `user_metadata` into `session.profile`. Prefer `betterSupabase.userMetadata()`, which also types it. */
|
|
566
571
|
readonly userMetadata?: StandardSchemaV1;
|
|
567
572
|
/**
|
|
568
573
|
* PostgREST's `db-max-rows`: the most rows one read returns. An unbounded
|
|
@@ -593,8 +598,8 @@ declare class BetterSupabase<M extends AnyModels = AnyModels, D = unknown, F ext
|
|
|
593
598
|
readonly schema: Schema<M, D, F>;
|
|
594
599
|
readonly plugins: readonly AnyPlugin[];
|
|
595
600
|
readonly events: EventHub;
|
|
596
|
-
readonly options:
|
|
597
|
-
constructor(schema: Schema<M, D, F>, plugins?: readonly AnyPlugin[], options?:
|
|
601
|
+
readonly options: SupabaseOptions;
|
|
602
|
+
constructor(schema: Schema<M, D, F>, plugins?: readonly AnyPlugin[], options?: SupabaseOptions, events?: EventHub);
|
|
598
603
|
get meta(): SchemaMeta;
|
|
599
604
|
/** The schema set by `claims()`; its output types `session.claims`. */
|
|
600
605
|
get claimsSchema(): StandardSchemaV1<unknown, C> | undefined;
|
|
@@ -606,7 +611,7 @@ declare class BetterSupabase<M extends AnyModels = AnyModels, D = unknown, F ext
|
|
|
606
611
|
* A token that fails it resolves to `{ kind: 'invalid', reason: 'claims' }`.
|
|
607
612
|
*
|
|
608
613
|
* ```ts
|
|
609
|
-
* const
|
|
614
|
+
* const betterSupabase = defineSupabase(schema).claims(z.object({ tenant_id: z.uuid() }));
|
|
610
615
|
* ```
|
|
611
616
|
*/
|
|
612
617
|
claims<S extends StandardSchemaV1>(schema: S): BetterSupabase<M, D, F, E, StandardSchemaV1.InferOutput<S>, P>;
|
|
@@ -619,7 +624,7 @@ declare class BetterSupabase<M extends AnyModels = AnyModels, D = unknown, F ext
|
|
|
619
624
|
* the verified claims, never from `profile`.
|
|
620
625
|
*
|
|
621
626
|
* ```ts
|
|
622
|
-
* const
|
|
627
|
+
* const betterSupabase = defineSupabase(schema).userMetadata(z.object({ display_name: z.string() }));
|
|
623
628
|
* ```
|
|
624
629
|
*/
|
|
625
630
|
userMetadata<S extends StandardSchemaV1>(schema: S): BetterSupabase<M, D, F, E, C, StandardSchemaV1.InferOutput<S>>;
|
|
@@ -629,13 +634,13 @@ declare class BetterSupabase<M extends AnyModels = AnyModels, D = unknown, F ext
|
|
|
629
634
|
* Results themselves keep their `DbError`.
|
|
630
635
|
*
|
|
631
636
|
* ```ts
|
|
632
|
-
* const
|
|
637
|
+
* const betterSupabase = defineSupabase(schema).mapError((error) => new AppError(error));
|
|
633
638
|
* ```
|
|
634
639
|
*/
|
|
635
640
|
mapError(mapper: (error: DbError) => unknown): BetterSupabase<M, D, F, E, C, P>;
|
|
636
641
|
/**
|
|
637
642
|
* Builds serializable `QuerySpec`s with the same arguments and result types
|
|
638
|
-
* as the repository: `
|
|
643
|
+
* as the repository: `betterSupabase.spec.customers.findMany({ select: ['id'] })`.
|
|
639
644
|
*/
|
|
640
645
|
get spec(): Specs<M, E>;
|
|
641
646
|
/** App keys of every table a spec reads; mutations of any of them make it stale. */
|
|
@@ -647,7 +652,7 @@ declare class BetterSupabase<M extends AnyModels = AnyModels, D = unknown, F ext
|
|
|
647
652
|
* invalidate them after it succeeds.
|
|
648
653
|
*
|
|
649
654
|
* ```ts
|
|
650
|
-
*
|
|
655
|
+
* betterSupabase.defineRpc('archive_customer', { invalidates: ['customers', 'notes'] });
|
|
651
656
|
* ```
|
|
652
657
|
*/
|
|
653
658
|
defineRpc(name: Extract<keyof F, string>, options: {
|
|
@@ -671,9 +676,9 @@ declare class BetterSupabase<M extends AnyModels = AnyModels, D = unknown, F ext
|
|
|
671
676
|
* Creates the data-layer definition from the generated `schema`.
|
|
672
677
|
*
|
|
673
678
|
* ```ts
|
|
674
|
-
* export const
|
|
679
|
+
* export const betterSupabase = defineSupabase(schema).use(timestamps()).use(softDelete());
|
|
675
680
|
* ```
|
|
676
681
|
*/
|
|
677
|
-
declare function defineSupabase<M extends AnyModels, D, F extends AnyFunctions>(schema: Schema<M, D, F>, options?:
|
|
682
|
+
declare function defineSupabase<M extends AnyModels, D, F extends AnyFunctions>(schema: Schema<M, D, F>, options?: SupabaseOptions): BetterSupabase<M, D, F>;
|
|
678
683
|
//#endregion
|
|
679
|
-
export { Specs as $, RpcOptions as A, ReadSet as B, FindExt as C, WhereInput as Ct, Repository as D, PageOf as E, EMPTY_STATS as F, ReadSetParams as G, ReadSetParamType as H, StatsRecorder as I, isReadSet as J, ReadSetResult as K, recordStats as L, UpsertArgs as M, WriteArgs as N, RepositoryOf as O, DbStats as P, ReadMethod as Q, SearchArgs as R, DeleteExt as S, SortDirection as St, OffsetPageArgs as T, ReadSetParamTypes as U, ReadSetOptions as V, ReadSetParamValue as W, InferResult as X, readSetTables as Y, QuerySpec as Z, CursorPage as _, OrderByInput as _t, defineSupabase as a, AggregateRow as at, DbHelpers as b, RelationMeasureArg as bt, postgrestExecutor as c, FieldFilter as ct, MemoryCache as d, IncludeArg as dt, TableSpecs as et, cacheTargetOf as f, IncludeArgs as ft, ConflictTarget as g, OrderByArg as gt, rpcCacheTargets as h, NumericMeasureArg as ht,
|
|
684
|
+
export { Specs as $, RpcOptions as A, ReadSet as B, FindExt as C, WhereInput as Ct, Repository as D, PageOf as E, EMPTY_STATS as F, ReadSetParams as G, ReadSetParamType as H, StatsRecorder as I, isReadSet as J, ReadSetResult as K, recordStats as L, UpsertArgs as M, WriteArgs as N, RepositoryOf as O, DbStats as P, ReadMethod as Q, SearchArgs as R, DeleteExt as S, SortDirection as St, OffsetPageArgs as T, ReadSetParamTypes as U, ReadSetOptions as V, ReadSetParamValue as W, InferResult as X, readSetTables as Y, QuerySpec as Z, CursorPage as _, OrderByInput as _t, defineSupabase as a, AggregateRow as at, DbHelpers as b, RelationMeasureArg as bt, postgrestExecutor as c, FieldFilter as ct, MemoryCache as d, IncludeArg as dt, TableSpecs as et, cacheTargetOf as f, IncludeArgs as ft, ConflictTarget as g, OrderByArg as gt, rpcCacheTargets as h, NumericMeasureArg as ht, SupabaseOptions as i, AggregateResult as it, UpdateArgs as j, Returned as k, CacheAdapter as l, FindFirstArgs as lt, rowKey as m, MeasureKey as mt, ConnectOptions as n, specTables as nt, PostgrestClientLike as o, CountArg as ot, memoryCache as p, MeasureArg as pt, defineReadSet as q, RpcDefinition as r, AggregateArgs as rt, explainPostgrest as s, CountArgs as st, BetterSupabase as t, isQuerySpec as tt, CacheTarget as u, FindManyArgs as ut, CursorPageArgs as v, Payload as vt, OffsetPage as w, DeleteArgs as x, SelectArg as xt, Db as y, ReadArgs as yt, InferReadSetParams as z };
|
package/dist/edge/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { N as TableKey, n as AnyModels, t as AnyFunctions } from "../types-
|
|
2
|
-
import { t as BetterSupabase } from "../define-
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { N as TableKey, n as AnyModels, t as AnyFunctions } from "../types-DONv9SHN.js";
|
|
2
|
+
import { t as BetterSupabase } from "../define-CRS2MRV3.js";
|
|
3
|
+
import { f as ServerContext, n as GuardOptions, p as ServerOptions, r as MiddlewareOptions, u as BetterServer } from "../respond-DgIbdrt8.js";
|
|
4
|
+
import { a as ResourceRouteOptions } from "../resource-BJcaIfxi.js";
|
|
5
5
|
//#region src/edge/index.d.ts
|
|
6
6
|
export interface CorsOptions {
|
|
7
7
|
/** Allowed origins, or `*`. Defaults to `*`. */
|
|
@@ -17,27 +17,23 @@ export interface EdgeOptions extends ServerOptions {
|
|
|
17
17
|
/** Include error details in problem responses. Defaults to `NODE_ENV === 'development'`. */
|
|
18
18
|
readonly exposeErrors?: boolean;
|
|
19
19
|
}
|
|
20
|
-
export interface HandlerOptions extends GuardOptions {
|
|
21
|
-
/** Refresh an expired cookie session and send the new cookies. */
|
|
22
|
-
readonly refresh?: boolean;
|
|
23
|
-
}
|
|
24
20
|
export type EdgeHandler = (request: Request) => Promise<Response>;
|
|
25
21
|
export type ResourceMap<M extends AnyModels> = { readonly [T in TableKey<M>]?: ResourceRouteOptions<M, T> | true; };
|
|
26
|
-
export interface ResourcesOptions extends
|
|
22
|
+
export interface ResourcesOptions extends MiddlewareOptions {
|
|
27
23
|
/** Path before the resources, e.g. `/api` (Supabase: `/<function-name>`). */
|
|
28
24
|
readonly basePath?: string;
|
|
29
25
|
}
|
|
30
|
-
export interface BetterEdge<M extends AnyModels, F extends AnyFunctions, E> extends BetterServer<M, F, E> {
|
|
26
|
+
export interface BetterEdge<M extends AnyModels, F extends AnyFunctions, E, C = unknown, P = unknown> extends BetterServer<M, F, E, C, P> {
|
|
31
27
|
/**
|
|
32
28
|
* A fetch handler (`Deno.serve`, Workers `fetch`) running as the caller.
|
|
33
29
|
* `Result`s become JSON or Problem Details; `undefined` becomes 204.
|
|
34
30
|
*/
|
|
35
|
-
handler(fn: (request: Request, ctx: ServerContext<M, F, E>) => unknown, options?:
|
|
31
|
+
handler(fn: (request: Request, ctx: ServerContext<M, F, E, C, P>) => unknown, options?: MiddlewareOptions): EdgeHandler;
|
|
36
32
|
/** REST resources matching `createOpenApi`, e.g. `Deno.serve(bs.resources({ customers: true }))`. */
|
|
37
33
|
resources(map: ResourceMap<M>, options?: ResourcesOptions): EdgeHandler;
|
|
38
34
|
}
|
|
39
35
|
export declare const SUPABASE_CORS_HEADERS: readonly string[];
|
|
40
36
|
/** Fetch-handler integration for Supabase Edge Functions, Deno, Bun and Workers. */
|
|
41
|
-
export declare function createEdge<M extends AnyModels, D, F extends AnyFunctions, E>(
|
|
37
|
+
export declare function createEdge<M extends AnyModels, D, F extends AnyFunctions, E, C = unknown, P = unknown>(betterSupabase: BetterSupabase<M, D, F, E, C, P>, options?: EdgeOptions): BetterEdge<M, F, E, C, P>;
|
|
42
38
|
//#endregion
|
|
43
|
-
export type { GuardOptions, ResourceRouteOptions };
|
|
39
|
+
export type { GuardOptions, MiddlewareOptions, ResourceRouteOptions };
|
package/dist/edge/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { n as dbError } from "../errors-
|
|
2
|
-
import { a as problemResponse } from "../problem-
|
|
3
|
-
import {
|
|
4
|
-
import { t as defineResource } from "../resource-
|
|
1
|
+
import { n as dbError } from "../errors-L0xK41y_.js";
|
|
2
|
+
import { a as problemResponse } from "../problem-BihjPR0t.js";
|
|
3
|
+
import { a as guard, i as defaultExpose, n as extendServer, s as respond, t as createServer } from "../server-BA75B0mT.js";
|
|
4
|
+
import { t as defineResource } from "../resource-My_y-Syh.js";
|
|
5
5
|
//#region src/edge/index.ts
|
|
6
6
|
const SUPABASE_CORS_HEADERS = [
|
|
7
7
|
"authorization",
|
|
@@ -9,15 +9,11 @@ const SUPABASE_CORS_HEADERS = [
|
|
|
9
9
|
"apikey",
|
|
10
10
|
"content-type"
|
|
11
11
|
];
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
/** The CORS headers for a request's origin; the fixed ones are joined once. */
|
|
13
|
+
function corsFor(cors) {
|
|
14
14
|
const allowed = cors.origin ?? "*";
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
else if (origin && (typeof allowed === "string" ? [allowed] : allowed).includes(origin)) value = origin;
|
|
18
|
-
if (!value) return void 0;
|
|
19
|
-
return {
|
|
20
|
-
"access-control-allow-origin": value,
|
|
15
|
+
const origins = new Set(typeof allowed === "string" ? [allowed] : allowed);
|
|
16
|
+
const fixed = {
|
|
21
17
|
"access-control-allow-headers": (cors.headers ?? SUPABASE_CORS_HEADERS).join(", "),
|
|
22
18
|
"access-control-allow-methods": (cors.methods ?? [
|
|
23
19
|
"GET",
|
|
@@ -26,8 +22,21 @@ function corsHeaders(request, cors) {
|
|
|
26
22
|
"DELETE",
|
|
27
23
|
"OPTIONS"
|
|
28
24
|
]).join(", "),
|
|
29
|
-
...cors.maxAge === void 0 ? {} : { "access-control-max-age": String(cors.maxAge) }
|
|
30
|
-
|
|
25
|
+
...cors.maxAge === void 0 ? {} : { "access-control-max-age": String(cors.maxAge) }
|
|
26
|
+
};
|
|
27
|
+
const any = {
|
|
28
|
+
"access-control-allow-origin": "*",
|
|
29
|
+
...fixed
|
|
30
|
+
};
|
|
31
|
+
return (request) => {
|
|
32
|
+
if (allowed === "*") return any;
|
|
33
|
+
const origin = request.headers.get("origin");
|
|
34
|
+
if (!origin || !origins.has(origin)) return;
|
|
35
|
+
return {
|
|
36
|
+
"access-control-allow-origin": origin,
|
|
37
|
+
...fixed,
|
|
38
|
+
vary: "origin"
|
|
39
|
+
};
|
|
31
40
|
};
|
|
32
41
|
}
|
|
33
42
|
function withHeaders(response, headers) {
|
|
@@ -41,20 +50,23 @@ function withHeaders(response, headers) {
|
|
|
41
50
|
return target;
|
|
42
51
|
}
|
|
43
52
|
/** Fetch-handler integration for Supabase Edge Functions, Deno, Bun and Workers. */
|
|
44
|
-
function createEdge(
|
|
45
|
-
const server = createServer(
|
|
53
|
+
function createEdge(betterSupabase, options = {}) {
|
|
54
|
+
const server = createServer(betterSupabase, options);
|
|
46
55
|
const expose = options.exposeErrors ?? defaultExpose();
|
|
47
56
|
const cors = options.cors === true ? {} : options.cors === false ? void 0 : options.cors;
|
|
48
|
-
const
|
|
57
|
+
const corsHeaders = cors ? corsFor(cors) : void 0;
|
|
58
|
+
const serve = (run, handlerOptions, early) => {
|
|
49
59
|
return async (request) => {
|
|
50
|
-
const extra =
|
|
60
|
+
const extra = corsHeaders?.(request);
|
|
51
61
|
if (cors && request.method === "OPTIONS") return new Response(null, {
|
|
52
62
|
status: 204,
|
|
53
63
|
headers: extra ?? {}
|
|
54
64
|
});
|
|
65
|
+
const answered = early?.(request);
|
|
66
|
+
if (answered) return extra ? withHeaders(answered, extra) : answered;
|
|
55
67
|
const ctx = await server.context(request, { refresh: handlerOptions.refresh ?? false });
|
|
56
68
|
const instance = new URL(request.url).pathname;
|
|
57
|
-
const denied = guard(ctx.auth, handlerOptions.allow, handlerOptions.aal);
|
|
69
|
+
const denied = guard(ctx.auth, handlerOptions.allow, handlerOptions.aal, handlerOptions.scopes);
|
|
58
70
|
let response;
|
|
59
71
|
try {
|
|
60
72
|
response = denied ? problemResponse(denied, {
|
|
@@ -83,19 +95,33 @@ function createEdge(sb, options = {}) {
|
|
|
83
95
|
const handlers = /* @__PURE__ */ new Map();
|
|
84
96
|
for (const [table, resource] of Object.entries(map)) {
|
|
85
97
|
if (!resource) continue;
|
|
86
|
-
handlers.set(table, defineResource(
|
|
98
|
+
handlers.set(table, defineResource(betterSupabase, table, resource === true ? {} : resource));
|
|
87
99
|
}
|
|
88
|
-
|
|
100
|
+
const routes = /* @__PURE__ */ new WeakMap();
|
|
101
|
+
const notFound = (request) => {
|
|
89
102
|
const { pathname } = new URL(request.url);
|
|
90
|
-
const instance = pathname;
|
|
91
103
|
const [table, id, extra] = (pathname.startsWith(`${base}/`) ? pathname.slice(base.length + 1) : void 0)?.split("/") ?? [];
|
|
92
104
|
const handler = table ? handlers.get(table) : void 0;
|
|
93
|
-
if (!handler || extra !== void 0 || id !== void 0 && !handler.keyParam) return problemResponse(dbError("not_found", `No route for ${pathname}`), { instance });
|
|
94
|
-
|
|
105
|
+
if (!handler || extra !== void 0 || id !== void 0 && !handler.keyParam) return problemResponse(dbError("not_found", `No route for ${pathname}`), { instance: pathname });
|
|
106
|
+
let key;
|
|
107
|
+
try {
|
|
108
|
+
key = id === void 0 || id === "" ? void 0 : decodeURIComponent(id);
|
|
109
|
+
} catch {
|
|
110
|
+
return problemResponse(dbError("invalid_request", `Malformed id in ${pathname}`), { instance: pathname });
|
|
111
|
+
}
|
|
112
|
+
routes.set(request, {
|
|
113
|
+
handler,
|
|
114
|
+
id: key,
|
|
115
|
+
instance: pathname
|
|
116
|
+
});
|
|
117
|
+
};
|
|
118
|
+
return serve((request, ctx) => {
|
|
119
|
+
const { handler, id, instance } = routes.get(request);
|
|
120
|
+
return handler.handle(request, ctx.db, id, {
|
|
95
121
|
instance,
|
|
96
122
|
expose
|
|
97
123
|
});
|
|
98
|
-
}, resourcesOptions);
|
|
124
|
+
}, resourcesOptions, notFound);
|
|
99
125
|
}
|
|
100
126
|
});
|
|
101
127
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as AuthSession } from "./view-
|
|
1
|
+
import { t as AuthSession } from "./view-B64o81wp.js";
|
|
2
2
|
//#region src/auth/entitlements.d.ts
|
|
3
3
|
/**
|
|
4
4
|
* One entry of the `memberships` claim, in PermDock's shape. PermDock strips
|
|
@@ -25,7 +25,7 @@ interface MembershipClaim {
|
|
|
25
25
|
}
|
|
26
26
|
/**
|
|
27
27
|
* Entitlement keys of the `features` claim: the literal union when
|
|
28
|
-
* `
|
|
28
|
+
* `betterSupabase.claims(schema)` declares one (`z.enum([...])`), otherwise `string`.
|
|
29
29
|
*/
|
|
30
30
|
type EntitlementKey<C> = C extends {
|
|
31
31
|
readonly features?: infer F;
|
package/dist/env/index.js
CHANGED
|
@@ -1,2 +1,204 @@
|
|
|
1
|
-
|
|
1
|
+
//#region src/env/index.ts
|
|
2
|
+
const PREFIXES = [
|
|
3
|
+
"",
|
|
4
|
+
"NEXT_PUBLIC_",
|
|
5
|
+
"VITE_",
|
|
6
|
+
"PUBLIC_",
|
|
7
|
+
"EXPO_PUBLIC_",
|
|
8
|
+
"NUXT_PUBLIC_"
|
|
9
|
+
];
|
|
10
|
+
const ENV_VARIABLES = {
|
|
11
|
+
url: PREFIXES.map((prefix) => `${prefix}SUPABASE_URL`),
|
|
12
|
+
publishableKey: PREFIXES.flatMap((prefix) => [`${prefix}SUPABASE_PUBLISHABLE_KEY`, `${prefix}SUPABASE_PUBLISHABLE_DEFAULT_KEY`]),
|
|
13
|
+
secretKey: ["SUPABASE_SECRET_KEY"],
|
|
14
|
+
dbUrl: ["SUPABASE_DB_URL", "DATABASE_URL"],
|
|
15
|
+
jwksUrl: ["SUPABASE_JWKS_URL"],
|
|
16
|
+
readUrl: ["SUPABASE_READ_URL"]
|
|
17
|
+
};
|
|
18
|
+
const LOOPBACK = /^(localhost|127(?:\.\d{1,3}){3}|\[::1\])$/;
|
|
19
|
+
const HOSTED = /^([a-z0-9]{20})\.supabase\.co$/;
|
|
20
|
+
var EnvValidationError = class extends Error {
|
|
21
|
+
name = "EnvValidationError";
|
|
22
|
+
issues;
|
|
23
|
+
constructor(issues) {
|
|
24
|
+
super(`Invalid Supabase environment:\n${issues.map((issue) => ` - ${issue.variables[0] ?? "env"}: ${issue.message}`).join("\n")}`);
|
|
25
|
+
this.issues = issues;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
function first(source, names) {
|
|
29
|
+
for (const name of names) {
|
|
30
|
+
const value = source[name]?.trim();
|
|
31
|
+
if (value) return value;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/** `SUPABASE_*_KEYS` JSON objects, as `@supabase/server` reads them. */
|
|
35
|
+
function keySet(source, name, kind, issues) {
|
|
36
|
+
const raw = source[name];
|
|
37
|
+
if (!raw) return void 0;
|
|
38
|
+
let parsed;
|
|
39
|
+
try {
|
|
40
|
+
parsed = JSON.parse(raw);
|
|
41
|
+
} catch {
|
|
42
|
+
parsed = void 0;
|
|
43
|
+
}
|
|
44
|
+
const entries = typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? Object.entries(parsed) : [];
|
|
45
|
+
if (entries.length === 0 || entries.some(([, value]) => typeof value !== "string")) {
|
|
46
|
+
issues.push({
|
|
47
|
+
variables: [name],
|
|
48
|
+
message: "must be a JSON object of key names to keys"
|
|
49
|
+
});
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const keys = {};
|
|
53
|
+
for (const [key, value] of entries) if (checkKey(value, kind, [name], issues)) keys[key] = value;
|
|
54
|
+
return keys;
|
|
55
|
+
}
|
|
56
|
+
function preferred(keys) {
|
|
57
|
+
if (!keys) return void 0;
|
|
58
|
+
return keys["default"] ?? Object.values(keys)[0];
|
|
59
|
+
}
|
|
60
|
+
function checkUrl(value, variables, issues) {
|
|
61
|
+
let url;
|
|
62
|
+
try {
|
|
63
|
+
url = new URL(value);
|
|
64
|
+
} catch {
|
|
65
|
+
issues.push({
|
|
66
|
+
variables,
|
|
67
|
+
message: "is not a valid URL"
|
|
68
|
+
});
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (url.protocol === "https:") return url;
|
|
72
|
+
if (url.protocol === "http:" && LOOPBACK.test(url.hostname)) return url;
|
|
73
|
+
issues.push({
|
|
74
|
+
variables,
|
|
75
|
+
message: "must use https (http is only allowed for localhost / 127.0.0.1 / [::1])"
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
function checkKey(value, kind, variables, issues) {
|
|
79
|
+
if (value.startsWith(`sb_${kind}_`)) return true;
|
|
80
|
+
if (value.startsWith("eyJ")) issues.push({
|
|
81
|
+
variables,
|
|
82
|
+
message: `is a legacy JWT key; use the new sb_${kind}_ key (Project Settings > API Keys)`
|
|
83
|
+
});
|
|
84
|
+
else if (value.startsWith(kind === "publishable" ? "sb_secret_" : "sb_publishable_")) issues.push({
|
|
85
|
+
variables,
|
|
86
|
+
message: kind === "publishable" ? "holds a secret key; never expose sb_secret_ keys as publishable" : "holds a publishable key, not a secret key"
|
|
87
|
+
});
|
|
88
|
+
else issues.push({
|
|
89
|
+
variables,
|
|
90
|
+
message: `must start with sb_${kind}_`
|
|
91
|
+
});
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Reads and validates Supabase settings. Accepts the `SUPABASE_`,
|
|
96
|
+
* `NEXT_PUBLIC_`, `VITE_`, `PUBLIC_`, `EXPO_PUBLIC_` and `NUXT_PUBLIC_`
|
|
97
|
+
* spellings. Issues name variables, never values.
|
|
98
|
+
*/
|
|
99
|
+
function parseEnv(source, options = {}) {
|
|
100
|
+
const issues = [];
|
|
101
|
+
const required = new Set(options.require ?? []);
|
|
102
|
+
const rawUrl = first(source, ENV_VARIABLES.url);
|
|
103
|
+
const url = rawUrl ? checkUrl(rawUrl, ENV_VARIABLES.url, issues) : void 0;
|
|
104
|
+
if (!rawUrl) issues.push({
|
|
105
|
+
variables: ENV_VARIABLES.url,
|
|
106
|
+
message: "is not set"
|
|
107
|
+
});
|
|
108
|
+
const publishableKeys = keySet(source, "SUPABASE_PUBLISHABLE_KEYS", "publishable", issues);
|
|
109
|
+
const singlePublishable = first(source, ENV_VARIABLES.publishableKey);
|
|
110
|
+
const publishableKey = singlePublishable ?? preferred(publishableKeys);
|
|
111
|
+
if (!publishableKey) issues.push({
|
|
112
|
+
variables: ENV_VARIABLES.publishableKey,
|
|
113
|
+
message: "is not set"
|
|
114
|
+
});
|
|
115
|
+
else if (singlePublishable) checkKey(publishableKey, "publishable", ENV_VARIABLES.publishableKey, issues);
|
|
116
|
+
const namedSecrets = keySet(source, "SUPABASE_SECRET_KEYS", "secret", issues);
|
|
117
|
+
const singleSecret = first(source, ENV_VARIABLES.secretKey);
|
|
118
|
+
const secretKey = singleSecret ?? preferred(namedSecrets);
|
|
119
|
+
if (singleSecret) checkKey(singleSecret, "secret", ENV_VARIABLES.secretKey, issues);
|
|
120
|
+
else if (!secretKey && required.has("secretKey")) issues.push({
|
|
121
|
+
variables: ENV_VARIABLES.secretKey,
|
|
122
|
+
message: "is not set"
|
|
123
|
+
});
|
|
124
|
+
const dbUrl = first(source, ENV_VARIABLES.dbUrl);
|
|
125
|
+
if (dbUrl && !/^postgres(ql)?:\/\//.test(dbUrl)) issues.push({
|
|
126
|
+
variables: ENV_VARIABLES.dbUrl,
|
|
127
|
+
message: "must be a postgres:// connection string"
|
|
128
|
+
});
|
|
129
|
+
else if (!dbUrl && required.has("dbUrl")) issues.push({
|
|
130
|
+
variables: ENV_VARIABLES.dbUrl,
|
|
131
|
+
message: "is not set"
|
|
132
|
+
});
|
|
133
|
+
const rawJwks = first(source, ENV_VARIABLES.jwksUrl);
|
|
134
|
+
const jwksOverride = rawJwks ? checkUrl(rawJwks, ENV_VARIABLES.jwksUrl, issues) : void 0;
|
|
135
|
+
const rawRead = first(source, ENV_VARIABLES.readUrl);
|
|
136
|
+
const readUrl = rawRead ? checkUrl(rawRead, ENV_VARIABLES.readUrl, issues) : void 0;
|
|
137
|
+
if (issues.length > 0 || !url || !publishableKey) return {
|
|
138
|
+
ok: false,
|
|
139
|
+
issues
|
|
140
|
+
};
|
|
141
|
+
const base = url.href.replace(/\/+$/, "");
|
|
142
|
+
const projectRef = HOSTED.exec(url.hostname)?.[1];
|
|
143
|
+
return {
|
|
144
|
+
ok: true,
|
|
145
|
+
env: {
|
|
146
|
+
url: base,
|
|
147
|
+
publishableKey,
|
|
148
|
+
jwksUrl: jwksOverride ?? new URL(`${base}/auth/v1/.well-known/jwks.json`),
|
|
149
|
+
...secretKey ? {
|
|
150
|
+
secretKey,
|
|
151
|
+
secretKeys: {
|
|
152
|
+
...namedSecrets,
|
|
153
|
+
default: secretKey
|
|
154
|
+
}
|
|
155
|
+
} : {},
|
|
156
|
+
...dbUrl ? { dbUrl } : {},
|
|
157
|
+
...projectRef ? { projectRef } : {},
|
|
158
|
+
...readUrl ? { readUrl: readUrl.href.replace(/\/+$/, "") } : {}
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
function processEnv() {
|
|
163
|
+
return globalThis.process?.env ?? {};
|
|
164
|
+
}
|
|
165
|
+
/** Like `parseEnv`, but throws `EnvValidationError`. Reads `process.env` by default. */
|
|
166
|
+
function loadEnv(source = processEnv(), options = {}) {
|
|
167
|
+
const result = parseEnv(source, options);
|
|
168
|
+
if (!result.ok) throw new EnvValidationError(result.issues);
|
|
169
|
+
return result.env;
|
|
170
|
+
}
|
|
171
|
+
/** The env validator as a Standard Schema, for t3-env, framework config or any validator slot. */
|
|
172
|
+
function envSchema(options = {}) {
|
|
173
|
+
return { "~standard": {
|
|
174
|
+
version: 1,
|
|
175
|
+
vendor: "better-supabase",
|
|
176
|
+
validate(value) {
|
|
177
|
+
if (typeof value !== "object" || value === null) return { issues: [{ message: "Expected an environment object" }] };
|
|
178
|
+
const result = parseEnv(value, options);
|
|
179
|
+
if (result.ok) return { value: result.env };
|
|
180
|
+
return { issues: result.issues.map((issue) => ({
|
|
181
|
+
message: `${issue.variables[0] ?? "env"} ${issue.message}`,
|
|
182
|
+
path: issue.variables.slice(0, 1)
|
|
183
|
+
})) };
|
|
184
|
+
}
|
|
185
|
+
} };
|
|
186
|
+
}
|
|
187
|
+
/** The parts that are safe in client bundles. */
|
|
188
|
+
function publicEnv(env) {
|
|
189
|
+
return {
|
|
190
|
+
url: env.url,
|
|
191
|
+
publishableKey: env.publishableKey
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
/** Converts to `@supabase/server`'s `SupabaseEnv` (the `env` option of `withSupabase`). */
|
|
195
|
+
function toServerEnv(env) {
|
|
196
|
+
return {
|
|
197
|
+
url: env.url,
|
|
198
|
+
publishableKeys: { default: env.publishableKey },
|
|
199
|
+
secretKeys: env.secretKeys ?? (env.secretKey ? { default: env.secretKey } : {}),
|
|
200
|
+
jwks: env.jwksUrl
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
//#endregion
|
|
2
204
|
export { ENV_VARIABLES, EnvValidationError, envSchema, loadEnv, parseEnv, publicEnv, toServerEnv };
|
|
@@ -41,7 +41,7 @@ function isDbError(value) {
|
|
|
41
41
|
}
|
|
42
42
|
/**
|
|
43
43
|
* The `DbError` in a `DbError`, a `DbException`, or an error whose `cause`
|
|
44
|
-
* is a `DbError` (what `
|
|
44
|
+
* is a `DbError` (what `betterSupabase.mapError()` mappers should set).
|
|
45
45
|
*/
|
|
46
46
|
function dbErrorOf(value) {
|
|
47
47
|
if (value instanceof DbException) return value.error;
|
package/dist/events/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as HttpMode, c as RowEventData, d as httpSink, f as isCloudEvent, i as ForwardOptions, l as forwardMutations, m as toHttp, n as CloudEventOptions, o as HttpSinkOptions, p as toCloudEvents, r as EventSink, s as ROW_EVENT_TYPES, t as CloudEvent, u as fromHttp } from "../index-
|
|
1
|
+
import { a as HttpMode, c as RowEventData, d as httpSink, f as isCloudEvent, i as ForwardOptions, l as forwardMutations, m as toHttp, n as CloudEventOptions, o as HttpSinkOptions, p as toCloudEvents, r as EventSink, s as ROW_EVENT_TYPES, t as CloudEvent, u as fromHttp } from "../index-D5IfUIDh.js";
|
|
2
2
|
export { CloudEvent, CloudEventOptions, EventSink, ForwardOptions, HttpMode, HttpSinkOptions, ROW_EVENT_TYPES, RowEventData, forwardMutations, fromHttp, httpSink, isCloudEvent, toCloudEvents, toHttp };
|