permdock 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -3
- package/dist/{2020-C9VN-x8c.js → 2020-CJbO8Bvz.js} +1 -3
- package/dist/a2a/index.d.ts +7 -7
- package/dist/a2a/index.js +9 -9
- package/dist/action-result-CL-QCITA.d.ts +19 -0
- package/dist/{adapter-context-CRhqyzCk.js → adapter-context-CIQpQxbE.js} +8 -2
- package/dist/{adoption-scan-DCYe60Pi.js → adoption-scan-BLs67P1l.js} +5 -5
- package/dist/agent/index.d.ts +3 -3
- package/dist/agent/index.js +1 -1
- package/dist/ai-sdk/index.d.ts +31 -10
- package/dist/ai-sdk/index.js +22 -12
- package/dist/{app-data-MuyzVqX8.js → app-data-UNNm07jV.js} +10 -7
- package/dist/{approval-header-CJACtHkv.js → approval-header-8QV6MU4H.js} +6 -3
- package/dist/{approval-prompt-Dg5LeAcT.js → approval-prompt-B8hQY69x.js} +5 -6
- package/dist/{approval-prompt-DvSSPQJX.d.ts → approval-prompt-PYagyQUj.d.ts} +13 -11
- package/dist/approvals/index.d.ts +5 -5
- package/dist/approvals/index.js +7 -7
- package/dist/{approvals-p1PGoVjb.js → approvals-DnIBTuXE.js} +128 -78
- package/dist/{approvers-CqPOLD-o.js → approvers-B4r0N_Uz.js} +8 -2
- package/dist/{arazzo-41WuzHou.js → arazzo-3RhGfkAK.js} +2 -2
- package/dist/{arazzo-CaUVBn7D.js → arazzo-B5-ulWif.js} +6 -6
- package/dist/{args-IIolxxKA.js → args-0FrVs5EH.js} +125 -8
- package/dist/astro/index.d.ts +30 -12
- package/dist/astro/index.js +2 -2
- package/dist/{audience-DabClFLQ.js → audience-BAkBDMqn.js} +8 -8
- package/dist/{auth-DRLEizbL.js → auth--yPyZNgr.js} +21 -10
- package/dist/authzen/index.d.ts +171 -25
- package/dist/authzen/index.js +321 -149
- package/dist/{automation-BNM3TtDo.d.ts → automation-DqEoWHBc.d.ts} +42 -32
- package/dist/{automation-DVjOckjV.js → automation-x3KEUusw.js} +22 -21
- package/dist/base-url-BQbddZO5.js +9 -0
- package/dist/better-auth/index.d.ts +2 -2
- package/dist/better-auth/index.js +13 -7
- package/dist/better-supabase/index.d.ts +392 -220
- package/dist/better-supabase/index.js +293 -152
- package/dist/{bind-DOyrv6zi.d.ts → bind-Cp2hBHzP.d.ts} +27 -12
- package/dist/{bind-CAvgUuKs.js → bind-D_sZSVA3.js} +22 -10
- package/dist/{body-CH5of8Ne.js → body-CJQwYVa8.js} +3 -3
- package/dist/{body-text-QcXok_SI.js → body-text-DQhcmqdY.js} +8 -4
- package/dist/{boundary-BM8a_P6E.js → boundary-BV3O1eud.js} +8 -2
- package/dist/{boundary-BmHxVH1J.d.ts → boundary-C9ck-3uK.d.ts} +13 -4
- package/dist/{budget-NbEtbJC_.js → budget-BELja5A9.js} +6 -3
- package/dist/{budget-JqcRqyhK.d.ts → budget-hYsPz_yE.d.ts} +6 -3
- package/dist/{build-instance-Bu_eDqYw.js → build-instance-CNWaYJyr.js} +3 -3
- package/dist/{canonical-json-BC8_nMTw.js → canonical-json-DwilZ1iB.js} +6 -3
- package/dist/{capability-N1K9IpqS.js → capability-BqX94r07.js} +31 -25
- package/dist/{capability-Drg-1YhL.d.ts → capability-ChuiONQU.d.ts} +41 -29
- package/dist/{casbin-Dyu2gnUD.js → casbin-H0rKxBx2.js} +16 -8
- package/dist/{casbin-Cr7RLtA3.js → casbin-cbSbhT_k.js} +2 -2
- package/dist/{casl-64gpT-8x.js → casl-C4OINZHI.js} +2 -2
- package/dist/{casl-DjEDhTCP.js → casl-CHHoCldP.js} +19 -10
- package/dist/catalog/index.d.ts +104 -23
- package/dist/catalog/index.js +117 -8
- package/dist/{catalog-HD2gf5mY.js → catalog-BFpz2EmT.js} +57 -26
- package/dist/{catalog-DZVbrF-z.js → catalog-DCspHDc8.js} +3 -3
- package/dist/{catalog-doc-Cdn7-0pQ.js → catalog-doc-DjMKzJp9.js} +53 -16
- package/dist/{catalog-fingerprint-CCP0-yQS.js → catalog-fingerprint-e6aCWosn.js} +19 -15
- package/dist/catalog-mRQQQhNK.js +1 -0
- package/dist/catalog-operations-Dadrl7Z-.js +60 -0
- package/dist/{create-CQWIpUG-.js → challenge-DImNcR7B.js} +157 -39
- package/dist/chat/index.d.ts +1 -1
- package/dist/chat/index.js +13 -10
- package/dist/chat-sdk/index.d.ts +44 -26
- package/dist/chat-sdk/index.js +17 -17
- package/dist/checks-CGkP3Z7A.js +40 -0
- package/dist/{claims-map-7oQ3ue4X.js → claims-map-CKkoAAYF.js} +5 -2
- package/dist/{claims-map-Ca-QX8C6.d.ts → claims-map-D1Pb5oRq.d.ts} +8 -5
- package/dist/claude-agent/index.d.ts +6 -6
- package/dist/claude-agent/index.js +6 -3
- package/dist/clerk/index.d.ts +11 -7
- package/dist/clerk/index.js +6 -6
- package/dist/cli/bin.js +4 -4
- package/dist/cli/index.d.ts +82 -7
- package/dist/cli/index.js +6 -6
- package/dist/{clients-C7zLFuWT.d.ts → clients-C_NOET3z.d.ts} +5 -5
- package/dist/{clients-DjU5ABMy.js → clients-DYr3U86j.js} +3 -3
- package/dist/cloud/index.d.ts +186 -38
- package/dist/cloud/index.js +293 -31
- package/dist/{cloud-ytQ3uviA.js → cloud-BFlGMaak.js} +5 -6
- package/dist/{codemod-5mpSpnUY.js → codemod-DLQ9Zpo4.js} +3 -4
- package/dist/{codemod-ua2hHy7w.js → codemod-DWSN2erG.js} +523 -201
- package/dist/collect-B5BL3klN.js +1 -0
- package/dist/{collect-mLTY4nwb.js → collect-B7ZFAJU3.js} +36 -64
- package/dist/{collect-Ci6akVwH.js → collect-Bzv3le0A.js} +6 -6
- package/dist/{compare-pfyVnBjE.js → compare-DTfyUunF.js} +2 -2
- package/dist/compile/index.d.ts +2 -2
- package/dist/compile/index.js +1 -1
- package/dist/{compile-1bsAezL0.d.ts → compile-BFzysW3o.d.ts} +36 -12
- package/dist/{compile-CMqMx_IN.js → compile-EzEMB-7v.js} +77 -33
- package/dist/{completion-BTFrHZhX.js → completion-saoYiRFO.js} +17 -8
- package/dist/config-BwPBfN0t.js +108 -0
- package/dist/{config-Bj2Ixq3d.js → config-DBeXXmBF.js} +2 -2
- package/dist/{config-report-DSpsLpCE.js → config-report-BipSWA6V.js} +9 -6
- package/dist/config-shape-ykV0Vm2n.js +134 -0
- package/dist/{connection-DjhIJSs2.js → connection-B72dg5Q2.js} +23 -22
- package/dist/connector-schema-CYLQNMYq.js +434 -0
- package/dist/{context-B_u3_bDJ.js → context-BnIzxTNE.js} +4 -3
- package/dist/convex/index.d.ts +13 -7
- package/dist/convex/index.js +9 -6
- package/dist/core-H-mbhpZc.js +341 -0
- package/dist/core-hWIARPDz.d.ts +206 -0
- package/dist/{create-CBMmFie-.d.ts → create-BSNrVuxh.d.ts} +87 -34
- package/dist/{create-B30OMUOJ.d.ts → create-BVq1lNQE.d.ts} +49 -28
- package/dist/{create-D_NmPOdH.d.ts → create-CM1FciYG.d.ts} +37 -29
- package/dist/{create-CGm28gyI.js → create-Cq4Uox0f.js} +13 -9
- package/dist/{create-DCF2SvoT.js → create-_noSrY1T.js} +15 -21
- package/dist/{credential-BcoiejpY.js → credential-CyyyvCsL.js} +42 -39
- package/dist/{credentials-DPyHmYz5.js → credentials-CdDxp7jN.js} +6 -6
- package/dist/{deciding-columns-Sq12mEA6.js → deciding-columns-NB4wcyBf.js} +13 -2
- package/dist/{delegation-j6-rc37o.js → delegation-CDB6_keF.js} +31 -22
- package/dist/delivery/index.d.ts +5 -5
- package/dist/delivery/index.js +6 -5
- package/dist/{delivery-DCAgNyCn.js → delivery-BupfvJIV.js} +81 -20
- package/dist/{delivery-event-xX4obB8F.js → delivery-event-JioK5YbS.js} +6 -6
- package/dist/denied-text-CHNlVInN.d.ts +22 -0
- package/dist/{describe-BybMRY7A.js → describe-Bb4hGK5d.js} +6 -5
- package/dist/{describe-B5qgDvEW.d.ts → describe-ByS9LgHK.d.ts} +5 -5
- package/dist/{device-BARQ8eYG.js → device-BwbJNmb2.js} +11 -8
- package/dist/{diff-CmuSD3vc.js → diff-CN8IYhC_.js} +2 -2
- package/dist/{diff-3jbx6Rm4.js → diff-iZWV65nC.js} +23 -14
- package/dist/{digest-B3kc_PgQ.d.ts → digest-8Yx2CchM.d.ts} +3 -3
- package/dist/{doctor-BdZw53-k.js → doctor-CHD1M9R5.js} +485 -141
- package/dist/{doctor-3ZqNHX_G.js → doctor-D3wo-yuz.js} +4 -4
- package/dist/drizzle/index.d.ts +33 -19
- package/dist/drizzle/index.js +17 -9
- package/dist/elysia/index.d.ts +17 -11
- package/dist/elysia/index.js +5 -5
- package/dist/{errors-BKy0EfhN.js → errors-B6R_lg2a.js} +13 -4
- package/dist/{errors-BWXBMaKK.d.ts → errors-CHwoRRpB.d.ts} +4 -1
- package/dist/{errors-CWTY6uih.js → errors-Vpu6rKHl.js} +14 -10
- package/dist/{errors-DH5QEGXh.d.ts → errors-zi_4T-rx.d.ts} +22 -6
- package/dist/{evaluate-CNClBvcj.js → evaluate-Dd8Ta0Ie.js} +185 -80
- package/dist/{evaluations-beAooV0n.js → evaluations-IBceAeKT.js} +41 -20
- package/dist/{evaluations-C_1vdSZc.d.ts → evaluations-z8dQFDaN.d.ts} +12 -6
- package/dist/eve/index.d.ts +9 -6
- package/dist/eve/index.js +4 -4
- package/dist/{event-time-CsegxXxB.js → event-time-BGy48400.js} +8 -4
- package/dist/{expiry-D4_YKRKD.js → expiry-6XByK0dm.js} +8 -5
- package/dist/express/index.d.ts +9 -6
- package/dist/express/index.js +9 -6
- package/dist/fastify/index.d.ts +16 -10
- package/dist/fastify/index.js +8 -5
- package/dist/{fetch-adapter-Dw0MTS3D.d.ts → fetch-adapter-C1DCvpqV.d.ts} +9 -6
- package/dist/{fetch-adapter-DD_gfmrC.js → fetch-adapter-JL43jD3E.js} +14 -11
- package/dist/fields-D0vUI6dq.js +498 -0
- package/dist/{files-C5ZI27eV.js → files-B3AA05f1.js} +21 -5
- package/dist/{files-D_JIzUrP.js → files-BSjrtIHw.js} +11 -4
- package/dist/{fixtures-B7XrLeY7.js → fixtures-A1_sp_tR.js} +15 -6
- package/dist/{flags-C3DktBDY.js → flags-DXjoTVbS.js} +2 -2
- package/dist/{freeze-CrU8nQeX.js → freeze-jjan0lCv.js} +4 -1
- package/dist/{from-snapshot-CTCMsFZk.js → from-snapshot-DCakWRsr.js} +26 -16
- package/dist/gen-B5kvbAoZ.js +58 -0
- package/dist/gen-DWCYcMQM.js +827 -0
- package/dist/generate-CRVV5V7l.js +165 -0
- package/dist/generate-CezbCaTI.js +275 -0
- package/dist/{grantee-hxrUsbpM.js → grantee-Dke-9rd1.js} +4 -4
- package/dist/{grantee-conditions-CcXf8hMM.js → grantee-conditions-BrYPe-w0.js} +12 -12
- package/dist/{grantee-match-DbENBHLB.js → grantee-match-7RZZvoT_.js} +12 -6
- package/dist/{graph-sql-B-dsAT6j.d.ts → graph-sql-BwFC4Qjs.d.ts} +3 -3
- package/dist/h3/index.d.ts +10 -7
- package/dist/h3/index.js +3 -3
- package/dist/headers-B9jQxjtW.d.ts +10 -0
- package/dist/{helpers-CBYVMjwh.js → helpers-DJicaG6f.js} +40 -28
- package/dist/hono/index.d.ts +16 -10
- package/dist/hono/index.js +5 -5
- package/dist/{hosted-BPk51-kX.d.ts → hosted-Cmtxogd0.d.ts} +44 -20
- package/dist/{hosted-B46-5LYE.js → hosted-D0IzESu_.js} +68 -25
- package/dist/{http-ujKm0JXE.js → http-DH94eh6f.js} +4 -4
- package/dist/{http-BBoKefeS.js → http-DKLXrFGk.js} +13 -7
- package/dist/{http-DXJ37RDA.js → http-DOL33cO0.js} +11 -8
- package/dist/{import-wyqXUyjm.js → import-CST57XLp.js} +64 -51
- package/dist/{import-CNV7I2Dw.js → import-_YqhhwvX.js} +6 -6
- package/dist/{index-B8YjkEZ4.d.ts → index-B8s204GL.d.ts} +64 -52
- package/dist/{index-Ch8LpNDp.d.ts → index-BT5-1VsX.d.ts} +64 -25
- package/dist/{index-DuWxc5dt.d.ts → index-BW_0MZOS.d.ts} +388 -149
- package/dist/index-BhxEUY9J.d.ts +233 -0
- package/dist/index-Bv5iXPqU.d.ts +210 -0
- package/dist/{index-C-6Letxg.d.ts → index-_9UiQIkt.d.ts} +164 -77
- package/dist/index.d.ts +22 -21
- package/dist/index.js +35 -33
- package/dist/{init-GG6Jh8HD.js → init-Dz_PsHdv.js} +5 -5
- package/dist/{init-DeMYsnYJ.js → init-cE3A8aXq.js} +10 -10
- package/dist/{instance-options-BsVpyGIk.d.ts → instance-options-B0KXqTrJ.d.ts} +4 -4
- package/dist/{instance-snapshot-BOEhcqIF.js → instance-snapshot--JWiTrvO.js} +81 -56
- package/dist/{instant-BluqDvyS.js → instant-DK3Iz83e.js} +2 -2
- package/dist/{internals-Dk8A8fX3.js → internals-B3IgHrvo.js} +6 -3
- package/dist/{json-schema-B-vAwlde.js → json-schema-BPGa-RjQ.js} +9 -3
- package/dist/{json-schema-CN_iLFH2.d.ts → json-schema-BfXgnRNT.d.ts} +4 -4
- package/dist/jwt/index.d.ts +125 -17
- package/dist/jwt/index.js +157 -16
- package/dist/{kernel-D0NVb1cK.js → kernel-C-fYydV2.js} +151 -16
- package/dist/kysely/index.d.ts +49 -33
- package/dist/kysely/index.js +9 -7
- package/dist/{live-options-BaAFCIiu.js → live-options-BBIT68le.js} +2 -2
- package/dist/{load-DFS_ry0W.js → load-DjSU5KXO.js} +6 -6
- package/dist/load-Dm0pSYH3.js +1 -0
- package/dist/{login-Dfe5RlYk.js → login-D-8tMqzo.js} +4 -4
- package/dist/{login-imhuwvn3.js → login-DplQ0s84.js} +18 -15
- package/dist/{manifest-dvL2XEe1.js → manifest-Cgiq5oqc.js} +67 -37
- package/dist/{manifest-mx5ghSFM.d.ts → manifest-CzzWtnAb.d.ts} +144 -28
- package/dist/{manifest-schema-C0kK_8V0.js → manifest-schema-2r37XRhD.js} +80 -9
- package/dist/{manifest-C8IzW3Do.js → manifest-wg8WkkpD.js} +11 -7
- package/dist/{map-claims-D3oRmTk0.js → map-claims-BNWCJtmP.js} +27 -18
- package/dist/{map-error-Dr70oA_3.js → map-error-pasIGqMT.js} +7 -7
- package/dist/{markers-C6joDI3o.js → markers-BeHZ4x9Q.js} +20 -5
- package/dist/mcp/index.d.ts +154 -47
- package/dist/mcp/index.js +200 -41
- package/dist/{migrate-CIq4-E9F.js → migrate-B7oP_sQU.js} +102 -31
- package/dist/module-values-BJTBdo6y.js +107 -0
- package/dist/nest/index.d.ts +23 -13
- package/dist/nest/index.js +18 -11
- package/dist/next/client.d.ts +5 -2
- package/dist/next/client.js +1 -1
- package/dist/next/index.d.ts +72 -26
- package/dist/next/index.js +110 -6
- package/dist/next/plugin.d.ts +1 -1
- package/dist/next/plugin.js +4 -3
- package/dist/node/index.d.ts +5 -5
- package/dist/node/index.js +3 -3
- package/dist/{ocsf-BFp-PZZA.js → ocsf-TcjRBgIs.js} +15 -5
- package/dist/openai/index.d.ts +13 -7
- package/dist/openai/index.js +3 -3
- package/dist/openapi/index.d.ts +61 -30
- package/dist/openapi/index.js +2 -2
- package/dist/{openapi-B7HZ0f-r.js → openapi-BOsx0xn9.js} +34 -24
- package/dist/{openapi-C4dDTVEd.js → openapi-CBZUhA3l.js} +4 -5
- package/dist/{openapi-DD1SV-5-.js → openapi-VeHHU2l9.js} +23 -14
- package/dist/{operation-findings-DgATDpvh.js → operation-findings-CXtFzlKJ.js} +3 -3
- package/dist/{operations-X0VM7F3m.d.ts → operations-Ci_rT6Uo.d.ts} +10 -7
- package/dist/orpc/index.d.ts +68 -14
- package/dist/orpc/index.js +62 -13
- package/dist/otel/index.d.ts +7 -4
- package/dist/otel/index.js +8 -5
- package/dist/output-files-BHOIlrfD.js +1 -0
- package/dist/{output-files-DhRBBE4n.js → output-files-BIQ_9pIs.js} +29 -17
- package/dist/{output-1im__-08.js → output-tkju6U7R.js} +15 -7
- package/dist/ownership-B4L59T9u.js +1054 -0
- package/dist/parse-1_ZheTW5.js +151 -0
- package/dist/parse-local-manifest-BQhTlLQS.d.ts +10 -0
- package/dist/parse-local-manifest-DEiCF4ah.js +69 -0
- package/dist/{parse-request-D_tUXG6M.js → parse-request-CwCZpyjV.js} +7 -8
- package/dist/{paths-DXSHAMIa.js → paths-CUvURzHp.js} +4 -1
- package/dist/pdp/index.d.ts +9 -6
- package/dist/pdp/index.js +23 -12
- package/dist/{peer-CRvC7Hg1.js → peer-C9LvBCcb.js} +1 -1
- package/dist/peer-Q0fuZ6hx.js +982 -0
- package/dist/{permdock-SV8ZINYT.d.ts → permdock-B6Sf4T_S.d.ts} +270 -117
- package/dist/{permdock-BrAscV28.js → permdock-L-_I_3zP.js} +226 -74
- package/dist/{permission-registry-Br4jSNVi.js → permission-registry-B8tYxPIt.js} +24 -11
- package/dist/{vocabulary-CN8H_9UF.d.ts → permission-types-CAY-GU7e.d.ts} +130 -104
- package/dist/{permissions-u_KHg-sN.d.ts → permissions-Bx6UI8n1.d.ts} +6 -2
- package/dist/{permissions-B-wCP5ZC.js → permissions-CVXmRILq.js} +3 -3
- package/dist/{permissions-BPxlwVhN.js → permissions-mDcTWoBs.js} +8 -5
- package/dist/pg-DQTqRrou.js +60 -0
- package/dist/{pins-8ILTftC9.js → pins-nqarl3oE.js} +4 -1
- package/dist/pkce-CnmmYqUZ.js +21 -0
- package/dist/{policy-77FSAq_V.d.ts → policy-Ba4bDhaj.d.ts} +5 -5
- package/dist/{policy-DbM5YYtV.js → policy-CLQ8__GF.js} +49 -20
- package/dist/{policy-from-catalog-C2gMa2Dj.js → policy-from-catalog-CJgOm6aq.js} +28 -25
- package/dist/{policy-module-CTlwMvLI.js → policy-module-xym9fnSq.js} +12 -6
- package/dist/{policy-types-n0uRTsW8.d.ts → policy-types-CCiDRZBH.d.ts} +802 -334
- package/dist/postgres-store-DcyrPS-r.js +1028 -0
- package/dist/{postgrest-DAjUkF9w.js → postgrest-D4nuPXIQ.js} +88 -36
- package/dist/{postgrest-CEgRbefE.d.ts → postgrest-DicQyqm-.d.ts} +60 -30
- package/dist/powersync-DHNQX06W.js +1117 -0
- package/dist/{powersync-DISt6SUe.js → powersync-DXqGuq9A.js} +3 -3
- package/dist/powersync-Djf-zCpB.js +1 -0
- package/dist/preset/index.d.ts +38 -28
- package/dist/preset/index.js +1 -1
- package/dist/{preset-DZdU0tne.js → preset-BjLzeFpp.js} +58 -34
- package/dist/{principal-source-pHneukrx.js → principal-source-C6N60GtM.js} +10 -10
- package/dist/prisma/index.d.ts +69 -41
- package/dist/prisma/index.js +21 -17
- package/dist/{problem-CTviyH5L.js → problem-BVLHFK33.js} +41 -21
- package/dist/{problem-details-cn5X30gZ.js → problem-details-CLDgX1KV.js} +13 -4
- package/dist/{problem-types-CJ2325SZ.js → problem-types-DSsRfONQ.js} +4 -1
- package/dist/prompt-BYc6drYW.js +938 -0
- package/dist/protected-action-BE7N_Luo.d.ts +58 -0
- package/dist/protected-action-DUYqb-Ma.js +80 -0
- package/dist/{protected-BlF0F6wL.js → protected-action-QEA8arRB.js} +48 -14
- package/dist/{provider-B1al-AZz.js → provider-C55OGXJ7.js} +5 -4
- package/dist/{provider-DILL9oPK.d.ts → provider-DXfq5c2d.d.ts} +1 -1
- package/dist/{provider-store-DM6DNcta.js → provider-store-CaTv00tr.js} +13 -9
- package/dist/pull-B65ndFNZ.js +1 -0
- package/dist/{pull-jEwbf80J.js → pull-CwpGaQSi.js} +12 -11
- package/dist/{push-BD4f15co.js → push-DgssgzkK.js} +62 -16
- package/dist/{pushed-policy-DCW91KQU.d.ts → pushed-policy-D1Eoi6NM.d.ts} +12 -6
- package/dist/{pushed-policy-CqtxkV4G.js → pushed-policy-ITwYKvvH.js} +10 -7
- package/dist/react/index.d.ts +9 -8
- package/dist/react/index.js +7 -6
- package/dist/react/provider-client.d.ts +1 -1
- package/dist/react/provider-client.js +1 -1
- package/dist/react-native/index.d.ts +104 -51
- package/dist/react-native/index.js +394 -67
- package/dist/{refs-K6eWUJ0H.js → refs-C8BKxc_e.js} +17 -3
- package/dist/{relation-walk-3OyDBF0S.js → relation-walk-DK_gkgL7.js} +12 -9
- package/dist/{relations-BnCWnJGI.js → relations-BxvRvDHK.js} +3 -3
- package/dist/{replay-Du1tJjG7.js → replay-BU09ad4L.js} +1 -1
- package/dist/{replay-Bkm-Ne4l.d.ts → replay-DNftIb_R.d.ts} +1 -1
- package/dist/{request-context-C81Pip9n.js → request-context-C25ilqiJ.js} +8 -8
- package/dist/{request-schema-CMreVuFM.js → request-schema-DhX7UbfQ.js} +4 -1
- package/dist/resend/index.d.ts +34 -28
- package/dist/resend/index.js +29 -29
- package/dist/resolve-names-CF7xXLSG.js +201 -0
- package/dist/{resource-relations-D_jw0BFx.js → resource-relations-8-pCScBO.js} +18 -9
- package/dist/{retire-CALjIQ7e.js → retire-B2xffQgY.js} +15 -6
- package/dist/{revocations-R07lFBnX.d.ts → revocations-BaUXHM1N.d.ts} +6 -3
- package/dist/{rls-DTvYd-lI.js → rls-CNEH2_BG.js} +743 -624
- package/dist/{rls-BAqP4q66.js → rls-Ca8Jz9b5.js} +41 -10
- package/dist/{role-builder-uWQZ4v84.js → role-builder-BK2-T6oD.js} +41 -20
- package/dist/rolldown-runtime-C3I60J0A.js +4 -0
- package/dist/{row-conditions-h2HythXQ.js → row-conditions-BAGHOmVq.js} +4 -3
- package/dist/{rpc-VSl5ylaQ.js → rpc-fNqAIqQk.js} +8 -5
- package/dist/{run-CUKuz0A8.js → run-Bz26OTfO.js} +26 -23
- package/dist/run-D-JE8QWb.js +1 -0
- package/dist/{run-ticket-DocwaTKn.d.ts → run-ticket-DbWI9f99.d.ts} +33 -13
- package/dist/{run-ticket-sxFI6LAk.js → run-ticket-Dv7aF7Dk.js} +29 -8
- package/dist/{runtime-D3VTAiCA.js → runtime-BGnrOkVH.js} +5 -2
- package/dist/{saas-BCXRuXca.js → saas-iWnUdwCt.js} +42 -29
- package/dist/{scan-qvOe0hS3.js → scan-DCj1KQfn.js} +1 -1
- package/dist/{schema-B4v0Qrac.js → schema-BOJjqlWL.js} +3 -2
- package/dist/{schema-yLuBWWsh.js → schema-Dst9I9Gs.js} +9 -5
- package/dist/scim/index.d.ts +3 -2
- package/dist/scim/index.js +3 -1
- package/dist/scim-D8YupzX1.js +44 -0
- package/dist/{scim-ClHtpyV3.js → scim-jJBJ7g1Z.js} +35 -551
- package/dist/{scopes-CUPSjo9q.js → scopes-0Up_UA2t.js} +42 -24
- package/dist/server/index.d.ts +12 -12
- package/dist/server/index.js +13 -13
- package/dist/{server-C3WXAHZj.js → server-3cVlTLde.js} +31 -31
- package/dist/{server-types-CKQiCnON.d.ts → server-types-CIlpSA2G.d.ts} +81 -46
- package/dist/{sha256-D9ihqmvd.js → sha256-C-4WXKIu.js} +4 -3
- package/dist/{shared-BAK8t4Uo.js → shared-Afctg7B0.js} +100 -61
- package/dist/{shared-DvvFzYXe.js → shared-l0oGGetg.js} +9 -6
- package/dist/{signals-D3NcTKUS.js → signals-B1vHR3fN.js} +2 -2
- package/dist/{sink-BEZSlMS_.js → sink-D9_vh372.js} +32 -21
- package/dist/{sink-4-eQIRWf.d.ts → sink-Dvi7YZG_.d.ts} +44 -20
- package/dist/{skills-B6lVdD_W.js → skills-Bjj7BNEQ.js} +16 -12
- package/dist/{skills-CTYwkl44.js → skills-OuoMR49L.js} +3 -3
- package/dist/{snapshot-B7DkYg6g.js → snapshot-CXlzi69u.js} +21 -18
- package/dist/{snapshot-cache-PXI-vGpY.d.ts → snapshot-cache-BAXZ0KOp.d.ts} +21 -12
- package/dist/{snapshot-cache-DZHQ0KF6.js → snapshot-cache-Bx_4xC_6.js} +14 -11
- package/dist/solid/index.d.ts +55 -15
- package/dist/solid/index.js +46 -12
- package/dist/solid-start/index.d.ts +30 -12
- package/dist/solid-start/index.js +3 -3
- package/dist/sources-B1Os_YUu.d.ts +312 -0
- package/dist/{sources-vs5dGOsS.js → sources-CMAM-2A3.js} +156 -51
- package/dist/sources-qoIJQrJv.js +11 -0
- package/dist/{sql-B5T1IL83.js → sql-0WjxIp9g.js} +32 -7
- package/dist/sql-B80DFdpG.d.ts +10 -0
- package/dist/{src-Cu2m75uo.js → src-DZ0l9UAg.js} +305 -123
- package/dist/ssf/index.d.ts +4 -4
- package/dist/ssf/index.js +665 -224
- package/dist/{standard-webhooks-rbD7LS6h.d.ts → standard-webhooks-C-qX4mJW.d.ts} +7 -7
- package/dist/{standard-webhooks-DgFFD-Ga.js → standard-webhooks-D67a3nzk.js} +5 -5
- package/dist/{store-BDutJkDL.js → store-RNFvaJJv.js} +43 -29
- package/dist/{store-options-u0ycEe8s.js → store-options-Dil3lraY.js} +105 -15
- package/dist/stores-C0Kta5Ft.d.ts +59 -0
- package/dist/{stores-CGhM8BN_.js → stores-DxZWDXCs.js} +42 -5
- package/dist/{stream-CvdUS9V1.js → stream-CDvF0sJm.js} +5 -5
- package/dist/{stream-CeCMJmBB.d.ts → stream-ltuLdtTG.d.ts} +4 -3
- package/dist/{style-DiKWnAvn.js → style-DblOtSga.js} +1 -1
- package/dist/{style-Uao76wO7.js → style-Ds11Hmk4.js} +3 -1
- package/dist/{subject-settings-CkEwrw3W.js → subject-settings-8sH5HlII.js} +8 -4
- package/dist/{row-check-Dt35czLy.d.ts → subject-settings-vNW8qmUH.d.ts} +30 -18
- package/dist/supabase/index.d.ts +48 -37
- package/dist/supabase/index.js +6 -6
- package/dist/supabase/middleware.d.ts +19 -13
- package/dist/supabase/middleware.js +7 -7
- package/dist/{supabase-x5JtR2tc.js → supabase-BL1qJzzY.js} +82 -36
- package/dist/{supabase-By_frk3U.js → supabase-D39cuGPt.js} +3 -3
- package/dist/{supabase-hook-BMoEhZir.js → supabase-hook-B-yXnzUl.js} +1206 -286
- package/dist/supabase-hook-H-MtE9Wd.js +1 -0
- package/dist/supautils-BU-pAEpf.js +808 -0
- package/dist/{support-session-C6xJQYut.js → support-session-BsmPCbz8.js} +22 -22
- package/dist/svelte/PermissionBoundary.svelte +2 -6
- package/dist/svelte/Protected.svelte +2 -8
- package/dist/svelte/index.d.ts +9 -8
- package/dist/svelte/index.js +10 -9
- package/dist/svelte/runtime.d.ts +4 -4
- package/dist/svelte/runtime.js +4 -4
- package/dist/svelte/source.d.ts +9 -8
- package/dist/svelte/source.js +6 -5
- package/dist/sveltekit/index.d.ts +30 -12
- package/dist/sveltekit/index.js +2 -2
- package/dist/{ownership-DqaJNJPn.js → tables-DeMNEy6V.js} +1025 -1085
- package/dist/tanstack-start/index.d.ts +22 -10
- package/dist/tanstack-start/index.js +2 -2
- package/dist/{target-Bw37TFNA.js → target-qdEAnnhU.js} +6 -6
- package/dist/{tenancy-DN2QAx9z.js → tenancy-5d1zVBvK.js} +36 -21
- package/dist/terminal/index.d.ts +23 -14
- package/dist/terminal/index.js +17 -20
- package/dist/testing/core.d.ts +2 -0
- package/dist/testing/core.js +1 -0
- package/dist/testing/fixtures/index.d.ts +15 -0
- package/dist/testing/fixtures/index.js +831 -0
- package/dist/testing/index.d.ts +235 -285
- package/dist/testing/index.js +502 -927
- package/dist/testing/saas/index.d.ts +43 -27
- package/dist/testing/saas/index.js +2 -2
- package/dist/testing/saas/permissions.d.ts +1 -1
- package/dist/testing/saas/permissions.js +1 -1
- package/dist/text-diff-BtfSmdUo.js +444 -0
- package/dist/{thenable-yD7SabqG.js → thenable-BNSM1U2R.js} +12 -3
- package/dist/{time-DkWjdL98.js → time-nR1JesoH.js} +32 -8
- package/dist/{token-BLZcjQgt.js → token-DC9EQiet.js} +15 -13
- package/dist/{tool-refusal-CMLN5xhn.js → tool-refusal-Qpjs_W6M.js} +5 -2
- package/dist/trpc/index.d.ts +11 -8
- package/dist/trpc/index.js +15 -9
- package/dist/type-helpers-BIPIDa6a.d.ts +50 -0
- package/dist/{types-8RnwUAvE.d.ts → types-AMJ5qoU_.d.ts} +49 -30
- package/dist/{types-C_IiEs64.d.ts → types-B2mlGuhW.d.ts} +14 -11
- package/dist/{types-_WhUP7ud.d.ts → types-B4uqKDnp.d.ts} +25 -12
- package/dist/{types-CX7AvRqP.d.ts → types-BJk0BKRX.d.ts} +24 -14
- package/dist/types-B_d_g7T3.d.ts +262 -0
- package/dist/{types-BdtSDbBO.d.ts → types-B_tiYvk8.d.ts} +59 -32
- package/dist/{types-DqzsnlSA.js → types-CcUXciSj.js} +17 -5
- package/dist/{types-Dfv0aTER.d.ts → types-DC1Loeh3.d.ts} +449 -168
- package/dist/{types-lUlG3TVd.d.ts → types-DHKPcqzr.d.ts} +2 -2
- package/dist/{types-C791HFu9.d.ts → types-DjuMBNF9.d.ts} +68 -32
- package/dist/{types-C863OQiR.d.ts → types-HzqOtvsJ.d.ts} +23 -12
- package/dist/{types-Druu9wLM.d.ts → types-ZzRGoViD.d.ts} +77 -24
- package/dist/{types-BzzaHxt3.d.ts → types-ah9NlU6j.d.ts} +137 -48
- package/dist/{types-CVZSNocA.d.ts → types-djVzLlIV.d.ts} +31 -14
- package/dist/{types-BtHtcKMr.d.ts → types-yUuPR5Hy.d.ts} +47 -24
- package/dist/unplugin/index.d.ts +1 -1
- package/dist/unplugin/index.js +2 -2
- package/dist/usage-CYeXek0p.js +1 -0
- package/dist/{usage-SveTRTyr.js → usage-CxEzS4ey.js} +50 -26
- package/dist/{usage-CRVl9V3t.js → usage-ab0PdusX.js} +2 -2
- package/dist/{validation-error-ZfUHbKvf.js → validation-error-CYg2kJEw.js} +4 -1
- package/dist/{validation-error-DHUrAkku.d.ts → validation-error-YGg2mXyH.d.ts} +5 -2
- package/dist/{validity-CZ7-y0Cj.js → validity-Buc7w8E9.js} +13 -10
- package/dist/{verifier-DHuh-okk.js → verifier-DUV6pLqZ.js} +10 -4
- package/dist/{verify-BaAKx7t6.js → verify-DZeqoWu5.js} +417 -489
- package/dist/version-DMQ0dnN5.js +48 -0
- package/dist/version-DizhmD72.js +1 -0
- package/dist/{views-DTIIO-oQ.js → views-CD8wuL4Z.js} +19 -6
- package/dist/vocabulary-DEJ5j4mR.d.ts +70 -0
- package/dist/vue/index.d.ts +71 -21
- package/dist/vue/index.js +50 -13
- package/dist/{waiter-B986w1oK.d.ts → waiter-Bu9zAlE0.d.ts} +13 -10
- package/dist/{waiter-BGUtGYoU.js → waiter-aBLM63_f.js} +1 -1
- package/dist/{watch-vea54PRw.js → watch-Cx_WciLE.js} +8 -8
- package/dist/watch-DB42U1ib.js +1 -0
- package/dist/webmcp/index.d.ts +11 -11
- package/dist/webmcp/index.js +8 -5
- package/dist/{where-scope-C9vfEphl.js → where-scope-DlCdCM_8.js} +56 -30
- package/dist/{who-can-DWBAcaCQ.js → who-can-rI7dCR9Q.js} +23 -20
- package/dist/workflow/index.d.ts +3 -3
- package/dist/workflow/index.js +13 -13
- package/dist/workflow-sdk/index.d.ts +19 -13
- package/dist/workflow-sdk/index.js +6 -6
- package/dist/{wrap-gX61EtpB.js → wrap-B2wziJI_.js} +11 -5
- package/dist/{wrap-C5jC6sKI.d.ts → wrap-DlJE3gS_.d.ts} +8 -5
- package/package.json +25 -14
- package/schemas/catalog-v1.json +3 -0
- package/schemas/cli-result-v1.json +1 -0
- package/schemas/cloud-api-v1.json +152 -7
- package/schemas/connector-v1.json +8 -0
- package/schemas/supabase-claims-v1.json +5 -0
- package/schemas/supabase-manifest-v1.json +308 -75
- package/skills/permdock/SKILL.md +1 -0
- package/skills/permdock-agents/references/runtimes.md +3 -1
- package/skills/permdock-approvals/references/stores-and-resume.md +2 -1
- package/skills/permdock-credentials/references/tokens-keys-links.md +8 -6
- package/skills/permdock-data/references/queries-and-rls.md +6 -2
- package/skills/permdock-tenancy/SKILL.md +1 -1
- package/skills/permdock-tenancy/references/ownership-and-custom-roles.md +2 -1
- package/skills/permdock-wire/references/adapters.md +28 -22
- package/skills/permdock-wire/references/policy-options.md +1 -0
- package/dist/catalog-BoWglDPI.js +0 -1
- package/dist/collect-D7eQDffE.js +0 -1
- package/dist/config-bs_kZeYq.js +0 -162
- package/dist/denied-text-CiFQNuMV.d.ts +0 -19
- package/dist/fields-OYG_JR78.js +0 -203
- package/dist/generate-CNU1pIOo.js +0 -171
- package/dist/headers-BIjfMaoC.js +0 -8
- package/dist/headers-CIbDTUTK.d.ts +0 -7
- package/dist/index-Cp_ilKi1.d.ts +0 -91
- package/dist/index-CueFnxQc.d.ts +0 -110
- package/dist/load-BxEtwlBS.js +0 -1
- package/dist/output-files-B3IZJksC.js +0 -1
- package/dist/package-root-Dk_ETdkp.js +0 -31
- package/dist/parse-Cxq0WxrA.js +0 -53
- package/dist/parse-local-manifest-5ODwqu8b.d.ts +0 -10
- package/dist/parse-local-manifest-CVSs6J9I.js +0 -34
- package/dist/peer-C8swJ2GH.js +0 -50
- package/dist/policies-DP2nqRoF.js +0 -295
- package/dist/powersync-BkWWCS1K.js +0 -538
- package/dist/powersync-MMJ2mI2q.js +0 -1
- package/dist/problem-details-B45V5d2b.d.ts +0 -7
- package/dist/prompt-DfZLJLIn.js +0 -32
- package/dist/protected-RFGpakN9.d.ts +0 -38
- package/dist/pull-CvpINcMK.js +0 -1
- package/dist/run-DDwUaJDU.js +0 -1
- package/dist/sources-Xc4zkszI.d.ts +0 -190
- package/dist/stores-BUGNbJTt.d.ts +0 -30
- package/dist/supabase-hook-CCw5m35C.js +0 -1
- package/dist/supautils-B6HYL9eL.js +0 -91
- package/dist/text-diff-BQcUapOb.js +0 -15
- package/dist/types-B3_ooZgZ.d.ts +0 -172
- package/dist/usage-CZpSQP6L.js +0 -1
- package/dist/version-CEbQ5UeM.js +0 -18
- package/dist/version-DXkYUISx.js +0 -1
- package/dist/watch--ovlPOc0.js +0 -1
|
@@ -1,29 +1,902 @@
|
|
|
1
1
|
import { r as isRecord } from "./compact-CAf557ZB.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { t as APPROVAL_REQUEST_SCHEMA } from "./request-schema-
|
|
5
|
-
import { a as describeError, i as configError } from "./errors-
|
|
6
|
-
import { i as readJsonFile, o as sqlFiles, s as writeFileEnsuringDir } from "./files-
|
|
7
|
-
import { a as SUPABASE_MANIFEST_SCHEMA } from "./version-
|
|
8
|
-
import { c as requirePolicy } from "./load-
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import "./
|
|
12
|
-
import
|
|
13
|
-
import { a as hookApiNames, d as keptKeys, t as AUTHZ_VERSION_TABLE, u as roleManifest } from "./sources-
|
|
14
|
-
import { o as readMemberships } from "./postgrest-
|
|
2
|
+
import { o as hasConditionOp } from "./refs-C8BKxc_e.js";
|
|
3
|
+
import { f as scopeList, l as rootScope, s as resolveScope, u as scopeChain } from "./scopes-0Up_UA2t.js";
|
|
4
|
+
import { t as APPROVAL_REQUEST_SCHEMA } from "./request-schema-DhX7UbfQ.js";
|
|
5
|
+
import { a as describeError, i as configError } from "./errors-Vpu6rKHl.js";
|
|
6
|
+
import { i as readJsonFile, o as sqlFiles, s as writeFileEnsuringDir } from "./files-BSjrtIHw.js";
|
|
7
|
+
import { a as SUPABASE_MANIFEST_SCHEMA } from "./version-DMQ0dnN5.js";
|
|
8
|
+
import { c as requirePolicy } from "./load-DjSU5KXO.js";
|
|
9
|
+
import { i as qualifySqlTable } from "./sql-0WjxIp9g.js";
|
|
10
|
+
import { i as scopeColumn } from "./compile-EzEMB-7v.js";
|
|
11
|
+
import { t as authorizeSql } from "./supabase-BL1qJzzY.js";
|
|
12
|
+
import "./budget-BELja5A9.js";
|
|
13
|
+
import { a as hookApiNames, d as keptKeys, t as AUTHZ_VERSION_TABLE, u as roleManifest } from "./sources-CMAM-2A3.js";
|
|
14
|
+
import { o as readMemberships } from "./postgrest-D4nuPXIQ.js";
|
|
15
15
|
import { t as beforeFirst } from "./text-BMFRfBqc.js";
|
|
16
|
-
import { n as GRANTS_MARKER, r as HOOK_MARKER, s as hookMarkerFields } from "./markers-
|
|
16
|
+
import { n as GRANTS_MARKER, r as HOOK_MARKER, s as hookMarkerFields } from "./markers-BeHZ4x9Q.js";
|
|
17
17
|
import { n as formatManifestJson, t as MANIFEST_FILE } from "./manifest-json-CAGzls-C.js";
|
|
18
18
|
import { n as MIGRATION_DIRS } from "./constants-DcJABbLW.js";
|
|
19
|
-
import { f as writeOutputFiles, l as partPath, r as driftOf, u as pgDeltaPath } from "./output-files-
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import { a as
|
|
23
|
-
import {
|
|
19
|
+
import { f as writeOutputFiles, l as partPath, r as driftOf, u as pgDeltaPath } from "./output-files-BIQ_9pIs.js";
|
|
20
|
+
import { A as quoteQualified, D as qualified, F as firstScopeType, I as scopeTypeOf, O as quoteIdent, R as tenantTypeOf, a as customRolesOn, j as quoteTable, k as quoteLiteral, l as USER_ID_HELPER, r as HELPERS, y as subjectIdSql } from "./shared-Afctg7B0.js";
|
|
21
|
+
import { E as TOKEN_SCOPE_ALLOWS, J as apiKeyFields, K as API_KEY_ALLOWS, R as globalRoleSource, _ as PERMISSION_HELPERS, at as memberForHelper, b as permissionKeysForHelper, bt as checkSuspension, ct as memberIdsHelper, dt as permittedForHelper, et as hasMemberFor, ft as permittedIdsHelper, g as OWNERSHIP, h as ASSIGNMENTS, lt as memberOfHelper, ot as memberForSources, rt as isTeamScope, st as memberForTable, tt as hasPermittedUsers, ut as memberRoleOf, v as checkName, vt as activeRowSql, x as permittedByPermissionHelper } from "./tables-DeMNEy6V.js";
|
|
22
|
+
import { a as guardedTables, t as ownershipRules, u as roleNames } from "./ownership-B4L59T9u.js";
|
|
23
|
+
import { t as membershipSourcesOf } from "./sources-qoIJQrJv.js";
|
|
24
|
+
import { a as splitUndiffed, r as tableKey, t as decidingColumns } from "./deciding-columns-NB4wcyBf.js";
|
|
25
|
+
import { n as pgConnector } from "./pg-DQTqRrou.js";
|
|
26
|
+
import { r as permittedUsersHelper, t as resolveNames } from "./resolve-names-CF7xXLSG.js";
|
|
27
|
+
import { c as ACTOR_MAY_WRITE, f as readOnlyActorKinds } from "./fields-D0vUI6dq.js";
|
|
24
28
|
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
25
29
|
import { dirname, join, posix, resolve } from "node:path";
|
|
26
|
-
|
|
30
|
+
//#region ../../node_modules/.pnpm/smol-toml@1.9.1/node_modules/smol-toml/dist/error.js
|
|
31
|
+
/*!
|
|
32
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
33
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
34
|
+
*
|
|
35
|
+
* Redistribution and use in source and binary forms, with or without
|
|
36
|
+
* modification, are permitted provided that the following conditions are met:
|
|
37
|
+
*
|
|
38
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
39
|
+
* list of conditions and the following disclaimer.
|
|
40
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
41
|
+
* this list of conditions and the following disclaimer in the
|
|
42
|
+
* documentation and/or other materials provided with the distribution.
|
|
43
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
44
|
+
* may be used to endorse or promote products derived from this software without
|
|
45
|
+
* specific prior written permission.
|
|
46
|
+
*
|
|
47
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
48
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
49
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
50
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
51
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
52
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
53
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
54
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
55
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
56
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
57
|
+
*/
|
|
58
|
+
function getLineColFromPtr(string, ptr) {
|
|
59
|
+
let lines = string.slice(0, ptr).split(/\r?\n/);
|
|
60
|
+
return [lines.length, lines.pop().length + 1];
|
|
61
|
+
}
|
|
62
|
+
function makeCodeBlock(string, line, column) {
|
|
63
|
+
let lines = string.split(/\r?\n/);
|
|
64
|
+
let codeblock = "";
|
|
65
|
+
let numberLen = (Math.log10(line + 1) | 0) + 1;
|
|
66
|
+
for (let i = line - 1; i <= line + 1; i++) {
|
|
67
|
+
let l = lines[i - 1];
|
|
68
|
+
if (!l) continue;
|
|
69
|
+
codeblock += i.toString().padEnd(numberLen, " ");
|
|
70
|
+
codeblock += ": ";
|
|
71
|
+
codeblock += l;
|
|
72
|
+
codeblock += "\n";
|
|
73
|
+
if (i === line) {
|
|
74
|
+
codeblock += " ".repeat(numberLen + column + 2);
|
|
75
|
+
codeblock += "^\n";
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return codeblock;
|
|
79
|
+
}
|
|
80
|
+
var TomlError = class TomlError extends Error {
|
|
81
|
+
line;
|
|
82
|
+
column;
|
|
83
|
+
codeblock;
|
|
84
|
+
constructor(message, options) {
|
|
85
|
+
const [line, column] = getLineColFromPtr(options.toml, options.ptr);
|
|
86
|
+
const codeblock = makeCodeBlock(options.toml, line, column);
|
|
87
|
+
super(`Invalid TOML document: ${message}\n\n${codeblock}`, options);
|
|
88
|
+
this.line = line;
|
|
89
|
+
this.column = column;
|
|
90
|
+
this.codeblock = codeblock;
|
|
91
|
+
}
|
|
92
|
+
/** @internal */
|
|
93
|
+
static x(message, ctx, ptr) {
|
|
94
|
+
throw new TomlError(message, {
|
|
95
|
+
toml: ctx.s,
|
|
96
|
+
ptr: ptr ?? ctx.p
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
//#endregion
|
|
101
|
+
//#region ../../node_modules/.pnpm/smol-toml@1.9.1/node_modules/smol-toml/dist/primitive.js
|
|
102
|
+
/*!
|
|
103
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
104
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
105
|
+
*
|
|
106
|
+
* Redistribution and use in source and binary forms, with or without
|
|
107
|
+
* modification, are permitted provided that the following conditions are met:
|
|
108
|
+
*
|
|
109
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
110
|
+
* list of conditions and the following disclaimer.
|
|
111
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
112
|
+
* this list of conditions and the following disclaimer in the
|
|
113
|
+
* documentation and/or other materials provided with the distribution.
|
|
114
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
115
|
+
* may be used to endorse or promote products derived from this software without
|
|
116
|
+
* specific prior written permission.
|
|
117
|
+
*
|
|
118
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
119
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
120
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
121
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
122
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
123
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
124
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
125
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
126
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
127
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
128
|
+
*/
|
|
129
|
+
/** @internal */
|
|
130
|
+
function parseString(ctx) {
|
|
131
|
+
let startPtr = ctx.p;
|
|
132
|
+
let c = ctx.s.charCodeAt(ctx.p++);
|
|
133
|
+
let first = c;
|
|
134
|
+
let isLiteral = c === 39;
|
|
135
|
+
let isMultiline = c === ctx.s.charCodeAt(ctx.p) && c === ctx.s.charCodeAt(ctx.p + 1);
|
|
136
|
+
if (isMultiline) {
|
|
137
|
+
if ((c = ctx.s.charCodeAt(ctx.p += 2)) === 10) ctx.p++;
|
|
138
|
+
else if (c === 13 && ctx.s.charCodeAt(ctx.p + 1) === 10) ctx.p += 2;
|
|
139
|
+
}
|
|
140
|
+
let parsed = "";
|
|
141
|
+
let sliceStart = ctx.p;
|
|
142
|
+
let state = 0;
|
|
143
|
+
for (; ctx.p < ctx.s.length; ctx.p++) {
|
|
144
|
+
c = ctx.s.charCodeAt(ctx.p);
|
|
145
|
+
if (isMultiline && (c === 10 || c === 13 && ctx.s.charCodeAt(ctx.p + 1) === 10)) state = state && 3;
|
|
146
|
+
else if (c < 32 && c !== 9 || c === 127) TomlError.x("control characters are not allowed in strings", ctx);
|
|
147
|
+
else if ((!state || state === 3) && c === first && (!isMultiline || ctx.s.charCodeAt(ctx.p + 1) === first && ctx.s.charCodeAt(ctx.p + 2) === first)) {
|
|
148
|
+
if (isMultiline) {
|
|
149
|
+
if (ctx.s.charCodeAt(ctx.p + 3) === first) ctx.p++;
|
|
150
|
+
if (ctx.s.charCodeAt(ctx.p + 3) === first) ctx.p++;
|
|
151
|
+
}
|
|
152
|
+
if (!state) {
|
|
153
|
+
let s = ctx.s.slice(sliceStart, ctx.p);
|
|
154
|
+
parsed = parsed ? parsed + s : s;
|
|
155
|
+
}
|
|
156
|
+
ctx.p += isMultiline ? 3 : 1;
|
|
157
|
+
return parsed;
|
|
158
|
+
} else if (!state) {
|
|
159
|
+
if (!isLiteral && c === 92) {
|
|
160
|
+
parsed += ctx.s.slice(sliceStart, sliceStart = ctx.p);
|
|
161
|
+
state = 1;
|
|
162
|
+
}
|
|
163
|
+
} else if (state === 1) {
|
|
164
|
+
if (c === 120 || c === 117 || c === 85) {
|
|
165
|
+
let errPtr = ctx.p++ - 1;
|
|
166
|
+
let value = 0;
|
|
167
|
+
let len = c === 120 ? 2 : c === 117 ? 4 : 8;
|
|
168
|
+
for (let j = 0; j < len; j++, ctx.p++) {
|
|
169
|
+
let hex = ctx.s.charCodeAt(ctx.p);
|
|
170
|
+
let digit = hex >= 48 && hex <= 57 ? hex - 48 : hex >= 65 && hex <= 70 ? hex - 65 + 10 : hex >= 97 && hex <= 102 ? hex - 97 + 10 : -1;
|
|
171
|
+
if (digit < 0) TomlError.x("invalid non-hex character in unicode escape", ctx);
|
|
172
|
+
value = value << 4 | digit;
|
|
173
|
+
}
|
|
174
|
+
if (value < 0 || value > 1114111 || value >= 55296 && value <= 57343) TomlError.x("invalid unicode escape", ctx, errPtr);
|
|
175
|
+
parsed += String.fromCodePoint(value);
|
|
176
|
+
sliceStart = ctx.p--;
|
|
177
|
+
state = 0;
|
|
178
|
+
} else if (isMultiline && (c === 32 || c === 9)) state = 2;
|
|
179
|
+
else {
|
|
180
|
+
if (c === 98) parsed += "\b";
|
|
181
|
+
else if (c === 116) parsed += " ";
|
|
182
|
+
else if (c === 110) parsed += "\n";
|
|
183
|
+
else if (c === 102) parsed += "\f";
|
|
184
|
+
else if (c === 114) parsed += "\r";
|
|
185
|
+
else if (c === 101) parsed += "\x1B";
|
|
186
|
+
else if (c === 34) parsed += "\"";
|
|
187
|
+
else if (c === 92) parsed += "\\";
|
|
188
|
+
else TomlError.x("unrecognised escape sequence", ctx);
|
|
189
|
+
sliceStart = ctx.p + 1;
|
|
190
|
+
state = 0;
|
|
191
|
+
}
|
|
192
|
+
} else if (c !== 32 && c !== 9) {
|
|
193
|
+
if (state === 2) TomlError.x("invalid escape: only line-ending whitespace may be escaped", ctx, sliceStart);
|
|
194
|
+
state = !isLiteral && c === 92 ? 1 : 0;
|
|
195
|
+
sliceStart = ctx.p;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
TomlError.x("unfinished string", ctx, startPtr);
|
|
199
|
+
}
|
|
200
|
+
//#endregion
|
|
201
|
+
//#region ../../node_modules/.pnpm/smol-toml@1.9.1/node_modules/smol-toml/dist/date.js
|
|
202
|
+
/*!
|
|
203
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
204
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
205
|
+
*
|
|
206
|
+
* Redistribution and use in source and binary forms, with or without
|
|
207
|
+
* modification, are permitted provided that the following conditions are met:
|
|
208
|
+
*
|
|
209
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
210
|
+
* list of conditions and the following disclaimer.
|
|
211
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
212
|
+
* this list of conditions and the following disclaimer in the
|
|
213
|
+
* documentation and/or other materials provided with the distribution.
|
|
214
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
215
|
+
* may be used to endorse or promote products derived from this software without
|
|
216
|
+
* specific prior written permission.
|
|
217
|
+
*
|
|
218
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
219
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
220
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
221
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
222
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
223
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
224
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
225
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
226
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
227
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
228
|
+
*/
|
|
229
|
+
let DATE_TIME_RE = /^(\d{4}-\d{2}-\d{2})?[Tt ]?(?:(\d{2}):\d{2}(?::\d{2}(?:\.\d+)?)?)?(Z|z|[-+]\d{2}:\d{2})?$/i;
|
|
230
|
+
var TomlDate = class TomlDate extends Date {
|
|
231
|
+
#hasDate = false;
|
|
232
|
+
#hasTime = false;
|
|
233
|
+
#offset = null;
|
|
234
|
+
constructor(date, fasttype, unsafeDelim) {
|
|
235
|
+
let hasDate = true;
|
|
236
|
+
let hasTime = true;
|
|
237
|
+
let offset = "Z";
|
|
238
|
+
let c;
|
|
239
|
+
if (typeof date === "string") {
|
|
240
|
+
if (fasttype) prep: {
|
|
241
|
+
if (fasttype < 3) {
|
|
242
|
+
if (+date.slice(11, 13) > 23) {
|
|
243
|
+
date = "";
|
|
244
|
+
break prep;
|
|
245
|
+
}
|
|
246
|
+
if (fasttype === 2) {
|
|
247
|
+
offset = null;
|
|
248
|
+
date += "Z";
|
|
249
|
+
} else if ((c = date.charCodeAt(date.length - 1)) !== 90 && c !== 122) offset = date.slice(date.length - 6);
|
|
250
|
+
if (unsafeDelim) date = date.slice(0, 10) + "T" + date.slice(11);
|
|
251
|
+
} else if (fasttype === 4) date = +date.slice(0, 2) > 23 ? "" : `0000-01-01T${date}Z`;
|
|
252
|
+
hasDate = fasttype !== 4;
|
|
253
|
+
hasTime = fasttype !== 3;
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
let match = date.match(DATE_TIME_RE);
|
|
257
|
+
if (match) {
|
|
258
|
+
if (!match[1]) {
|
|
259
|
+
hasDate = false;
|
|
260
|
+
date = `0000-01-01T${date}`;
|
|
261
|
+
}
|
|
262
|
+
hasTime = !!match[2];
|
|
263
|
+
hasTime && date[10] === " " && (date = date.replace(" ", "T"));
|
|
264
|
+
if (match[2] && +match[2] > 23) date = "";
|
|
265
|
+
else {
|
|
266
|
+
offset = match[3] || null;
|
|
267
|
+
if (!offset && hasTime) date += "Z";
|
|
268
|
+
}
|
|
269
|
+
} else date = "";
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
super(date);
|
|
273
|
+
if (!isNaN(this.getTime())) {
|
|
274
|
+
this.#hasDate = hasDate;
|
|
275
|
+
this.#hasTime = hasTime;
|
|
276
|
+
this.#offset = offset;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
isDateTime() {
|
|
280
|
+
return this.#hasDate && this.#hasTime;
|
|
281
|
+
}
|
|
282
|
+
isLocal() {
|
|
283
|
+
return !this.#hasDate || !this.#hasTime || !this.#offset;
|
|
284
|
+
}
|
|
285
|
+
isDate() {
|
|
286
|
+
return this.#hasDate && !this.#hasTime;
|
|
287
|
+
}
|
|
288
|
+
isTime() {
|
|
289
|
+
return this.#hasTime && !this.#hasDate;
|
|
290
|
+
}
|
|
291
|
+
isValid() {
|
|
292
|
+
return this.#hasDate || this.#hasTime;
|
|
293
|
+
}
|
|
294
|
+
toISOString() {
|
|
295
|
+
let iso = super.toISOString();
|
|
296
|
+
if (this.isDate()) return iso.slice(0, 10);
|
|
297
|
+
if (this.isTime()) return iso.slice(11, 23);
|
|
298
|
+
if (this.#offset === null) return iso.slice(0, -1);
|
|
299
|
+
if (this.#offset === "Z" || this.#offset === "z") return iso;
|
|
300
|
+
let offset = +this.#offset.slice(1, 3) * 60 + +this.#offset.slice(4, 6);
|
|
301
|
+
offset = this.#offset[0] === "-" ? offset : -offset;
|
|
302
|
+
return (/* @__PURE__ */ new Date(this.getTime() - offset * 6e4)).toISOString().slice(0, -1) + this.#offset;
|
|
303
|
+
}
|
|
304
|
+
static wrapAsOffsetDateTime(jsDate, offset = "Z") {
|
|
305
|
+
let date = new TomlDate(jsDate);
|
|
306
|
+
date.#offset = offset;
|
|
307
|
+
return date;
|
|
308
|
+
}
|
|
309
|
+
static wrapAsLocalDateTime(jsDate) {
|
|
310
|
+
let date = new TomlDate(jsDate);
|
|
311
|
+
date.#offset = null;
|
|
312
|
+
return date;
|
|
313
|
+
}
|
|
314
|
+
static wrapAsLocalDate(jsDate) {
|
|
315
|
+
let date = new TomlDate(jsDate);
|
|
316
|
+
date.#hasTime = false;
|
|
317
|
+
date.#offset = null;
|
|
318
|
+
return date;
|
|
319
|
+
}
|
|
320
|
+
static wrapAsLocalTime(jsDate) {
|
|
321
|
+
let date = new TomlDate(jsDate);
|
|
322
|
+
date.#hasDate = false;
|
|
323
|
+
date.#offset = null;
|
|
324
|
+
return date;
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
//#endregion
|
|
328
|
+
//#region ../../node_modules/.pnpm/smol-toml@1.9.1/node_modules/smol-toml/dist/extract.js
|
|
329
|
+
/*!
|
|
330
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
331
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
332
|
+
*
|
|
333
|
+
* Redistribution and use in source and binary forms, with or without
|
|
334
|
+
* modification, are permitted provided that the following conditions are met:
|
|
335
|
+
*
|
|
336
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
337
|
+
* list of conditions and the following disclaimer.
|
|
338
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
339
|
+
* this list of conditions and the following disclaimer in the
|
|
340
|
+
* documentation and/or other materials provided with the distribution.
|
|
341
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
342
|
+
* may be used to endorse or promote products derived from this software without
|
|
343
|
+
* specific prior written permission.
|
|
344
|
+
*
|
|
345
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
346
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
347
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
348
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
349
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
350
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
351
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
352
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
353
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
354
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
355
|
+
*/
|
|
356
|
+
function isDigit(char, base = 10) {
|
|
357
|
+
return base === 16 ? char > 47 && char < 58 || char > 64 && char < 71 || char > 96 && char < 103 : char > 47 && char < 48 + base;
|
|
358
|
+
}
|
|
359
|
+
function isEndOfValue(char, delim) {
|
|
360
|
+
return char === 32 || char === 9 || char === 10 || char === 13 || delim && (char === delim || char === 44) || char === 35;
|
|
361
|
+
}
|
|
362
|
+
/** @internal */
|
|
363
|
+
function extractValue(ctx, end) {
|
|
364
|
+
let errPtr = ctx.p;
|
|
365
|
+
let c = ctx.s.charCodeAt(ctx.p);
|
|
366
|
+
if (c === 91 || c === 123) {
|
|
367
|
+
ctx.d-- || TomlError.x("document contains excessively nested structures. aborting.", ctx);
|
|
368
|
+
let value = c === 91 ? parseArray(ctx) : parseInlineTable(ctx);
|
|
369
|
+
ctx.d++;
|
|
370
|
+
return value;
|
|
371
|
+
}
|
|
372
|
+
if (c === 34 || c === 39) return parseString(ctx);
|
|
373
|
+
if (c === 116) {
|
|
374
|
+
if (ctx.s.charCodeAt(++ctx.p) !== 114 || ctx.s.charCodeAt(++ctx.p) !== 117 || ctx.s.charCodeAt(++ctx.p) !== 101) TomlError.x("invalid value", ctx, errPtr);
|
|
375
|
+
return ctx.p++, true;
|
|
376
|
+
}
|
|
377
|
+
if (c === 102) {
|
|
378
|
+
if (ctx.s.charCodeAt(++ctx.p) !== 97 || ctx.s.charCodeAt(++ctx.p) !== 108 || ctx.s.charCodeAt(++ctx.p) !== 115 || ctx.s.charCodeAt(++ctx.p) !== 101) TomlError.x("invalid value", ctx, errPtr);
|
|
379
|
+
return ctx.p++, false;
|
|
380
|
+
}
|
|
381
|
+
if (c === 43 || c === 45) return parseNumber(ctx, ctx.p, ctx.s.charCodeAt(++ctx.p), 44 - c, end);
|
|
382
|
+
if (ctx.s.charCodeAt(ctx.p + 4) === 45 && ctx.s.charCodeAt(ctx.p + 7) === 45) return parseDate(ctx, c, end);
|
|
383
|
+
if (ctx.s.charCodeAt(ctx.p + 2) === 58) return parseTime(ctx, c, end);
|
|
384
|
+
return parseNumber(ctx, ctx.p, c, 0, end);
|
|
385
|
+
}
|
|
386
|
+
function parseNumber(ctx, startPtr, startChr, sign, endChr) {
|
|
387
|
+
let c = startChr;
|
|
388
|
+
let state = 0;
|
|
389
|
+
let hasUnderscores = false;
|
|
390
|
+
if (c === 105) {
|
|
391
|
+
if (ctx.s.charCodeAt(++ctx.p) !== 110 || ctx.s.charCodeAt(++ctx.p) !== 102) TomlError.x("invalid value", ctx, startPtr);
|
|
392
|
+
return ctx.p++, (sign || 1) / 0;
|
|
393
|
+
}
|
|
394
|
+
if (c === 110) {
|
|
395
|
+
if (ctx.s.charCodeAt(++ctx.p) !== 97 || ctx.s.charCodeAt(++ctx.p) !== 110) TomlError.x("invalid value", ctx, startPtr);
|
|
396
|
+
return ctx.p++, NaN;
|
|
397
|
+
}
|
|
398
|
+
if (c === 48) {
|
|
399
|
+
if (++ctx.p >= ctx.s.length || isEndOfValue(c = ctx.s.charCodeAt(ctx.p), endChr)) return ctx.bi === true ? 0n : 0;
|
|
400
|
+
if (!sign) {
|
|
401
|
+
if (c === 120) return parseIntegerBaseN(ctx, startPtr, 16, endChr);
|
|
402
|
+
else if (c === 98) return parseIntegerBaseN(ctx, startPtr, 2, endChr);
|
|
403
|
+
else if (c === 111) return parseIntegerBaseN(ctx, startPtr, 8, endChr);
|
|
404
|
+
}
|
|
405
|
+
if (c === 46) state = 2;
|
|
406
|
+
else if (c === 101 || c === 69) state = 4;
|
|
407
|
+
else TomlError.x("illegal leading zero", ctx, startPtr);
|
|
408
|
+
} else if (!isDigit(c)) TomlError.x("invalid value", ctx, startPtr);
|
|
409
|
+
while (++ctx.p < ctx.s.length && (c = ctx.s.charCodeAt(ctx.p), !isEndOfValue(c, endChr))) {
|
|
410
|
+
if (!state) state = 1;
|
|
411
|
+
if (c === 95) {
|
|
412
|
+
if (!(state & 1)) TomlError.x("illegal underscore", ctx);
|
|
413
|
+
state += 11;
|
|
414
|
+
hasUnderscores = true;
|
|
415
|
+
} else if (state === 1 && c === 46) state = 2;
|
|
416
|
+
else if ((state === 1 || state === 3) && (c === 101 || c === 69)) state = 4;
|
|
417
|
+
else if (state === 4 && (c === 43 || c === 45)) state = 6;
|
|
418
|
+
else if (!isDigit(c)) TomlError.x(`illegal character in numeric literal`, ctx);
|
|
419
|
+
else if (state > 9) state -= 11;
|
|
420
|
+
else if (!(state & 1)) state++;
|
|
421
|
+
}
|
|
422
|
+
if (!state) {
|
|
423
|
+
let val = (startChr - 48) * (sign || 1);
|
|
424
|
+
return ctx.bi === true ? BigInt(val) : val;
|
|
425
|
+
}
|
|
426
|
+
if (!(state & 1)) TomlError.x("unfinished numeric value", ctx, startPtr);
|
|
427
|
+
let str = ctx.s.slice(startPtr, ctx.p);
|
|
428
|
+
if (hasUnderscores) str = str.replaceAll("_", "");
|
|
429
|
+
return state > 1 ? parseFloat(str) : parseInteger(ctx, str, 10, startPtr);
|
|
430
|
+
}
|
|
431
|
+
function parseIntegerBaseN(ctx, startPtr, base, endChr) {
|
|
432
|
+
let c, underscore = 1;
|
|
433
|
+
while (++ctx.p < ctx.s.length && (c = ctx.s.charCodeAt(ctx.p), !isEndOfValue(c, endChr))) if (c === 95) {
|
|
434
|
+
if (underscore & 1) TomlError.x("illegal underscore", ctx);
|
|
435
|
+
underscore = 3;
|
|
436
|
+
} else if (!isDigit(c, base)) TomlError.x(`illegal character in numeric literal`, ctx);
|
|
437
|
+
else if (underscore & 1) underscore--;
|
|
438
|
+
if (underscore & 1) TomlError.x("unfinished numeric value", ctx);
|
|
439
|
+
let str = ctx.s.slice(startPtr + 2, ctx.p);
|
|
440
|
+
if (underscore) str = str.replaceAll("_", "");
|
|
441
|
+
return parseInteger(ctx, str, base, startPtr);
|
|
442
|
+
}
|
|
443
|
+
function parseInteger(ctx, str, base, startPtr) {
|
|
444
|
+
if (ctx.bi !== true) int: {
|
|
445
|
+
let val = parseInt(str, base);
|
|
446
|
+
if (!Number.isSafeInteger(val)) {
|
|
447
|
+
if (ctx.bi) break int;
|
|
448
|
+
TomlError.x("integer value cannot be represented losslessly", ctx, startPtr);
|
|
449
|
+
}
|
|
450
|
+
return val;
|
|
451
|
+
}
|
|
452
|
+
return base === 10 ? BigInt(str) : BigInt((base === 2 ? "0b" : base === 8 ? "0o" : "0x") + str);
|
|
453
|
+
}
|
|
454
|
+
function parseDate(ctx, c, endChr) {
|
|
455
|
+
let startPtr = ctx.p++, unsafeSeparator;
|
|
456
|
+
if (!isDigit(c) || !isDigit(ctx.s.charCodeAt(ctx.p++)) || !isDigit(ctx.s.charCodeAt(ctx.p++)) || !isDigit(ctx.s.charCodeAt(ctx.p++))) return parseNumber(ctx, ctx.p = startPtr, c, 0, endChr);
|
|
457
|
+
ctx.p += 5;
|
|
458
|
+
if (!isDigit(ctx.s.charCodeAt(ctx.p++))) TomlError.x("invalid date-time: date part is malformed", ctx, startPtr);
|
|
459
|
+
if (ctx.p >= ctx.s.length || ((c = ctx.s.charCodeAt(ctx.p)) !== 32 || (unsafeSeparator = true, !isDigit(ctx.s.charCodeAt(ctx.p + 1)))) && c !== 84 && c !== 116) return readDate(ctx, ctx.s.slice(startPtr, ctx.p), 3, false, startPtr);
|
|
460
|
+
if (ctx.s.charCodeAt(ctx.p += 3) !== 58) TomlError.x("invalid date-time: time part is malformed", ctx, startPtr);
|
|
461
|
+
if (ctx.s.charCodeAt(ctx.p += 3) === 58) ctx.p += 3;
|
|
462
|
+
if (ctx.s.charCodeAt(ctx.p) === 46) while (isDigit(ctx.s.charCodeAt(++ctx.p)));
|
|
463
|
+
if (c = ctx.s.charCodeAt(ctx.p)) {
|
|
464
|
+
if (c === 90 || c === 122) return readDate(ctx, ctx.s.slice(startPtr, ++ctx.p), 1, unsafeSeparator, startPtr, "[+00:00]");
|
|
465
|
+
if (c === 43 || c === 45) return readDate(ctx, ctx.s.slice(startPtr, ctx.p += 6), 1, unsafeSeparator, startPtr, !ctx.ld && "[" + ctx.s.slice(ctx.p - 6, ctx.p) + "]");
|
|
466
|
+
}
|
|
467
|
+
return readDate(ctx, ctx.s.slice(startPtr, ctx.p), 2, unsafeSeparator, startPtr);
|
|
468
|
+
}
|
|
469
|
+
function parseTime(ctx, c, endChr) {
|
|
470
|
+
let start = ctx.p;
|
|
471
|
+
if (!isDigit(c) || !isDigit(ctx.s.charCodeAt(++ctx.p))) return parseNumber(ctx, --ctx.p, c, 0, endChr);
|
|
472
|
+
if (ctx.s.charCodeAt(ctx.p += 4) === 58) ctx.p += 3;
|
|
473
|
+
if (ctx.s.charCodeAt(ctx.p) === 46) while (isDigit(ctx.s.charCodeAt(++ctx.p)));
|
|
474
|
+
return readDate(ctx, ctx.s.slice(start, ctx.p), 4, false, start);
|
|
475
|
+
}
|
|
476
|
+
function readDate(ctx, str, type, unsafeDelim, errPtr, temporalSuffix) {
|
|
477
|
+
if (ctx.ld) {
|
|
478
|
+
let date = new TomlDate(str, type, unsafeDelim);
|
|
479
|
+
if (!date.isValid()) TomlError.x("invalid date", ctx, errPtr);
|
|
480
|
+
return date;
|
|
481
|
+
}
|
|
482
|
+
try {
|
|
483
|
+
if (temporalSuffix) str += temporalSuffix;
|
|
484
|
+
switch (type) {
|
|
485
|
+
case 1: return Temporal.ZonedDateTime.from(str);
|
|
486
|
+
case 2: return Temporal.PlainDateTime.from(str);
|
|
487
|
+
case 3: return Temporal.PlainDate.from(str);
|
|
488
|
+
case 4: return Temporal.PlainTime.from(str);
|
|
489
|
+
}
|
|
490
|
+
} catch (e) {
|
|
491
|
+
TomlError.x(e instanceof Error ? e.message : "" + e, ctx, errPtr);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
//#endregion
|
|
495
|
+
//#region ../../node_modules/.pnpm/smol-toml@1.9.1/node_modules/smol-toml/dist/util.js
|
|
496
|
+
/*!
|
|
497
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
498
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
499
|
+
*
|
|
500
|
+
* Redistribution and use in source and binary forms, with or without
|
|
501
|
+
* modification, are permitted provided that the following conditions are met:
|
|
502
|
+
*
|
|
503
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
504
|
+
* list of conditions and the following disclaimer.
|
|
505
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
506
|
+
* this list of conditions and the following disclaimer in the
|
|
507
|
+
* documentation and/or other materials provided with the distribution.
|
|
508
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
509
|
+
* may be used to endorse or promote products derived from this software without
|
|
510
|
+
* specific prior written permission.
|
|
511
|
+
*
|
|
512
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
513
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
514
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
515
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
516
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
517
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
518
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
519
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
520
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
521
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
522
|
+
*/
|
|
523
|
+
/** @internal */
|
|
524
|
+
function skipComment(ctx) {
|
|
525
|
+
for (; ctx.p < ctx.s.length; ctx.p++) {
|
|
526
|
+
let c = ctx.s.charCodeAt(ctx.p);
|
|
527
|
+
if (c === 10) break;
|
|
528
|
+
if (c === 13 && ctx.s.charCodeAt(ctx.p + 1) === 10) {
|
|
529
|
+
ctx.p++;
|
|
530
|
+
break;
|
|
531
|
+
}
|
|
532
|
+
if (c < 32 && c !== 9 || c === 127) TomlError.x("control characters are not allowed in comments", ctx);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
/** @internal */
|
|
536
|
+
function skipVoid(ctx, banNewLines, banComments) {
|
|
537
|
+
let c;
|
|
538
|
+
while (ctx.p < ctx.s.length) {
|
|
539
|
+
while (ctx.p < ctx.s.length && ((c = ctx.s.charCodeAt(ctx.p)) === 32 || c === 9 || !banNewLines && (c === 10 || c === 13 && ctx.s.charCodeAt(ctx.p + 1) === 10))) ctx.p++;
|
|
540
|
+
if (banComments || c !== 35) break;
|
|
541
|
+
skipComment(ctx);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
//#endregion
|
|
545
|
+
//#region ../../node_modules/.pnpm/smol-toml@1.9.1/node_modules/smol-toml/dist/struct.js
|
|
546
|
+
/*!
|
|
547
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
548
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
549
|
+
*
|
|
550
|
+
* Redistribution and use in source and binary forms, with or without
|
|
551
|
+
* modification, are permitted provided that the following conditions are met:
|
|
552
|
+
*
|
|
553
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
554
|
+
* list of conditions and the following disclaimer.
|
|
555
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
556
|
+
* this list of conditions and the following disclaimer in the
|
|
557
|
+
* documentation and/or other materials provided with the distribution.
|
|
558
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
559
|
+
* may be used to endorse or promote products derived from this software without
|
|
560
|
+
* specific prior written permission.
|
|
561
|
+
*
|
|
562
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
563
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
564
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
565
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
566
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
567
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
568
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
569
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
570
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
571
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
572
|
+
*/
|
|
573
|
+
/** @internal */
|
|
574
|
+
function parseKey(ctx, end = 61) {
|
|
575
|
+
let startPtr;
|
|
576
|
+
let state = 0;
|
|
577
|
+
let parsed = [];
|
|
578
|
+
let sliceStart;
|
|
579
|
+
let c = ctx.s.charCodeAt(startPtr = ctx.p);
|
|
580
|
+
do
|
|
581
|
+
if (c === end) {
|
|
582
|
+
if (!state) TomlError.x("unexpected end of key", ctx);
|
|
583
|
+
if (state === 1) parsed.push(ctx.s.slice(sliceStart, ctx.p));
|
|
584
|
+
return ctx.p++, parsed;
|
|
585
|
+
} else if (c === 46) {
|
|
586
|
+
if (!state) TomlError.x("illegal empty bare key", ctx);
|
|
587
|
+
if (state === 1) parsed.push(ctx.s.slice(sliceStart, ctx.p));
|
|
588
|
+
state = 0;
|
|
589
|
+
} else if (!state && (c === 34 || c === 39)) {
|
|
590
|
+
if (c === ctx.s.charCodeAt(ctx.p + 1) && c === ctx.s.charCodeAt(ctx.p + 2)) TomlError.x("illegal quoted key: multiline strings are not allowed", ctx);
|
|
591
|
+
parsed.push(parseString(ctx));
|
|
592
|
+
state = 2;
|
|
593
|
+
ctx.p--;
|
|
594
|
+
} else if (c === 32 || c === 9) {
|
|
595
|
+
if (state === 1) {
|
|
596
|
+
parsed.push(ctx.s.slice(sliceStart, ctx.p));
|
|
597
|
+
state = 2;
|
|
598
|
+
}
|
|
599
|
+
} else if (state === 2 || c < 48 && c !== 45 || c > 57 && c < 65 || c > 90 && c < 97 && c !== 95 || c > 122) TomlError.x("illegal character in key", ctx);
|
|
600
|
+
else if (!state) {
|
|
601
|
+
state = 1;
|
|
602
|
+
sliceStart = ctx.p;
|
|
603
|
+
}
|
|
604
|
+
while (c = ctx.s.charCodeAt(++ctx.p));
|
|
605
|
+
TomlError.x("incomplete key-value: cannot find end of key", ctx, startPtr);
|
|
606
|
+
}
|
|
607
|
+
/** @internal */
|
|
608
|
+
function parseInlineTable(ctx) {
|
|
609
|
+
let startPtr = ctx.p++;
|
|
610
|
+
let res = Object.create(null);
|
|
611
|
+
let seen = /* @__PURE__ */ new Set();
|
|
612
|
+
let c;
|
|
613
|
+
while (ctx.p < ctx.s.length) {
|
|
614
|
+
skipVoid(ctx);
|
|
615
|
+
if ((c = ctx.s.charCodeAt(ctx.p)) === 125) {
|
|
616
|
+
ctx.p++;
|
|
617
|
+
return res;
|
|
618
|
+
}
|
|
619
|
+
let k;
|
|
620
|
+
let t = res;
|
|
621
|
+
let hasOwn = false;
|
|
622
|
+
let errPtr = ctx.p;
|
|
623
|
+
let key = parseKey(ctx);
|
|
624
|
+
for (let i = 0; i < key.length; i++) {
|
|
625
|
+
if (i) t = hasOwn ? t[k] : t[k] = Object.create(null);
|
|
626
|
+
k = key[i];
|
|
627
|
+
if ((hasOwn = Object.hasOwn(t, k)) && (typeof t[k] !== "object" || seen.has(t[k]))) TomlError.x("trying to redefine an already defined value", ctx, errPtr);
|
|
628
|
+
let unsafe = k === "__proto__";
|
|
629
|
+
if (ctx.uk && (unsafe || k === "constructor")) {
|
|
630
|
+
t = ctx.uk !== 1 && TomlError.x("document contains an unsafe property", ctx, errPtr);
|
|
631
|
+
break;
|
|
632
|
+
}
|
|
633
|
+
if (!hasOwn && unsafe) Object.defineProperty(t, k, {
|
|
634
|
+
enumerable: true,
|
|
635
|
+
configurable: true,
|
|
636
|
+
writable: true
|
|
637
|
+
});
|
|
638
|
+
}
|
|
639
|
+
if (hasOwn) TomlError.x("trying to redefine an already defined value", ctx, errPtr);
|
|
640
|
+
skipVoid(ctx, true, true);
|
|
641
|
+
let value = extractValue(ctx, 125);
|
|
642
|
+
if (t && typeof (t[k] = value) === "object") seen.add(value);
|
|
643
|
+
skipVoid(ctx);
|
|
644
|
+
if ((c = ctx.s.charCodeAt(ctx.p++)) === 125) return res;
|
|
645
|
+
if (c !== 44) TomlError.x("expected comma or end of structure", ctx, ctx.p - 1);
|
|
646
|
+
}
|
|
647
|
+
TomlError.x("unfinished table", ctx, startPtr);
|
|
648
|
+
}
|
|
649
|
+
/** @internal */
|
|
650
|
+
function parseArray(ctx) {
|
|
651
|
+
let startPtr = ctx.p++;
|
|
652
|
+
let res = [];
|
|
653
|
+
let c;
|
|
654
|
+
while (ctx.p < ctx.s.length) {
|
|
655
|
+
skipVoid(ctx);
|
|
656
|
+
if ((c = ctx.s.charCodeAt(ctx.p)) === 93) {
|
|
657
|
+
ctx.p++;
|
|
658
|
+
return res;
|
|
659
|
+
}
|
|
660
|
+
res.push(extractValue(ctx, 93));
|
|
661
|
+
skipVoid(ctx);
|
|
662
|
+
if ((c = ctx.s.charCodeAt(ctx.p++)) === 93) return res;
|
|
663
|
+
if (c !== 44) TomlError.x("expected comma or end of structure", ctx, ctx.p - 1);
|
|
664
|
+
}
|
|
665
|
+
TomlError.x("unfinished array", ctx, startPtr);
|
|
666
|
+
}
|
|
667
|
+
//#endregion
|
|
668
|
+
//#region ../../node_modules/.pnpm/smol-toml@1.9.1/node_modules/smol-toml/dist/parse.js
|
|
669
|
+
/*!
|
|
670
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
671
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
672
|
+
*
|
|
673
|
+
* Redistribution and use in source and binary forms, with or without
|
|
674
|
+
* modification, are permitted provided that the following conditions are met:
|
|
675
|
+
*
|
|
676
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
677
|
+
* list of conditions and the following disclaimer.
|
|
678
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
679
|
+
* this list of conditions and the following disclaimer in the
|
|
680
|
+
* documentation and/or other materials provided with the distribution.
|
|
681
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
682
|
+
* may be used to endorse or promote products derived from this software without
|
|
683
|
+
* specific prior written permission.
|
|
684
|
+
*
|
|
685
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
686
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
687
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
688
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
689
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
690
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
691
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
692
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
693
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
694
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
695
|
+
*/
|
|
696
|
+
function peekTable(ctx, key, table, meta, type) {
|
|
697
|
+
let t = table;
|
|
698
|
+
let m = meta;
|
|
699
|
+
let k;
|
|
700
|
+
let hasOwn = false;
|
|
701
|
+
let state;
|
|
702
|
+
for (let i = 0; i < key.length; i++) {
|
|
703
|
+
if (i) {
|
|
704
|
+
t = hasOwn ? t[k] : t[k] = Object.create(null);
|
|
705
|
+
m = (state = m[k]).c;
|
|
706
|
+
if (type === 0 && (state.t === 1 || state.t === 2)) return null;
|
|
707
|
+
if (state.t === 2) {
|
|
708
|
+
let l = t.length - 1;
|
|
709
|
+
t = t[l];
|
|
710
|
+
m = m[l].c;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
k = key[i];
|
|
714
|
+
if ((hasOwn = Object.hasOwn(t, k)) && m[k]?.t === 0 && m[k]?.d) return null;
|
|
715
|
+
if (!hasOwn) {
|
|
716
|
+
let unsafe = k === "__proto__";
|
|
717
|
+
if (ctx.uk && (unsafe || k === "constructor")) return false;
|
|
718
|
+
if (unsafe) {
|
|
719
|
+
Object.defineProperty(t, k, {
|
|
720
|
+
enumerable: true,
|
|
721
|
+
configurable: true,
|
|
722
|
+
writable: true
|
|
723
|
+
});
|
|
724
|
+
Object.defineProperty(m, k, {
|
|
725
|
+
enumerable: true,
|
|
726
|
+
configurable: true,
|
|
727
|
+
writable: true
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
m[k] = {
|
|
731
|
+
t: i < key.length - 1 && type === 2 ? 3 : type,
|
|
732
|
+
d: false,
|
|
733
|
+
i: 0,
|
|
734
|
+
c: Object.create(null)
|
|
735
|
+
};
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
state = m[k];
|
|
739
|
+
if (state.t !== type && !(type === 1 && state.t === 3)) return null;
|
|
740
|
+
if (type === 2) {
|
|
741
|
+
if (!state.d) {
|
|
742
|
+
state.d = true;
|
|
743
|
+
t[k] = [];
|
|
744
|
+
}
|
|
745
|
+
t[k].push(t = Object.create(null));
|
|
746
|
+
state.c[state.i++] = state = {
|
|
747
|
+
t: 1,
|
|
748
|
+
d: false,
|
|
749
|
+
i: 0,
|
|
750
|
+
c: Object.create(null)
|
|
751
|
+
};
|
|
752
|
+
}
|
|
753
|
+
if (state.d) return null;
|
|
754
|
+
state.d = true;
|
|
755
|
+
if (type === 1) t = hasOwn ? t[k] : t[k] = Object.create(null);
|
|
756
|
+
else if (type === 0 && hasOwn) return null;
|
|
757
|
+
return [
|
|
758
|
+
k,
|
|
759
|
+
t,
|
|
760
|
+
state.c
|
|
761
|
+
];
|
|
762
|
+
}
|
|
763
|
+
function validateTablePeek(ctx, peek, ptr) {
|
|
764
|
+
if (peek === null || ctx.uk === 2) TomlError.x(peek === null ? "trying to redefine an already defined table or value" : "document contains an unsafe property", ctx, ptr);
|
|
765
|
+
}
|
|
766
|
+
function parse(toml, options = {}) {
|
|
767
|
+
let ctx = {
|
|
768
|
+
s: toml,
|
|
769
|
+
p: 0,
|
|
770
|
+
d: options.maxDepth ?? 1e3,
|
|
771
|
+
bi: options.integersAsBigInt ?? false,
|
|
772
|
+
ld: options.useLegacyDate ?? true,
|
|
773
|
+
uk: options.unsafeKeyBehaviour === "throw" ? 2 : options.unsafeKeyBehaviour === "drop" ? 1 : 0
|
|
774
|
+
};
|
|
775
|
+
let res = Object.create(null);
|
|
776
|
+
let meta = Object.create(null);
|
|
777
|
+
let tmp;
|
|
778
|
+
let skipping = false;
|
|
779
|
+
let tbl = res;
|
|
780
|
+
let m = meta;
|
|
781
|
+
if (toml.charCodeAt(0) === 65279) ctx.p++;
|
|
782
|
+
skipVoid(ctx);
|
|
783
|
+
while (ctx.p < toml.length) {
|
|
784
|
+
if (toml.charCodeAt(ctx.p) === 91) {
|
|
785
|
+
let isTableArray = toml.charCodeAt(++ctx.p) === 91;
|
|
786
|
+
tmp = ctx.p += +isTableArray;
|
|
787
|
+
skipping = false;
|
|
788
|
+
let k = parseKey(ctx, 93);
|
|
789
|
+
if (isTableArray) {
|
|
790
|
+
if (toml.charCodeAt(ctx.p) !== 93) TomlError.x("expected end of table array declaration", ctx);
|
|
791
|
+
ctx.p++;
|
|
792
|
+
}
|
|
793
|
+
let p = peekTable(ctx, k, res, meta, isTableArray ? 2 : 1);
|
|
794
|
+
if (!p) {
|
|
795
|
+
validateTablePeek(ctx, p, tmp);
|
|
796
|
+
skipping = true;
|
|
797
|
+
} else {
|
|
798
|
+
m = p[2];
|
|
799
|
+
tbl = p[1];
|
|
800
|
+
}
|
|
801
|
+
} else {
|
|
802
|
+
tmp = ctx.p;
|
|
803
|
+
let p = peekTable(ctx, parseKey(ctx), tbl, m, 0);
|
|
804
|
+
if (!p && !skipping) validateTablePeek(ctx, p, tmp);
|
|
805
|
+
skipVoid(ctx, true, true);
|
|
806
|
+
let v = extractValue(ctx, void 0);
|
|
807
|
+
if (p && !skipping) p[1][p[0]] = v;
|
|
808
|
+
}
|
|
809
|
+
skipVoid(ctx, true);
|
|
810
|
+
if (ctx.p < toml.length && (tmp = toml.charCodeAt(ctx.p)) !== 10 && (tmp !== 13 || toml.charCodeAt(ctx.p + 1) !== 10)) TomlError.x("each key-value declaration must be followed by an end-of-line", ctx);
|
|
811
|
+
skipVoid(ctx);
|
|
812
|
+
}
|
|
813
|
+
return res;
|
|
814
|
+
}
|
|
815
|
+
//#endregion
|
|
816
|
+
//#region src/cli/rls/rbac.ts
|
|
817
|
+
/**
|
|
818
|
+
* Where the helpers read roles and memberships: the flag, `rls.authorize`,
|
|
819
|
+
* `rls.rbac.authorize`, then `database` with `rls.membershipSources`, with
|
|
820
|
+
* `--rbac` or with a mapped memberships table, else `jwt`.
|
|
821
|
+
*/
|
|
822
|
+
function resolveAuthorize(config, flags = {}) {
|
|
823
|
+
const rls = config.rls;
|
|
824
|
+
const explicit = flags.authorize ?? rls?.authorize ?? rls?.rbac?.authorize;
|
|
825
|
+
if (explicit !== void 0) return explicit;
|
|
826
|
+
if (rls?.membershipSources !== void 0 || flags.rbac === true) return "database";
|
|
827
|
+
const memberships = flags.memberships ?? rls?.memberships;
|
|
828
|
+
return Object.keys(memberships?.scopes ?? {}).length > 0 ? "database" : "jwt";
|
|
829
|
+
}
|
|
830
|
+
function parseRbacAuthorize(raw) {
|
|
831
|
+
if (raw === void 0) return;
|
|
832
|
+
if (raw === "database" || raw === "jwt") return raw;
|
|
833
|
+
throw configError(`PermDock CLI: --authorize must be database or jwt, got '${raw}'`);
|
|
834
|
+
}
|
|
835
|
+
function hookUri(schema) {
|
|
836
|
+
return `pg-functions://postgres/${schema}/custom_access_token_hook`;
|
|
837
|
+
}
|
|
838
|
+
function createEnum(schema, name, values) {
|
|
839
|
+
const list = values.map((value) => quoteLiteral(value)).join(", ");
|
|
840
|
+
return `do $$ begin
|
|
841
|
+
create type ${quoteTable(`${schema}.${name}`)} as enum (${list});
|
|
842
|
+
exception when duplicate_object then null;
|
|
843
|
+
end $$;`;
|
|
844
|
+
}
|
|
845
|
+
/**
|
|
846
|
+
* A read policy and `select` grant for `supabase_auth_admin` on a table the
|
|
847
|
+
* hook reads.
|
|
848
|
+
*/
|
|
849
|
+
function authAdminRead(table, label) {
|
|
850
|
+
const t = quoteQualified(table);
|
|
851
|
+
const policy = quoteIdent(`permdock_auth_admin_read_${label}`);
|
|
852
|
+
return `grant select on table ${t} to supabase_auth_admin;
|
|
853
|
+
drop policy if exists ${policy} on ${t};
|
|
854
|
+
create policy ${policy} on ${t}
|
|
855
|
+
as permissive for select
|
|
856
|
+
to supabase_auth_admin
|
|
857
|
+
using (true);`;
|
|
858
|
+
}
|
|
859
|
+
/**
|
|
860
|
+
* Supabase's Custom Claims and RBAC scaffold on top of the PermDock helpers:
|
|
861
|
+
* enums, `user_roles` and `authorize()` over the shared `role_permissions`. The
|
|
862
|
+
* token hook comes only from `permdock supabase hook generate`, so one function
|
|
863
|
+
* writes the claims. Policies never call `authorize()` per row; they call the
|
|
864
|
+
* helpers. Never grants anything to `service_role`.
|
|
865
|
+
*/
|
|
866
|
+
function rbacScaffold(policy, options) {
|
|
867
|
+
const schema = options.schema;
|
|
868
|
+
const q = (name) => quoteTable(`${schema}.${name}`);
|
|
869
|
+
const s = quoteIdent(schema);
|
|
870
|
+
const permissions = [...new Set(policy.grants.map((grant) => grant.permission.key))];
|
|
871
|
+
const authorizeFn = authorizeSql({
|
|
872
|
+
schema,
|
|
873
|
+
authorize: options.authorize,
|
|
874
|
+
...options.scope === void 0 ? {} : { scope: options.scope },
|
|
875
|
+
...options.memberships === void 0 ? {} : { tenant: options.memberships },
|
|
876
|
+
...options.customRoles === void 0 ? {} : { customRoles: options.customRoles },
|
|
877
|
+
...options.context?.suspension === void 0 ? {} : { suspension: options.context.suspension }
|
|
878
|
+
});
|
|
879
|
+
return {
|
|
880
|
+
head: `-- rbac scaffold (Supabase Custom Claims and RBAC)
|
|
881
|
+
-- authorize: ${options.authorize}${options.authorize === "jwt" ? " (reads the hook claims; stale until the token refreshes)" : " (reads user_roles on every statement)"}
|
|
882
|
+
-- the custom access token hook that writes user_role${options.authorize === "jwt" ? " and memberships" : ""}: permdock supabase hook generate
|
|
883
|
+
${schema === "public" ? "" : `create schema if not exists ${s};\n`}${createEnum(schema, "app_role", roleNames(policy))}
|
|
884
|
+
${createEnum(schema, "app_permission", permissions)}
|
|
885
|
+
|
|
886
|
+
create table if not exists ${q("user_roles")} (
|
|
887
|
+
user_id uuid not null references auth.users on delete cascade,
|
|
888
|
+
role ${options.customRoles === void 0 ? q("app_role") : "text"} not null,
|
|
889
|
+
primary key (user_id, role)
|
|
890
|
+
);
|
|
891
|
+
|
|
892
|
+
alter table ${q("user_roles")} enable row level security;
|
|
893
|
+
revoke all on table ${q("user_roles")} from authenticated, anon, public;
|
|
894
|
+
`,
|
|
895
|
+
tail: authorizeFn,
|
|
896
|
+
warnings: []
|
|
897
|
+
};
|
|
898
|
+
}
|
|
899
|
+
//#endregion
|
|
27
900
|
//#region src/cli/supabase-config.ts
|
|
28
901
|
const SUPABASE_CONFIG = "supabase/config.toml";
|
|
29
902
|
function table(value) {
|
|
@@ -50,6 +923,9 @@ function readSupabaseConfig(cwd) {
|
|
|
50
923
|
const paths = table(table(root["db"])?.["migrations"])?.["schema_paths"];
|
|
51
924
|
const schemaPaths = strings(paths);
|
|
52
925
|
const apiSchemas = strings(table(root["api"])?.["schemas"]);
|
|
926
|
+
const hookTable = table(table(table(root["auth"])?.["hook"])?.["custom_access_token"]);
|
|
927
|
+
const hookEnabled = hookTable?.["enabled"];
|
|
928
|
+
const hookUriValue = hookTable?.["uri"];
|
|
53
929
|
const pgDelta = table(table(root["experimental"])?.["pgdelta"]);
|
|
54
930
|
const schemaPath = pgDelta?.["declarative_schema_path"];
|
|
55
931
|
const enabled = pgDelta?.["enabled"];
|
|
@@ -59,6 +935,10 @@ function readSupabaseConfig(cwd) {
|
|
|
59
935
|
...typeof expiry === "number" ? { jwtExpiry: expiry } : {},
|
|
60
936
|
...schemaPaths === void 0 ? {} : { schemaPaths },
|
|
61
937
|
...apiSchemas === void 0 ? {} : { apiSchemas },
|
|
938
|
+
...hookTable === void 0 ? {} : { customAccessTokenHook: {
|
|
939
|
+
...typeof hookEnabled === "boolean" ? { enabled: hookEnabled } : {},
|
|
940
|
+
...typeof hookUriValue === "string" ? { uri: hookUriValue } : {}
|
|
941
|
+
} },
|
|
62
942
|
...pgDelta === void 0 ? {} : { pgDelta: {
|
|
63
943
|
...typeof enabled === "boolean" ? { enabled } : {},
|
|
64
944
|
schemaDir: declarativeSchemaDir(schemaPath)
|
|
@@ -66,16 +946,25 @@ function readSupabaseConfig(cwd) {
|
|
|
66
946
|
}
|
|
67
947
|
};
|
|
68
948
|
}
|
|
69
|
-
/**
|
|
949
|
+
/**
|
|
950
|
+
* `supabase/` joined with `declarative_schema_path`, which defaults to
|
|
951
|
+
* `schemas`.
|
|
952
|
+
*/
|
|
70
953
|
function declarativeSchemaDir(schemaPath) {
|
|
71
954
|
return posix.join("supabase", typeof schemaPath === "string" ? schemaPath : "schemas").replace(/\/$/u, "");
|
|
72
955
|
}
|
|
73
|
-
/**
|
|
956
|
+
/**
|
|
957
|
+
* The parsed config, or `{}` when it is missing or does not parse (PD045
|
|
958
|
+
* reports that).
|
|
959
|
+
*/
|
|
74
960
|
function supabaseConfig(cwd) {
|
|
75
961
|
const read = readSupabaseConfig(cwd);
|
|
76
962
|
return read?.ok === true ? read.config : {};
|
|
77
963
|
}
|
|
78
|
-
/**
|
|
964
|
+
/**
|
|
965
|
+
* PD045: a `supabase/config.toml` the CLI cannot parse, so every check that
|
|
966
|
+
* reads it falls back to defaults.
|
|
967
|
+
*/
|
|
79
968
|
function pd045(cwd) {
|
|
80
969
|
const read = readSupabaseConfig(cwd);
|
|
81
970
|
if (read === void 0 || read.ok) return [];
|
|
@@ -86,6 +975,32 @@ function pd045(cwd) {
|
|
|
86
975
|
fix: `fix the TOML syntax in ${SUPABASE_CONFIG}; until then PermDock assumes Supabase's defaults for jwt_expiry, schema_paths and [experimental.pgdelta], and generates for pg-delta`
|
|
87
976
|
}];
|
|
88
977
|
}
|
|
978
|
+
/**
|
|
979
|
+
* PD074: `supabase.hook` is configured but `[auth.hook.custom_access_token]` in
|
|
980
|
+
* `supabase/config.toml` does not enable the generated function, so a local
|
|
981
|
+
* stack and every branch push issue tokens without memberships.
|
|
982
|
+
*/
|
|
983
|
+
function pd074(cwd, config) {
|
|
984
|
+
const hook = config.supabase?.hook;
|
|
985
|
+
const read = readSupabaseConfig(cwd);
|
|
986
|
+
if (hook === void 0 || read === void 0 || !read.ok) return [];
|
|
987
|
+
const expected = hookUri(hook.schema ?? config.rls?.schema ?? "permdock");
|
|
988
|
+
const found = read.config.customAccessTokenHook;
|
|
989
|
+
const fix = `add to ${SUPABASE_CONFIG}:\n[auth.hook.custom_access_token]\nenabled = true\nuri = "${expected}"`;
|
|
990
|
+
if (found?.enabled !== true) return [{
|
|
991
|
+
code: "PD074",
|
|
992
|
+
severity: "warning",
|
|
993
|
+
message: `supabase.hook is configured but ${SUPABASE_CONFIG} does not set [auth.hook.custom_access_token] enabled = true, so Auth never calls the hook`,
|
|
994
|
+
fix
|
|
995
|
+
}];
|
|
996
|
+
if (found.uri !== expected) return [{
|
|
997
|
+
code: "PD074",
|
|
998
|
+
severity: "warning",
|
|
999
|
+
message: `[auth.hook.custom_access_token] uri is ${found.uri ?? "missing"}, but the generated hook is ${expected}`,
|
|
1000
|
+
fix: `set uri = "${expected}" in ${SUPABASE_CONFIG}`
|
|
1001
|
+
}];
|
|
1002
|
+
return [];
|
|
1003
|
+
}
|
|
89
1004
|
//#endregion
|
|
90
1005
|
//#region src/cli/claims-schema.ts
|
|
91
1006
|
/**
|
|
@@ -123,6 +1038,11 @@ const PERMDOCK_CLAIMS_SCHEMA = {
|
|
|
123
1038
|
description: "true when the size budget cut memberships or attrs.",
|
|
124
1039
|
type: "boolean"
|
|
125
1040
|
},
|
|
1041
|
+
team_ids: {
|
|
1042
|
+
description: "The uuid of every team the user belongs to (supabase.hook.teams), cut by the memberships budget.",
|
|
1043
|
+
type: "array",
|
|
1044
|
+
items: { type: "string" }
|
|
1045
|
+
},
|
|
126
1046
|
tenant_id: {
|
|
127
1047
|
description: "The active tenant (the default rls.tenantClaim): the canonical text of one instance of the first scope.",
|
|
128
1048
|
type: "string"
|
|
@@ -221,8 +1141,8 @@ const USER_EDITABLE = /^(raw_)?user_meta(_)?data$/iu;
|
|
|
221
1141
|
/**
|
|
222
1142
|
* Splits `supabase.hook.attrs` into table columns and `app_metadata` keys and
|
|
223
1143
|
* lists what cannot be compiled: `user_metadata` (the user can edit it), a
|
|
224
|
-
* direct `auth.users` column, an unsafe or prototype key, a duplicate key,
|
|
225
|
-
*
|
|
1144
|
+
* direct `auth.users` column, an unsafe or prototype key, a duplicate key, or a
|
|
1145
|
+
* table column without a table.
|
|
226
1146
|
*/
|
|
227
1147
|
function attrsPlan(attrs) {
|
|
228
1148
|
const errors = [];
|
|
@@ -268,6 +1188,7 @@ const RESERVED_CLAIMS = /* @__PURE__ */ new Set([
|
|
|
268
1188
|
"user_role",
|
|
269
1189
|
"memberships",
|
|
270
1190
|
"memberships_truncated",
|
|
1191
|
+
"team_ids",
|
|
271
1192
|
"attrs",
|
|
272
1193
|
"authz_ver",
|
|
273
1194
|
"sub",
|
|
@@ -336,8 +1257,8 @@ function beforeSql(before) {
|
|
|
336
1257
|
}
|
|
337
1258
|
/**
|
|
338
1259
|
* `hook.validate`: the claims the hook writes, dropped together when they do
|
|
339
|
-
* not match `supabase-claims-v1.json`, so a bad claim denies instead of
|
|
340
|
-
*
|
|
1260
|
+
* not match `supabase-claims-v1.json`, so a bad claim denies instead of failing
|
|
1261
|
+
* sign-in. `hook.claims` entries belong to other packages and stay.
|
|
341
1262
|
*/
|
|
342
1263
|
function validateSql(parts) {
|
|
343
1264
|
if (parts.hook.validate !== true) return "";
|
|
@@ -346,6 +1267,7 @@ function validateSql(parts) {
|
|
|
346
1267
|
"roles",
|
|
347
1268
|
"memberships",
|
|
348
1269
|
"memberships_truncated",
|
|
1270
|
+
...parts.hook.teams === void 0 ? [] : ["team_ids"],
|
|
349
1271
|
"attrs",
|
|
350
1272
|
"authz_ver",
|
|
351
1273
|
parts.tenantClaim
|
|
@@ -362,8 +1284,8 @@ grant usage on schema extensions to supabase_auth_admin;
|
|
|
362
1284
|
grant execute on function extensions.jsonb_matches_schema(json, jsonb) to supabase_auth_admin;` : "";
|
|
363
1285
|
}
|
|
364
1286
|
/**
|
|
365
|
-
* Fails the migration when a client role can write an `attrs` column: a
|
|
366
|
-
*
|
|
1287
|
+
* Fails the migration when a client role can write an `attrs` column: a claim
|
|
1288
|
+
* the user can set is not a server-owned attribute.
|
|
367
1289
|
*/
|
|
368
1290
|
function attrsGuardSql(plan) {
|
|
369
1291
|
if (plan?.table === void 0 || plan.columns.length === 0) return "";
|
|
@@ -398,6 +1320,7 @@ function hookClaims(parts) {
|
|
|
398
1320
|
permdockClaim("memberships", true),
|
|
399
1321
|
permdockClaim("memberships_truncated"),
|
|
400
1322
|
permdockClaim(parts.tenantClaim),
|
|
1323
|
+
...parts.hook.teams === void 0 ? [] : [permdockClaim("team_ids", true)],
|
|
401
1324
|
...parts.attrs === void 0 ? [] : [permdockClaim("attrs", true)],
|
|
402
1325
|
...parts.version ? [permdockClaim("authz_ver")] : [],
|
|
403
1326
|
...parts.extra.map((entry) => ({
|
|
@@ -408,6 +1331,19 @@ function hookClaims(parts) {
|
|
|
408
1331
|
];
|
|
409
1332
|
}
|
|
410
1333
|
//#endregion
|
|
1334
|
+
//#region src/cli/sql/declarative.ts
|
|
1335
|
+
/**
|
|
1336
|
+
* A migration's SQL as a declarative schema file: pg-delta diffs the file
|
|
1337
|
+
* against the database itself, so a `drop trigger if exists` or `drop policy if
|
|
1338
|
+
* exists` before its `create` is an error, and a trigger is `create or replace
|
|
1339
|
+
* trigger`. A constraint trigger stays `create constraint trigger`, because
|
|
1340
|
+
* pg-delta has no `create or replace constraint trigger`. A policy keeps its
|
|
1341
|
+
* plain `create policy`.
|
|
1342
|
+
*/
|
|
1343
|
+
function declarativeSql(sql) {
|
|
1344
|
+
return sql.replaceAll(/^drop (?:trigger|policy) if exists [^;\n]+;\n/gmu, "").replaceAll(/^create trigger /gmu, "create or replace trigger ");
|
|
1345
|
+
}
|
|
1346
|
+
//#endregion
|
|
411
1347
|
//#region src/cli/supabase-schemas.ts
|
|
412
1348
|
const MODES = [
|
|
413
1349
|
"pg-delta",
|
|
@@ -422,9 +1358,9 @@ function schemasRefusal(command, value) {
|
|
|
422
1358
|
return value === void 0 || isSupabaseSchemas(value) ? void 0 : `${command} --schemas must be ${MODES.join(", ")} (got ${value})`;
|
|
423
1359
|
}
|
|
424
1360
|
/**
|
|
425
|
-
* `--schemas`, else `supabase.schemas`, else `migra` when `config.toml`
|
|
426
|
-
*
|
|
427
|
-
*
|
|
1361
|
+
* `--schemas`, else `supabase.schemas`, else `migra` when `config.toml` sets
|
|
1362
|
+
* `[experimental.pgdelta] enabled = false`, else `pg-delta`: the default of new
|
|
1363
|
+
* Supabase projects and of the next Supabase CLI major.
|
|
428
1364
|
*/
|
|
429
1365
|
function resolveSchemas(cwd, config, flag) {
|
|
430
1366
|
const toml = supabaseConfig(cwd).pgDelta;
|
|
@@ -445,7 +1381,10 @@ const HELPER_NAME = /^(?:permdock_has|permitted_[a-z][a-z0-9_]*_ids|member_[a-z]
|
|
|
445
1381
|
function escape(text) {
|
|
446
1382
|
return text.replaceAll(/[.*+?^${}()|[\]\\]/gu, String.raw`\$&`);
|
|
447
1383
|
}
|
|
448
|
-
/**
|
|
1384
|
+
/**
|
|
1385
|
+
* The helper functions `sql` creates in `schema`; unqualified names count for
|
|
1386
|
+
* `public`.
|
|
1387
|
+
*/
|
|
449
1388
|
function helpersDefined(sql, schema) {
|
|
450
1389
|
const qualifier = schema === "public" ? String.raw`(?:(?:"public"|public)\.)?` : String.raw`(?:"${escape(schema)}"|${escape(schema)})\.`;
|
|
451
1390
|
const create = new RegExp(String.raw`\bcreate\s+(?:or\s+replace\s+)?function\s+${qualifier}"?([a-z_][a-z0-9_]*)"?\s*\(`, "giu");
|
|
@@ -457,9 +1396,9 @@ function helpersDefined(sql, schema) {
|
|
|
457
1396
|
return names;
|
|
458
1397
|
}
|
|
459
1398
|
/**
|
|
460
|
-
* SQL files that may hold the generated helpers: `rls.out` (else `rls.sql`;
|
|
461
|
-
*
|
|
462
|
-
*
|
|
1399
|
+
* SQL files that may hold the generated helpers: `rls.out` (else `rls.sql`; its
|
|
1400
|
+
* `helpers` part when it has `{part}`), the SQL files next to the hook, and the
|
|
1401
|
+
* migration folders, not the hook itself.
|
|
463
1402
|
*/
|
|
464
1403
|
function helperSources(cwd, config, hookOut) {
|
|
465
1404
|
const hook = resolve(cwd, hookOut);
|
|
@@ -492,7 +1431,10 @@ where n.nspname = $1 and p.proname = any($2::text[])`, [manifest.helpers.schema,
|
|
|
492
1431
|
function missingHelpersMessage(manifest, missing) {
|
|
493
1432
|
return `PD039 schema ${manifest.helpers.schema} has no ${missing.join(", ")}: the hook's claims are read by these helpers; run permdock rls generate and apply its migration`;
|
|
494
1433
|
}
|
|
495
|
-
/**
|
|
1434
|
+
/**
|
|
1435
|
+
* Bytes of JSON of each extra claim in the largest sample, for claims that pass
|
|
1436
|
+
* the budget.
|
|
1437
|
+
*/
|
|
496
1438
|
function oversizedClaims(samples, manifest) {
|
|
497
1439
|
const encoder = new TextEncoder();
|
|
498
1440
|
const oversized = [];
|
|
@@ -576,87 +1518,6 @@ function readClaimsFixture(path) {
|
|
|
576
1518
|
}
|
|
577
1519
|
}
|
|
578
1520
|
//#endregion
|
|
579
|
-
//#region src/cli/rls/rbac.ts
|
|
580
|
-
/**
|
|
581
|
-
* Where the helpers read roles and memberships: the flag, `rls.authorize`,
|
|
582
|
-
* `rls.rbac.authorize`, then `database` with `rls.membershipSources`, with
|
|
583
|
-
* `--rbac` or with a mapped memberships table, else `jwt`.
|
|
584
|
-
*/
|
|
585
|
-
function resolveAuthorize(config, flags = {}) {
|
|
586
|
-
const rls = config.rls;
|
|
587
|
-
const explicit = flags.authorize ?? rls?.authorize ?? rls?.rbac?.authorize;
|
|
588
|
-
if (explicit !== void 0) return explicit;
|
|
589
|
-
if (rls?.membershipSources !== void 0 || flags.rbac === true) return "database";
|
|
590
|
-
const memberships = flags.memberships ?? rls?.memberships;
|
|
591
|
-
return memberships?.tenant !== void 0 || memberships?.team !== void 0 || Object.keys(memberships?.scopes ?? {}).length > 0 ? "database" : "jwt";
|
|
592
|
-
}
|
|
593
|
-
function parseRbacAuthorize(raw) {
|
|
594
|
-
if (raw === void 0) return;
|
|
595
|
-
if (raw === "database" || raw === "jwt") return raw;
|
|
596
|
-
throw configError(`PermDock CLI: --authorize must be database or jwt, got '${raw}'`);
|
|
597
|
-
}
|
|
598
|
-
function hookUri(schema) {
|
|
599
|
-
return `pg-functions://postgres/${schema}/custom_access_token_hook`;
|
|
600
|
-
}
|
|
601
|
-
function createEnum(schema, name, values) {
|
|
602
|
-
const list = values.map((value) => quoteLiteral(value)).join(", ");
|
|
603
|
-
return `do $$ begin
|
|
604
|
-
create type ${quoteTable(`${schema}.${name}`)} as enum (${list});
|
|
605
|
-
exception when duplicate_object then null;
|
|
606
|
-
end $$;`;
|
|
607
|
-
}
|
|
608
|
-
/** A read policy and `select` grant for `supabase_auth_admin` on a table the hook reads. */
|
|
609
|
-
function authAdminRead(table, label) {
|
|
610
|
-
const t = quoteQualified(table);
|
|
611
|
-
const policy = quoteIdent(`permdock_auth_admin_read_${label}`);
|
|
612
|
-
return `grant select on table ${t} to supabase_auth_admin;
|
|
613
|
-
drop policy if exists ${policy} on ${t};
|
|
614
|
-
create policy ${policy} on ${t}
|
|
615
|
-
as permissive for select
|
|
616
|
-
to supabase_auth_admin
|
|
617
|
-
using (true);`;
|
|
618
|
-
}
|
|
619
|
-
/**
|
|
620
|
-
* Supabase's Custom Claims and RBAC scaffold on top of the PermDock helpers:
|
|
621
|
-
* enums, `user_roles` and `authorize()` over the shared `role_permissions`.
|
|
622
|
-
* The token hook comes only from `permdock supabase hook generate`, so one
|
|
623
|
-
* function writes the claims. Policies never call `authorize()` per row; they
|
|
624
|
-
* call the helpers. Never grants anything to `service_role`.
|
|
625
|
-
*/
|
|
626
|
-
function rbacScaffold(policy, options) {
|
|
627
|
-
const schema = options.schema;
|
|
628
|
-
const q = (name) => quoteTable(`${schema}.${name}`);
|
|
629
|
-
const s = quoteIdent(schema);
|
|
630
|
-
const permissions = [...new Set(policy.grants.map((grant) => grant.permission.key))];
|
|
631
|
-
const authorizeFn = authorizeSql({
|
|
632
|
-
schema,
|
|
633
|
-
authorize: options.authorize,
|
|
634
|
-
...options.scope === void 0 ? {} : { scope: options.scope },
|
|
635
|
-
...options.memberships === void 0 ? {} : { tenant: options.memberships },
|
|
636
|
-
...options.customRoles === void 0 ? {} : { customRoles: options.customRoles },
|
|
637
|
-
...options.context?.suspension === void 0 ? {} : { suspension: options.context.suspension }
|
|
638
|
-
});
|
|
639
|
-
return {
|
|
640
|
-
head: `-- rbac scaffold (Supabase Custom Claims and RBAC)
|
|
641
|
-
-- authorize: ${options.authorize}${options.authorize === "jwt" ? " (reads the hook claims; stale until the token refreshes)" : " (reads user_roles on every statement)"}
|
|
642
|
-
-- the custom access token hook that writes user_role${options.authorize === "jwt" ? " and memberships" : ""}: permdock supabase hook generate
|
|
643
|
-
${schema === "public" ? "" : `create schema if not exists ${s};\n`}${createEnum(schema, "app_role", roleNames(policy))}
|
|
644
|
-
${createEnum(schema, "app_permission", permissions)}
|
|
645
|
-
|
|
646
|
-
create table if not exists ${q("user_roles")} (
|
|
647
|
-
user_id uuid not null references auth.users on delete cascade,
|
|
648
|
-
role ${options.customRoles === void 0 ? q("app_role") : "text"} not null,
|
|
649
|
-
primary key (user_id, role)
|
|
650
|
-
);
|
|
651
|
-
|
|
652
|
-
alter table ${q("user_roles")} enable row level security;
|
|
653
|
-
revoke all on table ${q("user_roles")} from authenticated, anon, public;
|
|
654
|
-
`,
|
|
655
|
-
tail: authorizeFn,
|
|
656
|
-
warnings: []
|
|
657
|
-
};
|
|
658
|
-
}
|
|
659
|
-
//#endregion
|
|
660
1521
|
//#region src/cli/supabase-hook/memberships.ts
|
|
661
1522
|
function memberForPlan(input) {
|
|
662
1523
|
const memberFor = input.scopes.map((scope) => scope.name).filter((name) => hasMemberFor({
|
|
@@ -676,7 +1537,10 @@ function memberForPlan(input) {
|
|
|
676
1537
|
memberships: [...entries.values()]
|
|
677
1538
|
};
|
|
678
1539
|
}
|
|
679
|
-
/**
|
|
1540
|
+
/**
|
|
1541
|
+
* An `rls.memberships` table in the manifest's `tableMembershipSource` /
|
|
1542
|
+
* `junctionMembershipSource` shape, for scope `name`.
|
|
1543
|
+
*/
|
|
680
1544
|
function mappedMembership(mapped, scopes, name) {
|
|
681
1545
|
const id = scopeColumn(mapped, scopes, name) ?? "";
|
|
682
1546
|
const within = {};
|
|
@@ -781,18 +1645,18 @@ ${source.sql.select(`v_user_${String(index)}`).replaceAll(/^/gmu, " ")}
|
|
|
781
1645
|
//#region src/cli/supabase-hook/api.ts
|
|
782
1646
|
const SUBJECT_FOR = "subject_for";
|
|
783
1647
|
/**
|
|
784
|
-
* `subject_for(p_user uuid) returns jsonb`: what the hook would put in a
|
|
785
|
-
*
|
|
786
|
-
*
|
|
787
|
-
*
|
|
788
|
-
* subject for an acting user or a job from it. Naming the user is why no
|
|
789
|
-
*
|
|
1648
|
+
* `subject_for(p_user uuid) returns jsonb`: what the hook would put in a token
|
|
1649
|
+
* for `p_user`, from the same membership, role, suspension and version reads,
|
|
1650
|
+
* plus the custom roles the user holds when `database` mode keeps them in
|
|
1651
|
+
* tables. A backend that only has PostgREST (`postgrestSources`) builds a
|
|
1652
|
+
* subject for an acting user or a job from it. Naming the user is why no client
|
|
1653
|
+
* role may execute it.
|
|
790
1654
|
*/
|
|
791
1655
|
function subjectForSql(parts, config) {
|
|
792
1656
|
const schema = quoteIdent(parts.schema);
|
|
793
1657
|
const fn = `${schema}.${SUBJECT_FOR}`;
|
|
794
1658
|
const rows = parts.roles;
|
|
795
|
-
const roles = rows === void 0 ? ` held := '[]'::jsonb;` : ` select coalesce(jsonb_agg(distinct ${rows.roleSql} order by ${rows.roleSql}), '[]'::jsonb)
|
|
1659
|
+
const roles = rows === void 0 ? ` held := '[]'::jsonb;` : ` select coalesce(jsonb_agg(distinct ${rows.roleSql} order by ${rows.roleSql}) filter (where ${rows.roleSql} is not null), '[]'::jsonb)
|
|
796
1660
|
into held
|
|
797
1661
|
from ${rows.from}
|
|
798
1662
|
where ${rows.userSql} = v_roles_user;`;
|
|
@@ -803,6 +1667,20 @@ function subjectForSql(parts, config) {
|
|
|
803
1667
|
const version = parts.version ? `
|
|
804
1668
|
select v.version into ver from ${schema}.${quoteIdent(AUTHZ_VERSION_TABLE)} v where v.user_id = uid;
|
|
805
1669
|
ver := coalesce(ver, 0);` : "";
|
|
1670
|
+
const teamsConfig = parts.hook.teams;
|
|
1671
|
+
const teams = teamsConfig === void 0 ? "" : `
|
|
1672
|
+
select coalesce(jsonb_agg(to_jsonb(t.${quoteIdent(teamsConfig.team)}::text) order by t.${quoteIdent(teamsConfig.team)}), '[]'::jsonb)
|
|
1673
|
+
into team_ids
|
|
1674
|
+
from ${quoteQualified(teamsConfig.table)} t
|
|
1675
|
+
where t.${quoteIdent(teamsConfig.user)} = uid;
|
|
1676
|
+
if team_ids <> '[]'::jsonb then
|
|
1677
|
+
claims := jsonb_set(claims, '{team_ids}', team_ids);
|
|
1678
|
+
end if;`;
|
|
1679
|
+
const extra = parts.extra.map((entry) => `
|
|
1680
|
+
extra := ${quoteTable(entry.fn)}(uid);
|
|
1681
|
+
if extra is not null then
|
|
1682
|
+
claims := jsonb_set(claims, ${quoteLiteral(`{${entry.claim}}`)}, extra);
|
|
1683
|
+
end if;`).join("");
|
|
806
1684
|
const custom = customRolesOn(config.rls) && resolveAuthorize(config) === "database" ? customRolesOfSql(parts) : "";
|
|
807
1685
|
return `-- the subject the hook would mint for p_user, for a backend acting for a stored user; no client role may execute it
|
|
808
1686
|
create or replace function ${fn}(p_user uuid)
|
|
@@ -817,7 +1695,8 @@ declare
|
|
|
817
1695
|
held jsonb;
|
|
818
1696
|
memberships jsonb;
|
|
819
1697
|
custom jsonb := '[]'::jsonb;
|
|
820
|
-
ver bigint
|
|
1698
|
+
ver bigint;
|
|
1699
|
+
claims jsonb := '{}'::jsonb;${teamsConfig === void 0 ? "" : "\n team_ids jsonb := '[]'::jsonb;"}${parts.extra.length === 0 ? "" : "\n extra jsonb;"}${typedUsers(parts)}
|
|
821
1700
|
begin
|
|
822
1701
|
if uid is null or not exists (select 1 from auth.users u where u.id = uid) then
|
|
823
1702
|
return null;
|
|
@@ -827,8 +1706,9 @@ ${roles}
|
|
|
827
1706
|
into memberships
|
|
828
1707
|
from (
|
|
829
1708
|
${entriesSql(parts).replaceAll(/^/gmu, " ")}
|
|
830
|
-
) x;${custom}${version}
|
|
1709
|
+
) x;${custom}${version}${teams}${extra}
|
|
831
1710
|
return jsonb_strip_nulls(jsonb_build_object(
|
|
1711
|
+
'claims', case when claims = '{}'::jsonb then null else claims end,
|
|
832
1712
|
'id', uid::text,
|
|
833
1713
|
'active', true,
|
|
834
1714
|
'roles', held,
|
|
@@ -841,8 +1721,11 @@ $$;
|
|
|
841
1721
|
revoke execute on function ${fn}(uuid) from public, anon, authenticated;`;
|
|
842
1722
|
}
|
|
843
1723
|
/**
|
|
844
|
-
* The PostgREST wrappers `supabase.hook.api` asks for: one `security
|
|
1724
|
+
* The PostgREST wrappers `supabase.hook.api` asks for: one `security invoker`
|
|
845
1725
|
* function per reader, in the API schema, executable by `service_role` only.
|
|
1726
|
+
* The `security definer` readers stay in the hook schema, which the Data API
|
|
1727
|
+
* does not expose; `service_role` gets `usage` on it and `execute` on each
|
|
1728
|
+
* reader, so no definer function sits in an exposed schema.
|
|
846
1729
|
*/
|
|
847
1730
|
function apiWrappersSql(parts) {
|
|
848
1731
|
const api = parts.hook.api;
|
|
@@ -857,13 +1740,16 @@ function apiWrappersSql(parts) {
|
|
|
857
1740
|
returns ${returns}
|
|
858
1741
|
language sql
|
|
859
1742
|
stable
|
|
860
|
-
security
|
|
1743
|
+
security invoker
|
|
861
1744
|
set search_path = ''
|
|
862
1745
|
as $$ select ${source}.${inner}(${args}) $$;
|
|
863
1746
|
revoke execute on function ${fn}(${types}) from public, anon, authenticated;
|
|
864
|
-
grant execute on function ${fn}(${types}) to service_role
|
|
1747
|
+
grant execute on function ${fn}(${types}) to service_role;
|
|
1748
|
+
grant execute on function ${source}.${inner}(${types}) to service_role;`;
|
|
865
1749
|
};
|
|
866
|
-
return `-- supabase.hook.api: wrappers in ${quoteIdent(target)} for a backend that reaches the hook schema through the Data API; only service_role may execute them
|
|
1750
|
+
return `-- supabase.hook.api: security invoker wrappers in ${quoteIdent(target)} for a backend that reaches the hook schema through the Data API; only service_role may execute them, and the security definer readers stay in ${source}
|
|
1751
|
+
grant usage on schema ${source} to service_role;
|
|
1752
|
+
|
|
867
1753
|
${wrapper(names.subjectFor, SUBJECT_FOR, "p_user uuid", "p_user", "uuid", "jsonb")}
|
|
868
1754
|
|
|
869
1755
|
${wrapper(names.membersOf, MEMBERS_OF, "p_scope text, p_id text", "p_scope, p_id", "text, text", "jsonb")}
|
|
@@ -936,9 +1822,9 @@ revoke execute on function ${fn}(text, text) from public, anon, authenticated;`;
|
|
|
936
1822
|
}
|
|
937
1823
|
/**
|
|
938
1824
|
* The custom roles `p_user` holds: tenant and shared roles named on a
|
|
939
|
-
* membership of the scope (and instance) they live at, and platform roles
|
|
940
|
-
*
|
|
941
|
-
*
|
|
1825
|
+
* membership of the scope (and instance) they live at, and platform roles among
|
|
1826
|
+
* the global roles, each with its grants and includes in `CustomRole` form. A
|
|
1827
|
+
* shadowed tenant role comes along; `resolveCustomRole`'s callers drop it.
|
|
942
1828
|
*/
|
|
943
1829
|
function customRolesOfSql(parts) {
|
|
944
1830
|
const helpers = quoteIdent(parts.helpers.schema);
|
|
@@ -989,9 +1875,15 @@ function customRolesOfSql(parts) {
|
|
|
989
1875
|
}
|
|
990
1876
|
//#endregion
|
|
991
1877
|
//#region src/cli/rls/approvals.ts
|
|
992
|
-
/**
|
|
1878
|
+
/**
|
|
1879
|
+
* `rls.approvals`' approver check; better-supabase's `isApprover` template
|
|
1880
|
+
* calls it.
|
|
1881
|
+
*/
|
|
993
1882
|
const IS_APPROVER = "permdock_is_approver";
|
|
994
|
-
/**
|
|
1883
|
+
/**
|
|
1884
|
+
* The objects `rls.approvals` adds. Names are part of the SQL contract
|
|
1885
|
+
* `supabaseApprovalStore` calls.
|
|
1886
|
+
*/
|
|
995
1887
|
const APPROVAL_STORE = {
|
|
996
1888
|
table: "approval_requests",
|
|
997
1889
|
open: "permdock_approval_open",
|
|
@@ -1027,8 +1919,8 @@ function serverOnly(fn, args) {
|
|
|
1027
1919
|
const BODY_CHECK = `${APPROVAL_STORE.table}_body_schema`;
|
|
1028
1920
|
/**
|
|
1029
1921
|
* `rls.jsonSchema`: a pg_jsonschema check that `body` matches
|
|
1030
|
-
* `approval-request-v1.json`, added `not valid` and then validated. `auto`
|
|
1031
|
-
*
|
|
1922
|
+
* `approval-request-v1.json`, added `not valid` and then validated. `auto` adds
|
|
1923
|
+
* it only where the extension is available.
|
|
1032
1924
|
*/
|
|
1033
1925
|
function bodySchemaSql(table, mode, body = "body", check = BODY_CHECK) {
|
|
1034
1926
|
const statements = [
|
|
@@ -1050,11 +1942,11 @@ end
|
|
|
1050
1942
|
$permdock$;\n`;
|
|
1051
1943
|
}
|
|
1052
1944
|
/**
|
|
1053
|
-
* The approval store (`rls.approvals`): one table of `ApprovalRequest`
|
|
1054
|
-
*
|
|
1055
|
-
*
|
|
1056
|
-
*
|
|
1057
|
-
*
|
|
1945
|
+
* The approval store (`rls.approvals`): one table of `ApprovalRequest` bodies
|
|
1946
|
+
* with the columns a list filters on, and one `security definer` function per
|
|
1947
|
+
* `ApprovalStore` method, each one atomic statement. No client role may read
|
|
1948
|
+
* the table or execute the functions: approvals are opened and resolved by the
|
|
1949
|
+
* server, which grants its own role.
|
|
1058
1950
|
*/
|
|
1059
1951
|
function approvalStoreSql(ctx, jsonSchema = false) {
|
|
1060
1952
|
const table = qualified(ctx, APPROVAL_STORE.table);
|
|
@@ -1211,8 +2103,8 @@ ${serverOnly(fn(APPROVAL_STORE.cancel), "jsonb, text, text, text")}
|
|
|
1211
2103
|
/**
|
|
1212
2104
|
* `permdock_is_approver(p_approvers jsonb, p_tenant text default null)`: true
|
|
1213
2105
|
* when the signed-in user matches the serialised approvers of a request
|
|
1214
|
-
* (`approvers.by`), for policies on the app's own approval views. A list
|
|
1215
|
-
*
|
|
2106
|
+
* (`approvers.by`), for policies on the app's own approval views. A list needs
|
|
2107
|
+
* every item and `any-of` one of them; `user` compares the user id and
|
|
1216
2108
|
* `holder(permission)` reads `permitted_<root>_ids_by_permission` in
|
|
1217
2109
|
* `p_tenant`, or `permdock_has_permission` without one. Role, relation and
|
|
1218
2110
|
* other grantee approvers need facts the database does not hold for every
|
|
@@ -1309,19 +2201,22 @@ function approvalsSql(ctx, approvals, jsonSchema) {
|
|
|
1309
2201
|
}, jsonSchema);
|
|
1310
2202
|
return store + isApproverSql(ctx) + (delegations === true ? approvalDelegationsSql(ctx) : "");
|
|
1311
2203
|
}
|
|
1312
|
-
/**
|
|
2204
|
+
/**
|
|
2205
|
+
* The objects `rls.approvals.delegations` adds; `tableApprovalDelegationSource`
|
|
2206
|
+
* reads the table.
|
|
2207
|
+
*/
|
|
1313
2208
|
const DELEGATIONS = {
|
|
1314
2209
|
table: "approval_delegations",
|
|
1315
2210
|
covers: "permdock_cover_approves"
|
|
1316
2211
|
};
|
|
1317
2212
|
/**
|
|
1318
|
-
* `rls.approvals.delegations`: one table of out-of-office covers that a
|
|
1319
|
-
*
|
|
1320
|
-
*
|
|
1321
|
-
*
|
|
1322
|
-
* delegator
|
|
1323
|
-
*
|
|
1324
|
-
*
|
|
2213
|
+
* `rls.approvals.delegations`: one table of out-of-office covers that a user
|
|
2214
|
+
* writes for themselves, and a four-argument `permdock_is_approver` that also
|
|
2215
|
+
* answers for a delegate inside an active cover. One hop: a cover is checked
|
|
2216
|
+
* against the delegator's own approver rights, never the delegator's covers. A
|
|
2217
|
+
* delegator who is the requester never counts. A `holder()` approver through a
|
|
2218
|
+
* cover needs `rls.mode: "database"`, where the `_for` helpers exist; in `jwt`
|
|
2219
|
+
* mode only `user()` approvers pass.
|
|
1325
2220
|
*/
|
|
1326
2221
|
function approvalDelegationsSql(ctx) {
|
|
1327
2222
|
const table = qualified(ctx, DELEGATIONS.table);
|
|
@@ -1475,7 +2370,10 @@ revoke execute on function ${fn}(jsonb, text, text, text) from public, anon;
|
|
|
1475
2370
|
grant execute on function ${fn}(jsonb, text, text, text) to authenticated;
|
|
1476
2371
|
`;
|
|
1477
2372
|
}
|
|
1478
|
-
/**
|
|
2373
|
+
/**
|
|
2374
|
+
* The request fields an adopted table may mirror into its own columns, as SQL
|
|
2375
|
+
* over a body.
|
|
2376
|
+
*/
|
|
1479
2377
|
const MIRRORS = {
|
|
1480
2378
|
status: (body) => `${body} ->> 'status'`,
|
|
1481
2379
|
permission: (body) => `${body} ->> 'permission'`,
|
|
@@ -1499,7 +2397,10 @@ function mirrorsOf(adopt) {
|
|
|
1499
2397
|
}
|
|
1500
2398
|
return out;
|
|
1501
2399
|
}
|
|
1502
|
-
/**
|
|
2400
|
+
/**
|
|
2401
|
+
* One row of `table` from `values` (column, SQL), each converted to the
|
|
2402
|
+
* column's own type.
|
|
2403
|
+
*/
|
|
1503
2404
|
function populate(table, values) {
|
|
1504
2405
|
return `pg_catalog.jsonb_populate_record(null::${table}, pg_catalog.jsonb_build_object(${values.map(([column, sql]) => `${quoteLiteral(column)}, ${sql}`).join(", ")}))`;
|
|
1505
2406
|
}
|
|
@@ -1507,7 +2408,10 @@ function populate(table, values) {
|
|
|
1507
2408
|
function mirrorRow(table, mirror, body) {
|
|
1508
2409
|
return populate(table, mirror.map(([column, field]) => [column, MIRRORS[field](body)]));
|
|
1509
2410
|
}
|
|
1510
|
-
/**
|
|
2411
|
+
/**
|
|
2412
|
+
* `, (<mirrored columns>) = (select …)` for an update that writes `body`; empty
|
|
2413
|
+
* without mirrors.
|
|
2414
|
+
*/
|
|
1511
2415
|
function mirrorSet(table, mirror, body) {
|
|
1512
2416
|
if (mirror.length === 0) return "";
|
|
1513
2417
|
const columns = mirror.map(([column]) => quoteIdent(column));
|
|
@@ -1515,12 +2419,12 @@ function mirrorSet(table, mirror, body) {
|
|
|
1515
2419
|
return `,\n ${columns.length === 1 ? columns[0] ?? "" : `(${columns.join(", ")})`} = (select ${picked} from ${mirrorRow(table, mirror, body)} r)`;
|
|
1516
2420
|
}
|
|
1517
2421
|
/**
|
|
1518
|
-
* The approval store over a table the app already has (`rls.approvals:
|
|
1519
|
-
*
|
|
1520
|
-
*
|
|
1521
|
-
*
|
|
1522
|
-
*
|
|
1523
|
-
*
|
|
2422
|
+
* The approval store over a table the app already has (`rls.approvals: { table,
|
|
2423
|
+
* token?, body?, mirror? }`): the same `permdock_approval_*` functions, reading
|
|
2424
|
+
* every field from the request body in `body`, keyed by the text column
|
|
2425
|
+
* `token`, and copying the fields `mirror` names into the app's own columns,
|
|
2426
|
+
* converted to their types, on every write. The table's grants and policies
|
|
2427
|
+
* stay the app's.
|
|
1524
2428
|
*/
|
|
1525
2429
|
function adoptedApprovalStoreSql(ctx, adopt, jsonSchema = false) {
|
|
1526
2430
|
const table = quoteQualified(adopt.table);
|
|
@@ -1704,99 +2608,13 @@ ${serverOnly(fn(APPROVAL_STORE.cancel), "jsonb, text, text, text")}
|
|
|
1704
2608
|
`;
|
|
1705
2609
|
}
|
|
1706
2610
|
//#endregion
|
|
1707
|
-
//#region src/cli/rls/permission-holders.ts
|
|
1708
|
-
/** `permitted_<scope>_users(p_permission, p_id)`. Names are part of the SQL contract. */
|
|
1709
|
-
function permittedUsersHelper(scope) {
|
|
1710
|
-
return checkName(`permitted_${scope}_users`);
|
|
1711
|
-
}
|
|
1712
|
-
/** The users with a membership row on the instance `p_id`, or `undefined` when the scope's memberships are not all in tables. */
|
|
1713
|
-
function candidatesSql(ctx, scope, user) {
|
|
1714
|
-
const mapped = scopeTable(ctx, scope);
|
|
1715
|
-
if (mapped !== void 0) return {
|
|
1716
|
-
sql: ` select m.${quoteIdent(mapped.table.user)}::${user}
|
|
1717
|
-
from ${quoteQualified(mapped.table.table)} m
|
|
1718
|
-
where m.${quoteIdent(mapped.column)} = p_id`,
|
|
1719
|
-
keys: []
|
|
1720
|
-
};
|
|
1721
|
-
const sources = holderSources(ctx, scope);
|
|
1722
|
-
if (sources === void 0 || sources === "not-tables") return;
|
|
1723
|
-
return {
|
|
1724
|
-
sql: sources.map((source, index) => ` select h.user_id::${user}
|
|
1725
|
-
from (
|
|
1726
|
-
${source.holders.rows(scope, { id: `v_key_${String(index)}` }).replaceAll(/^/gmu, " ")}
|
|
1727
|
-
) h`).join("\n union\n"),
|
|
1728
|
-
keys: sources.map((source, index) => `v_key_${String(index)} ${source.holders.idType}`)
|
|
1729
|
-
};
|
|
1730
|
-
}
|
|
1731
|
-
/** `language sql`, or PL/pgSQL when a source's id column needs `p_id` in a `%type` variable. */
|
|
1732
|
-
function functionBody(keys, query) {
|
|
1733
|
-
if (keys.length === 0) return `language sql
|
|
1734
|
-
stable
|
|
1735
|
-
security definer
|
|
1736
|
-
set search_path = ''
|
|
1737
|
-
as $$
|
|
1738
|
-
${query}
|
|
1739
|
-
$$;`;
|
|
1740
|
-
return `language plpgsql
|
|
1741
|
-
stable
|
|
1742
|
-
security definer
|
|
1743
|
-
set search_path = ''
|
|
1744
|
-
as $$
|
|
1745
|
-
declare
|
|
1746
|
-
${keys.map((key) => ` ${key} := p_id;`).join("\n")}
|
|
1747
|
-
begin
|
|
1748
|
-
return query
|
|
1749
|
-
${query.replaceAll(/^/gmu, " ")};
|
|
1750
|
-
end
|
|
1751
|
-
$$;`;
|
|
1752
|
-
}
|
|
1753
|
-
/**
|
|
1754
|
-
* One `permitted_<scope>_users(p_permission, p_id)` per scope in `database`
|
|
1755
|
-
* mode: the users who hold a permission key on one instance, read from the
|
|
1756
|
-
* scope's membership rows and the global-roles table and kept when
|
|
1757
|
-
* `permitted_<scope>_ids_by_permission_for` lists the instance or
|
|
1758
|
-
* `permdock_has_permission_for` answers, so denies, custom roles, expiry and
|
|
1759
|
-
* suspension apply as for the user. It names other users, so no client role
|
|
1760
|
-
* may execute it, and a backend role needs its own grant.
|
|
1761
|
-
*/
|
|
1762
|
-
function permissionHoldersSql(ctx) {
|
|
1763
|
-
if (ctx.authorize !== "database") return "";
|
|
1764
|
-
const user = ctx.dialect === "supabase" ? "uuid" : "text";
|
|
1765
|
-
const global = globalRoleRows(ctx);
|
|
1766
|
-
const hasFor = qualified(ctx, PERMISSION_HELPERS.hasFor);
|
|
1767
|
-
return `${ctx.scopes.map(({ name }) => {
|
|
1768
|
-
const candidates = hasPermittedUsers(ctx, name) ? candidatesSql(ctx, name, user) : void 0;
|
|
1769
|
-
if (candidates === void 0) return `-- ${name}: no memberships table or table source, so permitted_${name}_users is not written`;
|
|
1770
|
-
const fn = qualified(ctx, permittedUsersHelper(name));
|
|
1771
|
-
const ids = qualified(ctx, checkName(`${permittedByPermissionHelper(name)}_for`));
|
|
1772
|
-
const type = scopeTypeOf(ctx, name);
|
|
1773
|
-
return `-- the users who hold a permission on one ${name}: its members and the global-role holders for whom the _for helpers answer; no client role may execute it
|
|
1774
|
-
create or replace function ${fn}(p_permission text, p_id ${type})
|
|
1775
|
-
returns setof ${user}
|
|
1776
|
-
${functionBody(candidates.keys, ` select c.user_id
|
|
1777
|
-
from (
|
|
1778
|
-
${candidates.sql}
|
|
1779
|
-
union
|
|
1780
|
-
select ${global.userSql}::${user}
|
|
1781
|
-
from ${global.from}
|
|
1782
|
-
) c(user_id)
|
|
1783
|
-
where c.user_id is not null
|
|
1784
|
-
and (
|
|
1785
|
-
p_id in (select ${ids}(c.user_id, p_permission))
|
|
1786
|
-
or ${hasFor}(c.user_id, p_permission)
|
|
1787
|
-
)
|
|
1788
|
-
order by 1`)}
|
|
1789
|
-
revoke execute on function ${fn}(text, ${type}) from public, anon, authenticated;`;
|
|
1790
|
-
}).join("\n\n")}\n`;
|
|
1791
|
-
}
|
|
1792
|
-
//#endregion
|
|
1793
2611
|
//#region src/cli/supabase-hook/sql.ts
|
|
1794
2612
|
const MANAGED_TRIGGER = "permdock_protect_managed";
|
|
1795
2613
|
function hookSql(parts) {
|
|
1796
2614
|
const schema = quoteIdent(parts.schema);
|
|
1797
2615
|
const fn = `${schema}.custom_access_token_hook`;
|
|
1798
2616
|
const rows = parts.roles;
|
|
1799
|
-
const roles = rows === void 0 ? ` held := '[]'::jsonb;` : ` select coalesce(jsonb_agg(distinct ${rows.roleSql} order by ${rows.roleSql}), '[]'::jsonb)
|
|
2617
|
+
const roles = rows === void 0 ? ` held := '[]'::jsonb;` : ` select coalesce(jsonb_agg(distinct ${rows.roleSql} order by ${rows.roleSql}) filter (where ${rows.roleSql} is not null), '[]'::jsonb)
|
|
1800
2618
|
into held
|
|
1801
2619
|
from ${rows.from}
|
|
1802
2620
|
where ${rows.userSql} = v_roles_user;`;
|
|
@@ -1828,11 +2646,29 @@ function hookSql(parts) {
|
|
|
1828
2646
|
if extra is not null then
|
|
1829
2647
|
claims := jsonb_set(claims, ${quoteLiteral(`{${entry.claim}}`)}, extra);
|
|
1830
2648
|
end if;`).join("");
|
|
2649
|
+
const dropTeams = parts.hook.teams === void 0 ? "" : " - 'team_ids'";
|
|
1831
2650
|
const suspended = parts.users === void 0 ? "" : `
|
|
1832
2651
|
if not ${activeRowSql(parts.users, "uid")} then
|
|
1833
|
-
claims := claims - 'memberships_truncated' - 'attrs' - ${quoteLiteral(parts.tenantClaim)}${dropExtra};
|
|
2652
|
+
claims := claims - 'memberships_truncated' - 'attrs'${dropTeams} - ${quoteLiteral(parts.tenantClaim)}${dropExtra};
|
|
1834
2653
|
claims := claims || jsonb_build_object('user_role', '[]'::jsonb, 'roles', '[]'::jsonb, 'memberships', '[]'::jsonb);${version}
|
|
1835
2654
|
return jsonb_set(event, '{claims}', claims);
|
|
2655
|
+
end if;`;
|
|
2656
|
+
const teamsConfig = parts.hook.teams;
|
|
2657
|
+
const teams = teamsConfig === void 0 ? "" : `
|
|
2658
|
+
for team in
|
|
2659
|
+
select t.${quoteIdent(teamsConfig.team)}::text as id
|
|
2660
|
+
from ${quoteQualified(teamsConfig.table)} t
|
|
2661
|
+
where t.${quoteIdent(teamsConfig.user)} = uid
|
|
2662
|
+
order by ${teamsConfig.tenant === void 0 ? "" : `(t.${quoteIdent(teamsConfig.tenant)}::text is not distinct from active) desc, `}t.${quoteIdent(teamsConfig.team)}
|
|
2663
|
+
loop
|
|
2664
|
+
if octet_length(kept::text) + used + octet_length((team_ids || to_jsonb(team.id))::text) > budget then
|
|
2665
|
+
truncated := true;
|
|
2666
|
+
exit;
|
|
2667
|
+
end if;
|
|
2668
|
+
team_ids := team_ids || jsonb_build_array(team.id);
|
|
2669
|
+
end loop;
|
|
2670
|
+
if team_ids <> '[]'::jsonb then
|
|
2671
|
+
claims := jsonb_set(claims, '{team_ids}', team_ids);
|
|
1836
2672
|
end if;`;
|
|
1837
2673
|
return `${parts.schema === "public" ? "" : `create schema if not exists ${schema};\nrevoke all on schema ${schema} from public;\n\n`}create or replace function ${fn}(event jsonb)
|
|
1838
2674
|
returns jsonb
|
|
@@ -1850,9 +2686,9 @@ declare
|
|
|
1850
2686
|
in_active boolean := false;
|
|
1851
2687
|
budget integer := ${String(parts.budget)};
|
|
1852
2688
|
used integer := 0;
|
|
1853
|
-
item record;${typedUsers(parts)}${plan === void 0 ? "" : "\n attrs jsonb;"}${parts.extra.length === 0 ? "" : "\n extra jsonb;"}${parts.version ? "\n ver bigint;" : ""}${parts.before.length === 0 ? "" : "\n checked jsonb;"}
|
|
2689
|
+
item record;${teamsConfig === void 0 ? "" : "\n team record;\n team_ids jsonb := '[]'::jsonb;"}${typedUsers(parts)}${plan === void 0 ? "" : "\n attrs jsonb;"}${parts.extra.length === 0 ? "" : "\n extra jsonb;"}${parts.version ? "\n ver bigint;" : ""}${parts.before.length === 0 ? "" : "\n checked jsonb;"}
|
|
1854
2690
|
begin${beforeSql(parts.before)}${suspended}
|
|
1855
|
-
claims := claims - 'attrs'${dropExtra};
|
|
2691
|
+
claims := claims - 'attrs'${dropTeams}${dropExtra};
|
|
1856
2692
|
${roles}
|
|
1857
2693
|
claims := jsonb_set(claims, '{roles}', held);
|
|
1858
2694
|
if jsonb_array_length(held) = 1 then
|
|
@@ -1875,7 +2711,7 @@ ${entriesSql(parts).replaceAll(/^/gmu, " ")}
|
|
|
1875
2711
|
kept := kept || jsonb_build_array(item.entry);
|
|
1876
2712
|
in_active := in_active or (active is not null and item.current);
|
|
1877
2713
|
end loop;
|
|
1878
|
-
claims := jsonb_set(claims, '{memberships}', kept)
|
|
2714
|
+
claims := jsonb_set(claims, '{memberships}', kept);${teams}
|
|
1879
2715
|
if truncated then
|
|
1880
2716
|
claims := jsonb_set(claims, '{memberships_truncated}', 'true'::jsonb);
|
|
1881
2717
|
else
|
|
@@ -1902,11 +2738,11 @@ revoke execute on function ${fn}(jsonb) from authenticated, anon, public;${extra
|
|
|
1902
2738
|
].filter((chunk) => chunk !== "").join("\n");
|
|
1903
2739
|
}
|
|
1904
2740
|
function extraGrantsSql(extra) {
|
|
1905
|
-
return [...[...new Set(extra.map((entry) => entry.fn.split(".")[0]))].map((name) => `\ngrant usage on schema ${quoteIdent(name ?? "")} to supabase_auth_admin;`), ...extra.map((entry) => `\ngrant execute on function ${quoteTable(entry.fn)}(uuid) to supabase_auth_admin;`)].join("");
|
|
2741
|
+
return [...[...new Set(extra.map((entry) => entry.fn.split(".")[0]))].map((name) => `\ngrant usage on schema ${quoteIdent(name ?? "")} to supabase_auth_admin;`), ...extra.map((entry) => `\nrevoke all on function ${quoteTable(entry.fn)}(uuid) from public, anon, authenticated;\ngrant execute on function ${quoteTable(entry.fn)}(uuid) to supabase_auth_admin;`)].join("");
|
|
1906
2742
|
}
|
|
1907
2743
|
function beforeGrantsSql(before, extra) {
|
|
1908
2744
|
const granted = new Set(extra.map((entry) => entry.fn.split(".")[0]));
|
|
1909
|
-
return [...[...new Set(before.map((fn) => beforeFirst(fn, ".")))].filter((name) => !granted.has(name)).map((name) => `\ngrant usage on schema ${quoteIdent(name)} to supabase_auth_admin;`), ...before.map((fn) => `\ngrant execute on function ${quoteTable(fn)}(jsonb) to supabase_auth_admin;`)].join("");
|
|
2745
|
+
return [...[...new Set(before.map((fn) => beforeFirst(fn, ".")))].filter((name) => !granted.has(name)).map((name) => `\ngrant usage on schema ${quoteIdent(name)} to supabase_auth_admin;`), ...before.map((fn) => `\nrevoke all on function ${quoteTable(fn)}(jsonb) from public, anon, authenticated;\ngrant execute on function ${quoteTable(fn)}(jsonb) to supabase_auth_admin;`)].join("");
|
|
1910
2746
|
}
|
|
1911
2747
|
/**
|
|
1912
2748
|
* Execute on each `member_<scope>_ids_for(uuid)` for the `hook.claims`
|
|
@@ -1933,6 +2769,7 @@ function readsSql(parts) {
|
|
|
1933
2769
|
reads.set(rolesTable, reads.get(rolesTable) ?? "roles");
|
|
1934
2770
|
if (through !== void 0) reads.set(through.table, reads.get(through.table) ?? "role_keys");
|
|
1935
2771
|
}
|
|
2772
|
+
if (parts.hook.teams !== void 0) reads.set(parts.hook.teams.table, reads.get(parts.hook.teams.table) ?? "teams");
|
|
1936
2773
|
if (parts.attrs?.table !== void 0 && parts.attrs.columns.length > 0) reads.set(parts.attrs.table, reads.get(parts.attrs.table) ?? "attrs");
|
|
1937
2774
|
if (parts.users !== void 0) reads.set(parts.users.table, reads.get(parts.users.table) ?? "status_users");
|
|
1938
2775
|
return [...[...new Set([...reads.keys()].map((name) => name.includes(".") ? name.split(".")[0] : "public").filter((schema) => schema !== void 0 && schema !== parts.schema && schema !== "auth"))].map((schema) => `grant usage on schema ${quoteIdent(schema)} to supabase_auth_admin;`), ...[...reads].map(([name, label]) => authAdminRead(name, label))].join("\n");
|
|
@@ -2010,7 +2847,7 @@ function hookParts(scopes, config, overrides) {
|
|
|
2010
2847
|
...memberForPlan({
|
|
2011
2848
|
scopes,
|
|
2012
2849
|
...config.rls?.memberships === void 0 ? {} : { memberships: config.rls.memberships },
|
|
2013
|
-
memberSources: config
|
|
2850
|
+
memberSources: membershipSourcesOf(config)
|
|
2014
2851
|
})
|
|
2015
2852
|
}
|
|
2016
2853
|
};
|
|
@@ -2079,10 +2916,10 @@ function signedUp(user) {
|
|
|
2079
2916
|
return `exists (select 1 from auth.users a where a.id = ${user})`;
|
|
2080
2917
|
}
|
|
2081
2918
|
/**
|
|
2082
|
-
* Every membership source whose user id lives in another table: a row of
|
|
2083
|
-
*
|
|
2084
|
-
*
|
|
2085
|
-
*
|
|
2919
|
+
* Every membership source whose user id lives in another table: a row of the
|
|
2920
|
+
* source bumps the users its old and new references hold, and a change of that
|
|
2921
|
+
* table's user id (a contact re-linked to another login) bumps the old and the
|
|
2922
|
+
* new user.
|
|
2086
2923
|
*/
|
|
2087
2924
|
function memberUsersVersionSql(parts, bumpFor) {
|
|
2088
2925
|
const holders = /* @__PURE__ */ new Map();
|
|
@@ -2194,7 +3031,10 @@ $$;
|
|
|
2194
3031
|
revoke execute on function ${linkedBump}() from public, anon, authenticated;
|
|
2195
3032
|
${userTriggers}`;
|
|
2196
3033
|
}
|
|
2197
|
-
/**
|
|
3034
|
+
/**
|
|
3035
|
+
* Every table whose role column references a roles table: the global roles and
|
|
3036
|
+
* the membership sources.
|
|
3037
|
+
*/
|
|
2198
3038
|
function roleKeyHolders(parts) {
|
|
2199
3039
|
const holders = [];
|
|
2200
3040
|
if (parts.roles?.through !== void 0) holders.push({
|
|
@@ -2228,7 +3068,10 @@ function roleKeyHolders(parts) {
|
|
|
2228
3068
|
return true;
|
|
2229
3069
|
});
|
|
2230
3070
|
}
|
|
2231
|
-
/**
|
|
3071
|
+
/**
|
|
3072
|
+
* The bump for one roles table: unchanged keys and ids return early, else every
|
|
3073
|
+
* holder of `old` is bumped.
|
|
3074
|
+
*/
|
|
2232
3075
|
function roleKeysBumpSql(holders, versionTable, indent) {
|
|
2233
3076
|
return `${indent}if tg_op = 'UPDATE'
|
|
2234
3077
|
${indent} and ${[...new Set(holders.flatMap((holder) => [holder.through.key, holder.through.id]))].map((column) => `new.${quoteIdent(column)} is not distinct from old.${quoteIdent(column)}`).join(`\n${indent} and `)} then
|
|
@@ -2244,9 +3087,9 @@ ${indent} and exists (select 1 from auth.users au where au.id = h.user_id)
|
|
|
2244
3087
|
${indent}on conflict (user_id) do update set version = v.version + 1;`;
|
|
2245
3088
|
}
|
|
2246
3089
|
/**
|
|
2247
|
-
* A renamed role key changes the `roles` claim of everyone who holds it and
|
|
2248
|
-
*
|
|
2249
|
-
*
|
|
3090
|
+
* A renamed role key changes the `roles` claim of everyone who holds it and the
|
|
3091
|
+
* `roles` of every membership that references it, so updates to a roles table
|
|
3092
|
+
* bump each holder.
|
|
2250
3093
|
*/
|
|
2251
3094
|
function roleKeysVersionSql(parts, versionTable) {
|
|
2252
3095
|
const holders = roleKeyHolders(parts);
|
|
@@ -2301,7 +3144,8 @@ function helperList(parts, types) {
|
|
|
2301
3144
|
return [
|
|
2302
3145
|
helperEntry(permittedIdsHelper(scope.name), "p_grant text", returns, client),
|
|
2303
3146
|
helperEntry(memberIdsHelper(scope.name), "", returns, client),
|
|
2304
|
-
...parts.helpers.memberFor.includes(scope.name) ? [helperEntry(memberForHelper(scope.name), "p_user uuid", returns, parts.extra.length === 0 ? [] : ["supabase_auth_admin"])] : []
|
|
3147
|
+
...parts.helpers.memberFor.includes(scope.name) ? [helperEntry(memberForHelper(scope.name), "p_user uuid", returns, parts.extra.length === 0 ? [] : ["supabase_auth_admin"])] : [],
|
|
3148
|
+
...parts.helpers.memberFor.includes(scope.name) && isTeamScope(scope.name) ? [helperEntry(memberOfHelper(scope.name), "p_user uuid", returns, client)] : []
|
|
2305
3149
|
];
|
|
2306
3150
|
})];
|
|
2307
3151
|
}
|
|
@@ -2314,8 +3158,8 @@ function helperEntry(name, args, returns, execute) {
|
|
|
2314
3158
|
};
|
|
2315
3159
|
}
|
|
2316
3160
|
/**
|
|
2317
|
-
* The helpers `rls generate` writes beyond the ones the hook's claims feed:
|
|
2318
|
-
*
|
|
3161
|
+
* The helpers `rls generate` writes beyond the ones the hook's claims feed: the
|
|
3162
|
+
* `_for` forms in `database` mode, and the assignment checks when a role
|
|
2319
3163
|
* declares `assigns` (known only with the policy).
|
|
2320
3164
|
*/
|
|
2321
3165
|
function trustedHelpers(parts, config, types, tenantType, policy) {
|
|
@@ -2333,8 +3177,9 @@ function trustedHelpers(parts, config, types, tenantType, policy) {
|
|
|
2333
3177
|
const keyed = [
|
|
2334
3178
|
helperEntry(USER_ID_HELPER, "", "uuid", client),
|
|
2335
3179
|
...config.rls?.apiKeys === void 0 ? [] : [helperEntry(API_KEY_ALLOWS, "p_grant text", "boolean", client)],
|
|
3180
|
+
...config.rls?.tokenScopes === true ? [helperEntry(TOKEN_SCOPE_ALLOWS, "p_grant text", "boolean", client)] : [],
|
|
2336
3181
|
...readOnlyActorKinds(config.rls?.readOnlyActors) === void 0 ? [] : [helperEntry(ACTOR_MAY_WRITE, "", "boolean", client)],
|
|
2337
|
-
|
|
3182
|
+
...config.rls?.approvals === true || typeof config.rls?.approvals === "object" ? [helperEntry(IS_APPROVER, typeof config.rls.approvals === "object" && config.rls.approvals.delegations === true ? "p_approvers jsonb, p_tenant text, p_requester text, p_resource text" : "p_approvers jsonb, p_tenant text", "boolean", client)] : [],
|
|
2338
3183
|
...forUser
|
|
2339
3184
|
];
|
|
2340
3185
|
if (!(policy !== void 0 && (ownershipRules(policy, parts.scopes)?.assigns.length ?? 0) > 0)) return keyed;
|
|
@@ -2361,7 +3206,10 @@ function activeRowManifest(row) {
|
|
|
2361
3206
|
...keep.length === 0 ? {} : { keep }
|
|
2362
3207
|
};
|
|
2363
3208
|
}
|
|
2364
|
-
/**
|
|
3209
|
+
/**
|
|
3210
|
+
* The `rls` settings a package writing SQL next to the helpers reads: custom
|
|
3211
|
+
* roles, global roles, suspension and assignment triggers.
|
|
3212
|
+
*/
|
|
2365
3213
|
function rlsSettings(parts, config) {
|
|
2366
3214
|
const rls = config.rls;
|
|
2367
3215
|
const suspension = checkSuspension(rls?.suspension, parts.scopes);
|
|
@@ -2380,7 +3228,8 @@ function rlsSettings(parts, config) {
|
|
|
2380
3228
|
...suspension.memberships === void 0 ? {} : { memberships: { keep: keptKeys(suspension.memberships) } }
|
|
2381
3229
|
} },
|
|
2382
3230
|
...assigned === void 0 ? {} : { assignments: { tables: assigned } },
|
|
2383
|
-
...rls?.apiKeys === void 0 ? {} : { apiKeys: apiKeyFields(rls.apiKeys) }
|
|
3231
|
+
...rls?.apiKeys === void 0 ? {} : { apiKeys: apiKeyFields(rls.apiKeys) },
|
|
3232
|
+
...rls?.tokenScopes === true ? { tokenScopes: true } : {}
|
|
2384
3233
|
};
|
|
2385
3234
|
}
|
|
2386
3235
|
/** The `supabase/sdk` release `requires.capabilities` names features of. */
|
|
@@ -2416,8 +3265,7 @@ function manifestOf(parts, out, config, policy) {
|
|
|
2416
3265
|
scopes: parts.scopes,
|
|
2417
3266
|
tenantClaim: parts.tenantClaim,
|
|
2418
3267
|
gucPrefix: rls?.gucPrefix ?? "app",
|
|
2419
|
-
tenantType: rls?.
|
|
2420
|
-
...rls?.teamType === void 0 ? {} : { teamType: rls.teamType },
|
|
3268
|
+
tenantType: firstScopeType(rls?.scopeTypes, parts.scopes),
|
|
2421
3269
|
...rls?.scopeTypes === void 0 ? {} : { scopeTypes: rls.scopeTypes }
|
|
2422
3270
|
};
|
|
2423
3271
|
const types = new Map(parts.scopes.map((scope) => [scope.name, scopeTypeOf(ctx, scope.name)]));
|
|
@@ -2464,15 +3312,30 @@ function manifestOf(parts, out, config, policy) {
|
|
|
2464
3312
|
decidingColumns: decidingColumns(config, parts.attrs === void 0 ? void 0 : {
|
|
2465
3313
|
...parts.attrs.table === void 0 ? {} : { table: parts.attrs.table },
|
|
2466
3314
|
columns: parts.attrs.columns
|
|
2467
|
-
}),
|
|
3315
|
+
}, parts.hook.teams),
|
|
2468
3316
|
markers: {
|
|
2469
3317
|
hook: "v1",
|
|
2470
3318
|
grants: "v1"
|
|
2471
3319
|
},
|
|
2472
|
-
requires: requiredCapabilities(config, policy)
|
|
3320
|
+
requires: requiredCapabilities(config, policy),
|
|
3321
|
+
...policy === void 0 ? {} : { names: resolveNames(policy, config, {
|
|
3322
|
+
schema: parts.helpers.schema,
|
|
3323
|
+
tenantClaim: parts.tenantClaim
|
|
3324
|
+
}) }
|
|
2473
3325
|
};
|
|
2474
3326
|
}
|
|
2475
|
-
/**
|
|
3327
|
+
/**
|
|
3328
|
+
* The manifest without the token hook: what a project with no `supabase.hook`
|
|
3329
|
+
* records.
|
|
3330
|
+
*/
|
|
3331
|
+
function databaseManifestOf(parts, out, config, policy) {
|
|
3332
|
+
const { hook: _hook, budget: _budget, claims: _claims, authzVersion: _authzVersion, authzVersionBump: _authzVersionBump, memberships: _memberships, ...rest } = manifestOf(parts, out, config, policy);
|
|
3333
|
+
return rest;
|
|
3334
|
+
}
|
|
3335
|
+
/**
|
|
3336
|
+
* The first line of the generated hook: fields `--check` compares before the
|
|
3337
|
+
* full text.
|
|
3338
|
+
*/
|
|
2476
3339
|
function hookMarker(manifest) {
|
|
2477
3340
|
return `${HOOK_MARKER} schema=${manifest.hook.schema} tenant=${manifest.tenantClaim} budget=${String(manifest.budget.bytes)} claims=${manifest.claims.map((claim) => claim.name).join(",")}`;
|
|
2478
3341
|
}
|
|
@@ -2498,7 +3361,10 @@ budget, the claims the hook writes, the membership sources and the columns that
|
|
|
2498
3361
|
--out writes it as JSON, to permdock.manifest.json without a path; --check exits 1 when that
|
|
2499
3362
|
file differs.
|
|
2500
3363
|
`;
|
|
2501
|
-
/**
|
|
3364
|
+
/**
|
|
3365
|
+
* `supabase.hook.out`, else pg-delta's per-schema path under pg-delta, else
|
|
3366
|
+
* `supabase/permdock-hook.sql`.
|
|
3367
|
+
*/
|
|
2502
3368
|
function hookOut(cwd, config, schema, flag) {
|
|
2503
3369
|
const schemas = resolveSchemas(cwd, config, flag);
|
|
2504
3370
|
return config.supabase?.hook?.out !== void 0 || schemas.mode !== "pg-delta" ? defaultOut(config) : pgDeltaPath(schemas.schemaDir, "hook", schema ?? config.supabase?.hook?.schema ?? config.rls?.schema ?? "permdock");
|
|
@@ -2519,8 +3385,26 @@ function supabaseHookManifest(scopes, config, overrides = {}, policy) {
|
|
|
2519
3385
|
};
|
|
2520
3386
|
}
|
|
2521
3387
|
/**
|
|
2522
|
-
* The
|
|
2523
|
-
*
|
|
3388
|
+
* The manifest of a project in `rls.authorize: 'database'` mode with no
|
|
3389
|
+
* `supabase.hook`: the helpers, scopes, membership sources and grants, and no
|
|
3390
|
+
* token hook.
|
|
3391
|
+
*/
|
|
3392
|
+
function supabaseDatabaseManifest(scopes, config, overrides = {}, policy) {
|
|
3393
|
+
return databaseManifestOf(hookParts(scopes, {
|
|
3394
|
+
...config,
|
|
3395
|
+
supabase: {
|
|
3396
|
+
...config.supabase,
|
|
3397
|
+
hook: { memberships: membershipSourcesOf(config) }
|
|
3398
|
+
}
|
|
3399
|
+
}, overrides), overrides.out ?? defaultOut(config), config, policy);
|
|
3400
|
+
}
|
|
3401
|
+
/** Whether the project is in the one case that has a manifest without a hook. */
|
|
3402
|
+
function hooklessDatabase(config) {
|
|
3403
|
+
return config.supabase?.hook === void 0 && resolveAuthorize(config) === "database";
|
|
3404
|
+
}
|
|
3405
|
+
/**
|
|
3406
|
+
* The hook migration. With `grantsOut`, the statements `supabase db diff` drops
|
|
3407
|
+
* are left out of `sql` and returned in `grants` for that file.
|
|
2524
3408
|
*/
|
|
2525
3409
|
function supabaseHookSql(scopes, config, overrides = {}, grantsOut) {
|
|
2526
3410
|
const parts = hookParts(scopes, config, overrides);
|
|
@@ -2564,14 +3448,33 @@ function markerDrift(onDisk, expected, outRel) {
|
|
|
2564
3448
|
const changed = Object.keys(want).filter((key) => found[key] !== want[key]).map((key) => `${key} ${found[key] ?? "(none)"} -> ${want[key] ?? ""}`);
|
|
2565
3449
|
return changed.length === 0 ? "supabase hook drift" : `supabase hook drift: ${changed.join("; ")}`;
|
|
2566
3450
|
}
|
|
2567
|
-
|
|
3451
|
+
/** Supabase's default access token lifetime when `[auth] jwt_expiry` is unset. */
|
|
3452
|
+
const DEFAULT_JWT_EXPIRY = 3600;
|
|
3453
|
+
function managementApi(cwd, manifest) {
|
|
3454
|
+
return {
|
|
3455
|
+
hook_custom_access_token_enabled: true,
|
|
3456
|
+
hook_custom_access_token_uri: hookUri(manifest.hook.schema),
|
|
3457
|
+
jwt_exp: supabaseConfig(cwd).jwtExpiry ?? DEFAULT_JWT_EXPIRY
|
|
3458
|
+
};
|
|
3459
|
+
}
|
|
3460
|
+
function inspectText(manifest, api) {
|
|
2568
3461
|
return [
|
|
2569
3462
|
`hook ${manifest.hook.schema}.${manifest.hook.function} (${manifest.hook.out})`,
|
|
2570
3463
|
`helpers ${manifest.helpers.functions.map((fn) => `${manifest.helpers.schema}.${fn}`).join(", ")}`,
|
|
2571
3464
|
`tenant claim ${manifest.tenantClaim}`,
|
|
2572
3465
|
`budget ${String(manifest.budget.bytes)} bytes of ${manifest.budget.measure}`,
|
|
2573
3466
|
`claims ${manifest.claims.map((claim) => `${claim.name}${claim.source === "permdock" ? "" : ` (${claim.source})`}${claim.budget ? " [budget]" : ""}`).join(", ")}`,
|
|
2574
|
-
`authz_ver ${manifest.authzVersion ? "on" : "off"}
|
|
3467
|
+
`authz_ver ${manifest.authzVersion ? "on" : "off"}`,
|
|
3468
|
+
`hook_custom_access_token_enabled ${String(api.hook_custom_access_token_enabled)}`,
|
|
3469
|
+
`hook_custom_access_token_uri ${api.hook_custom_access_token_uri}`,
|
|
3470
|
+
`jwt_exp ${String(api.jwt_exp)}`
|
|
3471
|
+
].join("\n");
|
|
3472
|
+
}
|
|
3473
|
+
function databaseInspectText(manifest) {
|
|
3474
|
+
return [
|
|
3475
|
+
"no token hook (rls.authorize: database, no supabase.hook)",
|
|
3476
|
+
`helpers ${manifest.helpers.functions.map((fn) => `${manifest.helpers.schema}.${fn}`).join(", ")}`,
|
|
3477
|
+
`tenant claim ${manifest.tenantClaim}`
|
|
2575
3478
|
].join("\n");
|
|
2576
3479
|
}
|
|
2577
3480
|
/**
|
|
@@ -2632,15 +3535,30 @@ async function runSupabase(input) {
|
|
|
2632
3535
|
}).filter(([, value]) => value !== void 0));
|
|
2633
3536
|
if (area === "inspect" && action === void 0) {
|
|
2634
3537
|
const policy = await loadHookPolicy(input.cwd, input.config);
|
|
3538
|
+
if (hooklessDatabase(input.config)) {
|
|
3539
|
+
const bare = supabaseDatabaseManifest(scopeList(policy.scopes), input.config, overrides, policy);
|
|
3540
|
+
if (input.out !== void 0 || input.check) return manifestFile(input.cwd, typeof input.out === "string" ? input.out : MANIFEST_FILE, bare, input.check);
|
|
3541
|
+
return {
|
|
3542
|
+
code: 0,
|
|
3543
|
+
output: input.json === true ? JSON.stringify(bare, null, 2) : databaseInspectText(bare)
|
|
3544
|
+
};
|
|
3545
|
+
}
|
|
2635
3546
|
const manifest = supabaseHookManifest(scopeList(policy.scopes), input.config, {
|
|
2636
3547
|
...overrides,
|
|
2637
3548
|
out: hookOut(input.cwd, input.config, input.schema, flag),
|
|
2638
3549
|
schemas: schemas.mode
|
|
2639
3550
|
}, policy);
|
|
2640
|
-
|
|
3551
|
+
const api = managementApi(input.cwd, manifest);
|
|
3552
|
+
if (input.out !== void 0 || input.check) return manifestFile(input.cwd, typeof input.out === "string" ? input.out : MANIFEST_FILE, {
|
|
3553
|
+
...manifest,
|
|
3554
|
+
managementApi: api
|
|
3555
|
+
}, input.check);
|
|
2641
3556
|
return {
|
|
2642
3557
|
code: 0,
|
|
2643
|
-
output: input.json === true ? JSON.stringify(
|
|
3558
|
+
output: input.json === true ? JSON.stringify({
|
|
3559
|
+
...manifest,
|
|
3560
|
+
managementApi: managementApi(input.cwd, manifest)
|
|
3561
|
+
}, null, 2) : inspectText(manifest, api)
|
|
2644
3562
|
};
|
|
2645
3563
|
}
|
|
2646
3564
|
if (area !== "hook" || action !== "generate") return {
|
|
@@ -2651,7 +3569,9 @@ async function runSupabase(input) {
|
|
|
2651
3569
|
code: 2,
|
|
2652
3570
|
output: `supabase hook generate --grants-out is for --schemas migra: ${schemas.mode === "pg-delta" ? "pg-delta keeps the grants in the hook file" : "a hand-written migration keeps its grants"}, so drop --grants-out`
|
|
2653
3571
|
};
|
|
2654
|
-
const
|
|
3572
|
+
const generated = supabaseHookSql(await loadScopes(input.cwd, input.config), input.config, overrides, grantsLabel(input.grantsOut));
|
|
3573
|
+
const { grants, manifest } = generated;
|
|
3574
|
+
const sql = schemas.mode === "pg-delta" && typeof input.out !== "string" && input.config.supabase?.hook?.out === void 0 ? declarativeSql(generated.sql) : generated.sql;
|
|
2655
3575
|
const outRel = typeof input.out === "string" ? input.out : hookOut(input.cwd, input.config, input.schema, flag);
|
|
2656
3576
|
const outPath = resolve(input.cwd, outRel);
|
|
2657
3577
|
const hook = input.config.supabase?.hook;
|
|
@@ -2702,4 +3622,4 @@ async function runSupabase(input) {
|
|
|
2702
3622
|
};
|
|
2703
3623
|
}
|
|
2704
3624
|
//#endregion
|
|
2705
|
-
export {
|
|
3625
|
+
export { supabaseConfig as _, supabaseHookManifest as a, resolveAuthorize as b, pd039 as c, schemasRefusal as d, declarativeSql as f, readSupabaseConfig as g, pd074 as h, runSupabase as i, isSupabaseSchemas as l, pd045 as m, hookOut as n, supabaseHookSql as o, attrsPlan as p, loadScopes as r, approvalsSql as s, grantsLabel as t, resolveSchemas as u, parseRbacAuthorize as v, rbacScaffold as y };
|