better-supabase 0.7.1 → 0.9.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 (1377) hide show
  1. package/README.md +146 -81
  2. package/bin/better-supabase.js +14 -2
  3. package/dist/access-sql-DUSSMaC3.js +201 -0
  4. package/dist/actor-BAhb-d1S.d.ts +104 -0
  5. package/dist/actor-KHDOKGb1.js +151 -0
  6. package/dist/adapter-CEjmtazZ.js +1984 -0
  7. package/dist/agents-BCNhIxVZ.d.ts +111 -0
  8. package/dist/ai-cache-Dps7aRu1.d.ts +70 -0
  9. package/dist/ai-cache-zeUL94pB.js +84 -0
  10. package/dist/ai-chat-3GBSlFR4.d.ts +608 -0
  11. package/dist/ai-files-D2_9YLjF.js +331 -0
  12. package/dist/ai-message-DfaP8sis.js +14 -0
  13. package/dist/ai-sdk/agents/index.d.ts +154 -10
  14. package/dist/ai-sdk/agents/index.js +172 -17
  15. package/dist/ai-sdk/batches/index.d.ts +4 -4
  16. package/dist/ai-sdk/batches/index.js +5 -5
  17. package/dist/ai-sdk/cache/index.d.ts +2 -2
  18. package/dist/ai-sdk/cache/index.js +2 -2
  19. package/dist/ai-sdk/chat/index.d.ts +1 -1
  20. package/dist/ai-sdk/chat/index.js +10 -21
  21. package/dist/ai-sdk/embeddings/index.d.ts +3 -3
  22. package/dist/ai-sdk/embeddings/index.js +1 -2
  23. package/dist/ai-sdk/files/index.d.ts +3 -3
  24. package/dist/ai-sdk/files/index.js +4 -4
  25. package/dist/ai-sdk/index.d.ts +38 -9
  26. package/dist/ai-sdk/index.js +5 -3
  27. package/dist/ai-sdk/mcp/index.d.ts +43 -6
  28. package/dist/ai-sdk/mcp/index.js +37 -8
  29. package/dist/ai-sdk/memory/index.d.ts +5 -2
  30. package/dist/ai-sdk/memory/index.js +2 -2
  31. package/dist/ai-sdk/react/index.js +1 -2
  32. package/dist/ai-sdk/workflow/index.d.ts +7 -6
  33. package/dist/ai-sdk/workflow/index.js +15 -26
  34. package/dist/ai-tasks-Ih5oHfyj.d.ts +157 -0
  35. package/dist/announcements-BHCzraR6.js +128 -0
  36. package/dist/api-CFjuYKFY.js +680 -0
  37. package/dist/api-TG3jE5aO.d.ts +411 -0
  38. package/dist/api-keys-BEQatEUW.js +318 -0
  39. package/dist/api-keys-BYoGCM9p.d.ts +205 -0
  40. package/dist/app-tables-BGl5_U2x.js +584 -0
  41. package/dist/approvals-a2KmioBh.d.ts +124 -0
  42. package/dist/arazzo/index.d.ts +255 -0
  43. package/dist/arazzo/index.js +622 -0
  44. package/dist/assistant-Bf2cA6RO.d.ts +148 -0
  45. package/dist/astro/index.d.ts +9 -8
  46. package/dist/astro/index.js +12 -9
  47. package/dist/asyncapi/index.d.ts +103 -0
  48. package/dist/asyncapi/index.js +569 -0
  49. package/dist/attachments-DAj2Yp95.js +264 -0
  50. package/dist/attributes-D4mA7WhI.js +38 -0
  51. package/dist/audit-log-BMMuGPdP.js +786 -0
  52. package/dist/auth-CdBKt0CS.js +20 -0
  53. package/dist/auth-reply-DUCwb8YO.js +31 -0
  54. package/dist/auth-reply-Dj124sbX.d.ts +11 -0
  55. package/dist/authorization-DpRfs6Wx.d.ts +1412 -0
  56. package/dist/authorization-hooks-DkmrnDX7.d.ts +214 -0
  57. package/dist/authorizer-DH7DjkL3.js +126 -0
  58. package/dist/authorizer-eiOjo-3l.d.ts +73 -0
  59. package/dist/base64-BmeCBgGo.js +42 -0
  60. package/dist/batch-limit-DKVQDz4o.js +5 -0
  61. package/dist/before-route-B98js9m_.js +30 -0
  62. package/dist/better-result/index.d.ts +118 -0
  63. package/dist/better-result/index.js +64 -0
  64. package/dist/bind-a7sUgvf4.d.ts +70 -0
  65. package/dist/block-env-CBd_SoL5.js +29 -0
  66. package/dist/block-env-Dxl7rsI0.d.ts +10 -0
  67. package/dist/block-events-DD9Q_NUz.js +96 -0
  68. package/dist/block-fields-5UA84ZUg.d.ts +55 -0
  69. package/dist/block-fields-ffD6Gxe4.js +139 -0
  70. package/dist/block-helpers-C86hPEjI.d.ts +37 -0
  71. package/dist/block-helpers-CfG_MvDR.js +264 -0
  72. package/dist/block-hooks-BLPWD3Jt.d.ts +107 -0
  73. package/dist/block-hooks-BsXncUlZ.js +114 -0
  74. package/dist/block-transport-DaGGXjIw.d.ts +70 -0
  75. package/dist/block-transport-G4t1umrR.js +85 -0
  76. package/dist/blocks/access-requests/index.d.ts +98 -0
  77. package/dist/blocks/access-requests/index.js +99 -0
  78. package/dist/blocks/agents/index.d.ts +21 -3
  79. package/dist/blocks/agents/index.js +65 -18
  80. package/dist/blocks/ai-cache/index.d.ts +8 -3
  81. package/dist/blocks/ai-cache/index.js +15 -3
  82. package/dist/blocks/ai-chat/index.d.ts +28 -4
  83. package/dist/blocks/ai-chat/index.js +31 -5
  84. package/dist/blocks/ai-chat/react/index.d.ts +12 -46
  85. package/dist/blocks/ai-chat/react/index.js +43 -335
  86. package/dist/blocks/ai-chat/solid/index.d.ts +34 -0
  87. package/dist/blocks/ai-chat/solid/index.js +41 -0
  88. package/dist/blocks/ai-chat/svelte/index.d.ts +34 -0
  89. package/dist/blocks/ai-chat/svelte/index.js +41 -0
  90. package/dist/blocks/ai-chat/vue/index.d.ts +34 -0
  91. package/dist/blocks/ai-chat/vue/index.js +41 -0
  92. package/dist/blocks/ai-files/index.d.ts +11 -4
  93. package/dist/blocks/ai-files/index.js +16 -3
  94. package/dist/blocks/ai-providers/index.d.ts +18 -3
  95. package/dist/blocks/ai-providers/index.js +41 -15
  96. package/dist/blocks/ai-tasks/index.d.ts +10 -3
  97. package/dist/blocks/ai-tasks/index.js +71 -21
  98. package/dist/blocks/announcements/index.d.ts +18 -3
  99. package/dist/blocks/announcements/index.js +27 -3
  100. package/dist/blocks/announcements/react/index.d.ts +4 -14
  101. package/dist/blocks/announcements/react/index.js +22 -70
  102. package/dist/blocks/announcements/solid/index.d.ts +13 -0
  103. package/dist/blocks/announcements/solid/index.js +14 -0
  104. package/dist/blocks/announcements/svelte/index.d.ts +13 -0
  105. package/dist/blocks/announcements/svelte/index.js +14 -0
  106. package/dist/blocks/announcements/vue/index.d.ts +13 -0
  107. package/dist/blocks/announcements/vue/index.js +14 -0
  108. package/dist/blocks/api-keys/index.d.ts +24 -7
  109. package/dist/blocks/api-keys/index.js +30 -295
  110. package/dist/blocks/api-keys/react/index.d.ts +29 -0
  111. package/dist/blocks/api-keys/react/index.js +43 -0
  112. package/dist/blocks/api-keys/react/server.d.ts +7 -0
  113. package/dist/blocks/api-keys/react/server.js +7 -0
  114. package/dist/blocks/api-keys/solid/index.d.ts +13 -0
  115. package/dist/blocks/api-keys/solid/index.js +14 -0
  116. package/dist/blocks/api-keys/svelte/index.d.ts +13 -0
  117. package/dist/blocks/api-keys/svelte/index.js +14 -0
  118. package/dist/blocks/api-keys/vue/index.d.ts +13 -0
  119. package/dist/blocks/api-keys/vue/index.js +14 -0
  120. package/dist/blocks/approvals/index.d.ts +22 -0
  121. package/dist/blocks/approvals/index.js +189 -0
  122. package/dist/blocks/attachments/index.d.ts +18 -223
  123. package/dist/blocks/attachments/index.js +26 -233
  124. package/dist/blocks/audit/index.d.ts +72 -354
  125. package/dist/blocks/audit/index.js +91 -695
  126. package/dist/blocks/audit/react/index.d.ts +26 -0
  127. package/dist/blocks/audit/react/index.js +44 -0
  128. package/dist/blocks/audit/react/server.d.ts +7 -0
  129. package/dist/blocks/audit/react/server.js +7 -0
  130. package/dist/blocks/audit/solid/index.d.ts +13 -0
  131. package/dist/blocks/audit/solid/index.js +14 -0
  132. package/dist/blocks/audit/svelte/index.d.ts +13 -0
  133. package/dist/blocks/audit/svelte/index.js +14 -0
  134. package/dist/blocks/audit/vue/index.d.ts +13 -0
  135. package/dist/blocks/audit/vue/index.js +14 -0
  136. package/dist/blocks/billing/index.d.ts +40 -13
  137. package/dist/blocks/billing/index.js +49 -18
  138. package/dist/blocks/billing/react/index.d.ts +34 -0
  139. package/dist/blocks/billing/react/index.js +36 -0
  140. package/dist/blocks/billing/react/server.d.ts +7 -0
  141. package/dist/blocks/billing/react/server.js +7 -0
  142. package/dist/blocks/billing/solid/index.d.ts +15 -0
  143. package/dist/blocks/billing/solid/index.js +14 -0
  144. package/dist/blocks/billing/svelte/index.d.ts +15 -0
  145. package/dist/blocks/billing/svelte/index.js +14 -0
  146. package/dist/blocks/billing/vue/index.d.ts +15 -0
  147. package/dist/blocks/billing/vue/index.js +14 -0
  148. package/dist/blocks/bookings/index.d.ts +36 -0
  149. package/dist/blocks/bookings/index.js +28 -0
  150. package/dist/blocks/bookings/react/index.d.ts +31 -0
  151. package/dist/blocks/bookings/react/index.js +59 -0
  152. package/dist/blocks/bookings/react/server.d.ts +6 -0
  153. package/dist/blocks/bookings/react/server.js +7 -0
  154. package/dist/blocks/bookings/solid/index.d.ts +13 -0
  155. package/dist/blocks/bookings/solid/index.js +14 -0
  156. package/dist/blocks/bookings/svelte/index.d.ts +13 -0
  157. package/dist/blocks/bookings/svelte/index.js +14 -0
  158. package/dist/blocks/bookings/vue/index.d.ts +13 -0
  159. package/dist/blocks/bookings/vue/index.js +14 -0
  160. package/dist/blocks/bulk/index.d.ts +142 -0
  161. package/dist/blocks/bulk/index.js +154 -0
  162. package/dist/blocks/calendar/index.d.ts +20 -0
  163. package/dist/blocks/calendar/index.js +33 -0
  164. package/dist/blocks/calendar/react/index.d.ts +26 -0
  165. package/dist/blocks/calendar/react/index.js +58 -0
  166. package/dist/blocks/calendar/react/server.d.ts +6 -0
  167. package/dist/blocks/calendar/react/server.js +7 -0
  168. package/dist/blocks/calendar/solid/index.d.ts +13 -0
  169. package/dist/blocks/calendar/solid/index.js +14 -0
  170. package/dist/blocks/calendar/svelte/index.d.ts +13 -0
  171. package/dist/blocks/calendar/svelte/index.js +14 -0
  172. package/dist/blocks/calendar/vue/index.d.ts +13 -0
  173. package/dist/blocks/calendar/vue/index.js +14 -0
  174. package/dist/blocks/catalog/index.d.ts +224 -0
  175. package/dist/blocks/catalog/index.js +292 -0
  176. package/dist/blocks/collections/index.d.ts +184 -0
  177. package/dist/blocks/collections/index.js +208 -0
  178. package/dist/blocks/comments/index.d.ts +19 -166
  179. package/dist/blocks/comments/index.js +26 -206
  180. package/dist/blocks/comments/react/index.d.ts +27 -0
  181. package/dist/blocks/comments/react/index.js +45 -0
  182. package/dist/blocks/comments/react/server.d.ts +7 -0
  183. package/dist/blocks/comments/react/server.js +7 -0
  184. package/dist/blocks/comments/solid/index.d.ts +13 -0
  185. package/dist/blocks/comments/solid/index.js +14 -0
  186. package/dist/blocks/comments/svelte/index.d.ts +13 -0
  187. package/dist/blocks/comments/svelte/index.js +14 -0
  188. package/dist/blocks/comments/vue/index.d.ts +13 -0
  189. package/dist/blocks/comments/vue/index.js +14 -0
  190. package/dist/blocks/connectors/index.d.ts +21 -3
  191. package/dist/blocks/connectors/index.js +54 -18
  192. package/dist/blocks/custom-fields/index.d.ts +62 -0
  193. package/dist/blocks/custom-fields/index.js +85 -0
  194. package/dist/blocks/data-lifecycle/index.d.ts +119 -10
  195. package/dist/blocks/data-lifecycle/index.js +103 -12
  196. package/dist/blocks/deals/index.d.ts +262 -0
  197. package/dist/blocks/deals/index.js +380 -0
  198. package/dist/blocks/documents/index.d.ts +17 -0
  199. package/dist/blocks/documents/index.js +118 -0
  200. package/dist/blocks/domains/index.d.ts +117 -0
  201. package/dist/blocks/domains/index.js +118 -0
  202. package/dist/blocks/drive/index.d.ts +296 -0
  203. package/dist/blocks/drive/index.js +483 -0
  204. package/dist/blocks/employees/index.d.ts +205 -0
  205. package/dist/blocks/employees/index.js +289 -0
  206. package/dist/blocks/engagements/index.d.ts +125 -0
  207. package/dist/blocks/engagements/index.js +143 -0
  208. package/dist/blocks/entitlements/index.d.ts +40 -4
  209. package/dist/blocks/entitlements/index.js +14 -24
  210. package/dist/blocks/entitlements/react/index.d.ts +24 -0
  211. package/dist/blocks/entitlements/react/index.js +35 -0
  212. package/dist/blocks/entitlements/react/server.d.ts +6 -0
  213. package/dist/blocks/entitlements/react/server.js +7 -0
  214. package/dist/blocks/entitlements/solid/index.d.ts +13 -0
  215. package/dist/blocks/entitlements/solid/index.js +14 -0
  216. package/dist/blocks/entitlements/svelte/index.d.ts +13 -0
  217. package/dist/blocks/entitlements/svelte/index.js +14 -0
  218. package/dist/blocks/entitlements/vue/index.d.ts +13 -0
  219. package/dist/blocks/entitlements/vue/index.js +14 -0
  220. package/dist/blocks/flags/index.d.ts +61 -187
  221. package/dist/blocks/flags/index.js +65 -252
  222. package/dist/blocks/forms/index.d.ts +302 -0
  223. package/dist/blocks/forms/index.js +341 -0
  224. package/dist/blocks/forms/react/index.d.ts +16 -0
  225. package/dist/blocks/forms/react/index.js +25 -0
  226. package/dist/blocks/forms/react/server.d.ts +6 -0
  227. package/dist/blocks/forms/react/server.js +7 -0
  228. package/dist/blocks/forms/solid/index.d.ts +13 -0
  229. package/dist/blocks/forms/solid/index.js +14 -0
  230. package/dist/blocks/forms/svelte/index.d.ts +13 -0
  231. package/dist/blocks/forms/svelte/index.js +14 -0
  232. package/dist/blocks/forms/vue/index.d.ts +13 -0
  233. package/dist/blocks/forms/vue/index.js +14 -0
  234. package/dist/blocks/hiring/index.d.ts +154 -0
  235. package/dist/blocks/hiring/index.js +180 -0
  236. package/dist/blocks/identities/index.d.ts +83 -0
  237. package/dist/blocks/identities/index.js +103 -0
  238. package/dist/blocks/imports/index.d.ts +91 -0
  239. package/dist/blocks/imports/index.js +123 -0
  240. package/dist/blocks/inbox/index.d.ts +22 -3
  241. package/dist/blocks/inbox/index.js +78 -6
  242. package/dist/blocks/inbox/react/index.d.ts +3 -2
  243. package/dist/blocks/inbox/react/index.js +55 -199
  244. package/dist/blocks/inbox/react/server.d.ts +2 -1
  245. package/dist/blocks/inbox/solid/index.d.ts +27 -0
  246. package/dist/blocks/inbox/solid/index.js +32 -0
  247. package/dist/blocks/inbox/svelte/index.d.ts +27 -0
  248. package/dist/blocks/inbox/svelte/index.js +32 -0
  249. package/dist/blocks/inbox/vue/index.d.ts +27 -0
  250. package/dist/blocks/inbox/vue/index.js +32 -0
  251. package/dist/blocks/index.d.ts +9 -64
  252. package/dist/blocks/index.js +193 -57
  253. package/dist/blocks/inventory/index.d.ts +181 -0
  254. package/dist/blocks/inventory/index.js +219 -0
  255. package/dist/blocks/invoices/index.d.ts +154 -0
  256. package/dist/blocks/invoices/index.js +216 -0
  257. package/dist/blocks/jobs/index.d.ts +188 -49
  258. package/dist/blocks/jobs/index.js +698 -527
  259. package/dist/blocks/knowledge/index.d.ts +10 -3
  260. package/dist/blocks/knowledge/index.js +17 -3
  261. package/dist/blocks/leave/index.d.ts +241 -0
  262. package/dist/blocks/leave/index.js +209 -0
  263. package/dist/blocks/memory/index.d.ts +9 -4
  264. package/dist/blocks/memory/index.js +49 -12
  265. package/dist/blocks/metrics/index.d.ts +174 -0
  266. package/dist/blocks/metrics/index.js +217 -0
  267. package/dist/blocks/mfa/index.d.ts +7 -0
  268. package/dist/blocks/mfa/index.js +12 -0
  269. package/dist/blocks/mfa/react/index.d.ts +30 -0
  270. package/dist/blocks/mfa/react/index.js +45 -0
  271. package/dist/blocks/mfa/react/server.d.ts +9 -0
  272. package/dist/blocks/mfa/react/server.js +12 -0
  273. package/dist/blocks/mfa/solid/index.d.ts +20 -0
  274. package/dist/blocks/mfa/solid/index.js +23 -0
  275. package/dist/blocks/mfa/svelte/index.d.ts +20 -0
  276. package/dist/blocks/mfa/svelte/index.js +23 -0
  277. package/dist/blocks/mfa/vue/index.d.ts +20 -0
  278. package/dist/blocks/mfa/vue/index.js +23 -0
  279. package/dist/blocks/notifications/index.d.ts +345 -26
  280. package/dist/blocks/notifications/index.js +744 -120
  281. package/dist/blocks/notifications/react/index.d.ts +7 -32
  282. package/dist/blocks/notifications/react/index.js +23 -49
  283. package/dist/blocks/notifications/react/server.d.ts +2 -1
  284. package/dist/blocks/notifications/solid/index.d.ts +13 -0
  285. package/dist/blocks/notifications/solid/index.js +14 -0
  286. package/dist/blocks/notifications/svelte/index.d.ts +13 -0
  287. package/dist/blocks/notifications/svelte/index.js +14 -0
  288. package/dist/blocks/notifications/vue/index.d.ts +13 -0
  289. package/dist/blocks/notifications/vue/index.js +14 -0
  290. package/dist/blocks/number-sequences/index.d.ts +39 -0
  291. package/dist/blocks/number-sequences/index.js +38 -0
  292. package/dist/blocks/oauth-server/index.d.ts +228 -0
  293. package/dist/blocks/oauth-server/index.js +309 -0
  294. package/dist/blocks/onboarding/index.d.ts +8 -3
  295. package/dist/blocks/onboarding/index.js +17 -63
  296. package/dist/blocks/onboarding/react/index.d.ts +3 -12
  297. package/dist/blocks/onboarding/react/index.js +18 -60
  298. package/dist/blocks/onboarding/react/server.d.ts +2 -2
  299. package/dist/blocks/onboarding/react/server.js +2 -2
  300. package/dist/blocks/onboarding/solid/index.d.ts +13 -0
  301. package/dist/blocks/onboarding/solid/index.js +14 -0
  302. package/dist/blocks/onboarding/svelte/index.d.ts +13 -0
  303. package/dist/blocks/onboarding/svelte/index.js +14 -0
  304. package/dist/blocks/onboarding/vue/index.d.ts +13 -0
  305. package/dist/blocks/onboarding/vue/index.js +14 -0
  306. package/dist/blocks/orders/index.d.ts +264 -0
  307. package/dist/blocks/orders/index.js +589 -0
  308. package/dist/blocks/organizations/index.d.ts +31 -238
  309. package/dist/blocks/organizations/index.js +49 -399
  310. package/dist/blocks/organizations/react/index.d.ts +108 -0
  311. package/dist/blocks/organizations/react/index.js +113 -0
  312. package/dist/blocks/organizations/react/server.d.ts +11 -0
  313. package/dist/blocks/organizations/react/server.js +15 -0
  314. package/dist/blocks/organizations/solid/index.d.ts +34 -0
  315. package/dist/blocks/organizations/solid/index.js +32 -0
  316. package/dist/blocks/organizations/svelte/index.d.ts +34 -0
  317. package/dist/blocks/organizations/svelte/index.js +32 -0
  318. package/dist/blocks/organizations/vue/index.d.ts +34 -0
  319. package/dist/blocks/organizations/vue/index.js +32 -0
  320. package/dist/blocks/outbox/index.d.ts +12 -3
  321. package/dist/blocks/outbox/index.js +97 -67
  322. package/dist/blocks/parties/index.d.ts +181 -0
  323. package/dist/blocks/parties/index.js +258 -0
  324. package/dist/blocks/pipelines/index.d.ts +189 -0
  325. package/dist/blocks/pipelines/index.js +204 -0
  326. package/dist/blocks/profiles/index.d.ts +14 -9
  327. package/dist/blocks/profiles/index.js +20 -6
  328. package/dist/blocks/promotions/index.d.ts +125 -0
  329. package/dist/blocks/promotions/index.js +123 -0
  330. package/dist/blocks/push/index.d.ts +48 -28
  331. package/dist/blocks/push/index.js +45 -16
  332. package/dist/blocks/quotes/index.d.ts +152 -0
  333. package/dist/blocks/quotes/index.js +209 -0
  334. package/dist/blocks/rank/index.d.ts +71 -0
  335. package/dist/blocks/rank/index.js +53 -0
  336. package/dist/blocks/reactions/index.d.ts +18 -0
  337. package/dist/blocks/reactions/index.js +26 -0
  338. package/dist/blocks/reactions/react/index.d.ts +23 -0
  339. package/dist/blocks/reactions/react/index.js +46 -0
  340. package/dist/blocks/reactions/react/server.d.ts +6 -0
  341. package/dist/blocks/reactions/react/server.js +7 -0
  342. package/dist/blocks/reactions/solid/index.d.ts +13 -0
  343. package/dist/blocks/reactions/solid/index.js +14 -0
  344. package/dist/blocks/reactions/svelte/index.d.ts +13 -0
  345. package/dist/blocks/reactions/svelte/index.js +14 -0
  346. package/dist/blocks/reactions/vue/index.d.ts +13 -0
  347. package/dist/blocks/reactions/vue/index.js +14 -0
  348. package/dist/blocks/relations/index.d.ts +180 -0
  349. package/dist/blocks/relations/index.js +254 -0
  350. package/dist/blocks/reminders/index.d.ts +177 -0
  351. package/dist/blocks/reminders/index.js +171 -0
  352. package/dist/blocks/reviews/index.d.ts +148 -0
  353. package/dist/blocks/reviews/index.js +139 -0
  354. package/dist/blocks/rules/index.d.ts +103 -0
  355. package/dist/blocks/rules/index.js +54 -0
  356. package/dist/blocks/rules/react/index.d.ts +34 -0
  357. package/dist/blocks/rules/react/index.js +55 -0
  358. package/dist/blocks/rules/react/server.d.ts +6 -0
  359. package/dist/blocks/rules/react/server.js +7 -0
  360. package/dist/blocks/rules/solid/index.d.ts +13 -0
  361. package/dist/blocks/rules/solid/index.js +14 -0
  362. package/dist/blocks/rules/svelte/index.d.ts +13 -0
  363. package/dist/blocks/rules/svelte/index.js +14 -0
  364. package/dist/blocks/rules/vue/index.d.ts +13 -0
  365. package/dist/blocks/rules/vue/index.js +14 -0
  366. package/dist/blocks/saved-views/index.d.ts +17 -0
  367. package/dist/blocks/saved-views/index.js +29 -0
  368. package/dist/blocks/saved-views/react/index.d.ts +34 -0
  369. package/dist/blocks/saved-views/react/index.js +57 -0
  370. package/dist/blocks/saved-views/react/server.d.ts +7 -0
  371. package/dist/blocks/saved-views/react/server.js +7 -0
  372. package/dist/blocks/saved-views/solid/index.d.ts +13 -0
  373. package/dist/blocks/saved-views/solid/index.js +14 -0
  374. package/dist/blocks/saved-views/svelte/index.d.ts +13 -0
  375. package/dist/blocks/saved-views/svelte/index.js +14 -0
  376. package/dist/blocks/saved-views/vue/index.d.ts +13 -0
  377. package/dist/blocks/saved-views/vue/index.js +14 -0
  378. package/dist/blocks/search/index.d.ts +31 -0
  379. package/dist/blocks/search/index.js +61 -0
  380. package/dist/blocks/search/react/index.d.ts +36 -0
  381. package/dist/blocks/search/react/index.js +49 -0
  382. package/dist/blocks/search/react/server.d.ts +7 -0
  383. package/dist/blocks/search/react/server.js +8 -0
  384. package/dist/blocks/search/solid/index.d.ts +13 -0
  385. package/dist/blocks/search/solid/index.js +14 -0
  386. package/dist/blocks/search/svelte/index.d.ts +13 -0
  387. package/dist/blocks/search/svelte/index.js +14 -0
  388. package/dist/blocks/search/vue/index.d.ts +13 -0
  389. package/dist/blocks/search/vue/index.js +14 -0
  390. package/dist/blocks/service-principals/index.d.ts +126 -0
  391. package/dist/blocks/service-principals/index.js +107 -0
  392. package/dist/blocks/sessions/index.d.ts +7 -0
  393. package/dist/blocks/sessions/index.js +14 -0
  394. package/dist/blocks/sessions/react/index.d.ts +31 -0
  395. package/dist/blocks/sessions/react/index.js +51 -0
  396. package/dist/blocks/sessions/react/server.d.ts +9 -0
  397. package/dist/blocks/sessions/react/server.js +11 -0
  398. package/dist/blocks/sessions/solid/index.d.ts +20 -0
  399. package/dist/blocks/sessions/solid/index.js +23 -0
  400. package/dist/blocks/sessions/svelte/index.d.ts +20 -0
  401. package/dist/blocks/sessions/svelte/index.js +23 -0
  402. package/dist/blocks/sessions/vue/index.d.ts +20 -0
  403. package/dist/blocks/sessions/vue/index.js +23 -0
  404. package/dist/blocks/settings/index.d.ts +20 -86
  405. package/dist/blocks/settings/index.js +28 -101
  406. package/dist/blocks/settings/react/index.d.ts +25 -0
  407. package/dist/blocks/settings/react/index.js +37 -0
  408. package/dist/blocks/settings/react/server.d.ts +7 -0
  409. package/dist/blocks/settings/react/server.js +7 -0
  410. package/dist/blocks/settings/solid/index.d.ts +13 -0
  411. package/dist/blocks/settings/solid/index.js +14 -0
  412. package/dist/blocks/settings/svelte/index.d.ts +13 -0
  413. package/dist/blocks/settings/svelte/index.js +14 -0
  414. package/dist/blocks/settings/vue/index.d.ts +13 -0
  415. package/dist/blocks/settings/vue/index.js +14 -0
  416. package/dist/blocks/share-links/index.d.ts +99 -0
  417. package/dist/blocks/share-links/index.js +99 -0
  418. package/dist/blocks/shared-signals/index.d.ts +395 -0
  419. package/dist/blocks/shared-signals/index.js +880 -0
  420. package/dist/blocks/signing-keys/index.d.ts +29 -0
  421. package/dist/blocks/signing-keys/index.js +161 -0
  422. package/dist/blocks/sla/index.d.ts +114 -0
  423. package/dist/blocks/sla/index.js +122 -0
  424. package/dist/blocks/sso/index.d.ts +169 -147
  425. package/dist/blocks/sso/index.js +259 -321
  426. package/dist/blocks/state-machine/index.d.ts +105 -0
  427. package/dist/blocks/state-machine/index.js +116 -0
  428. package/dist/blocks/tags/index.d.ts +20 -0
  429. package/dist/blocks/tags/index.js +28 -0
  430. package/dist/blocks/tags/react/index.d.ts +28 -0
  431. package/dist/blocks/tags/react/index.js +47 -0
  432. package/dist/blocks/tags/react/server.d.ts +7 -0
  433. package/dist/blocks/tags/react/server.js +7 -0
  434. package/dist/blocks/tags/solid/index.d.ts +13 -0
  435. package/dist/blocks/tags/solid/index.js +14 -0
  436. package/dist/blocks/tags/svelte/index.d.ts +13 -0
  437. package/dist/blocks/tags/svelte/index.js +14 -0
  438. package/dist/blocks/tags/vue/index.d.ts +13 -0
  439. package/dist/blocks/tags/vue/index.js +14 -0
  440. package/dist/blocks/targets/index.d.ts +82 -0
  441. package/dist/blocks/targets/index.js +73 -0
  442. package/dist/blocks/teams/index.d.ts +61 -0
  443. package/dist/blocks/teams/index.js +83 -0
  444. package/dist/blocks/templates/index.d.ts +362 -0
  445. package/dist/blocks/templates/index.js +483 -0
  446. package/dist/blocks/time-tracking/index.d.ts +250 -0
  447. package/dist/blocks/time-tracking/index.js +317 -0
  448. package/dist/blocks/trash/index.d.ts +78 -0
  449. package/dist/blocks/trash/index.js +79 -0
  450. package/dist/blocks/undo/index.d.ts +9 -0
  451. package/dist/blocks/undo/index.js +14 -0
  452. package/dist/blocks/undo/react/index.d.ts +17 -0
  453. package/dist/blocks/undo/react/index.js +24 -0
  454. package/dist/blocks/undo/react/server.d.ts +7 -0
  455. package/dist/blocks/undo/react/server.js +7 -0
  456. package/dist/blocks/undo/solid/index.d.ts +13 -0
  457. package/dist/blocks/undo/solid/index.js +14 -0
  458. package/dist/blocks/undo/svelte/index.d.ts +13 -0
  459. package/dist/blocks/undo/svelte/index.js +14 -0
  460. package/dist/blocks/undo/vue/index.d.ts +13 -0
  461. package/dist/blocks/undo/vue/index.js +14 -0
  462. package/dist/blocks/usage/index.d.ts +10 -4
  463. package/dist/blocks/usage/index.js +16 -232
  464. package/dist/blocks/usage/react/index.d.ts +23 -0
  465. package/dist/blocks/usage/react/index.js +38 -0
  466. package/dist/blocks/usage/react/server.d.ts +7 -0
  467. package/dist/blocks/usage/react/server.js +7 -0
  468. package/dist/blocks/usage/solid/index.d.ts +13 -0
  469. package/dist/blocks/usage/solid/index.js +14 -0
  470. package/dist/blocks/usage/svelte/index.d.ts +13 -0
  471. package/dist/blocks/usage/svelte/index.js +14 -0
  472. package/dist/blocks/usage/vue/index.d.ts +13 -0
  473. package/dist/blocks/usage/vue/index.js +14 -0
  474. package/dist/blocks/versions/index.d.ts +165 -0
  475. package/dist/blocks/versions/index.js +283 -0
  476. package/dist/blocks/waitlist/index.d.ts +57 -19
  477. package/dist/blocks/waitlist/index.js +47 -12
  478. package/dist/blocks/webhooks/index.d.ts +275 -134
  479. package/dist/blocks/webhooks/index.js +775 -231
  480. package/dist/blocks/work-items/index.d.ts +208 -0
  481. package/dist/blocks/work-items/index.js +305 -0
  482. package/dist/blocks/workflow-builder/index.d.ts +26 -6
  483. package/dist/blocks/workflow-builder/index.js +30 -5
  484. package/dist/blocks/workflow-builder/react/index.d.ts +4 -19
  485. package/dist/blocks/workflow-builder/react/index.js +45 -89
  486. package/dist/blocks/workflow-builder/solid/index.d.ts +20 -0
  487. package/dist/blocks/workflow-builder/solid/index.js +23 -0
  488. package/dist/blocks/workflow-builder/svelte/index.d.ts +20 -0
  489. package/dist/blocks/workflow-builder/svelte/index.js +23 -0
  490. package/dist/blocks/workflow-builder/vue/index.d.ts +20 -0
  491. package/dist/blocks/workflow-builder/vue/index.js +23 -0
  492. package/dist/blocks/workflows/index.d.ts +20 -3
  493. package/dist/blocks/workflows/index.js +27 -3
  494. package/dist/blocks/workflows/react/index.d.ts +5 -20
  495. package/dist/blocks/workflows/react/index.js +41 -113
  496. package/dist/blocks/workflows/solid/index.d.ts +20 -0
  497. package/dist/blocks/workflows/solid/index.js +23 -0
  498. package/dist/blocks/workflows/svelte/index.d.ts +20 -0
  499. package/dist/blocks/workflows/svelte/index.js +23 -0
  500. package/dist/blocks/workflows/vue/index.d.ts +20 -0
  501. package/dist/blocks/workflows/vue/index.js +23 -0
  502. package/dist/blocks-D2WQ63PI.js +84 -0
  503. package/dist/bookings-0XnhHNLM.js +181 -0
  504. package/dist/build-Cm0T5MVG.js +1815 -0
  505. package/dist/build-Cx08LOT7.js +689 -0
  506. package/dist/calendar-DcFrpSOy.js +801 -0
  507. package/dist/casing-DdFWEtqr.js +16 -0
  508. package/dist/channel-D-LHCY11.d.ts +78 -0
  509. package/dist/channels-C-GCoNLd.js +114 -0
  510. package/dist/chat-sdk/index.d.ts +131 -7
  511. package/dist/chat-sdk/index.js +155 -6
  512. package/dist/chat-sdk/react/index.d.ts +2 -1
  513. package/dist/chat-sdk/react/index.js +1 -2
  514. package/dist/chat-sdk/react/server.d.ts +2 -1
  515. package/dist/chat-sdk/react/server.js +1 -2
  516. package/dist/claims-0KZVT804.js +61 -0
  517. package/dist/cli/add-B0zoJUYX.js +651 -0
  518. package/dist/cli/add-Bd5M6uEZ.js +75 -0
  519. package/dist/cli/add-CT6p5psO.js +1 -0
  520. package/dist/cli/adopt-C9jl8z0h.js +1 -0
  521. package/dist/cli/adopt-CebmlHL-.js +393 -0
  522. package/dist/cli/agent-CCt_aXpJ.js +176 -0
  523. package/dist/cli/apply-Dxk8AUNU.js +302 -0
  524. package/dist/cli/arazzo-1.0-BalU61-_.js +532 -0
  525. package/dist/cli/arazzo-1.1-Bnfasbun.js +705 -0
  526. package/dist/cli/asyncapi-3.0.0-C78dBjR6.js +5593 -0
  527. package/dist/cli/asyncapi-3.1.0-g-7aIfV1.js +5833 -0
  528. package/dist/cli/bin.js +41 -21
  529. package/dist/cli/blocks-Bzz326nn.js +1 -0
  530. package/dist/cli/blocks-Dq25D80b.js +124 -0
  531. package/dist/cli/cache-Cx6qlRDR.js +502 -0
  532. package/dist/cli/catalog-Di15TkM2.js +187 -0
  533. package/dist/cli/codemod-woL4cVe0.js +985 -0
  534. package/dist/cli/command-CK9Cn8HV.js +836 -0
  535. package/dist/cli/completion-BO5UK6bG.js +1 -0
  536. package/dist/cli/completion-CWoDmFZr.js +205 -0
  537. package/dist/cli/completion-J3dqnNoW.js +30 -0
  538. package/dist/cli/config-C1d-mbUA.js +1 -0
  539. package/dist/cli/config-CLHpTk9Y.js +1421 -0
  540. package/dist/cli/config-MuKY9kUj.js +39 -0
  541. package/dist/cli/config-edit-Ct1lXe8a.js +603 -0
  542. package/dist/cli/db-DT1bGB02.js +78 -0
  543. package/dist/cli/design-edit-B-WsnhUF.js +175 -0
  544. package/dist/cli/detect-DYDUBLU4.js +84 -0
  545. package/dist/cli/dist-D_VbPAMR.js +129 -0
  546. package/dist/cli/dist-DuiMMRbJ.js +1112 -0
  547. package/dist/cli/doctor-SGw36h1D.js +3806 -0
  548. package/dist/cli/emit-ZAYeh4Yn.js +1042 -0
  549. package/dist/cli/env-CVXvJoLP.js +142 -0
  550. package/dist/cli/env-D3gZ-OHj.js +1 -0
  551. package/dist/cli/env-DJ4ZaJpe.js +1 -0
  552. package/dist/cli/env-DMw_MBe5.js +996 -0
  553. package/dist/cli/errors-Caiz_0so.js +98 -0
  554. package/dist/cli/fastest-levenshtein-dhRRvrM2.js +120 -0
  555. package/dist/cli/files-DDvAwTko.js +963 -0
  556. package/dist/cli/gen-B344S1Oy.js +304 -0
  557. package/dist/cli/guards-CUlDNYZs.js +8 -0
  558. package/dist/cli/index.d.ts +297 -140
  559. package/dist/cli/index.js +13 -8
  560. package/dist/cli/init-B1dL-RZL.js +393 -0
  561. package/dist/cli/introspect-BPcFi8ow.js +51 -0
  562. package/dist/cli/io-BiPX-_J1.js +37 -0
  563. package/dist/cli/jsonc-C8M0EhHB.js +1 -0
  564. package/dist/cli/keys-jsxCNJdz.js +106 -0
  565. package/dist/cli/metadata-CxBZo4KM.js +138 -0
  566. package/dist/cli/module-migration-YFFdWC5X.js +592 -0
  567. package/dist/cli/moved-D9OT_Uyy.js +152 -0
  568. package/dist/cli/names-D6LrQnOv.js +6 -0
  569. package/dist/cli/openapi-3.0-t7xwkuRH.js +928 -0
  570. package/dist/cli/openapi-3.1-CVze7tBS.js +870 -0
  571. package/dist/cli/openapi-3.2-CFoMYM01.js +1031 -0
  572. package/dist/cli/parse-DE59XyWt.js +170 -0
  573. package/dist/cli/preset-DmcC4nWE.js +129 -0
  574. package/dist/cli/prompts-Bvg_DBpe.js +1137 -0
  575. package/dist/cli/redact-PjNswZOs.js +35 -0
  576. package/dist/cli/rolldown-runtime-kJ_i4yPo.js +26 -0
  577. package/dist/cli/run-CM_2g6KQ.js +684 -0
  578. package/dist/cli/run-DaHfUUO9.js +1539 -0
  579. package/dist/cli/scaffold-CFdDq36-.js +898 -0
  580. package/dist/cli/scaffold-Dsjr7sOT.js +1 -0
  581. package/dist/cli/seed-DldDdXWO.js +113 -0
  582. package/dist/cli/seed-DtRFysBe.js +1 -0
  583. package/dist/cli/shell-Btv_4Yhe.js +10 -0
  584. package/dist/cli/skills-v34NDb2D.js +121 -0
  585. package/dist/cli/snapshot-DAxLi4hO.js +347 -0
  586. package/dist/cli/source-args-0I9zylYy.js +47 -0
  587. package/dist/cli/spec-CaaSOYZS.js +7501 -0
  588. package/dist/cli/spec-De0cfceR.js +1 -0
  589. package/dist/cli/sql-0I1EQ3JG.js +2 -0
  590. package/dist/cli/sql-DDLWwzh9.js +326 -0
  591. package/dist/cli/stack-status-CRanl-CN.js +456 -0
  592. package/dist/cli/style-2JfIPVMQ.js +29 -0
  593. package/dist/cli/supabase-toml-DjLgBYEo.js +1153 -0
  594. package/dist/cli/sync-DFx-6t5n.js +88 -0
  595. package/dist/cli/topics-GJuIDwlY.js +30 -0
  596. package/dist/cli/trace-VbdO6bcN.js +7 -0
  597. package/dist/cli/typegen--TfvOPLh.js +494 -0
  598. package/dist/cli/typegen-version-BNBPI4Eu.js +9 -0
  599. package/dist/cli/validate-BfWNKvxy.js +7522 -0
  600. package/dist/cli/version-DNRW4DAP.js +4 -0
  601. package/dist/cli/write-BS6F3Yvz.js +180 -0
  602. package/dist/client/index.d.ts +7 -3
  603. package/dist/client/index.js +207 -4
  604. package/dist/client/native/index.d.ts +71 -4
  605. package/dist/client/native/index.js +65 -6
  606. package/dist/client-01MAuqzW.js +137 -0
  607. package/dist/client-B7QVIrJS.d.ts +263 -0
  608. package/dist/client-B9CqzgPO.js +75 -0
  609. package/dist/client-BAcILZOf.d.ts +122 -0
  610. package/dist/client-BOT2KVIp.js +128 -0
  611. package/dist/client-BUGIS__1.js +1051 -0
  612. package/dist/client-BVZtq_rQ.d.ts +34 -0
  613. package/dist/client-BYaOGCOG.js +84 -0
  614. package/dist/client-BfgwocyT.js +155 -0
  615. package/dist/client-BpS8a6Fm.js +51 -0
  616. package/dist/client-BxnLb9bz.d.ts +58 -0
  617. package/dist/client-BzCv4kKE.js +65 -0
  618. package/dist/client-C-2ajnhM.js +89 -0
  619. package/dist/client-C5mUEb2n.js +55 -0
  620. package/dist/client-C9QrWrnt.js +209 -0
  621. package/dist/client-CFdMJ1h9.d.ts +277 -0
  622. package/dist/client-CHmjaI0j.d.ts +103 -0
  623. package/dist/client-CWs3X4g1.js +120 -0
  624. package/dist/client-Cdedx_lw.js +438 -0
  625. package/dist/client-CiGjS6us.js +169 -0
  626. package/dist/client-CilSKXNu.js +288 -0
  627. package/dist/client-ClZ0D-if.d.ts +162 -0
  628. package/dist/client-Cmensu7l.d.ts +419 -0
  629. package/dist/client-Co6BPmvr.d.ts +108 -0
  630. package/dist/client-CoVGPi0c.js +133 -0
  631. package/dist/client-CvITjt-9.js +310 -0
  632. package/dist/client-CzI4QpG3.d.ts +131 -0
  633. package/dist/client-D5CZ2a34.d.ts +455 -0
  634. package/dist/client-DAHsEOVV.d.ts +155 -0
  635. package/dist/client-DG7FwgZD.js +104 -0
  636. package/dist/client-DIrCmOXz.d.ts +157 -0
  637. package/dist/client-DNq8xYb-.js +52 -0
  638. package/dist/client-DdfSIZ3M.d.ts +107 -0
  639. package/dist/client-DjTRlN3a.d.ts +68 -0
  640. package/dist/client-Ezlbskjq.js +60 -0
  641. package/dist/client-LLmgiCwJ.d.ts +135 -0
  642. package/dist/client-Lx3mlvKO.d.ts +100 -0
  643. package/dist/client-PGRk3DGz.js +98 -0
  644. package/dist/client-Tc47rlSe.d.ts +350 -0
  645. package/dist/client-VvY0K3wr.d.ts +59 -0
  646. package/dist/client-WAdEBBrH.d.ts +65 -0
  647. package/dist/client-WHeWTNVL.d.ts +130 -0
  648. package/dist/client-WgrPIHH-.js +213 -0
  649. package/dist/client-ZTtSV3l8.js +40 -0
  650. package/dist/client-b2_GjzzD.js +438 -0
  651. package/dist/client-ckXfdy1k.js +38 -0
  652. package/dist/client-e-hFkLUf.d.ts +34 -0
  653. package/dist/client-hyP_nS5R.d.ts +218 -0
  654. package/dist/client-i8glKhxh.js +67 -0
  655. package/dist/client-iDLLvGR4.d.ts +52 -0
  656. package/dist/client-pxjbgOz6.js +376 -0
  657. package/dist/client-xkSCp9hN.d.ts +101 -0
  658. package/dist/client-ysNShuJZ.d.ts +39 -0
  659. package/dist/clone-dN9XOL1K.js +29 -0
  660. package/dist/cloud-event-5rCEzIgK.d.ts +64 -0
  661. package/dist/cloud-event-CTh9Sr5w.js +60 -0
  662. package/dist/codecs-Bm46sVxr.d.ts +215 -0
  663. package/dist/codecs-YAekuQ08.js +358 -0
  664. package/dist/codegen-DeoSt1mi.d.ts +1571 -0
  665. package/dist/comments-D7sbd0xG.js +230 -0
  666. package/dist/commerce/index.d.ts +211 -0
  667. package/dist/commerce/index.js +517 -0
  668. package/dist/compiler-BVxepAY0.d.ts +14 -0
  669. package/dist/compose-Djntdacs.js +53 -0
  670. package/dist/composite-M6zPs1Xm.js +130 -0
  671. package/dist/composite-djtGy6bz.d.ts +67 -0
  672. package/dist/config/index.d.ts +7 -6
  673. package/dist/config/index.js +7 -4
  674. package/dist/config-BA1K4OPk.js +557 -0
  675. package/dist/config-C4MozTD7.js +3892 -0
  676. package/dist/connector-Cp8CqssJ.d.ts +107 -0
  677. package/dist/connectors-CjD-R2ks.d.ts +141 -0
  678. package/dist/context-1sSWcd7_.d.ts +365 -0
  679. package/dist/context-B8_p3MXo.js +11 -0
  680. package/dist/context-BDDgjoxz.js +41 -0
  681. package/dist/context-C-bHOtoD.js +5 -0
  682. package/dist/context-D6ZMKc2L.js +19 -0
  683. package/dist/context-wDKxSl9x.js +9 -0
  684. package/dist/controller-D6NyNrlZ.js +79 -0
  685. package/dist/controller-D845qKh2.d.ts +46 -0
  686. package/dist/credentials/index.d.ts +15 -5
  687. package/dist/credentials/index.js +17 -17
  688. package/dist/cron-CUaKTjWC.js +145 -0
  689. package/dist/cron-route-CoL-By8Z.js +24 -0
  690. package/dist/csv-CVfXqaAu.js +89 -0
  691. package/dist/csv-D3eKxV1T.d.ts +28 -0
  692. package/dist/define-B2ln373W.js +1896 -0
  693. package/dist/define-DxHHbNEb.d.ts +1005 -0
  694. package/dist/define-block-B6Gjs57G.js +52 -0
  695. package/dist/define-block-CLZMEFeK.d.ts +256 -0
  696. package/dist/delegation-Dt8hMJWu.js +140 -0
  697. package/dist/delivery-B1mKaOen.js +30 -0
  698. package/dist/delivery-BeHgwS3k.d.ts +69 -0
  699. package/dist/documents-CWn2mtYf.d.ts +96 -0
  700. package/dist/edge/index.d.ts +68 -13
  701. package/dist/edge/index.js +75 -43
  702. package/dist/elysia/index.d.ts +1 -1
  703. package/dist/elysia/index.js +2 -2
  704. package/dist/email-BcmbIWOX.d.ts +42 -0
  705. package/dist/embeddings-C2S14foD.d.ts +78 -0
  706. package/dist/embeddings-CVeOoufZ.js +128 -0
  707. package/dist/ended-nIdGCHxk.d.ts +70 -0
  708. package/dist/entitlements-BvU5dLpW.js +45 -0
  709. package/dist/entitlements-CbzCKalR.d.ts +53 -0
  710. package/dist/env/index.d.ts +1 -1
  711. package/dist/env/index.js +12 -5
  712. package/dist/envelope-CHYk5MXU.js +90 -0
  713. package/dist/errors-8i6tSICm.js +301 -0
  714. package/dist/errors-PIpcoe4z.js +44 -0
  715. package/dist/escape-like-AUEPn-C5.d.ts +15 -0
  716. package/dist/eve/index.d.ts +5 -5
  717. package/dist/eve/index.js +11 -17
  718. package/dist/eve-DUF70Vgi.d.ts +151 -0
  719. package/dist/event-calendar-DJXXMJ3x.d.ts +217 -0
  720. package/dist/event-map-Dy2vKHai.js +19 -0
  721. package/dist/events/index.d.ts +4 -4
  722. package/dist/events/index.js +16 -8
  723. package/dist/events-CTreRrgP.d.ts +800 -0
  724. package/dist/events-xbpHkcK9.js +82 -0
  725. package/dist/executor-BBHgjUJu.d.ts +39 -0
  726. package/dist/executor-BINiCFNp.d.ts +95 -0
  727. package/dist/executor-BXSHYyW2.js +735 -0
  728. package/dist/executor-D1kYY5BA.js +206 -0
  729. package/dist/executor-D3K3tycZ.js +147 -0
  730. package/dist/executor-DKrZr3AC.d.ts +174 -0
  731. package/dist/executor-DoE-5iM8.d.ts +272 -0
  732. package/dist/expo/index.d.ts +4 -4
  733. package/dist/expo/index.js +7 -7
  734. package/dist/expo-sqlite/index.d.ts +3 -3
  735. package/dist/expo-sqlite/index.js +2 -2
  736. package/dist/extra-CGQ2_q3S.js +10 -0
  737. package/dist/field-errors-CWXN_h_E.d.ts +113 -0
  738. package/dist/field-errors-DZVRWRkf.js +13 -0
  739. package/dist/field-formats-Cif5gr7c.js +102 -0
  740. package/dist/field-formats-DCvOQlOy.d.ts +39 -0
  741. package/dist/filter-evaluate-C0ULNfS7.js +214 -0
  742. package/dist/filter-evaluate-CjcFq0RT.d.ts +34 -0
  743. package/dist/filter-query-B3lhckKX.js +518 -0
  744. package/dist/filter-query-BKmRYrTE.d.ts +121 -0
  745. package/dist/flags-D_D1jAHB.d.ts +230 -0
  746. package/dist/flags-XAOsdNAc.js +279 -0
  747. package/dist/flags-sdk/index.d.ts +143 -0
  748. package/dist/flags-sdk/index.js +175 -0
  749. package/dist/form-definition-sagoefQr.d.ts +95 -0
  750. package/dist/format-CNwSjXUU.d.ts +70 -0
  751. package/dist/framework-DG5Bv39u.d.ts +26 -0
  752. package/dist/framework-INbjMZX1.js +51 -0
  753. package/dist/function-contract-B4c0XuTU.d.ts +21 -0
  754. package/dist/function-contract-DmkBg19r.js +5 -0
  755. package/dist/gateway-Cup00l0w.d.ts +109 -0
  756. package/dist/gateway-options-ClvvfuuU.d.ts +29 -0
  757. package/dist/gateway-options-DcLcWL5_.js +27 -0
  758. package/dist/graph-Cs28bOlK.js +360 -0
  759. package/dist/groups-CxonH3u5.js +16 -0
  760. package/dist/guards-6F2bCtQR.js +12 -0
  761. package/dist/h3/index.d.ts +7 -3
  762. package/dist/h3/index.js +3 -3
  763. package/dist/h3/v1/index.d.ts +1 -1
  764. package/dist/h3/v1/index.js +2 -2
  765. package/dist/history-GH1HJWQV.js +271 -0
  766. package/dist/hmac-DCud0myt.js +22 -0
  767. package/dist/hono/index.d.ts +33 -14
  768. package/dist/hono/index.js +58 -25
  769. package/dist/http-BF-V0CUF.js +25 -0
  770. package/dist/impersonation-CDeCzZP6.js +62 -0
  771. package/dist/impersonation-D5chOkrO.d.ts +25 -0
  772. package/dist/inbox-3ql4phyr.d.ts +400 -0
  773. package/dist/index-BIi8i6BO.d.ts +97 -0
  774. package/dist/index-BkzNUPId.d.ts +131 -0
  775. package/dist/index-BlqrGvb3.d.ts +227 -0
  776. package/dist/index-Brhm22eL.d.ts +138 -0
  777. package/dist/index-Bvw9r94Q.d.ts +245 -0
  778. package/dist/index-CETRk4YO.d.ts +82 -0
  779. package/dist/index-CrZitvSC.d.ts +258 -0
  780. package/dist/index-DfVXx4Ia.d.ts +202 -0
  781. package/dist/index-DygICr8c.d.ts +206 -0
  782. package/dist/index-Ej8XQ9w9.d.ts +58 -0
  783. package/dist/index-jhqhynmh.d.ts +58 -0
  784. package/dist/index.d.ts +90 -15
  785. package/dist/index.js +16 -14
  786. package/dist/iso4217-A8ev-CNW.js +176 -0
  787. package/dist/json-schema-CpYINXG8.js +548 -0
  788. package/dist/jws-35a8VhFV.d.ts +60 -0
  789. package/dist/jws-milwSg7E.js +191 -0
  790. package/dist/kit-D5S7KNFe.d.ts +66 -0
  791. package/dist/kit-MUK34-ZG.js +104 -0
  792. package/dist/knowledge-BXQ2-V0a.d.ts +187 -0
  793. package/dist/knowledge-CJ_Mm3ic.js +272 -0
  794. package/dist/lint/index.js +9 -9
  795. package/dist/list/index.d.ts +4 -3
  796. package/dist/list/index.js +4 -2
  797. package/dist/list-query-CBXNfJt4.js +549 -0
  798. package/dist/list-query-PvP3pPGQ.d.ts +194 -0
  799. package/dist/live-DwDreq1n.js +239 -0
  800. package/dist/mcp/index.d.ts +67 -20
  801. package/dist/mcp/index.js +220 -135
  802. package/dist/mcp/sdk/index.d.ts +38 -6
  803. package/dist/mcp/sdk/index.js +89 -7
  804. package/dist/message-B0fNJgq8.d.ts +93 -0
  805. package/dist/messages-Cx4ttLJJ.js +493 -0
  806. package/dist/metric-definition-95HFoW1V.d.ts +70 -0
  807. package/dist/metric-definition-BjxVn4R5.js +117 -0
  808. package/dist/mfa-DtflCXEt.d.ts +30 -0
  809. package/dist/model-lUafmeBQ.d.ts +311 -0
  810. package/dist/model-messages-CTu-6kBu.js +206 -0
  811. package/dist/model-messages-D4GZllOD.d.ts +34 -0
  812. package/dist/money-95Rff2vT.js +185 -0
  813. package/dist/money-DFpWzQvk.d.ts +76 -0
  814. package/dist/money-codec-C_-K5ZUU.js +41 -0
  815. package/dist/nestjs/index.d.ts +2 -2
  816. package/dist/nestjs/index.js +2 -2
  817. package/dist/next/index.d.ts +115 -55
  818. package/dist/next/index.js +208 -173
  819. package/dist/node/index.d.ts +2 -2
  820. package/dist/node/index.js +3 -3
  821. package/dist/nuxt/index.d.ts +2 -2
  822. package/dist/nuxt/index.js +3 -2
  823. package/dist/onboarding-BZvLLPaY.js +68 -0
  824. package/dist/openapi/index.d.ts +4 -2
  825. package/dist/openapi/index.js +21 -343
  826. package/dist/operations-C9-UcReN.d.ts +6 -0
  827. package/dist/operations-CsIfMED7.js +29 -0
  828. package/dist/optional-peer-Dx8TaYXw.js +29 -0
  829. package/dist/options-B0FcEKtH.js +5 -0
  830. package/dist/options-B5BU2Yg7.js +11 -0
  831. package/dist/options-B5woz53h.js +5 -0
  832. package/dist/options-B7EJaOX-.js +5 -0
  833. package/dist/options-B9q8CROT.js +9 -0
  834. package/dist/options-BA6jV6py.js +10 -0
  835. package/dist/options-BAW2ZlZ8.js +8 -0
  836. package/dist/options-BMjcVuaI.js +82 -0
  837. package/dist/options-BOOEzor9.js +5 -0
  838. package/dist/options-BQ07tTYr.js +11 -0
  839. package/dist/options-BZsoPJGX.js +5 -0
  840. package/dist/options-BesyRBnM.js +16 -0
  841. package/dist/options-Bf96aVk5.js +10 -0
  842. package/dist/options-BlOPivzq.js +8 -0
  843. package/dist/options-Blg8lAkz.js +9 -0
  844. package/dist/options-Bn4cu0gt.js +5 -0
  845. package/dist/options-BnoJOwXK.js +8 -0
  846. package/dist/options-Bp7sgKvl.js +30 -0
  847. package/dist/options-BqO9GYig.js +311 -0
  848. package/dist/options-BxcFLL1G.js +8 -0
  849. package/dist/options-C1HR4UZd.js +13 -0
  850. package/dist/options-C239TLRF.js +14 -0
  851. package/dist/options-C2HesT4A.js +9 -0
  852. package/dist/options-C3EzJATk.js +10 -0
  853. package/dist/options-C3hZ1fbC.js +10 -0
  854. package/dist/options-C6rEL6U5.js +8 -0
  855. package/dist/options-CAzVf-1T.js +8 -0
  856. package/dist/options-CGKSUFUq.js +5 -0
  857. package/dist/options-CGjGE8xS.js +12 -0
  858. package/dist/options-CK5WiFwG.js +11 -0
  859. package/dist/options-CN7PHkhU.js +8 -0
  860. package/dist/options-CTZNpb2n.js +5 -0
  861. package/dist/options-CUqQ9pm7.js +9 -0
  862. package/dist/options-CVSWgZpY.js +8 -0
  863. package/dist/options-CXFz0xxS.js +8 -0
  864. package/dist/options-CZk_fbbg.js +9 -0
  865. package/dist/options-C_pb1Nd3.js +5 -0
  866. package/dist/options-CbSOj53r.d.ts +52 -0
  867. package/dist/options-ChD15QxJ.js +9 -0
  868. package/dist/options-CkScQRJR.js +12 -0
  869. package/dist/options-CljDnQt2.js +25 -0
  870. package/dist/options-CmraJhd9.js +5 -0
  871. package/dist/options-CoX6VKGb.js +8 -0
  872. package/dist/options-CrC78Tee.js +5 -0
  873. package/dist/options-Ctac2R0Q.js +11 -0
  874. package/dist/options-CyD7OObW.js +17 -0
  875. package/dist/options-D1blDihM.js +9 -0
  876. package/dist/options-D2Gd6VfS.js +8 -0
  877. package/dist/options-D2d1fFuw.js +11 -0
  878. package/dist/options-D40CQzji.js +8 -0
  879. package/dist/options-D7f2VKzj.js +25 -0
  880. package/dist/options-DARkpk2P.js +8 -0
  881. package/dist/options-DCduTMST.js +17 -0
  882. package/dist/options-DDzggjN7.js +8 -0
  883. package/dist/options-DMR68VAC.js +5 -0
  884. package/dist/options-DNKyN5uq.js +20 -0
  885. package/dist/options-DTDxFT6J.js +13 -0
  886. package/dist/options-DWpz3V3F.js +8 -0
  887. package/dist/options-DXqcJyOP.js +10 -0
  888. package/dist/options-DYBQ973I.js +8 -0
  889. package/dist/options-Dh4wu9Ks.js +15 -0
  890. package/dist/options-Dmg1Da9P.js +25 -0
  891. package/dist/options-DsUgamiy.js +5 -0
  892. package/dist/options-EsUh744F.js +13 -0
  893. package/dist/options-Fz6xqu-b.js +5 -0
  894. package/dist/options-HSv8R6h5.js +13 -0
  895. package/dist/options-I8zVkB_y.js +8 -0
  896. package/dist/options-MHhjOoWz.js +5 -0
  897. package/dist/options-MLxMkd5B.js +11 -0
  898. package/dist/options-OJ5zmgr8.js +10 -0
  899. package/dist/options-QKP9FFcK.js +8 -0
  900. package/dist/options-SViK_2x2.js +12 -0
  901. package/dist/options-XgfTctbI.js +5 -0
  902. package/dist/options-_9arpsX9.js +11 -0
  903. package/dist/options-eBPsk4WI.js +11 -0
  904. package/dist/options-kLKILdIu.js +10 -0
  905. package/dist/options-n22NK3PL.js +8 -0
  906. package/dist/options-oeAq4Ho5.js +12 -0
  907. package/dist/options-qU8vgxhO.js +18 -0
  908. package/dist/options-vXMBEWSH.js +5 -0
  909. package/dist/options-wFnK3qWl.js +9 -0
  910. package/dist/options-xVAy3UsV.js +9 -0
  911. package/dist/organizations-Cw7om8uk.js +398 -0
  912. package/dist/orpc/index.d.ts +26 -10
  913. package/dist/orpc/index.js +66 -44
  914. package/dist/otel/index.d.ts +3 -3
  915. package/dist/otel/index.js +42 -7
  916. package/dist/outbox-BTeqjbum.d.ts +181 -0
  917. package/dist/overlay/index.d.ts +233 -0
  918. package/dist/overlay/index.js +554 -0
  919. package/dist/payments-h45bswA-.js +16 -0
  920. package/dist/pg-error-BV_X8Isq.js +26 -0
  921. package/dist/plugin-CDLJRFFg.d.ts +190 -0
  922. package/dist/plugins/actor/index.d.ts +1 -1
  923. package/dist/plugins/actor/index.js +1 -1
  924. package/dist/plugins/rules/index.d.ts +2 -2
  925. package/dist/plugins/rules/index.js +2 -2
  926. package/dist/plugins/soft-delete/index.d.ts +3 -3
  927. package/dist/plugins/soft-delete/index.js +11 -4
  928. package/dist/plugins/tenant/index.d.ts +9 -3
  929. package/dist/plugins/tenant/index.js +17 -3
  930. package/dist/plugins/timestamps/index.d.ts +1 -1
  931. package/dist/plugins/timestamps/index.js +8 -1
  932. package/dist/plugins/validation/index.d.ts +2 -2
  933. package/dist/plugins/validation/index.js +4 -4
  934. package/dist/pool-CwOCsX9e.d.ts +114 -0
  935. package/dist/pool-errors-GMjlCN0d.js +27 -0
  936. package/dist/ports-Ca63W4cW.d.ts +285 -0
  937. package/dist/ports-DAdQyjZz.d.ts +86 -0
  938. package/dist/ports-DGK3KTDH.js +133 -0
  939. package/dist/postgres/index.d.ts +28 -6
  940. package/dist/postgres/index.js +54 -22
  941. package/dist/postgrest-Cw9Bs5gm.d.ts +53 -0
  942. package/dist/powersync/index.d.ts +5 -5
  943. package/dist/powersync/index.js +4 -4
  944. package/dist/powersync/react/index.d.ts +8 -3
  945. package/dist/powersync/react/index.js +11 -3
  946. package/dist/preset/index.d.ts +352 -0
  947. package/dist/preset/index.js +564 -0
  948. package/dist/problem-CEjyhV5T.d.ts +76 -0
  949. package/dist/problem-pIiL3WbE.js +159 -0
  950. package/dist/provider-9gBq9W6k.d.ts +113 -0
  951. package/dist/provider-DKh2xFZb.js +57 -0
  952. package/dist/push-token-D6REHMMw.js +16 -0
  953. package/dist/push-token-asrmi7-6.d.ts +24 -0
  954. package/dist/query/index.d.ts +2 -2
  955. package/dist/query/index.js +1 -1
  956. package/dist/query-Ctz-qKRx.js +303 -0
  957. package/dist/range-DwpWe8e7.js +7 -0
  958. package/dist/range-p5V4rBhZ.d.ts +8 -0
  959. package/dist/rank-keys-DcPMt_Jk.js +60 -0
  960. package/dist/rank-result-DS8IoLup.js +18 -0
  961. package/dist/rank-result-Dngpt2n5.d.ts +14 -0
  962. package/dist/rate-limit--QSiFA6D.js +325 -0
  963. package/dist/rate-limit-BtbddDnE.js +49 -0
  964. package/dist/rate-limit-C88MEAOm.d.ts +41 -0
  965. package/dist/ratelimit-headers-Bsxx0Tj2.js +62 -0
  966. package/dist/react/index.d.ts +9 -9
  967. package/dist/react/index.js +4 -5
  968. package/dist/react/native/index.d.ts +1 -1
  969. package/dist/react/native/index.js +2 -2
  970. package/dist/react/server.d.ts +10 -10
  971. package/dist/react/server.js +4 -4
  972. package/dist/react/session.d.ts +2 -2
  973. package/dist/react-CKXUkwPx.js +410 -0
  974. package/dist/react-controller-Xn-IU44p.js +40 -0
  975. package/dist/react-env-Cc7Vf6eb.js +13 -0
  976. package/dist/react-router/index.d.ts +6 -6
  977. package/dist/react-router/index.js +10 -12
  978. package/dist/read-set-GEb-i0On.js +314 -0
  979. package/dist/realtime/index.d.ts +8 -4
  980. package/dist/realtime/index.js +5 -333
  981. package/dist/realtime-status-D2dw1hOE.js +12 -0
  982. package/dist/realtime-status-DcsO00Gw.d.ts +8 -0
  983. package/dist/refusal-br4Ma9Cf.js +61 -0
  984. package/dist/refusal-oD3ISM9h.d.ts +18 -0
  985. package/dist/replicas-BvIL4_jL.js +94 -0
  986. package/dist/resolve-CAR9oaKW.js +869 -0
  987. package/dist/resolve-w9EpHzuM.d.ts +266 -0
  988. package/dist/resource-B4ka8dDH.d.ts +106 -0
  989. package/dist/resource-C8r5xGqY.js +463 -0
  990. package/dist/resource-DO4gbVi5.js +91 -0
  991. package/dist/resource-execute-D0yQ-8WR.d.ts +12 -0
  992. package/dist/resource-schemas-BJ518zFH.js +79 -0
  993. package/dist/resource-types-D2vEQVXI.d.ts +141 -0
  994. package/dist/resources-BklF-rjz.d.ts +7 -0
  995. package/dist/resources-BlZdLsWQ.js +64 -0
  996. package/dist/respond-C7I8kLK_.d.ts +93 -0
  997. package/dist/respond-DdhZ9Wbn.js +95 -0
  998. package/dist/result-BlgnMB0H.js +128 -0
  999. package/dist/result-Cj3yWhjH.d.ts +298 -0
  1000. package/dist/rrule-zBh3CA1r.js +290 -0
  1001. package/dist/rules-B0-3Iosu.js +261 -0
  1002. package/dist/run-watch-CQRdpy-f.js +53 -0
  1003. package/dist/sales-lines-BAk8In-Z.js +41 -0
  1004. package/dist/sales-lines-C6gafAwg.d.ts +28 -0
  1005. package/dist/sales-shared-DAAGwQwN.d.ts +8 -0
  1006. package/dist/sales-shared-SblIgCgI.js +22 -0
  1007. package/dist/scope-DgWjuXUw.js +90 -0
  1008. package/dist/search-B6h03cAx.js +106 -0
  1009. package/dist/search-BtoWY6n_.js +9 -0
  1010. package/dist/server/index.d.ts +211 -43
  1011. package/dist/server/index.js +296 -19
  1012. package/dist/server-types-OohhIQb2.d.ts +737 -0
  1013. package/dist/session-DiWHtYrO.d.ts +95 -0
  1014. package/dist/settings-BXFn9zpS.js +90 -0
  1015. package/dist/shared-BmMcMoW9.js +89 -0
  1016. package/dist/shared-DbO3Dfms.js +14 -0
  1017. package/dist/shared-as0EG51f.js +60 -0
  1018. package/dist/sign-in-D0xN6E_l.js +360 -0
  1019. package/dist/signatures-B41ApWXA.js +145 -0
  1020. package/dist/signatures-BMdJ7neI.d.ts +43 -0
  1021. package/dist/signers-CXt_wA9S.d.ts +385 -0
  1022. package/dist/signing-keys-Bq9mMCTh.d.ts +90 -0
  1023. package/dist/solid/index.d.ts +9 -18
  1024. package/dist/solid/index.js +4 -9
  1025. package/dist/solid-controller-DLsmrczT.js +33 -0
  1026. package/dist/solid-controller-DqlvYFZa.d.ts +11 -0
  1027. package/dist/solid-start/index.d.ts +8 -12
  1028. package/dist/solid-start/index.js +10 -9
  1029. package/dist/spec/index.d.ts +154 -0
  1030. package/dist/spec/index.js +386 -0
  1031. package/dist/spec-pins-Dqpml2dZ.d.ts +84 -0
  1032. package/dist/spec-pins-S4PymRxp.js +60 -0
  1033. package/dist/sql/index.d.ts +327 -140
  1034. package/dist/sql/index.js +71245 -23282
  1035. package/dist/sql-DJrXG-3Z.js +422 -0
  1036. package/dist/sso-BDva_-4y.js +217 -0
  1037. package/dist/sso-BN0LnMqE.d.ts +131 -0
  1038. package/dist/ssr/index.d.ts +5 -6
  1039. package/dist/ssr/index.js +4 -3
  1040. package/dist/standard-B5fe2gnW.js +25 -0
  1041. package/dist/standard-C3_AAF3g.d.ts +7 -0
  1042. package/dist/stats-D6vkb89f.js +1128 -0
  1043. package/dist/storage/index.d.ts +4 -6
  1044. package/dist/storage/index.js +23 -20
  1045. package/dist/storage-api-Cx-1iWBd.d.ts +582 -0
  1046. package/dist/store-B5qYKsTh.d.ts +68 -0
  1047. package/dist/streams/index.d.ts +5 -5
  1048. package/dist/streams/index.js +6 -5
  1049. package/dist/streams/redis/index.d.ts +1 -1
  1050. package/dist/streams/redis/index.js +6 -12
  1051. package/dist/stripe/index.d.ts +16 -0
  1052. package/dist/stripe/index.js +14 -0
  1053. package/dist/stripe-NVcNOhHy.d.ts +140 -0
  1054. package/dist/stripe-XZrSmDTf.js +32 -0
  1055. package/dist/subject-readers-DiePmaYP.js +46 -0
  1056. package/dist/subject-readers-fxP5wu0s.d.ts +21 -0
  1057. package/dist/subjects-z8VWA_lF.d.ts +69 -0
  1058. package/dist/subscribers-Cq--DL1E.js +34 -0
  1059. package/dist/supabase-mcp-C6tMoEjn.d.ts +43 -0
  1060. package/dist/supabase-mcp-DomZ-amK.js +28 -0
  1061. package/dist/support-BsKkvA92.js +522 -0
  1062. package/dist/support-view-BbcZR7Io.d.ts +17 -0
  1063. package/dist/svelte/index.d.ts +8 -17
  1064. package/dist/svelte/index.js +3 -3
  1065. package/dist/svelte-controller-CDAujo-_.js +50 -0
  1066. package/dist/svelte-controller-DxxHEHxD.d.ts +10 -0
  1067. package/dist/sveltekit/index.d.ts +11 -13
  1068. package/dist/sveltekit/index.js +12 -14
  1069. package/dist/table-schema-pQlER3jj.js +283 -0
  1070. package/dist/tags-Dw8vKkcI.d.ts +30 -0
  1071. package/dist/tags-PaG0Ns_9.js +84 -0
  1072. package/dist/tanstack-db/index.d.ts +2 -2
  1073. package/dist/tanstack-db/index.js +1 -1
  1074. package/dist/tanstack-db/supabase/index.d.ts +51 -0
  1075. package/dist/tanstack-db/supabase/index.js +268 -0
  1076. package/dist/tanstack-start/index.d.ts +7 -7
  1077. package/dist/tanstack-start/index.js +9 -13
  1078. package/dist/tax-DDZUB_oc.d.ts +273 -0
  1079. package/dist/tax-D_kSCdWU.js +140 -0
  1080. package/dist/tee-Bsisfd7t.js +101 -0
  1081. package/dist/template-DdgYjIZ5.js +123 -0
  1082. package/dist/temporal-CB5Fpo5d.js +79 -0
  1083. package/dist/temporal-required-DqRzr7i0.js +20 -0
  1084. package/dist/tenant-B-fiItlJ.js +27 -0
  1085. package/dist/tenant-DdmVhsff.d.ts +17 -0
  1086. package/dist/tenant-naming-Bsj3Uvap.js +27 -0
  1087. package/dist/testing/index.d.ts +459 -125
  1088. package/dist/testing/index.js +2368 -720
  1089. package/dist/timing-BMCWgpdZ.js +92 -0
  1090. package/dist/topic-ByDz9edV.js +542 -0
  1091. package/dist/topic-cMS7UtM1.d.ts +359 -0
  1092. package/dist/ttl-cache-XzZ-Q2eX.js +29 -0
  1093. package/dist/types-6oiy6rIa.d.ts +205 -0
  1094. package/dist/types-BRTSpOIh.js +5 -0
  1095. package/dist/types-CdP0z5tS.d.ts +564 -0
  1096. package/dist/types-D0W4fnsc.d.ts +162 -0
  1097. package/dist/types-R6syp1el.js +29 -0
  1098. package/dist/types-YfwpIE-d.d.ts +357 -0
  1099. package/dist/types-pNY_UpDs.d.ts +240 -0
  1100. package/dist/types-vaoP9S9_.d.ts +635 -0
  1101. package/dist/undo-CEGIRkPA.js +44 -0
  1102. package/dist/undo-DGo0skyO.d.ts +43 -0
  1103. package/dist/usage-CdlfuS3i.js +250 -0
  1104. package/dist/usage-DM2rzczj.d.ts +202 -0
  1105. package/dist/vault-tOkPLnMB.d.ts +50 -0
  1106. package/dist/vercel-connect/index.d.ts +1 -1
  1107. package/dist/vercel-connect/index.js +6 -12
  1108. package/dist/verify-D63A2ALE.d.ts +142 -0
  1109. package/dist/verify-EQcC3Khp.js +126 -0
  1110. package/dist/version-D87ZteKy.js +4 -0
  1111. package/dist/view-DZ63nqwt.js +105 -0
  1112. package/dist/view-Dv0A949a.d.ts +90 -0
  1113. package/dist/vue/index.d.ts +9 -18
  1114. package/dist/vue/index.js +4 -17
  1115. package/dist/vue-controller-C9tFzqAc.js +32 -0
  1116. package/dist/vue-controller-HPfMTDa2.d.ts +11 -0
  1117. package/dist/watch-DDuWYv0Y.d.ts +84 -0
  1118. package/dist/watch-DT_B3CnJ.js +139 -0
  1119. package/dist/watch-topic-EFpOIIDE.d.ts +28 -0
  1120. package/dist/watch-topic-miuymrli.js +57 -0
  1121. package/dist/wire-DEY0ajW9.js +45 -0
  1122. package/dist/workflow-builder-OrglbXUh.js +681 -0
  1123. package/dist/workflow-sdk/builder/index.d.ts +46 -15
  1124. package/dist/workflow-sdk/builder/index.js +69 -21
  1125. package/dist/workflow-sdk/index.d.ts +75 -2
  1126. package/dist/workflow-sdk/index.js +83 -3
  1127. package/dist/workflow-sdk/world/index.d.ts +51 -20
  1128. package/dist/workflow-sdk/world/index.js +189 -128
  1129. package/dist/workflow-sdk-BZ6qsRlY.js +243 -0
  1130. package/dist/workflow-sdk-q8cLwW1K.d.ts +161 -0
  1131. package/dist/workflow-sdk-world-DPMdBfzn.js +2103 -0
  1132. package/dist/workflows-C-OvZpeg.js +282 -0
  1133. package/dist/workflows-DFQeXDAI.d.ts +243 -0
  1134. package/dist/yjs/index.d.ts +67 -0
  1135. package/dist/yjs/index.js +212 -0
  1136. package/package.json +837 -44
  1137. package/schemas/cli-commands-v1.json +220 -0
  1138. package/schemas/cli-result-v1.json +138 -0
  1139. package/schemas/config-v1.json +4317 -653
  1140. package/schemas/doctor-report-v1.json +27 -1
  1141. package/schemas/snapshot-v2.json +271 -0
  1142. package/schemas/spec-manifest-v1.json +95 -0
  1143. package/skills/better-supabase/SKILL.md +19 -8
  1144. package/skills/better-supabase/references/plugins.md +2 -2
  1145. package/skills/better-supabase/references/troubleshooting.md +20 -20
  1146. package/skills/better-supabase/references/ui-recipes.md +18652 -0
  1147. package/skills/better-supabase-api/SKILL.md +14 -14
  1148. package/skills/better-supabase-api/references/adapters.md +12 -2
  1149. package/skills/better-supabase-api/references/ai.md +4 -4
  1150. package/skills/better-supabase-api/references/expo.md +7 -4
  1151. package/skills/better-supabase-api/references/powersync.md +2 -1
  1152. package/skills/better-supabase-api/references/streams-credentials.md +8 -5
  1153. package/skills/better-supabase-auth/SKILL.md +18 -11
  1154. package/skills/better-supabase-auth/references/authorization-providers.md +5 -5
  1155. package/skills/better-supabase-testing/SKILL.md +2 -2
  1156. package/testing/act-cases.json +370 -0
  1157. package/dist/access-sql-B0dF-SoF.js +0 -181
  1158. package/dist/actor-CQTlc1Hh.d.ts +0 -43
  1159. package/dist/adapter-iKgjHVPx.js +0 -1190
  1160. package/dist/agents-CVHGd7It.d.ts +0 -94
  1161. package/dist/ai-cache-CBWs1W0k.js +0 -80
  1162. package/dist/ai-cache-DaDu_G5L.d.ts +0 -64
  1163. package/dist/ai-chat-7amvXjmQ.d.ts +0 -590
  1164. package/dist/ai-chat-B24UI962.js +0 -743
  1165. package/dist/ai-files-CSPNswUY.js +0 -319
  1166. package/dist/ai-tasks-Cd1HMFvB.d.ts +0 -131
  1167. package/dist/announcements-CiyOs-xP.js +0 -107
  1168. package/dist/announcements-ZRGnScWI.d.ts +0 -72
  1169. package/dist/api-keys-CIjghYjV.d.ts +0 -156
  1170. package/dist/assistant-DwdpDH1q.d.ts +0 -147
  1171. package/dist/attributes-5dYul0u0.js +0 -13
  1172. package/dist/authorization-BFCqamMs.d.ts +0 -172
  1173. package/dist/base64-D2gsioCY.js +0 -42
  1174. package/dist/before-route-CnR0C0Jr.js +0 -30
  1175. package/dist/bind-Bu_ZNa3W.d.ts +0 -62
  1176. package/dist/bind-l4kAvYSv.js +0 -97
  1177. package/dist/block-events-CrT8r7Fe.js +0 -76
  1178. package/dist/block-fields-GFkxl4dP.js +0 -49
  1179. package/dist/block-fields-SJ6fEf3o.d.ts +0 -31
  1180. package/dist/block-helpers-CKtbFcRv.d.ts +0 -37
  1181. package/dist/block-helpers-DWHxHsEQ.js +0 -190
  1182. package/dist/block-hooks-BmjMyXTa.js +0 -114
  1183. package/dist/block-hooks-plbZ0AbJ.d.ts +0 -107
  1184. package/dist/block-transport-BLr-ZgLc.js +0 -59
  1185. package/dist/block-transport-DvaoPuZ9.d.ts +0 -48
  1186. package/dist/bucket-Cl46E3jS.d.ts +0 -347
  1187. package/dist/build-BXIzE6Xv.js +0 -689
  1188. package/dist/channel-_2Mx1Oyu.d.ts +0 -70
  1189. package/dist/channels-CkgQ_X60.js +0 -114
  1190. package/dist/claims-DDBQT6BK.js +0 -61
  1191. package/dist/cli/bin.d.ts +0 -1
  1192. package/dist/cli/codemod-Bl_tQpHn.js +0 -491
  1193. package/dist/cli/command-CK14fP91.js +0 -502
  1194. package/dist/cli/config-B9HkL8nF.js +0 -2
  1195. package/dist/cli/config-DU7EJImt.js +0 -49
  1196. package/dist/cli/config-NiPxAmUF.js +0 -1077
  1197. package/dist/cli/db-DOBPt660.js +0 -52
  1198. package/dist/cli/diff-SjkO5rNr.js +0 -752
  1199. package/dist/cli/dist-DBPdlPYK.js +0 -1112
  1200. package/dist/cli/dist-DRAVaE6w.js +0 -842
  1201. package/dist/cli/dist-DreZ24Sz.js +0 -129
  1202. package/dist/cli/doctor-DJk0aeBi.js +0 -3591
  1203. package/dist/cli/env-CJLbUVPB.js +0 -108
  1204. package/dist/cli/env-qXgyMV6r.js +0 -511
  1205. package/dist/cli/errors-4v4DTtda.js +0 -56
  1206. package/dist/cli/fastest-levenshtein-CFN-lNDv.js +0 -120
  1207. package/dist/cli/gen-CCMc39Dx.js +0 -3100
  1208. package/dist/cli/gen-DRmzPI75.js +0 -2
  1209. package/dist/cli/init-BHuEQrQK.js +0 -765
  1210. package/dist/cli/introspect-DzR2nyQb.js +0 -81
  1211. package/dist/cli/io-DI1mTdSA.js +0 -33
  1212. package/dist/cli/jsonc-BUniUpOk.js +0 -2
  1213. package/dist/cli/keys-BGCnnb-s.js +0 -85
  1214. package/dist/cli/openapi-BlRJ18s3.js +0 -66
  1215. package/dist/cli/project-DZRaBaY7.js +0 -75
  1216. package/dist/cli/prompts-BNcNfAve.js +0 -1142
  1217. package/dist/cli/prompts-BTYQGunc.js +0 -2
  1218. package/dist/cli/read-sets-CETOSFx4.js +0 -223
  1219. package/dist/cli/rolldown-runtime-BPOCksWG.js +0 -24
  1220. package/dist/cli/run-BqDPh9UH.js +0 -361
  1221. package/dist/cli/seed-DQzqT7LP.js +0 -100
  1222. package/dist/cli/skills-QQs4q68J.js +0 -138
  1223. package/dist/cli/sql-B8csQPyn.js +0 -495
  1224. package/dist/cli/sql-layout-D6cphHT3.js +0 -69
  1225. package/dist/cli/style-C0NFdJRL.js +0 -29
  1226. package/dist/cli/supabase-toml-B-bIukQF.js +0 -1095
  1227. package/dist/cli/typegen-version-DeFbtzYI.js +0 -8
  1228. package/dist/cli/version-59gcepIG.js +0 -4
  1229. package/dist/client-CI0Z2zWX.js +0 -277
  1230. package/dist/clone-BfgmLU90.js +0 -21
  1231. package/dist/cloud-event-BnmD5fb9.js +0 -46
  1232. package/dist/cloud-event-C1JCc1bH.d.ts +0 -50
  1233. package/dist/compiler-DY_wkj4R.d.ts +0 -14
  1234. package/dist/compose-BIBNgAnq.js +0 -53
  1235. package/dist/composite--yqry7uW.d.ts +0 -146
  1236. package/dist/composite-DXVUibdi.js +0 -130
  1237. package/dist/config-D44Y7PAv.d.ts +0 -984
  1238. package/dist/config-Dn7F5k9A.js +0 -202
  1239. package/dist/connector-Dv8kK0MO.d.ts +0 -107
  1240. package/dist/connectors-CrpknU0P.d.ts +0 -120
  1241. package/dist/context-BCrWe7ow.d.ts +0 -237
  1242. package/dist/cron-DVPUg5k3.js +0 -145
  1243. package/dist/csv-DCK-PT1n.js +0 -25
  1244. package/dist/define-B-TVjC25.js +0 -1915
  1245. package/dist/define-CJJkkr1-.d.ts +0 -980
  1246. package/dist/embeddings-4ZvFzjsU.js +0 -127
  1247. package/dist/embeddings-C9KGQnXt.d.ts +0 -68
  1248. package/dist/ended-XjeGQ5XW.d.ts +0 -63
  1249. package/dist/entitlements-BKSVGtrG.d.ts +0 -51
  1250. package/dist/entitlements-DRl6ZJUm.js +0 -24
  1251. package/dist/envelope-DqnYGRw7.js +0 -47
  1252. package/dist/errors-B11Duf73.js +0 -266
  1253. package/dist/errors-DLjJHPLK.js +0 -44
  1254. package/dist/escape-like-ImTK0ps_.d.ts +0 -15
  1255. package/dist/eve-gT2Fpjut.d.ts +0 -151
  1256. package/dist/events-DWDhx77e.d.ts +0 -549
  1257. package/dist/executor-BVBFM86G.d.ts +0 -36
  1258. package/dist/executor-Bq28caBo.js +0 -718
  1259. package/dist/executor-C-R4pucm.js +0 -83
  1260. package/dist/executor-CaWigTyR.d.ts +0 -148
  1261. package/dist/executor-DbvExCFC.d.ts +0 -30
  1262. package/dist/executor-De1Of3m3.js +0 -523
  1263. package/dist/executor-DvsBbNBS.d.ts +0 -261
  1264. package/dist/field-errors-BFOa7WhB.d.ts +0 -99
  1265. package/dist/field-errors-VF1yb8yI.js +0 -13
  1266. package/dist/framework-BmzgK32X.d.ts +0 -25
  1267. package/dist/framework-a7aRCIqv.js +0 -51
  1268. package/dist/gateway-C1ssRHnf.d.ts +0 -130
  1269. package/dist/graph-BGyLLFLX.js +0 -265
  1270. package/dist/guards-BnzDvFrz.js +0 -10
  1271. package/dist/history-BZih6SFP.js +0 -64
  1272. package/dist/hooks-1BTCJsiw.js +0 -309
  1273. package/dist/impersonation-DcqaTBHx.js +0 -148
  1274. package/dist/inbox-i7E1ppo6.d.ts +0 -384
  1275. package/dist/index-ACiNPN4Z.d.ts +0 -74
  1276. package/dist/index-Bepi-Hgg.d.ts +0 -206
  1277. package/dist/index-BkWT_uBO.d.ts +0 -51
  1278. package/dist/index-Bxih3l0u.d.ts +0 -81
  1279. package/dist/index-CLg87OBW.d.ts +0 -76
  1280. package/dist/index-CaxrMD1A.d.ts +0 -1
  1281. package/dist/index-CdZKQF98.d.ts +0 -138
  1282. package/dist/index-CewnYSpv.d.ts +0 -267
  1283. package/dist/index-ClmjK_o-.d.ts +0 -55
  1284. package/dist/index-D48jVS-N.d.ts +0 -246
  1285. package/dist/index-DQh4VCc9.d.ts +0 -98
  1286. package/dist/index-DunNRdnT.d.ts +0 -300
  1287. package/dist/json-schema-CvER4kgT.js +0 -502
  1288. package/dist/keys-4MnkWTTh.js +0 -35
  1289. package/dist/kit-CkNzZUqv.d.ts +0 -60
  1290. package/dist/kit-Fm-Fv7q5.js +0 -78
  1291. package/dist/knowledge-BXBbT0Tr.d.ts +0 -176
  1292. package/dist/knowledge-CDmiMLew.js +0 -255
  1293. package/dist/list-query-BRt-zDF7.d.ts +0 -164
  1294. package/dist/list-query-gl808ac1.js +0 -459
  1295. package/dist/live-CTAZQkwl.js +0 -257
  1296. package/dist/message-CaKlqdsX.js +0 -219
  1297. package/dist/message-CfDoR0Y6.d.ts +0 -94
  1298. package/dist/messages-B9-5887d.js +0 -715
  1299. package/dist/messages-DYP0sUTe.d.ts +0 -59
  1300. package/dist/mfa-Daak8ukG.d.ts +0 -54
  1301. package/dist/modules-DpPwzC7E.d.ts +0 -192
  1302. package/dist/modules-dxrVK3ID.js +0 -228
  1303. package/dist/onboarding-BZGHYJks.d.ts +0 -62
  1304. package/dist/outbox-Cq7pPYvl.d.ts +0 -161
  1305. package/dist/path-Cv__-OTj.d.ts +0 -17
  1306. package/dist/plugin-FGY8UhYm.d.ts +0 -151
  1307. package/dist/pool-CAu2nLrL.d.ts +0 -89
  1308. package/dist/postgrest-BLVdEnfe.d.ts +0 -53
  1309. package/dist/problem-BreOl8b8.js +0 -115
  1310. package/dist/problem-DD8LZFjc.d.ts +0 -67
  1311. package/dist/provider-D-UEMvSD.d.ts +0 -113
  1312. package/dist/provider-Di3sRutW.js +0 -57
  1313. package/dist/query-BQ-NaZon.js +0 -303
  1314. package/dist/queue-CLJurhdy.d.ts +0 -427
  1315. package/dist/react-F80mF4-t.js +0 -409
  1316. package/dist/react-topic-seAWjL3_.js +0 -38
  1317. package/dist/read-set-DuKWC9Mj.js +0 -314
  1318. package/dist/refusal-CeJWxmkH.js +0 -61
  1319. package/dist/refusal-DhSU2Vvr.d.ts +0 -15
  1320. package/dist/replicas-CwrYp5Zj.js +0 -94
  1321. package/dist/resolve-ChTYeTEl.d.ts +0 -169
  1322. package/dist/resolve-tJZY3FEa.js +0 -697
  1323. package/dist/resource-BsvzCMlX.js +0 -212
  1324. package/dist/resource-IPS5xi9q.d.ts +0 -74
  1325. package/dist/respond-BUgsXNgk.js +0 -91
  1326. package/dist/respond-DprrgyXX.d.ts +0 -93
  1327. package/dist/result-D7y2fT87.d.ts +0 -282
  1328. package/dist/result-DzUbqgdW.js +0 -128
  1329. package/dist/scope-CDHcS7dE.js +0 -90
  1330. package/dist/search-CUWCRYKL.js +0 -9
  1331. package/dist/server-Bh0EVSwU.d.ts +0 -558
  1332. package/dist/session-ChiXDZdZ.d.ts +0 -72
  1333. package/dist/shared-CBxosKK3.js +0 -75
  1334. package/dist/shared-CxWmcyqB.js +0 -73
  1335. package/dist/sign-in-Cb1mwv6X.js +0 -86
  1336. package/dist/signers-4y62_VIi.d.ts +0 -166
  1337. package/dist/spec-pins--j6mTok4.js +0 -27
  1338. package/dist/spec-pins-C89s6DyW.d.ts +0 -27
  1339. package/dist/standard-BK0cqJ7y.js +0 -25
  1340. package/dist/standard-CYsm7xpT.d.ts +0 -7
  1341. package/dist/stats-D_AD9GGu.js +0 -1123
  1342. package/dist/store-CGjgWu5n.d.ts +0 -68
  1343. package/dist/stripe-BMj5LtsT.js +0 -38
  1344. package/dist/stripe-D04h-QBT.d.ts +0 -136
  1345. package/dist/support-ig_K4PvS.js +0 -314
  1346. package/dist/support-view-CVOJJLpc.d.ts +0 -17
  1347. package/dist/tags-Cx-LnIQP.d.ts +0 -30
  1348. package/dist/tee-CoEppCER.js +0 -101
  1349. package/dist/template--jDkl3UP.js +0 -114
  1350. package/dist/template-CwO38Do8.d.ts +0 -6
  1351. package/dist/temporal-BJGitm-h.js +0 -79
  1352. package/dist/temporal-required-BVvW7SYJ.js +0 -20
  1353. package/dist/tenant-BxNFk9bx.d.ts +0 -17
  1354. package/dist/tenant-I1TEZ_BX.js +0 -27
  1355. package/dist/timing-CyTQPubY.js +0 -92
  1356. package/dist/types-6BdhkmZe.d.ts +0 -340
  1357. package/dist/types-6cYK9pbJ.js +0 -29
  1358. package/dist/types-6rocye-y.d.ts +0 -156
  1359. package/dist/types-AYOvcyep.d.ts +0 -359
  1360. package/dist/types-C05bxW-W.d.ts +0 -220
  1361. package/dist/types-DGs5L0VN.d.ts +0 -192
  1362. package/dist/usage-CrvrL2vw.d.ts +0 -177
  1363. package/dist/vault-wlbBhqm7.d.ts +0 -50
  1364. package/dist/verify-DL41hbvY.js +0 -232
  1365. package/dist/verify-DPuWngD4.d.ts +0 -172
  1366. package/dist/version-C6OfRAIn.js +0 -4
  1367. package/dist/view-BeFcRV6G.js +0 -99
  1368. package/dist/view-CF7ihnkg.d.ts +0 -87
  1369. package/dist/watch-DI34G86j.d.ts +0 -60
  1370. package/dist/watch-Xuxrvxq-.js +0 -122
  1371. package/dist/wire-DtZQ4sdE.js +0 -45
  1372. package/dist/workflow-builder-DJ1oHn8g.js +0 -398
  1373. package/dist/workflow-sdk-B3yLD6Br.d.ts +0 -98
  1374. package/dist/workflow-sdk-C2WJ_G2O.js +0 -173
  1375. package/dist/workflow-sdk-world-D-prir6O.js +0 -1397
  1376. package/dist/workflows-B0j9WKPu.d.ts +0 -185
  1377. package/dist/workflows-wu1WWBn7.js +0 -216
@@ -1,3100 +0,0 @@
1
- import { r as defineCliCommand } from "./command-CK14fP91.js";
2
- import { n as CliError } from "./errors-4v4DTtda.js";
3
- import { i as writeIfChanged, n as importPath, r as sameText, t as display } from "./io-DI1mTdSA.js";
4
- import { r as painter } from "./style-C0NFdJRL.js";
5
- import { t as VERSION } from "./version-59gcepIG.js";
6
- import { a as entitlementsMode, c as unsafeKey, i as entitlementRequirements, n as accessProviderMode, o as moduleKeyProblems, r as accessRequirements, s as providerLabel, t as compiledReadSets } from "./read-sets-CETOSFx4.js";
7
- import { s as stdinDatabaseUrl, t as databaseUrl } from "./config-NiPxAmUF.js";
8
- import { l as pgFunctionHooks, p as tomlGet, u as readSupabaseToml } from "./supabase-toml-B-bIukQF.js";
9
- import { t as fileDiff } from "./diff-SjkO5rNr.js";
10
- import { t as byCodePoint } from "./compare-BmIWVEui.js";
11
- import { t as TYPEGEN_VERSION } from "./typegen-version-DeFbtzYI.js";
12
- import { n as withSpinner } from "./prompts-BNcNfAve.js";
13
- import { t as connect } from "./db-DOBPt660.js";
14
- import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
15
- import { existsSync } from "node:fs";
16
- import { mkdir, readFile, rename, rm, stat, writeFile } from "node:fs/promises";
17
- import { setTimeout } from "node:timers/promises";
18
- import { DEFAULT_CLAIMS, jsonSchema, tenantClaimPaths, valibot, zod } from "better-supabase/config";
19
- import { SQL_MODULES, moduleLayout, modulePermissionKeys, renderModules, resolveModules, resolveProviderSql, sameModuleFile } from "better-supabase/sql";
20
- import { toCamel } from "better-supabase";
21
- import { createHash } from "node:crypto";
22
- //#region src/cli/introspect/catalog.ts
23
- const byName = (a, b) => a.schema === b.schema ? a.name < b.name ? -1 : a.name > b.name ? 1 : 0 : a.schema < b.schema ? -1 : 1;
24
- function toColumn(column) {
25
- const isArray = column.data_type === "ARRAY";
26
- const udt = isArray ? column.format.replace(/^_/, "") : column.format;
27
- const defaultValue = column.default_value === null || column.default_value === void 0 ? null : String(column.default_value);
28
- return {
29
- name: column.name,
30
- udt,
31
- format: column.format,
32
- typeSchema: column.type_schema,
33
- isArray,
34
- isEnum: column.enums.length > 0,
35
- nullable: column.is_nullable,
36
- hasDefault: defaultValue !== null || column.identity_generation !== null || column.is_generated,
37
- default: defaultValue,
38
- identity: column.identity_generation === "ALWAYS" ? "always" : column.identity_generation === "BY DEFAULT" ? "by default" : null,
39
- generated: column.is_generated,
40
- updatable: column.is_updatable,
41
- comment: column.comment
42
- };
43
- }
44
- function toFunction(fn, typeOf, relationName) {
45
- const args = [];
46
- const table = [];
47
- fn.args.forEach((arg, index) => {
48
- const type = typeOf(arg.type_id);
49
- const raw = type?.name ?? "unknown";
50
- const typeSchema = type ? { typeSchema: type.schema } : {};
51
- const name = arg.name || `arg${index + 1}`;
52
- if (arg.mode === "in" || arg.mode === "inout" || arg.mode === "variadic") {
53
- const isArray = raw.startsWith("_");
54
- args.push({
55
- name,
56
- udt: isArray ? raw.slice(1) : raw,
57
- ...typeSchema,
58
- isArray,
59
- hasDefault: arg.has_default === true
60
- });
61
- }
62
- if (arg.mode === "table" || arg.mode === "out" || arg.mode === "inout") table.push({
63
- name,
64
- udt: raw,
65
- ...typeSchema
66
- });
67
- });
68
- const returnType = typeOf(fn.return_type_id);
69
- const searchPath = fn.config_params?.["search_path"];
70
- return {
71
- schema: fn.schema,
72
- name: fn.name,
73
- signature: fn.identity_argument_types,
74
- args,
75
- returnsTable: fn.args.some((arg) => arg.mode === "table") ? table : null,
76
- returns: returnType?.name ?? fn.return_type,
77
- ...returnType ? { returnsSchema: returnType.schema } : {},
78
- returnsRelation: relationName(fn.return_type_relation_id),
79
- returnsSet: fn.is_set_returning_function,
80
- volatility: fn.behavior.toLowerCase(),
81
- securityDefiner: fn.security_definer,
82
- language: fn.language,
83
- searchPath: searchPath === void 0 ? null : searchPath.replace(/^""$/, "")
84
- };
85
- }
86
- /** Joins the typegen metadata and the extras into one record per object. */
87
- function toCatalog(snapshot) {
88
- const meta = snapshot.generator;
89
- const extras = new Map(snapshot.extras.tables.map((table) => [table.id, table]));
90
- const columns = /* @__PURE__ */ new Map();
91
- for (const column of meta.columns) {
92
- const list = columns.get(column.table_id);
93
- if (list) list.push(column);
94
- else columns.set(column.table_id, [column]);
95
- }
96
- const primaryKeys = /* @__PURE__ */ new Map();
97
- for (const key of meta.primaryKeys) {
98
- const list = primaryKeys.get(key.table_id);
99
- if (list) list.push(key.name);
100
- else primaryKeys.set(key.table_id, [key.name]);
101
- }
102
- const relationNames = /* @__PURE__ */ new Map();
103
- for (const list of [
104
- meta.tables,
105
- meta.foreignTables,
106
- meta.views,
107
- meta.materializedViews
108
- ]) for (const entry of list) relationNames.set(entry.id, `${entry.schema}.${entry.name}`);
109
- const viewNames = new Set([...meta.views, ...meta.materializedViews].map((view) => `${view.schema}.${view.name}`));
110
- const foreignKeysOf = (schema, name, extra) => {
111
- const actions = new Map((extra?.foreignKeys ?? []).map((fk) => [fk.name, fk]));
112
- return meta.relationships.filter((rel) => rel.schema === schema && rel.relation === name && actions.has(rel.foreign_key_name) && !viewNames.has(`${rel.referenced_schema}.${rel.referenced_relation}`)).map((rel) => {
113
- const action = actions.get(rel.foreign_key_name);
114
- return {
115
- name: rel.foreign_key_name,
116
- columns: rel.columns,
117
- refSchema: rel.referenced_schema,
118
- refTable: rel.referenced_relation,
119
- refColumns: rel.referenced_columns,
120
- oneToOne: rel.is_one_to_one,
121
- onDelete: action?.onDelete ?? "no action",
122
- onUpdate: action?.onUpdate ?? "no action"
123
- };
124
- }).sort((a, b) => byCodePoint(a.name, b.name));
125
- };
126
- const build = (entry, flags) => {
127
- const extra = extras.get(entry.id);
128
- const own = [...columns.get(entry.id) ?? []].sort((a, b) => a.ordinal_position - b.ordinal_position);
129
- return {
130
- id: entry.id,
131
- schema: entry.schema,
132
- name: entry.name,
133
- comment: entry.comment,
134
- ...flags,
135
- columns: own.map(toColumn),
136
- primaryKey: extra && extra.primaryKey.length > 0 ? extra.primaryKey : primaryKeys.get(entry.id) ?? [],
137
- uniques: extra?.uniques ?? [],
138
- foreignKeys: foreignKeysOf(entry.schema, entry.name, extra),
139
- checks: extra?.checks ?? [],
140
- indexes: extra?.indexes ?? [],
141
- policies: extra?.policies ?? [],
142
- triggers: extra?.triggers ?? [],
143
- grants: extra?.grants ?? [],
144
- ...extra?.columnGrants ? { columnGrants: extra.columnGrants } : {}
145
- };
146
- };
147
- const tables = [
148
- ...meta.tables.map((table) => build(table, {
149
- kind: "table",
150
- rls: table.rls_enabled,
151
- forceRls: table.rls_forced,
152
- replicaIdentity: table.replica_identity,
153
- insertable: true,
154
- updatable: true
155
- })),
156
- ...meta.foreignTables.map((table) => build(table, {
157
- kind: "table",
158
- rls: false,
159
- forceRls: false,
160
- replicaIdentity: null,
161
- insertable: true,
162
- updatable: true
163
- })),
164
- ...meta.views.map((view) => build(view, {
165
- kind: "view",
166
- rls: false,
167
- forceRls: false,
168
- replicaIdentity: null,
169
- insertable: view.is_insert_enabled ?? view.is_updatable,
170
- updatable: view.is_update_enabled ?? view.is_updatable
171
- })),
172
- ...meta.materializedViews.map((view) => build(view, {
173
- kind: "view",
174
- rls: false,
175
- forceRls: false,
176
- replicaIdentity: null,
177
- insertable: false,
178
- updatable: false
179
- }))
180
- ].sort(byName);
181
- const included = new Set(snapshot.schemas);
182
- const enums = meta.types.filter((type) => type.enums.length > 0 && included.has(type.schema)).map((type) => ({
183
- schema: type.schema,
184
- name: type.name,
185
- values: type.enums
186
- })).sort(byName);
187
- const types = new Map(meta.types.map((type) => [type.id, type]));
188
- const functions = meta.functions.map((fn) => toFunction(fn, (id) => types.get(id), (id) => id === null ? null : relationNames.get(id) ?? null)).sort((a, b) => byName(a, b) || byCodePoint(a.signature, b.signature));
189
- return {
190
- schemas: snapshot.schemas,
191
- tables,
192
- enums,
193
- functions,
194
- buckets: snapshot.extras.buckets,
195
- realtime: snapshot.extras.realtime
196
- };
197
- }
198
- //#endregion
199
- //#region src/cli/doctor/shared.ts
200
- const catalogs = /* @__PURE__ */ new WeakMap();
201
- /** The snapshot joined per table and function, computed once per snapshot. */
202
- function catalogOf(context) {
203
- let catalog = catalogs.get(context.snapshot);
204
- if (!catalog) {
205
- catalog = toCatalog(context.snapshot);
206
- catalogs.set(context.snapshot, catalog);
207
- }
208
- return catalog;
209
- }
210
- /** `[api] schemas` from `config.toml`, the schemas PostgREST serves, or `config.schemas` without one. */
211
- function exposedSchemas(context) {
212
- const listed = context.configToml ? tomlGet(context.configToml.document, ["api", "schemas"]) : void 0;
213
- return Array.isArray(listed) && listed.every((entry) => typeof entry === "string") ? listed : context.config.schemas;
214
- }
215
- const exposed = (context) => {
216
- const schemas = exposedSchemas(context);
217
- return catalogOf(context).tables.filter((table) => schemas.includes(table.schema));
218
- };
219
- const qualified = (table) => `${table.schema}.${table.name}`;
220
- const tableObject = (table) => ({
221
- kind: "table",
222
- schema: table.schema,
223
- name: table.name
224
- });
225
- const policyObject = (table, policy) => ({
226
- kind: "policy",
227
- schema: table.schema,
228
- name: policy.name,
229
- table: table.name
230
- });
231
- const splitTexts = /* @__PURE__ */ new Map();
232
- const SPLIT_CACHE_SIZE = 64;
233
- /** `text` split into lines; doctor locates many objects in the same SQL files. */
234
- function linesOf(text) {
235
- let lines = splitTexts.get(text);
236
- if (!lines) {
237
- if (splitTexts.size >= SPLIT_CACHE_SIZE) splitTexts.clear();
238
- lines = text.split("\n");
239
- splitTexts.set(text, lines);
240
- }
241
- return lines;
242
- }
243
- /** Line number (1-based) of the first line matching `pattern`. */
244
- function lineOf(text, pattern) {
245
- const index = linesOf(text).findIndex((line) => pattern.test(line));
246
- return index === -1 ? void 0 : index + 1;
247
- }
248
- /** The keys of `authorization.permissions`, for `api-keys` scopes `"catalog"`. */
249
- const permissionCatalogKeys = (context) => context.config.authorization?.permissions?.map((entry) => entry.key);
250
- //#endregion
251
- //#region src/cli/doctor/authorization.ts
252
- const TEMPLATE_EFFECT = {
253
- memberIds: "their membership checks read the tenant module's memberships table instead of the provider",
254
- idsWithFor: "their checks of another user's tenant permissions (can_user, member_can) raise 0A000 (ACCESS_CALLER_ONLY) or are skipped",
255
- isPlatformFor: "their checks of another user's platform permissions (platform_can) answer false or are skipped",
256
- canAssignFor: "better_supabase.can_assign_as is not written and the inviter's right to assign the role is not checked again when the invitation is accepted"
257
- };
258
- /** The optional templates installed modules call that the provider doesn't set. */
259
- function missingTemplates(context, provider) {
260
- const installed = new Set(context.config.sql.moduleNames);
261
- const callers = /* @__PURE__ */ new Map();
262
- for (const module of Object.values(SQL_MODULES)) {
263
- if (!installed.has(module.name)) continue;
264
- for (const name of module.providerFunctions ?? []) {
265
- if (provider.functions[name] !== void 0) continue;
266
- if (name === "canAssignFor" && context.config.sql.modules.access?.functions?.canAssignFor) continue;
267
- callers.set(name, [...callers.get(name) ?? [], module.name]);
268
- }
269
- }
270
- return [...callers].map(([name, modules]) => ({
271
- severity: "warning",
272
- message: `The ${modules.join(", ")} ${modules.length > 1 ? "modules call" : "module calls"} authorization.functions.${name}, which ${providerLabel(provider)} doesn't set, so under the provider model ${TEMPLATE_EFFECT[name] ?? "those calls fail"}. Use a provider that sets ${name}${name === "canAssignFor" ? ", or set sql.modules.access.functions.canAssignFor" : ""}.`,
273
- target: `authorization.functions.${name}`
274
- }));
275
- }
276
- /** Tables whose generated policies call the provider's functions by role and scope only. */
277
- const POLICY_TABLES = /* @__PURE__ */ new Set(["storage.objects", "realtime.messages"]);
278
- const POLICY = /create\s+policy\s+("(?:[^"]|"")+"|[\w$]+)\s+on\s+((?:"[^"]+"|\w+)\s*\.\s*(?:"[^"]+"|\w+))([\s\S]*?);/gi;
279
- const unquote = (name) => name.replaceAll(/^"|"$/g, "").replaceAll("\"\"", "\"");
280
- const escapeRegExp = (text) => text.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`);
281
- /**
282
- * A pattern for a filled template: `{permission}` captures the key literal
283
- * (optionally passed by name), `{scope}` captures the scope name, and
284
- * whitespace may differ.
285
- */
286
- function templatePattern(template) {
287
- const source = template.split(/(\{\w+\})/).map((part) => {
288
- if (part === "{permission}") return String.raw`(?:\w+\s*=>\s*)?'((?:[^']|'')*)'`;
289
- if (part === "{scope}") return "([a-z][a-z0-9_]*)";
290
- if (/^\{\w+\}$/.test(part)) return String.raw`[\s\S]*?`;
291
- return escapeRegExp(part.trim()).replaceAll(/\s+/g, String.raw`\s*`);
292
- }).filter((part) => part !== "").join(String.raw`\s*`);
293
- return new RegExp(source, "gi");
294
- }
295
- /** The keys and scopes a policy body passes to the provider's `idsWith` and `isPlatform`. */
296
- function providerCalls(provider, body) {
297
- const calls = [];
298
- const { idsWith, isPlatform } = provider.functions;
299
- const groups = (template) => [...template.matchAll(/\{(permission|scope)\}/g)].map((match) => match[1]);
300
- const idsGroups = groups(idsWith);
301
- for (const match of body.matchAll(templatePattern(idsWith))) {
302
- const key = match[idsGroups.indexOf("permission") + 1];
303
- if (key === void 0) continue;
304
- const scopeIndex = idsGroups.indexOf("scope");
305
- calls.push({
306
- key: key.replaceAll("''", "'"),
307
- scope: scopeIndex === -1 ? provider.tenantScope : match[scopeIndex + 1]
308
- });
309
- }
310
- const platformGroups = groups(isPlatform);
311
- for (const match of body.matchAll(templatePattern(isPlatform))) {
312
- const key = match[platformGroups.indexOf("permission") + 1];
313
- if (key !== void 0) calls.push({
314
- key: key.replaceAll("''", "'"),
315
- scope: "platform"
316
- });
317
- }
318
- return calls;
319
- }
320
- /**
321
- * Policies better-supabase generates (`bs_` names) on `storage.objects` and
322
- * `realtime.messages` that call the provider's templates, with the keys
323
- * they pass. The first file that declares a policy wins, matching the
324
- * `sqlFiles` order (declarative schemas, then the newest migration).
325
- */
326
- function providerPolicies(provider, files) {
327
- const seen = /* @__PURE__ */ new Set();
328
- const found = [];
329
- for (const file of files) for (const match of file.text.matchAll(POLICY)) {
330
- const name = unquote(match[1]);
331
- const table = match[2].split(".").map((part) => unquote(part.trim())).join(".");
332
- if (!POLICY_TABLES.has(table) || !name.startsWith("bs_")) continue;
333
- const id = `${table}.${name}`;
334
- if (seen.has(id)) continue;
335
- seen.add(id);
336
- const calls = providerCalls(provider, match[3]);
337
- if (calls.length === 0) continue;
338
- found.push({
339
- name,
340
- table,
341
- calls,
342
- file: file.path,
343
- line: file.text.slice(0, match.index).split("\n").length
344
- });
345
- }
346
- return found;
347
- }
348
- /**
349
- * `buckets` entries whose access policy reaches the provider's functions:
350
- * through `sql` templates, or through the access contract under the
351
- * `provider` model. Their keys and scope (the tenant scope for `tenant`).
352
- */
353
- function providerBucketKeys(config) {
354
- const provider = config.authorization;
355
- if (!provider) return [];
356
- const providerModel = config.sql.modules.access?.model === "provider";
357
- return Object.entries(config.buckets).flatMap(([bucket, entry]) => {
358
- const policy = entry.policy;
359
- if (policy === void 0 || typeof policy === "string") return [];
360
- if (policy.sql === void 0 && !providerModel) return [];
361
- const scope = policy.scope ?? "tenant";
362
- return [{
363
- bucket,
364
- keys: [...new Set(Object.values(policy.access).filter((key) => typeof key === "string"))],
365
- scope: scope === "tenant" ? provider.tenantScope : scope
366
- }];
367
- });
368
- }
369
- /**
370
- * Why a policy's scope can't work with the provider: a scope it doesn't
371
- * declare, or a key it grants only at other scopes.
372
- */
373
- function placementProblems(provider, call, where) {
374
- if (call.scope === "platform") return [];
375
- const label = providerLabel(provider);
376
- if (!provider.scopes.some((scope) => scope.name === call.scope)) return [`${where} uses scope "${call.scope}", which ${label} doesn't declare. Use one of ${provider.scopes.map((scope) => scope.name).join(", ") || "its scopes"}.`];
377
- const declared = provider.permissions?.find((permission) => permission.key === call.key)?.scopes;
378
- if (!declared || declared.length === 0 || declared.includes(call.scope)) return [];
379
- return [`${where} checks "${call.key}" at scope "${call.scope}", but ${label} grants it at ${declared.map((scope) => `"${scope}"`).join(", ")}, so its SQL functions never grant it there. Use scope "${declared[0]}".`];
380
- }
381
- /** The provider's memberships for the `entitlements` SQL module, when that mode is valid. */
382
- function entitlementsModule(context) {
383
- const mode = entitlementsMode(context.config);
384
- return mode.kind === "provider" ? mode.provider : void 0;
385
- }
386
- /** The provider for the `provider` access model, when `sql.modules` installs `access`. */
387
- function accessModule(context) {
388
- if (!resolveModules(context.config.sql.moduleNames, {}).some((module) => module.name === "access")) return { kind: "off" };
389
- return accessProviderMode(context.config);
390
- }
391
- /**
392
- * Checks a function a template calls against `authorization.requires` and
393
- * the database: listed, executable by `role`, and present when the
394
- * snapshot read its schema. `undefined` when it passes.
395
- */
396
- function requirementProblem(context, provider, requirement, caller) {
397
- const label = providerLabel(provider);
398
- const listed = (provider.requires ?? []).filter((entry) => entry.function === requirement.function);
399
- if (provider.requires !== void 0 && listed.length === 0) return { message: `${caller} calls ${requirement.function}, but ${label} doesn't list it in authorization.requires. Use a provider version that lists every function its templates call.` };
400
- if (listed.length > 0 && !listed.some((entry) => entry.role === requirement.role)) return { message: `${label} says only ${listed.map((entry) => entry.role).join(", ")} may execute ${requirement.function}, but ${caller} calls it as ${requirement.role}. Grant it execute to ${requirement.role} through the provider.` };
401
- const schema = requirement.function.slice(0, requirement.function.indexOf("."));
402
- if (!context.snapshot.schemas.includes(schema)) return void 0;
403
- return catalogOf(context).functions.some((fn) => `${fn.schema}.${fn.name}` === requirement.function) ? void 0 : { message: `${requirement.function} is not in the database, but ${caller} calls it. Apply the provider's migration before the SQL modules.` };
404
- }
405
- const AUTHORIZATION_RULES = [
406
- {
407
- code: "BS214",
408
- severity: "error",
409
- title: "Permission the provider's SQL functions don't fully answer in a Storage or Realtime policy",
410
- description: "An access policy on a bucket or topic that reaches the authorization provider's functions (through `sql` templates, or through the access contract under the `provider` model) decides by role and scope only. A permission whose `authorization.permissions` entry isn't `sqlComplete: true` would grant every object or topic in the scope, so it is reported, and so is a key the provider doesn't list or every key when it lists no permissions. A scope the provider doesn't declare, and a key checked at another scope than its entry's `scopes`, are reported too. Doctor reads the keys from `buckets` in the config and from the generated `bs_` policies on `storage.objects` and `realtime.messages`. It also warns when a bucket's `sql` templates differ from the provider's `idsWith` and `isPlatform`, since a copy goes stale when the provider changes; `sql: \"provider\"` renders them at `gen` time instead.",
411
- check: (context) => {
412
- const provider = context.config.authorization;
413
- if (!provider) return [];
414
- const findings = [];
415
- for (const { bucket, keys, scope } of providerBucketKeys(context.config)) for (const key of keys) {
416
- for (const message of placementProblems(provider, {
417
- key,
418
- scope
419
- }, `buckets.${bucket} ("${key}")`)) findings.push({
420
- message,
421
- target: `buckets.${bucket}:${key}`
422
- });
423
- const problem = unsafeKey(provider, key);
424
- if (!problem) continue;
425
- findings.push({
426
- message: `buckets.${bucket} uses "${key}", which ${problem.reason}. The bucket policy could grant every object in the scope. ${problem.fix}`,
427
- target: `buckets.${bucket}:${key}`
428
- });
429
- }
430
- for (const [bucket, entry] of Object.entries(context.config.buckets)) {
431
- const sql = typeof entry.policy === "object" ? entry.policy.sql : void 0;
432
- if (typeof sql !== "object") continue;
433
- const stale = ["idsWith", "isPlatform"].filter((name) => sql[name] !== provider.functions[name]);
434
- if (stale.length === 0) continue;
435
- findings.push({
436
- severity: "warning",
437
- message: `buckets.${bucket} copies sql templates that differ from ${providerLabel(provider)}'s ${stale.join(" and ")}. Set sql: "provider" so gen renders the provider's templates.`,
438
- target: `buckets.${bucket}.policy.sql`
439
- });
440
- }
441
- for (const policy of providerPolicies(provider, context.sqlFiles ?? [])) {
442
- const seen = /* @__PURE__ */ new Set();
443
- for (const call of policy.calls) for (const message of placementProblems(provider, call, `Policy "${policy.name}" on ${policy.table}`)) {
444
- if (seen.has(message)) continue;
445
- seen.add(message);
446
- findings.push({
447
- message,
448
- target: `${policy.table}.${policy.name}:${call.key}`,
449
- location: {
450
- file: policy.file,
451
- line: policy.line
452
- }
453
- });
454
- }
455
- for (const key of new Set(policy.calls.map((call) => call.key))) {
456
- const problem = unsafeKey(provider, key);
457
- if (!problem) continue;
458
- findings.push({
459
- message: `Policy "${policy.name}" on ${policy.table} passes "${key}" to the provider's SQL functions, but it ${problem.reason}. ${problem.fix}`,
460
- target: `${policy.table}.${policy.name}:${key}`,
461
- location: {
462
- file: policy.file,
463
- line: policy.line
464
- }
465
- });
466
- }
467
- }
468
- return findings;
469
- }
470
- },
471
- {
472
- code: "BS408",
473
- severity: "warning",
474
- title: "The entitlements module can't read the provider's memberships",
475
- description: "With `entitlements.memberships: 'provider'` (the default with `authorization`), the `entitlements` SQL module reads memberships through the provider's `memberIds` template (in `has_entitlement`, as `authenticated`) and `memberIdsFor` (in `feature_claims`, which the provider's hook calls as `supabase_auth_admin`). Doctor warns when the provider can't back that mode (no tenant scope, an id type the module doesn't render, no `memberIds` or `memberIdsFor`), when its hook doesn't fill `claims.features` from `better_supabase.feature_claims` (unless `entitlements.claim` is `false`), when no membership table covers the tenant scope, and when a function those templates call is missing from `authorization.requires`, not executable by that role, or not in the database.",
476
- check: (context) => {
477
- if (!context.config.sql.moduleNames.includes("entitlements")) return [];
478
- const mode = entitlementsMode(context.config);
479
- if (mode.kind === "tenant") return [];
480
- if (mode.kind === "invalid") return [{
481
- message: mode.problem,
482
- target: "entitlements.memberships"
483
- }];
484
- const provider = context.config.authorization;
485
- const label = providerLabel(provider);
486
- const findings = [];
487
- const features = context.config.claims.features;
488
- const hook = provider.tokenHook;
489
- if (hook && context.config.entitlements.claim !== false) {
490
- const claims = hook.registeredClaims ?? [];
491
- const featureClaim = claims.find((claim) => claim.name === features);
492
- if (featureClaim?.function !== "better_supabase.feature_claims") {
493
- const registered = claims.find((claim) => claim.function === "better_supabase.feature_claims");
494
- findings.push({
495
- message: registered ? `The hook of ${label} fills the "${registered.name}" claim from better_supabase.feature_claims, but claims.features is "${features}", so hasEntitlement() never finds the plan features. Set claims.features to "${registered.name}".` : featureClaim ? `The hook of ${label} fills the "${features}" claim from ${featureClaim.function}, not better_supabase.feature_claims, so the claim doesn't carry the entitlements module's features. Point the provider's "${features}" claim at better_supabase.feature_claims.` : `The hook of ${label} has no "${features}" claim, so it never writes the plan features hasEntitlement() reads. Have it fill "${features}" from better_supabase.feature_claims, or set \`entitlements.claim: false\` to keep the features out of the token and check them in SQL with has_entitlement.`,
496
- target: `claims.${features}`
497
- });
498
- }
499
- }
500
- const scope = mode.provider.scope;
501
- if (provider.memberships === void 0) findings.push({
502
- severity: "info",
503
- message: `${label} lists no authorization.memberships, so entitlement_members() can't tell which tables hold "${scope}" memberships and plan changes never invalidate sessions.`,
504
- target: "authorization.memberships"
505
- });
506
- else if (mode.provider.memberships.length === 0) findings.push({
507
- message: `${label} maps no membership table to scope "${scope}", so entitlement_members() finds no users and plan changes never invalidate sessions. Add a membership table for "${scope}" to the provider.`,
508
- target: "authorization.memberships"
509
- });
510
- for (const requirement of entitlementRequirements(mode.provider)) {
511
- const problem = requirementProblem(context, provider, requirement, requirement.caller);
512
- if (!problem) continue;
513
- findings.push({
514
- ...requirement.kind === "member-for" && problem.message.includes("may execute") ? { severity: "info" } : {},
515
- message: problem.message,
516
- target: requirement.function
517
- });
518
- }
519
- return findings;
520
- }
521
- },
522
- {
523
- code: "BS409",
524
- severity: "warning",
525
- title: "The authorization provider and the better-supabase config disagree",
526
- description: "The provider's hook writes the active tenant to `tokenHook.tenantClaim`, and its tenant scope is `tenantScope`. Doctor warns when `claims.tenant` names another claim (the tenant plugin, guards and RLS would read a claim the hook never writes), notes when `claims.scope` is neither `tenant` nor the provider's tenant scope, notes when the provider sets `suspension` or `roleSources` but `sql.modules.access.model` is not `provider` (only that model reads them), and reports the `problems` the provider found while it was built.",
527
- check: (context) => {
528
- const provider = context.config.authorization;
529
- if (!provider) return [];
530
- const label = providerLabel(provider);
531
- const findings = (provider.problems ?? []).map((problem) => ({
532
- message: `${label}: ${problem}`,
533
- target: "authorization"
534
- }));
535
- const tenantClaim = provider.tokenHook?.tenantClaim;
536
- if (tenantClaim !== void 0 && tenantClaim !== context.config.claims.tenant) findings.push({
537
- message: `The hook of ${label} writes the active tenant to "${tenantClaim}", but claims.tenant is "${context.config.claims.tenant}". Set claims.tenant to "${tenantClaim}", or change the provider's tenant claim.`,
538
- target: "claims.tenant"
539
- });
540
- const scope = context.config.claims.scope;
541
- if (scope !== "tenant" && scope !== provider.tenantScope) findings.push({
542
- severity: "info",
543
- message: `claims.scope is "${scope}", but the tenant scope of ${label} is "${provider.tenantScope}". The tenant module's membership claims then use another scope than the provider's. Set claims.scope to "${provider.tenantScope}" (or "tenant").`,
544
- target: "claims.scope"
545
- });
546
- const model = context.config.sql.modules.access?.model ?? "roles";
547
- const unread = [...provider.suspension ? ["suspension"] : [], ...provider.roleSources && provider.roleSources.length > 0 ? ["roleSources"] : []];
548
- if (model !== "provider" && unread.length > 0) findings.push({
549
- severity: "info",
550
- message: `${label} sets ${unread.join(" and ")}, but sql.modules.access.model is "${model}", so the SQL modules ignore ${unread.length > 1 ? "them" : "it"}. Set sql.modules.access.model to "provider" to use them, or set sql.modules.access.disabled yourself.`,
551
- target: `authorization.${unread[0]}`
552
- });
553
- return findings;
554
- }
555
- },
556
- {
557
- code: "BS411",
558
- severity: "error",
559
- title: "The provider access model can't use the authorization provider",
560
- description: "With `sql.modules.access.model: 'provider'`, the `access` module fills the provider's `idsWith` template for tenant checks and `isPlatform` for platform checks, at its tenant scope. Doctor reports a config without `authorization`, a tenant scope or id type the module can't render, a function those templates call that `authorization.requires` doesn't list, doesn't let `authenticated` execute or the database lacks, and every module permission key (from `modulePermissionKeys`) the provider doesn't mark `sqlComplete: true`, since its functions are trusted with role and scope only. It warns when neither `sql.modules.access.functions.canAssign` nor the provider's `canAssign` is set, because only the service role then assigns roles, and when an installed module calls a template the provider doesn't set (`idsWithFor` and `isPlatformFor` to check another user, `canAssignFor` to recheck an inviter).",
561
- check: (context) => {
562
- const mode = accessModule(context);
563
- if (mode.kind === "off") return [];
564
- if (mode.kind === "invalid") return [{
565
- message: mode.problem,
566
- target: "authorization"
567
- }];
568
- const provider = context.config.authorization;
569
- const findings = [];
570
- for (const requirement of accessRequirements(mode.access)) {
571
- const problem = requirementProblem(context, provider, requirement, "the provider access model (can() and the SQL modules)");
572
- if (problem) findings.push({
573
- message: problem.message,
574
- target: requirement.function
575
- });
576
- }
577
- findings.push(...moduleKeyProblems(provider, modulePermissionKeys(context.config.sql.modules, context.config.sql.moduleNames)));
578
- if ((context.config.sql.modules.access?.functions?.canAssign ?? provider.functions.canAssign) === void 0) findings.push({
579
- severity: "warning",
580
- message: `Neither sql.modules.access.functions.canAssign nor ${providerLabel(provider)} sets canAssign, so under the provider model only the service role assigns roles: the memberships guard refuses every membership a member adds or changes. Use a provider that sets authorization.functions.canAssign, or set sql.modules.access.functions.canAssign.`,
581
- target: "sql.modules.access.functions.canAssign"
582
- });
583
- findings.push(...missingTemplates(context, provider));
584
- return findings;
585
- }
586
- }
587
- ];
588
- //#endregion
589
- //#region src/cli/introspect/typegen.ts
590
- const TYPEGEN = "@supabase/postgrest-typegen";
591
- /** Why a command that reads or generates schema types stops without the peer. */
592
- const TYPEGEN_MISSING = `better-supabase needs the "${TYPEGEN}" package to read your schema and generate types. Install it: pnpm add -D ${TYPEGEN}@${TYPEGEN_VERSION}`;
593
- /** Thrown by every function here when the optional peer is not installed. */
594
- var TypegenMissingError = class extends Error {
595
- constructor() {
596
- super(TYPEGEN_MISSING);
597
- this.name = "TypegenMissingError";
598
- }
599
- };
600
- const missing = () => {
601
- throw new TypegenMissingError();
602
- };
603
- /**
604
- * `/generation` is light and its functions are synchronous (`buildModel`
605
- * calls `tsTypeOf`), so it loads with this module, which the commands that
606
- * need it import on demand. The package root and `/introspection` build
607
- * their arktype schemas on import (about 90 ms), so they load when a command
608
- * reads or validates metadata, not for `--help`.
609
- */
610
- const generation = await import("@supabase/postgrest-typegen/generation").catch(() => void 0);
611
- const loadGeneration = () => generation ?? missing();
612
- const metadataModule = () => import("@supabase/postgrest-typegen").catch(missing);
613
- const introspectionModule = () => import("@supabase/postgrest-typegen/introspection").catch(missing);
614
- /** Introspects `schemas`, keeping only the types they reference. */
615
- async function readGeneratorMetadata(db, schemas) {
616
- const [metadata, positions] = await Promise.all([introspectionModule().then(({ introspect }) => introspect(db, { includedSchemas: [...schemas] })), db.query(argumentPositionsSql(schemas))]);
617
- return pruneTypes(orderArgsByPosition(metadata, positions.rows), schemas);
618
- }
619
- const sqlLiteral = (value) => `'${value.replaceAll("'", "''")}'`;
620
- /**
621
- * The argument order postgrest-typegen loses: its catalog query aggregates
622
- * the arguments without an order, so two unnamed arguments (pgvector's
623
- * operators, citext casts) swap places between database resets.
624
- */
625
- function argumentPositionsSql(schemas) {
626
- return `select p.oid::int8 as id,
627
- coalesce(p.proallargtypes, p.proargtypes::oid[])::int8[] as types,
628
- p.proargnames as names
629
- from pg_catalog.pg_proc p
630
- join pg_catalog.pg_namespace n on n.oid = p.pronamespace
631
- where p.prokind = 'f'
632
- and n.nspname = any (array[${schemas.map(sqlLiteral).join(", ") || "''"}]::text[])`;
633
- }
634
- /**
635
- * Puts every function's arguments back in declaration order, so the sort by
636
- * name that follows (stable) keeps unnamed arguments by position.
637
- */
638
- function orderArgsByPosition(metadata, rows) {
639
- const byId = new Map(rows.map((row) => [Number(row.id), row]));
640
- return {
641
- ...metadata,
642
- functions: metadata.functions.map((fn) => {
643
- const row = byId.get(fn.id);
644
- if (!row?.types || fn.args.length < 2) return fn;
645
- const pending = [...fn.args];
646
- const ordered = [];
647
- row.types.forEach((type, index) => {
648
- const name = row.names?.[index] ?? "";
649
- const at = pending.findIndex((arg) => arg.type_id === Number(type) && arg.name === name);
650
- if (at >= 0) ordered.push(...pending.splice(at, 1));
651
- });
652
- return {
653
- ...fn,
654
- args: [...ordered, ...pending]
655
- };
656
- })
657
- };
658
- }
659
- /** Postgres assigns oids below this to built-in objects; those are stable. */
660
- const FIRST_NORMAL_OID = 16384;
661
- /**
662
- * Replaces the oids of user objects with ids derived from their names and
663
- * zeroes size estimates, so a snapshot of the same schema is byte-identical
664
- * after `supabase db reset` or on another machine. Returns the id mapping
665
- * for data keyed by the old oids.
666
- */
667
- function stabilizeMetadata(metadata) {
668
- const ids = /* @__PURE__ */ new Map();
669
- const assign = (base, entries) => {
670
- [...entries].sort((a, b) => byCodePoint(a.key, b.key)).forEach((entry, index) => {
671
- if (entry.id >= FIRST_NORMAL_OID) ids.set(entry.id, base + index);
672
- });
673
- };
674
- assign(1e6, [
675
- ...metadata.tables,
676
- ...metadata.foreignTables,
677
- ...metadata.views,
678
- ...metadata.materializedViews
679
- ].map((entry) => ({
680
- id: entry.id,
681
- key: `${entry.schema}.${entry.name}`
682
- })));
683
- assign(2e6, metadata.types.map((entry) => ({
684
- id: entry.id,
685
- key: `${entry.schema}.${entry.name}`
686
- })));
687
- assign(3e6, metadata.functions.map((entry) => ({
688
- id: entry.id,
689
- key: `${entry.schema}.${entry.name}(${entry.identity_argument_types})`
690
- })));
691
- assign(4e6, metadata.schemas.map((entry) => ({
692
- id: entry.id,
693
- key: entry.name
694
- })));
695
- const map = (id) => ids.get(id) ?? id;
696
- const mapNullable = (id) => id === null ? null : map(id);
697
- const stable = {
698
- ...metadata,
699
- schemas: metadata.schemas.map((entry) => ({
700
- ...entry,
701
- id: map(entry.id)
702
- })),
703
- tables: metadata.tables.map((entry) => ({
704
- ...entry,
705
- id: map(entry.id),
706
- bytes: 0,
707
- size: "0 bytes",
708
- live_rows_estimate: 0,
709
- dead_rows_estimate: 0
710
- })),
711
- foreignTables: metadata.foreignTables.map((entry) => ({
712
- ...entry,
713
- id: map(entry.id)
714
- })),
715
- views: metadata.views.map((entry) => ({
716
- ...entry,
717
- id: map(entry.id)
718
- })),
719
- materializedViews: metadata.materializedViews.map((entry) => ({
720
- ...entry,
721
- id: map(entry.id)
722
- })),
723
- columns: metadata.columns.map((entry) => ({
724
- ...entry,
725
- table_id: map(entry.table_id),
726
- id: `${map(entry.table_id)}.${entry.ordinal_position}`
727
- })),
728
- primaryKeys: metadata.primaryKeys.map((entry) => ({
729
- ...entry,
730
- table_id: map(entry.table_id)
731
- })),
732
- functions: metadata.functions.map((entry) => ({
733
- ...entry,
734
- id: map(entry.id),
735
- return_type_id: map(entry.return_type_id),
736
- return_type_relation_id: mapNullable(entry.return_type_relation_id),
737
- args: entry.args.map((arg) => ({
738
- ...arg,
739
- type_id: map(arg.type_id)
740
- }))
741
- })),
742
- types: metadata.types.map((entry) => ({
743
- ...entry,
744
- id: map(entry.id),
745
- type_relation_id: mapNullable(entry.type_relation_id),
746
- attributes: entry.attributes.map((attribute) => ({
747
- ...attribute,
748
- type_id: map(attribute.type_id)
749
- }))
750
- }))
751
- };
752
- return {
753
- metadata: loadGeneration().sortGeneratorMetadata(stable),
754
- ids
755
- };
756
- }
757
- /** Validates metadata loaded from a snapshot file. */
758
- async function validateGeneratorMetadata(data) {
759
- const { parseGeneratorMetadata } = await metadataModule();
760
- return parseGeneratorMetadata(data);
761
- }
762
- /**
763
- * A `GeneratorMetadata` document `gen --metadata` refuses: not JSON, another
764
- * `GENERATOR_METADATA_VERSION`, or a shape the schema rejects. `gen` exits 65
765
- * for it, the code `@supabase/typegen` maps to `MetadataRejectedError`.
766
- */
767
- var MetadataRejectedError = class extends Error {
768
- /** The document's `version`, when it had one. */
769
- version;
770
- constructor(message, version) {
771
- super(message);
772
- this.name = "MetadataRejectedError";
773
- this.version = version;
774
- }
775
- };
776
- /**
777
- * Parses the JSON document an out-of-process generator reads on stdin,
778
- * checking its `version` against the `GENERATOR_METADATA_VERSION` this
779
- * release of `@supabase/postgrest-typegen` writes.
780
- */
781
- async function parseMetadataDocument(text) {
782
- const { GENERATOR_METADATA_VERSION, parseGeneratorMetadata } = await metadataModule();
783
- let data;
784
- try {
785
- data = JSON.parse(text);
786
- } catch (cause) {
787
- throw new MetadataRejectedError(text.trim() === "" ? "The GeneratorMetadata document is empty." : `The GeneratorMetadata document is not JSON: ${cause instanceof Error ? cause.message : String(cause)}`);
788
- }
789
- const version = typeof data === "object" && data !== null && "version" in data ? data.version : void 0;
790
- if (version !== GENERATOR_METADATA_VERSION) throw new MetadataRejectedError(version === void 0 ? `The document has no "version", so it is not GeneratorMetadata. better-supabase reads version ${GENERATOR_METADATA_VERSION}.` : `The document is GeneratorMetadata version ${JSON.stringify(version)}, and better-supabase reads version ${GENERATOR_METADATA_VERSION} (${TYPEGEN}@${TYPEGEN_VERSION}). Update better-supabase or the tool that wrote the document so both agree.`, version);
791
- try {
792
- return parseGeneratorMetadata(data);
793
- } catch (cause) {
794
- throw new MetadataRejectedError(cause instanceof Error ? cause.message : String(cause), version);
795
- }
796
- }
797
- /** The JSON document out-of-process generators read. */
798
- async function serializeGenerator(metadata) {
799
- const { serializeGeneratorMetadata } = await metadataModule();
800
- return serializeGeneratorMetadata(loadGeneration().sortGeneratorMetadata(metadata));
801
- }
802
- /**
803
- * Keeps only what belongs to `schemas`, so the Database type matches
804
- * `supabase gen types --schema ...` for exactly those schemas.
805
- */
806
- function restrictSchemas(metadata, schemas) {
807
- const keep = new Set(schemas);
808
- return {
809
- ...metadata,
810
- schemas: metadata.schemas.filter((schema) => keep.has(schema.name)),
811
- tables: metadata.tables.filter((table) => keep.has(table.schema)),
812
- foreignTables: metadata.foreignTables.filter((table) => keep.has(table.schema)),
813
- views: metadata.views.filter((view) => keep.has(view.schema)),
814
- materializedViews: metadata.materializedViews.filter((view) => keep.has(view.schema)),
815
- columns: metadata.columns.filter((column) => keep.has(column.schema)),
816
- primaryKeys: metadata.primaryKeys.filter((key) => keep.has(key.schema)),
817
- relationships: metadata.relationships.filter((relationship) => keep.has(relationship.schema)),
818
- functions: metadata.functions.filter((fn) => keep.has(fn.schema))
819
- };
820
- }
821
- let oxfmt;
822
- /** oxfmt is an optional peer, loaded on demand; `undefined` when it is not installed. */
823
- function loadOxfmt() {
824
- oxfmt ??= import("oxfmt").catch(() => void 0);
825
- return oxfmt;
826
- }
827
- /** Whether `database.types.ts` comes out formatted. */
828
- async function oxfmtInstalled() {
829
- return await loadOxfmt() !== void 0;
830
- }
831
- /** Formats like `supabase gen types`, or returns `code` as it is without oxfmt. */
832
- async function formatTypes(code) {
833
- const formatter = await loadOxfmt();
834
- if (!formatter) return code;
835
- const { code: formatted, errors } = await formatter.format("output.ts", code, {
836
- semi: false,
837
- printWidth: 80
838
- });
839
- if (errors.length > 0) throw new Error(`oxfmt failed to format database.types.ts: ${errors.map((error) => error.message).join("; ")}`);
840
- return formatted;
841
- }
842
- /**
843
- * Renders `database.types.ts` as `supabase gen types` prints it when oxfmt is
844
- * installed, plus the `ComputedFields` keys Supabase CLI 2.119 doesn't write.
845
- */
846
- function generateDatabaseTypes(metadata, options) {
847
- const { generateTypescript, sortGeneratorMetadata } = loadGeneration();
848
- return generateTypescript(sortGeneratorMetadata(restrictSchemas(metadata, options.schemas)), {
849
- postgrestVersion: options.postgrestVersion,
850
- detectOneToOneRelationships: true,
851
- format: formatTypes
852
- });
853
- }
854
- /**
855
- * TypeScript type for a column or argument, resolved exactly like the
856
- * `Database` type does (domains, composites, enums in other schemas).
857
- */
858
- function tsTypeOf(metadata, schema, format, typeSchema) {
859
- const owner = metadata.schemas.find((entry) => entry.name === schema) ?? {
860
- id: 0,
861
- name: schema,
862
- owner: ""
863
- };
864
- return loadGeneration().pgTypeToTsType(owner, format, {
865
- types: metadata.types,
866
- schemas: metadata.schemas,
867
- tables: metadata.tables,
868
- views: metadata.views,
869
- foreignTables: metadata.foreignTables,
870
- materializedViews: metadata.materializedViews
871
- }, typeSchema);
872
- }
873
- /**
874
- * `introspect()` returns every type in the database (hundreds of built-ins).
875
- * Keep the ones in the read schemas and those referenced by columns,
876
- * functions and composite attributes; built-in scalars resolve by name.
877
- */
878
- function pruneTypes(metadata, schemas) {
879
- const byId = new Map(metadata.types.map((type) => [type.id, type]));
880
- const byName = new Map(metadata.types.map((type) => [`${type.schema}.${type.name}`, type]));
881
- const keep = /* @__PURE__ */ new Set();
882
- const visit = (id) => {
883
- if (id === null || id === void 0 || keep.has(id)) return;
884
- const type = byId.get(id);
885
- if (!type) return;
886
- keep.add(id);
887
- for (const attribute of type.attributes) visit(attribute.type_id);
888
- };
889
- for (const type of metadata.types) if (schemas.includes(type.schema)) visit(type.id);
890
- for (const column of metadata.columns) {
891
- visit(byName.get(`${column.type_schema}.${column.format}`)?.id);
892
- visit(byName.get(`${column.type_schema}.${column.format.replace(/^_/, "")}`)?.id);
893
- }
894
- for (const fn of metadata.functions) {
895
- visit(fn.return_type_id);
896
- for (const arg of fn.args) visit(arg.type_id);
897
- }
898
- return {
899
- ...metadata,
900
- types: metadata.types.filter((type) => keep.has(type.id))
901
- };
902
- }
903
- //#endregion
904
- //#region src/cli/gen/shared.ts
905
- const q = (value) => JSON.stringify(value);
906
- /** A property key: bare when it is a valid identifier, quoted otherwise. */
907
- function prop(name) {
908
- return /^[A-Za-z_$][\w$]*$/.test(name) ? name : q(name);
909
- }
910
- function nullable(type, isNullable) {
911
- return isNullable ? `${type} | null` : type;
912
- }
913
- /** `T[]`, parenthesized when `T` is a union or other compound type. */
914
- function arrayOf(type) {
915
- return /^[\w.$]+$/.test(type) ? `${type}[]` : `(${type})[]`;
916
- }
917
- function indent(lines, depth) {
918
- const pad = " ".repeat(depth);
919
- return lines.flatMap((line) => line.split("\n")).map((line) => line === "" ? line : pad + line);
920
- }
921
- /** `name: {` + indented children + `};`, or an inline empty type. */
922
- function block(name, children, empty = "{ [_ in never]: never }") {
923
- if (children.length === 0) return [`${name}: ${empty};`];
924
- return [
925
- `${name}: {`,
926
- ...indent(children, 1),
927
- "};"
928
- ];
929
- }
930
- function sameColumns(left, right) {
931
- return left.length === right.length && left.every((column) => right.includes(column));
932
- }
933
- function singular(name) {
934
- if (name.endsWith("ies")) return `${name.slice(0, -3)}y`;
935
- if (name.endsWith("sses")) return name.slice(0, -2);
936
- if (name.endsWith("s") && !name.endsWith("ss")) return name.slice(0, -1);
937
- return name;
938
- }
939
- function pascal(name) {
940
- return name.replaceAll(/(^|[_-]+)([a-z0-9])/g, (_, __, char) => char.toUpperCase()).replace(/^[a-z]/, (char) => char.toUpperCase());
941
- }
942
- /** A valid TypeScript identifier: other characters become `_`, a leading digit gets one. */
943
- function identifier(name) {
944
- const safe = name.replaceAll(/[^\w$]/g, "_");
945
- return /^\d/.test(safe) ? `_${safe}` : safe;
946
- }
947
- /**
948
- * The config entry for a database object, keyed `schema.name` or `name`.
949
- * The qualified key wins.
950
- */
951
- function configFor(entries, schema, name) {
952
- return entries[`${schema}.${name}`] ?? entries[name];
953
- }
954
- function isJsonUdt(udt) {
955
- return udt === "json" || udt === "jsonb";
956
- }
957
- const CHECK_ANY = /^CHECK \(\(\(?"?(\w+)"?\)?(?:::\w+)? = ANY \(\(?ARRAY\[(.+)\]\)?(?:::\w+\[\])?\)\)\)$/;
958
- const CHECK_OR = /^CHECK \(\((.+)\)\)$/;
959
- const OR_TERM = /^\(?"?(\w+)"?\)?(?:::\w+)? = '((?:[^']|'')*)'(?:::\w+)?\)?$/;
960
- const LITERAL = /'((?:[^']|'')*)'(?:::[\w ]+)?/g;
961
- /**
962
- * Extracts `column in ('a', 'b')` CHECK constraints, which Postgres stores as
963
- * `CHECK ((col = ANY (ARRAY['a'::text, 'b'::text])))` or an OR chain.
964
- */
965
- function parseCheckUnion(definition) {
966
- const any = CHECK_ANY.exec(definition);
967
- if (any?.[1] && any[2]) {
968
- const values = [...any[2].matchAll(LITERAL)].map((match) => (match[1] ?? "").replaceAll("''", "'"));
969
- return values.length > 0 ? {
970
- column: any[1],
971
- values
972
- } : void 0;
973
- }
974
- const chain = CHECK_OR.exec(definition);
975
- if (chain?.[1]) {
976
- const terms = chain[1].split(/\) OR \(|\s+OR\s+/);
977
- let column;
978
- const values = [];
979
- for (const term of terms) {
980
- const match = OR_TERM.exec(term.trim());
981
- if (!match?.[1]) return void 0;
982
- if (column && column !== match[1]) return void 0;
983
- column = match[1];
984
- values.push((match[2] ?? "").replaceAll("''", "'"));
985
- }
986
- return column && values.length > 1 ? {
987
- column,
988
- values
989
- } : void 0;
990
- }
991
- }
992
- /** The text inside one pair of parentheses that wraps all of `text`, if any. */
993
- function unwrap(text) {
994
- let current = text.trim();
995
- while (current.startsWith("(") && current.endsWith(")")) {
996
- let depth = 0;
997
- let wraps = true;
998
- for (let index = 0; index < current.length; index++) {
999
- const char = current[index];
1000
- if (char === "(") depth++;
1001
- else if (char === ")") depth--;
1002
- if (depth === 0 && index < current.length - 1) {
1003
- wraps = false;
1004
- break;
1005
- }
1006
- }
1007
- if (!wraps) break;
1008
- current = current.slice(1, -1).trim();
1009
- }
1010
- return current;
1011
- }
1012
- /** Splits `text` on a keyword outside parentheses and quotes. */
1013
- function splitTopLevel(text, keyword) {
1014
- const parts = [];
1015
- let depth = 0;
1016
- let quote;
1017
- let start = 0;
1018
- const separator = ` ${keyword} `;
1019
- for (let index = 0; index < text.length; index++) {
1020
- const char = text[index];
1021
- if (quote) {
1022
- if (char === quote) quote = void 0;
1023
- continue;
1024
- }
1025
- if (char === "'" || char === "\"") quote = char;
1026
- else if (char === "(") depth++;
1027
- else if (char === ")") depth--;
1028
- else if (depth === 0 && text.slice(index, index + separator.length).toUpperCase() === separator) {
1029
- parts.push(text.slice(start, index));
1030
- start = index + separator.length;
1031
- index += separator.length - 1;
1032
- }
1033
- }
1034
- parts.push(text.slice(start));
1035
- return parts.map((part) => part.trim());
1036
- }
1037
- const IS_NOT_NULL = /^(?:"((?:[^"]|"")+)"|([\w$]+)) IS NOT NULL$/i;
1038
- /**
1039
- * Columns a CHECK constraint makes not null: `CHECK ((slug IS NOT NULL))` and
1040
- * the `IS NOT NULL` terms of a top-level `AND`. A term under `OR`, `NOT` or
1041
- * any other expression narrows nothing, and neither does a `NOT VALID` one.
1042
- */
1043
- function parseCheckNotNull(definition) {
1044
- const text = definition.trim();
1045
- if (/\bNOT VALID$/i.test(text)) return [];
1046
- const body = /^CHECK\s*(.*)$/is.exec(text)?.[1];
1047
- if (!body) return [];
1048
- const expression = unwrap(body);
1049
- if (splitTopLevel(expression, "OR").length > 1) return [];
1050
- return splitTopLevel(expression, "AND").flatMap((term) => {
1051
- const match = IS_NOT_NULL.exec(unwrap(term));
1052
- if (!match) return [];
1053
- return [match[1]?.replaceAll("\"\"", "\"") ?? match[2] ?? ""];
1054
- });
1055
- }
1056
- //#endregion
1057
- //#region src/cli/gen/model.ts
1058
- const SOFT_DELETE_UDTS = /* @__PURE__ */ new Set(["timestamptz", "timestamp"]);
1059
- const applyCasing = (name, casing) => casing === "camel" ? toCamel(name) : name;
1060
- /** The overloads of each function name, in model order. */
1061
- function functionGroups(functions) {
1062
- const groups = /* @__PURE__ */ new Map();
1063
- for (const fn of functions) {
1064
- const group = groups.get(fn.key);
1065
- if (group) group.push(fn);
1066
- else groups.set(fn.key, [fn]);
1067
- }
1068
- return groups;
1069
- }
1070
- function signatureOf(fn) {
1071
- const { name: _name, schema: _schema, ...signature } = fn.meta;
1072
- return {
1073
- ...signature,
1074
- args: signature.args.map((arg, index) => fn.args[index]?.optional ? {
1075
- ...arg,
1076
- optional: true
1077
- } : arg)
1078
- };
1079
- }
1080
- function tableKey(table, casing, schemas) {
1081
- const base = applyCasing(table.name, casing);
1082
- if (schemas.length === 1 || table.schema === "public") return base;
1083
- return applyCasing(`${table.schema}_${table.name}`, casing);
1084
- }
1085
- const CODEC_TYPE = {
1086
- instant: "Temporal.Instant",
1087
- plainDateTime: "Temporal.PlainDateTime",
1088
- bigint: "bigint",
1089
- string: "string"
1090
- };
1091
- function codecFor(udt, config) {
1092
- const { codecs } = config;
1093
- if (codecs.timestamptz === "instant") {
1094
- if (udt === "timestamptz") return "instant";
1095
- if (udt === "timestamp") return "plainDateTime";
1096
- }
1097
- if (udt === "int8" && codecs.int8 !== "number") return codecs.int8;
1098
- if (udt === "numeric" && codecs.numeric === "string") return "string";
1099
- }
1100
- const TEXT_UDTS = /* @__PURE__ */ new Set([
1101
- "text",
1102
- "varchar",
1103
- "bpchar"
1104
- ]);
1105
- /** `config.storagePaths` resolved to bucket ids, with a check that every key is used. */
1106
- function storagePathsOf(config) {
1107
- const bucketId = (name) => {
1108
- const bucket = config.buckets[name];
1109
- if (!bucket) return name;
1110
- return bucket.id ?? name.replaceAll(/[A-Z]/g, (char) => `-${char.toLowerCase()}`);
1111
- };
1112
- const unused = new Set(Object.keys(config.storagePaths));
1113
- return {
1114
- lookup(schema, table, column, udt) {
1115
- const key = [`${schema}.${table}.${column}`, `${table}.${column}`].find((candidate) => candidate in config.storagePaths);
1116
- if (key === void 0) return;
1117
- unused.delete(key);
1118
- if (!TEXT_UDTS.has(udt)) throw new TypeError(`storagePaths["${key}"]: ${schema}.${table}.${column} is ${udt}, not a text column`);
1119
- return bucketId(config.storagePaths[key]);
1120
- },
1121
- assertUsed() {
1122
- const [first] = unused;
1123
- if (first !== void 0) throw new TypeError(`storagePaths["${first}"]: no such column. Use \`table.column\` or \`schema.table.column\` (database names) in \`schemas\`.`);
1124
- }
1125
- };
1126
- }
1127
- function enumType(values) {
1128
- return values.map((value) => JSON.stringify(value)).join(" | ");
1129
- }
1130
- /** Builds the codegen model from a snapshot and config. */
1131
- function buildModel(snapshot, config) {
1132
- const catalog = toCatalog(snapshot);
1133
- const introspection = restrictSchemas(snapshot.generator, config.schemas);
1134
- const tsType = (schema, format, typeSchema) => tsTypeOf(introspection, schema, format, typeSchema).replaceAll(/\(([\w.$]+)\)\[\]/g, "$1[]");
1135
- const enumsByName = /* @__PURE__ */ new Map();
1136
- for (const entry of catalog.enums) enumsByName.set(`${entry.schema}.${entry.name}`, entry.values);
1137
- const jsonImports = /* @__PURE__ */ new Map();
1138
- const unusedJson = new Set(Object.keys(config.json));
1139
- const jsonTypeFor = (schema, table, column) => {
1140
- const key = [`${schema}.${table}.${column}`, `${table}.${column}`].find((candidate) => candidate in config.json);
1141
- const override = key === void 0 ? void 0 : config.json[key];
1142
- if (key === void 0 || !override) return void 0;
1143
- unusedJson.delete(key);
1144
- if ("type" in override) return override.type;
1145
- const [from, name] = override.import.split("#");
1146
- if (!from || !name) throw new TypeError(`json["${key}"].import must look like "./path.ts#TypeName"`);
1147
- jsonImports.set(name, {
1148
- name,
1149
- from
1150
- });
1151
- return name;
1152
- };
1153
- const optionsOf = (table) => configFor(config.tables, table.schema, table.name);
1154
- const storagePaths = storagePathsOf(config);
1155
- const included = catalog.tables.filter((table) => config.schemas.includes(table.schema) && !optionsOf(table)?.exclude);
1156
- const keyOf = /* @__PURE__ */ new Map();
1157
- const ownerOf = /* @__PURE__ */ new Map();
1158
- for (const table of included) {
1159
- const id = `${table.schema}.${table.name}`;
1160
- const key = tableKey(table, config.casing, config.schemas);
1161
- const other = ownerOf.get(key);
1162
- if (other !== void 0) throw new TypeError(`${other} and ${id} both generate the model key "${key}". Exclude one with \`tables["${id}"].exclude\`, or rename one of the tables.`);
1163
- ownerOf.set(key, id);
1164
- keyOf.set(id, key);
1165
- }
1166
- const tables = included.map((table) => {
1167
- const casing = optionsOf(table)?.casing ?? config.casing;
1168
- const checks = /* @__PURE__ */ new Map();
1169
- const checkedNotNull = /* @__PURE__ */ new Set();
1170
- for (const check of table.checks) {
1171
- const union = parseCheckUnion(check.definition);
1172
- if (union) checks.set(union.column, union.values);
1173
- for (const column of parseCheckNotNull(check.definition)) checkedNotNull.add(column);
1174
- }
1175
- const beforeInsert = table.triggers.some((trigger) => trigger.timing === "before" && trigger.level === "row" && trigger.events.includes("insert"));
1176
- const insertOptional = new Set(optionsOf(table)?.insertOptional ?? []);
1177
- for (const name of insertOptional) if (!table.columns.some((column) => column.name === name)) throw new TypeError(`tables.${table.name}.insertOptional: "${name}" is not a column of ${table.schema}.${table.name}`);
1178
- const columns = table.columns.map((column) => {
1179
- const values = (column.isEnum ? enumsByName.get(`${column.typeSchema}.${column.udt}`) : void 0) ?? checks.get(column.name);
1180
- const json = isJsonUdt(column.udt);
1181
- const override = json ? jsonTypeFor(table.schema, table.name, column.name) : void 0;
1182
- const storage = storagePaths.lookup(table.schema, table.name, column.name, column.udt);
1183
- const codec = override || values || storage ? void 0 : codecFor(column.udt, config);
1184
- const base = override ?? (values ? enumType(values) : storage ? `StoragePath<${JSON.stringify(storage)}>` : codec ? CODEC_TYPE[codec] : void 0);
1185
- const columnType = base === void 0 ? tsType(table.schema, column.format, column.typeSchema) : column.isArray ? arrayOf(base) : base;
1186
- const readonly = column.generated || column.identity === "always";
1187
- const narrowed = column.nullable && checkedNotNull.has(column.name);
1188
- const nullable = column.nullable && !narrowed;
1189
- const filled = column.hasDefault || insertOptional.has(column.name) || narrowed && beforeInsert;
1190
- const insertable = !readonly && table.insertable && (table.kind !== "view" || column.updatable);
1191
- const updatable = !readonly && table.updatable && column.updatable;
1192
- return {
1193
- app: applyCasing(column.name, casing),
1194
- db: column.name,
1195
- snapshot: column,
1196
- tsType: columnType,
1197
- nullable,
1198
- filled,
1199
- optional: nullable || filled || readonly,
1200
- readonly,
1201
- values,
1202
- json,
1203
- codec,
1204
- storage,
1205
- insertable,
1206
- updatable
1207
- };
1208
- });
1209
- const byApp = /* @__PURE__ */ new Map();
1210
- for (const column of columns) {
1211
- const other = byApp.get(column.app);
1212
- if (other !== void 0) throw new TypeError(`${table.schema}.${table.name}: columns "${other}" and "${column.db}" both become "${column.app}". Rename one, or set \`tables["${table.schema}.${table.name}"].casing: "snake"\`.`);
1213
- byApp.set(column.app, column.db);
1214
- }
1215
- return {
1216
- table,
1217
- casing,
1218
- columns,
1219
- byDb: new Map(columns.map((column) => [column.db, column]))
1220
- };
1221
- });
1222
- storagePaths.assertUsed();
1223
- const schemasOf = /* @__PURE__ */ new Map();
1224
- for (const table of catalog.tables) {
1225
- if (!config.schemas.includes(table.schema)) continue;
1226
- schemasOf.set(table.name, [...schemasOf.get(table.name) ?? [], table.schema]);
1227
- }
1228
- const known = (key) => {
1229
- const dot = key.indexOf(".");
1230
- if (dot === -1) return schemasOf.has(key);
1231
- return schemasOf.get(key.slice(dot + 1))?.includes(key.slice(0, dot)) ?? false;
1232
- };
1233
- const warnings = [
1234
- ...Object.keys(config.tables).filter((name) => !known(name)).map((name) => `tables["${name}"]: no table by that name in ${config.schemas.join(", ")}, so the entry does nothing.`),
1235
- ...Object.keys(config.tables).flatMap((name) => {
1236
- const shared = (schemasOf.get(name) ?? []).filter((schema) => !(`${schema}.${name}` in config.tables)).map((schema) => `${schema}.${name}`);
1237
- return shared.length > 1 ? [`tables["${name}"]: ${shared.join(" and ")} share the name, so the entry applies to each. Key it \`schema.table\` to pick one.`] : [];
1238
- }),
1239
- ...[...unusedJson].map((key) => `json["${key}"]: no json or jsonb column by that name, so the type is not used. Keys are \`table.column\` or \`schema.table.column\` with database names.`)
1240
- ];
1241
- const byKey = /* @__PURE__ */ new Map();
1242
- for (const entry of tables) byKey.set(`${entry.table.schema}.${entry.table.name}`, entry);
1243
- const appName = (schema, table, column) => {
1244
- return byKey.get(`${schema}.${table}`)?.byDb.get(column)?.app ?? column;
1245
- };
1246
- const relations = /* @__PURE__ */ new Map();
1247
- const push = (tableId, relation) => {
1248
- const list = relations.get(tableId);
1249
- if (list) list.push(relation);
1250
- else relations.set(tableId, [relation]);
1251
- };
1252
- for (const { table, casing, byDb: own } of tables) {
1253
- const sourceId = `${table.schema}.${table.name}`;
1254
- for (const fk of table.foreignKeys) {
1255
- const targetId = `${fk.refSchema}.${fk.refTable}`;
1256
- const target = byKey.get(targetId);
1257
- if (!target) continue;
1258
- const targetKey = keyOf.get(targetId) ?? fk.refTable;
1259
- const sourceColumns = fk.columns.map((column) => appName(table.schema, table.name, column));
1260
- const targetColumns = fk.refColumns.map((column) => appName(fk.refSchema, fk.refTable, column));
1261
- const nullable = config.relations.nullableUnderRls && target.table.rls || fk.columns.some((column) => own.get(column)?.nullable ?? true);
1262
- const onDelete = fk.onDelete === "cascade" || fk.onDelete === "set null" || fk.onDelete === "set default" ? { onDelete: fk.onDelete } : {};
1263
- const naming = namingColumns(fk.columns, fk.refColumns);
1264
- const [only] = naming;
1265
- const forwardBase = naming.length === 1 && only?.endsWith("_id") ? only.slice(0, -3) : singular(fk.refTable);
1266
- push(sourceId, {
1267
- name: applyCasing(forwardBase, casing),
1268
- base: forwardBase,
1269
- fkColumns: fk.columns,
1270
- refColumns: fk.refColumns,
1271
- meta: {
1272
- table: targetKey,
1273
- kind: "one",
1274
- nullable,
1275
- foreignKey: fk.name,
1276
- columns: sourceColumns,
1277
- references: targetColumns,
1278
- direction: "forward",
1279
- ...onDelete
1280
- }
1281
- });
1282
- const unique = fk.oneToOne || sameColumns(table.primaryKey, fk.columns) || table.uniques.some((key) => sameColumns(key.columns, fk.columns));
1283
- const reverseBase = unique ? singular(table.name) : table.name;
1284
- push(targetId, {
1285
- name: applyCasing(reverseBase, target.casing),
1286
- base: reverseBase,
1287
- fkColumns: fk.columns,
1288
- refColumns: fk.refColumns,
1289
- meta: {
1290
- table: keyOf.get(sourceId) ?? table.name,
1291
- kind: unique ? "one" : "many",
1292
- nullable: true,
1293
- foreignKey: fk.name,
1294
- columns: targetColumns,
1295
- references: sourceColumns,
1296
- direction: "reverse",
1297
- ...onDelete
1298
- }
1299
- });
1300
- }
1301
- }
1302
- const flagsConfig = config.plugins;
1303
- const tableModels = tables.map(({ table, casing, columns, byDb }) => {
1304
- const id = `${table.schema}.${table.name}`;
1305
- const renames = optionsOf(table)?.relations ?? {};
1306
- const columnNames = new Set(columns.map((column) => column.app));
1307
- const list = dedupeRelations(relations.get(id) ?? [], columnNames, casing).map((relation) => ({
1308
- ...relation,
1309
- name: renames[relation.name] ?? relation.name
1310
- }));
1311
- const has = (db) => byDb.get(db)?.app;
1312
- const flags = {};
1313
- if (flagsConfig.softDelete) {
1314
- const db = flagsConfig.softDelete.column;
1315
- const column = byDb.get(db);
1316
- if (column) {
1317
- const udt = column.snapshot.udt;
1318
- if (column.snapshot.isArray || !SOFT_DELETE_UDTS.has(udt)) throw new TypeError(`plugins.softDelete.column: ${table.schema}.${table.name}.${db} is ${udt}, but softDelete() writes a timestamp. Use timestamptz or timestamp.`);
1319
- flags.softDelete = column.app;
1320
- }
1321
- }
1322
- if (flagsConfig.timestamps) {
1323
- const createdAt = has(flagsConfig.timestamps.createdAt);
1324
- const updatedAt = has(flagsConfig.timestamps.updatedAt);
1325
- if (createdAt || updatedAt) flags.timestamps = {
1326
- ...createdAt ? { createdAt } : {},
1327
- ...updatedAt ? { updatedAt } : {}
1328
- };
1329
- }
1330
- if (flagsConfig.tenant) {
1331
- const column = has(flagsConfig.tenant.column);
1332
- if (column) flags.tenant = column;
1333
- }
1334
- if (flagsConfig.actor) {
1335
- const createdBy = has(flagsConfig.actor.createdBy);
1336
- const updatedBy = has(flagsConfig.actor.updatedBy);
1337
- const impersonatedBy = has(flagsConfig.actor.impersonatedBy);
1338
- if (createdBy || updatedBy || impersonatedBy) flags.actor = {
1339
- ...createdBy ? { createdBy } : {},
1340
- ...updatedBy ? { updatedBy } : {},
1341
- ...impersonatedBy ? { impersonatedBy } : {}
1342
- };
1343
- }
1344
- const key = keyOf.get(id) ?? table.name;
1345
- const columnMeta = {};
1346
- for (const column of columns) {
1347
- const meta = {
1348
- db: column.db,
1349
- type: column.snapshot.udt,
1350
- nullable: column.nullable,
1351
- hasDefault: column.filled
1352
- };
1353
- if (column.readonly) meta.generated = true;
1354
- if (column.snapshot.identity) meta.identity = column.snapshot.identity;
1355
- if (!column.readonly && !column.insertable) meta.insertable = false;
1356
- if (!column.readonly && !column.updatable) meta.updatable = false;
1357
- if (column.snapshot.isArray) meta.array = true;
1358
- if (column.json) meta.json = true;
1359
- if (column.values) meta.enum = column.values;
1360
- if (column.codec) meta.codec = column.codec;
1361
- if (column.storage) meta.storage = column.storage;
1362
- if (config.sensitive.includes(`${table.name}.${column.db}`) || config.sensitive.includes(`${table.schema}.${table.name}.${column.db}`)) meta.sensitive = true;
1363
- columnMeta[column.app] = meta;
1364
- }
1365
- const app = (db) => byDb.get(db)?.app ?? db;
1366
- const uniqueKeys = {};
1367
- for (const unique of table.uniques) uniqueKeys[unique.name] = unique.columns.map(app);
1368
- const relationMeta = {};
1369
- for (const relation of list) relationMeta[relation.name] = relation.meta;
1370
- return {
1371
- key,
1372
- snapshot: table,
1373
- casing,
1374
- columns,
1375
- relations: list,
1376
- meta: {
1377
- key,
1378
- name: table.name,
1379
- schema: table.schema,
1380
- kind: table.kind,
1381
- columns: columnMeta,
1382
- primaryKey: table.primaryKey.map(app),
1383
- uniqueKeys,
1384
- relations: relationMeta,
1385
- flags
1386
- }
1387
- };
1388
- });
1389
- const includedEnums = catalog.enums.filter((entry) => config.schemas.includes(entry.schema));
1390
- const enumNameCount = /* @__PURE__ */ new Map();
1391
- for (const entry of includedEnums) enumNameCount.set(entry.name, (enumNameCount.get(entry.name) ?? 0) + 1);
1392
- const enums = includedEnums.map((entry) => {
1393
- const key = entry.schema !== "public" && (enumNameCount.get(entry.name) ?? 0) > 1 ? `${entry.schema}_${entry.name}` : entry.name;
1394
- return {
1395
- schema: entry.schema,
1396
- name: entry.name,
1397
- key,
1398
- constant: identifier(`${toCamel(key)}Values`),
1399
- typeName: identifier(pascal(key)),
1400
- values: entry.values
1401
- };
1402
- });
1403
- const tablesByName = new Map(tableModels.map((table) => [`${table.snapshot.schema}.${table.snapshot.name}`, table]));
1404
- const callable = catalog.functions.filter((fn) => config.schemas.includes(fn.schema)).filter((fn) => fn.returns !== "trigger" && fn.returns !== "event_trigger").filter((fn) => !fn.args.some((arg) => arg.udt === "internal"));
1405
- const ownerSchema = /* @__PURE__ */ new Map();
1406
- for (const schema of config.schemas) for (const fn of callable) if (fn.schema === schema && !ownerSchema.has(fn.name)) ownerSchema.set(fn.name, schema);
1407
- const shadowed = /* @__PURE__ */ new Set();
1408
- const functions = callable.filter((fn) => {
1409
- if (ownerSchema.get(fn.name) === fn.schema) return true;
1410
- shadowed.add(`${fn.schema}.${fn.name}`);
1411
- return false;
1412
- }).map((fn) => {
1413
- const typeOf = (format, typeSchema) => {
1414
- const isArray = format.startsWith("_");
1415
- const values = enumsByName.get(`${typeSchema ?? fn.schema}.${isArray ? format.slice(1) : format}`);
1416
- if (values) return isArray ? arrayOf(enumType(values)) : enumType(values);
1417
- return tsType(fn.schema, format, typeSchema);
1418
- };
1419
- const notNull = configFor(config.functions, fn.schema, fn.name)?.notNull;
1420
- const notNullColumns = new Set(Array.isArray(notNull) ? notNull : []);
1421
- if (Array.isArray(notNull)) {
1422
- for (const name of notNullColumns) if (!fn.returnsTable?.some((column) => column.name === name)) throw new TypeError(`functions.${fn.name}.notNull: "${name}" is not a column the function returns`);
1423
- }
1424
- const orNull = (type, column) => notNull === true || column !== void 0 && notNullColumns.has(column) || type === "undefined" || type === "Json" || type === "unknown" ? type : `${type} | null`;
1425
- let returns;
1426
- let result;
1427
- const rowTable = fn.returnsRelation ? tablesByName.get(fn.returnsRelation) : void 0;
1428
- if (fn.returnsTable) {
1429
- const columns = fn.returnsTable.map((column) => {
1430
- const codec = codecFor(column.udt, config);
1431
- return {
1432
- db: column.name,
1433
- app: applyCasing(column.name, config.casing),
1434
- codec,
1435
- tsType: codec ? CODEC_TYPE[codec] : typeOf(column.udt, column.typeSchema)
1436
- };
1437
- });
1438
- returns = `{ ${columns.map((column) => `${JSON.stringify(column.app)}: ${orNull(column.tsType, column.db)}`).join("; ")} }[]`;
1439
- if (columns.some((column) => column.codec !== void 0 || column.app !== column.db)) result = { columns: columns.map(({ db, app, codec }) => ({
1440
- db,
1441
- ...app === db ? {} : { name: app },
1442
- ...codec ? { codec } : {}
1443
- })) };
1444
- } else if (rowTable) {
1445
- returns = `Models[${JSON.stringify(rowTable.key)}]['Row']`;
1446
- returns = fn.returnsSet ? arrayOf(returns) : orNull(returns);
1447
- if (rowTable.columns.some((column) => column.codec !== void 0 || column.app !== column.db)) result = { table: rowTable.key };
1448
- } else {
1449
- returns = orNull(typeOf(fn.returns, fn.returnsSchema));
1450
- if (fn.returnsSet) returns = arrayOf(returns);
1451
- }
1452
- return {
1453
- key: fn.name,
1454
- meta: {
1455
- name: fn.name,
1456
- schema: fn.schema,
1457
- args: fn.args.map((arg) => ({
1458
- name: arg.name,
1459
- type: arg.udt
1460
- })),
1461
- returns: fn.returns,
1462
- returnsSet: fn.returnsSet,
1463
- volatility: fn.volatility,
1464
- ...result ? { result } : {}
1465
- },
1466
- args: fn.args.map((arg) => ({
1467
- name: arg.name,
1468
- tsType: typeOf(arg.isArray ? `_${arg.udt}` : arg.udt, arg.typeSchema),
1469
- optional: arg.hasDefault
1470
- })),
1471
- returns
1472
- };
1473
- });
1474
- for (const name of Object.keys(config.functions)) if (!functions.some((fn) => fn.key === name || `${fn.meta.schema}.${fn.key}` === name)) throw new TypeError(`functions.${name}: no function "${name}" in ${config.schemas.join(", ")}`);
1475
- for (const id of shadowed) {
1476
- const name = id.slice(id.indexOf(".") + 1);
1477
- warnings.push(`${id}: ${ownerSchema.get(name) ?? ""}.${name} has the same name and comes first in \`schemas\`, so ${id} gets no \`$rpc\` types.`);
1478
- }
1479
- const tablesMeta = {};
1480
- for (const table of tableModels) tablesMeta[table.key] = table.meta;
1481
- const enumsMeta = {};
1482
- for (const entry of enums) enumsMeta[entry.key] = entry.values;
1483
- const functionsMeta = {};
1484
- for (const [key, group] of functionGroups(functions)) {
1485
- const [first] = group;
1486
- if (!first) continue;
1487
- functionsMeta[key] = group.length === 1 ? first.meta : {
1488
- ...first.meta,
1489
- overloads: group.map(signatureOf)
1490
- };
1491
- }
1492
- const claimOverrides = {};
1493
- for (const key of Object.keys(DEFAULT_CLAIMS)) if (config.claims[key] !== DEFAULT_CLAIMS[key]) claimOverrides[key] = config.claims[key];
1494
- const tenantClaim = config.claims.tenant === DEFAULT_CLAIMS.tenant ? void 0 : tenantClaimPaths(config.claims.tenant);
1495
- const meta = {
1496
- version: 1,
1497
- casing: config.casing,
1498
- tables: tablesMeta,
1499
- enums: enumsMeta,
1500
- functions: functionsMeta,
1501
- ...Object.keys(config.buckets).length > 0 ? { buckets: Object.fromEntries(Object.entries(config.buckets).map(([name, bucket]) => [name, {
1502
- id: bucket.id ?? name.replaceAll(/[A-Z]/g, (char) => `-${char.toLowerCase()}`),
1503
- public: bucket.public ?? false,
1504
- path: bucket.path,
1505
- ...bucket.policy ? { policy: typeof bucket.policy === "string" ? bucket.policy : resolveProviderSql(`buckets.${name}`, bucket.policy, config.authorization?.functions) } : {},
1506
- ...bucket.policy === "tenant" && tenantClaim ? { tenant: { claim: tenantClaim } } : {},
1507
- ...bucket.fileSizeLimit ? { fileSizeLimit: bucket.fileSizeLimit } : {},
1508
- ...bucket.allowedMimeTypes ? { allowedMimeTypes: bucket.allowedMimeTypes } : {},
1509
- ...bucket.versioning ? { versioning: true } : {},
1510
- ...bucket.lifecycle ? { lifecycle: bucket.lifecycle } : {}
1511
- }])) } : {},
1512
- ...Object.keys(config.topics).length > 0 ? { topics: config.topics } : {},
1513
- ...config.realtime.tables.length > 0 ? { realtime: realtimeMeta(config.realtime.tables, config.realtime.users, tableModels) } : {},
1514
- ...Object.keys(claimOverrides).length > 0 ? { claims: claimOverrides } : {}
1515
- };
1516
- return {
1517
- tables: tableModels,
1518
- enums,
1519
- functions,
1520
- jsonImports: [...jsonImports.values()],
1521
- meta,
1522
- config,
1523
- catalog,
1524
- introspection,
1525
- warnings
1526
- };
1527
- }
1528
- function deepFreeze(value) {
1529
- if (typeof value === "object" && value !== null && !Object.isFrozen(value)) {
1530
- Object.freeze(value);
1531
- for (const entry of Object.values(value)) deepFreeze(entry);
1532
- }
1533
- return value;
1534
- }
1535
- /** The public, frozen view of the model that generators receive. */
1536
- function generatorModel(model) {
1537
- return deepFreeze({
1538
- tables: model.tables.map((table) => ({
1539
- key: table.key,
1540
- schema: table.snapshot.schema,
1541
- name: table.snapshot.name,
1542
- casing: table.casing,
1543
- columns: table.columns.map((column) => ({
1544
- app: column.app,
1545
- db: column.db,
1546
- tsType: column.tsType,
1547
- nullable: column.nullable,
1548
- optional: column.optional,
1549
- readonly: column.readonly,
1550
- values: column.values === void 0 ? void 0 : [...column.values],
1551
- json: column.json
1552
- }))
1553
- })),
1554
- enums: model.enums.map((entry) => ({
1555
- schema: entry.schema,
1556
- name: entry.name,
1557
- values: [...entry.values]
1558
- }))
1559
- });
1560
- }
1561
- /**
1562
- * The columns that name a relation. A composite key that repeats a column on
1563
- * both sides, such as `(customer_id, organization_id)` referencing
1564
- * `(id, organization_id)` to keep rows in one tenant, is named by the rest.
1565
- */
1566
- function namingColumns(columns, references) {
1567
- const own = columns.filter((column, index) => column !== references[index]);
1568
- return own.length > 0 ? own : columns;
1569
- }
1570
- /**
1571
- * Makes relation names unique per table and distinct from column names:
1572
- * two FKs to the same table become `customersByPrimaryContact`-style names.
1573
- * When those still collide, the names use every column of the key
1574
- * (`locationsByCustomerOrganization`), then the constraint name, and only
1575
- * then a trailing `_`.
1576
- */
1577
- function dedupeRelations(list, columns, casing) {
1578
- const suffixed = (relation, suffix) => applyCasing(`${relation.base}_by_${suffix}`, casing);
1579
- const keyColumns = (relation, all) => (all ? relation.fkColumns : namingColumns(relation.fkColumns, relation.refColumns)).map((column) => column.replace(/_?[iI]d$/, "")).join("_");
1580
- const repeated = (names) => {
1581
- const seen = /* @__PURE__ */ new Set();
1582
- const twice = /* @__PURE__ */ new Set();
1583
- for (const name of names) (seen.has(name) ? twice : seen).add(name);
1584
- return twice;
1585
- };
1586
- const plain = repeated(list.map((relation) => relation.name));
1587
- const names = [(relation) => suffixed(relation, keyColumns(relation, true)), (relation) => suffixed(relation, relation.meta.foreignKey)].reduce((current, step) => {
1588
- const clash = repeated(current);
1589
- return list.map((relation, index) => {
1590
- const name = current[index] ?? relation.name;
1591
- return clash.has(name) || columns.has(name) ? step(relation) : name;
1592
- });
1593
- }, list.map((relation) => plain.has(relation.name) || columns.has(relation.name) ? suffixed(relation, keyColumns(relation, false)) : relation.name));
1594
- const used = /* @__PURE__ */ new Set();
1595
- return list.map((relation, index) => {
1596
- let name = names[index] ?? relation.name;
1597
- while (used.has(name) || columns.has(name)) name = `${name}_`;
1598
- used.add(name);
1599
- return {
1600
- ...relation,
1601
- name
1602
- };
1603
- });
1604
- }
1605
- function realtimeMeta(names, users, tables) {
1606
- const out = {};
1607
- for (const name of names) {
1608
- const table = tables.find((candidate) => candidate.meta.name === name || `${candidate.meta.schema}.${candidate.meta.name}` === name);
1609
- if (!table) throw new Error(`realtime.tables: unknown table "${name}". Check the name and \`schemas\`.`);
1610
- const owner = users[name];
1611
- if (owner !== void 0) {
1612
- const user = Object.entries(table.meta.columns).find(([, column]) => column.db === owner)?.[0];
1613
- if (user === void 0) throw new Error(`realtime.users: "${name}" has no column "${owner}".`);
1614
- out[table.key] = { user };
1615
- continue;
1616
- }
1617
- const tenant = table.meta.flags.tenant;
1618
- out[table.key] = tenant ? { tenant } : {};
1619
- }
1620
- return out;
1621
- }
1622
- //#endregion
1623
- //#region src/cli/gen/emit.ts
1624
- const GENERATED_HEADER = "// @generated by better-supabase gen. Do not edit; run `better-supabase gen` instead.";
1625
- function rowEntries(columns, name) {
1626
- return columns.map((column) => `${prop(column[name])}: ${nullable(column.tsType, column.nullable)};`);
1627
- }
1628
- function insertEntries(columns, name) {
1629
- return columns.map((column) => {
1630
- if (!column.insertable) return `${prop(column[name])}?: never;`;
1631
- const optional = column.optional ? "?" : "";
1632
- return `${prop(column[name])}${optional}: ${nullable(column.tsType, column.nullable)};`;
1633
- });
1634
- }
1635
- function updateEntries(columns, name) {
1636
- return columns.map((column) => {
1637
- if (!column.updatable) return `${prop(column[name])}?: never;`;
1638
- return `${prop(column[name])}?: ${nullable(column.tsType, column.nullable)};`;
1639
- });
1640
- }
1641
- /** Postgres passes `null` to any argument, so every argument accepts it. */
1642
- function argEntries(fn) {
1643
- return fn.args.map((arg) => `${prop(arg.name)}${arg.optional ? "?" : ""}: ${nullable(arg.tsType, true)};`);
1644
- }
1645
- function enrichedDatabase(model) {
1646
- const schemas = model.config.schemas.flatMap((schema) => {
1647
- const tables = model.tables.filter((t) => t.snapshot.schema === schema).flatMap((table) => {
1648
- const overrides = table.columns.filter((column) => column.values !== void 0 && !column.snapshot.isEnum || column.json && column.tsType !== "Json" || column.storage !== void 0).map((column) => `${prop(column.db)}: ${column.tsType};`);
1649
- return overrides.length > 0 ? block(prop(table.snapshot.name), overrides) : [];
1650
- });
1651
- return tables.length > 0 ? block(prop(schema), tables) : [];
1652
- });
1653
- if (schemas.length === 0) return ["export type Database = SupabaseDatabase;"];
1654
- return [
1655
- "export type Database = EnrichDatabase<",
1656
- " SupabaseDatabase,",
1657
- " {",
1658
- ...indent(schemas, 2),
1659
- " }",
1660
- ">;"
1661
- ];
1662
- }
1663
- function modelsType(model) {
1664
- return [
1665
- "export type Models = {",
1666
- ...indent(model.tables.flatMap((table) => {
1667
- const relations = table.relations.map((relation) => `${prop(relation.name)}: { table: ${q(relation.meta.table)}; kind: ${q(relation.meta.kind)}; nullable: ${String(relation.meta.nullable)} };`);
1668
- const pk = table.meta.primaryKey;
1669
- const uniques = Object.entries(table.meta.uniqueKeys).map(([name, columns]) => `${prop(name)}: readonly [${columns.map(q).join(", ")}];`);
1670
- const flags = [];
1671
- const tableFlags = table.meta.flags;
1672
- if (tableFlags.softDelete) flags.push(`softDelete: ${q(tableFlags.softDelete)};`);
1673
- if (tableFlags.timestamps) flags.push("timestamps: true;");
1674
- if (tableFlags.tenant) flags.push(`tenant: ${q(tableFlags.tenant)};`);
1675
- if (tableFlags.actor) flags.push("actor: true;");
1676
- const none = "Record<never, never>";
1677
- const union = (names) => names.length === 0 ? "never" : names.map(q).join(" | ");
1678
- return block(prop(table.key), [
1679
- ...block("Row", rowEntries(table.columns, "app"), none),
1680
- ...table.snapshot.insertable ? block("Insert", insertEntries(table.columns, "app"), none) : ["Insert: never;"],
1681
- ...table.snapshot.updatable ? block("Update", updateEntries(table.columns, "app"), none) : ["Update: never;"],
1682
- ...block("Relations", relations, none),
1683
- `PrimaryKey: ${union(pk)};`,
1684
- ...block("UniqueKeys", uniques, none),
1685
- `Checks: ${union(table.snapshot.checks.map((check) => check.name))};`,
1686
- `ForeignKeys: ${union(table.snapshot.foreignKeys.map((fk) => fk.name))};`,
1687
- ...block("Flags", flags, none)
1688
- ]);
1689
- }), 1),
1690
- "};"
1691
- ];
1692
- }
1693
- function functionsType(model) {
1694
- if (model.functions.length === 0) return ["export type Functions = Record<never, never>;"];
1695
- return [
1696
- "export type Functions = {",
1697
- ...indent([...functionGroups(model.functions)].flatMap(([key, group]) => {
1698
- const [first] = group;
1699
- if (group.length === 1 && first) return block(prop(key), [...block("Args", argEntries(first), "Record<never, never>"), `Returns: ${first.returns};`]);
1700
- return [`${prop(key)}:`, ...indent(group.flatMap((fn, index) => {
1701
- const lines = [...block("Args", argEntries(fn), "Record<PropertyKey, never>"), `Returns: ${fn.returns};`];
1702
- const end = index === group.length - 1 ? "};" : "}";
1703
- return [
1704
- "| {",
1705
- ...indent(lines, 1),
1706
- end
1707
- ];
1708
- }), 1)];
1709
- }), 1),
1710
- "};"
1711
- ];
1712
- }
1713
- /** The metadata module next to `generated.ts`: `generated.meta.js` and its `.d.ts`. */
1714
- function metaPaths(output) {
1715
- const base = output.replace(/\.[cm]?[jt]sx?$/, "");
1716
- return {
1717
- js: `${base}.meta.js`,
1718
- dts: `${base}.meta.d.ts`
1719
- };
1720
- }
1721
- /**
1722
- * JSON with one line per table, function and other named entry, so the
1723
- * module stays small to load and a schema change still diffs per entry.
1724
- */
1725
- function compactJson(meta) {
1726
- return `{\n${Object.entries(meta).map(([key, value]) => {
1727
- const name = JSON.stringify(key);
1728
- if (typeof value !== "object" || value === null || Array.isArray(value)) return ` ${name}: ${JSON.stringify(value)}`;
1729
- const inner = Object.entries(value).map(([entry, item]) => ` ${JSON.stringify(entry)}: ${JSON.stringify(item)}`);
1730
- return inner.length === 0 ? ` ${name}: {}` : ` ${name}: {\n${inner.join(",\n")}\n }`;
1731
- }).join(",\n")}\n}`;
1732
- }
1733
- /**
1734
- * The schema metadata as plain JavaScript plus a one-line declaration, so
1735
- * TypeScript reads `SchemaMeta` instead of checking thousands of lines of
1736
- * object literal in every program that imports the generated module.
1737
- */
1738
- function emitMeta(model, options = {}) {
1739
- const runtime = options.runtimeImport ?? "better-supabase";
1740
- return {
1741
- js: [
1742
- GENERATED_HEADER,
1743
- `// @ts-self-types="${options.types ?? "./generated.meta.d.ts"}"`,
1744
- "/* oxlint-disable */",
1745
- "/* eslint-disable */",
1746
- "",
1747
- `export default ${compactJson({ ...model.meta })};`,
1748
- ""
1749
- ].join("\n"),
1750
- dts: [
1751
- GENERATED_HEADER,
1752
- "/* oxlint-disable */",
1753
- "/* eslint-disable */",
1754
- "",
1755
- `import type { SchemaMeta } from ${q(runtime)};`,
1756
- "",
1757
- "declare const meta: SchemaMeta;",
1758
- "export default meta;",
1759
- ""
1760
- ].join("\n")
1761
- };
1762
- }
1763
- /** Names the generated module declares or imports itself. */
1764
- const RESERVED_EXPORTS = [
1765
- "defineSchema",
1766
- "Schema",
1767
- "SchemaMeta",
1768
- "EnrichDatabase",
1769
- "MutableWhere",
1770
- "OrderByArg",
1771
- "OrderByInput",
1772
- "StoragePath",
1773
- "SupabaseDatabase",
1774
- "meta",
1775
- "Json",
1776
- "Database",
1777
- "Models",
1778
- "Functions",
1779
- "TableName",
1780
- "UniqueConstraint",
1781
- "CheckConstraint",
1782
- "ForeignKeyConstraint",
1783
- "RowOf",
1784
- "InsertOf",
1785
- "UpdateOf",
1786
- "WhereOf",
1787
- "OrderByOf",
1788
- "OrderTermOf",
1789
- "buckets",
1790
- "topics",
1791
- "schema"
1792
- ];
1793
- /** Renders the generated module. */
1794
- function emitModule(model, options) {
1795
- const runtime = options.runtimeImport ?? "better-supabase";
1796
- const lines = [
1797
- GENERATED_HEADER,
1798
- "/* oxlint-disable */",
1799
- "/* eslint-disable */",
1800
- "",
1801
- `import { defineSchema, type Schema${options.inlineMeta ? ", type SchemaMeta" : ""} } from ${q(runtime)};`
1802
- ];
1803
- const storagePaths = model.tables.some((table) => table.columns.some((column) => column.storage !== void 0));
1804
- lines.push(`import type { EnrichDatabase, MutableWhere, OrderByArg, OrderByInput${storagePaths ? ", StoragePath" : ""} } from ${q(runtime)};`, `import type { Database as SupabaseDatabase } from ${q(options.databaseTypesImport ?? "./database.types.ts")};`);
1805
- const byFile = /* @__PURE__ */ new Map();
1806
- for (const entry of model.jsonImports) {
1807
- const list = byFile.get(entry.from) ?? [];
1808
- list.push(entry.name);
1809
- byFile.set(entry.from, list);
1810
- }
1811
- for (const [from, names] of [...byFile.entries()].sort(([a], [b]) => byCodePoint(a, b))) lines.push(`import type { ${names.sort().join(", ")} } from ${q(options.importPathFor(from))};`);
1812
- lines.push(options.inlineMeta ? `\nconst meta: SchemaMeta = ${compactJson({ ...model.meta })};` : `import meta from ${q(options.metaImport ?? "./generated.meta.js")};`, "", "export type Json = string | number | boolean | null | { [key: string]: Json | undefined } | Json[];", "", ...enrichedDatabase(model), "");
1813
- const exported = new Map([...RESERVED_EXPORTS, ...model.jsonImports.map((entry) => entry.name)].map((name) => [name, "the generated module"]));
1814
- const claim = (name, source) => {
1815
- const other = exported.get(name);
1816
- if (other !== void 0) throw new TypeError(`${source} and ${other} both export "${name}" from the generated module. Rename one of them in the database.`);
1817
- exported.set(name, source);
1818
- return name;
1819
- };
1820
- for (const entry of model.enums) {
1821
- const source = `enum ${entry.schema}.${entry.name}`;
1822
- lines.push(`export const ${claim(entry.constant, source)} = [${entry.values.map(q).join(", ")}] as const;`, `export type ${claim(entry.typeName, source)} = (typeof ${entry.constant})[number];`);
1823
- }
1824
- for (const table of model.tables) for (const column of table.columns) if (column.values && !column.snapshot.isEnum) {
1825
- const source = `the CHECK on ${table.snapshot.schema}.${table.snapshot.name}.${column.db}`;
1826
- const constant = identifier(`${table.key}${pascal(column.app)}Values`.replace(/^[A-Z]/, (c) => c.toLowerCase()));
1827
- const typeName = identifier(`${pascal(table.key)}${pascal(column.app)}`);
1828
- lines.push(`export const ${claim(constant, source)} = [${column.values.map(q).join(", ")}] as const;`, `export type ${claim(typeName, source)} = (typeof ${constant})[number];`);
1829
- }
1830
- if (model.enums.length > 0) lines.push("");
1831
- lines.push(...modelsType(model), "", ...functionsType(model), "", "export type TableName = keyof Models;", "/** Constraint names for `isConflict`, `isCheck` and `isForeignKey`. */", "export type UniqueConstraint = { [T in TableName]: Extract<keyof Models[T]['UniqueKeys'], string> }[TableName];", "export type CheckConstraint = Models[TableName]['Checks'];", "export type ForeignKeyConstraint = Models[TableName]['ForeignKeys'];", "export type RowOf<T extends TableName> = Models[T]['Row'];", "export type InsertOf<T extends TableName> = Models[T]['Insert'];", "export type UpdateOf<T extends TableName> = Models[T]['Update'];", "/** A `where` for `T` you can assign to one key at a time. */", "export type WhereOf<T extends TableName> = MutableWhere<Models, T>;", "/** An `orderBy` for `T`: one sort or a list, by column or to-one relation. */", "export type OrderByOf<T extends TableName> = OrderByArg<Models, T>;", "/** One sort term of `T`'s `orderBy`, by column or to-one relation. */", "export type OrderTermOf<T extends TableName> = OrderByInput<Models, T>;", "");
1832
- if (model.meta.buckets) lines.push("/** Bucket configs for `defineBucket` from `better-supabase/storage`. */", `export const buckets = ${JSON.stringify(model.meta.buckets, null, 2)} as const;`, "");
1833
- if (model.meta.topics) lines.push("/** Topic templates for `defineTopic` from `better-supabase/realtime`. */", `export const topics = ${JSON.stringify(model.meta.topics, null, 2)} as const;`, "");
1834
- lines.push("export const schema: Schema<Models, Database, Functions> = defineSchema(meta);", "");
1835
- return lines.join("\n");
1836
- }
1837
- //#endregion
1838
- //#region src/cli/introspect/extras.ts
1839
- /**
1840
- * Catalog details `@supabase/postgrest-typegen` leaves out: named unique and
1841
- * CHECK constraints, foreign key actions, ordered primary keys, indexes,
1842
- * policies, triggers, grants, buckets and the realtime publication.
1843
- *
1844
- * The SQL takes no bind parameters because the Management API endpoint only
1845
- * accepts a query string; schema names are inlined as escaped literals.
1846
- */
1847
- const literalArray = (values) => `array[${values.map((value) => `'${value.replaceAll("'", "''")}'`).join(", ")}]::text[]`;
1848
- /** Row estimate from which a table counts as large in the snapshot. */
1849
- const LARGE_TABLE_ROWS = 1e4;
1850
- const RELATIONS = (schemas) => `
1851
- select c.oid::int8 as id, n.nspname as schema, c.relname as name,
1852
- c.reltuples >= ${LARGE_TABLE_ROWS} as large
1853
- from pg_class c
1854
- join pg_namespace n on n.oid = c.relnamespace
1855
- where n.nspname = any(${schemas}) and c.relkind in ('r', 'p', 'v', 'm', 'f')
1856
- order by 2, 3`;
1857
- const CONSTRAINTS = (schemas) => `
1858
- select con.conrelid::int8 as table_id, con.conname as name, con.contype as type,
1859
- array(select a.attname from unnest(con.conkey) with ordinality k(attnum, ord)
1860
- join pg_attribute a on a.attrelid = con.conrelid and a.attnum = k.attnum order by k.ord)::text[] as columns,
1861
- con.confdeltype as on_delete, con.confupdtype as on_update,
1862
- pg_get_constraintdef(con.oid) as definition
1863
- from pg_constraint con
1864
- join pg_class c on c.oid = con.conrelid
1865
- join pg_namespace n on n.oid = c.relnamespace
1866
- where n.nspname = any(${schemas}) and con.contype in ('p', 'u', 'f', 'c')
1867
- order by 1, 2`;
1868
- const INDEXES = (schemas) => `
1869
- select ix.indrelid::int8 as table_id, i.relname as name,
1870
- ix.indisunique as unique, ix.indisprimary as primary,
1871
- (ix.indpred is not null or 0 = any(ix.indkey::int2[])) as partial,
1872
- am.amname as method, pg_get_expr(ix.indpred, ix.indrelid) as predicate,
1873
- array(select a.attname from unnest((ix.indkey::int2[])[0:ix.indnkeyatts - 1]) with ordinality k(attnum, ord)
1874
- join pg_attribute a on a.attrelid = ix.indrelid and a.attnum = k.attnum order by k.ord)::text[] as columns
1875
- from pg_index ix
1876
- join pg_class i on i.oid = ix.indexrelid
1877
- join pg_am am on am.oid = i.relam
1878
- join pg_class c on c.oid = ix.indrelid
1879
- join pg_namespace n on n.oid = c.relnamespace
1880
- where n.nspname = any(${schemas}) and ix.indisvalid
1881
- order by 1, 2`;
1882
- const POLICIES = (schemas) => `
1883
- select c.oid::int8 as table_id, p.policyname as name,
1884
- (p.permissive = 'PERMISSIVE') as permissive, p.roles::text[] as roles, lower(p.cmd) as command,
1885
- p.qual as using_expr, p.with_check as check_expr,
1886
- array(
1887
- select distinct fn.nspname || '.' || pr.proname
1888
- from pg_policy pol
1889
- join pg_depend d on d.classid = 'pg_policy'::regclass and d.objid = pol.oid
1890
- and d.refclassid = 'pg_proc'::regclass
1891
- join pg_proc pr on pr.oid = d.refobjid
1892
- join pg_namespace fn on fn.oid = pr.pronamespace
1893
- where pol.polrelid = c.oid and pol.polname = p.policyname
1894
- order by 1
1895
- )::text[] as functions
1896
- from pg_policies p
1897
- join pg_namespace n on n.nspname = p.schemaname
1898
- join pg_class c on c.relnamespace = n.oid and c.relname = p.tablename
1899
- where p.schemaname = any(${schemas})
1900
- order by 1, 2`;
1901
- const FUNCTIONS = (schemas) => `
1902
- select n.nspname as schema, p.proname as name,
1903
- pg_get_function_identity_arguments(p.oid) as signature,
1904
- l.lanname as language, p.provolatile as volatility,
1905
- p.prosecdef as security_definer, coalesce(p.proconfig, '{}')::text[] as config,
1906
- array(
1907
- select r from unnest(array['anon', 'authenticated']) r
1908
- where has_function_privilege(r, p.oid, 'EXECUTE')
1909
- ) as execute
1910
- from pg_proc p
1911
- join pg_namespace n on n.oid = p.pronamespace
1912
- join pg_language l on l.oid = p.prolang
1913
- where p.oid in (
1914
- select d.refobjid
1915
- from pg_depend d
1916
- join pg_policy pol on d.classid = 'pg_policy'::regclass and d.objid = pol.oid
1917
- join pg_class c on c.oid = pol.polrelid
1918
- join pg_namespace cn on cn.oid = c.relnamespace
1919
- where d.refclassid = 'pg_proc'::regclass and cn.nspname = any(${schemas})
1920
- )
1921
- or (n.nspname = any(${schemas}) and ((p.prosecdef
1922
- and p.prorettype not in ('trigger'::regtype, 'event_trigger'::regtype)) or exists (
1923
- select 1 from unnest(p.proconfig) setting where setting not like 'search_path=%'
1924
- )))
1925
- order by 1, 2, 3`;
1926
- /** Roles the hook checks care about: the one Auth calls it as, and the API roles. */
1927
- const HOOK_ROLES = literalArray([
1928
- "supabase_auth_admin",
1929
- "authenticated",
1930
- "anon"
1931
- ]);
1932
- const HOOKS = (names) => `
1933
- select n.nspname as schema, p.proname as name,
1934
- pg_get_function_identity_arguments(p.oid) as signature,
1935
- l.lanname as language, p.provolatile as volatility,
1936
- p.prosecdef as security_definer, coalesce(p.proconfig, '{}')::text[] as config,
1937
- array(select r.rolname::text from pg_roles r
1938
- where r.rolname = any(${HOOK_ROLES}) and has_function_privilege(r.oid, p.oid, 'execute')
1939
- order by 1) as execute,
1940
- exists(select 1 from aclexplode(coalesce(p.proacl, acldefault('f', p.proowner))) a
1941
- where a.grantee = 0 and a.privilege_type = 'EXECUTE') as public_execute,
1942
- array(select r.rolname::text from pg_roles r
1943
- where r.rolname = any(${HOOK_ROLES}) and has_schema_privilege(r.oid, n.oid, 'usage')
1944
- order by 1) as schema_usage,
1945
- p.prosrc as source
1946
- from pg_proc p
1947
- join pg_namespace n on n.oid = p.pronamespace
1948
- join pg_language l on l.oid = p.prolang
1949
- where n.nspname || '.' || p.proname = any(${names})
1950
- order by 1, 2, 3`;
1951
- const TRIGGERS = (schemas) => `
1952
- select t.tgrelid::int8 as table_id, t.tgname as name,
1953
- pn.nspname || '.' || p.proname as function,
1954
- case when t.tgtype & 2 = 2 then 'before' when t.tgtype & 64 = 64 then 'instead of' else 'after' end as timing,
1955
- array_remove(array[
1956
- case when t.tgtype & 4 = 4 then 'insert' end,
1957
- case when t.tgtype & 16 = 16 then 'update' end,
1958
- case when t.tgtype & 8 = 8 then 'delete' end,
1959
- case when t.tgtype & 32 = 32 then 'truncate' end
1960
- ], null)::text[] as events,
1961
- case when t.tgtype & 1 = 1 then 'row' else 'statement' end as level
1962
- from pg_trigger t
1963
- join pg_class c on c.oid = t.tgrelid
1964
- join pg_namespace n on n.oid = c.relnamespace
1965
- join pg_proc p on p.oid = t.tgfoid
1966
- join pg_namespace pn on pn.oid = p.pronamespace
1967
- where not t.tgisinternal and n.nspname = any(${schemas})
1968
- order by 1, 2`;
1969
- const GRANTS = (schemas) => `
1970
- select c.oid::int8 as table_id, coalesce(r.rolname, 'PUBLIC') as role,
1971
- array_agg(distinct acl.privilege_type order by acl.privilege_type)::text[] as privileges
1972
- from pg_class c
1973
- join pg_namespace n on n.oid = c.relnamespace
1974
- cross join lateral aclexplode(coalesce(c.relacl, acldefault('r', c.relowner))) acl
1975
- left join pg_roles r on r.oid = acl.grantee
1976
- where n.nspname = any(${schemas}) and c.relkind in ('r', 'p', 'v', 'm', 'f')
1977
- and (acl.grantee = 0 or r.rolname in ('anon', 'authenticated', 'service_role'))
1978
- and acl.privilege_type <> 'MAINTAIN'
1979
- group by 1, 2
1980
- order by 1, 2`;
1981
- const COLUMN_GRANTS = (schemas) => `
1982
- select c.oid::int8 as table_id, a.attname as column, coalesce(r.rolname, 'PUBLIC') as role,
1983
- array_agg(distinct acl.privilege_type order by acl.privilege_type)::text[] as privileges
1984
- from pg_class c
1985
- join pg_namespace n on n.oid = c.relnamespace
1986
- join pg_attribute a on a.attrelid = c.oid and a.attnum > 0 and not a.attisdropped and a.attacl is not null
1987
- cross join lateral aclexplode(a.attacl) acl
1988
- left join pg_roles r on r.oid = acl.grantee
1989
- where n.nspname = any(${schemas})
1990
- and (acl.grantee = 0 or r.rolname in ('anon', 'authenticated'))
1991
- and acl.privilege_type in ('INSERT', 'UPDATE')
1992
- group by 1, 2, 3
1993
- order by 1, 2, 3`;
1994
- const BUCKETS = `
1995
- select id, public, file_size_limit, allowed_mime_types,
1996
- to_jsonb(b) ? 'versioning_status' as has_versioning,
1997
- to_jsonb(b) -> 'versioning_status' as versioning_status,
1998
- to_jsonb(b) ? 'lifecycle_configuration' as has_lifecycle,
1999
- to_jsonb(b) -> 'lifecycle_configuration' as lifecycle_configuration
2000
- from storage.buckets b
2001
- order by id`;
2002
- const REALTIME = `
2003
- select schemaname || '.' || tablename as name
2004
- from pg_publication_tables
2005
- where pubname = 'supabase_realtime'
2006
- order by 1`;
2007
- const ROLE_SETTINGS = `
2008
- select r.rolname as role, s.setconfig as config
2009
- from pg_catalog.pg_db_role_setting s
2010
- join pg_catalog.pg_roles r on r.oid = s.setrole
2011
- where r.rolname in ('authenticator', 'anon', 'authenticated')
2012
- and s.setdatabase in (0, (select oid from pg_catalog.pg_database where datname = current_database()))
2013
- order by s.setdatabase`;
2014
- const HAS_TABLE = (qualified) => `select to_regclass('${qualified}') is not null as present`;
2015
- const ACTIONS = {
2016
- a: "no action",
2017
- r: "restrict",
2018
- c: "cascade",
2019
- n: "set null",
2020
- d: "set default"
2021
- };
2022
- const VOLATILITY = {
2023
- i: "immutable",
2024
- s: "stable",
2025
- v: "volatile"
2026
- };
2027
- /** `['statement_timeout=5s']` as `{ statement_timeout: '5s' }`. */
2028
- function settingsOf(config) {
2029
- const settings = {};
2030
- for (const entry of config ?? []) {
2031
- const at = entry.indexOf("=");
2032
- if (at > 0) settings[entry.slice(0, at)] = entry.slice(at + 1);
2033
- }
2034
- return settings;
2035
- }
2036
- const functionOf = (row) => ({
2037
- schema: row.schema,
2038
- name: row.name,
2039
- signature: row.signature,
2040
- language: row.language,
2041
- volatility: VOLATILITY[row.volatility],
2042
- securityDefiner: row.security_definer,
2043
- settings: settingsOf(row.config)
2044
- });
2045
- /** The functions behind Auth hooks, in any schema, with their ACLs. */
2046
- async function readHooks(db, targets) {
2047
- if (targets.length === 0) return [];
2048
- const found = await rows(db, HOOKS(literalArray(targets.map((t) => `${t.schema}.${t.name}`))));
2049
- return targets.map((target) => ({
2050
- hook: target.hook,
2051
- schema: target.schema,
2052
- name: target.name,
2053
- functions: found.filter((row) => row.schema === target.schema && row.name === target.name).map((row) => ({
2054
- ...functionOf(row),
2055
- execute: row.execute,
2056
- publicExecute: row.public_execute,
2057
- schemaUsage: row.schema_usage,
2058
- ...row.source === null ? {} : { source: row.source }
2059
- }))
2060
- }));
2061
- }
2062
- async function rows(db, sql) {
2063
- return (await db.query(sql)).rows;
2064
- }
2065
- /** Rows from a table owned by another Supabase service, if it exists. */
2066
- async function serviceRows(db, qualified, sql) {
2067
- const [probe] = await rows(db, HAS_TABLE(qualified));
2068
- return probe?.present ? rows(db, sql) : [];
2069
- }
2070
- function groupById(list) {
2071
- const map = /* @__PURE__ */ new Map();
2072
- for (const row of list) {
2073
- const id = Number(row.table_id);
2074
- const entry = map.get(id);
2075
- if (entry) entry.push(row);
2076
- else map.set(id, [row]);
2077
- }
2078
- return map;
2079
- }
2080
- /** Reads the extras for `schemas`, with the catalog queries in flight together. */
2081
- async function readExtras(db, schemas, hooks = []) {
2082
- const list = literalArray(schemas);
2083
- const [relations, constraintRows, indexRows, policyRows, triggerRows, grantRows, columnGrantRows, buckets, realtime, functions, roleRows, hookRows] = await Promise.all([
2084
- rows(db, RELATIONS(list)),
2085
- rows(db, CONSTRAINTS(list)),
2086
- rows(db, INDEXES(list)),
2087
- rows(db, POLICIES(list)),
2088
- rows(db, TRIGGERS(list)),
2089
- rows(db, GRANTS(list)),
2090
- rows(db, COLUMN_GRANTS(list)),
2091
- serviceRows(db, "storage.buckets", BUCKETS),
2092
- rows(db, REALTIME),
2093
- rows(db, FUNCTIONS(list)),
2094
- rows(db, ROLE_SETTINGS),
2095
- hooks.length > 0 ? readHooks(db, hooks) : void 0
2096
- ]);
2097
- const constraints = groupById(constraintRows);
2098
- const indexes = groupById(indexRows);
2099
- const policies = groupById(policyRows);
2100
- const triggers = groupById(triggerRows);
2101
- const grants = groupById(grantRows);
2102
- const columnGrants = groupById(columnGrantRows);
2103
- const roleSettings = {};
2104
- for (const row of roleRows) Object.assign(roleSettings[row.role] ??= {}, settingsOf(row.config));
2105
- return {
2106
- tables: relations.map((relation) => {
2107
- const id = Number(relation.id);
2108
- const own = constraints.get(id) ?? [];
2109
- const ownIndexes = indexes.get(id) ?? [];
2110
- const uniques = own.filter((con) => con.type === "u").map((con) => ({
2111
- name: con.name,
2112
- columns: con.columns
2113
- }));
2114
- const constraintNames = new Set(own.map((con) => con.name));
2115
- for (const index of ownIndexes) if (index.unique && !index.primary && !index.partial && !constraintNames.has(index.name)) uniques.push({
2116
- name: index.name,
2117
- columns: index.columns
2118
- });
2119
- return {
2120
- id,
2121
- schema: relation.schema,
2122
- name: relation.name,
2123
- primaryKey: own.find((con) => con.type === "p")?.columns ?? [],
2124
- uniques,
2125
- foreignKeys: own.filter((con) => con.type === "f").map((con) => ({
2126
- name: con.name,
2127
- onDelete: ACTIONS[con.on_delete] ?? "no action",
2128
- onUpdate: ACTIONS[con.on_update] ?? "no action"
2129
- })),
2130
- checks: own.filter((con) => con.type === "c").map((con) => ({
2131
- name: con.name,
2132
- definition: con.definition
2133
- })),
2134
- indexes: ownIndexes.map((index) => ({
2135
- name: index.name,
2136
- columns: index.columns,
2137
- unique: index.unique,
2138
- primary: index.primary,
2139
- partial: index.partial,
2140
- method: index.method,
2141
- predicate: index.predicate
2142
- })),
2143
- policies: (policies.get(id) ?? []).map((policy) => ({
2144
- name: policy.name,
2145
- command: policy.command,
2146
- roles: policy.roles,
2147
- permissive: policy.permissive,
2148
- using: policy.using_expr,
2149
- check: policy.check_expr,
2150
- functions: policy.functions ?? []
2151
- })),
2152
- triggers: (triggers.get(id) ?? []).map((trigger) => ({
2153
- name: trigger.name,
2154
- timing: trigger.timing,
2155
- events: trigger.events,
2156
- level: trigger.level,
2157
- function: trigger.function
2158
- })),
2159
- grants: (grants.get(id) ?? []).map((grant) => ({
2160
- role: grant.role,
2161
- privileges: grant.privileges
2162
- })),
2163
- columnGrants: (columnGrants.get(id) ?? []).map((grant) => ({
2164
- column: grant.column,
2165
- role: grant.role,
2166
- privileges: grant.privileges
2167
- })),
2168
- ...relation.large ? { large: true } : {}
2169
- };
2170
- }),
2171
- buckets: buckets.map((row) => ({
2172
- id: row.id,
2173
- public: row.public,
2174
- fileSizeLimit: row.file_size_limit === null ? null : Number(row.file_size_limit),
2175
- allowedMimeTypes: row.allowed_mime_types,
2176
- ...row.has_versioning ? { versioning: row.versioning_status } : {},
2177
- ...row.has_lifecycle ? { lifecycle: row.lifecycle_configuration } : {}
2178
- })),
2179
- realtime: realtime.map((row) => row.name),
2180
- roleSettings,
2181
- functions: functions.map((row) => ({
2182
- ...functionOf(row),
2183
- execute: row.execute
2184
- })),
2185
- ...hookRows ? { hooks: hookRows } : {}
2186
- };
2187
- }
2188
- //#endregion
2189
- //#region src/cli/introspect/fingerprint.ts
2190
- /**
2191
- * Catalogs whose rows only change with DDL, grants, comments or settings,
2192
- * with the column that ties a row to a relation or namespace, if any.
2193
- */
2194
- const CATALOGS = [
2195
- ["pg_namespace", "oid"],
2196
- ["pg_attribute", "attrelid"],
2197
- ["pg_attrdef", "adrelid"],
2198
- ["pg_constraint", "conrelid"],
2199
- ["pg_index", "indrelid"],
2200
- ["pg_inherits"],
2201
- ["pg_rewrite"],
2202
- ["pg_policy"],
2203
- ["pg_trigger", "tgrelid"],
2204
- ["pg_proc"],
2205
- ["pg_type", "typnamespace"],
2206
- ["pg_enum"],
2207
- ["pg_description"],
2208
- ["pg_db_role_setting"],
2209
- ["pg_publication"],
2210
- ["pg_publication_rel"],
2211
- ["pg_extension"]
2212
- ];
2213
- const TEMP_NAMESPACES = String.raw`(select oid from pg_catalog.pg_namespace where nspname like 'pg\_temp\_%' or nspname like 'pg\_toast\_temp\_%')`;
2214
- const TEMP_RELATIONS = `(select oid from pg_catalog.pg_class where relnamespace in ${TEMP_NAMESPACES})`;
2215
- const catalogRows = ([name, column]) => {
2216
- if (column === void 0) return `pg_catalog.${name}`;
2217
- return `(select * from pg_catalog.${name} where ${column} not in ${column === "oid" || column === "typnamespace" ? TEMP_NAMESPACES : TEMP_RELATIONS})`;
2218
- };
2219
- const digest = (from) => `(select md5(coalesce(string_agg(x::text, ',' order by x::text), '')) from ${from} x)`;
2220
- /**
2221
- * One cheap query whose result changes whenever introspection could. pg_class
2222
- * leaves out the planner statistics that VACUUM and ANALYZE rewrite, except
2223
- * the row-count threshold the snapshot records. pg_depend is limited to the
2224
- * policies' rows, which name the tables and functions each policy uses.
2225
- * pg_auth_members decides which privileges a role inherits, so the execute
2226
- * lists change with it. Bucket rows are data, so they are hashed when
2227
- * `storage.buckets` exists.
2228
- */
2229
- const FINGERPRINT_SQL = `select md5(concat_ws('|',
2230
- ${digest(`(select oid, relname, relnamespace, relkind, relacl, reloptions, relrowsecurity, relforcerowsecurity, relreplident, relispartition, reltuples >= ${LARGE_TABLE_ROWS} as large from pg_catalog.pg_class where relnamespace not in ${TEMP_NAMESPACES})`)},
2231
- ${CATALOGS.map((entry) => digest(catalogRows(entry))).join(",\n ")},
2232
- ${digest(`(select objid, refclassid, refobjid, refobjsubid, deptype from pg_catalog.pg_depend where classid = 'pg_catalog.pg_policy'::regclass)`)},
2233
- (select md5(coalesce(string_agg(rolname, ',' order by rolname), '')) from pg_catalog.pg_roles),
2234
- ${digest("pg_catalog.pg_auth_members")},
2235
- case when to_regclass('storage.buckets') is not null
2236
- then md5(query_to_xml('select id, public, file_size_limit, allowed_mime_types, to_jsonb(b) -> ''versioning_status'' as versioning, to_jsonb(b) -> ''lifecycle_configuration'' as lifecycle from storage.buckets b order by id', false, false, '')::text)
2237
- end
2238
- )) as fingerprint`;
2239
- /** A hash of the catalog; equal values mean introspection would return the same snapshot. */
2240
- async function catalogFingerprint(db) {
2241
- const [row] = (await db.query(FINGERPRINT_SQL)).rows;
2242
- const value = row && typeof row === "object" && "fingerprint" in row ? row.fingerprint : void 0;
2243
- if (typeof value !== "string") throw new TypeError("The catalog fingerprint query returned no row.");
2244
- return value;
2245
- }
2246
- //#endregion
2247
- //#region src/cli/introspect/cache.ts
2248
- /** Shared with the splinter download cache. */
2249
- const CACHE_DIR = "node_modules/.cache/better-supabase";
2250
- const sha256 = (text) => createHash("sha256").update(text).digest("hex");
2251
- function isEntry(value) {
2252
- return typeof value === "object" && value !== null && "key" in value && typeof value.key === "string" && "snapshot" in value && typeof value.snapshot === "object";
2253
- }
2254
- /**
2255
- * Calls `read`, or returns the snapshot cached under `root` when the catalog
2256
- * fingerprint, the `inputs` (schemas and hooks), the CLI version and the
2257
- * typegen version all match. One file per source keeps the cache from growing. A source that
2258
- * cannot report a fingerprint is read every time.
2259
- */
2260
- async function cachedIntrospect(root, source, inputs, read) {
2261
- const fingerprint = await catalogFingerprint(source.queryable).catch(() => void 0);
2262
- if (fingerprint === void 0) return read();
2263
- const key = sha256(JSON.stringify([
2264
- VERSION,
2265
- TYPEGEN_VERSION,
2266
- source.describe,
2267
- inputs,
2268
- fingerprint
2269
- ]));
2270
- const file = resolve(root, CACHE_DIR, `snapshot-${sha256(source.describe).slice(0, 16)}.json`);
2271
- const cached = await readFile(file, "utf8").then((text) => JSON.parse(text)).catch(() => void 0);
2272
- if (isEntry(cached) && cached.key === key) return cached.snapshot;
2273
- const snapshot = await read();
2274
- await writeAtomic(file, JSON.stringify({
2275
- key,
2276
- snapshot
2277
- })).catch(() => void 0);
2278
- return snapshot;
2279
- }
2280
- /**
2281
- * Calls `produce`, or returns the `database.types.ts` cached under `root`
2282
- * for the same `inputs`, CLI version and typegen version. Typegen and oxfmt
2283
- * are most of a `gen` run on a large schema, and their output only depends
2284
- * on the inputs.
2285
- */
2286
- async function cachedDatabaseTypes(root, inputs, produce) {
2287
- const key = sha256(JSON.stringify([
2288
- VERSION,
2289
- TYPEGEN_VERSION,
2290
- inputs
2291
- ]));
2292
- const file = resolve(root, CACHE_DIR, "database-types.json");
2293
- const cached = await readFile(file, "utf8").then((text) => JSON.parse(text)).catch(() => void 0);
2294
- if (typeof cached === "object" && cached !== null && "key" in cached && cached.key === key && "contents" in cached && typeof cached.contents === "string") return cached.contents;
2295
- const contents = await produce();
2296
- await writeAtomic(file, JSON.stringify({
2297
- key,
2298
- contents
2299
- })).catch(() => void 0);
2300
- return contents;
2301
- }
2302
- /** Writes through a temporary file, so a concurrent reader never sees half a file. */
2303
- async function writeAtomic(file, contents) {
2304
- await mkdir(dirname(file), { recursive: true });
2305
- const temporary = `${file}.${process.pid}-${crypto.randomUUID()}.tmp`;
2306
- try {
2307
- await writeFile(temporary, contents);
2308
- await rename(temporary, file);
2309
- } catch (cause) {
2310
- await rm(temporary, { force: true });
2311
- throw cause;
2312
- }
2313
- }
2314
- //#endregion
2315
- //#region src/cli/introspect/from-metadata.ts
2316
- /** What the extras query set reads that a `GeneratorMetadata` document leaves out. */
2317
- const METADATA_GAPS = [
2318
- "multi-column unique keys and checks",
2319
- "foreign key actions",
2320
- "indexes",
2321
- "triggers",
2322
- "policies",
2323
- "grants",
2324
- "storage buckets",
2325
- "the realtime publication"
2326
- ];
2327
- /** `METADATA_GAPS` as one phrase for notices. */
2328
- const METADATA_GAPS_TEXT = `${METADATA_GAPS.slice(0, -1).join(", ")} or ${METADATA_GAPS.at(-1) ?? ""}`;
2329
- /**
2330
- * Builds a snapshot from a `GeneratorMetadata` document alone, for
2331
- * `gen --metadata`. Relations come from `relationships`, single-column unique
2332
- * keys from `is_unique` and single-column checks from `check`, named as
2333
- * Postgres names them by default (`<table>_<column>_key`, `<table>_<column>_check`).
2334
- * Everything else the extras carry is empty, and `extras.fromMetadata` says so.
2335
- */
2336
- function fromMetadata(document) {
2337
- const { metadata } = stabilizeMetadata(document);
2338
- const tableIds = new Set(metadata.tables.map((table) => table.id));
2339
- const tables = [
2340
- ...metadata.tables,
2341
- ...metadata.foreignTables,
2342
- ...metadata.views,
2343
- ...metadata.materializedViews
2344
- ].map((relation) => {
2345
- const columns = metadata.columns.filter((column) => column.table_id === relation.id).sort((a, b) => a.ordinal_position - b.ordinal_position);
2346
- const own = tableIds.has(relation.id);
2347
- return {
2348
- id: relation.id,
2349
- schema: relation.schema,
2350
- name: relation.name,
2351
- primaryKey: [],
2352
- uniques: own ? columns.filter((column) => column.is_unique).map((column) => ({
2353
- name: `${relation.name}_${column.name}_key`,
2354
- columns: [column.name]
2355
- })) : [],
2356
- foreignKeys: own ? metadata.relationships.filter((fk) => fk.schema === relation.schema && fk.relation === relation.name).map((fk) => ({
2357
- name: fk.foreign_key_name,
2358
- onDelete: "no action",
2359
- onUpdate: "no action"
2360
- })).sort((a, b) => byCodePoint(a.name, b.name)) : [],
2361
- checks: own ? columns.flatMap((column) => column.check === null ? [] : [{
2362
- name: `${relation.name}_${column.name}_check`,
2363
- definition: `CHECK ((${column.check}))`
2364
- }]) : [],
2365
- indexes: [],
2366
- policies: [],
2367
- triggers: [],
2368
- grants: []
2369
- };
2370
- });
2371
- return {
2372
- version: 2,
2373
- schemas: [...new Set(metadata.schemas.map((schema) => schema.name))].sort(byCodePoint),
2374
- generator: metadata,
2375
- extras: {
2376
- tables,
2377
- buckets: [],
2378
- realtime: [],
2379
- fromMetadata: true
2380
- }
2381
- };
2382
- }
2383
- //#endregion
2384
- //#region src/cli/introspect/source.ts
2385
- const POOL_SIZE = 4;
2386
- const STATEMENT_TIMEOUT_MS = 12e4;
2387
- /**
2388
- * A small `pg` pool, since introspection issues its queries concurrently. A
2389
- * `connect` that returns a single client gets its queries queued, because one
2390
- * `pg.Client` runs them one at a time.
2391
- */
2392
- async function pgSource(url, open = connect, signal) {
2393
- const { client, pooled, close, describe } = await open(url, void 0, {
2394
- pool: POOL_SIZE,
2395
- statementTimeout: STATEMENT_TIMEOUT_MS,
2396
- ...signal ? { signal } : {}
2397
- });
2398
- if (pooled) return {
2399
- queryable: client,
2400
- close,
2401
- describe
2402
- };
2403
- let queue = Promise.resolve();
2404
- return {
2405
- queryable: { query(sql) {
2406
- const next = queue.then(() => client.query(sql));
2407
- queue = next.catch(() => void 0);
2408
- return next;
2409
- } },
2410
- close,
2411
- describe
2412
- };
2413
- }
2414
- /**
2415
- * Runs introspection SQL through the Supabase Management API as the
2416
- * read-only database user, so hosted projects need no database password.
2417
- */
2418
- function managementSource(options) {
2419
- const base = (options.apiUrl ?? "https://api.supabase.com").replace(/\/$/, "");
2420
- const doFetch = options.fetch ?? fetch;
2421
- const endpoint = `${base}/v1/projects/${encodeURIComponent(options.projectRef)}/database/query/read-only`;
2422
- return {
2423
- queryable: { async query(sql) {
2424
- const response = await doFetch(endpoint, {
2425
- method: "POST",
2426
- headers: {
2427
- authorization: `Bearer ${options.accessToken}`,
2428
- "content-type": "application/json"
2429
- },
2430
- body: JSON.stringify({ query: sql }),
2431
- ...options.signal ? { signal: options.signal } : {}
2432
- });
2433
- const text = await response.text();
2434
- if (!response.ok) throw new Error(`Management API query failed (${response.status}) for project ${options.projectRef}: ${text.slice(0, 500)}`);
2435
- const rows = JSON.parse(text);
2436
- if (!Array.isArray(rows)) throw new TypeError(`Management API returned an unexpected body for project ${options.projectRef}.`);
2437
- return { rows };
2438
- } },
2439
- describe: `project ${options.projectRef} (Management API)`,
2440
- close: () => Promise.resolve()
2441
- };
2442
- }
2443
- //#endregion
2444
- //#region src/cli/introspect/index.ts
2445
- /** Reads a v2 snapshot: typegen metadata plus the extras. */
2446
- async function introspect(db, schemas, options = {}) {
2447
- const unique = [...new Set(schemas)].sort();
2448
- const [metadata, extras] = await Promise.all([readGeneratorMetadata(db, unique), readExtras(db, unique, options.hooks)]);
2449
- const { metadata: generator, ids } = stabilizeMetadata(metadata);
2450
- return {
2451
- version: 2,
2452
- schemas: unique,
2453
- generator,
2454
- extras: {
2455
- ...extras,
2456
- tables: extras.tables.map((table) => ({
2457
- ...table,
2458
- id: ids.get(table.id) ?? table.id
2459
- }))
2460
- }
2461
- };
2462
- }
2463
- //#endregion
2464
- //#region src/cli/commands/snapshot.ts
2465
- const SNAPSHOT_SCHEMA_URL = "https://unpkg.com/better-supabase/schemas/snapshot-v2.json";
2466
- /** Schemas that are always read, for doctor checks on helper functions. */
2467
- const EXTRA_SCHEMAS = ["better_supabase"];
2468
- /** The hosted project to read through the Management API, if any. */
2469
- function managementTarget(config, env, source) {
2470
- if (source.dbUrl) return void 0;
2471
- const projectRef = source.projectRef ?? (config.source.dbUrl ? void 0 : config.source.projectRef);
2472
- if (!projectRef) return void 0;
2473
- const accessToken = config.source.accessToken ?? env.SUPABASE_ACCESS_TOKEN;
2474
- if (!accessToken) throw new CliError("missing_value", `Reading project ${projectRef} needs a Supabase access token. Set SUPABASE_ACCESS_TOKEN to a token scoped to this project (https://supabase.com/dashboard/account/tokens), or read the database with $DATABASE_URL or --db-url-stdin.`, { flag: "SUPABASE_ACCESS_TOKEN" });
2475
- return {
2476
- projectRef,
2477
- accessToken,
2478
- ...env.SUPABASE_API_URL ? { apiUrl: env.SUPABASE_API_URL } : {}
2479
- };
2480
- }
2481
- /**
2482
- * Where to read the schema from: `--db-url-stdin`, `--project-ref`, then the
2483
- * config's `source.dbUrl` / `source.projectRef`, `$DATABASE_URL`, and finally
2484
- * the local stack.
2485
- */
2486
- async function openSource(config, env, source, open = connect) {
2487
- if (source.dbUrl) return pgSource(source.dbUrl, open, source.signal);
2488
- const target = managementTarget(config, env, source);
2489
- if (target) return managementSource({
2490
- ...target,
2491
- ...source.signal ? { signal: source.signal } : {}
2492
- });
2493
- return pgSource(await databaseUrl(config, env), open, source.signal);
2494
- }
2495
- /** Whether `loadSnapshot` reads a saved file rather than a database. */
2496
- function snapshotFile(config, source) {
2497
- return source.snapshotPath ?? (source.live || source.dbUrl || source.projectRef ? void 0 : config.source.snapshot);
2498
- }
2499
- /**
2500
- * Loads a saved snapshot or introspects the database. With `shared`, it
2501
- * introspects over that source and leaves closing it to the caller, so later
2502
- * queries reuse the connection.
2503
- */
2504
- async function loadSnapshot(config, env, source, open = connect, shared) {
2505
- const path = snapshotFile(config, source);
2506
- if (path) return readSnapshotFile(resolve(config.root, path), path);
2507
- const [tomlRead, opened] = await Promise.allSettled([readSupabaseToml(config.root), shared ? shared() : openSource(config, env, source, open)]);
2508
- if (tomlRead.status === "rejected") {
2509
- if (opened.status === "fulfilled" && !shared) await opened.value.close().catch(() => void 0);
2510
- throw tomlRead.reason;
2511
- }
2512
- if (opened.status === "rejected") throw opened.reason;
2513
- const toml = tomlRead.value;
2514
- const db = opened.value;
2515
- const hooks = toml ? pgFunctionHooks(toml.document) : [];
2516
- const schemas = [...config.schemas, ...EXTRA_SCHEMAS];
2517
- try {
2518
- const read = () => introspect(db.queryable, schemas, { hooks });
2519
- return await (source.cache ? cachedIntrospect(config.root, db, [schemas, hooks], read) : read());
2520
- } finally {
2521
- if (!shared) await db.close();
2522
- }
2523
- }
2524
- async function readSnapshotFile(absolute, label = absolute) {
2525
- if (!existsSync(absolute)) throw new Error(`Snapshot not found: ${label}`);
2526
- return parseSnapshot(JSON.parse(await readFile(absolute, "utf8")), label);
2527
- }
2528
- /** Validates a parsed snapshot document. */
2529
- async function parseSnapshot(data, label = "snapshot") {
2530
- const doc = data;
2531
- if (!doc || typeof doc !== "object" || doc.version !== 2) throw new Error(`${label} is not a version 2 snapshot. Run \`better-supabase introspect\` to refresh it.`);
2532
- if (!Array.isArray(doc.schemas) || !doc.extras || !Array.isArray(doc.extras.tables)) throw new Error(`${label} is missing "schemas" or "extras".`);
2533
- let generator;
2534
- try {
2535
- generator = await validateGeneratorMetadata(doc.generator);
2536
- } catch (cause) {
2537
- if (cause instanceof TypegenMissingError) throw cause;
2538
- throw new Error(`${label} has invalid "generator" metadata: ${cause instanceof Error ? cause.message : String(cause)}`, { cause });
2539
- }
2540
- return {
2541
- version: 2,
2542
- schemas: doc.schemas,
2543
- generator,
2544
- extras: {
2545
- tables: doc.extras.tables,
2546
- buckets: doc.extras.buckets ?? [],
2547
- realtime: doc.extras.realtime ?? [],
2548
- ...doc.extras.roleSettings ? { roleSettings: doc.extras.roleSettings } : {},
2549
- ...doc.extras.functions ? { functions: doc.extras.functions } : {},
2550
- ...doc.extras.hooks ? { hooks: doc.extras.hooks } : {}
2551
- }
2552
- };
2553
- }
2554
- function serializeSnapshot(snapshot) {
2555
- const { $schema: _ignored, ...rest } = snapshot;
2556
- return `${JSON.stringify({
2557
- $schema: SNAPSHOT_SCHEMA_URL,
2558
- ...rest
2559
- }, null, 2)}\n`;
2560
- }
2561
- //#endregion
2562
- //#region src/cli/commands/gen.ts
2563
- /**
2564
- * Renders every generated file for a snapshot, without touching disk:
2565
- * `database.types.ts` (what `supabase gen types` prints), the main module,
2566
- * then each configured generator's files.
2567
- */
2568
- async function renderFiles(config, snapshot, options = {}) {
2569
- return (await render(config, snapshot, options)).files;
2570
- }
2571
- async function render(config, snapshot, options = {}) {
2572
- const model = buildModel(snapshot, config);
2573
- const runtime = options.runtimeImport ? { runtimeImport: options.runtimeImport } : {};
2574
- const output = resolve(config.root, config.output);
2575
- const typegenOptions = {
2576
- schemas: config.schemas,
2577
- postgrestVersion: config.postgrestVersion
2578
- };
2579
- const databaseTypes = await cachedDatabaseTypes(config.root, [
2580
- typegenOptions,
2581
- await oxfmtInstalled(),
2582
- snapshot.generator
2583
- ], () => generateDatabaseTypes(snapshot.generator, typegenOptions));
2584
- const metaFiles = metaPaths(config.output);
2585
- const main = emitModule(model, {
2586
- databaseTypesImport: importPath(output, resolve(config.root, config.databaseTypesOutput)),
2587
- importPathFor: (from) => importPath(output, resolve(config.root, from)),
2588
- metaImport: `./${basename(metaFiles.js)}`,
2589
- ...options.inlineMeta ? { inlineMeta: true } : {},
2590
- ...runtime
2591
- });
2592
- const meta = emitMeta(model, {
2593
- types: `./${basename(metaFiles.dts)}`,
2594
- ...runtime
2595
- });
2596
- const files = [
2597
- {
2598
- path: config.databaseTypesOutput,
2599
- contents: databaseTypes
2600
- },
2601
- {
2602
- path: config.output,
2603
- contents: main
2604
- },
2605
- {
2606
- path: metaFiles.js,
2607
- contents: meta.js
2608
- },
2609
- {
2610
- path: metaFiles.dts,
2611
- contents: meta.dts
2612
- }
2613
- ];
2614
- const owners = new Map(files.map((file) => [resolve(config.root, file.path), "gen"]));
2615
- let view;
2616
- for (const generator of config.generators) {
2617
- let extra;
2618
- try {
2619
- extra = await generator.generate({
2620
- meta: model.meta,
2621
- introspection: model.introspection,
2622
- extras: snapshot.extras,
2623
- config,
2624
- output,
2625
- importPath: (from, to) => importPath(resolve(config.root, from), resolve(config.root, to)),
2626
- model: view ??= generatorModel(model)
2627
- });
2628
- } catch (cause) {
2629
- throw new Error(`generator "${generator.name}" failed: ${cause instanceof Error ? cause.message : String(cause)}`, { cause });
2630
- }
2631
- for (const file of extra) {
2632
- const path = resolve(config.root, file.path);
2633
- const inside = relative(config.root, path);
2634
- if (inside === "" || inside.startsWith("..") || isAbsolute(inside)) throw new Error(`generator "${generator.name}" wrote ${file.path}, which is outside the project root`);
2635
- const owner = owners.get(path);
2636
- if (owner !== void 0) throw new Error(`generator "${generator.name}" wrote ${file.path}, which ${owner === "gen" ? "better-supabase gen writes" : `generator "${owner}" also writes`}`);
2637
- owners.set(path, generator.name);
2638
- files.push(file);
2639
- }
2640
- }
2641
- return {
2642
- files,
2643
- warnings: model.warnings
2644
- };
2645
- }
2646
- /** The `read-sets` SQL module file for `config.readSets`, if any are configured. */
2647
- async function readSetFile(config) {
2648
- if (config.readSets.length === 0) return void 0;
2649
- const readSets = await compiledReadSets(config);
2650
- return renderModules(["read-sets"], moduleLayout(config, config.sql.testsDir, readSets))[0];
2651
- }
2652
- /**
2653
- * `buckets` keys that reach the authorization provider's functions but
2654
- * aren't marked `sqlComplete: true` in `authorization.permissions`, as
2655
- * error lines.
2656
- */
2657
- function rowConditionedBuckets(config) {
2658
- const provider = config.authorization;
2659
- if (!provider) return [];
2660
- return providerBucketKeys(config).flatMap(({ bucket, keys }) => keys.flatMap((key) => {
2661
- const problem = unsafeKey(provider, key);
2662
- return problem ? [` buckets.${bucket}: "${key}" ${problem.reason}. ${problem.fix}`] : [];
2663
- }));
2664
- }
2665
- /** The exit `gen` stops with when bucket keys aren't fully answered by the provider's SQL functions. */
2666
- function refuseRowConditionedBuckets(config) {
2667
- const refused = rowConditionedBuckets(config);
2668
- return refused.length === 0 || !config.authorization ? void 0 : {
2669
- code: 1,
2670
- error: `The SQL functions of ${providerLabel(config.authorization)} decide by role and scope only, so these bucket policies could grant every object in the scope:\n${refused.join("\n")}\nSee doctor BS214.`
2671
- };
2672
- }
2673
- /** The files the last `gen` wrote, so the next one can remove those it no longer writes. */
2674
- const MANIFEST = `${CACHE_DIR}/gen-manifest.json`;
2675
- const manifestPath = (root, path) => relative(root, resolve(root, path)).split(sep).join("/");
2676
- async function readManifest(root) {
2677
- const parsed = await readFile(resolve(root, MANIFEST), "utf8").then((text) => JSON.parse(text)).catch(() => void 0);
2678
- if (typeof parsed !== "object" || parsed === null || !("version" in parsed) || parsed.version !== 1 || !("files" in parsed) || !Array.isArray(parsed.files)) return [];
2679
- return parsed.files.filter((path) => typeof path === "string");
2680
- }
2681
- /** Files in the last manifest that this run doesn't generate and that still exist inside the root. */
2682
- async function leftoverFiles(root, generated) {
2683
- const current = new Set(generated);
2684
- return (await readManifest(root)).filter((path) => {
2685
- const inside = relative(root, resolve(root, path));
2686
- return !current.has(path) && inside !== "" && !inside.startsWith("..") && !isAbsolute(inside) && existsSync(resolve(root, path));
2687
- });
2688
- }
2689
- const writeManifest = (root, files) => writeAtomic(resolve(root, MANIFEST), `${JSON.stringify({
2690
- version: 1,
2691
- files: [...files].sort()
2692
- }, null, 2)}\n`).catch(() => void 0);
2693
- const UNFORMATTED = "oxfmt is not installed, so database.types.ts is not formatted like `supabase gen types` output. Install it: pnpm add -D oxfmt. @supabase/postgrest-typegen pins oxfmt 0.66.0 as its peer; to allow a newer one, add it to peerDependencyRules.allowedVersions in pnpm-workspace.yaml, keyed \"@supabase/postgrest-typegen>oxfmt\".";
2694
- const METADATA_ONLY = `Notice: the schema came from a GeneratorMetadata document, which has no ${METADATA_GAPS_TEXT}. Unique keys and checks cover single columns, relations have no onDelete, and columns a before-insert trigger fills stay required on insert. Run \`better-supabase gen\` against the database for the full model.`;
2695
- /** The formatter notice, the metadata-only notice and the config warnings, one line each. */
2696
- async function generationNotices(snapshot, warnings) {
2697
- return [
2698
- ...await oxfmtInstalled() ? [] : [UNFORMATTED],
2699
- ...snapshot.extras.fromMetadata ? [METADATA_ONLY] : [],
2700
- ...warnings.map((warning) => `Warning: ${warning}`)
2701
- ];
2702
- }
2703
- async function runGen(options) {
2704
- const { config } = options;
2705
- const refused = refuseRowConditionedBuckets(config);
2706
- if (refused) return refused;
2707
- const snapshot = options.snapshot ?? await loadSnapshot(config, options.env, options);
2708
- const { files, warnings } = await render(config, snapshot);
2709
- const pathsOf = (readSets) => [...files, ...readSets ? [readSets] : []].map((file) => manifestPath(config.root, file.path));
2710
- const notice = (await generationNotices(snapshot, warnings)).map((line) => `\n${line}`).join("");
2711
- const readSetsOf = () => options.isolated ? Promise.resolve(void 0) : readSetFile(config);
2712
- const leftoversOf = (generated) => options.isolated ? Promise.resolve([]) : leftoverFiles(config.root, generated);
2713
- if (options.check) {
2714
- const readSets = await readSetsOf();
2715
- const generated = pathsOf(readSets);
2716
- const leftovers = await leftoversOf(generated);
2717
- const stale = [];
2718
- const diffs = [];
2719
- const compare = (file, current) => {
2720
- const shown = display(config.root, file.path);
2721
- stale.push(shown);
2722
- diffs.push(fileDiff(shown, current, file.contents, options.paint));
2723
- };
2724
- for (const file of files) {
2725
- const path = resolve(config.root, file.path);
2726
- const current = existsSync(path) ? await readFile(path, "utf8") : void 0;
2727
- if (!sameText(current, file.contents)) compare(file, current);
2728
- }
2729
- if (readSets) {
2730
- const path = resolve(config.root, readSets.path);
2731
- const current = existsSync(path) ? await readFile(path, "utf8") : void 0;
2732
- if (!sameModuleFile(current, readSets.contents)) compare(readSets, current);
2733
- }
2734
- if (stale.length > 0 || leftovers.length > 0) {
2735
- const lines = [...stale.map((path) => ` ${path}`), ...leftovers.map((path) => ` ${path} (no longer generated)`)];
2736
- return {
2737
- code: 1,
2738
- output: `${diffs.join("\n\n")}${notice}`,
2739
- error: `Generated files are out of date:\n${lines.join("\n")}\nRun \`better-supabase gen\`.`,
2740
- data: {
2741
- upToDate: false,
2742
- stale,
2743
- leftovers,
2744
- warnings
2745
- }
2746
- };
2747
- }
2748
- return {
2749
- code: 0,
2750
- output: `Generated files are up to date (${generated.length}).${notice}`,
2751
- data: {
2752
- upToDate: true,
2753
- stale: [],
2754
- leftovers: [],
2755
- warnings
2756
- }
2757
- };
2758
- }
2759
- const written = [];
2760
- for (const file of files) if (await writeIfChanged(resolve(config.root, file.path), file.contents)) written.push(display(config.root, file.path));
2761
- const readSets = await readSetsOf();
2762
- if (readSets && await writeIfChanged(resolve(config.root, readSets.path), readSets.contents)) written.push(display(config.root, readSets.path));
2763
- const generated = pathsOf(readSets);
2764
- const removed = [];
2765
- for (const path of await leftoversOf(generated)) {
2766
- await rm(resolve(config.root, path), { force: true });
2767
- removed.push(path);
2768
- }
2769
- if (!options.isolated) await writeManifest(config.root, generated);
2770
- const tables = snapshot.extras.tables.filter((table) => config.schemas.includes(table.schema)).length;
2771
- const changes = [...written.map((path) => ` ${path}`), ...removed.map((path) => ` ${path} (removed, no longer generated)`)];
2772
- return {
2773
- code: 0,
2774
- output: `${changes.length === 0 ? `No changes (${tables} tables).` : `Generated ${tables} tables:\n${changes.join("\n")}`}${notice}`,
2775
- data: {
2776
- tables,
2777
- written,
2778
- removed,
2779
- warnings
2780
- }
2781
- };
2782
- }
2783
- /** Where to read the schema from, shared by gen, introspect and doctor. */
2784
- const SOURCE_ARGS = {
2785
- snapshot: {
2786
- type: "string",
2787
- description: "Read a saved snapshot instead of the database",
2788
- valueHint: "file"
2789
- },
2790
- "db-url-stdin": {
2791
- type: "boolean",
2792
- description: "Read the connection string from stdin instead of $DATABASE_URL or the config"
2793
- },
2794
- "project-ref": {
2795
- type: "string",
2796
- description: "Read a hosted project through the Management API",
2797
- valueHint: "ref"
2798
- }
2799
- };
2800
- async function sourceArgs(args, io) {
2801
- const snapshotPath = args.snapshot;
2802
- const dbUrl = await stdinDatabaseUrl(args["db-url-stdin"], io);
2803
- const projectRef = args["project-ref"];
2804
- return {
2805
- ...snapshotPath ? { snapshotPath } : {},
2806
- ...dbUrl ? { dbUrl } : {},
2807
- ...projectRef ? { projectRef } : {}
2808
- };
2809
- }
2810
- /** The files `gen --metadata` can write to stdout. */
2811
- const EMITS = [
2812
- "schema",
2813
- "types",
2814
- "zod",
2815
- "valibot",
2816
- "json-schema"
2817
- ];
2818
- const isEmit = (value) => EMITS.some((emit) => emit === value);
2819
- /** The configured generator for an `--emit` target, or one with its defaults. */
2820
- function emitGenerator(config, emit) {
2821
- const configured = config.generators.find((generator) => generator.name === emit);
2822
- switch (emit) {
2823
- case "schema":
2824
- case "types": return;
2825
- case "zod": return configured ?? zod();
2826
- case "valibot": return configured ?? valibot();
2827
- case "json-schema": return configured ?? jsonSchema();
2828
- default: throw new Error(`unknown --emit ${String(emit)}`);
2829
- }
2830
- }
2831
- /**
2832
- * The one file `gen --metadata` prints: the `defineSchema` module with its
2833
- * metadata inlined, `database.types.ts`, or one generator's output.
2834
- */
2835
- async function renderEmit(config, snapshot, emit) {
2836
- const generator = emitGenerator(config, emit);
2837
- const { files, warnings } = await render({
2838
- ...config,
2839
- generators: generator ? [generator] : []
2840
- }, snapshot, { inlineMeta: emit === "schema" });
2841
- const path = emit === "schema" ? config.output : emit === "types" ? config.databaseTypesOutput : void 0;
2842
- const own = /* @__PURE__ */ new Set([
2843
- config.databaseTypesOutput,
2844
- config.output,
2845
- ...Object.values(metaPaths(config.output))
2846
- ]);
2847
- const picked = path === void 0 ? files.filter((file) => !own.has(file.path)) : files.filter((file) => file.path === path);
2848
- const [file] = picked;
2849
- if (!file || picked.length > 1) throw new Error(`--emit ${emit} expects one file, and the generator wrote ${picked.length}. Pass --out <dir> to write them all.`);
2850
- return {
2851
- files: picked,
2852
- warnings,
2853
- contents: file.contents
2854
- };
2855
- }
2856
- /**
2857
- * Reads `--metadata <path|->` (a file relative to `cwd`, or stdin for `-`)
2858
- * into a snapshot. Throws `MetadataRejectedError` for a document that can't
2859
- * be read or that `parseMetadataDocument` refuses.
2860
- */
2861
- async function readMetadataSnapshot(source, cwd, io) {
2862
- let text;
2863
- try {
2864
- if (source !== "-") text = await readFile(resolve(cwd, source), "utf8");
2865
- else if (io.stdin) text = await io.stdin();
2866
- else throw new Error("there is no stdin to read");
2867
- } catch (cause) {
2868
- throw new MetadataRejectedError(`Could not read ${source === "-" ? "stdin" : source}: ${cause instanceof Error ? cause.message : String(cause)}`);
2869
- }
2870
- return fromMetadata(await parseMetadataDocument(text));
2871
- }
2872
- /**
2873
- * `gen --metadata`: the out-of-process generator contract of
2874
- * `@supabase/typegen`. Without `--out` it prints one file on stdout and
2875
- * everything else on stderr; with `--out` it writes the usual files there.
2876
- */
2877
- async function runMetadataGen(options) {
2878
- const { config, io } = options;
2879
- const emit = options.emit ?? "schema";
2880
- if (!isEmit(emit)) return {
2881
- code: 2,
2882
- error: `--emit must be one of ${EMITS.join(", ")}, got "${emit}"`
2883
- };
2884
- if (options.out !== void 0 && options.emit !== void 0) return {
2885
- code: 2,
2886
- error: "--emit picks the one file gen prints; --out writes them all. Pass one of them."
2887
- };
2888
- if (options.out === void 0 && options.check) return {
2889
- code: 2,
2890
- error: "--check with --metadata needs --out <dir>"
2891
- };
2892
- if (options.out === void 0 && options.json) return {
2893
- code: 2,
2894
- error: "--metadata prints the generated code on stdout, so --json has nothing to print. Pass --out <dir> for the JSON summary."
2895
- };
2896
- let snapshot;
2897
- try {
2898
- snapshot = await readMetadataSnapshot(options.metadata, options.cwd, io);
2899
- } catch (cause) {
2900
- if (cause instanceof MetadataRejectedError) return {
2901
- code: 65,
2902
- error: cause.message
2903
- };
2904
- throw cause;
2905
- }
2906
- if (options.out !== void 0) {
2907
- const dir = relative(config.root, resolve(options.cwd, options.out));
2908
- const into = (path) => join(dir, basename(path)).split(sep).join("/");
2909
- return runGen({
2910
- config: {
2911
- ...config,
2912
- output: into(config.output),
2913
- databaseTypesOutput: into(config.databaseTypesOutput)
2914
- },
2915
- env: options.env,
2916
- check: options.check,
2917
- snapshot,
2918
- isolated: true,
2919
- ...options.paint ? { paint: options.paint } : {}
2920
- });
2921
- }
2922
- const refused = refuseRowConditionedBuckets(config);
2923
- if (refused) return refused;
2924
- const { contents, warnings } = await renderEmit(config, snapshot, emit);
2925
- io.stdout(contents);
2926
- const notices = await generationNotices(snapshot, warnings);
2927
- const shown = emit === "types" ? notices : notices.filter((line) => line !== UNFORMATTED);
2928
- for (const line of shown) io.stderr(`${line}\n`);
2929
- return { code: 0 };
2930
- }
2931
- const ARGS = {
2932
- metadata: {
2933
- type: "string",
2934
- description: "Read a GeneratorMetadata document (- for stdin) and print one file on stdout",
2935
- valueHint: "path|-"
2936
- },
2937
- emit: {
2938
- type: "string",
2939
- description: `With --metadata, the file to print: ${EMITS.join(", ")}. Defaults to schema`,
2940
- valueHint: "file"
2941
- },
2942
- out: {
2943
- type: "string",
2944
- description: "With --metadata, write every generated file into this directory instead of printing one",
2945
- valueHint: "dir"
2946
- },
2947
- check: {
2948
- type: "boolean",
2949
- description: "Fail when a generated file is out of date"
2950
- },
2951
- watch: {
2952
- type: "boolean",
2953
- description: "Regenerate whenever the schema or the config file changes"
2954
- },
2955
- interval: {
2956
- type: "string",
2957
- description: "Milliseconds between checks in --watch. Defaults to 2000",
2958
- valueHint: "ms"
2959
- },
2960
- ...SOURCE_ARGS
2961
- };
2962
- const sleep = (ms, signal) => setTimeout(ms, void 0, signal ? { signal } : {}).catch(() => void 0);
2963
- /**
2964
- * Reads the schema when it may have changed. Returns the new change marker (the
2965
- * catalog fingerprint, or the snapshot itself when the source has none) and
2966
- * the snapshot, or no snapshot when the fingerprint still matches `last`.
2967
- */
2968
- async function poll(options, db, last) {
2969
- const fingerprint = db ? await catalogFingerprint(db.queryable).catch(() => void 0) : void 0;
2970
- if (fingerprint !== void 0 && fingerprint === last) return { marker: last };
2971
- const snapshot = await loadSnapshot(options.config, options.env, options, void 0, db ? () => Promise.resolve(db) : void 0);
2972
- const marker = fingerprint ?? JSON.stringify(snapshot);
2973
- return marker === last ? { marker } : {
2974
- marker,
2975
- snapshot
2976
- };
2977
- }
2978
- const regenerate = (options, snapshot) => runGen({
2979
- ...options,
2980
- snapshot
2981
- }).catch((cause) => ({
2982
- code: 1,
2983
- error: cause instanceof Error ? cause.message : String(cause)
2984
- }));
2985
- const modified = (file) => file ? stat(file).then((stats) => stats.mtimeMs, () => void 0) : Promise.resolve(void 0);
2986
- /**
2987
- * Regenerates whenever the schema or the config file changes. A database
2988
- * source keeps one connection open and polls the catalog fingerprint, so an
2989
- * unchanged schema costs one small query per interval; a source without a
2990
- * fingerprint is introspected each time and compared. A changed config file
2991
- * is loaded again and forces a run. A failed run is retried every interval
2992
- * until it succeeds, and the same error is printed once.
2993
- */
2994
- async function watch(initial, interval, { io, signal, configFile, reloadConfig }) {
2995
- let options = initial;
2996
- let last = "";
2997
- let reported = "";
2998
- let stamp = await modified(configFile);
2999
- let db;
3000
- const aborted = () => signal?.aborted ?? false;
3001
- const report = (message) => {
3002
- if (message !== reported) io.stderr(`${message}\n`);
3003
- reported = message;
3004
- };
3005
- const closeDb = async () => {
3006
- await db?.close().catch(() => void 0);
3007
- db = void 0;
3008
- };
3009
- try {
3010
- while (!aborted()) {
3011
- const changed = await modified(configFile);
3012
- if (reloadConfig && changed !== stamp) try {
3013
- options = {
3014
- ...options,
3015
- config: await reloadConfig()
3016
- };
3017
- stamp = changed;
3018
- last = "";
3019
- await closeDb();
3020
- } catch (cause) {
3021
- report(cause instanceof Error ? cause.message : String(cause));
3022
- await sleep(interval, signal);
3023
- continue;
3024
- }
3025
- let polled;
3026
- try {
3027
- db ??= snapshotFile(options.config, options) === void 0 ? await openSource(options.config, options.env, options) : void 0;
3028
- polled = await poll(options, db, last);
3029
- } catch (cause) {
3030
- report(cause instanceof Error ? cause.message : String(cause));
3031
- await closeDb();
3032
- }
3033
- const result = polled?.snapshot ? await regenerate(options, polled.snapshot) : void 0;
3034
- if (result && result.code !== 0) report(result.error ?? `gen exited with code ${result.code}`);
3035
- else if (polled) {
3036
- if (result?.output) io.stdout(`${result.output}\n`);
3037
- last = polled.marker;
3038
- reported = "";
3039
- }
3040
- await sleep(interval, signal);
3041
- }
3042
- } finally {
3043
- await closeDb();
3044
- }
3045
- return { code: 0 };
3046
- }
3047
- const genCommand = defineCliCommand({
3048
- meta: {
3049
- name: "gen",
3050
- description: "Writes database.types.ts, generated.ts and its metadata module from the database"
3051
- },
3052
- args: ARGS,
3053
- run: async (args, context) => {
3054
- if (args.metadata !== void 0) {
3055
- const conflicting = [
3056
- ...args.watch === true ? ["--watch"] : [],
3057
- ...args.snapshot === void 0 ? [] : ["--snapshot"],
3058
- ...args["db-url-stdin"] === true ? ["--db-url-stdin"] : [],
3059
- ...args["project-ref"] === void 0 ? [] : ["--project-ref"]
3060
- ];
3061
- if (conflicting.length > 0) return {
3062
- code: 2,
3063
- error: `--metadata reads the schema from the document, so it can't be combined with ${conflicting.join(", ")}`
3064
- };
3065
- return runMetadataGen({
3066
- config: context.config,
3067
- env: context.env,
3068
- cwd: context.cwd,
3069
- io: context.io,
3070
- metadata: args.metadata,
3071
- check: args.check === true,
3072
- json: context.json,
3073
- paint: painter(context.io.color),
3074
- ...args.emit === void 0 ? {} : { emit: args.emit },
3075
- ...args.out === void 0 ? {} : { out: args.out }
3076
- });
3077
- }
3078
- if (args.emit !== void 0 || args.out !== void 0) return {
3079
- code: 2,
3080
- error: `${args.emit === void 0 ? "--out" : "--emit"} only applies with --metadata`
3081
- };
3082
- const options = {
3083
- config: context.config,
3084
- env: context.env,
3085
- check: args.check === true,
3086
- paint: painter(context.io.color),
3087
- ...await sourceArgs(args, context.io),
3088
- ...context.signal ? { signal: context.signal } : {},
3089
- cache: true
3090
- };
3091
- const interval = Number(args.interval ?? 2e3);
3092
- if (!Number.isFinite(interval) || interval <= 0) return {
3093
- code: 2,
3094
- error: `--interval must be a positive number of milliseconds, got "${args.interval}"`
3095
- };
3096
- return args.watch === true ? watch(options, interval, context) : withSpinner(context.io.prompts, "Generating from the schema", () => runGen(options));
3097
- }
3098
- });
3099
- //#endregion
3100
- export { exposed as A, MetadataRejectedError as C, accessModule as D, AUTHORIZATION_RULES as E, qualified as F, tableObject as I, toCatalog as L, lineOf as M, permissionCatalogKeys as N, entitlementsModule as O, policyObject as P, configFor as S, serializeGenerator as T, METADATA_GAPS_TEXT as _, renderFiles as a, emitModule as b, loadSnapshot as c, parseSnapshot as d, serializeSnapshot as f, pgSource as g, managementSource as h, render as i, exposedSchemas as j, catalogOf as k, managementTarget as l, introspect as m, genCommand as n, runGen as o, snapshotFile as p, readMetadataSnapshot as r, sourceArgs as s, SOURCE_ARGS as t, openSource as u, CACHE_DIR as v, restrictSchemas as w, buildModel as x, GENERATED_HEADER as y };