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.
- package/README.md +299 -41
- package/dist/access-sql-B0dF-SoF.js +181 -0
- package/dist/actor-CQTlc1Hh.d.ts +43 -0
- package/dist/adapter-Bc1o3zyy.js +1106 -0
- package/dist/agents-CVHGd7It.d.ts +94 -0
- package/dist/ai-cache-CBWs1W0k.js +80 -0
- package/dist/ai-cache-DaDu_G5L.d.ts +64 -0
- package/dist/ai-chat-7amvXjmQ.d.ts +590 -0
- package/dist/ai-chat-B24UI962.js +743 -0
- package/dist/ai-files-CSPNswUY.js +319 -0
- package/dist/ai-sdk/agents/index.d.ts +74 -0
- package/dist/ai-sdk/agents/index.js +159 -0
- package/dist/ai-sdk/batches/index.d.ts +74 -0
- package/dist/ai-sdk/batches/index.js +180 -0
- package/dist/ai-sdk/cache/index.d.ts +38 -0
- package/dist/ai-sdk/cache/index.js +127 -0
- package/dist/ai-sdk/chat/index.d.ts +2 -0
- package/dist/ai-sdk/chat/index.js +246 -0
- package/dist/ai-sdk/embeddings/index.d.ts +3 -0
- package/dist/ai-sdk/embeddings/index.js +2 -0
- package/dist/ai-sdk/files/index.d.ts +61 -0
- package/dist/ai-sdk/files/index.js +111 -0
- package/dist/ai-sdk/index.d.ts +145 -0
- package/dist/ai-sdk/index.js +174 -0
- package/dist/ai-sdk/mcp/index.d.ts +102 -0
- package/dist/ai-sdk/mcp/index.js +362 -0
- package/dist/ai-sdk/memory/index.d.ts +67 -0
- package/dist/ai-sdk/memory/index.js +175 -0
- package/dist/ai-sdk/react/index.d.ts +2 -0
- package/dist/ai-sdk/react/index.js +3 -0
- package/dist/ai-sdk/react/server.d.ts +6 -0
- package/dist/ai-sdk/react/server.js +7 -0
- package/dist/ai-sdk/workflow/index.d.ts +249 -0
- package/dist/ai-sdk/workflow/index.js +575 -0
- package/dist/ai-sdk/workflow/react/index.d.ts +20 -0
- package/dist/ai-sdk/workflow/react/index.js +66 -0
- package/dist/ai-sdk/workflow/react/server.d.ts +10 -0
- package/dist/ai-sdk/workflow/react/server.js +12 -0
- package/dist/ai-tasks-Cd1HMFvB.d.ts +131 -0
- package/dist/announcements-CiyOs-xP.js +107 -0
- package/dist/announcements-ZRGnScWI.d.ts +72 -0
- package/dist/api-keys-rCGtKaZA.d.ts +156 -0
- package/dist/assistant-DwdpDH1q.d.ts +147 -0
- package/dist/astro/index.d.ts +86 -0
- package/dist/astro/index.js +93 -0
- package/dist/attributes-5dYul0u0.js +13 -0
- package/dist/auth-link-BjFPqwLz.d.ts +97 -0
- package/dist/auth-link-DrDX9KOT.js +114 -0
- package/dist/authorization-BFCqamMs.d.ts +172 -0
- package/dist/before-route-CnR0C0Jr.js +30 -0
- package/dist/bind-Bu_ZNa3W.d.ts +62 -0
- package/dist/bind-l4kAvYSv.js +97 -0
- package/dist/block-events-CrT8r7Fe.js +76 -0
- package/dist/block-fields-GFkxl4dP.js +49 -0
- package/dist/block-fields-SJ6fEf3o.d.ts +31 -0
- package/dist/block-helpers-CKtbFcRv.d.ts +37 -0
- package/dist/block-helpers-DWHxHsEQ.js +190 -0
- package/dist/block-hooks-BmjMyXTa.js +114 -0
- package/dist/block-hooks-plbZ0AbJ.d.ts +107 -0
- package/dist/{kit-transport-DJlHQUBU.js → block-transport-BLr-ZgLc.js} +11 -7
- package/dist/block-transport-DvaoPuZ9.d.ts +48 -0
- package/dist/blocks/agents/index.d.ts +3 -0
- package/dist/blocks/agents/index.js +123 -0
- package/dist/blocks/ai-cache/index.d.ts +3 -0
- package/dist/blocks/ai-cache/index.js +3 -0
- package/dist/blocks/ai-chat/index.d.ts +31 -0
- package/dist/blocks/ai-chat/index.js +5 -0
- package/dist/blocks/ai-chat/react/index.d.ts +77 -0
- package/dist/blocks/ai-chat/react/index.js +387 -0
- package/dist/blocks/ai-chat/react/server.d.ts +16 -0
- package/dist/blocks/ai-chat/react/server.js +14 -0
- package/dist/blocks/ai-files/index.d.ts +14 -0
- package/dist/blocks/ai-files/index.js +3 -0
- package/dist/blocks/ai-providers/index.d.ts +7 -0
- package/dist/blocks/ai-providers/index.js +211 -0
- package/dist/blocks/ai-tasks/index.d.ts +3 -0
- package/dist/blocks/ai-tasks/index.js +203 -0
- package/dist/blocks/announcements/index.d.ts +3 -0
- package/dist/blocks/announcements/index.js +3 -0
- package/dist/blocks/announcements/react/index.d.ts +31 -0
- package/dist/blocks/announcements/react/index.js +86 -0
- package/dist/blocks/announcements/react/server.d.ts +6 -0
- package/dist/blocks/announcements/react/server.js +7 -0
- package/dist/blocks/api-keys/index.d.ts +35 -0
- package/dist/blocks/api-keys/index.js +334 -0
- package/dist/blocks/attachments/index.d.ts +210 -0
- package/dist/blocks/attachments/index.js +222 -0
- package/dist/blocks/audit/index.d.ts +366 -0
- package/dist/blocks/audit/index.js +714 -0
- package/dist/blocks/billing/index.d.ts +265 -0
- package/dist/blocks/billing/index.js +400 -0
- package/dist/blocks/comments/index.d.ts +200 -0
- package/dist/blocks/comments/index.js +207 -0
- package/dist/blocks/connectors/index.d.ts +3 -0
- package/dist/blocks/connectors/index.js +164 -0
- package/dist/blocks/data-lifecycle/index.d.ts +251 -0
- package/dist/blocks/data-lifecycle/index.js +353 -0
- package/dist/blocks/entitlements/index.d.ts +14 -0
- package/dist/blocks/entitlements/index.js +25 -0
- package/dist/blocks/flags/index.d.ts +226 -0
- package/dist/blocks/flags/index.js +282 -0
- package/dist/blocks/inbox/index.d.ts +6 -0
- package/dist/blocks/inbox/index.js +499 -0
- package/dist/blocks/inbox/react/index.d.ts +2 -0
- package/dist/blocks/inbox/react/index.js +225 -0
- package/dist/blocks/inbox/react/server.d.ts +10 -0
- package/dist/blocks/inbox/react/server.js +12 -0
- package/dist/blocks/index.d.ts +65 -0
- package/dist/blocks/index.js +77 -0
- package/dist/blocks/jobs/index.d.ts +297 -0
- package/dist/blocks/jobs/index.js +1051 -0
- package/dist/blocks/knowledge/index.d.ts +3 -0
- package/dist/blocks/knowledge/index.js +3 -0
- package/dist/blocks/memory/index.d.ts +8 -0
- package/dist/blocks/memory/index.js +289 -0
- package/dist/blocks/notifications/index.d.ts +297 -0
- package/dist/blocks/notifications/index.js +425 -0
- package/dist/blocks/notifications/react/index.d.ts +44 -0
- package/dist/blocks/notifications/react/index.js +67 -0
- package/dist/blocks/notifications/react/server.d.ts +6 -0
- package/dist/blocks/notifications/react/server.js +7 -0
- package/dist/blocks/onboarding/index.d.ts +3 -0
- package/dist/blocks/onboarding/index.js +64 -0
- package/dist/blocks/onboarding/react/index.d.ts +28 -0
- package/dist/blocks/onboarding/react/index.js +78 -0
- package/dist/blocks/onboarding/react/server.d.ts +7 -0
- package/dist/blocks/onboarding/react/server.js +7 -0
- package/dist/blocks/organizations/index.d.ts +241 -0
- package/dist/blocks/organizations/index.js +400 -0
- package/dist/blocks/outbox/index.d.ts +3 -0
- package/dist/blocks/outbox/index.js +266 -0
- package/dist/blocks/profiles/index.d.ts +40 -0
- package/dist/blocks/profiles/index.js +28 -0
- package/dist/blocks/push/index.d.ts +185 -0
- package/dist/blocks/push/index.js +258 -0
- package/dist/blocks/settings/index.d.ts +89 -0
- package/dist/blocks/settings/index.js +104 -0
- package/dist/blocks/sso/index.d.ts +198 -0
- package/dist/blocks/sso/index.js +1297 -0
- package/dist/blocks/usage/index.d.ts +4 -0
- package/dist/blocks/usage/index.js +233 -0
- package/dist/blocks/waitlist/index.d.ts +117 -0
- package/dist/blocks/waitlist/index.js +132 -0
- package/dist/blocks/webhooks/index.d.ts +304 -0
- package/dist/{webhooks → blocks/webhooks}/index.js +468 -148
- package/dist/blocks/workflow-builder/index.d.ts +21 -0
- package/dist/blocks/workflow-builder/index.js +5 -0
- package/dist/blocks/workflow-builder/react/index.d.ts +47 -0
- package/dist/blocks/workflow-builder/react/index.js +119 -0
- package/dist/blocks/workflow-builder/react/server.d.ts +8 -0
- package/dist/blocks/workflow-builder/react/server.js +11 -0
- package/dist/blocks/workflows/index.d.ts +3 -0
- package/dist/blocks/workflows/index.js +3 -0
- package/dist/blocks/workflows/react/index.d.ts +47 -0
- package/dist/blocks/workflows/react/index.js +137 -0
- package/dist/blocks/workflows/react/server.d.ts +8 -0
- package/dist/blocks/workflows/react/server.js +11 -0
- package/dist/{index-SaTsEfGP.d.ts → bucket-Cl46E3jS.d.ts} +134 -91
- package/dist/{simplify-_0oUKqCd.js → build-BXIzE6Xv.js} +222 -124
- package/dist/{channel-FQW-CnGR.d.ts → channel-_2Mx1Oyu.d.ts} +2 -2
- package/dist/channels-CkgQ_X60.js +114 -0
- package/dist/chat-sdk/index.d.ts +303 -0
- package/dist/chat-sdk/index.js +733 -0
- package/dist/chat-sdk/react/index.d.ts +2 -0
- package/dist/chat-sdk/react/index.js +3 -0
- package/dist/chat-sdk/react/server.d.ts +3 -0
- package/dist/chat-sdk/react/server.js +2 -0
- package/dist/claims-DDBQT6BK.js +61 -0
- package/dist/{claims-BAf6c7is.js → claims-PqzCxaTD.js} +39 -2
- package/dist/cli/bin.js +1 -1
- package/dist/cli/{codemod-DqV7612m.js → codemod-Bl_tQpHn.js} +105 -2
- package/dist/cli/config-B9HkL8nF.js +2 -0
- package/dist/cli/config-DU7EJImt.js +49 -0
- package/dist/cli/config-NiPxAmUF.js +1077 -0
- package/dist/cli/{dist-xn4wlboc.js → dist-DRAVaE6w.js} +111 -1
- package/dist/cli/{doctor-L7Z8mYTx.js → doctor-B4JOm_ox.js} +992 -316
- package/dist/cli/{env-DmKv_G4A.js → env-CJLbUVPB.js} +1 -1
- package/dist/cli/{env-jIFUADLY.js → env-qXgyMV6r.js} +2 -2
- package/dist/cli/fresh-import-BeYf9I3x.js +40 -0
- package/dist/cli/gen-BGLb_zou.js +3100 -0
- package/dist/cli/gen-DAH8FM2W.js +2 -0
- package/dist/cli/index.d.ts +44 -5
- package/dist/cli/index.js +7 -7
- package/dist/cli/{init-Saf5-R9T.js → init-BIIwclPg.js} +242 -27
- package/dist/cli/{introspect--H7oGmcd.js → introspect-DNUTuNvb.js} +5 -5
- package/dist/cli/{io-k41_z-jT.js → io-DI1mTdSA.js} +12 -3
- package/dist/cli/{keys-ByKHnvP9.js → keys-BGCnnb-s.js} +8 -6
- package/dist/cli/{ohash-D7bG_EOb.js → ohash-BjQY1cBb.js} +1 -1
- package/dist/cli/{openapi-Cp5Fyta-.js → openapi-BlRJ18s3.js} +2 -2
- package/dist/cli/{project-B_GeXyHh.js → project-DZRaBaY7.js} +11 -6
- package/dist/cli/read-sets-CETOSFx4.js +223 -0
- package/dist/cli/{run-BKR2W_79.js → run-DNWxHynX.js} +33 -23
- package/dist/cli/{seed-CUlqWh-8.js → seed-DQzqT7LP.js} +8 -6
- package/dist/cli/{skills-LJJIhLFR.js → skills-QQs4q68J.js} +3 -2
- package/dist/cli/sql-D0GUtUPp.js +536 -0
- package/dist/cli/{config-CPVpXP5I.js → supabase-toml-B-bIukQF.js} +72 -942
- package/dist/cli/typegen-version-DeFbtzYI.js +8 -0
- package/dist/cli/{version-BDJuO0UR.js → version-hr88OZG0.js} +1 -1
- package/dist/client/index.d.ts +3 -2
- package/dist/client/index.js +11 -71
- package/dist/client/native/index.d.ts +228 -0
- package/dist/client/native/index.js +361 -0
- package/dist/client-CI0Z2zWX.js +277 -0
- package/dist/cloud-event-BnmD5fb9.js +46 -0
- package/dist/cloud-event-C1JCc1bH.d.ts +50 -0
- package/dist/{compiler-BXH_aZ7N.d.ts → compiler-DY_wkj4R.d.ts} +2 -2
- package/dist/compose-BIBNgAnq.js +53 -0
- package/dist/composite-Bt1YK3Ke.d.ts +146 -0
- package/dist/composite-DhE66P5u.js +130 -0
- package/dist/config/index.d.ts +6 -4
- package/dist/config/index.js +5 -5
- package/dist/{config-T_ejwyd3.d.ts → config-D44Y7PAv.d.ts} +406 -205
- package/dist/{config-DreERlKo.js → config-Dn7F5k9A.js} +62 -14
- package/dist/connector-Dv8kK0MO.d.ts +107 -0
- package/dist/connectors-hkLCwyEz.d.ts +120 -0
- package/dist/context-BCrWe7ow.d.ts +237 -0
- package/dist/credentials/index.d.ts +31 -0
- package/dist/credentials/index.js +168 -0
- package/dist/cron-DVPUg5k3.js +145 -0
- package/dist/csv-CPAzEmB6.js +25 -0
- package/dist/db-exception-CnWcYPxL.js +15 -0
- package/dist/{define-cNKzqwL_.js → define-B-TVjC25.js} +784 -227
- package/dist/{define-Bp_BZa5h.d.ts → define-CJJkkr1-.d.ts} +353 -61
- package/dist/edge/index.d.ts +69 -11
- package/dist/edge/index.js +191 -75
- package/dist/elysia/index.d.ts +59 -0
- package/dist/elysia/index.js +62 -0
- package/dist/embeddings-4ZvFzjsU.js +127 -0
- package/dist/embeddings-C9KGQnXt.d.ts +68 -0
- package/dist/{refresh-BTrQ_ZTp.d.ts → ended-jLfvw8h-.d.ts} +20 -2
- package/dist/{entitlements-DUxU4oHe.d.ts → entitlements-DHrY2UDZ.d.ts} +16 -7
- package/dist/entitlements-DRl6ZJUm.js +24 -0
- package/dist/envelope-DqnYGRw7.js +47 -0
- package/dist/{errors-DtwXa6b8.js → errors-B11Duf73.js} +82 -13
- package/dist/errors-DLjJHPLK.js +44 -0
- package/dist/escape-like-DHfx6jRr.js +7 -0
- package/dist/escape-like-ImTK0ps_.d.ts +15 -0
- package/dist/eve/index.d.ts +220 -0
- package/dist/eve/index.js +504 -0
- package/dist/eve-gT2Fpjut.d.ts +151 -0
- package/dist/events/index.d.ts +4 -3
- package/dist/events/index.js +9 -50
- package/dist/events-DWDhx77e.d.ts +549 -0
- package/dist/executor-Bq28caBo.js +718 -0
- package/dist/executor-C-R4pucm.js +83 -0
- package/dist/executor-CaWigTyR.d.ts +148 -0
- package/dist/executor-D14tGopJ.d.ts +36 -0
- package/dist/{executor-Cghdstwu.d.ts → executor-DbvExCFC.d.ts} +7 -1
- package/dist/{sql-Coh6n4cC.js → executor-De1Of3m3.js} +210 -11
- package/dist/executor-DvsBbNBS.d.ts +261 -0
- package/dist/expo/index.d.ts +79 -0
- package/dist/expo/index.js +129 -0
- package/dist/expo-sqlite/index.d.ts +58 -0
- package/dist/expo-sqlite/index.js +104 -0
- package/dist/field-errors-BFOa7WhB.d.ts +99 -0
- package/dist/field-errors-VF1yb8yI.js +13 -0
- package/dist/framework-CONDyPYx.js +51 -0
- package/dist/framework-DuVb4Xa8.d.ts +25 -0
- package/dist/gateway-C1ssRHnf.d.ts +130 -0
- package/dist/graph-BGyLLFLX.js +265 -0
- package/dist/h3/index.d.ts +59 -0
- package/dist/h3/index.js +55 -0
- package/dist/h3/v1/index.d.ts +63 -0
- package/dist/h3/v1/index.js +49 -0
- package/dist/history-BZih6SFP.js +64 -0
- package/dist/hono/index.d.ts +56 -7
- package/dist/hono/index.js +97 -45
- package/dist/{react-C_s7kiNz.js → hooks-1BTCJsiw.js} +104 -133
- package/dist/http-Cv4T29xh.js +40 -0
- package/dist/http-DdYadv-o.js +126 -0
- package/dist/image-url-pIVlO6R1.js +41 -0
- package/dist/impersonation-DcqaTBHx.js +148 -0
- package/dist/inbox-i7E1ppo6.d.ts +384 -0
- package/dist/index-ACiNPN4Z.d.ts +74 -0
- package/dist/{index-DgILJRXj.d.ts → index-Bepi-Hgg.d.ts} +91 -28
- package/dist/index-BkWT_uBO.d.ts +51 -0
- package/dist/index-BpFYMsi0.d.ts +53 -0
- package/dist/{index-C7f8cOBM.d.ts → index-Bxih3l0u.d.ts} +2 -2
- package/dist/index-CaxrMD1A.d.ts +1 -0
- package/dist/index-ClmjK_o-.d.ts +55 -0
- package/dist/index-CtuakVRc.d.ts +267 -0
- package/dist/index-D48jVS-N.d.ts +246 -0
- package/dist/index-DDrYaUcq.d.ts +138 -0
- package/dist/index-DQh4VCc9.d.ts +98 -0
- package/dist/{live-D9W2M5aO.d.ts → index-DunNRdnT.d.ts} +136 -38
- package/dist/index.d.ts +65 -18
- package/dist/index.js +42 -14
- package/dist/invalidate-BBqhpxyB.d.ts +19 -0
- package/dist/json-CEnpTHlZ.js +16 -0
- package/dist/json-schema-CvER4kgT.js +502 -0
- package/dist/keys-4MnkWTTh.js +35 -0
- package/dist/kit-B5tid-q5.d.ts +60 -0
- package/dist/kit-Fm-Fv7q5.js +78 -0
- package/dist/knowledge-BXBbT0Tr.d.ts +176 -0
- package/dist/knowledge-CDmiMLew.js +255 -0
- package/dist/lint/index.d.ts +1 -1
- package/dist/lint/index.js +37 -0
- package/dist/list/index.d.ts +3 -2
- package/dist/list/index.js +1 -444
- package/dist/{index-fag8VJZ2.d.ts → list-query-BRt-zDF7.d.ts} +20 -12
- package/dist/list-query-gl808ac1.js +459 -0
- package/dist/{live-CdJBOc4f.js → live-CTAZQkwl.js} +99 -14
- package/dist/logger-DWVYUmwi.d.ts +18 -0
- package/dist/mcp/index.d.ts +38 -11
- package/dist/mcp/index.js +82 -46
- package/dist/mcp/sdk/index.d.ts +105 -0
- package/dist/mcp/sdk/index.js +126 -0
- package/dist/message-CaKlqdsX.js +219 -0
- package/dist/message-CfDoR0Y6.d.ts +94 -0
- package/dist/messages-B9-5887d.js +715 -0
- package/dist/messages-DYP0sUTe.d.ts +59 -0
- package/dist/{mfa-CusDgPaD.d.ts → mfa-Daak8ukG.d.ts} +8 -2
- package/dist/modules-DpPwzC7E.d.ts +192 -0
- package/dist/modules-dxrVK3ID.js +228 -0
- package/dist/nestjs/index.d.ts +68 -0
- package/dist/nestjs/index.js +164 -0
- package/dist/next/client/index.d.ts +35 -0
- package/dist/next/client/index.js +36 -0
- package/dist/next/image/index.js +3 -24
- package/dist/next/index.d.ts +150 -51
- package/dist/next/index.js +261 -107
- package/dist/node/index.d.ts +4 -0
- package/dist/node/index.js +210 -0
- package/dist/node-headers-AO06VhqH.d.ts +24 -0
- package/dist/node-headers-C71zNQHe.js +55 -0
- package/dist/nuxt/index.d.ts +60 -0
- package/dist/nuxt/index.js +64 -0
- package/dist/onboarding-BZGHYJks.d.ts +62 -0
- package/dist/openapi/index.d.ts +1 -1
- package/dist/openapi/index.js +3 -3
- package/dist/orpc/index.d.ts +70 -11
- package/dist/orpc/index.js +73 -24
- package/dist/otel/index.d.ts +7 -7
- package/dist/otel/index.js +87 -57
- package/dist/outbox-Cq7pPYvl.d.ts +161 -0
- package/dist/{plugin-o144f322.d.ts → plugin-FGY8UhYm.d.ts} +30 -10
- package/dist/plugin-tfXW1-qO.js +45 -0
- package/dist/plugins/actor/index.d.ts +2 -2
- package/dist/plugins/actor/index.js +3 -3
- package/dist/plugins/rules/index.d.ts +11 -4
- package/dist/plugins/rules/index.js +40 -13
- package/dist/plugins/soft-delete/index.d.ts +5 -4
- package/dist/plugins/soft-delete/index.js +10 -5
- package/dist/plugins/tenant/index.d.ts +2 -2
- package/dist/plugins/tenant/index.js +18 -11
- package/dist/plugins/timestamps/index.d.ts +5 -3
- package/dist/plugins/timestamps/index.js +6 -4
- package/dist/plugins/validation/index.d.ts +2 -2
- package/dist/plugins/validation/index.js +10 -6
- package/dist/{pool-C9voM4Kw.d.ts → pool-CAu2nLrL.d.ts} +2 -2
- package/dist/postgres/index.d.ts +4 -4
- package/dist/postgres/index.js +1 -2
- package/dist/{postgrest-CruYKAvV.d.ts → postgrest-BLVdEnfe.d.ts} +13 -3
- package/dist/powersync/index.d.ts +43 -0
- package/dist/powersync/index.js +199 -0
- package/dist/powersync/react/index.d.ts +87 -0
- package/dist/powersync/react/index.js +108 -0
- package/dist/{problem-BW1KhzSG.js → problem-BreOl8b8.js} +14 -3
- package/dist/{problem-Blxe8S31.d.ts → problem-DD8LZFjc.d.ts} +21 -3
- package/dist/provider-BH5UWZJ6.d.ts +113 -0
- package/dist/provider-Di3sRutW.js +57 -0
- package/dist/query/index.d.ts +4 -2
- package/dist/query/index.js +4 -3
- package/dist/{query-CCbo44lG.js → query-BQ-NaZon.js} +141 -24
- package/dist/{queue-BYUCjr59.d.ts → queue-CLJurhdy.d.ts} +258 -83
- package/dist/react/index.d.ts +11 -7
- package/dist/react/index.js +7 -3
- package/dist/react/native/index.d.ts +116 -0
- package/dist/react/native/index.js +130 -0
- package/dist/react/server.d.ts +28 -10
- package/dist/react/server.js +22 -5
- package/dist/react/session.d.ts +2 -2
- package/dist/react-4ZqkP8da.js +79 -0
- package/dist/react-F80mF4-t.js +409 -0
- package/dist/react-router/index.d.ts +83 -0
- package/dist/react-router/index.js +89 -0
- package/dist/react-topic-seAWjL3_.js +38 -0
- package/dist/{read-set-DQFt1N_Y.js → read-set-DuKWC9Mj.js} +67 -25
- package/dist/realtime/index.d.ts +4 -5
- package/dist/realtime/index.js +144 -82
- package/dist/refusal-CeJWxmkH.js +61 -0
- package/dist/refusal-D1rgbzNq.d.ts +15 -0
- package/dist/replicas-CwrYp5Zj.js +94 -0
- package/dist/{view-Bq64ki8-.js → resolve-D_IcnvFd.js} +239 -289
- package/dist/{resolve-C15TJq77.d.ts → resolve-KW8nCeL6.d.ts} +29 -45
- package/dist/{resource-CRxxwkQq.js → resource-BsvzCMlX.js} +4 -4
- package/dist/{resource-D8iqWMr-.d.ts → resource-D6Uc7Sk7.d.ts} +5 -5
- package/dist/respond-BUgsXNgk.js +91 -0
- package/dist/respond-DoBijysA.d.ts +93 -0
- package/dist/result-D7y2fT87.d.ts +282 -0
- package/dist/{result-BKiliPY7.js → result-DzUbqgdW.js} +27 -2
- package/dist/run-state-CPo-1X2B.d.ts +12 -0
- package/dist/run-state-CgBKzYMW.js +13 -0
- package/dist/search-CUWCRYKL.js +9 -0
- package/dist/server/index.d.ts +143 -21
- package/dist/server/index.js +46 -14
- package/dist/{respond-D2OQl62-.d.ts → server-CeVeeXwz.d.ts} +225 -80
- package/dist/session-ChiXDZdZ.d.ts +72 -0
- package/dist/shared-CBxosKK3.js +75 -0
- package/dist/{shared-D1dRUrAg.js → shared-CxWmcyqB.js} +2 -1
- package/dist/shared-DDSjEGDR.d.ts +11 -0
- package/dist/sign-in-BCV5S2WZ.d.ts +49 -0
- package/dist/sign-in-Cb1mwv6X.js +86 -0
- package/dist/{signers-Cc6r98SW.d.ts → signers-4y62_VIi.d.ts} +13 -9
- package/dist/simplify-DDO0j0LI.js +83 -0
- package/dist/solid/index.d.ts +131 -0
- package/dist/solid/index.js +344 -0
- package/dist/solid-start/index.d.ts +75 -0
- package/dist/solid-start/index.js +58 -0
- package/dist/{spec-pins-C3oc-Tdp.js → spec-pins--j6mTok4.js} +8 -1
- package/dist/{spec-pins-CqorWDnO.d.ts → spec-pins-C89s6DyW.d.ts} +7 -0
- package/dist/sql/index.d.ts +330 -194
- package/dist/sql/index.js +34901 -6489
- package/dist/ssr/index.d.ts +6 -5
- package/dist/ssr/index.js +3 -3
- package/dist/{standard-D7r6dMUu.js → standard-BK0cqJ7y.js} +4 -3
- package/dist/{standard-J4YgMOLm.d.ts → standard-CYsm7xpT.d.ts} +1 -1
- package/dist/stats-D_AD9GGu.js +1123 -0
- package/dist/storage/index.d.ts +5 -5
- package/dist/storage/index.js +1027 -368
- package/dist/store-BdH5ruDx.js +66 -0
- package/dist/store-CGjgWu5n.d.ts +68 -0
- package/dist/streams/index.d.ts +76 -0
- package/dist/streams/index.js +77 -0
- package/dist/streams/redis/index.d.ts +52 -0
- package/dist/streams/redis/index.js +185 -0
- package/dist/stripe-BMj5LtsT.js +38 -0
- package/dist/stripe-D04h-QBT.d.ts +136 -0
- package/dist/{support-Dk6vdmEw.js → support-BivNqSpK.js} +35 -12
- package/dist/{support-view-Da5peKFg.d.ts → support-view-33Oi07TT.d.ts} +1 -1
- package/dist/svelte/index.d.ts +114 -0
- package/dist/svelte/index.js +344 -0
- package/dist/sveltekit/index.d.ts +116 -0
- package/dist/sveltekit/index.js +106 -0
- package/dist/tags-B99_U9Pp.js +39 -0
- package/dist/tags-Cx-LnIQP.d.ts +30 -0
- package/dist/tanstack-db/index.d.ts +71 -0
- package/dist/tanstack-db/index.js +72 -0
- package/dist/tanstack-start/index.d.ts +75 -0
- package/dist/tanstack-start/index.js +95 -0
- package/dist/tee-CoEppCER.js +101 -0
- package/dist/{template-TxrGI5jR.js → template--jDkl3UP.js} +34 -13
- package/dist/template-CwO38Do8.d.ts +6 -0
- package/dist/temporal-BJGitm-h.js +79 -0
- package/dist/{temporal-required-CAt4Dc9Z.js → temporal-required-BVvW7SYJ.js} +3 -2
- package/dist/tenant-I1TEZ_BX.js +27 -0
- package/dist/tenant-icPeuUBN.d.ts +17 -0
- package/dist/testing/index.d.ts +343 -37
- package/dist/testing/index.js +1186 -79
- package/dist/timing-CyTQPubY.js +92 -0
- package/dist/ttl-Hr34gRu8.js +12 -0
- package/dist/{types-Dnf_wRDz.d.ts → types-6BdhkmZe.d.ts} +111 -45
- package/dist/types-BI-0Sl2v.d.ts +359 -0
- package/dist/types-C05bxW-W.d.ts +220 -0
- package/dist/types-DGs5L0VN.d.ts +192 -0
- package/dist/types-TaiEeBGA.d.ts +156 -0
- package/dist/usage-CrvrL2vw.d.ts +177 -0
- package/dist/user-change-XzvgafU4.js +130 -0
- package/dist/vault-CSO7ss5C.d.ts +50 -0
- package/dist/vercel-connect/index.d.ts +47 -0
- package/dist/vercel-connect/index.js +119 -0
- package/dist/{verify-Ce49ETPz.js → verify-DL41hbvY.js} +85 -13
- package/dist/verify-DPuWngD4.d.ts +172 -0
- package/dist/{version-DM_Roffb.js → version-Bvv6aLjZ.js} +1 -1
- package/dist/view-BeFcRV6G.js +99 -0
- package/dist/{view-BEf0diC5.d.ts → view-DbxLNu8L.d.ts} +35 -32
- package/dist/vue/index.d.ts +141 -0
- package/dist/vue/index.js +362 -0
- package/dist/watch-DI34G86j.d.ts +60 -0
- package/dist/watch-Xuxrvxq-.js +122 -0
- package/dist/{wire-D2dT86vi.js → wire-DtZQ4sdE.js} +15 -5
- package/dist/workflow-builder-DJ1oHn8g.js +398 -0
- package/dist/workflow-sdk/builder/index.d.ts +85 -0
- package/dist/workflow-sdk/builder/index.js +250 -0
- package/dist/workflow-sdk/index.d.ts +14 -0
- package/dist/workflow-sdk/index.js +3 -0
- package/dist/workflow-sdk/world/index.d.ts +107 -0
- package/dist/workflow-sdk/world/index.js +702 -0
- package/dist/workflow-sdk-B3yLD6Br.d.ts +98 -0
- package/dist/workflow-sdk-C2WJ_G2O.js +173 -0
- package/dist/workflow-sdk-world-D-prir6O.js +1397 -0
- package/dist/workflows-B0j9WKPu.d.ts +185 -0
- package/dist/workflows-wu1WWBn7.js +216 -0
- package/package.json +470 -29
- package/schemas/ai-message-v1.json +258 -0
- package/schemas/config-v1.json +1074 -140
- package/schemas/doctor-report-v1.json +21 -1
- package/schemas/snapshot-v2.json +8 -0
- package/skills/better-supabase/SKILL.md +41 -12
- package/skills/better-supabase/references/frontend.md +96 -0
- package/skills/better-supabase/references/plugins.md +10 -6
- package/skills/better-supabase/references/troubleshooting.md +2 -1
- package/skills/better-supabase-api/SKILL.md +76 -22
- package/skills/better-supabase-api/references/adapters.md +207 -0
- package/skills/better-supabase-api/references/ai.md +125 -0
- package/skills/better-supabase-api/references/expo.md +65 -0
- package/skills/better-supabase-api/references/powersync.md +35 -0
- package/skills/better-supabase-api/references/streams-credentials.md +105 -0
- package/skills/better-supabase-auth/SKILL.md +62 -18
- package/skills/better-supabase-auth/references/authorization-providers.md +51 -0
- package/skills/better-supabase-testing/SKILL.md +3 -1
- package/dist/cli/config-dtoekM0v.js +0 -2
- package/dist/cli/gen-BJc9vdyu.js +0 -2
- package/dist/cli/gen-C2osRcr5.js +0 -2204
- package/dist/cli/read-sets-BfMQcKy8.js +0 -289
- package/dist/cli/sql-DzPbfngx.js +0 -348
- package/dist/entitlements-CTEBm7IB.js +0 -20
- package/dist/events-aIO7vsIk.d.ts +0 -230
- package/dist/executor-BunPOO-k.d.ts +0 -402
- package/dist/executor-XycESQPH.js +0 -94
- package/dist/impersonation-VfaGc4Q_.js +0 -41
- package/dist/index-BGdgBPdf.d.ts +0 -161
- package/dist/index-DOESKG27.d.ts +0 -100
- package/dist/index-DmXSxbLi.d.ts +0 -62
- package/dist/index-Dxn2a5cw.d.ts +0 -50
- package/dist/jobs/index.d.ts +0 -226
- package/dist/jobs/index.js +0 -1007
- package/dist/json-schema-m1fiwKgN.js +0 -208
- package/dist/kit-events-CTFDfSwb.js +0 -60
- package/dist/kit-transport-B82k1djG.d.ts +0 -33
- package/dist/kits-CGLLrNPd.js +0 -157
- package/dist/notifications/index.d.ts +0 -162
- package/dist/notifications/index.js +0 -264
- package/dist/orgs/index.d.ts +0 -132
- package/dist/orgs/index.js +0 -245
- package/dist/permdock-sql-C2Inc6Xc.d.ts +0 -29
- package/dist/permdock-sql-DgOfeixi.js +0 -51
- package/dist/plugin-DwARMuQp.js +0 -59
- package/dist/server-Csx2sRjg.js +0 -655
- package/dist/stats-Bqob3WqT.js +0 -592
- package/dist/support-DT-OhSxD.d.ts +0 -88
- package/dist/template-mbvlysOo.d.ts +0 -6
- package/dist/temporal-CVlIV2DZ.js +0 -40
- package/dist/user-change-CHFEUro1.js +0 -49
- package/dist/webhooks/index.d.ts +0 -285
- 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" }
|
package/schemas/snapshot-v2.json
CHANGED
|
@@ -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
|
|
20
|
-
|
|
21
|
-
`[experimental.pgdelta] enabled = true`
|
|
22
|
-
|
|
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.
|
|
27
|
-
Postgres runs once per statement, not `
|
|
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
|
|
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
|
|
69
|
-
|
|
70
|
-
|
|
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
|
-
-
|
|
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 `
|
|
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.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
the
|
|
65
|
-
|
|
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) |
|
|
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
|
|
61
|
-
|
|
|
62
|
-
| Next.js
|
|
63
|
-
| Hono
|
|
64
|
-
| oRPC
|
|
65
|
-
|
|
|
66
|
-
|
|
|
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
|
-
##
|
|
100
|
+
## AI chat (`sql add ai-chat`; `ai`, `@ai-sdk/react`, `@ai-sdk/workflow` and `workflow` as optional peers)
|
|
90
101
|
|
|
91
|
-
-
|
|
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
|
-
- `
|
|
94
|
-
- Times are `Temporal.Instant`: `EnqueueOptions.runAt`, `Job.enqueuedAt`, `Job.visibleUntil`, `
|
|
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/
|
|
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 `
|
|
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 `
|
|
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
|
|
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
|
|
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
|
|
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
|
|
120
|
-
|
|
121
|
-
https://bettersupabase.com/docs/
|
|
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.
|