better-supabase 0.4.0 → 0.5.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 (179) hide show
  1. package/README.md +2 -0
  2. package/dist/channel-FQW-CnGR.d.ts +70 -0
  3. package/dist/cli/bin.js +1 -1
  4. package/dist/cli/codemod-DqV7612m.js +388 -0
  5. package/dist/cli/{config-D9R0o1LH.js → config-CPVpXP5I.js} +78 -8
  6. package/dist/cli/{config-SSKSTUl2.js → config-dtoekM0v.js} +1 -1
  7. package/dist/cli/{read-sets-CMa29t9a.js → diff-SjkO5rNr.js} +1 -220
  8. package/dist/cli/{dist-CFgGknmZ.js → dist-DBPdlPYK.js} +4 -4
  9. package/dist/cli/{dist-B1MvLv-M.js → dist-DreZ24Sz.js} +1 -1
  10. package/dist/cli/{dist-Du7VnEUG.js → dist-xn4wlboc.js} +112 -1
  11. package/dist/cli/{doctor-BOym3mbL.js → doctor-L7Z8mYTx.js} +531 -50
  12. package/dist/cli/{env-BZ0uy8XK.js → env-DmKv_G4A.js} +1 -1
  13. package/dist/cli/gen-BJc9vdyu.js +2 -0
  14. package/dist/cli/{gen-Ccn_p90L.js → gen-C2osRcr5.js} +283 -87
  15. package/dist/cli/index.d.ts +1 -1
  16. package/dist/cli/index.js +4 -4
  17. package/dist/cli/{init-ClnxRYBF.js → init-Saf5-R9T.js} +2 -2
  18. package/dist/cli/{introspect-DxqfkVIv.js → introspect--H7oGmcd.js} +2 -2
  19. package/dist/cli/{openapi-8WHjxiTJ.js → openapi-Cp5Fyta-.js} +1 -1
  20. package/dist/cli/read-sets-BfMQcKy8.js +289 -0
  21. package/dist/cli/{run-CP20LKk_.js → run-BKR2W_79.js} +16 -12
  22. package/dist/cli/{seed-5J6eu_Xg.js → seed-CUlqWh-8.js} +1 -1
  23. package/dist/cli/sql-DzPbfngx.js +348 -0
  24. package/dist/cli/{version-5mW_8sY1.js → version-BDJuO0UR.js} +1 -1
  25. package/dist/client/index.d.ts +1 -1
  26. package/dist/client/index.js +3 -10
  27. package/dist/clone-BfgmLU90.js +21 -0
  28. package/dist/{compiler-DB3aSFOA.d.ts → compiler-BXH_aZ7N.d.ts} +2 -2
  29. package/dist/config/index.d.ts +4 -4
  30. package/dist/config/index.js +4 -4
  31. package/dist/{config-CbvFmGD8.js → config-DreERlKo.js} +1 -1
  32. package/dist/{config-C1CYcm6o.d.ts → config-T_ejwyd3.d.ts} +176 -11
  33. package/dist/{define-CRS2MRV3.d.ts → define-Bp_BZa5h.d.ts} +11 -7
  34. package/dist/{define-Bh0AqTik.js → define-cNKzqwL_.js} +202 -16
  35. package/dist/edge/index.d.ts +16 -5
  36. package/dist/edge/index.js +10 -7
  37. package/dist/{entitlements-Dm-FHpNH.d.ts → entitlements-DUxU4oHe.d.ts} +1 -1
  38. package/dist/env/index.d.ts +2 -2
  39. package/dist/env/index.js +34 -1
  40. package/dist/{errors-L0xK41y_.js → errors-DtwXa6b8.js} +1 -0
  41. package/dist/events/index.d.ts +3 -2
  42. package/dist/events/index.js +65 -12
  43. package/dist/events-aIO7vsIk.d.ts +230 -0
  44. package/dist/{result-CqEsbgYs.d.ts → executor-BunPOO-k.d.ts} +200 -1
  45. package/dist/{executor-CZ7ImRiD.d.ts → executor-Cghdstwu.d.ts} +1 -2
  46. package/dist/{executor-CVt6dD0B.js → executor-XycESQPH.js} +3 -3
  47. package/dist/hono/index.d.ts +17 -6
  48. package/dist/hono/index.js +40 -5
  49. package/dist/impersonation-VfaGc4Q_.js +41 -0
  50. package/dist/{index-BBdvo-5d.d.ts → index-BGdgBPdf.d.ts} +49 -6
  51. package/dist/{index-BhHEC04r.d.ts → index-C7f8cOBM.d.ts} +2 -2
  52. package/dist/{index-Dy6kuF0P.d.ts → index-CLg87OBW.d.ts} +6 -1
  53. package/dist/{index-D5IfUIDh.d.ts → index-DOESKG27.d.ts} +33 -8
  54. package/dist/{index-DFmOpBGC.d.ts → index-DgILJRXj.d.ts} +35 -9
  55. package/dist/{index-RlLXd8dL.d.ts → index-DmXSxbLi.d.ts} +4 -4
  56. package/dist/{index-Cf-D2jk1.d.ts → index-Dxn2a5cw.d.ts} +2 -2
  57. package/dist/{index-528Ugmyp.d.ts → index-SaTsEfGP.d.ts} +76 -8
  58. package/dist/{index-BAy4tsAP.d.ts → index-fag8VJZ2.d.ts} +3 -4
  59. package/dist/index.d.ts +30 -13
  60. package/dist/index.js +10 -9
  61. package/dist/jobs/index.d.ts +147 -101
  62. package/dist/jobs/index.js +744 -237
  63. package/dist/{json-schema-DP6V7cbr.js → json-schema-m1fiwKgN.js} +22 -1
  64. package/dist/kit-events-CTFDfSwb.js +60 -0
  65. package/dist/kit-transport-B82k1djG.d.ts +33 -0
  66. package/dist/kit-transport-DJlHQUBU.js +55 -0
  67. package/dist/{config-BpxDfnbg.js → kits-CGLLrNPd.js} +37 -9
  68. package/dist/list/index.d.ts +1 -1
  69. package/dist/{live-BHakSWWo.d.ts → live-D9W2M5aO.d.ts} +6 -5
  70. package/dist/mcp/index.d.ts +25 -8
  71. package/dist/mcp/index.js +23 -14
  72. package/dist/{mfa-C7MNQ1Ob.d.ts → mfa-CusDgPaD.d.ts} +5 -1
  73. package/dist/next/index.d.ts +31 -10
  74. package/dist/next/index.js +136 -27
  75. package/dist/notifications/index.d.ts +162 -0
  76. package/dist/notifications/index.js +264 -0
  77. package/dist/openapi/index.d.ts +1 -1
  78. package/dist/openapi/index.js +2 -2
  79. package/dist/orgs/index.d.ts +132 -0
  80. package/dist/orgs/index.js +245 -0
  81. package/dist/orpc/index.d.ts +28 -8
  82. package/dist/orpc/index.js +16 -3
  83. package/dist/otel/index.d.ts +21 -2
  84. package/dist/otel/index.js +50 -9
  85. package/dist/permdock-sql-C2Inc6Xc.d.ts +29 -0
  86. package/dist/permdock-sql-DgOfeixi.js +51 -0
  87. package/dist/plugin-DwARMuQp.js +59 -0
  88. package/dist/{plugin-bNhvJwRh.d.ts → plugin-o144f322.d.ts} +17 -5
  89. package/dist/plugins/actor/index.d.ts +5 -2
  90. package/dist/plugins/actor/index.js +22 -8
  91. package/dist/plugins/rules/index.d.ts +2 -2
  92. package/dist/plugins/rules/index.js +15 -10
  93. package/dist/plugins/soft-delete/index.d.ts +3 -3
  94. package/dist/plugins/soft-delete/index.js +14 -5
  95. package/dist/plugins/tenant/index.d.ts +2 -2
  96. package/dist/plugins/tenant/index.js +38 -20
  97. package/dist/plugins/timestamps/index.d.ts +1 -1
  98. package/dist/plugins/timestamps/index.js +4 -3
  99. package/dist/plugins/validation/index.d.ts +2 -2
  100. package/dist/plugins/validation/index.js +26 -6
  101. package/dist/{pool-DFwEQwmN.d.ts → pool-C9voM4Kw.d.ts} +17 -6
  102. package/dist/postgres/index.d.ts +5 -5
  103. package/dist/postgres/index.js +20 -11
  104. package/dist/{postgrest-Bc-0Xw62.d.ts → postgrest-CruYKAvV.d.ts} +1 -1
  105. package/dist/{problem-BihjPR0t.js → problem-BW1KhzSG.js} +2 -1
  106. package/dist/{problem-U8UEKccv.d.ts → problem-Blxe8S31.d.ts} +1 -1
  107. package/dist/query/index.d.ts +2 -2
  108. package/dist/query/index.js +3 -3
  109. package/dist/{query-BMMSWbI7.js → query-CCbo44lG.js} +2 -2
  110. package/dist/queue-BYUCjr59.d.ts +252 -0
  111. package/dist/react/index.d.ts +8 -7
  112. package/dist/react/index.js +4 -3
  113. package/dist/react/server.d.ts +14 -3
  114. package/dist/react/server.js +10 -2
  115. package/dist/react/session.d.ts +7 -1
  116. package/dist/react/session.js +9 -1
  117. package/dist/{react-CQHMaESR.js → react-C_s7kiNz.js} +103 -11
  118. package/dist/{read-set-FWK8qQ58.js → read-set-DQFt1N_Y.js} +22 -1
  119. package/dist/realtime/index.d.ts +3 -3
  120. package/dist/realtime/index.js +5 -4
  121. package/dist/{refresh-BwYkyNOQ.d.ts → refresh-BTrQ_ZTp.d.ts} +1 -1
  122. package/dist/{resolve-BAqQcwMW.d.ts → resolve-C15TJq77.d.ts} +11 -5
  123. package/dist/{resource-My_y-Syh.js → resource-CRxxwkQq.js} +22 -7
  124. package/dist/{resource-BJcaIfxi.d.ts → resource-D8iqWMr-.d.ts} +5 -5
  125. package/dist/respond-D2OQl62-.d.ts +371 -0
  126. package/dist/{result-Bj6yt33D.js → result-BKiliPY7.js} +1 -1
  127. package/dist/server/index.d.ts +14 -12
  128. package/dist/server/index.js +11 -17
  129. package/dist/{server-BA75B0mT.js → server-Csx2sRjg.js} +251 -34
  130. package/dist/{shared-DnoCdMDr.js → shared-D1dRUrAg.js} +16 -2
  131. package/dist/signers-Cc6r98SW.d.ts +162 -0
  132. package/dist/{simplify-Cqvfr9dj.js → simplify-_0oUKqCd.js} +4 -115
  133. package/dist/sql/index.d.ts +247 -10
  134. package/dist/sql/index.js +8590 -779
  135. package/dist/{sql-B34HU2DI.js → sql-Coh6n4cC.js} +9 -2
  136. package/dist/ssr/index.d.ts +4 -4
  137. package/dist/ssr/index.js +1 -2
  138. package/dist/{standard-BRyBGTtp.js → standard-D7r6dMUu.js} +6 -3
  139. package/dist/{standard-BsaCYQJc.d.ts → standard-J4YgMOLm.d.ts} +1 -1
  140. package/dist/{stats-C_YxA2r1.js → stats-Bqob3WqT.js} +4 -4
  141. package/dist/storage/index.d.ts +4 -4
  142. package/dist/storage/index.js +155 -26
  143. package/dist/support-DT-OhSxD.d.ts +88 -0
  144. package/dist/support-Dk6vdmEw.js +291 -0
  145. package/dist/support-view-Da5peKFg.d.ts +17 -0
  146. package/dist/support-view-g4YLBeqX.js +18 -0
  147. package/dist/{permdock-sql-C4KFzLc9.js → template-TxrGI5jR.js} +2 -31
  148. package/dist/{temporal-BwshQk0W.js → temporal-CVlIV2DZ.js} +17 -4
  149. package/dist/{temporal-required-CBNHT6ni.js → temporal-required-CAt4Dc9Z.js} +2 -2
  150. package/dist/testing/index.d.ts +100 -10
  151. package/dist/testing/index.js +336 -8
  152. package/dist/{types-DONv9SHN.d.ts → types-Dnf_wRDz.d.ts} +26 -3
  153. package/dist/user-change-CHFEUro1.js +49 -0
  154. package/dist/{webhooks-Bh_Jf_-l.js → verify-Ce49ETPz.js} +5 -5
  155. package/dist/{version-Bmf7_FzM.js → version-DM_Roffb.js} +1 -1
  156. package/dist/{view-B64o81wp.d.ts → view-BEf0diC5.d.ts} +8 -3
  157. package/dist/{mfa-byfjruR9.js → view-Bq64ki8-.js} +95 -38
  158. package/dist/webhooks/index.d.ts +135 -4
  159. package/dist/webhooks/index.js +588 -2
  160. package/dist/wire-D2dT86vi.js +35 -0
  161. package/package.json +16 -8
  162. package/schemas/config-v1.json +131 -1
  163. package/schemas/doctor-report-v1.json +10 -0
  164. package/skills/better-supabase/SKILL.md +9 -6
  165. package/skills/better-supabase/references/plugins.md +6 -3
  166. package/skills/better-supabase/references/troubleshooting.md +1 -0
  167. package/skills/better-supabase-api/SKILL.md +9 -2
  168. package/skills/better-supabase-api/references/adapters.md +11 -8
  169. package/skills/better-supabase-auth/SKILL.md +3 -0
  170. package/skills/better-supabase-auth/references/permdock.md +56 -11
  171. package/dist/cli/gen-D5cLCULx.js +0 -2
  172. package/dist/cli/sql-D4VbqmXi.js +0 -199
  173. package/dist/events-B21UOhvP.d.ts +0 -84
  174. package/dist/executor-B5IoUxLE.d.ts +0 -195
  175. package/dist/invalidate-CgxmRamI.js +0 -24
  176. package/dist/permdock-sql-DImJULY-.d.ts +0 -17
  177. package/dist/plugin-BqR6wKMB.js +0 -23
  178. package/dist/respond-DgIbdrt8.d.ts +0 -194
  179. package/dist/view-BrJI2LKp.js +0 -45
@@ -1,6 +1,150 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { A as SchemaMeta, a as Casing, b as PermdockBucketPolicy, i as BucketPolicyName } from "./types-DONv9SHN.js";
2
+ import { a as BucketPolicyName, j as SchemaMeta, o as Casing, t as AccessBucketPolicy, x as PermdockBucketPolicy } from "./types-Dnf_wRDz.js";
3
3
  import { GeneratorMetadata } from "@supabase/postgrest-typegen";
4
+ //#region src/config/kits.d.ts
5
+ /**
6
+ * `kits` in `better-supabase.config.ts`: how each SQL kit module maps onto
7
+ * the app's database. A module's contract (the functions other modules and
8
+ * the TypeScript side call) stays the same in every mode; only the tables
9
+ * behind it change.
10
+ */
11
+ /**
12
+ * `managed`: the kit owns its tables. `adopt`: the kit writes its functions
13
+ * and views over tables the app already has (`tables` and `columns`), never
14
+ * `create table`. `custom`: the app implements the contract functions itself;
15
+ * the kit writes nothing and doctor checks the signatures (BS307).
16
+ */
17
+ type KitMode = "managed" | "adopt" | "custom";
18
+ /** Options every module takes. */
19
+ interface KitModuleConfig {
20
+ readonly mode?: KitMode;
21
+ /** Schema of the module's functions and managed tables. Defaults to `better_supabase`. */
22
+ readonly schema?: string;
23
+ /**
24
+ * Logical table to `table` or `schema.table`, e.g.
25
+ * `{ memberships: 'public.organization_users' }`. An unqualified name is in
26
+ * `schema`. `null` marks an optional table the app doesn't have.
27
+ */
28
+ readonly tables?: Readonly<Record<string, string | null>>;
29
+ /**
30
+ * Logical table to logical column to column name, e.g.
31
+ * `{ memberships: { tenant: 'organization_id', role: 'role_id' } }`.
32
+ * `null` marks an optional column the adopted table doesn't have.
33
+ */
34
+ readonly columns?: Readonly<Record<string, Readonly<Record<string, string | null>>>>;
35
+ /** Type of tenant ids: `uuid` (default), `text`, `bigint` or `integer`. */
36
+ readonly idType?: string;
37
+ /**
38
+ * Kit action to permission key, checked through the access contract, e.g.
39
+ * `{ invite: 'organization.members.invite' }`.
40
+ */
41
+ readonly permissions?: Readonly<Record<string, string>>;
42
+ /** Module-specific options; each module's docs page lists them. */
43
+ readonly options?: Readonly<Record<string, unknown>>;
44
+ /**
45
+ * The app's optional `before_*` and `after_*` functions the module calls
46
+ * when they exist, e.g. `after_organization_create(org, user)`. They are
47
+ * looked up in `schema` (default `public`); `functions` maps a hook name
48
+ * to another function, e.g. `{ after_organization_create: 'app.seed_org' }`.
49
+ */
50
+ readonly hooks?: {
51
+ readonly schema?: string;
52
+ readonly functions?: Readonly<Record<string, string>>;
53
+ };
54
+ /**
55
+ * Whether the module writes its events to the outbox (`emit_event`) when
56
+ * the `outbox` module is installed. Defaults to true.
57
+ */
58
+ readonly events?: boolean;
59
+ }
60
+ /**
61
+ * Where the active tenant of a request comes from. Every source counts only
62
+ * while the caller is a member, so a stale claim or setting grants nothing.
63
+ */
64
+ type ActiveTenantSource = "claim" | "resolver" | {
65
+ readonly profileColumn: string;
66
+ readonly key?: string;
67
+ };
68
+ /** URL tenancy: the tenant comes from the request (a slug), not a stored setting. */
69
+ declare const DEFAULT_ACTIVE_TENANT: ActiveTenantSource;
70
+ /**
71
+ * The access contract every kit checks permissions through:
72
+ * `can(scope, id, permission)`, `tenant_ids_with(permission)`,
73
+ * `is_platform(permission)` and `can_user(user, scope, id, permission)`.
74
+ */
75
+ interface AccessKitConfig extends KitModuleConfig {
76
+ /**
77
+ * `roles`: a fixed role list from `roles` (the default). `catalog`: role,
78
+ * permission and override tables (`tables.roles`, `permissions`,
79
+ * `rolePermissions`, `overrides`, `platformAssignments`). `permdock`:
80
+ * PermDock's `permitted_<scope>_ids` and `permdock_has`. `custom`:
81
+ * expression templates in `functions`.
82
+ */
83
+ readonly model?: "roles" | "catalog" | "permdock" | "custom";
84
+ /**
85
+ * `roles` model: role name to permission keys. `*` grants everything and
86
+ * `prefix.*` a prefix. Defaults to owner, admin, member and viewer.
87
+ */
88
+ readonly roles?: Readonly<Record<string, readonly string[]>>;
89
+ /**
90
+ * `custom` model: SQL expressions with `{scope}`, `{id}`, `{permission}`
91
+ * and `{user}` placeholders, e.g.
92
+ * `{ can: 'public.authorize_scope({scope}::public.scope_type, {id}, {permission})' }`.
93
+ */
94
+ readonly functions?: {
95
+ readonly can?: string;
96
+ readonly tenantIdsWith?: string;
97
+ readonly isPlatform?: string;
98
+ readonly canUser?: string;
99
+ /** `{tenant}` and `{role}`: whether the caller may assign the role. Defaults to true. */
100
+ readonly canAssign?: string;
101
+ /** `{user}`: the permission claim for the access token hook. */
102
+ readonly permissionClaims?: string;
103
+ };
104
+ /**
105
+ * `roles` model: the JWT claim holding the caller's platform permission
106
+ * keys (an array). Defaults to `platform_permissions`.
107
+ */
108
+ readonly platformClaim?: string;
109
+ /**
110
+ * Columns that disable a tenant or a user when set, as
111
+ * `schema.table.column`, keyed by the table's `id` (tenant) or the column
112
+ * named in `userKey` (user). Disabled tenants and users get no permissions.
113
+ */
114
+ readonly disabled?: {
115
+ readonly tenant?: string;
116
+ readonly user?: string;
117
+ readonly userKey?: string;
118
+ };
119
+ readonly activeTenant?: ActiveTenantSource;
120
+ /** `permdock` model: PermDock's `rls.schema` and the scope tenants are. */
121
+ readonly permdock?: {
122
+ readonly schema?: string;
123
+ readonly scope?: string;
124
+ };
125
+ }
126
+ /** `kits` in the config, keyed by module name. */
127
+ interface KitsConfig {
128
+ readonly access?: AccessKitConfig;
129
+ /** `AccessKitConfig` is listed so an `access` literal passes the excess-property check. */
130
+ readonly [module: string]: KitModuleConfig | AccessKitConfig | undefined;
131
+ }
132
+ /** A module's config with defaults applied. */
133
+ interface ResolvedKitModule {
134
+ readonly mode: KitMode;
135
+ readonly schema: string;
136
+ readonly tables: Readonly<Record<string, string | null>>;
137
+ readonly columns: Readonly<Record<string, Readonly<Record<string, string | null>>>>;
138
+ readonly idType?: string;
139
+ readonly permissions: Readonly<Record<string, string>>;
140
+ readonly options: Readonly<Record<string, unknown>>;
141
+ readonly hooks: {
142
+ readonly schema: string;
143
+ readonly functions: Readonly<Record<string, string>>;
144
+ };
145
+ readonly events: boolean;
146
+ }
147
+ //#endregion
4
148
  //#region src/config/snapshot.d.ts
5
149
  /**
6
150
  * What `better-supabase introspect` reads from Postgres. `generator` is the
@@ -330,6 +474,8 @@ interface ClaimsConfig {
330
474
  interface ActorConfig {
331
475
  readonly createdBy?: string;
332
476
  readonly updatedBy?: string;
477
+ /** Defaults to `impersonated_by`, the column the SQL kit's `track_actor` fills. */
478
+ readonly impersonatedBy?: string;
333
479
  }
334
480
  interface PluginFlagsConfig {
335
481
  readonly timestamps?: boolean | TimestampsConfig;
@@ -342,8 +488,11 @@ interface BucketConfig {
342
488
  readonly public?: boolean;
343
489
  /** Path template with `{placeholders}`, e.g. `{orgId}/{customerId}/logo.webp`. */
344
490
  readonly path: string;
345
- /** Generated storage policy, or a PermDock policy (`{ permdock, scope }`). */
346
- readonly policy?: BucketPolicyName | PermdockBucketPolicy;
491
+ /**
492
+ * Generated storage policy, a PermDock policy (`{ permdock, scope }`) or
493
+ * an access contract policy (`{ access }`).
494
+ */
495
+ readonly policy?: BucketPolicyName | PermdockBucketPolicy | AccessBucketPolicy;
347
496
  readonly fileSizeLimit?: string;
348
497
  readonly allowedMimeTypes?: readonly string[];
349
498
  }
@@ -443,12 +592,19 @@ interface RealtimeConfig {
443
592
  * triggers with `better-supabase sql add realtime-tables`.
444
593
  */
445
594
  readonly tables?: readonly string[];
595
+ /**
596
+ * Tables in `tables` without a tenant column. They broadcast on one topic
597
+ * every signed-in user receives. With the `tenant` plugin, a table that
598
+ * lacks the tenant column and is not listed here fails to install.
599
+ */
600
+ readonly global?: readonly string[];
446
601
  }
447
602
  interface EntitlementsConfig {
448
603
  /**
449
604
  * `table.column` (or `schema.table.column`) holding each tenant's Stripe
450
- * customer id, read by the `entitlements` SQL kit module. Defaults to
451
- * `organizations.stripe_customer_id`.
605
+ * customer id, read by the `entitlements` SQL kit module. Required
606
+ * without the `organizations` module; with it, defaults to the
607
+ * `stripe_customer_id` column that module adds.
452
608
  */
453
609
  readonly customer?: string;
454
610
  /** The tenant id column of that table. Defaults to `id`. */
@@ -457,8 +613,9 @@ interface EntitlementsConfig {
457
613
  * With a PermDock manifest, `has_entitlement` and `feature_claims` read
458
614
  * PermDock's memberships (`member_<scope>_ids()` and
459
615
  * `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.
616
+ * `scope` is the PermDock scope tenants are. It defaults to the manifest's
617
+ * root scope (the `rls.scopes` entry without `within`); `false` keeps the
618
+ * kit's memberships table.
462
619
  */
463
620
  readonly permdock?: false | {
464
621
  readonly scope?: string;
@@ -558,6 +715,12 @@ interface BetterSupabaseConfig {
558
715
  */
559
716
  readonly vectorSearch?: Readonly<Record<string, VectorSearchConfig>>;
560
717
  readonly sql?: SqlConfig;
718
+ /**
719
+ * How each SQL kit module maps onto the database: `managed` tables, or
720
+ * `adopt` and `custom` over the app's own, with table, column and
721
+ * permission names, keyed by module name.
722
+ */
723
+ readonly kits?: KitsConfig;
561
724
  readonly seed?: SeedConfig;
562
725
  readonly openapi?: OpenApiConfig;
563
726
  readonly doctor?: DoctorConfig;
@@ -589,11 +752,12 @@ interface ResolvedConfig {
589
752
  readonly claims: Required<ClaimsConfig>;
590
753
  readonly buckets: Readonly<Record<string, BucketConfig>>;
591
754
  readonly entitlements: {
592
- readonly table: string;
593
- readonly column: string;
755
+ /** Unset without `entitlements.customer`. */
756
+ readonly table?: string;
757
+ readonly column?: string;
594
758
  readonly key: string;
595
759
  readonly permdock: false | {
596
- readonly scope: string;
760
+ readonly scope?: string;
597
761
  };
598
762
  };
599
763
  readonly permdock: Required<PermdockPathsConfig>;
@@ -605,6 +769,7 @@ interface ResolvedConfig {
605
769
  readonly topics: Readonly<Record<string, string>>;
606
770
  readonly realtime: Required<RealtimeConfig>;
607
771
  readonly sql: Required<SqlConfig>;
772
+ readonly kits: KitsConfig;
608
773
  readonly seed: Required<SeedConfig>;
609
774
  readonly openapi: Required<OpenApiConfig>;
610
775
  readonly doctor: Required<Omit<DoctorConfig, "claimsLimit">> & Pick<DoctorConfig, "claimsLimit">;
@@ -615,4 +780,4 @@ declare function defineConfig(config: BetterSupabaseConfig): BetterSupabaseConfi
615
780
  /** Applies defaults. Paths stay relative to `root`. */
616
781
  declare function resolveConfig(config: BetterSupabaseConfig, root: string): ResolvedConfig;
617
782
  //#endregion
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 };
783
+ 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, DEFAULT_ACTIVE_TENANT as at, ResolvedConfig as b, EntitlementsConfig as c, KitsConfig as ct, Generator as d, Snapshot as et, GeneratorInput as f, PermdockPathsConfig as g, OpenApiConfig as h, CONFIG_SCHEMA_URL as i, ActiveTenantSource as it, defineConfig as j, VectorDistance as k, ExposeConfig as l, ResolvedKitModule as lt, JsonTypeConfig as m, BetterSupabaseConfig as n, SnapshotExtras as nt, CodecsConfig as o, KitMode as ot, JsonSchemaSource as p, CatalogUnique as q, BucketConfig as r, AccessKitConfig as rt, DoctorConfig as s, KitModuleConfig as st, ActorConfig as t, SnapshotBucket as tt, GeneratedFile as u, Privilege as v, SourceConfig as w, ResolvedExpose as x, RealtimeConfig as y, CatalogForeignKey as z };
@@ -1,11 +1,10 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { A as SchemaMeta, C as PrimaryKeyValue, D as Relations, E as RelationTypes, I as UniqueKeyName, L as UniqueWhere, N as TableKey, O as Row, P as TableMeta, R as Update, g as Insert, j as Simplify, k as Schema, n as AnyModels, t as AnyFunctions } from "./types-DONv9SHN.js";
3
- import { g as Operation, l as CountMode, r as Executor } from "./executor-B5IoUxLE.js";
4
- import { p as DbError, s as ThrowMapper, t as AsyncResult, v as ErrorMapper } from "./result-CqEsbgYs.js";
5
- import { a as EventHub, f as Logger, i as EventHandler, o as EventName, s as MutationNotice, u as RpcNotice } from "./events-B21UOhvP.js";
6
- import { a as ExtensionOf, g as WithExtension, h as RequestContext, n as AnyPlugin, r as ApplyExtension } from "./plugin-bNhvJwRh.js";
7
- import { t as StandardSchemaV1 } from "./standard-BsaCYQJc.js";
8
- import { i as PostgrestPlan } from "./postgrest-Bc-0Xw62.js";
2
+ import { A as Schema, D as RelationTypes, F as TableMeta, L as UniqueKeyName, M as Simplify, O as Relations, P as TableKey, R as UniqueWhere, _ as Insert, j as SchemaMeta, k as Row, n as AnyFunctions, r as AnyModels, w as PrimaryKeyValue, z as Update } from "./types-Dnf_wRDz.js";
3
+ import { I as CountMode, S as ErrorMapper, U as Operation, _ as DbError, a as AsyncResult, d as ThrowMapper, r as Executor } from "./executor-BunPOO-k.js";
4
+ import { E as Logger, a as EventHub, i as EventHandler, o as EventName, s as MutationNotice, u as RpcNotice } from "./events-aIO7vsIk.js";
5
+ import { _ as WithExtension, a as ExtensionOf, g as RequestContext, n as AnyPlugin, r as ApplyExtension } from "./plugin-o144f322.js";
6
+ import { t as StandardSchemaV1 } from "./standard-J4YgMOLm.js";
7
+ import { i as PostgrestPlan } from "./postgrest-CruYKAvV.js";
9
8
  //#region src/ir/args.d.ts
10
9
  interface BaseOps<V> {
11
10
  readonly eq?: V;
@@ -337,6 +336,11 @@ type DeleteExt<E, M extends AnyModels, T extends keyof M> = ApplyExtension<E, M,
337
336
  interface WriteArgs<M extends AnyModels, T extends keyof M> extends ReadArgs<M, T> {
338
337
  /** `false` skips `RETURNING` (needed when RLS hides the written row). */
339
338
  readonly returning?: boolean;
339
+ /**
340
+ * Keep caller-supplied values for columns that `timestamps()`, `actor()`
341
+ * and `softDelete()` fill (imports, backfills). Without it they are refused.
342
+ */
343
+ readonly override?: boolean;
340
344
  }
341
345
  interface UpdateArgs<M extends AnyModels, T extends keyof M> extends WriteArgs<M, T> {
342
346
  /**
@@ -1,16 +1,18 @@
1
- import { n as dbError, t as DbException } from "./errors-L0xK41y_.js";
2
- import { a as invalidRequest, c as needsDecoding, o as decodeRows, r as builderFor, s as encodeValue } from "./simplify-Cqvfr9dj.js";
1
+ import { t as cloneValue } from "./clone-BfgmLU90.js";
2
+ import { n as dbError, t as DbException } from "./errors-DtwXa6b8.js";
3
+ import { a as invalidRequest, r as builderFor } from "./simplify-_0oUKqCd.js";
3
4
  import { t as lookupOf } from "./lookup-BaP5bI27.js";
4
- import { n as nowInstant } from "./temporal-BwshQk0W.js";
5
5
  import { i as or, n as column, r as not, t as and } from "./types-6cYK9pbJ.js";
6
- import { i as ok, n as err, o as toDbError, s as withErrorMapper, t as AsyncResult } from "./result-Bj6yt33D.js";
6
+ import { n as nowInstant } from "./temporal-CVlIV2DZ.js";
7
+ import { n as decodeValue, r as encodeValue, t as decodeScalar } from "./wire-D2dT86vi.js";
8
+ import { i as ok, n as err, o as toDbError, s as withErrorMapper, t as AsyncResult } from "./result-BKiliPY7.js";
7
9
  import { t as invalidationTargets } from "./tables-Cb-3_VWc.js";
8
10
  import { t as consoleLogger } from "./logger-glM28NVN.js";
9
- import { r as orderPlugins } from "./plugin-BqR6wKMB.js";
10
- import { a as postgrestExecutor, n as StatsRecorder, r as recordStats } from "./stats-C_YxA2r1.js";
11
- import { d as isQuerySpec, f as specTables, n as checkParams, o as isReadSet, r as containsPlaceholder, t as bindParams, u as createSpecs } from "./read-set-FWK8qQ58.js";
11
+ import { i as orderPlugins, s as tenantOf } from "./plugin-DwARMuQp.js";
12
+ import { a as postgrestExecutor, n as StatsRecorder, r as recordStats } from "./stats-Bqob3WqT.js";
13
+ import { d as isQuerySpec, f as specTables, n as checkParams, o as isReadSet, r as containsPlaceholder, t as bindParams, u as createSpecs } from "./read-set-DQFt1N_Y.js";
12
14
  import { a as toBase64Url, t as base64ToText } from "./base64-D2gsioCY.js";
13
- import { t as validate } from "./standard-BRyBGTtp.js";
15
+ import { t as validate } from "./standard-D7r6dMUu.js";
14
16
  //#region src/core/batch.ts
15
17
  /**
16
18
  * Holds operations until each of `readers` has either submitted one or
@@ -61,8 +63,9 @@ function rowKey(table, row) {
61
63
  }
62
64
  function cacheTargetOf(meta, notice) {
63
65
  const table = meta.tables[notice.table];
64
- const ids = table ? [...new Set(notice.rows.flatMap((row) => rowKey(table, row) ?? []))] : [];
65
- const tenant = notice.context.tenant;
66
+ const rows = notice.rows.length > 0 ? notice.rows : notice.keys ?? [];
67
+ const ids = table ? [...new Set(rows.flatMap((row) => rowKey(table, row) ?? []))] : [];
68
+ const tenant = notice.tenant ?? notice.context.tenant;
66
69
  return {
67
70
  table: notice.table,
68
71
  tables: notice.kind === "delete" ? invalidationTargets(meta, notice.table) : [notice.table],
@@ -108,6 +111,7 @@ function isDevelopment() {
108
111
  var EventHub = class {
109
112
  #handlers = /* @__PURE__ */ new Map();
110
113
  #warned = /* @__PURE__ */ new Set();
114
+ #pending = /* @__PURE__ */ new Set();
111
115
  logger;
112
116
  constructor(logger = consoleLogger) {
113
117
  this.logger = logger;
@@ -130,6 +134,24 @@ var EventHub = class {
130
134
  has(name) {
131
135
  return (this.#handlers.get(name)?.size ?? 0) > 0;
132
136
  }
137
+ /**
138
+ * Keeps async work a handler started (a sink send) until it settles, so
139
+ * adapters can hand it to `after()` or `waitUntil`. Its outcome is ignored:
140
+ * handlers report their own failures.
141
+ */
142
+ track(work) {
143
+ const settled = Promise.resolve(work).then(() => void 0, () => void 0);
144
+ this.#pending.add(settled);
145
+ settled.then(() => this.#pending.delete(settled));
146
+ }
147
+ /** Whether tracked work is still running. */
148
+ get pending() {
149
+ return this.#pending.size > 0;
150
+ }
151
+ /** Resolves once the work tracked so far has settled. Never rejects. */
152
+ async settled() {
153
+ await Promise.all(this.#pending);
154
+ }
133
155
  emit(name, event) {
134
156
  const set = this.#handlers.get(name);
135
157
  if (!set) return;
@@ -141,6 +163,99 @@ var EventHub = class {
141
163
  }
142
164
  };
143
165
  //#endregion
166
+ //#region src/ir/codec.ts
167
+ /** Whether decoding `selection` changes anything, so plain reads skip the walk. */
168
+ function needsDecoding(selection) {
169
+ let needs = decodes.get(selection);
170
+ if (needs === void 0) {
171
+ needs = computeNeedsDecoding(selection);
172
+ decodes.set(selection, needs);
173
+ }
174
+ return needs;
175
+ }
176
+ const decodes = /* @__PURE__ */ new WeakMap();
177
+ function computeNeedsDecoding(selection) {
178
+ return selection.aggregate !== void 0 || selection.columns.some((column) => column.codec !== void 0) || selection.includes.some((include) => include.count !== void 0 || include.aggregate !== void 0 || needsDecoding(include.selection));
179
+ }
180
+ /** PostgREST returns `[{ count }]` for a `(count)` embed; SQL returns the number. */
181
+ function countOf(value) {
182
+ if (Array.isArray(value)) {
183
+ const first = value[0];
184
+ return Number(first?.count ?? 0);
185
+ }
186
+ return Number(value ?? 0);
187
+ }
188
+ function measureOf(measure, value) {
189
+ if (value === void 0 || value === null) return null;
190
+ return measure.codec ? decodeScalar(measure.codec, value) : value;
191
+ }
192
+ /** Adds `value` under `row[key][name]`, next to what is already there. */
193
+ function fold(row, folded, key, name, value) {
194
+ let target = folded.get(key);
195
+ if (!target) {
196
+ target = { ...row[key] };
197
+ folded.set(key, target);
198
+ row[key] = target;
199
+ }
200
+ target[name] = value;
201
+ }
202
+ const droppedKeys = /* @__PURE__ */ new WeakMap();
203
+ /** Wire keys that decoding folds into `_count`, `_sum` and the rest. */
204
+ function droppedOf(selection) {
205
+ let dropped = droppedKeys.get(selection);
206
+ if (!dropped) {
207
+ dropped = /* @__PURE__ */ new Set([...selection.aggregate?.measures.map((measure) => measure.key) ?? [], ...selection.includes.filter((include) => include.count !== void 0 || include.aggregate !== void 0).map((include) => include.alias)]);
208
+ droppedKeys.set(selection, dropped);
209
+ }
210
+ return dropped;
211
+ }
212
+ function decodeRow(selection, row) {
213
+ const dropped = droppedOf(selection);
214
+ const out = {};
215
+ for (const key in row) if (!dropped.has(key) && Object.hasOwn(row, key)) out[key] = row[key];
216
+ const folded = /* @__PURE__ */ new Map();
217
+ for (const column of selection.columns) {
218
+ if (!column.codec || !(column.alias in out)) continue;
219
+ try {
220
+ out[column.alias] = decodeValue(column.codec, out[column.alias]);
221
+ } catch (cause) {
222
+ if (!(cause instanceof DbException) || cause.error.kind !== "invalid_value") throw cause;
223
+ throw new DbException(dbError("invalid_value", `${column.alias}: ${cause.error.message}`, { column: column.alias }));
224
+ }
225
+ }
226
+ if (selection.aggregate) {
227
+ if (selection.aggregate.count) out["_count"] = countOf(out["_count"]);
228
+ for (const measure of selection.aggregate.measures) {
229
+ const value = row[measure.key];
230
+ fold(out, folded, `_${measure.fn}`, measure.alias, measureOf(measure, value));
231
+ }
232
+ }
233
+ for (const include of selection.includes) {
234
+ const value = row[include.alias];
235
+ if (include.count !== void 0) {
236
+ if (!(include.alias in row)) continue;
237
+ fold(out, folded, "_count", include.count, countOf(value));
238
+ continue;
239
+ }
240
+ if (include.aggregate !== void 0) {
241
+ if (!(include.alias in row)) continue;
242
+ const inner = Array.isArray(value) ? value[0] : value;
243
+ const measures = {};
244
+ for (const measure of include.selection.aggregate?.measures ?? []) measures[measure.alias] = measureOf(measure, inner?.[measure.key]);
245
+ fold(out, folded, `_${include.aggregate.fn}`, include.aggregate.name, measures);
246
+ continue;
247
+ }
248
+ if (Array.isArray(value)) out[include.alias] = value.map((item) => decodeRow(include.selection, item));
249
+ else if (value && typeof value === "object") out[include.alias] = decodeRow(include.selection, value);
250
+ }
251
+ return out;
252
+ }
253
+ /** Applies column codecs to returned rows, including embedded relations. */
254
+ function decodeRows(selection, rows, checked = false) {
255
+ if (!selection || !checked && !needsDecoding(selection)) return rows;
256
+ return rows.map((row) => decodeRow(selection, row));
257
+ }
258
+ //#endregion
144
259
  //#region src/core/cursor.ts
145
260
  /** Opaque, URL-safe keyset cursor. */
146
261
  function encodeCursor(values) {
@@ -208,6 +323,42 @@ function signalOf(args) {
208
323
  const signal = args?.["signal"];
209
324
  return signal instanceof AbortSignal ? signal : void 0;
210
325
  }
326
+ function cloneRows(rows) {
327
+ return rows.map((row) => cloneValue(row));
328
+ }
329
+ /** App-cased primary keys of `rows`, or of a `where` that pins the primary key. */
330
+ function keysOf(op, rows) {
331
+ const { primaryKey } = op.table;
332
+ if (primaryKey.length === 0) return void 0;
333
+ const fromRows = rows.flatMap((row) => primaryKey.every((name) => row[name] !== void 0 && row[name] !== null) ? [Object.fromEntries(primaryKey.map((name) => [name, row[name]]))] : []);
334
+ if (fromRows.length > 0) return fromRows;
335
+ if (op.kind === "insert") return void 0;
336
+ return keysFromWhere(op.table, op.where);
337
+ }
338
+ function keysFromWhere(table, where) {
339
+ if (!where) return void 0;
340
+ const { byDb } = lookupOf(table);
341
+ const pinned = /* @__PURE__ */ new Map();
342
+ const items = [];
343
+ const flatten = (condition) => {
344
+ if (condition.kind === "and") condition.items.forEach(flatten);
345
+ else items.push(condition);
346
+ };
347
+ flatten(where);
348
+ for (const item of items) {
349
+ if (item.kind !== "column") continue;
350
+ const app = byDb.get(item.column)?.[0];
351
+ if (app === void 0 || !table.primaryKey.includes(app)) continue;
352
+ if (item.op === "eq") pinned.set(app, [item.value]);
353
+ else if (item.op === "in" && Array.isArray(item.value)) pinned.set(app, item.value);
354
+ }
355
+ if (pinned.size !== table.primaryKey.length) return void 0;
356
+ const [first, ...rest] = table.primaryKey;
357
+ if (first === void 0) return void 0;
358
+ if (rest.length === 0) return (pinned.get(first) ?? []).map((value) => ({ [first]: value }));
359
+ if ([...pinned.values()].some((values) => values.length !== 1)) return void 0;
360
+ return [Object.fromEntries(table.primaryKey.map((name) => [name, pinned.get(name)?.[0]]))];
361
+ }
211
362
  function mutationKind(op) {
212
363
  if (op.kind === "insert") return op.onConflict ? "upsert" : "insert";
213
364
  return op.kind;
@@ -286,18 +437,25 @@ var OperationRunner = class {
286
437
  truncated
287
438
  });
288
439
  if (!result.ok) return this.fail(op.table, result.error);
289
- if (current.kind !== "select") await this.afterMutation(current, result.data);
440
+ if (current.kind !== "select") await this.afterMutation(op, current, result.data);
290
441
  return result;
291
442
  }
292
- async afterMutation(op, data) {
443
+ async afterMutation(requested, op, data) {
293
444
  const { runtime } = this;
294
445
  const plugins = this.#hooks.afterMutation;
295
446
  const listening = runtime.events.has("mutation");
296
447
  if (plugins.length === 0 && !listening) return;
448
+ const kind = mutationKind(op);
449
+ const rows = cloneRows(data.rows);
450
+ const keys = keysOf(op, rows);
451
+ const tenant = tenantOf(runtime.context);
297
452
  const event = {
298
453
  table: op.table,
299
- kind: mutationKind(op),
300
- rows: data.rows,
454
+ kind,
455
+ intent: requested.kind === "delete" && op.kind === "update" ? "softDelete" : kind,
456
+ rows,
457
+ ...keys ? { keys } : {},
458
+ ...tenant === void 0 ? {} : { tenant },
301
459
  context: runtime.context
302
460
  };
303
461
  for (const plugin of plugins) try {
@@ -309,7 +467,10 @@ var OperationRunner = class {
309
467
  if (listening) runtime.events.emit("mutation", {
310
468
  table: op.table.key,
311
469
  kind: event.kind,
470
+ ...event.intent ? { intent: event.intent } : {},
312
471
  rows: event.rows,
472
+ ...event.keys ? { keys: event.keys } : {},
473
+ ...event.tenant === void 0 ? {} : { tenant: event.tenant },
313
474
  context: event.context
314
475
  });
315
476
  }
@@ -325,9 +486,20 @@ var OperationRunner = class {
325
486
  return err(withTable);
326
487
  }
327
488
  };
489
+ const sensitiveByTable = /* @__PURE__ */ new WeakMap();
490
+ /** Database names of the table's `config.sensitive` columns. */
491
+ function sensitiveColumnsOf(table) {
492
+ let sensitive = sensitiveByTable.get(table);
493
+ if (!sensitive) {
494
+ sensitive = new Set(lookupOf(table).entries.filter(([, column]) => column.sensitive).map(([, column]) => column.db));
495
+ sensitiveByTable.set(table, sensitive);
496
+ }
497
+ return sensitive;
498
+ }
328
499
  /** Creates the runtime repository object for one table. */
329
500
  function createRepository(runner, table) {
330
501
  const { builder } = runner.runtime;
502
+ const sensitiveDb = sensitiveColumnsOf(table);
331
503
  const selection = (args) => builder.selection(table, args?.["select"], args?.["include"]);
332
504
  const selectOp = (args, patch = {}) => ({
333
505
  kind: "select",
@@ -342,7 +514,17 @@ function createRepository(runner, table) {
342
514
  single: void 0,
343
515
  ...patch
344
516
  });
345
- const returning = (args) => args?.["returning"] === false ? void 0 : selection(args);
517
+ /** Writes return every column but the sensitive ones unless they are asked for. */
518
+ const returning = (args) => {
519
+ if (args?.["returning"] === false) return void 0;
520
+ const all = selection(args);
521
+ if (args?.["select"] !== void 0 || args?.["sensitive"] === true) return all;
522
+ const columns = all.columns.filter((entry) => !sensitiveDb.has(entry.column));
523
+ return columns.length === all.columns.length ? all : {
524
+ ...all,
525
+ columns
526
+ };
527
+ };
346
528
  const run = (op, args) => runner.run(op, optionsOf(args), signalOf(args));
347
529
  let primaryOrder;
348
530
  /** `primaryKey` holds app names; order terms take database names. */
@@ -579,8 +761,11 @@ function createRepository(runner, table) {
579
761
  const number = args["page"] === void 0 ? 1 : Number(args["page"]);
580
762
  if (!Number.isInteger(number) || number < 1) return runner.fail(table, dbError("invalid_request", "\"page\" must be a positive integer"));
581
763
  const count = args["count"];
764
+ const orderBy = builder.orderBy(table, args["orderBy"]);
582
765
  const op = selectOp(args, {
766
+ orderBy: orderBy.length > 0 || table.primaryKey.length === 0 ? orderBy : defaultOrder(),
583
767
  limit: size + 1,
768
+ lookAhead: true,
584
769
  offset: (number - 1) * size,
585
770
  count: count === "exact" || count === "planned" || count === "estimated" ? count : void 0
586
771
  });
@@ -616,6 +801,7 @@ function createRepository(runner, table) {
616
801
  where: and(builder.where(table, args["where"]), after),
617
802
  orderBy,
618
803
  limit: size + 1,
804
+ lookAhead: true,
619
805
  offset: void 0
620
806
  });
621
807
  const result = await run(op, args);
@@ -1169,4 +1355,4 @@ function defineSupabase(schema, options) {
1169
1355
  return new BetterSupabase(schema, [], options);
1170
1356
  }
1171
1357
  //#endregion
1172
- export { EventHub as a, rowKey as c, encodeCursor as i, rpcCacheTargets as l, defineSupabase as n, cacheTargetOf as o, decodeCursor as r, memoryCache as s, BetterSupabase as t };
1358
+ export { decodeRows as a, memoryCache as c, encodeCursor as i, rowKey as l, defineSupabase as n, EventHub as o, decodeCursor as r, cacheTargetOf as s, BetterSupabase as t, rpcCacheTargets as u };
@@ -1,7 +1,7 @@
1
- import { N as TableKey, n as AnyModels, t as AnyFunctions } from "../types-DONv9SHN.js";
2
- import { t as BetterSupabase } from "../define-CRS2MRV3.js";
3
- import { f as ServerContext, n as GuardOptions, p as ServerOptions, r as MiddlewareOptions, u as BetterServer } from "../respond-DgIbdrt8.js";
4
- import { a as ResourceRouteOptions } from "../resource-BJcaIfxi.js";
1
+ import { P as TableKey, n as AnyFunctions, r as AnyModels } from "../types-Dnf_wRDz.js";
2
+ import { t as BetterSupabase } from "../define-Bp_BZa5h.js";
3
+ import { f as ServerContext, n as GuardOptions, p as ServerOptions, r as MiddlewareOptions, u as BetterServer } from "../respond-D2OQl62-.js";
4
+ import { a as ResourceRouteOptions } from "../resource-D8iqWMr-.js";
5
5
  //#region src/edge/index.d.ts
6
6
  export interface CorsOptions {
7
7
  /** Allowed origins, or `*`. Defaults to `*`. */
@@ -16,8 +16,19 @@ export interface EdgeOptions extends ServerOptions {
16
16
  readonly cors?: boolean | CorsOptions;
17
17
  /** Include error details in problem responses. Defaults to `NODE_ENV === 'development'`. */
18
18
  readonly exposeErrors?: boolean;
19
+ /**
20
+ * Keeps the invocation alive for event sink sends a handler started, e.g.
21
+ * `EdgeRuntime.waitUntil` on Supabase. On Workers the `ctx` the runtime
22
+ * passes to `fetch` is used when this is unset.
23
+ */
24
+ readonly waitUntil?: (promise: Promise<unknown>) => void;
25
+ }
26
+ /** The platform context Workers pass as the third `fetch` argument. */
27
+ export interface EdgeExecutionContext {
28
+ waitUntil(promise: Promise<unknown>): void;
19
29
  }
20
- export type EdgeHandler = (request: Request) => Promise<Response>;
30
+ /** `Deno.serve` passes `(request, info)`, Workers `fetch` passes `(request, env, ctx)`. */
31
+ export type EdgeHandler = (request: Request, env?: unknown, executionContext?: EdgeExecutionContext) => Promise<Response>;
21
32
  export type ResourceMap<M extends AnyModels> = { readonly [T in TableKey<M>]?: ResourceRouteOptions<M, T> | true; };
22
33
  export interface ResourcesOptions extends MiddlewareOptions {
23
34
  /** Path before the resources, e.g. `/api` (Supabase: `/<function-name>`). */