better-supabase 0.1.0 → 0.2.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.
Files changed (115) hide show
  1. package/bin/better-supabase.js +2 -1
  2. package/dist/claims-CoTobNC-.js +25 -0
  3. package/dist/cli/bin.js +1 -1
  4. package/dist/cli/index.d.ts +2 -2
  5. package/dist/cli/index.js +1 -1
  6. package/dist/{cli-CoByWYja.js → cli-DrSgDOQC.js} +333 -159
  7. package/dist/client/index.d.ts +1 -1
  8. package/dist/{compiler-DL18ukPe.d.ts → compiler-CZ9nIuqy.d.ts} +2 -2
  9. package/dist/config/index.d.ts +3 -3
  10. package/dist/config/index.js +2 -2
  11. package/dist/{config-D-aR2ZoN.js → config-ClDXmVtY.js} +11 -10
  12. package/dist/{define-QGkq04oe.js → define-BXMYD9AY.js} +65 -62
  13. package/dist/{define-CTfWw-SS.d.ts → define-e3zI4_4g.d.ts} +27 -10
  14. package/dist/edge/index.d.ts +4 -4
  15. package/dist/edge/index.js +3 -3
  16. package/dist/entitlements-CTEBm7IB.js +20 -0
  17. package/dist/entitlements-Dng-ctuT.d.ts +42 -0
  18. package/dist/events/index.d.ts +1 -1
  19. package/dist/{events-2OJsVG_d.d.ts → events-DOt3nSO-.d.ts} +2 -2
  20. package/dist/{executor-Bje4suQF.d.ts → executor-BYXQ9AGn.d.ts} +1 -1
  21. package/dist/{executor-Bazhgsgq.d.ts → executor-CGdNQ27g.d.ts} +1 -1
  22. package/dist/{executor-Ceq60hPM.js → executor-DeppvirK.js} +1 -1
  23. package/dist/guards-BnzDvFrz.js +10 -0
  24. package/dist/hono/index.d.ts +5 -5
  25. package/dist/hono/index.js +3 -3
  26. package/dist/{index-JXHBuS53.d.ts → index-Bw1bwtC0.d.ts} +3 -3
  27. package/dist/{index-Hf8PP9sP.d.ts → index-CBDufH1M.d.ts} +15 -11
  28. package/dist/{index-cEeweTeM.d.ts → index-CG69s15v.d.ts} +3 -3
  29. package/dist/{index-DQVvHzjW.d.ts → index-Ciu5Xlml.d.ts} +3 -3
  30. package/dist/{index-Sw43J8HG.d.ts → index-D4v7sncu.d.ts} +6 -6
  31. package/dist/{index-BD6wKthp.d.ts → index-DOsjFvMf.d.ts} +28 -7
  32. package/dist/{index-DRid0qIv.d.ts → index-DbxFr7XG.d.ts} +2 -2
  33. package/dist/{index-Nxo3TJcm.d.ts → index-DuP14VHo.d.ts} +11 -3
  34. package/dist/{index-Dup-nSe9.d.ts → index-K-3WM2Hp.d.ts} +2 -2
  35. package/dist/index.d.ts +9 -9
  36. package/dist/index.js +7 -6
  37. package/dist/jobs/index.d.ts +1 -1
  38. package/dist/jobs/index.js +6 -5
  39. package/dist/{json-schema-BbwO2mZg.js → json-schema-BpYqkCKf.js} +2 -1
  40. package/dist/list/index.d.ts +1 -1
  41. package/dist/{live-6b9i72Ux.d.ts → live-DJyZMD6w.d.ts} +14 -3
  42. package/dist/logger-glM28NVN.js +21 -0
  43. package/dist/mcp/index.d.ts +41 -4
  44. package/dist/mcp/index.js +194 -61
  45. package/dist/{mfa-CpogP66z.js → mfa-CpLfJSde.js} +23 -3
  46. package/dist/next/index.d.ts +23 -23
  47. package/dist/next/index.js +9 -8
  48. package/dist/openapi/index.d.ts +1 -1
  49. package/dist/openapi/index.js +3 -3
  50. package/dist/orpc/index.d.ts +4 -4
  51. package/dist/orpc/index.js +2 -2
  52. package/dist/otel/index.d.ts +3 -3
  53. package/dist/otel/index.js +1 -1
  54. package/dist/{template-BeOGnynM.js → permdock-sql-CghlHPuH.js} +25 -1
  55. package/dist/{plugin-HvGqCurB.d.ts → plugin-C4TR9J0Z.d.ts} +2 -2
  56. package/dist/plugins/actor/index.d.ts +1 -1
  57. package/dist/plugins/rules/index.d.ts +4 -3
  58. package/dist/plugins/rules/index.js +4 -11
  59. package/dist/plugins/soft-delete/index.d.ts +2 -2
  60. package/dist/plugins/tenant/index.d.ts +10 -4
  61. package/dist/plugins/tenant/index.js +15 -13
  62. package/dist/plugins/timestamps/index.d.ts +1 -1
  63. package/dist/plugins/validation/index.d.ts +1 -1
  64. package/dist/{pool-BFeqzwQS.d.ts → pool-R2m_DkXi.d.ts} +1 -1
  65. package/dist/postgres/index.d.ts +4 -4
  66. package/dist/postgres/index.js +2 -2
  67. package/dist/{postgrest-Dm-vhY6R.d.ts → postgrest-cAEQ_IQN.d.ts} +1 -1
  68. package/dist/{problem-DPu6Fh-t.js → problem-BTkTtRV9.js} +4 -4
  69. package/dist/query/index.d.ts +1 -1
  70. package/dist/react/index.d.ts +6 -6
  71. package/dist/react/index.js +3 -3
  72. package/dist/react/server.d.ts +5 -5
  73. package/dist/react/server.js +1 -1
  74. package/dist/react/session.d.ts +1 -1
  75. package/dist/react/session.js +1 -1
  76. package/dist/{react-CrOvrnIP.js → react-C83BdBGt.js} +9 -8
  77. package/dist/{read-set-DhX2d04c.js → read-set-4lI3W_gZ.js} +1 -1
  78. package/dist/realtime/index.d.ts +3 -2
  79. package/dist/realtime/index.js +26 -11
  80. package/dist/{resolve-DW8h9NPm.d.ts → resolve-CjHILk2w.d.ts} +21 -6
  81. package/dist/{resource-CYiu6Ygi.js → resource-BHEWmQJK.js} +1 -1
  82. package/dist/{resource-SkPTRJDD.d.ts → resource-CgZa3YG_.d.ts} +4 -4
  83. package/dist/{respond-4-dhoV7x.js → respond-DMcbQwfN.js} +7 -4
  84. package/dist/{respond-PoTpy5DT.d.ts → respond-Dne1ARSa.d.ts} +14 -14
  85. package/dist/server/index.d.ts +7 -7
  86. package/dist/server/index.js +5 -5
  87. package/dist/{session-C3osL21k.d.ts → session-C3LxnQ0e.d.ts} +4 -3
  88. package/dist/{session-CD-3orO_.js → session-CqEwzVup.js} +2 -1
  89. package/dist/{simplify-oHiDKRVQ.js → simplify-bwJpLnaS.js} +12 -12
  90. package/dist/{spec-pins-t6sPaHvl.js → spec-pins-C3oc-Tdp.js} +1 -1
  91. package/dist/{spec-pins-CJPVghHy.d.ts → spec-pins-CqorWDnO.d.ts} +1 -1
  92. package/dist/{sql-M8l3fnS0.js → sql-DTjA1LPj.js} +1 -1
  93. package/dist/ssr/index.d.ts +5 -5
  94. package/dist/ssr/index.js +3 -3
  95. package/dist/{stats-3iy8u3_P.js → stats-C5W-rBfR.js} +1 -1
  96. package/dist/storage/index.d.ts +3 -2
  97. package/dist/storage/index.js +1 -1
  98. package/dist/{storage-BWXVUXGk.js → storage-DuGn38fr.js} +72 -6
  99. package/dist/testing/index.d.ts +46 -15
  100. package/dist/testing/index.js +111 -43
  101. package/dist/{types-C2fslP1z.d.ts → types-C83v5SQz.d.ts} +55 -2
  102. package/dist/{view-B0ltUmTi.d.ts → view-D1s0wa0T.d.ts} +9 -3
  103. package/dist/{view-B6F9QbG-.js → view-aOYizTeE.js} +2 -1
  104. package/dist/webhooks/index.d.ts +3 -3
  105. package/dist/webhooks/index.js +1 -1
  106. package/dist/{webhooks-DbMTJJX2.js → webhooks-DMipjhSP.js} +1 -1
  107. package/package.json +8 -4
  108. package/schemas/config-v1.json +49 -4
  109. package/schemas/doctor-report-v1.json +1 -0
  110. package/schemas/snapshot-v2.json +4 -0
  111. package/skills/better-supabase/references/plugins.md +9 -0
  112. package/skills/better-supabase-api/SKILL.md +2 -2
  113. package/skills/better-supabase-testing/SKILL.md +4 -3
  114. package/dist/entitlements-BBg61DQZ.d.ts +0 -20
  115. package/dist/entitlements-BC_khwRy.js +0 -17
@@ -1,12 +1,12 @@
1
- import { n as AnyModels, t as AnyFunctions } from "./types-C2fslP1z.js";
1
+ import { n as AnyModels, t as AnyFunctions } from "./types-C83v5SQz.js";
2
2
  import { p as DbError, t as AsyncResult } from "./result-CTkCZ6JA.js";
3
- import { I as StatsRecorder, P as DbStats, t as BetterSupabase, y as Db } from "./define-CTfWw-SS.js";
4
- import { h as RequestContext } from "./plugin-HvGqCurB.js";
3
+ import { I as StatsRecorder, P as DbStats, t as BetterSupabase, y as Db } from "./define-e3zI4_4g.js";
4
+ import { h as RequestContext } from "./plugin-C4TR9J0Z.js";
5
5
  import { t as BetterSupabaseEnv } from "./index-Dy6kuF0P.js";
6
- import { r as SqlClaims, t as Postgres } from "./pool-BFeqzwQS.js";
6
+ import { r as SqlClaims, t as Postgres } from "./pool-R2m_DkXi.js";
7
7
  import { o as ImpersonationOptions, t as Aal } from "./mfa-TVia554c.js";
8
- import { a as ResolveAuthOptions, r as AuthState, t as AuthResolution } from "./resolve-DW8h9NPm.js";
9
- import { n as Bucket } from "./index-Nxo3TJcm.js";
8
+ import { a as ResolveAuthOptions, r as AuthState, t as AuthResolution } from "./resolve-CjHILk2w.js";
9
+ import { n as Bucket } from "./index-DuP14VHo.js";
10
10
  import { SupabaseClient } from "@supabase/supabase-js";
11
11
  //#region src/server/delete-account.d.ts
12
12
  interface DeleteAccountOptions {
@@ -67,9 +67,9 @@ interface ServerOptions {
67
67
  readonly pinMs?: number;
68
68
  };
69
69
  }
70
- interface ServerContext<M extends AnyModels, F extends AnyFunctions, E, C = unknown> {
71
- readonly auth: AuthState<C>;
72
- readonly resolution: AuthResolution<C>;
70
+ interface ServerContext<M extends AnyModels, F extends AnyFunctions, E, C = unknown, P = unknown> {
71
+ readonly auth: AuthState<C, P>;
72
+ readonly resolution: AuthResolution<C, P>;
73
73
  /** supabase-js client scoped to the caller (RLS applies). */
74
74
  readonly supabase: SupabaseClient;
75
75
  /** Repositories over PostgREST as the caller. */
@@ -88,18 +88,18 @@ interface ContextOptions {
88
88
  /** Also records this context's calls into a request-wide recorder. */
89
89
  readonly stats?: StatsRecorder;
90
90
  }
91
- interface BetterServer<M extends AnyModels, F extends AnyFunctions, E, C = unknown> {
91
+ interface BetterServer<M extends AnyModels, F extends AnyFunctions, E, C = unknown, P = unknown> {
92
92
  readonly env: BetterSupabaseEnv;
93
93
  resolve(request: Request, options?: {
94
94
  readonly refresh?: boolean;
95
- }): Promise<AuthResolution<C>>;
95
+ }): Promise<AuthResolution<C, P>>;
96
96
  /**
97
97
  * Resolves auth and binds repositories to the caller. Refreshes an expired
98
98
  * cookie session only with `refresh: true`; send `ctx.resolution.apply(response)`.
99
99
  */
100
- context(request: Request, options?: ContextOptions): Promise<ServerContext<M, F, E, C>>;
100
+ context(request: Request, options?: ContextOptions): Promise<ServerContext<M, F, E, C, P>>;
101
101
  /** The context for an auth state resolved elsewhere (the proxy, a queue message). */
102
- contextFor(auth: AuthState<C>, options?: ContextOptions): ServerContext<M, F, E, C>;
102
+ contextFor(auth: AuthState<C, P>, options?: ContextOptions): ServerContext<M, F, E, C, P>;
103
103
  /** A stateless supabase-js client for an auth state, optionally with extra request headers. */
104
104
  supabaseFor(auth: AuthState, headers?: Readonly<Record<string, string>>): SupabaseClient;
105
105
  /** Repositories for an auth state (e.g. one resolved by the proxy). */
@@ -123,7 +123,7 @@ interface BetterServer<M extends AnyModels, F extends AnyFunctions, E, C = unkno
123
123
  * Server-side entry point for APIs, jobs, MCP servers and framework
124
124
  * adapters. Holds the secrets; `sb` stays isomorphic.
125
125
  */
126
- declare function createServer<M extends AnyModels, D, F extends AnyFunctions, E, C = unknown>(sb: BetterSupabase<M, D, F, E, C>, options?: ServerOptions): BetterServer<M, F, E, C>;
126
+ declare function createServer<M extends AnyModels, D, F extends AnyFunctions, E, C = unknown, P = unknown>(sb: BetterSupabase<M, D, F, E, C, P>, options?: ServerOptions): BetterServer<M, F, E, C, P>;
127
127
  //#endregion
128
128
  //#region src/server/respond.d.ts
129
129
  type AuthKind = AuthState["kind"];
@@ -1,12 +1,12 @@
1
- import { n as AnyModels, t as AnyFunctions } from "../types-C2fslP1z.js";
2
- import { t as BetterSupabase, y as Db } from "../define-CTfWw-SS.js";
3
- import { h as RequestContext } from "../plugin-HvGqCurB.js";
1
+ import { n as AnyModels, t as AnyFunctions } from "../types-C83v5SQz.js";
2
+ import { t as BetterSupabase, y as Db } from "../define-e3zI4_4g.js";
3
+ import { h as RequestContext } from "../plugin-C4TR9J0Z.js";
4
4
  import { a as checkAal, c as impersonatorOf, i as amrOf, n as AmrEntry, o as ImpersonationOptions, r as aalOf, s as Impersonator, t as Aal } from "../mfa-TVia554c.js";
5
- import { _ as readSession, a as ResolveAuthOptions, b as writeSession, c as clientIp, d as CookieOptions, f as CookieRecord, i as InvalidReason, l as resolveAuth, m as StoredSession, n as AuthResolver, o as ResolvedState, p as CookieWrite, r as AuthState, s as authContext, t as AuthResolution, u as AUTH_CACHE_HEADERS, y as sessionCookieName } from "../resolve-DW8h9NPm.js";
6
- import { _ as DeleteAccountResult, a as guard, c as settle, d as ServerContext, f as ServerOptions, g as DeleteAccountOptions, h as ReplicaState, i as Settled, l as BetterServer, m as PRIMARY_COOKIE, n as GuardOptions, o as isResult, p as createServer, r as RespondOptions, s as respond, t as AuthKind, u as ContextOptions } from "../respond-PoTpy5DT.js";
7
- import { a as defineResource, i as ResourceRouteOptions, n as ResourceInput, r as ResourceList, t as ResourceHandler } from "../resource-SkPTRJDD.js";
5
+ import { _ as readSession, a as ResolveAuthOptions, b as writeSession, c as clientIp, d as CookieOptions, f as CookieRecord, i as InvalidReason, l as resolveAuth, m as StoredSession, n as AuthResolver, o as ResolvedState, p as CookieWrite, r as AuthState, s as authContext, t as AuthResolution, u as AUTH_CACHE_HEADERS, y as sessionCookieName } from "../resolve-CjHILk2w.js";
6
+ import { _ as DeleteAccountResult, a as guard, c as settle, d as ServerContext, f as ServerOptions, g as DeleteAccountOptions, h as ReplicaState, i as Settled, l as BetterServer, m as PRIMARY_COOKIE, n as GuardOptions, o as isResult, p as createServer, r as RespondOptions, s as respond, t as AuthKind, u as ContextOptions } from "../respond-Dne1ARSa.js";
7
+ import { a as defineResource, i as ResourceRouteOptions, n as ResourceInput, r as ResourceList, t as ResourceHandler } from "../resource-CgZa3YG_.js";
8
8
  import { a as ProblemResponseOptions, c as problemResponse, i as ProblemOptions, l as toProblem, n as PROBLEM_TYPE_BASE, o as fromProblem, r as ProblemDetails, s as isProblem, t as PROBLEM_CONTENT_TYPE } from "../problem-DlgB0lYl.js";
9
- import { n as RefreshOutcome, r as refreshSession } from "../index-cEeweTeM.js";
9
+ import { n as RefreshOutcome, r as refreshSession } from "../index-CG69s15v.js";
10
10
  import { SupabaseClient } from "@supabase/supabase-js";
11
11
  import { Middleware } from "@supabase/middleware";
12
12
  import { AuthMode, JWTClaims, UserClaims } from "@supabase/server";
@@ -1,8 +1,8 @@
1
- import { a as problemResponse, i as isProblem, n as PROBLEM_TYPE_BASE, o as toProblem, r as fromProblem, t as PROBLEM_CONTENT_TYPE } from "../problem-DPu6Fh-t.js";
2
- import { a as settle, i as respond, n as guard, o as createServer, r as isResult, u as PRIMARY_COOKIE } from "../respond-4-dhoV7x.js";
3
- import { a as clientIp, f as sessionCookieName, g as impersonatorOf, i as authContext, m as refreshSession, n as amrOf, o as resolveAuth, p as writeSession, r as checkAal, s as AUTH_CACHE_HEADERS, t as aalOf, u as readSession } from "../mfa-CpogP66z.js";
4
- import { n as postgresExecutor } from "../executor-Ceq60hPM.js";
5
- import { t as defineResource } from "../resource-CYiu6Ygi.js";
1
+ import { a as problemResponse, i as isProblem, n as PROBLEM_TYPE_BASE, o as toProblem, r as fromProblem, t as PROBLEM_CONTENT_TYPE } from "../problem-BTkTtRV9.js";
2
+ import { a as settle, i as respond, n as guard, o as createServer, r as isResult, u as PRIMARY_COOKIE } from "../respond-DMcbQwfN.js";
3
+ import { a as clientIp, f as sessionCookieName, g as impersonatorOf, i as authContext, m as refreshSession, n as amrOf, o as resolveAuth, p as writeSession, r as checkAal, s as AUTH_CACHE_HEADERS, t as aalOf, u as readSession } from "../mfa-CpLfJSde.js";
4
+ import { n as postgresExecutor } from "../executor-DeppvirK.js";
5
+ import { t as defineResource } from "../resource-BHEWmQJK.js";
6
6
  import { defineMiddleware } from "@supabase/middleware";
7
7
  //#region src/server/middleware.ts
8
8
  /** Repository context from a `@supabase/server` context. */
@@ -1,4 +1,4 @@
1
- import { t as AuthSession } from "./view-B0ltUmTi.js";
1
+ import { t as AuthSession } from "./view-D1s0wa0T.js";
2
2
  import { ReactNode } from "react";
3
3
  //#region src/react/session.d.ts
4
4
  interface SessionProviderProps {
@@ -14,8 +14,9 @@ declare function SessionProvider(props: SessionProviderProps): ReactNode;
14
14
  /**
15
15
  * The session from the nearest `<SessionProvider>`. Suspends until the
16
16
  * promise resolves, so render it inside `<Suspense>`. `C` types the claims
17
- * (the output of `sb.claims(schema)`); `createHooks().useSession` infers it.
17
+ * (the output of `sb.claims(schema)`) and `P` the profile (the output of
18
+ * `sb.userMetadata(schema)`); `createHooks().useSession` infers both.
18
19
  */
19
- declare function useSession<C = unknown>(): AuthSession<C>;
20
+ declare function useSession<C = unknown, P = unknown>(): AuthSession<C, P>;
20
21
  //#endregion
21
22
  export { SessionProviderProps as n, useSession as r, SessionProvider as t };
@@ -8,7 +8,8 @@ function SessionProvider(props) {
8
8
  /**
9
9
  * The session from the nearest `<SessionProvider>`. Suspends until the
10
10
  * promise resolves, so render it inside `<Suspense>`. `C` types the claims
11
- * (the output of `sb.claims(schema)`); `createHooks().useSession` infers it.
11
+ * (the output of `sb.claims(schema)`) and `P` the profile (the output of
12
+ * `sb.userMetadata(schema)`); `createHooks().useSession` infers both.
12
13
  */
13
14
  function useSession() {
14
15
  const promise = useContext(SessionContext);
@@ -236,8 +236,8 @@ var IrBuilder = class {
236
236
  const keys = Object.keys(value);
237
237
  if (keys.length > 0 && keys.every((key) => key === "is" || key === "isNot")) {
238
238
  const items = [];
239
- if (value.is !== void 0) items.push(value.is === null ? make("none", null) : make("some", value.is));
240
- if (value.isNot !== void 0) items.push(value.isNot === null ? make("some", null) : not(make("some", value.isNot)));
239
+ if (value["is"] !== void 0) items.push(value["is"] === null ? make("none", null) : make("some", value["is"]));
240
+ if (value["isNot"] !== void 0) items.push(value["isNot"] === null ? make("some", null) : not(make("some", value["isNot"])));
241
241
  return and(...items) ?? make("some", null);
242
242
  }
243
243
  }
@@ -341,7 +341,7 @@ var IrBuilder = class {
341
341
  * of each group.
342
342
  */
343
343
  aggregation(table, args) {
344
- const groupBy = args.groupBy ?? [];
344
+ const groupBy = args["groupBy"] ?? [];
345
345
  if (!Array.isArray(groupBy)) invalidRequest(`"groupBy" on "${table.key}" must be an array`, table.key);
346
346
  const columns = groupBy.map((name) => this.selectColumn(table, String(name)));
347
347
  const measures = [];
@@ -350,7 +350,7 @@ var IrBuilder = class {
350
350
  if (value === void 0) continue;
351
351
  for (const alias of this.measured(table, key, value)) measures.push(this.measure(table, fn, alias, `${key}_${alias}`));
352
352
  }
353
- const count = args._count === true;
353
+ const count = args["_count"] === true;
354
354
  if (!count && measures.length === 0) invalidRequest(`aggregate on "${table.key}" needs _count, _sum, _avg, _min or _max`, table.key);
355
355
  return {
356
356
  columns,
@@ -461,7 +461,7 @@ var IrBuilder = class {
461
461
  columns: [],
462
462
  includes: []
463
463
  },
464
- where: this.where(target, args.where),
464
+ where: this.where(target, args["where"]),
465
465
  orderBy: [],
466
466
  limit: void 0,
467
467
  required: false,
@@ -477,11 +477,11 @@ var IrBuilder = class {
477
477
  alias: name,
478
478
  relation,
479
479
  target,
480
- selection: this.selection(target, args.select, args.include),
481
- where: this.where(target, args.where),
482
- orderBy: this.orderBy(target, args.orderBy),
483
- limit: typeof args.limit === "number" ? args.limit : void 0,
484
- required: args.required === true
480
+ selection: this.selection(target, args["select"], args["include"]),
481
+ where: this.where(target, args["where"]),
482
+ orderBy: this.orderBy(target, args["orderBy"]),
483
+ limit: typeof args["limit"] === "number" ? args["limit"] : void 0,
484
+ required: args["required"] === true
485
485
  };
486
486
  }
487
487
  orderBy(table, input) {
@@ -498,8 +498,8 @@ var IrBuilder = class {
498
498
  direction: spec
499
499
  });
500
500
  else if (isPlainObject(spec)) {
501
- const direction = spec.direction === "desc" ? "desc" : "asc";
502
- const nulls = spec.nulls;
501
+ const direction = spec["direction"] === "desc" ? "desc" : "asc";
502
+ const nulls = spec["nulls"];
503
503
  terms.push(nulls === "first" || nulls === "last" ? {
504
504
  column,
505
505
  direction,
@@ -5,7 +5,7 @@
5
5
  */
6
6
  const SPEC_PINS = {
7
7
  otelSemconv: "1.37.0",
8
- mcp: "2025-06-18",
8
+ mcp: "2026-07-28",
9
9
  openapi: "3.1.1",
10
10
  cloudevents: "1.0.2",
11
11
  standardWebhooks: "1.0.0",
@@ -5,7 +5,7 @@
5
5
  */
6
6
  declare const SPEC_PINS: {
7
7
  readonly otelSemconv: "1.37.0";
8
- readonly mcp: "2025-06-18";
8
+ readonly mcp: "2026-07-28";
9
9
  readonly openapi: "3.1.1";
10
10
  readonly cloudevents: "1.0.2";
11
11
  readonly standardWebhooks: "1.0.0";
@@ -1,4 +1,4 @@
1
- import { a as invalidRequest, n as simplifyOrFalse } from "./simplify-oHiDKRVQ.js";
1
+ import { a as invalidRequest, n as simplifyOrFalse } from "./simplify-bwJpLnaS.js";
2
2
  //#region src/compile/sql.ts
3
3
  const MAX_PAIRS = 50;
4
4
  function quoteIdent(name) {
@@ -1,5 +1,5 @@
1
- import { _ as readSession, a as ResolveAuthOptions, b as writeSession, d as CookieOptions, f as CookieRecord, g as parseCookies, h as applyCookieWrites, l as resolveAuth, m as StoredSession, n as AuthResolver, p as CookieWrite, r as AuthState, s as authContext, t as AuthResolution, u as AUTH_CACHE_HEADERS, v as serializeCookie, y as sessionCookieName } from "../resolve-DW8h9NPm.js";
2
- import { n as toSession, t as AuthSession } from "../view-B0ltUmTi.js";
3
- import { n as hasEntitlement, t as EntitlementKey } from "../entitlements-BBg61DQZ.js";
4
- import { n as RefreshOutcome, r as refreshSession, t as RefreshOptions } from "../index-cEeweTeM.js";
5
- export { AUTH_CACHE_HEADERS, type AuthResolution, type AuthResolver, type AuthSession, type AuthState, type CookieOptions, type CookieRecord, type CookieWrite, type EntitlementKey, type RefreshOptions, type RefreshOutcome, type ResolveAuthOptions, type StoredSession, applyCookieWrites, authContext, hasEntitlement, parseCookies, readSession, refreshSession, resolveAuth, serializeCookie, sessionCookieName, toSession, writeSession };
1
+ import { _ as readSession, a as ResolveAuthOptions, b as writeSession, d as CookieOptions, f as CookieRecord, g as parseCookies, h as applyCookieWrites, l as resolveAuth, m as StoredSession, n as AuthResolver, p as CookieWrite, r as AuthState, s as authContext, t as AuthResolution, u as AUTH_CACHE_HEADERS, v as serializeCookie, y as sessionCookieName } from "../resolve-CjHILk2w.js";
2
+ import { n as toSession, t as AuthSession } from "../view-D1s0wa0T.js";
3
+ import { n as MembershipClaim, r as hasEntitlement, t as EntitlementKey } from "../entitlements-Dng-ctuT.js";
4
+ import { n as RefreshOutcome, r as refreshSession, t as RefreshOptions } from "../index-CG69s15v.js";
5
+ export { AUTH_CACHE_HEADERS, type AuthResolution, type AuthResolver, type AuthSession, type AuthState, type CookieOptions, type CookieRecord, type CookieWrite, type EntitlementKey, type MembershipClaim, type RefreshOptions, type RefreshOutcome, type ResolveAuthOptions, type StoredSession, applyCookieWrites, authContext, hasEntitlement, parseCookies, readSession, refreshSession, resolveAuth, serializeCookie, sessionCookieName, toSession, writeSession };
package/dist/ssr/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as hasEntitlement } from "../entitlements-BC_khwRy.js";
2
- import { c as applyCookieWrites, d as serializeCookie, f as sessionCookieName, i as authContext, l as parseCookies, m as refreshSession, o as resolveAuth, p as writeSession, s as AUTH_CACHE_HEADERS, u as readSession } from "../mfa-CpogP66z.js";
3
- import { t as toSession } from "../view-B6F9QbG-.js";
1
+ import { t as hasEntitlement } from "../entitlements-CTEBm7IB.js";
2
+ import { c as applyCookieWrites, d as serializeCookie, f as sessionCookieName, i as authContext, l as parseCookies, m as refreshSession, o as resolveAuth, p as writeSession, s as AUTH_CACHE_HEADERS, u as readSession } from "../mfa-CpLfJSde.js";
3
+ import { t as toSession } from "../view-aOYizTeE.js";
4
4
  export { AUTH_CACHE_HEADERS, applyCookieWrites, authContext, hasEntitlement, parseCookies, readSession, refreshSession, resolveAuth, serializeCookie, sessionCookieName, toSession, writeSession };
@@ -1,5 +1,5 @@
1
1
  import { c as mapDbError, n as dbError } from "./errors-Bl3rkOzo.js";
2
- import { a as invalidRequest, n as simplifyOrFalse } from "./simplify-oHiDKRVQ.js";
2
+ import { a as invalidRequest, n as simplifyOrFalse } from "./simplify-bwJpLnaS.js";
3
3
  import { i as ok, n as err, o as toDbError } from "./result-DWXatkd6.js";
4
4
  //#region src/compile/postgrest.ts
5
5
  function scalar(value) {
@@ -1,4 +1,5 @@
1
+ import { b as PermdockBucketPolicy } from "../types-C83v5SQz.js";
1
2
  import { n as StoragePath, t as PathIn } from "../path-Cv__-OTj.js";
2
3
  import { n as TemplateValues, t as TemplateParams } from "../template-mbvlysOo.js";
3
- import { C as parseSize, S as fromStorageError, _ as TtlPreset, a as BucketDrift, b as UrlOptions, c as ReplaceOptions, d as StorageClient, f as StoredObject, g as TransformOptions, h as TTL, i as BucketConfig, l as ReplaceResult, m as SweepResult, n as Bucket, o as BucketPolicy, p as SweepOptions, r as BucketClient, s as ObjectTarget, t as ActualBucket, u as Reservation, v as UploadBody, x as defineBucket, y as UploadOptions } from "../index-Nxo3TJcm.js";
4
- export { ActualBucket, Bucket, BucketClient, BucketConfig, BucketDrift, BucketPolicy, ObjectTarget, type PathIn, ReplaceOptions, ReplaceResult, Reservation, StorageClient, type StoragePath, StoredObject, SweepOptions, SweepResult, TTL, type TemplateParams, type TemplateValues, TransformOptions, TtlPreset, UploadBody, UploadOptions, UrlOptions, defineBucket, fromStorageError, parseSize };
4
+ import { C as parseSize, S as fromStorageError, _ as TtlPreset, a as BucketDrift, b as UrlOptions, c as ReplaceOptions, d as StorageClient, f as StoredObject, g as TransformOptions, h as TTL, i as BucketConfig, l as ReplaceResult, m as SweepResult, n as Bucket, o as BucketPolicy, p as SweepOptions, r as BucketClient, s as ObjectTarget, t as ActualBucket, u as Reservation, v as UploadBody, x as defineBucket, y as UploadOptions } from "../index-DuP14VHo.js";
5
+ export { ActualBucket, Bucket, BucketClient, BucketConfig, BucketDrift, BucketPolicy, ObjectTarget, type PathIn, type PermdockBucketPolicy, ReplaceOptions, ReplaceResult, Reservation, StorageClient, type StoragePath, StoredObject, SweepOptions, SweepResult, TTL, type TemplateParams, type TemplateValues, TransformOptions, TtlPreset, UploadBody, UploadOptions, UrlOptions, defineBucket, fromStorageError, parseSize };
@@ -1,2 +1,2 @@
1
- import { i as parseSize, n as defineBucket, r as fromStorageError, t as TTL } from "../storage-BWXVUXGk.js";
1
+ import { i as parseSize, n as defineBucket, r as fromStorageError, t as TTL } from "../storage-DuGn38fr.js";
2
2
  export { TTL, defineBucket, fromStorageError, parseSize };
@@ -1,7 +1,14 @@
1
1
  import { n as dbError, o as isDbError, t as DbException } from "./errors-Bl3rkOzo.js";
2
2
  import { i as ok, n as err, o as toDbError, t as AsyncResult } from "./result-DWXatkd6.js";
3
- import { i as sqlString, n as slug, r as sqlIdent, t as parseTemplate } from "./template-BeOGnynM.js";
3
+ import { i as tenantClaimPaths } from "./claims-CoTobNC-.js";
4
+ import { a as sqlString, i as sqlIdent, n as parseTemplate, r as slug, t as permdockCheck } from "./permdock-sql-CghlHPuH.js";
4
5
  //#region src/storage/index.ts
6
+ /** Storage operations that list objects; every other `select` is a read. */
7
+ const LIST_OPERATIONS = [
8
+ "object.list",
9
+ "object.list_v2",
10
+ "s3.object.list"
11
+ ];
5
12
  const TTL = {
6
13
  minute: 60,
7
14
  hour: 3600,
@@ -114,11 +121,12 @@ function defineBucket(config) {
114
121
  if (index === void 0) throw new TypeError(`defineBucket: a ${kind} policy needs {${param}} as a whole path segment in "${config.path}"`);
115
122
  return index;
116
123
  }
124
+ const mode = typeof policy === "string" ? policy : "permdock";
117
125
  const accessCheck = (() => {
118
- switch (policy) {
126
+ switch (mode) {
119
127
  case "tenant": {
120
128
  const index = segmentFor(config.tenant?.param ?? "orgId", "tenant");
121
- const expression = config.tenant?.sql ?? claimSql(config.tenant?.claim ?? ["org_id", "app_metadata.org_id"]);
129
+ const expression = config.tenant?.sql ?? claimSql(config.tenant?.claim ?? tenantClaimPaths());
122
130
  return `split_part(name, '/', ${String(index)}) = (${expression})`;
123
131
  }
124
132
  case "owner": {
@@ -126,10 +134,24 @@ function defineBucket(config) {
126
134
  return `split_part(name, '/', ${String(index)}) = (select auth.uid())::text`;
127
135
  }
128
136
  case "public":
129
- case "none": return;
130
- default: throw new TypeError(`defineBucket: unknown policy "${String(policy)}"`);
137
+ case "none":
138
+ case "permdock": return;
139
+ default: throw new TypeError(`defineBucket: unknown policy "${String(mode)}"`);
131
140
  }
132
141
  })();
142
+ const permdock = (() => {
143
+ if (typeof policy === "string") return void 0;
144
+ const where = `defineBucket(${config.id})`;
145
+ const id = policy.scope === "global" ? void 0 : `split_part(name, '/', ${String(policy.segment ?? segmentFor(config.tenant?.param ?? "orgId", "PermDock"))})`;
146
+ const check = (key) => permdockCheck(where, policy, key, id);
147
+ const keys = policy.permdock;
148
+ return {
149
+ read: check(keys.read),
150
+ ...keys.list === void 0 ? {} : { list: check(keys.list) },
151
+ write: check(keys.write),
152
+ delete: check(keys.delete ?? keys.write)
153
+ };
154
+ })();
133
155
  const resolve = (target) => {
134
156
  if (typeof target !== "string") return template.build(target);
135
157
  if (!template.match(target)) throw new DbException(dbError("invalid_input", `Path "${target}" does not match "${config.path}"`));
@@ -200,10 +222,54 @@ function defineBucket(config) {
200
222
  inBucket,
201
223
  void 0
202
224
  ]);
225
+ else if (permdock) {
226
+ const listing = `storage.allow_any_operation(array[${LIST_OPERATIONS.map(sqlString).join(", ")}])`;
227
+ if (permdock.list) policies.push([
228
+ "select",
229
+ "select",
230
+ "authenticated",
231
+ `${inBucket} and not ${listing} and ${permdock.read}`,
232
+ void 0
233
+ ], [
234
+ "list",
235
+ "select",
236
+ "authenticated",
237
+ `${inBucket} and ${listing} and ${permdock.list}`,
238
+ void 0
239
+ ]);
240
+ else policies.push([
241
+ "select",
242
+ "select",
243
+ "authenticated",
244
+ `${inBucket} and ${permdock.read}`,
245
+ void 0
246
+ ]);
247
+ const write = `${inBucket} and ${permdock.write}`;
248
+ policies.push([
249
+ "insert",
250
+ "insert",
251
+ "authenticated",
252
+ void 0,
253
+ `${write} and ${shape}`
254
+ ], [
255
+ "update",
256
+ "update",
257
+ "authenticated",
258
+ write,
259
+ `${write} and ${shape}`
260
+ ], [
261
+ "delete",
262
+ "delete",
263
+ "authenticated",
264
+ `${inBucket} and ${permdock.delete}`,
265
+ void 0
266
+ ]);
267
+ }
203
268
  for (const [suffix, command, roles, using, withCheck] of policies) {
204
269
  const policyName = sqlIdent(`bs_${name}_${suffix}`);
205
270
  lines.push("", `drop policy if exists ${policyName} on storage.objects;`, `create policy ${policyName} on storage.objects for ${command} to ${roles}${using ? `\n using (${using})` : ""}${withCheck ? `\n with check (${withCheck})` : ""};`);
206
271
  }
272
+ if (permdock && !permdock.list) lines.push("", `drop policy if exists ${sqlIdent(`bs_${name}_list`)} on storage.objects;`);
207
273
  return `${lines.join("\n")}\n`;
208
274
  },
209
275
  toml() {
@@ -355,7 +421,7 @@ function connectBucket(bucket, client, resolve) {
355
421
  const paths = targets.map(resolve);
356
422
  if (paths.length === 0) return ok([]);
357
423
  return run(() => api().createSignedUrls(paths, ttlSeconds(options?.ttl), download(options?.download))).andThen(async (data) => {
358
- const failed = data.find((entry) => entry.error || !entry.signedUrl);
424
+ const failed = data.find((entry) => entry.error != null || !entry.signedUrl);
359
425
  if (failed) return err(dbError("not_found", failed.error ?? `No URL for ${String(failed.path)}`, { table: bucket.id }));
360
426
  return ok(data.map((entry) => entry.signedUrl));
361
427
  });
@@ -1,12 +1,12 @@
1
- import { d as GeneratorInput, u as Generator, v as ResolvedConfig } from "../index-BD6wKthp.js";
2
- import { E as SchemaMeta, P as Update, h as Insert, k as TableKey, n as AnyModels, t as AnyFunctions } from "../types-C2fslP1z.js";
3
- import { r as Executor } from "../executor-Bazhgsgq.js";
4
- import { P as DbStats, l as CacheAdapter, t as BetterSupabase, y as Db } from "../define-CTfWw-SS.js";
5
- import { h as RequestContext, n as AnyPlugin } from "../plugin-HvGqCurB.js";
6
- import { t as SqlClient } from "../executor-Bje4suQF.js";
7
- import { t as Postgres } from "../pool-BFeqzwQS.js";
8
- import { n as AuthResolver } from "../resolve-DW8h9NPm.js";
9
- import { r as EventSink, t as CloudEvent } from "../index-DQVvHzjW.js";
1
+ import { d as Generator, f as GeneratorInput, y as ResolvedConfig } from "../index-DOsjFvMf.js";
2
+ import { A as SchemaMeta, N as TableKey, R as Update, _ as Insert, n as AnyModels, t as AnyFunctions } from "../types-C83v5SQz.js";
3
+ import { r as Executor } from "../executor-CGdNQ27g.js";
4
+ import { P as DbStats, l as CacheAdapter, t as BetterSupabase, y as Db } from "../define-e3zI4_4g.js";
5
+ import { h as RequestContext, n as AnyPlugin } from "../plugin-C4TR9J0Z.js";
6
+ import { t as SqlClient } from "../executor-BYXQ9AGn.js";
7
+ import { t as Postgres } from "../pool-R2m_DkXi.js";
8
+ import { n as AuthResolver } from "../resolve-CjHILk2w.js";
9
+ import { r as EventSink, t as CloudEvent } from "../index-Ciu5Xlml.js";
10
10
  import { SupabaseClient } from "@supabase/supabase-js";
11
11
  //#region src/testing/jwt.d.ts
12
12
  interface TestJwtClaims {
@@ -35,9 +35,28 @@ interface TestSigner {
35
35
  };
36
36
  sign(claims: TestJwtClaims): Promise<string>;
37
37
  }
38
+ /** A private ES256 JWK, as `better-supabase keys` writes to `supabase/signing_keys.json`. */
39
+ interface SigningJwk extends JsonWebKey {
40
+ readonly kid: string;
41
+ }
42
+ /**
43
+ * Signs an ES256 access token with a private JWK, the way the local stack
44
+ * signs them once `signing_keys_path` is set. Test-only.
45
+ */
46
+ export declare function signTestJwtWithKey(key: SigningJwk, claims: TestJwtClaims): Promise<string>;
38
47
  /** An in-memory ES256 key pair that signs tokens like Supabase Auth's asymmetric keys. */
39
48
  export declare function createTestSigner(): Promise<TestSigner>;
40
49
  //#endregion
50
+ //#region src/testing/local-key.d.ts
51
+ /**
52
+ * The key the local stack signs with: the first entry of the file
53
+ * `better-supabase keys` wrote. `path` defaults to `$SUPABASE_SIGNING_KEYS_PATH`,
54
+ * then `signing_keys_path` from the nearest `supabase/config.toml`.
55
+ */
56
+ export declare function localSigningKey(path?: string): Promise<SigningJwk>;
57
+ /** Signs a token with the local stack's ES256 key (see `localSigningKey`). Test-only. */
58
+ export declare function signLocalJwt(claims: TestJwtClaims, path?: string): Promise<string>;
59
+ //#endregion
41
60
  //#region src/testing/as-user.d.ts
42
61
  /** The local CLI stack's default JWT secret. */
43
62
  export declare const LOCAL_JWT_SECRET = "super-secret-jwt-token-with-at-least-32-characters-long";
@@ -46,7 +65,17 @@ interface LocalStack {
46
65
  readonly url?: string;
47
66
  /** Defaults to `$SUPABASE_PUBLISHABLE_KEY`, then `$SUPABASE_ANON_KEY`. */
48
67
  readonly publishableKey?: string;
49
- /** Defaults to `$SUPABASE_JWT_SECRET`, then the CLI default. */
68
+ /**
69
+ * `ES256` (default) signs with the key `better-supabase keys` wrote, as
70
+ * the hosted project's asymmetric keys do. `HS256` signs with the shared
71
+ * JWT secret and only works against a local stack.
72
+ */
73
+ readonly alg?: "ES256" | "HS256";
74
+ /** The private ES256 key. Defaults to the first key in `signingKeysPath`. */
75
+ readonly signingKey?: SigningJwk;
76
+ /** Defaults to `$SUPABASE_SIGNING_KEYS_PATH`, then `signing_keys_path` in `supabase/config.toml`. */
77
+ readonly signingKeysPath?: string;
78
+ /** For `alg: 'HS256'`. Defaults to `$SUPABASE_JWT_SECRET`, then the CLI default. */
50
79
  readonly jwtSecret?: string;
51
80
  /** Service-role key for `expectTenantIsolation`; defaults to `$SUPABASE_SECRET_KEY`. */
52
81
  readonly secretKey?: string;
@@ -65,10 +94,12 @@ interface TestUser<M extends AnyModels, F extends AnyFunctions, E> {
65
94
  }
66
95
  /**
67
96
  * A test user against the local stack: a signed token and repositories that
68
- * run as that user, for live RLS tests.
97
+ * run as that user, for live RLS tests. The token is ES256-signed with the
98
+ * key from `better-supabase keys`; pass `{ alg: 'HS256' }` for a stack that
99
+ * still uses the shared JWT secret.
69
100
  *
70
101
  * ```ts
71
- * const alice = await asUser(sb, { sub: aliceId, org_id: acme });
102
+ * const alice = await asUser(sb, { sub: aliceId, tenant_id: acme });
72
103
  * expect(await alice.db.customers.count().orThrow()).toBe(3);
73
104
  * ```
74
105
  */
@@ -247,8 +278,8 @@ interface TenantIsolationOptions<M extends AnyModels> {
247
278
  * ```ts
248
279
  * await expectTenantIsolation(sb, {
249
280
  * tenants: [
250
- * { id: ACME, claims: { sub: alice, org_id: ACME } },
251
- * { id: GLOBEX, claims: { sub: bob, org_id: GLOBEX } },
281
+ * { id: ACME, claims: { sub: alice, tenant_id: ACME } },
282
+ * { id: GLOBEX, claims: { sub: bob, tenant_id: GLOBEX } },
252
283
  * ],
253
284
  * tables: {
254
285
  * tags: {
@@ -291,4 +322,4 @@ export declare function isSeed(value: unknown): value is Seed<unknown>;
291
322
  */
292
323
  export declare function defineSeed<M extends AnyModels, D, F extends AnyFunctions, E, const S extends SeedFixtures<M>>(sb: BetterSupabase<M, D, F, E>, fixtures: S & ExactSeed<M, S>): Seed<S>;
293
324
  //#endregion
294
- export type { BudgetPage, BudgetResponse, ConformanceCheck, ConformanceReport, DbBudgetExpectation, ExactSeed, IsolationTable, IsolationTables, IsolationTenant, LocalStack, MeasuredRender, Seed, SeedFixtures, TenantIsolationOptions, TestAuthResolverOptions, TestEventSinkOptions, TestExecutorOptions, TestGeneratorOptions, TestJwtClaims, TestPluginOptions, TestSigner, TestUser };
325
+ export type { BudgetPage, BudgetResponse, ConformanceCheck, ConformanceReport, DbBudgetExpectation, ExactSeed, IsolationTable, IsolationTables, IsolationTenant, LocalStack, MeasuredRender, Seed, SeedFixtures, SigningJwk, TenantIsolationOptions, TestAuthResolverOptions, TestEventSinkOptions, TestExecutorOptions, TestGeneratorOptions, TestJwtClaims, TestPluginOptions, TestSigner, TestUser };