better-supabase 0.15.0 → 0.16.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/dist/{adapter-B0b6MXYS.js → adapter-Dyks1lX1.js} +1 -1
- package/dist/{agents-5n8DWRfP.d.ts → agents-CMIB3802.d.ts} +1 -1
- package/dist/{ai-cache-DyHohbFP.d.ts → ai-cache-2LGgaT7F.d.ts} +1 -1
- package/dist/{ai-chat-D1GuRnke.d.ts → ai-chat-BCaKsvLW.d.ts} +1 -1
- package/dist/{ai-schedules-CAquecT_.d.ts → ai-schedules-BmkARmQ9.d.ts} +2 -2
- package/dist/ai-sdk/agents/index.d.ts +4 -4
- package/dist/ai-sdk/batches/index.d.ts +1 -1
- package/dist/ai-sdk/cache/index.d.ts +1 -1
- package/dist/ai-sdk/chat/index.d.ts +1 -1
- package/dist/ai-sdk/embeddings/index.d.ts +2 -2
- package/dist/ai-sdk/index.d.ts +4 -4
- package/dist/ai-sdk/memory/index.d.ts +3 -3
- package/dist/ai-sdk/workflow/index.d.ts +3 -3
- package/dist/{api-DxAPqMrE.d.ts → api-hHwieEfz.d.ts} +1 -1
- package/dist/{app-tables-CF2DD-Mu.d.ts → app-tables-yMQ4ubyY.d.ts} +1 -1
- package/dist/{approvals-Crutd4-o.d.ts → approvals-Dh9dUXrN.d.ts} +1 -1
- package/dist/{assistant-CD_h8Vxx.d.ts → assistant-ndGdOBax.d.ts} +2 -2
- package/dist/astro/index.d.ts +4 -4
- package/dist/astro/index.js +2 -2
- package/dist/{auth-module-BEFESDC4.js → auth-module-BbmX-N4L.js} +12 -4
- package/dist/{authorization-hooks-Cs1vP_ej.d.ts → authorization-hooks-D_pwXlBs.d.ts} +4 -0
- package/dist/better-result/index.d.ts +2 -2
- package/dist/{bind-CrMBwrPN.d.ts → bind-JGCPGUJh.d.ts} +4 -4
- package/dist/{block-env-B_uEM2xz.d.ts → block-env-y65GF_px.d.ts} +4 -4
- package/dist/blocks/access-requests/index.d.ts +1 -1
- package/dist/blocks/activities/index.d.ts +2 -2
- package/dist/blocks/agents/index.d.ts +2 -2
- package/dist/blocks/ai-cache/index.d.ts +2 -2
- package/dist/blocks/ai-chat/index.d.ts +5 -5
- package/dist/blocks/ai-files/index.d.ts +1 -1
- package/dist/blocks/ai-keys/index.d.ts +1 -1
- package/dist/blocks/ai-schedules/index.d.ts +2 -2
- package/dist/blocks/announcements/index.d.ts +4 -4
- package/dist/blocks/api-keys/index.d.ts +2 -2
- package/dist/blocks/approvals/index.d.ts +2 -2
- package/dist/blocks/assets/index.d.ts +1 -1
- package/dist/blocks/assignment/index.d.ts +1 -1
- package/dist/blocks/attachments/index.d.ts +2 -2
- package/dist/blocks/audit/index.d.ts +5 -5
- package/dist/blocks/automations/index.d.ts +4 -4
- package/dist/blocks/billable-time/index.d.ts +1 -1
- package/dist/blocks/billing/index.d.ts +3 -3
- package/dist/blocks/bookings/index.d.ts +3 -3
- package/dist/blocks/bulk/index.d.ts +1 -1
- package/dist/blocks/calendar/index.d.ts +2 -2
- package/dist/blocks/catalog/index.d.ts +1 -1
- package/dist/blocks/channels/index.d.ts +1 -1
- package/dist/blocks/collections/index.d.ts +1 -1
- package/dist/blocks/comments/index.d.ts +4 -4
- package/dist/blocks/compliance/index.d.ts +1 -1
- package/dist/blocks/connectors/index.d.ts +1 -1
- package/dist/blocks/contacts/index.d.ts +1 -1
- package/dist/blocks/content/index.d.ts +1 -1
- package/dist/blocks/contracts/index.d.ts +1 -1
- package/dist/blocks/courses/index.d.ts +1 -1
- package/dist/blocks/created-by/index.d.ts +1 -1
- package/dist/blocks/custom-fields/index.d.ts +1 -1
- package/dist/blocks/data-lifecycle/index.d.ts +2 -2
- package/dist/blocks/deals/index.d.ts +1 -1
- package/dist/blocks/dispatch/index.d.ts +1 -1
- package/dist/blocks/documents/index.d.ts +1 -1
- package/dist/blocks/domains/index.d.ts +1 -1
- package/dist/blocks/donations/index.d.ts +1 -1
- package/dist/blocks/drive/index.d.ts +2 -2
- package/dist/blocks/employees/index.d.ts +2 -2
- package/dist/blocks/enrichment/index.d.ts +1 -1
- package/dist/blocks/enrollments/index.d.ts +1 -1
- package/dist/blocks/entitlements/index.d.ts +3 -3
- package/dist/blocks/expenses/index.d.ts +1 -1
- package/dist/blocks/field-history/index.d.ts +1 -1
- package/dist/blocks/flags/index.d.ts +1 -1
- package/dist/blocks/forecasts/index.d.ts +1 -1
- package/dist/blocks/forms/index.d.ts +2 -2
- package/dist/blocks/goals/index.d.ts +1 -1
- package/dist/blocks/guests/index.d.ts +1 -1
- package/dist/blocks/hiring/index.d.ts +1 -1
- package/dist/blocks/identities/index.d.ts +2 -2
- package/dist/blocks/imports/index.d.ts +1 -1
- package/dist/blocks/inbox/index.d.ts +5 -5
- package/dist/blocks/incidents/index.d.ts +1 -1
- package/dist/blocks/index.d.ts +2 -2
- package/dist/blocks/inventory/index.d.ts +2 -2
- package/dist/blocks/invoices/index.d.ts +1 -1
- package/dist/blocks/knowledge/index.d.ts +2 -2
- package/dist/blocks/lead-scoring/index.d.ts +1 -1
- package/dist/blocks/leases/index.d.ts +1 -1
- package/dist/blocks/leave/index.d.ts +1 -1
- package/dist/blocks/ledger/index.d.ts +1 -1
- package/dist/blocks/mail-sync/index.d.ts +1 -1
- package/dist/blocks/memberships/index.d.ts +1 -1
- package/dist/blocks/memory/index.d.ts +3 -3
- package/dist/blocks/messaging/index.d.ts +4 -4
- package/dist/blocks/metrics/index.d.ts +2 -2
- package/dist/blocks/mfa/index.d.ts +2 -2
- package/dist/blocks/moderation/index.d.ts +1 -1
- package/dist/blocks/notifications/index.d.ts +5 -5
- package/dist/blocks/numbering/index.d.ts +1 -1
- package/dist/blocks/oauth-server/index.d.ts +1 -1
- package/dist/blocks/onboarding/index.d.ts +2 -2
- package/dist/blocks/orders/index.d.ts +3 -3
- package/dist/blocks/organizations/index.d.ts +2 -2
- package/dist/blocks/outbox/index.d.ts +2 -2
- package/dist/blocks/passes/index.d.ts +2 -2
- package/dist/blocks/permissions/index.d.ts +3 -3
- package/dist/blocks/pipelines/index.d.ts +1 -1
- package/dist/blocks/posts/index.d.ts +1 -1
- package/dist/blocks/profiles/index.d.ts +1 -1
- package/dist/blocks/promotions/index.d.ts +1 -1
- package/dist/blocks/push/index.d.ts +2 -2
- package/dist/blocks/queue/index.d.ts +30 -3
- package/dist/blocks/queue/index.js +2 -2
- package/dist/blocks/quotes/index.d.ts +1 -1
- package/dist/blocks/rank/index.d.ts +2 -2
- package/dist/blocks/reactions/index.d.ts +4 -4
- package/dist/blocks/relations/index.d.ts +1 -1
- package/dist/blocks/reminders/index.d.ts +3 -3
- package/dist/blocks/reviews/index.d.ts +1 -1
- package/dist/blocks/saved-views/index.d.ts +3 -3
- package/dist/blocks/scores/index.d.ts +1 -1
- package/dist/blocks/search/index.d.ts +3 -3
- package/dist/blocks/security-events/index.d.ts +1 -1
- package/dist/blocks/segments/index.d.ts +1 -1
- package/dist/blocks/sequences/index.d.ts +1 -1
- package/dist/blocks/service-accounts/index.d.ts +1 -1
- package/dist/blocks/sessions/index.d.ts +2 -2
- package/dist/blocks/settings/index.d.ts +2 -2
- package/dist/blocks/share-links/index.d.ts +1 -1
- package/dist/blocks/shipments/index.d.ts +1 -1
- package/dist/blocks/signatures/index.d.ts +1 -1
- package/dist/blocks/signing-keys/index.d.ts +1 -1
- package/dist/blocks/sla/index.d.ts +1 -1
- package/dist/blocks/sso/index.d.ts +1 -1
- package/dist/blocks/state-machine/index.d.ts +1 -1
- package/dist/blocks/subjects/index.d.ts +2 -2
- package/dist/blocks/tags/index.d.ts +2 -2
- package/dist/blocks/tasks/index.d.ts +2 -2
- package/dist/blocks/teams/index.d.ts +1 -1
- package/dist/blocks/templates/index.d.ts +3 -3
- package/dist/blocks/time-tracking/index.d.ts +1 -1
- package/dist/blocks/timeline/index.d.ts +3 -3
- package/dist/blocks/trash/index.d.ts +1 -1
- package/dist/blocks/undo/index.d.ts +2 -2
- package/dist/blocks/updated-at/index.d.ts +1 -1
- package/dist/blocks/usage/index.d.ts +3 -3
- package/dist/blocks/vercel-marketplace/index.d.ts +1 -1
- package/dist/blocks/versions/index.d.ts +1 -1
- package/dist/blocks/waitlist/index.d.ts +1 -1
- package/dist/blocks/webhooks/index.d.ts +4 -4
- package/dist/blocks/webhooks/index.js +1 -1
- package/dist/blocks/workflow-editor/index.d.ts +6 -6
- package/dist/blocks/workflow-editor/index.js +12 -1
- package/dist/blocks/workflows/index.d.ts +4 -4
- package/dist/{bookings-D4dvGXiR.d.ts → bookings-Dox2rced.d.ts} +1 -1
- package/dist/{bucket-CiNi8sIw.d.ts → bucket-vc-QRrva.d.ts} +40 -1
- package/dist/chat-sdk/index.d.ts +1 -1
- package/dist/cli/add-Bfb_ISrO.js +1 -0
- package/dist/cli/{add-BgsUjCan.js → add-D7TkPdco.js} +17 -12
- package/dist/cli/{add-DCI5JKjA.js → add-I8OW-qJH.js} +2 -2
- package/dist/cli/{backfill-nxPbcsns.js → backfill-DIz5DnlQ.js} +1 -1
- package/dist/cli/bin.js +1 -1
- package/dist/cli/{blocks-Cr4HGePW.js → blocks-Bp5RPoft.js} +1 -1
- package/dist/cli/{blocks-BZHI8mRC.js → blocks-xk-SE8gS.js} +1 -1
- package/dist/cli/{cache-CXgR_Ahi.js → cache-AznIssjI.js} +1 -1
- package/dist/cli/{codemod-DSN7iAdg.js → codemod-Aewxza6i.js} +95 -3
- package/dist/cli/{content-mapper-DNs7lTu7.js → content-mapper-DCrz6OIv.js} +2 -2
- package/dist/cli/{doctor-DDrEM6S1.js → doctor-DkOSLPEQ.js} +29 -14
- package/dist/cli/{gen-MtijJQ9r.js → gen-CFkYUnWq.js} +10 -10
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.js +6 -6
- package/dist/cli/{init-D-aDv9r5.js → init-CHj9ad4S.js} +5 -5
- package/dist/cli/legacy-prefix-DkTA3Rhx.js +141 -0
- package/dist/cli/{live-iEeH15ck.js → live-DGdLR41j.js} +2 -2
- package/dist/cli/{mcp-BAPyaQ62.js → mcp-BZno503V.js} +2 -2
- package/dist/cli/{metadata-DVx9Zgbj.js → metadata-BfgHMe4q.js} +3 -3
- package/dist/cli/{migration-safety-D7PhzFxm.js → migration-safety-BnnXPAro.js} +1 -1
- package/dist/cli/{module-migration-aPCckev6.js → module-migration-O_IxewFs.js} +5 -216
- package/dist/cli/{print-BeWO7OJY.js → print-DosQIFSy.js} +1 -1
- package/dist/cli/{remove-B46Dmd2M.js → remove-DK2G_KHm.js} +5 -4
- package/dist/cli/{render-ucJmUyuM.js → render-5y5a1QZr.js} +3 -3
- package/dist/cli/{run-CvYVAztY.js → run-Bs4OKdDI.js} +20 -7
- package/dist/cli/{run-DYhLBcFW.js → run-MRET30vh.js} +20 -20
- package/dist/cli/{shared-LZroULBe.js → shared-BLqbvY2x.js} +1 -1
- package/dist/cli/{snapshot-C8MVPyO8.js → snapshot-uTUlEzY2.js} +2 -2
- package/dist/cli/{source-DANaJJVc.js → source-D2gJHKwC.js} +1 -1
- package/dist/cli/{spec-DGVNMSSB.js → spec-Cm2einTO.js} +2 -2
- package/dist/cli/{spec-g8_G5K7o.js → spec-DUjOtciN.js} +1 -1
- package/dist/cli/sql-layout-lUWenjJw.js +247 -0
- package/dist/cli/{sync-btj01bcM.js → sync-CZMRB3aU.js} +2 -1
- package/dist/cli/{upgrade-B596d4t8.js → upgrade-BFEIMC7U.js} +4 -137
- package/dist/cli/{upgrade-Dw3TMQzn.js → upgrade-fVsJniXm.js} +2 -2
- package/dist/cli/{version-Du4CgONY.js → version-B2Dr6VmJ.js} +1 -1
- package/dist/client/index.d.ts +5 -5
- package/dist/client/index.js +1 -1
- package/dist/client/native/index.d.ts +5 -5
- package/dist/client/native/index.js +1 -1
- package/dist/{client-BAEbEA7t.js → client-C_mlji5R.js} +6 -5
- package/dist/{composite-BARuBEDE.js → composite-B3TIjId4.js} +1 -1
- package/dist/{composite-Dsxj7T5K.d.ts → composite-CfYyU3vs.d.ts} +4 -3
- package/dist/config/index.d.ts +1 -1
- package/dist/{context-CEuTKrkz.d.ts → context-8kb8m5uO.d.ts} +24 -2
- package/dist/{controller-BrP0gn47.d.ts → controller-BW-5Opig.d.ts} +1 -1
- package/dist/{conversion-BAbucuXq.d.ts → conversion-3iv2r7YC.d.ts} +1 -1
- package/dist/create/index.d.ts +2 -2
- package/dist/create/index.js +1 -1
- package/dist/{define-DFBnQyYg.d.ts → define-C5AcEkEJ.d.ts} +1 -1
- package/dist/{define-block-BVcLQ3DF.d.ts → define-block-C1RHXz7L.d.ts} +3 -3
- package/dist/delegation-C7eWP2r8.d.ts +14 -0
- package/dist/{delegation--93jRsVO.js → delegation-DGOIiT8k.js} +12 -5
- package/dist/edge/index.d.ts +5 -5
- package/dist/edge/index.js +3 -3
- package/dist/{embeddings-kFbRvuic.d.ts → embeddings-D_RsS6ow.d.ts} +1 -1
- package/dist/{entitlements-CJpYQXeE.d.ts → entitlements-sO977DO-.d.ts} +1 -1
- package/dist/{envelope-Bzu0JnY2.js → envelope-DEI2iX-d.js} +1 -1
- package/dist/eve/index.d.ts +2 -2
- package/dist/{eve-BFSwTu1z.d.ts → eve-B7jxYPCw.d.ts} +2 -2
- package/dist/{executor-CVIn6JHa.d.ts → executor-BcNWcD-4.d.ts} +2 -2
- package/dist/{executor-_2ekNofh.d.ts → executor-Bi056Cnj.d.ts} +1 -1
- package/dist/expo/index.d.ts +2 -2
- package/dist/expo/index.js +2 -2
- package/dist/{field-errors-fsbFktYF.d.ts → field-errors-Dt86dCKk.d.ts} +12 -12
- package/dist/{framework-BKyTeS-j.d.ts → framework-BGdZVyPL.d.ts} +3 -3
- package/dist/{framework-DDdkR7FX.js → framework-BozTXRzt.js} +1 -1
- package/dist/{gateway-TD1pRfTP.d.ts → gateway-DzI687yd.d.ts} +3 -3
- package/dist/hono/index.d.ts +4 -4
- package/dist/hono/index.js +2 -2
- package/dist/{index-C-qpk8EQ.d.ts → index-CENWq3zb.d.ts} +1 -1
- package/dist/{index-Do2ChN_y.d.ts → index-CQhPHHDF.d.ts} +20 -2
- package/dist/{index-B938YqY-.d.ts → index-CTu-3fJB.d.ts} +51 -3
- package/dist/{index-CguFm716.d.ts → index-Cc4mIQS8.d.ts} +32 -4
- package/dist/{index-DLq69k3F.d.ts → index-CcAmFNVi.d.ts} +2 -2
- package/dist/{index-BnH4Gomw.d.ts → index-Craf712U.d.ts} +44 -12
- package/dist/{index-BUuVq1co.d.ts → index-DZKCc2WM.d.ts} +3 -3
- package/dist/index.d.ts +2 -2
- package/dist/{knowledge-CtL-Vfgy.d.ts → knowledge-F1IhRI4Q.d.ts} +1 -1
- package/dist/list/index.d.ts +1 -1
- package/dist/{list-query-BDVutLFr.d.ts → list-query-DYhgRTd5.d.ts} +1 -1
- package/dist/mapper/bin.js +5 -5
- package/dist/mcp/index.d.ts +3 -3
- package/dist/mcp/index.js +1 -1
- package/dist/mcp/sdk/index.d.ts +2 -2
- package/dist/mcp/sdk/index.js +1 -1
- package/dist/next/client/index.d.ts +81 -1
- package/dist/next/client/index.js +178 -2
- package/dist/next/index.d.ts +15 -14
- package/dist/next/index.js +2 -2
- package/dist/orpc/index.d.ts +4 -4
- package/dist/orpc/index.js +1 -1
- package/dist/otel/index.js +4 -4
- package/dist/{outbox-HvGAJuBe.d.ts → outbox-HxjZTfF6.d.ts} +1 -1
- package/dist/{ports-DOhtuw3c.js → ports-CaVRXjxq.js} +1 -1
- package/dist/{ports-sx226JUL.d.ts → ports-mObLgH1z.d.ts} +1 -1
- package/dist/powersync/index.d.ts +2 -2
- package/dist/preset/index.d.ts +3 -3
- package/dist/{push-token-D3Vcf0Pf.d.ts → push-token-BSSvsWXZ.d.ts} +1 -1
- package/dist/query/index.d.ts +1 -1
- package/dist/{rate-limit-o44SYkVY.js → rate-limit-Dt9vAY4E.js} +53 -0
- package/dist/react/index.d.ts +6 -6
- package/dist/react/index.js +3 -3
- package/dist/react/native/index.d.ts +1 -1
- package/dist/react/native/index.js +1 -1
- package/dist/react/server.d.ts +12 -7
- package/dist/react/server.js +8 -3
- package/dist/react/session.d.ts +5 -0
- package/dist/react/session.js +9 -1
- package/dist/{react-BuDYI62C.js → react-CZUZYn9E.js} +41 -4
- package/dist/react-router/index.d.ts +3 -3
- package/dist/react-router/index.js +2 -2
- package/dist/realtime/index.d.ts +6 -6
- package/dist/realtime/index.js +2 -1
- package/dist/{record-form-BYs9xv_N.d.ts → record-form-D9ILuVtA.d.ts} +1 -1
- package/dist/records/index.d.ts +7 -7
- package/dist/relay-gKvKJ3xf.js +208 -0
- package/dist/{resource-execute-CzHuDsil.d.ts → resource-execute-Cpnob1Vj.d.ts} +1 -1
- package/dist/{resource-types-DnKiH4G2.d.ts → resource-types-pMeLs68X.d.ts} +1 -1
- package/dist/{resources-B9cQxhjw.d.ts → resources-7iq2-5_A.d.ts} +1 -1
- package/dist/server/index.d.ts +150 -11
- package/dist/server/index.js +400 -4
- package/dist/{server-types-CFtehAsr.d.ts → server-types-CK8mUIUT.d.ts} +5 -354
- package/dist/{session-CH0SKgIz.d.ts → session-DWmFv3vB.d.ts} +2 -1
- package/dist/session-status-qQLm7jzh.d.ts +82 -0
- package/dist/{sign-in-DNCdrk05.js → sign-in-B64114O4.js} +1 -1
- package/dist/{sign-in-BsIaNx2C.js → sign-in-CmPK1AgM.js} +20 -10
- package/dist/solid/index.d.ts +7 -7
- package/dist/solid/index.js +1 -1
- package/dist/solid-start/index.d.ts +3 -3
- package/dist/solid-start/index.js +2 -2
- package/dist/spec/index.d.ts +1 -1
- package/dist/sql/index.d.ts +4 -4
- package/dist/sql/index.js +2 -2
- package/dist/{sql-ClHIdgKS.js → sql-Dl3Alk43.js} +402 -13
- package/dist/sqlite/index.d.ts +1 -1
- package/dist/ssr/index.d.ts +1 -1
- package/dist/storage/index.d.ts +3 -3
- package/dist/storage/index.js +54 -1
- package/dist/{subject-readers-BNSzkqw_.d.ts → subject-readers-8GySC9Z8.d.ts} +1 -1
- package/dist/support-B4ZBVxt3.d.ts +357 -0
- package/dist/svelte/index.d.ts +7 -7
- package/dist/svelte/index.js +1 -1
- package/dist/sveltekit/index.d.ts +4 -4
- package/dist/sveltekit/index.js +2 -2
- package/dist/{tags-BjHflcHF.d.ts → tags-qvVk79pp.d.ts} +1 -1
- package/dist/tanstack-db/index.d.ts +1 -1
- package/dist/tanstack-start/index.d.ts +3 -3
- package/dist/tanstack-start/index.js +2 -2
- package/dist/{tenant-yYg0E2-n.d.ts → tenant-DOKIJI62.d.ts} +1 -1
- package/dist/testing/index.d.ts +13 -12
- package/dist/{timeline-CtG0sehj.d.ts → timeline-CvTuXYvn.d.ts} +3 -3
- package/dist/{topic-CJrQZQaa.d.ts → topic-CZXHhZye.d.ts} +3 -3
- package/dist/{types-CAQBmpDx.d.ts → types-A4yyKEsg.d.ts} +1 -1
- package/dist/{types-SFRomQF7.d.ts → types-Czq9Xtpa.d.ts} +1 -7
- package/dist/{types-BBQLbui9.d.ts → types-DsRfiQ0v.d.ts} +1 -1
- package/dist/{usage-D7QkrwzV.d.ts → usage-Dp45V42p.d.ts} +1 -1
- package/dist/{verify-CMou8dWZ.d.ts → verify-CjvNLY7N.d.ts} +1 -1
- package/dist/vue/index.d.ts +7 -7
- package/dist/vue/index.js +1 -1
- package/dist/{watch-topic-BcGfvZOE.d.ts → watch-topic-BAxoPKZx.d.ts} +1 -1
- package/dist/workflow-sdk/builder/index.d.ts +3 -3
- package/dist/workflow-sdk/builder/index.js +1 -1
- package/dist/workflow-sdk/index.d.ts +1 -1
- package/dist/workflow-sdk/index.js +1 -1
- package/dist/{workflow-sdk-BFHu4sci.d.ts → workflow-sdk-B3Ss55Fy.d.ts} +1 -1
- package/dist/{workflow-sdk-BVlFEB5Q.js → workflow-sdk-Cf0LAOFF.js} +2 -2
- package/dist/yjs/index.d.ts +1 -1
- package/package.json +1 -1
- package/schemas/doctor-report-v1.json +1 -0
- package/skills/better-supabase-api/SKILL.md +3 -1
- package/skills/better-supabase-auth/SKILL.md +7 -0
- package/dist/cli/add-DWjlVwvP.js +0 -1
package/dist/server/index.d.ts
CHANGED
|
@@ -4,31 +4,36 @@ import { Ct as Events, lt as SupportEventData } from "../events-vcqenSYU.js";
|
|
|
4
4
|
import { C as readSession, D as writeSession, T as sessionCookieName, _ as StoredSession, a as ResolveAuthOptions, c as clientIp, d as CookieOptions, f as CookieRecord, i as InvalidReason, l as resolveAuth, m as CookieWrite, n as AuthResolver, r as AuthState, s as ResolvedState, t as AuthResolution, u as AUTH_CACHE_HEADERS } from "../resolve-CXX6DHv3.js";
|
|
5
5
|
import { n as SqlClient } from "../executor-hGjrop3A.js";
|
|
6
6
|
import { a as SessionActor, c as agentClaims, i as IDENTITY_SCOPES, l as delegationOf, n as ActorOutcome, o as SessionDelegation, r as AgentActOptions, s as actorOf, t as ActClaim } from "../actor-CoveJgya.js";
|
|
7
|
-
import {
|
|
7
|
+
import { n as PERMISSION_CAP_CLAIM } from "../delegation-C7eWP2r8.js";
|
|
8
|
+
import { a as ProblemFormat, c as fromProblem, d as toProblem, i as ProblemDetails, l as isProblem, n as PROBLEM_CONTENT_TYPE, o as ProblemOptions, r as PROBLEM_TYPE_BASE, s as ProblemResponseOptions, u as problemResponse } from "../problem-DNwN8iGz.js";
|
|
8
9
|
import { a as AuthorizationSubject, c as AuthzVersionCache, d as bindAuthorizer, f as defineAuthorizer, i as AuthorizationResource, l as PermissionRef, n as AuthorizationOutcome, o as Authorizer, p as requestMemo, r as AuthorizationRequest, s as AuthorizerRuntime, t as AnyAuthorizer, u as RequestMemo } from "../authorizer-B6X09otb.js";
|
|
9
|
-
import { J as DbStats, t as BetterSupabase, v as Db } from "../define-
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
10
|
+
import { J as DbStats, t as BetterSupabase, v as Db } from "../define-C5AcEkEJ.js";
|
|
11
|
+
import { j as StorageApi } from "../bucket-vc-QRrva.js";
|
|
12
|
+
import { A as isSessionSnapshot, C as DeleteAccountResult, D as SessionMemoStats, E as SessionMemoOptions, M as sessionCacheKey, N as sessionMemo, O as SessionSnapshot, P as snapshotOf, S as DeleteAccountOptions, T as SessionMemo, _ as suspendAccount, a as ServerContext, b as ReplicaState, c as ServerOptions, d as EndSessionsResult, f as LastSignIn, g as lastSignIns, h as endSessions, i as ForContextOptions, j as issuedAtOf, k as authzVersionOf, m as SuspendAccountResult, n as BetterServer, o as ServerDbOptions, p as SuspendAccountOptions, r as ContextOptions, s as ServerKeys, t as AdminDb, u as TENANT_HEADER, v as RequestIdOptions, w as deleteAccount, x as LiteDriver, y as PRIMARY_COOKIE } from "../server-types-CK8mUIUT.js";
|
|
12
13
|
import { n as Impersonator, r as impersonatorOf, t as ImpersonationOptions } from "../impersonation-YTa9dZUv.js";
|
|
13
14
|
import { a as checkAal, i as amrOf, n as AmrEntry, r as aalOf, t as Aal } from "../mfa-oIOYTpvc.js";
|
|
14
|
-
import { _ as SupportAuthorize, a as AutomationHooks, b as TicketSubject, c as ChatActionHook, d as IdentityRef, f as IdentityTarget, g as SubscriberPolicy, h as SubscriberEvent, i as AuthorizationHooks, l as DelegationPermissions, m as Subscriber, n as Approver, o as AutomationRef, p as PrincipalByIdentity, r as ApproverOf, s as ChatAction, t as ApprovalRequestRef, u as DelegationRef, v as SupportAuthorizeInput, x as defineAuthorizationHooks, y as SupportDecision } from "../authorization-hooks-
|
|
15
|
+
import { _ as SupportAuthorize, a as AutomationHooks, b as TicketSubject, c as ChatActionHook, d as IdentityRef, f as IdentityTarget, g as SubscriberPolicy, h as SubscriberEvent, i as AuthorizationHooks, l as DelegationPermissions, m as Subscriber, n as Approver, o as AutomationRef, p as PrincipalByIdentity, r as ApproverOf, s as ChatAction, t as ApprovalRequestRef, u as DelegationRef, v as SupportAuthorizeInput, x as defineAuthorizationHooks, y as SupportDecision } from "../authorization-hooks-D_pwXlBs.js";
|
|
16
|
+
import { c as RealtimeClient } from "../topic-CZXHhZye.js";
|
|
15
17
|
import { n as toSession, t as AuthSession } from "../view-DyFdMCqg.js";
|
|
16
|
-
import { a as
|
|
18
|
+
import { C as SupportSessionStore, E as supportClaims, S as SupportSession, T as sqlSupportStore, _ as SupportCallerClaims, a as SupportPolicy, b as SupportRequest, c as supportSessions, d as clearSupportCookie, f as supportCookie, g as SupportApprover, h as SupportApprovalQuery, i as SupportOptions, l as SUPPORT_COOKIE, m as SqlSupportStoreOptions, n as SupportApi, o as SupportSessions, p as supportCookieValue, r as SupportExpireRouteOptions, s as SupportStartRequest, t as ActiveSupport, u as SupportCookieOptions, v as SupportEndedBy, w as SupportStartInput, x as SupportRequestInput, y as SupportListFilter } from "../support-B4ZBVxt3.js";
|
|
19
|
+
import { a as serverCore, i as ServerCore, n as SessionEntryConfig, r as withSession, t as AuthOutageHook } from "../session-DWmFv3vB.js";
|
|
17
20
|
import { a as RespondOptions, c as isResult, d as RefreshPolicy, f as isPrefetch, h as shouldRefresh, i as MiddlewareOptions, l as respond, m as shouldCheckSession, n as AuthKind, o as Settled, p as refreshFor, r as GuardOptions, s as guard, u as settle } from "../respond-Dn1_YhC1.js";
|
|
18
|
-
import { a as GuardEntryConfig, i as withBetterSupabase, n as BetterSupabaseContributions, o as withGuard, r as BetterSupabaseEntry, t as BetterSupabaseConfig } from "../composite-
|
|
21
|
+
import { a as GuardEntryConfig, i as withBetterSupabase, n as BetterSupabaseContributions, o as withGuard, r as BetterSupabaseEntry, t as BetterSupabaseConfig } from "../composite-CfYyU3vs.js";
|
|
19
22
|
import { a as AuthorizedContext, c as ResourceLoaderContext, d as rolesAt, i as AuthorizeOptions, o as BlockActionOptions, r as ActionResult, s as BlockRequireOptions, u as hasRole } from "../kit-DOwKpSkA.js";
|
|
20
|
-
import { n as subjectReaders, t as SubjectReadersOptions } from "../subject-readers-
|
|
23
|
+
import { n as subjectReaders, t as SubjectReadersOptions } from "../subject-readers-8GySC9Z8.js";
|
|
21
24
|
import { i as toCsv, n as csvColumns, t as CsvOptions } from "../csv-DhHQS2x_.js";
|
|
22
25
|
import { i as JwsAlgorithm, n as Jwks, r as JwksOfOptions } from "../jws-D0toeQlA.js";
|
|
23
26
|
import { i as ResourcePagination } from "../resource-D8pzB5Qf.js";
|
|
24
|
-
import { a as ResourceHandler, c as ResourceList, l as ResourceRouteOptions, s as ResourceInput } from "../resource-types-
|
|
25
|
-
import { i as
|
|
27
|
+
import { a as ResourceHandler, c as ResourceList, l as ResourceRouteOptions, s as ResourceInput } from "../resource-types-pMeLs68X.js";
|
|
28
|
+
import { a as claimsFingerprint, i as SessionWatchStatus, n as SessionStatusRouteOptions, o as sessionStatusRoute, r as SessionStatusServer, t as SessionStatusBody } from "../session-status-qQLm7jzh.js";
|
|
29
|
+
import { i as tagFor, n as cacheTagsOf, r as tagCache, t as TagOptions } from "../tags-qvVk79pp.js";
|
|
26
30
|
import { n as RefreshOutcome, r as refreshSession } from "../refresh-DT_ICaK-.js";
|
|
27
31
|
import { n as passwordGrant, r as safeRedirectPath, t as PasswordGrantOptions } from "../sign-in-BAjR49fq.js";
|
|
28
32
|
import { n as supportOf, t as SupportView } from "../support-view-BYOgwXsJ.js";
|
|
29
33
|
import { a as sessionStatus, i as clearSessionCookies, n as SessionStatus, o as authContext, r as SessionStatusOptions, t as ClearSessionCookiesOptions } from "../ended-gUsMZVNg.js";
|
|
30
34
|
import { SupabaseClient } from "@supabase/supabase-js";
|
|
31
35
|
import { Middleware, SingleKeyEntry } from "@supabase/middleware";
|
|
36
|
+
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
32
37
|
import { AuthMode, JWTClaims, UserClaims } from "@supabase/server";
|
|
33
38
|
import { PostgresApi } from "@supabase/server/middleware/postgres";
|
|
34
39
|
//#region src/server/csv.d.ts
|
|
@@ -193,6 +198,140 @@ interface SupportStorageOptions {
|
|
|
193
198
|
*/
|
|
194
199
|
export declare function supportStorage(options: SupportStorageOptions): StorageApi;
|
|
195
200
|
//#endregion
|
|
201
|
+
//#region src/server/realtime-relay.d.ts
|
|
202
|
+
/**
|
|
203
|
+
* A topic the relay serves: a `defineTopic(...)` topic, or `liveRelayTopic` for
|
|
204
|
+
* the `realtime-tables` channels behind `liveQuery` and `useLiveQuery`.
|
|
205
|
+
*/
|
|
206
|
+
interface RelayTopic {
|
|
207
|
+
readonly private: boolean;
|
|
208
|
+
/** Join with presence, so members' states reach the client. */
|
|
209
|
+
readonly presence?: boolean;
|
|
210
|
+
/** Whether clients may broadcast on it (`defineTopic`'s `send` option). */
|
|
211
|
+
readonly clientSend?: boolean;
|
|
212
|
+
/** Payload schemas per event; a send through the relay is validated. */
|
|
213
|
+
readonly events?: Readonly<Record<string, StandardSchemaV1>>;
|
|
214
|
+
/** Anything but `null` when `topic` is one of this topic's names. */
|
|
215
|
+
match(topic: string): unknown;
|
|
216
|
+
}
|
|
217
|
+
/** The channels `liveQuery` joins: `bsb:t:<schema>.<table>[:...]`, private. */
|
|
218
|
+
export declare const liveRelayTopic: RelayTopic;
|
|
219
|
+
/** What `authorize` decides on. */
|
|
220
|
+
interface RelayAccessInput {
|
|
221
|
+
readonly topic: string;
|
|
222
|
+
readonly action: "receive" | "send";
|
|
223
|
+
/** The caller: in a support session, the viewed user. */
|
|
224
|
+
readonly auth: AuthState;
|
|
225
|
+
readonly support: ActiveSupport | undefined;
|
|
226
|
+
/** The claims the check runs with: the target's in a support session. */
|
|
227
|
+
readonly claims: Readonly<Record<string, unknown>>;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Decides whether the caller may receive or send on a topic. A throw or
|
|
231
|
+
* rejection denies.
|
|
232
|
+
*/
|
|
233
|
+
type RelayAuthorize = (input: RelayAccessInput) => boolean | PromiseLike<boolean>;
|
|
234
|
+
/**
|
|
235
|
+
* The part of a server the relay uses: `createServer`, `createNext` and the
|
|
236
|
+
* other adapters fit.
|
|
237
|
+
*/
|
|
238
|
+
interface RelayServer {
|
|
239
|
+
context(request: Request, options?: {
|
|
240
|
+
readonly refresh?: boolean;
|
|
241
|
+
}): Promise<{
|
|
242
|
+
readonly auth: AuthState;
|
|
243
|
+
readonly resolution: {
|
|
244
|
+
readonly auth: AuthState;
|
|
245
|
+
};
|
|
246
|
+
readonly support?: ActiveSupport;
|
|
247
|
+
apply(response: Response): Response;
|
|
248
|
+
}>;
|
|
249
|
+
admin(): {
|
|
250
|
+
readonly $client: RealtimeClient;
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
/** A pool that runs a function in one transaction: `createPostgres()`. */
|
|
254
|
+
interface RelayPostgres {
|
|
255
|
+
transaction<T>(fn: (client: SqlClient) => Promise<T>): Promise<T>;
|
|
256
|
+
}
|
|
257
|
+
interface RealtimeRelayOptions {
|
|
258
|
+
/** The topics the relay serves; any other name answers 404. */
|
|
259
|
+
readonly topics: readonly RelayTopic[];
|
|
260
|
+
/**
|
|
261
|
+
* Checks each join and send against the `realtime.messages` policies, run as
|
|
262
|
+
* the caller (the viewed user in a support session) the way Realtime checks a
|
|
263
|
+
* browser's join. Needs a pool whose role may assume `authenticated`, such as
|
|
264
|
+
* `createPostgres()`.
|
|
265
|
+
*/
|
|
266
|
+
readonly postgres?: RelayPostgres;
|
|
267
|
+
/** Decides access instead of the policies. */
|
|
268
|
+
readonly authorize?: RelayAuthorize;
|
|
269
|
+
/**
|
|
270
|
+
* The client that joins upstream. Defaults to the server's secret-key client
|
|
271
|
+
* (`server.admin().$client`); joins of a topic share one channel per
|
|
272
|
+
* process.
|
|
273
|
+
*/
|
|
274
|
+
readonly upstream?: RealtimeClient;
|
|
275
|
+
/** Milliseconds between keep-alive comments. Defaults to 25000. */
|
|
276
|
+
readonly heartbeatMs?: number;
|
|
277
|
+
/**
|
|
278
|
+
* Milliseconds a stream stays open before it ends with `max_duration` and the
|
|
279
|
+
* client reconnects, which checks access again. Defaults to 240000, under
|
|
280
|
+
* common serverless limits.
|
|
281
|
+
*/
|
|
282
|
+
readonly maxDurationMs?: number;
|
|
283
|
+
/**
|
|
284
|
+
* Events a slow client may fall behind by before its stream ends with
|
|
285
|
+
* `overflow`; the reconnect reports a rejoin, so the client refetches.
|
|
286
|
+
* Defaults to 256.
|
|
287
|
+
*/
|
|
288
|
+
readonly maxQueued?: number;
|
|
289
|
+
/** Milliseconds the client waits before reconnecting. Defaults to 1000. */
|
|
290
|
+
readonly retryMs?: number;
|
|
291
|
+
/**
|
|
292
|
+
* Refresh an expiring session cookie and send the new cookies. Defaults to
|
|
293
|
+
* false: the proxy refreshes, and an expired session answers 401.
|
|
294
|
+
*/
|
|
295
|
+
readonly refresh?: boolean;
|
|
296
|
+
readonly problem?: ProblemFormat;
|
|
297
|
+
}
|
|
298
|
+
/** Why the relay ended a stream, in its `end` event. */
|
|
299
|
+
type RelayEndReason = "expired" | "max_duration" | "overflow" | "closed" | "upstream_error";
|
|
300
|
+
/**
|
|
301
|
+
* Whether `claims` may receive or send on `topic`, by the `realtime.messages`
|
|
302
|
+
* policies, checked the way Realtime checks a join: a probe message is
|
|
303
|
+
* inserted, then read (receive) or written (send) as the caller, and the
|
|
304
|
+
* transaction rolls back.
|
|
305
|
+
*/
|
|
306
|
+
export declare function realtimeTopicAccess(postgres: RelayPostgres, input: {
|
|
307
|
+
readonly claims: Readonly<Record<string, unknown>>;
|
|
308
|
+
readonly topic: string;
|
|
309
|
+
readonly action: "receive" | "send";
|
|
310
|
+
readonly extension?: "broadcast" | "presence";
|
|
311
|
+
}): Promise<boolean>;
|
|
312
|
+
/**
|
|
313
|
+
* Realtime for callers without a browser token of their own: a support session
|
|
314
|
+
* ("view as user"), or an app that keeps sessions in httpOnly cookies. `GET
|
|
315
|
+
* ?topic=<name>` resolves the caller, checks the topic's access as that caller
|
|
316
|
+
* (the viewed user in a support session), joins upstream with the secret key
|
|
317
|
+
* and streams the topic's broadcasts and presence as server-sent events. `POST
|
|
318
|
+
* { topic, event, payload }` broadcasts for the caller after the same check on
|
|
319
|
+
* the send policy; read-only support sessions can't send.
|
|
320
|
+
* `relayRealtimeClient(url)` from `better-supabase/realtime` is the client.
|
|
321
|
+
*
|
|
322
|
+
* ```ts
|
|
323
|
+
* // app/api/realtime/route.ts
|
|
324
|
+
* export const { GET, POST } = realtimeRelay(bsb, {
|
|
325
|
+
* topics: [notifications, liveRelayTopic],
|
|
326
|
+
* postgres,
|
|
327
|
+
* });
|
|
328
|
+
* ```
|
|
329
|
+
*/
|
|
330
|
+
export declare function realtimeRelay(server: RelayServer, options: RealtimeRelayOptions): {
|
|
331
|
+
readonly GET: (request: Request) => Promise<Response>;
|
|
332
|
+
readonly POST: (request: Request) => Promise<Response>;
|
|
333
|
+
};
|
|
334
|
+
//#endregion
|
|
196
335
|
//#region src/server/entries/upstream.d.ts
|
|
197
336
|
/** The `withSupabase` context keys `withBetterDb` and `withBetterPostgres` read. */
|
|
198
337
|
interface SupabaseAuthContext {
|
|
@@ -499,4 +638,4 @@ export declare function withDbStats(options?: {
|
|
|
499
638
|
};
|
|
500
639
|
}, () => DbStats>;
|
|
501
640
|
//#endregion
|
|
502
|
-
export { AUTH_CACHE_HEADERS, type Aal, type AccessTokenResolverOptions, type AccessTokenRevocation, type AccountEventType, type ActClaim, type ActionResult, type ActiveSupport, type ActorOutcome, type AdminDb, type AgentActOptions, type AmrEntry, type AnyAuthorizer, type ApprovalRequestRef, type Approver, type ApproverOf, type AuthKind, type AuthOutageHook, type AuthResolution, type AuthResolver, type AuthSession, type AuthState, type AuthorizationHooks, type AuthorizationOutcome, type AuthorizationRequest, type AuthorizationResource, type AuthorizationSubject, type AuthorizeOptions, type AuthorizedContext, type Authorizer, type AuthorizerRuntime, type AuthzVersionCache, type AuthzVersionChannel, type AuthzVersionClient, type AuthzVersionSubscription, type AutomationHooks, type AutomationRef, type BetterServer, type BetterSupabaseConfig, type BetterSupabaseContributions, type BetterSupabaseEntry, type BlockActionOptions, type BlockRequireOptions, type ChatAction, type ChatActionHook, type ClearSessionCookiesOptions, type ContextOptions, type CookieOptions, type CookieRecord, type CookieWrite, type CsvOptions, type CsvResponseOptions, type DelegationPermissions, type DelegationRef, type DeleteAccountOptions, type DeleteAccountResult, type EndSessionsResult, type ForContextOptions, type GuardEntryConfig, type GuardOptions, type HandleOptions, IDENTITY_SCOPES, type IdentityRef, type IdentityTarget, type ImpersonationEvents, type ImpersonationOptions, type Impersonator, type InvalidReason, type LastSignIn, type LiteDriver, type MiddlewareOptions, PRIMARY_COOKIE, PROBLEM_CONTENT_TYPE, PROBLEM_TYPE_BASE, type PasswordGrantOptions, type PermissionRef, type PrincipalByIdentity, type ProblemDetails, type ProblemOptions, type ProblemResponseOptions, type RateLimitPolicy, type RateLimitState, type RefreshOutcome, type RefreshPolicy, type ReplicaState, type RequestIdOptions, type RequestMemo, type ResolveAuthOptions, type ResolvedState, type ResourceHandler, type ResourceInput, type ResourceList, type ResourceLoaderContext, type ResourcePagination, type ResourceRouteOptions, type RespondOptions, SUPPORT_COOKIE, type ServerContext, type ServerCore, type ServerDbOptions, type ServerOptions, type ServerTiming, type SessionActor, type SessionDelegation, type SessionEntryConfig, type SessionLookup, type SessionMemo, type SessionMemoOptions, type SessionMemoStats, type SessionSnapshot, type SessionStatus, type SessionStatusOptions, type Settled, type SqlSupportStoreOptions, type StoredSession, type SubjectReadersOptions, type SubscribeAuthzVersionsOptions, type Subscriber, type SubscriberEvent, type SubscriberPolicy, type SupabaseAuthContext, type SupportApi, type SupportApprovalQuery, type SupportApprover, type SupportAuthorize, type SupportAuthorizeInput, type SupportCallerClaims, type SupportCookieOptions, type SupportDecision, type SupportEndedBy, type SupportExpireRouteOptions, type SupportListFilter, type SupportOptions, type SupportPolicy, type SupportRequest, type SupportRequestInput, type SupportSession, type SupportSessionStore, type SupportSessions, type SupportStartInput, type SupportStartRequest, type SupportStorageOptions, type SupportView, type SuspendAccountOptions, type SuspendAccountResult, TENANT_HEADER, type TagOptions, type TicketSubject, aalOf, actorOf, agentClaims, amrOf, authContext, authzVersionOf, bindAuthorizer, cacheTagsOf, checkAal, clearSessionCookies, clearSupportCookie, clientIp, csvColumns, defineAuthorizationHooks, defineAuthorizer, delegationOf, deleteAccount, endSessions, fromProblem, guard, hasRole, impersonatorOf, isPrefetch, isProblem, isResult, isSessionSnapshot, issuedAtOf, lastSignIns, passwordGrant, problemResponse, readSession, refreshFor, refreshSession, requestMemo, resolveAuth, respond, rolesAt, safeRedirectPath, serverCore, sessionCacheKey, sessionCookieName, sessionMemo, sessionStatus, settle, shouldCheckSession, shouldRefresh, snapshotOf, sqlSupportStore, subjectReaders, supportClaims, supportCookie, supportCookieValue, supportOf, supportSessions, suspendAccount, tagCache, tagFor, toCsv, toProblem, toSession, withBetterSupabase, withGuard, withSession, writeSession };
|
|
641
|
+
export { AUTH_CACHE_HEADERS, type Aal, type AccessTokenResolverOptions, type AccessTokenRevocation, type AccountEventType, type ActClaim, type ActionResult, type ActiveSupport, type ActorOutcome, type AdminDb, type AgentActOptions, type AmrEntry, type AnyAuthorizer, type ApprovalRequestRef, type Approver, type ApproverOf, type AuthKind, type AuthOutageHook, type AuthResolution, type AuthResolver, type AuthSession, type AuthState, type AuthorizationHooks, type AuthorizationOutcome, type AuthorizationRequest, type AuthorizationResource, type AuthorizationSubject, type AuthorizeOptions, type AuthorizedContext, type Authorizer, type AuthorizerRuntime, type AuthzVersionCache, type AuthzVersionChannel, type AuthzVersionClient, type AuthzVersionSubscription, type AutomationHooks, type AutomationRef, type BetterServer, type BetterSupabaseConfig, type BetterSupabaseContributions, type BetterSupabaseEntry, type BlockActionOptions, type BlockRequireOptions, type ChatAction, type ChatActionHook, type ClearSessionCookiesOptions, type ContextOptions, type CookieOptions, type CookieRecord, type CookieWrite, type CsvOptions, type CsvResponseOptions, type DelegationPermissions, type DelegationRef, type DeleteAccountOptions, type DeleteAccountResult, type EndSessionsResult, type ForContextOptions, type GuardEntryConfig, type GuardOptions, type HandleOptions, IDENTITY_SCOPES, type IdentityRef, type IdentityTarget, type ImpersonationEvents, type ImpersonationOptions, type Impersonator, type InvalidReason, type LastSignIn, type LiteDriver, type MiddlewareOptions, PERMISSION_CAP_CLAIM, PRIMARY_COOKIE, PROBLEM_CONTENT_TYPE, PROBLEM_TYPE_BASE, type PasswordGrantOptions, type PermissionRef, type PrincipalByIdentity, type ProblemDetails, type ProblemOptions, type ProblemResponseOptions, type RateLimitPolicy, type RateLimitState, type RealtimeRelayOptions, type RefreshOutcome, type RefreshPolicy, type RelayAccessInput, type RelayAuthorize, type RelayEndReason, type RelayPostgres, type RelayServer, type RelayTopic, type ReplicaState, type RequestIdOptions, type RequestMemo, type ResolveAuthOptions, type ResolvedState, type ResourceHandler, type ResourceInput, type ResourceList, type ResourceLoaderContext, type ResourcePagination, type ResourceRouteOptions, type RespondOptions, SUPPORT_COOKIE, type ServerContext, type ServerCore, type ServerDbOptions, type ServerOptions, type ServerTiming, type SessionActor, type SessionDelegation, type SessionEntryConfig, type SessionLookup, type SessionMemo, type SessionMemoOptions, type SessionMemoStats, type SessionSnapshot, type SessionStatus, type SessionStatusBody, type SessionStatusOptions, type SessionStatusRouteOptions, type SessionStatusServer, type SessionWatchStatus, type Settled, type SqlSupportStoreOptions, type StoredSession, type SubjectReadersOptions, type SubscribeAuthzVersionsOptions, type Subscriber, type SubscriberEvent, type SubscriberPolicy, type SupabaseAuthContext, type SupportApi, type SupportApprovalQuery, type SupportApprover, type SupportAuthorize, type SupportAuthorizeInput, type SupportCallerClaims, type SupportCookieOptions, type SupportDecision, type SupportEndedBy, type SupportExpireRouteOptions, type SupportListFilter, type SupportOptions, type SupportPolicy, type SupportRequest, type SupportRequestInput, type SupportSession, type SupportSessionStore, type SupportSessions, type SupportStartInput, type SupportStartRequest, type SupportStorageOptions, type SupportView, type SuspendAccountOptions, type SuspendAccountResult, TENANT_HEADER, type TagOptions, type TicketSubject, aalOf, actorOf, agentClaims, amrOf, authContext, authzVersionOf, bindAuthorizer, cacheTagsOf, checkAal, claimsFingerprint, clearSessionCookies, clearSupportCookie, clientIp, csvColumns, defineAuthorizationHooks, defineAuthorizer, delegationOf, deleteAccount, endSessions, fromProblem, guard, hasRole, impersonatorOf, isPrefetch, isProblem, isResult, isSessionSnapshot, issuedAtOf, lastSignIns, passwordGrant, problemResponse, readSession, refreshFor, refreshSession, requestMemo, resolveAuth, respond, rolesAt, safeRedirectPath, serverCore, sessionCacheKey, sessionCookieName, sessionMemo, sessionStatus, sessionStatusRoute, settle, shouldCheckSession, shouldRefresh, snapshotOf, sqlSupportStore, subjectReaders, supportClaims, supportCookie, supportCookieValue, supportOf, supportSessions, suspendAccount, tagCache, tagFor, toCsv, toProblem, toSession, withBetterSupabase, withGuard, withSession, writeSession };
|
package/dist/server/index.js
CHANGED
|
@@ -1,24 +1,27 @@
|
|
|
1
1
|
import { n as dbError } from "../errors-BVFgt8BZ.js";
|
|
2
2
|
import { n as isRecord } from "../guards-6F2bCtQR.js";
|
|
3
3
|
import { t as base64ToText } from "../base64-B9Wlsdj7.js";
|
|
4
|
+
import { n as validate } from "../standard-BA3mLh6w.js";
|
|
4
5
|
import { c as toProblem, i as isProblem, n as PROBLEM_TYPE_BASE, o as problemResponse, r as fromProblem, t as PROBLEM_CONTENT_TYPE } from "../problem-Bf0cJ7tk.js";
|
|
5
6
|
import { i as delegationOf, n as actorOf, r as agentClaims, t as IDENTITY_SCOPES } from "../actor-go7p9-CJ.js";
|
|
6
7
|
import { i as userContext, r as impersonatorOf } from "../impersonation-DM3oWNoD.js";
|
|
7
8
|
import { t as supportOf } from "../support-view-g4YLBeqX.js";
|
|
9
|
+
import { t as joinTopic } from "../channels-CfcFPuo_.js";
|
|
8
10
|
import { r as toCsv, t as csvColumns } from "../csv-2rXGPNtP.js";
|
|
9
|
-
import { A as suspendAccount, C as shouldRefresh, D as SERVER_EVENT_SOURCE, E as defineAuthorizationHooks, O as endSessions, S as shouldCheckSession, T as serverCore, a as unexpectedResponse, b as isPrefetch, c as extendServer, d as clearSupportCookie, f as supportCookie, h as TENANT_HEADER, i as resolveToken, j as deleteAccount, k as lastSignIns, l as supportStorage, m as supportCookieValue, n as flushEvents, o as withFlush, r as handle, s as createServer, u as SUPPORT_COOKIE, x as refreshFor, y as withSession } from "../adapter-
|
|
11
|
+
import { A as suspendAccount, C as shouldRefresh, D as SERVER_EVENT_SOURCE, E as defineAuthorizationHooks, O as endSessions, S as shouldCheckSession, T as serverCore, a as unexpectedResponse, b as isPrefetch, c as extendServer, d as clearSupportCookie, f as supportCookie, h as TENANT_HEADER, i as resolveToken, j as deleteAccount, k as lastSignIns, l as supportStorage, m as supportCookieValue, n as flushEvents, o as withFlush, r as handle, s as createServer, u as SUPPORT_COOKIE, x as refreshFor, y as withSession } from "../adapter-Dyks1lX1.js";
|
|
10
12
|
import { n as PRIMARY_COOKIE } from "../replicas-Dyoh3CEg.js";
|
|
11
13
|
import { t as authContext } from "../context-DBicfUNz.js";
|
|
14
|
+
import { r as PERMISSION_CAP_CLAIM } from "../delegation-DGOIiT8k.js";
|
|
12
15
|
import { a as refreshSession, c as AUTH_CACHE_HEADERS, g as sessionCookieName, i as resolveAuth, m as readSession, o as clearSessionCookies, s as sessionStatus, t as clientIp, v as writeSession } from "../resolve-B0mW2m7f.js";
|
|
13
16
|
import { i as defineAuthorizer, o as requestMemo, t as bindAuthorizer } from "../authorizer-BGhXaDmo.js";
|
|
14
17
|
import { a as isSessionSnapshot, c as sessionMemo, d as amrOf, f as checkAal, i as authzVersionOf, l as snapshotOf, n as toSession, o as issuedAtOf, s as sessionCacheKey, u as aalOf } from "../view-C8Ve14ja.js";
|
|
15
18
|
import { a as respond, i as isResult, o as settle, r as guard } from "../respond-C3CcOZlA.js";
|
|
16
|
-
import { a as sqlSupportStore, i as supportSessions, n as passwordGrant, o as supportClaims, r as safeRedirectPath } from "../sign-in-
|
|
19
|
+
import { a as sqlSupportStore, i as supportSessions, n as passwordGrant, o as supportClaims, r as safeRedirectPath } from "../sign-in-B64114O4.js";
|
|
17
20
|
import { n as event, t as defineEvents } from "../event-map-CtPFhcOp.js";
|
|
18
21
|
import { t as subjectReaders } from "../subject-readers-B-pQ9Mmo.js";
|
|
19
22
|
import { t as postgresExecutor } from "../executor-3qcMhg6R.js";
|
|
20
23
|
import { n as jwtClaimsOf, r as userClaimsOf, t as authModeOf } from "../claims-DTy6R6my.js";
|
|
21
|
-
import { n as withGuard, t as withBetterSupabase } from "../composite-
|
|
24
|
+
import { n as withGuard, t as withBetterSupabase } from "../composite-B3TIjId4.js";
|
|
22
25
|
import { c as verifyCompact, t as JwsError } from "../jws-DOgHJKHb.js";
|
|
23
26
|
import { t as jwksSource } from "../jwks-cache-DEsKI0hJ.js";
|
|
24
27
|
import { i as rateLimitPolicyHeader, n as periodSeconds, r as rateLimitHeader, t as isRateLimitPolicyName } from "../ratelimit-headers-kEcXyO3H.js";
|
|
@@ -56,6 +59,399 @@ const impersonationEvents = defineEvents({
|
|
|
56
59
|
"support.denied": event()
|
|
57
60
|
});
|
|
58
61
|
//#endregion
|
|
62
|
+
//#region src/server/session-status.ts
|
|
63
|
+
const VOLATILE_CLAIMS = [
|
|
64
|
+
"exp",
|
|
65
|
+
"iat",
|
|
66
|
+
"nbf",
|
|
67
|
+
"jti"
|
|
68
|
+
];
|
|
69
|
+
const HEADERS = {
|
|
70
|
+
"content-type": "application/json",
|
|
71
|
+
"cache-control": "no-store, private"
|
|
72
|
+
};
|
|
73
|
+
/** JSON with object keys sorted at every level, so equal claims hash alike. */
|
|
74
|
+
function canonical(value) {
|
|
75
|
+
if (value === void 0) return "null";
|
|
76
|
+
if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
|
|
77
|
+
if (value !== null && typeof value === "object") return `{${Object.entries(value).filter(([, each]) => each !== void 0).toSorted(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, each]) => `${JSON.stringify(key)}:${canonical(each)}`).join(",")}}`;
|
|
78
|
+
return JSON.stringify(value);
|
|
79
|
+
}
|
|
80
|
+
async function sha256Hex(text) {
|
|
81
|
+
const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(text));
|
|
82
|
+
return Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* The fingerprint `sessionStatusRoute` reports for a user's claims and support
|
|
86
|
+
* session: a SHA-256 hex digest that changes when a claim that decides access
|
|
87
|
+
* changes (role, tenant, memberships, `aal`) or the support target does.
|
|
88
|
+
*/
|
|
89
|
+
async function claimsFingerprint(claims, support, ignore = []) {
|
|
90
|
+
const skip = /* @__PURE__ */ new Set([...VOLATILE_CLAIMS, ...ignore]);
|
|
91
|
+
return sha256Hex(canonical({
|
|
92
|
+
claims: Object.fromEntries(Object.entries(claims).filter(([key]) => !skip.has(key))),
|
|
93
|
+
support: support ? {
|
|
94
|
+
session: support.session.id,
|
|
95
|
+
target: support.session.targetUserId,
|
|
96
|
+
readOnly: support.session.readOnly
|
|
97
|
+
} : null
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
const statusOf = (resolution) => {
|
|
101
|
+
if (resolution.sessionEnded) return resolution.sessionEndedReason ?? "ended";
|
|
102
|
+
const { auth } = resolution;
|
|
103
|
+
if (auth.kind === "user") return "active";
|
|
104
|
+
return auth.kind === "anon" && auth.reason === "expired" ? "expired" : "signed_out";
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* A `GET` handler that tells a browser whether its session still holds, for
|
|
108
|
+
* apps that keep the session in httpOnly cookies and have no browser Supabase
|
|
109
|
+
* client: `useSessionWatch()` from `better-supabase/next/client` polls it. It
|
|
110
|
+
* answers `{ status, userId, fingerprint, expiresAt, support }` with
|
|
111
|
+
* `Cache-Control: no-store`.
|
|
112
|
+
*
|
|
113
|
+
* ```ts
|
|
114
|
+
* // app/api/session-status/route.ts
|
|
115
|
+
* export const GET = sessionStatusRoute(bsb);
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
function sessionStatusRoute(server, options = {}) {
|
|
119
|
+
const checkSession = options.checkSession ?? true;
|
|
120
|
+
const refresh = options.refresh ?? false;
|
|
121
|
+
return async (request) => {
|
|
122
|
+
if (request.method !== "GET" && request.method !== "HEAD") return new Response(null, {
|
|
123
|
+
status: 405,
|
|
124
|
+
headers: { allow: "GET, HEAD" }
|
|
125
|
+
});
|
|
126
|
+
const resolution = await server.resolve(request, {
|
|
127
|
+
checkSession,
|
|
128
|
+
refresh
|
|
129
|
+
});
|
|
130
|
+
const status = statusOf(resolution);
|
|
131
|
+
const { auth } = resolution;
|
|
132
|
+
const user = auth.kind === "user" ? auth : void 0;
|
|
133
|
+
const support = user && status === "active" ? await server.support.current(request, user) : void 0;
|
|
134
|
+
const body = {
|
|
135
|
+
status,
|
|
136
|
+
userId: user?.user.id ?? null,
|
|
137
|
+
fingerprint: user && status === "active" ? await claimsFingerprint(user.claims, support, options.ignoreClaims) : null,
|
|
138
|
+
expiresAt: user?.expiresAt ?? null,
|
|
139
|
+
support: support ? {
|
|
140
|
+
sessionId: support.session.id,
|
|
141
|
+
targetUserId: support.session.targetUserId,
|
|
142
|
+
readOnly: support.session.readOnly
|
|
143
|
+
} : null
|
|
144
|
+
};
|
|
145
|
+
return resolution.apply(new Response(request.method === "HEAD" ? null : JSON.stringify(body), {
|
|
146
|
+
status: 200,
|
|
147
|
+
headers: HEADERS
|
|
148
|
+
}));
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
//#endregion
|
|
152
|
+
//#region src/server/realtime-relay.ts
|
|
153
|
+
/** The channels `liveQuery` joins: `bsb:t:<schema>.<table>[:...]`, private. */
|
|
154
|
+
const liveRelayTopic = {
|
|
155
|
+
private: true,
|
|
156
|
+
match: (topic) => /^bsb:t:[^:]+\.[^:]+(?::.+)?$/.test(topic) ? {} : null
|
|
157
|
+
};
|
|
158
|
+
var Verdict = class extends Error {
|
|
159
|
+
allowed;
|
|
160
|
+
constructor(allowed) {
|
|
161
|
+
super(allowed ? "allowed" : "denied");
|
|
162
|
+
this.allowed = allowed;
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
const RLS_DENIED = "42501";
|
|
166
|
+
function codeOf(cause) {
|
|
167
|
+
return typeof cause === "object" && cause !== null && "code" in cause ? cause.code : void 0;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Whether `claims` may receive or send on `topic`, by the `realtime.messages`
|
|
171
|
+
* policies, checked the way Realtime checks a join: a probe message is
|
|
172
|
+
* inserted, then read (receive) or written (send) as the caller, and the
|
|
173
|
+
* transaction rolls back.
|
|
174
|
+
*/
|
|
175
|
+
async function realtimeTopicAccess(postgres, input) {
|
|
176
|
+
const role = input.claims["role"] === "anon" ? "anon" : "authenticated";
|
|
177
|
+
const sub = input.claims["sub"];
|
|
178
|
+
const extension = input.extension ?? "broadcast";
|
|
179
|
+
const insert = "insert into realtime.messages (topic, extension, event, payload, private) values ($1, $2, 'bsb_relay_probe', '{}'::jsonb, true)";
|
|
180
|
+
const assume = async (sql) => {
|
|
181
|
+
await sql.queryRaw("select set_config('request.jwt.claims', $1, true), set_config('request.jwt.claim.sub', $2, true), set_config('request.jwt.claim.role', $3, true), set_config('realtime.topic', $4, true), set_config('role', $3, true)", [
|
|
182
|
+
JSON.stringify({
|
|
183
|
+
...input.claims,
|
|
184
|
+
role
|
|
185
|
+
}),
|
|
186
|
+
typeof sub === "string" ? sub : "",
|
|
187
|
+
role,
|
|
188
|
+
input.topic
|
|
189
|
+
]);
|
|
190
|
+
};
|
|
191
|
+
try {
|
|
192
|
+
await postgres.transaction(async (sql) => {
|
|
193
|
+
if (input.action === "receive") {
|
|
194
|
+
const [probe] = await sql.queryRaw(`${insert} returning id::text as id`, [input.topic, extension]);
|
|
195
|
+
await assume(sql);
|
|
196
|
+
const [row] = await sql.queryRaw("select exists (select 1 from realtime.messages m where m.id::text = $1) as allowed", [probe?.id ?? ""]);
|
|
197
|
+
throw new Verdict(row?.allowed === true);
|
|
198
|
+
}
|
|
199
|
+
await assume(sql);
|
|
200
|
+
try {
|
|
201
|
+
await sql.queryRaw(insert, [input.topic, extension]);
|
|
202
|
+
} catch (cause) {
|
|
203
|
+
if (codeOf(cause) === RLS_DENIED) throw new Verdict(false);
|
|
204
|
+
throw cause;
|
|
205
|
+
}
|
|
206
|
+
throw new Verdict(true);
|
|
207
|
+
});
|
|
208
|
+
} catch (cause) {
|
|
209
|
+
if (cause instanceof Verdict) return cause.allowed;
|
|
210
|
+
throw cause;
|
|
211
|
+
}
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
const encoder = new TextEncoder();
|
|
215
|
+
const frame = (event, data) => encoder.encode(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`);
|
|
216
|
+
const PING = encoder.encode(": ping\n\n");
|
|
217
|
+
const STREAM_HEADERS = {
|
|
218
|
+
"content-type": "text/event-stream; charset=utf-8",
|
|
219
|
+
"cache-control": "no-store, no-transform",
|
|
220
|
+
"x-accel-buffering": "no"
|
|
221
|
+
};
|
|
222
|
+
function readOnlyError() {
|
|
223
|
+
return {
|
|
224
|
+
...dbError("forbidden", "The support session is read-only"),
|
|
225
|
+
code: "SUPPORT_READ_ONLY"
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
function isSendBody(value) {
|
|
229
|
+
if (typeof value !== "object" || value === null) return false;
|
|
230
|
+
const body = value;
|
|
231
|
+
return typeof body.topic === "string" && typeof body.event === "string" && body.event !== "";
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Realtime for callers without a browser token of their own: a support session
|
|
235
|
+
* ("view as user"), or an app that keeps sessions in httpOnly cookies. `GET
|
|
236
|
+
* ?topic=<name>` resolves the caller, checks the topic's access as that caller
|
|
237
|
+
* (the viewed user in a support session), joins upstream with the secret key
|
|
238
|
+
* and streams the topic's broadcasts and presence as server-sent events. `POST
|
|
239
|
+
* { topic, event, payload }` broadcasts for the caller after the same check on
|
|
240
|
+
* the send policy; read-only support sessions can't send.
|
|
241
|
+
* `relayRealtimeClient(url)` from `better-supabase/realtime` is the client.
|
|
242
|
+
*
|
|
243
|
+
* ```ts
|
|
244
|
+
* // app/api/realtime/route.ts
|
|
245
|
+
* export const { GET, POST } = realtimeRelay(bsb, {
|
|
246
|
+
* topics: [notifications, liveRelayTopic],
|
|
247
|
+
* postgres,
|
|
248
|
+
* });
|
|
249
|
+
* ```
|
|
250
|
+
*/
|
|
251
|
+
function realtimeRelay(server, options) {
|
|
252
|
+
const { postgres, authorize } = options;
|
|
253
|
+
if (!postgres && !authorize) throw new TypeError("realtimeRelay needs `postgres` to check the realtime.messages policies, or `authorize`");
|
|
254
|
+
const heartbeatMs = options.heartbeatMs ?? 25e3;
|
|
255
|
+
const maxDurationMs = options.maxDurationMs ?? 24e4;
|
|
256
|
+
const maxQueued = Math.max(1, options.maxQueued ?? 256);
|
|
257
|
+
const retryMs = options.retryMs ?? 1e3;
|
|
258
|
+
const refresh = options.refresh ?? false;
|
|
259
|
+
let upstream = options.upstream;
|
|
260
|
+
const upstreamClient = () => {
|
|
261
|
+
upstream ??= server.admin().$client;
|
|
262
|
+
return upstream;
|
|
263
|
+
};
|
|
264
|
+
const problem = (error) => problemResponse(error, { format: options.problem });
|
|
265
|
+
const topicOf = (name) => options.topics.find((each) => each.match(name) !== null);
|
|
266
|
+
const allowed = async (input) => {
|
|
267
|
+
try {
|
|
268
|
+
if (authorize) return await authorize(input);
|
|
269
|
+
if (input.auth.kind === "service") return true;
|
|
270
|
+
return postgres ? await realtimeTopicAccess(postgres, {
|
|
271
|
+
claims: input.claims,
|
|
272
|
+
topic: input.topic,
|
|
273
|
+
action: input.action
|
|
274
|
+
}) : false;
|
|
275
|
+
} catch {
|
|
276
|
+
return false;
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
const claimsOf = (auth, support) => {
|
|
280
|
+
if (support) return support.claims;
|
|
281
|
+
switch (auth.kind) {
|
|
282
|
+
case "user": return auth.claims;
|
|
283
|
+
case "apiKey": return auth.claims;
|
|
284
|
+
case "anon": return { role: "anon" };
|
|
285
|
+
case "service": return { role: "service_role" };
|
|
286
|
+
case "invalid": return { role: "anon" };
|
|
287
|
+
default: return auth;
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
/** Resolves the caller and checks `action` on `name`; a Response refuses. */
|
|
291
|
+
const admit = async (request, name, action) => {
|
|
292
|
+
const topic = topicOf(name);
|
|
293
|
+
if (!topic) return { refusal: problem(dbError("not_found", `No relayed topic "${name}"`)) };
|
|
294
|
+
const ctx = await server.context(request, { refresh });
|
|
295
|
+
const { auth, support } = ctx;
|
|
296
|
+
if (auth.kind === "invalid") return { refusal: ctx.apply(problem(auth.error)) };
|
|
297
|
+
if (!(auth.kind !== "anon") && (topic.private || action === "send")) return { refusal: ctx.apply(problem(dbError("unauthorized", "Sign in to join this topic"))) };
|
|
298
|
+
if (action === "send" && support?.session.readOnly === true) return { refusal: ctx.apply(problem(readOnlyError())) };
|
|
299
|
+
if (!(!topic.private && action === "receive" ? true : await allowed({
|
|
300
|
+
topic: name,
|
|
301
|
+
action,
|
|
302
|
+
auth,
|
|
303
|
+
support,
|
|
304
|
+
claims: claimsOf(auth, support)
|
|
305
|
+
}))) return { refusal: ctx.apply(problem(dbError("forbidden", `Not allowed to ${action} on "${name}"`))) };
|
|
306
|
+
return {
|
|
307
|
+
topic,
|
|
308
|
+
ctx
|
|
309
|
+
};
|
|
310
|
+
};
|
|
311
|
+
const expiryOf = (auth, support) => {
|
|
312
|
+
const times = [];
|
|
313
|
+
if (auth.kind === "user" && auth.expiresAt !== null) times.push(auth.expiresAt * 1e3);
|
|
314
|
+
if (support) times.push(support.session.expiresAt.epochMilliseconds);
|
|
315
|
+
return times.length === 0 ? void 0 : Math.min(...times);
|
|
316
|
+
};
|
|
317
|
+
const GET = async (request) => {
|
|
318
|
+
const name = new URL(request.url).searchParams.get("topic");
|
|
319
|
+
if (!name) return problem(dbError("invalid_request", "Pass ?topic=<name>"));
|
|
320
|
+
const admitted = await admit(request, name, "receive");
|
|
321
|
+
if ("refusal" in admitted) return admitted.refusal;
|
|
322
|
+
const { topic, ctx } = admitted;
|
|
323
|
+
const expiresAt = expiryOf(ctx.resolution.auth, ctx.support);
|
|
324
|
+
const client = upstreamClient();
|
|
325
|
+
let finish = () => void 0;
|
|
326
|
+
const stream = new ReadableStream({
|
|
327
|
+
start(controller) {
|
|
328
|
+
let closed = false;
|
|
329
|
+
let subscribed = false;
|
|
330
|
+
let leave;
|
|
331
|
+
const timers = [];
|
|
332
|
+
const enqueue = (chunk) => {
|
|
333
|
+
try {
|
|
334
|
+
controller.enqueue(chunk);
|
|
335
|
+
} catch {
|
|
336
|
+
finish(null);
|
|
337
|
+
}
|
|
338
|
+
};
|
|
339
|
+
const push = (chunk) => {
|
|
340
|
+
if (closed) return;
|
|
341
|
+
if ((controller.desiredSize ?? 1) <= 0) {
|
|
342
|
+
finish("overflow");
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
enqueue(chunk);
|
|
346
|
+
};
|
|
347
|
+
finish = (reason) => {
|
|
348
|
+
if (closed) return;
|
|
349
|
+
closed = true;
|
|
350
|
+
for (const timer of timers) {
|
|
351
|
+
clearTimeout(timer);
|
|
352
|
+
clearInterval(timer);
|
|
353
|
+
}
|
|
354
|
+
request.signal.removeEventListener("abort", aborted);
|
|
355
|
+
leave?.();
|
|
356
|
+
if (reason !== null) enqueue(frame("end", { reason }));
|
|
357
|
+
try {
|
|
358
|
+
controller.close();
|
|
359
|
+
} catch {}
|
|
360
|
+
};
|
|
361
|
+
const aborted = () => {
|
|
362
|
+
finish(null);
|
|
363
|
+
};
|
|
364
|
+
const onStatus = (status) => {
|
|
365
|
+
switch (status) {
|
|
366
|
+
case "joining": return;
|
|
367
|
+
case "subscribed":
|
|
368
|
+
push(frame("status", {
|
|
369
|
+
status,
|
|
370
|
+
rejoin: subscribed
|
|
371
|
+
}));
|
|
372
|
+
subscribed = true;
|
|
373
|
+
return;
|
|
374
|
+
case "error":
|
|
375
|
+
if (subscribed) push(frame("status", { status }));
|
|
376
|
+
else finish("upstream_error");
|
|
377
|
+
return;
|
|
378
|
+
case "closed":
|
|
379
|
+
finish("closed");
|
|
380
|
+
return;
|
|
381
|
+
default: finish(status);
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
const subscriber = {
|
|
385
|
+
onStatus,
|
|
386
|
+
receive: (message) => {
|
|
387
|
+
push(frame("broadcast", {
|
|
388
|
+
event: message.event,
|
|
389
|
+
payload: message.payload
|
|
390
|
+
}));
|
|
391
|
+
},
|
|
392
|
+
...topic.presence ? { sync: (state) => {
|
|
393
|
+
push(frame("presence", state));
|
|
394
|
+
} } : {}
|
|
395
|
+
};
|
|
396
|
+
enqueue(encoder.encode(`retry: ${String(retryMs)}\n\n`));
|
|
397
|
+
if (request.signal.aborted) {
|
|
398
|
+
finish(null);
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
request.signal.addEventListener("abort", aborted);
|
|
402
|
+
timers.push(setInterval(() => {
|
|
403
|
+
push(PING);
|
|
404
|
+
}, heartbeatMs), setTimeout(() => {
|
|
405
|
+
finish("max_duration");
|
|
406
|
+
}, maxDurationMs));
|
|
407
|
+
if (expiresAt !== void 0) timers.push(setTimeout(() => {
|
|
408
|
+
finish("expired");
|
|
409
|
+
}, Math.max(0, expiresAt - Date.now())));
|
|
410
|
+
try {
|
|
411
|
+
leave = joinTopic(client, name, topic.private, false, topic.presence === true, subscriber).leave;
|
|
412
|
+
} catch {
|
|
413
|
+
finish("upstream_error");
|
|
414
|
+
}
|
|
415
|
+
},
|
|
416
|
+
cancel() {
|
|
417
|
+
finish(null);
|
|
418
|
+
}
|
|
419
|
+
}, new CountQueuingStrategy({ highWaterMark: maxQueued }));
|
|
420
|
+
return ctx.apply(new Response(stream, {
|
|
421
|
+
status: 200,
|
|
422
|
+
headers: STREAM_HEADERS
|
|
423
|
+
}));
|
|
424
|
+
};
|
|
425
|
+
const POST = async (request) => {
|
|
426
|
+
const body = await request.json().catch(() => void 0);
|
|
427
|
+
if (!isSendBody(body)) return problem(dbError("invalid_request", "Send a JSON body with `topic`, `event` and `payload`"));
|
|
428
|
+
const known = topicOf(body.topic);
|
|
429
|
+
if (known && !known.clientSend) return problem(dbError("forbidden", `"${body.topic}" takes no client broadcasts`));
|
|
430
|
+
const admitted = await admit(request, body.topic, "send");
|
|
431
|
+
if ("refusal" in admitted) return admitted.refusal;
|
|
432
|
+
const { topic, ctx } = admitted;
|
|
433
|
+
const schema = topic.events?.[body.event];
|
|
434
|
+
const checked = schema ? await validate(schema, body.payload, "payload") : {
|
|
435
|
+
ok: true,
|
|
436
|
+
data: body.payload
|
|
437
|
+
};
|
|
438
|
+
if (!checked.ok) return ctx.apply(problem(checked.error));
|
|
439
|
+
const client = upstreamClient();
|
|
440
|
+
const open = client.getChannels().some((existing) => existing.topic === `realtime:${body.topic}`);
|
|
441
|
+
const channel = client.channel(body.topic, { config: { private: topic.private } });
|
|
442
|
+
try {
|
|
443
|
+
const sent = await channel.httpSend(body.event, checked.data);
|
|
444
|
+
return ctx.apply(sent.success ? new Response(null, { status: 202 }) : problem(dbError("network", sent.error)));
|
|
445
|
+
} finally {
|
|
446
|
+
if (!open) await client.removeChannel(channel);
|
|
447
|
+
}
|
|
448
|
+
};
|
|
449
|
+
return {
|
|
450
|
+
GET,
|
|
451
|
+
POST
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
//#endregion
|
|
59
455
|
//#region src/server/entries/upstream.ts
|
|
60
456
|
/** Repository context from a `@supabase/server` context. */
|
|
61
457
|
function contextFromSupabase(ctx) {
|
|
@@ -451,4 +847,4 @@ function subscribeAuthzVersions(options) {
|
|
|
451
847
|
return subscription;
|
|
452
848
|
}
|
|
453
849
|
//#endregion
|
|
454
|
-
export { AUTH_CACHE_HEADERS, DB_CALLS_HEADER, IDENTITY_SCOPES, PRIMARY_COOKIE, PROBLEM_CONTENT_TYPE, PROBLEM_TYPE_BASE, SERVER_EVENT_SOURCE, SUPPORT_COOKIE, TENANT_HEADER, aalOf, accessTokenResolver, actorOf, agentClaims, amrOf, authContext, authModeOf, authzVersionOf, bindAuthorizer, cacheTagsOf, checkAal, checkSession, clearSessionCookies, clearSupportCookie, clientIp, contextFromSupabase, createServer, csvColumns, csvResponse, defineAuthorizationHooks, defineAuthorizer, defineResource, delegationOf, deleteAccount, endSessions, extendServer, flushEvents, fromProblem, guard, handle, hasRole, impersonationEvents, impersonatorOf, isPrefetch, isProblem, isRateLimitPolicyName, isResult, isSessionSnapshot, issuedAtOf, jwtClaimsOf, lastSignIns, parseDbStats, passwordGrant, periodSeconds, problemResponse, rateLimitHeader, rateLimitPolicyHeader, readSession, refreshFor, refreshSession, requestMemo, resolveAuth, resolveToken, respond, rolesAt, safeRedirectPath, serverCore, sessionCacheKey, sessionCookieName, sessionMemo, sessionStatus, settle, shouldCheckSession, shouldRefresh, snapshotOf, sqlSupportStore, subjectReaders, subscribeAuthzVersions, supportClaims, supportCookie, supportCookieValue, supportOf, supportSessions, supportStorage, suspendAccount, tagCache, tagFor, toCsv, toProblem, toSession, unexpectedResponse, userClaimsOf, withBetterDb, withBetterPostgres, withBetterSupabase, withBlock, withDbStats, withFlush, withGuard, withServerTiming, withSession, writeSession };
|
|
850
|
+
export { AUTH_CACHE_HEADERS, DB_CALLS_HEADER, IDENTITY_SCOPES, PERMISSION_CAP_CLAIM, PRIMARY_COOKIE, PROBLEM_CONTENT_TYPE, PROBLEM_TYPE_BASE, SERVER_EVENT_SOURCE, SUPPORT_COOKIE, TENANT_HEADER, aalOf, accessTokenResolver, actorOf, agentClaims, amrOf, authContext, authModeOf, authzVersionOf, bindAuthorizer, cacheTagsOf, checkAal, checkSession, claimsFingerprint, clearSessionCookies, clearSupportCookie, clientIp, contextFromSupabase, createServer, csvColumns, csvResponse, defineAuthorizationHooks, defineAuthorizer, defineResource, delegationOf, deleteAccount, endSessions, extendServer, flushEvents, fromProblem, guard, handle, hasRole, impersonationEvents, impersonatorOf, isPrefetch, isProblem, isRateLimitPolicyName, isResult, isSessionSnapshot, issuedAtOf, jwtClaimsOf, lastSignIns, liveRelayTopic, parseDbStats, passwordGrant, periodSeconds, problemResponse, rateLimitHeader, rateLimitPolicyHeader, readSession, realtimeRelay, realtimeTopicAccess, refreshFor, refreshSession, requestMemo, resolveAuth, resolveToken, respond, rolesAt, safeRedirectPath, serverCore, sessionCacheKey, sessionCookieName, sessionMemo, sessionStatus, sessionStatusRoute, settle, shouldCheckSession, shouldRefresh, snapshotOf, sqlSupportStore, subjectReaders, subscribeAuthzVersions, supportClaims, supportCookie, supportCookieValue, supportOf, supportSessions, supportStorage, suspendAccount, tagCache, tagFor, toCsv, toProblem, toSession, unexpectedResponse, userClaimsOf, withBetterDb, withBetterPostgres, withBetterSupabase, withBlock, withDbStats, withFlush, withGuard, withServerTiming, withSession, writeSession };
|