better-supabase 0.7.0 → 0.8.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 (500) hide show
  1. package/README.md +6 -2
  2. package/dist/{access-sql-B0dF-SoF.js → access-sql-CrSbK1q-.js} +1 -1
  3. package/dist/{adapter-B-tL8hqg.js → adapter-CN45ibbV.js} +663 -157
  4. package/dist/{agents-CVHGd7It.d.ts → agents-BY_LQXtQ.d.ts} +4 -4
  5. package/dist/{ai-cache-CBWs1W0k.js → ai-cache-Dfgk8nBT.js} +2 -1
  6. package/dist/{ai-cache-DaDu_G5L.d.ts → ai-cache-DrUMMgp6.d.ts} +4 -4
  7. package/dist/{ai-chat-B24UI962.js → ai-chat-CVLRWbtS.js} +4 -3
  8. package/dist/{ai-chat-7amvXjmQ.d.ts → ai-chat-DXkMy74O.d.ts} +5 -5
  9. package/dist/{ai-files-CSPNswUY.js → ai-files-CioLu5du.js} +5 -4
  10. package/dist/ai-message-DfaP8sis.js +14 -0
  11. package/dist/ai-sdk/agents/index.d.ts +4 -4
  12. package/dist/ai-sdk/batches/index.d.ts +4 -4
  13. package/dist/ai-sdk/batches/index.js +4 -4
  14. package/dist/ai-sdk/cache/index.d.ts +2 -2
  15. package/dist/ai-sdk/cache/index.js +2 -2
  16. package/dist/ai-sdk/chat/index.d.ts +1 -1
  17. package/dist/ai-sdk/chat/index.js +8 -20
  18. package/dist/ai-sdk/embeddings/index.d.ts +2 -2
  19. package/dist/ai-sdk/files/index.d.ts +3 -3
  20. package/dist/ai-sdk/files/index.js +4 -4
  21. package/dist/ai-sdk/index.d.ts +37 -9
  22. package/dist/ai-sdk/index.js +3 -2
  23. package/dist/ai-sdk/mcp/index.d.ts +43 -6
  24. package/dist/ai-sdk/mcp/index.js +36 -7
  25. package/dist/ai-sdk/memory/index.d.ts +2 -2
  26. package/dist/ai-sdk/memory/index.js +1 -1
  27. package/dist/ai-sdk/workflow/index.d.ts +6 -6
  28. package/dist/ai-sdk/workflow/index.js +13 -24
  29. package/dist/{ai-tasks-Cd1HMFvB.d.ts → ai-tasks-BRQ6iQLc.d.ts} +4 -4
  30. package/dist/{announcements-ZRGnScWI.d.ts → announcements-Bouy0Ski.d.ts} +3 -3
  31. package/dist/{announcements-CiyOs-xP.js → announcements-p_BFofiR.js} +1 -1
  32. package/dist/api-Dnf2q-Ht.d.ts +370 -0
  33. package/dist/api-DtHFC037.js +676 -0
  34. package/dist/{api-keys-CIjghYjV.d.ts → api-keys-C8BlF3L2.d.ts} +4 -4
  35. package/dist/arazzo/index.d.ts +255 -0
  36. package/dist/arazzo/index.js +622 -0
  37. package/dist/{assistant-DwdpDH1q.d.ts → assistant-DBlFDZsi.d.ts} +5 -5
  38. package/dist/astro/index.d.ts +7 -7
  39. package/dist/astro/index.js +7 -7
  40. package/dist/asyncapi/index.d.ts +103 -0
  41. package/dist/asyncapi/index.js +569 -0
  42. package/dist/authorizer-ayxUDXXP.js +126 -0
  43. package/dist/authorizer-eiOjo-3l.d.ts +73 -0
  44. package/dist/better-result/index.d.ts +118 -0
  45. package/dist/better-result/index.js +64 -0
  46. package/dist/{bind-l4kAvYSv.js → bind-ButSzrHe.js} +1 -1
  47. package/dist/{bind-Bu_ZNa3W.d.ts → bind-CQ5mPyX1.d.ts} +3 -3
  48. package/dist/{block-events-CrT8r7Fe.js → block-events-DTxU5tfr.js} +18 -3
  49. package/dist/{block-fields-GFkxl4dP.js → block-fields-CroxUuF2.js} +3 -3
  50. package/dist/{block-fields-SJ6fEf3o.d.ts → block-fields-D1pfrcIY.d.ts} +2 -2
  51. package/dist/{block-helpers-CKtbFcRv.d.ts → block-helpers-C0Xj8War.d.ts} +2 -2
  52. package/dist/{block-helpers-DWHxHsEQ.js → block-helpers-Cy3pB96I.js} +41 -9
  53. package/dist/{block-hooks-BmjMyXTa.js → block-hooks-BPNMIlLl.js} +3 -3
  54. package/dist/{block-hooks-plbZ0AbJ.d.ts → block-hooks-DaOVC7SC.d.ts} +3 -3
  55. package/dist/{block-transport-BLr-ZgLc.js → block-transport-bAKh-dGc.js} +28 -2
  56. package/dist/{block-transport-DvaoPuZ9.d.ts → block-transport-inD4fFq-.d.ts} +24 -2
  57. package/dist/blocks/agents/index.d.ts +3 -3
  58. package/dist/blocks/agents/index.js +5 -4
  59. package/dist/blocks/ai-cache/index.d.ts +3 -3
  60. package/dist/blocks/ai-cache/index.js +3 -3
  61. package/dist/blocks/ai-chat/index.d.ts +9 -4
  62. package/dist/blocks/ai-chat/index.js +5 -5
  63. package/dist/blocks/ai-chat/react/index.d.ts +3 -3
  64. package/dist/blocks/ai-chat/react/index.js +5 -5
  65. package/dist/blocks/ai-files/index.d.ts +3 -3
  66. package/dist/blocks/ai-files/index.js +3 -3
  67. package/dist/blocks/ai-providers/index.d.ts +3 -3
  68. package/dist/blocks/ai-providers/index.js +8 -7
  69. package/dist/blocks/ai-tasks/index.d.ts +3 -3
  70. package/dist/blocks/ai-tasks/index.js +7 -6
  71. package/dist/blocks/announcements/index.d.ts +3 -3
  72. package/dist/blocks/announcements/index.js +3 -3
  73. package/dist/blocks/announcements/react/index.d.ts +3 -3
  74. package/dist/blocks/announcements/react/index.js +3 -3
  75. package/dist/blocks/api-keys/index.d.ts +5 -5
  76. package/dist/blocks/api-keys/index.js +8 -8
  77. package/dist/blocks/attachments/index.d.ts +12 -8
  78. package/dist/blocks/attachments/index.js +22 -13
  79. package/dist/blocks/audit/index.d.ts +21 -10
  80. package/dist/blocks/audit/index.js +30 -11
  81. package/dist/blocks/billing/index.d.ts +11 -9
  82. package/dist/blocks/billing/index.js +15 -15
  83. package/dist/blocks/comments/index.d.ts +8 -8
  84. package/dist/blocks/comments/index.js +8 -7
  85. package/dist/blocks/connectors/index.d.ts +3 -3
  86. package/dist/blocks/connectors/index.js +7 -6
  87. package/dist/blocks/data-lifecycle/index.d.ts +12 -8
  88. package/dist/blocks/data-lifecycle/index.js +13 -8
  89. package/dist/blocks/entitlements/index.d.ts +3 -3
  90. package/dist/blocks/entitlements/index.js +1 -1
  91. package/dist/blocks/flags/index.d.ts +4 -4
  92. package/dist/blocks/flags/index.js +4 -3
  93. package/dist/blocks/inbox/index.d.ts +3 -3
  94. package/dist/blocks/inbox/index.js +4 -5
  95. package/dist/blocks/inbox/react/index.d.ts +1 -1
  96. package/dist/blocks/inbox/react/index.js +1 -1
  97. package/dist/blocks/inbox/react/server.d.ts +1 -1
  98. package/dist/blocks/index.d.ts +10 -10
  99. package/dist/blocks/index.js +6 -6
  100. package/dist/blocks/jobs/index.d.ts +48 -32
  101. package/dist/blocks/jobs/index.js +44 -287
  102. package/dist/blocks/knowledge/index.d.ts +3 -3
  103. package/dist/blocks/knowledge/index.js +3 -3
  104. package/dist/blocks/memory/index.d.ts +4 -4
  105. package/dist/blocks/memory/index.js +7 -6
  106. package/dist/blocks/notifications/index.d.ts +11 -9
  107. package/dist/blocks/notifications/index.js +20 -25
  108. package/dist/blocks/notifications/react/index.d.ts +1 -1
  109. package/dist/blocks/notifications/react/index.js +1 -1
  110. package/dist/blocks/onboarding/index.d.ts +3 -3
  111. package/dist/blocks/onboarding/index.js +3 -3
  112. package/dist/blocks/onboarding/react/index.d.ts +2 -2
  113. package/dist/blocks/onboarding/react/index.js +2 -2
  114. package/dist/blocks/onboarding/react/server.d.ts +1 -1
  115. package/dist/blocks/organizations/index.d.ts +9 -9
  116. package/dist/blocks/organizations/index.js +11 -18
  117. package/dist/blocks/outbox/index.d.ts +2 -2
  118. package/dist/blocks/outbox/index.js +16 -25
  119. package/dist/blocks/profiles/index.d.ts +7 -7
  120. package/dist/blocks/profiles/index.js +7 -6
  121. package/dist/blocks/push/index.d.ts +4 -4
  122. package/dist/blocks/push/index.js +3 -3
  123. package/dist/blocks/settings/index.d.ts +4 -4
  124. package/dist/blocks/settings/index.js +7 -6
  125. package/dist/blocks/sso/index.d.ts +5 -5
  126. package/dist/blocks/sso/index.js +6 -5
  127. package/dist/blocks/usage/index.d.ts +3 -3
  128. package/dist/blocks/usage/index.js +5 -4
  129. package/dist/blocks/waitlist/index.d.ts +5 -5
  130. package/dist/blocks/waitlist/index.js +5 -4
  131. package/dist/blocks/webhooks/index.d.ts +22 -13
  132. package/dist/blocks/webhooks/index.js +41 -70
  133. package/dist/blocks/workflow-builder/index.d.ts +4 -4
  134. package/dist/blocks/workflow-builder/index.js +3 -3
  135. package/dist/blocks/workflow-builder/react/index.d.ts +4 -4
  136. package/dist/blocks/workflow-builder/react/index.js +4 -4
  137. package/dist/blocks/workflows/index.d.ts +3 -3
  138. package/dist/blocks/workflows/index.js +3 -3
  139. package/dist/blocks/workflows/react/index.d.ts +3 -3
  140. package/dist/blocks/workflows/react/index.js +3 -3
  141. package/dist/build-hPwk3_X5.js +1296 -0
  142. package/dist/{build-BXIzE6Xv.js → build-meLuYGri.js} +3 -3
  143. package/dist/casing-DdFWEtqr.js +16 -0
  144. package/dist/chat-sdk/index.d.ts +6 -6
  145. package/dist/chat-sdk/index.js +5 -4
  146. package/dist/chat-sdk/react/index.d.ts +1 -1
  147. package/dist/chat-sdk/react/server.d.ts +1 -1
  148. package/dist/{claims-DDBQT6BK.js → claims-0KZVT804.js} +1 -1
  149. package/dist/cli/add-1dc5wM5k.js +69 -0
  150. package/dist/cli/arazzo-1.0-BalU61-_.js +532 -0
  151. package/dist/cli/arazzo-1.1-Bnfasbun.js +705 -0
  152. package/dist/cli/asyncapi-3.0.0-C78dBjR6.js +5593 -0
  153. package/dist/cli/asyncapi-3.1.0-g-7aIfV1.js +5833 -0
  154. package/dist/cli/bin.js +4 -4
  155. package/dist/cli/cache-CIfA-jBV.js +483 -0
  156. package/dist/cli/{codemod-Bl_tQpHn.js → codemod-JVlTQQG2.js} +4 -4
  157. package/dist/cli/{command-CK14fP91.js → command-DV-StG1x.js} +5 -0
  158. package/dist/cli/{config-DU7EJImt.js → config-C2Pz2_4A.js} +7 -4
  159. package/dist/cli/config-DpbF8ML3.js +2 -0
  160. package/dist/cli/{config-NiPxAmUF.js → config-M-WzL9O2.js} +116 -18
  161. package/dist/cli/{db-DOBPt660.js → db-BkcfOlyB.js} +2 -1
  162. package/dist/cli/{diff-SjkO5rNr.js → diff-D1jGdb3Y.js} +1 -1
  163. package/dist/cli/{doctor-CVdnLahA.js → doctor-VcDtuusV.js} +317 -222
  164. package/dist/cli/emit-BHHfwUoT.js +1136 -0
  165. package/dist/cli/{env-qXgyMV6r.js → env-B--LMhEe.js} +13 -10
  166. package/dist/cli/env-vzBG90Um.js +2 -0
  167. package/dist/cli/{env-CJLbUVPB.js → env-zHJtMIBo.js} +11 -3
  168. package/dist/cli/{errors-4v4DTtda.js → errors-CqTLXe2M.js} +18 -2
  169. package/dist/cli/{fastest-levenshtein-CFN-lNDv.js → fastest-levenshtein-CF7BCi9l.js} +1 -1
  170. package/dist/cli/files-BVupXPIC.js +34 -0
  171. package/dist/cli/gen-DmVj3u4L.js +322 -0
  172. package/dist/cli/{init-Cr6arjXU.js → glue-C1UE8gQN.js} +16 -313
  173. package/dist/cli/index.d.ts +59 -31
  174. package/dist/cli/index.js +8 -6
  175. package/dist/cli/init-CVZ3s5kl.js +258 -0
  176. package/dist/cli/{introspect-Bzuv1HHj.js → introspect-BToGNfm-.js} +14 -14
  177. package/dist/cli/{io-DI1mTdSA.js → io-CFzJVJ68.js} +5 -1
  178. package/dist/cli/{keys-BGCnnb-s.js → keys-CJhtIxJ3.js} +4 -4
  179. package/dist/cli/metadata-DSRKCaf-.js +133 -0
  180. package/dist/cli/names-D6LrQnOv.js +6 -0
  181. package/dist/cli/openapi-3.0-t7xwkuRH.js +928 -0
  182. package/dist/cli/openapi-3.1-CVze7tBS.js +870 -0
  183. package/dist/cli/openapi-3.2-CFoMYM01.js +1031 -0
  184. package/dist/cli/{openapi-BlRJ18s3.js → openapi-DWa4Ir1q.js} +8 -14
  185. package/dist/cli/prompts-BdeVmVpg.js +2 -0
  186. package/dist/cli/{prompts-BNcNfAve.js → prompts-DZJB1nTw.js} +6 -6
  187. package/dist/cli/{rolldown-runtime-BPOCksWG.js → rolldown-runtime-CMFfr-1z.js} +3 -1
  188. package/dist/cli/run-DA6_lg3w.js +389 -0
  189. package/dist/cli/run-DuN1MX-7.js +705 -0
  190. package/dist/cli/scaffold-5DenHSxF.js +292 -0
  191. package/dist/cli/scaffold-CwQUMFRb.js +2 -0
  192. package/dist/cli/{seed-DQzqT7LP.js → seed-CzBmrGON.js} +14 -18
  193. package/dist/cli/seed-DOmit9Hq.js +2 -0
  194. package/dist/cli/{skills-QQs4q68J.js → skills-CnO8QFS7.js} +7 -6
  195. package/dist/cli/snapshot-Bstk6ulj.js +287 -0
  196. package/dist/cli/source-args-BYfq6imV.js +31 -0
  197. package/dist/cli/spec-CzosTYm3.js +7438 -0
  198. package/dist/cli/spec-T_0Bcyw7.js +2 -0
  199. package/dist/cli/{sql-B8csQPyn.js → sql-BKOOQAX3.js} +240 -218
  200. package/dist/cli/sql-DJrNDxQm.js +3 -0
  201. package/dist/cli/{style-C0NFdJRL.js → style-CB3vxgh0.js} +3 -3
  202. package/dist/cli/typegen-Demi5-VQ.js +486 -0
  203. package/dist/cli/validate-Ca13ktgz.js +7522 -0
  204. package/dist/cli/{version-Bp4fyubI.js → version-B4k0aUxS.js} +1 -1
  205. package/dist/client/index.d.ts +4 -3
  206. package/dist/client/index.js +60 -3
  207. package/dist/client/native/index.d.ts +3 -3
  208. package/dist/client/native/index.js +3 -3
  209. package/dist/{client-CI0Z2zWX.js → client-wxeTQFtB.js} +36 -3
  210. package/dist/{clone-BfgmLU90.js → clone-dN9XOL1K.js} +9 -1
  211. package/dist/{cloud-event-BnmD5fb9.js → cloud-event-CTh9Sr5w.js} +16 -2
  212. package/dist/{cloud-event-C1JCc1bH.d.ts → cloud-event-Dune0KI7.d.ts} +16 -2
  213. package/dist/{compiler-DY_wkj4R.d.ts → compiler-V1qvcST1.d.ts} +2 -2
  214. package/dist/{compose-BIBNgAnq.js → compose-BHej1acw.js} +3 -3
  215. package/dist/{composite-CpHLEo-G.d.ts → composite-CWAJTRBF.d.ts} +6 -6
  216. package/dist/{composite-C6I8ZyaF.js → composite-zTe0TCqj.js} +4 -4
  217. package/dist/config/index.d.ts +3 -4
  218. package/dist/config/index.js +4 -4
  219. package/dist/config-DlKvtt95.js +540 -0
  220. package/dist/{connector-Dv8kK0MO.d.ts → connector-CySQEFcW.d.ts} +1 -1
  221. package/dist/{connectors-CrpknU0P.d.ts → connectors--PGhmiu0.d.ts} +4 -4
  222. package/dist/{context-BCrWe7ow.d.ts → context-DsV2SueA.d.ts} +11 -2
  223. package/dist/context-nPDvQ-Zl.js +41 -0
  224. package/dist/credentials/index.d.ts +5 -5
  225. package/dist/credentials/index.js +9 -17
  226. package/dist/{cron-DVPUg5k3.js → cron-D25Ukpxy.js} +1 -1
  227. package/dist/cron-route-D2AN9SA1.js +24 -0
  228. package/dist/{csv-DCK-PT1n.js → csv-BZnHA1Py.js} +1 -1
  229. package/dist/{define-B-TVjC25.js → define-CFQcvM20.js} +263 -229
  230. package/dist/{define-CJJkkr1-.d.ts → define-DmcfoNXB.d.ts} +136 -111
  231. package/dist/edge/index.d.ts +66 -13
  232. package/dist/edge/index.js +65 -39
  233. package/dist/elysia/index.d.ts +1 -1
  234. package/dist/elysia/index.js +1 -1
  235. package/dist/{embeddings-C9KGQnXt.d.ts → embeddings-B4vhS-dY.d.ts} +1 -1
  236. package/dist/{ended-XjeGQ5XW.d.ts → ended-CcvcRqEd.d.ts} +7 -1
  237. package/dist/{entitlements-DRl6ZJUm.js → entitlements-BYFf0Cdh.js} +2 -2
  238. package/dist/{entitlements-BKSVGtrG.d.ts → entitlements-Ds8qoYZ-.d.ts} +1 -1
  239. package/dist/env/index.d.ts +1 -1
  240. package/dist/env/index.js +9 -2
  241. package/dist/{errors-B11Duf73.js → errors-2M6CKMP4.js} +5 -0
  242. package/dist/{errors-DLjJHPLK.js → errors-rZ7VIqp6.js} +2 -2
  243. package/dist/{escape-like-ImTK0ps_.d.ts → escape-like-DDWoHzh_.d.ts} +1 -1
  244. package/dist/eve/index.d.ts +5 -5
  245. package/dist/eve/index.js +5 -11
  246. package/dist/{eve-gT2Fpjut.d.ts → eve-CoAIcCkq.d.ts} +2 -2
  247. package/dist/events/index.d.ts +4 -4
  248. package/dist/events/index.js +7 -2
  249. package/dist/{events-DWDhx77e.d.ts → events-D1BOCll8.d.ts} +6 -4
  250. package/dist/{executor-Bq28caBo.js → executor-B-fD7DLt.js} +52 -35
  251. package/dist/executor-B_Hfobee.js +162 -0
  252. package/dist/{executor-BVBFM86G.d.ts → executor-CpxLPCiz.d.ts} +1 -1
  253. package/dist/{executor-CaWigTyR.d.ts → executor-DfEtf0cq.d.ts} +43 -27
  254. package/dist/{executor-DvsBbNBS.d.ts → executor-Drzu3dBK.d.ts} +2 -2
  255. package/dist/{executor-DbvExCFC.d.ts → executor-ngjKL_Pe.d.ts} +2 -2
  256. package/dist/expo/index.d.ts +4 -4
  257. package/dist/expo/index.js +6 -6
  258. package/dist/expo-sqlite/index.d.ts +3 -3
  259. package/dist/expo-sqlite/index.js +2 -2
  260. package/dist/extra-CGQ2_q3S.js +10 -0
  261. package/dist/{field-errors-BFOa7WhB.d.ts → field-errors-DIe9XYWL.d.ts} +17 -7
  262. package/dist/{field-errors-VF1yb8yI.js → field-errors-DZVRWRkf.js} +1 -1
  263. package/dist/format-DTXdu8ya.d.ts +70 -0
  264. package/dist/{framework-KIPvRQJU.d.ts → framework-148t1m3C.d.ts} +5 -5
  265. package/dist/{framework-BDCpJI7o.js → framework-3ey3QmrO.js} +2 -2
  266. package/dist/function-contract-BcZenXMO.d.ts +8 -0
  267. package/dist/{gateway-C1ssRHnf.d.ts → gateway-S9vicgeo.d.ts} +4 -4
  268. package/dist/{guards-BnzDvFrz.js → guards-6F2bCtQR.js} +3 -1
  269. package/dist/h3/index.d.ts +1 -1
  270. package/dist/h3/index.js +1 -1
  271. package/dist/h3/v1/index.d.ts +1 -1
  272. package/dist/h3/v1/index.js +1 -1
  273. package/dist/{message-CaKlqdsX.js → history-GH1HJWQV.js} +65 -13
  274. package/dist/hmac-DCud0myt.js +22 -0
  275. package/dist/hono/index.d.ts +19 -14
  276. package/dist/hono/index.js +21 -16
  277. package/dist/{hooks-1BTCJsiw.js → hooks-Bhza9Hnr.js} +68 -100
  278. package/dist/http-sbmBe5d2.js +25 -0
  279. package/dist/{inbox-i7E1ppo6.d.ts → inbox-Cd1KCEBL.d.ts} +3 -3
  280. package/dist/index-B72Rvv_j.d.ts +89 -0
  281. package/dist/{index-DunNRdnT.d.ts → index-BCHR4Ucl.d.ts} +4 -4
  282. package/dist/{index-CLg87OBW.d.ts → index-BUK7jUzR.d.ts} +6 -0
  283. package/dist/{config-D44Y7PAv.d.ts → index-Ba1SI-uO.d.ts} +625 -278
  284. package/dist/{index-D48jVS-N.d.ts → index-BfxOaOYs.d.ts} +4 -5
  285. package/dist/{index-ClmjK_o-.d.ts → index-CicIyqOe.d.ts} +4 -4
  286. package/dist/{index-ACiNPN4Z.d.ts → index-D69h4QqD.d.ts} +1 -1
  287. package/dist/index-DG2SUXDQ.d.ts +58 -0
  288. package/dist/{index-Bepi-Hgg.d.ts → index-DoNVLHOU.d.ts} +3 -3
  289. package/dist/{index-CdZKQF98.d.ts → index-R274XFlg.d.ts} +1 -1
  290. package/dist/{index-CewnYSpv.d.ts → index-_4R4b01v.d.ts} +8 -18
  291. package/dist/index.d.ts +89 -14
  292. package/dist/index.js +12 -11
  293. package/dist/{json-schema-CvER4kgT.js → json-schema-CT4tvrkA.js} +148 -102
  294. package/dist/{kit-Fm-Fv7q5.js → kit-BhHr9T9v.js} +36 -10
  295. package/dist/{kit-CkNzZUqv.d.ts → kit-W99LCPBS.d.ts} +13 -7
  296. package/dist/{knowledge-BXBbT0Tr.d.ts → knowledge-CAReFpRA.d.ts} +5 -5
  297. package/dist/{knowledge-CDmiMLew.js → knowledge-DnHtb64A.js} +4 -3
  298. package/dist/list/index.d.ts +1 -2
  299. package/dist/{list-query-BRt-zDF7.d.ts → list-query-D3JQeEL7.d.ts} +4 -4
  300. package/dist/mcp/index.d.ts +49 -19
  301. package/dist/mcp/index.js +158 -94
  302. package/dist/mcp/sdk/index.d.ts +38 -6
  303. package/dist/mcp/sdk/index.js +88 -6
  304. package/dist/{message-CfDoR0Y6.d.ts → message-B0fNJgq8.d.ts} +1 -2
  305. package/dist/{messages-B9-5887d.js → messages-CJoHHCWT.js} +4 -205
  306. package/dist/{mfa-Daak8ukG.d.ts → mfa-SZc9YYyb.d.ts} +1 -1
  307. package/dist/model-OgBxvk3N.d.ts +300 -0
  308. package/dist/model-messages-Cxw_Up4f.js +206 -0
  309. package/dist/model-messages-D4GZllOD.d.ts +34 -0
  310. package/dist/modules-DksjZyMW.js +77 -0
  311. package/dist/nestjs/index.d.ts +2 -2
  312. package/dist/nestjs/index.js +1 -1
  313. package/dist/next/index.d.ts +105 -55
  314. package/dist/next/index.js +204 -170
  315. package/dist/node/index.d.ts +2 -2
  316. package/dist/node/index.js +1 -1
  317. package/dist/{onboarding-BZGHYJks.d.ts → onboarding-LZvlK1P4.d.ts} +3 -3
  318. package/dist/openapi/index.d.ts +4 -2
  319. package/dist/openapi/index.js +21 -343
  320. package/dist/optional-peer-D1pi-skw.js +24 -0
  321. package/dist/orpc/index.d.ts +8 -8
  322. package/dist/orpc/index.js +21 -20
  323. package/dist/otel/index.d.ts +3 -3
  324. package/dist/otel/index.js +7 -7
  325. package/dist/{outbox-Cq7pPYvl.d.ts → outbox-DZfAvfzC.d.ts} +6 -6
  326. package/dist/overlay/index.d.ts +233 -0
  327. package/dist/overlay/index.js +554 -0
  328. package/dist/{plugin-FGY8UhYm.d.ts → plugin-CPK2HsbY.d.ts} +42 -3
  329. package/dist/plugins/actor/index.d.ts +1 -1
  330. package/dist/plugins/actor/index.js +1 -1
  331. package/dist/plugins/rules/index.d.ts +2 -2
  332. package/dist/plugins/rules/index.js +1 -1
  333. package/dist/plugins/soft-delete/index.d.ts +3 -3
  334. package/dist/plugins/soft-delete/index.js +9 -2
  335. package/dist/plugins/tenant/index.d.ts +7 -2
  336. package/dist/plugins/tenant/index.js +16 -2
  337. package/dist/plugins/timestamps/index.d.ts +1 -1
  338. package/dist/plugins/timestamps/index.js +8 -1
  339. package/dist/plugins/validation/index.d.ts +2 -2
  340. package/dist/plugins/validation/index.js +4 -4
  341. package/dist/{pool-CAu2nLrL.d.ts → pool-gkhbGp2E.d.ts} +2 -2
  342. package/dist/postgres/index.d.ts +4 -4
  343. package/dist/postgres/index.js +2 -1
  344. package/dist/{postgrest-BLVdEnfe.d.ts → postgrest-BUqLag2Q.d.ts} +1 -1
  345. package/dist/powersync/index.d.ts +5 -5
  346. package/dist/powersync/index.js +4 -4
  347. package/dist/powersync/react/index.d.ts +3 -3
  348. package/dist/powersync/react/index.js +1 -1
  349. package/dist/{problem-BreOl8b8.js → problem-CJvFeGu7.js} +13 -2
  350. package/dist/{problem-DD8LZFjc.d.ts → problem-TvGdxO1t.d.ts} +7 -1
  351. package/dist/{provider-Di3sRutW.js → provider-DxRTex4x.js} +1 -1
  352. package/dist/{provider-D-UEMvSD.d.ts → provider-ib9wzUDz.d.ts} +2 -2
  353. package/dist/query/index.d.ts +2 -2
  354. package/dist/query/index.js +1 -1
  355. package/dist/{query-BQ-NaZon.js → query-Ctz-qKRx.js} +1 -1
  356. package/dist/rate-limit-Bw7HgmFj.js +260 -0
  357. package/dist/react/index.d.ts +9 -9
  358. package/dist/react/index.js +4 -4
  359. package/dist/react/native/index.d.ts +1 -1
  360. package/dist/react/native/index.js +2 -2
  361. package/dist/react/server.d.ts +10 -10
  362. package/dist/react/server.js +3 -3
  363. package/dist/react/session.d.ts +2 -2
  364. package/dist/{react-F80mF4-t.js → react-Bmpo59D7.js} +4 -4
  365. package/dist/react-router/index.d.ts +6 -6
  366. package/dist/react-router/index.js +9 -11
  367. package/dist/{read-set-DuKWC9Mj.js → read-set-DAeWhqPf.js} +2 -2
  368. package/dist/realtime/index.d.ts +3 -3
  369. package/dist/realtime/index.js +30 -36
  370. package/dist/{refusal-DhSU2Vvr.d.ts → refusal-CFI8-5nf.d.ts} +4 -1
  371. package/dist/{refusal-CeJWxmkH.js → refusal-K78A1Vmq.js} +5 -5
  372. package/dist/{resolve-tJZY3FEa.js → resolve-Bvgf3ut_.js} +131 -42
  373. package/dist/{resolve-ChTYeTEl.d.ts → resolve-MxXVWyhd.d.ts} +12 -8
  374. package/dist/resource--vTrBe6I.d.ts +103 -0
  375. package/dist/resource-BqNqlYg9.js +91 -0
  376. package/dist/resource-DA811u_4.js +463 -0
  377. package/dist/resource-execute-rbKvuCsY.d.ts +12 -0
  378. package/dist/resource-schemas-BJ518zFH.js +79 -0
  379. package/dist/resource-types-CqB6GWGT.d.ts +141 -0
  380. package/dist/resources-BVYPnuLo.js +56 -0
  381. package/dist/resources-DZSk8tXJ.d.ts +7 -0
  382. package/dist/{respond-DprrgyXX.d.ts → respond-Cw-zanCm.d.ts} +3 -3
  383. package/dist/{respond-BUgsXNgk.js → respond-volM3ByS.js} +4 -4
  384. package/dist/{result-D7y2fT87.d.ts → result-BchM1XZn.d.ts} +7 -1
  385. package/dist/{result-DzUbqgdW.js → result-DEqHCMKP.js} +1 -1
  386. package/dist/server/index.d.ts +81 -19
  387. package/dist/server/index.js +16 -14
  388. package/dist/{server-ZSJ9rCcV.d.ts → server-types-CrAmZ8jv.d.ts} +110 -36
  389. package/dist/{shared-CxWmcyqB.js → shared-DHjhfRdV.js} +2 -15
  390. package/dist/shared-DTneRoxi.js +14 -0
  391. package/dist/{sign-in-Cb1mwv6X.js → sign-in-D_yoP0PF.js} +1 -1
  392. package/dist/signatures-BRS_p3WD.d.ts +34 -0
  393. package/dist/signatures-DsWv_bYR.js +103 -0
  394. package/dist/{signers-4y62_VIi.d.ts → signers-cpdmZYrv.d.ts} +1 -1
  395. package/dist/solid/index.d.ts +9 -18
  396. package/dist/solid/index.js +2 -2
  397. package/dist/solid-start/index.d.ts +6 -6
  398. package/dist/solid-start/index.js +7 -7
  399. package/dist/spec/index.d.ts +134 -0
  400. package/dist/spec/index.js +353 -0
  401. package/dist/{spec-pins-C89s6DyW.d.ts → spec-pins-CwzDY25w.d.ts} +18 -1
  402. package/dist/{spec-pins--j6mTok4.js → spec-pins-DsLfUH7l.js} +14 -1
  403. package/dist/sql/index.d.ts +145 -119
  404. package/dist/sql/index.js +19921 -19798
  405. package/dist/{executor-De1Of3m3.js → sql-CwuqaQ4Y.js} +34 -169
  406. package/dist/ssr/index.d.ts +4 -4
  407. package/dist/ssr/index.js +3 -2
  408. package/dist/{standard-BK0cqJ7y.js → standard-DkzZUneg.js} +2 -2
  409. package/dist/{standard-CYsm7xpT.d.ts → standard-lmkbOtPB.d.ts} +1 -1
  410. package/dist/{stats-D_AD9GGu.js → stats-DhU78Ctf.js} +8 -4
  411. package/dist/storage/index.d.ts +4 -6
  412. package/dist/storage/index.js +16 -17
  413. package/dist/{bucket-Cl46E3jS.d.ts → storage-api-CB7Zl1Ci.d.ts} +243 -8
  414. package/dist/{store-CGjgWu5n.d.ts → store-DsIYEBnv.d.ts} +1 -1
  415. package/dist/streams/index.d.ts +4 -4
  416. package/dist/streams/index.js +5 -4
  417. package/dist/streams/redis/index.d.ts +1 -1
  418. package/dist/streams/redis/index.js +5 -11
  419. package/dist/{stripe-BMj5LtsT.js → stripe-v-Y2lmop.js} +2 -8
  420. package/dist/supabase-mcp-C6tMoEjn.d.ts +43 -0
  421. package/dist/supabase-mcp-Cpn5A4i-.js +28 -0
  422. package/dist/{support-DWwzVf-O.js → support-D1pFFouF.js} +71 -35
  423. package/dist/{support-view-CVOJJLpc.d.ts → support-view-scqMgtOo.d.ts} +1 -1
  424. package/dist/svelte/index.d.ts +8 -17
  425. package/dist/svelte/index.js +2 -2
  426. package/dist/sveltekit/index.d.ts +7 -7
  427. package/dist/sveltekit/index.js +10 -12
  428. package/dist/table-schema-htM_SbCW.js +286 -0
  429. package/dist/{tags-Cx-LnIQP.d.ts → tags-BO9LjtWG.d.ts} +1 -1
  430. package/dist/tanstack-db/index.d.ts +2 -2
  431. package/dist/tanstack-db/supabase/index.d.ts +52 -0
  432. package/dist/tanstack-db/supabase/index.js +97 -0
  433. package/dist/tanstack-start/index.d.ts +6 -6
  434. package/dist/tanstack-start/index.js +8 -12
  435. package/dist/{tee-CoEppCER.js → tee-Cb98Vn3b.js} +1 -1
  436. package/dist/{template--jDkl3UP.js → template-lPVh-EwW.js} +11 -2
  437. package/dist/{temporal-required-BVvW7SYJ.js → temporal-required-BtynQtM-.js} +1 -1
  438. package/dist/{tenant-BxNFk9bx.d.ts → tenant-CM368LXb.d.ts} +2 -2
  439. package/dist/testing/index.d.ts +249 -118
  440. package/dist/testing/index.js +1418 -870
  441. package/dist/ttl-cache-XzZ-Q2eX.js +29 -0
  442. package/dist/types-BRTSpOIh.js +5 -0
  443. package/dist/{types-C05bxW-W.d.ts → types-Bb_4-vdW.d.ts} +4 -4
  444. package/dist/{types-AYOvcyep.d.ts → types-CD6yCDx3.d.ts} +5 -5
  445. package/dist/{types-6rocye-y.d.ts → types-CbOUc5IH.d.ts} +4 -4
  446. package/dist/{types-6BdhkmZe.d.ts → types-CoE5Zwy4.d.ts} +8 -0
  447. package/dist/{types-DGs5L0VN.d.ts → types-DSJ3-m9X.d.ts} +4 -4
  448. package/dist/{queue-CLJurhdy.d.ts → types-D__3EN0q.d.ts} +17 -19
  449. package/dist/{usage-CrvrL2vw.d.ts → usage-D0NNUFfr.d.ts} +3 -3
  450. package/dist/{vault-wlbBhqm7.d.ts → vault-BpmApxxW.d.ts} +3 -3
  451. package/dist/vercel-connect/index.d.ts +1 -1
  452. package/dist/vercel-connect/index.js +5 -11
  453. package/dist/{verify-DPuWngD4.d.ts → verify-C91Wyp40.d.ts} +5 -35
  454. package/dist/verify-CJbYfADA.js +124 -0
  455. package/dist/{version--AolB5ej.js → version-Cq8gfDbd.js} +1 -1
  456. package/dist/{view-BeFcRV6G.js → view-D5ryq3gz.js} +1 -1
  457. package/dist/{view-CF7ihnkg.d.ts → view-TpXEUcVN.d.ts} +3 -3
  458. package/dist/vue/index.d.ts +9 -18
  459. package/dist/vue/index.js +2 -2
  460. package/dist/{watch-Xuxrvxq-.js → watch-BcvtAHOd.js} +2 -2
  461. package/dist/{watch-DI34G86j.d.ts → watch-COzRWvVN.d.ts} +23 -9
  462. package/dist/{wire-DtZQ4sdE.js → wire-Df3EWkG8.js} +2 -2
  463. package/dist/{workflow-builder-DJ1oHn8g.js → workflow-builder-CHqHpAVt.js} +6 -5
  464. package/dist/workflow-sdk/builder/index.d.ts +3 -3
  465. package/dist/workflow-sdk/index.d.ts +1 -1
  466. package/dist/workflow-sdk/world/index.d.ts +23 -17
  467. package/dist/workflow-sdk/world/index.js +59 -76
  468. package/dist/{workflow-sdk-B3yLD6Br.d.ts → workflow-sdk-DTZyrvNo.d.ts} +3 -3
  469. package/dist/{workflow-sdk-world-D-prir6O.js → workflow-sdk-world-CMV1ahFW.js} +528 -526
  470. package/dist/{workflows-B0j9WKPu.d.ts → workflows-CcpCBfIe.d.ts} +3 -3
  471. package/dist/{workflows-wu1WWBn7.js → workflows-IvxzG2cl.js} +5 -4
  472. package/package.json +54 -3
  473. package/schemas/config-v1.json +243 -0
  474. package/schemas/doctor-report-v1.json +4 -1
  475. package/schemas/spec-manifest-v1.json +95 -0
  476. package/skills/better-supabase/SKILL.md +8 -4
  477. package/skills/better-supabase/references/troubleshooting.md +20 -20
  478. package/skills/better-supabase-api/references/expo.md +6 -3
  479. package/skills/better-supabase-api/references/powersync.md +2 -1
  480. package/skills/better-supabase-auth/SKILL.md +8 -4
  481. package/dist/cli/config-B9HkL8nF.js +0 -2
  482. package/dist/cli/gen-AIf4MREI.js +0 -3100
  483. package/dist/cli/gen-DSrahEdX.js +0 -2
  484. package/dist/cli/prompts-BTYQGunc.js +0 -2
  485. package/dist/cli/run-BO052mki.js +0 -361
  486. package/dist/config-Dn7F5k9A.js +0 -202
  487. package/dist/history-BZih6SFP.js +0 -64
  488. package/dist/index-BkWT_uBO.d.ts +0 -51
  489. package/dist/index-Bxih3l0u.d.ts +0 -81
  490. package/dist/index-CaxrMD1A.d.ts +0 -1
  491. package/dist/index-DQh4VCc9.d.ts +0 -98
  492. package/dist/keys-4MnkWTTh.js +0 -35
  493. package/dist/messages-DYP0sUTe.d.ts +0 -59
  494. package/dist/modules-dxrVK3ID.js +0 -228
  495. package/dist/path-Cv__-OTj.d.ts +0 -17
  496. package/dist/resource-BsvzCMlX.js +0 -212
  497. package/dist/resource-IPS5xi9q.d.ts +0 -74
  498. package/dist/template-CwO38Do8.d.ts +0 -6
  499. package/dist/verify-DL41hbvY.js +0 -232
  500. package/dist/cli/{read-sets-CETOSFx4.js → read-sets-DjJrm8Wj.js} +1 -1
@@ -1,105 +1,28 @@
1
- import { a as list, r as defineCliCommand } from "./command-CK14fP91.js";
2
- import { n as CliError } from "./errors-4v4DTtda.js";
3
- import { i as writeIfChanged, t as display } from "./io-DI1mTdSA.js";
4
- import { i as plain, r as painter } from "./style-C0NFdJRL.js";
5
- import { t as VERSION } from "./version-Bp4fyubI.js";
6
- import { s as providerLabel, t as compiledReadSets } from "./read-sets-CETOSFx4.js";
7
- import { s as stdinDatabaseUrl } from "./config-NiPxAmUF.js";
8
- import { c as migrationCommand, d as schemaPaths, i as findRepoRoot, l as pgFunctionHooks, p as tomlGet, r as diffEngine, s as httpHooks, u as readSupabaseToml } from "./supabase-toml-B-bIukQF.js";
1
+ import { a as list, r as defineCliCommand } from "./command-DV-StG1x.js";
2
+ import { n as CliError, r as errorText } from "./errors-CqTLXe2M.js";
3
+ import { a as writeIfChanged, i as sameText, t as display } from "./io-CFzJVJ68.js";
4
+ import { i as plain, r as painter } from "./style-CB3vxgh0.js";
5
+ import { t as VERSION } from "./version-B4k0aUxS.js";
6
+ import { t as CACHE_DIR } from "./cache-CIfA-jBV.js";
9
7
  import { t as byCodePoint } from "./compare-BmIWVEui.js";
10
- import { A as exposed, C as MetadataRejectedError, D as accessModule, E as AUTHORIZATION_RULES, F as qualified, I as tableObject, M as lineOf, N as permissionCatalogKeys, O as entitlementsModule, P as policyObject, S as configFor, _ as METADATA_GAPS_TEXT, a as renderFiles, c as loadSnapshot, j as exposedSchemas, k as catalogOf, l as managementTarget, p as snapshotFile, r as readMetadataSnapshot, u as openSource, v as CACHE_DIR } from "./gen-AIf4MREI.js";
11
- import { n as withSpinner } from "./prompts-BNcNfAve.js";
12
- import { t as connect } from "./db-DOBPt660.js";
8
+ import { h as satisfies, m as peerVersions, t as MetadataRejectedError } from "./typegen-Demi5-VQ.js";
9
+ import { s as configFor } from "./emit-BHHfwUoT.js";
10
+ import { _ as tableObject, a as METADATA_GAPS_TEXT, c as accessModule, d as exposed, f as exposedSchemas, g as qualified, h as policyObject, l as entitlementsModule, m as permissionCatalogKeys, p as lineOf, s as AUTHORIZATION_RULES, u as catalogOf, y as renderFiles } from "./run-DuN1MX-7.js";
11
+ import { s as providerLabel, t as compiledReadSets } from "./read-sets-DjJrm8Wj.js";
12
+ import { c as stdinDatabaseUrl } from "./config-M-WzL9O2.js";
13
+ import { c as migrationCommand, d as schemaPaths, i as findRepoRoot, l as pgFunctionHooks, p as tomlGet, r as diffEngine, s as httpHooks, u as readSupabaseToml } from "./supabase-toml-B-bIukQF.js";
14
+ import { t as connect } from "./db-BkcfOlyB.js";
15
+ import { c as isSqliteLiteDriver, n as managementTarget, o as snapshotFile, r as openSource, s as liteDriverOf, t as loadSnapshot } from "./snapshot-Bstk6ulj.js";
13
16
  import { n as moduleLayoutFor } from "./sql-layout-D6cphHT3.js";
17
+ import { n as readMetadataSnapshot } from "./metadata-DSRKCaf-.js";
18
+ import { n as withSpinner } from "./prompts-DZJB1nTw.js";
14
19
  import { dirname, resolve } from "node:path";
15
20
  import { existsSync } from "node:fs";
16
21
  import { glob, mkdir, readFile, readdir, writeFile } from "node:fs/promises";
22
+ import { createHash } from "node:crypto";
17
23
  import { DEFAULT_ACTIVE_TENANT, tenantClaimPaths } from "better-supabase/config";
18
24
  import { SQL_MODULES, contractSignature, customContracts, migrationOptionUses, moduleDeprecations, moduleEventTriggers, moduleFileVersion, moduleLayout, moduleVersion, renderModules, sameModuleFile, sharedRolesProblems } from "better-supabase/sql";
19
- import { createHash } from "node:crypto";
20
25
  import { defineBucket, parseSize } from "better-supabase/storage";
21
- //#region src/cli/doctor/advisors.ts
22
- /**
23
- * splinter (https://github.com/supabase/splinter), the linter behind the
24
- * dashboard's Security and Performance Advisors. It has no license, so it is
25
- * downloaded at this commit and checked against the hash instead of bundled.
26
- */
27
- const SPLINTER_COMMIT = "e74a9e36cb12258cb67d1464bc1cb196e9cd8446";
28
- const SPLINTER_SHA256 = "d8d558baad3e03832e521c527907fa50a9a172fabd899dd0f5c2504a5a0e9349";
29
- const SPLINTER_URL = `https://raw.githubusercontent.com/supabase/splinter/${SPLINTER_COMMIT}/splinter.sql`;
30
- function isLint(value) {
31
- const lint = value;
32
- return typeof lint === "object" && lint !== null && typeof lint.name === "string" && typeof lint.level === "string" && Array.isArray(lint.categories);
33
- }
34
- /** The hosted project's advisors (`GET /v1/projects/{ref}/advisors/{category}`). */
35
- function managementAdvisors(options) {
36
- const base = (options.apiUrl ?? "https://api.supabase.com").replace(/\/$/, "");
37
- const doFetch = options.fetch ?? fetch;
38
- return {
39
- describe: `project ${options.projectRef} advisors (Management API)`,
40
- async lints(category) {
41
- const url = `${base}/v1/projects/${encodeURIComponent(options.projectRef)}/advisors/${category}`;
42
- const response = await doFetch(url, { headers: { authorization: `Bearer ${options.accessToken}` } });
43
- const text = await response.text();
44
- if (!response.ok) throw new Error(`Management API ${category} advisors failed (${response.status}): ${text.slice(0, 300)}`);
45
- const body = JSON.parse(text);
46
- if (!Array.isArray(body.lints)) throw new TypeError(`Management API ${category} advisors returned no "lints".`);
47
- return body.lints.filter(isLint);
48
- }
49
- };
50
- }
51
- /** The `[api] schemas` list of a `config.toml`, when it names any. */
52
- function apiSchemas(document) {
53
- const value = document ? tomlGet(document, ["api", "schemas"]) : void 0;
54
- if (!Array.isArray(value)) return [];
55
- return value.filter((schema) => typeof schema === "string" && schema.trim() !== "");
56
- }
57
- const literal$1 = (value) => `'${value.replaceAll("'", "''")}'`;
58
- /** The read-only transaction splinter runs in, with `pgrst.db_schemas` set first. */
59
- function splinterScript(sql, schemas = []) {
60
- return `begin read only;\n${schemas.length > 0 ? `set local pgrst.db_schemas = ${literal$1(schemas.join(","))};\n` : ""}${sql}\n;\nrollback;`;
61
- }
62
- const sha256 = (text) => createHash("sha256").update(text).digest("hex");
63
- /** Downloads (once) and verifies the pinned `splinter.sql`. */
64
- async function splinterSql(options) {
65
- const file = resolve(options.cacheDir, `splinter-${SPLINTER_COMMIT}.sql`);
66
- if (existsSync(file)) {
67
- const cached = await readFile(file, "utf8");
68
- if (sha256(cached) === SPLINTER_SHA256) return cached;
69
- }
70
- const response = await (options.fetch ?? fetch)(SPLINTER_URL);
71
- if (!response.ok) throw new Error(`Downloading splinter.sql failed (${response.status}) from ${SPLINTER_URL}`);
72
- const text = await response.text();
73
- if (sha256(text) !== SPLINTER_SHA256) throw new Error(`splinter.sql from ${SPLINTER_URL} does not match the pinned hash; refusing to run it.`);
74
- await mkdir(dirname(file), { recursive: true });
75
- await writeFile(file, text);
76
- return text;
77
- }
78
- /** `pg` returns one result per statement for a multi-statement query. */
79
- function lintRows(result) {
80
- const results = Array.isArray(result) ? result : [result];
81
- return results.find((entry) => entry.fields?.some((field) => field.name === "cache_key"))?.rows ?? results.at(-1)?.rows ?? [];
82
- }
83
- /**
84
- * Runs splinter against a database (local stack, `$DATABASE_URL` or `--db-url-stdin`) in a
85
- * read-only transaction that is rolled back.
86
- */
87
- function splinterAdvisors(queryable, describe, options) {
88
- let all;
89
- const run = async () => {
90
- const sql = await splinterSql(options);
91
- return lintRows(await queryable.query(splinterScript(sql, options.schemas))).filter(isLint);
92
- };
93
- return {
94
- describe: `${describe} (splinter ${SPLINTER_COMMIT.slice(0, 7)})`,
95
- async lints(category) {
96
- all ??= run();
97
- const wanted = category.toUpperCase();
98
- return (await all).filter((lint) => lint.categories.includes(wanted));
99
- }
100
- };
101
- }
102
- //#endregion
103
26
  //#region src/cli/doctor/advisor-rules.ts
104
27
  /** One request per advisor category, shared by the advisor rules and the rules that defer to them. */
105
28
  const fetched = /* @__PURE__ */ new WeakMap();
@@ -163,7 +86,7 @@ function advisorRule(code, category, title, description) {
163
86
  try {
164
87
  return (await lintsOf(advisors, category)).map(lintFinding);
165
88
  } catch (cause) {
166
- return [{ message: `The ${category} advisor could not run (${advisors.describe}): ${cause instanceof Error ? cause.message : String(cause)}` }];
89
+ return [{ message: `The ${category} advisor could not run (${advisors.describe}): ${errorText(cause)}` }];
167
90
  }
168
91
  }
169
92
  };
@@ -247,6 +170,18 @@ const COOKIE_RULES = [{
247
170
  check: encodingDrift
248
171
  }];
249
172
  //#endregion
173
+ //#region src/cli/doctor/dependencies.ts
174
+ const DEPENDENCY_RULES = [{
175
+ code: "BS601",
176
+ severity: "warning",
177
+ title: "Peer outside its range",
178
+ description: "An optional peer of better-supabase is installed at a version outside the range better-supabase declares. With strict peer checks the install fails, and the subpath that needs the peer can break at runtime.",
179
+ check: (context) => (context.peers ?? []).flatMap((peer) => peer.installed !== void 0 && satisfies(peer.installed, peer.range) === false ? [{
180
+ message: `${peer.name}@${peer.installed} is installed, but better-supabase needs ${peer.range}. Install a version in that range, or remove ${peer.name} if nothing imports it.`,
181
+ target: peer.name
182
+ }] : [])
183
+ }];
184
+ //#endregion
250
185
  //#region src/cli/doctor/live.ts
251
186
  /** Statements slower than this (ms, mean) with more calls than `SLOW_CALLS` are BS209. */
252
187
  const SLOW_MEAN_MS = 50;
@@ -255,8 +190,7 @@ const SLOW_CALLS = 1e3;
255
190
  const EXPLAIN_LIMIT = 1e3;
256
191
  const escape$2 = (name) => name.replaceAll(/[.*+?^${}()|[\]\\]/g, "\\$&");
257
192
  const ident$1 = (name) => `"${name.replaceAll("\"", "\"\"")}"`;
258
- const literal = (text) => `'${text.replaceAll("'", "''")}'`;
259
- const errorText = (cause) => cause instanceof Error ? cause.message : String(cause);
193
+ const literal$1 = (text) => `'${text.replaceAll("'", "''")}'`;
260
194
  const oneLine = (query, max = 160) => {
261
195
  const flat = query.replaceAll(/\s+/g, " ").trim();
262
196
  return flat.length > max ? `${flat.slice(0, max - 1)}…` : flat;
@@ -328,7 +262,7 @@ async function explainTable(db, table, claims) {
328
262
  tracked = false;
329
263
  await db.query("rollback to savepoint bs_track");
330
264
  }
331
- await db.query(`select set_config('request.jwt.claims', ${literal(JSON.stringify(claims))}, true)`);
265
+ await db.query(`select set_config('request.jwt.claims', ${literal$1(JSON.stringify(claims))}, true)`);
332
266
  const before = tracked ? await functionTimes(db) : /* @__PURE__ */ new Map();
333
267
  await db.query(`set local role ${ident$1(role)}`);
334
268
  const [row] = await db.query(`explain (analyze, buffers, format json) select * from ${ident$1(table.schema)}.${ident$1(table.name)} limit ${EXPLAIN_LIMIT}`);
@@ -433,7 +367,7 @@ const LIVE_RULES = [
433
367
  const db = live(context);
434
368
  if (!db || "skipped" in db || !db.session) return [{
435
369
  severity: "warning",
436
- message: `--explain needs a direct database connection (local stack, $DATABASE_URL or --db-url-stdin)${db && "skipped" in db ? `: ${db.skipped}` : "."}`
370
+ message: `--explain needs a direct database connection (local stack, $DATABASE_URL, $SUPABASE_DB_URL or --db-url-stdin)${db && "skipped" in db ? `: ${db.skipped}` : "."}`
437
371
  }];
438
372
  const who = typeof request.claims["sub"] === "string" ? `${String(request.claims["role"] ?? "anon")} ${request.claims["sub"]}` : String(request.claims["role"] ?? "anon");
439
373
  const findings = [];
@@ -679,12 +613,12 @@ async function withHookEvent(db, userId, run) {
679
613
  'amr', jsonb_build_array(jsonb_build_object(
680
614
  'method', 'password', 'timestamp', extract(epoch from now())::int8
681
615
  )),
682
- 'iss', ${literal(DOCTOR_ISSUER)},
616
+ 'iss', ${literal$1(DOCTOR_ISSUER)},
683
617
  'iat', extract(epoch from now())::int8,
684
618
  'exp', extract(epoch from now())::int8 + 3600
685
619
  )
686
620
  )::text, true) as event
687
- from auth.users u where u.id = ${literal(userId)}::uuid`);
621
+ from auth.users u where u.id = ${literal$1(userId)}::uuid`);
688
622
  if (!user?.event) return void 0;
689
623
  const [role] = await db.query(`select case when exists(select 1 from pg_roles where rolname = 'supabase_auth_admin')
690
624
  then pg_has_role('supabase_auth_admin', 'member') else false end as member`);
@@ -705,8 +639,8 @@ async function hookClaims(db, fn, userId) {
705
639
  });
706
640
  }
707
641
  async function hookClaimsSize(db, fn, userId, budget) {
708
- const budgetSql = budget && budget.claims.length > 0 ? budget.claims.map((claim) => `coalesce(octet_length((c -> ${literal(claim)})::text), 0)`).join(" + ") : "0";
709
- const truncatedSql = budget?.truncatedClaim ? `c ->> ${literal(budget.truncatedClaim)} = 'true'` : "false";
642
+ const budgetSql = budget && budget.claims.length > 0 ? budget.claims.map((claim) => `coalesce(octet_length((c -> ${literal$1(claim)})::text), 0)`).join(" + ") : "0";
643
+ const truncatedSql = budget?.truncatedClaim ? `c ->> ${literal$1(budget.truncatedClaim)} = 'true'` : "false";
710
644
  return withHookEvent(db, userId, async () => {
711
645
  const [row] = await db.query(`select octet_length(c::text) as bytes,
712
646
  octet_length((c -> 'memberships')::text) as memberships,
@@ -799,7 +733,7 @@ const HOOK_RULES = [
799
733
  if (!db || "skipped" in db || !db.session) {
800
734
  findings.push({
801
735
  severity: "info",
802
- message: `Measuring the hook's claims needs a direct database connection (local stack, $DATABASE_URL or --db-url-stdin)${db && "skipped" in db ? `: ${db.skipped}` : "."}`,
736
+ message: `Measuring the hook's claims needs a direct database connection (local stack, $DATABASE_URL, $SUPABASE_DB_URL or --db-url-stdin)${db && "skipped" in db ? `: ${db.skipped}` : "."}`,
803
737
  target: `${signatureOf(fn)}:claims`
804
738
  });
805
739
  continue;
@@ -937,6 +871,68 @@ const HOOK_RULES = [
937
871
  }
938
872
  ];
939
873
  //#endregion
874
+ //#region src/cli/doctor/lite.ts
875
+ const RPC_CALL = /(?:\.|\$)rpc\s*\(|\brpcTransport\s*\(/;
876
+ const MISSING_FEATURES = [{
877
+ feature: "Realtime",
878
+ pattern: /from\s+["']better-supabase\/realtime["']|\.channel\s*\(|\.removeChannel\s*\(/
879
+ }, {
880
+ feature: "Edge Functions",
881
+ pattern: /\.functions\.invoke\s*\(|\bfunctions\(\)\.invoke\s*\(/
882
+ }];
883
+ /** The `[db] driver` of a Supabase Lite project, or `undefined` for any other project. */
884
+ function liteDriver(context) {
885
+ try {
886
+ return liteDriverOf(context.configToml);
887
+ } catch {
888
+ return;
889
+ }
890
+ }
891
+ function rpcOnSqlite(context) {
892
+ const driver = liteDriver(context);
893
+ if (driver === void 0 || !isSqliteLiteDriver(driver)) return [];
894
+ return context.sources.flatMap((file) => {
895
+ const line = lineOf(file.text, RPC_CALL);
896
+ if (line === void 0) return [];
897
+ return [{
898
+ message: `${file.path} calls a Postgres function, but Supabase Lite's ${driver} driver has no rpc(), so the call returns an unsupported error. Switch [db] driver to "pglite" or "postgres" in supabase/config.toml, or replace the function with table queries.`,
899
+ target: `${file.path}:rpc`,
900
+ location: {
901
+ file: file.path,
902
+ line
903
+ }
904
+ }];
905
+ });
906
+ }
907
+ function missingLiteFeature(context) {
908
+ if (liteDriver(context) === void 0) return [];
909
+ return context.sources.flatMap((file) => MISSING_FEATURES.flatMap(({ feature, pattern }) => {
910
+ const line = lineOf(file.text, pattern);
911
+ if (line === void 0) return [];
912
+ return [{
913
+ message: `${file.path} uses ${feature}, which Supabase Lite does not implement on any driver. Run the full Supabase stack for this feature, or move the project off Lite with \`supabase lite upgrade\`.`,
914
+ target: `${file.path}:${feature}`,
915
+ location: {
916
+ file: file.path,
917
+ line
918
+ }
919
+ }];
920
+ }));
921
+ }
922
+ const LITE_RULES = [{
923
+ code: "BS328",
924
+ severity: "warning",
925
+ title: "rpc() on a Supabase Lite SQLite driver",
926
+ description: "`[db] driver` in `config.toml` is `sqlite-postgres` or `sqlite`, which have no `rpc()`, but the app calls a Postgres function. Those calls return an `unsupported` error.",
927
+ check: rpcOnSqlite
928
+ }, {
929
+ code: "BS329",
930
+ severity: "warning",
931
+ title: "Feature Supabase Lite does not implement",
932
+ description: "`config.toml` sets `[db] driver`, so the project runs on Supabase Lite, but the app uses Realtime or Edge Functions, which Lite does not implement.",
933
+ check: missingLiteFeature
934
+ }];
935
+ //#endregion
940
936
  //#region src/cli/doctor/metadata.ts
941
937
  /**
942
938
  * Rules that read what a `GeneratorMetadata` document leaves out (policies,
@@ -1114,7 +1110,7 @@ async function missingContracts(context) {
1114
1110
  name: check.name
1115
1111
  }
1116
1112
  }));
1117
- const names = checks.map((check) => `(${literal(check.schema)}, ${literal(check.name)})`).join(", ");
1113
+ const names = checks.map((check) => `(${literal$1(check.schema)}, ${literal$1(check.name)})`).join(", ");
1118
1114
  let rows;
1119
1115
  try {
1120
1116
  rows = await live.query(`select n.nspname as schema, p.proname as name,
@@ -2623,7 +2619,7 @@ const RULES = [
2623
2619
  code: "BS106",
2624
2620
  severity: "error",
2625
2621
  title: "Table not granted to the Data API",
2626
- description: "Supabase no longer grants new tables to anon and authenticated. Without a grant, every Data API request fails with 42501 before RLS runs. Tables in `expose` need the privileges listed there; other tables need `select` for authenticated, except tables with no permissive policy under `sql.modules.grants.options.fromPolicies`, which are service-only. Tables marked `serviceRole` in `tables` must have no grants for either role.",
2622
+ description: "Supabase no longer grants new tables to anon and authenticated. Without a grant, every Data API request fails with 42501 before RLS runs. Tables in `expose` need the privileges listed there; other tables need `select` for authenticated, except tables with RLS on and no permissive policy under `sql.modules.grants.options.fromPolicies`, which are service-only. Tables marked `serviceRole` in `tables` must have no grants for either role.",
2627
2623
  check: (context) => {
2628
2624
  const auto = context.configToml ? tomlGet(context.configToml.document, ["api", "auto_expose_new_tables"]) : void 0;
2629
2625
  const note = auto === false || auto === "false" ? " config.toml sets [api] auto_expose_new_tables = false, so new tables start without grants." : "";
@@ -2826,7 +2822,7 @@ const RULES = [
2826
2822
  const stale = [];
2827
2823
  for (const file of await renderFiles(context.config, context.snapshot)) {
2828
2824
  const current = await readFile(resolve(context.config.root, file.path), "utf8").catch(() => void 0);
2829
- if (current !== file.contents) stale.push({
2825
+ if (!sameText(current, file.contents)) stale.push({
2830
2826
  message: `${file.path} is ${current === void 0 ? "missing" : "out of date"}. Run \`better-supabase gen\`.`,
2831
2827
  target: file.path,
2832
2828
  ...current === void 0 ? {} : { location: {
@@ -2965,7 +2961,7 @@ const RULES = [
2965
2961
  title: "Local stack signs tokens with a shared secret",
2966
2962
  description: "Hosted projects sign with asymmetric keys. Using the same locally means local tokens verify through JWKS just like production.",
2967
2963
  check: (context) => {
2968
- if (!context.configToml || authSetting(context, "signing_keys_path")) return [];
2964
+ if (!context.configToml || authSetting(context, "signing_keys_path") || tomlGet(context.configToml.document, ["db", "driver"]) !== void 0) return [];
2969
2965
  const location = tomlLocation(context, "signing_keys_path");
2970
2966
  return [{
2971
2967
  message: "No [auth] signing_keys_path. Run `better-supabase keys` to sign local tokens with ES256.",
@@ -3033,7 +3029,9 @@ const RULES = [
3033
3029
  ...AUTHORIZATION_RULES,
3034
3030
  ...LIVE_RULES,
3035
3031
  ...MODULE_RULES,
3036
- ...PGDELTA_RULES
3032
+ ...PGDELTA_RULES,
3033
+ ...LITE_RULES,
3034
+ ...DEPENDENCY_RULES
3037
3035
  ].sort((a, b) => byCodePoint(a.code, b.code));
3038
3036
  const RULE_CODES = RULES.map((rule) => rule.code);
3039
3037
  async function runRules(context, rules = RULES) {
@@ -3167,75 +3165,7 @@ function formatReport(findings, options) {
3167
3165
  }
3168
3166
  }
3169
3167
  //#endregion
3170
- //#region src/cli/commands/doctor.ts
3171
- const ARGS = {
3172
- format: {
3173
- type: "string",
3174
- description: "text (default), sarif (code scanning) or github (workflow annotations); --json for the JSON report",
3175
- valueHint: "format"
3176
- },
3177
- out: {
3178
- type: "string",
3179
- description: "Write the report to a file",
3180
- valueHint: "file"
3181
- },
3182
- only: {
3183
- type: "string",
3184
- description: "Run only these checks, e.g. --only BS100,BS304",
3185
- valueHint: "codes"
3186
- },
3187
- ignore: {
3188
- type: "string",
3189
- description: "Skip checks; also doctor.ignore in the config",
3190
- valueHint: "codes"
3191
- },
3192
- strict: {
3193
- type: "boolean",
3194
- description: "Fail on warnings; also doctor.strict"
3195
- },
3196
- snapshot: {
3197
- type: "string",
3198
- description: "Check a saved snapshot instead of the database",
3199
- valueHint: "file"
3200
- },
3201
- metadata: {
3202
- type: "string",
3203
- description: "Check a GeneratorMetadata document (- for stdin); checks it lacks data for are skipped",
3204
- valueHint: "path|-"
3205
- },
3206
- "db-url-stdin": {
3207
- type: "boolean",
3208
- description: "Read the connection string from stdin instead of $DATABASE_URL or the config"
3209
- },
3210
- "project-ref": {
3211
- type: "string",
3212
- description: "Read a hosted project through the Management API",
3213
- valueHint: "ref"
3214
- },
3215
- stats: {
3216
- type: "boolean",
3217
- description: "Report slow frequent statements from pg_stat_statements (BS209)"
3218
- },
3219
- explain: {
3220
- type: "string",
3221
- description: "EXPLAIN ANALYZE these tables under RLS, rolled back (BS212)",
3222
- valueHint: "tables"
3223
- },
3224
- as: {
3225
- type: "string",
3226
- description: "Plan as this authenticated user, and measure the claims the custom access token hook returns for them (BS405)",
3227
- valueHint: "uuid"
3228
- },
3229
- claims: {
3230
- type: "string",
3231
- description: "Plan with these JWT claims ({\"role\":\"authenticated\",...})",
3232
- valueHint: "json"
3233
- },
3234
- "fix-grants": {
3235
- type: "boolean",
3236
- description: "Print the grant and revoke SQL BS404 asks for, to add to your schema or migration"
3237
- }
3238
- };
3168
+ //#region src/cli/doctor/inputs.ts
3239
3169
  const ENV_FILES = [
3240
3170
  ".env",
3241
3171
  ".env.local",
@@ -3276,44 +3206,90 @@ async function sourceFiles(config) {
3276
3206
  });
3277
3207
  return files.sort((a, b) => byCodePoint(a.path, b.path));
3278
3208
  }
3279
- const escape = (name) => name.replaceAll(/[.*+?^${}()|[\]\\]/g, "\\$&");
3280
- /** Where a table, function or policy is declared: declarative schemas first, then the newest migration. */
3281
- function locate(files, object) {
3282
- const name = `"?${escape(object.name)}"?`;
3283
- const qualifiedName = `(?:"?${escape(object.schema)}"?\\.)?${name}`;
3284
- if (object.kind === "policy" && object.table !== void 0) {
3285
- const onTable = new RegExp(`create\\s+policy\\s+${name}\\s+on\\s+(?:only\\s+)?(?:"?${escape(object.schema)}"?\\.)?"?${escape(object.table)}"?(?:\\s|;|$)`, "i");
3286
- for (const file of files) {
3287
- const match = onTable.exec(file.text);
3288
- if (match) return {
3289
- file: file.path,
3290
- line: file.text.slice(0, match.index).split("\n").length
3291
- };
3209
+ //#endregion
3210
+ //#region src/cli/doctor/advisors.ts
3211
+ /**
3212
+ * splinter (https://github.com/supabase/splinter), the linter behind the
3213
+ * dashboard's Security and Performance Advisors. It has no license, so it is
3214
+ * downloaded at this commit and checked against the hash instead of bundled.
3215
+ */
3216
+ const SPLINTER_COMMIT = "e74a9e36cb12258cb67d1464bc1cb196e9cd8446";
3217
+ const SPLINTER_SHA256 = "d8d558baad3e03832e521c527907fa50a9a172fabd899dd0f5c2504a5a0e9349";
3218
+ const SPLINTER_URL = `https://raw.githubusercontent.com/supabase/splinter/${SPLINTER_COMMIT}/splinter.sql`;
3219
+ function isLint(value) {
3220
+ const lint = value;
3221
+ return typeof lint === "object" && lint !== null && typeof lint.name === "string" && typeof lint.level === "string" && Array.isArray(lint.categories);
3222
+ }
3223
+ /** The hosted project's advisors (`GET /v1/projects/{ref}/advisors/{category}`). */
3224
+ function managementAdvisors(options) {
3225
+ const base = (options.apiUrl ?? "https://api.supabase.com").replace(/\/$/, "");
3226
+ const doFetch = options.fetch ?? fetch;
3227
+ return {
3228
+ describe: `project ${options.projectRef} advisors (Management API)`,
3229
+ async lints(category) {
3230
+ const url = `${base}/v1/projects/${encodeURIComponent(options.projectRef)}/advisors/${category}`;
3231
+ const response = await doFetch(url, { headers: { authorization: `Bearer ${options.accessToken}` } });
3232
+ const text = await response.text();
3233
+ if (!response.ok) throw new Error(`Management API ${category} advisors failed (${response.status}): ${text.slice(0, 300)}`);
3234
+ const body = JSON.parse(text);
3235
+ if (!Array.isArray(body.lints)) throw new TypeError(`Management API ${category} advisors returned no "lints".`);
3236
+ return body.lints.filter(isLint);
3292
3237
  }
3293
- return;
3294
- }
3295
- const pattern = object.kind === "table" ? new RegExp(`create\\s+(?:unlogged\\s+)?table\\s+(?:if\\s+not\\s+exists\\s+)?${qualifiedName}(?:\\s|\\(|$)`, "i") : object.kind === "function" ? new RegExp(`create\\s+(?:or\\s+replace\\s+)?function\\s+${qualifiedName}\\s*\\(`, "i") : new RegExp(`create\\s+policy\\s+${name}`, "i");
3296
- for (const file of files) {
3297
- const line = lineOf(file.text, pattern);
3298
- if (line) return {
3299
- file: file.path,
3300
- line
3301
- };
3302
- }
3238
+ };
3303
3239
  }
3304
- const FLAG_FORMATS = DOCTOR_FORMATS.filter((format) => format !== "json");
3305
- /** `--json` picks the JSON report; `--format` picks between the others. */
3306
- function reportFormat(args) {
3307
- if (args.format === "json") throw new CliError("usage", "--format json is now the global --json flag");
3308
- if (args.json === true) {
3309
- if (args.format !== void 0) throw new CliError("usage", "Pass --json or --format, not both");
3310
- return "json";
3240
+ /** The `[api] schemas` list of a `config.toml`, when it names any. */
3241
+ function apiSchemas(document) {
3242
+ const value = document ? tomlGet(document, ["api", "schemas"]) : void 0;
3243
+ if (!Array.isArray(value)) return [];
3244
+ return value.filter((schema) => typeof schema === "string" && schema.trim() !== "");
3245
+ }
3246
+ const literal = (value) => `'${value.replaceAll("'", "''")}'`;
3247
+ /** The read-only transaction splinter runs in, with `pgrst.db_schemas` set first. */
3248
+ function splinterScript(sql, schemas = []) {
3249
+ return `begin read only;\n${schemas.length > 0 ? `set local pgrst.db_schemas = ${literal(schemas.join(","))};\n` : ""}${sql}\n;\nrollback;`;
3250
+ }
3251
+ const sha256 = (text) => createHash("sha256").update(text).digest("hex");
3252
+ /** Downloads (once) and verifies the pinned `splinter.sql`. */
3253
+ async function splinterSql(options) {
3254
+ const file = resolve(options.cacheDir, `splinter-${SPLINTER_COMMIT}.sql`);
3255
+ if (existsSync(file)) {
3256
+ const cached = await readFile(file, "utf8");
3257
+ if (sha256(cached) === SPLINTER_SHA256) return cached;
3311
3258
  }
3312
- if (args.format === void 0) return "text";
3313
- const format = FLAG_FORMATS.find((candidate) => candidate === args.format);
3314
- if (!format) throw new CliError("usage", `--format must be one of ${FLAG_FORMATS.join(", ")}`);
3315
- return format;
3259
+ const response = await (options.fetch ?? fetch)(SPLINTER_URL);
3260
+ if (!response.ok) throw new Error(`Downloading splinter.sql failed (${response.status}) from ${SPLINTER_URL}`);
3261
+ const text = await response.text();
3262
+ if (sha256(text) !== SPLINTER_SHA256) throw new Error(`splinter.sql from ${SPLINTER_URL} does not match the pinned hash; refusing to run it.`);
3263
+ await mkdir(dirname(file), { recursive: true });
3264
+ await writeFile(file, text);
3265
+ return text;
3266
+ }
3267
+ /** `pg` returns one result per statement for a multi-statement query. */
3268
+ function lintRows(result) {
3269
+ const results = Array.isArray(result) ? result : [result];
3270
+ return results.find((entry) => entry.fields?.some((field) => field.name === "cache_key"))?.rows ?? results.at(-1)?.rows ?? [];
3271
+ }
3272
+ /**
3273
+ * Runs splinter against a database (local stack, `$DATABASE_URL` or `--db-url-stdin`) in a
3274
+ * read-only transaction that is rolled back.
3275
+ */
3276
+ function splinterAdvisors(queryable, describe, options) {
3277
+ let all;
3278
+ const run = async () => {
3279
+ const sql = await splinterSql(options);
3280
+ return lintRows(await queryable.query(splinterScript(sql, options.schemas))).filter(isLint);
3281
+ };
3282
+ return {
3283
+ describe: `${describe} (splinter ${SPLINTER_COMMIT.slice(0, 7)})`,
3284
+ async lints(category) {
3285
+ all ??= run();
3286
+ const wanted = category.toUpperCase();
3287
+ return (await all).filter((lint) => lint.categories.includes(wanted));
3288
+ }
3289
+ };
3316
3290
  }
3291
+ //#endregion
3292
+ //#region src/cli/doctor/live-source.ts
3317
3293
  /** Checks that read the database itself rather than the snapshot. */
3318
3294
  const LIVE_CODES = /* @__PURE__ */ new Set([
3319
3295
  "BS100",
@@ -3331,7 +3307,7 @@ function openLive(config, env, source, pg) {
3331
3307
  const none = { close: () => Promise.resolve() };
3332
3308
  const file = snapshotFile(config, source);
3333
3309
  if (file) {
3334
- const skipped = `reading the saved snapshot ${file}; set $DATABASE_URL, or pass --db-url-stdin or --project-ref, to check a database.`;
3310
+ const skipped = `reading the saved snapshot ${file}; set $DATABASE_URL or $SUPABASE_DB_URL, or pass --db-url-stdin or --project-ref, to check a database.`;
3335
3311
  return {
3336
3312
  ...none,
3337
3313
  advisors: { skipped },
@@ -3375,6 +3351,48 @@ function openLive(config, env, source, pg) {
3375
3351
  close
3376
3352
  };
3377
3353
  }
3354
+ //#endregion
3355
+ //#region src/cli/doctor/locate.ts
3356
+ const escape = (name) => name.replaceAll(/[.*+?^${}()|[\]\\]/g, "\\$&");
3357
+ /** Where a table, function or policy is declared: declarative schemas first, then the newest migration. */
3358
+ function locate(files, object) {
3359
+ const name = `"?${escape(object.name)}"?`;
3360
+ const qualifiedName = `(?:"?${escape(object.schema)}"?\\.)?${name}`;
3361
+ if (object.kind === "policy" && object.table !== void 0) {
3362
+ const onTable = new RegExp(`create\\s+policy\\s+${name}\\s+on\\s+(?:only\\s+)?(?:"?${escape(object.schema)}"?\\.)?"?${escape(object.table)}"?(?:\\s|;|$)`, "i");
3363
+ for (const file of files) {
3364
+ const match = onTable.exec(file.text);
3365
+ if (match) return {
3366
+ file: file.path,
3367
+ line: file.text.slice(0, match.index).split("\n").length
3368
+ };
3369
+ }
3370
+ return;
3371
+ }
3372
+ const pattern = object.kind === "table" ? new RegExp(`create\\s+(?:unlogged\\s+)?table\\s+(?:if\\s+not\\s+exists\\s+)?${qualifiedName}(?:\\s|\\(|$)`, "i") : object.kind === "function" ? new RegExp(`create\\s+(?:or\\s+replace\\s+)?function\\s+${qualifiedName}\\s*\\(`, "i") : new RegExp(`create\\s+policy\\s+${name}`, "i");
3373
+ for (const file of files) {
3374
+ const line = lineOf(file.text, pattern);
3375
+ if (line) return {
3376
+ file: file.path,
3377
+ line
3378
+ };
3379
+ }
3380
+ }
3381
+ //#endregion
3382
+ //#region src/cli/doctor/options.ts
3383
+ const FLAG_FORMATS = DOCTOR_FORMATS.filter((format) => format !== "json");
3384
+ /** `--json` picks the JSON report; `--format`, then `doctor.format`, picks between the others. */
3385
+ function reportFormat(args, configured) {
3386
+ if (args.format === "json") throw new CliError("usage", "--format json is now the global --json flag");
3387
+ if (args.json === true) {
3388
+ if (args.format !== void 0) throw new CliError("usage", "Pass --json or --format, not both");
3389
+ return "json";
3390
+ }
3391
+ if (args.format === void 0) return configured;
3392
+ const format = FLAG_FORMATS.find((candidate) => candidate === args.format);
3393
+ if (!format) throw new CliError("usage", `--format must be one of ${FLAG_FORMATS.join(", ")}`);
3394
+ return format;
3395
+ }
3378
3396
  const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
3379
3397
  /** `--as <uuid>` or `--claims <json>` as `request.jwt.claims`. */
3380
3398
  function explainClaims(args) {
@@ -3397,12 +3415,82 @@ function explainClaims(args) {
3397
3415
  ...parsed
3398
3416
  };
3399
3417
  } catch (cause) {
3400
- return { error: `--claims is not valid JSON: ${cause instanceof Error ? cause.message : String(cause)}` };
3418
+ return { error: `--claims is not valid JSON: ${errorText(cause)}` };
3401
3419
  }
3402
3420
  }
3421
+ //#endregion
3422
+ //#region src/cli/commands/doctor.ts
3423
+ const ARGS = {
3424
+ format: {
3425
+ type: "string",
3426
+ description: "text, sarif (code scanning) or github (workflow annotations); also doctor.format, default text. --json for the JSON report",
3427
+ valueHint: "format"
3428
+ },
3429
+ out: {
3430
+ type: "string",
3431
+ description: "Write the report to a file; also doctor.output",
3432
+ valueHint: "file"
3433
+ },
3434
+ only: {
3435
+ type: "string",
3436
+ description: "Run only these checks, e.g. --only BS100,BS304; also doctor.only",
3437
+ valueHint: "codes"
3438
+ },
3439
+ ignore: {
3440
+ type: "string",
3441
+ description: "Skip checks; also doctor.ignore in the config",
3442
+ valueHint: "codes"
3443
+ },
3444
+ strict: {
3445
+ type: "boolean",
3446
+ description: "Fail on warnings; also doctor.strict"
3447
+ },
3448
+ snapshot: {
3449
+ type: "string",
3450
+ description: "Check a saved snapshot instead of the database",
3451
+ valueHint: "file"
3452
+ },
3453
+ metadata: {
3454
+ type: "string",
3455
+ description: "Check a GeneratorMetadata document (- for stdin); checks it lacks data for are skipped",
3456
+ valueHint: "path|-"
3457
+ },
3458
+ "db-url-stdin": {
3459
+ type: "boolean",
3460
+ description: "Read the connection string from stdin instead of the config, $DATABASE_URL or $SUPABASE_DB_URL"
3461
+ },
3462
+ "project-ref": {
3463
+ type: "string",
3464
+ description: "Read a hosted project through the Management API",
3465
+ valueHint: "ref"
3466
+ },
3467
+ stats: {
3468
+ type: "boolean",
3469
+ description: "Report slow frequent statements from pg_stat_statements (BS209)"
3470
+ },
3471
+ explain: {
3472
+ type: "string",
3473
+ description: "EXPLAIN ANALYZE these tables under RLS, rolled back (BS212)",
3474
+ valueHint: "tables"
3475
+ },
3476
+ as: {
3477
+ type: "string",
3478
+ description: "Plan as this authenticated user, and measure the claims the custom access token hook returns for them (BS405)",
3479
+ valueHint: "uuid"
3480
+ },
3481
+ claims: {
3482
+ type: "string",
3483
+ description: "Plan with these JWT claims ({\"role\":\"authenticated\",...})",
3484
+ valueHint: "json"
3485
+ },
3486
+ "fix-grants": {
3487
+ type: "boolean",
3488
+ description: "Print the grant and revoke SQL BS404 asks for, to add to your schema or migration"
3489
+ }
3490
+ };
3403
3491
  async function runDoctor(config, args, env, options = {}) {
3404
- const format = reportFormat(args);
3405
- const only = list(args.only);
3492
+ const format = reportFormat(args, config.doctor.format);
3493
+ const only = args.only === void 0 ? [...config.doctor.only] : list(args.only);
3406
3494
  const ignore = /* @__PURE__ */ new Set([...config.doctor.ignore, ...list(args.ignore)]);
3407
3495
  const unknown = [...only, ...ignore].filter((code) => !RULE_CODES.includes(code));
3408
3496
  if (unknown.length > 0) return {
@@ -3445,17 +3533,23 @@ async function runDoctor(config, args, env, options = {}) {
3445
3533
  ...options.advisors === void 0 ? {} : { advisors: options.advisors },
3446
3534
  ...options.database === void 0 ? {} : { database: options.database }
3447
3535
  };
3448
- const [snapshot, envFiles, [configToml, sql], gitignore, sources, readSets] = await Promise.all([
3536
+ const [snapshot, envFiles, [configToml, sql], gitignore, sources, readSets, peers] = await Promise.all([
3449
3537
  options.snapshot ?? loadSnapshot(config, env, source, pg, opened.open),
3450
3538
  Promise.all(ENV_FILES.map((path) => readText(config.root, path))).then((files) => files.filter((file) => file !== void 0)),
3451
3539
  readSupabaseToml(config.root).then(async (toml) => [toml, await sqlFiles(config.root, toml)]),
3452
3540
  readText(config.root, ".gitignore"),
3453
3541
  sourceFiles(config),
3454
- compiledReadSets(config).catch((cause) => ({ skipped: cause instanceof Error ? cause.message : String(cause) }))
3542
+ compiledReadSets(config).catch((cause) => ({ skipped: errorText(cause) })),
3543
+ options.peers ?? peerVersions(config.root).catch(() => [])
3455
3544
  ]).catch(async (cause) => {
3456
3545
  await opened.close();
3457
3546
  throw cause;
3458
3547
  });
3548
+ const replay = opened.open ? (await opened.open()).replay : void 0;
3549
+ const live = replay ? {
3550
+ advisors: options.advisors ?? { skipped: replay },
3551
+ database: options.database ?? { skipped: replay }
3552
+ } : opened;
3459
3553
  const context = {
3460
3554
  config,
3461
3555
  snapshot,
@@ -3465,8 +3559,9 @@ async function runDoctor(config, args, env, options = {}) {
3465
3559
  gitignore: gitignore?.text ?? "",
3466
3560
  sources,
3467
3561
  readSets,
3468
- ...opened.advisors ? { advisors: opened.advisors } : {},
3469
- ...opened.database ? { database: opened.database } : {},
3562
+ peers,
3563
+ ...live.advisors ? { advisors: live.advisors } : {},
3564
+ ...live.database ? { database: live.database } : {},
3470
3565
  ...stats ? { stats } : {},
3471
3566
  ...hookUser ? { hookUser } : {},
3472
3567
  ...explainTables.length > 0 ? { explain: {
@@ -3495,7 +3590,7 @@ async function runDoctor(config, args, env, options = {}) {
3495
3590
  location
3496
3591
  } : finding;
3497
3592
  });
3498
- const out = args.out;
3593
+ const out = args.out ?? (format === config.doctor.format ? config.doctor.output : void 0);
3499
3594
  const fromRepo = format === "sarif" || format === "github";
3500
3595
  const repoRoot = findRepoRoot(config.root);
3501
3596
  const repoPath = (file) => display(repoRoot, resolve(config.root, file));
@@ -3571,7 +3666,7 @@ const doctorCommand = defineCliCommand({
3571
3666
  };
3572
3667
  throw cause;
3573
3668
  }
3574
- const skipped = `reading a GeneratorMetadata document; set $DATABASE_URL, or pass --db-url-stdin or --project-ref, to check a database.`;
3669
+ const skipped = `reading a GeneratorMetadata document; set $DATABASE_URL or $SUPABASE_DB_URL, or pass --db-url-stdin or --project-ref, to check a database.`;
3575
3670
  return runDoctor(config, args, env, {
3576
3671
  snapshot,
3577
3672
  advisors: { skipped },