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
@@ -90,4 +90,28 @@ function slug(value) {
90
90
  return value.replace(/[^A-Za-z0-9]+/g, "_").replace(/^_|_$/g, "").toLowerCase();
91
91
  }
92
92
  //#endregion
93
- export { sqlString as i, slug as n, sqlIdent as r, parseTemplate as t };
93
+ //#region src/core/permdock-sql.ts
94
+ const SCOPE = /^[a-z_][a-z0-9_]*$/;
95
+ /** PermDock splits a key with row conditions into `key#1`, `key#2`, ...: those need its own policies. */
96
+ const SPLIT_KEY = /#\d+$/;
97
+ /**
98
+ * The SQL condition for one PermDock permission key. `id` is the text
99
+ * expression holding the scope id; it is compared as text, so a malformed
100
+ * path never raises a cast error.
101
+ *
102
+ * The helpers check role and scope, not a permission's row conditions, so
103
+ * the condition is only correct for permissions whose grants have none
104
+ * beyond the scope. `#n` keys are refused; other row-conditioned keys can't
105
+ * be detected here.
106
+ */
107
+ function permdockCheck(where, target, key, id) {
108
+ if (key === "") throw new TypeError(`${where}: a PermDock permission key is empty`);
109
+ if (SPLIT_KEY.test(key)) throw new TypeError(`${where}: "${key}" is one part of a permission PermDock splits by row condition. Use PermDock's generated policies for it.`);
110
+ const schema = sqlIdent(target.schema ?? "public");
111
+ if (target.scope === "global") return `(select ${schema}.permdock_has(${sqlString(key)}))`;
112
+ if (!SCOPE.test(target.scope)) throw new TypeError(`${where}: invalid PermDock scope "${target.scope}"`);
113
+ if (id === void 0) throw new TypeError(`${where}: scope "${target.scope}" needs a segment`);
114
+ return `${id} in (select t.id::text from ${schema}.${sqlIdent(`permitted_${target.scope}_ids`)}(${sqlString(key)}) as t(id))`;
115
+ }
116
+ //#endregion
117
+ export { sqlString as a, sqlIdent as i, parseTemplate as n, slug as r, permdockCheck as t };
@@ -1,5 +1,5 @@
1
- import { A as TableMeta, E as SchemaMeta, n as AnyModels } from "./types-C2fslP1z.js";
2
- import { g as Operation, h as MutationOp, r as Executor } from "./executor-Bazhgsgq.js";
1
+ import { A as SchemaMeta, P as TableMeta, n as AnyModels } from "./types-C83v5SQz.js";
2
+ import { g as Operation, h as MutationOp, r as Executor } from "./executor-CGdNQ27g.js";
3
3
  import { v as ErrorMapper } from "./result-CTkCZ6JA.js";
4
4
  //#region src/core/plugin.d.ts
5
5
  /** Who is making the request. */
@@ -1,4 +1,4 @@
1
- import { f as Plugin, h as RequestContext } from "../../plugin-HvGqCurB.js";
1
+ import { f as Plugin, h as RequestContext } from "../../plugin-C4TR9J0Z.js";
2
2
  //#region src/plugins/actor/index.d.ts
3
3
  export interface ActorOptions {
4
4
  /** Custom actor id resolution. Defaults to `context.actor.id` for users and services. */
@@ -1,5 +1,5 @@
1
- import { g as Operation } from "../../executor-Bazhgsgq.js";
2
- import { f as Plugin, m as RepositoryExtension } from "../../plugin-HvGqCurB.js";
1
+ import { g as Operation } from "../../executor-CGdNQ27g.js";
2
+ import { f as Plugin, m as RepositoryExtension } from "../../plugin-C4TR9J0Z.js";
3
3
  //#region src/plugins/rules/index.d.ts
4
4
  export type RuleLevel = "off" | "warn" | "error";
5
5
  /** A level, or a level with the rule's option: `['error', 500]`. */
@@ -20,7 +20,8 @@ export interface RuleSet {
20
20
  readonly maxIncludeDepth?: RuleSetting<number>;
21
21
  /**
22
22
  * Tenant tables queried without a tenant: neither `context.tenant` nor the
23
- * given claim (default `org_id`). Service connections are exempt.
23
+ * given claim (default `config.claims.tenant`, `tenant_id`). Service
24
+ * connections are exempt.
24
25
  */
25
26
  readonly requireTenantContext?: RuleSetting<string>;
26
27
  /** A service-role connection used where `window` and `document` exist. */
@@ -1,5 +1,6 @@
1
1
  import { n as dbError, t as DbException } from "../../errors-Bl3rkOzo.js";
2
2
  import { n as definePlugin } from "../../plugin-BqR6wKMB.js";
3
+ import { n as claimAt, r as claimsOf } from "../../claims-CoTobNC-.js";
3
4
  //#region src/plugins/rules/index.ts
4
5
  /** Catches data-exposure and correctness mistakes; everything else off. */
5
6
  function safe() {
@@ -56,14 +57,6 @@ function sensitiveColumns(selection, table) {
56
57
  function isBrowser() {
57
58
  return typeof globalThis.window !== "undefined" && typeof globalThis.document !== "undefined";
58
59
  }
59
- function claimValue(context, claim) {
60
- let value = context.claims;
61
- for (const part of claim.split(".")) {
62
- if (typeof value !== "object" || value === null) return void 0;
63
- value = value[part];
64
- }
65
- return value;
66
- }
67
60
  const TEXT_TYPES = /* @__PURE__ */ new Set([
68
61
  "text",
69
62
  "varchar",
@@ -107,10 +100,10 @@ function checks(rules) {
107
100
  const depth = selection ? includeDepth(selection) : 0;
108
101
  return depth > max ? `includes nest ${depth} levels deep (maximum ${max})` : void 0;
109
102
  },
110
- requireTenantContext: (op, { context }) => {
103
+ requireTenantContext: (op, { context, schema }) => {
111
104
  if (!op.table.flags.tenant || context.actor?.kind === "service") return void 0;
112
- const claim = optionOf(rules.requireTenantContext, "org_id");
113
- return context.tenant === void 0 && claimValue(context, claim) === void 0 ? `"${op.table.key}" is tenant-scoped but the request has no tenant (context.tenant or claim "${claim}")` : void 0;
105
+ const claim = optionOf(rules.requireTenantContext, claimsOf(schema).tenant);
106
+ return context.tenant === void 0 && claimAt(context.claims, claim) === void 0 ? `"${op.table.key}" is tenant-scoped but the request has no tenant (context.tenant or claim "${claim}")` : void 0;
114
107
  },
115
108
  noAdminInBrowser: (_op, { context }) => context.actor?.kind === "service" && isBrowser() ? "a service-role connection is running in a browser" : void 0,
116
109
  noSensitiveSelect: (op, { options }) => {
@@ -1,6 +1,6 @@
1
- import { y as PrimaryKeyValue } from "../../types-C2fslP1z.js";
1
+ import { C as PrimaryKeyValue } from "../../types-C83v5SQz.js";
2
2
  import { t as AsyncResult } from "../../result-CTkCZ6JA.js";
3
- import { f as Plugin, m as RepositoryExtension, o as HasFlag } from "../../plugin-HvGqCurB.js";
3
+ import { f as Plugin, m as RepositoryExtension, o as HasFlag } from "../../plugin-C4TR9J0Z.js";
4
4
  //#region src/plugins/soft-delete/index.d.ts
5
5
  export interface SoftDeleteFindArgs {
6
6
  /** Include soft-deleted rows of the queried table. */
@@ -1,4 +1,5 @@
1
- import { f as Plugin, h as RequestContext, m as RepositoryExtension, o as HasFlag } from "../../plugin-HvGqCurB.js";
1
+ import { A as SchemaMeta } from "../../types-C83v5SQz.js";
2
+ import { f as Plugin, h as RequestContext, m as RepositoryExtension, o as HasFlag } from "../../plugin-C4TR9J0Z.js";
2
3
  //#region src/plugins/tenant/index.d.ts
3
4
  /**
4
5
  * Dotted paths to the string claims of `C` (up to three levels), e.g.
@@ -10,7 +11,9 @@ type StringPaths<T, Depth extends readonly unknown[]> = T extends object ? T ext
10
11
  export interface TenantOptions<C = unknown> {
11
12
  /**
12
13
  * JWT claim path(s) holding the tenant id when `context.tenant` is not set.
13
- * Dots walk into objects. Default `['org_id', 'app_metadata.org_id']`.
14
+ * Dots walk into objects. Defaults to `config.claims.tenant` (`tenant_id`),
15
+ * then the same key in `app_metadata`. `user_metadata` is never a source:
16
+ * users can write it.
14
17
  */
15
18
  readonly claim?: ClaimPath<C> | readonly ClaimPath<C>[];
16
19
  /** Custom resolution, e.g. from a header validated against memberships. */
@@ -30,8 +33,11 @@ export interface TenantExtension extends RepositoryExtension {
30
33
  readonly methods: unknown;
31
34
  readonly deleteArgs: HasFlag<this["M"], this["T"], "tenant"> extends true ? TenantFindArgs : unknown;
32
35
  }
33
- /** The tenant for a request: `context.tenant`, then the configured claim. */
34
- export declare function resolveTenant<C = unknown>(context: RequestContext, options?: TenantOptions<C>): string | undefined;
36
+ /**
37
+ * The tenant for a request: `context.tenant`, then the configured claim.
38
+ * `schema` supplies the default claim (`config.claims.tenant`).
39
+ */
40
+ export declare function resolveTenant<C = unknown>(context: RequestContext, options?: TenantOptions<C>, schema?: Pick<SchemaMeta, "claims">): string | undefined;
35
41
  /**
36
42
  * Multi-tenancy for tables generated with `Flags.tenant`. Scopes reads,
37
43
  * updates and deletes to the request's tenant (nested includes and relation
@@ -1,21 +1,23 @@
1
1
  import { n as dbError, t as DbException } from "../../errors-Bl3rkOzo.js";
2
2
  import { n as definePlugin } from "../../plugin-BqR6wKMB.js";
3
3
  import { n as scopeOperation } from "../../scope-CDHcS7dE.js";
4
+ import { i as tenantClaimPaths, n as claimAt, r as claimsOf } from "../../claims-CoTobNC-.js";
4
5
  import { n as equals, r as forbidden, t as dbName } from "../../shared-_6-uPL7E.js";
5
6
  //#region src/plugins/tenant/index.ts
6
- /** The tenant for a request: `context.tenant`, then the configured claim. */
7
- function resolveTenant(context, options = {}) {
7
+ /**
8
+ * The tenant for a request: `context.tenant`, then the configured claim.
9
+ * `schema` supplies the default claim (`config.claims.tenant`).
10
+ */
11
+ function resolveTenant(context, options = {}, schema) {
8
12
  if (options.resolve) return options.resolve(context);
9
13
  if (typeof context.tenant === "string") return context.tenant;
10
14
  const claim = options.claim;
11
- const paths = typeof claim === "string" ? [claim] : claim ?? DEFAULT_CLAIMS;
15
+ const paths = typeof claim === "string" ? [claim] : claim ?? tenantClaimPaths(claimsOf(schema).tenant);
12
16
  for (const path of paths) {
13
- let value = context.claims;
14
- for (const segment of path.split(".")) value = typeof value === "object" && value !== null ? value[segment] : void 0;
15
- if (typeof value === "string" && value.length > 0) return value;
17
+ const value = claimAt(context.claims, path);
18
+ if (value !== void 0) return value;
16
19
  }
17
20
  }
18
- const DEFAULT_CLAIMS = ["org_id", "app_metadata.org_id"];
19
21
  function tenantColumn(table) {
20
22
  return dbName(table, table.flags.tenant);
21
23
  }
@@ -28,26 +30,26 @@ function tenantColumn(table) {
28
30
  */
29
31
  function tenant(options = {}) {
30
32
  const onMissing = options.onMissing ?? "error";
31
- const current = (table, context) => {
32
- const id = resolveTenant(context, options);
33
+ const current = (table, context, schema) => {
34
+ const id = resolveTenant(context, options, schema);
33
35
  if (id === void 0 && onMissing === "error" && tenantColumn(table)) throw new DbException(dbError("forbidden", `No tenant in the request context for "${table.key}"`));
34
36
  return id;
35
37
  };
36
38
  return definePlugin({
37
39
  name: "tenant",
38
- transformQuery(op, { context, options: call }) {
40
+ transformQuery(op, { context, schema, options: call }) {
39
41
  if (call["allTenants"] === true) return op;
40
- const id = current(op.table, context);
42
+ const id = current(op.table, context, schema);
41
43
  if (id === void 0) return op;
42
44
  return scopeOperation(op, (table) => {
43
45
  const column = tenantColumn(table);
44
46
  return column ? equals(column, id) : void 0;
45
47
  });
46
48
  },
47
- beforeMutation(op, { table, context, options: call }) {
49
+ beforeMutation(op, { table, context, schema, options: call }) {
48
50
  const column = tenantColumn(table);
49
51
  if (!column || call["allTenants"] === true) return op;
50
- const id = current(table, context);
52
+ const id = current(table, context, schema);
51
53
  if (id === void 0) return op;
52
54
  switch (op.kind) {
53
55
  case "insert": return {
@@ -1,4 +1,4 @@
1
- import { f as Plugin } from "../../plugin-HvGqCurB.js";
1
+ import { f as Plugin } from "../../plugin-C4TR9J0Z.js";
2
2
  //#region src/plugins/timestamps/index.d.ts
3
3
  /**
4
4
  * Stamps the columns generated as `Flags.timestamps`: `createdAt` on insert,
@@ -1,4 +1,4 @@
1
- import { f as Plugin } from "../../plugin-HvGqCurB.js";
1
+ import { f as Plugin } from "../../plugin-C4TR9J0Z.js";
2
2
  import { t as StandardSchemaV1 } from "../../standard-CyhRzctb.js";
3
3
  //#region src/plugins/validation/index.d.ts
4
4
  export interface TableValidators {
@@ -1,4 +1,4 @@
1
- import { t as SqlClient } from "./executor-Bje4suQF.js";
1
+ import { t as SqlClient } from "./executor-BYXQ9AGn.js";
2
2
  //#region src/postgres/pool.d.ts
3
3
  interface PostgresOptions {
4
4
  /** Defaults to `$SUPABASE_DB_URL`, then `$DATABASE_URL`. */
@@ -1,7 +1,7 @@
1
- import { g as Operation } from "../executor-Bazhgsgq.js";
2
- import { n as fromPgError, r as postgresExecutor, t as SqlClient } from "../executor-Bje4suQF.js";
3
- import { i as createPostgres, n as PostgresOptions, r as SqlClaims, t as Postgres } from "../pool-BFeqzwQS.js";
4
- import { t as Compiler } from "../compiler-DL18ukPe.js";
1
+ import { g as Operation } from "../executor-CGdNQ27g.js";
2
+ import { n as fromPgError, r as postgresExecutor, t as SqlClient } from "../executor-BYXQ9AGn.js";
3
+ import { i as createPostgres, n as PostgresOptions, r as SqlClaims, t as Postgres } from "../pool-R2m_DkXi.js";
4
+ import { t as Compiler } from "../compiler-CZ9nIuqy.js";
5
5
  //#region src/compile/sql.d.ts
6
6
  interface SqlQuery {
7
7
  readonly text: string;
@@ -1,5 +1,5 @@
1
- import { n as quoteIdent, t as compileSql } from "../sql-M8l3fnS0.js";
2
- import { n as postgresExecutor, t as fromPgError } from "../executor-Ceq60hPM.js";
1
+ import { n as quoteIdent, t as compileSql } from "../sql-DTjA1LPj.js";
2
+ import { n as postgresExecutor, t as fromPgError } from "../executor-DeppvirK.js";
3
3
  import { Pool } from "pg";
4
4
  //#region src/postgres/pool.ts
5
5
  const ROLES = /* @__PURE__ */ new Set(["authenticated", "anon"]);
@@ -1,4 +1,4 @@
1
- import { g as Operation } from "./executor-Bazhgsgq.js";
1
+ import { g as Operation } from "./executor-CGdNQ27g.js";
2
2
  //#region src/compile/postgrest.d.ts
3
3
  /**
4
4
  * A compiled PostgREST request, expressed as calls on the public
@@ -43,11 +43,11 @@ function toProblem(error, options = {}) {
43
43
  if (error.code) problem["code"] = error.code;
44
44
  if (error.hint) problem["hint"] = error.hint;
45
45
  if ("constraint" in error && error.constraint) problem["constraint"] = error.constraint;
46
- if ("columns" in error && error.columns) problem["columns"] = error.columns;
46
+ if ("columns" in error) problem["columns"] = error.columns;
47
47
  if ("column" in error && error.column) problem["column"] = error.column;
48
48
  if ("issues" in error) problem["issues"] = error.issues;
49
- if ("required" in error && error.required) problem["required"] = error.required;
50
- if ("retryAfter" in error && error.retryAfter !== void 0) problem["retryAfter"] = error.retryAfter;
49
+ if ("required" in error) problem["required"] = error.required;
50
+ if ("retryAfter" in error) problem["retryAfter"] = error.retryAfter;
51
51
  return problem;
52
52
  }
53
53
  /**
@@ -62,7 +62,7 @@ function problemResponse(error, options = {}) {
62
62
  const params = error.code === "MISSING_CREDENTIALS" ? "" : ", error=\"invalid_token\"";
63
63
  headers.set("www-authenticate", `Bearer realm="${realm}"${params}`);
64
64
  }
65
- if ("retryAfter" in error && error.retryAfter !== void 0 && !headers.has("retry-after")) headers.set("retry-after", String(error.retryAfter));
65
+ if ("retryAfter" in error && !headers.has("retry-after")) headers.set("retry-after", String(error.retryAfter));
66
66
  return new Response(JSON.stringify(toProblem(error, options)), {
67
67
  status: error.status,
68
68
  headers
@@ -1,2 +1,2 @@
1
- import { a as QueryHelpers, c as TableQueries, d as queryCache, f as BetterQueryMeta, i as Queries, l as createQueries, n as InfiniteOptionsOf, o as QueryKeyOf, p as invalidateTables, r as MutationOptionsOf, s as QueryOptionsOf, t as CreateQueriesOptions, u as invalidateOnMutation } from "../index-Dup-nSe9.js";
1
+ import { a as QueryHelpers, c as TableQueries, d as queryCache, f as BetterQueryMeta, i as Queries, l as createQueries, n as InfiniteOptionsOf, o as QueryKeyOf, p as invalidateTables, r as MutationOptionsOf, s as QueryOptionsOf, t as CreateQueriesOptions, u as invalidateOnMutation } from "../index-K-3WM2Hp.js";
2
2
  export { type BetterQueryMeta, CreateQueriesOptions, InfiniteOptionsOf, MutationOptionsOf, Queries, QueryHelpers, QueryKeyOf, QueryOptionsOf, TableQueries, createQueries, invalidateOnMutation, invalidateTables, queryCache };
@@ -1,7 +1,7 @@
1
1
  import { s as Impersonator } from "../mfa-TVia554c.js";
2
- import { t as AuthSession } from "../view-B0ltUmTi.js";
3
- import { r as LiveCountSeed } from "../live-6b9i72Ux.js";
4
- import { n as hasEntitlement, t as EntitlementKey } from "../entitlements-BBg61DQZ.js";
5
- import { n as SessionProviderProps, r as useSession, t as SessionProvider } from "../session-C3osL21k.js";
6
- import { a as BrowserLike, c as LiveCountHookOptions, d as useAuth, f as useBroadcast, h as useSupabase, i as BroadcastOptions, l as LiveQueryHookOptions, m as useLiveQuery, n as BetterSupabaseProvider, o as ClaimsOf, p as useLiveCount, r as BetterSupabaseProviderProps, s as LiveCount, t as BetterHooks, u as createHooks } from "../index-Hf8PP9sP.js";
7
- export { type AuthSession, BetterHooks, BetterSupabaseProvider, BetterSupabaseProviderProps, BroadcastOptions, BrowserLike, ClaimsOf, type EntitlementKey, type Impersonator, LiveCount, LiveCountHookOptions, type LiveCountSeed, LiveQueryHookOptions, SessionProvider, type SessionProviderProps, createHooks, hasEntitlement, useAuth, useBroadcast, useLiveCount, useLiveQuery, useSession, useSupabase };
2
+ import { t as AuthSession } from "../view-D1s0wa0T.js";
3
+ import { r as LiveCountSeed } from "../live-DJyZMD6w.js";
4
+ import { n as MembershipClaim, r as hasEntitlement, t as EntitlementKey } from "../entitlements-Dng-ctuT.js";
5
+ import { n as SessionProviderProps, r as useSession, t as SessionProvider } from "../session-C3LxnQ0e.js";
6
+ import { a as BrowserLike, c as LiveCountHookOptions, d as createHooks, f as useAuth, g as useSupabase, h as useLiveQuery, i as BroadcastOptions, l as LiveQueryHookOptions, m as useLiveCount, n as BetterSupabaseProvider, o as ClaimsOf, p as useBroadcast, r as BetterSupabaseProviderProps, s as LiveCount, t as BetterHooks, u as ProfileOf } from "../index-CBDufH1M.js";
7
+ export { type AuthSession, BetterHooks, BetterSupabaseProvider, BetterSupabaseProviderProps, BroadcastOptions, BrowserLike, ClaimsOf, type EntitlementKey, type Impersonator, LiveCount, LiveCountHookOptions, type LiveCountSeed, LiveQueryHookOptions, type MembershipClaim, ProfileOf, SessionProvider, type SessionProviderProps, createHooks, hasEntitlement, useAuth, useBroadcast, useLiveCount, useLiveQuery, useSession, useSupabase };
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { n as useSession, t as SessionProvider } from "../session-CD-3orO_.js";
3
- import { t as hasEntitlement } from "../entitlements-BC_khwRy.js";
4
- import { a as useLiveCount, i as useBroadcast, n as createHooks, o as useLiveQuery, r as useAuth, s as useSupabase, t as BetterSupabaseProvider } from "../react-CrOvrnIP.js";
2
+ import { n as useSession, t as SessionProvider } from "../session-CqEwzVup.js";
3
+ import { t as hasEntitlement } from "../entitlements-CTEBm7IB.js";
4
+ import { a as useLiveCount, i as useBroadcast, n as createHooks, o as useLiveQuery, r as useAuth, s as useSupabase, t as BetterSupabaseProvider } from "../react-C83BdBGt.js";
5
5
  export { BetterSupabaseProvider, SessionProvider, createHooks, hasEntitlement, useAuth, useBroadcast, useLiveCount, useLiveQuery, useSession, useSupabase };
@@ -1,13 +1,13 @@
1
- import { t as AuthSession } from "../view-B0ltUmTi.js";
2
- import { n as SessionProviderProps, t as SessionProvider } from "../session-C3osL21k.js";
3
- import { a as BrowserLike, d as useAuth, f as useBroadcast, h as useSupabase, i as BroadcastOptions, l as LiveQueryHookOptions, m as useLiveQuery, n as BetterSupabaseProvider, o as ClaimsOf, r as BetterSupabaseProviderProps, t as BetterHooks } from "../index-Hf8PP9sP.js";
1
+ import { t as AuthSession } from "../view-D1s0wa0T.js";
2
+ import { n as SessionProviderProps, t as SessionProvider } from "../session-C3LxnQ0e.js";
3
+ import { a as BrowserLike, f as useAuth, g as useSupabase, h as useLiveQuery, i as BroadcastOptions, l as LiveQueryHookOptions, n as BetterSupabaseProvider, o as ClaimsOf, p as useBroadcast, r as BetterSupabaseProviderProps, t as BetterHooks, u as ProfileOf } from "../index-CBDufH1M.js";
4
4
  //#region src/react/server.d.ts
5
5
  /** The `react-server` build of `useSession`: await `next.session()` instead. */
6
- export declare const useSession: <C = unknown>() => AuthSession<C>;
6
+ export declare const useSession: <C = unknown, P = unknown>() => AuthSession<C, P>;
7
7
  /**
8
8
  * The `react-server` build of `createHooks`: importing a module that creates
9
9
  * hooks is safe on the server, calling a hook there throws.
10
10
  */
11
11
  export declare function createHooks<B extends BrowserLike>(): BetterHooks<B>;
12
12
  //#endregion
13
- export { type AuthSession, type BetterHooks, BetterSupabaseProvider, type BetterSupabaseProviderProps, type BroadcastOptions, type BrowserLike, type ClaimsOf, type LiveQueryHookOptions, SessionProvider, type SessionProviderProps, useAuth, useBroadcast, useLiveQuery, useSupabase };
13
+ export { type AuthSession, type BetterHooks, BetterSupabaseProvider, type BetterSupabaseProviderProps, type BroadcastOptions, type BrowserLike, type ClaimsOf, type LiveQueryHookOptions, type ProfileOf, SessionProvider, type SessionProviderProps, useAuth, useBroadcast, useLiveQuery, useSupabase };
@@ -1,4 +1,4 @@
1
- import { i as useBroadcast, o as useLiveQuery, r as useAuth, s as useSupabase, t as BetterSupabaseProvider } from "../react-CrOvrnIP.js";
1
+ import { i as useBroadcast, o as useLiveQuery, r as useAuth, s as useSupabase, t as BetterSupabaseProvider } from "../react-C83BdBGt.js";
2
2
  import { SessionProvider } from "./session.js";
3
3
  //#region src/react/server.ts
4
4
  function clientOnly(name) {
@@ -1,2 +1,2 @@
1
- import { n as SessionProviderProps, r as useSession, t as SessionProvider } from "../session-C3osL21k.js";
1
+ import { n as SessionProviderProps, r as useSession, t as SessionProvider } from "../session-C3LxnQ0e.js";
2
2
  export { SessionProvider, SessionProviderProps, useSession };
@@ -1,3 +1,3 @@
1
1
  "use client";
2
- import { n as useSession, t as SessionProvider } from "../session-CD-3orO_.js";
2
+ import { n as useSession, t as SessionProvider } from "../session-CqEwzVup.js";
3
3
  export { SessionProvider, useSession };
@@ -1,6 +1,7 @@
1
+ import { i as tenantClaimPaths, n as claimAt, r as claimsOf } from "./claims-CoTobNC-.js";
1
2
  import { t as invalidateTables } from "./invalidate-DbxuL2jL.js";
2
3
  import { n as liveQuery, t as liveCount } from "./live-D8rV1Ldw.js";
3
- import { n as useSession } from "./session-CD-3orO_.js";
4
+ import { n as useSession } from "./session-CqEwzVup.js";
4
5
  import { createContext, createElement, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
5
6
  //#region src/react/index.ts
6
7
  const BrowserContext = createContext(null);
@@ -124,12 +125,12 @@ function useBroadcast(topic, values, handlers, options) {
124
125
  ]);
125
126
  return status;
126
127
  }
127
- function claimedTenant(auth) {
128
+ function claimedTenant(auth, meta) {
128
129
  if (auth.status !== "signed-in") return void 0;
129
- const top = auth.claims["org_id"];
130
- if (typeof top === "string") return top;
131
- const app = auth.claims["app_metadata"];
132
- return typeof app?.["org_id"] === "string" ? app["org_id"] : void 0;
130
+ for (const path of tenantClaimPaths(claimsOf(meta).tenant)) {
131
+ const value = claimAt(auth.claims, path);
132
+ if (value !== void 0) return value;
133
+ }
133
134
  }
134
135
  /**
135
136
  * Keeps a query fresh: invalidates every cached query that read a table the
@@ -148,7 +149,7 @@ function useLiveQuery(spec, options = {}) {
148
149
  const [status, setStatus] = useState("closed");
149
150
  if (spec && !queryClient) throw new Error("better-supabase: useLiveQuery needs <BetterSupabaseProvider queryClient={...}>");
150
151
  const key = spec ? JSON.stringify(spec) : null;
151
- const tenant = options.tenant ?? claimedTenant(auth);
152
+ const tenant = options.tenant ?? claimedTenant(auth, browser.sb.meta);
152
153
  const userId = auth.user?.id ?? null;
153
154
  const debounceMs = options.debounceMs;
154
155
  useEffect(() => {
@@ -196,7 +197,7 @@ function useLiveCount(source, options = {}) {
196
197
  });
197
198
  const [status, setStatus] = useState("closed");
198
199
  const key = spec ? JSON.stringify(spec) : null;
199
- const tenant = options.tenant ?? claimedTenant(auth);
200
+ const tenant = options.tenant ?? claimedTenant(auth, browser.sb.meta);
200
201
  const userId = auth.user?.id ?? null;
201
202
  const debounceMs = options.debounceMs;
202
203
  const hasInitial = initial !== void 0;
@@ -1,4 +1,4 @@
1
- import { r as IrBuilder, u as tableMeta } from "./simplify-oHiDKRVQ.js";
1
+ import { r as IrBuilder, u as tableMeta } from "./simplify-bwJpLnaS.js";
2
2
  import { n as touchedTables } from "./tables-rZxRxNPW.js";
3
3
  //#region src/core/spec.ts
4
4
  const READ_METHODS = [
@@ -1,3 +1,4 @@
1
+ import { x as PermdockTopicPolicy } from "../types-C83v5SQz.js";
1
2
  import { n as TemplateValues, t as TemplateParams } from "../template-mbvlysOo.js";
2
- import { C as defineTopic, S as TriggerOptions, _ as TopicEvent, a as LiveSource, b as TopicOptions, c as liveQuery, d as RealtimeClient, f as RowChange, g as Topic, h as SubscriptionStatus, i as LiveQueryOptions, l as liveTopic, m as Subscription, n as LiveCountOptions, o as LiveSubscription, p as SubscribeOptions, r as LiveCountSeed, s as liveCount, t as CountRunner, u as EventSchemas, v as TopicHandlers, w as rowChange, x as TopicPayload, y as TopicMessage } from "../live-6b9i72Ux.js";
3
- export { type CountRunner, EventSchemas, type LiveCountOptions, type LiveCountSeed, type LiveQueryOptions, type LiveSource, type LiveSubscription, RealtimeClient, RowChange, SubscribeOptions, Subscription, SubscriptionStatus, type TemplateParams, type TemplateValues, Topic, TopicEvent, TopicHandlers, TopicMessage, TopicOptions, TopicPayload, TriggerOptions, defineTopic, liveCount, liveQuery, liveTopic, rowChange };
3
+ import { C as defineTopic, S as TriggerOptions, _ as TopicEvent, a as LiveSource, b as TopicOptions, c as liveQuery, d as RealtimeClient, f as RowChange, g as Topic, h as SubscriptionStatus, i as LiveQueryOptions, l as liveTopic, m as Subscription, n as LiveCountOptions, o as LiveSubscription, p as SubscribeOptions, r as LiveCountSeed, s as liveCount, t as CountRunner, u as EventSchemas, v as TopicHandlers, w as rowChange, x as TopicPayload, y as TopicMessage } from "../live-DJyZMD6w.js";
4
+ export { type CountRunner, EventSchemas, type LiveCountOptions, type LiveCountSeed, type LiveQueryOptions, type LiveSource, type LiveSubscription, type PermdockTopicPolicy, RealtimeClient, RowChange, SubscribeOptions, Subscription, SubscriptionStatus, type TemplateParams, type TemplateValues, Topic, TopicEvent, TopicHandlers, TopicMessage, TopicOptions, TopicPayload, TriggerOptions, defineTopic, liveCount, liveQuery, liveTopic, rowChange };
@@ -1,8 +1,9 @@
1
1
  import { n as dbError } from "../errors-Bl3rkOzo.js";
2
2
  import { i as ok, n as err, t as AsyncResult } from "../result-DWXatkd6.js";
3
+ import { i as tenantClaimPaths } from "../claims-CoTobNC-.js";
3
4
  import { n as liveQuery, r as liveTopic, t as liveCount } from "../live-D8rV1Ldw.js";
4
5
  import { s as toApp } from "../shared-_6-uPL7E.js";
5
- import { i as sqlString, n as slug, r as sqlIdent, t as parseTemplate } from "../template-BeOGnynM.js";
6
+ import { a as sqlString, i as sqlIdent, n as parseTemplate, r as slug, t as permdockCheck } from "../permdock-sql-CghlHPuH.js";
6
7
  import { REALTIME_SUBSCRIBE_STATES } from "@supabase/supabase-js";
7
8
  //#region src/realtime/index.ts
8
9
  const VALUE = /^[\w.@+=-]+$/;
@@ -64,10 +65,21 @@ function defineTopic(template, options = {}) {
64
65
  return index;
65
66
  };
66
67
  const checks = [];
68
+ const permdock = options.permdock;
67
69
  const tenantParam = options.tenant === false ? void 0 : options.tenant?.param ?? "orgId";
68
- if (tenantParam && (options.tenant || parsed.params.includes(tenantParam))) {
69
- const tenant = options.tenant || {};
70
- const expression = tenant.sql ?? claimSql(tenant.claim ?? ["org_id", "app_metadata.org_id"]);
70
+ const permdockChecks = (() => {
71
+ if (!permdock) return void 0;
72
+ const where = `defineTopic(${template})`;
73
+ const id = permdock.scope === "global" ? void 0 : `split_part((select realtime.topic()), ':', ${String(permdock.segment ?? segment(tenantParam ?? "orgId", "PermDock"))})`;
74
+ const receive = permdockCheck(where, permdock, permdock.receive, id);
75
+ return {
76
+ receive,
77
+ send: permdock.send === void 0 ? receive : permdockCheck(where, permdock, permdock.send, id)
78
+ };
79
+ })();
80
+ if (!permdock && tenantParam && (options.tenant || parsed.params.includes(tenantParam))) {
81
+ const tenant = options.tenant === false ? {} : options.tenant ?? {};
82
+ const expression = tenant.sql ?? claimSql(tenant.claim ?? tenantClaimPaths());
71
83
  checks.push(`split_part((select realtime.topic()), ':', ${String(segment(tenantParam, "tenant"))}) = (${expression})`);
72
84
  }
73
85
  const ownerParam = options.owner === false ? void 0 : options.owner?.param ?? "userId";
@@ -82,25 +94,28 @@ function defineTopic(template, options = {}) {
82
94
  match: (topic) => parsed.match(topic),
83
95
  sql() {
84
96
  const extensions = options.presence ? "('broadcast', 'presence')" : "('broadcast')";
85
- const condition = [
97
+ const condition = (extra) => [
86
98
  `(select realtime.topic()) ~ ${sqlString(parsed.sqlPattern)}`,
87
99
  `realtime.messages.extension in ${extensions}`,
88
- ...checks
100
+ ...checks,
101
+ ...extra === void 0 ? [] : [extra]
89
102
  ].join("\n and ");
90
103
  const lines = [`-- better-supabase: topic ${template}`];
91
104
  const policies = [[
92
105
  "receive",
93
106
  "select",
94
- "using"
107
+ "using",
108
+ condition(permdockChecks?.receive)
95
109
  ]];
96
- if (options.send || options.presence) policies.push([
110
+ if (options.send || options.presence || permdock?.send !== void 0) policies.push([
97
111
  "send",
98
112
  "insert",
99
- "with check"
113
+ "with check",
114
+ condition(permdockChecks?.send)
100
115
  ]);
101
- for (const [suffix, command, clause] of policies) {
116
+ for (const [suffix, command, clause, check] of policies) {
102
117
  const policy = sqlIdent(`bs_topic_${name}_${suffix}`);
103
- lines.push(`drop policy if exists ${policy} on realtime.messages;`, `create policy ${policy} on realtime.messages for ${command} to authenticated\n ${clause} (\n ${condition}\n );`);
118
+ lines.push(`drop policy if exists ${policy} on realtime.messages;`, `create policy ${policy} on realtime.messages for ${command} to authenticated\n ${clause} (\n ${check}\n );`);
104
119
  }
105
120
  return `${lines.join("\n")}\n`;
106
121
  },
@@ -1,6 +1,6 @@
1
1
  import { p as DbError } from "./result-CTkCZ6JA.js";
2
- import { l as RefreshEvent } from "./events-2OJsVG_d.js";
3
- import { h as RequestContext } from "./plugin-HvGqCurB.js";
2
+ import { f as Logger, l as RefreshEvent } from "./events-DOt3nSO-.js";
3
+ import { h as RequestContext } from "./plugin-C4TR9J0Z.js";
4
4
  import { t as StandardSchemaV1 } from "./standard-CyhRzctb.js";
5
5
  import { t as BetterSupabaseEnv } from "./index-Dy6kuF0P.js";
6
6
  import { CookieOptions } from "@supabase/ssr";
@@ -47,9 +47,10 @@ declare function applyCookieWrites(cookies: readonly CookieRecord[], writes: rea
47
47
  //#region src/auth/resolve.d.ts
48
48
  /**
49
49
  * Who is calling. `C` is the claims type from `sb.claims(schema)`; the
50
- * verified payload keeps every JWT claim and adds the schema's output.
50
+ * verified payload keeps every JWT claim and adds the schema's output. `P`
51
+ * is the `user_metadata` type from `sb.userMetadata(schema)`.
51
52
  */
52
- type AuthState<C = unknown> = {
53
+ type AuthState<C = unknown, P = unknown> = {
53
54
  readonly kind: "user";
54
55
  readonly token: string;
55
56
  readonly claims: JWTClaims & C;
@@ -57,6 +58,12 @@ type AuthState<C = unknown> = {
57
58
  readonly source: "bearer" | "cookie" | (string & {});
58
59
  /** Seconds since epoch, from the token's `exp`. */
59
60
  readonly expiresAt: number | null;
61
+ /**
62
+ * `user_metadata` parsed by `sb.userMetadata(schema)`; `undefined`
63
+ * without a schema or when the metadata fails it. Users can write this
64
+ * data themselves: use it for display, never for access.
65
+ */
66
+ readonly profile?: P;
60
67
  } | {
61
68
  readonly kind: "service";
62
69
  readonly keyName: string;
@@ -114,6 +121,14 @@ interface ResolveAuthOptions {
114
121
  * resolves to `{ kind: 'invalid', reason: 'claims' }`.
115
122
  */
116
123
  readonly claims?: StandardSchemaV1;
124
+ /**
125
+ * Parses `user_metadata` into `profile` (`sb.userMetadata(schema)` sets
126
+ * it). A failure leaves `profile` undefined and warns once; the session
127
+ * stays valid.
128
+ */
129
+ readonly userMetadata?: StandardSchemaV1;
130
+ /** Receives the `userMetadata` warning. Defaults to `console`. */
131
+ readonly logger?: Logger;
117
132
  readonly resolvers?: readonly AuthResolver[];
118
133
  /**
119
134
  * The caller's IP, sent to Auth as `Sb-Forwarded-For` on refreshes so its
@@ -127,8 +142,8 @@ interface ResolveAuthOptions {
127
142
  readonly fetch?: typeof fetch;
128
143
  readonly now?: () => number;
129
144
  }
130
- interface AuthResolution<C = unknown> {
131
- readonly auth: AuthState<C>;
145
+ interface AuthResolution<C = unknown, P = unknown> {
146
+ readonly auth: AuthState<C, P>;
132
147
  /** Cookie writes for the response. Empty unless the session was refreshed or cleared. */
133
148
  readonly cookies: readonly CookieWrite[];
134
149
  /** No-store headers, set whenever `cookies` is not empty. */
@@ -1,7 +1,7 @@
1
1
  import { n as dbError } from "./errors-Bl3rkOzo.js";
2
2
  import { i as ok, n as err } from "./result-DWXatkd6.js";
3
3
  import { t as validate } from "./standard-FUi3Z3-7.js";
4
- import { i as respond } from "./respond-4-dhoV7x.js";
4
+ import { i as respond } from "./respond-DMcbQwfN.js";
5
5
  //#region src/server/resource.ts
6
6
  const INTEGER = /* @__PURE__ */ new Set([
7
7
  "int2",
@@ -1,8 +1,8 @@
1
- import { A as TableMeta, P as Update, h as Insert, k as TableKey, n as AnyModels, t as AnyFunctions } from "./types-C2fslP1z.js";
1
+ import { N as TableKey, P as TableMeta, R as Update, _ as Insert, n as AnyModels, t as AnyFunctions } from "./types-C83v5SQz.js";
2
2
  import { b as ValidationIssue, o as Result } from "./result-CTkCZ6JA.js";
3
- import { t as BetterSupabase, xt as SelectArg } from "./define-CTfWw-SS.js";
4
- import { r as RespondOptions } from "./respond-PoTpy5DT.js";
5
- import { i as ResourceOperation } from "./index-DRid0qIv.js";
3
+ import { t as BetterSupabase, xt as SelectArg } from "./define-e3zI4_4g.js";
4
+ import { r as RespondOptions } from "./respond-Dne1ARSa.js";
5
+ import { i as ResourceOperation } from "./index-DbxFr7XG.js";
6
6
  import { StandardSchemaV1 } from "@standard-schema/spec";
7
7
  //#region src/server/resource.d.ts
8
8
  /** What a resource needs from `defineListQuery`. */
@@ -1,10 +1,10 @@
1
1
  import { n as dbError, o as isDbError, r as dbErrorOf } 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 { a as postgrestExecutor, n as StatsRecorder } from "./stats-3iy8u3_P.js";
4
- import { a as problemResponse } from "./problem-DPu6Fh-t.js";
3
+ import { a as postgrestExecutor, n as StatsRecorder } from "./stats-C5W-rBfR.js";
4
+ import { a as problemResponse } from "./problem-BTkTtRV9.js";
5
5
  import { i as loadEnv } from "./env-BEToab0I.js";
6
- import { h as actClaim, i as authContext, o as resolveAuth, r as checkAal } from "./mfa-CpogP66z.js";
7
- import { n as postgresExecutor } from "./executor-Ceq60hPM.js";
6
+ import { h as actClaim, i as authContext, o as resolveAuth, r as checkAal } from "./mfa-CpLfJSde.js";
7
+ import { n as postgresExecutor } from "./executor-DeppvirK.js";
8
8
  import { createClient } from "@supabase/supabase-js";
9
9
  //#region src/server/replicas.ts
10
10
  /** Cookie holding the epoch ms until which reads stay on the primary. */
@@ -257,9 +257,12 @@ function createServer(sb, options = {}) {
257
257
  };
258
258
  const resolve = async (request, resolveOptions = {}) => {
259
259
  const claims = options.auth?.claims ?? sb.claimsSchema;
260
+ const userMetadata = sb.userMetadataSchema;
260
261
  const resolution = await resolveAuth(request, {
262
+ logger: sb.events.logger,
261
263
  ...options.auth,
262
264
  ...claims ? { claims } : {},
265
+ ...userMetadata ? { userMetadata } : {},
263
266
  env: env(),
264
267
  ...resolveOptions.refresh !== void 0 ? { refresh: resolveOptions.refresh } : {},
265
268
  onRefresh: (event) => {