better-supabase 0.9.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/{access-sql-DUSSMaC3.js → access-sql-CTJPHjCL.js} +1 -1
- package/dist/{actor-KHDOKGb1.js → actor-CAL8mMih.js} +1 -1
- package/dist/{adapter-CEjmtazZ.js → adapter-B2WRsRIg.js} +29 -15
- package/dist/{agents-BCNhIxVZ.d.ts → agents-CbUIrH-w.d.ts} +7 -7
- package/dist/{ai-cache-Dps7aRu1.d.ts → ai-cache-BdeJKlrV.d.ts} +5 -5
- package/dist/{ai-cache-zeUL94pB.js → ai-cache-CLninP-F.js} +2 -2
- package/dist/{ai-chat-3GBSlFR4.d.ts → ai-chat-D-2MH1sU.d.ts} +7 -7
- package/dist/{ai-files-D2_9YLjF.js → ai-files-DXbgWA5M.js} +6 -6
- package/dist/ai-sdk/agents/index.d.ts +6 -6
- package/dist/ai-sdk/agents/index.js +2 -2
- package/dist/ai-sdk/batches/index.d.ts +4 -4
- package/dist/ai-sdk/batches/index.js +4 -4
- package/dist/ai-sdk/cache/index.d.ts +2 -2
- package/dist/ai-sdk/cache/index.js +1 -1
- package/dist/ai-sdk/chat/index.d.ts +1 -1
- package/dist/ai-sdk/chat/index.js +5 -5
- package/dist/ai-sdk/embeddings/index.d.ts +2 -2
- package/dist/ai-sdk/files/index.d.ts +2 -2
- package/dist/ai-sdk/files/index.js +4 -4
- package/dist/ai-sdk/index.d.ts +6 -6
- package/dist/ai-sdk/index.js +2 -2
- package/dist/ai-sdk/mcp/index.d.ts +4 -4
- package/dist/ai-sdk/mcp/index.js +4 -4
- package/dist/ai-sdk/memory/index.d.ts +3 -3
- package/dist/ai-sdk/workflow/index.d.ts +4 -4
- package/dist/ai-sdk/workflow/index.js +6 -6
- package/dist/{ai-tasks-Ih5oHfyj.d.ts → ai-tasks-BJJChl-D.d.ts} +8 -8
- package/dist/{announcements-BHCzraR6.js → announcements-BNxTW5HJ.js} +4 -4
- package/dist/{api-CFjuYKFY.js → api-C43_FYDp.js} +1 -1
- package/dist/{api-TG3jE5aO.d.ts → api-DoWK3dTw.d.ts} +6 -6
- package/dist/{api-keys-BEQatEUW.js → api-keys-BSXwI2jF.js} +6 -6
- package/dist/{api-keys-BYoGCM9p.d.ts → api-keys-qnM63qjS.d.ts} +7 -7
- package/dist/{app-tables-BGl5_U2x.js → app-tables-BRjMcWhW.js} +248 -13
- package/dist/app-tables-BrMBjyuq.d.ts +35 -0
- package/dist/{approvals-a2KmioBh.d.ts → approvals-CRZtzxNt.d.ts} +7 -7
- package/dist/arazzo/index.d.ts +2 -2
- package/dist/arazzo/index.js +2 -2
- package/dist/{assistant-Bf2cA6RO.d.ts → assistant-DZsHsYIx.d.ts} +4 -4
- package/dist/astro/index.d.ts +12 -12
- package/dist/astro/index.js +5 -5
- package/dist/asyncapi/index.d.ts +1 -1
- package/dist/asyncapi/index.js +2 -2
- package/dist/{attachments-DAj2Yp95.js → attachments-Bk3tyeUF.js} +6 -6
- package/dist/{audit-log-BMMuGPdP.js → audit-log-ovUlF4Mk.js} +8 -8
- package/dist/auth-module-DbZv2WrR.js +10 -0
- package/dist/{auth-reply-DUCwb8YO.js → auth-reply-Daq72lY4.js} +2 -2
- package/dist/{authorization-DpRfs6Wx.d.ts → authorization-ClWBcXJi.d.ts} +47 -3
- package/dist/{authorization-hooks-DkmrnDX7.d.ts → authorization-hooks-mLi894KH.d.ts} +2 -2
- package/dist/{authorizer-DH7DjkL3.js → authorizer-B3yyCVUF.js} +2 -2
- package/dist/{base64-BmeCBgGo.js → base64-D4aqdnDR.js} +4 -4
- package/dist/better-result/index.d.ts +5 -5
- package/dist/better-result/index.js +1 -1
- package/dist/{bind-a7sUgvf4.d.ts → bind-CTNKpBM6.d.ts} +4 -4
- package/dist/{block-fields-ffD6Gxe4.js → block-fields-Bv1hV855.js} +3 -3
- package/dist/{block-fields-5UA84ZUg.d.ts → block-fields-DnaDbgZS.d.ts} +2 -2
- package/dist/{block-helpers-C86hPEjI.d.ts → block-helpers-CjcQM1yA.d.ts} +2 -2
- package/dist/{block-helpers-CfG_MvDR.js → block-helpers-DkVZNDrj.js} +4 -4
- package/dist/{block-hooks-BsXncUlZ.js → block-hooks-C22vuIUd.js} +3 -3
- package/dist/{block-hooks-BLPWD3Jt.d.ts → block-hooks-DcPJHztl.d.ts} +3 -3
- package/dist/{block-transport-DaGGXjIw.d.ts → block-transport-DezJPPA0.d.ts} +2 -2
- package/dist/{block-transport-G4t1umrR.js → block-transport-J7ZepTq2.js} +1 -1
- package/dist/blocks/access-requests/index.d.ts +8 -8
- package/dist/blocks/access-requests/index.js +7 -7
- package/dist/blocks/agents/index.d.ts +4 -4
- package/dist/blocks/agents/index.js +6 -6
- package/dist/blocks/ai-cache/index.d.ts +3 -3
- package/dist/blocks/ai-cache/index.js +3 -3
- package/dist/blocks/ai-chat/index.d.ts +5 -5
- package/dist/blocks/ai-chat/index.js +4 -4
- package/dist/blocks/ai-chat/react/index.d.ts +2 -2
- package/dist/blocks/ai-chat/react/index.js +2 -2
- package/dist/blocks/ai-chat/solid/index.d.ts +2 -2
- package/dist/blocks/ai-chat/solid/index.js +1 -1
- package/dist/blocks/ai-chat/svelte/index.d.ts +2 -2
- package/dist/blocks/ai-chat/svelte/index.js +1 -1
- package/dist/blocks/ai-chat/vue/index.d.ts +2 -2
- package/dist/blocks/ai-chat/vue/index.js +1 -1
- package/dist/blocks/ai-files/index.d.ts +5 -5
- package/dist/blocks/ai-files/index.js +3 -3
- package/dist/blocks/ai-providers/index.d.ts +4 -4
- package/dist/blocks/ai-providers/index.js +8 -8
- package/dist/blocks/ai-tasks/index.d.ts +3 -3
- package/dist/blocks/ai-tasks/index.js +9 -9
- package/dist/blocks/announcements/index.d.ts +4 -4
- package/dist/blocks/announcements/index.js +3 -3
- package/dist/blocks/announcements/react/index.d.ts +1 -1
- package/dist/blocks/announcements/react/index.js +2 -2
- package/dist/blocks/announcements/solid/index.d.ts +2 -2
- package/dist/blocks/announcements/svelte/index.d.ts +2 -2
- package/dist/blocks/announcements/vue/index.d.ts +2 -2
- package/dist/blocks/api-keys/index.d.ts +7 -7
- package/dist/blocks/api-keys/index.js +6 -6
- package/dist/blocks/api-keys/react/index.d.ts +1 -1
- package/dist/blocks/api-keys/react/index.js +3 -3
- package/dist/blocks/api-keys/react/server.d.ts +1 -1
- package/dist/blocks/api-keys/solid/index.d.ts +2 -2
- package/dist/blocks/api-keys/solid/index.js +1 -1
- package/dist/blocks/api-keys/svelte/index.d.ts +2 -2
- package/dist/blocks/api-keys/svelte/index.js +1 -1
- package/dist/blocks/api-keys/vue/index.d.ts +2 -2
- package/dist/blocks/api-keys/vue/index.js +1 -1
- package/dist/blocks/approvals/index.d.ts +4 -4
- package/dist/blocks/approvals/index.js +7 -7
- package/dist/blocks/attachments/index.d.ts +4 -4
- package/dist/blocks/attachments/index.js +3 -3
- package/dist/blocks/audit/index.d.ts +6 -6
- package/dist/blocks/audit/index.js +7 -7
- package/dist/blocks/audit/react/index.d.ts +1 -1
- package/dist/blocks/audit/react/index.js +2 -2
- package/dist/blocks/audit/react/server.d.ts +1 -1
- package/dist/blocks/audit/solid/index.d.ts +2 -2
- package/dist/blocks/audit/svelte/index.d.ts +2 -2
- package/dist/blocks/audit/vue/index.d.ts +2 -2
- package/dist/blocks/billing/index.d.ts +26 -10
- package/dist/blocks/billing/index.js +43 -10
- package/dist/blocks/billing/react/index.d.ts +2 -2
- package/dist/blocks/billing/react/index.js +1 -1
- package/dist/blocks/billing/react/server.d.ts +1 -1
- package/dist/blocks/billing/solid/index.d.ts +2 -2
- package/dist/blocks/billing/solid/index.js +1 -1
- package/dist/blocks/billing/svelte/index.d.ts +2 -2
- package/dist/blocks/billing/svelte/index.js +1 -1
- package/dist/blocks/billing/vue/index.d.ts +2 -2
- package/dist/blocks/billing/vue/index.js +1 -1
- package/dist/blocks/bookings/index.d.ts +3 -3
- package/dist/blocks/bookings/index.js +3 -3
- package/dist/blocks/bookings/react/index.d.ts +1 -1
- package/dist/blocks/bookings/react/index.js +3 -3
- package/dist/blocks/bookings/solid/index.d.ts +2 -2
- package/dist/blocks/bookings/solid/index.js +1 -1
- package/dist/blocks/bookings/svelte/index.d.ts +2 -2
- package/dist/blocks/bookings/svelte/index.js +1 -1
- package/dist/blocks/bookings/vue/index.d.ts +2 -2
- package/dist/blocks/bookings/vue/index.js +1 -1
- package/dist/blocks/bulk/index.d.ts +10 -6
- package/dist/blocks/bulk/index.js +4 -4
- package/dist/blocks/calendar/index.d.ts +3 -3
- package/dist/blocks/calendar/index.js +3 -3
- package/dist/blocks/calendar/react/index.d.ts +1 -1
- package/dist/blocks/calendar/react/index.js +3 -3
- package/dist/blocks/calendar/solid/index.d.ts +2 -2
- package/dist/blocks/calendar/solid/index.js +1 -1
- package/dist/blocks/calendar/svelte/index.d.ts +2 -2
- package/dist/blocks/calendar/svelte/index.js +1 -1
- package/dist/blocks/calendar/vue/index.d.ts +2 -2
- package/dist/blocks/calendar/vue/index.js +1 -1
- package/dist/blocks/catalog/index.d.ts +11 -11
- package/dist/blocks/catalog/index.js +9 -9
- package/dist/blocks/collections/index.d.ts +10 -10
- package/dist/blocks/collections/index.js +7 -7
- package/dist/blocks/comments/index.d.ts +4 -4
- package/dist/blocks/comments/index.js +4 -4
- package/dist/blocks/comments/react/index.d.ts +1 -1
- package/dist/blocks/comments/react/index.js +3 -3
- package/dist/blocks/comments/react/server.d.ts +1 -1
- package/dist/blocks/comments/solid/index.d.ts +2 -2
- package/dist/blocks/comments/solid/index.js +1 -1
- package/dist/blocks/comments/svelte/index.d.ts +2 -2
- package/dist/blocks/comments/svelte/index.js +1 -1
- package/dist/blocks/comments/vue/index.d.ts +2 -2
- package/dist/blocks/comments/vue/index.js +1 -1
- package/dist/blocks/connectors/index.d.ts +4 -4
- package/dist/blocks/connectors/index.js +8 -8
- package/dist/blocks/custom-fields/index.d.ts +6 -6
- package/dist/blocks/custom-fields/index.js +5 -5
- package/dist/blocks/data-lifecycle/index.d.ts +9 -9
- package/dist/blocks/data-lifecycle/index.js +8 -8
- package/dist/blocks/deals/index.d.ts +10 -10
- package/dist/blocks/deals/index.js +10 -10
- package/dist/blocks/documents/index.d.ts +4 -4
- package/dist/blocks/documents/index.js +5 -5
- package/dist/blocks/domains/index.d.ts +7 -7
- package/dist/blocks/domains/index.js +7 -7
- package/dist/blocks/drive/index.d.ts +10 -10
- package/dist/blocks/drive/index.js +8 -8
- package/dist/blocks/employees/index.d.ts +10 -10
- package/dist/blocks/employees/index.js +9 -9
- package/dist/blocks/engagements/index.d.ts +9 -9
- package/dist/blocks/engagements/index.js +6 -6
- package/dist/blocks/entitlements/index.d.ts +7 -7
- package/dist/blocks/entitlements/index.js +2 -2
- package/dist/blocks/entitlements/react/index.d.ts +2 -2
- package/dist/blocks/entitlements/solid/index.d.ts +2 -2
- package/dist/blocks/entitlements/svelte/index.d.ts +2 -2
- package/dist/blocks/entitlements/vue/index.d.ts +2 -2
- package/dist/blocks/flags/index.d.ts +8 -8
- package/dist/blocks/flags/index.js +7 -7
- package/dist/blocks/forms/index.d.ts +9 -9
- package/dist/blocks/forms/index.js +6 -6
- package/dist/blocks/forms/react/index.d.ts +1 -1
- package/dist/blocks/forms/solid/index.d.ts +2 -2
- package/dist/blocks/forms/svelte/index.d.ts +2 -2
- package/dist/blocks/forms/vue/index.d.ts +2 -2
- package/dist/blocks/hiring/index.d.ts +9 -9
- package/dist/blocks/hiring/index.js +7 -7
- package/dist/blocks/identities/index.d.ts +6 -6
- package/dist/blocks/identities/index.js +4 -4
- package/dist/blocks/imports/index.d.ts +75 -7
- package/dist/blocks/imports/index.js +111 -7
- package/dist/blocks/inbox/index.d.ts +5 -5
- package/dist/blocks/inbox/index.js +4 -4
- package/dist/blocks/inbox/react/index.d.ts +2 -2
- package/dist/blocks/inbox/react/server.d.ts +2 -2
- package/dist/blocks/inbox/solid/index.d.ts +2 -2
- package/dist/blocks/inbox/svelte/index.d.ts +2 -2
- package/dist/blocks/inbox/vue/index.d.ts +2 -2
- package/dist/blocks/index.d.ts +28 -9
- package/dist/blocks/index.js +5 -5
- package/dist/blocks/inventory/index.d.ts +9 -9
- package/dist/blocks/inventory/index.js +7 -7
- package/dist/blocks/invoices/index.d.ts +9 -9
- package/dist/blocks/invoices/index.js +9 -9
- package/dist/blocks/jobs/index.d.ts +61 -11
- package/dist/blocks/jobs/index.js +127 -14
- package/dist/blocks/knowledge/index.d.ts +3 -3
- package/dist/blocks/knowledge/index.js +3 -3
- package/dist/blocks/leave/index.d.ts +8 -8
- package/dist/blocks/leave/index.js +6 -6
- package/dist/blocks/memory/index.d.ts +4 -4
- package/dist/blocks/memory/index.js +7 -7
- package/dist/blocks/metrics/index.d.ts +7 -7
- package/dist/blocks/metrics/index.js +7 -7
- package/dist/blocks/mfa/index.d.ts +2 -2
- package/dist/blocks/mfa/index.js +1 -1
- package/dist/blocks/mfa/react/index.d.ts +1 -1
- package/dist/blocks/mfa/react/index.js +1 -1
- package/dist/blocks/mfa/react/server.d.ts +1 -1
- package/dist/blocks/mfa/react/server.js +1 -1
- package/dist/blocks/mfa/solid/index.d.ts +2 -2
- package/dist/blocks/mfa/solid/index.js +1 -1
- package/dist/blocks/mfa/svelte/index.d.ts +2 -2
- package/dist/blocks/mfa/svelte/index.js +1 -1
- package/dist/blocks/mfa/vue/index.d.ts +2 -2
- package/dist/blocks/mfa/vue/index.js +1 -1
- package/dist/blocks/notifications/index.d.ts +13 -13
- package/dist/blocks/notifications/index.js +13 -13
- package/dist/blocks/notifications/react/index.d.ts +1 -1
- package/dist/blocks/notifications/react/server.d.ts +1 -1
- package/dist/blocks/notifications/solid/index.d.ts +2 -2
- package/dist/blocks/notifications/svelte/index.d.ts +2 -2
- package/dist/blocks/notifications/vue/index.d.ts +2 -2
- package/dist/blocks/number-sequences/index.d.ts +11 -5
- package/dist/blocks/number-sequences/index.js +22 -11
- package/dist/blocks/oauth-server/index.d.ts +28 -8
- package/dist/blocks/oauth-server/index.js +24 -15
- package/dist/blocks/onboarding/index.d.ts +3 -3
- package/dist/blocks/onboarding/index.js +3 -3
- package/dist/blocks/onboarding/react/index.d.ts +1 -1
- package/dist/blocks/onboarding/react/index.js +2 -2
- package/dist/blocks/onboarding/react/server.d.ts +1 -1
- package/dist/blocks/onboarding/solid/index.d.ts +2 -2
- package/dist/blocks/onboarding/svelte/index.d.ts +2 -2
- package/dist/blocks/onboarding/vue/index.d.ts +2 -2
- package/dist/blocks/orders/index.d.ts +12 -12
- package/dist/blocks/orders/index.js +12 -12
- package/dist/blocks/organizations/index.d.ts +5 -5
- package/dist/blocks/organizations/index.js +5 -5
- package/dist/blocks/organizations/react/index.d.ts +1 -1
- package/dist/blocks/organizations/react/index.js +3 -3
- package/dist/blocks/organizations/react/server.d.ts +1 -1
- package/dist/blocks/organizations/solid/index.d.ts +2 -2
- package/dist/blocks/organizations/solid/index.js +1 -1
- package/dist/blocks/organizations/svelte/index.d.ts +2 -2
- package/dist/blocks/organizations/svelte/index.js +1 -1
- package/dist/blocks/organizations/vue/index.d.ts +2 -2
- package/dist/blocks/organizations/vue/index.js +1 -1
- package/dist/blocks/outbox/index.d.ts +4 -4
- package/dist/blocks/outbox/index.js +6 -6
- package/dist/blocks/parties/index.d.ts +10 -10
- package/dist/blocks/parties/index.js +5 -5
- package/dist/blocks/pipelines/index.d.ts +10 -10
- package/dist/blocks/pipelines/index.js +8 -8
- package/dist/blocks/profiles/index.d.ts +7 -7
- package/dist/blocks/profiles/index.js +6 -6
- package/dist/blocks/promotions/index.d.ts +9 -9
- package/dist/blocks/promotions/index.js +8 -8
- package/dist/blocks/push/index.d.ts +9 -9
- package/dist/blocks/push/index.js +5 -5
- package/dist/blocks/quotes/index.d.ts +9 -9
- package/dist/blocks/quotes/index.js +9 -9
- package/dist/blocks/rank/index.d.ts +6 -6
- package/dist/blocks/rank/index.js +4 -4
- package/dist/blocks/reactions/index.d.ts +4 -4
- package/dist/blocks/reactions/index.js +3 -3
- package/dist/blocks/reactions/react/index.d.ts +1 -1
- package/dist/blocks/reactions/react/index.js +2 -2
- package/dist/blocks/reactions/solid/index.d.ts +2 -2
- package/dist/blocks/reactions/solid/index.js +1 -1
- package/dist/blocks/reactions/svelte/index.d.ts +2 -2
- package/dist/blocks/reactions/svelte/index.js +1 -1
- package/dist/blocks/reactions/vue/index.d.ts +2 -2
- package/dist/blocks/reactions/vue/index.js +1 -1
- package/dist/blocks/relations/index.d.ts +8 -8
- package/dist/blocks/relations/index.js +5 -5
- package/dist/blocks/reminders/index.d.ts +10 -10
- package/dist/blocks/reminders/index.js +9 -9
- package/dist/blocks/reviews/index.d.ts +8 -8
- package/dist/blocks/reviews/index.js +6 -6
- package/dist/blocks/rules/index.d.ts +75 -9
- package/dist/blocks/rules/index.js +117 -8
- package/dist/blocks/rules/react/index.d.ts +2 -2
- package/dist/blocks/rules/react/index.js +3 -3
- package/dist/blocks/rules/solid/index.d.ts +2 -2
- package/dist/blocks/rules/solid/index.js +1 -1
- package/dist/blocks/rules/svelte/index.d.ts +2 -2
- package/dist/blocks/rules/svelte/index.js +1 -1
- package/dist/blocks/rules/vue/index.d.ts +2 -2
- package/dist/blocks/rules/vue/index.js +1 -1
- package/dist/blocks/saved-views/index.d.ts +3 -3
- package/dist/blocks/saved-views/index.js +2 -2
- package/dist/blocks/saved-views/react/index.d.ts +1 -1
- package/dist/blocks/saved-views/react/index.js +1 -1
- package/dist/blocks/saved-views/react/server.d.ts +1 -1
- package/dist/blocks/saved-views/solid/index.d.ts +2 -2
- package/dist/blocks/saved-views/solid/index.js +1 -1
- package/dist/blocks/saved-views/svelte/index.d.ts +2 -2
- package/dist/blocks/saved-views/svelte/index.js +1 -1
- package/dist/blocks/saved-views/vue/index.d.ts +2 -2
- package/dist/blocks/saved-views/vue/index.js +1 -1
- package/dist/blocks/search/index.d.ts +4 -4
- package/dist/blocks/search/index.js +4 -4
- package/dist/blocks/search/react/index.d.ts +1 -1
- package/dist/blocks/search/react/index.js +2 -2
- package/dist/blocks/search/react/server.d.ts +1 -1
- package/dist/blocks/search/solid/index.d.ts +2 -2
- package/dist/blocks/search/svelte/index.d.ts +2 -2
- package/dist/blocks/search/vue/index.d.ts +2 -2
- package/dist/blocks/service-principals/index.d.ts +8 -8
- package/dist/blocks/service-principals/index.js +7 -7
- package/dist/blocks/sessions/index.d.ts +2 -2
- package/dist/blocks/sessions/index.js +2 -2
- package/dist/blocks/sessions/react/index.d.ts +1 -1
- package/dist/blocks/sessions/react/index.js +1 -1
- package/dist/blocks/sessions/react/server.d.ts +1 -1
- package/dist/blocks/sessions/solid/index.d.ts +2 -2
- package/dist/blocks/sessions/solid/index.js +1 -1
- package/dist/blocks/sessions/svelte/index.d.ts +2 -2
- package/dist/blocks/sessions/svelte/index.js +1 -1
- package/dist/blocks/sessions/vue/index.d.ts +2 -2
- package/dist/blocks/sessions/vue/index.js +1 -1
- package/dist/blocks/settings/index.d.ts +4 -4
- package/dist/blocks/settings/index.js +4 -4
- package/dist/blocks/settings/react/index.d.ts +1 -1
- package/dist/blocks/settings/react/index.js +3 -3
- package/dist/blocks/settings/react/server.d.ts +1 -1
- package/dist/blocks/settings/solid/index.d.ts +2 -2
- package/dist/blocks/settings/solid/index.js +1 -1
- package/dist/blocks/settings/svelte/index.d.ts +2 -2
- package/dist/blocks/settings/svelte/index.js +1 -1
- package/dist/blocks/settings/vue/index.d.ts +2 -2
- package/dist/blocks/settings/vue/index.js +1 -1
- package/dist/blocks/share-links/index.d.ts +15 -8
- package/dist/blocks/share-links/index.js +9 -6
- package/dist/blocks/shared-signals/index.d.ts +8 -8
- package/dist/blocks/shared-signals/index.js +8 -8
- package/dist/blocks/signing-keys/index.d.ts +5 -5
- package/dist/blocks/signing-keys/index.js +48 -22
- package/dist/blocks/sla/index.d.ts +9 -9
- package/dist/blocks/sla/index.js +6 -6
- package/dist/blocks/sso/index.d.ts +7 -7
- package/dist/blocks/sso/index.js +5 -5
- package/dist/blocks/state-machine/index.d.ts +5 -5
- package/dist/blocks/state-machine/index.js +3 -3
- package/dist/blocks/tags/index.d.ts +3 -3
- package/dist/blocks/tags/index.js +3 -3
- package/dist/blocks/tags/react/index.d.ts +1 -1
- package/dist/blocks/tags/react/index.js +3 -3
- package/dist/blocks/tags/react/server.d.ts +1 -1
- package/dist/blocks/tags/solid/index.d.ts +2 -2
- package/dist/blocks/tags/solid/index.js +1 -1
- package/dist/blocks/tags/svelte/index.d.ts +2 -2
- package/dist/blocks/tags/svelte/index.js +1 -1
- package/dist/blocks/tags/vue/index.d.ts +2 -2
- package/dist/blocks/tags/vue/index.js +1 -1
- package/dist/blocks/targets/index.d.ts +7 -7
- package/dist/blocks/targets/index.js +6 -6
- package/dist/blocks/teams/index.d.ts +7 -7
- package/dist/blocks/teams/index.js +4 -4
- package/dist/blocks/templates/index.d.ts +10 -10
- package/dist/blocks/templates/index.js +8 -8
- package/dist/blocks/time-tracking/index.d.ts +9 -9
- package/dist/blocks/time-tracking/index.js +9 -9
- package/dist/blocks/trash/index.d.ts +8 -8
- package/dist/blocks/trash/index.js +5 -5
- package/dist/blocks/undo/index.d.ts +4 -4
- package/dist/blocks/undo/index.js +2 -2
- package/dist/blocks/undo/react/index.d.ts +1 -1
- package/dist/blocks/undo/react/server.d.ts +1 -1
- package/dist/blocks/undo/solid/index.d.ts +2 -2
- package/dist/blocks/undo/svelte/index.d.ts +2 -2
- package/dist/blocks/undo/vue/index.d.ts +2 -2
- package/dist/blocks/usage/index.d.ts +4 -4
- package/dist/blocks/usage/index.js +3 -3
- package/dist/blocks/usage/react/index.d.ts +1 -1
- package/dist/blocks/usage/react/index.js +2 -2
- package/dist/blocks/usage/react/server.d.ts +1 -1
- package/dist/blocks/usage/solid/index.d.ts +2 -2
- package/dist/blocks/usage/svelte/index.d.ts +2 -2
- package/dist/blocks/usage/vue/index.d.ts +2 -2
- package/dist/blocks/vercel-marketplace/index.d.ts +193 -0
- package/dist/blocks/vercel-marketplace/index.js +300 -0
- package/dist/blocks/versions/index.d.ts +13 -9
- package/dist/blocks/versions/index.js +19 -14
- package/dist/blocks/waitlist/index.d.ts +9 -9
- package/dist/blocks/waitlist/index.js +6 -6
- package/dist/blocks/webhooks/index.d.ts +16 -16
- package/dist/blocks/webhooks/index.js +17 -17
- package/dist/blocks/work-items/index.d.ts +10 -10
- package/dist/blocks/work-items/index.js +7 -7
- package/dist/blocks/workflow-builder/index.d.ts +9 -9
- package/dist/blocks/workflow-builder/index.js +3 -3
- package/dist/blocks/workflow-builder/react/index.d.ts +2 -2
- package/dist/blocks/workflow-builder/react/index.js +3 -3
- package/dist/blocks/workflow-builder/solid/index.d.ts +2 -2
- package/dist/blocks/workflow-builder/svelte/index.d.ts +2 -2
- package/dist/blocks/workflow-builder/vue/index.d.ts +2 -2
- package/dist/blocks/workflows/index.d.ts +5 -5
- package/dist/blocks/workflows/index.js +2 -2
- package/dist/blocks/workflows/react/index.d.ts +2 -2
- package/dist/blocks/workflows/react/index.js +2 -2
- package/dist/blocks/workflows/solid/index.d.ts +2 -2
- package/dist/blocks/workflows/svelte/index.d.ts +2 -2
- package/dist/blocks/workflows/vue/index.d.ts +2 -2
- package/dist/{bookings-0XnhHNLM.js → bookings-DQ7P888X.js} +5 -5
- package/dist/{storage-api-Cx-1iWBd.d.ts → bucket-BBSNDFNH.d.ts} +219 -219
- package/dist/{build-Cx08LOT7.js → build-C-D_vn0U.js} +8 -3
- package/dist/{build-Cm0T5MVG.js → build-CT6SPZkI.js} +1 -1
- package/dist/{calendar-DcFrpSOy.js → calendar-eqyuQAoy.js} +7 -7
- package/dist/chat-sdk/index.d.ts +6 -6
- package/dist/chat-sdk/index.js +3 -3
- package/dist/chat-sdk/react/index.d.ts +2 -2
- package/dist/chat-sdk/react/server.d.ts +2 -2
- package/dist/cli/{add-B0zoJUYX.js → add-B5V6uokQ.js} +6 -6
- package/dist/cli/{add-Bd5M6uEZ.js → add-BcOHumvq.js} +2 -2
- package/dist/cli/add-DzRJEHzD.js +1 -0
- package/dist/cli/adopt-DDy50yz9.js +1 -0
- package/dist/cli/{adopt-CebmlHL-.js → adopt-Ht34C3QD.js} +28 -9
- package/dist/cli/{agent-CCt_aXpJ.js → agent-CCrTYK3W.js} +1 -1
- package/dist/cli/{apply-Dxk8AUNU.js → apply-4BmTvj2A.js} +40 -10
- package/dist/cli/bin.js +1 -1
- package/dist/cli/{blocks-Bzz326nn.js → blocks-bBI050w6.js} +1 -1
- package/dist/cli/{blocks-Dq25D80b.js → blocks-jIvPqPtw.js} +1 -1
- package/dist/cli/{cache-Cx6qlRDR.js → cache-CVJmPGpd.js} +9 -4
- package/dist/cli/{catalog-Di15TkM2.js → catalog-Cm6BtquM.js} +2 -1
- package/dist/cli/{codemod-woL4cVe0.js → codemod-vsknM1Ue.js} +2 -2
- package/dist/cli/{command-CK9Cn8HV.js → command-DLCZeHdo.js} +40 -0
- package/dist/cli/{completion-CWoDmFZr.js → completion-BAm8SwGQ.js} +2 -2
- package/dist/cli/{completion-BO5UK6bG.js → completion-CEZ-c3ja.js} +1 -1
- package/dist/cli/{completion-J3dqnNoW.js → completion-D2BObVth.js} +2 -2
- package/dist/cli/{config-CLHpTk9Y.js → config-C4e_RrmL.js} +54 -12
- package/dist/cli/{config-MuKY9kUj.js → config-CC5DXgKX.js} +1 -1
- package/dist/cli/{config-C1d-mbUA.js → config-CynctXbc.js} +1 -1
- package/dist/cli/db-BxMRcHrY.js +90 -0
- package/dist/cli/{detect-DYDUBLU4.js → detect-DQsVeBHg.js} +2 -2
- package/dist/cli/{doctor-SGw36h1D.js → doctor-D47sFjh9.js} +253 -376
- package/dist/cli/{emit-ZAYeh4Yn.js → emit-56LAG_Px.js} +32 -7
- package/dist/cli/{env-CVXvJoLP.js → env--JFvv45k.js} +3 -3
- package/dist/cli/{env-DJ4ZaJpe.js → env-B7TWPEt0.js} +1 -1
- package/dist/cli/{env-DMw_MBe5.js → env-C8R7Nf0a.js} +94 -2
- package/dist/cli/env-D-O91RK1.js +1 -0
- package/dist/cli/{gen-B344S1Oy.js → gen-D2E8osBE.js} +11 -11
- package/dist/cli/index.d.ts +8 -4
- package/dist/cli/index.js +10 -9
- package/dist/cli/{init-B1dL-RZL.js → init-Cx7DDAdQ.js} +15 -8
- package/dist/cli/{introspect-BPcFi8ow.js → introspect-Ck7aa6v0.js} +3 -3
- package/dist/cli/{keys-jsxCNJdz.js → keys-6ufnWeZl.js} +2 -2
- package/dist/cli/live-CLxJNC0r.js +329 -0
- package/dist/cli/mcp-BVWvEoKo.js +237 -0
- package/dist/cli/{metadata-CxBZo4KM.js → metadata-BRywyPvv.js} +2 -2
- package/dist/cli/migration-safety-DjVpz2D6.js +206 -0
- package/dist/cli/{module-migration-YFFdWC5X.js → module-migration-CPhuiY8C.js} +2 -2
- package/dist/cli/{moved-D9OT_Uyy.js → moved-BmtFuMK3.js} +1 -1
- package/dist/cli/{parse-DE59XyWt.js → parse-ksnw4phM.js} +1 -1
- package/dist/cli/{preset-DmcC4nWE.js → preset-B1o6KbFp.js} +1 -1
- package/dist/cli/{run-DaHfUUO9.js → run-Bb8Nn8Ax.js} +59 -70
- package/dist/cli/{run-CM_2g6KQ.js → run-nX5ffQM_.js} +44 -42
- package/dist/cli/{scaffold-CFdDq36-.js → scaffold-DcXr4z7M.js} +4 -4
- package/dist/cli/{scaffold-Dsjr7sOT.js → scaffold-fO-FJGoO.js} +1 -1
- package/dist/cli/{seed-DldDdXWO.js → seed-BmOC6_iz.js} +7 -6
- package/dist/cli/seed-C_BmN498.js +1 -0
- package/dist/cli/shared-DKLuA1Tp.js +145 -0
- package/dist/cli/{skills-v34NDb2D.js → skills-CUx7S0bk.js} +1 -1
- package/dist/cli/{snapshot-DAxLi4hO.js → snapshot-ClgWGd-b.js} +4 -4
- package/dist/cli/{source-args-0I9zylYy.js → source-args-BDiUhsH8.js} +8 -2
- package/dist/cli/{spec-CaaSOYZS.js → spec-CM7iyRnE.js} +5 -5
- package/dist/cli/{spec-De0cfceR.js → spec-DjHpWZJM.js} +1 -1
- package/dist/cli/{sql-0I1EQ3JG.js → sql-C4ymac2h.js} +2 -2
- package/dist/cli/{sql-DDLWwzh9.js → sql-ybcjbz20.js} +5 -5
- package/dist/cli/{stack-status-CRanl-CN.js → stack-status-Cb_D79ZR.js} +2 -2
- package/dist/cli/{supabase-toml-DjLgBYEo.js → supabase-toml-BC5sNVKU.js} +1 -1
- package/dist/cli/{sync-DFx-6t5n.js → sync-DBvknfOK.js} +2 -2
- package/dist/cli/{topics-GJuIDwlY.js → topics-BBE1-Vrg.js} +1 -1
- package/dist/cli/{version-DNRW4DAP.js → version-CUKjFbNd.js} +1 -1
- package/dist/cli/{write-BS6F3Yvz.js → write-VZljwoTB.js} +25 -7
- package/dist/client/index.d.ts +6 -6
- package/dist/client/index.js +4 -4
- package/dist/client/native/index.d.ts +6 -6
- package/dist/client/native/index.js +4 -4
- package/dist/{client-DjTRlN3a.d.ts → client-5YAtJjyT.d.ts} +2 -2
- package/dist/{client-BAcILZOf.d.ts → client-9ZOirdtr.d.ts} +9 -9
- package/dist/{client-CFdMJ1h9.d.ts → client-B4a7f5ma.d.ts} +8 -8
- package/dist/{client-BVZtq_rQ.d.ts → client-B9_8yzct.d.ts} +2 -2
- package/dist/{client-BOT2KVIp.js → client-BDO6i2Oe.js} +2 -2
- package/dist/{client-LLmgiCwJ.d.ts → client-BNy-K6XT.d.ts} +3 -3
- package/dist/{client-ClZ0D-if.d.ts → client-BXv09wO1.d.ts} +5 -5
- package/dist/{client-D5CZ2a34.d.ts → client-B_vHBwB6.d.ts} +12 -12
- package/dist/{client-Co6BPmvr.d.ts → client-Bovn6-M9.d.ts} +7 -7
- package/dist/{client-BxnLb9bz.d.ts → client-BqoYuTK3.d.ts} +3 -3
- package/dist/{client-VvY0K3wr.d.ts → client-C3rmP3b0.d.ts} +6 -6
- package/dist/{client-hyP_nS5R.d.ts → client-CBQ2TV0r.d.ts} +7 -7
- package/dist/{client-Lx3mlvKO.d.ts → client-CCGSn7m5.d.ts} +4 -4
- package/dist/{client-BUGIS__1.js → client-CFKONrrU.js} +6 -6
- package/dist/{client-CvITjt-9.js → client-CHR8IBNG.js} +10 -2
- package/dist/{client-CHmjaI0j.d.ts → client-CJT3xiuI.d.ts} +7 -7
- package/dist/{client-DdfSIZ3M.d.ts → client-CNh-pjkT.d.ts} +5 -5
- package/dist/{client-e-hFkLUf.d.ts → client-CXTDJCIs.d.ts} +3 -3
- package/dist/{client-CWs3X4g1.js → client-C_-NZRrg.js} +1 -1
- package/dist/{client-CilSKXNu.js → client-CcPxbHeT.js} +2 -2
- package/dist/{client-ysNShuJZ.d.ts → client-CeH7vd-g.d.ts} +2 -2
- package/dist/{client-PGRk3DGz.js → client-CosiUrUb.js} +1 -1
- package/dist/{client-DAHsEOVV.d.ts → client-CrZKZVbb.d.ts} +4 -4
- package/dist/{client-CiGjS6us.js → client-D7T7OLiw.js} +4 -4
- package/dist/{client-WHeWTNVL.d.ts → client-DLz68Qga.d.ts} +2 -2
- package/dist/{client-Cmensu7l.d.ts → client-DarDYaQj.d.ts} +9 -9
- package/dist/{client-CzI4QpG3.d.ts → client-DbxvLC9Y.d.ts} +2 -2
- package/dist/{client-Tc47rlSe.d.ts → client-Dft5Vq6m.d.ts} +46 -8
- package/dist/{client-BYaOGCOG.js → client-DyfWYU8S.js} +2 -2
- package/dist/{client-C9QrWrnt.js → client-Dz1jWDA2.js} +3 -3
- package/dist/{client-01MAuqzW.js → client-DzTtOVRR.js} +2 -2
- package/dist/{client-xkSCp9hN.d.ts → client-GdJH4XJM.d.ts} +4 -4
- package/dist/{client-B7QVIrJS.d.ts → client-QvuCfO4b.d.ts} +13 -13
- package/dist/{client-CoVGPi0c.js → client-UnM3e32l.js} +2 -2
- package/dist/{client-DG7FwgZD.js → client-arq4daO_.js} +1 -1
- package/dist/{client-DIrCmOXz.d.ts → client-cWUWrgis.d.ts} +6 -6
- package/dist/{client-Cdedx_lw.js → client-eCDPjOMo.js} +6 -6
- package/dist/{client-WAdEBBrH.d.ts → client-eCtwzCbQ.d.ts} +5 -5
- package/dist/{client-iDLLvGR4.d.ts → client-ehjQ2tIT.d.ts} +3 -3
- package/dist/{client-i8glKhxh.js → client-iaFm0aVf.js} +1 -1
- package/dist/{cloud-event-5rCEzIgK.d.ts → cloud-event-DXkNoI6v.d.ts} +1 -1
- package/dist/{codecs-YAekuQ08.js → codecs-D-rpDifG.js} +3 -3
- package/dist/{codecs-Bm46sVxr.d.ts → codecs-RwFNK8Jh.d.ts} +2 -2
- package/dist/{codegen-DeoSt1mi.d.ts → codegen-C64C0NZG.d.ts} +108 -14
- package/dist/{comments-D7sbd0xG.js → comments-CV5O8q50.js} +5 -5
- package/dist/commerce/index.d.ts +2 -2
- package/dist/commerce/index.js +6 -6
- package/dist/{compiler-BVxepAY0.d.ts → compiler-D_Gjpw_O.d.ts} +2 -2
- package/dist/{compose-Djntdacs.js → compose-CP0ss-cQ.js} +3 -3
- package/dist/{composite-djtGy6bz.d.ts → composite-B1Mmo4TU.d.ts} +13 -13
- package/dist/{composite-M6zPs1Xm.js → composite-BFatHqOU.js} +3 -3
- package/dist/config/index.d.ts +6 -6
- package/dist/config/index.js +4 -4
- package/dist/{config-C4MozTD7.js → config-DHhQmmuD.js} +26 -1
- package/dist/{config-BA1K4OPk.js → config-NQmw_wsk.js} +4 -3
- package/dist/{connector-Cp8CqssJ.d.ts → connector-D9NMNkv0.d.ts} +1 -1
- package/dist/{connectors-CjD-R2ks.d.ts → connectors-CR9FJGzV.d.ts} +7 -7
- package/dist/{context-BDDgjoxz.js → context-BiwgsycK.js} +1 -1
- package/dist/{context-1sSWcd7_.d.ts → context-Cv3KlxWY.d.ts} +15 -3
- package/dist/{controller-D845qKh2.d.ts → controller-BBXX1RMw.d.ts} +1 -1
- package/dist/cors-h_v7TPxl.js +24 -0
- package/dist/cors-kLq6VM06.d.ts +15 -0
- package/dist/create/index.d.ts +597 -0
- package/dist/create/index.js +2049 -0
- package/dist/create/lite/index.d.ts +85 -0
- package/dist/create/lite/index.js +126 -0
- package/dist/create/supabase/index.d.ts +68 -0
- package/dist/create/supabase/index.js +312 -0
- package/dist/credentials/index.d.ts +5 -5
- package/dist/credentials/index.js +8 -8
- package/dist/{cron-CUaKTjWC.js → cron-BHdXZFsJ.js} +1 -1
- package/dist/{cron-route-CoL-By8Z.js → cron-route-mTvWhork.js} +3 -3
- package/dist/{define-B2ln373W.js → define-Bu1v781m.js} +82 -16
- package/dist/{define-DxHHbNEb.d.ts → define-M_r1d2AT.d.ts} +96 -43
- package/dist/{define-block-CLZMEFeK.d.ts → define-block-CPyJ95rq.d.ts} +7 -7
- package/dist/{delegation-Dt8hMJWu.js → delegation-B7uNnz6z.js} +2 -2
- package/dist/{documents-CWn2mtYf.d.ts → documents-CqtVr2fg.d.ts} +4 -4
- package/dist/edge/index.d.ts +27 -38
- package/dist/edge/index.js +12 -32
- package/dist/elysia/index.d.ts +1 -1
- package/dist/elysia/index.js +1 -1
- package/dist/{embeddings-C2S14foD.d.ts → embeddings-lTUwzvW4.d.ts} +1 -1
- package/dist/{ended-nIdGCHxk.d.ts → ended-DQmwYosO.d.ts} +2 -2
- package/dist/{entitlements-BvU5dLpW.js → entitlements-C8UvF1Rz.js} +3 -3
- package/dist/{entitlements-CbzCKalR.d.ts → entitlements-DgkeStXd.d.ts} +2 -2
- package/dist/env/index.d.ts +1 -1
- package/dist/env/index.js +6 -1
- package/dist/{envelope-CHYk5MXU.js → envelope-C4Z55LKW.js} +4 -4
- package/dist/{errors-8i6tSICm.js → errors-BV1SKTVs.js} +15 -1
- package/dist/{errors-PIpcoe4z.js → errors-D3BR8iUk.js} +2 -2
- package/dist/{escape-like-AUEPn-C5.d.ts → escape-like-B339PlP-.d.ts} +1 -1
- package/dist/eve/index.d.ts +5 -5
- package/dist/eve/index.js +2 -2
- package/dist/{eve-DUF70Vgi.d.ts → eve-C_Onyk_j.d.ts} +2 -2
- package/dist/events/index.d.ts +3 -3
- package/dist/{events-CTreRrgP.d.ts → events-P3raDX2E.d.ts} +3 -3
- package/dist/{executor-BXSHYyW2.js → executor-BiB0wMBA.js} +4 -4
- package/dist/{executor-DoE-5iM8.d.ts → executor-BnMC0lj3.d.ts} +2 -2
- package/dist/{executor-DKrZr3AC.d.ts → executor-CvsNcQsa.d.ts} +3 -3
- package/dist/{executor-D1kYY5BA.js → executor-CxGQiQN_.js} +3 -3
- package/dist/{executor-BBHgjUJu.d.ts → executor-D1hECPGG.d.ts} +1 -1
- package/dist/{executor-BINiCFNp.d.ts → executor-DfdC00xr.d.ts} +1 -1
- package/dist/expo/index.d.ts +11 -9
- package/dist/expo/index.js +42 -7
- package/dist/expo-sqlite/index.d.ts +3 -3
- package/dist/expo-sqlite/index.js +2 -2
- package/dist/{field-errors-CWXN_h_E.d.ts → field-errors-DmJICh93.d.ts} +7 -7
- package/dist/{filter-evaluate-CjcFq0RT.d.ts → filter-evaluate-BJcaL3o1.d.ts} +1 -1
- package/dist/{filter-query-BKmRYrTE.d.ts → filter-query-Bc_Qa8V_.d.ts} +1 -1
- package/dist/{flags-D_D1jAHB.d.ts → flags-6KK6Vqkr.d.ts} +3 -3
- package/dist/{flags-XAOsdNAc.js → flags-aUR7Rod6.js} +1 -1
- package/dist/flags-sdk/index.d.ts +1 -1
- package/dist/flags-sdk/index.js +2 -2
- package/dist/{options-BqO9GYig.js → form-definition-GVZTILhS.js} +13 -13
- package/dist/{framework-INbjMZX1.js → framework-Ch8bMmQY.js} +2 -2
- package/dist/{framework-DG5Bv39u.d.ts → framework-D6IFkuAg.d.ts} +7 -7
- package/dist/{function-contract-B4c0XuTU.d.ts → function-contract-DWqFl_QO.d.ts} +1 -1
- package/dist/{gateway-Cup00l0w.d.ts → gateway-Bq_tWwxE.d.ts} +4 -4
- package/dist/h3/index.d.ts +1 -1
- package/dist/h3/index.js +1 -1
- package/dist/h3/v1/index.d.ts +1 -1
- package/dist/h3/v1/index.js +1 -1
- package/dist/{hmac-DCud0myt.js → hmac-BgpThYQW.js} +2 -1
- package/dist/hono/index.d.ts +34 -25
- package/dist/hono/index.js +18 -12
- package/dist/{http-BF-V0CUF.js → http-C7trc6uN.js} +2 -2
- package/dist/{impersonation-CDeCzZP6.js → impersonation-DxU6yHJV.js} +1 -1
- package/dist/{inbox-3ql4phyr.d.ts → inbox-Du5aPwKB.d.ts} +4 -4
- package/dist/{index-BlqrGvb3.d.ts → index-BpyBH5O2.d.ts} +4 -4
- package/dist/{index-Brhm22eL.d.ts → index-Bq409YZn.d.ts} +1 -1
- package/dist/index-CEcDqDhc.d.ts +722 -0
- package/dist/{index-CrZitvSC.d.ts → index-CK0Sxx57.d.ts} +8 -8
- package/dist/{index-DygICr8c.d.ts → index-Csi8jD-m.d.ts} +3 -3
- package/dist/{index-CETRk4YO.d.ts → index-CxmVzT-3.d.ts} +5 -1
- package/dist/index-D8yhOz_4.d.ts +344 -0
- package/dist/{index-Bvw9r94Q.d.ts → index-DHReeV74.d.ts} +2 -2
- package/dist/{index-jhqhynmh.d.ts → index-DgobXyil.d.ts} +1 -1
- package/dist/{index-BkzNUPId.d.ts → index-F6XTTkC9.d.ts} +8 -8
- package/dist/{index-DfVXx4Ia.d.ts → index-k-rrfG1g.d.ts} +2 -2
- package/dist/{index-BIi8i6BO.d.ts → index-qCG78-Rf.d.ts} +4 -4
- package/dist/{index-Ej8XQ9w9.d.ts → index-wTnPJUhv.d.ts} +2 -2
- package/dist/index.d.ts +13 -13
- package/dist/index.js +10 -10
- package/dist/jwks-cache-C4rA69hD.js +49 -0
- package/dist/{jws-milwSg7E.js → jws-CwBB5QAT.js} +5 -3
- package/dist/{kit-D5S7KNFe.d.ts → kit-BeZX2pR_.d.ts} +4 -4
- package/dist/{kit-MUK34-ZG.js → kit-LTbHrWWD.js} +6 -6
- package/dist/{knowledge-CJ_Mm3ic.js → knowledge-BbdXOJvY.js} +4 -4
- package/dist/{knowledge-BXQ2-V0a.d.ts → knowledge-CRk1jOAJ.d.ts} +6 -6
- package/dist/lint/index.d.ts +1 -1
- package/dist/lint/index.js +47 -2
- package/dist/list/index.d.ts +3 -3
- package/dist/{list-query-PvP3pPGQ.d.ts → list-query-FhFXzObg.d.ts} +5 -5
- package/dist/management-D1gG89z2.d.ts +53 -0
- package/dist/mcp/index.d.ts +56 -31
- package/dist/mcp/index.js +142 -59
- package/dist/mcp/sdk/index.d.ts +17 -17
- package/dist/mcp/sdk/index.js +5 -5
- package/dist/{messages-Cx4ttLJJ.js → messages-D5nIfCCf.js} +2 -2
- package/dist/{options-BQ07tTYr.js → methods-7u6vSgz_.js} +4 -4
- package/dist/{mfa-DtflCXEt.d.ts → mfa-YzkRjNad.d.ts} +1 -1
- package/dist/{model-messages-CTu-6kBu.js → model-messages-CIdqdUtk.js} +1 -1
- package/dist/{money-codec-C_-K5ZUU.js → money-codec-C21MWw50.js} +2 -2
- package/dist/nestjs/index.d.ts +2 -2
- package/dist/nestjs/index.js +1 -1
- package/dist/next/index.d.ts +34 -29
- package/dist/next/index.js +14 -14
- package/dist/node/index.d.ts +2 -2
- package/dist/node/index.js +1 -1
- package/dist/{onboarding-BZvLLPaY.js → onboarding-Du6kCmhF.js} +2 -2
- package/dist/openapi/index.d.ts +2 -2
- package/dist/openapi/index.js +2 -2
- package/dist/{operations-C9-UcReN.d.ts → operations-DQCWqkt3.d.ts} +1 -1
- package/dist/{options-CZk_fbbg.js → options-BCrqe3HH.js} +2 -1
- package/dist/options-CEMawFrr.js +5 -0
- package/dist/options-RKYdmIdV.js +5 -0
- package/dist/{options-CbSOj53r.d.ts → options-ZQzNKKBS.d.ts} +1 -1
- package/dist/{organizations-Cw7om8uk.js → organizations-CO2qg44D.js} +6 -6
- package/dist/orpc/index.d.ts +18 -18
- package/dist/orpc/index.js +7 -7
- package/dist/otel/index.d.ts +2 -2
- package/dist/otel/index.js +5 -5
- package/dist/{outbox-BTeqjbum.d.ts → outbox-njgoVzFA.d.ts} +6 -6
- package/dist/{payments-h45bswA-.js → payments-CzjCdIcz.js} +1 -1
- package/dist/{plugin-CDLJRFFg.d.ts → plugin-D-95Q0w0.d.ts} +3 -3
- package/dist/plugins/actor/index.d.ts +1 -1
- package/dist/plugins/actor/index.js +1 -1
- package/dist/plugins/rules/index.d.ts +2 -2
- package/dist/plugins/rules/index.js +1 -1
- package/dist/plugins/soft-delete/index.d.ts +3 -3
- package/dist/plugins/soft-delete/index.js +2 -2
- package/dist/plugins/tenant/index.d.ts +2 -2
- package/dist/plugins/tenant/index.js +2 -2
- package/dist/plugins/timestamps/index.d.ts +1 -1
- package/dist/plugins/timestamps/index.js +1 -1
- package/dist/plugins/validation/index.d.ts +2 -2
- package/dist/plugins/validation/index.js +3 -3
- package/dist/{pool-CwOCsX9e.d.ts → pool-cM3rpOQr.d.ts} +7 -4
- package/dist/{pool-errors-GMjlCN0d.js → pool-errors-CGqvTQOC.js} +2 -2
- package/dist/{ports-DAdQyjZz.d.ts → ports-DCAcG26M.d.ts} +2 -2
- package/dist/{ports-Ca63W4cW.d.ts → ports-DGe1vzF2.d.ts} +10 -10
- package/dist/{ports-DGK3KTDH.js → ports-aALjot-D.js} +11 -7
- package/dist/postgres/index.d.ts +5 -5
- package/dist/postgres/index.js +11 -5
- package/dist/{postgrest-Cw9Bs5gm.d.ts → postgrest-CjnO1hbr.d.ts} +1 -1
- package/dist/powersync/index.d.ts +4 -4
- package/dist/powersync/index.js +4 -4
- package/dist/powersync/react/index.d.ts +3 -3
- package/dist/powersync/react/index.js +1 -1
- package/dist/preset/index.d.ts +4 -352
- package/dist/preset/index.js +4 -564
- package/dist/preset-Cqwlwx6G.js +648 -0
- package/dist/{problem-CEjyhV5T.d.ts → problem-DCDIQiTA.d.ts} +1 -1
- package/dist/{problem-pIiL3WbE.js → problem-JRCohp1j.js} +1 -1
- package/dist/{provider-DKh2xFZb.js → provider-C-Ti38J6.js} +1 -1
- package/dist/{provider-9gBq9W6k.d.ts → provider-CNs0Jx0I.d.ts} +2 -2
- package/dist/{push-token-asrmi7-6.d.ts → push-token-D2sDxSNN.d.ts} +1 -1
- package/dist/query/index.d.ts +2 -2
- package/dist/{rank-result-Dngpt2n5.d.ts → rank-result-BcYfDA0x.d.ts} +1 -1
- package/dist/{rank-result-DS8IoLup.js → rank-result-DtQuIvob.js} +2 -2
- package/dist/{rate-limit-BtbddDnE.js → rate-limit-DVZ7qIzW.js} +1 -1
- package/dist/{rate-limit--QSiFA6D.js → rate-limit-I3AncmM8.js} +8 -8
- package/dist/{rate-limit-C88MEAOm.d.ts → rate-limit-c6c1mB6R.d.ts} +2 -2
- package/dist/react/index.d.ts +8 -8
- package/dist/react/index.js +2 -2
- package/dist/react/native/index.d.ts +1 -1
- package/dist/react/native/index.js +1 -1
- package/dist/react/server.d.ts +9 -9
- package/dist/react/server.js +2 -2
- package/dist/react/session.d.ts +2 -2
- package/dist/{react-CKXUkwPx.js → react-DzukE6Wp.js} +3 -3
- package/dist/react-router/index.d.ts +11 -11
- package/dist/react-router/index.js +6 -6
- package/dist/{read-set-GEb-i0On.js → read-set-DeesfeL_.js} +2 -2
- package/dist/realtime/index.d.ts +7 -7
- package/dist/realtime/index.js +2 -2
- package/dist/{refusal-br4Ma9Cf.js → refusal-CFpfmjcS.js} +4 -4
- package/dist/{refusal-oD3ISM9h.d.ts → refusal-CufncwaN.d.ts} +1 -1
- package/dist/{resolve-w9EpHzuM.d.ts → resolve-Bqb8TMTt.d.ts} +4 -4
- package/dist/{resolve-CAR9oaKW.js → resolve-f8QNuYI3.js} +5 -4
- package/dist/{resource-C8r5xGqY.js → resource-Bdkqi8jo.js} +6 -6
- package/dist/{resource-B4ka8dDH.d.ts → resource-DYEtc-KN.d.ts} +1 -1
- package/dist/{resource-execute-D0yQ-8WR.d.ts → resource-execute-ruP2L1op.d.ts} +2 -2
- package/dist/{resource-types-D2vEQVXI.d.ts → resource-types-CGr0BbL-.d.ts} +6 -6
- package/dist/{resources-BklF-rjz.d.ts → resources-BiQpsM6O.d.ts} +2 -2
- package/dist/{resources-BlZdLsWQ.js → resources-Ck7itNeX.js} +3 -3
- package/dist/{respond-DdhZ9Wbn.js → respond-Bhp3G__q.js} +5 -5
- package/dist/{respond-C7I8kLK_.d.ts → respond-CEBC6KUX.d.ts} +3 -3
- package/dist/{result-Cj3yWhjH.d.ts → result-BREt7qOh.d.ts} +15 -1
- package/dist/{result-BlgnMB0H.js → result-DIeYscA3.js} +7 -1
- package/dist/{rrule-zBh3CA1r.js → rrule-Cw4x4Pf_.js} +1 -1
- package/dist/{rules-B0-3Iosu.js → rules-BiQgmZ_U.js} +32 -6
- package/dist/runtime-BOXURhEW.js +45 -0
- package/dist/{sales-lines-BAk8In-Z.js → sales-lines-CQ1iC6QM.js} +3 -3
- package/dist/{sales-shared-SblIgCgI.js → sales-shared-CDSytDEn.js} +2 -2
- package/dist/{search-B6h03cAx.js → search-ZP13UTT4.js} +3 -3
- package/dist/server/index.d.ts +26 -26
- package/dist/server/index.js +19 -64
- package/dist/{server-types-OohhIQb2.d.ts → server-types-BKN_R4Ws.d.ts} +45 -27
- package/dist/{session-DiWHtYrO.d.ts → session-CwpfitmI.d.ts} +11 -11
- package/dist/{settings-BXFn9zpS.js → settings-BiHDFglz.js} +5 -5
- package/dist/{shared-DbO3Dfms.js → shared-C9zvURqC.js} +1 -1
- package/dist/{shared-as0EG51f.js → shared-D5Djh43x.js} +1 -1
- package/dist/{sign-in-D0xN6E_l.js → sign-in-z2BaBdps.js} +10 -3
- package/dist/{signatures-BMdJ7neI.d.ts → signatures-BXlDXV3D.d.ts} +1 -1
- package/dist/{signatures-B41ApWXA.js → signatures-CeIoAelK.js} +5 -5
- package/dist/{signers-CXt_wA9S.d.ts → signers-BwKV-9S6.d.ts} +6 -6
- package/dist/{signing-keys-Bq9mMCTh.d.ts → signing-keys-v2MRYkDF.d.ts} +20 -5
- package/dist/solid/index.d.ts +8 -8
- package/dist/solid/index.js +1 -1
- package/dist/{solid-controller-DqlvYFZa.d.ts → solid-controller-Uqi5ef6z.d.ts} +1 -1
- package/dist/solid-start/index.d.ts +11 -11
- package/dist/solid-start/index.js +5 -5
- package/dist/spec/index.d.ts +3 -3
- package/dist/spec/index.js +3 -3
- package/dist/sql/index.d.ts +5 -709
- package/dist/sql/index.js +5 -86238
- package/dist/{sql-DJrXG-3Z.js → sql-BPKRNutj.js} +3 -3
- package/dist/sql-DCfCbS2j.js +88660 -0
- package/dist/{sso-BDva_-4y.js → sso-BaU_6ePE.js} +4 -4
- package/dist/{sso-BN0LnMqE.d.ts → sso-Bu0mVh0V.d.ts} +4 -4
- package/dist/ssr/index.d.ts +4 -4
- package/dist/ssr/index.js +3 -3
- package/dist/{standard-B5fe2gnW.js → standard-B1BigegP.js} +2 -2
- package/dist/{standard-C3_AAF3g.d.ts → standard-BcUQuUgu.d.ts} +1 -1
- package/dist/{stats-D6vkb89f.js → stats-Di5VAsYU.js} +4 -4
- package/dist/storage/index.d.ts +3 -3
- package/dist/storage/index.js +6 -6
- package/dist/{store-B5qYKsTh.d.ts → store-B18bIvKc.d.ts} +1 -1
- package/dist/streams/index.d.ts +3 -3
- package/dist/streams/index.js +3 -3
- package/dist/streams/redis/index.d.ts +1 -1
- package/dist/streams/redis/index.js +2 -2
- package/dist/{subject-readers-fxP5wu0s.d.ts → subject-readers-BNQzBDN9.d.ts} +2 -2
- package/dist/{subject-readers-DiePmaYP.js → subject-readers-BpwUFJtp.js} +1 -1
- package/dist/{subjects-z8VWA_lF.d.ts → subjects-DP-fvFkk.d.ts} +8 -0
- package/dist/{support-BsKkvA92.js → support-BAhTqI7y.js} +8 -8
- package/dist/{support-view-BbcZR7Io.d.ts → support-view-IRnDLuGN.d.ts} +1 -1
- package/dist/svelte/index.d.ts +7 -7
- package/dist/svelte/index.js +1 -1
- package/dist/{svelte-controller-DxxHEHxD.d.ts → svelte-controller-BQOIXWEw.d.ts} +1 -1
- package/dist/sveltekit/index.d.ts +13 -13
- package/dist/sveltekit/index.js +7 -7
- package/dist/{tags-Dw8vKkcI.d.ts → tags-AUpl4Ob9.d.ts} +1 -1
- package/dist/{tags-PaG0Ns_9.js → tags-BqgaxCnv.js} +5 -5
- package/dist/tanstack-db/index.d.ts +2 -2
- package/dist/tanstack-db/supabase/index.d.ts +2 -2
- package/dist/tanstack-start/index.d.ts +11 -11
- package/dist/tanstack-start/index.js +5 -5
- package/dist/{tax-DDZUB_oc.d.ts → tax-DMWDUzKt.d.ts} +2 -2
- package/dist/{tax-D_kSCdWU.js → tax-wm9g2mD2.js} +2 -2
- package/dist/{tee-Bsisfd7t.js → tee-Cw-iJAWL.js} +1 -1
- package/dist/{template-DdgYjIZ5.js → template-Dw3dTmKe.js} +1 -1
- package/dist/{temporal-required-DqRzr7i0.js → temporal-required-nfZ87U-0.js} +1 -1
- package/dist/{tenant-DdmVhsff.d.ts → tenant-BNp3kBAG.d.ts} +2 -2
- package/dist/testing/index.d.ts +133 -57
- package/dist/testing/index.js +252 -164
- package/dist/{topic-cMS7UtM1.d.ts → topic-1WTkDnPd.d.ts} +46 -18
- package/dist/{topic-ByDz9edV.js → topic-mee21pux.js} +112 -25
- package/dist/{types-6oiy6rIa.d.ts → types-B4zhT6dq.d.ts} +5 -5
- package/dist/{types-CdP0z5tS.d.ts → types-BEEFkNFY.d.ts} +7 -7
- package/dist/{types-vaoP9S9_.d.ts → types-Bq64h5nY.d.ts} +25 -11
- package/dist/{types-YfwpIE-d.d.ts → types-BrpW5ixT.d.ts} +14 -1
- package/dist/{types-D0W4fnsc.d.ts → types-DDQ-Rsep.d.ts} +5 -5
- package/dist/types-DGHfTW8_.d.ts +9 -0
- package/dist/{types-pNY_UpDs.d.ts → types-DO9xWsGC.d.ts} +6 -6
- package/dist/{undo-CEGIRkPA.js → undo-B5LgpGLy.js} +4 -4
- package/dist/{undo-DGo0skyO.d.ts → undo-BsdYRox7.d.ts} +3 -3
- package/dist/{usage-DM2rzczj.d.ts → usage-C504GF55.d.ts} +23 -5
- package/dist/{usage-CdlfuS3i.js → usage-DdqT13_X.js} +14 -3
- package/dist/{vault-tOkPLnMB.d.ts → vault-DR2-zOjz.d.ts} +3 -3
- package/dist/vercel-connect/index.d.ts +1 -1
- package/dist/vercel-connect/index.js +2 -2
- package/dist/{verify-D63A2ALE.d.ts → verify-BucYsoKq.d.ts} +4 -4
- package/dist/{verify-EQcC3Khp.js → verify-DnU-uWU2.js} +5 -5
- package/dist/{version-D87ZteKy.js → version-TXpQEfh1.js} +1 -1
- package/dist/{view-Dv0A949a.d.ts → view-Bf7e07rQ.d.ts} +3 -3
- package/dist/{view-DZ63nqwt.js → view-CYX1wsgp.js} +3 -3
- package/dist/vue/index.d.ts +8 -8
- package/dist/vue/index.js +1 -1
- package/dist/{vue-controller-HPfMTDa2.d.ts → vue-controller-Cav6Wt_r.d.ts} +1 -1
- package/dist/{watch-DT_B3CnJ.js → watch-BAuIzC2r.js} +1 -1
- package/dist/{watch-DDuWYv0Y.d.ts → watch-ry70AEm6.d.ts} +6 -6
- package/dist/{watch-topic-EFpOIIDE.d.ts → watch-topic-DWHy63ZJ.d.ts} +1 -1
- package/dist/{wire-DEY0ajW9.js → wire-BCJxCtHS.js} +2 -2
- package/dist/{workflow-builder-OrglbXUh.js → workflow-builder-CynLqc6H.js} +28 -12
- package/dist/workflow-sdk/builder/index.d.ts +3 -3
- package/dist/workflow-sdk/builder/index.js +1 -1
- package/dist/workflow-sdk/index.d.ts +1 -1
- package/dist/workflow-sdk/index.js +1 -1
- package/dist/workflow-sdk/world/index.d.ts +1 -1
- package/dist/workflow-sdk/world/index.js +6 -6
- package/dist/{workflow-sdk-q8cLwW1K.d.ts → workflow-sdk-DM7T3sF4.d.ts} +3 -3
- package/dist/{workflow-sdk-BZ6qsRlY.js → workflow-sdk-QnnzIQRc.js} +2 -2
- package/dist/{workflow-sdk-world-DPMdBfzn.js → workflow-sdk-world-QzcxaaCD.js} +1 -1
- package/dist/{workflows-DFQeXDAI.d.ts → workflows-DQBCzrHC.d.ts} +4 -4
- package/dist/{workflows-C-OvZpeg.js → workflows-H9qJge3f.js} +5 -5
- package/dist/yjs/index.d.ts +3 -3
- package/dist/yjs/index.js +3 -3
- package/package.json +36 -15
- package/schemas/config-v1.json +226 -9
- package/schemas/doctor-report-v1.json +10 -0
- package/schemas/snapshot-v2.json +4 -0
- package/skills/better-supabase/SKILL.md +1 -0
- package/skills/better-supabase/references/ui-recipes.md +683 -11
- package/dist/cli/add-CT6p5psO.js +0 -1
- package/dist/cli/adopt-C9jl8z0h.js +0 -1
- package/dist/cli/env-D3gZ-OHj.js +0 -1
- package/dist/cli/seed-DtRFysBe.js +0 -1
- package/dist/{client-b2_GjzzD.js → client-BGnJ5WJi.js} +1 -1
|
@@ -1,22 +1,25 @@
|
|
|
1
|
-
import { a as list, p as commandMeta, r as defineCliCommand } from "./command-
|
|
1
|
+
import { a as list, p as commandMeta, r as defineCliCommand } from "./command-DLCZeHdo.js";
|
|
2
2
|
import { i as plain } from "./style-2JfIPVMQ.js";
|
|
3
|
-
import { t as VERSION } from "./version-
|
|
3
|
+
import { t as VERSION } from "./version-CUKjFbNd.js";
|
|
4
4
|
import { n as CliError, r as errorText } from "./errors-Caiz_0so.js";
|
|
5
5
|
import { a as sameText, t as display } from "./io-BiPX-_J1.js";
|
|
6
|
-
import { t as CACHE_DIR } from "./cache-
|
|
6
|
+
import { t as CACHE_DIR } from "./cache-CVJmPGpd.js";
|
|
7
7
|
import { t as byCodePoint } from "./compare-BmIWVEui.js";
|
|
8
8
|
import { h as satisfies, m as peerVersions, t as MetadataRejectedError } from "./typegen--TfvOPLh.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
9
|
+
import { t as isRecord } from "./guards-CUlDNYZs.js";
|
|
10
|
+
import { c as configFor, s as notNullTag } from "./emit-56LAG_Px.js";
|
|
11
|
+
import { _ as withoutStrings, a as METADATA_GAPS_TEXT, c as accessModule, d as RLS_RULES, f as appliesTo, g as policyHelpers, h as functionObject, l as entitlementsModule, m as functionBody, p as escape$1, s as AUTHORIZATION_RULES, u as COMMANDS$1, v as advisorRule, x as renderFiles, y as splinterTables } from "./run-Bb8Nn8Ax.js";
|
|
12
|
+
import { D as providerLabel, a as migrationModules, i as migrationHolds, r as latestMigration, t as MODULES_SUFFIX, v as migrationsDir, x as compiledReadSets, y as moduleLayoutFor } from "./module-migration-CPhuiY8C.js";
|
|
13
|
+
import { l as stdinDatabaseUrl } from "./config-C4e_RrmL.js";
|
|
14
|
+
import { a as findRepoRoot, c as httpHooks, d as readSupabaseToml, f as schemaPaths, h as tomlGet, i as diffEngine, l as migrationCommand, n as declarativeSchemasDir, p as sqlWorkflow, u as pgFunctionHooks } from "./supabase-toml-BC5sNVKU.js";
|
|
14
15
|
import { t as connect } from "./db-DT1bGB02.js";
|
|
15
|
-
import { c as isSqliteLiteDriver, n as managementTarget, o as snapshotFile, p as request, r as openSource, s as liteDriverOf, t as loadSnapshot } from "./snapshot-
|
|
16
|
+
import { c as isSqliteLiteDriver, n as managementTarget, o as snapshotFile, p as request, r as openSource, s as liteDriverOf, t as loadSnapshot } from "./snapshot-ClgWGd-b.js";
|
|
16
17
|
import { n as applyPlan, o as insideRoot, r as changeLines } from "./files-DDvAwTko.js";
|
|
17
|
-
import { t as
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
18
|
+
import { a as permissionCatalogKeys, i as lineOf, l as tableObject, n as exposed, o as policyObject, r as exposedSchemas, s as qualified, t as catalogOf, u as workflowOf } from "./shared-DKLuA1Tp.js";
|
|
19
|
+
import { t as MIGRATION_SAFETY_RULES } from "./migration-safety-DjVpz2D6.js";
|
|
20
|
+
import { a as sourceFlags, n as SOURCE_ARGS } from "./source-args-BDiUhsH8.js";
|
|
21
|
+
import { i as reservedRoles, n as ident$1, r as literal$1, t as LIVE_RULES } from "./live-CLxJNC0r.js";
|
|
22
|
+
import { i as refuseWithMetadata, r as readMetadataSnapshot } from "./metadata-BRywyPvv.js";
|
|
20
23
|
import { existsSync } from "node:fs";
|
|
21
24
|
import { dirname, resolve } from "node:path";
|
|
22
25
|
import { createHash } from "node:crypto";
|
|
@@ -98,6 +101,45 @@ const ADOPTION_RULES = [
|
|
|
98
101
|
});
|
|
99
102
|
}
|
|
100
103
|
},
|
|
104
|
+
{
|
|
105
|
+
code: "BS342",
|
|
106
|
+
severity: "error",
|
|
107
|
+
title: "Adopted enum column the module writes as text",
|
|
108
|
+
description: "A module in adopt mode writes a text parameter or computed text value into a column the snapshot declares as an enum; string literals are fine. Postgres has no implicit cast from text to an enum, so the module's functions fail when they run. Columns the module casts to their declared type, such as the tags `kind` and the number-sequences `entity`, may be enums.",
|
|
109
|
+
check: (context) => {
|
|
110
|
+
const { tables } = catalogOf(context);
|
|
111
|
+
return adoptedTables(context.config.blocks).flatMap((adopted) => {
|
|
112
|
+
const table = tables.find((entry) => entry.schema === adopted.schema && entry.name === adopted.table);
|
|
113
|
+
if (table === void 0) return [];
|
|
114
|
+
return adopted.textColumns.flatMap((logical) => {
|
|
115
|
+
const name = adopted.columns[logical];
|
|
116
|
+
const column = table.columns.find((entry) => entry.name === name);
|
|
117
|
+
if (column?.isEnum !== true || column.isArray) return [];
|
|
118
|
+
const target = `${qualified(table)}.${column.name}`;
|
|
119
|
+
return [{
|
|
120
|
+
message: `blocks.${adopted.module} is in adopt mode and writes text into ${target} (${adopted.logical}.${logical}), which is the enum ${column.typeSchema}.${column.udt}. Postgres does not cast text to an enum, so the module's functions fail. Change the column to text with a check constraint on its values.`,
|
|
121
|
+
target
|
|
122
|
+
}];
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
code: "BS344",
|
|
129
|
+
severity: "warning",
|
|
130
|
+
title: "Adopted webhook endpoints without a format",
|
|
131
|
+
description: "An adopted `webhooks-out` endpoints table that maps no `format` column sends every endpoint in `blocks.webhooks-out.options.defaultFormat`. Its default changed from the 0.8 body (`standard`) to `cloudevents` in 0.9, so receivers built for the old body break without any change to the config. `sql sync` refuses this config; doctor reports it for configs it loads without that check. Set `defaultFormat` explicitly, or add a format column and map it in `columns.endpoints.format`.",
|
|
132
|
+
check: (context) => {
|
|
133
|
+
const block = context.config.blocks["webhooks-out"];
|
|
134
|
+
if (block?.mode !== "adopt" || block.options?.["defaultFormat"] !== void 0 || typeof block.columns?.["endpoints"]?.["format"] === "string") return [];
|
|
135
|
+
const adopted = adoptedTables(context.config.blocks).find((entry) => entry.module === "webhooks-out" && entry.logical === "endpoints");
|
|
136
|
+
const table = adopted === void 0 ? void 0 : catalogOf(context).tables.find((entry) => entry.schema === adopted.schema && entry.name === adopted.table);
|
|
137
|
+
return [{
|
|
138
|
+
message: `${adopted === void 0 ? "The adopted endpoints table" : `${adopted.schema}.${adopted.table}`} ${table?.columns.some((column) => column.name === "format") ? "has a format column the config doesn't map" : "has no format column"}, so every endpoint gets blocks.webhooks-out.options.defaultFormat, which defaults to "cloudevents" since 0.9 ("standard" before). Set defaultFormat to the body your receivers expect, or map columns.endpoints.format.`,
|
|
139
|
+
target: "blocks.webhooks-out.options.defaultFormat"
|
|
140
|
+
}];
|
|
141
|
+
}
|
|
142
|
+
},
|
|
101
143
|
{
|
|
102
144
|
code: "BS341",
|
|
103
145
|
severity: "warning",
|
|
@@ -246,331 +288,6 @@ const FLAG_RULES = [{
|
|
|
246
288
|
check: expiredFlags
|
|
247
289
|
}];
|
|
248
290
|
//#endregion
|
|
249
|
-
//#region src/cli/doctor/reserved-roles.ts
|
|
250
|
-
/**
|
|
251
|
-
* supautils' `reserved_roles` on Supabase. Nobody but a superuser may alter,
|
|
252
|
-
* drop or change the memberships of these.
|
|
253
|
-
*/
|
|
254
|
-
const RESERVED_ROLES = /* @__PURE__ */ new Set([
|
|
255
|
-
"supabase_admin",
|
|
256
|
-
"supabase_auth_admin",
|
|
257
|
-
"supabase_storage_admin",
|
|
258
|
-
"supabase_functions_admin",
|
|
259
|
-
"supabase_read_only_user",
|
|
260
|
-
"supabase_realtime_admin",
|
|
261
|
-
"supabase_replication_admin",
|
|
262
|
-
"supabase_etl_admin",
|
|
263
|
-
"dashboard_user",
|
|
264
|
-
"pgbouncer"
|
|
265
|
-
]);
|
|
266
|
-
/** Reserved roles whose settings (`alter role ... set`) supautils allows changing. */
|
|
267
|
-
const SETTINGS_ONLY_ROLES = /* @__PURE__ */ new Set([
|
|
268
|
-
"authenticator",
|
|
269
|
-
"authenticated",
|
|
270
|
-
"anon",
|
|
271
|
-
"service_role"
|
|
272
|
-
]);
|
|
273
|
-
/**
|
|
274
|
-
* Roles that Supabase's own services log in as. Their statements (PostgREST's
|
|
275
|
-
* schema cache query, Auth and Storage migrations) aren't the app's.
|
|
276
|
-
*/
|
|
277
|
-
const PLATFORM_ROLES = /* @__PURE__ */ new Set([...RESERVED_ROLES, "authenticator"]);
|
|
278
|
-
/** Comments and string literals blanked, newlines kept so offsets map to lines. */
|
|
279
|
-
const sqlCode = (text) => text.replaceAll(/\/\*[\s\S]*?\*\//g, (comment) => comment.replaceAll(/[^\n]/g, " ")).replaceAll(/--[^\n]*/g, "").replaceAll(/'(?:[^']|'')*'/g, "''");
|
|
280
|
-
const roleNames = (list) => list.split(",").map((name) => name.trim().replaceAll("\"", "").toLowerCase()).filter((name) => name !== "");
|
|
281
|
-
/** Why a statement changes a reserved role, or undefined when it doesn't. */
|
|
282
|
-
function reservedRoleChange(statement) {
|
|
283
|
-
const alter = /^\s*(alter|drop)\s+(?:role|user)\s+(?:if\s+exists\s+)?("[^"]+"|\w+)\s*(\w*)/i.exec(statement);
|
|
284
|
-
if (alter) {
|
|
285
|
-
const role = roleNames(alter[2])[0];
|
|
286
|
-
const verb = alter[1].toLowerCase();
|
|
287
|
-
const next = alter[3].toLowerCase();
|
|
288
|
-
if (RESERVED_ROLES.has(role)) return `${verb}s the reserved role ${role}`;
|
|
289
|
-
if (SETTINGS_ONLY_ROLES.has(role) && (verb === "drop" || next !== "set" && next !== "reset" && next !== "in")) return `${verb}s the reserved role ${role}; only \`alter role ${role} set ...\` is allowed`;
|
|
290
|
-
return;
|
|
291
|
-
}
|
|
292
|
-
const membership = /^\s*(grant|revoke)\s+(?![\s\S]*\bon\b)([\w",\s]+?)\s+(?:to|from)\s+([\w",\s]+?)(?:\s+with\s+\w+\s+option)?\s*$/i.exec(statement);
|
|
293
|
-
if (!membership) return;
|
|
294
|
-
const role = [...roleNames(membership[2]), ...roleNames(membership[3])].find((name) => RESERVED_ROLES.has(name));
|
|
295
|
-
return role === void 0 ? void 0 : `${membership[1].toLowerCase()}s a membership of the reserved role ${role}`;
|
|
296
|
-
}
|
|
297
|
-
/** Where a statement ends, including statements inside `do` blocks and function bodies. */
|
|
298
|
-
const STATEMENT_BOUNDARY = /;|\$\w*\$|\b(?:begin|then|else|loop)\b/gi;
|
|
299
|
-
/** Statements in schema files and migrations that supautils rejects on Supabase. */
|
|
300
|
-
function reservedRoles(context) {
|
|
301
|
-
return (context.sqlFiles ?? []).flatMap((file) => {
|
|
302
|
-
const code = sqlCode(file.text);
|
|
303
|
-
const findings = [];
|
|
304
|
-
let start = 0;
|
|
305
|
-
for (const end of [...code.matchAll(STATEMENT_BOUNDARY), void 0]) {
|
|
306
|
-
const until = end?.index ?? code.length;
|
|
307
|
-
const statement = code.slice(start, until);
|
|
308
|
-
const reason = reservedRoleChange(statement);
|
|
309
|
-
if (reason !== void 0) {
|
|
310
|
-
const at = start + statement.search(/\S/);
|
|
311
|
-
const line = code.slice(0, at).split("\n").length;
|
|
312
|
-
findings.push({
|
|
313
|
-
message: `${file.path}:${String(line)} ${reason}. supautils rejects it on Supabase, so the migration fails on a hosted project; grant privileges to your own role instead.`,
|
|
314
|
-
target: `${file.path}:${String(line)}`,
|
|
315
|
-
location: {
|
|
316
|
-
file: file.path,
|
|
317
|
-
line
|
|
318
|
-
}
|
|
319
|
-
});
|
|
320
|
-
}
|
|
321
|
-
start = until + (end?.[0].length ?? 0);
|
|
322
|
-
}
|
|
323
|
-
return findings;
|
|
324
|
-
});
|
|
325
|
-
}
|
|
326
|
-
//#endregion
|
|
327
|
-
//#region src/cli/doctor/live.ts
|
|
328
|
-
/** Statements slower than this (ms, mean) with more calls than `SLOW_CALLS` are BS209. */
|
|
329
|
-
const SLOW_MEAN_MS = 50;
|
|
330
|
-
const SLOW_CALLS = 1e3;
|
|
331
|
-
/** Rows `--explain` reads, like a `findMany()` under Supabase's default `max_rows`. */
|
|
332
|
-
const EXPLAIN_LIMIT = 1e3;
|
|
333
|
-
const escape$1 = (name) => name.replaceAll(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
334
|
-
const ident$1 = (name) => `"${name.replaceAll("\"", "\"\"")}"`;
|
|
335
|
-
const literal$1 = (text) => `'${text.replaceAll("'", "''")}'`;
|
|
336
|
-
const oneLine = (query, max = 160) => {
|
|
337
|
-
const flat = query.replaceAll(/\s+/g, " ").trim();
|
|
338
|
-
return flat.length > max ? `${flat.slice(0, max - 1)}…` : flat;
|
|
339
|
-
};
|
|
340
|
-
const plural$1 = (count, word) => `${count} ${word}${count === 1 ? "" : "s"}`;
|
|
341
|
-
const megabytes = (bytes) => `${(bytes / 1024 / 1024).toFixed(1)} MB`;
|
|
342
|
-
/** The schema `pg_stat_statements` lives in, when the extension is installed. */
|
|
343
|
-
async function statementsView(db) {
|
|
344
|
-
const [row] = await db.query(`select n.nspname as schema from pg_extension e join pg_namespace n on n.oid = e.extnamespace where e.extname = 'pg_stat_statements'`);
|
|
345
|
-
return row ? `${ident$1(row.schema)}.pg_stat_statements` : void 0;
|
|
346
|
-
}
|
|
347
|
-
/** The first exposed table a statement names, to locate it in the SQL files. */
|
|
348
|
-
function tableIn(query, tables) {
|
|
349
|
-
return tables.find((table) => {
|
|
350
|
-
const schema = escape$1(table.schema);
|
|
351
|
-
const name = escape$1(table.name);
|
|
352
|
-
return new RegExp(`(?:"${schema}"|\\b${schema})\\.(?:"${name}"|${name}\\b)`).test(query);
|
|
353
|
-
});
|
|
354
|
-
}
|
|
355
|
-
const live = (context) => context.database;
|
|
356
|
-
/**
|
|
357
|
-
* Function calls and self time so far in this transaction. The view can
|
|
358
|
-
* still hold unflushed counts from earlier transactions, so callers diff two
|
|
359
|
-
* readings.
|
|
360
|
-
*/
|
|
361
|
-
async function functionTimes(db) {
|
|
362
|
-
const rows = await db.query(`select schemaname || '.' || funcname as name, calls, self_time from pg_stat_xact_user_functions`);
|
|
363
|
-
return new Map(rows.map((row) => [row.name, {
|
|
364
|
-
calls: Number(row.calls),
|
|
365
|
-
selfTime: Number(row.self_time)
|
|
366
|
-
}]));
|
|
367
|
-
}
|
|
368
|
-
/** Node types, timings and loops of an `EXPLAIN (ANALYZE, FORMAT JSON)` plan; never rows. */
|
|
369
|
-
function summarizePlan(output) {
|
|
370
|
-
const nodes = [];
|
|
371
|
-
const perRowSubPlans = [];
|
|
372
|
-
let initPlans = 0;
|
|
373
|
-
const walk = (node) => {
|
|
374
|
-
const loops = node["Actual Loops"] ?? 1;
|
|
375
|
-
const ms = (node["Actual Total Time"] ?? 0).toFixed(2);
|
|
376
|
-
const on = node["Relation Name"] ? ` on ${node["Relation Name"]}` : "";
|
|
377
|
-
const sub = node["Subplan Name"] ? `${node["Subplan Name"]}: ` : "";
|
|
378
|
-
nodes.push(`${sub}${node["Node Type"]}${on} ${ms} ms ×${loops}`);
|
|
379
|
-
if (node["Parent Relationship"] === "InitPlan") initPlans += 1;
|
|
380
|
-
if (node["Parent Relationship"] === "SubPlan" && loops > 1) perRowSubPlans.push(`${sub}${node["Node Type"]}${on} ×${loops}`);
|
|
381
|
-
for (const child of node.Plans ?? []) walk(child);
|
|
382
|
-
};
|
|
383
|
-
walk(output.Plan);
|
|
384
|
-
return {
|
|
385
|
-
nodes,
|
|
386
|
-
initPlans,
|
|
387
|
-
perRowSubPlans,
|
|
388
|
-
executionMs: output["Execution Time"] ?? 0
|
|
389
|
-
};
|
|
390
|
-
}
|
|
391
|
-
const ROLE = /^[a-z_][a-z0-9_]*$/;
|
|
392
|
-
async function explainTable(db, table, claims) {
|
|
393
|
-
const role = typeof claims["role"] === "string" ? claims["role"] : "anon";
|
|
394
|
-
if (!ROLE.test(role)) throw new Error(`Invalid role "${role}" in the claims`);
|
|
395
|
-
await db.query("begin");
|
|
396
|
-
try {
|
|
397
|
-
await db.query(`set local statement_timeout = '30s'`);
|
|
398
|
-
let tracked = true;
|
|
399
|
-
await db.query("savepoint bs_track");
|
|
400
|
-
try {
|
|
401
|
-
await db.query(`set local track_functions = 'all'`);
|
|
402
|
-
await db.query("release savepoint bs_track");
|
|
403
|
-
} catch {
|
|
404
|
-
tracked = false;
|
|
405
|
-
await db.query("rollback to savepoint bs_track");
|
|
406
|
-
}
|
|
407
|
-
await db.query(`select set_config('request.jwt.claims', ${literal$1(JSON.stringify(claims))}, true)`);
|
|
408
|
-
const before = tracked ? await functionTimes(db) : /* @__PURE__ */ new Map();
|
|
409
|
-
await db.query(`set local role ${ident$1(role)}`);
|
|
410
|
-
const [row] = await db.query(`explain (analyze, buffers, format json) select * from ${ident$1(table.schema)}.${ident$1(table.name)} limit ${EXPLAIN_LIMIT}`);
|
|
411
|
-
const raw = row?.["QUERY PLAN"];
|
|
412
|
-
const plan = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
413
|
-
if (!plan?.[0]) throw new Error("EXPLAIN returned no plan");
|
|
414
|
-
const functions = tracked ? [...await functionTimes(db)].map(([name, after]) => {
|
|
415
|
-
const start = before.get(name);
|
|
416
|
-
return {
|
|
417
|
-
name,
|
|
418
|
-
calls: after.calls - (start?.calls ?? 0),
|
|
419
|
-
selfTime: after.selfTime - (start?.selfTime ?? 0)
|
|
420
|
-
};
|
|
421
|
-
}).filter((fn) => fn.calls > 0).sort((a, b) => b.selfTime - a.selfTime) : void 0;
|
|
422
|
-
return {
|
|
423
|
-
summary: summarizePlan(plan[0]),
|
|
424
|
-
functions
|
|
425
|
-
};
|
|
426
|
-
} finally {
|
|
427
|
-
await db.query("rollback");
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
function resolveTable(context, name) {
|
|
431
|
-
return name.includes(".") ? catalogOf(context).tables.find((table) => qualified(table) === name) : exposed(context).find((table) => table.name === name);
|
|
432
|
-
}
|
|
433
|
-
const LIVE_RULES = [
|
|
434
|
-
{
|
|
435
|
-
code: "BS208",
|
|
436
|
-
severity: "warning",
|
|
437
|
-
title: "Queries spill to temporary files",
|
|
438
|
-
description: "Sorts and hashes that exceed `work_mem` write temporary files, which is slow. Reads `pg_stat_database` and, when installed, the top statements from `pg_stat_statements`. When every statement that spilled ran as a Supabase service role (PostgREST's schema cache query as `authenticator`, Auth or Storage) or came from better-supabase's own catalog reads (`introspect`, `gen`, `doctor`), there is no finding.",
|
|
439
|
-
async check(context) {
|
|
440
|
-
const db = live(context);
|
|
441
|
-
if (!db || "skipped" in db) return [];
|
|
442
|
-
try {
|
|
443
|
-
const [stats] = await db.query(`select temp_files, temp_bytes, current_setting('work_mem') as work_mem from pg_stat_database where datname = current_database()`);
|
|
444
|
-
const files = Number(stats?.temp_files ?? 0);
|
|
445
|
-
if (files === 0) return [];
|
|
446
|
-
let top = "";
|
|
447
|
-
const view = await statementsView(db);
|
|
448
|
-
if (view) {
|
|
449
|
-
const spilled = await db.query(`select s.query, s.temp_blks_written, r.rolname as role from ${view} s left join pg_roles r on r.oid = s.userid where s.temp_blks_written > 0 order by s.temp_blks_written desc limit 50`).catch(() => []);
|
|
450
|
-
const statements = spilled.filter((statement) => !statement.query.startsWith("/* better-supabase */") && (statement.role === null || !PLATFORM_ROLES.has(statement.role))).slice(0, 5);
|
|
451
|
-
if (spilled.length > 0 && statements.length === 0) return [];
|
|
452
|
-
if (statements.length > 0) top = ` Top statements by temporary blocks written: ${statements.map((statement) => `${oneLine(statement.query, 100)} (${statement.temp_blks_written} blocks)`).join("; ")}.`;
|
|
453
|
-
}
|
|
454
|
-
return [{
|
|
455
|
-
message: `${files} temporary files (${megabytes(Number(stats?.temp_bytes ?? 0))}) since the statistics were reset; work_mem is ${stats?.work_mem}. Add indexes so large sorts go away, or raise work_mem for the role that runs them.${top}`,
|
|
456
|
-
target: "pg_stat_database:temp_files"
|
|
457
|
-
}];
|
|
458
|
-
} catch (cause) {
|
|
459
|
-
return [{
|
|
460
|
-
severity: "info",
|
|
461
|
-
message: `Could not read pg_stat_database (${db.describe}): ${errorText(cause)}`
|
|
462
|
-
}];
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
},
|
|
466
|
-
{
|
|
467
|
-
code: "BS209",
|
|
468
|
-
severity: "warning",
|
|
469
|
-
title: "Slow frequent statements",
|
|
470
|
-
description: `Statements from \`pg_stat_statements\` with a mean time above ${SLOW_MEAN_MS} ms and more than ${SLOW_CALLS} calls. Runs with \`--stats\`.`,
|
|
471
|
-
async check(context) {
|
|
472
|
-
if (!context.stats) return [];
|
|
473
|
-
const db = live(context);
|
|
474
|
-
if (!db) return [];
|
|
475
|
-
if ("skipped" in db) return [{
|
|
476
|
-
severity: "info",
|
|
477
|
-
message: `Skipped --stats: ${db.skipped}`
|
|
478
|
-
}];
|
|
479
|
-
try {
|
|
480
|
-
const view = await statementsView(db);
|
|
481
|
-
if (!view) return [{
|
|
482
|
-
severity: "info",
|
|
483
|
-
message: "pg_stat_statements is not installed, so --stats has nothing to read. Run `create extension pg_stat_statements with schema extensions;`."
|
|
484
|
-
}];
|
|
485
|
-
const statements = await db.query(`select queryid::text as queryid, query, calls, mean_exec_time from ${view} where calls > ${SLOW_CALLS} and mean_exec_time > ${SLOW_MEAN_MS} order by total_exec_time desc limit 20`);
|
|
486
|
-
const tables = exposed(context);
|
|
487
|
-
return statements.map((statement) => {
|
|
488
|
-
const table = tableIn(statement.query, tables);
|
|
489
|
-
return {
|
|
490
|
-
message: `${Number(statement.mean_exec_time).toFixed(1)} ms mean over ${statement.calls} calls: ${oneLine(statement.query)}`,
|
|
491
|
-
target: `pg_stat_statements:${statement.queryid}`,
|
|
492
|
-
...table ? { object: tableObject(table) } : {}
|
|
493
|
-
};
|
|
494
|
-
});
|
|
495
|
-
} catch (cause) {
|
|
496
|
-
return [{
|
|
497
|
-
severity: "info",
|
|
498
|
-
message: `Could not read pg_stat_statements (${db.describe}): ${errorText(cause)}`
|
|
499
|
-
}];
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
},
|
|
503
|
-
{
|
|
504
|
-
code: "BS225",
|
|
505
|
-
severity: "info",
|
|
506
|
-
title: "pg_stat_statements is not installed",
|
|
507
|
-
description: "`pg_stat_statements` records the time and calls of each statement, which `--stats` (BS209), BS208 and the Supabase query performance report read. Without it there is no record of which queries are slow. Needs a database; saved snapshots skip it.",
|
|
508
|
-
async check(context) {
|
|
509
|
-
const db = live(context);
|
|
510
|
-
if (!db || "skipped" in db) return [];
|
|
511
|
-
if (context.stats && context.codes?.includes("BS209")) return [];
|
|
512
|
-
try {
|
|
513
|
-
if (await statementsView(db)) return [];
|
|
514
|
-
} catch {
|
|
515
|
-
return [];
|
|
516
|
-
}
|
|
517
|
-
return [{
|
|
518
|
-
message: `pg_stat_statements is not installed on the ${db.describe}, so nothing records which statements are slow. Run \`create extension if not exists pg_stat_statements with schema extensions;\` in a migration.`,
|
|
519
|
-
target: "extension:pg_stat_statements"
|
|
520
|
-
}];
|
|
521
|
-
}
|
|
522
|
-
},
|
|
523
|
-
{
|
|
524
|
-
code: "BS212",
|
|
525
|
-
severity: "info",
|
|
526
|
-
title: "RLS plan for a table",
|
|
527
|
-
description: `\`--explain <tables>\` runs \`EXPLAIN (ANALYZE, BUFFERS)\` on \`select * from <table> limit ${EXPLAIN_LIMIT}\` as the given claims, in a transaction that is rolled back. It reports node types, timings and loops, never rows, and warns when a policy SubPlan runs once per row.`,
|
|
528
|
-
async check(context) {
|
|
529
|
-
const request = context.explain;
|
|
530
|
-
if (!request) return [];
|
|
531
|
-
const db = live(context);
|
|
532
|
-
if (!db || "skipped" in db || !db.session) return [{
|
|
533
|
-
severity: "warning",
|
|
534
|
-
message: `--explain needs a direct database connection (local stack, $DATABASE_URL, $SUPABASE_DB_URL or --db-url-stdin)${db && "skipped" in db ? `: ${db.skipped}` : "."}`
|
|
535
|
-
}];
|
|
536
|
-
const who = typeof request.claims["sub"] === "string" ? `${String(request.claims["role"] ?? "anon")} ${request.claims["sub"]}` : String(request.claims["role"] ?? "anon");
|
|
537
|
-
const findings = [];
|
|
538
|
-
for (const name of request.tables) {
|
|
539
|
-
const table = resolveTable(context, name);
|
|
540
|
-
if (!table) {
|
|
541
|
-
findings.push({
|
|
542
|
-
severity: "warning",
|
|
543
|
-
message: `--explain: no table "${name}" in the exposed schemas; qualify tables in other schemas, like better_supabase.memberships.`
|
|
544
|
-
});
|
|
545
|
-
continue;
|
|
546
|
-
}
|
|
547
|
-
try {
|
|
548
|
-
const { summary, functions } = await explainTable(db, table, request.claims);
|
|
549
|
-
const helpers = functions ? functions.length > 0 ? ` Function time: ${functions.map((fn) => {
|
|
550
|
-
const self = fn.selfTime;
|
|
551
|
-
const share = summary.executionMs > 0 ? Math.round(self / summary.executionMs * 100) : 0;
|
|
552
|
-
return `${fn.name} ${self.toFixed(2)} ms over ${plural$1(fn.calls, "call")} (${share}%)`;
|
|
553
|
-
}).join(", ")}.` : " No tracked function ran; inlined SQL functions are part of the plan." : " Function times need `track_functions`, which this role may not set; showing the plan only.";
|
|
554
|
-
const perRow = summary.perRowSubPlans.length > 0 ? ` Per-row SubPlans: ${summary.perRowSubPlans.join(", ")}; wrap the policy's function calls in \`(select ...)\` so they run once as an InitPlan.` : "";
|
|
555
|
-
findings.push({
|
|
556
|
-
...summary.perRowSubPlans.length > 0 ? { severity: "warning" } : {},
|
|
557
|
-
message: `${qualified(table)} as ${who}: ${summary.executionMs.toFixed(2)} ms, ${plural$1(summary.initPlans, "InitPlan")}. Plan: ${summary.nodes.join(" > ")}.${perRow}${helpers}`,
|
|
558
|
-
target: `${qualified(table)}:explain`,
|
|
559
|
-
object: tableObject(table)
|
|
560
|
-
});
|
|
561
|
-
} catch (cause) {
|
|
562
|
-
findings.push({
|
|
563
|
-
severity: "warning",
|
|
564
|
-
message: `--explain ${qualified(table)} failed: ${errorText(cause)}`,
|
|
565
|
-
target: `${qualified(table)}:explain`
|
|
566
|
-
});
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
return findings;
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
];
|
|
573
|
-
//#endregion
|
|
574
291
|
//#region src/cli/doctor/hooks.ts
|
|
575
292
|
/** Claims past this size make every request carry a large cookie and header. */
|
|
576
293
|
const HOOK_CLAIMS_LIMIT = 2048;
|
|
@@ -601,7 +318,7 @@ const splitName = (qualified) => {
|
|
|
601
318
|
name: qualified.slice(dot + 1)
|
|
602
319
|
};
|
|
603
320
|
};
|
|
604
|
-
const escapeRegExp$
|
|
321
|
+
const escapeRegExp$2 = (text) => text.replaceAll(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
605
322
|
/**
|
|
606
323
|
* The claims the provider's hook writes that a second writer would
|
|
607
324
|
* contradict, with the tenant claim it writes to.
|
|
@@ -609,7 +326,7 @@ const escapeRegExp$1 = (text) => text.replaceAll(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
|
609
326
|
function ownedClaims(hook) {
|
|
610
327
|
return [.../* @__PURE__ */ new Set([...hook.ownedClaims, ...hook.tenantClaim ? [hook.tenantClaim] : []])];
|
|
611
328
|
}
|
|
612
|
-
const quotedName = (schema, name) => `(?:"?${escapeRegExp$
|
|
329
|
+
const quotedName = (schema, name) => `(?:"?${escapeRegExp$2(schema)}"?\\s*\\.\\s*)?"?${escapeRegExp$2(name)}"?`;
|
|
613
330
|
const createsFunction = (fn) => new RegExp(`create\\s+(?:or\\s+replace\\s+)?function\\s+${quotedName(fn.schema, fn.name)}\\s*\\(`, "i");
|
|
614
331
|
/** The SQL file that has the provider's hook marker and creates `fn`. */
|
|
615
332
|
function markerFileFor(context, fn) {
|
|
@@ -633,7 +350,7 @@ function wrapsProviderHook(hook, source) {
|
|
|
633
350
|
/** Which of `claims` the hook body writes through `jsonb_set` or `jsonb_build_object`. */
|
|
634
351
|
function writtenClaims(source, claims) {
|
|
635
352
|
return claims.filter((claim) => {
|
|
636
|
-
const name = escapeRegExp$
|
|
353
|
+
const name = escapeRegExp$2(claim);
|
|
637
354
|
return new RegExp(`jsonb_set\\s*\\([^;]*?'\\{\\s*(?:claims\\s*,\\s*)?${name}\\s*\\}'`, "i").test(source) || new RegExp(`jsonb_build_object\\s*\\([^;]*?'${name}'\\s*,`, "i").test(source);
|
|
638
355
|
});
|
|
639
356
|
}
|
|
@@ -1220,6 +937,187 @@ async function fileState(context, file) {
|
|
|
1220
937
|
};
|
|
1221
938
|
}
|
|
1222
939
|
//#endregion
|
|
940
|
+
//#region src/cli/doctor/attachment-subjects.ts
|
|
941
|
+
/** The attachments subjects as the block resolves them, with the per-subject keys each one has. */
|
|
942
|
+
function attachmentSubjects(context) {
|
|
943
|
+
const registry = context.config.subjects;
|
|
944
|
+
const raw = context.config.blocks["attachments"]?.options?.["subjects"];
|
|
945
|
+
return (raw === void 0 ? Object.keys(registry).map((type) => [type, {}]) : Array.isArray(raw) ? raw.filter((type) => typeof type === "string").map((type) => [type, {}]) : isRecord(raw) ? Object.entries(raw).flatMap(([type, entry]) => isRecord(entry) ? [[type, entry]] : []) : []).flatMap(([type, entry]) => {
|
|
946
|
+
const registered = registry[type];
|
|
947
|
+
const table = entry["table"] ?? registered?.table;
|
|
948
|
+
const tenant = entry["tenant"] ?? registered?.tenant ?? "organization_id";
|
|
949
|
+
if (typeof table !== "string" || typeof tenant !== "string") return [];
|
|
950
|
+
const own = isRecord(entry["permissions"]) ? Object.keys(entry["permissions"]) : [];
|
|
951
|
+
const fromRegistry = Object.keys(registered?.permissions ?? {}).filter((key) => key !== "read");
|
|
952
|
+
const subjectRead = typeof entry["permission"] === "string" || registered?.permissions?.["read"] !== void 0 ? ["read"] : [];
|
|
953
|
+
return [{
|
|
954
|
+
type,
|
|
955
|
+
table,
|
|
956
|
+
tenant,
|
|
957
|
+
keys: /* @__PURE__ */ new Set([
|
|
958
|
+
...own,
|
|
959
|
+
...fromRegistry,
|
|
960
|
+
...subjectRead
|
|
961
|
+
])
|
|
962
|
+
}];
|
|
963
|
+
});
|
|
964
|
+
}
|
|
965
|
+
/**
|
|
966
|
+
* Whether `expression` only checks that the caller is a member of the row's
|
|
967
|
+
* tenant: `current_tenant_id()`, a `*_ids_with` or `*member_*ids` function in
|
|
968
|
+
* any schema (the provider's own helpers included), `can('tenant', ...)` or
|
|
969
|
+
* `member_can`, joined by `and`, with a soft-delete `is null` allowed. A
|
|
970
|
+
* permission call passes only with one of `keys`.
|
|
971
|
+
*/
|
|
972
|
+
function tenantOnly(expression, column, keys) {
|
|
973
|
+
const col = `(?:"?\\w+"?\\.)?"?${escape$1(column)}"?(?:::\\w+)?`;
|
|
974
|
+
const key = `'([^']*)'(?:::text)?`;
|
|
975
|
+
const atoms = [
|
|
976
|
+
`${col}\\s*=\\s*\\(?\\s*(?:select\\s+)?better_supabase\\.current_tenant_id\\(\\)(?:\\s+as\\s+\\w+)?`,
|
|
977
|
+
`${col}\\s+in\\s+\\(\\s*select\\s+(?:\\w+\\.)?\\w*_ids_with\\(\\s*${key}\\s*\\)(?:\\s+as\\s+\\w+)?\\s*\\)`,
|
|
978
|
+
`${col}\\s+in\\s+\\(\\s*select\\s+(?:\\w+\\.)?\\w*member_\\w*ids\\(\\s*\\)(?:\\s+as\\s+\\w+)?\\s*\\)`,
|
|
979
|
+
`better_supabase\\.can\\(\\s*'tenant'(?:::text)?\\s*,\\s*${col}\\s*,\\s*${key}\\s*\\)`,
|
|
980
|
+
`better_supabase\\.member_can\\(\\s*${col}\\s*,\\s*${key}\\s*\\)`,
|
|
981
|
+
`(?:"?\\w+"?\\.)?"?\\w+"?\\s+is\\s+null`
|
|
982
|
+
];
|
|
983
|
+
const used = [];
|
|
984
|
+
let rest = expression;
|
|
985
|
+
for (const atom of atoms) rest = rest.replaceAll(new RegExp(atom, "gi"), (_match, key) => {
|
|
986
|
+
if (typeof key === "string") used.push(key);
|
|
987
|
+
return " ";
|
|
988
|
+
});
|
|
989
|
+
return used.every((key) => keys.has(key)) && rest.replaceAll(/\band\b|[()\s]/gi, "") === "";
|
|
990
|
+
}
|
|
991
|
+
/** The top-level `or` branches of `expression`, outer parentheses removed. */
|
|
992
|
+
function branches(expression) {
|
|
993
|
+
let text = expression.trim();
|
|
994
|
+
while (text.startsWith("(") && closingParen(text) === text.length - 1) text = text.slice(1, -1).trim();
|
|
995
|
+
const parts = [];
|
|
996
|
+
let depth = 0;
|
|
997
|
+
let start = 0;
|
|
998
|
+
for (let index = 0; index < text.length; index += 1) {
|
|
999
|
+
const char = text[index];
|
|
1000
|
+
if (char === "(") depth += 1;
|
|
1001
|
+
else if (char === ")") depth -= 1;
|
|
1002
|
+
else if (depth === 0 && /^\sor\s/i.test(text.slice(index, index + 4))) {
|
|
1003
|
+
parts.push(text.slice(start, index));
|
|
1004
|
+
start = index + 4;
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
parts.push(text.slice(start));
|
|
1008
|
+
return parts;
|
|
1009
|
+
}
|
|
1010
|
+
/** The index of the parenthesis closing the one at the start of `text`. */
|
|
1011
|
+
function closingParen(text) {
|
|
1012
|
+
let depth = 0;
|
|
1013
|
+
for (let index = 0; index < text.length; index += 1) if (text[index] === "(") depth += 1;
|
|
1014
|
+
else if (text[index] === ")") {
|
|
1015
|
+
depth -= 1;
|
|
1016
|
+
if (depth === 0) return index;
|
|
1017
|
+
}
|
|
1018
|
+
return -1;
|
|
1019
|
+
}
|
|
1020
|
+
/** Tenant membership alone lets the caller through: the whole check, or one `or` branch of it. */
|
|
1021
|
+
function tenantSuffices(expression, column, keys) {
|
|
1022
|
+
return [expression, ...branches(expression)].some((part) => tenantOnly(part, column, keys));
|
|
1023
|
+
}
|
|
1024
|
+
function attachmentSubjectsOnDefaults(context) {
|
|
1025
|
+
if (!context.config.blockNames.includes("attachments")) return [];
|
|
1026
|
+
const { tables } = catalogOf(context);
|
|
1027
|
+
const overrides = context.config.blocks["attachments"]?.permissions ?? {};
|
|
1028
|
+
const actions = [{
|
|
1029
|
+
action: "read",
|
|
1030
|
+
commands: ["select"],
|
|
1031
|
+
what: "reads"
|
|
1032
|
+
}, {
|
|
1033
|
+
action: "upload",
|
|
1034
|
+
commands: ["insert", "update"],
|
|
1035
|
+
what: "writes"
|
|
1036
|
+
}];
|
|
1037
|
+
return attachmentSubjects(context).flatMap(({ type, table: name, tenant, keys }) => {
|
|
1038
|
+
const [schema, bare] = name.includes(".") ? name.split(".", 2) : ["public", name];
|
|
1039
|
+
const table = tables.find((candidate) => candidate.schema === schema && candidate.name === bare);
|
|
1040
|
+
if (table?.kind !== "table" || !table.rls) return [];
|
|
1041
|
+
const stricter = actions.filter(({ action, commands }) => {
|
|
1042
|
+
if (keys.has(action)) return false;
|
|
1043
|
+
const blockKey = overrides[action] ?? `attachments.${action}`;
|
|
1044
|
+
return commands.some((command) => {
|
|
1045
|
+
const applying = table.policies.filter((policy) => policy.permissive && (policy.command === "all" || policy.command === command) && appliesTo(policy, "authenticated"));
|
|
1046
|
+
if (command !== "select" && applying.length === 0) return false;
|
|
1047
|
+
return !applying.some((policy) => {
|
|
1048
|
+
const expression = command === "select" ? policy.using : policy.check ?? policy.using;
|
|
1049
|
+
return expression !== null && tenantSuffices(expression, tenant, /* @__PURE__ */ new Set([blockKey]));
|
|
1050
|
+
});
|
|
1051
|
+
});
|
|
1052
|
+
});
|
|
1053
|
+
if (stricter.length === 0) return [];
|
|
1054
|
+
const target = `${table.schema}.${table.name}`;
|
|
1055
|
+
return [{
|
|
1056
|
+
message: `Attachments on ${type} use the block-wide ${stricter.map(({ action }) => action).join(" and ")} key, but ${target} checks more than tenant membership for ${stricter.map(({ what: verb }) => verb).join(" and ")}, so any member of the tenant gets the files of a ${type} they can't open. Set ${stricter.map(({ action }) => action === "read" ? `blocks.attachments.options.subjects.${type}.permissions.read` : `subjects.${type}.permissions.upload`).join(" and ")} to the key the table checks.`,
|
|
1057
|
+
target,
|
|
1058
|
+
object: tableObject(table)
|
|
1059
|
+
}];
|
|
1060
|
+
});
|
|
1061
|
+
}
|
|
1062
|
+
//#endregion
|
|
1063
|
+
//#region src/cli/doctor/audit-coverage.ts
|
|
1064
|
+
const escapeRegExp$1 = (value) => value.replaceAll(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1065
|
+
/** `exempt` entries: a glob, or `{ table, reason }` where `table` is a glob. */
|
|
1066
|
+
function exemptions(value) {
|
|
1067
|
+
return (Array.isArray(value) ? value : []).flatMap((entry) => {
|
|
1068
|
+
if (typeof entry === "string") return [{
|
|
1069
|
+
glob: entry,
|
|
1070
|
+
reason: void 0
|
|
1071
|
+
}];
|
|
1072
|
+
if (typeof entry === "object" && entry !== null && "table" in entry && typeof entry.table === "string") {
|
|
1073
|
+
const reason = "reason" in entry && typeof entry.reason === "string" ? entry.reason.trim() : "";
|
|
1074
|
+
return [{
|
|
1075
|
+
glob: entry.table,
|
|
1076
|
+
reason: reason === "" ? void 0 : reason
|
|
1077
|
+
}];
|
|
1078
|
+
}
|
|
1079
|
+
return [];
|
|
1080
|
+
});
|
|
1081
|
+
}
|
|
1082
|
+
/** `exempt` globs (`public.*_archive`): `*` matches any run of characters. */
|
|
1083
|
+
const globs = (value) => (Array.isArray(value) ? value : []).filter((entry) => typeof entry === "string").map((glob) => new RegExp(`^${glob.split("*").map(escapeRegExp$1).join(".*")}$`, "i"));
|
|
1084
|
+
/** The module schemas and the app tables SQL modules adopted, which the audit trigger skips. */
|
|
1085
|
+
function moduleOwned(context) {
|
|
1086
|
+
const schemas = /* @__PURE__ */ new Set(["better_supabase"]);
|
|
1087
|
+
const tables = /* @__PURE__ */ new Set();
|
|
1088
|
+
for (const module of Object.values(context.config.blocks)) {
|
|
1089
|
+
if (module?.schema !== void 0) schemas.add(module.schema);
|
|
1090
|
+
for (const table of Object.values(module?.tables ?? {})) {
|
|
1091
|
+
if (table === null) continue;
|
|
1092
|
+
tables.add(table.includes(".") ? table : `${module?.schema ?? "better_supabase"}.${table}`);
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
return {
|
|
1096
|
+
schemas,
|
|
1097
|
+
tables
|
|
1098
|
+
};
|
|
1099
|
+
}
|
|
1100
|
+
/**
|
|
1101
|
+
* Tables in `config.schemas` without the `bs_audit` trigger, when `audit` is
|
|
1102
|
+
* in `blocks`, and exemptions that give no reason.
|
|
1103
|
+
*/
|
|
1104
|
+
function unauditedTables(context) {
|
|
1105
|
+
if (!context.config.blockNames.includes("audit")) return [];
|
|
1106
|
+
const entries = exemptions(context.config.blocks["audit"]?.options?.["exempt"]);
|
|
1107
|
+
const exempt = globs(entries.map((entry) => entry.glob));
|
|
1108
|
+
const owned = moduleOwned(context);
|
|
1109
|
+
const unaudited = catalogOf(context).tables.filter((table) => table.kind === "table" && table.partitionOf === void 0 && context.config.schemas.includes(table.schema) && !owned.schemas.has(table.schema) && !owned.tables.has(qualified(table)) && !exempt.some((pattern) => pattern.test(qualified(table))) && !table.triggers.some((trigger) => trigger.name.startsWith("bs_audit") || trigger.function.split(".").at(-1) === "audit_row_change")).map((table) => ({
|
|
1110
|
+
message: `${qualified(table)} has no audit trigger, so its inserts, updates and deletes are not in the audit log. Run \`select better_supabase.audit('${qualified(table)}')\` in a schema file, or list it in blocks.audit.options.exempt as \`{ table: '${qualified(table)}', reason: '...' }\`.`,
|
|
1111
|
+
target: qualified(table),
|
|
1112
|
+
object: tableObject(table)
|
|
1113
|
+
}));
|
|
1114
|
+
const unexplained = entries.filter((entry) => entry.reason === void 0).map((entry) => ({
|
|
1115
|
+
message: `blocks.audit.options.exempt lists ${entry.glob} without a reason. Write it as { table: '${entry.glob}', reason: 'why its changes need no audit entry' } so a reviewer can tell an intended gap from a forgotten table.`,
|
|
1116
|
+
target: `blocks.audit.options.exempt:${entry.glob}`
|
|
1117
|
+
}));
|
|
1118
|
+
return [...unaudited, ...unexplained];
|
|
1119
|
+
}
|
|
1120
|
+
//#endregion
|
|
1223
1121
|
//#region src/cli/doctor/modules.ts
|
|
1224
1122
|
/** The non-empty string at a dotted path, as the tenant() plugin reads it. */
|
|
1225
1123
|
function claimAt(claims, path) {
|
|
@@ -1541,35 +1439,6 @@ function duplicateTriggers(context) {
|
|
|
1541
1439
|
}));
|
|
1542
1440
|
}));
|
|
1543
1441
|
}
|
|
1544
|
-
/** `exempt` globs (`public.*_archive`): `*` matches any run of characters. */
|
|
1545
|
-
const globs = (value) => (Array.isArray(value) ? value : []).filter((entry) => typeof entry === "string").map((glob) => new RegExp(`^${glob.split("*").map(escapeRegExp).join(".*")}$`, "i"));
|
|
1546
|
-
/** The module schemas and the app tables SQL modules adopted, which the audit trigger skips. */
|
|
1547
|
-
function moduleOwned(context) {
|
|
1548
|
-
const schemas = /* @__PURE__ */ new Set(["better_supabase"]);
|
|
1549
|
-
const tables = /* @__PURE__ */ new Set();
|
|
1550
|
-
for (const module of Object.values(context.config.blocks)) {
|
|
1551
|
-
if (module?.schema !== void 0) schemas.add(module.schema);
|
|
1552
|
-
for (const table of Object.values(module?.tables ?? {})) {
|
|
1553
|
-
if (table === null) continue;
|
|
1554
|
-
tables.add(table.includes(".") ? table : `${module?.schema ?? "better_supabase"}.${table}`);
|
|
1555
|
-
}
|
|
1556
|
-
}
|
|
1557
|
-
return {
|
|
1558
|
-
schemas,
|
|
1559
|
-
tables
|
|
1560
|
-
};
|
|
1561
|
-
}
|
|
1562
|
-
/** Tables in `config.schemas` without the `bs_audit` trigger, when `audit` is in `blocks`. */
|
|
1563
|
-
function unauditedTables(context) {
|
|
1564
|
-
if (!context.config.blockNames.includes("audit")) return [];
|
|
1565
|
-
const exempt = globs(context.config.blocks["audit"]?.options?.["exempt"]);
|
|
1566
|
-
const owned = moduleOwned(context);
|
|
1567
|
-
return catalogOf(context).tables.filter((table) => table.kind === "table" && context.config.schemas.includes(table.schema) && !owned.schemas.has(table.schema) && !owned.tables.has(qualified(table)) && !exempt.some((pattern) => pattern.test(qualified(table))) && !table.triggers.some((trigger) => trigger.name === "bs_audit" || trigger.function.split(".").at(-1) === "audit_row_change")).map((table) => ({
|
|
1568
|
-
message: `${qualified(table)} has no audit trigger, so its inserts, updates and deletes are not in the audit log. Run \`select better_supabase.audit('${qualified(table)}')\` in a schema file, or list it in blocks.audit.options.exempt.`,
|
|
1569
|
-
target: qualified(table),
|
|
1570
|
-
object: tableObject(table)
|
|
1571
|
-
}));
|
|
1572
|
-
}
|
|
1573
1442
|
/** RLS tables in `config.schemas` without a restrictive `session_active()` policy, when `sessions` is in `blocks`. */
|
|
1574
1443
|
function sessionlessTables(context) {
|
|
1575
1444
|
if (!context.config.blockNames.includes("sessions")) return [];
|
|
@@ -1668,7 +1537,7 @@ const MODULE_RULES = [
|
|
|
1668
1537
|
code: "BS315",
|
|
1669
1538
|
severity: "warning",
|
|
1670
1539
|
title: "Table without an audit trigger",
|
|
1671
|
-
description: "The `audit` module is in `blocks`, and a table in `schemas` has no `bs_audit` trigger (or another trigger that calls `audit_row_change()`), so its changes are not in the audit log. The module's own schemas and the tables SQL modules adopt are skipped; `blocks.audit.options.exempt` lists more, as `schema.table`
|
|
1540
|
+
description: "The `audit` module is in `blocks`, and a table in `schemas` has no `bs_audit` trigger (or another trigger that calls `audit_row_change()`), so its changes are not in the audit log. The module's own schemas and the tables SQL modules adopt are skipped; `blocks.audit.options.exempt` lists more, as `{ table, reason }` entries where `table` is a `schema.table` glob such as `public.*_archive`; a bare glob string still works but gets a finding that asks for the reason. Partitions are covered by their parent.",
|
|
1672
1541
|
check: unauditedTables
|
|
1673
1542
|
},
|
|
1674
1543
|
{
|
|
@@ -1748,6 +1617,13 @@ const MODULE_RULES = [
|
|
|
1748
1617
|
description: "A table in `config.subjects` has row level security disabled. `can_subject` treats a row the caller can read as visible, so without RLS every signed-in user passes the visibility half of the check for every row.",
|
|
1749
1618
|
check: subjectsWithoutRls
|
|
1750
1619
|
},
|
|
1620
|
+
{
|
|
1621
|
+
code: "BS345",
|
|
1622
|
+
severity: "warning",
|
|
1623
|
+
title: "Attachments subject on block-wide keys with stricter RLS",
|
|
1624
|
+
description: "An `attachments` subject has no `read` or `upload` key of its own, so its files are checked with the block-wide `attachments.read` and `attachments.upload` keys, but the subject table's own policies check more than tenant membership: a permission key of their own, an owner or `auth.uid()` comparison, or another condition. Any member of the tenant then reads and uploads files of rows they can't open. Doctor recognizes `current_tenant_id()`, `tenant_ids_with`, `member_<tenant>_ids`, `can('tenant', ...)` and `member_can` with the block's key as tenant membership. Set `subjects.<type>.permissions.upload`, or `blocks.attachments.options.subjects.<type>.permissions` for `read`, to the keys the table checks.",
|
|
1625
|
+
check: attachmentSubjectsOnDefaults
|
|
1626
|
+
},
|
|
1751
1627
|
{
|
|
1752
1628
|
code: "BS335",
|
|
1753
1629
|
severity: "warning",
|
|
@@ -2239,7 +2115,7 @@ const POLICY_RULES = [
|
|
|
2239
2115
|
const dot = name.indexOf(".");
|
|
2240
2116
|
const schema = name.slice(0, dot);
|
|
2241
2117
|
if (schema === "auth" || volatility.get(name) === "immutable") return false;
|
|
2242
|
-
return new RegExp(`(?<!\\bselect\\s+)(?<![\\w."])(?:"?${escape$
|
|
2118
|
+
return new RegExp(`(?<!\\bselect\\s+)(?<![\\w."])(?:"?${escape$1(schema)}"?\\.)?"?${escape$1(name.slice(dot + 1))}"?\\s*\\(\\s*\\)`, "i").test(text);
|
|
2243
2119
|
});
|
|
2244
2120
|
if (bare.length === 0) return [];
|
|
2245
2121
|
return [{
|
|
@@ -2295,7 +2171,7 @@ const APP_COLUMN_FORMAT = {
|
|
|
2295
2171
|
*/
|
|
2296
2172
|
const skipsNullKeys = (predicate, columns) => {
|
|
2297
2173
|
if (!predicate) return false;
|
|
2298
|
-
return predicate.split(/\s+AND\s+/i).every((part) => columns.some((column) => new RegExp(`^\\(*\\s*"?${escape$
|
|
2174
|
+
return predicate.split(/\s+AND\s+/i).every((part) => columns.some((column) => new RegExp(`^\\(*\\s*"?${escape$1(column)}"?\\s+IS\\s+NOT\\s+NULL\\s*\\)*$`, "i").test(part.trim())));
|
|
2299
2175
|
};
|
|
2300
2176
|
/** Whether the first `columns.length` columns of an index are exactly `columns`, in any order, and it holds every row that references something. */
|
|
2301
2177
|
const covers = (index, columns) => (!index.partial || skipsNullKeys(index.predicate, columns)) && index.columns.length >= columns.length && index.columns.slice(0, columns.length).every((column) => columns.includes(column));
|
|
@@ -2386,7 +2262,7 @@ const SCHEMA_DESIGN_RULES = [
|
|
|
2386
2262
|
if (table.kind !== "table") return [];
|
|
2387
2263
|
const column = table.columns.find((entry) => SOFT_DELETE.test(entry.name) && entry.nullable);
|
|
2388
2264
|
if (!column) return [];
|
|
2389
|
-
const isNull = new RegExp(`"?${escape$
|
|
2265
|
+
const isNull = new RegExp(`"?${escape$1(column.name)}"?\\s+IS\\s+NULL`, "i");
|
|
2390
2266
|
if (table.indexes.some((index) => index.partial && (index.predicate === void 0 || index.predicate !== null && isNull.test(index.predicate)))) return [];
|
|
2391
2267
|
return [{
|
|
2392
2268
|
message: `${qualified(table)} soft-deletes with ${column.name}, but no index has \`where ${column.name} is null\`. Index the live rows you list, for example \`create index on ${qualified(table)} (created_at desc) where ${column.name} is null;\`.`,
|
|
@@ -2411,7 +2287,7 @@ const SCHEMA_DESIGN_RULES = [
|
|
|
2411
2287
|
return table.columns.filter((column) => {
|
|
2412
2288
|
if (!column.isArray && column.udt !== "jsonb") return false;
|
|
2413
2289
|
if (table.indexes.some((index) => index.columns[0] === column.name && (index.method === void 0 || index.method === "gin"))) return false;
|
|
2414
|
-
const used = new RegExp(`"?${escape$
|
|
2290
|
+
const used = new RegExp(`"?${escape$1(column.name)}"?\\s*${CONTAINS}|${CONTAINS}\\s*[\\w."]*\\b${escape$1(column.name)}\\b`);
|
|
2415
2291
|
return filtered.has(column.name) || used.test(own) || functions.includes(table.name) && used.test(functions);
|
|
2416
2292
|
}).map((column) => ({
|
|
2417
2293
|
message: `${qualified(table)}.${column.name} is filtered by containment but has no GIN index, so each query scans the table. Run \`create index on ${qualified(table)} using gin (${column.name}${column.udt === "jsonb" ? " jsonb_path_ops" : ""});\`${column.udt === "jsonb" ? " (`jsonb_path_ops` supports `@>` only; drop it for `?`)" : ""}.`,
|
|
@@ -2732,7 +2608,7 @@ const RULES = [
|
|
|
2732
2608
|
return exposed(context).flatMap((table) => {
|
|
2733
2609
|
const options = configFor(context.config.tables, table.schema, table.name);
|
|
2734
2610
|
if (options?.exclude) return [];
|
|
2735
|
-
const granted = (role) => new Set(table.grants.filter((grant) => grant.role === role || grant.role === "PUBLIC").flatMap((grant) => grant.privileges.map((privilege) => privilege.toLowerCase())));
|
|
2611
|
+
const granted = (role) => new Set([...table.grants, ...table.columnGrants ?? []].filter((grant) => grant.role === role || grant.role === "PUBLIC").flatMap((grant) => grant.privileges.map((privilege) => privilege.toLowerCase())));
|
|
2736
2612
|
if (options?.serviceRole) {
|
|
2737
2613
|
const fromPublic = table.grants.some((grant) => grant.role === "PUBLIC" && grant.privileges.length > 0);
|
|
2738
2614
|
return ["anon", "authenticated"].flatMap((role) => {
|
|
@@ -3147,7 +3023,8 @@ const RULES = [
|
|
|
3147
3023
|
...WORKFLOW_BUILDER_RULES,
|
|
3148
3024
|
...FLAG_RULES,
|
|
3149
3025
|
...REALTIME_RULES,
|
|
3150
|
-
...ADOPTION_RULES
|
|
3026
|
+
...ADOPTION_RULES,
|
|
3027
|
+
...MIGRATION_SAFETY_RULES
|
|
3151
3028
|
].sort((a, b) => byCodePoint(a.code, b.code));
|
|
3152
3029
|
const RULE_CODES = RULES.map((rule) => rule.code);
|
|
3153
3030
|
async function runRules(context, rules = RULES) {
|