better-supabase 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/README.md +34 -31
  2. package/dist/base64-CQeB1eSf.js +42 -0
  3. package/dist/client/index.d.ts +1 -1
  4. package/dist/client/index.js +4 -14
  5. package/dist/{compiler-CZ9nIuqy.d.ts → compiler-2zqGzxVZ.d.ts} +2 -2
  6. package/dist/config/index.d.ts +4 -3
  7. package/dist/config/index.js +5 -3
  8. package/dist/config-Be4GwsqI.js +129 -0
  9. package/dist/{index-DOsjFvMf.d.ts → config-C1CYcm6o.d.ts} +49 -49
  10. package/dist/{config-ClDXmVtY.js → config-DOsGYSiT.js} +14 -137
  11. package/dist/{define-BXMYD9AY.js → define-DF341GDj.js} +71 -51
  12. package/dist/{define-e3zI4_4g.d.ts → define-DUbydmJa.d.ts} +10 -9
  13. package/dist/edge/index.d.ts +4 -4
  14. package/dist/edge/index.js +4 -4
  15. package/dist/{entitlements-Dng-ctuT.d.ts → entitlements-DvJXoI02.d.ts} +1 -1
  16. package/dist/env/index.js +203 -1
  17. package/dist/events/index.d.ts +1 -1
  18. package/dist/events/index.js +139 -1
  19. package/dist/{events-DOt3nSO-.d.ts → events-Do8jXh4D.d.ts} +3 -3
  20. package/dist/{executor-BYXQ9AGn.d.ts → executor-B26lgbHD.d.ts} +2 -2
  21. package/dist/{executor-DeppvirK.js → executor-C57jx2pn.js} +7 -2
  22. package/dist/{executor-CGdNQ27g.d.ts → executor-DynmIWhq.d.ts} +2 -2
  23. package/dist/hono/index.d.ts +5 -5
  24. package/dist/hono/index.js +4 -4
  25. package/dist/{index-CBDufH1M.d.ts → index-BNsABq7P.d.ts} +8 -8
  26. package/dist/{index-Bw1bwtC0.d.ts → index-CADlNHK-.d.ts} +27 -14
  27. package/dist/{index-DuP14VHo.d.ts → index-CTTMS6_1.d.ts} +19 -8
  28. package/dist/index-Cf-D2jk1.d.ts +50 -0
  29. package/dist/{index-K-3WM2Hp.d.ts → index-CriFFJ_p.d.ts} +4 -4
  30. package/dist/{index-Ciu5Xlml.d.ts → index-GV77NpRP.d.ts} +5 -4
  31. package/dist/{index-D4v7sncu.d.ts → index-UJ-LUxtI.d.ts} +3 -3
  32. package/dist/{index-CG69s15v.d.ts → index-kpgopLNv.d.ts} +4 -3
  33. package/dist/{index-DbxFr7XG.d.ts → index-qriRM9cZ.d.ts} +7 -2
  34. package/dist/index.d.ts +12 -12
  35. package/dist/index.js +16 -7
  36. package/dist/jobs/index.d.ts +25 -24
  37. package/dist/jobs/index.js +16 -10
  38. package/dist/{json-schema-BpYqkCKf.js → json-schema--aOXAGfU.js} +7 -2
  39. package/dist/lint/index.js +1 -1
  40. package/dist/list/index.d.ts +2 -2
  41. package/dist/list/index.js +128 -93
  42. package/dist/{live-DJyZMD6w.d.ts → live-QE3UPbGm.d.ts} +16 -6
  43. package/dist/mcp/index.d.ts +24 -17
  44. package/dist/mcp/index.js +41 -12
  45. package/dist/{mfa-CpLfJSde.js → mfa-BxoR1RkN.js} +74 -19
  46. package/dist/{mfa-TVia554c.d.ts → mfa-x3V3vGh-.d.ts} +1 -1
  47. package/dist/next/index.d.ts +39 -26
  48. package/dist/next/index.js +28 -23
  49. package/dist/openapi/index.d.ts +1 -1
  50. package/dist/openapi/index.js +57 -34
  51. package/dist/orpc/index.d.ts +6 -6
  52. package/dist/orpc/index.js +3 -3
  53. package/dist/otel/index.d.ts +2 -2
  54. package/dist/otel/index.js +4 -2
  55. package/dist/{permdock-sql-CghlHPuH.js → permdock-sql-Bta_G0v-.js} +11 -6
  56. package/dist/permdock-sql-DImJULY-.d.ts +17 -0
  57. package/dist/{plugin-C4TR9J0Z.d.ts → plugin-DVRB8qNE.d.ts} +5 -4
  58. package/dist/plugins/actor/index.d.ts +1 -1
  59. package/dist/plugins/rules/index.d.ts +2 -2
  60. package/dist/plugins/rules/index.js +4 -4
  61. package/dist/plugins/soft-delete/index.d.ts +3 -3
  62. package/dist/plugins/soft-delete/index.js +2 -2
  63. package/dist/plugins/tenant/index.d.ts +2 -2
  64. package/dist/plugins/timestamps/index.d.ts +1 -1
  65. package/dist/plugins/timestamps/index.js +1 -1
  66. package/dist/plugins/validation/index.d.ts +2 -2
  67. package/dist/pool-B9qsLyFR.d.ts +71 -0
  68. package/dist/postgres/index.d.ts +10 -5
  69. package/dist/postgres/index.js +36 -16
  70. package/dist/{postgrest-cAEQ_IQN.d.ts → postgrest-DmBlevh-.d.ts} +1 -1
  71. package/dist/{problem-BTkTtRV9.js → problem-CGt1ADix.js} +10 -4
  72. package/dist/{problem-DlgB0lYl.d.ts → problem-Z2RTQjZD.d.ts} +6 -4
  73. package/dist/query/index.d.ts +2 -2
  74. package/dist/query/index.js +1 -1
  75. package/dist/{query-ChvDbsDE.js → query-BdKLTPlj.js} +2 -2
  76. package/dist/react/index.d.ts +7 -7
  77. package/dist/react/index.js +2 -2
  78. package/dist/react/server.d.ts +3 -3
  79. package/dist/react/server.js +1 -1
  80. package/dist/react/session.d.ts +21 -2
  81. package/dist/react/session.js +19 -1
  82. package/dist/{react-C83BdBGt.js → react-DNBYNazu.js} +20 -16
  83. package/dist/{read-set-4lI3W_gZ.js → read-set-D0qBcboM.js} +3 -3
  84. package/dist/realtime/index.d.ts +4 -3
  85. package/dist/realtime/index.js +7 -6
  86. package/dist/{resolve-CjHILk2w.d.ts → resolve-BRciX2jK.d.ts} +6 -5
  87. package/dist/{resource-CgZa3YG_.d.ts → resource-CwVgiI5q.d.ts} +16 -7
  88. package/dist/{resource-BHEWmQJK.js → resource-D30rp0GN.js} +38 -16
  89. package/dist/{respond-DMcbQwfN.js → respond-C44EZAJo.js} +35 -19
  90. package/dist/{respond-Dne1ARSa.d.ts → respond-DAkPIdTH.d.ts} +15 -9
  91. package/dist/{result-CTkCZ6JA.d.ts → result-c2OYgCV2.d.ts} +13 -8
  92. package/dist/server/index.d.ts +35 -10
  93. package/dist/server/index.js +38 -9
  94. package/dist/{simplify-bwJpLnaS.js → simplify-LakqK1vH.js} +10 -16
  95. package/dist/sql/index.d.ts +139 -0
  96. package/dist/sql/index.js +1983 -0
  97. package/dist/{sql-DTjA1LPj.js → sql-BIgk12ew.js} +72 -16
  98. package/dist/ssr/index.d.ts +4 -4
  99. package/dist/ssr/index.js +2 -2
  100. package/dist/{standard-CyhRzctb.d.ts → standard-eudBiRk1.d.ts} +1 -1
  101. package/dist/{stats-C5W-rBfR.js → stats-D78UQ8Yu.js} +8 -7
  102. package/dist/storage/index.d.ts +4 -3
  103. package/dist/storage/index.js +530 -1
  104. package/dist/{tables-rZxRxNPW.js → tables-Dhha3BXM.js} +5 -5
  105. package/dist/temporal-BwshQk0W.js +27 -0
  106. package/dist/temporal-required-CMxeSVPo.js +19 -0
  107. package/dist/testing/index.d.ts +13 -11
  108. package/dist/testing/index.js +128 -29
  109. package/dist/{types-C83v5SQz.d.ts → types-DONv9SHN.d.ts} +14 -11
  110. package/dist/{version-Cqq1m3UY.js → version-BfpG2gks.js} +1 -1
  111. package/dist/{view-D1s0wa0T.d.ts → view-3Po_PVlr.d.ts} +34 -4
  112. package/dist/{view-aOYizTeE.js → view-wZ-9qIUz.js} +11 -2
  113. package/dist/webhooks/index.d.ts +18 -16
  114. package/dist/webhooks/index.js +1 -1
  115. package/dist/{webhooks-DMipjhSP.js → webhooks-CAIFQSTM.js} +11 -9
  116. package/package.json +24 -28
  117. package/schemas/config-v1.json +31 -1
  118. package/schemas/doctor-report-v1.json +17 -1
  119. package/schemas/snapshot-v2.json +35 -0
  120. package/skills/better-supabase/SKILL.md +23 -11
  121. package/skills/better-supabase/references/plugins.md +21 -18
  122. package/skills/better-supabase/references/troubleshooting.md +15 -15
  123. package/skills/better-supabase-api/SKILL.md +7 -7
  124. package/skills/better-supabase-api/references/adapters.md +30 -25
  125. package/skills/better-supabase-testing/SKILL.md +11 -8
  126. package/bin/better-supabase.js +0 -4
  127. package/dist/casing-da0uRTqt.js +0 -14
  128. package/dist/cli/bin.d.ts +0 -1
  129. package/dist/cli/bin.js +0 -15
  130. package/dist/cli/index.d.ts +0 -226
  131. package/dist/cli/index.js +0 -3
  132. package/dist/cli-DrSgDOQC.js +0 -6646
  133. package/dist/env-BEToab0I.js +0 -204
  134. package/dist/events-BuzTgn2D.js +0 -135
  135. package/dist/pool-R2m_DkXi.d.ts +0 -37
  136. package/dist/seed-CzecODcJ.js +0 -101
  137. package/dist/session-C3LxnQ0e.d.ts +0 -22
  138. package/dist/session-CqEwzVup.js +0 -20
  139. package/dist/storage-DuGn38fr.js +0 -527
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  [![npm](https://img.shields.io/npm/v/better-supabase)](https://www.npmjs.com/package/better-supabase)
6
6
  [![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/ScaleDockHQ/better-supabase/blob/main/LICENSE)
7
- ![TypeScript](https://img.shields.io/badge/TypeScript-5.9%20%7C%206%20%7C%207-3178c6.svg)
7
+ ![TypeScript](https://img.shields.io/badge/TypeScript-6%20%7C%207-3178c6.svg)
8
8
 
9
9
  `better-supabase gen` extends `supabase gen types` with relation cardinality, unique keys, CHECK unions and typed jsonb. The generated `schema` gives every table a typed repository that compiles to one PostgREST request, returns a `Result` instead of throwing, and runs as the caller so RLS always applies.
10
10
 
@@ -12,13 +12,15 @@
12
12
 
13
13
  ```bash
14
14
  pnpm add better-supabase @supabase/supabase-js
15
- pnpm add -D pg
15
+ pnpm add -D @better-supabase/cli pg
16
16
  ```
17
17
 
18
- ESM only. Node 24 or later for the CLI; the runtime entries run on every WinterTC runtime (Node, Deno, Bun, Workers, Supabase Edge Functions). TypeScript 5.9, 6 and 7 are tested.
18
+ ESM only. The CLI ships as [`@better-supabase/cli`](https://www.npmjs.com/package/@better-supabase/cli), always at the same version as `better-supabase`, and needs Node 24 or later; the runtime entries run on every WinterTC runtime (Node, Deno, Bun, Workers, Supabase Edge Functions). TypeScript 6 and 7 are tested.
19
19
 
20
20
  ## Quick start
21
21
 
22
+ Or start with `npx @better-supabase/cli init`, which detects your frameworks and prints the install command.
23
+
22
24
  ```bash
23
25
  supabase start
24
26
  pnpm better-supabase init # config, src/lib/supabase.ts and framework glue
@@ -26,20 +28,20 @@ pnpm better-supabase gen # database.types.ts and generated.ts
26
28
  ```
27
29
 
28
30
  ```ts
29
- import { createClient } from '@supabase/supabase-js';
30
- import { defineSupabase } from 'better-supabase';
31
+ import { createClient } from "@supabase/supabase-js";
32
+ import { defineSupabase } from "better-supabase";
31
33
 
32
- import { schema } from './lib/supabase/generated.ts';
34
+ import { schema } from "./lib/supabase/generated.ts";
33
35
 
34
36
  export const sb = defineSupabase(schema);
35
37
 
36
38
  const db = sb.connect(createClient(url, publishableKey));
37
39
 
38
40
  const result = await db.customers.findMany({
39
- select: ['id', 'name'],
40
- where: { status: 'active', notes: { some: { kind: 'call' } } },
41
- include: { organization: { select: ['name'] } },
42
- orderBy: { name: 'asc' },
41
+ select: ["id", "name"],
42
+ where: { status: "active", notes: { some: { kind: "call" } } },
43
+ include: { organization: { select: ["name"] } },
44
+ orderBy: { name: "asc" },
43
45
  limit: 20,
44
46
  });
45
47
  if (!result.ok) return result; // DbError: kind, message, status, code
@@ -47,27 +49,28 @@ if (!result.ok) return result; // DbError: kind, message, status, code
47
49
 
48
50
  ## Subpaths
49
51
 
50
- | Import | What it gives you |
51
- | --- | --- |
52
- | `better-supabase` | `defineSupabase`, repositories, `Result`, `DbError`, `SPEC_PINS` |
53
- | `better-supabase/config` | `defineConfig` and generators for `better-supabase.config.ts` |
54
- | `better-supabase/client` | Browser repositories that follow the session |
55
- | `better-supabase/react` | Provider, typed hooks and the server session |
56
- | `better-supabase/query` | TanStack Query options with table-based invalidation |
57
- | `better-supabase/server` | Repositories bound to the caller, admin and acting-as identities |
58
- | `better-supabase/postgres` | The same repositories over direct Postgres |
59
- | `better-supabase/ssr` | The `@supabase/ssr` cookie format for any framework |
60
- | `better-supabase/next`, `/next/image` | Proxy, Server Components, route handlers, server actions, Storage images |
61
- | `better-supabase/hono`, `/orpc`, `/edge` | Framework adapters |
62
- | `better-supabase/mcp` | MCP servers whose tools run as the signed-in user |
63
- | `better-supabase/jobs` | Supabase Queues jobs, idempotency keys and a webhook inbox |
64
- | `better-supabase/list` | Search, facets, sorting and pagination from one definition |
65
- | `better-supabase/storage`, `/realtime` | Typed bucket paths and broadcast topics |
66
- | `better-supabase/env` | Validated Supabase settings |
67
- | `better-supabase/events`, `/webhooks`, `/openapi`, `/otel` | CloudEvents, Standard Webhooks, OpenAPI 3.1 and OpenTelemetry |
68
- | `better-supabase/plugins/*` | Timestamps, soft delete, tenant, actor, validation and runtime rules |
69
- | `better-supabase/lint` | Editor rules for unbounded reads and unscoped deletes |
70
- | `better-supabase/testing` | `asUser`, `localAuth`, typed seeds and conformance kits |
52
+ | Import | What it gives you |
53
+ | ---------------------------------------------------------- | ------------------------------------------------------------------------ |
54
+ | `better-supabase` | `defineSupabase`, repositories, `Result`, `DbError`, `SPEC_PINS` |
55
+ | `better-supabase/config` | `defineConfig` and generators for `better-supabase.config.ts` |
56
+ | `better-supabase/client` | Browser repositories that follow the session |
57
+ | `better-supabase/react` | Provider, typed hooks and the server session |
58
+ | `better-supabase/query` | TanStack Query options with table-based invalidation |
59
+ | `better-supabase/server` | Repositories bound to the caller, admin and acting-as identities |
60
+ | `better-supabase/postgres` | The same repositories over direct Postgres |
61
+ | `better-supabase/ssr` | The `@supabase/ssr` cookie format for any framework |
62
+ | `better-supabase/next`, `/next/image` | Proxy, Server Components, route handlers, server actions, Storage images |
63
+ | `better-supabase/hono`, `/orpc`, `/edge` | Framework adapters |
64
+ | `better-supabase/mcp` | MCP servers whose tools run as the signed-in user |
65
+ | `better-supabase/jobs` | Supabase Queues jobs, idempotency keys and a webhook inbox |
66
+ | `better-supabase/list` | Search, facets, sorting and pagination from one definition |
67
+ | `better-supabase/storage`, `/realtime` | Typed bucket paths and broadcast topics |
68
+ | `better-supabase/env` | Validated Supabase settings |
69
+ | `better-supabase/events`, `/webhooks`, `/openapi`, `/otel` | CloudEvents, Standard Webhooks, OpenAPI 3.1 and OpenTelemetry |
70
+ | `better-supabase/plugins/*` | Timestamps, soft delete, tenant, actor, validation and runtime rules |
71
+ | `better-supabase/sql` | The SQL kit modules and read-set compiler behind `better-supabase sql` |
72
+ | `better-supabase/lint` | Editor rules for unbounded reads and unscoped deletes |
73
+ | `better-supabase/testing` | `asUser`, `localAuth`, typed seeds and conformance kits |
71
74
 
72
75
  ## For AI agents
73
76
 
@@ -0,0 +1,42 @@
1
+ //#region src/core/base64.ts
2
+ const encoder = new TextEncoder();
3
+ const decoder = new TextDecoder();
4
+ /** Standard base64 (RFC 4648 section 4) of `input`, with padding. */
5
+ function toBase64(input) {
6
+ const bytes = typeof input === "string" ? encoder.encode(input) : input;
7
+ let binary = "";
8
+ for (const byte of bytes) binary += String.fromCodePoint(byte);
9
+ return btoa(binary);
10
+ }
11
+ /** Bytes of standard or URL-safe base64, padded or not. Throws on invalid input. */
12
+ function fromBase64(text) {
13
+ const base64 = text.replaceAll("-", "+").replaceAll("_", "/");
14
+ const binary = atob(base64 + "=".repeat((4 - base64.length % 4) % 4));
15
+ const bytes = new Uint8Array(binary.length);
16
+ for (let index = 0; index < binary.length; index += 1) bytes[index] = binary.codePointAt(index) ?? 0;
17
+ return bytes;
18
+ }
19
+ /** URL-safe base64 (RFC 4648 section 5) of `input`, without padding. */
20
+ function toBase64Url(input) {
21
+ return toBase64(input).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
22
+ }
23
+ /** UTF-8 text of base64 or base64url. Throws on invalid input. */
24
+ function base64ToText(text) {
25
+ return decoder.decode(fromBase64(text));
26
+ }
27
+ /**
28
+ * The payload of a JWT, decoded without verifying the signature. Only for
29
+ * reading claims such as `exp` from a token that is verified elsewhere.
30
+ */
31
+ function decodeJwtPayload(token) {
32
+ const part = token.split(".")[1];
33
+ if (!part) return void 0;
34
+ try {
35
+ const parsed = JSON.parse(base64ToText(part));
36
+ return typeof parsed === "object" && parsed !== null ? parsed : void 0;
37
+ } catch {
38
+ return;
39
+ }
40
+ }
41
+ //#endregion
42
+ export { toBase64Url as a, toBase64 as i, decodeJwtPayload as n, fromBase64 as r, base64ToText as t };
@@ -1,2 +1,2 @@
1
- import { a as BrowserOptions, i as BrowserAuth, n as AuthUser, o as createBrowser, r as BetterBrowser, t as AuthSnapshot } from "../index-D4v7sncu.js";
1
+ import { a as BrowserOptions, i as BrowserAuth, n as AuthUser, o as createBrowser, r as BetterBrowser, t as AuthSnapshot } from "../index-UJ-LUxtI.js";
2
2
  export { AuthSnapshot, AuthUser, BetterBrowser, BrowserAuth, BrowserOptions, createBrowser };
@@ -1,5 +1,6 @@
1
- import { a as parseEnv, n as EnvValidationError } from "../env-BEToab0I.js";
2
- import { t as createQueries } from "../query-ChvDbsDE.js";
1
+ import { n as decodeJwtPayload } from "../base64-CQeB1eSf.js";
2
+ import { EnvValidationError, parseEnv } from "../env/index.js";
3
+ import { t as createQueries } from "../query-BdKLTPlj.js";
3
4
  import { createBrowserClient } from "@supabase/ssr";
4
5
  import { createClient } from "@supabase/supabase-js";
5
6
  //#region src/client/index.ts
@@ -13,20 +14,9 @@ const SIGNED_OUT = {
13
14
  user: null,
14
15
  claims: null
15
16
  };
16
- function decodeClaims(token) {
17
- const part = token.split(".")[1];
18
- if (!part) return {};
19
- try {
20
- const bytes = Uint8Array.from(atob(part.replace(/-/g, "+").replace(/_/g, "/")), (char) => char.charCodeAt(0));
21
- const parsed = JSON.parse(new TextDecoder().decode(bytes));
22
- return typeof parsed === "object" && parsed !== null ? parsed : {};
23
- } catch {
24
- return {};
25
- }
26
- }
27
17
  function snapshotOf(session) {
28
18
  if (!session) return SIGNED_OUT;
29
- const claims = decodeClaims(session.access_token);
19
+ const claims = decodeJwtPayload(session.access_token) ?? {};
30
20
  const role = typeof claims["role"] === "string" ? claims["role"] : session.user.role;
31
21
  return {
32
22
  status: "signed-in",
@@ -1,5 +1,5 @@
1
- import { g as Operation } from "./executor-CGdNQ27g.js";
2
- import { i as PostgrestPlan } from "./postgrest-cAEQ_IQN.js";
1
+ import { g as Operation } from "./executor-DynmIWhq.js";
2
+ import { i as PostgrestPlan } from "./postgrest-DmBlevh-.js";
3
3
  //#region src/core/compiler.d.ts
4
4
  /**
5
5
  * Turns an IR operation into something a backend runs. An `Executor` for a
@@ -1,3 +1,4 @@
1
- import { A as defineConfig, C as SourceConfig, D as TimestampsConfig, E as TenantConfig, F as ValibotGeneratorOptions, I as valibot, L as JsonSchemaGeneratorOptions, M as resolveJsonSchema, N as ZodGeneratorOptions, O as VectorDistance, P as zod, R as buildJsonSchema, S as SoftDeleteConfig, T as TableConfig, _ as Privilege, a as ClaimsConfig, b as ResolvedExpose, c as EntitlementsConfig, d as Generator, f as GeneratorInput, g as PluginFlagsConfig, h as OpenApiConfig, i as CONFIG_SCHEMA_URL, j as resolveConfig, k as VectorSearchConfig, l as ExposeConfig, m as JsonTypeConfig, n as BetterSupabaseConfig, o as CodecsConfig, p as JsonSchemaSource, r as BucketConfig, s as DoctorConfig, t as ActorConfig, u as GeneratedFile, v as RealtimeConfig, w as SqlConfig, x as SeedConfig, y as ResolvedConfig, z as jsonSchema } from "../index-DOsjFvMf.js";
2
- import { a as Casing } from "../types-C83v5SQz.js";
3
- export { ActorConfig, BetterSupabaseConfig, BucketConfig, CONFIG_SCHEMA_URL, type Casing, ClaimsConfig, CodecsConfig, DoctorConfig, EntitlementsConfig, ExposeConfig, GeneratedFile, Generator, GeneratorInput, type JsonSchemaGeneratorOptions, JsonSchemaSource, JsonTypeConfig, OpenApiConfig, PluginFlagsConfig, Privilege, RealtimeConfig, ResolvedConfig, ResolvedExpose, SeedConfig, SoftDeleteConfig, SourceConfig, SqlConfig, TableConfig, TenantConfig, TimestampsConfig, type ValibotGeneratorOptions, VectorDistance, VectorSearchConfig, type ZodGeneratorOptions, buildJsonSchema, defineConfig, jsonSchema, resolveConfig, resolveJsonSchema, valibot, zod };
1
+ import { a as Casing } from "../types-DONv9SHN.js";
2
+ import { $ as GeneratorMetadata, A as VectorSearchConfig, B as CatalogFunction, C as SoftDeleteConfig, D as TenantConfig, E as TableConfig, F as CatalogCheck, G as CatalogTable, H as CatalogGrant, I as CatalogColumn, J as ExtrasFunction, K as CatalogTrigger, L as CatalogColumnGrant, M as resolveConfig, N as resolveJsonSchema, O as TimestampsConfig, P as Catalog, Q as ForeignKeyAction, R as CatalogEnum, S as SeedConfig, T as SqlConfig, U as CatalogIndex, V as CatalogFunctionArg, W as CatalogPolicy, X as ExtrasHookFunction, Y as ExtrasHook, Z as ExtrasTable, _ as PluginFlagsConfig, a as ClaimsConfig, b as ResolvedConfig, c as EntitlementsConfig, d as Generator, et as Snapshot, f as GeneratorInput, g as PermdockPathsConfig, h as OpenApiConfig, i as CONFIG_SCHEMA_URL, j as defineConfig, k as VectorDistance, l as ExposeConfig, m as JsonTypeConfig, n as BetterSupabaseConfig, nt as SnapshotExtras, o as CodecsConfig, p as JsonSchemaSource, q as CatalogUnique, r as BucketConfig, s as DoctorConfig, t as ActorConfig, tt as SnapshotBucket, u as GeneratedFile, v as Privilege, w as SourceConfig, x as ResolvedExpose, y as RealtimeConfig, z as CatalogForeignKey } from "../config-C1CYcm6o.js";
3
+ import { a as JsonSchemaGeneratorOptions, c as DEFAULT_CLAIMS, i as valibot, l as tenantClaimPaths, n as zod, o as buildJsonSchema, r as ValibotGeneratorOptions, s as jsonSchema, t as ZodGeneratorOptions } from "../index-Cf-D2jk1.js";
4
+ export { type ActorConfig, type BetterSupabaseConfig, type BucketConfig, CONFIG_SCHEMA_URL, type Casing, type Catalog, type CatalogCheck, type CatalogColumn, type CatalogColumnGrant, type CatalogEnum, type CatalogForeignKey, type CatalogFunction, type CatalogFunctionArg, type CatalogGrant, type CatalogIndex, type CatalogPolicy, type CatalogTable, type CatalogTrigger, type CatalogUnique, type ClaimsConfig, type CodecsConfig, DEFAULT_CLAIMS, type DoctorConfig, type EntitlementsConfig, type ExposeConfig, type ExtrasFunction, type ExtrasHook, type ExtrasHookFunction, type ExtrasTable, type ForeignKeyAction, type GeneratedFile, type Generator, type GeneratorInput, type GeneratorMetadata, type JsonSchemaGeneratorOptions, type JsonSchemaSource, type JsonTypeConfig, type OpenApiConfig, type PermdockPathsConfig, type PluginFlagsConfig, type Privilege, type RealtimeConfig, type ResolvedConfig, type ResolvedExpose, type SeedConfig, type Snapshot, type SnapshotBucket, type SnapshotExtras, type SoftDeleteConfig, type SourceConfig, type SqlConfig, type TableConfig, type TenantConfig, type TimestampsConfig, type ValibotGeneratorOptions, type VectorDistance, type VectorSearchConfig, type ZodGeneratorOptions, buildJsonSchema, defineConfig, jsonSchema, resolveConfig, resolveJsonSchema, tenantClaimPaths, valibot, zod };
@@ -1,3 +1,5 @@
1
- import { n as jsonSchema, t as buildJsonSchema } from "../json-schema-BpYqkCKf.js";
2
- import { a as zod, i as resolveJsonSchema, n as defineConfig, o as valibot, r as resolveConfig, t as CONFIG_SCHEMA_URL } from "../config-ClDXmVtY.js";
3
- export { CONFIG_SCHEMA_URL, buildJsonSchema, defineConfig, jsonSchema, resolveConfig, resolveJsonSchema, valibot, zod };
1
+ import { i as tenantClaimPaths, t as DEFAULT_CLAIMS } from "../claims-CoTobNC-.js";
2
+ import { i as resolveJsonSchema, n as defineConfig, r as resolveConfig, t as CONFIG_SCHEMA_URL } from "../config-Be4GwsqI.js";
3
+ import { n as jsonSchema, t as buildJsonSchema } from "../json-schema--aOXAGfU.js";
4
+ import { n as valibot, t as zod } from "../config-DOsGYSiT.js";
5
+ export { CONFIG_SCHEMA_URL, DEFAULT_CLAIMS, buildJsonSchema, defineConfig, jsonSchema, resolveConfig, resolveJsonSchema, tenantClaimPaths, valibot, zod };
@@ -0,0 +1,129 @@
1
+ import { t as DEFAULT_CLAIMS } from "./claims-CoTobNC-.js";
2
+ //#region src/config/config.ts
3
+ /** The JSON Schema document for a `json[...].schema` entry. */
4
+ function resolveJsonSchema(source) {
5
+ const standard = source["~standard"];
6
+ if (standard === void 0) return source;
7
+ const jsonSchema = standard.jsonSchema;
8
+ if (typeof jsonSchema?.input !== "function") throw new TypeError("json[...].schema: this Standard Schema library does not implement Standard JSON Schema; pass a JSON Schema object instead");
9
+ return jsonSchema.input({ target: "draft-2020-12" });
10
+ }
11
+ function entitlementsOf(config = {}) {
12
+ const customer = config.customer ?? "organizations.stripe_customer_id";
13
+ const dot = customer.lastIndexOf(".");
14
+ if (dot <= 0) throw new TypeError(`entitlements.customer must be "table.column", got "${customer}"`);
15
+ return {
16
+ table: customer.slice(0, dot),
17
+ column: customer.slice(dot + 1),
18
+ key: config.key ?? "id",
19
+ permdock: config.permdock === false ? false : { scope: config.permdock?.scope ?? "organization" }
20
+ };
21
+ }
22
+ function vectorSearchOf(config = {}) {
23
+ return Object.entries(config).map(([table, entry]) => typeof entry === "string" ? {
24
+ table,
25
+ column: entry,
26
+ distance: "cosine"
27
+ } : {
28
+ table,
29
+ column: entry.column,
30
+ distance: entry.distance ?? "cosine"
31
+ });
32
+ }
33
+ const CONFIG_SCHEMA_URL = "https://unpkg.com/better-supabase/schemas/config-v1.json";
34
+ /** Identity helper that types `better-supabase.config.ts`. */
35
+ function defineConfig(config) {
36
+ return config;
37
+ }
38
+ function pick(value, defaults) {
39
+ if (value === void 0 || value === false) return void 0;
40
+ if (value === true) return defaults;
41
+ return {
42
+ ...defaults,
43
+ ...value
44
+ };
45
+ }
46
+ function resolveExpose(entry) {
47
+ if (Array.isArray(entry)) return {
48
+ anon: [],
49
+ authenticated: entry
50
+ };
51
+ const roles = entry;
52
+ return {
53
+ anon: roles.anon ?? [],
54
+ authenticated: roles.authenticated ?? []
55
+ };
56
+ }
57
+ /** Applies defaults. Paths stay relative to `root`. */
58
+ function resolveConfig(config, root) {
59
+ const output = config.output ?? "src/lib/supabase/generated.ts";
60
+ return {
61
+ root,
62
+ source: config.source ?? {},
63
+ schemas: config.schemas ?? ["public"],
64
+ casing: config.casing ?? "snake",
65
+ tables: config.tables ?? {},
66
+ output,
67
+ databaseTypesOutput: output.replace(/[^/]+$/, "database.types.ts"),
68
+ postgrestVersion: config.postgrestVersion ?? "13",
69
+ json: config.json ?? {},
70
+ codecs: {
71
+ timestamptz: config.codecs?.timestamptz ?? "string",
72
+ int8: config.codecs?.int8 ?? "number",
73
+ numeric: config.codecs?.numeric ?? "number"
74
+ },
75
+ sensitive: config.sensitive ?? [],
76
+ storagePaths: config.storagePaths ?? {},
77
+ expose: Object.fromEntries(Object.entries(config.expose ?? {}).map(([table, entry]) => [table, resolveExpose(entry)])),
78
+ readSets: config.readSets ?? [],
79
+ generators: config.generators ?? [],
80
+ plugins: {
81
+ timestamps: pick(config.plugins?.timestamps, {
82
+ createdAt: "created_at",
83
+ updatedAt: "updated_at"
84
+ }),
85
+ softDelete: pick(config.plugins?.softDelete, { column: "deleted_at" }),
86
+ tenant: pick(config.plugins?.tenant, { column: "organization_id" }),
87
+ actor: pick(config.plugins?.actor, {
88
+ createdBy: "created_by",
89
+ updatedBy: "updated_by"
90
+ })
91
+ },
92
+ claims: {
93
+ ...DEFAULT_CLAIMS,
94
+ ...config.claims
95
+ },
96
+ buckets: config.buckets ?? {},
97
+ topics: config.topics ?? {},
98
+ realtime: { tables: config.realtime?.tables ?? [] },
99
+ entitlements: entitlementsOf(config.entitlements),
100
+ permdock: {
101
+ manifest: config.permdock?.manifest ?? "permdock.manifest.json",
102
+ catalog: config.permdock?.catalog ?? "permissions.catalog.json"
103
+ },
104
+ vectorSearch: vectorSearchOf(config.vectorSearch),
105
+ sql: {
106
+ dir: config.sql?.dir ?? "supabase/schemas",
107
+ prefix: config.sql?.prefix ?? "900_better_supabase",
108
+ testsDir: config.sql?.testsDir ?? "supabase/tests",
109
+ kit: config.sql?.kit ?? []
110
+ },
111
+ seed: {
112
+ entry: config.seed?.entry ?? "supabase/seed.ts",
113
+ output: config.seed?.output ?? "supabase/seeds/000_better_supabase.sql"
114
+ },
115
+ openapi: {
116
+ entry: config.openapi?.entry ?? "src/lib/openapi.ts",
117
+ output: config.openapi?.output ?? "openapi.json"
118
+ },
119
+ doctor: {
120
+ ignore: config.doctor?.ignore ?? [],
121
+ strict: config.doctor?.strict ?? false,
122
+ sources: config.doctor?.sources ?? ["src/**/*.{ts,tsx}"],
123
+ policyHelperLimit: config.doctor?.policyHelperLimit ?? 5,
124
+ ...config.doctor?.claimsLimit === void 0 ? {} : { claimsLimit: config.doctor.claimsLimit }
125
+ }
126
+ };
127
+ }
128
+ //#endregion
129
+ export { resolveJsonSchema as i, defineConfig as n, resolveConfig as r, CONFIG_SCHEMA_URL as t };
@@ -1,6 +1,7 @@
1
- import { A as SchemaMeta, a as Casing, b as PermdockBucketPolicy, i as BucketPolicyName } from "./types-C83v5SQz.js";
2
- import { GeneratorMetadata, Queryable } from "@supabase/postgrest-typegen";
3
- //#region src/cli/introspect/types.d.ts
1
+ /// <reference lib="esnext.temporal" />
2
+ import { A as SchemaMeta, a as Casing, b as PermdockBucketPolicy, i as BucketPolicyName } from "./types-DONv9SHN.js";
3
+ import { GeneratorMetadata } from "@supabase/postgrest-typegen";
4
+ //#region src/config/snapshot.d.ts
4
5
  /**
5
6
  * What `better-supabase introspect` reads from Postgres. `generator` is the
6
7
  * `@supabase/postgrest-typegen` contract (the same metadata behind
@@ -72,6 +73,8 @@ interface ExtrasFunction {
72
73
  readonly securityDefiner: boolean;
73
74
  /** `set` options, e.g. `{ statement_timeout: '5s' }`. */
74
75
  readonly settings: Readonly<Record<string, string>>;
76
+ /** Which of `anon` and `authenticated` may execute it. Absent in older snapshots. */
77
+ readonly execute?: readonly string[];
75
78
  }
76
79
  interface ExtrasTable {
77
80
  /** Table oid, matching `GeneratorMetadata.tables[].id`. */
@@ -91,6 +94,8 @@ interface ExtrasTable {
91
94
  readonly policies: readonly CatalogPolicy[];
92
95
  readonly triggers: readonly CatalogTrigger[];
93
96
  readonly grants: readonly CatalogGrant[];
97
+ /** Absent in snapshots taken before column grants were introspected. */
98
+ readonly columnGrants?: readonly CatalogColumnGrant[];
94
99
  /** Postgres estimates at least `LARGE_TABLE_ROWS` rows; the `unbounded-read` lint reads it. */
95
100
  readonly large?: true;
96
101
  }
@@ -109,6 +114,10 @@ interface CatalogIndex {
109
114
  readonly unique: boolean;
110
115
  readonly primary: boolean;
111
116
  readonly partial: boolean;
117
+ /** Access method (`btree`, `gin`, `gist`, ...). Absent in older snapshots. */
118
+ readonly method?: string;
119
+ /** The `where` of a partial index, as Postgres prints it. Absent in older snapshots. */
120
+ readonly predicate?: string | null;
112
121
  }
113
122
  interface CatalogPolicy {
114
123
  readonly name: string;
@@ -134,6 +143,12 @@ interface CatalogGrant {
134
143
  readonly role: string;
135
144
  readonly privileges: readonly string[];
136
145
  }
146
+ /** A column-level `insert` or `update` grant to `anon` or `authenticated`. */
147
+ interface CatalogColumnGrant {
148
+ readonly column: string;
149
+ readonly role: string;
150
+ readonly privileges: readonly string[];
151
+ }
137
152
  interface SnapshotBucket {
138
153
  readonly id: string;
139
154
  readonly public: boolean;
@@ -175,6 +190,8 @@ interface CatalogTable {
175
190
  readonly policies: readonly CatalogPolicy[];
176
191
  readonly triggers: readonly CatalogTrigger[];
177
192
  readonly grants: readonly CatalogGrant[];
193
+ /** Absent in snapshots taken before column grants were introspected. */
194
+ readonly columnGrants?: readonly CatalogColumnGrant[];
178
195
  }
179
196
  interface CatalogColumn {
180
197
  readonly name: string;
@@ -237,49 +254,7 @@ interface CatalogFunctionArg {
237
254
  readonly hasDefault: boolean;
238
255
  }
239
256
  //#endregion
240
- //#region src/generators/shared.d.ts
241
- /** What field planning reads: the metadata and the typed-jsonb config. */
242
- interface SchemaSource {
243
- readonly meta: SchemaMeta;
244
- readonly config: {
245
- readonly json: Readonly<Record<string, unknown>>;
246
- };
247
- }
248
- //#endregion
249
- //#region src/generators/json-schema.d.ts
250
- interface JsonSchemaGeneratorOptions {
251
- /** Output path relative to the project root. Defaults to `<output>.schema.json`. */
252
- readonly output?: string;
253
- /** `$id` of the document. */
254
- readonly id?: string;
255
- }
256
- type JsonSchema = Record<string, unknown>;
257
- /** JSON Schema (2020-12) `$defs` for every table: `customersRow`, `customersInsert`, ... */
258
- declare function buildJsonSchema(input: SchemaSource, id?: string): JsonSchema;
259
- /** Writes the JSON Schema document; `createOpenApi` reuses the same `$defs`. */
260
- declare function jsonSchema(options?: JsonSchemaGeneratorOptions): Generator;
261
- //#endregion
262
- //#region src/generators/valibot.d.ts
263
- interface ValibotGeneratorOptions {
264
- /** Output path relative to the project root. Defaults to `<output>.valibot.ts`. */
265
- readonly output?: string;
266
- /** Schemas for typed jsonb columns: `{ 'customers.metadata': './schemas.ts#metadata' }`. */
267
- readonly json?: Readonly<Record<string, string>>;
268
- }
269
- /** Valibot schemas for every table's Row, Insert and Update shape. */
270
- declare function valibot(options?: ValibotGeneratorOptions): Generator;
271
- //#endregion
272
- //#region src/generators/zod.d.ts
273
- interface ZodGeneratorOptions {
274
- /** Output path relative to the project root. Defaults to `<output>.zod.ts`. */
275
- readonly output?: string;
276
- /** Schemas for typed jsonb columns: `{ 'customers.metadata': './schemas.ts#metadata' }`. */
277
- readonly json?: Readonly<Record<string, string>>;
278
- }
279
- /** Zod 4 schemas for every table's Row, Insert and Update shape. */
280
- declare function zod(options?: ZodGeneratorOptions): Generator;
281
- //#endregion
282
- //#region src/config/index.d.ts
257
+ //#region src/config/config.d.ts
283
258
  /**
284
259
  * Where codegen reads the database from. Without any of these, `$DATABASE_URL`
285
260
  * and then the local stack (`supabase start`) are used.
@@ -423,8 +398,11 @@ interface DoctorConfig {
423
398
  * `numeric` as numbers.
424
399
  */
425
400
  interface CodecsConfig {
426
- /** `'date'` decodes `timestamptz`/`timestamp` columns to `Date`. */
427
- readonly timestamptz?: "string" | "date";
401
+ /**
402
+ * `'instant'` decodes `timestamptz` columns to `Temporal.Instant` and
403
+ * `timestamp` columns to `Temporal.PlainDateTime`.
404
+ */
405
+ readonly timestamptz?: "string" | "instant";
428
406
  /** `'bigint'` or `'string'` read `int8` exactly (above 2^53). */
429
407
  readonly int8?: "number" | "string" | "bigint";
430
408
  /** `'string'` reads `numeric` exactly. */
@@ -475,6 +453,22 @@ interface EntitlementsConfig {
475
453
  readonly customer?: string;
476
454
  /** The tenant id column of that table. Defaults to `id`. */
477
455
  readonly key?: string;
456
+ /**
457
+ * With a PermDock manifest, `has_entitlement` and `feature_claims` read
458
+ * PermDock's memberships (`member_<scope>_ids()` and
459
+ * `member_<scope>_ids_for(user)`) instead of `better_supabase.memberships`.
460
+ * `scope` is the PermDock scope tenants are (default `organization`);
461
+ * `false` keeps the kit's memberships table.
462
+ */
463
+ readonly permdock?: false | {
464
+ readonly scope?: string;
465
+ };
466
+ }
467
+ interface PermdockPathsConfig {
468
+ /** What `permdock supabase inspect --out` writes. Defaults to `permdock.manifest.json`. */
469
+ readonly manifest?: string;
470
+ /** What `permdock catalog` writes. Defaults to `permissions.catalog.json`. */
471
+ readonly catalog?: string;
478
472
  }
479
473
  /** pgvector distance: `<=>` (cosine), `<->` (l2) or `<#>` (negative inner product). */
480
474
  type VectorDistance = "cosine" | "l2" | "inner_product";
@@ -555,6 +549,8 @@ interface BetterSupabaseConfig {
555
549
  readonly topics?: Readonly<Record<string, string>>;
556
550
  readonly realtime?: RealtimeConfig;
557
551
  readonly entitlements?: EntitlementsConfig;
552
+ /** Where PermDock's JSON outputs are, for doctor, `gen` and the SQL kit. */
553
+ readonly permdock?: PermdockPathsConfig;
558
554
  /**
559
555
  * Embedding columns, keyed by `table` or `schema.table`. The
560
556
  * `vector-search` SQL kit module writes `search_<table>(query, k)` for each,
@@ -596,7 +592,11 @@ interface ResolvedConfig {
596
592
  readonly table: string;
597
593
  readonly column: string;
598
594
  readonly key: string;
595
+ readonly permdock: false | {
596
+ readonly scope: string;
597
+ };
599
598
  };
599
+ readonly permdock: Required<PermdockPathsConfig>;
600
600
  readonly vectorSearch: readonly {
601
601
  readonly table: string;
602
602
  readonly column: string;
@@ -615,4 +615,4 @@ declare function defineConfig(config: BetterSupabaseConfig): BetterSupabaseConfi
615
615
  /** Applies defaults. Paths stay relative to `root`. */
616
616
  declare function resolveConfig(config: BetterSupabaseConfig, root: string): ResolvedConfig;
617
617
  //#endregion
618
- export { ExtrasFunction as $, defineConfig as A, Catalog as B, SourceConfig as C, TimestampsConfig as D, TenantConfig as E, ValibotGeneratorOptions as F, CatalogFunction as G, CatalogColumn as H, valibot as I, CatalogIndex as J, CatalogFunctionArg as K, JsonSchemaGeneratorOptions as L, resolveJsonSchema as M, ZodGeneratorOptions as N, VectorDistance as O, zod as P, CatalogUnique as Q, buildJsonSchema as R, SoftDeleteConfig as S, TableConfig as T, CatalogEnum as U, CatalogCheck as V, CatalogForeignKey as W, CatalogTable as X, CatalogPolicy as Y, CatalogTrigger as Z, Privilege as _, ClaimsConfig as a, SnapshotBucket as at, ResolvedExpose as b, EntitlementsConfig as c, Queryable as ct, Generator as d, ExtrasHook as et, GeneratorInput as f, PluginFlagsConfig as g, OpenApiConfig as h, CONFIG_SCHEMA_URL as i, Snapshot as it, resolveConfig as j, VectorSearchConfig as k, ExposeConfig as l, JsonTypeConfig as m, BetterSupabaseConfig as n, ExtrasTable as nt, CodecsConfig as o, SnapshotExtras as ot, JsonSchemaSource as p, CatalogGrant as q, BucketConfig as r, ForeignKeyAction as rt, DoctorConfig as s, GeneratorMetadata as st, ActorConfig as t, ExtrasHookFunction as tt, GeneratedFile as u, RealtimeConfig as v, SqlConfig as w, SeedConfig as x, ResolvedConfig as y, jsonSchema as z };
618
+ export { GeneratorMetadata as $, VectorSearchConfig as A, CatalogFunction as B, SoftDeleteConfig as C, TenantConfig as D, TableConfig as E, CatalogCheck as F, CatalogTable as G, CatalogGrant as H, CatalogColumn as I, ExtrasFunction as J, CatalogTrigger as K, CatalogColumnGrant as L, resolveConfig as M, resolveJsonSchema as N, TimestampsConfig as O, Catalog as P, ForeignKeyAction as Q, CatalogEnum as R, SeedConfig as S, SqlConfig as T, CatalogIndex as U, CatalogFunctionArg as V, CatalogPolicy as W, ExtrasHookFunction as X, ExtrasHook as Y, ExtrasTable as Z, PluginFlagsConfig as _, ClaimsConfig as a, ResolvedConfig as b, EntitlementsConfig as c, Generator as d, Snapshot as et, GeneratorInput as f, PermdockPathsConfig as g, OpenApiConfig as h, CONFIG_SCHEMA_URL as i, defineConfig as j, VectorDistance as k, ExposeConfig as l, JsonTypeConfig as m, BetterSupabaseConfig as n, SnapshotExtras as nt, CodecsConfig as o, JsonSchemaSource as p, CatalogUnique as q, BucketConfig as r, DoctorConfig as s, ActorConfig as t, SnapshotBucket as tt, GeneratedFile as u, Privilege as v, SourceConfig as w, ResolvedExpose as x, RealtimeConfig as y, CatalogForeignKey as z };