better-supabase 0.5.0 → 0.6.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 (536) hide show
  1. package/README.md +299 -41
  2. package/dist/access-sql-B0dF-SoF.js +181 -0
  3. package/dist/actor-CQTlc1Hh.d.ts +43 -0
  4. package/dist/adapter-Bc1o3zyy.js +1106 -0
  5. package/dist/agents-CVHGd7It.d.ts +94 -0
  6. package/dist/ai-cache-CBWs1W0k.js +80 -0
  7. package/dist/ai-cache-DaDu_G5L.d.ts +64 -0
  8. package/dist/ai-chat-7amvXjmQ.d.ts +590 -0
  9. package/dist/ai-chat-B24UI962.js +743 -0
  10. package/dist/ai-files-CSPNswUY.js +319 -0
  11. package/dist/ai-sdk/agents/index.d.ts +74 -0
  12. package/dist/ai-sdk/agents/index.js +159 -0
  13. package/dist/ai-sdk/batches/index.d.ts +74 -0
  14. package/dist/ai-sdk/batches/index.js +180 -0
  15. package/dist/ai-sdk/cache/index.d.ts +38 -0
  16. package/dist/ai-sdk/cache/index.js +127 -0
  17. package/dist/ai-sdk/chat/index.d.ts +2 -0
  18. package/dist/ai-sdk/chat/index.js +246 -0
  19. package/dist/ai-sdk/embeddings/index.d.ts +3 -0
  20. package/dist/ai-sdk/embeddings/index.js +2 -0
  21. package/dist/ai-sdk/files/index.d.ts +61 -0
  22. package/dist/ai-sdk/files/index.js +111 -0
  23. package/dist/ai-sdk/index.d.ts +145 -0
  24. package/dist/ai-sdk/index.js +174 -0
  25. package/dist/ai-sdk/mcp/index.d.ts +102 -0
  26. package/dist/ai-sdk/mcp/index.js +362 -0
  27. package/dist/ai-sdk/memory/index.d.ts +67 -0
  28. package/dist/ai-sdk/memory/index.js +175 -0
  29. package/dist/ai-sdk/react/index.d.ts +2 -0
  30. package/dist/ai-sdk/react/index.js +3 -0
  31. package/dist/ai-sdk/react/server.d.ts +6 -0
  32. package/dist/ai-sdk/react/server.js +7 -0
  33. package/dist/ai-sdk/workflow/index.d.ts +249 -0
  34. package/dist/ai-sdk/workflow/index.js +575 -0
  35. package/dist/ai-sdk/workflow/react/index.d.ts +20 -0
  36. package/dist/ai-sdk/workflow/react/index.js +66 -0
  37. package/dist/ai-sdk/workflow/react/server.d.ts +10 -0
  38. package/dist/ai-sdk/workflow/react/server.js +12 -0
  39. package/dist/ai-tasks-Cd1HMFvB.d.ts +131 -0
  40. package/dist/announcements-CiyOs-xP.js +107 -0
  41. package/dist/announcements-ZRGnScWI.d.ts +72 -0
  42. package/dist/api-keys-rCGtKaZA.d.ts +156 -0
  43. package/dist/assistant-DwdpDH1q.d.ts +147 -0
  44. package/dist/astro/index.d.ts +86 -0
  45. package/dist/astro/index.js +93 -0
  46. package/dist/attributes-5dYul0u0.js +13 -0
  47. package/dist/auth-link-BjFPqwLz.d.ts +97 -0
  48. package/dist/auth-link-DrDX9KOT.js +114 -0
  49. package/dist/authorization-BFCqamMs.d.ts +172 -0
  50. package/dist/before-route-CnR0C0Jr.js +30 -0
  51. package/dist/bind-Bu_ZNa3W.d.ts +62 -0
  52. package/dist/bind-l4kAvYSv.js +97 -0
  53. package/dist/block-events-CrT8r7Fe.js +76 -0
  54. package/dist/block-fields-GFkxl4dP.js +49 -0
  55. package/dist/block-fields-SJ6fEf3o.d.ts +31 -0
  56. package/dist/block-helpers-CKtbFcRv.d.ts +37 -0
  57. package/dist/block-helpers-DWHxHsEQ.js +190 -0
  58. package/dist/block-hooks-BmjMyXTa.js +114 -0
  59. package/dist/block-hooks-plbZ0AbJ.d.ts +107 -0
  60. package/dist/{kit-transport-DJlHQUBU.js → block-transport-BLr-ZgLc.js} +11 -7
  61. package/dist/block-transport-DvaoPuZ9.d.ts +48 -0
  62. package/dist/blocks/agents/index.d.ts +3 -0
  63. package/dist/blocks/agents/index.js +123 -0
  64. package/dist/blocks/ai-cache/index.d.ts +3 -0
  65. package/dist/blocks/ai-cache/index.js +3 -0
  66. package/dist/blocks/ai-chat/index.d.ts +31 -0
  67. package/dist/blocks/ai-chat/index.js +5 -0
  68. package/dist/blocks/ai-chat/react/index.d.ts +77 -0
  69. package/dist/blocks/ai-chat/react/index.js +387 -0
  70. package/dist/blocks/ai-chat/react/server.d.ts +16 -0
  71. package/dist/blocks/ai-chat/react/server.js +14 -0
  72. package/dist/blocks/ai-files/index.d.ts +14 -0
  73. package/dist/blocks/ai-files/index.js +3 -0
  74. package/dist/blocks/ai-providers/index.d.ts +7 -0
  75. package/dist/blocks/ai-providers/index.js +211 -0
  76. package/dist/blocks/ai-tasks/index.d.ts +3 -0
  77. package/dist/blocks/ai-tasks/index.js +203 -0
  78. package/dist/blocks/announcements/index.d.ts +3 -0
  79. package/dist/blocks/announcements/index.js +3 -0
  80. package/dist/blocks/announcements/react/index.d.ts +31 -0
  81. package/dist/blocks/announcements/react/index.js +86 -0
  82. package/dist/blocks/announcements/react/server.d.ts +6 -0
  83. package/dist/blocks/announcements/react/server.js +7 -0
  84. package/dist/blocks/api-keys/index.d.ts +35 -0
  85. package/dist/blocks/api-keys/index.js +334 -0
  86. package/dist/blocks/attachments/index.d.ts +210 -0
  87. package/dist/blocks/attachments/index.js +222 -0
  88. package/dist/blocks/audit/index.d.ts +366 -0
  89. package/dist/blocks/audit/index.js +714 -0
  90. package/dist/blocks/billing/index.d.ts +265 -0
  91. package/dist/blocks/billing/index.js +400 -0
  92. package/dist/blocks/comments/index.d.ts +200 -0
  93. package/dist/blocks/comments/index.js +207 -0
  94. package/dist/blocks/connectors/index.d.ts +3 -0
  95. package/dist/blocks/connectors/index.js +164 -0
  96. package/dist/blocks/data-lifecycle/index.d.ts +251 -0
  97. package/dist/blocks/data-lifecycle/index.js +353 -0
  98. package/dist/blocks/entitlements/index.d.ts +14 -0
  99. package/dist/blocks/entitlements/index.js +25 -0
  100. package/dist/blocks/flags/index.d.ts +226 -0
  101. package/dist/blocks/flags/index.js +282 -0
  102. package/dist/blocks/inbox/index.d.ts +6 -0
  103. package/dist/blocks/inbox/index.js +499 -0
  104. package/dist/blocks/inbox/react/index.d.ts +2 -0
  105. package/dist/blocks/inbox/react/index.js +225 -0
  106. package/dist/blocks/inbox/react/server.d.ts +10 -0
  107. package/dist/blocks/inbox/react/server.js +12 -0
  108. package/dist/blocks/index.d.ts +65 -0
  109. package/dist/blocks/index.js +77 -0
  110. package/dist/blocks/jobs/index.d.ts +297 -0
  111. package/dist/blocks/jobs/index.js +1051 -0
  112. package/dist/blocks/knowledge/index.d.ts +3 -0
  113. package/dist/blocks/knowledge/index.js +3 -0
  114. package/dist/blocks/memory/index.d.ts +8 -0
  115. package/dist/blocks/memory/index.js +289 -0
  116. package/dist/blocks/notifications/index.d.ts +297 -0
  117. package/dist/blocks/notifications/index.js +425 -0
  118. package/dist/blocks/notifications/react/index.d.ts +44 -0
  119. package/dist/blocks/notifications/react/index.js +67 -0
  120. package/dist/blocks/notifications/react/server.d.ts +6 -0
  121. package/dist/blocks/notifications/react/server.js +7 -0
  122. package/dist/blocks/onboarding/index.d.ts +3 -0
  123. package/dist/blocks/onboarding/index.js +64 -0
  124. package/dist/blocks/onboarding/react/index.d.ts +28 -0
  125. package/dist/blocks/onboarding/react/index.js +78 -0
  126. package/dist/blocks/onboarding/react/server.d.ts +7 -0
  127. package/dist/blocks/onboarding/react/server.js +7 -0
  128. package/dist/blocks/organizations/index.d.ts +241 -0
  129. package/dist/blocks/organizations/index.js +400 -0
  130. package/dist/blocks/outbox/index.d.ts +3 -0
  131. package/dist/blocks/outbox/index.js +266 -0
  132. package/dist/blocks/profiles/index.d.ts +40 -0
  133. package/dist/blocks/profiles/index.js +28 -0
  134. package/dist/blocks/push/index.d.ts +185 -0
  135. package/dist/blocks/push/index.js +258 -0
  136. package/dist/blocks/settings/index.d.ts +89 -0
  137. package/dist/blocks/settings/index.js +104 -0
  138. package/dist/blocks/sso/index.d.ts +198 -0
  139. package/dist/blocks/sso/index.js +1297 -0
  140. package/dist/blocks/usage/index.d.ts +4 -0
  141. package/dist/blocks/usage/index.js +233 -0
  142. package/dist/blocks/waitlist/index.d.ts +117 -0
  143. package/dist/blocks/waitlist/index.js +132 -0
  144. package/dist/blocks/webhooks/index.d.ts +304 -0
  145. package/dist/{webhooks → blocks/webhooks}/index.js +468 -148
  146. package/dist/blocks/workflow-builder/index.d.ts +21 -0
  147. package/dist/blocks/workflow-builder/index.js +5 -0
  148. package/dist/blocks/workflow-builder/react/index.d.ts +47 -0
  149. package/dist/blocks/workflow-builder/react/index.js +119 -0
  150. package/dist/blocks/workflow-builder/react/server.d.ts +8 -0
  151. package/dist/blocks/workflow-builder/react/server.js +11 -0
  152. package/dist/blocks/workflows/index.d.ts +3 -0
  153. package/dist/blocks/workflows/index.js +3 -0
  154. package/dist/blocks/workflows/react/index.d.ts +47 -0
  155. package/dist/blocks/workflows/react/index.js +137 -0
  156. package/dist/blocks/workflows/react/server.d.ts +8 -0
  157. package/dist/blocks/workflows/react/server.js +11 -0
  158. package/dist/{index-SaTsEfGP.d.ts → bucket-Cl46E3jS.d.ts} +134 -91
  159. package/dist/{simplify-_0oUKqCd.js → build-BXIzE6Xv.js} +222 -124
  160. package/dist/{channel-FQW-CnGR.d.ts → channel-_2Mx1Oyu.d.ts} +2 -2
  161. package/dist/channels-CkgQ_X60.js +114 -0
  162. package/dist/chat-sdk/index.d.ts +303 -0
  163. package/dist/chat-sdk/index.js +733 -0
  164. package/dist/chat-sdk/react/index.d.ts +2 -0
  165. package/dist/chat-sdk/react/index.js +3 -0
  166. package/dist/chat-sdk/react/server.d.ts +3 -0
  167. package/dist/chat-sdk/react/server.js +2 -0
  168. package/dist/claims-DDBQT6BK.js +61 -0
  169. package/dist/{claims-BAf6c7is.js → claims-PqzCxaTD.js} +39 -2
  170. package/dist/cli/bin.js +1 -1
  171. package/dist/cli/{codemod-DqV7612m.js → codemod-Bl_tQpHn.js} +105 -2
  172. package/dist/cli/config-B9HkL8nF.js +2 -0
  173. package/dist/cli/config-DU7EJImt.js +49 -0
  174. package/dist/cli/config-NiPxAmUF.js +1077 -0
  175. package/dist/cli/{dist-xn4wlboc.js → dist-DRAVaE6w.js} +111 -1
  176. package/dist/cli/{doctor-L7Z8mYTx.js → doctor-B4JOm_ox.js} +992 -316
  177. package/dist/cli/{env-DmKv_G4A.js → env-CJLbUVPB.js} +1 -1
  178. package/dist/cli/{env-jIFUADLY.js → env-qXgyMV6r.js} +2 -2
  179. package/dist/cli/fresh-import-BeYf9I3x.js +40 -0
  180. package/dist/cli/gen-BGLb_zou.js +3100 -0
  181. package/dist/cli/gen-DAH8FM2W.js +2 -0
  182. package/dist/cli/index.d.ts +44 -5
  183. package/dist/cli/index.js +7 -7
  184. package/dist/cli/{init-Saf5-R9T.js → init-BIIwclPg.js} +242 -27
  185. package/dist/cli/{introspect--H7oGmcd.js → introspect-DNUTuNvb.js} +5 -5
  186. package/dist/cli/{io-k41_z-jT.js → io-DI1mTdSA.js} +12 -3
  187. package/dist/cli/{keys-ByKHnvP9.js → keys-BGCnnb-s.js} +8 -6
  188. package/dist/cli/{ohash-D7bG_EOb.js → ohash-BjQY1cBb.js} +1 -1
  189. package/dist/cli/{openapi-Cp5Fyta-.js → openapi-BlRJ18s3.js} +2 -2
  190. package/dist/cli/{project-B_GeXyHh.js → project-DZRaBaY7.js} +11 -6
  191. package/dist/cli/read-sets-CETOSFx4.js +223 -0
  192. package/dist/cli/{run-BKR2W_79.js → run-DNWxHynX.js} +33 -23
  193. package/dist/cli/{seed-CUlqWh-8.js → seed-DQzqT7LP.js} +8 -6
  194. package/dist/cli/{skills-LJJIhLFR.js → skills-QQs4q68J.js} +3 -2
  195. package/dist/cli/sql-D0GUtUPp.js +536 -0
  196. package/dist/cli/{config-CPVpXP5I.js → supabase-toml-B-bIukQF.js} +72 -942
  197. package/dist/cli/typegen-version-DeFbtzYI.js +8 -0
  198. package/dist/cli/{version-BDJuO0UR.js → version-hr88OZG0.js} +1 -1
  199. package/dist/client/index.d.ts +3 -2
  200. package/dist/client/index.js +11 -71
  201. package/dist/client/native/index.d.ts +228 -0
  202. package/dist/client/native/index.js +361 -0
  203. package/dist/client-CI0Z2zWX.js +277 -0
  204. package/dist/cloud-event-BnmD5fb9.js +46 -0
  205. package/dist/cloud-event-C1JCc1bH.d.ts +50 -0
  206. package/dist/{compiler-BXH_aZ7N.d.ts → compiler-DY_wkj4R.d.ts} +2 -2
  207. package/dist/compose-BIBNgAnq.js +53 -0
  208. package/dist/composite-Bt1YK3Ke.d.ts +146 -0
  209. package/dist/composite-DhE66P5u.js +130 -0
  210. package/dist/config/index.d.ts +6 -4
  211. package/dist/config/index.js +5 -5
  212. package/dist/{config-T_ejwyd3.d.ts → config-D44Y7PAv.d.ts} +406 -205
  213. package/dist/{config-DreERlKo.js → config-Dn7F5k9A.js} +62 -14
  214. package/dist/connector-Dv8kK0MO.d.ts +107 -0
  215. package/dist/connectors-hkLCwyEz.d.ts +120 -0
  216. package/dist/context-BCrWe7ow.d.ts +237 -0
  217. package/dist/credentials/index.d.ts +31 -0
  218. package/dist/credentials/index.js +168 -0
  219. package/dist/cron-DVPUg5k3.js +145 -0
  220. package/dist/csv-CPAzEmB6.js +25 -0
  221. package/dist/db-exception-CnWcYPxL.js +15 -0
  222. package/dist/{define-cNKzqwL_.js → define-B-TVjC25.js} +784 -227
  223. package/dist/{define-Bp_BZa5h.d.ts → define-CJJkkr1-.d.ts} +353 -61
  224. package/dist/edge/index.d.ts +69 -11
  225. package/dist/edge/index.js +191 -75
  226. package/dist/elysia/index.d.ts +59 -0
  227. package/dist/elysia/index.js +62 -0
  228. package/dist/embeddings-4ZvFzjsU.js +127 -0
  229. package/dist/embeddings-C9KGQnXt.d.ts +68 -0
  230. package/dist/{refresh-BTrQ_ZTp.d.ts → ended-jLfvw8h-.d.ts} +20 -2
  231. package/dist/{entitlements-DUxU4oHe.d.ts → entitlements-DHrY2UDZ.d.ts} +16 -7
  232. package/dist/entitlements-DRl6ZJUm.js +24 -0
  233. package/dist/envelope-DqnYGRw7.js +47 -0
  234. package/dist/{errors-DtwXa6b8.js → errors-B11Duf73.js} +82 -13
  235. package/dist/errors-DLjJHPLK.js +44 -0
  236. package/dist/escape-like-DHfx6jRr.js +7 -0
  237. package/dist/escape-like-ImTK0ps_.d.ts +15 -0
  238. package/dist/eve/index.d.ts +220 -0
  239. package/dist/eve/index.js +504 -0
  240. package/dist/eve-gT2Fpjut.d.ts +151 -0
  241. package/dist/events/index.d.ts +4 -3
  242. package/dist/events/index.js +9 -50
  243. package/dist/events-DWDhx77e.d.ts +549 -0
  244. package/dist/executor-Bq28caBo.js +718 -0
  245. package/dist/executor-C-R4pucm.js +83 -0
  246. package/dist/executor-CaWigTyR.d.ts +148 -0
  247. package/dist/executor-D14tGopJ.d.ts +36 -0
  248. package/dist/{executor-Cghdstwu.d.ts → executor-DbvExCFC.d.ts} +7 -1
  249. package/dist/{sql-Coh6n4cC.js → executor-De1Of3m3.js} +210 -11
  250. package/dist/executor-DvsBbNBS.d.ts +261 -0
  251. package/dist/expo/index.d.ts +79 -0
  252. package/dist/expo/index.js +129 -0
  253. package/dist/expo-sqlite/index.d.ts +58 -0
  254. package/dist/expo-sqlite/index.js +104 -0
  255. package/dist/field-errors-BFOa7WhB.d.ts +99 -0
  256. package/dist/field-errors-VF1yb8yI.js +13 -0
  257. package/dist/framework-CONDyPYx.js +51 -0
  258. package/dist/framework-DuVb4Xa8.d.ts +25 -0
  259. package/dist/gateway-C1ssRHnf.d.ts +130 -0
  260. package/dist/graph-BGyLLFLX.js +265 -0
  261. package/dist/h3/index.d.ts +59 -0
  262. package/dist/h3/index.js +55 -0
  263. package/dist/h3/v1/index.d.ts +63 -0
  264. package/dist/h3/v1/index.js +49 -0
  265. package/dist/history-BZih6SFP.js +64 -0
  266. package/dist/hono/index.d.ts +56 -7
  267. package/dist/hono/index.js +97 -45
  268. package/dist/{react-C_s7kiNz.js → hooks-1BTCJsiw.js} +104 -133
  269. package/dist/http-Cv4T29xh.js +40 -0
  270. package/dist/http-DdYadv-o.js +126 -0
  271. package/dist/image-url-pIVlO6R1.js +41 -0
  272. package/dist/impersonation-DcqaTBHx.js +148 -0
  273. package/dist/inbox-i7E1ppo6.d.ts +384 -0
  274. package/dist/index-ACiNPN4Z.d.ts +74 -0
  275. package/dist/{index-DgILJRXj.d.ts → index-Bepi-Hgg.d.ts} +91 -28
  276. package/dist/index-BkWT_uBO.d.ts +51 -0
  277. package/dist/index-BpFYMsi0.d.ts +53 -0
  278. package/dist/{index-C7f8cOBM.d.ts → index-Bxih3l0u.d.ts} +2 -2
  279. package/dist/index-CaxrMD1A.d.ts +1 -0
  280. package/dist/index-ClmjK_o-.d.ts +55 -0
  281. package/dist/index-CtuakVRc.d.ts +267 -0
  282. package/dist/index-D48jVS-N.d.ts +246 -0
  283. package/dist/index-DDrYaUcq.d.ts +138 -0
  284. package/dist/index-DQh4VCc9.d.ts +98 -0
  285. package/dist/{live-D9W2M5aO.d.ts → index-DunNRdnT.d.ts} +136 -38
  286. package/dist/index.d.ts +65 -18
  287. package/dist/index.js +42 -14
  288. package/dist/invalidate-BBqhpxyB.d.ts +19 -0
  289. package/dist/json-CEnpTHlZ.js +16 -0
  290. package/dist/json-schema-CvER4kgT.js +502 -0
  291. package/dist/keys-4MnkWTTh.js +35 -0
  292. package/dist/kit-B5tid-q5.d.ts +60 -0
  293. package/dist/kit-Fm-Fv7q5.js +78 -0
  294. package/dist/knowledge-BXBbT0Tr.d.ts +176 -0
  295. package/dist/knowledge-CDmiMLew.js +255 -0
  296. package/dist/lint/index.d.ts +1 -1
  297. package/dist/lint/index.js +37 -0
  298. package/dist/list/index.d.ts +3 -2
  299. package/dist/list/index.js +1 -444
  300. package/dist/{index-fag8VJZ2.d.ts → list-query-BRt-zDF7.d.ts} +20 -12
  301. package/dist/list-query-gl808ac1.js +459 -0
  302. package/dist/{live-CdJBOc4f.js → live-CTAZQkwl.js} +99 -14
  303. package/dist/logger-DWVYUmwi.d.ts +18 -0
  304. package/dist/mcp/index.d.ts +38 -11
  305. package/dist/mcp/index.js +82 -46
  306. package/dist/mcp/sdk/index.d.ts +105 -0
  307. package/dist/mcp/sdk/index.js +126 -0
  308. package/dist/message-CaKlqdsX.js +219 -0
  309. package/dist/message-CfDoR0Y6.d.ts +94 -0
  310. package/dist/messages-B9-5887d.js +715 -0
  311. package/dist/messages-DYP0sUTe.d.ts +59 -0
  312. package/dist/{mfa-CusDgPaD.d.ts → mfa-Daak8ukG.d.ts} +8 -2
  313. package/dist/modules-DpPwzC7E.d.ts +192 -0
  314. package/dist/modules-dxrVK3ID.js +228 -0
  315. package/dist/nestjs/index.d.ts +68 -0
  316. package/dist/nestjs/index.js +164 -0
  317. package/dist/next/client/index.d.ts +35 -0
  318. package/dist/next/client/index.js +36 -0
  319. package/dist/next/image/index.js +3 -24
  320. package/dist/next/index.d.ts +150 -51
  321. package/dist/next/index.js +261 -107
  322. package/dist/node/index.d.ts +4 -0
  323. package/dist/node/index.js +210 -0
  324. package/dist/node-headers-AO06VhqH.d.ts +24 -0
  325. package/dist/node-headers-C71zNQHe.js +55 -0
  326. package/dist/nuxt/index.d.ts +60 -0
  327. package/dist/nuxt/index.js +64 -0
  328. package/dist/onboarding-BZGHYJks.d.ts +62 -0
  329. package/dist/openapi/index.d.ts +1 -1
  330. package/dist/openapi/index.js +3 -3
  331. package/dist/orpc/index.d.ts +70 -11
  332. package/dist/orpc/index.js +73 -24
  333. package/dist/otel/index.d.ts +7 -7
  334. package/dist/otel/index.js +87 -57
  335. package/dist/outbox-Cq7pPYvl.d.ts +161 -0
  336. package/dist/{plugin-o144f322.d.ts → plugin-FGY8UhYm.d.ts} +30 -10
  337. package/dist/plugin-tfXW1-qO.js +45 -0
  338. package/dist/plugins/actor/index.d.ts +2 -2
  339. package/dist/plugins/actor/index.js +3 -3
  340. package/dist/plugins/rules/index.d.ts +11 -4
  341. package/dist/plugins/rules/index.js +40 -13
  342. package/dist/plugins/soft-delete/index.d.ts +5 -4
  343. package/dist/plugins/soft-delete/index.js +10 -5
  344. package/dist/plugins/tenant/index.d.ts +2 -2
  345. package/dist/plugins/tenant/index.js +18 -11
  346. package/dist/plugins/timestamps/index.d.ts +5 -3
  347. package/dist/plugins/timestamps/index.js +6 -4
  348. package/dist/plugins/validation/index.d.ts +2 -2
  349. package/dist/plugins/validation/index.js +10 -6
  350. package/dist/{pool-C9voM4Kw.d.ts → pool-CAu2nLrL.d.ts} +2 -2
  351. package/dist/postgres/index.d.ts +4 -4
  352. package/dist/postgres/index.js +1 -2
  353. package/dist/{postgrest-CruYKAvV.d.ts → postgrest-BLVdEnfe.d.ts} +13 -3
  354. package/dist/powersync/index.d.ts +43 -0
  355. package/dist/powersync/index.js +199 -0
  356. package/dist/powersync/react/index.d.ts +87 -0
  357. package/dist/powersync/react/index.js +108 -0
  358. package/dist/{problem-BW1KhzSG.js → problem-BreOl8b8.js} +14 -3
  359. package/dist/{problem-Blxe8S31.d.ts → problem-DD8LZFjc.d.ts} +21 -3
  360. package/dist/provider-BH5UWZJ6.d.ts +113 -0
  361. package/dist/provider-Di3sRutW.js +57 -0
  362. package/dist/query/index.d.ts +4 -2
  363. package/dist/query/index.js +4 -3
  364. package/dist/{query-CCbo44lG.js → query-BQ-NaZon.js} +141 -24
  365. package/dist/{queue-BYUCjr59.d.ts → queue-CLJurhdy.d.ts} +258 -83
  366. package/dist/react/index.d.ts +11 -7
  367. package/dist/react/index.js +7 -3
  368. package/dist/react/native/index.d.ts +116 -0
  369. package/dist/react/native/index.js +130 -0
  370. package/dist/react/server.d.ts +28 -10
  371. package/dist/react/server.js +22 -5
  372. package/dist/react/session.d.ts +2 -2
  373. package/dist/react-4ZqkP8da.js +79 -0
  374. package/dist/react-F80mF4-t.js +409 -0
  375. package/dist/react-router/index.d.ts +83 -0
  376. package/dist/react-router/index.js +89 -0
  377. package/dist/react-topic-seAWjL3_.js +38 -0
  378. package/dist/{read-set-DQFt1N_Y.js → read-set-DuKWC9Mj.js} +67 -25
  379. package/dist/realtime/index.d.ts +4 -5
  380. package/dist/realtime/index.js +144 -82
  381. package/dist/refusal-CeJWxmkH.js +61 -0
  382. package/dist/refusal-D1rgbzNq.d.ts +15 -0
  383. package/dist/replicas-CwrYp5Zj.js +94 -0
  384. package/dist/{view-Bq64ki8-.js → resolve-D_IcnvFd.js} +239 -289
  385. package/dist/{resolve-C15TJq77.d.ts → resolve-KW8nCeL6.d.ts} +29 -45
  386. package/dist/{resource-CRxxwkQq.js → resource-BsvzCMlX.js} +4 -4
  387. package/dist/{resource-D8iqWMr-.d.ts → resource-D6Uc7Sk7.d.ts} +5 -5
  388. package/dist/respond-BUgsXNgk.js +91 -0
  389. package/dist/respond-DoBijysA.d.ts +93 -0
  390. package/dist/result-D7y2fT87.d.ts +282 -0
  391. package/dist/{result-BKiliPY7.js → result-DzUbqgdW.js} +27 -2
  392. package/dist/run-state-CPo-1X2B.d.ts +12 -0
  393. package/dist/run-state-CgBKzYMW.js +13 -0
  394. package/dist/search-CUWCRYKL.js +9 -0
  395. package/dist/server/index.d.ts +143 -21
  396. package/dist/server/index.js +46 -14
  397. package/dist/{respond-D2OQl62-.d.ts → server-CeVeeXwz.d.ts} +225 -80
  398. package/dist/session-ChiXDZdZ.d.ts +72 -0
  399. package/dist/shared-CBxosKK3.js +75 -0
  400. package/dist/{shared-D1dRUrAg.js → shared-CxWmcyqB.js} +2 -1
  401. package/dist/shared-DDSjEGDR.d.ts +11 -0
  402. package/dist/sign-in-BCV5S2WZ.d.ts +49 -0
  403. package/dist/sign-in-Cb1mwv6X.js +86 -0
  404. package/dist/{signers-Cc6r98SW.d.ts → signers-4y62_VIi.d.ts} +13 -9
  405. package/dist/simplify-DDO0j0LI.js +83 -0
  406. package/dist/solid/index.d.ts +131 -0
  407. package/dist/solid/index.js +344 -0
  408. package/dist/solid-start/index.d.ts +75 -0
  409. package/dist/solid-start/index.js +58 -0
  410. package/dist/{spec-pins-C3oc-Tdp.js → spec-pins--j6mTok4.js} +8 -1
  411. package/dist/{spec-pins-CqorWDnO.d.ts → spec-pins-C89s6DyW.d.ts} +7 -0
  412. package/dist/sql/index.d.ts +330 -194
  413. package/dist/sql/index.js +34901 -6489
  414. package/dist/ssr/index.d.ts +6 -5
  415. package/dist/ssr/index.js +3 -3
  416. package/dist/{standard-D7r6dMUu.js → standard-BK0cqJ7y.js} +4 -3
  417. package/dist/{standard-J4YgMOLm.d.ts → standard-CYsm7xpT.d.ts} +1 -1
  418. package/dist/stats-D_AD9GGu.js +1123 -0
  419. package/dist/storage/index.d.ts +5 -5
  420. package/dist/storage/index.js +1027 -368
  421. package/dist/store-BdH5ruDx.js +66 -0
  422. package/dist/store-CGjgWu5n.d.ts +68 -0
  423. package/dist/streams/index.d.ts +76 -0
  424. package/dist/streams/index.js +77 -0
  425. package/dist/streams/redis/index.d.ts +52 -0
  426. package/dist/streams/redis/index.js +185 -0
  427. package/dist/stripe-BMj5LtsT.js +38 -0
  428. package/dist/stripe-D04h-QBT.d.ts +136 -0
  429. package/dist/{support-Dk6vdmEw.js → support-BivNqSpK.js} +35 -12
  430. package/dist/{support-view-Da5peKFg.d.ts → support-view-33Oi07TT.d.ts} +1 -1
  431. package/dist/svelte/index.d.ts +114 -0
  432. package/dist/svelte/index.js +344 -0
  433. package/dist/sveltekit/index.d.ts +116 -0
  434. package/dist/sveltekit/index.js +106 -0
  435. package/dist/tags-B99_U9Pp.js +39 -0
  436. package/dist/tags-Cx-LnIQP.d.ts +30 -0
  437. package/dist/tanstack-db/index.d.ts +71 -0
  438. package/dist/tanstack-db/index.js +72 -0
  439. package/dist/tanstack-start/index.d.ts +75 -0
  440. package/dist/tanstack-start/index.js +95 -0
  441. package/dist/tee-CoEppCER.js +101 -0
  442. package/dist/{template-TxrGI5jR.js → template--jDkl3UP.js} +34 -13
  443. package/dist/template-CwO38Do8.d.ts +6 -0
  444. package/dist/temporal-BJGitm-h.js +79 -0
  445. package/dist/{temporal-required-CAt4Dc9Z.js → temporal-required-BVvW7SYJ.js} +3 -2
  446. package/dist/tenant-I1TEZ_BX.js +27 -0
  447. package/dist/tenant-icPeuUBN.d.ts +17 -0
  448. package/dist/testing/index.d.ts +343 -37
  449. package/dist/testing/index.js +1186 -79
  450. package/dist/timing-CyTQPubY.js +92 -0
  451. package/dist/ttl-Hr34gRu8.js +12 -0
  452. package/dist/{types-Dnf_wRDz.d.ts → types-6BdhkmZe.d.ts} +111 -45
  453. package/dist/types-BI-0Sl2v.d.ts +359 -0
  454. package/dist/types-C05bxW-W.d.ts +220 -0
  455. package/dist/types-DGs5L0VN.d.ts +192 -0
  456. package/dist/types-TaiEeBGA.d.ts +156 -0
  457. package/dist/usage-CrvrL2vw.d.ts +177 -0
  458. package/dist/user-change-XzvgafU4.js +130 -0
  459. package/dist/vault-CSO7ss5C.d.ts +50 -0
  460. package/dist/vercel-connect/index.d.ts +47 -0
  461. package/dist/vercel-connect/index.js +119 -0
  462. package/dist/{verify-Ce49ETPz.js → verify-DL41hbvY.js} +85 -13
  463. package/dist/verify-DPuWngD4.d.ts +172 -0
  464. package/dist/{version-DM_Roffb.js → version-Bvv6aLjZ.js} +1 -1
  465. package/dist/view-BeFcRV6G.js +99 -0
  466. package/dist/{view-BEf0diC5.d.ts → view-DbxLNu8L.d.ts} +35 -32
  467. package/dist/vue/index.d.ts +141 -0
  468. package/dist/vue/index.js +362 -0
  469. package/dist/watch-DI34G86j.d.ts +60 -0
  470. package/dist/watch-Xuxrvxq-.js +122 -0
  471. package/dist/{wire-D2dT86vi.js → wire-DtZQ4sdE.js} +15 -5
  472. package/dist/workflow-builder-DJ1oHn8g.js +398 -0
  473. package/dist/workflow-sdk/builder/index.d.ts +85 -0
  474. package/dist/workflow-sdk/builder/index.js +250 -0
  475. package/dist/workflow-sdk/index.d.ts +14 -0
  476. package/dist/workflow-sdk/index.js +3 -0
  477. package/dist/workflow-sdk/world/index.d.ts +107 -0
  478. package/dist/workflow-sdk/world/index.js +702 -0
  479. package/dist/workflow-sdk-B3yLD6Br.d.ts +98 -0
  480. package/dist/workflow-sdk-C2WJ_G2O.js +173 -0
  481. package/dist/workflow-sdk-world-D-prir6O.js +1397 -0
  482. package/dist/workflows-B0j9WKPu.d.ts +185 -0
  483. package/dist/workflows-wu1WWBn7.js +216 -0
  484. package/package.json +470 -29
  485. package/schemas/ai-message-v1.json +258 -0
  486. package/schemas/config-v1.json +1074 -140
  487. package/schemas/doctor-report-v1.json +21 -1
  488. package/schemas/snapshot-v2.json +8 -0
  489. package/skills/better-supabase/SKILL.md +41 -12
  490. package/skills/better-supabase/references/frontend.md +96 -0
  491. package/skills/better-supabase/references/plugins.md +10 -6
  492. package/skills/better-supabase/references/troubleshooting.md +2 -1
  493. package/skills/better-supabase-api/SKILL.md +76 -22
  494. package/skills/better-supabase-api/references/adapters.md +207 -0
  495. package/skills/better-supabase-api/references/ai.md +125 -0
  496. package/skills/better-supabase-api/references/expo.md +65 -0
  497. package/skills/better-supabase-api/references/powersync.md +35 -0
  498. package/skills/better-supabase-api/references/streams-credentials.md +105 -0
  499. package/skills/better-supabase-auth/SKILL.md +62 -18
  500. package/skills/better-supabase-auth/references/authorization-providers.md +51 -0
  501. package/skills/better-supabase-testing/SKILL.md +3 -1
  502. package/dist/cli/config-dtoekM0v.js +0 -2
  503. package/dist/cli/gen-BJc9vdyu.js +0 -2
  504. package/dist/cli/gen-C2osRcr5.js +0 -2204
  505. package/dist/cli/read-sets-BfMQcKy8.js +0 -289
  506. package/dist/cli/sql-DzPbfngx.js +0 -348
  507. package/dist/entitlements-CTEBm7IB.js +0 -20
  508. package/dist/events-aIO7vsIk.d.ts +0 -230
  509. package/dist/executor-BunPOO-k.d.ts +0 -402
  510. package/dist/executor-XycESQPH.js +0 -94
  511. package/dist/impersonation-VfaGc4Q_.js +0 -41
  512. package/dist/index-BGdgBPdf.d.ts +0 -161
  513. package/dist/index-DOESKG27.d.ts +0 -100
  514. package/dist/index-DmXSxbLi.d.ts +0 -62
  515. package/dist/index-Dxn2a5cw.d.ts +0 -50
  516. package/dist/jobs/index.d.ts +0 -226
  517. package/dist/jobs/index.js +0 -1007
  518. package/dist/json-schema-m1fiwKgN.js +0 -208
  519. package/dist/kit-events-CTFDfSwb.js +0 -60
  520. package/dist/kit-transport-B82k1djG.d.ts +0 -33
  521. package/dist/kits-CGLLrNPd.js +0 -157
  522. package/dist/notifications/index.d.ts +0 -162
  523. package/dist/notifications/index.js +0 -264
  524. package/dist/orgs/index.d.ts +0 -132
  525. package/dist/orgs/index.js +0 -245
  526. package/dist/permdock-sql-C2Inc6Xc.d.ts +0 -29
  527. package/dist/permdock-sql-DgOfeixi.js +0 -51
  528. package/dist/plugin-DwARMuQp.js +0 -59
  529. package/dist/server-Csx2sRjg.js +0 -655
  530. package/dist/stats-Bqob3WqT.js +0 -592
  531. package/dist/support-DT-OhSxD.d.ts +0 -88
  532. package/dist/template-mbvlysOo.d.ts +0 -6
  533. package/dist/temporal-CVlIV2DZ.js +0 -40
  534. package/dist/user-change-CHFEUro1.js +0 -49
  535. package/dist/webhooks/index.d.ts +0 -285
  536. package/skills/better-supabase-auth/references/permdock.md +0 -100
package/README.md CHANGED
@@ -1,32 +1,87 @@
1
1
  # better-supabase
2
2
 
3
- **A typed data layer, auth glue and CLI for Supabase apps, APIs, MCP servers and jobs.**
3
+ **Typed repositories, auth glue and a CLI for Supabase apps, APIs, MCP servers and jobs.**
4
4
 
5
5
  [![npm](https://img.shields.io/npm/v/better-supabase)](https://www.npmjs.com/package/better-supabase)
6
6
  [![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/ScaleDockHQ/better-supabase/blob/main/LICENSE)
7
7
  ![TypeScript](https://img.shields.io/badge/TypeScript-6%20%7C%207-3178c6.svg)
8
8
 
9
- `better-supabase gen` extends `supabase gen types` with relation cardinality, unique keys, CHECK unions and typed jsonb. The generated `schema` gives every table a typed repository that compiles to one PostgREST request, returns a `Result` instead of throwing, and runs as the caller so RLS always applies.
9
+ [Docs](https://bettersupabase.com/docs) · [Quickstart](https://bettersupabase.com/docs/getting-started) · [Examples](https://bettersupabase.com/docs/examples) · [Changelog](https://bettersupabase.com/changelog) · [GitHub](https://github.com/ScaleDockHQ/better-supabase)
10
+
11
+ better-supabase sits on top of the supabase-js client you already use. You keep your database, your RLS policies, Supabase Auth and Storage. The CLI reads your schema and generates a typed repository for every table, so a query is a typed object instead of a string, a typo in a column name is a compile error, and the row type follows what you selected.
12
+
13
+ It also writes the glue every Supabase app repeats: the session cookie and token refresh for Next.js, Hono, oRPC, Edge Functions, MCP servers and [every other supported framework](https://bettersupabase.com/docs/frameworks), pagination, soft delete, timestamps, cache invalidation, background jobs and typed Storage and Realtime. It is built on [`@supabase/supabase-js`](https://github.com/supabase/supabase-js), [`@supabase/server`](https://github.com/supabase/server), [`@supabase/middleware`](https://github.com/supabase/middleware) and [`@supabase/ssr`](https://github.com/supabase/ssr). It is an independent open-source project, not made by Supabase.
14
+
15
+ ## Before and after
16
+
17
+ With supabase-js, the query is a string and the error is a Postgres code:
18
+
19
+ ```ts
20
+ const { data, error } = await supabase
21
+ .from("customers")
22
+ .select("id, name, organization(name), notes!inner(kind)")
23
+ .eq("status", "active")
24
+ .eq("notes.kind", "call")
25
+ .order("name")
26
+ .limit(20);
27
+ if (error) throw error;
28
+
29
+ const { error: insertError } = await supabase.from("tags").insert({ name });
30
+ if (insertError?.code === "23505") return { message: "Tag already exists" };
31
+ ```
32
+
33
+ With better-supabase, every column, relation and operator is typed, and errors are values with a `kind`:
34
+
35
+ ```ts
36
+ const customers = await db.customers.findMany({
37
+ select: ["id", "name"],
38
+ where: { status: "active", notes: { some: { kind: "call" } } },
39
+ include: { organization: { select: ["name"] } },
40
+ orderBy: { name: "asc" },
41
+ limit: 20,
42
+ });
43
+ // customers.data: { id: string; name: string; organization: { name: string } }[]
44
+
45
+ const tag = await db.tags.create({ organizationId, name });
46
+ if (tag.error?.kind === "conflict") return { message: "Tag already exists" };
47
+ ```
48
+
49
+ Each call is still one PostgREST request, and it runs as the signed-in user, so your RLS policies decide what it can read and write. The [supabase-js migration guide](https://bettersupabase.com/docs/migration/supabase-js) maps every supabase-js call to its repository equivalent, and the two work side by side while you move over.
50
+
51
+ ## What you get
52
+
53
+ - **Stronger generated types.** [`better-supabase gen`](https://bettersupabase.com/docs/cli/gen) writes the same `database.types.ts` as `supabase gen types` and adds relationship cardinality, unique keys, CHECK-constraint unions, typed jsonb and camelCase column maps.
54
+ - **A typed repository per table.** [`findMany`, `findUnique`, `create`, `upsert`, `paginate`, counts and aggregates](https://bettersupabase.com/docs/repository), with nested relation filters and includes, compiled to PostgREST or to SQL on a direct Postgres connection.
55
+ - **Results instead of exceptions.** Every call returns a [`Result` with a plain, serializable `DbError`](https://bettersupabase.com/docs/concepts/results) that you can return from server actions and RPC handlers. `.orThrow()` is opt-in, and adapters turn errors into RFC 9457 Problem Details with the right status.
56
+ - **Your casing.** Keep database names with `casing: 'snake'`, or get [camelCase rows](https://bettersupabase.com/docs/concepts/casing) renamed inside the PostgREST query.
57
+ - **Auth without extra round trips.** Valid access tokens are [verified locally](https://bettersupabase.com/docs/auth) against the JWKS and never reach the Auth server. Refresh happens once, in the proxy. The service role is an explicit `bs.admin()` call.
58
+ - **Cache tags that follow writes.** Mutations [invalidate the tables they change](https://bettersupabase.com/docs/concepts/caching), with read-your-writes in Next.js server actions and table-based invalidation in TanStack Query.
59
+ - **Plugins.** [Timestamps, soft delete, tenant scoping, actor columns, validation and rules](https://bettersupabase.com/docs/plugins), each versioned and opt-in.
60
+ - **Blocks for the SQL every app repeats.** [Jobs on Supabase Queues](https://bettersupabase.com/docs/blocks/jobs), webhook inboxes, idempotency keys, organizations and invitations, notifications, outgoing webhooks, API keys, billing, usage quotas, feature flags, SSO and SCIM, vector search and Stripe entitlements. [`better-supabase sql add`](https://bettersupabase.com/docs/blocks/sql) writes the tables, functions and policies into your declarative schema.
61
+ - **Tests and CI checks.** [`asUser`](https://bettersupabase.com/docs/testing) runs RLS tests as any user against the local stack, `gen --check` fails on schema drift, and [`doctor`](https://bettersupabase.com/docs/cli/doctor) reports security and performance findings, with SARIF output for code scanning.
10
62
 
11
63
  ## Install
12
64
 
13
65
  ```bash
14
66
  pnpm add better-supabase @supabase/supabase-js
15
- pnpm add -D pg
67
+ pnpm add -D pg @supabase/postgrest-typegen@0.4.0
16
68
  ```
17
69
 
18
- ESM only. The package includes the `better-supabase` CLI, which needs Node 24 or later; the runtime entries run on every WinterTC runtime (Node, Deno, Bun, Workers, Supabase Edge Functions). TypeScript 6 and 7 are tested.
70
+ `pg` and `@supabase/postgrest-typegen` are optional peers that only the CLI loads, to read your schema and write `database.types.ts`; apps that only run the runtime entries skip them. Before installing, `npx better-supabase init` detects your frameworks and prints the install command for your package manager. The package is ESM only. The CLI needs Node 24 or later, and the runtime entries run on every WinterTC runtime. On runtimes without a native `Temporal` (Node 24, Safari), load [`temporal-polyfill`](https://bettersupabase.com/docs/concepts/temporal) once at startup. TypeScript 6 and 7 are tested.
19
71
 
20
72
  ## Quick start
21
73
 
22
- Or start with `npx better-supabase init`, which detects your frameworks and prints the install command.
74
+ Generate the typed schema from your local stack:
23
75
 
24
76
  ```bash
25
77
  supabase start
26
78
  pnpm better-supabase init # config, src/lib/supabase/index.ts and framework glue
79
+ pnpm better-supabase env # URL and keys into .env.local
27
80
  pnpm better-supabase gen # database.types.ts and generated.ts
28
81
  ```
29
82
 
83
+ Define the client once, then connect it per request with the current user's Supabase client:
84
+
30
85
  ```ts
31
86
  import { createClient } from "@supabase/supabase-js";
32
87
  import { defineSupabase } from "better-supabase";
@@ -37,47 +92,250 @@ export const betterSupabase = defineSupabase(schema);
37
92
 
38
93
  const db = betterSupabase.connect(createClient(url, publishableKey));
39
94
 
40
- const result = await db.customers.findMany({
41
- select: ["id", "name"],
42
- where: { status: "active", notes: { some: { kind: "call" } } },
43
- include: { organization: { select: ["name"] } },
44
- orderBy: { name: "asc" },
45
- limit: 20,
95
+ const customers = await db.customers
96
+ .findMany({ select: ["id", "name"], where: { status: "active" } })
97
+ .orThrow();
98
+ ```
99
+
100
+ `defineSupabase` holds no secrets and no connection. Because you connect with the client for the current user, every query runs under their RLS policies.
101
+
102
+ ## Use it where you run
103
+
104
+ An adapter verifies the session, refreshes it where it should and gives each handler a `db` for the caller. In Next.js:
105
+
106
+ ```tsx
107
+ // src/lib/supabase/server.ts
108
+ export const bs = createNext(betterSupabase);
109
+
110
+ // src/proxy.ts
111
+ export const proxy = (request: NextRequest) => bs.proxy(request);
112
+
113
+ // app/customers/page.tsx
114
+ export default async function Customers() {
115
+ const { db } = await bs.context();
116
+ const customers = await db.customers
117
+ .findMany({ select: ["id", "name"] })
118
+ .orThrow();
119
+ return <CustomerList customers={customers} />;
120
+ }
121
+ ```
122
+
123
+ | Where you run | What the adapter gives you | Docs |
124
+ | ---------------------------------- | -------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
125
+ | Next.js | Proxy, Server Components, route handlers, server actions and cache tags | [Next.js](https://bettersupabase.com/docs/frameworks/next) |
126
+ | Hono | Middleware, Result-aware handlers and REST resources that match OpenAPI | [Hono](https://bettersupabase.com/docs/frameworks/hono) |
127
+ | oRPC | A middleware that adds the caller's repositories to the oRPC context | [oRPC](https://bettersupabase.com/docs/frameworks/orpc) |
128
+ | Edge Functions, Deno, Bun, Workers | Fetch handlers with the caller's repositories | [Edge](https://bettersupabase.com/docs/frameworks/edge) |
129
+ | Expo Router | Server loaders, API routes and middleware that run as the caller | [Expo Router](https://bettersupabase.com/docs/frameworks/expo) |
130
+ | TanStack Start | Request middleware with the caller's repositories in every server function | [TanStack Start](https://bettersupabase.com/docs/frameworks/tanstack-start) |
131
+ | SvelteKit | A `handle` hook with the caller's repositories on `event.locals` | [SvelteKit](https://bettersupabase.com/docs/frameworks/sveltekit) |
132
+ | React Router | Server middleware with the caller's repositories in loaders and actions | [React Router](https://bettersupabase.com/docs/frameworks/react-router) |
133
+ | H3, Nitro and Nuxt | H3 2 middleware, Nitro 2 middleware and a Nuxt module | [H3](https://bettersupabase.com/docs/frameworks/h3), [Nuxt](https://bettersupabase.com/docs/frameworks/nuxt) |
134
+ | Elysia | The caller's repositories derived into every route | [Elysia](https://bettersupabase.com/docs/frameworks/elysia) |
135
+ | Node, Express, Fastify, Koa | Middleware with route guards and Problem Details errors | [Node](https://bettersupabase.com/docs/frameworks/node) |
136
+ | NestJS | Middleware, `@Ctx()` and role guards | [NestJS](https://bettersupabase.com/docs/frameworks/nestjs) |
137
+ | Astro and SolidStart | Middleware, page guards and actions | [Astro](https://bettersupabase.com/docs/frameworks/astro), [SolidStart](https://bettersupabase.com/docs/frameworks/solid-start) |
138
+ | MCP servers | Tools from your tables and your own code, running as the signed-in user | [MCP](https://bettersupabase.com/docs/frameworks/mcp) |
139
+ | React and TanStack Query | A browser client, typed hooks, query and mutation options, live queries | [Frontend](https://bettersupabase.com/docs/frontend/query) |
140
+ | Vue, Solid and Svelte | Live queries, presence, actions and the session | [Vue](https://bettersupabase.com/docs/frontend/vue), [Solid](https://bettersupabase.com/docs/frontend/solid), [Svelte](https://bettersupabase.com/docs/frontend/svelte) |
141
+
142
+ Every adapter is listed on the [frameworks overview](https://bettersupabase.com/docs/frameworks).
143
+
144
+ ## The CLI
145
+
146
+ The `better-supabase` command ships in this package:
147
+
148
+ ```bash
149
+ pnpm better-supabase init # config, client and framework glue
150
+ pnpm better-supabase env # local URL and keys into .env.local
151
+ pnpm better-supabase gen # database.types.ts and generated.ts
152
+ pnpm better-supabase gen --check # exit 1 in CI when the schema drifted
153
+ pnpm better-supabase doctor # RLS, grants, indexes and Supabase advisors
154
+ pnpm better-supabase doctor --format sarif # the same findings for GitHub code scanning
155
+ pnpm better-supabase sql add jobs # a SQL module into supabase/schemas
156
+ pnpm better-supabase skills install # Agent Skills for your coding agent
157
+ ```
158
+
159
+ See the [CLI reference](https://bettersupabase.com/docs/cli) for every command and flag.
160
+
161
+ ## Blocks
162
+
163
+ Blocks are the features most SaaS apps build by hand. Each one installs [SQL modules](https://bettersupabase.com/docs/blocks/sql) (tables, functions and RLS policies) into your declarative schema, and blocks with a TypeScript side import it from `better-supabase/blocks/<name>`:
164
+
165
+ ```bash
166
+ pnpm better-supabase sql add organizations invitations
167
+ ```
168
+
169
+ List them in `sql.modules` in `better-supabase.config.ts` so `better-supabase sql sync` keeps the files up to date. Each key is a module, and its value holds that module's settings, such as its roles, permission keys or the existing tables it adopts:
170
+
171
+ ```ts
172
+ export default defineConfig({
173
+ sql: {
174
+ modules: {
175
+ access: {
176
+ roles: {
177
+ owner: ["*"],
178
+ admin: ["organization.*", "members.*"],
179
+ member: ["organization.read"],
180
+ },
181
+ },
182
+ organizations: {},
183
+ invitations: { permissions: { invite: "organization.members.invite" } },
184
+ },
185
+ },
46
186
  });
47
- if (!result.ok) return result; // DbError: kind, message, status, code
48
187
  ```
49
188
 
189
+ The TypeScript side calls those functions as the signed-in user:
190
+
191
+ ```ts
192
+ import { createOrganizations } from "better-supabase/blocks/organizations";
193
+
194
+ const organizations = createOrganizations({ transport, actorId: user.id });
195
+ await organizations.invite({ organizationId, email, role: "member" });
196
+ ```
197
+
198
+ | Block | Import | SQL modules |
199
+ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | -------------------------------------- |
200
+ | [createBlocks](https://bettersupabase.com/docs/blocks/create-blocks): builds several blocks from one set of options and wires the blocks that use each other | `better-supabase/blocks` | none |
201
+ | [Access contract](https://bettersupabase.com/docs/blocks/access): `can()` for policies, over fixed roles, your own permission catalog or an authorization provider | SQL only | `access`, `tenant` |
202
+ | [Organizations](https://bettersupabase.com/docs/blocks/organizations): members, invitations, roles and switching | `better-supabase/blocks/organizations` | `organizations`, `invitations` |
203
+ | [Profiles](https://bettersupabase.com/docs/blocks/profiles): a profile row per user, synced from Auth | `better-supabase/blocks/profiles` | `profiles` |
204
+ | [Jobs](https://bettersupabase.com/docs/blocks/jobs): Supabase Queues jobs, cron, idempotency keys and a webhook inbox | `better-supabase/blocks/jobs` | `jobs`, `idempotency`, `webhook-inbox` |
205
+ | [Outbox](https://bettersupabase.com/docs/blocks/outbox): transactional events with consumer cursors, relayed as CloudEvents | `better-supabase/blocks/outbox` | `outbox` |
206
+ | [Notifications](https://bettersupabase.com/docs/blocks/notifications): sending, listing and delivering notifications, and `useNotifications` for a live list | `better-supabase/blocks/notifications`, `better-supabase/blocks/notifications/react` | `notifications` |
207
+ | [Inbox](https://bettersupabase.com/docs/blocks/inbox): shared inboxes with conversations, assignment, notes, read receipts and channel delivery, plus `useInbox` and a chat widget | `better-supabase/blocks/inbox`, `better-supabase/blocks/inbox/react` | `inbox`, `chat-sdk-state` |
208
+ | [Webhooks](https://bettersupabase.com/docs/blocks/webhooks-out): Standard Webhooks, verifying incoming ones and delivering outgoing ones | `better-supabase/blocks/webhooks` | `webhooks-out` |
209
+ | [API keys](https://bettersupabase.com/docs/blocks/api-keys): hashed keys per tenant and per user, with scopes, rotation, expiry and an `apiKey` caller in every adapter | `better-supabase/blocks/api-keys` | `api-keys` |
210
+ | [Audit log](https://bettersupabase.com/docs/blocks/audit): list, filter, export as NDJSON or OCSF, and purge per tenant | `better-supabase/blocks/audit` | `audit` |
211
+ | [Settings](https://bettersupabase.com/docs/blocks/settings): typed settings per user and per organization, validated with Standard Schema | `better-supabase/blocks/settings` | `settings` |
212
+ | [Usage](https://bettersupabase.com/docs/blocks/usage): idempotent usage counters, quotas in RLS and RPCs, and Stripe meter reporting | `better-supabase/blocks/usage` | `usage` |
213
+ | [Billing](https://bettersupabase.com/docs/blocks/billing): Stripe Checkout, the customer portal, seat sync and webhook handling | `better-supabase/blocks/billing` | `billing` |
214
+ | [Feature flags](https://bettersupabase.com/docs/blocks/flags): targeting rules, overrides and rollouts, evaluated in RLS and in an OpenFeature-shaped provider | `better-supabase/blocks/flags` | `flags` |
215
+ | [Comments](https://bettersupabase.com/docs/blocks/comments): threaded comments with mentions, and an activity feed from the outbox | `better-supabase/blocks/comments` | `comments` |
216
+ | [Attachments](https://bettersupabase.com/docs/blocks/attachments): files linked to records, signed uploads and downloads, and a malware scan gate | `better-supabase/blocks/attachments` | `attachments` |
217
+ | [Data lifecycle](https://bettersupabase.com/docs/blocks/data-lifecycle): data exports and organization deletion with a grace period | `better-supabase/blocks/data-lifecycle` | `data-lifecycle` |
218
+ | [SSO](https://bettersupabase.com/docs/blocks/sso): verified domains, SAML per organization, SSO enforcement and SCIM 2.0 | `better-supabase/blocks/sso` | `sso` |
219
+ | [Onboarding](https://bettersupabase.com/docs/blocks/onboarding): checklists per user or organization, and `useOnboarding` | `better-supabase/blocks/onboarding`, `better-supabase/blocks/onboarding/react` | `onboarding` |
220
+ | [Waitlist](https://bettersupabase.com/docs/blocks/waitlist): a waitlist with approvals, hashed invite codes and an invite-only sign-up hook | `better-supabase/blocks/waitlist` | `waitlist` |
221
+ | [Announcements](https://bettersupabase.com/docs/blocks/announcements): in-app announcements by audience and time window, and `useAnnouncements` | `better-supabase/blocks/announcements`, `better-supabase/blocks/announcements/react` | `announcements` |
222
+ | [AI chat](https://bettersupabase.com/docs/blocks/ai-chat): chats with branches, shares, a model catalog, moderation and runs, in the canonical message format, and `useAiChats` | `better-supabase/blocks/ai-chat`, `better-supabase/blocks/ai-chat/react` | `ai-chat` |
223
+ | [AI files](https://bettersupabase.com/docs/blocks/ai-files): attachments and generated files in a private bucket, provider file references and versioned documents with suggested edits | `better-supabase/blocks/ai-files` | `ai-files` |
224
+ | [Knowledge](https://bettersupabase.com/docs/blocks/knowledge): documents chunked and embedded per organization, user, agent or chat, and hybrid search | `better-supabase/blocks/knowledge` | `knowledge` |
225
+ | [Memory](https://bettersupabase.com/docs/blocks/memory): memory files, archival facts and message recall per user, agent or chat | `better-supabase/blocks/memory` | `memory` |
226
+ | [Agents](https://bettersupabase.com/docs/blocks/agents): custom assistants with instructions, tools, knowledge and starters, a gallery with installs and ratings | `better-supabase/blocks/agents` | `agents` |
227
+ | [Connectors](https://bettersupabase.com/docs/blocks/connectors): MCP servers per organization, per-user grants behind a `credential_ref`, sessions and tool fingerprints | `better-supabase/blocks/connectors` | `connectors` |
228
+ | [AI tasks](https://bettersupabase.com/docs/blocks/ai-tasks): scheduled prompts that run an agent on a cron and record each run | `better-supabase/blocks/ai-tasks` | `ai-tasks` |
229
+ | [Push notifications](https://bettersupabase.com/docs/blocks/push): device tokens with RLS, Expo registration and an Expo Push API sender | `better-supabase/blocks/push` | `push` |
230
+ | [AI cache](https://bettersupabase.com/docs/blocks/ai-cache): model responses cached by key with a capped TTL and a purge job | `better-supabase/blocks/ai-cache` | `ai-cache` |
231
+ | [AI providers](https://bettersupabase.com/docs/blocks/ai-providers): per-tenant provider keys as credential refs, batch jobs and sandboxes with an idle stop | `better-supabase/blocks/ai-providers` | `ai-providers` |
232
+ | [Workflows](https://bettersupabase.com/docs/blocks/workflows): a run registry for any engine, schedules, semaphores, admission control, and `useWorkflowRuns` | `better-supabase/blocks/workflows`, `better-supabase/blocks/workflows/react` | `workflows`, `workflow-sdk-world` |
233
+ | [Workflow builder](https://bettersupabase.com/docs/blocks/workflow-builder): graph workflows members edit and publish, triggers, credentials, node run status and alerts | `better-supabase/blocks/workflow-builder`, `better-supabase/blocks/workflow-builder/react` | `workflow-builder` |
234
+ | [Entitlements](https://bettersupabase.com/docs/blocks/entitlements): Stripe entitlements per tenant, `hasEntitlement` and the members of a plan change | `better-supabase/blocks/entitlements` | `entitlements` |
235
+ | [Vector search](https://bettersupabase.com/docs/blocks/vector-search): `search_<table>` functions over embedding columns, called with `db.$search` | SQL only | `vector-search` |
236
+
237
+ The other SQL modules (`updated-at`, `actor`, `rate-limit`, `support-sessions` and the rest) are listed on the [SQL modules page](https://bettersupabase.com/docs/blocks/sql), and the [roadmap](https://bettersupabase.com/docs/roadmap) lists what comes next.
238
+
239
+ ## Works with
240
+
241
+ | Area | Supported |
242
+ | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
243
+ | Frameworks | Next.js 16, Hono, oRPC, Expo Router, TanStack Start, SvelteKit, React Router, H3 and Nitro, Nuxt, Elysia, Node (`node:http`, Express, Fastify, Koa), NestJS, Astro, SolidStart, Supabase Edge Functions, MCP servers |
244
+ | Runtimes | Node.js, Deno, Bun, Cloudflare Workers, Vercel Functions, Supabase Edge |
245
+ | Frontend | React 19, React Native and Expo, Vue, Solid, Svelte 5, TanStack Query 5, TanStack DB, live queries over Realtime |
246
+ | Local data | PowerSync, expo-sqlite |
247
+ | AI | AI SDK, Chat SDK, eve, Workflow SDK, MCP |
248
+ | Validation | Zod, Valibot and any Standard Schema |
249
+ | Standards | OpenAPI 3.1, RFC 9457, OpenTelemetry, CloudEvents, Standard Webhooks, MCP |
250
+ | Testing | Vitest, pgTAP, the Supabase local stack |
251
+
252
+ ## Good to know
253
+
254
+ - **It does not replace supabase-js.** Auth flows, Storage and Realtime stay on the supabase-js client, which is one property away as `db.$client`.
255
+ - **It does not replace RLS.** Queries run as the caller and your policies decide. Bypassing them takes an explicit `bs.admin()`.
256
+ - **A direct Postgres connection is optional.** Queries go through PostgREST by default. [`better-supabase/postgres`](https://bettersupabase.com/docs/auth/postgres) runs the same repository API over SQL for jobs, scripts and transactions.
257
+ - **PostgREST's limits still apply.** There are no transactions across requests, and a few filters only work on reads. The [limitations page](https://bettersupabase.com/docs/guides/limitations) lists each one and what to use instead.
258
+
50
259
  ## Subpaths
51
260
 
52
- | Import | What it gives you |
53
- | ---------------------------------------------------------- | ------------------------------------------------------------------------ |
54
- | `better-supabase` | `defineSupabase`, repositories, `Result`, `DbError`, `SPEC_PINS` |
55
- | `better-supabase/config` | `defineConfig` and generators for `better-supabase.config.ts` |
56
- | `better-supabase/cli` | `run`, `registerCommand` and codegen for scripts that drive the CLI |
57
- | `better-supabase/client` | Browser repositories that follow the session |
58
- | `better-supabase/react` | Provider, typed hooks and the server session |
59
- | `better-supabase/query` | TanStack Query options with table-based invalidation |
60
- | `better-supabase/server` | Repositories bound to the caller, admin and acting-as identities |
61
- | `better-supabase/postgres` | The same repositories over direct Postgres |
62
- | `better-supabase/ssr` | The `@supabase/ssr` cookie format for any framework |
63
- | `better-supabase/next`, `/next/image` | Proxy, Server Components, route handlers, server actions, Storage images |
64
- | `better-supabase/hono`, `/orpc`, `/edge` | Framework adapters |
65
- | `better-supabase/mcp` | MCP servers whose tools run as the signed-in user |
66
- | `better-supabase/jobs` | Supabase Queues jobs, idempotency keys and a webhook inbox |
67
- | `better-supabase/orgs` | Organizations, members, invitations and switching from the SQL kit |
68
- | `better-supabase/notifications` | Sending, listing and delivering notifications from the SQL kit |
69
- | `better-supabase/list` | Search, facets, sorting and pagination from one definition |
70
- | `better-supabase/storage`, `/realtime` | Typed bucket paths and broadcast topics |
71
- | `better-supabase/env` | Validated Supabase settings |
72
- | `better-supabase/events`, `/webhooks`, `/openapi`, `/otel` | CloudEvents, Standard Webhooks, OpenAPI 3.1 and OpenTelemetry |
73
- | `better-supabase/plugins/*` | Timestamps, soft delete, tenant, actor, validation and runtime rules |
74
- | `better-supabase/sql` | The SQL kit modules and read-set compiler behind `better-supabase sql` |
75
- | `better-supabase/lint` | Editor rules for unbounded reads and unscoped deletes |
76
- | `better-supabase/testing` | `asUser`, `localAuth`, typed seeds and conformance kits |
261
+ The package has one entry per feature, so an app only loads what it imports. Every subpath is listed below, grouped by area. In a cell with several imports, `/name` is short for `better-supabase/name`.
262
+
263
+ ### Core
264
+
265
+ | Import | What it gives you |
266
+ | ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ |
267
+ | `better-supabase` | `defineSupabase`, repositories, `Result`, `DbError`, `SPEC_PINS` |
268
+ | `better-supabase/config` | `defineConfig` and generators for `better-supabase.config.ts` |
269
+ | `better-supabase/server` | Repositories bound to the caller, admin and acting-as identities |
270
+ | `better-supabase/postgres` | The same repositories over direct Postgres |
271
+ | `better-supabase/env` | Validated Supabase settings |
272
+ | `better-supabase/list` | Search, facets, sorting and pagination from one definition |
273
+ | `better-supabase/storage`, `/realtime` | Typed buckets (paths, versions, vector, analytics) and broadcast topics |
274
+ | `better-supabase/plugins/timestamps`, `/plugins/soft-delete`, `/plugins/tenant`, `/plugins/actor`, `/plugins/validation`, `/plugins/rules` | Timestamps, soft delete, tenant scoping, actor columns, validation and runtime rules |
275
+ | `better-supabase/sql` | The SQL modules and read-set compiler behind `better-supabase sql` |
276
+ | `better-supabase/lint` | Editor rules for unbounded reads and unscoped deletes |
277
+ | `better-supabase/cli` | `run`, `registerCommand` and codegen for scripts that drive the CLI |
278
+ | `better-supabase/testing` | `asUser`, `localAuth`, typed seeds and conformance kits |
279
+ | `better-supabase/events`, `/openapi`, `/otel` | CloudEvents, OpenAPI 3.1 and OpenTelemetry |
280
+
281
+ ### Frontend and local data
282
+
283
+ | Import | What it gives you |
284
+ | ----------------------------------------------- | ---------------------------------------------------------------------------------------------- |
285
+ | `better-supabase/client` | Browser repositories that follow the session |
286
+ | `better-supabase/client/native` | The same for React Native, without `@supabase/ssr`, and keychain storage |
287
+ | `better-supabase/react` | Provider, typed hooks and the server session |
288
+ | `better-supabase/react/native` | OAuth, auth deep links, a protected route hook and `AuthGate` for Expo |
289
+ | `better-supabase/query` | TanStack Query options with table-based invalidation |
290
+ | `better-supabase/tanstack-db` | TanStack DB collections that load through a query and write through the repositories |
291
+ | `better-supabase/vue`, `/solid`, `/svelte` | Live queries, presence, actions and the session for Vue, Solid and Svelte 5 |
292
+ | `better-supabase/powersync`, `/powersync/react` | The repositories over PowerSync's local SQLite, `useWatch`, `useSyncStatus` and `useConflicts` |
293
+ | `better-supabase/expo-sqlite` | The same repositories over a local expo-sqlite database, with live queries |
294
+
295
+ ### Server adapters
296
+
297
+ | Import | What it gives you |
298
+ | ----------------------------------------------------- | ------------------------------------------------------------------------------------------- |
299
+ | `better-supabase/ssr` | The `@supabase/ssr` cookie format for any framework |
300
+ | `better-supabase/next`, `/next/image`, `/next/client` | Proxy, Server Components, route handlers, Storage images, session-change hook |
301
+ | `better-supabase/hono`, `/orpc` | Hono middleware and REST resources, and an oRPC middleware |
302
+ | `better-supabase/edge` | Fetch handlers for Supabase Edge Functions, Deno, Bun and Workers |
303
+ | `better-supabase/expo` | Expo Router server loaders, API routes and middleware |
304
+ | `better-supabase/tanstack-start`, `/sveltekit` | TanStack Start request middleware and a SvelteKit `handle` hook |
305
+ | `better-supabase/react-router`, `/h3`, `/elysia` | Middleware for React Router, H3 2 and Elysia |
306
+ | `better-supabase/h3/v1`, `/nuxt` | Middleware for Nitro 2, and a Nuxt module that registers it |
307
+ | `better-supabase/node`, `/nestjs` | Node `http`, Express, Fastify, Koa and NestJS |
308
+ | `better-supabase/astro`, `/solid-start` | Astro middleware, Actions and images; SolidStart middleware and actions |
309
+ | `better-supabase/mcp`, `/mcp/sdk` | MCP servers whose tools run as the signed-in user, and bearer auth for the official MCP SDK |
310
+
311
+ ### AI and agents
312
+
313
+ | Import | What it gives you |
314
+ | ----------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
315
+ | `better-supabase/ai-sdk` | AI SDK message converters, gateway usage attribution and the model catalog |
316
+ | `better-supabase/ai-sdk/chat`, `/ai-sdk/react` | `createAssistant` for a chat route and `useAssistant` on the client |
317
+ | `better-supabase/ai-sdk/files`, `/ai-sdk/cache` | File parts from Storage and generated files, and a middleware that answers from the AI cache |
318
+ | `better-supabase/ai-sdk/batches` | AI SDK batches per tenant, polled from a job, with results in Postgres |
319
+ | `better-supabase/ai-sdk/embeddings`, `/ai-sdk/memory` | Embedders, reranking and a knowledge search tool; memory and recall tools and fact extraction |
320
+ | `better-supabase/ai-sdk/agents`, `/ai-sdk/mcp` | A `ToolLoopAgent` from a stored agent with moderation, and MCP connections authorized through OAuth |
321
+ | `better-supabase/ai-sdk/workflow`, `/ai-sdk/workflow/react` | Durable chat on the Workflow SDK with `durableChat`, `durableTurn` and `useDurableAssistant` |
322
+ | `better-supabase/chat-sdk`, `/chat-sdk/react` | Chat SDK state in Postgres, the inbox adapter and channel webhooks |
323
+ | `better-supabase/eve` | eve on Supabase: route auth, connections over credential providers, memory, sessions and the inbox channel (Node) |
324
+
325
+ ### Workflows, streams and credentials
326
+
327
+ | Import | What it gives you |
328
+ | ----------------------------------------------------- | ----------------------------------------------------------------------------------- |
329
+ | `better-supabase/workflow-sdk`, `/workflow-sdk/world` | Workflow SDK helpers bound to the caller, and a World on Supabase (Node) |
330
+ | `better-supabase/workflow-sdk/builder` | Compiles workflow builder graphs to Workflow SDK workflows and starts them |
331
+ | `better-supabase/streams`, `/streams/redis` | Resumable output for chats, workflows and agents, in Postgres or Redis |
332
+ | `better-supabase/credentials`, `/vercel-connect` | Third-party tokens behind a `credential_ref`, over Supabase Vault or Vercel Connect |
333
+
334
+ The 40 `better-supabase/blocks/*` subpaths are listed under [Blocks](#blocks).
77
335
 
78
336
  ## For AI agents
79
337
 
80
- The package ships [Agent Skills](https://agentskills.io) in `skills/`:
338
+ The package ships [Agent Skills](https://agentskills.io) for queries, APIs, auth and tests:
81
339
 
82
340
  ```bash
83
341
  npx skills add ScaleDockHQ/better-supabase
@@ -85,12 +343,12 @@ npx skills add ScaleDockHQ/better-supabase
85
343
  pnpm better-supabase skills install
86
344
  ```
87
345
 
88
- The docs are also available as [`/llms.txt`](https://bettersupabase.com/llms.txt), as Markdown at `/docs/<page>.md`, and through the docs MCP server at `https://bettersupabase.com/mcp`.
346
+ The docs are also available as [`/llms.txt`](https://bettersupabase.com/llms.txt), as Markdown at `/docs/<page>.md`, and through the read-only docs MCP server at `https://bettersupabase.com/mcp`.
89
347
 
90
348
  ## Documentation
91
349
 
92
- [bettersupabase.com/docs](https://bettersupabase.com/docs)
350
+ The full documentation is at [bettersupabase.com/docs](https://bettersupabase.com/docs), and a runnable app for every adapter is in [`apps/examples`](https://github.com/ScaleDockHQ/better-supabase/tree/main/apps/examples).
93
351
 
94
352
  ## License
95
353
 
96
- [MIT](https://github.com/ScaleDockHQ/better-supabase/blob/main/LICENSE)
354
+ [MIT](https://github.com/ScaleDockHQ/better-supabase/blob/main/LICENSE) © 2026 ScaleDock
@@ -0,0 +1,181 @@
1
+ import { i as sqlString } from "./template--jDkl3UP.js";
2
+ //#region src/core/access-sql.ts
3
+ const SCOPE = /^[a-z][a-z0-9_]*$/;
4
+ /** Whether `name` can be a scope: it is put unquoted into templates. */
5
+ const isScopeName = (name) => SCOPE.test(name);
6
+ /** The placeholders each authorization template may use. */
7
+ const TEMPLATE_PLACEHOLDERS = {
8
+ idsWith: ["permission", "scope"],
9
+ isPlatform: ["permission"],
10
+ idsWithFor: [
11
+ "user",
12
+ "permission",
13
+ "scope"
14
+ ],
15
+ isPlatformFor: ["user", "permission"],
16
+ memberIds: ["scope"],
17
+ memberIdsFor: ["user", "scope"],
18
+ canAssign: [
19
+ "role",
20
+ "tenant",
21
+ "scope"
22
+ ],
23
+ canAssignFor: [
24
+ "user",
25
+ "role",
26
+ "tenant",
27
+ "scope"
28
+ ],
29
+ permissionsFor: [
30
+ "user",
31
+ "tenant",
32
+ "scope"
33
+ ],
34
+ canApprove: [
35
+ "tool",
36
+ "tenant",
37
+ "scope"
38
+ ]
39
+ };
40
+ /** The Postgres types a scope's ids can have. */
41
+ const SCOPE_ID_TYPES = [
42
+ "uuid",
43
+ "text",
44
+ "bigint",
45
+ "integer"
46
+ ];
47
+ /**
48
+ * What is wrong with a provider's scopes: an unknown tenant scope or
49
+ * parent, a parent cycle, an id type outside `SCOPE_ID_TYPES`, or a tenant
50
+ * scope without one.
51
+ */
52
+ function scopeProblems(provider) {
53
+ const problems = [];
54
+ const byName = new Map(provider.scopes.map((scope) => [scope.name, scope]));
55
+ for (const scope of provider.scopes) {
56
+ if (scope.idType !== void 0 && !SCOPE_ID_TYPES.includes(scope.idType)) problems.push(`scope "${scope.name}" has idType "${scope.idType}"; use ${SCOPE_ID_TYPES.join(", ")}`);
57
+ if (scope.parent !== void 0 && !byName.has(scope.parent)) problems.push(`scope "${scope.name}" has parent "${scope.parent}", which is not a scope`);
58
+ }
59
+ const cyclic = /* @__PURE__ */ new Set();
60
+ for (const scope of provider.scopes) {
61
+ const seen = /* @__PURE__ */ new Set();
62
+ let current = scope.name;
63
+ while (current !== void 0 && !seen.has(current)) {
64
+ seen.add(current);
65
+ current = byName.get(current)?.parent;
66
+ }
67
+ if (current !== void 0 && !cyclic.has(current)) {
68
+ for (const name of seen) cyclic.add(name);
69
+ problems.push(`scope "${current}" is its own ancestor (a parent cycle)`);
70
+ }
71
+ }
72
+ const tenant = byName.get(provider.tenantScope);
73
+ if (tenant === void 0) problems.push(`tenantScope "${provider.tenantScope}" is not a scope`);
74
+ else if (tenant.idType === void 0) problems.push(`tenant scope "${tenant.name}" has no idType`);
75
+ return problems;
76
+ }
77
+ const CALL_KEYWORDS = /* @__PURE__ */ new Set([
78
+ "all",
79
+ "and",
80
+ "any",
81
+ "array",
82
+ "as",
83
+ "cast",
84
+ "coalesce",
85
+ "exists",
86
+ "from",
87
+ "greatest",
88
+ "in",
89
+ "is",
90
+ "least",
91
+ "not",
92
+ "nullif",
93
+ "on",
94
+ "or",
95
+ "row",
96
+ "select",
97
+ "some",
98
+ "values",
99
+ "when",
100
+ "where"
101
+ ]);
102
+ /**
103
+ * What makes a template unsafe to put into generated SQL: a `$$`, `;` or
104
+ * `--` (outside string literals), or a function call without a schema.
105
+ */
106
+ function templateProblems(template) {
107
+ const code = template.replaceAll(/'(?:[^']|'')*'/g, "''").replaceAll(/\{(\w+)\}/g, "$1");
108
+ const problems = [];
109
+ for (const token of [
110
+ "$$",
111
+ ";",
112
+ "--"
113
+ ]) if (code.includes(token)) problems.push(`contains "${token}"`);
114
+ for (const match of code.matchAll(/(?<![\w$.":])"?([a-z_][\w$]*)"?\s*\(/gi)) {
115
+ const name = match[1];
116
+ if (CALL_KEYWORDS.has(name.toLowerCase())) continue;
117
+ problems.push(`calls ${name}() without a schema`);
118
+ }
119
+ return problems;
120
+ }
121
+ /** The `{name}` placeholders in a template. */
122
+ const templatePlaceholders = (template) => [...new Set([...template.matchAll(/\{(\w+)\}/g)].map((match) => match[1]))];
123
+ /**
124
+ * Fills a template's `{name}` placeholders. `where` names the setting in
125
+ * the error for a placeholder `values` doesn't have.
126
+ */
127
+ function fillTemplate(where, template, values) {
128
+ return template.replaceAll(/\{(\w+)\}/g, (match, name) => {
129
+ const value = values[name];
130
+ if (value === void 0) throw new TypeError(`${where}: ${match} is not available here. Use ${Object.keys(values).map((key) => `{${key}}`).join(", ")}`);
131
+ return value;
132
+ });
133
+ }
134
+ /** The `schema.name` of every schema-qualified function a template calls, with `{scope}` filled. */
135
+ function templateFunctions(template, scope) {
136
+ const filled = scope === void 0 ? template : template.replaceAll("{scope}", scope);
137
+ return [...new Set([...filled.matchAll(/(?<![\w$."])"?([a-z_][\w$]*)"?\s*\.\s*"?([a-z_][\w${}]*)"?\s*\(/gi)].map((match) => `${match[1]}.${match[2]}`))];
138
+ }
139
+ /**
140
+ * `target` with `sql: "provider"` replaced by the provider's `idsWith` and
141
+ * `isPlatform`. `where` names the policy in the error when there is no
142
+ * provider.
143
+ */
144
+ function resolveProviderSql(where, target, functions) {
145
+ if (target.sql !== "provider") return target;
146
+ if (functions === void 0) throw new TypeError(`${where}: sql "provider" needs \`authorization\` in better-supabase.config.ts`);
147
+ return {
148
+ ...target,
149
+ sql: {
150
+ idsWith: functions.idsWith,
151
+ isPlatform: functions.isPlatform
152
+ }
153
+ };
154
+ }
155
+ /**
156
+ * The SQL condition for one permission key of an access policy. `id` is the
157
+ * text expression holding the scope id, compared as text so a malformed path
158
+ * never raises a cast error. Without `sql` it calls the access contract
159
+ * (`tenant_ids_with`, `is_platform`); with it, the templates.
160
+ */
161
+ function accessCheck(where, target, key, id) {
162
+ if (key === "") throw new TypeError(`${where}: a permission key is empty`);
163
+ const scope = target.scope ?? "tenant";
164
+ const permission = sqlString(key);
165
+ if (target.sql === "provider") throw new TypeError(`${where}: sql "provider" needs the config's authorization provider; write the policy with \`better-supabase gen\` or pass its templates`);
166
+ if (!target.sql) {
167
+ if (scope === "platform") return `(select better_supabase.is_platform(${permission}))`;
168
+ if (scope !== "tenant") throw new TypeError(`${where}: scope "${scope}" needs sql templates; without them use "tenant" or "platform"`);
169
+ if (id === void 0) throw new TypeError(`${where}: scope "tenant" needs a segment`);
170
+ return `${id} in (select t::text from better_supabase.tenant_ids_with(${permission}) t)`;
171
+ }
172
+ if (scope === "platform") return `(select ${fillTemplate(`${where} sql.isPlatform`, target.sql.isPlatform, { permission })})`;
173
+ if (!isScopeName(scope)) throw new TypeError(`${where}: invalid scope "${scope}"`);
174
+ if (id === void 0) throw new TypeError(`${where}: scope "${scope}" needs a segment`);
175
+ return `${id} in (select t.id::text from ${fillTemplate(`${where} sql.idsWith`, target.sql.idsWith, {
176
+ permission,
177
+ scope
178
+ })} as t(id))`;
179
+ }
180
+ //#endregion
181
+ export { isScopeName as a, templateFunctions as c, fillTemplate as i, templatePlaceholders as l, TEMPLATE_PLACEHOLDERS as n, resolveProviderSql as o, accessCheck as r, scopeProblems as s, SCOPE_ID_TYPES as t, templateProblems as u };