better-supabase 0.5.1 → 0.6.1
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 +187 -46
- package/dist/access-sql-B0dF-SoF.js +181 -0
- package/dist/{actor-DaJjqD5R.d.ts → actor-CQTlc1Hh.d.ts} +1 -1
- package/dist/adapter-CHnPkCPd.js +1160 -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 +224 -0
- package/dist/blocks/attachments/index.js +234 -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 +259 -0
- package/dist/blocks/data-lifecycle/index.js +358 -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-C_A-KEAz.js → doctor-BMqBgM3X.js} +991 -317
- 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-4JlOwgWG.js +2 -0
- package/dist/cli/gen-DeuDgPxN.js +3100 -0
- package/dist/cli/index.d.ts +44 -5
- package/dist/cli/index.js +7 -7
- package/dist/cli/{init-DMa6M7hV.js → init-C7Xd0Kda.js} +242 -27
- package/dist/cli/{introspect-BKlaIu_M.js → introspect-CSnMJ94U.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-Bo_NLT5n.js → run-C8tnlHSb.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-BCtlgDQx.js → version-C_4JwyiM.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-CLqs9-OA.js +130 -0
- package/dist/composite-pSfeJNce.d.ts +146 -0
- package/dist/config/index.d.ts +6 -4
- package/dist/config/index.js +5 -5
- package/dist/{config-Bv7gvfzC.d.ts → config-D44Y7PAv.d.ts} +406 -214
- 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-CFPX0Qft.d.ts → ended-jLfvw8h-.d.ts} +20 -2
- package/dist/{entitlements-BiJZ4t49.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-CdPDPpFs.d.ts +25 -0
- package/dist/framework-xjTBoyBB.js +51 -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-BgSHAYLf.js → impersonation-DcqaTBHx.js} +21 -6
- 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-Daak8ukG.d.ts +54 -0
- 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-Bn6HNKUe.js → resolve-D_IcnvFd.js} +248 -240
- package/dist/{impersonation-BmePsuxz.d.ts → resolve-KW8nCeL6.d.ts} +29 -69
- package/dist/{resource-mqfJW4YF.js → resource-BsvzCMlX.js} +4 -4
- package/dist/{resource-DNRFP7KR.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 -22
- package/dist/server/index.js +46 -14
- package/dist/{respond-BR1fJWOB.d.ts → server-C6DWVEVG.d.ts} +237 -85
- 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 +313 -212
- package/dist/sql/index.js +34924 -6609
- 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-view-B8SlToQX.d.ts → support-view-33Oi07TT.d.ts} +1 -1
- package/dist/{support-wHnK6zp-.js → support-zIa1URaN.js} +32 -11
- 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 +315 -41
- package/dist/testing/index.js +1046 -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-DOYTYwHP.js → version-CQt77F3T.js} +1 -1
- package/dist/view-BeFcRV6G.js +99 -0
- package/dist/{view-CbgObAeb.d.ts → view-DbxLNu8L.d.ts} +22 -5
- 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 +461 -20
- package/schemas/ai-message-v1.json +258 -0
- package/schemas/config-v1.json +1074 -140
- package/schemas/doctor-report-v1.json +20 -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 +47 -11
- 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-CIdSQZad.js +0 -2
- package/dist/cli/gen-CjElD1Vw.js +0 -2241
- package/dist/cli/read-sets-VQcPgxU9.js +0 -436
- package/dist/cli/sql-CVx-1O8G.js +0 -373
- 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/index-CWMDdEr4.d.ts +0 -50
- package/dist/index-DOESKG27.d.ts +0 -100
- package/dist/index-DmXSxbLi.d.ts +0 -62
- package/dist/index-Dp2VDwog.d.ts +0 -161
- 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/mfa-Cu96oJdw.d.ts +0 -30
- 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-B1mZ7CgQ.js +0 -660
- package/dist/stats-Bqob3WqT.js +0 -592
- package/dist/support-CEPwlw2G.d.ts +0 -89
- 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 -122
|
@@ -1,20 +1,41 @@
|
|
|
1
|
-
import { t as cloneValue } from "./clone-BfgmLU90.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { n as isPlainObject, t as cloneValue } from "./clone-BfgmLU90.js";
|
|
2
|
+
import { t as DbException } from "./db-exception-CnWcYPxL.js";
|
|
3
|
+
import { n as dbError } from "./errors-B11Duf73.js";
|
|
4
|
+
import { n as invalidRequest, t as builderFor } from "./build-BXIzE6Xv.js";
|
|
4
5
|
import { t as lookupOf } from "./lookup-BaP5bI27.js";
|
|
5
6
|
import { i as or, n as column, r as not, t as and } from "./types-6cYK9pbJ.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { c as optionalTemporal, l as provideTemporal, s as nowInstant, u as providedTemporal } from "./temporal-BJGitm-h.js";
|
|
8
|
+
import { i as encodeValue, n as decodeScalar, r as decodeValue } from "./wire-DtZQ4sdE.js";
|
|
9
|
+
import { a as ok, c as withErrorMapper, r as err, s as toDbError, t as AsyncResult } from "./result-DzUbqgdW.js";
|
|
9
10
|
import { t as invalidationTargets } from "./tables-Cb-3_VWc.js";
|
|
10
11
|
import { t as consoleLogger } from "./logger-glM28NVN.js";
|
|
11
|
-
import { i as orderPlugins
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
12
|
+
import { i as orderPlugins } from "./plugin-tfXW1-qO.js";
|
|
13
|
+
import { t as simplify } from "./simplify-DDO0j0LI.js";
|
|
14
|
+
import { a as postgrestExecutor, c as invalidTuning, l as tuningOf, n as StatsRecorder, o as NO_TUNING, r as recordStats, s as deadline } from "./stats-D_AD9GGu.js";
|
|
15
|
+
import { d as isQuerySpec, f as specTables, n as checkParams, o as isReadSet, r as containsPlaceholder, t as bindParams, u as createSpecs } from "./read-set-DuKWC9Mj.js";
|
|
14
16
|
import { a as toBase64Url, t as base64ToText } from "./base64-D2gsioCY.js";
|
|
15
|
-
import { t as
|
|
17
|
+
import { t as isList } from "./guards-BnzDvFrz.js";
|
|
18
|
+
import { t as vectorLiteral } from "./search-CUWCRYKL.js";
|
|
19
|
+
import { n as validate } from "./standard-BK0cqJ7y.js";
|
|
16
20
|
//#region src/core/batch.ts
|
|
17
21
|
/**
|
|
22
|
+
* A signal that aborts once every reader's signal has, so one reader giving
|
|
23
|
+
* up never cancels the operations of the others. `undefined` when a reader
|
|
24
|
+
* has no signal.
|
|
25
|
+
*/
|
|
26
|
+
function allAborted(signals) {
|
|
27
|
+
const present = signals.filter((signal) => signal !== void 0);
|
|
28
|
+
if (present.length < signals.length) return void 0;
|
|
29
|
+
if (present.length === 1) return present[0];
|
|
30
|
+
const controller = new AbortController();
|
|
31
|
+
const check = () => {
|
|
32
|
+
if (present.every((signal) => signal.aborted)) controller.abort();
|
|
33
|
+
};
|
|
34
|
+
for (const signal of present) signal.addEventListener("abort", check, { once: true });
|
|
35
|
+
check();
|
|
36
|
+
return controller.signal;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
18
39
|
* Holds operations until each of `readers` has either submitted one or
|
|
19
40
|
* finished, then runs the held ones through `batch` together. A reader that
|
|
20
41
|
* runs a second operation joins the next batch.
|
|
@@ -25,7 +46,16 @@ function batchingExecutor(base, readers) {
|
|
|
25
46
|
const flush = () => {
|
|
26
47
|
if (queue.length === 0 || queue.length < running) return;
|
|
27
48
|
const items = queue.splice(0);
|
|
28
|
-
|
|
49
|
+
const { signal: _first, ...shared } = items[0].context;
|
|
50
|
+
const signal = allAborted(items.map((item) => item.context.signal));
|
|
51
|
+
const context = signal ? {
|
|
52
|
+
...shared,
|
|
53
|
+
signal
|
|
54
|
+
} : shared;
|
|
55
|
+
for (const item of items) item.context.signal?.addEventListener("abort", () => {
|
|
56
|
+
item.resolve(err(dbError("aborted", "The request was aborted")));
|
|
57
|
+
}, { once: true });
|
|
58
|
+
base.batch(items.map((item) => item.op), context).then((results) => {
|
|
29
59
|
items.forEach((item, index) => {
|
|
30
60
|
item.resolve(results[index] ?? err(toDbError(/* @__PURE__ */ new Error(`Executor "${base.name}" returned too few results`))));
|
|
31
61
|
});
|
|
@@ -99,6 +129,24 @@ function memoryCache() {
|
|
|
99
129
|
}
|
|
100
130
|
//#endregion
|
|
101
131
|
//#region src/core/events.ts
|
|
132
|
+
function deepFreeze(value) {
|
|
133
|
+
if (Array.isArray(value) || isPlainObject(value)) {
|
|
134
|
+
for (const item of Object.values(value)) deepFreeze(item);
|
|
135
|
+
Object.freeze(value);
|
|
136
|
+
}
|
|
137
|
+
return value;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* The `error` event for `error`: a frozen copy, so a handler can't change
|
|
141
|
+
* the `DbError` the caller gets back (invariant 5).
|
|
142
|
+
*/
|
|
143
|
+
function errorEvent(error, table) {
|
|
144
|
+
const copy = deepFreeze(cloneValue(error));
|
|
145
|
+
return table === void 0 ? { error: copy } : {
|
|
146
|
+
table,
|
|
147
|
+
error: copy
|
|
148
|
+
};
|
|
149
|
+
}
|
|
102
150
|
/** More handlers than this for one event usually means a missing unsubscribe. */
|
|
103
151
|
const HANDLER_WARNING = 50;
|
|
104
152
|
function isDevelopment() {
|
|
@@ -163,6 +211,60 @@ var EventHub = class {
|
|
|
163
211
|
}
|
|
164
212
|
};
|
|
165
213
|
//#endregion
|
|
214
|
+
//#region src/core/diagnostics.ts
|
|
215
|
+
/**
|
|
216
|
+
* Debug records for the `diagnostics` option, after the Supabase SDK
|
|
217
|
+
* capability `client.observability.diagnostic_logging`
|
|
218
|
+
* (`SPEC_PINS.supabaseSdkCapabilities`). Fields are names, kinds, counts and
|
|
219
|
+
* timings only: never tokens, keys, row values, filters, query strings,
|
|
220
|
+
* headers or database error messages, which can quote the data.
|
|
221
|
+
*/
|
|
222
|
+
function logDiagnostics(events) {
|
|
223
|
+
const logger = { debug(message, fields) {
|
|
224
|
+
try {
|
|
225
|
+
events.logger.debug(message, fields);
|
|
226
|
+
} catch {}
|
|
227
|
+
} };
|
|
228
|
+
events.on("query", (event) => {
|
|
229
|
+
logger.debug(`${event.operation} ${event.table} ${event.ok ? "ok" : "failed"} in ${String(Math.round(event.durationMs))}ms`, {
|
|
230
|
+
table: event.table,
|
|
231
|
+
operation: event.operation,
|
|
232
|
+
ok: event.ok,
|
|
233
|
+
durationMs: event.durationMs,
|
|
234
|
+
rows: event.rows,
|
|
235
|
+
truncated: event.truncated
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
events.on("error", ({ table, error }) => {
|
|
239
|
+
logger.debug(`${error.kind} error${table ? ` on ${table}` : ""}`, {
|
|
240
|
+
...table ? { table } : {},
|
|
241
|
+
kind: error.kind,
|
|
242
|
+
status: error.status,
|
|
243
|
+
...error.code ? { code: error.code } : {}
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
events.on("refresh", (event) => {
|
|
247
|
+
logger.debug(`session refresh ${event.ok ? "ok" : "failed"} in ${String(Math.round(event.durationMs))}ms`, {
|
|
248
|
+
ok: event.ok,
|
|
249
|
+
shared: event.shared,
|
|
250
|
+
durationMs: event.durationMs
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
events.on("auth", (event) => {
|
|
254
|
+
logger.debug(`auth from ${event.source}: ${event.ok ? "user" : event.reason ?? "no user"}`, {
|
|
255
|
+
source: event.source,
|
|
256
|
+
ok: event.ok,
|
|
257
|
+
...event.reason ? { reason: event.reason } : {}
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
/** The event hub of a new definition, with the diagnostic handlers when `diagnostics` is on. */
|
|
262
|
+
function definitionEvents(options) {
|
|
263
|
+
const events = new EventHub(options.logger ?? consoleLogger);
|
|
264
|
+
if (options.diagnostics === true) logDiagnostics(events);
|
|
265
|
+
return events;
|
|
266
|
+
}
|
|
267
|
+
//#endregion
|
|
166
268
|
//#region src/ir/codec.ts
|
|
167
269
|
/** Whether decoding `selection` changes anything, so plain reads skip the walk. */
|
|
168
270
|
function needsDecoding(selection) {
|
|
@@ -178,7 +280,7 @@ function computeNeedsDecoding(selection) {
|
|
|
178
280
|
return selection.aggregate !== void 0 || selection.columns.some((column) => column.codec !== void 0) || selection.includes.some((include) => include.count !== void 0 || include.aggregate !== void 0 || needsDecoding(include.selection));
|
|
179
281
|
}
|
|
180
282
|
/** PostgREST returns `[{ count }]` for a `(count)` embed; SQL returns the number. */
|
|
181
|
-
function countOf(value) {
|
|
283
|
+
function countOf$1(value) {
|
|
182
284
|
if (Array.isArray(value)) {
|
|
183
285
|
const first = value[0];
|
|
184
286
|
return Number(first?.count ?? 0);
|
|
@@ -209,7 +311,7 @@ function droppedOf(selection) {
|
|
|
209
311
|
}
|
|
210
312
|
return dropped;
|
|
211
313
|
}
|
|
212
|
-
function decodeRow(selection, row) {
|
|
314
|
+
function decodeRow$1(selection, row) {
|
|
213
315
|
const dropped = droppedOf(selection);
|
|
214
316
|
const out = {};
|
|
215
317
|
for (const key in row) if (!dropped.has(key) && Object.hasOwn(row, key)) out[key] = row[key];
|
|
@@ -224,7 +326,7 @@ function decodeRow(selection, row) {
|
|
|
224
326
|
}
|
|
225
327
|
}
|
|
226
328
|
if (selection.aggregate) {
|
|
227
|
-
if (selection.aggregate.count) out["_count"] = countOf(out["_count"]);
|
|
329
|
+
if (selection.aggregate.count) out["_count"] = countOf$1(out["_count"]);
|
|
228
330
|
for (const measure of selection.aggregate.measures) {
|
|
229
331
|
const value = row[measure.key];
|
|
230
332
|
fold(out, folded, `_${measure.fn}`, measure.alias, measureOf(measure, value));
|
|
@@ -234,7 +336,7 @@ function decodeRow(selection, row) {
|
|
|
234
336
|
const value = row[include.alias];
|
|
235
337
|
if (include.count !== void 0) {
|
|
236
338
|
if (!(include.alias in row)) continue;
|
|
237
|
-
fold(out, folded, "_count", include.count, countOf(value));
|
|
339
|
+
fold(out, folded, "_count", include.count, countOf$1(value));
|
|
238
340
|
continue;
|
|
239
341
|
}
|
|
240
342
|
if (include.aggregate !== void 0) {
|
|
@@ -245,29 +347,175 @@ function decodeRow(selection, row) {
|
|
|
245
347
|
fold(out, folded, `_${include.aggregate.fn}`, include.aggregate.name, measures);
|
|
246
348
|
continue;
|
|
247
349
|
}
|
|
248
|
-
if (Array.isArray(value)) out[include.alias] = value.map((item) => decodeRow(include.selection, item));
|
|
249
|
-
else if (value && typeof value === "object") out[include.alias] = decodeRow(include.selection, value);
|
|
350
|
+
if (Array.isArray(value)) out[include.alias] = value.map((item) => decodeRow$1(include.selection, item));
|
|
351
|
+
else if (value && typeof value === "object") out[include.alias] = decodeRow$1(include.selection, value);
|
|
250
352
|
}
|
|
251
353
|
return out;
|
|
252
354
|
}
|
|
253
355
|
/** Applies column codecs to returned rows, including embedded relations. */
|
|
254
356
|
function decodeRows(selection, rows, checked = false) {
|
|
255
357
|
if (!selection || !checked && !needsDecoding(selection)) return rows;
|
|
256
|
-
return rows.map((row) => decodeRow(selection, row));
|
|
358
|
+
return rows.map((row) => decodeRow$1(selection, row));
|
|
257
359
|
}
|
|
258
360
|
//#endregion
|
|
259
361
|
//#region src/core/cursor.ts
|
|
362
|
+
function isBound(value) {
|
|
363
|
+
return typeof value === "object" && value !== null && "s" in value && typeof value.s === "string" && "v" in value && Array.isArray(value.v);
|
|
364
|
+
}
|
|
365
|
+
function parse(cursor) {
|
|
366
|
+
try {
|
|
367
|
+
return JSON.parse(base64ToText(cursor));
|
|
368
|
+
} catch {
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
260
372
|
/** Opaque, URL-safe keyset cursor. */
|
|
261
373
|
function encodeCursor(values) {
|
|
262
374
|
return toBase64Url(JSON.stringify(values));
|
|
263
375
|
}
|
|
376
|
+
/** The values of a cursor from `encodeCursor` or from `paginate()`. */
|
|
264
377
|
function decodeCursor(cursor) {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
378
|
+
const parsed = parse(cursor);
|
|
379
|
+
if (isList(parsed)) return [...parsed];
|
|
380
|
+
return isBound(parsed) ? parsed.v : void 0;
|
|
381
|
+
}
|
|
382
|
+
/** A short FNV-1a hash of `text`, enough to tell two sorts apart. */
|
|
383
|
+
function sortKey(text) {
|
|
384
|
+
let hash = 2166136261;
|
|
385
|
+
for (let index = 0; index < text.length; index++) {
|
|
386
|
+
hash ^= text.codePointAt(index) ?? 0;
|
|
387
|
+
hash = Math.imul(hash, 16777619);
|
|
388
|
+
}
|
|
389
|
+
return (hash >>> 0).toString(36);
|
|
390
|
+
}
|
|
391
|
+
/** A `paginate()` cursor that only continues the sort `key` names. */
|
|
392
|
+
function encodeBoundCursor(values, key) {
|
|
393
|
+
return toBase64Url(JSON.stringify({
|
|
394
|
+
s: key,
|
|
395
|
+
v: values
|
|
396
|
+
}));
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* The values of a `paginate()` cursor made for the sort `key`. `sort` means
|
|
400
|
+
* the cursor is valid but continues another sort or table.
|
|
401
|
+
*/
|
|
402
|
+
function decodeBoundCursor(cursor, key) {
|
|
403
|
+
const parsed = parse(cursor);
|
|
404
|
+
if (!isBound(parsed)) return { invalid: "cursor" };
|
|
405
|
+
return parsed.s === key ? { values: parsed.v } : { invalid: "sort" };
|
|
406
|
+
}
|
|
407
|
+
//#endregion
|
|
408
|
+
//#region src/core/keyset.ts
|
|
409
|
+
/**
|
|
410
|
+
* The rows after the cursor `values` in `orderBy` order, as an OR of ANDs:
|
|
411
|
+
* `a > x or (a = x and b > y)`. The SQL compiler sends that shape as the row
|
|
412
|
+
* comparison `(a, b) > (x, y)`. Nulls sort where Postgres puts them: last
|
|
413
|
+
* for `asc`, first for `desc`, unless the term says otherwise.
|
|
414
|
+
*/
|
|
415
|
+
function keysetCondition(orderBy, values, nullable) {
|
|
416
|
+
const isNull = (name) => column(name, "is", null);
|
|
417
|
+
const branches = orderBy.flatMap((term, index) => {
|
|
418
|
+
const value = values[index];
|
|
419
|
+
const nullsFirst = (term.nulls ?? (term.direction === "desc" ? "first" : "last")) === "first";
|
|
420
|
+
const after = column(term.column, term.direction === "asc" ? "gt" : "lt", value);
|
|
421
|
+
const step = value === null ? nullsFirst ? not(isNull(term.column)) : void 0 : nullsFirst || !nullable(term.column) ? after : or(after, isNull(term.column));
|
|
422
|
+
if (!step) return [];
|
|
423
|
+
const equal = orderBy.slice(0, index).map((prev, prevIndex) => values[prevIndex] === null ? isNull(prev.column) : column(prev.column, "eq", values[prevIndex]));
|
|
424
|
+
return [and(...equal, step) ?? step];
|
|
425
|
+
});
|
|
426
|
+
if (branches.length === 0) return column(orderBy[0]?.column ?? "", "in", []);
|
|
427
|
+
const after = or(...branches);
|
|
428
|
+
const [first] = orderBy;
|
|
429
|
+
if (orderBy.length < 2 || !first || values[0] === null || nullable(first.column)) return after;
|
|
430
|
+
const bound = column(first.column, first.direction === "asc" ? "gte" : "lte", values[0]);
|
|
431
|
+
return and(bound, after) ?? after;
|
|
432
|
+
}
|
|
433
|
+
//#endregion
|
|
434
|
+
//#region src/core/row-keys.ts
|
|
435
|
+
/** App-cased primary keys of `rows`, or of a `where` that pins the primary key. */
|
|
436
|
+
function keysOf(op, rows) {
|
|
437
|
+
const { primaryKey } = op.table;
|
|
438
|
+
if (primaryKey.length === 0) return void 0;
|
|
439
|
+
const fromRows = rows.flatMap((row) => primaryKey.every((name) => row[name] !== void 0 && row[name] !== null) ? [Object.fromEntries(primaryKey.map((name) => [name, row[name]]))] : []);
|
|
440
|
+
if (fromRows.length > 0) return fromRows;
|
|
441
|
+
if (op.kind === "insert") return void 0;
|
|
442
|
+
return keysFromWhere(op.table, op.where);
|
|
443
|
+
}
|
|
444
|
+
function keysFromWhere(table, where) {
|
|
445
|
+
if (!where) return void 0;
|
|
446
|
+
const { byDb } = lookupOf(table);
|
|
447
|
+
const pinned = /* @__PURE__ */ new Map();
|
|
448
|
+
const items = [];
|
|
449
|
+
const flatten = (condition) => {
|
|
450
|
+
if (condition.kind === "and") condition.items.forEach(flatten);
|
|
451
|
+
else items.push(condition);
|
|
452
|
+
};
|
|
453
|
+
flatten(where);
|
|
454
|
+
for (const item of items) {
|
|
455
|
+
if (item.kind !== "column" || item.path) continue;
|
|
456
|
+
const app = byDb.get(item.column)?.[0];
|
|
457
|
+
if (app === void 0 || !table.primaryKey.includes(app)) continue;
|
|
458
|
+
if (item.op === "eq") pinned.set(app, [item.value]);
|
|
459
|
+
else if (item.op === "in" && Array.isArray(item.value)) pinned.set(app, item.value);
|
|
270
460
|
}
|
|
461
|
+
if (pinned.size !== table.primaryKey.length) return void 0;
|
|
462
|
+
const [first, ...rest] = table.primaryKey;
|
|
463
|
+
if (first === void 0) return void 0;
|
|
464
|
+
if (rest.length === 0) return (pinned.get(first) ?? []).map((value) => ({ [first]: value }));
|
|
465
|
+
if ([...pinned.values()].some((values) => values.length !== 1)) return void 0;
|
|
466
|
+
return [Object.fromEntries(table.primaryKey.map((name) => [name, pinned.get(name)?.[0]]))];
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* Rows in conflict-key order, so concurrent upserts lock the same rows in
|
|
470
|
+
* the same order instead of deadlocking.
|
|
471
|
+
*/
|
|
472
|
+
function byKey(rows, columns) {
|
|
473
|
+
const compare = (left, right) => {
|
|
474
|
+
if (left === right) return 0;
|
|
475
|
+
if (left === null || left === void 0) return 1;
|
|
476
|
+
if (right === null || right === void 0) return -1;
|
|
477
|
+
if (typeof left === "number" && typeof right === "number") return left - right;
|
|
478
|
+
if (typeof left === "bigint" && typeof right === "bigint") return left < right ? -1 : 1;
|
|
479
|
+
const a = String(left);
|
|
480
|
+
const b = String(right);
|
|
481
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
482
|
+
};
|
|
483
|
+
const keyed = rows.map((row) => ({
|
|
484
|
+
row,
|
|
485
|
+
key: columns.map((column) => {
|
|
486
|
+
const value = row[column];
|
|
487
|
+
return typeof value === "object" && value !== null ? String(value) : value;
|
|
488
|
+
})
|
|
489
|
+
}));
|
|
490
|
+
keyed.sort((left, right) => {
|
|
491
|
+
for (let index = 0; index < columns.length; index++) {
|
|
492
|
+
const order = compare(left.key[index], right.key[index]);
|
|
493
|
+
if (order !== 0) return order;
|
|
494
|
+
}
|
|
495
|
+
return 0;
|
|
496
|
+
});
|
|
497
|
+
return keyed.map((entry) => entry.row);
|
|
498
|
+
}
|
|
499
|
+
//#endregion
|
|
500
|
+
//#region src/core/write-args.ts
|
|
501
|
+
const COUNT_MODES = /* @__PURE__ */ new Set([
|
|
502
|
+
"exact",
|
|
503
|
+
"planned",
|
|
504
|
+
"estimated"
|
|
505
|
+
]);
|
|
506
|
+
function isCountMode(value) {
|
|
507
|
+
return COUNT_MODES.has(value);
|
|
508
|
+
}
|
|
509
|
+
/** `maxAffected` from a call, or a message when it isn't a non-negative integer. */
|
|
510
|
+
function maxAffectedOf(args) {
|
|
511
|
+
const value = args["maxAffected"];
|
|
512
|
+
if (value === void 0) return {};
|
|
513
|
+
return typeof value === "number" && Number.isInteger(value) && value >= 0 ? { maxAffected: value } : { invalid: `"maxAffected" must be a non-negative integer, got ${String(value)}` };
|
|
514
|
+
}
|
|
515
|
+
/** The `count` mode a mutation asks for, when it names a valid one. */
|
|
516
|
+
function countOf(args) {
|
|
517
|
+
const count = args?.["count"];
|
|
518
|
+
return isCountMode(count) ? { count } : {};
|
|
271
519
|
}
|
|
272
520
|
//#endregion
|
|
273
521
|
//#region src/core/repository.ts
|
|
@@ -294,7 +542,11 @@ const KNOWN_KEYS = /* @__PURE__ */ new Set([
|
|
|
294
542
|
"_sum",
|
|
295
543
|
"_avg",
|
|
296
544
|
"_min",
|
|
297
|
-
"_max"
|
|
545
|
+
"_max",
|
|
546
|
+
"timeout",
|
|
547
|
+
"retry",
|
|
548
|
+
"maxAffected",
|
|
549
|
+
"defaultToNull"
|
|
298
550
|
]);
|
|
299
551
|
const NO_OPTIONS = Object.freeze({});
|
|
300
552
|
function optionsOf(args) {
|
|
@@ -326,39 +578,6 @@ function signalOf(args) {
|
|
|
326
578
|
function cloneRows(rows) {
|
|
327
579
|
return rows.map((row) => cloneValue(row));
|
|
328
580
|
}
|
|
329
|
-
/** App-cased primary keys of `rows`, or of a `where` that pins the primary key. */
|
|
330
|
-
function keysOf(op, rows) {
|
|
331
|
-
const { primaryKey } = op.table;
|
|
332
|
-
if (primaryKey.length === 0) return void 0;
|
|
333
|
-
const fromRows = rows.flatMap((row) => primaryKey.every((name) => row[name] !== void 0 && row[name] !== null) ? [Object.fromEntries(primaryKey.map((name) => [name, row[name]]))] : []);
|
|
334
|
-
if (fromRows.length > 0) return fromRows;
|
|
335
|
-
if (op.kind === "insert") return void 0;
|
|
336
|
-
return keysFromWhere(op.table, op.where);
|
|
337
|
-
}
|
|
338
|
-
function keysFromWhere(table, where) {
|
|
339
|
-
if (!where) return void 0;
|
|
340
|
-
const { byDb } = lookupOf(table);
|
|
341
|
-
const pinned = /* @__PURE__ */ new Map();
|
|
342
|
-
const items = [];
|
|
343
|
-
const flatten = (condition) => {
|
|
344
|
-
if (condition.kind === "and") condition.items.forEach(flatten);
|
|
345
|
-
else items.push(condition);
|
|
346
|
-
};
|
|
347
|
-
flatten(where);
|
|
348
|
-
for (const item of items) {
|
|
349
|
-
if (item.kind !== "column") continue;
|
|
350
|
-
const app = byDb.get(item.column)?.[0];
|
|
351
|
-
if (app === void 0 || !table.primaryKey.includes(app)) continue;
|
|
352
|
-
if (item.op === "eq") pinned.set(app, [item.value]);
|
|
353
|
-
else if (item.op === "in" && Array.isArray(item.value)) pinned.set(app, item.value);
|
|
354
|
-
}
|
|
355
|
-
if (pinned.size !== table.primaryKey.length) return void 0;
|
|
356
|
-
const [first, ...rest] = table.primaryKey;
|
|
357
|
-
if (first === void 0) return void 0;
|
|
358
|
-
if (rest.length === 0) return (pinned.get(first) ?? []).map((value) => ({ [first]: value }));
|
|
359
|
-
if ([...pinned.values()].some((values) => values.length !== 1)) return void 0;
|
|
360
|
-
return [Object.fromEntries(table.primaryKey.map((name) => [name, pinned.get(name)?.[0]]))];
|
|
361
|
-
}
|
|
362
581
|
function mutationKind(op) {
|
|
363
582
|
if (op.kind === "insert") return op.onConflict ? "upsert" : "insert";
|
|
364
583
|
return op.kind;
|
|
@@ -371,26 +590,42 @@ var OperationRunner = class {
|
|
|
371
590
|
this.runtime = runtime;
|
|
372
591
|
this.#hooks = hooksOf(runtime.plugins);
|
|
373
592
|
}
|
|
374
|
-
hookArgs(table, options) {
|
|
593
|
+
hookArgs(table, options, signal) {
|
|
375
594
|
return {
|
|
376
595
|
table,
|
|
377
596
|
schema: this.runtime.meta,
|
|
378
597
|
context: this.runtime.context,
|
|
379
598
|
options,
|
|
380
|
-
now: this.runtime.now
|
|
599
|
+
now: this.runtime.now,
|
|
600
|
+
...signal ? { signal } : {}
|
|
381
601
|
};
|
|
382
602
|
}
|
|
383
|
-
async run(op, options, signal) {
|
|
603
|
+
async run(op, options, signal, tuning = NO_TUNING) {
|
|
384
604
|
const { runtime } = this;
|
|
385
605
|
const hooks = this.#hooks;
|
|
606
|
+
if ("invalid" in tuning) return this.fail(op.table, dbError("invalid_request", tuning.invalid));
|
|
607
|
+
const { timeout, retry } = {
|
|
608
|
+
...runtime.tuning,
|
|
609
|
+
...tuning
|
|
610
|
+
};
|
|
611
|
+
const invalid = invalidTuning({
|
|
612
|
+
timeout,
|
|
613
|
+
retry
|
|
614
|
+
});
|
|
615
|
+
if (invalid) return this.fail(op.table, dbError("invalid_request", invalid));
|
|
386
616
|
let current = op;
|
|
387
617
|
if (hooks.transformQuery.length > 0 || hooks.beforeMutation.length > 0) {
|
|
388
|
-
const hook = this.hookArgs(op.table, options);
|
|
618
|
+
const hook = this.hookArgs(op.table, options, signal);
|
|
619
|
+
let active = "";
|
|
389
620
|
try {
|
|
390
|
-
for (const plugin of hooks.transformQuery)
|
|
621
|
+
for (const plugin of hooks.transformQuery) {
|
|
622
|
+
active = `plugin "${plugin.name}" transformQuery`;
|
|
623
|
+
current = plugin.transformQuery(current, hook);
|
|
624
|
+
}
|
|
391
625
|
if (current.kind !== "select") {
|
|
392
626
|
let mutation = current;
|
|
393
627
|
for (const plugin of hooks.beforeMutation) {
|
|
628
|
+
active = `plugin "${plugin.name}" beforeMutation`;
|
|
394
629
|
const next = plugin.beforeMutation(mutation, hook);
|
|
395
630
|
mutation = isThenable(next) ? await next : next;
|
|
396
631
|
}
|
|
@@ -398,16 +633,16 @@ var OperationRunner = class {
|
|
|
398
633
|
}
|
|
399
634
|
} catch (cause) {
|
|
400
635
|
if (cause instanceof DbException) return this.fail(op.table, cause.error);
|
|
401
|
-
|
|
636
|
+
return this.fail(op.table, {
|
|
637
|
+
...toDbError(cause),
|
|
638
|
+
details: `${active} threw`
|
|
639
|
+
});
|
|
402
640
|
}
|
|
403
641
|
}
|
|
642
|
+
if (current.kind === "update" && Object.keys(current.set).length === 0) return this.fail(op.table, dbError("invalid_request", `The update on "${op.table.key}" sets no columns`));
|
|
404
643
|
const timed = runtime.events.has("query");
|
|
405
644
|
const started = timed ? performance.now() : 0;
|
|
406
|
-
const
|
|
407
|
-
signal,
|
|
408
|
-
errorMappers: runtime.errorMappers
|
|
409
|
-
} : { errorMappers: runtime.errorMappers };
|
|
410
|
-
const executed = await runtime.executor.execute(current, context);
|
|
645
|
+
const executed = await this.#execute(current, signal, timeout, retry);
|
|
411
646
|
const selection = current.kind === "select" ? current.selection : current.returning;
|
|
412
647
|
let result = executed;
|
|
413
648
|
if (executed.ok && selection && needsDecoding(selection)) try {
|
|
@@ -437,10 +672,44 @@ var OperationRunner = class {
|
|
|
437
672
|
truncated
|
|
438
673
|
});
|
|
439
674
|
if (!result.ok) return this.fail(op.table, result.error);
|
|
440
|
-
if (current.kind !== "select") await this.afterMutation(
|
|
675
|
+
if (current.kind !== "select") await this.afterMutation(current, result.data);
|
|
441
676
|
return result;
|
|
442
677
|
}
|
|
443
|
-
|
|
678
|
+
/**
|
|
679
|
+
* Runs `op` without plugins or decoding, with the connection's timeout and
|
|
680
|
+
* retry, and fails on `table`: for reads the library makes itself, such
|
|
681
|
+
* as the scores of `db.$search({ score: true })`.
|
|
682
|
+
*/
|
|
683
|
+
async runInternal(op, table, signal) {
|
|
684
|
+
const { timeout, retry } = this.runtime.tuning ?? NO_TUNING;
|
|
685
|
+
const invalid = invalidTuning({
|
|
686
|
+
timeout,
|
|
687
|
+
retry
|
|
688
|
+
});
|
|
689
|
+
if (invalid) return this.fail(table, dbError("invalid_request", invalid));
|
|
690
|
+
const executed = await this.#execute(op, signal, timeout, retry);
|
|
691
|
+
return executed.ok ? executed : this.fail(table, {
|
|
692
|
+
...executed.error,
|
|
693
|
+
table: table.key
|
|
694
|
+
});
|
|
695
|
+
}
|
|
696
|
+
async #execute(op, signal, timeout, retry) {
|
|
697
|
+
const limit = deadline(signal, timeout);
|
|
698
|
+
const context = {
|
|
699
|
+
errorMappers: this.runtime.errorMappers,
|
|
700
|
+
...limit.signal ? { signal: limit.signal } : {},
|
|
701
|
+
...retry === void 0 ? {} : { retry }
|
|
702
|
+
};
|
|
703
|
+
let executed;
|
|
704
|
+
try {
|
|
705
|
+
executed = await this.runtime.executor.execute(op, context);
|
|
706
|
+
} finally {
|
|
707
|
+
limit.clear();
|
|
708
|
+
}
|
|
709
|
+
if (!executed.ok && limit.timedOut()) return err(dbError("timeout", `The request timed out after ${timeout} ms`));
|
|
710
|
+
return executed;
|
|
711
|
+
}
|
|
712
|
+
async afterMutation(op, data) {
|
|
444
713
|
const { runtime } = this;
|
|
445
714
|
const plugins = this.#hooks.afterMutation;
|
|
446
715
|
const listening = runtime.events.has("mutation");
|
|
@@ -448,11 +717,11 @@ var OperationRunner = class {
|
|
|
448
717
|
const kind = mutationKind(op);
|
|
449
718
|
const rows = cloneRows(data.rows);
|
|
450
719
|
const keys = keysOf(op, rows);
|
|
451
|
-
const tenant =
|
|
720
|
+
const { tenant } = runtime.context;
|
|
452
721
|
const event = {
|
|
453
722
|
table: op.table,
|
|
454
723
|
kind,
|
|
455
|
-
intent:
|
|
724
|
+
intent: op.intent ?? kind,
|
|
456
725
|
rows,
|
|
457
726
|
...keys ? { keys } : {},
|
|
458
727
|
...tenant === void 0 ? {} : { tenant },
|
|
@@ -479,14 +748,13 @@ var OperationRunner = class {
|
|
|
479
748
|
...error,
|
|
480
749
|
table: table.key
|
|
481
750
|
};
|
|
482
|
-
if (this.runtime.events.has("error")) this.runtime.events.emit("error",
|
|
483
|
-
table: table.key,
|
|
484
|
-
error: withTable
|
|
485
|
-
});
|
|
751
|
+
if (this.runtime.events.has("error")) this.runtime.events.emit("error", errorEvent(withTable, table.key));
|
|
486
752
|
return err(withTable);
|
|
487
753
|
}
|
|
488
754
|
};
|
|
489
755
|
const sensitiveByTable = /* @__PURE__ */ new WeakMap();
|
|
756
|
+
const primaryOrders = /* @__PURE__ */ new WeakMap();
|
|
757
|
+
const existsSelections = /* @__PURE__ */ new WeakMap();
|
|
490
758
|
/** Database names of the table's `config.sensitive` columns. */
|
|
491
759
|
function sensitiveColumnsOf(table) {
|
|
492
760
|
let sensitive = sensitiveByTable.get(table);
|
|
@@ -501,14 +769,20 @@ function createRepository(runner, table) {
|
|
|
501
769
|
const { builder } = runner.runtime;
|
|
502
770
|
const sensitiveDb = sensitiveColumnsOf(table);
|
|
503
771
|
const selection = (args) => builder.selection(table, args?.["select"], args?.["include"]);
|
|
772
|
+
const rowCount = (args, name) => {
|
|
773
|
+
const value = args?.[name];
|
|
774
|
+
if (value === void 0) return void 0;
|
|
775
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) invalidRequest(`"${name}" must be a non-negative integer, not ${String(value)}`, table.key);
|
|
776
|
+
return value;
|
|
777
|
+
};
|
|
504
778
|
const selectOp = (args, patch = {}) => ({
|
|
505
779
|
kind: "select",
|
|
506
780
|
table,
|
|
507
781
|
selection: selection(args),
|
|
508
782
|
where: builder.where(table, args?.["where"]),
|
|
509
783
|
orderBy: builder.orderBy(table, args?.["orderBy"]),
|
|
510
|
-
limit:
|
|
511
|
-
offset:
|
|
784
|
+
limit: rowCount(args, "limit"),
|
|
785
|
+
offset: rowCount(args, "offset"),
|
|
512
786
|
count: void 0,
|
|
513
787
|
head: false,
|
|
514
788
|
single: void 0,
|
|
@@ -525,19 +799,34 @@ function createRepository(runner, table) {
|
|
|
525
799
|
columns
|
|
526
800
|
};
|
|
527
801
|
};
|
|
528
|
-
const run = (op, args) => runner.run(op, optionsOf(args), signalOf(args));
|
|
529
|
-
let primaryOrder;
|
|
802
|
+
const run = (op, args) => runner.run(op, optionsOf(args), signalOf(args), tuningOf(args));
|
|
530
803
|
/** `primaryKey` holds app names; order terms take database names. */
|
|
531
|
-
const defaultOrder = () =>
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
804
|
+
const defaultOrder = () => {
|
|
805
|
+
let order = primaryOrders.get(table);
|
|
806
|
+
if (!order) {
|
|
807
|
+
order = table.primaryKey.map((name) => ({
|
|
808
|
+
column: builder.column(table, name),
|
|
809
|
+
direction: "asc",
|
|
810
|
+
implicit: true
|
|
811
|
+
}));
|
|
812
|
+
primaryOrders.set(table, order);
|
|
813
|
+
}
|
|
814
|
+
return order;
|
|
815
|
+
};
|
|
535
816
|
const notFound = () => runner.fail(table, dbError("not_found", `No ${table.key} row matched`));
|
|
817
|
+
/** Arguments the builder rejects fail like any other error: with the table and an `error` event. */
|
|
818
|
+
const guarded = (work) => AsyncResult.from(async () => {
|
|
819
|
+
try {
|
|
820
|
+
return await work();
|
|
821
|
+
} catch (cause) {
|
|
822
|
+
return runner.fail(table, toDbError(cause));
|
|
823
|
+
}
|
|
824
|
+
});
|
|
536
825
|
const base = {
|
|
537
826
|
$tableName: table.key,
|
|
538
827
|
$meta: table,
|
|
539
828
|
findMany(args) {
|
|
540
|
-
return
|
|
829
|
+
return guarded(async () => {
|
|
541
830
|
const op = selectOp(args);
|
|
542
831
|
const ordered = op.orderBy.length > 0 || table.primaryKey.length === 0 ? op : {
|
|
543
832
|
...op,
|
|
@@ -548,13 +837,24 @@ function createRepository(runner, table) {
|
|
|
548
837
|
});
|
|
549
838
|
},
|
|
550
839
|
findFirst(args) {
|
|
551
|
-
return
|
|
840
|
+
return guarded(async () => {
|
|
552
841
|
const result = await run(selectOp(args, { limit: 1 }), args);
|
|
553
842
|
return result.ok ? ok(result.data.rows[0] ?? null) : result;
|
|
554
843
|
});
|
|
555
844
|
},
|
|
845
|
+
findOnly(args) {
|
|
846
|
+
return guarded(async () => {
|
|
847
|
+
const result = await run(selectOp(args, {
|
|
848
|
+
limit: 2,
|
|
849
|
+
unpaged: true
|
|
850
|
+
}), args);
|
|
851
|
+
if (!result.ok) return result;
|
|
852
|
+
if (result.data.rows.length > 1) return runner.fail(table, dbError("multiple_rows", `More than one ${table.key} row matched; findOnly expects at most one`));
|
|
853
|
+
return ok(result.data.rows[0] ?? null);
|
|
854
|
+
});
|
|
855
|
+
},
|
|
556
856
|
findUnique(args) {
|
|
557
|
-
return
|
|
857
|
+
return guarded(async () => {
|
|
558
858
|
const op = selectOp(args, {
|
|
559
859
|
where: builder.uniqueKey(table, args["where"]),
|
|
560
860
|
limit: 1
|
|
@@ -564,7 +864,7 @@ function createRepository(runner, table) {
|
|
|
564
864
|
});
|
|
565
865
|
},
|
|
566
866
|
findById(id, args) {
|
|
567
|
-
return
|
|
867
|
+
return guarded(async () => {
|
|
568
868
|
const op = selectOp(args, {
|
|
569
869
|
where: builder.primaryKey(table, id),
|
|
570
870
|
limit: 1
|
|
@@ -576,7 +876,7 @@ function createRepository(runner, table) {
|
|
|
576
876
|
});
|
|
577
877
|
},
|
|
578
878
|
count(args) {
|
|
579
|
-
return
|
|
879
|
+
return guarded(async () => {
|
|
580
880
|
const mode = args?.["mode"];
|
|
581
881
|
const op = selectOp({ where: args?.["where"] }, {
|
|
582
882
|
selection: {
|
|
@@ -591,12 +891,9 @@ function createRepository(runner, table) {
|
|
|
591
891
|
});
|
|
592
892
|
},
|
|
593
893
|
aggregate(args) {
|
|
594
|
-
return
|
|
894
|
+
return guarded(async () => {
|
|
595
895
|
const aggregation = builder.aggregation(table, args);
|
|
596
|
-
const orderBy = builder.
|
|
597
|
-
const grouped = new Set(aggregation.columns.map((c) => c.column));
|
|
598
|
-
const loose = orderBy.find((term) => !grouped.has(term.column));
|
|
599
|
-
if (loose) return runner.fail(table, dbError("invalid_request", `aggregate on "${table.key}" can only sort by groupBy columns, not "${loose.column}"`));
|
|
896
|
+
const orderBy = builder.aggregateOrderBy(table, args["orderBy"], aggregation);
|
|
600
897
|
const op = selectOp({
|
|
601
898
|
where: args["where"],
|
|
602
899
|
limit: args["limit"],
|
|
@@ -612,13 +909,9 @@ function createRepository(runner, table) {
|
|
|
612
909
|
});
|
|
613
910
|
},
|
|
614
911
|
exists(args) {
|
|
615
|
-
return
|
|
616
|
-
const columns = table.primaryKey.slice(0, 1).map((alias) => builder.selectColumn(table, alias));
|
|
912
|
+
return guarded(async () => {
|
|
617
913
|
const op = selectOp({ where: args?.["where"] }, {
|
|
618
|
-
selection:
|
|
619
|
-
columns,
|
|
620
|
-
includes: []
|
|
621
|
-
},
|
|
914
|
+
selection: existsSelection(),
|
|
622
915
|
limit: 1
|
|
623
916
|
});
|
|
624
917
|
const result = await run(op, args);
|
|
@@ -626,10 +919,10 @@ function createRepository(runner, table) {
|
|
|
626
919
|
});
|
|
627
920
|
},
|
|
628
921
|
paginate(args) {
|
|
629
|
-
return
|
|
922
|
+
return guarded(async () => "after" in args ? cursorPage(args) : offsetPage(args));
|
|
630
923
|
},
|
|
631
924
|
create(data, args) {
|
|
632
|
-
return
|
|
925
|
+
return guarded(async () => {
|
|
633
926
|
const op = insertOp([data], args, void 0);
|
|
634
927
|
const result = await run(op, args);
|
|
635
928
|
if (!result.ok) return result;
|
|
@@ -637,7 +930,7 @@ function createRepository(runner, table) {
|
|
|
637
930
|
});
|
|
638
931
|
},
|
|
639
932
|
createMany(rows, args) {
|
|
640
|
-
return
|
|
933
|
+
return guarded(async () => {
|
|
641
934
|
if (rows.length === 0) return ok(args?.["returning"] === false ? { count: 0 } : []);
|
|
642
935
|
const result = await run(insertOp(rows, args, void 0), args);
|
|
643
936
|
if (!result.ok) return result;
|
|
@@ -645,8 +938,8 @@ function createRepository(runner, table) {
|
|
|
645
938
|
});
|
|
646
939
|
},
|
|
647
940
|
update(id, patch, args) {
|
|
648
|
-
return
|
|
649
|
-
const key = builder.primaryKey(table, id);
|
|
941
|
+
return guarded(async () => {
|
|
942
|
+
const key = and(builder.primaryKey(table, id), builder.where(table, args?.["where"]));
|
|
650
943
|
const expect = args?.["expect"] ? builder.where(table, args["expect"]) : void 0;
|
|
651
944
|
const op = {
|
|
652
945
|
kind: "update",
|
|
@@ -675,20 +968,28 @@ function createRepository(runner, table) {
|
|
|
675
968
|
});
|
|
676
969
|
},
|
|
677
970
|
updateMany(args) {
|
|
678
|
-
return
|
|
971
|
+
return guarded(async () => {
|
|
972
|
+
const where = builder.where(table, args["where"]);
|
|
973
|
+
if (simplify(where) === true && args["allowAll"] !== true) return runner.fail(table, dbError("invalid_request", "updateMany needs a \"where\" that filters rows; pass allowAll: true to update every row"));
|
|
974
|
+
const rows = args["returning"] === true;
|
|
975
|
+
const bound = maxAffectedOf(args);
|
|
976
|
+
if ("invalid" in bound) return runner.fail(table, dbError("invalid_request", bound.invalid));
|
|
679
977
|
const op = {
|
|
680
978
|
kind: "update",
|
|
681
979
|
table,
|
|
682
980
|
set: builder.row(table, args["data"], "update"),
|
|
683
|
-
where
|
|
684
|
-
returning: void 0
|
|
981
|
+
where,
|
|
982
|
+
returning: rows ? returning(args) : void 0,
|
|
983
|
+
...bound,
|
|
984
|
+
...countOf(args)
|
|
685
985
|
};
|
|
686
986
|
const result = await run(op, args);
|
|
687
|
-
|
|
987
|
+
if (!result.ok) return result;
|
|
988
|
+
return ok(rows ? result.data.rows : { count: result.data.count ?? 0 });
|
|
688
989
|
});
|
|
689
990
|
},
|
|
690
991
|
upsert(data, args) {
|
|
691
|
-
return
|
|
992
|
+
return guarded(async () => {
|
|
692
993
|
const op = insertOp([data], args, conflictColumns(args?.["onConflict"]));
|
|
693
994
|
const result = await run(op, args);
|
|
694
995
|
if (!result.ok) return result;
|
|
@@ -696,7 +997,7 @@ function createRepository(runner, table) {
|
|
|
696
997
|
});
|
|
697
998
|
},
|
|
698
999
|
upsertMany(rows, args) {
|
|
699
|
-
return
|
|
1000
|
+
return guarded(async () => {
|
|
700
1001
|
if (rows.length === 0) return ok(args?.["returning"] === false ? { count: 0 } : []);
|
|
701
1002
|
const op = insertOp(rows, args, conflictColumns(args?.["onConflict"]));
|
|
702
1003
|
const result = await run(op, args);
|
|
@@ -705,7 +1006,7 @@ function createRepository(runner, table) {
|
|
|
705
1006
|
});
|
|
706
1007
|
},
|
|
707
1008
|
delete(id, args) {
|
|
708
|
-
return
|
|
1009
|
+
return guarded(async () => {
|
|
709
1010
|
const op = {
|
|
710
1011
|
kind: "delete",
|
|
711
1012
|
table,
|
|
@@ -718,16 +1019,26 @@ function createRepository(runner, table) {
|
|
|
718
1019
|
});
|
|
719
1020
|
},
|
|
720
1021
|
deleteMany(args) {
|
|
721
|
-
return
|
|
1022
|
+
return guarded(async () => {
|
|
722
1023
|
const where = builder.where(table, args["where"]);
|
|
723
|
-
if (!where) return runner.fail(table, dbError("invalid_request", "deleteMany needs a
|
|
724
|
-
const
|
|
1024
|
+
if (!where || simplify(where) === true) return runner.fail(table, dbError("invalid_request", "deleteMany needs a \"where\" that filters rows"));
|
|
1025
|
+
const rows = args["returning"] === true;
|
|
1026
|
+
const bound = maxAffectedOf(args);
|
|
1027
|
+
if ("invalid" in bound) return runner.fail(table, dbError("invalid_request", bound.invalid));
|
|
1028
|
+
const op = {
|
|
725
1029
|
kind: "delete",
|
|
726
1030
|
table,
|
|
727
1031
|
where,
|
|
728
|
-
returning: void 0
|
|
729
|
-
|
|
730
|
-
|
|
1032
|
+
returning: rows ? returning(args) : void 0,
|
|
1033
|
+
...bound,
|
|
1034
|
+
...countOf(args)
|
|
1035
|
+
};
|
|
1036
|
+
const result = await runner.run(op, rows ? {
|
|
1037
|
+
...optionsOf(args),
|
|
1038
|
+
returning: true
|
|
1039
|
+
} : optionsOf(args), signalOf(args), tuningOf(args));
|
|
1040
|
+
if (!result.ok) return result;
|
|
1041
|
+
return ok(rows ? result.data.rows : { count: result.data.count ?? 0 });
|
|
731
1042
|
});
|
|
732
1043
|
}
|
|
733
1044
|
};
|
|
@@ -742,9 +1053,27 @@ function createRepository(runner, table) {
|
|
|
742
1053
|
columns: conflict,
|
|
743
1054
|
action: args?.["ignoreDuplicates"] === true ? "ignore" : "update"
|
|
744
1055
|
} : void 0,
|
|
745
|
-
defaultToNull:
|
|
1056
|
+
defaultToNull: args?.["defaultToNull"] === true,
|
|
1057
|
+
...countOf(args)
|
|
746
1058
|
};
|
|
747
1059
|
}
|
|
1060
|
+
/** One column is enough to see a row: the primary key, or the first non-sensitive column. */
|
|
1061
|
+
function existsSelection() {
|
|
1062
|
+
let found = existsSelections.get(table);
|
|
1063
|
+
if (!found) {
|
|
1064
|
+
const names = Object.keys(table.columns);
|
|
1065
|
+
const alias = table.primaryKey[0] ?? names.find((name) => !table.columns[name]?.sensitive) ?? names[0];
|
|
1066
|
+
found = {
|
|
1067
|
+
columns: alias === void 0 ? [] : [{
|
|
1068
|
+
alias,
|
|
1069
|
+
column: builder.column(table, alias)
|
|
1070
|
+
}],
|
|
1071
|
+
includes: []
|
|
1072
|
+
};
|
|
1073
|
+
existsSelections.set(table, found);
|
|
1074
|
+
}
|
|
1075
|
+
return found;
|
|
1076
|
+
}
|
|
748
1077
|
function conflictColumns(target) {
|
|
749
1078
|
if (target === void 0 || target === "primaryKey") return table.primaryKey.map((name) => builder.column(table, name));
|
|
750
1079
|
if (typeof target === "string") {
|
|
@@ -755,18 +1084,39 @@ function createRepository(runner, table) {
|
|
|
755
1084
|
if (Array.isArray(target)) return target.map((name) => builder.column(table, String(name)));
|
|
756
1085
|
return invalidRequest(`Invalid onConflict on "${table.key}"`, table.key);
|
|
757
1086
|
}
|
|
758
|
-
|
|
1087
|
+
function pageWindow(args) {
|
|
1088
|
+
if (args["offset"] !== void 0 || args["limit"] !== void 0) {
|
|
1089
|
+
if (args["page"] !== void 0 || args["size"] !== void 0) return { invalid: "Pass \"offset\" and \"limit\" or \"page\" and \"size\"" };
|
|
1090
|
+
const limit = Number(args["limit"]);
|
|
1091
|
+
if (!Number.isInteger(limit) || limit < 1) return { invalid: "\"limit\" must be a positive integer" };
|
|
1092
|
+
const offset = Number(args["offset"]);
|
|
1093
|
+
if (!Number.isInteger(offset) || offset < 0) return { invalid: "\"offset\" must be a non-negative integer" };
|
|
1094
|
+
return {
|
|
1095
|
+
size: limit,
|
|
1096
|
+
offset
|
|
1097
|
+
};
|
|
1098
|
+
}
|
|
759
1099
|
const size = Number(args["size"]);
|
|
760
|
-
if (!Number.isInteger(size) || size < 1) return
|
|
1100
|
+
if (!Number.isInteger(size) || size < 1) return { invalid: "\"size\" must be a positive integer" };
|
|
761
1101
|
const number = args["page"] === void 0 ? 1 : Number(args["page"]);
|
|
762
|
-
if (!Number.isInteger(number) || number < 1) return
|
|
1102
|
+
if (!Number.isInteger(number) || number < 1) return { invalid: "\"page\" must be a positive integer" };
|
|
1103
|
+
return {
|
|
1104
|
+
size,
|
|
1105
|
+
offset: (number - 1) * size
|
|
1106
|
+
};
|
|
1107
|
+
}
|
|
1108
|
+
async function offsetPage(args) {
|
|
1109
|
+
const window = pageWindow(args);
|
|
1110
|
+
if ("invalid" in window) return runner.fail(table, dbError("invalid_request", window.invalid));
|
|
1111
|
+
const { size, offset } = window;
|
|
1112
|
+
const number = Math.floor(offset / size) + 1;
|
|
763
1113
|
const count = args["count"];
|
|
764
1114
|
const orderBy = builder.orderBy(table, args["orderBy"]);
|
|
765
1115
|
const op = selectOp(args, {
|
|
766
1116
|
orderBy: orderBy.length > 0 || table.primaryKey.length === 0 ? orderBy : defaultOrder(),
|
|
767
1117
|
limit: size + 1,
|
|
768
1118
|
lookAhead: true,
|
|
769
|
-
offset
|
|
1119
|
+
offset,
|
|
770
1120
|
count: count === "exact" || count === "planned" || count === "estimated" ? count : void 0
|
|
771
1121
|
});
|
|
772
1122
|
const result = await run(op, args);
|
|
@@ -787,11 +1137,17 @@ function createRepository(runner, table) {
|
|
|
787
1137
|
async function cursorPage(args) {
|
|
788
1138
|
const size = Number(args["size"]);
|
|
789
1139
|
if (!Number.isInteger(size) || size < 1) return runner.fail(table, dbError("invalid_request", "\"size\" must be a positive integer"));
|
|
790
|
-
const
|
|
1140
|
+
const requested = builder.orderBy(table, args["orderBy"]);
|
|
1141
|
+
const related = requested.find((term) => term.relation);
|
|
1142
|
+
if (related) return runner.fail(table, dbError("invalid_request", `Cursor pages can't sort by the relation "${related.relation?.name}"; use an offset page`));
|
|
1143
|
+
const orderBy = withTieBreaker(requested);
|
|
791
1144
|
const { selection: withSort, added } = ensureColumns(selection(args), orderBy);
|
|
1145
|
+
const sort = sortKey(`${table.key}|${orderBy.map((term) => `${term.column}.${term.direction}.${term.nulls ?? ""}`).join(",")}`);
|
|
792
1146
|
let after;
|
|
793
1147
|
if (typeof args["after"] === "string") {
|
|
794
|
-
const
|
|
1148
|
+
const decoded = decodeBoundCursor(args["after"], sort);
|
|
1149
|
+
if ("invalid" in decoded && decoded.invalid === "sort") return runner.fail(table, dbError("invalid_request", "The cursor continues another orderBy; pass after: null to start the new order"));
|
|
1150
|
+
const values = "values" in decoded ? decoded.values : void 0;
|
|
795
1151
|
if (!values || values.length !== orderBy.length) return runner.fail(table, dbError("invalid_request", "Invalid cursor"));
|
|
796
1152
|
const { byDb } = lookupOf(table);
|
|
797
1153
|
after = keysetCondition(orderBy, values, (name) => byDb.get(name)?.[1].nullable ?? true);
|
|
@@ -810,7 +1166,7 @@ function createRepository(runner, table) {
|
|
|
810
1166
|
const hasMore = result.data.rows.length > size;
|
|
811
1167
|
const last = rows.at(-1);
|
|
812
1168
|
const aliases = new Map(withSort.columns.map((entry) => [entry.column, entry.alias]));
|
|
813
|
-
const nextCursor = hasMore && last ?
|
|
1169
|
+
const nextCursor = hasMore && last ? encodeBoundCursor(orderBy.map((term) => encodeValue(last[aliases.get(term.column) ?? term.column])), sort) : null;
|
|
814
1170
|
return ok({
|
|
815
1171
|
items: added.length > 0 ? rows.map((row) => strip(row, added)) : rows,
|
|
816
1172
|
nextCursor,
|
|
@@ -835,13 +1191,13 @@ function createRepository(runner, table) {
|
|
|
835
1191
|
const added = [];
|
|
836
1192
|
for (const term of orderBy) {
|
|
837
1193
|
if (selected.has(term.column)) continue;
|
|
838
|
-
const alias = byDb.get(term.column)?.[0]
|
|
839
|
-
columns.push({
|
|
840
|
-
alias,
|
|
1194
|
+
const alias = byDb.get(term.column)?.[0];
|
|
1195
|
+
columns.push(alias === void 0 ? {
|
|
1196
|
+
alias: term.column,
|
|
841
1197
|
column: term.column
|
|
842
|
-
});
|
|
1198
|
+
} : builder.selectColumn(table, alias));
|
|
843
1199
|
selected.add(term.column);
|
|
844
|
-
added.push(alias);
|
|
1200
|
+
added.push(alias ?? term.column);
|
|
845
1201
|
}
|
|
846
1202
|
return {
|
|
847
1203
|
selection: {
|
|
@@ -858,69 +1214,101 @@ function strip(row, keys) {
|
|
|
858
1214
|
for (const key in row) if (!keys.includes(key) && Object.hasOwn(row, key)) copy[key] = row[key];
|
|
859
1215
|
return copy;
|
|
860
1216
|
}
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
if (
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
return a < b ? -1 : a > b ? 1 : 0;
|
|
875
|
-
};
|
|
876
|
-
const keyed = rows.map((row) => ({
|
|
877
|
-
row,
|
|
878
|
-
key: columns.map((column) => {
|
|
879
|
-
const value = row[column];
|
|
880
|
-
return typeof value === "object" && value !== null ? String(value) : value;
|
|
881
|
-
})
|
|
882
|
-
}));
|
|
883
|
-
keyed.sort((left, right) => {
|
|
884
|
-
for (let index = 0; index < columns.length; index++) {
|
|
885
|
-
const order = compare(left.key[index], right.key[index]);
|
|
886
|
-
if (order !== 0) return order;
|
|
1217
|
+
//#endregion
|
|
1218
|
+
//#region src/core/rpc-result.ts
|
|
1219
|
+
const columnsByFunction = /* @__PURE__ */ new WeakMap();
|
|
1220
|
+
function columnsOf(meta, fn) {
|
|
1221
|
+
const cached = columnsByFunction.get(fn);
|
|
1222
|
+
if (cached !== void 0) return cached;
|
|
1223
|
+
let columns = null;
|
|
1224
|
+
const { result } = fn;
|
|
1225
|
+
if (result && "table" in result) {
|
|
1226
|
+
const table = meta.tables[result.table];
|
|
1227
|
+
if (table) {
|
|
1228
|
+
columns = /* @__PURE__ */ new Map();
|
|
1229
|
+
for (const [db, [app, column]] of lookupOf(table).byDb) if (app !== db || column.codec) columns.set(db, [app, column.codec]);
|
|
887
1230
|
}
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
return
|
|
1231
|
+
} else if (result) columns = new Map(result.columns.map((column) => [column.db, [column.name ?? column.db, column.codec]]));
|
|
1232
|
+
columnsByFunction.set(fn, columns);
|
|
1233
|
+
return columns;
|
|
1234
|
+
}
|
|
1235
|
+
function decodeRow(columns, row) {
|
|
1236
|
+
if (!isPlainObject(row)) return row;
|
|
1237
|
+
const out = {};
|
|
1238
|
+
for (const key in row) {
|
|
1239
|
+
if (!Object.hasOwn(row, key)) continue;
|
|
1240
|
+
const column = columns.get(key);
|
|
1241
|
+
if (!column) {
|
|
1242
|
+
out[key] = row[key];
|
|
1243
|
+
continue;
|
|
1244
|
+
}
|
|
1245
|
+
const [app, codec] = column;
|
|
1246
|
+
out[app] = codec ? decodeValue(codec, row[key]) : row[key];
|
|
1247
|
+
}
|
|
1248
|
+
return out;
|
|
891
1249
|
}
|
|
1250
|
+
const overloadMeta = /* @__PURE__ */ new WeakMap();
|
|
892
1251
|
/**
|
|
893
|
-
* The
|
|
894
|
-
*
|
|
895
|
-
*
|
|
896
|
-
*
|
|
1252
|
+
* The signature `$rpc` calls: PostgREST picks an overload by the argument
|
|
1253
|
+
* names, so a call matches the overload that has every name it passes and
|
|
1254
|
+
* every argument without a default. Undefined when the function is in
|
|
1255
|
+
* another schema or when no overload, or more than one, matches.
|
|
897
1256
|
*/
|
|
898
|
-
function
|
|
899
|
-
const
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
1257
|
+
function rpcFunction(meta, name, schema, args) {
|
|
1258
|
+
const fn = meta.functions[name];
|
|
1259
|
+
if (!fn || fn.schema !== schema) return void 0;
|
|
1260
|
+
if (!fn.overloads) return fn;
|
|
1261
|
+
const keys = Object.keys(args).filter((key) => args[key] !== void 0);
|
|
1262
|
+
const matches = fn.overloads.filter((overload) => keys.every((key) => overload.args.some((arg) => arg.name === key)) && overload.args.every((arg) => arg.optional === true || keys.includes(arg.name)));
|
|
1263
|
+
const [match] = matches;
|
|
1264
|
+
if (!match || matches.length > 1) return void 0;
|
|
1265
|
+
let resolved = overloadMeta.get(match);
|
|
1266
|
+
if (!resolved) {
|
|
1267
|
+
resolved = {
|
|
1268
|
+
...match,
|
|
1269
|
+
name: fn.name,
|
|
1270
|
+
schema: fn.schema
|
|
1271
|
+
};
|
|
1272
|
+
overloadMeta.set(match, resolved);
|
|
1273
|
+
}
|
|
1274
|
+
return resolved;
|
|
910
1275
|
}
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
1276
|
+
/**
|
|
1277
|
+
* The `$rpc` result in app form: rows of a table or a `returns table (...)`
|
|
1278
|
+
* record get the configured casing and codecs, like repository reads.
|
|
1279
|
+
* Scalars, json and calls without a known signature come back unchanged.
|
|
1280
|
+
*/
|
|
1281
|
+
function decodeRpcResult(meta, fn, data) {
|
|
1282
|
+
if (!fn) return data;
|
|
1283
|
+
const columns = columnsOf(meta, fn);
|
|
1284
|
+
if (!columns || columns.size === 0) return data;
|
|
1285
|
+
return Array.isArray(data) ? data.map((row) => decodeRow(columns, row)) : decodeRow(columns, data);
|
|
918
1286
|
}
|
|
919
1287
|
//#endregion
|
|
920
1288
|
//#region src/core/define.ts
|
|
921
1289
|
function isExecutor(value) {
|
|
922
1290
|
return typeof value === "object" && value !== null && typeof value.execute === "function" && typeof value.name === "string";
|
|
923
1291
|
}
|
|
1292
|
+
/** No plugins, one shared array so the caches keyed on a plugin list hit. */
|
|
1293
|
+
const NO_PLUGINS = Object.freeze([]);
|
|
1294
|
+
/** The kept lists per installed list and `keep` names, so each is one stable array. */
|
|
1295
|
+
const keptLists = /* @__PURE__ */ new WeakMap();
|
|
1296
|
+
/** The installed plugins named in `keep`; a name that isn't installed throws, so a typo can't drop tracing silently. */
|
|
1297
|
+
function keptPlugins(plugins, keep) {
|
|
1298
|
+
if (keep.length === 0) return NO_PLUGINS;
|
|
1299
|
+
let byKeep = keptLists.get(plugins);
|
|
1300
|
+
if (!byKeep) {
|
|
1301
|
+
byKeep = /* @__PURE__ */ new Map();
|
|
1302
|
+
keptLists.set(plugins, byKeep);
|
|
1303
|
+
}
|
|
1304
|
+
const key = keep.join("\0");
|
|
1305
|
+
const cached = byKeep.get(key);
|
|
1306
|
+
if (cached) return cached;
|
|
1307
|
+
for (const name of keep) if (!plugins.some((plugin) => plugin.name === name)) throw new TypeError(`better-supabase: $withoutPlugins({ keep }) names "${name}", which is not installed. Installed: ${plugins.map((plugin) => plugin.name).join(", ") || "none"}`);
|
|
1308
|
+
const kept = plugins.filter((plugin) => keep.includes(plugin.name));
|
|
1309
|
+
byKeep.set(key, kept);
|
|
1310
|
+
return kept;
|
|
1311
|
+
}
|
|
924
1312
|
/**
|
|
925
1313
|
* The isomorphic definition of your data layer: schema plus plugins. Holds no
|
|
926
1314
|
* secrets and no connection; `connect()` binds it to a client per request.
|
|
@@ -930,15 +1318,37 @@ var BetterSupabase = class BetterSupabase {
|
|
|
930
1318
|
plugins;
|
|
931
1319
|
events;
|
|
932
1320
|
options;
|
|
933
|
-
constructor(schema, plugins = [], options = {}, events =
|
|
1321
|
+
constructor(schema, plugins = [], options = {}, events = definitionEvents(options)) {
|
|
1322
|
+
const names = /* @__PURE__ */ new Set();
|
|
1323
|
+
for (const plugin of plugins) {
|
|
1324
|
+
if (plugin.apiVersion !== 1) throw new TypeError(`better-supabase: plugin "${plugin.name}" targets plugin API v${String(plugin.apiVersion)}; this version supports v1`);
|
|
1325
|
+
if (names.has(plugin.name)) throw new TypeError(`better-supabase: plugin "${plugin.name}" is already installed`);
|
|
1326
|
+
names.add(plugin.name);
|
|
1327
|
+
}
|
|
934
1328
|
this.schema = schema;
|
|
935
1329
|
this.plugins = orderPlugins(plugins);
|
|
936
1330
|
this.options = options;
|
|
937
1331
|
this.events = events;
|
|
1332
|
+
const { temporal } = options;
|
|
1333
|
+
if (temporal !== void 0) {
|
|
1334
|
+
const previous = providedTemporal();
|
|
1335
|
+
if (previous !== void 0 && previous !== temporal) events.logger.warn("defineSupabase got a different `temporal` namespace than the one already provided; decoded rows, jobs and webhooks in this process now use the newer one. Pass the same namespace to every definition.");
|
|
1336
|
+
provideTemporal(temporal);
|
|
1337
|
+
}
|
|
938
1338
|
}
|
|
939
1339
|
get meta() {
|
|
940
1340
|
return this.schema.meta;
|
|
941
1341
|
}
|
|
1342
|
+
/** The `now` option, else this definition's own `Temporal` clock. */
|
|
1343
|
+
#now() {
|
|
1344
|
+
const { now, temporal } = this.options;
|
|
1345
|
+
if (now) return now;
|
|
1346
|
+
return temporal ? () => temporal.Now.instant() : nowInstant;
|
|
1347
|
+
}
|
|
1348
|
+
/** The `Temporal` this definition uses: the `temporal` option, else the global. */
|
|
1349
|
+
get temporal() {
|
|
1350
|
+
return this.options.temporal ?? optionalTemporal();
|
|
1351
|
+
}
|
|
942
1352
|
/** The schema set by `claims()`; its output types `session.claims`. */
|
|
943
1353
|
get claimsSchema() {
|
|
944
1354
|
return this.options.claims;
|
|
@@ -1016,8 +1426,6 @@ var BetterSupabase = class BetterSupabase {
|
|
|
1016
1426
|
}
|
|
1017
1427
|
/** Returns a new instance with the plugin appended. */
|
|
1018
1428
|
use(plugin) {
|
|
1019
|
-
if (plugin.apiVersion !== 1) throw new TypeError(`better-supabase: plugin "${plugin.name}" targets plugin API v${String(plugin.apiVersion)}; this version supports v1`);
|
|
1020
|
-
if (this.plugins.some((existing) => existing.name === plugin.name)) throw new TypeError(`better-supabase: plugin "${plugin.name}" is already installed`);
|
|
1021
1429
|
return new BetterSupabase(this.schema, [...this.plugins, plugin], this.options, this.events);
|
|
1022
1430
|
}
|
|
1023
1431
|
/**
|
|
@@ -1076,11 +1484,41 @@ var BetterSupabase = class BetterSupabase {
|
|
|
1076
1484
|
}
|
|
1077
1485
|
connect(source, context = {}, options = {}) {
|
|
1078
1486
|
const client = isExecutor(source) ? void 0 : source;
|
|
1079
|
-
const base = options.executor ?? (isExecutor(source) ? source : postgrestExecutor(source));
|
|
1487
|
+
const base = options.executor ?? (isExecutor(source) ? source : postgrestExecutor(source, this.executorOptions()));
|
|
1080
1488
|
const recorder = new StatsRecorder(options.stats);
|
|
1081
|
-
|
|
1489
|
+
const tuning = {
|
|
1490
|
+
...options.timeout === void 0 ? {} : { timeout: options.timeout },
|
|
1491
|
+
...options.retry === void 0 ? {} : { retry: options.retry }
|
|
1492
|
+
};
|
|
1493
|
+
return this.#db(client, base, context, this.plugins, recorder, tuning);
|
|
1494
|
+
}
|
|
1495
|
+
/**
|
|
1496
|
+
* The `postgrestExecutor` options this definition implies
|
|
1497
|
+
* (`urlLengthLimit`, `postgrestVersion`), for adapters that build their
|
|
1498
|
+
* own executor and should chunk reads the same way.
|
|
1499
|
+
*/
|
|
1500
|
+
executorOptions() {
|
|
1501
|
+
const { urlLengthLimit, postgrestVersion } = this.options;
|
|
1502
|
+
return {
|
|
1503
|
+
...urlLengthLimit === void 0 ? {} : { urlLengthLimit },
|
|
1504
|
+
...postgrestVersion === void 0 ? {} : { postgrestVersion }
|
|
1505
|
+
};
|
|
1506
|
+
}
|
|
1507
|
+
/** The caller's context with every plugin's `context` hook applied. */
|
|
1508
|
+
#derive(given, plugins) {
|
|
1509
|
+
let context = given;
|
|
1510
|
+
for (const plugin of plugins) {
|
|
1511
|
+
if (!plugin.context) continue;
|
|
1512
|
+
try {
|
|
1513
|
+
context = plugin.context(context, { schema: this.meta });
|
|
1514
|
+
} catch (cause) {
|
|
1515
|
+
this.events.logger.error(`plugin "${plugin.name}" context threw`, { cause });
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
return context;
|
|
1082
1519
|
}
|
|
1083
|
-
#db(client, base,
|
|
1520
|
+
#db(client, base, given, plugins, recorder, tuning = {}, events = this.events) {
|
|
1521
|
+
const context = this.#derive(given, plugins);
|
|
1084
1522
|
let executor = base;
|
|
1085
1523
|
for (const plugin of plugins) if (plugin.wrapExecutor) executor = plugin.wrapExecutor(executor);
|
|
1086
1524
|
executor = recordStats(executor, recorder);
|
|
@@ -1093,10 +1531,90 @@ var BetterSupabase = class BetterSupabase {
|
|
|
1093
1531
|
context,
|
|
1094
1532
|
events,
|
|
1095
1533
|
errorMappers,
|
|
1096
|
-
now: this
|
|
1534
|
+
now: this.#now(),
|
|
1097
1535
|
maxRows: this.options.maxRows ?? 1e3,
|
|
1098
|
-
truncatedTables: this.#truncatedTables
|
|
1536
|
+
truncatedTables: this.#truncatedTables,
|
|
1537
|
+
tuning
|
|
1099
1538
|
});
|
|
1539
|
+
/**
|
|
1540
|
+
* `db.$search({ score: true })`: the ranked ids and scores from
|
|
1541
|
+
* `search_<table>_scores`, then those rows through the table (RLS and
|
|
1542
|
+
* `where` apply), best first, each with `$score`.
|
|
1543
|
+
*/
|
|
1544
|
+
const scoredSearch = async (table, fnArgs, args, hint) => {
|
|
1545
|
+
const [key, ...rest] = table.primaryKey;
|
|
1546
|
+
if (key === void 0 || rest.length > 0) return err(dbError("invalid_request", "db.$search({ score: true }) needs a table with a one-column primary key", { table: table.key }));
|
|
1547
|
+
const { builder } = runner.runtime;
|
|
1548
|
+
const scoresTable = {
|
|
1549
|
+
key: `${table.key}$scores`,
|
|
1550
|
+
name: `search_${table.name}_scores`,
|
|
1551
|
+
schema: table.schema,
|
|
1552
|
+
kind: "view",
|
|
1553
|
+
columns: {
|
|
1554
|
+
id: {
|
|
1555
|
+
db: "id",
|
|
1556
|
+
type: "jsonb",
|
|
1557
|
+
nullable: false,
|
|
1558
|
+
hasDefault: false
|
|
1559
|
+
},
|
|
1560
|
+
score: {
|
|
1561
|
+
db: "score",
|
|
1562
|
+
type: "float8",
|
|
1563
|
+
nullable: false,
|
|
1564
|
+
hasDefault: false
|
|
1565
|
+
}
|
|
1566
|
+
},
|
|
1567
|
+
primaryKey: [],
|
|
1568
|
+
uniqueKeys: {},
|
|
1569
|
+
relations: {},
|
|
1570
|
+
flags: {}
|
|
1571
|
+
};
|
|
1572
|
+
const scored = await runner.runInternal({
|
|
1573
|
+
kind: "select",
|
|
1574
|
+
table: scoresTable,
|
|
1575
|
+
selection: builder.selection(scoresTable, ["id", "score"], void 0),
|
|
1576
|
+
where: void 0,
|
|
1577
|
+
orderBy: [],
|
|
1578
|
+
limit: void 0,
|
|
1579
|
+
offset: void 0,
|
|
1580
|
+
count: void 0,
|
|
1581
|
+
head: false,
|
|
1582
|
+
single: void 0,
|
|
1583
|
+
source: {
|
|
1584
|
+
schema: table.schema,
|
|
1585
|
+
name: scoresTable.name,
|
|
1586
|
+
args: fnArgs
|
|
1587
|
+
}
|
|
1588
|
+
}, table, args.signal);
|
|
1589
|
+
if (!scored.ok) return err(hint(scored.error));
|
|
1590
|
+
const ranked = scored.data.rows.flatMap((row) => row["score"] === void 0 || row["score"] === null ? [] : [{
|
|
1591
|
+
id: row["id"],
|
|
1592
|
+
score: Number(row["score"])
|
|
1593
|
+
}]);
|
|
1594
|
+
if (ranked.length === 0) return ok([]);
|
|
1595
|
+
const byId = new Map(ranked.map((entry) => [String(entry.id), entry]));
|
|
1596
|
+
const op = {
|
|
1597
|
+
kind: "select",
|
|
1598
|
+
table,
|
|
1599
|
+
selection: builder.selection(table, args.select, args.include),
|
|
1600
|
+
where: builder.where(table, { AND: [...args.where === void 0 ? [] : [args.where], { [key]: { in: ranked.map((entry) => entry.id) } }] }),
|
|
1601
|
+
orderBy: [],
|
|
1602
|
+
limit: ranked.length,
|
|
1603
|
+
offset: void 0,
|
|
1604
|
+
count: void 0,
|
|
1605
|
+
head: false,
|
|
1606
|
+
single: void 0
|
|
1607
|
+
};
|
|
1608
|
+
const result = await runner.run(op, {}, args.signal);
|
|
1609
|
+
if (!result.ok) return result;
|
|
1610
|
+
return ok(result.data.rows.flatMap((row) => {
|
|
1611
|
+
const entry = byId.get(String(row[key]));
|
|
1612
|
+
return entry ? [{
|
|
1613
|
+
...row,
|
|
1614
|
+
$score: entry.score
|
|
1615
|
+
}] : [];
|
|
1616
|
+
}).toSorted((a, b) => b.$score - a.$score));
|
|
1617
|
+
};
|
|
1100
1618
|
const db = Object.create(this.#tablePrototype());
|
|
1101
1619
|
dbStates.set(db, {
|
|
1102
1620
|
runner,
|
|
@@ -1107,7 +1625,7 @@ var BetterSupabase = class BetterSupabase {
|
|
|
1107
1625
|
$client: client,
|
|
1108
1626
|
$executor: executor,
|
|
1109
1627
|
$context: context,
|
|
1110
|
-
$rpc: (name, ...rest) => rpc(executor, errorMappers, name, rest).map((data) => {
|
|
1628
|
+
$rpc: (name, ...rest) => rpc(this.schema.meta, executor, errorMappers, tuning, name, rest).map((data) => {
|
|
1111
1629
|
const registered = this.options.rpc?.[name];
|
|
1112
1630
|
if (registered) this.events.emit("rpc", {
|
|
1113
1631
|
name,
|
|
@@ -1115,12 +1633,15 @@ var BetterSupabase = class BetterSupabase {
|
|
|
1115
1633
|
context
|
|
1116
1634
|
});
|
|
1117
1635
|
return data;
|
|
1636
|
+
}).mapError((error) => {
|
|
1637
|
+
if (events.has("error")) events.emit("error", errorEvent(error));
|
|
1638
|
+
return error;
|
|
1118
1639
|
}),
|
|
1119
1640
|
$with: (extra) => this.#db(client, base, {
|
|
1120
|
-
...
|
|
1641
|
+
...given,
|
|
1121
1642
|
...extra
|
|
1122
|
-
}, plugins, recorder),
|
|
1123
|
-
$withoutPlugins: () => this.#db(client, base,
|
|
1643
|
+
}, plugins, recorder, tuning),
|
|
1644
|
+
$withoutPlugins: (options) => this.#db(client, base, given, keptPlugins(plugins, options?.keep ?? []), recorder, tuning),
|
|
1124
1645
|
$stats: () => recorder.snapshot(),
|
|
1125
1646
|
$table: (name) => {
|
|
1126
1647
|
if (!Object.hasOwn(this.meta.tables, name)) throw new TypeError(`better-supabase: unknown table "${name}". Known: ${Object.keys(this.meta.tables).join(", ")}`);
|
|
@@ -1140,10 +1661,21 @@ var BetterSupabase = class BetterSupabase {
|
|
|
1140
1661
|
const table = Object.hasOwn(this.meta.tables, name) ? this.meta.tables[name] : void 0;
|
|
1141
1662
|
if (!table) return err(dbError("invalid_request", `db.$search(): unknown table "${name}"`));
|
|
1142
1663
|
if (!base.functionSources) return err(dbError("invalid_request", `db.$search() reads from a function; the ${base.name} executor doesn't support that`, { table: table.key }));
|
|
1143
|
-
const query = vectorLiteral(args.vector);
|
|
1664
|
+
const query = (args.vector === void 0 || args.vector === null) && args.text !== void 0 ? null : vectorLiteral(args.vector ?? []);
|
|
1144
1665
|
const k = args.k ?? 10;
|
|
1145
|
-
if (query === void 0 || !Number.isInteger(k) || k < 1) return err(dbError("invalid_input", "db.$search() needs a vector of finite numbers and a positive integer k", { table: table.key }));
|
|
1666
|
+
if (query === void 0 || !Number.isInteger(k) || k < 1) return err(dbError("invalid_input", "db.$search() needs a vector of finite numbers (or text alone on a hybrid entry) and a positive integer k", { table: table.key }));
|
|
1146
1667
|
const { builder } = runner.runtime;
|
|
1668
|
+
const fnArgs = {
|
|
1669
|
+
query,
|
|
1670
|
+
k,
|
|
1671
|
+
...args.filter === void 0 ? {} : { filter: args.filter },
|
|
1672
|
+
...args.text === void 0 ? {} : { text_query: args.text }
|
|
1673
|
+
};
|
|
1674
|
+
const hint = (error) => error.code === "PGRST202" || error.code === "42883" ? {
|
|
1675
|
+
...error,
|
|
1676
|
+
hint: `Add "${table.schema}.${table.name}" to vectorSearch in better-supabase.config.ts (with prefilter or hybrid for filter and text) and run \`better-supabase sql sync\`.`
|
|
1677
|
+
} : error;
|
|
1678
|
+
if (args.score) return scoredSearch(table, fnArgs, args, hint);
|
|
1147
1679
|
const op = {
|
|
1148
1680
|
kind: "select",
|
|
1149
1681
|
table,
|
|
@@ -1158,18 +1690,12 @@ var BetterSupabase = class BetterSupabase {
|
|
|
1158
1690
|
source: {
|
|
1159
1691
|
schema: table.schema,
|
|
1160
1692
|
name: `search_${table.name}`,
|
|
1161
|
-
args:
|
|
1162
|
-
query,
|
|
1163
|
-
k
|
|
1164
|
-
}
|
|
1693
|
+
args: fnArgs
|
|
1165
1694
|
}
|
|
1166
1695
|
};
|
|
1167
1696
|
const result = await runner.run(op, {}, args.signal);
|
|
1168
1697
|
if (result.ok) return ok(result.data.rows);
|
|
1169
|
-
return result.error
|
|
1170
|
-
...result.error,
|
|
1171
|
-
hint: `Add "${table.schema}.${table.name}" to vectorSearch in better-supabase.config.ts and run \`better-supabase sql sync\`.`
|
|
1172
|
-
}) : result;
|
|
1698
|
+
return err(hint(result.error));
|
|
1173
1699
|
})
|
|
1174
1700
|
});
|
|
1175
1701
|
const many = (specs, signal, usePlugins) => AsyncResult.from(async () => {
|
|
@@ -1181,7 +1707,7 @@ var BetterSupabase = class BetterSupabase {
|
|
|
1181
1707
|
...base,
|
|
1182
1708
|
batch
|
|
1183
1709
|
}, specs.length) : void 0;
|
|
1184
|
-
const target = batching ? this.#db(client, batching.executor,
|
|
1710
|
+
const target = batching ? this.#db(client, batching.executor, given, active, recorder, tuning) : usePlugins ? db : this.#db(client, base, given, NO_PLUGINS, recorder, tuning);
|
|
1185
1711
|
const results = await Promise.all(specs.map(async (spec) => {
|
|
1186
1712
|
try {
|
|
1187
1713
|
return await runSpec(target, spec, signal);
|
|
@@ -1200,8 +1726,9 @@ var BetterSupabase = class BetterSupabase {
|
|
|
1200
1726
|
const problems = checkParams(set, values);
|
|
1201
1727
|
if (problems.length > 0) return err(dbError("invalid_request", `db.$many(${set.name}): ${problems.join(", ")}`));
|
|
1202
1728
|
const keys = Object.keys(set.specs);
|
|
1203
|
-
const bound = bindParams(set, values
|
|
1729
|
+
const { specs: bound, noCaller } = bindParams(set, values, context);
|
|
1204
1730
|
if (base.batch || !executor.rpc) {
|
|
1731
|
+
if (noCaller) return err(noCaller);
|
|
1205
1732
|
const result = await many(keys.map((key) => bound[key]), signal, false);
|
|
1206
1733
|
if (!result.ok) return result;
|
|
1207
1734
|
return ok(Object.fromEntries(keys.map((key, i) => [key, result.data[i]])));
|
|
@@ -1231,24 +1758,28 @@ var BetterSupabase = class BetterSupabase {
|
|
|
1231
1758
|
*/
|
|
1232
1759
|
async #decodeReadSet(client, context, set, specs, data) {
|
|
1233
1760
|
const payload = data ?? {};
|
|
1761
|
+
let rows = [];
|
|
1762
|
+
let count = null;
|
|
1763
|
+
const decoder = this.#db(client, {
|
|
1764
|
+
name: "read-set",
|
|
1765
|
+
execute: (op) => {
|
|
1766
|
+
if (op.kind === "select" && op.single) {
|
|
1767
|
+
if (rows.length > 1) return Promise.resolve(err(dbError("multiple_rows", `Expected one ${op.table.key} row`)));
|
|
1768
|
+
if (rows.length === 0 && op.single === "one") return Promise.resolve(err(dbError("not_found", `No ${op.table.key} row matched`)));
|
|
1769
|
+
}
|
|
1770
|
+
return Promise.resolve(ok({
|
|
1771
|
+
rows,
|
|
1772
|
+
count
|
|
1773
|
+
}));
|
|
1774
|
+
}
|
|
1775
|
+
}, context, NO_PLUGINS, new StatsRecorder(), {}, this.#decodeEvents ??= new EventHub(this.events.logger));
|
|
1234
1776
|
const out = {};
|
|
1235
1777
|
for (const [key, spec] of Object.entries(specs)) {
|
|
1236
1778
|
const entry = payload[key];
|
|
1237
1779
|
if (!entry) return err(dbError("unexpected", `${set.functionName}() returned no "${key}". Run \`better-supabase gen\` and migrate.`));
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
execute: (op) => {
|
|
1242
|
-
if (op.kind === "select" && op.single) {
|
|
1243
|
-
if (rows.length > 1) return Promise.resolve(err(dbError("multiple_rows", `Expected one ${op.table.key} row`)));
|
|
1244
|
-
if (rows.length === 0 && op.single === "one") return Promise.resolve(err(dbError("not_found", `No ${op.table.key} row matched`)));
|
|
1245
|
-
}
|
|
1246
|
-
return Promise.resolve(ok({
|
|
1247
|
-
rows,
|
|
1248
|
-
count: entry.count ?? null
|
|
1249
|
-
}));
|
|
1250
|
-
}
|
|
1251
|
-
}, context, [], new StatsRecorder(), this.#decodeEvents ??= new EventHub(this.events.logger)), spec, void 0);
|
|
1780
|
+
rows = entry.rows ?? [];
|
|
1781
|
+
count = entry.count ?? null;
|
|
1782
|
+
const result = await runSpec(decoder, spec, void 0);
|
|
1252
1783
|
if (!result.ok) return result;
|
|
1253
1784
|
out[key] = result.data;
|
|
1254
1785
|
}
|
|
@@ -1329,18 +1860,44 @@ function runSpec(db, spec, signal) {
|
|
|
1329
1860
|
}
|
|
1330
1861
|
return method(...args);
|
|
1331
1862
|
}
|
|
1332
|
-
function rpc(executor, errorMappers, name, rest) {
|
|
1863
|
+
function rpc(meta, executor, errorMappers, defaults, name, rest) {
|
|
1333
1864
|
const [args, options] = rest;
|
|
1334
1865
|
return AsyncResult.from(async () => {
|
|
1335
1866
|
if (!executor.rpc) return err(dbError("invalid_request", `Executor "${executor.name}" does not support rpc()`));
|
|
1867
|
+
const tuning = {
|
|
1868
|
+
...defaults,
|
|
1869
|
+
...options?.timeout === void 0 ? {} : { timeout: options.timeout },
|
|
1870
|
+
...options?.retry === void 0 ? {} : { retry: options.retry }
|
|
1871
|
+
};
|
|
1872
|
+
const invalid = invalidTuning(tuning);
|
|
1873
|
+
if (invalid) return err(dbError("invalid_request", invalid));
|
|
1874
|
+
const limit = deadline(options?.signal, tuning.timeout);
|
|
1875
|
+
const schema = options?.schema ?? "public";
|
|
1876
|
+
const fn = rpcFunction(meta, name, schema, args ?? {});
|
|
1336
1877
|
const context = {
|
|
1337
|
-
schema
|
|
1878
|
+
schema,
|
|
1338
1879
|
errorMappers,
|
|
1339
|
-
...
|
|
1880
|
+
...limit.signal ? { signal: limit.signal } : {},
|
|
1881
|
+
...tuning.retry === void 0 ? {} : { retry: tuning.retry },
|
|
1882
|
+
...fn ? { function: fn } : {}
|
|
1340
1883
|
};
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1884
|
+
let result;
|
|
1885
|
+
try {
|
|
1886
|
+
result = await executor.rpc(name, args ?? {}, context);
|
|
1887
|
+
} finally {
|
|
1888
|
+
limit.clear();
|
|
1889
|
+
}
|
|
1890
|
+
if (!result.ok && limit.timedOut()) return err(dbError("timeout", `The request timed out after ${tuning.timeout} ms`));
|
|
1891
|
+
if (!result.ok) return result;
|
|
1892
|
+
let data = result.data;
|
|
1893
|
+
if (options?.raw !== true) try {
|
|
1894
|
+
data = decodeRpcResult(meta, fn, data);
|
|
1895
|
+
} catch (cause) {
|
|
1896
|
+
if (cause instanceof DbException) return err(cause.error);
|
|
1897
|
+
throw cause;
|
|
1898
|
+
}
|
|
1899
|
+
if (!options?.returns) return ok(data);
|
|
1900
|
+
const checked = await validate(options.returns, data, `${name}() result`);
|
|
1344
1901
|
return checked.ok ? ok(checked.data) : checked;
|
|
1345
1902
|
});
|
|
1346
1903
|
}
|