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
@@ -67,6 +67,7 @@
67
67
  "BS219",
68
68
  "BS220",
69
69
  "BS221",
70
+ "BS222",
70
71
  "BS301",
71
72
  "BS302",
72
73
  "BS303",
@@ -81,6 +82,19 @@
81
82
  "BS312",
82
83
  "BS313",
83
84
  "BS314",
85
+ "BS315",
86
+ "BS316",
87
+ "BS317",
88
+ "BS318",
89
+ "BS319",
90
+ "BS320",
91
+ "BS321",
92
+ "BS322",
93
+ "BS323",
94
+ "BS324",
95
+ "BS325",
96
+ "BS326",
97
+ "BS327",
84
98
  "BS401",
85
99
  "BS402",
86
100
  "BS403",
@@ -91,6 +105,8 @@
91
105
  "BS408",
92
106
  "BS409",
93
107
  "BS410",
108
+ "BS411",
109
+ "BS412",
94
110
  "BS501",
95
111
  "BS502"
96
112
  ]
@@ -121,7 +137,11 @@
121
137
  "properties": {
122
138
  "kind": { "enum": ["table", "function", "policy"] },
123
139
  "schema": { "type": "string" },
124
- "name": { "type": "string" }
140
+ "name": { "type": "string" },
141
+ "table": {
142
+ "description": "The table a policy is on.",
143
+ "type": "string"
144
+ }
125
145
  }
126
146
  },
127
147
  "help": { "type": "string", "format": "uri" }
@@ -633,6 +633,14 @@
633
633
  "items": {
634
634
  "type": "string"
635
635
  }
636
+ },
637
+ "versioning": {
638
+ "description": "storage.buckets.versioning_status; absent when Storage has no versioning.",
639
+ "enum": ["DISABLED", "ENABLED", "SUSPENDED", null]
640
+ },
641
+ "lifecycle": {
642
+ "description": "storage.buckets.lifecycle_configuration; absent when Storage has no lifecycles.",
643
+ "type": ["object", "null"]
636
644
  }
637
645
  }
638
646
  }
@@ -16,15 +16,15 @@ is no separate CLI package to add.
16
16
  ## Workflow: change the schema
17
17
 
18
18
  1. Write the migration: edit `supabase/schemas/*.sql`, then run
19
- `supabase db schema declarative sync -f <name>` (pg-delta;
20
- `supabase db diff -f <name>` when `config.toml` has no
21
- `[experimental.pgdelta] enabled = true`), or `supabase migration new` for
22
- data and role settings.
19
+ `supabase db schema declarative sync -f <name>`, or `supabase migration
20
+ new` for data and role settings. The sync needs
21
+ `[experimental.pgdelta] enabled = true` in `supabase/config.toml`;
22
+ doctor reports BS316 when a project is still on the legacy migra engine.
23
23
  2. For a new table in an exposed schema, in the same file: `enable row level
24
24
  security`, a policy per role and command the app uses, and an index on
25
25
  every column a policy filters by. Write tenant checks as
26
- `organization_id in (select better_supabase.member_org_ids())`, which
27
- Postgres runs once per statement, not `has_org_role(organization_id)`,
26
+ `organization_id in (select better_supabase.member_organization_ids())`, which
27
+ Postgres runs once per statement, not `has_organization_role(organization_id)`,
28
28
  which runs once per row. List the table in `expose` in
29
29
  `better-supabase.config.ts` and run `pnpm better-supabase sql add grants`:
30
30
  new tables get no Data API grants on their own.
@@ -56,7 +56,7 @@ stay hidden.
56
56
  1. Run `pnpm better-supabase codemod <version> --dry-run` for each minor
57
57
  version you crossed (`codemod` without a name lists them), then without
58
58
  `--dry-run`, and fix the lines it lists for review.
59
- 2. Run `pnpm better-supabase sql upgrade`, so the kit modules get the
59
+ 2. Run `pnpm better-supabase sql upgrade`, so the SQL modules get the
60
60
  release's SQL and any forward steps land in a migration, then write a
61
61
  migration from the changed files.
62
62
  3. Run `pnpm better-supabase gen` and commit the result. Since 0.3, a
@@ -65,9 +65,11 @@ stay hidden.
65
65
  the config to keep an old relation name.
66
66
  4. Run `pnpm better-supabase skills install --check` and reinstall the skills
67
67
  when it reports them stale.
68
- 5. Read the release's breaking changes in
69
- https://github.com/ScaleDockHQ/better-supabase/blob/main/CHANGELOG.md
70
- (guides live under https://bettersupabase.com/docs/migration). For 0.3: time values are
68
+ 5. Read the release's guide: https://bettersupabase.com/docs/migration/0.5-to-0.6
69
+ for 0.6 (kits are blocks, feature modules import from
70
+ `better-supabase/blocks/<name>`), and the other versions at
71
+ https://bettersupabase.com/docs/migration. Every breaking change is in
72
+ https://github.com/ScaleDockHQ/better-supabase/blob/main/CHANGELOG.md. For 0.3: time values are
71
73
  `Temporal` (see below), `--db-url` is gone, `doctor --format json` is
72
74
  `doctor --json`, `BetterResultShape` is `BetterResultValue`, and an
73
75
  exhaustive `switch` over the `invalid` auth reason needs an `'actor'` case.
@@ -80,14 +82,40 @@ Name the definition `betterSupabase` (in `lib/supabase/index.ts`) and every runt
80
82
 
81
83
  - Next.js: `const { db } = await bs.context()`, `bs.route(...)`, `bs.action(...)`
82
84
  - Next.js Cache Components: keep layouts synchronous; read `bs.session()` in a `'use cache: private'` function inside `<Suspense>`, pass the promise to `<SessionProvider>` and read it with `useSession()`
85
+ - Next.js with the tenant in the route (`/[organizationId]/...`): `bs.context({ tenant: organizationId })`, `bs.cached({ tenant })` inside a `'use cache: private'` function that takes the tenant as an argument, and `bs.action({ input, tenant: (input) => input.organizationId }, fn)`. The tenant gets the resolver's membership checks. Client Components get the id as a prop and pass it to actions and to `useLiveQuery(spec, { tenant })`; the browser client only knows the claim's tenant
83
86
  - Hono: `c.var.db` after `bs.middleware()`
84
87
  - oRPC: `context.db` after `bs.middleware()`
85
88
  - Edge Functions: `bs.handler((request, { db }) => ...)`
89
+ - Express: `res.locals.db`; Fastify: `request.locals.db`; Koa: `ctx.state.db`; NestJS: `@Ctx("db")`
90
+ - SvelteKit: `event.locals.db`; H3, Nitro and Nuxt: `event.context.db`; TanStack Start: the middleware `context.db`
91
+ - Astro: `bs.locals(Astro).db`; SolidStart: `(await bs.require()).db`
86
92
  - Browser: `bs.db`, or the hooks from `createHooks<typeof bs>()`
93
+ - Vue, Solid and Svelte, TanStack DB collections and a local expo-sqlite database: [references/frontend.md](references/frontend.md)
87
94
 
88
95
  For who the caller is (sessions, claims, OAuth clients, agents, scopes), use
89
96
  the `better-supabase-auth` skill.
90
97
 
98
+ ## Forms and actions (Next.js)
99
+
100
+ - Put the permission check in the action's options, not its body:
101
+ `bs.action({ input, requireTenant: true, authorize: (session, input) => can(session, "members.invite") }, (input, { db, tenant, session }) => ...)`.
102
+ `requireTenant` types `tenant` as a string; a refusal is a `forbidden`
103
+ `ActionResult`. `bs.route(handler, { requireTenant, authorize })` takes the same.
104
+ - A form: `const form = useActionForm(action, { onSuccess })` from
105
+ `better-supabase/react`, then `<form {...form.formProps}>`, `form.pending`
106
+ and `form.fieldErrors.<field>`. Fields survive a failed submit. Pass
107
+ `resetOnSuccess: false` for edit forms.
108
+ - A button or row action: `const remove = useAction(action, { onError })`,
109
+ `remove.run(input)`, and `remove.pendingInputs` to mark the row in flight.
110
+ - Error copy: `createErrorMessages({ ...one entry per DbError kind })` from
111
+ `better-supabase`; a missing kind is a type error.
112
+ - A page only some callers may see: `await bs.require({ authorize })` throws
113
+ `forbidden()` or `unauthorized()` (needs `experimental.authInterrupts`).
114
+ Under Cache Components, check the privately cached session and call
115
+ `forbidden()` instead, so the page stays prefetchable.
116
+ - The active tenant of a session: `tenantOf(session)`, on the server and in
117
+ the browser.
118
+
91
119
  ## Querying
92
120
 
93
121
  ```ts
@@ -103,11 +131,12 @@ const customers = result.data;
103
131
  ```
104
132
 
105
133
  - Methods return a `Result`, and database errors never throw. Use `.orThrow()` only where an exception is really wanted.
134
+ - Apps on better-result: `toBetterResult(result, Result, mapError)` converts at the boundary, and `defineBetterResultErrors(Result, { not_found: NotFound }, DbFailure)` maps `DbError` kinds to `TaggedError` classes once. Annotate the expected `Result<T, E>` type instead of casting.
106
135
  - Column names use the configured casing (`casing: 'camel'` means `organizationId`). Raw escape hatches (`$client`, and `queryRaw` on the `better-supabase/postgres` clients) use database names.
107
136
  - Writes: `create`, `createMany`, `update(id, patch)`, `updateMany`, `upsert`, `delete`.
108
- - Page lists with a cursor: `paginate({ after: null, size: 25, orderBy })`, then pass `nextCursor` back as `after` with the same `orderBy` and `where`. Use `page` numbers only when users jump to a page and need a total.
137
+ - Page lists with a cursor: `paginate({ after: null, size: 25, orderBy })`, then pass `nextCursor` back as `after` with the same `orderBy` and `where`. Use `page` numbers only when users jump to a page and need a total, and `paginate({ offset, limit, count: 'exact' })` when the caller already has an offset; both return the rows and the total in one request.
109
138
  - Handlers may return a `Result` directly. Adapters turn errors into RFC 9457 Problem Details with the right status.
110
- - Server-only admin access: `bs.admin()`. Only use it for trusted jobs, never for a user's request.
139
+ - Jobs and webhooks run as a user so RLS applies: `bs.forContext(job.context)` for a job enqueued with `{ context: db.$context }`, `bs.actingAs(userId, { tenant_id })` for a webhook or script. `bs.admin()` bypasses RLS: use it only for work no user owns, never for a user's request.
111
140
  - PostgREST has no multi-request transactions. Put multi-step writes in a database function (`db.$rpc()`) or use `postgres.transaction()` on the server.
112
141
 
113
142
  ## Time values
@@ -0,0 +1,96 @@
1
+ # Vue, Solid, Svelte, TanStack DB and expo-sqlite
2
+
3
+ Each framework binding wraps the browser client `bs` from
4
+ `lib/supabase/client.ts` and the TanStack Query client for that framework.
5
+ Reads still go through PostgREST as the signed-in user, so RLS applies.
6
+
7
+ ## Vue
8
+
9
+ ```ts title="src/main.ts"
10
+ import { betterSupabase } from "better-supabase/vue";
11
+
12
+ createApp(App)
13
+ .use(VueQueryPlugin, { queryClient })
14
+ .use(betterSupabase(bs, { queryClient }))
15
+ .mount("#app");
16
+ ```
17
+
18
+ ```ts title="src/lib/composables.ts"
19
+ import { createBindings } from "better-supabase/vue";
20
+ import type { bs } from "./supabase/client";
21
+
22
+ export const { useDb, useQueries, useAuth, useSession } =
23
+ createBindings<typeof bs>();
24
+ ```
25
+
26
+ Use `useQuery(q.customers.findMany({ ... }))` from `@tanstack/vue-query`
27
+ with `const q = useQueries()`. `useLiveQuery`, `useLiveCount`,
28
+ `useBroadcast`, `usePresence` and `useAction` come from
29
+ `better-supabase/vue` directly.
30
+
31
+ ## Solid
32
+
33
+ Wrap the app in `<BetterSupabaseProvider client={bs} queryClient={queryClient}>`
34
+ inside `QueryClientProvider`, and get typed primitives from
35
+ `createBindings<typeof bs>()` in `better-supabase/solid`. Pass a function to
36
+ the live primitives, so they track their inputs:
37
+ `useLiveCount(() => betterSupabase.spec.messages.count({ where: { read: false } }))`.
38
+
39
+ ## Svelte 5
40
+
41
+ In the root `+layout.svelte`, call `setBetterSupabase(bs, { queryClient })`
42
+ and `setSession(() => data.session)` from `better-supabase/svelte`. In
43
+ components, `useAuth()`, `useLiveQuery(() => spec)` and `useLiveCount(() => spec)`
44
+ return objects whose fields are reactive (`auth.current.status`,
45
+ `unread.count`). Return `null` from the spec function to pause a query.
46
+
47
+ ## TanStack DB
48
+
49
+ ```ts
50
+ import { createCollection } from "@tanstack/react-db";
51
+ import { queryCollectionOptions } from "@tanstack/query-db-collection";
52
+ import { collectionOptions } from "better-supabase/tanstack-db";
53
+
54
+ export const customers = createCollection(
55
+ queryCollectionOptions(
56
+ collectionOptions(betterSupabase, db, "customers", {
57
+ query: queries.customers.findMany({ where: { status: "active" } }),
58
+ queryClient,
59
+ }),
60
+ ),
61
+ );
62
+ ```
63
+
64
+ The collection loads through the query and writes through the
65
+ repositories, so its inserts and updates run as the signed-in user.
66
+
67
+ ## expo-sqlite
68
+
69
+ Run the same repositories over a local database on the device, without
70
+ PowerSync:
71
+
72
+ ```ts
73
+ import { addDatabaseChangeListener, openDatabaseAsync } from "expo-sqlite";
74
+ import {
75
+ expoSqliteDatabase,
76
+ expoSqliteExecutor,
77
+ } from "better-supabase/expo-sqlite";
78
+
79
+ const sqlite = await openDatabaseAsync("app.db", {
80
+ enableChangeListener: true,
81
+ });
82
+ export const local = betterSupabase.connect(
83
+ expoSqliteExecutor(sqlite, { addDatabaseChangeListener }),
84
+ );
85
+ export const database = expoSqliteDatabase(sqlite, {
86
+ addDatabaseChangeListener,
87
+ });
88
+ ```
89
+
90
+ Keep a list live with `useWatch({ db: database, tables: ["notes"], query: () => local.notes.findMany(...) })`
91
+ from `better-supabase/powersync/react`. The local database has no RLS: it
92
+ holds only what this device's user synced or wrote.
93
+
94
+ Docs: https://bettersupabase.com/docs/frontend/vue.md (and `solid`,
95
+ `svelte`, `tanstack-db` under `/docs/frontend/`) and
96
+ https://bettersupabase.com/docs/repository/expo-sqlite.md.
@@ -54,14 +54,18 @@ RLS still decides what a user can read and write. `tenant()` makes queries
54
54
  explicit and fills the column; it doesn't replace the policy.
55
55
 
56
56
  The tenant comes from `context.tenant`, which the server's `tenant` resolver
57
- sets per request (the default `kits.access.activeTenant: 'resolver'`), then
57
+ sets per request (the default `sql.modules.access.activeTenant: 'resolver'`), then
58
58
  the verified `tenant_id` claim (renamed with `claims.tenant` in
59
59
  `better-supabase.config.ts`), then `app_metadata.tenant_id`. A resolver may
60
60
  read the URL, but `current_tenant_id()` only returns a tenant the caller is a
61
- member of. Never trust a tenant from `user_metadata` or a request body. When the project
62
- has a `permdock.config.ts`, PermDock's hook writes that claim and the
63
- memberships: don't run `sql add tenant`, and follow the PermDock reference of
64
- the `better-supabase-auth` skill
65
- (https://bettersupabase.com/docs/auth/permdock.md).
61
+ member of. In Next.js Server Components and actions there is no request URL:
62
+ pass the route's tenant with `bs.context({ tenant })`, `bs.cached({ tenant })`
63
+ or `bs.action({ tenant: (input) => input.organizationId })`, which take the
64
+ resolver's path and get the same check. Never trust a tenant from
65
+ `user_metadata`, and never use one from a request body outside those options. When the config
66
+ has an `authorization` provider whose hook owns `memberships`, that hook
67
+ writes the claim and the memberships: don't run `sql add tenant`, and follow
68
+ the authorization providers reference of the `better-supabase-auth` skill
69
+ (https://bettersupabase.com/docs/extending/authorization-providers.md).
66
70
 
67
71
  Docs: https://bettersupabase.com/docs/plugins.md
@@ -22,8 +22,9 @@ Branch on `result.error.kind`, not on the message.
22
22
  | `multiple_rows` | `findUnique` or a single-row write matched more than one row | Filter by a unique key |
23
23
  | `stale` | `update(..., { expect })` found a newer row | Reload the row and retry |
24
24
  | `serialization`, `timeout`, `network`, `rate_limited` | Transient | Retry with backoff, or surface the error |
25
+ | `unsupported` | The executor can't run the query, such as an include on SQLite (PowerSync) | Read it on the server, or check list definitions with `checkSqlite` in a test |
25
26
  | `raised` | A database function raised an exception | Read `message` and `code` from the function |
26
- | `unexpected` naming `temporal-polyfill/global` | The runtime has no `Temporal` (Node 24, Safari) | Install `temporal-polyfill` and import `temporal-polyfill/global` at startup |
27
+ | `unexpected` naming `temporal-polyfill/global` | The runtime has no `Temporal` (Node 24, Safari) | Pass `temporal: Temporal` from `temporal-polyfill` to `defineSupabase` |
27
28
 
28
29
  ## By error `code`
29
30
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: better-supabase-api
3
- description: Build HTTP APIs, Edge Functions and MCP servers on Supabase with better-supabase adapters. Use when adding a route, REST resource, oRPC procedure, Edge Function, MCP tool, OAuth or agent scopes, webhook, background job, cleanup cron or idempotent endpoint.
3
+ description: Build HTTP APIs, Edge Functions and MCP servers on Supabase with better-supabase adapters. Use when adding a route, REST resource, oRPC procedure, Edge Function, MCP tool, AI chat route, knowledge or memory, stored agent, MCP connector, eve agent, Chat SDK bot, resumable stream, third-party credential, OAuth or agent scopes, webhook, background job, cleanup cron or idempotent endpoint.
4
4
  ---
5
5
 
6
6
  # APIs with better-supabase
@@ -57,13 +57,23 @@ never limits it. RLS still decides the rows: the token's `sub` is the user.
57
57
 
58
58
  ## Adapters
59
59
 
60
- | Where | Setup | Handler |
61
- | -------------- | --------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
62
- | Next.js | `createNext(betterSupabase)` in `lib/supabase/server.ts` | `bs.route((req, { db }) => ...)`, `bs.action({ input: schema }, (input, { db }) => ...)` |
63
- | Hono | `createHono(betterSupabase)`, `.use('/api/*', bs.middleware())` | `c.var.db`; `bs.resource('customers', {...})` for REST |
64
- | oRPC | `createOrpc(betterSupabase)`, `base.use(bs.middleware())` | `bs.unwrap(context.db.customers.findMany(...))` |
65
- | Edge Functions | `createEdge(betterSupabase, { cors: true })` | `Deno.serve(bs.handler((req, { db }) => ...))` |
66
- | MCP | `createMcp(betterSupabase, { name, version, resources })` | `.tool({ name, input, run: (args, { db }) => ... })` |
60
+ | Where | Setup | Handler |
61
+ | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
62
+ | Next.js | `createNext(betterSupabase)` in `lib/supabase/server.ts` | `bs.route((req, { db }) => ...)`, `bs.action({ input: schema }, (input, { db }) => ...)` |
63
+ | Hono | `createHono(betterSupabase)`, `.use('/api/*', bs.middleware())` | `c.var.db`; `bs.resource('customers', {...})` for REST |
64
+ | oRPC | `createOrpc(betterSupabase)`, `base.use(bs.middleware())` | `bs.unwrap(context.db.customers.findMany(...))` |
65
+ | Expo Router | `createExpo(betterSupabase)`, `+middleware.ts` with `bs.middleware()` | `export const loader = bs.loader(({ db }) => ...)`, `bs.handler(...)` in `+api.ts` |
66
+ | Edge Functions | `createEdge(betterSupabase, { cors: true })` | `Deno.serve(bs.handler((req, { db }) => ...))` |
67
+ | MCP | `createMcp(betterSupabase, { name, version, resources })` | `.tool({ name, input, run: (args, { db }) => ... })` |
68
+ | Node, Express, Fastify, Koa | `toNodeHandler`, `toExpress`, `toFastify`, `toKoa` from `better-supabase/node` | `res.locals.db`, `request.locals.db`, `ctx.state.db`; `guard`, `fastifyGuard`, `koaGuard` |
69
+ | NestJS | `toNestMiddleware(entries)` from `better-supabase/nestjs` | `@Ctx("db") db`, `@UseGuards(guard({ roles }))`, `@UseFilters(problemFilter())` |
70
+ | Astro | `createAstro(betterSupabase)`, `export const onRequest = bs.onRequest` | `bs.locals(Astro).db`, `bs.guard(Astro, options)`, `bs.action(...)` |
71
+ | SolidStart | `createSolidStart(betterSupabase, { getRequestEvent })`, `createMiddleware(bs.middleware)` | `await bs.require()` in a `"use server"` query, `bs.action(...)` |
72
+ | Nuxt, Nitro 2 | the `better-supabase/nuxt` module, or `toH3V1(entries)` from `better-supabase/h3/v1` | `event.context.db`, `guard(options)` |
73
+ | H3 2, Nitro 3 | `toH3(entries)` from `better-supabase/h3` | `event.context.db`, `guard(options)` |
74
+ | TanStack Start, SvelteKit, React Router, Elysia | `withBetterSupabase(server)` in a bridge: `toTanStackStart`, `toSvelteKit`, `toReactRouter`, `toElysia` | the framework's context (`context.db`, `locals.db`, `context.get(key).db`) |
75
+
76
+ Never use `@supabase/server/adapters/*` (deprecated, removed 2026-12-01).
67
77
 
68
78
  Don't build error JSON by hand; errors become Problem Details.
69
79
 
@@ -85,24 +95,65 @@ for lists that clients read page by page: the list takes `after` instead of
85
95
  - `authorize(ctx, tool, args)` refuses a call (`{ allowed: false, reason, scopes }`; with `scopes` it is a 403 `insufficient_scope`). `visible(ctx, tool)` hides tools from `tools/list`. Put a permission or a label in a tool's `meta`; clients never see it.
86
96
  - `scopes` on `createMcp` only advertises scopes. Refuse calls in `authorize`, reading `toSession(ctx.auth).delegation?.scopes`.
87
97
  - Set `allowedOrigins` and `allowedHosts` (every host the server answers on, previews and local included) against DNS rebinding, and `resourceDocumentation` to a page that explains how to connect.
98
+ - On the official MCP SDK, keep its `McpServer`: `createMcpAuth(betterSupabase, { resource })` from `better-supabase/mcp/sdk` verifies the token and serves the metadata (`auth.serve(createMcpHandler(factory))`), and `withBetterSupabaseMcp(server, auth)` gives every `registerTool` callback `db`, `auth` and `bs`. With a permission library that wraps `McpServer`, wrap with it first, then `withBetterSupabaseMcp`.
88
99
 
89
- ## Background work (`better-supabase/jobs`, needs `sql add jobs idempotency webhook-inbox`)
100
+ ## AI chat (`sql add ai-chat`; `ai`, `@ai-sdk/react`, `@ai-sdk/workflow` and `workflow` as optional peers)
90
101
 
91
- - `createJobs(postgres.admin, { queue_name: zodSchema })` runs on Supabase Queues (pgmq): `enqueue` in the request, then `work` or `drain` in a worker. The handler throws to retry. `schedule(name, cron, queue, payload, { timeZone })` uses pg_cron, or with `kits.jobs.options.scheduler: "drain"` a `jobs.drainRoute({ secret: process.env.CRON_SECRET, handlers })` route that Vercel Cron calls; `kits.jobs.options.backend: "table"` runs without pgmq. Queue names are lowercase letters, digits and underscores. With a service-role Supabase client instead of SQL, it uses the `pgmq_public` RPCs (no dedupe or schedules).
102
+ - Store chats with `createAiChat({ transport, service })` from `better-supabase/blocks/ai-chat`: `transport` calls as the user, `service` as the service role for assistant messages, runs and the model catalog. Never write assistant messages from the client.
103
+ - Serve the chat with `createAssistant({ streams, run, defaultModel, quota })` from `better-supabase/ai-sdk/chat`: `respond` on `POST /api/chat`, `resume` on `GET /api/chat/[id]/stream`, `stop` on `POST /api/chat/[id]/stop`. Return `streamText(...)` from `run` with the `messages`, `abortSignal` and `providerOptions` it receives, and pass `waitUntil` (`after` in Next.js) so the answer is stored after the response.
104
+ - On the client use `useAssistant({ id, messages })` from `better-supabase/ai-sdk/react`; load `messages` on the server with `toUIMessages(await aiChat.messages.path(id, { native: true }).orThrow())`.
105
+ - Models are AI Gateway `provider/model` strings checked against `ai_model_catalog`; refresh it with the `modelCatalogRefresh` job and backfill costs with `costBackfill` from `better-supabase/ai-sdk`.
106
+ - For answers that must outlive the request (long agents, approvals that wait hours), use `durableChat({ assistant, workflow, streams })` from `better-supabase/ai-sdk/workflow` with a `"use workflow"` function that calls `durableTurn(input, { runId: getWorkflowMetadata().workflowRunId, createHook, getWritable, step, agent })`. `step` is one `"use step"` function that calls `runDurableStep(serviceAiChat, name, input)`, and the agent's model is a gateway string. The route context is the assistant context; its `chats.runs` (from `createAiChat`) serves the runs. On the client use `useDurableAssistant({ id, messages, resume: chat.activeStreamId !== undefined })` from `better-supabase/ai-sdk/workflow/react`. Record a long run's progress with `chats.runs.steps.record(runId, { key, label, status })` and list undecided approvals with `chats.runs.pendingApprovals()`.
107
+ - For tenant keys, add the `ai-providers` SQL module: store the key with the credential provider first, save its `credential_ref` with `createAiProviders({ transport, service, credentials }).keys.save(organizationId, key)` from `better-supabase/blocks/ai-providers`, and merge `byokOptions(await providers.keys.resolve(organizationId).orThrow())` into `providerOptions.gateway`. Call `keys.removeAll(organizationId)` when a tenant is deleted. The same module tracks batches (`aiBatches({ providers })` from `better-supabase/ai-sdk/batches`, with its `pollJob`) and sandboxes (`trackedSandbox`, `sandboxes.idleStopJob`).
108
+ - For repeated model calls, add the `ai-cache` SQL module and wrap the model with `wrapLanguageModel({ model, middleware: cacheMiddleware({ cache, ttl, organizationId }) })` from `better-supabase/ai-sdk/cache`; the cache is service-role only, so create it with a service transport. Meter spend with `meterTelemetry` through `registerTelemetry` and reconcile it nightly with the `spendReconciliation` job.
109
+ - Blocks never import an AI SDK. Put SDK code in the app or an adapter subpath, and store third-party tokens as a `credential_ref`, never in a column.
110
+
111
+ ## AI blocks, agents and bots
112
+
113
+ Knowledge, memory, stored agents, MCP connectors, scheduled AI tasks, the AI
114
+ SDK helpers (`better-supabase/ai-sdk/agents`, `/mcp`, `/embeddings`,
115
+ `/memory`, `/files`, `/batches`), eve and Chat SDK bots are in
116
+ [references/ai.md](references/ai.md).
117
+
118
+ ## Streams, credentials and the Workflow World
119
+
120
+ Resumable output (`better-supabase/streams`, `/streams/redis`), third-party
121
+ tokens behind a `credential_ref` (`better-supabase/credentials`,
122
+ `/vercel-connect`) and the Node-only Workflow World
123
+ (`better-supabase/workflow-sdk/world`) are in
124
+ [references/streams-credentials.md](references/streams-credentials.md).
125
+
126
+ ## Native and offline apps
127
+
128
+ For Expo and React Native, follow [references/expo.md](references/expo.md):
129
+ server loaders for the web, `better-supabase/client/native` on the device.
130
+ To read and write offline, run the same repositories on a PowerSync database
131
+ and upload through `bs.db`, as in [references/powersync.md](references/powersync.md).
132
+
133
+ ## Background work (`better-supabase/blocks/jobs`, needs `sql add jobs idempotency webhook-inbox`)
134
+
135
+ - `createJobs(postgres.admin, { queue_name: zodSchema })` runs on Supabase Queues (pgmq): `enqueue(queue, payload, { context: db.$context })` in the request, then `work` or `drain` in a worker, where `const db = await bs.forContext(job.context).orThrow()` runs the work as the enqueuing user with RLS (it fails with `forbidden` for a job without a user; use `bs.admin(job.context)` only for work no user owns). The handler throws to retry. `schedule(name, cron, queue, payload, { timeZone })` uses pg_cron, or with `sql.modules.jobs.options.scheduler: "drain"` a `jobs.drainRoute({ secret: process.env.CRON_SECRET, handlers })` route that Vercel Cron calls; `sql.modules.jobs.options.backend: "table"` runs without pgmq. Queue names are lowercase letters, digits and underscores. With a service-role Supabase client instead of SQL, it uses the `pgmq_public` RPCs (no dedupe or schedules).
92
136
  - `createIdempotency(postgres.admin).handle(request, handler)` for POST endpoints that clients retry.
93
- - `createInbox(postgres.admin, { source, secrets }).receive(request)` for webhooks; `process(handler)` later.
94
- - Times are `Temporal.Instant`: `EnqueueOptions.runAt`, `Job.enqueuedAt`, `Job.visibleUntil`, `InboxMessage.receivedAt` and webhook timestamps.
137
+ - `createWebhookInbox(postgres.admin, { source, secrets }).receive(request)` for webhooks; `process(handler)` later. `createInbox` is the conversation inbox (`blocks/inbox`), not this.
138
+ - Times are `Temporal.Instant`: `EnqueueOptions.runAt`, `Job.enqueuedAt`, `Job.visibleUntil`, `WebhookInboxMessage.receivedAt` and webhook timestamps.
95
139
  - Schedule cleanup with pg_cron at a quiet hour: `better_supabase.purge_job_archive('<queue>')`, `purge_webhooks()`, `purge_audit_log()`, `purge_idempotency_keys()`, `purge_rate_limits()`, `purge_outbox()`, `purge_notifications()` and `purge_webhook_deliveries()`, for the modules you installed. Only `service_role` can execute them.
96
- - Audit a table with `better_supabase.audit('public.t', redact => '{secret}', event_prefix => 't')`; record non-row events with `better_supabase.audit_event(event_type, ...)` and an `idempotency_key`. For per-tenant retention, write an `audit_retention(tenant)` SQL function or call `purgeAuditLog(sql, { retention })` from `better-supabase/jobs`.
140
+ - Audit a table with `better_supabase.audit('public.t', redact => '{secret}', event_prefix => 't')`; record non-row events with `better_supabase.audit_event(event_type, ...)` and an `idempotency_key`. For per-tenant retention, write an `audit_retention(tenant)` SQL function or call `purgeAuditLog(sql, { retention })` from `better-supabase/blocks/audit`, which also has `auditListQuery` and `exportAuditLog` (NDJSON or OCSF). `sql sync` writes a pgTAP file per audited table, and doctor BS315 lists tables without the trigger; exempt the rest with `sql.modules.audit.options.exempt` globs.
97
141
  - For a "view as user" support mode, add the `support-sessions` SQL module, pass `support: supportSessions({ store: sqlSupportStore(postgres) })` to `createServer`, call `bs.startSupport({ targetUserId, reason })` and `bs.stopSupport()` from server actions, and show a banner with `useSupportSession()`. Sessions are read-only by default; grant admins the `support.start` platform permission.
98
- - For teams, add the `organizations` and `invitations` SQL modules and call them through `createOrgs({ transport: sqlTransport(postgres.asUser(claims)), events: betterSupabase.events, onInvite })` from `better-supabase/orgs`. Send the invitation email in `onInvite`, show `previewInvitation(token)` on the accept page, and switch with `orgs.switch(id)`, refreshing the session when it returns `refresh: true`. Errors carry codes such as `ORG_SLUG_TAKEN` in `hint`. Existing tables work with `mode: 'adopt'`.
99
- - For user profiles, add the `profiles` SQL module: sign-up creates the row from auth metadata with a unique username and mirrors the email; users update only the `updatable` columns. Adopt an existing table with `mode: 'adopt'` and `syncTrigger: false` when your own trigger creates profiles. Use `avatarBucket()` and `orgLogoBucket()` from `better-supabase/storage` for uploads; `policy: { access: { read, write } }` checks any bucket through the access contract.
100
- - For events other systems must see, add the `outbox` SQL module and write events with `emit_event(type, payload, subject, tenant, key)` inside the same transaction as the change (the kit modules emit theirs automatically). Relay them with `createOutbox(postgres.admin, { source }).relayRoute({ secret, consumers: { name: httpSink(url) } })` from `better-supabase/jobs` after `outbox.register(name, { types })`. Delivery is at least once; receivers deduplicate on the CloudEvent `id`.
101
- - For in-app notifications, add the `notifications` SQL module and send with `createNotifications({ transport: sqlTransport(postgres.asUser(claims)), types })` from `better-supabase/notifications`, where `types` maps each notification type to a Standard Schema for its data. Pass a `key` so retries don't notify twice. Show them with `useNotifications({ topic, load })` from `better-supabase/react`; the topic defaults to `notifications:{userId}`. For email or push, pass `channels` and call `notifications.deliver()` from a cron route with a service connection.
102
- - For webhooks to customers' endpoints, add the `webhooks-out` SQL module and publish with `createWebhooks({ transport: sqlTransport(postgres.admin) }).publish({ type, data, tenant, id })` from `better-supabase/webhooks`. Pass an `id` so retries don't send twice. Send with `webhooks.deliverRoute({ secret: process.env.CRON_SECRET })` from a cron route; deliveries are signed with Standard Webhooks and only go to public HTTPS URLs by default.
142
+ - For teams, add the `organizations` and `invitations` SQL modules and call them through `createOrganizations({ transport: sqlTransport(postgres.asUser(claims)), events: betterSupabase.events, onInvite })` from `better-supabase/blocks/organizations`. Send the invitation email in `onInvite`, show `previewInvitation(token)` on the accept page, and switch with `organizations.switch(id)`, refreshing the session when it returns `refresh: true`. Errors carry codes such as `ORGANIZATION_SLUG_TAKEN` in `hint`. Existing tables work with `mode: 'adopt'`.
143
+ - For user profiles, add the `profiles` SQL module: sign-up creates the row from auth metadata with a unique username and mirrors the email; users update only the `updatable` columns. Adopt an existing table with `mode: 'adopt'` and `syncTrigger: false` when your own trigger creates profiles. Use `avatarBucket()` and `organizationLogoBucket()` from `better-supabase/storage` for uploads; `policy: { access: { read, write } }` checks any bucket through the access contract.
144
+ - For events other systems must see, add the `outbox` SQL module and write events with `emit_event(type, payload, subject, tenant, key)` inside the same transaction as the change (the SQL modules emit theirs automatically). Relay them with `createOutbox(postgres.admin, { source }).relayRoute({ secret, consumers: { name: httpSink(url) } })` from `better-supabase/blocks/outbox` after `outbox.register(name, { types })`. Delivery is at least once; receivers deduplicate on the CloudEvent `id`.
145
+ - For in-app notifications, add the `notifications` SQL module and send with `createNotifications({ transport: sqlTransport(postgres.asUser(claims)), types })` from `better-supabase/blocks/notifications`, where `types` maps each notification type to a Standard Schema for its data. Pass a `key` so retries don't notify twice. Show them with `useNotifications({ topic, load })` from `better-supabase/blocks/notifications/react`; the topic defaults to `notifications:{userId}`. For email or push, pass `channels` and call `notifications.deliver()` from a cron route with a service connection.
146
+ - For a support inbox, add the `inbox` SQL module (with `jobs` for bot and delivery jobs) and call `createInbox({ transport: sqlTransport(postgres.asUser(claims)) })` from `better-supabase/blocks/inbox`; staff need `inbox.read`, `inbox.reply`, `inbox.assign` or `inbox.manage`. Keep lists and threads live with `useInbox`, `useConversation` and `useInboxWidget` from `better-supabase/blocks/inbox/react`, each loading through a server action. For bots and channels, add `chat-sdk-state` and use `better-supabase/chat-sdk`: `createSupabaseState` as the Chat SDK state, `inboxAdapter` for the in-app widget, `webhook`, `inboundHandler` and `deliver` for Slack, WhatsApp or SMS, and `maintain` from a cron route. Platform tokens stay behind a `credential_ref`. Docs: `https://bettersupabase.com/docs/blocks/inbox.md` and `https://bettersupabase.com/docs/chat-sdk.md`.
147
+ - For webhooks to customers' endpoints, add the `webhooks-out` SQL module and publish with `createWebhooks({ transport: sqlTransport(postgres.admin) }).publish({ type, data, tenant, id })` from `better-supabase/blocks/webhooks`. Pass an `id` so retries don't send twice. Send with `webhooks.deliverRoute({ secret: process.env.CRON_SECRET })` from a cron route; deliveries are signed with Standard Webhooks and only go to public HTTPS URLs by default.
148
+ - Each SaaS block below is an SQL module of the same name plus `better-supabase/blocks/<name>`, called through `sqlTransport(postgres.asUser(claims))` for user actions and `postgres.admin` for service work; errors carry a code in `hint`. Its docs page is `https://bettersupabase.com/docs/blocks/<name>.md`.
149
+ - `api-keys`: `createApiKeys`, and `auth: { resolvers: [apiKeyResolver({ keys })] }` in the adapter so key callers get `auth.kind === "apiKey"`. Show a new key once; only its hash is stored.
150
+ - `settings`: `defineSettings` with a Standard Schema per key; `usage`: `createUsage` with a `key` per increment, `within_quota` in policies; `billing`: `createBilling` with `stripe` as an optional peer; `flags`: `createFlagsProvider` for OpenFeature, `flag_enabled(key)` in policies.
151
+ - `comments`, `attachments` (signed URLs, served only after a scan), `data-lifecycle` (exports, organization deletion with a grace period), `sso` (verified domains, SAML, SCIM), `onboarding` (`defineChecklist`, `useOnboarding`), `waitlist` (`createWaitlist`, `waitlistHook` for invite-only sign-up) and `announcements` (`createAnnouncements`, `useAnnouncements`).
152
+ - `workflows`: `createWorkflows` for the run registry of any engine (`runs.list`, `runs.requestCancel`), schedules and admission whose `tick` hands each start to an engine, and `useWorkflowRuns` from `better-supabase/blocks/workflows/react`. With the Workflow SDK, add the `workflow-sdk-world` module, set `WORKFLOW_TARGET_WORLD=better-supabase/workflow-sdk/world`, start runs with `startFor(ctx, workflow, args)` from `better-supabase/workflow-sdk` so members see them under RLS, pass `workflowStarter({ name: workflow })` to `tick`, and check `authorizeHook(token, ctx)` before `resumeHook`. The World is Node-only (`https://bettersupabase.com/docs/blocks/workflow-sdk.md`).
153
+ - `workflow-builder`: `createBuilder` with `compile: compileGraph` and `start: graphStarter({ steps, executor })` from `better-supabase/workflow-sdk/builder`, and a service-role `service` transport for webhooks, events, `credentials.resolve` and `nodeRuns.record`. Call `steps.sync()` at deploy time so publishing accepts the steps. Wrap each step in `nodeRunReporter` for the canvas status, and read it with `useWorkflowCanvasRun` (`https://bettersupabase.com/docs/blocks/workflow-builder.md`).
103
154
 
104
155
  Done when a failing job is retried and then archived after `maxAttempts`,
105
- a replayed webhook or POST doesn't run twice, and each kit table has a purge
156
+ a replayed webhook or POST doesn't run twice, and each block table has a purge
106
157
  schedule.
107
158
 
108
159
  ## Direct Postgres on the server
@@ -116,7 +167,10 @@ schedule.
116
167
  Sign tokens with `signLocalJwt` or `asUser` from `better-supabase/testing`;
117
168
  the adapter verifies them against the local JWKS. See the `better-supabase-testing` skill.
118
169
 
119
- Docs: https://bettersupabase.com/docs/frameworks/hono.md (and `next`,
120
- `orpc`, `edge`, `mcp` under `/docs/frameworks/`),
121
- https://bettersupabase.com/docs/kits/jobs.md and
170
+ Docs: https://bettersupabase.com/docs/frameworks.md lists every adapter;
171
+ each has a page such as https://bettersupabase.com/docs/frameworks/hono.md,
172
+ https://bettersupabase.com/docs/repository/powersync.md,
173
+ https://bettersupabase.com/docs/blocks/jobs.md,
174
+ https://bettersupabase.com/docs/ai-sdk/chat.md,
175
+ https://bettersupabase.com/docs/ai-sdk/workflow.md and
122
176
  https://bettersupabase.com/docs/auth/postgres.md.