better-supabase 0.5.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (536) hide show
  1. package/README.md +187 -46
  2. package/dist/access-sql-B0dF-SoF.js +181 -0
  3. package/dist/{actor-DaJjqD5R.d.ts → actor-CQTlc1Hh.d.ts} +1 -1
  4. package/dist/adapter-Bc1o3zyy.js +1106 -0
  5. package/dist/agents-CVHGd7It.d.ts +94 -0
  6. package/dist/ai-cache-CBWs1W0k.js +80 -0
  7. package/dist/ai-cache-DaDu_G5L.d.ts +64 -0
  8. package/dist/ai-chat-7amvXjmQ.d.ts +590 -0
  9. package/dist/ai-chat-B24UI962.js +743 -0
  10. package/dist/ai-files-CSPNswUY.js +319 -0
  11. package/dist/ai-sdk/agents/index.d.ts +74 -0
  12. package/dist/ai-sdk/agents/index.js +159 -0
  13. package/dist/ai-sdk/batches/index.d.ts +74 -0
  14. package/dist/ai-sdk/batches/index.js +180 -0
  15. package/dist/ai-sdk/cache/index.d.ts +38 -0
  16. package/dist/ai-sdk/cache/index.js +127 -0
  17. package/dist/ai-sdk/chat/index.d.ts +2 -0
  18. package/dist/ai-sdk/chat/index.js +246 -0
  19. package/dist/ai-sdk/embeddings/index.d.ts +3 -0
  20. package/dist/ai-sdk/embeddings/index.js +2 -0
  21. package/dist/ai-sdk/files/index.d.ts +61 -0
  22. package/dist/ai-sdk/files/index.js +111 -0
  23. package/dist/ai-sdk/index.d.ts +145 -0
  24. package/dist/ai-sdk/index.js +174 -0
  25. package/dist/ai-sdk/mcp/index.d.ts +102 -0
  26. package/dist/ai-sdk/mcp/index.js +362 -0
  27. package/dist/ai-sdk/memory/index.d.ts +67 -0
  28. package/dist/ai-sdk/memory/index.js +175 -0
  29. package/dist/ai-sdk/react/index.d.ts +2 -0
  30. package/dist/ai-sdk/react/index.js +3 -0
  31. package/dist/ai-sdk/react/server.d.ts +6 -0
  32. package/dist/ai-sdk/react/server.js +7 -0
  33. package/dist/ai-sdk/workflow/index.d.ts +249 -0
  34. package/dist/ai-sdk/workflow/index.js +575 -0
  35. package/dist/ai-sdk/workflow/react/index.d.ts +20 -0
  36. package/dist/ai-sdk/workflow/react/index.js +66 -0
  37. package/dist/ai-sdk/workflow/react/server.d.ts +10 -0
  38. package/dist/ai-sdk/workflow/react/server.js +12 -0
  39. package/dist/ai-tasks-Cd1HMFvB.d.ts +131 -0
  40. package/dist/announcements-CiyOs-xP.js +107 -0
  41. package/dist/announcements-ZRGnScWI.d.ts +72 -0
  42. package/dist/api-keys-rCGtKaZA.d.ts +156 -0
  43. package/dist/assistant-DwdpDH1q.d.ts +147 -0
  44. package/dist/astro/index.d.ts +86 -0
  45. package/dist/astro/index.js +93 -0
  46. package/dist/attributes-5dYul0u0.js +13 -0
  47. package/dist/auth-link-BjFPqwLz.d.ts +97 -0
  48. package/dist/auth-link-DrDX9KOT.js +114 -0
  49. package/dist/authorization-BFCqamMs.d.ts +172 -0
  50. package/dist/before-route-CnR0C0Jr.js +30 -0
  51. package/dist/bind-Bu_ZNa3W.d.ts +62 -0
  52. package/dist/bind-l4kAvYSv.js +97 -0
  53. package/dist/block-events-CrT8r7Fe.js +76 -0
  54. package/dist/block-fields-GFkxl4dP.js +49 -0
  55. package/dist/block-fields-SJ6fEf3o.d.ts +31 -0
  56. package/dist/block-helpers-CKtbFcRv.d.ts +37 -0
  57. package/dist/block-helpers-DWHxHsEQ.js +190 -0
  58. package/dist/block-hooks-BmjMyXTa.js +114 -0
  59. package/dist/block-hooks-plbZ0AbJ.d.ts +107 -0
  60. package/dist/{kit-transport-DJlHQUBU.js → block-transport-BLr-ZgLc.js} +11 -7
  61. package/dist/block-transport-DvaoPuZ9.d.ts +48 -0
  62. package/dist/blocks/agents/index.d.ts +3 -0
  63. package/dist/blocks/agents/index.js +123 -0
  64. package/dist/blocks/ai-cache/index.d.ts +3 -0
  65. package/dist/blocks/ai-cache/index.js +3 -0
  66. package/dist/blocks/ai-chat/index.d.ts +31 -0
  67. package/dist/blocks/ai-chat/index.js +5 -0
  68. package/dist/blocks/ai-chat/react/index.d.ts +77 -0
  69. package/dist/blocks/ai-chat/react/index.js +387 -0
  70. package/dist/blocks/ai-chat/react/server.d.ts +16 -0
  71. package/dist/blocks/ai-chat/react/server.js +14 -0
  72. package/dist/blocks/ai-files/index.d.ts +14 -0
  73. package/dist/blocks/ai-files/index.js +3 -0
  74. package/dist/blocks/ai-providers/index.d.ts +7 -0
  75. package/dist/blocks/ai-providers/index.js +211 -0
  76. package/dist/blocks/ai-tasks/index.d.ts +3 -0
  77. package/dist/blocks/ai-tasks/index.js +203 -0
  78. package/dist/blocks/announcements/index.d.ts +3 -0
  79. package/dist/blocks/announcements/index.js +3 -0
  80. package/dist/blocks/announcements/react/index.d.ts +31 -0
  81. package/dist/blocks/announcements/react/index.js +86 -0
  82. package/dist/blocks/announcements/react/server.d.ts +6 -0
  83. package/dist/blocks/announcements/react/server.js +7 -0
  84. package/dist/blocks/api-keys/index.d.ts +35 -0
  85. package/dist/blocks/api-keys/index.js +334 -0
  86. package/dist/blocks/attachments/index.d.ts +210 -0
  87. package/dist/blocks/attachments/index.js +222 -0
  88. package/dist/blocks/audit/index.d.ts +366 -0
  89. package/dist/blocks/audit/index.js +714 -0
  90. package/dist/blocks/billing/index.d.ts +265 -0
  91. package/dist/blocks/billing/index.js +400 -0
  92. package/dist/blocks/comments/index.d.ts +200 -0
  93. package/dist/blocks/comments/index.js +207 -0
  94. package/dist/blocks/connectors/index.d.ts +3 -0
  95. package/dist/blocks/connectors/index.js +164 -0
  96. package/dist/blocks/data-lifecycle/index.d.ts +251 -0
  97. package/dist/blocks/data-lifecycle/index.js +353 -0
  98. package/dist/blocks/entitlements/index.d.ts +14 -0
  99. package/dist/blocks/entitlements/index.js +25 -0
  100. package/dist/blocks/flags/index.d.ts +226 -0
  101. package/dist/blocks/flags/index.js +282 -0
  102. package/dist/blocks/inbox/index.d.ts +6 -0
  103. package/dist/blocks/inbox/index.js +499 -0
  104. package/dist/blocks/inbox/react/index.d.ts +2 -0
  105. package/dist/blocks/inbox/react/index.js +225 -0
  106. package/dist/blocks/inbox/react/server.d.ts +10 -0
  107. package/dist/blocks/inbox/react/server.js +12 -0
  108. package/dist/blocks/index.d.ts +65 -0
  109. package/dist/blocks/index.js +77 -0
  110. package/dist/blocks/jobs/index.d.ts +297 -0
  111. package/dist/blocks/jobs/index.js +1051 -0
  112. package/dist/blocks/knowledge/index.d.ts +3 -0
  113. package/dist/blocks/knowledge/index.js +3 -0
  114. package/dist/blocks/memory/index.d.ts +8 -0
  115. package/dist/blocks/memory/index.js +289 -0
  116. package/dist/blocks/notifications/index.d.ts +297 -0
  117. package/dist/blocks/notifications/index.js +425 -0
  118. package/dist/blocks/notifications/react/index.d.ts +44 -0
  119. package/dist/blocks/notifications/react/index.js +67 -0
  120. package/dist/blocks/notifications/react/server.d.ts +6 -0
  121. package/dist/blocks/notifications/react/server.js +7 -0
  122. package/dist/blocks/onboarding/index.d.ts +3 -0
  123. package/dist/blocks/onboarding/index.js +64 -0
  124. package/dist/blocks/onboarding/react/index.d.ts +28 -0
  125. package/dist/blocks/onboarding/react/index.js +78 -0
  126. package/dist/blocks/onboarding/react/server.d.ts +7 -0
  127. package/dist/blocks/onboarding/react/server.js +7 -0
  128. package/dist/blocks/organizations/index.d.ts +241 -0
  129. package/dist/blocks/organizations/index.js +400 -0
  130. package/dist/blocks/outbox/index.d.ts +3 -0
  131. package/dist/blocks/outbox/index.js +266 -0
  132. package/dist/blocks/profiles/index.d.ts +40 -0
  133. package/dist/blocks/profiles/index.js +28 -0
  134. package/dist/blocks/push/index.d.ts +185 -0
  135. package/dist/blocks/push/index.js +258 -0
  136. package/dist/blocks/settings/index.d.ts +89 -0
  137. package/dist/blocks/settings/index.js +104 -0
  138. package/dist/blocks/sso/index.d.ts +198 -0
  139. package/dist/blocks/sso/index.js +1297 -0
  140. package/dist/blocks/usage/index.d.ts +4 -0
  141. package/dist/blocks/usage/index.js +233 -0
  142. package/dist/blocks/waitlist/index.d.ts +117 -0
  143. package/dist/blocks/waitlist/index.js +132 -0
  144. package/dist/blocks/webhooks/index.d.ts +304 -0
  145. package/dist/{webhooks → blocks/webhooks}/index.js +468 -148
  146. package/dist/blocks/workflow-builder/index.d.ts +21 -0
  147. package/dist/blocks/workflow-builder/index.js +5 -0
  148. package/dist/blocks/workflow-builder/react/index.d.ts +47 -0
  149. package/dist/blocks/workflow-builder/react/index.js +119 -0
  150. package/dist/blocks/workflow-builder/react/server.d.ts +8 -0
  151. package/dist/blocks/workflow-builder/react/server.js +11 -0
  152. package/dist/blocks/workflows/index.d.ts +3 -0
  153. package/dist/blocks/workflows/index.js +3 -0
  154. package/dist/blocks/workflows/react/index.d.ts +47 -0
  155. package/dist/blocks/workflows/react/index.js +137 -0
  156. package/dist/blocks/workflows/react/server.d.ts +8 -0
  157. package/dist/blocks/workflows/react/server.js +11 -0
  158. package/dist/{index-SaTsEfGP.d.ts → bucket-Cl46E3jS.d.ts} +134 -91
  159. package/dist/{simplify-_0oUKqCd.js → build-BXIzE6Xv.js} +222 -124
  160. package/dist/{channel-FQW-CnGR.d.ts → channel-_2Mx1Oyu.d.ts} +2 -2
  161. package/dist/channels-CkgQ_X60.js +114 -0
  162. package/dist/chat-sdk/index.d.ts +303 -0
  163. package/dist/chat-sdk/index.js +733 -0
  164. package/dist/chat-sdk/react/index.d.ts +2 -0
  165. package/dist/chat-sdk/react/index.js +3 -0
  166. package/dist/chat-sdk/react/server.d.ts +3 -0
  167. package/dist/chat-sdk/react/server.js +2 -0
  168. package/dist/claims-DDBQT6BK.js +61 -0
  169. package/dist/{claims-BAf6c7is.js → claims-PqzCxaTD.js} +39 -2
  170. package/dist/cli/bin.js +1 -1
  171. package/dist/cli/{codemod-DqV7612m.js → codemod-Bl_tQpHn.js} +105 -2
  172. package/dist/cli/config-B9HkL8nF.js +2 -0
  173. package/dist/cli/config-DU7EJImt.js +49 -0
  174. package/dist/cli/config-NiPxAmUF.js +1077 -0
  175. package/dist/cli/{dist-xn4wlboc.js → dist-DRAVaE6w.js} +111 -1
  176. package/dist/cli/{doctor-C_A-KEAz.js → doctor-B4JOm_ox.js} +991 -317
  177. package/dist/cli/{env-DmKv_G4A.js → env-CJLbUVPB.js} +1 -1
  178. package/dist/cli/{env-jIFUADLY.js → env-qXgyMV6r.js} +2 -2
  179. package/dist/cli/fresh-import-BeYf9I3x.js +40 -0
  180. package/dist/cli/gen-BGLb_zou.js +3100 -0
  181. package/dist/cli/gen-DAH8FM2W.js +2 -0
  182. package/dist/cli/index.d.ts +44 -5
  183. package/dist/cli/index.js +7 -7
  184. package/dist/cli/{init-DMa6M7hV.js → init-BIIwclPg.js} +242 -27
  185. package/dist/cli/{introspect-BKlaIu_M.js → introspect-DNUTuNvb.js} +5 -5
  186. package/dist/cli/{io-k41_z-jT.js → io-DI1mTdSA.js} +12 -3
  187. package/dist/cli/{keys-ByKHnvP9.js → keys-BGCnnb-s.js} +8 -6
  188. package/dist/cli/{ohash-D7bG_EOb.js → ohash-BjQY1cBb.js} +1 -1
  189. package/dist/cli/{openapi-Cp5Fyta-.js → openapi-BlRJ18s3.js} +2 -2
  190. package/dist/cli/{project-B_GeXyHh.js → project-DZRaBaY7.js} +11 -6
  191. package/dist/cli/read-sets-CETOSFx4.js +223 -0
  192. package/dist/cli/{run-Bo_NLT5n.js → run-DNWxHynX.js} +33 -23
  193. package/dist/cli/{seed-CUlqWh-8.js → seed-DQzqT7LP.js} +8 -6
  194. package/dist/cli/{skills-LJJIhLFR.js → skills-QQs4q68J.js} +3 -2
  195. package/dist/cli/sql-D0GUtUPp.js +536 -0
  196. package/dist/cli/{config-CPVpXP5I.js → supabase-toml-B-bIukQF.js} +72 -942
  197. package/dist/cli/typegen-version-DeFbtzYI.js +8 -0
  198. package/dist/cli/{version-BCtlgDQx.js → version-hr88OZG0.js} +1 -1
  199. package/dist/client/index.d.ts +3 -2
  200. package/dist/client/index.js +11 -71
  201. package/dist/client/native/index.d.ts +228 -0
  202. package/dist/client/native/index.js +361 -0
  203. package/dist/client-CI0Z2zWX.js +277 -0
  204. package/dist/cloud-event-BnmD5fb9.js +46 -0
  205. package/dist/cloud-event-C1JCc1bH.d.ts +50 -0
  206. package/dist/{compiler-BXH_aZ7N.d.ts → compiler-DY_wkj4R.d.ts} +2 -2
  207. package/dist/compose-BIBNgAnq.js +53 -0
  208. package/dist/composite-Bt1YK3Ke.d.ts +146 -0
  209. package/dist/composite-DhE66P5u.js +130 -0
  210. package/dist/config/index.d.ts +6 -4
  211. package/dist/config/index.js +5 -5
  212. package/dist/{config-Bv7gvfzC.d.ts → config-D44Y7PAv.d.ts} +406 -214
  213. package/dist/{config-DreERlKo.js → config-Dn7F5k9A.js} +62 -14
  214. package/dist/connector-Dv8kK0MO.d.ts +107 -0
  215. package/dist/connectors-hkLCwyEz.d.ts +120 -0
  216. package/dist/context-BCrWe7ow.d.ts +237 -0
  217. package/dist/credentials/index.d.ts +31 -0
  218. package/dist/credentials/index.js +168 -0
  219. package/dist/cron-DVPUg5k3.js +145 -0
  220. package/dist/csv-CPAzEmB6.js +25 -0
  221. package/dist/db-exception-CnWcYPxL.js +15 -0
  222. package/dist/{define-cNKzqwL_.js → define-B-TVjC25.js} +784 -227
  223. package/dist/{define-Bp_BZa5h.d.ts → define-CJJkkr1-.d.ts} +353 -61
  224. package/dist/edge/index.d.ts +69 -11
  225. package/dist/edge/index.js +191 -75
  226. package/dist/elysia/index.d.ts +59 -0
  227. package/dist/elysia/index.js +62 -0
  228. package/dist/embeddings-4ZvFzjsU.js +127 -0
  229. package/dist/embeddings-C9KGQnXt.d.ts +68 -0
  230. package/dist/{refresh-CFPX0Qft.d.ts → ended-jLfvw8h-.d.ts} +20 -2
  231. package/dist/{entitlements-BiJZ4t49.d.ts → entitlements-DHrY2UDZ.d.ts} +16 -7
  232. package/dist/entitlements-DRl6ZJUm.js +24 -0
  233. package/dist/envelope-DqnYGRw7.js +47 -0
  234. package/dist/{errors-DtwXa6b8.js → errors-B11Duf73.js} +82 -13
  235. package/dist/errors-DLjJHPLK.js +44 -0
  236. package/dist/escape-like-DHfx6jRr.js +7 -0
  237. package/dist/escape-like-ImTK0ps_.d.ts +15 -0
  238. package/dist/eve/index.d.ts +220 -0
  239. package/dist/eve/index.js +504 -0
  240. package/dist/eve-gT2Fpjut.d.ts +151 -0
  241. package/dist/events/index.d.ts +4 -3
  242. package/dist/events/index.js +9 -50
  243. package/dist/events-DWDhx77e.d.ts +549 -0
  244. package/dist/executor-Bq28caBo.js +718 -0
  245. package/dist/executor-C-R4pucm.js +83 -0
  246. package/dist/executor-CaWigTyR.d.ts +148 -0
  247. package/dist/executor-D14tGopJ.d.ts +36 -0
  248. package/dist/{executor-Cghdstwu.d.ts → executor-DbvExCFC.d.ts} +7 -1
  249. package/dist/{sql-Coh6n4cC.js → executor-De1Of3m3.js} +210 -11
  250. package/dist/executor-DvsBbNBS.d.ts +261 -0
  251. package/dist/expo/index.d.ts +79 -0
  252. package/dist/expo/index.js +129 -0
  253. package/dist/expo-sqlite/index.d.ts +58 -0
  254. package/dist/expo-sqlite/index.js +104 -0
  255. package/dist/field-errors-BFOa7WhB.d.ts +99 -0
  256. package/dist/field-errors-VF1yb8yI.js +13 -0
  257. package/dist/framework-CONDyPYx.js +51 -0
  258. package/dist/framework-DuVb4Xa8.d.ts +25 -0
  259. package/dist/gateway-C1ssRHnf.d.ts +130 -0
  260. package/dist/graph-BGyLLFLX.js +265 -0
  261. package/dist/h3/index.d.ts +59 -0
  262. package/dist/h3/index.js +55 -0
  263. package/dist/h3/v1/index.d.ts +63 -0
  264. package/dist/h3/v1/index.js +49 -0
  265. package/dist/history-BZih6SFP.js +64 -0
  266. package/dist/hono/index.d.ts +56 -7
  267. package/dist/hono/index.js +97 -45
  268. package/dist/{react-C_s7kiNz.js → hooks-1BTCJsiw.js} +104 -133
  269. package/dist/http-Cv4T29xh.js +40 -0
  270. package/dist/http-DdYadv-o.js +126 -0
  271. package/dist/image-url-pIVlO6R1.js +41 -0
  272. package/dist/{impersonation-BgSHAYLf.js → impersonation-DcqaTBHx.js} +21 -6
  273. package/dist/inbox-i7E1ppo6.d.ts +384 -0
  274. package/dist/index-ACiNPN4Z.d.ts +74 -0
  275. package/dist/{index-DgILJRXj.d.ts → index-Bepi-Hgg.d.ts} +91 -28
  276. package/dist/index-BkWT_uBO.d.ts +51 -0
  277. package/dist/index-BpFYMsi0.d.ts +53 -0
  278. package/dist/{index-C7f8cOBM.d.ts → index-Bxih3l0u.d.ts} +2 -2
  279. package/dist/index-CaxrMD1A.d.ts +1 -0
  280. package/dist/index-ClmjK_o-.d.ts +55 -0
  281. package/dist/index-CtuakVRc.d.ts +267 -0
  282. package/dist/index-D48jVS-N.d.ts +246 -0
  283. package/dist/index-DDrYaUcq.d.ts +138 -0
  284. package/dist/index-DQh4VCc9.d.ts +98 -0
  285. package/dist/{live-D9W2M5aO.d.ts → index-DunNRdnT.d.ts} +136 -38
  286. package/dist/index.d.ts +65 -18
  287. package/dist/index.js +42 -14
  288. package/dist/invalidate-BBqhpxyB.d.ts +19 -0
  289. package/dist/json-CEnpTHlZ.js +16 -0
  290. package/dist/json-schema-CvER4kgT.js +502 -0
  291. package/dist/keys-4MnkWTTh.js +35 -0
  292. package/dist/kit-B5tid-q5.d.ts +60 -0
  293. package/dist/kit-Fm-Fv7q5.js +78 -0
  294. package/dist/knowledge-BXBbT0Tr.d.ts +176 -0
  295. package/dist/knowledge-CDmiMLew.js +255 -0
  296. package/dist/lint/index.d.ts +1 -1
  297. package/dist/lint/index.js +37 -0
  298. package/dist/list/index.d.ts +3 -2
  299. package/dist/list/index.js +1 -444
  300. package/dist/{index-fag8VJZ2.d.ts → list-query-BRt-zDF7.d.ts} +20 -12
  301. package/dist/list-query-gl808ac1.js +459 -0
  302. package/dist/{live-CdJBOc4f.js → live-CTAZQkwl.js} +99 -14
  303. package/dist/logger-DWVYUmwi.d.ts +18 -0
  304. package/dist/mcp/index.d.ts +38 -11
  305. package/dist/mcp/index.js +82 -46
  306. package/dist/mcp/sdk/index.d.ts +105 -0
  307. package/dist/mcp/sdk/index.js +126 -0
  308. package/dist/message-CaKlqdsX.js +219 -0
  309. package/dist/message-CfDoR0Y6.d.ts +94 -0
  310. package/dist/messages-B9-5887d.js +715 -0
  311. package/dist/messages-DYP0sUTe.d.ts +59 -0
  312. package/dist/mfa-Daak8ukG.d.ts +54 -0
  313. package/dist/modules-DpPwzC7E.d.ts +192 -0
  314. package/dist/modules-dxrVK3ID.js +228 -0
  315. package/dist/nestjs/index.d.ts +68 -0
  316. package/dist/nestjs/index.js +164 -0
  317. package/dist/next/client/index.d.ts +35 -0
  318. package/dist/next/client/index.js +36 -0
  319. package/dist/next/image/index.js +3 -24
  320. package/dist/next/index.d.ts +150 -51
  321. package/dist/next/index.js +261 -107
  322. package/dist/node/index.d.ts +4 -0
  323. package/dist/node/index.js +210 -0
  324. package/dist/node-headers-AO06VhqH.d.ts +24 -0
  325. package/dist/node-headers-C71zNQHe.js +55 -0
  326. package/dist/nuxt/index.d.ts +60 -0
  327. package/dist/nuxt/index.js +64 -0
  328. package/dist/onboarding-BZGHYJks.d.ts +62 -0
  329. package/dist/openapi/index.d.ts +1 -1
  330. package/dist/openapi/index.js +3 -3
  331. package/dist/orpc/index.d.ts +70 -11
  332. package/dist/orpc/index.js +73 -24
  333. package/dist/otel/index.d.ts +7 -7
  334. package/dist/otel/index.js +87 -57
  335. package/dist/outbox-Cq7pPYvl.d.ts +161 -0
  336. package/dist/{plugin-o144f322.d.ts → plugin-FGY8UhYm.d.ts} +30 -10
  337. package/dist/plugin-tfXW1-qO.js +45 -0
  338. package/dist/plugins/actor/index.d.ts +2 -2
  339. package/dist/plugins/actor/index.js +3 -3
  340. package/dist/plugins/rules/index.d.ts +11 -4
  341. package/dist/plugins/rules/index.js +40 -13
  342. package/dist/plugins/soft-delete/index.d.ts +5 -4
  343. package/dist/plugins/soft-delete/index.js +10 -5
  344. package/dist/plugins/tenant/index.d.ts +2 -2
  345. package/dist/plugins/tenant/index.js +18 -11
  346. package/dist/plugins/timestamps/index.d.ts +5 -3
  347. package/dist/plugins/timestamps/index.js +6 -4
  348. package/dist/plugins/validation/index.d.ts +2 -2
  349. package/dist/plugins/validation/index.js +10 -6
  350. package/dist/{pool-C9voM4Kw.d.ts → pool-CAu2nLrL.d.ts} +2 -2
  351. package/dist/postgres/index.d.ts +4 -4
  352. package/dist/postgres/index.js +1 -2
  353. package/dist/{postgrest-CruYKAvV.d.ts → postgrest-BLVdEnfe.d.ts} +13 -3
  354. package/dist/powersync/index.d.ts +43 -0
  355. package/dist/powersync/index.js +199 -0
  356. package/dist/powersync/react/index.d.ts +87 -0
  357. package/dist/powersync/react/index.js +108 -0
  358. package/dist/{problem-BW1KhzSG.js → problem-BreOl8b8.js} +14 -3
  359. package/dist/{problem-Blxe8S31.d.ts → problem-DD8LZFjc.d.ts} +21 -3
  360. package/dist/provider-BH5UWZJ6.d.ts +113 -0
  361. package/dist/provider-Di3sRutW.js +57 -0
  362. package/dist/query/index.d.ts +4 -2
  363. package/dist/query/index.js +4 -3
  364. package/dist/{query-CCbo44lG.js → query-BQ-NaZon.js} +141 -24
  365. package/dist/{queue-BYUCjr59.d.ts → queue-CLJurhdy.d.ts} +258 -83
  366. package/dist/react/index.d.ts +11 -7
  367. package/dist/react/index.js +7 -3
  368. package/dist/react/native/index.d.ts +116 -0
  369. package/dist/react/native/index.js +130 -0
  370. package/dist/react/server.d.ts +28 -10
  371. package/dist/react/server.js +22 -5
  372. package/dist/react/session.d.ts +2 -2
  373. package/dist/react-4ZqkP8da.js +79 -0
  374. package/dist/react-F80mF4-t.js +409 -0
  375. package/dist/react-router/index.d.ts +83 -0
  376. package/dist/react-router/index.js +89 -0
  377. package/dist/react-topic-seAWjL3_.js +38 -0
  378. package/dist/{read-set-DQFt1N_Y.js → read-set-DuKWC9Mj.js} +67 -25
  379. package/dist/realtime/index.d.ts +4 -5
  380. package/dist/realtime/index.js +144 -82
  381. package/dist/refusal-CeJWxmkH.js +61 -0
  382. package/dist/refusal-D1rgbzNq.d.ts +15 -0
  383. package/dist/replicas-CwrYp5Zj.js +94 -0
  384. package/dist/{view-Bn6HNKUe.js → resolve-D_IcnvFd.js} +248 -240
  385. package/dist/{impersonation-BmePsuxz.d.ts → resolve-KW8nCeL6.d.ts} +29 -69
  386. package/dist/{resource-mqfJW4YF.js → resource-BsvzCMlX.js} +4 -4
  387. package/dist/{resource-DNRFP7KR.d.ts → resource-D6Uc7Sk7.d.ts} +5 -5
  388. package/dist/respond-BUgsXNgk.js +91 -0
  389. package/dist/respond-DoBijysA.d.ts +93 -0
  390. package/dist/result-D7y2fT87.d.ts +282 -0
  391. package/dist/{result-BKiliPY7.js → result-DzUbqgdW.js} +27 -2
  392. package/dist/run-state-CPo-1X2B.d.ts +12 -0
  393. package/dist/run-state-CgBKzYMW.js +13 -0
  394. package/dist/search-CUWCRYKL.js +9 -0
  395. package/dist/server/index.d.ts +143 -22
  396. package/dist/server/index.js +46 -14
  397. package/dist/{respond-BR1fJWOB.d.ts → server-CeVeeXwz.d.ts} +224 -85
  398. package/dist/session-ChiXDZdZ.d.ts +72 -0
  399. package/dist/shared-CBxosKK3.js +75 -0
  400. package/dist/{shared-D1dRUrAg.js → shared-CxWmcyqB.js} +2 -1
  401. package/dist/shared-DDSjEGDR.d.ts +11 -0
  402. package/dist/sign-in-BCV5S2WZ.d.ts +49 -0
  403. package/dist/sign-in-Cb1mwv6X.js +86 -0
  404. package/dist/{signers-Cc6r98SW.d.ts → signers-4y62_VIi.d.ts} +13 -9
  405. package/dist/simplify-DDO0j0LI.js +83 -0
  406. package/dist/solid/index.d.ts +131 -0
  407. package/dist/solid/index.js +344 -0
  408. package/dist/solid-start/index.d.ts +75 -0
  409. package/dist/solid-start/index.js +58 -0
  410. package/dist/{spec-pins-C3oc-Tdp.js → spec-pins--j6mTok4.js} +8 -1
  411. package/dist/{spec-pins-CqorWDnO.d.ts → spec-pins-C89s6DyW.d.ts} +7 -0
  412. package/dist/sql/index.d.ts +313 -212
  413. package/dist/sql/index.js +34872 -6579
  414. package/dist/ssr/index.d.ts +6 -5
  415. package/dist/ssr/index.js +3 -3
  416. package/dist/{standard-D7r6dMUu.js → standard-BK0cqJ7y.js} +4 -3
  417. package/dist/{standard-J4YgMOLm.d.ts → standard-CYsm7xpT.d.ts} +1 -1
  418. package/dist/stats-D_AD9GGu.js +1123 -0
  419. package/dist/storage/index.d.ts +5 -5
  420. package/dist/storage/index.js +1027 -368
  421. package/dist/store-BdH5ruDx.js +66 -0
  422. package/dist/store-CGjgWu5n.d.ts +68 -0
  423. package/dist/streams/index.d.ts +76 -0
  424. package/dist/streams/index.js +77 -0
  425. package/dist/streams/redis/index.d.ts +52 -0
  426. package/dist/streams/redis/index.js +185 -0
  427. package/dist/stripe-BMj5LtsT.js +38 -0
  428. package/dist/stripe-D04h-QBT.d.ts +136 -0
  429. package/dist/{support-wHnK6zp-.js → support-BivNqSpK.js} +32 -11
  430. package/dist/{support-view-B8SlToQX.d.ts → support-view-33Oi07TT.d.ts} +1 -1
  431. package/dist/svelte/index.d.ts +114 -0
  432. package/dist/svelte/index.js +344 -0
  433. package/dist/sveltekit/index.d.ts +116 -0
  434. package/dist/sveltekit/index.js +106 -0
  435. package/dist/tags-B99_U9Pp.js +39 -0
  436. package/dist/tags-Cx-LnIQP.d.ts +30 -0
  437. package/dist/tanstack-db/index.d.ts +71 -0
  438. package/dist/tanstack-db/index.js +72 -0
  439. package/dist/tanstack-start/index.d.ts +75 -0
  440. package/dist/tanstack-start/index.js +95 -0
  441. package/dist/tee-CoEppCER.js +101 -0
  442. package/dist/{template-TxrGI5jR.js → template--jDkl3UP.js} +34 -13
  443. package/dist/template-CwO38Do8.d.ts +6 -0
  444. package/dist/temporal-BJGitm-h.js +79 -0
  445. package/dist/{temporal-required-CAt4Dc9Z.js → temporal-required-BVvW7SYJ.js} +3 -2
  446. package/dist/tenant-I1TEZ_BX.js +27 -0
  447. package/dist/tenant-icPeuUBN.d.ts +17 -0
  448. package/dist/testing/index.d.ts +315 -41
  449. package/dist/testing/index.js +1046 -79
  450. package/dist/timing-CyTQPubY.js +92 -0
  451. package/dist/ttl-Hr34gRu8.js +12 -0
  452. package/dist/{types-Dnf_wRDz.d.ts → types-6BdhkmZe.d.ts} +111 -45
  453. package/dist/types-BI-0Sl2v.d.ts +359 -0
  454. package/dist/types-C05bxW-W.d.ts +220 -0
  455. package/dist/types-DGs5L0VN.d.ts +192 -0
  456. package/dist/types-TaiEeBGA.d.ts +156 -0
  457. package/dist/usage-CrvrL2vw.d.ts +177 -0
  458. package/dist/user-change-XzvgafU4.js +130 -0
  459. package/dist/vault-CSO7ss5C.d.ts +50 -0
  460. package/dist/vercel-connect/index.d.ts +47 -0
  461. package/dist/vercel-connect/index.js +119 -0
  462. package/dist/{verify-Ce49ETPz.js → verify-DL41hbvY.js} +85 -13
  463. package/dist/verify-DPuWngD4.d.ts +172 -0
  464. package/dist/{version-DOYTYwHP.js → version-Bvv6aLjZ.js} +1 -1
  465. package/dist/view-BeFcRV6G.js +99 -0
  466. package/dist/{view-CbgObAeb.d.ts → view-DbxLNu8L.d.ts} +22 -5
  467. package/dist/vue/index.d.ts +141 -0
  468. package/dist/vue/index.js +362 -0
  469. package/dist/watch-DI34G86j.d.ts +60 -0
  470. package/dist/watch-Xuxrvxq-.js +122 -0
  471. package/dist/{wire-D2dT86vi.js → wire-DtZQ4sdE.js} +15 -5
  472. package/dist/workflow-builder-DJ1oHn8g.js +398 -0
  473. package/dist/workflow-sdk/builder/index.d.ts +85 -0
  474. package/dist/workflow-sdk/builder/index.js +250 -0
  475. package/dist/workflow-sdk/index.d.ts +14 -0
  476. package/dist/workflow-sdk/index.js +3 -0
  477. package/dist/workflow-sdk/world/index.d.ts +107 -0
  478. package/dist/workflow-sdk/world/index.js +702 -0
  479. package/dist/workflow-sdk-B3yLD6Br.d.ts +98 -0
  480. package/dist/workflow-sdk-C2WJ_G2O.js +173 -0
  481. package/dist/workflow-sdk-world-D-prir6O.js +1397 -0
  482. package/dist/workflows-B0j9WKPu.d.ts +185 -0
  483. package/dist/workflows-wu1WWBn7.js +216 -0
  484. package/package.json +461 -20
  485. package/schemas/ai-message-v1.json +258 -0
  486. package/schemas/config-v1.json +1074 -140
  487. package/schemas/doctor-report-v1.json +20 -1
  488. package/schemas/snapshot-v2.json +8 -0
  489. package/skills/better-supabase/SKILL.md +41 -12
  490. package/skills/better-supabase/references/frontend.md +96 -0
  491. package/skills/better-supabase/references/plugins.md +10 -6
  492. package/skills/better-supabase/references/troubleshooting.md +2 -1
  493. package/skills/better-supabase-api/SKILL.md +76 -22
  494. package/skills/better-supabase-api/references/adapters.md +207 -0
  495. package/skills/better-supabase-api/references/ai.md +125 -0
  496. package/skills/better-supabase-api/references/expo.md +65 -0
  497. package/skills/better-supabase-api/references/powersync.md +35 -0
  498. package/skills/better-supabase-api/references/streams-credentials.md +105 -0
  499. package/skills/better-supabase-auth/SKILL.md +47 -11
  500. package/skills/better-supabase-auth/references/authorization-providers.md +51 -0
  501. package/skills/better-supabase-testing/SKILL.md +3 -1
  502. package/dist/cli/config-dtoekM0v.js +0 -2
  503. package/dist/cli/gen-CIdSQZad.js +0 -2
  504. package/dist/cli/gen-CjElD1Vw.js +0 -2241
  505. package/dist/cli/read-sets-VQcPgxU9.js +0 -436
  506. package/dist/cli/sql-CVx-1O8G.js +0 -373
  507. package/dist/entitlements-CTEBm7IB.js +0 -20
  508. package/dist/events-aIO7vsIk.d.ts +0 -230
  509. package/dist/executor-BunPOO-k.d.ts +0 -402
  510. package/dist/executor-XycESQPH.js +0 -94
  511. package/dist/index-CWMDdEr4.d.ts +0 -50
  512. package/dist/index-DOESKG27.d.ts +0 -100
  513. package/dist/index-DmXSxbLi.d.ts +0 -62
  514. package/dist/index-Dp2VDwog.d.ts +0 -161
  515. package/dist/jobs/index.d.ts +0 -226
  516. package/dist/jobs/index.js +0 -1007
  517. package/dist/json-schema-m1fiwKgN.js +0 -208
  518. package/dist/kit-events-CTFDfSwb.js +0 -60
  519. package/dist/kit-transport-B82k1djG.d.ts +0 -33
  520. package/dist/kits-CGLLrNPd.js +0 -157
  521. package/dist/mfa-Cu96oJdw.d.ts +0 -30
  522. package/dist/notifications/index.d.ts +0 -162
  523. package/dist/notifications/index.js +0 -264
  524. package/dist/orgs/index.d.ts +0 -132
  525. package/dist/orgs/index.js +0 -245
  526. package/dist/permdock-sql-C2Inc6Xc.d.ts +0 -29
  527. package/dist/permdock-sql-DgOfeixi.js +0 -51
  528. package/dist/plugin-DwARMuQp.js +0 -59
  529. package/dist/server-B1mZ7CgQ.js +0 -660
  530. package/dist/stats-Bqob3WqT.js +0 -592
  531. package/dist/support-CEPwlw2G.d.ts +0 -89
  532. package/dist/template-mbvlysOo.d.ts +0 -6
  533. package/dist/temporal-CVlIV2DZ.js +0 -40
  534. package/dist/user-change-CHFEUro1.js +0 -49
  535. package/dist/webhooks/index.d.ts +0 -285
  536. package/skills/better-supabase-auth/references/permdock.md +0 -122
@@ -1,20 +1,41 @@
1
- import { t as cloneValue } from "./clone-BfgmLU90.js";
2
- import { n as dbError, t as DbException } from "./errors-DtwXa6b8.js";
3
- import { a as invalidRequest, r as builderFor } from "./simplify-_0oUKqCd.js";
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 { n as nowInstant } from "./temporal-CVlIV2DZ.js";
7
- import { n as decodeValue, r as encodeValue, t as decodeScalar } from "./wire-D2dT86vi.js";
8
- import { i as ok, n as err, o as toDbError, s as withErrorMapper, t as AsyncResult } from "./result-BKiliPY7.js";
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, s as tenantOf } from "./plugin-DwARMuQp.js";
12
- import { a as postgrestExecutor, n as StatsRecorder, r as recordStats } from "./stats-Bqob3WqT.js";
13
- 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-DQFt1N_Y.js";
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 validate } from "./standard-D7r6dMUu.js";
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
- base.batch(items.map((item) => item.op), items[0].context).then((results) => {
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
- try {
266
- const parsed = JSON.parse(base64ToText(cursor));
267
- return Array.isArray(parsed) ? parsed : void 0;
268
- } catch {
269
- return;
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) current = plugin.transformQuery(current, hook);
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
- throw cause;
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 context = signal ? {
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(op, current, result.data);
675
+ if (current.kind !== "select") await this.afterMutation(current, result.data);
441
676
  return result;
442
677
  }
443
- async afterMutation(requested, op, data) {
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 = tenantOf(runtime.context);
720
+ const { tenant } = runtime.context;
452
721
  const event = {
453
722
  table: op.table,
454
723
  kind,
455
- intent: requested.kind === "delete" && op.kind === "update" ? "softDelete" : kind,
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: typeof args?.["limit"] === "number" ? args["limit"] : void 0,
511
- offset: typeof args?.["offset"] === "number" ? args["offset"] : void 0,
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 = () => primaryOrder ??= table.primaryKey.map((name) => ({
532
- column: builder.column(table, name),
533
- direction: "asc"
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 AsyncResult.from(async () => {
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 AsyncResult.from(async () => {
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 AsyncResult.from(async () => {
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 AsyncResult.from(async () => {
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 AsyncResult.from(async () => {
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 AsyncResult.from(async () => {
894
+ return guarded(async () => {
595
895
  const aggregation = builder.aggregation(table, args);
596
- const orderBy = builder.orderBy(table, args["orderBy"]);
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 AsyncResult.from(async () => {
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 AsyncResult.from(async () => "after" in args ? cursorPage(args) : offsetPage(args));
922
+ return guarded(async () => "after" in args ? cursorPage(args) : offsetPage(args));
630
923
  },
631
924
  create(data, args) {
632
- return AsyncResult.from(async () => {
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 AsyncResult.from(async () => {
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 AsyncResult.from(async () => {
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 AsyncResult.from(async () => {
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: builder.where(table, args["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
- return result.ok ? ok({ count: result.data.count ?? 0 }) : result;
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 AsyncResult.from(async () => {
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 AsyncResult.from(async () => {
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 AsyncResult.from(async () => {
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 AsyncResult.from(async () => {
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 non-empty \"where\""));
724
- const result = await run({
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
- }, args);
730
- return result.ok ? ok({ count: result.data.count ?? 0 }) : result;
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: false
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
- async function offsetPage(args) {
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 runner.fail(table, dbError("invalid_request", "\"size\" must be a positive integer"));
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 runner.fail(table, dbError("invalid_request", "\"page\" must be a positive integer"));
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: (number - 1) * size,
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 orderBy = withTieBreaker(builder.orderBy(table, args["orderBy"]));
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 values = decodeCursor(args["after"]);
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 ? encodeCursor(orderBy.map((term) => encodeValue(last[aliases.get(term.column) ?? term.column]))) : null;
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] ?? term.column;
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
- * Rows in conflict-key order, so concurrent upserts lock the same rows in
863
- * the same order instead of deadlocking.
864
- */
865
- function byKey(rows, columns) {
866
- const compare = (left, right) => {
867
- if (left === right) return 0;
868
- if (left === null || left === void 0) return 1;
869
- if (right === null || right === void 0) return -1;
870
- if (typeof left === "number" && typeof right === "number") return left - right;
871
- if (typeof left === "bigint" && typeof right === "bigint") return left < right ? -1 : 1;
872
- const a = String(left);
873
- const b = String(right);
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
- return 0;
889
- });
890
- return keyed.map((entry) => entry.row);
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 rows after the cursor `values` in `orderBy` order, as an OR of ANDs:
894
- * `a > x or (a = x and b > y)`. The SQL compiler sends that shape as the row
895
- * comparison `(a, b) > (x, y)`. Nulls sort where Postgres puts them: last
896
- * for `asc`, first for `desc`, unless the term says otherwise.
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 keysetCondition(orderBy, values, nullable) {
899
- const isNull = (name) => column(name, "is", null);
900
- const branches = orderBy.flatMap((term, index) => {
901
- const value = values[index];
902
- const nullsFirst = (term.nulls ?? (term.direction === "desc" ? "first" : "last")) === "first";
903
- const after = column(term.column, term.direction === "asc" ? "gt" : "lt", value);
904
- const step = value === null ? nullsFirst ? not(isNull(term.column)) : void 0 : nullsFirst || !nullable(term.column) ? after : or(after, isNull(term.column));
905
- if (!step) return [];
906
- const equal = orderBy.slice(0, index).map((prev, prevIndex) => values[prevIndex] === null ? isNull(prev.column) : column(prev.column, "eq", values[prevIndex]));
907
- return [and(...equal, step) ?? step];
908
- });
909
- return branches.length > 0 ? or(...branches) : column(orderBy[0]?.column ?? "", "in", []);
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
- //#endregion
912
- //#region src/core/search.ts
913
- /** pgvector's text form, or `undefined` for anything that isn't a finite vector. */
914
- function vectorLiteral(vector) {
915
- if (typeof vector === "string") return /^\[[^\]]+\]$/.test(vector.trim()) ? vector.trim() : void 0;
916
- if (vector.length === 0 || !vector.every(Number.isFinite)) return void 0;
917
- return `[${vector.join(",")}]`;
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 = new EventHub(options.logger)) {
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
- return this.#db(client, base, context, this.plugins, recorder);
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, context, plugins, recorder, events = this.events) {
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.options.now ?? nowInstant,
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
- ...context,
1641
+ ...given,
1121
1642
  ...extra
1122
- }, plugins, recorder),
1123
- $withoutPlugins: () => this.#db(client, base, context, [], recorder),
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.code === "PGRST202" || result.error.code === "42883" ? err({
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, context, active, recorder) : usePlugins ? db : this.#db(client, base, context, [], recorder);
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
- const rows = entry.rows ?? [];
1239
- const result = await runSpec(this.#db(client, {
1240
- name: "read-set",
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: options?.schema ?? "public",
1878
+ schema,
1338
1879
  errorMappers,
1339
- ...options?.signal ? { signal: options.signal } : {}
1880
+ ...limit.signal ? { signal: limit.signal } : {},
1881
+ ...tuning.retry === void 0 ? {} : { retry: tuning.retry },
1882
+ ...fn ? { function: fn } : {}
1340
1883
  };
1341
- const result = await executor.rpc(name, args ?? {}, context);
1342
- if (!result.ok || !options?.returns) return result;
1343
- const checked = await validate(options.returns, result.data, `${name}() result`);
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
  }