better-supabase 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/README.md +37 -33
  2. package/dist/base64-D2gsioCY.js +42 -0
  3. package/dist/claims-BAf6c7is.js +48 -0
  4. package/dist/cli/_format-Cax5EsM9.js +101 -0
  5. package/dist/cli/bin.js +39 -6
  6. package/dist/cli/command-CK14fP91.js +502 -0
  7. package/dist/cli/compare-BmIWVEui.js +9 -0
  8. package/dist/cli/config-D9R0o1LH.js +1895 -0
  9. package/dist/cli/config-SSKSTUl2.js +2 -0
  10. package/dist/cli/db-DOBPt660.js +52 -0
  11. package/dist/cli/dist-B1MvLv-M.js +129 -0
  12. package/dist/cli/dist-CFgGknmZ.js +1112 -0
  13. package/dist/cli/dist-Du7VnEUG.js +621 -0
  14. package/dist/cli/doctor-BOym3mbL.js +2382 -0
  15. package/dist/cli/env-BZ0uy8XK.js +108 -0
  16. package/dist/cli/env-jIFUADLY.js +511 -0
  17. package/dist/cli/errors-4v4DTtda.js +56 -0
  18. package/dist/cli/fastest-levenshtein-CFN-lNDv.js +120 -0
  19. package/dist/cli/gen-Ccn_p90L.js +2008 -0
  20. package/dist/cli/gen-D5cLCULx.js +2 -0
  21. package/dist/cli/index.d.ts +295 -28
  22. package/dist/cli/index.js +184 -3
  23. package/dist/cli/init-ClnxRYBF.js +550 -0
  24. package/dist/cli/introspect-DxqfkVIv.js +81 -0
  25. package/dist/cli/io-k41_z-jT.js +24 -0
  26. package/dist/cli/json5-ChRycquj.js +787 -0
  27. package/dist/cli/jsonc-BUniUpOk.js +2 -0
  28. package/dist/cli/jsonc-D5Fu67jw.js +45 -0
  29. package/dist/cli/keys-ByKHnvP9.js +83 -0
  30. package/dist/cli/ohash-D7bG_EOb.js +277 -0
  31. package/dist/cli/openapi-8WHjxiTJ.js +66 -0
  32. package/dist/cli/project-B_GeXyHh.js +70 -0
  33. package/dist/cli/prompts-BNcNfAve.js +1142 -0
  34. package/dist/cli/prompts-BTYQGunc.js +2 -0
  35. package/dist/cli/read-sets-CMa29t9a.js +971 -0
  36. package/dist/cli/rolldown-runtime-BPOCksWG.js +24 -0
  37. package/dist/cli/run-CP20LKk_.js +347 -0
  38. package/dist/cli/seed-5J6eu_Xg.js +98 -0
  39. package/dist/cli/skills-LJJIhLFR.js +137 -0
  40. package/dist/cli/sql-D4VbqmXi.js +199 -0
  41. package/dist/cli/style-C0NFdJRL.js +29 -0
  42. package/dist/cli/toml-DB-MNnFs.js +424 -0
  43. package/dist/{version-Cqq1m3UY.js → cli/version-5mW_8sY1.js} +1 -1
  44. package/dist/cli/yaml-CYCbJ6et.js +2252 -0
  45. package/dist/client/index.d.ts +2 -2
  46. package/dist/client/index.js +15 -25
  47. package/dist/{compiler-CZ9nIuqy.d.ts → compiler-DB3aSFOA.d.ts} +2 -2
  48. package/dist/config/index.d.ts +4 -3
  49. package/dist/config/index.js +5 -3
  50. package/dist/config-BpxDfnbg.js +129 -0
  51. package/dist/{index-DOsjFvMf.d.ts → config-C1CYcm6o.d.ts} +49 -49
  52. package/dist/{config-ClDXmVtY.js → config-CbvFmGD8.js} +14 -137
  53. package/dist/{define-BXMYD9AY.js → define-Bh0AqTik.js} +221 -120
  54. package/dist/{define-e3zI4_4g.d.ts → define-CRS2MRV3.d.ts} +36 -31
  55. package/dist/edge/index.d.ts +9 -13
  56. package/dist/edge/index.js +51 -25
  57. package/dist/{entitlements-Dng-ctuT.d.ts → entitlements-Dm-FHpNH.d.ts} +2 -2
  58. package/dist/env/index.js +203 -1
  59. package/dist/{errors-Bl3rkOzo.js → errors-L0xK41y_.js} +1 -1
  60. package/dist/events/index.d.ts +1 -1
  61. package/dist/events/index.js +139 -1
  62. package/dist/{events-DOt3nSO-.d.ts → events-B21UOhvP.d.ts} +4 -4
  63. package/dist/{executor-CGdNQ27g.d.ts → executor-B5IoUxLE.d.ts} +2 -2
  64. package/dist/{executor-DeppvirK.js → executor-CVt6dD0B.js} +9 -4
  65. package/dist/{executor-BYXQ9AGn.d.ts → executor-CZ7ImRiD.d.ts} +2 -2
  66. package/dist/hono/index.d.ts +17 -24
  67. package/dist/hono/index.js +11 -11
  68. package/dist/{index-DuP14VHo.d.ts → index-528Ugmyp.d.ts} +30 -10
  69. package/dist/{index-Bw1bwtC0.d.ts → index-BAy4tsAP.d.ts} +28 -15
  70. package/dist/{index-CBDufH1M.d.ts → index-BBdvo-5d.d.ts} +24 -26
  71. package/dist/{index-DbxFr7XG.d.ts → index-BhHEC04r.d.ts} +9 -4
  72. package/dist/index-Cf-D2jk1.d.ts +50 -0
  73. package/dist/{index-Ciu5Xlml.d.ts → index-D5IfUIDh.d.ts} +6 -5
  74. package/dist/{index-K-3WM2Hp.d.ts → index-DFmOpBGC.d.ts} +13 -13
  75. package/dist/{index-D4v7sncu.d.ts → index-RlLXd8dL.d.ts} +13 -13
  76. package/dist/index.d.ts +17 -17
  77. package/dist/index.js +23 -14
  78. package/dist/{invalidate-DbxuL2jL.js → invalidate-CgxmRamI.js} +7 -1
  79. package/dist/jobs/index.d.ts +33 -26
  80. package/dist/jobs/index.js +44 -22
  81. package/dist/{json-schema-BpYqkCKf.js → json-schema-DP6V7cbr.js} +8 -3
  82. package/dist/lint/index.js +1 -1
  83. package/dist/list/index.d.ts +2 -2
  84. package/dist/list/index.js +131 -96
  85. package/dist/{live-DJyZMD6w.d.ts → live-BHakSWWo.d.ts} +26 -16
  86. package/dist/{live-D8rV1Ldw.js → live-CdJBOc4f.js} +13 -9
  87. package/dist/lookup-BaP5bI27.js +18 -0
  88. package/dist/mcp/index.d.ts +34 -27
  89. package/dist/mcp/index.js +59 -25
  90. package/dist/{mfa-TVia554c.d.ts → mfa-C7MNQ1Ob.d.ts} +1 -1
  91. package/dist/{mfa-CpLfJSde.js → mfa-byfjruR9.js} +190 -46
  92. package/dist/next/image/index.js +6 -3
  93. package/dist/next/index.d.ts +64 -48
  94. package/dist/next/index.js +63 -50
  95. package/dist/openapi/index.d.ts +1 -1
  96. package/dist/openapi/index.js +61 -38
  97. package/dist/orpc/index.d.ts +18 -21
  98. package/dist/orpc/index.js +12 -12
  99. package/dist/otel/index.d.ts +5 -5
  100. package/dist/otel/index.js +84 -63
  101. package/dist/{permdock-sql-CghlHPuH.js → permdock-sql-C4KFzLc9.js} +12 -7
  102. package/dist/permdock-sql-DImJULY-.d.ts +17 -0
  103. package/dist/{plugin-C4TR9J0Z.d.ts → plugin-bNhvJwRh.d.ts} +5 -4
  104. package/dist/plugins/actor/index.d.ts +1 -1
  105. package/dist/plugins/actor/index.js +1 -1
  106. package/dist/plugins/rules/index.d.ts +2 -2
  107. package/dist/plugins/rules/index.js +46 -16
  108. package/dist/plugins/soft-delete/index.d.ts +3 -3
  109. package/dist/plugins/soft-delete/index.js +4 -4
  110. package/dist/plugins/tenant/index.d.ts +3 -3
  111. package/dist/plugins/tenant/index.js +10 -4
  112. package/dist/plugins/timestamps/index.d.ts +1 -1
  113. package/dist/plugins/timestamps/index.js +2 -2
  114. package/dist/plugins/validation/index.d.ts +2 -2
  115. package/dist/plugins/validation/index.js +3 -3
  116. package/dist/pool-DFwEQwmN.d.ts +78 -0
  117. package/dist/postgres/index.d.ts +10 -5
  118. package/dist/postgres/index.js +37 -16
  119. package/dist/{postgrest-cAEQ_IQN.d.ts → postgrest-Bc-0Xw62.d.ts} +1 -1
  120. package/dist/{problem-BTkTtRV9.js → problem-BihjPR0t.js} +11 -5
  121. package/dist/{problem-DlgB0lYl.d.ts → problem-U8UEKccv.d.ts} +6 -4
  122. package/dist/query/index.d.ts +2 -2
  123. package/dist/query/index.js +2 -2
  124. package/dist/{query-ChvDbsDE.js → query-BMMSWbI7.js} +19 -19
  125. package/dist/react/index.d.ts +7 -7
  126. package/dist/react/index.js +2 -2
  127. package/dist/react/server.d.ts +6 -6
  128. package/dist/react/server.js +3 -3
  129. package/dist/react/session.d.ts +21 -2
  130. package/dist/react/session.js +19 -1
  131. package/dist/{react-C83BdBGt.js → react-CQHMaESR.js} +59 -55
  132. package/dist/{read-set-4lI3W_gZ.js → read-set-FWK8qQ58.js} +51 -16
  133. package/dist/realtime/index.d.ts +4 -3
  134. package/dist/realtime/index.js +19 -17
  135. package/dist/{index-CG69s15v.d.ts → refresh-BwYkyNOQ.d.ts} +7 -3
  136. package/dist/{resolve-CjHILk2w.d.ts → resolve-BAqQcwMW.d.ts} +17 -11
  137. package/dist/{resource-CgZa3YG_.d.ts → resource-BJcaIfxi.d.ts} +17 -8
  138. package/dist/{resource-BHEWmQJK.js → resource-My_y-Syh.js} +43 -21
  139. package/dist/{respond-Dne1ARSa.d.ts → respond-DgIbdrt8.d.ts} +39 -14
  140. package/dist/{result-DWXatkd6.js → result-Bj6yt33D.js} +2 -2
  141. package/dist/{result-CTkCZ6JA.d.ts → result-CqEsbgYs.d.ts} +16 -11
  142. package/dist/server/index.d.ts +38 -13
  143. package/dist/server/index.js +43 -14
  144. package/dist/{respond-DMcbQwfN.js → server-BA75B0mT.js} +151 -96
  145. package/dist/{shared-_6-uPL7E.js → shared-DnoCdMDr.js} +4 -3
  146. package/dist/{simplify-bwJpLnaS.js → simplify-Cqvfr9dj.js} +76 -39
  147. package/dist/sql/index.d.ts +139 -0
  148. package/dist/sql/index.js +1983 -0
  149. package/dist/{sql-DTjA1LPj.js → sql-B34HU2DI.js} +74 -17
  150. package/dist/ssr/index.d.ts +4 -4
  151. package/dist/ssr/index.js +2 -2
  152. package/dist/{standard-FUi3Z3-7.js → standard-BRyBGTtp.js} +2 -2
  153. package/dist/{standard-CyhRzctb.d.ts → standard-BsaCYQJc.d.ts} +1 -1
  154. package/dist/{stats-C5W-rBfR.js → stats-C_YxA2r1.js} +40 -14
  155. package/dist/storage/index.d.ts +4 -3
  156. package/dist/storage/index.js +548 -1
  157. package/dist/{tables-rZxRxNPW.js → tables-Cb-3_VWc.js} +19 -5
  158. package/dist/temporal-BwshQk0W.js +27 -0
  159. package/dist/temporal-required-CBNHT6ni.js +19 -0
  160. package/dist/testing/index.d.ts +25 -24
  161. package/dist/testing/index.js +165 -66
  162. package/dist/{types-C83v5SQz.d.ts → types-DONv9SHN.d.ts} +14 -11
  163. package/dist/version-Bmf7_FzM.js +4 -0
  164. package/dist/{view-D1s0wa0T.d.ts → view-B64o81wp.d.ts} +36 -6
  165. package/dist/{view-aOYizTeE.js → view-BrJI2LKp.js} +11 -2
  166. package/dist/webhooks/index.d.ts +19 -17
  167. package/dist/webhooks/index.js +1 -1
  168. package/dist/{webhooks-DMipjhSP.js → webhooks-Bh_Jf_-l.js} +45 -24
  169. package/package.json +50 -22
  170. package/schemas/config-v1.json +31 -1
  171. package/schemas/doctor-report-v1.json +17 -1
  172. package/schemas/snapshot-v2.json +35 -0
  173. package/skills/better-supabase/SKILL.md +77 -18
  174. package/skills/better-supabase/references/plugins.md +21 -22
  175. package/skills/better-supabase/references/troubleshooting.md +38 -18
  176. package/skills/better-supabase-api/SKILL.md +66 -18
  177. package/skills/better-supabase-api/references/adapters.md +64 -41
  178. package/skills/better-supabase-auth/SKILL.md +146 -0
  179. package/skills/better-supabase-auth/references/permdock.md +55 -0
  180. package/skills/better-supabase-testing/SKILL.md +68 -11
  181. package/dist/casing-da0uRTqt.js +0 -14
  182. package/dist/claims-CoTobNC-.js +0 -25
  183. package/dist/cli-DrSgDOQC.js +0 -6646
  184. package/dist/env-BEToab0I.js +0 -204
  185. package/dist/events-BuzTgn2D.js +0 -135
  186. package/dist/pool-R2m_DkXi.d.ts +0 -37
  187. package/dist/seed-CzecODcJ.js +0 -101
  188. package/dist/session-C3LxnQ0e.d.ts +0 -22
  189. package/dist/session-CqEwzVup.js +0 -20
  190. package/dist/storage-DuGn38fr.js +0 -527
@@ -1,13 +1,14 @@
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";
1
+ import { A as SchemaMeta, N as TableKey, R as Update, g as Insert, n as AnyModels, t as AnyFunctions } from "../types-DONv9SHN.js";
2
+ import { r as Executor } from "../executor-B5IoUxLE.js";
3
+ import { P as DbStats, l as CacheAdapter, t as BetterSupabase, y as Db } from "../define-CRS2MRV3.js";
4
+ import { h as RequestContext, n as AnyPlugin } from "../plugin-bNhvJwRh.js";
5
+ import { b as ResolvedConfig, d as Generator, f as GeneratorInput } from "../config-C1CYcm6o.js";
6
+ import { t as SqlClient } from "../executor-CZ7ImRiD.js";
7
+ import { t as BetterPostgres } from "../pool-DFwEQwmN.js";
8
+ import { n as AuthResolver } from "../resolve-BAqQcwMW.js";
9
+ import { r as EventSink, t as CloudEvent } from "../index-D5IfUIDh.js";
10
10
  import { SupabaseClient } from "@supabase/supabase-js";
11
+ import { webcrypto } from "node:crypto";
11
12
  //#region src/testing/jwt.d.ts
12
13
  interface TestJwtClaims {
13
14
  readonly sub: string;
@@ -24,19 +25,19 @@ interface TestJwtClaims {
24
25
  export declare function signTestJwt(secret: string, claims: TestJwtClaims): Promise<string>;
25
26
  /**
26
27
  * Accepts `signTestJwt` tokens as users, for API servers tested against the
27
- * local stack: `createServer(sb, { auth: { resolvers: [localAuth(secret)] } })`.
28
+ * local stack: `createServer(betterSupabase, { auth: { resolvers: [localAuth(secret)] } })`.
28
29
  * Tokens that are not HS256-signed with `secret` fall through. Test-only.
29
30
  */
30
31
  export declare function localAuth(secret: string): AuthResolver;
31
32
  interface TestSigner {
32
33
  /** Public JWKS; pass as `jwks` to `resolveAuth` / `createServer({ auth: { jwks } })`. */
33
34
  readonly jwks: {
34
- readonly keys: readonly JsonWebKey[];
35
+ readonly keys: readonly webcrypto.JsonWebKey[];
35
36
  };
36
37
  sign(claims: TestJwtClaims): Promise<string>;
37
38
  }
38
39
  /** A private ES256 JWK, as `better-supabase keys` writes to `supabase/signing_keys.json`. */
39
- interface SigningJwk extends JsonWebKey {
40
+ interface SigningJwk extends webcrypto.JsonWebKey {
40
41
  readonly kid: string;
41
42
  }
42
43
  /**
@@ -80,7 +81,7 @@ interface LocalStack {
80
81
  /** Service-role key for `expectTenantIsolation`; defaults to `$SUPABASE_SECRET_KEY`. */
81
82
  readonly secretKey?: string;
82
83
  /** Enables `sql`: the same user over direct Postgres. */
83
- readonly postgres?: Postgres;
84
+ readonly postgres?: BetterPostgres;
84
85
  }
85
86
  interface TestUser<M extends AnyModels, F extends AnyFunctions, E> {
86
87
  readonly token: string;
@@ -99,11 +100,11 @@ interface TestUser<M extends AnyModels, F extends AnyFunctions, E> {
99
100
  * still uses the shared JWT secret.
100
101
  *
101
102
  * ```ts
102
- * const alice = await asUser(sb, { sub: aliceId, tenant_id: acme });
103
+ * const alice = await asUser(betterSupabase, { sub: aliceId, tenant_id: acme });
103
104
  * expect(await alice.db.customers.count().orThrow()).toBe(3);
104
105
  * ```
105
106
  */
106
- export declare function asUser<M extends AnyModels, D, F extends AnyFunctions, E>(sb: BetterSupabase<M, D, F, E>, claims: TestJwtClaims, stack?: LocalStack): Promise<TestUser<M, F, E>>;
107
+ export declare function asUser<M extends AnyModels, D, F extends AnyFunctions, E>(betterSupabase: BetterSupabase<M, D, F, E>, claims: TestJwtClaims, stack?: LocalStack): Promise<TestUser<M, F, E>>;
107
108
  //#endregion
108
109
  //#region src/testing/budget.d.ts
109
110
  /** The part of a Playwright `Response` the budget check reads. */
@@ -146,7 +147,7 @@ interface MeasuredRender {
146
147
  /**
147
148
  * Measures every document and RSC navigation response during `during` and
148
149
  * fails when one render makes more database calls or waves than allowed.
149
- * Needs `createNext(sb, { debug })` and `next.debugRoute()` in the app.
150
+ * Needs `createNext(betterSupabase, { debug })` and `bs.debugRoute()` in the app.
150
151
  */
151
152
  export declare function expectDbBudget(page: BudgetPage, expectation: DbBudgetExpectation): Promise<readonly MeasuredRender[]>;
152
153
  //#endregion
@@ -169,7 +170,7 @@ export declare class ConformanceError extends Error {
169
170
  type AnySupabase = BetterSupabase<any, any, any, any>;
170
171
  interface TestExecutorOptions {
171
172
  /** A definition whose schema matches the executor's database. Install no plugins. */
172
- readonly sb: AnySupabase;
173
+ readonly betterSupabase: AnySupabase;
173
174
  /** App key of a table with rows the executor can read. Defaults to the first table. */
174
175
  readonly table?: string;
175
176
  /** A row to insert and delete again, to check writes. Skips write checks when omitted. */
@@ -181,7 +182,7 @@ interface TestExecutorOptions {
181
182
  * than thrown, and (with `create`) a write round trip.
182
183
  *
183
184
  * ```ts
184
- * it('conforms', () => testExecutor(myExecutor, { sb, table: 'tags', create: { name: 'x' } }));
185
+ * it('conforms', () => testExecutor(myExecutor, { betterSupabase, table: 'tags', create: { name: 'x' } }));
185
186
  * ```
186
187
  */
187
188
  export declare function testExecutor(executor: Executor, options: TestExecutorOptions): Promise<ConformanceReport>;
@@ -226,7 +227,7 @@ interface TestGeneratorOptions {
226
227
  export declare function testGenerator(generator: Generator, options: TestGeneratorOptions): Promise<ConformanceReport>;
227
228
  interface TestPluginOptions {
228
229
  /** The definition without this plugin. */
229
- readonly sb: AnySupabase;
230
+ readonly betterSupabase: AnySupabase;
230
231
  /** Table to exercise. Defaults to the first table. */
231
232
  readonly table?: string;
232
233
  /** Context the plugin needs, such as `{ tenant }` for `tenant()`. */
@@ -271,12 +272,12 @@ interface TenantIsolationOptions<M extends AnyModels> {
271
272
  /**
272
273
  * Checks row-level security between two tenants against a running stack: for
273
274
  * each table, a user of one tenant must not select, insert, update or delete
274
- * the other tenant's rows. Runs without `sb`'s plugins, so the `tenant()`
275
+ * the other tenant's rows. Runs without `betterSupabase`'s plugins, so the `tenant()`
275
276
  * plugin can't hide a missing policy. Throws a `ConformanceError` naming each
276
277
  * table and command that leaks; removes every row it created.
277
278
  *
278
279
  * ```ts
279
- * await expectTenantIsolation(sb, {
280
+ * await expectTenantIsolation(betterSupabase, {
280
281
  * tenants: [
281
282
  * { id: ACME, claims: { sub: alice, tenant_id: ACME } },
282
283
  * { id: GLOBEX, claims: { sub: bob, tenant_id: GLOBEX } },
@@ -290,7 +291,7 @@ interface TenantIsolationOptions<M extends AnyModels> {
290
291
  * });
291
292
  * ```
292
293
  */
293
- export declare function expectTenantIsolation<M extends AnyModels, D, F extends AnyFunctions, E>(sb: BetterSupabase<M, D, F, E>, options: TenantIsolationOptions<M>): Promise<ConformanceReport>;
294
+ export declare function expectTenantIsolation<M extends AnyModels, D, F extends AnyFunctions, E>(betterSupabase: BetterSupabase<M, D, F, E>, options: TenantIsolationOptions<M>): Promise<ConformanceReport>;
294
295
  //#endregion
295
296
  //#region src/testing/seed.d.ts
296
297
  /** Named rows per table, in app casing: `{ customers: { acme: { ... } } }`. */
@@ -314,12 +315,12 @@ export declare function isSeed(value: unknown): value is Seed<unknown>;
314
315
  * casing and Insert types; `better-supabase seed` renders them to SQL.
315
316
  *
316
317
  * ```ts
317
- * export const seed = defineSeed(sb, {
318
+ * export const seed = defineSeed(betterSupabase, {
318
319
  * organizations: { acme: { id: ACME, name: 'Acme' } },
319
320
  * customers: { first: { organizationId: ACME, name: 'First customer' } },
320
321
  * });
321
322
  * ```
322
323
  */
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>;
324
+ export declare function defineSeed<M extends AnyModels, D, F extends AnyFunctions, E, const S extends SeedFixtures<M>>(betterSupabase: BetterSupabase<M, D, F, E>, fixtures: S & ExactSeed<M, S>): Seed<S>;
324
325
  //#endregion
325
326
  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 };
@@ -1,24 +1,20 @@
1
- import { n as dbError } from "../errors-Bl3rkOzo.js";
2
- import { i as ok } from "../result-DWXatkd6.js";
3
- import { t as BetterSupabase } from "../define-BXMYD9AY.js";
1
+ import { n as dbError } from "../errors-L0xK41y_.js";
2
+ import { i as temporalText } from "../temporal-BwshQk0W.js";
3
+ import { t as temporal } from "../temporal-required-CBNHT6ni.js";
4
+ import { i as ok } from "../result-Bj6yt33D.js";
5
+ import { t as BetterSupabase } from "../define-Bh0AqTik.js";
6
+ import { a as toBase64Url, r as fromBase64, t as base64ToText } from "../base64-D2gsioCY.js";
7
+ import { r as resolveConfig } from "../config-BpxDfnbg.js";
4
8
  import { t as isList } from "../guards-BnzDvFrz.js";
5
- import { r as resolveConfig } from "../config-ClDXmVtY.js";
6
- import { t as ENV_VARIABLES } from "../env-BEToab0I.js";
7
- import { n as postgresExecutor } from "../executor-DeppvirK.js";
8
- import { o as toCloudEvents } from "../events-BuzTgn2D.js";
9
- import { n as isSeed, t as defineSeed } from "../seed-CzecODcJ.js";
9
+ import { ENV_VARIABLES } from "../env/index.js";
10
+ import { n as postgresExecutor } from "../executor-CVt6dD0B.js";
11
+ import { toCloudEvents } from "../events/index.js";
10
12
  import { createClient } from "@supabase/supabase-js";
11
13
  import { existsSync } from "node:fs";
12
14
  import { readFile } from "node:fs/promises";
13
15
  import { dirname, join, resolve } from "node:path";
14
16
  //#region src/testing/jwt.ts
15
- const encoder = new TextEncoder();
16
- function base64url(input) {
17
- const bytes = typeof input === "string" ? encoder.encode(input) : input;
18
- let binary = "";
19
- for (const byte of bytes) binary += String.fromCharCode(byte);
20
- return btoa(binary).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
21
- }
17
+ const encoder = /* @__PURE__ */ new TextEncoder();
22
18
  /**
23
19
  * Signs an HS256 access token the local Supabase stack accepts. Test-only:
24
20
  * production tokens come from Supabase Auth.
@@ -34,25 +30,21 @@ async function signTestJwt(secret, claims) {
34
30
  exp: now + expiresIn,
35
31
  ...rest
36
32
  };
37
- const header = base64url(JSON.stringify({
33
+ const header = toBase64Url(JSON.stringify({
38
34
  alg: "HS256",
39
35
  typ: "JWT"
40
36
  }));
41
- const body = base64url(JSON.stringify(payload));
37
+ const body = toBase64Url(JSON.stringify(payload));
42
38
  const key = await crypto.subtle.importKey("raw", encoder.encode(secret), {
43
39
  name: "HMAC",
44
40
  hash: "SHA-256"
45
41
  }, false, ["sign"]);
46
42
  const signature = await crypto.subtle.sign("HMAC", key, encoder.encode(`${header}.${body}`));
47
- return `${header}.${body}.${base64url(new Uint8Array(signature))}`;
48
- }
49
- function base64urlDecode(input) {
50
- const binary = atob(input.replaceAll("-", "+").replaceAll("_", "/"));
51
- return Uint8Array.from(binary, (char) => char.charCodeAt(0));
43
+ return `${header}.${body}.${toBase64Url(new Uint8Array(signature))}`;
52
44
  }
53
45
  /**
54
46
  * Accepts `signTestJwt` tokens as users, for API servers tested against the
55
- * local stack: `createServer(sb, { auth: { resolvers: [localAuth(secret)] } })`.
47
+ * local stack: `createServer(betterSupabase, { auth: { resolvers: [localAuth(secret)] } })`.
56
48
  * Tokens that are not HS256-signed with `secret` fall through. Test-only.
57
49
  */
58
50
  function localAuth(secret) {
@@ -65,9 +57,9 @@ function localAuth(secret) {
65
57
  async resolve(request) {
66
58
  const token = /^Bearer (.+)$/i.exec(request.headers.get("authorization") ?? "")?.[1];
67
59
  const [header, body, signature] = token?.split(".") ?? [];
68
- if (!token || !header || !body || !signature) return void 0;
69
- if (!await crypto.subtle.verify("HMAC", await key, base64urlDecode(signature), encoder.encode(`${header}.${body}`)).catch(() => false)) return void 0;
70
- const claims = JSON.parse(new TextDecoder().decode(base64urlDecode(body)));
60
+ if (!token || !header || !body || !signature) return;
61
+ if (!await crypto.subtle.verify("HMAC", await key, fromBase64(signature), encoder.encode(`${header}.${body}`)).catch(() => false)) return;
62
+ const claims = JSON.parse(base64ToText(body));
71
63
  if (typeof claims.exp === "number" && claims.exp * 1e3 < Date.now()) return {
72
64
  kind: "invalid",
73
65
  error: dbError("unauthorized", "The token has expired")
@@ -98,17 +90,17 @@ async function signEs256(key, kid, claims) {
98
90
  exp: now + expiresIn,
99
91
  ...rest
100
92
  };
101
- const header = base64url(JSON.stringify({
93
+ const header = toBase64Url(JSON.stringify({
102
94
  alg: "ES256",
103
95
  typ: "JWT",
104
96
  kid
105
97
  }));
106
- const body = base64url(JSON.stringify(payload));
98
+ const body = toBase64Url(JSON.stringify(payload));
107
99
  const signature = await crypto.subtle.sign({
108
100
  name: "ECDSA",
109
101
  hash: "SHA-256"
110
102
  }, key, encoder.encode(`${header}.${body}`));
111
- return `${header}.${body}.${base64url(new Uint8Array(signature))}`;
103
+ return `${header}.${body}.${toBase64Url(new Uint8Array(signature))}`;
112
104
  }
113
105
  /**
114
106
  * Signs an ES256 access token with a private JWK, the way the local stack
@@ -206,11 +198,11 @@ async function signFor(stack, url, claims) {
206
198
  * still uses the shared JWT secret.
207
199
  *
208
200
  * ```ts
209
- * const alice = await asUser(sb, { sub: aliceId, tenant_id: acme });
201
+ * const alice = await asUser(betterSupabase, { sub: aliceId, tenant_id: acme });
210
202
  * expect(await alice.db.customers.count().orThrow()).toBe(3);
211
203
  * ```
212
204
  */
213
- async function asUser(sb, claims, stack = {}) {
205
+ async function asUser(betterSupabase, claims, stack = {}) {
214
206
  const url = stack.url ?? env$1(...ENV_VARIABLES.url) ?? "http://127.0.0.1:54321";
215
207
  const publishableKey = stack.publishableKey ?? env$1(...ENV_VARIABLES.publishableKey, "SUPABASE_ANON_KEY");
216
208
  if (!publishableKey) throw new TypeError("asUser needs publishableKey or $SUPABASE_PUBLISHABLE_KEY. Run `better-supabase env` to write it to .env.local.");
@@ -233,8 +225,8 @@ async function asUser(sb, claims, stack = {}) {
233
225
  token,
234
226
  claims: full,
235
227
  supabase,
236
- db: sb.connect(supabase, context),
237
- sql: stack.postgres ? sb.connect(postgresExecutor(stack.postgres.asUser(full)), context) : void 0
228
+ db: betterSupabase.connect(supabase, context),
229
+ sql: stack.postgres ? betterSupabase.connect(postgresExecutor(stack.postgres.asUser(full)), context) : void 0
238
230
  };
239
231
  }
240
232
  //#endregion
@@ -247,12 +239,14 @@ function settle(promise, ms) {
247
239
  let timer;
248
240
  return Promise.race([promise, new Promise((done) => {
249
241
  timer = setTimeout(done, ms);
250
- })]).finally(() => clearTimeout(timer));
242
+ })]).finally(() => {
243
+ clearTimeout(timer);
244
+ });
251
245
  }
252
246
  /**
253
247
  * Measures every document and RSC navigation response during `during` and
254
248
  * fails when one render makes more database calls or waves than allowed.
255
- * Needs `createNext(sb, { debug })` and `next.debugRoute()` in the app.
249
+ * Needs `createNext(betterSupabase, { debug })` and `bs.debugRoute()` in the app.
256
250
  */
257
251
  async function expectDbBudget(page, expectation) {
258
252
  const seen = [];
@@ -273,12 +267,12 @@ async function expectDbBudget(page, expectation) {
273
267
  } finally {
274
268
  page.off("response", listener);
275
269
  }
276
- if (seen.length === 0) throw new Error("expectDbBudget: no response carried x-bs-request-id. Enable createNext(sb, { debug: { enabled: true } }) and run the proxy.");
270
+ if (seen.length === 0) throw new Error("expectDbBudget: no response carried x-bs-request-id. Enable createNext(betterSupabase, { debug: { enabled: true } }) and run the proxy.");
277
271
  await Promise.all(seen.map(({ response }) => settle(response.finished(), expectation.timeoutMs ?? 1e4)));
278
272
  const renders = [];
279
273
  for (const { response, id, url } of seen) {
280
274
  const reply = await page.request.get(url);
281
- if (!reply.ok()) throw new Error(`expectDbBudget: ${url} answered ${reply.status()}. Mount next.debugRoute() at that path.`);
275
+ if (!reply.ok()) throw new Error(`expectDbBudget: ${url} answered ${reply.status()}. Mount bs.debugRoute() at that path.`);
282
276
  renders.push({
283
277
  url: response.url(),
284
278
  requestId: id,
@@ -354,34 +348,36 @@ const recorder = (ops) => ({
354
348
  }));
355
349
  }
356
350
  });
357
- /** The operation `run` sends to the executor, built by `sb` without touching a database. */
358
- async function captureOp(sb, run) {
351
+ /** The operation `run` sends to the executor, built by `betterSupabase` without touching a database. */
352
+ async function captureOp(betterSupabase, run) {
359
353
  const ops = [];
360
- await run(sb.connect(recorder(ops)));
354
+ await run(betterSupabase.connect(recorder(ops)));
361
355
  const [op] = ops;
362
356
  if (!op) throw new Error("the repository call did not reach the executor");
363
357
  return op;
364
358
  }
365
- function tableKey(sb, table) {
366
- const key = table ?? Object.keys(sb.meta.tables)[0];
367
- if (!key || !(key in sb.meta.tables)) throw new TypeError(`better-supabase: unknown table "${String(key)}"`);
359
+ function tableKey(betterSupabase, table) {
360
+ const key = table ?? Object.keys(betterSupabase.meta.tables)[0];
361
+ if (!key || !(key in betterSupabase.meta.tables)) throw new TypeError(`better-supabase: unknown table "${String(key)}"`);
368
362
  return key;
369
363
  }
370
- const hasName = (subject) => ["has a name", () => expect(typeof subject.name === "string" && subject.name.length > 0, "name must be a non-empty string")];
364
+ const hasName = (subject) => ["has a name", () => {
365
+ expect(typeof subject.name === "string" && subject.name.length > 0, "name must be a non-empty string");
366
+ }];
371
367
  /**
372
368
  * Proves an `Executor` meets the contract: rows keyed by the selection's
373
369
  * aliases, counts, `aborted` errors, failures returned as `Result`s rather
374
370
  * than thrown, and (with `create`) a write round trip.
375
371
  *
376
372
  * ```ts
377
- * it('conforms', () => testExecutor(myExecutor, { sb, table: 'tags', create: { name: 'x' } }));
373
+ * it('conforms', () => testExecutor(myExecutor, { betterSupabase, table: 'tags', create: { name: 'x' } }));
378
374
  * ```
379
375
  */
380
376
  function testExecutor(executor, options) {
381
- const { sb } = options;
382
- const table = tableKey(sb, options.table);
377
+ const { betterSupabase } = options;
378
+ const table = tableKey(betterSupabase, options.table);
383
379
  const context = { errorMappers: [] };
384
- const read = () => captureOp(sb, (db) => db[table]["findMany"]({ limit: 2 }));
380
+ const read = () => captureOp(betterSupabase, (db) => db[table]["findMany"]({ limit: 2 }));
385
381
  const create = options.create;
386
382
  return conform(`Executor "${executor.name}"`, [
387
383
  hasName(executor),
@@ -400,7 +396,7 @@ function testExecutor(executor, options) {
400
396
  }
401
397
  }],
402
398
  ["counts rows", async () => {
403
- const op = await captureOp(sb, (db) => db[table]["count"]());
399
+ const op = await captureOp(betterSupabase, (db) => db[table]["count"]());
404
400
  const result = await executor.execute(op, context);
405
401
  expect(result.ok, `count failed: ${result.ok ? "" : result.error.message}`);
406
402
  expect(typeof result.data.count === "number" && result.data.count >= 0, "count must be a number");
@@ -448,7 +444,7 @@ function testExecutor(executor, options) {
448
444
  }],
449
445
  executor.batch && ["batch returns one result per operation, in order", async () => {
450
446
  const rows = await read();
451
- const count = await captureOp(sb, (db) => db[table]["count"]());
447
+ const count = await captureOp(betterSupabase, (db) => db[table]["count"]());
452
448
  const missing = {
453
449
  ...rows,
454
450
  table: {
@@ -468,12 +464,12 @@ function testExecutor(executor, options) {
468
464
  expect(third?.ok === false, "a failing operation must fail on its own, as a result");
469
465
  }],
470
466
  create && ["round-trips a write", async () => {
471
- const repository = sb.connect(executor)[table];
467
+ const repository = betterSupabase.connect(executor)[table];
472
468
  const created = await repository["create"](create);
473
469
  expect(created.ok, `create failed: ${JSON.stringify(created.error)}`);
474
470
  const row = created.data;
475
471
  for (const [key, value] of Object.entries(create)) expect(same(row[key], value), `created row has ${key} = ${JSON.stringify(row[key])}`);
476
- const [primary] = sb.meta.tables[table].primaryKey;
472
+ const [primary] = betterSupabase.meta.tables[table].primaryKey;
477
473
  expect(primary, "write checks need a table with a primary key");
478
474
  const removed = await repository["delete"](row[primary]);
479
475
  expect(removed.ok, `delete failed: ${JSON.stringify(removed.error)}`);
@@ -647,33 +643,35 @@ function testGenerator(generator, options) {
647
643
  * results intact when it wraps them.
648
644
  */
649
645
  function testPlugin(plugin, options) {
650
- const { sb } = options;
651
- const table = tableKey(sb, options.table);
646
+ const { betterSupabase } = options;
647
+ const table = tableKey(betterSupabase, options.table);
652
648
  const context = options.context ?? {};
653
649
  const hook = (op) => ({
654
650
  table: op.table,
655
- schema: sb.meta,
651
+ schema: betterSupabase.meta,
656
652
  context,
657
653
  options: {},
658
- now: () => /* @__PURE__ */ new Date(0)
654
+ now: () => temporal().Instant.fromEpochMilliseconds(0)
659
655
  });
660
656
  const create = options.create;
661
657
  return conform(`Plugin "${plugin.name}"`, [
662
658
  hasName(plugin),
663
- ["targets plugin API v1", () => expect(plugin.apiVersion === 1, `apiVersion is ${String(plugin.apiVersion)}`)],
659
+ ["targets plugin API v1", () => {
660
+ expect(plugin.apiVersion === 1, `apiVersion is ${String(plugin.apiVersion)}`);
661
+ }],
664
662
  ["installs and builds repositories", () => {
665
- const db = sb.use(plugin).connect(recorder([]), context);
666
- for (const key of Object.keys(sb.meta.tables)) expect(db[key], `db.${key} is missing`);
663
+ const db = betterSupabase.use(plugin).connect(recorder([]), context);
664
+ for (const key of Object.keys(betterSupabase.meta.tables)) expect(db[key], `db.${key} is missing`);
667
665
  }],
668
666
  plugin.transformQuery && ["transformQuery is pure and deterministic", async () => {
669
- const op = await captureOp(sb, (db) => db[table]["findMany"]({ limit: 1 }));
667
+ const op = await captureOp(betterSupabase, (db) => db[table]["findMany"]({ limit: 1 }));
670
668
  const first = plugin.transformQuery(frozenCopy(op), hook(op));
671
669
  const second = plugin.transformQuery(frozenCopy(op), hook(op));
672
670
  expect(typeof first === "object" && first !== null && first.kind === op.kind, "must return an operation of the same kind");
673
671
  expect(same(first, second), "two calls with the same input differ");
674
672
  }],
675
673
  plugin.beforeMutation && create && ["beforeMutation is pure and deterministic", async () => {
676
- const op = await captureOp(sb, (db) => db[table]["create"](create));
674
+ const op = await captureOp(betterSupabase, (db) => db[table]["create"](create));
677
675
  if (op.kind === "select") throw new Violation("create did not produce a mutation");
678
676
  const first = await plugin.beforeMutation(frozenCopy(op), hook(op));
679
677
  const second = await plugin.beforeMutation(frozenCopy(op), hook(op));
@@ -681,7 +679,7 @@ function testPlugin(plugin, options) {
681
679
  expect(same(first, second), "two calls with the same input differ");
682
680
  }],
683
681
  plugin.wrapExecutor && ["wrapExecutor keeps results intact", async () => {
684
- const op = await captureOp(sb, (db) => db[table]["findMany"]({ limit: 1 }));
682
+ const op = await captureOp(betterSupabase, (db) => db[table]["findMany"]({ limit: 1 }));
685
683
  const data = {
686
684
  rows: [{ marker: "conformance" }],
687
685
  count: 1
@@ -725,12 +723,12 @@ function env(names) {
725
723
  /**
726
724
  * Checks row-level security between two tenants against a running stack: for
727
725
  * each table, a user of one tenant must not select, insert, update or delete
728
- * the other tenant's rows. Runs without `sb`'s plugins, so the `tenant()`
726
+ * the other tenant's rows. Runs without `betterSupabase`'s plugins, so the `tenant()`
729
727
  * plugin can't hide a missing policy. Throws a `ConformanceError` naming each
730
728
  * table and command that leaks; removes every row it created.
731
729
  *
732
730
  * ```ts
733
- * await expectTenantIsolation(sb, {
731
+ * await expectTenantIsolation(betterSupabase, {
734
732
  * tenants: [
735
733
  * { id: ACME, claims: { sub: alice, tenant_id: ACME } },
736
734
  * { id: GLOBEX, claims: { sub: bob, tenant_id: GLOBEX } },
@@ -744,9 +742,9 @@ function env(names) {
744
742
  * });
745
743
  * ```
746
744
  */
747
- async function expectTenantIsolation(sb, options) {
745
+ async function expectTenantIsolation(betterSupabase, options) {
748
746
  const stack = options.stack ?? {};
749
- const bare = new BetterSupabase(sb.schema);
747
+ const bare = new BetterSupabase(betterSupabase.schema);
750
748
  const url = stack.url ?? env(ENV_VARIABLES.url) ?? "http://127.0.0.1:54321";
751
749
  const secretKey = stack.secretKey ?? env(ENV_VARIABLES.secretKey);
752
750
  if (!secretKey) throw new TypeError("expectTenantIsolation needs stack.secretKey or $SUPABASE_SECRET_KEY to seed rows.");
@@ -816,4 +814,105 @@ async function expectTenantIsolation(sb, options) {
816
814
  }
817
815
  }
818
816
  //#endregion
817
+ //#region src/testing/seed.ts
818
+ const SEED = Symbol.for("better-supabase.seed");
819
+ function isSeed(value) {
820
+ return typeof value === "object" && value !== null && SEED in value;
821
+ }
822
+ const quote = (text) => `'${text.replaceAll("'", "''")}'`;
823
+ function arrayLiteral(values) {
824
+ return `{${values.map((value) => {
825
+ if (value === null) return "NULL";
826
+ if (Array.isArray(value)) return arrayLiteral(value);
827
+ return `"${(temporalText(value) ?? String(value)).replaceAll(/[\\"]/g, "\\$&")}"`;
828
+ }).join(",")}}`;
829
+ }
830
+ function literal(value, column, where) {
831
+ if (value === null) return "null";
832
+ if (column.json) return quote(JSON.stringify(value));
833
+ if (Array.isArray(value)) return quote(arrayLiteral(value));
834
+ const temporalValue = temporalText(value);
835
+ if (temporalValue !== void 0) return quote(temporalValue);
836
+ const kind = typeof value;
837
+ switch (kind) {
838
+ case "string": return quote(value);
839
+ case "boolean":
840
+ case "bigint": return String(value);
841
+ case "number":
842
+ if (!Number.isFinite(value)) throw new TypeError(`${where}: ${String(value)} is not a finite number`);
843
+ return String(value);
844
+ case "object":
845
+ case "function":
846
+ case "symbol":
847
+ case "undefined": throw new TypeError(`${where}: unsupported value of type ${kind}`);
848
+ default: throw new TypeError(`${where}: unsupported value of type ${String(kind)}`);
849
+ }
850
+ }
851
+ const ident = (name) => `"${name.replaceAll("\"", "\"\"")}"`;
852
+ /** Parents first (by forward relations), otherwise in the order given. */
853
+ function order(meta, keys) {
854
+ const sorted = [];
855
+ const visiting = /* @__PURE__ */ new Set();
856
+ const visit = (key) => {
857
+ if (sorted.includes(key) || visiting.has(key)) return;
858
+ visiting.add(key);
859
+ for (const relation of Object.values(meta.tables[key]?.relations ?? {})) if (relation.direction === "forward" && relation.table !== key && keys.includes(relation.table)) visit(relation.table);
860
+ visiting.delete(key);
861
+ sorted.push(key);
862
+ };
863
+ for (const key of keys) visit(key);
864
+ return sorted;
865
+ }
866
+ function statement(table, rows) {
867
+ const entries = Object.entries(rows);
868
+ if (entries.length === 0) return void 0;
869
+ const columns = [];
870
+ for (const [, row] of entries) for (const [key, value] of Object.entries(row)) {
871
+ if (value === void 0 || columns.includes(key)) continue;
872
+ const column = table.columns[key];
873
+ if (!column) throw new TypeError(`seed ${table.key}: unknown column "${key}"`);
874
+ if (column.generated) throw new TypeError(`seed ${table.key}: "${key}" is a generated column`);
875
+ columns.push(key);
876
+ }
877
+ const values = entries.map(([name, row]) => {
878
+ return ` (${columns.map((key) => row[key] === void 0 ? "default" : literal(row[key], table.columns[key], `seed ${table.key}.${name}.${key}`)).join(", ")})`;
879
+ });
880
+ return `insert into ${`${ident(table.schema)}.${ident(table.name)}`} (${columns.map((key) => ident(table.columns[key].db)).join(", ")}) values\n${values.join(",\n")}\non conflict do nothing;`;
881
+ }
882
+ /**
883
+ * Typed fixtures shared by `supabase/seeds` and your tests. Rows use app
884
+ * casing and Insert types; `better-supabase seed` renders them to SQL.
885
+ *
886
+ * ```ts
887
+ * export const seed = defineSeed(betterSupabase, {
888
+ * organizations: { acme: { id: ACME, name: 'Acme' } },
889
+ * customers: { first: { organizationId: ACME, name: 'First customer' } },
890
+ * });
891
+ * ```
892
+ */
893
+ function defineSeed(betterSupabase, fixtures) {
894
+ const meta = betterSupabase.meta;
895
+ const statements = () => {
896
+ const keys = Object.keys(fixtures).filter((key) => fixtures[key] !== void 0);
897
+ for (const key of keys) {
898
+ const table = meta.tables[key];
899
+ if (!table) throw new TypeError(`seed: unknown table "${key}"`);
900
+ if (table.kind === "view") throw new TypeError(`seed: "${key}" is a view`);
901
+ }
902
+ return order(meta, keys).flatMap((key) => {
903
+ const sql = statement(meta.tables[key], fixtures[key]);
904
+ return sql ? [sql] : [];
905
+ });
906
+ };
907
+ return {
908
+ [SEED]: true,
909
+ rows: fixtures,
910
+ statements,
911
+ sql: () => statements().join("\n\n"),
912
+ async insert(sql) {
913
+ for (const text of statements()) await sql.queryRaw(text);
914
+ }
915
+ };
916
+ }
917
+ //#endregion
819
918
  export { ConformanceError, LOCAL_JWT_SECRET, asUser, createTestSigner, defineSeed, expectDbBudget, expectTenantIsolation, isSeed, localAuth, localSigningKey, signLocalJwt, signTestJwt, signTestJwtWithKey, testAuthResolver, testCacheAdapter, testEventSink, testExecutor, testGenerator, testPlugin };
@@ -1,3 +1,4 @@
1
+ /// <reference lib="esnext.temporal" />
1
2
  //#region src/schema/types.d.ts
2
3
  type Casing = "snake" | "camel";
3
4
  /** Runtime metadata for one column. Keyed by the app (cased) column name. */
@@ -27,10 +28,12 @@ interface ColumnMeta {
27
28
  readonly storage?: string;
28
29
  }
29
30
  /**
30
- * Runtime representation for a column: `date` decodes timestamps to `Date`,
31
- * `bigint` and `string` read the exact text of `int8`/`numeric` values.
31
+ * Runtime representation for a column: `instant` decodes `timestamptz` to
32
+ * `Temporal.Instant`, `plainDateTime` decodes `timestamp` to
33
+ * `Temporal.PlainDateTime`, and `bigint` and `string` read the exact text of
34
+ * `int8`/`numeric` values.
32
35
  */
33
- type Codec = "date" | "bigint" | "string";
36
+ type Codec = "instant" | "plainDateTime" | "bigint" | "string";
34
37
  interface RelationMeta {
35
38
  /** App key of the target table. */
36
39
  readonly table: string;
@@ -165,19 +168,19 @@ interface BucketMeta {
165
168
  readonly fileSizeLimit?: string;
166
169
  readonly allowedMimeTypes?: readonly string[];
167
170
  }
168
- interface RelationShape {
171
+ interface RelationTypes {
169
172
  readonly table: string;
170
173
  readonly kind: "one" | "many";
171
174
  readonly nullable: boolean;
172
175
  }
173
- interface FlagsShape {
176
+ interface ModelFlags {
174
177
  readonly softDelete?: string;
175
178
  readonly timestamps?: true;
176
179
  readonly tenant?: string;
177
180
  readonly actor?: true;
178
181
  readonly version?: string;
179
182
  }
180
- interface ModelShape {
183
+ interface ModelTypes {
181
184
  readonly Row: object;
182
185
  readonly Insert: object;
183
186
  readonly Update: object;
@@ -188,17 +191,17 @@ interface ModelShape {
188
191
  readonly Checks?: string;
189
192
  /** Foreign key constraint names on this table. */
190
193
  readonly ForeignKeys?: string;
191
- readonly Flags: FlagsShape;
194
+ readonly Flags: ModelFlags;
192
195
  }
193
196
  type AnyModels = {
194
- readonly [table: string]: ModelShape;
197
+ readonly [table: string]: ModelTypes;
195
198
  };
196
- type FunctionShape = {
199
+ type FunctionTypes = {
197
200
  readonly Args: object;
198
201
  readonly Returns: unknown;
199
202
  };
200
203
  type AnyFunctions = {
201
- readonly [name: string]: FunctionShape;
204
+ readonly [name: string]: FunctionTypes;
202
205
  };
203
206
  /**
204
207
  * Carries the model types next to the runtime metadata. Created by
@@ -245,4 +248,4 @@ type IsUnion<T, U = T> = T extends unknown ? [U] extends [T] ? false : true : ne
245
248
  type PrimaryKeyValue<M extends AnyModels, T extends keyof M> = true extends IsUnion<PrimaryKeyColumn<M, T>> ? { readonly [K in PrimaryKeyColumn<M, T>]: Row<M, T>[K]; } : Row<M, T>[PrimaryKeyColumn<M, T>];
246
249
  type Simplify<T> = { [K in keyof T]: T[K]; } & {};
247
250
  //#endregion
248
- export { SchemaMeta as A, PrimaryKeyValue as C, Relations as D, RelationShape as E, UniqueConstraint as F, UniqueKeyName as I, UniqueWhere as L, TableFlags as M, TableKey as N, Row as O, TableMeta as P, Update as R, PrimaryKeyColumn as S, RelationMeta as T, Insert as _, Casing as a, PermdockBucketPolicy as b, Codec as c, Flags as d, FlagsShape as f, FunctionsOf as g, FunctionShape as h, BucketPolicyName as i, Simplify as j, Schema as k, ColumnMeta as l, FunctionMeta as m, AnyModels as n, CheckConstraint as o, ForeignKeyConstraint as p, BucketMeta as r, ClaimsMeta as s, AnyFunctions as t, DatabaseOf as u, ModelShape as v, RealtimeTableMeta as w, PermdockTopicPolicy as x, ModelsOf as y };
251
+ export { SchemaMeta as A, PrimaryKeyValue as C, Relations as D, RelationTypes as E, UniqueConstraint as F, UniqueKeyName as I, UniqueWhere as L, TableFlags as M, TableKey as N, Row as O, TableMeta as P, Update as R, PrimaryKeyColumn as S, RelationMeta as T, ModelFlags as _, Casing as a, PermdockBucketPolicy as b, Codec as c, Flags as d, ForeignKeyConstraint as f, Insert as g, FunctionsOf as h, BucketPolicyName as i, Simplify as j, Schema as k, ColumnMeta as l, FunctionTypes as m, AnyModels as n, CheckConstraint as o, FunctionMeta as p, BucketMeta as r, ClaimsMeta as s, AnyFunctions as t, DatabaseOf as u, ModelTypes as v, RealtimeTableMeta as w, PermdockTopicPolicy as x, ModelsOf as y };
@@ -0,0 +1,4 @@
1
+ //#region src/core/version.ts
2
+ const VERSION = "0.4.0";
3
+ //#endregion
4
+ export { VERSION as t };