@transcend-io/cli 10.28.0 → 10.29.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 +81 -15
- package/dist/{app-DCY8E776.mjs → app-C5baDSA2.mjs} +21 -21
- package/dist/app-C5baDSA2.mjs.map +1 -0
- package/dist/{approvePrivacyRequests-80SV_94y.mjs → approvePrivacyRequests-B8x7oxTn.mjs} +2 -2
- package/dist/{approvePrivacyRequests-80SV_94y.mjs.map → approvePrivacyRequests-B8x7oxTn.mjs.map} +1 -1
- package/dist/bin/bash-complete.mjs +1 -1
- package/dist/bin/cli.mjs +1 -1
- package/dist/bin/deprecated-command.mjs +1 -1
- package/dist/{buildExamples-2YDkSvtA.mjs → buildExamples-7KXBjl-b.mjs} +2 -2
- package/dist/{buildExamples-2YDkSvtA.mjs.map → buildExamples-7KXBjl-b.mjs.map} +1 -1
- package/dist/{buildXdiSyncEndpoint-B3zUrI16.mjs → buildXdiSyncEndpoint-DcrkZ2Gu.mjs} +2 -2
- package/dist/{buildXdiSyncEndpoint-B3zUrI16.mjs.map → buildXdiSyncEndpoint-DcrkZ2Gu.mjs.map} +1 -1
- package/dist/{bulkRestartRequests-BLb8OJmf.mjs → bulkRestartRequests-CysUfl98.mjs} +2 -2
- package/dist/{bulkRestartRequests-BLb8OJmf.mjs.map → bulkRestartRequests-CysUfl98.mjs.map} +1 -1
- package/dist/{bulkRetryEnrichers-BA9cboSe.mjs → bulkRetryEnrichers-DaLE67Ht.mjs} +2 -2
- package/dist/{bulkRetryEnrichers-BA9cboSe.mjs.map → bulkRetryEnrichers-DaLE67Ht.mjs.map} +1 -1
- package/dist/{cancelPrivacyRequests-BEyOBJ2r.mjs → cancelPrivacyRequests-D0zNUNdS.mjs} +2 -2
- package/dist/{cancelPrivacyRequests-BEyOBJ2r.mjs.map → cancelPrivacyRequests-D0zNUNdS.mjs.map} +1 -1
- package/dist/codecs-CTxFjCg4.mjs +2 -0
- package/dist/codecs-CTxFjCg4.mjs.map +1 -0
- package/dist/{collectCsvFilesOrExit-BqnmK63h.mjs → collectCsvFilesOrExit-B1VOVGWN.mjs} +1 -1
- package/dist/{collectCsvFilesOrExit-BqnmK63h.mjs.map → collectCsvFilesOrExit-B1VOVGWN.mjs.map} +1 -1
- package/dist/{collectParquetFilesOrExit-BiksFI-Q.mjs → collectParquetFilesOrExit-DVlv5ctt.mjs} +1 -1
- package/dist/{collectParquetFilesOrExit-BiksFI-Q.mjs.map → collectParquetFilesOrExit-DVlv5ctt.mjs.map} +1 -1
- package/dist/{command-eIenZMOx.mjs → command-CIv9yk86.mjs} +2 -2
- package/dist/{command-eIenZMOx.mjs.map → command-CIv9yk86.mjs.map} +1 -1
- package/dist/commands/admin/chunk-csv/worker.mjs +1 -1
- package/dist/commands/admin/parquet-to-csv/worker.mjs +1 -1
- package/dist/{consentManagersToBusinessEntities-O4KBox9u.mjs → consentManagersToBusinessEntities-CBJ81aGO.mjs} +1 -1
- package/dist/{consentManagersToBusinessEntities-O4KBox9u.mjs.map → consentManagersToBusinessEntities-CBJ81aGO.mjs.map} +1 -1
- package/dist/{constants-BpQ5awGp.mjs → constants-DXzsg2CQ.mjs} +2 -2
- package/dist/{constants-BpQ5awGp.mjs.map → constants-DXzsg2CQ.mjs.map} +1 -1
- package/dist/{constants-C1seVfCu.mjs → constants-D_HVDaOy.mjs} +1 -1
- package/dist/{constants-C1seVfCu.mjs.map → constants-D_HVDaOy.mjs.map} +1 -1
- package/dist/{constants-BG53Mbi9.mjs → constants-jjHIzHGm.mjs} +2 -2
- package/dist/{constants-BG53Mbi9.mjs.map → constants-jjHIzHGm.mjs.map} +1 -1
- package/dist/{context-CZYrQfAn.mjs → context-B33NT3ki.mjs} +1 -1
- package/dist/{context-CZYrQfAn.mjs.map → context-B33NT3ki.mjs.map} +1 -1
- package/dist/{createPoolingCommandUi-C39R_zo3.mjs → createPoolingCommandUi-uiDjLlqf.mjs} +2 -2
- package/dist/{createPoolingCommandUi-C39R_zo3.mjs.map → createPoolingCommandUi-uiDjLlqf.mjs.map} +1 -1
- package/dist/{dataFlowsToDataSilos-CLSHb1GA.mjs → dataFlowsToDataSilos-BF6fzWcm.mjs} +1 -1
- package/dist/{dataFlowsToDataSilos-CLSHb1GA.mjs.map → dataFlowsToDataSilos-BF6fzWcm.mjs.map} +1 -1
- package/dist/deno-runtime-DV52X8-P.mjs +2 -0
- package/dist/deno-runtime-DV52X8-P.mjs.map +1 -0
- package/dist/{done-input-validation-Cjk7a3jX.mjs → done-input-validation-BUz-aVC5.mjs} +1 -1
- package/dist/{done-input-validation-Cjk7a3jX.mjs.map → done-input-validation-BUz-aVC5.mjs.map} +1 -1
- package/dist/{downloadPrivacyRequestFiles-CLFgQItk.mjs → downloadPrivacyRequestFiles-B_BVxW5Z.mjs} +2 -2
- package/dist/{downloadPrivacyRequestFiles-CLFgQItk.mjs.map → downloadPrivacyRequestFiles-B_BVxW5Z.mjs.map} +1 -1
- package/dist/{extractClientError-C_6ly7Gw.mjs → extractClientError-HZ2U7yqV.mjs} +1 -1
- package/dist/{extractClientError-C_6ly7Gw.mjs.map → extractClientError-HZ2U7yqV.mjs.map} +1 -1
- package/dist/{fetchAllRequests-CEDKdq0c.mjs → fetchAllRequests-2TZr-LfT.mjs} +2 -2
- package/dist/{fetchAllRequests-CEDKdq0c.mjs.map → fetchAllRequests-2TZr-LfT.mjs.map} +1 -1
- package/dist/{formatPolicyBundleVersionSummary-CrFtcPwS.mjs → formatPolicyBundleVersionSummary-CJmMCLtJ.mjs} +1 -1
- package/dist/{formatPolicyBundleVersionSummary-CrFtcPwS.mjs.map → formatPolicyBundleVersionSummary-CJmMCLtJ.mjs.map} +1 -1
- package/dist/{fuzzyMatchColumns-OTsFJ21f.mjs → fuzzyMatchColumns-CQCzpjWC.mjs} +2 -2
- package/dist/{fuzzyMatchColumns-OTsFJ21f.mjs.map → fuzzyMatchColumns-CQCzpjWC.mjs.map} +1 -1
- package/dist/{generateCrossAccountApiKeys-D6O_Qm3Y.mjs → generateCrossAccountApiKeys-Bnqgmj-H.mjs} +2 -2
- package/dist/{generateCrossAccountApiKeys-D6O_Qm3Y.mjs.map → generateCrossAccountApiKeys-Bnqgmj-H.mjs.map} +1 -1
- package/dist/impl--JGnR3wp.mjs +3 -0
- package/dist/{impl-CzxvoiGW.mjs.map → impl--JGnR3wp.mjs.map} +1 -1
- package/dist/{impl-BqrSLoig.mjs → impl-2iVTxNn4.mjs} +2 -2
- package/dist/{impl-BqrSLoig.mjs.map → impl-2iVTxNn4.mjs.map} +1 -1
- package/dist/{impl-Drql0g72.mjs → impl-7UqkSO3x2.mjs} +2 -2
- package/dist/impl-7UqkSO3x2.mjs.map +1 -0
- package/dist/{impl-C50tdWlL2.mjs → impl-B-j5ACi02.mjs} +2 -2
- package/dist/{impl-C50tdWlL2.mjs.map → impl-B-j5ACi02.mjs.map} +1 -1
- package/dist/impl-B4BgGuF_.mjs +3 -0
- package/dist/impl-B4BgGuF_.mjs.map +1 -0
- package/dist/{impl-zZFaSmxd2.mjs → impl-BDrvzlpf2.mjs} +2 -2
- package/dist/{impl-zZFaSmxd2.mjs.map → impl-BDrvzlpf2.mjs.map} +1 -1
- package/dist/{impl-Dk6TZKrp2.mjs → impl-BH_A5rgL.mjs} +2 -2
- package/dist/impl-BH_A5rgL.mjs.map +1 -0
- package/dist/{impl-CHmjV-Pa.mjs → impl-BOawPhYE.mjs} +2 -2
- package/dist/{impl-CHmjV-Pa.mjs.map → impl-BOawPhYE.mjs.map} +1 -1
- package/dist/{impl-CXUJ1eRC.mjs → impl-BPoEH3Nf2.mjs} +2 -2
- package/dist/impl-BPoEH3Nf2.mjs.map +1 -0
- package/dist/{impl-CqF9xIIy.mjs → impl-BXUYpR27.mjs} +2 -2
- package/dist/{impl-CqF9xIIy.mjs.map → impl-BXUYpR27.mjs.map} +1 -1
- package/dist/{impl-DYf10-BD2.mjs → impl-Bc6p8A1l2.mjs} +2 -2
- package/dist/{impl-DYf10-BD2.mjs.map → impl-Bc6p8A1l2.mjs.map} +1 -1
- package/dist/{impl-M3Eu4QjS.mjs → impl-BqWQh9Ss.mjs} +2 -2
- package/dist/{impl-M3Eu4QjS.mjs.map → impl-BqWQh9Ss.mjs.map} +1 -1
- package/dist/impl-C6HtWd1t.mjs +2 -0
- package/dist/{impl-BcJ019T2.mjs.map → impl-C6HtWd1t.mjs.map} +1 -1
- package/dist/{impl-GHukPBnk.mjs → impl-CL29fOWM.mjs} +2 -2
- package/dist/{impl-GHukPBnk.mjs.map → impl-CL29fOWM.mjs.map} +1 -1
- package/dist/{impl-BvNZqLrT.mjs → impl-CO4ZqlLV.mjs} +2 -2
- package/dist/{impl-BvNZqLrT.mjs.map → impl-CO4ZqlLV.mjs.map} +1 -1
- package/dist/{impl-DJLlcqSg.mjs → impl-COujMWgp.mjs} +2 -2
- package/dist/{impl-DJLlcqSg.mjs.map → impl-COujMWgp.mjs.map} +1 -1
- package/dist/{impl-Bs-drNBf.mjs → impl-CPSEzCc9.mjs} +2 -2
- package/dist/{impl-Bs-drNBf.mjs.map → impl-CPSEzCc9.mjs.map} +1 -1
- package/dist/{impl-Dib6Fff12.mjs → impl-CQVy2k3o.mjs} +2 -2
- package/dist/impl-CQVy2k3o.mjs.map +1 -0
- package/dist/{impl-B3_hrFPX.mjs → impl-CUOVJsRg.mjs} +2 -2
- package/dist/{impl-B3_hrFPX.mjs.map → impl-CUOVJsRg.mjs.map} +1 -1
- package/dist/{impl-BySmbxEt.mjs → impl-CUiYbk6G.mjs} +2 -2
- package/dist/{impl-BySmbxEt.mjs.map → impl-CUiYbk6G.mjs.map} +1 -1
- package/dist/{impl-CWh9H7mL.mjs → impl-CXTBcYo6.mjs} +2 -2
- package/dist/{impl-CWh9H7mL.mjs.map → impl-CXTBcYo6.mjs.map} +1 -1
- package/dist/{impl-Cx3T0Iei.mjs → impl-CfvxD3RI.mjs} +2 -2
- package/dist/{impl-Cx3T0Iei.mjs.map → impl-CfvxD3RI.mjs.map} +1 -1
- package/dist/{impl-DHfYO9T52.mjs → impl-Cli2XRp02.mjs} +2 -2
- package/dist/{impl-DHfYO9T52.mjs.map → impl-Cli2XRp02.mjs.map} +1 -1
- package/dist/{impl-CDtUusmg.mjs → impl-CuDs6SsI.mjs} +2 -2
- package/dist/{impl-CDtUusmg.mjs.map → impl-CuDs6SsI.mjs.map} +1 -1
- package/dist/{impl-BYGNx-8W2.mjs → impl-CvLI_Jig.mjs} +2 -2
- package/dist/impl-CvLI_Jig.mjs.map +1 -0
- package/dist/{impl-BFJtKA2o2.mjs → impl-CwKYKBYb.mjs} +2 -2
- package/dist/impl-CwKYKBYb.mjs.map +1 -0
- package/dist/{impl-BewF8tB6.mjs → impl-CwXp3Tbr.mjs} +2 -2
- package/dist/{impl-BewF8tB6.mjs.map → impl-CwXp3Tbr.mjs.map} +1 -1
- package/dist/{impl-B--lr5RJ2.mjs → impl-CyQRmuM72.mjs} +2 -2
- package/dist/{impl-B--lr5RJ2.mjs.map → impl-CyQRmuM72.mjs.map} +1 -1
- package/dist/impl-DEJpYLPB.mjs +2 -0
- package/dist/impl-DEJpYLPB.mjs.map +1 -0
- package/dist/impl-DEhw1iNn.mjs +2 -0
- package/dist/impl-DEhw1iNn.mjs.map +1 -0
- package/dist/impl-DK7nSMle2.mjs +303 -0
- package/dist/impl-DK7nSMle2.mjs.map +1 -0
- package/dist/{impl-DOoR93T6.mjs → impl-DKepRc812.mjs} +2 -2
- package/dist/impl-DKepRc812.mjs.map +1 -0
- package/dist/{impl-CTIWliTx.mjs → impl-DLG0Egy6.mjs} +2 -2
- package/dist/{impl-CTIWliTx.mjs.map → impl-DLG0Egy6.mjs.map} +1 -1
- package/dist/impl-DMe_OqJx.mjs +2 -0
- package/dist/{impl-BsC1KVxS.mjs.map → impl-DMe_OqJx.mjs.map} +1 -1
- package/dist/{impl-BwRcpAno.mjs → impl-DNe-gRXe2.mjs} +2 -2
- package/dist/impl-DNe-gRXe2.mjs.map +1 -0
- package/dist/{impl-Dm-Fkr392.mjs → impl-DNzkRayg.mjs} +2 -2
- package/dist/impl-DNzkRayg.mjs.map +1 -0
- package/dist/{impl-DzNk41xd.mjs → impl-DPtx5iZO.mjs} +2 -2
- package/dist/{impl-DzNk41xd.mjs.map → impl-DPtx5iZO.mjs.map} +1 -1
- package/dist/{impl-syp5hclX.mjs → impl-DRpK-QLC.mjs} +2 -2
- package/dist/{impl-syp5hclX.mjs.map → impl-DRpK-QLC.mjs.map} +1 -1
- package/dist/{impl-Bq6g_xYv.mjs → impl-DVQmuZQY.mjs} +2 -2
- package/dist/{impl-Bq6g_xYv.mjs.map → impl-DVQmuZQY.mjs.map} +1 -1
- package/dist/{impl-DYwojWvN.mjs → impl-DVeGQCrr.mjs} +2 -2
- package/dist/{impl-DYwojWvN.mjs.map → impl-DVeGQCrr.mjs.map} +1 -1
- package/dist/{impl-DF8RGVlT.mjs → impl-DXRDWiB1.mjs} +2 -2
- package/dist/{impl-DF8RGVlT.mjs.map → impl-DXRDWiB1.mjs.map} +1 -1
- package/dist/{impl-CiYKuCHV.mjs → impl-DXowiNOz.mjs} +2 -2
- package/dist/{impl-CiYKuCHV.mjs.map → impl-DXowiNOz.mjs.map} +1 -1
- package/dist/{impl-DpuhHpuk.mjs → impl-DaH1_ZzK.mjs} +2 -2
- package/dist/{impl-DpuhHpuk.mjs.map → impl-DaH1_ZzK.mjs.map} +1 -1
- package/dist/{impl-DIPvFKiP.mjs → impl-DdIa0zla.mjs} +2 -2
- package/dist/{impl-DIPvFKiP.mjs.map → impl-DdIa0zla.mjs.map} +1 -1
- package/dist/{impl-DbZ1cYoR.mjs → impl-DqhZR11m.mjs} +2 -2
- package/dist/{impl-DbZ1cYoR.mjs.map → impl-DqhZR11m.mjs.map} +1 -1
- package/dist/{impl-VPBEqV0w2.mjs → impl-Dqqb0lVN.mjs} +2 -2
- package/dist/impl-Dqqb0lVN.mjs.map +1 -0
- package/dist/{impl-6m7GXUAe.mjs → impl-DryC3OJu.mjs} +2 -2
- package/dist/{impl-6m7GXUAe.mjs.map → impl-DryC3OJu.mjs.map} +1 -1
- package/dist/{impl-CQGeH47F.mjs → impl-DuZjI6p0.mjs} +2 -2
- package/dist/{impl-CQGeH47F.mjs.map → impl-DuZjI6p0.mjs.map} +1 -1
- package/dist/{impl-C5dzaDga2.mjs → impl-Dw8NYkzw.mjs} +2 -2
- package/dist/impl-Dw8NYkzw.mjs.map +1 -0
- package/dist/impl-Dx_TfvW1.mjs +2 -0
- package/dist/{impl-C8BmxFQ2.mjs.map → impl-Dx_TfvW1.mjs.map} +1 -1
- package/dist/{impl-DXNcD7CZ.mjs → impl-DypttZd6.mjs} +2 -2
- package/dist/{impl-DXNcD7CZ.mjs.map → impl-DypttZd6.mjs.map} +1 -1
- package/dist/{impl-CfPXYgT42.mjs → impl-DzUTmaID2.mjs} +2 -2
- package/dist/{impl-CfPXYgT42.mjs.map → impl-DzUTmaID2.mjs.map} +1 -1
- package/dist/{impl-BJlKQJdS2.mjs → impl-INhq_CiK.mjs} +2 -2
- package/dist/impl-INhq_CiK.mjs.map +1 -0
- package/dist/{impl-KKrDTraf.mjs → impl-KmCNH-yw.mjs} +2 -2
- package/dist/{impl-KKrDTraf.mjs.map → impl-KmCNH-yw.mjs.map} +1 -1
- package/dist/{impl-CE56-wQh.mjs → impl-RPG-BTmX.mjs} +2 -2
- package/dist/{impl-CE56-wQh.mjs.map → impl-RPG-BTmX.mjs.map} +1 -1
- package/dist/{impl-amV0wRWk.mjs → impl-XrTL-TDl.mjs} +2 -2
- package/dist/{impl-amV0wRWk.mjs.map → impl-XrTL-TDl.mjs.map} +1 -1
- package/dist/impl-Z8oWVENM.mjs +2 -0
- package/dist/impl-Z8oWVENM.mjs.map +1 -0
- package/dist/{impl-m3QXCc6n.mjs → impl-a_Y8bnSn.mjs} +4 -4
- package/dist/impl-a_Y8bnSn.mjs.map +1 -0
- package/dist/{impl-CEmXPEq22.mjs → impl-hwpT9u5o2.mjs} +2 -2
- package/dist/{impl-CEmXPEq22.mjs.map → impl-hwpT9u5o2.mjs.map} +1 -1
- package/dist/{impl-BWVe4VGF2.mjs → impl-xq89cSSz2.mjs} +2 -2
- package/dist/{impl-BWVe4VGF2.mjs.map → impl-xq89cSSz2.mjs.map} +1 -1
- package/dist/index.d.mts +12797 -1840
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +3 -3
- package/dist/index.mjs.map +1 -1
- package/dist/{initializeCliRuntime-802-P8MC.mjs → initializeCliRuntime-6wI_VIHV.mjs} +1 -1
- package/dist/{initializeCliRuntime-802-P8MC.mjs.map → initializeCliRuntime-6wI_VIHV.mjs.map} +1 -1
- package/dist/{inquirer-DkFTQU00.mjs → inquirer-BeaBetMO.mjs} +2 -2
- package/dist/{inquirer-DkFTQU00.mjs.map → inquirer-BeaBetMO.mjs.map} +1 -1
- package/dist/jsonc-D9dDWb1J.mjs +6 -0
- package/dist/jsonc-D9dDWb1J.mjs.map +1 -0
- package/dist/{listFiles-CWHAdKY-.mjs → listFiles-BdFUbX5x.mjs} +1 -1
- package/dist/{listFiles-CWHAdKY-.mjs.map → listFiles-BdFUbX5x.mjs.map} +1 -1
- package/dist/logger-zplFSeXU.mjs +2 -0
- package/dist/logger-zplFSeXU.mjs.map +1 -0
- package/dist/manifest-BNIpO_zW.mjs +2 -0
- package/dist/manifest-BNIpO_zW.mjs.map +1 -0
- package/dist/{mapConsentCsvRowsToInputs-MMPZwzrV.mjs → mapConsentCsvRowsToInputs-Dqb6WL4r.mjs} +1 -1
- package/dist/{mapConsentCsvRowsToInputs-MMPZwzrV.mjs.map → mapConsentCsvRowsToInputs-Dqb6WL4r.mjs.map} +1 -1
- package/dist/{markRequestDataSiloIdsCompleted-PKCcn5wQ.mjs → markRequestDataSiloIdsCompleted-B5N-cQWr.mjs} +2 -2
- package/dist/{markRequestDataSiloIdsCompleted-PKCcn5wQ.mjs.map → markRequestDataSiloIdsCompleted-B5N-cQWr.mjs.map} +1 -1
- package/dist/{markSilentPrivacyRequests-7l9I99pe.mjs → markSilentPrivacyRequests-BiaButWF.mjs} +2 -2
- package/dist/{markSilentPrivacyRequests-7l9I99pe.mjs.map → markSilentPrivacyRequests-BiaButWF.mjs.map} +1 -1
- package/dist/mergeTranscendInputs-DFQcbh8b.mjs +3 -0
- package/dist/mergeTranscendInputs-DFQcbh8b.mjs.map +1 -0
- package/dist/missing-manifest-DgcukXfg.mjs +2 -0
- package/dist/missing-manifest-DgcukXfg.mjs.map +1 -0
- package/dist/{module-graph-DBC7ZvyA.mjs → module-graph-Cb0g74Ft.mjs} +1 -1
- package/dist/{module-graph-DBC7ZvyA.mjs.map → module-graph-Cb0g74Ft.mjs.map} +1 -1
- package/dist/{notifyPrivacyRequestsAdditionalTime-BPIYuCov.mjs → notifyPrivacyRequestsAdditionalTime-D3Vtvg5G.mjs} +2 -2
- package/dist/{notifyPrivacyRequestsAdditionalTime-BPIYuCov.mjs.map → notifyPrivacyRequestsAdditionalTime-D3Vtvg5G.mjs.map} +1 -1
- package/dist/{parquetToCsvOneFile-CSVdrLvq.mjs → parquetToCsvOneFile-ChmPC6dL.mjs} +2 -2
- package/dist/{parquetToCsvOneFile-CSVdrLvq.mjs.map → parquetToCsvOneFile-ChmPC6dL.mjs.map} +1 -1
- package/dist/{parseAttributesFromString-C5-KGkPH.mjs → parseAttributesFromString-CO16oAlx.mjs} +2 -2
- package/dist/{parseAttributesFromString-C5-KGkPH.mjs.map → parseAttributesFromString-CO16oAlx.mjs.map} +1 -1
- package/dist/{parseVariablesFromString-Cr3x2uq3.mjs → parseVariablesFromString-BOSfQ4QF.mjs} +1 -1
- package/dist/{parseVariablesFromString-Cr3x2uq3.mjs.map → parseVariablesFromString-BOSfQ4QF.mjs.map} +1 -1
- package/dist/path-safety-D5Qwl40b.mjs +2 -0
- package/dist/path-safety-D5Qwl40b.mjs.map +1 -0
- package/dist/policy-bundle-manifest-D6dkbjNi.mjs +7 -0
- package/dist/policy-bundle-manifest-D6dkbjNi.mjs.map +1 -0
- package/dist/policy-runtime-BMKa-Upy.mjs +2 -0
- package/dist/policy-runtime-BMKa-Upy.mjs.map +1 -0
- package/dist/{printResult-esxW3HhT.mjs → printResult-CHe3nRN4.mjs} +5 -5
- package/dist/printResult-CHe3nRN4.mjs.map +1 -0
- package/dist/project-plan-apply-Dvndx455.mjs +3 -0
- package/dist/project-plan-apply-Dvndx455.mjs.map +1 -0
- package/dist/prompts-ClBXdELk.mjs +4 -0
- package/dist/prompts-ClBXdELk.mjs.map +1 -0
- package/dist/{pullAllDatapoints-H92qjLSx.mjs → pullAllDatapoints-uk5ggk6O.mjs} +2 -2
- package/dist/{pullAllDatapoints-H92qjLSx.mjs.map → pullAllDatapoints-uk5ggk6O.mjs.map} +1 -1
- package/dist/{pullChunkedCustomSiloOutstandingIdentifiers-BrDmPbvc.mjs → pullChunkedCustomSiloOutstandingIdentifiers-D85P1W_8.mjs} +2 -2
- package/dist/{pullChunkedCustomSiloOutstandingIdentifiers-BrDmPbvc.mjs.map → pullChunkedCustomSiloOutstandingIdentifiers-D85P1W_8.mjs.map} +1 -1
- package/dist/{pullConsentManagerMetrics-Cvex-gpd.mjs → pullConsentManagerMetrics-Dv5n1ZGp.mjs} +2 -2
- package/dist/{pullConsentManagerMetrics-Cvex-gpd.mjs.map → pullConsentManagerMetrics-Dv5n1ZGp.mjs.map} +1 -1
- package/dist/{pullManualEnrichmentIdentifiersToCsv-qjdNA75O.mjs → pullManualEnrichmentIdentifiersToCsv-DbNSrKEk.mjs} +2 -2
- package/dist/{pullManualEnrichmentIdentifiersToCsv-qjdNA75O.mjs.map → pullManualEnrichmentIdentifiersToCsv-DbNSrKEk.mjs.map} +1 -1
- package/dist/{pullTranscendConfiguration-CD7Frn8z.mjs → pullTranscendConfiguration-B63M3ild.mjs} +3 -3
- package/dist/{pullTranscendConfiguration-CD7Frn8z.mjs.map → pullTranscendConfiguration-B63M3ild.mjs.map} +1 -1
- package/dist/{pullUnstructuredSubDataPointRecommendations-Dmh_-r95.mjs → pullUnstructuredSubDataPointRecommendations-YTBzfkRZ.mjs} +2 -2
- package/dist/{pullUnstructuredSubDataPointRecommendations-Dmh_-r95.mjs.map → pullUnstructuredSubDataPointRecommendations-YTBzfkRZ.mjs.map} +1 -1
- package/dist/{pushCronIdentifiersFromCsv-DjeY7TtK.mjs → pushCronIdentifiersFromCsv-5ruUKHtL.mjs} +2 -2
- package/dist/{pushCronIdentifiersFromCsv-DjeY7TtK.mjs.map → pushCronIdentifiersFromCsv-5ruUKHtL.mjs.map} +1 -1
- package/dist/{pushManualEnrichmentIdentifiersFromCsv-BDtMo13j.mjs → pushManualEnrichmentIdentifiersFromCsv-B0i2239u.mjs} +2 -2
- package/dist/{pushManualEnrichmentIdentifiersFromCsv-BDtMo13j.mjs.map → pushManualEnrichmentIdentifiersFromCsv-B0i2239u.mjs.map} +1 -1
- package/dist/{readCsv-Cr_1t8F5.mjs → readCsv-DLg8pwjd.mjs} +1 -1
- package/dist/{readCsv-Cr_1t8F5.mjs.map → readCsv-DLg8pwjd.mjs.map} +1 -1
- package/dist/readTranscendYaml-BNn6-Ofi.mjs +4 -0
- package/dist/readTranscendYaml-BNn6-Ofi.mjs.map +1 -0
- package/dist/{removeUnverifiedRequestIdentifiers-B9uPApVR.mjs → removeUnverifiedRequestIdentifiers-QmeqrmxM.mjs} +2 -2
- package/dist/{removeUnverifiedRequestIdentifiers-B9uPApVR.mjs.map → removeUnverifiedRequestIdentifiers-QmeqrmxM.mjs.map} +1 -1
- package/dist/{renderTable-DKTZbMjY.mjs → renderTable-D68QasPc.mjs} +1 -1
- package/dist/{renderTable-DKTZbMjY.mjs.map → renderTable-D68QasPc.mjs.map} +1 -1
- package/dist/{request-B1yRTdG-.mjs → request-BiPv6jmP.mjs} +1 -1
- package/dist/{request-B1yRTdG-.mjs.map → request-BiPv6jmP.mjs.map} +1 -1
- package/dist/{resolveBundleIdByName-DuxWYrDF.mjs → resolveBundleIdByName-qXZBrUz_.mjs} +2 -2
- package/dist/{resolveBundleIdByName-DuxWYrDF.mjs.map → resolveBundleIdByName-qXZBrUz_.mjs.map} +1 -1
- package/dist/{resolvePolicyBundleVersion-DhXZKwb4.mjs → resolvePolicyBundleVersion-BG7XqBBP.mjs} +2 -2
- package/dist/{resolvePolicyBundleVersion-DhXZKwb4.mjs.map → resolvePolicyBundleVersion-BG7XqBBP.mjs.map} +1 -1
- package/dist/{retryRequestDataSilos-D9dBtbdl.mjs → retryRequestDataSilos-BfckLjOJ.mjs} +2 -2
- package/dist/{retryRequestDataSilos-D9dBtbdl.mjs.map → retryRequestDataSilos-BfckLjOJ.mjs.map} +1 -1
- package/dist/{run-captured-process-CpZBh0lG.mjs → run-captured-process-BXwWXuTh.mjs} +1 -1
- package/dist/{run-captured-process-CpZBh0lG.mjs.map → run-captured-process-BXwWXuTh.mjs.map} +1 -1
- package/dist/runOpa-CswzJxIs.mjs +2 -0
- package/dist/runOpa-CswzJxIs.mjs.map +1 -0
- package/dist/scaffold-model-BAbYTR0q.mjs +2 -0
- package/dist/scaffold-model-BAbYTR0q.mjs.map +1 -0
- package/dist/scaffold-planning-CNv83t_v.mjs +123 -0
- package/dist/scaffold-planning-CNv83t_v.mjs.map +1 -0
- package/dist/scaffold-templates-DzDGTZie.mjs +84 -0
- package/dist/scaffold-templates-DzDGTZie.mjs.map +1 -0
- package/dist/{skipPreflightJobs-Beia_iB6.mjs → skipPreflightJobs-Do_kwu3m.mjs} +2 -2
- package/dist/{skipPreflightJobs-Beia_iB6.mjs.map → skipPreflightJobs-Do_kwu3m.mjs.map} +1 -1
- package/dist/{skipRequestDataSilos-BSNLacnR.mjs → skipRequestDataSilos-BNDhdllD.mjs} +2 -2
- package/dist/{skipRequestDataSilos-BSNLacnR.mjs.map → skipRequestDataSilos-BNDhdllD.mjs.map} +1 -1
- package/dist/{streamPrivacyRequestsToCsv-Cksb9D49.mjs → streamPrivacyRequestsToCsv-CbJfhV6A.mjs} +2 -2
- package/dist/{streamPrivacyRequestsToCsv-Cksb9D49.mjs.map → streamPrivacyRequestsToCsv-CbJfhV6A.mjs.map} +1 -1
- package/dist/{syncCodePackages-DsC1tE8B.mjs → syncCodePackages-BHE2Tn1Q.mjs} +2 -2
- package/dist/{syncCodePackages-DsC1tE8B.mjs.map → syncCodePackages-BHE2Tn1Q.mjs.map} +1 -1
- package/dist/{updateConsentManagerVersionToLatest-CaEkTnlL.mjs → updateConsentManagerVersionToLatest-DEFwH4Se.mjs} +2 -2
- package/dist/{updateConsentManagerVersionToLatest-CaEkTnlL.mjs.map → updateConsentManagerVersionToLatest-DEFwH4Se.mjs.map} +1 -1
- package/dist/{uploadConsents-CNyuYx0o.mjs → uploadConsents-ChmFIw_j.mjs} +2 -2
- package/dist/{uploadConsents-CNyuYx0o.mjs.map → uploadConsents-ChmFIw_j.mjs.map} +1 -1
- package/dist/{uploadPrivacyRequestsFromCsv-BdTQOZnF.mjs → uploadPrivacyRequestsFromCsv-D3KSb1qH.mjs} +2 -2
- package/dist/{uploadPrivacyRequestsFromCsv-BdTQOZnF.mjs.map → uploadPrivacyRequestsFromCsv-D3KSb1qH.mjs.map} +1 -1
- package/dist/{validateTranscendAuth-CnHMn77m.mjs → validateTranscendAuth-D6Wr1cxY.mjs} +2 -2
- package/dist/{validateTranscendAuth-CnHMn77m.mjs.map → validateTranscendAuth-D6Wr1cxY.mjs.map} +1 -1
- package/dist/{writeCsv-D46aDkGf.mjs → writeCsv-D-2siSwE.mjs} +1 -1
- package/dist/{writeCsv-D46aDkGf.mjs.map → writeCsv-D-2siSwE.mjs.map} +1 -1
- package/package.json +8 -7
- package/dist/app-DCY8E776.mjs.map +0 -1
- package/dist/codecs-BsQFAFGT.mjs +0 -2
- package/dist/codecs-BsQFAFGT.mjs.map +0 -1
- package/dist/constants-BMAOvdcA.mjs +0 -2
- package/dist/constants-BMAOvdcA.mjs.map +0 -1
- package/dist/deno-runtime-QqwBDKXX.mjs +0 -2
- package/dist/deno-runtime-QqwBDKXX.mjs.map +0 -1
- package/dist/impl-BFJtKA2o2.mjs.map +0 -1
- package/dist/impl-BJlKQJdS2.mjs.map +0 -1
- package/dist/impl-BNPgYSBT.mjs +0 -3
- package/dist/impl-BNPgYSBT.mjs.map +0 -1
- package/dist/impl-BYGNx-8W2.mjs.map +0 -1
- package/dist/impl-BcJ019T2.mjs +0 -2
- package/dist/impl-BsC1KVxS.mjs +0 -2
- package/dist/impl-BwRcpAno.mjs.map +0 -1
- package/dist/impl-C5dzaDga2.mjs.map +0 -1
- package/dist/impl-C8BmxFQ2.mjs +0 -2
- package/dist/impl-CXUJ1eRC.mjs.map +0 -1
- package/dist/impl-CzxvoiGW.mjs +0 -3
- package/dist/impl-D-SQJc3t.mjs +0 -2
- package/dist/impl-D-SQJc3t.mjs.map +0 -1
- package/dist/impl-D23kJPAQ2.mjs +0 -3
- package/dist/impl-D23kJPAQ2.mjs.map +0 -1
- package/dist/impl-DOoR93T6.mjs.map +0 -1
- package/dist/impl-Dib6Fff12.mjs.map +0 -1
- package/dist/impl-Dk6TZKrp2.mjs.map +0 -1
- package/dist/impl-Dm-Fkr392.mjs.map +0 -1
- package/dist/impl-Drql0g72.mjs.map +0 -1
- package/dist/impl-FLj_mWLO.mjs +0 -2
- package/dist/impl-FLj_mWLO.mjs.map +0 -1
- package/dist/impl-VPBEqV0w2.mjs.map +0 -1
- package/dist/impl-m3QXCc6n.mjs.map +0 -1
- package/dist/logger-9T6vva73.mjs +0 -2
- package/dist/logger-9T6vva73.mjs.map +0 -1
- package/dist/manifest-DVuW_vvO.mjs +0 -2
- package/dist/manifest-DVuW_vvO.mjs.map +0 -1
- package/dist/mergeTranscendInputs-CWHXH0kF.mjs +0 -3
- package/dist/mergeTranscendInputs-CWHXH0kF.mjs.map +0 -1
- package/dist/missing-manifest-BKj1j-jg.mjs +0 -2
- package/dist/missing-manifest-BKj1j-jg.mjs.map +0 -1
- package/dist/printResult-esxW3HhT.mjs.map +0 -1
- package/dist/project-plan-apply-C2DfikVN.mjs +0 -3
- package/dist/project-plan-apply-C2DfikVN.mjs.map +0 -1
- package/dist/readTranscendYaml-STYnRzq-.mjs +0 -4
- package/dist/readTranscendYaml-STYnRzq-.mjs.map +0 -1
- package/dist/runOpa-CkKAwsvB.mjs +0 -2
- package/dist/runOpa-CkKAwsvB.mjs.map +0 -1
- package/dist/scaffold-planning-DMACXSnX.mjs +0 -121
- package/dist/scaffold-planning-DMACXSnX.mjs.map +0 -1
- package/dist/scaffold-templates-CsHM1y80.mjs +0 -84
- package/dist/scaffold-templates-CsHM1y80.mjs.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mergeTranscendInputs-CWHXH0kF.mjs","names":[],"sources":["../src/lib/preference-management/validatePreferenceManagementSlugs.ts","../src/lib/graphql/ensureAllDataSubjectsExist.ts","../src/lib/graphql/normalizeDeletionDependencies.ts","../src/lib/graphql/syncDataSilos.ts","../src/lib/graphql/syncConfigurationToTranscend.ts","../src/lib/mergeTranscendInputs.ts"],"sourcesContent":["import type { TranscendInput } from '../../codecs.js';\n\n/** Slugs for preference topics and option values must be alphabetical letters only. */\nexport const PREFERENCE_SLUG_REGEX = /^[A-Za-z]+$/;\n\n/**\n * Validate preference topic and option value slugs before push.\n *\n * @param input - Parsed transcend.yml input\n * @returns List of validation error messages (empty when valid)\n */\nexport function validatePreferenceManagementSlugs(input: TranscendInput): string[] {\n const errors: string[] = [];\n\n const validateSlug = (slug: string, context: string): void => {\n if (!PREFERENCE_SLUG_REGEX.test(slug)) {\n errors.push(\n `${context}: slug \"${slug}\" is invalid — slugs must contain only alphabetical letters (A-Z, a-z). ` +\n 'Topic slugs are normalized to PascalCase server-side, so YAML slugs should already be PascalCase ' +\n 'or matching will break on subsequent pulls.',\n );\n }\n };\n\n for (const option of input['preference-options'] ?? []) {\n validateSlug(option.slug, 'preference-options');\n }\n\n for (const purpose of input.purposes ?? []) {\n for (const topic of purpose['preference-topics'] ?? []) {\n validateSlug(topic.slug, `purposes (topic \"${topic.title}\")`);\n for (const option of topic.options ?? []) {\n validateSlug(option.slug, `purposes (topic \"${topic.title}\" option \"${option.title}\")`);\n }\n }\n }\n\n return errors;\n}\n","import { createDataSubject, fetchAllDataSubjects, type DataSubject } from '@transcend-io/sdk';\nimport colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\nimport { keyBy, flatten, uniq, difference } from 'lodash-es';\n\nimport { TranscendInput } from '../../codecs.js';\nimport { logger } from '../../logger.js';\n\n/**\n * Fetch all of the data subjects in the organization\n *\n * @param input - Input to fetch\n * @param client - GraphQL client\n * @param fetchAll - When true, always fetch all subjects\n * @returns The list of data subjects\n */\nexport async function ensureAllDataSubjectsExist(\n {\n 'data-silos': dataSilos = [],\n 'data-subjects': dataSubjects = [],\n 'processing-activities': processingActivities = [],\n enrichers = [],\n }: TranscendInput,\n client: GraphQLClient,\n fetchAll = false,\n): Promise<{ [type in string]: DataSubject }> {\n const expectedDataSubjects = uniq([\n ...flatten(dataSilos.map((silo) => silo['data-subjects'] || []) || []),\n ...flatten(processingActivities.map(({ dataSubjectTypes }) => dataSubjectTypes ?? []) ?? []),\n ...flatten(enrichers.map((enricher) => enricher['data-subjects'] || []) || []),\n ...dataSubjects.map((subject) => subject.type),\n ]);\n if (expectedDataSubjects.length === 0 && !fetchAll) {\n return {};\n }\n\n const internalSubjects = await fetchAllDataSubjects(client, { logger });\n const dataSubjectByName = keyBy(internalSubjects, 'type');\n\n const missingDataSubjects = difference(\n expectedDataSubjects,\n internalSubjects.map(({ type }) => type),\n );\n\n if (missingDataSubjects.length > 0) {\n logger.info(colors.magenta(`Creating ${missingDataSubjects.length} new data subjects...`));\n for (const dataSubjectType of missingDataSubjects) {\n logger.info(colors.magenta(`Creating data subject ${dataSubjectType}...`));\n const created = await createDataSubject(client, { input: dataSubjectType, logger });\n logger.info(colors.green(`Created data subject ${dataSubjectType}!`));\n dataSubjectByName[dataSubjectType] = created;\n }\n }\n\n return dataSubjectByName;\n}\n","import type { DependedOnDataSiloInput } from '@transcend-io/sdk';\nimport { uniq } from 'lodash-es';\n\nimport type { DeletionDependencies, DeletionDependencyInput } from '../../codecs.js';\n\n/**\n * Convert the `deletion-dependencies` entries for a single data silo into the\n * `dependedOnDataSilos` input accepted by the `updateDataSilos` mutation.\n *\n * A list of titles becomes a single global entry. A list of objects may declare\n * at most one global configuration (`{ titles }`) plus per-workflow overrides;\n * workflows that are absent from the list are left untouched.\n *\n * @param dependencies - The `deletion-dependencies` entries from transcend.yml\n * @param dataSiloTitle - Title of the data silo being synced, used in error messages\n * @returns The dependency entries to send to the API\n */\nexport function normalizeDeletionDependencies(\n dependencies: DeletionDependencies,\n dataSiloTitle: string,\n): DependedOnDataSiloInput[] {\n if (dependencies.length === 0) {\n return [];\n }\n\n // Legacy / no-overrides form: a flat list of data silo titles\n if (typeof dependencies[0] === 'string') {\n return [{ titles: uniq(dependencies as string[]) }];\n }\n\n let globalTitles: string[] | undefined;\n const workflowOverrides: DependedOnDataSiloInput[] = [];\n const seenWorkflows = new Set<string>();\n\n /**\n * Record an override for a single workflow, rejecting duplicates before the API does\n * so that the error names the data silo\n *\n * @param workflow - Internal name of the workflow being overridden\n * @param override - Titles or reset flag to send for that workflow\n */\n const addWorkflowOverride = (\n workflow: string,\n override: Omit<DependedOnDataSiloInput, 'workflowConfigInternalName'>,\n ): void => {\n if (seenWorkflows.has(workflow)) {\n throw new Error(\n `Data silo \"${dataSiloTitle}\" has multiple deletion-dependencies entries for workflow ` +\n `\"${workflow}\". Combine them into a single entry.`,\n );\n }\n seenWorkflows.add(workflow);\n workflowOverrides.push({ workflowConfigInternalName: workflow, ...override });\n };\n\n (dependencies as DeletionDependencyInput[]).forEach((dependency) => {\n // io-ts codecs allow extra properties, so this combination decodes cleanly\n // even though the two halves contradict each other\n if ('reset-to-global' in dependency && 'titles' in dependency) {\n throw new Error(\n `Data silo \"${dataSiloTitle}\" has a deletion-dependencies entry for workflow ` +\n `\"${dependency.workflow}\" that sets both \"reset-to-global\" and \"titles\". ` +\n 'Use \"titles: []\" to override the global configuration with no dependencies, ' +\n 'or \"reset-to-global: true\" to fall back to the global configuration.',\n );\n }\n\n if ('reset-to-global' in dependency) {\n addWorkflowOverride(dependency.workflow, { resetToGlobal: true });\n return;\n }\n\n if (dependency.workflow) {\n addWorkflowOverride(dependency.workflow, { titles: dependency.titles });\n return;\n }\n\n if (globalTitles !== undefined) {\n throw new Error(\n `Data silo \"${dataSiloTitle}\" has multiple global deletion-dependencies entries. ` +\n 'Combine them into a single `{ titles: [...] }` entry.',\n );\n }\n globalTitles = dependency.titles;\n });\n\n return [\n ...(globalTitles !== undefined ? [{ titles: uniq(globalTitles) }] : []),\n ...workflowOverrides,\n ];\n}\n","import {\n makeGraphQLRequest,\n ApiKey,\n convertToDataSubjectBlockList,\n type DataSubject,\n fetchAllDataSilos,\n type DataSilo,\n CREATE_DATA_SILOS,\n UPDATE_DATA_SILOS,\n UPDATE_OR_CREATE_DATA_POINT,\n} from '@transcend-io/sdk';\nimport { apply } from '@transcend-io/type-utils';\nimport { mapSeries, map } from '@transcend-io/utils';\n/* eslint-disable max-lines */\nimport cliProgress from 'cli-progress';\nimport colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\nimport { chunk, keyBy } from 'lodash-es';\n\nimport { DataSiloInput } from '../../codecs.js';\nimport { logger } from '../../logger.js';\n\nconst BATCH_SILOS_LIMIT = 20;\n\n/**\n * Sync a data silo configuration\n *\n * @param dataSilos - Data silos to sync\n * @param client - GraphQL client\n * @param options - Options\n * @returns Data silo info\n */\nexport async function syncDataSilos(\n dataSilos: DataSiloInput[],\n client: GraphQLClient,\n {\n pageSize,\n dataSubjectsByName,\n apiKeysByTitle,\n }: {\n /** Page size */\n pageSize: number;\n /** The data subjects in the organization */\n dataSubjectsByName: { [type in string]: DataSubject };\n /** API key title to API key */\n apiKeysByTitle: { [title in string]: ApiKey };\n },\n): Promise<{\n /** Whether successfully updated */\n success: boolean;\n /** A mapping between data silo title to data silo ID */\n dataSiloTitleToId: { [k in string]: string };\n}> {\n let encounteredError = false;\n\n // Time duration\n const t0 = new Date().getTime();\n logger.info(colors.magenta(`Syncing \"${dataSilos.length}\" data silos...`));\n\n // Determine the set of data silos that already exist\n const existingDataSilos = await fetchAllDataSilos(client, {\n titles: dataSilos.map(({ title }) => title),\n pageSize,\n logger,\n });\n\n // Create a mapping of title -> existing silo, if it exists\n const existingDataSiloByTitle = keyBy<Pick<DataSilo, 'id' | 'title'>>(existingDataSilos, 'title');\n\n // Create new silos that do not exist\n const newDataSiloInputs = dataSilos.filter(({ title }) => !existingDataSiloByTitle[title]);\n if (newDataSiloInputs.length > 0) {\n logger.info(\n colors.magenta(`Creating \"${newDataSiloInputs.length}\" data silos that did not exist...`),\n );\n\n // Batch the creation\n const chunked = chunk(newDataSiloInputs, BATCH_SILOS_LIMIT);\n await mapSeries(chunked, async (dependencyUpdateChunk) => {\n const {\n createDataSilos: { dataSilos },\n } = await makeGraphQLRequest<{\n /** Mutation result */\n createDataSilos: {\n /** New data silos */\n dataSilos: Pick<DataSilo, 'id' | 'title'>[];\n };\n }>(client, CREATE_DATA_SILOS, {\n variables: {\n input: dependencyUpdateChunk.map((input) => ({\n name: input['outer-type'] || input.integrationName,\n title: input.title,\n country: input.country,\n countrySubDivision: input.countrySubDivision,\n sombraId: input['sombra-id'],\n })),\n },\n logger,\n });\n\n // save mapping of title and id\n dataSilos.forEach((silo) => {\n existingDataSiloByTitle[silo.title] = silo;\n });\n });\n\n logger.info(colors.green(`Successfully created \"${newDataSiloInputs.length}\" data silos!`));\n }\n\n // Batch the updates\n const chunkedUpdates = chunk(dataSilos, BATCH_SILOS_LIMIT);\n await mapSeries(chunkedUpdates, async (dataSiloUpdateChunk, ind) => {\n logger.info(\n colors.magenta(\n `[Batch ${ind + 1}/${chunkedUpdates.length}] Syncing \"${\n dataSiloUpdateChunk.length\n }\" data silos`,\n ),\n );\n await makeGraphQLRequest<{\n /** Mutation result */\n updateDataSilos: {\n /** New data silos */\n dataSilos: Pick<DataSilo, 'id' | 'title'>[];\n };\n }>(client, UPDATE_DATA_SILOS, {\n variables: {\n input: {\n dataSilos: dataSiloUpdateChunk.map((input) => ({\n id: existingDataSiloByTitle[input.title].id,\n country: input.country,\n countrySubDivision: input.countrySubDivision,\n url: input.url,\n headers: input.headers,\n description: input.description,\n identifiers: input['identity-keys'],\n isLive: !input.disabled,\n ownerEmails: input.owners,\n teamNames: input.teams,\n // clear out the global config if not specified, otherwise the update needs to be\n // applied after all data silos are created\n dependedOnDataSilos: input['deletion-dependencies'] ? undefined : [{ titles: [] }],\n apiKeyId: input['api-key-title']\n ? apiKeysByTitle[input['api-key-title']].id\n : undefined,\n dataSubjectBlockListIds: input['data-subjects']\n ? convertToDataSubjectBlockList(input['data-subjects'], dataSubjectsByName)\n : undefined,\n attributes: input.attributes,\n businessEntityTitles: input.businessEntityTitles,\n sombraId: input['sombra-id'],\n // AVC settings\n notifyEmailAddress: input['email-settings']?.['notify-email-address'],\n promptAVendorEmailSendFrequency: input['email-settings']?.['send-frequency'],\n promptAVendorEmailSendType: input['email-settings']?.['send-type'],\n promptAVendorEmailIncludeIdentifiersAttachment:\n input['email-settings']?.['include-identifiers-attachment'],\n promptAVendorEmailCompletionLinkType: input['email-settings']?.['completion-link-type'],\n manualWorkRetryFrequency: input['email-settings']?.['manual-work-retry-frequency'],\n })),\n },\n },\n logger,\n });\n logger.info(\n colors.green(\n `[Batch ${ind + 1}/${chunkedUpdates.length}] Synced \"${\n dataSiloUpdateChunk.length\n }\" data silos!`,\n ),\n );\n });\n\n // Sync datapoints\n\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);\n const dataSilosWithDataPoints = dataSilos.filter(({ datapoints = [] }) => datapoints.length > 0);\n const totalDataPoints = dataSilos\n .map(({ datapoints = [] }) => datapoints.length)\n .reduce((acc, count) => acc + count, 0);\n logger.info(\n colors.magenta(\n `Syncing \"${totalDataPoints}\" datapoints from \"${dataSilosWithDataPoints.length}\" data silos...`,\n ),\n );\n progressBar.start(totalDataPoints, 0);\n let total = 0;\n\n await map(\n dataSilosWithDataPoints,\n async ({ datapoints, title }) => {\n if (datapoints) {\n await mapSeries(datapoints, async (datapoint) => {\n const fields = datapoint.fields\n ? datapoint.fields.map(\n ({ key, description, categories, purposes, attributes, ...rest }) =>\n // TODO: Support setting title separately from the 'key/name'\n ({\n name: key,\n description,\n categories: !categories\n ? undefined\n : categories.map((category) => ({\n ...category,\n name: category.name || 'Other',\n })),\n purposes: !purposes\n ? undefined\n : purposes.map((purpose) => ({\n ...purpose,\n name: purpose.name || 'Other',\n })),\n attributes,\n accessRequestVisibilityEnabled: rest['access-request-visibility-enabled'],\n erasureRequestRedactionEnabled: rest['erasure-request-redaction-enabled'],\n }),\n )\n : undefined;\n\n const payload = {\n dataSiloId: existingDataSiloByTitle[title].id,\n path: datapoint.path,\n name: datapoint.key,\n title: datapoint.title,\n description: datapoint.description,\n ...(datapoint.owners\n ? {\n ownerEmails: datapoint.owners,\n }\n : {}),\n ...(datapoint.teams\n ? {\n teamNames: datapoint.teams,\n }\n : {}),\n ...(datapoint['data-collection-tag']\n ? { dataCollectionTag: datapoint['data-collection-tag'] }\n : {}),\n querySuggestions: !datapoint['privacy-action-queries']\n ? undefined\n : Object.entries(datapoint['privacy-action-queries']).map(([key, value]) => ({\n requestType: key,\n suggestedQuery: value,\n })),\n enabledActions: datapoint['privacy-actions'] || [], // clear out when not specified\n subDataPoints: fields,\n };\n\n // Ensure no duplicate sub-datapoints are provided\n const subDataPointsToUpdate = (payload.subDataPoints || []).map(({ name }) => name);\n const duplicateDataPoints = subDataPointsToUpdate.filter(\n (name, index) => subDataPointsToUpdate.indexOf(name) !== index,\n );\n if (duplicateDataPoints.length > 0) {\n logger.info(\n colors.red(\n `\\nCannot update datapoint \"${\n datapoint.key\n }\" as it has duplicate sub-datapoints with the same name: \\n${duplicateDataPoints.join(\n '\\n',\n )}`,\n ),\n );\n encounteredError = true;\n } else {\n try {\n await makeGraphQLRequest(client, UPDATE_OR_CREATE_DATA_POINT, {\n variables: payload,\n logger,\n });\n } catch (err) {\n logger.info(\n colors.red(\n `\\nFailed to update datapoint \"${datapoint.key}\" for data silo \"${title}\"! - \\n${err.message}`,\n ),\n );\n encounteredError = true;\n }\n }\n total += 1;\n progressBar.update(total);\n });\n }\n },\n {\n concurrency: 10,\n },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Synced \"${dataSilos.length}\" data silos and \"${totalDataPoints}\" datapoints in \"${\n totalTime / 1000\n }\" seconds!`,\n ),\n );\n return {\n success: !encounteredError,\n dataSiloTitleToId: apply(existingDataSiloByTitle, ({ id }) => id),\n };\n}\n/* eslint-enable max-lines */\n","import {\n fetchAllActions,\n fetchAllAttributes,\n fetchAllDataSubjects,\n fetchApiKeys,\n fetchIdentifiersAndCreateMissing,\n syncAction,\n syncActionItemCollections,\n syncActionItems,\n syncAttribute,\n syncBusinessEntities,\n syncDataCategories,\n syncConsentManager,\n syncCookies,\n syncDataFlows,\n syncDataSubject,\n syncDataSiloDependencies,\n syncEnricher,\n syncIdentifier,\n syncIntlMessages,\n syncPartitions,\n syncPolicies,\n syncPrivacyCenter,\n syncProcessingActivities,\n syncProcessingPurposes,\n syncConsentWorkflowTriggers,\n syncWorkflowConfigs,\n syncPreferenceOptionValues,\n syncPurposes,\n syncPreferenceTopics,\n syncTeams,\n syncTemplate,\n syncVendors,\n type DependedOnDataSiloInput,\n type Identifier,\n} from '@transcend-io/sdk';\nimport { map, type Logger, type SyncError, type SyncResult } from '@transcend-io/utils';\nimport colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\n\n/* eslint-disable max-lines */\nimport { TranscendInput } from '../../codecs.js';\nimport { logger } from '../../logger.js';\nimport { validatePreferenceManagementSlugs } from '../preference-management/validatePreferenceManagementSlugs.js';\nimport { ensureAllDataSubjectsExist } from './ensureAllDataSubjectsExist.js';\nimport { normalizeDeletionDependencies } from './normalizeDeletionDependencies.js';\nimport { syncDataSilos } from './syncDataSilos.js';\n\nconst CONCURRENCY = 10;\n\n/**\n * Sync the yaml input back to Transcend using the GraphQL APIs\n *\n * @param input - The yml input\n * @param client - GraphQL client\n * @param pageSize - Page size\n * @returns Structured sync result with per-resource errors\n */\nexport async function syncConfigurationToTranscend(\n input: TranscendInput,\n client: GraphQLClient,\n {\n pageSize = 50,\n // TODO: https://transcend.height.app/T-23779\n publishToPrivacyCenter = true,\n classifyService = false,\n deleteExtraAttributeValues = false,\n logger: syncLogger,\n warnings = [],\n }: {\n /** Page size */\n pageSize?: number;\n /** When true, skip publishing to privacy center */\n publishToPrivacyCenter?: boolean;\n /** When true, delete any attributes being synced up */\n deleteExtraAttributeValues?: boolean;\n /** classify data flow service if missing */\n classifyService?: boolean;\n /** Optional logger (e.g. collecting logger for MCP debug responses) */\n logger?: Logger;\n /** Non-fatal warnings to include in the result */\n warnings?: string[];\n },\n): Promise<SyncResult> {\n const activeLogger = syncLogger ?? logger;\n const errors: SyncError[] = [];\n let encounteredError = false;\n\n const recordError = (resource: string, message: string, item?: string): void => {\n errors.push({ resource, item, message });\n encounteredError = true;\n };\n\n activeLogger.info(colors.magenta(`Fetching data with page size ${pageSize}...`));\n\n const {\n templates,\n attributes,\n actions,\n identifiers,\n 'data-subjects': dataSubjects,\n 'business-entities': businessEntities,\n enrichers,\n cookies,\n 'consent-manager': consentManager,\n 'data-silos': dataSilos,\n 'data-flows': dataFlows,\n vendors,\n 'data-categories': dataCategories,\n 'processing-activities': processingActivities,\n 'processing-purposes': processingPurposes,\n 'action-items': actionItems,\n 'action-item-collections': actionItemCollections,\n teams,\n 'privacy-center': privacyCenter,\n messages,\n policies,\n partitions,\n 'preference-workflow-configs': preferenceWorkflowConfigs,\n 'workflow-configs': workflowConfigs,\n } = input;\n\n const preferenceOptions = input['preference-options'];\n const purposes = input.purposes;\n\n const preferenceSlugErrors = validatePreferenceManagementSlugs(input);\n if (preferenceSlugErrors.length > 0) {\n for (const message of preferenceSlugErrors) {\n recordError('preference-slugs', message);\n }\n return {\n success: false,\n errors,\n warnings: warnings.length > 0 ? warnings : undefined,\n };\n }\n\n const [identifierByName, dataSubjectsByName, apiKeyTitleMap] = await Promise.all([\n // Ensure all identifiers are created and create a map from name -> identifier.id\n enrichers || identifiers\n ? fetchIdentifiersAndCreateMissing(client, {\n input,\n skipPublish: !publishToPrivacyCenter,\n logger,\n })\n : ({} as { [k in string]: Identifier }),\n // Grab all data subjects in the organization\n dataSilos || dataSubjects || enrichers || processingActivities\n ? ensureAllDataSubjectsExist(input, client)\n : {},\n // Grab API keys\n dataSilos &&\n dataSilos\n .map((dataSilo) => dataSilo['api-key-title'] || [])\n .reduce((acc, lst) => acc + lst.length, 0) > 0\n ? fetchApiKeys(client, { apiKeyInputs: input, logger })\n : {},\n ]);\n\n if (preferenceWorkflowConfigs?.length) {\n const preferenceWorkflowConfigsSuccess = await syncConsentWorkflowTriggers(\n client,\n preferenceWorkflowConfigs,\n {\n logger: activeLogger,\n pageSize,\n },\n );\n if (!preferenceWorkflowConfigsSuccess) {\n recordError('preference-workflow-configs', 'Failed to sync preference workflow configs');\n }\n }\n\n if (workflowConfigs?.length) {\n const workflowConfigsSuccess = await syncWorkflowConfigs(client, workflowConfigs, {\n logger: activeLogger,\n });\n if (!workflowConfigsSuccess) {\n recordError('workflow-configs', 'Failed to sync workflow configs');\n }\n }\n\n if (preferenceOptions?.length) {\n const preferenceOptionsSuccess = await syncPreferenceOptionValues(client, preferenceOptions, {\n logger: activeLogger,\n });\n if (!preferenceOptionsSuccess) {\n recordError('preference-options', 'Failed to sync preference option values');\n }\n }\n\n // Sync consent purposes and their nested preference topics.\n // Order matters: option values (above) exist first, then purposes, then topics\n // (which link to their purpose by ID and to option values by slug).\n if (purposes?.length) {\n const { success: purposesSuccess, purposeIdByTrackingType } = await syncPurposes(\n client,\n purposes,\n { logger: activeLogger },\n );\n if (!purposesSuccess) {\n recordError('purposes', 'Failed to sync one or more purposes');\n }\n\n const topics = purposes.flatMap((purpose) =>\n (purpose['preference-topics'] ?? []).map((topic) => ({\n ...topic,\n 'tracking-type': purpose.trackingType,\n })),\n );\n if (topics.length > 0) {\n const topicsSuccess = await syncPreferenceTopics(client, topics, {\n logger: activeLogger,\n purposeIdByTrackingType,\n });\n if (!topicsSuccess) {\n recordError('preference-topics', 'Failed to sync one or more preference topics');\n }\n }\n }\n\n // Sync consent manager\n if (consentManager) {\n activeLogger.info(colors.magenta('Syncing consent manager...'));\n try {\n await syncConsentManager(client, consentManager, { logger: activeLogger });\n activeLogger.info(colors.green('Successfully synced consent manager!'));\n } catch (err) {\n recordError('consent-manager', (err as Error).message);\n activeLogger.error(colors.red(`Failed to sync consent manager! - ${(err as Error).message}`));\n }\n }\n\n if (teams) {\n const teamsSuccess = await syncTeams(client, teams, { logger });\n encounteredError = encounteredError || !teamsSuccess;\n }\n\n // Sync email templates\n if (templates) {\n logger.info(colors.magenta(`Syncing \"${templates.length}\" email templates...`));\n await map(\n templates,\n async (template) => {\n logger.info(colors.magenta(`Syncing template \"${template.title}\"...`));\n try {\n await syncTemplate(client, template, { logger });\n logger.info(colors.green(`Successfully synced template \"${template.title}\"!`));\n } catch (err) {\n encounteredError = true;\n logger.error(colors.red(`Failed to sync template \"${template.title}\"! - ${err.message}`));\n }\n },\n {\n concurrency: CONCURRENCY,\n },\n );\n logger.info(colors.green(`Synced \"${templates.length}\" email templates!`));\n }\n\n // Sync business entities\n if (businessEntities) {\n const businessEntitySuccess = await syncBusinessEntities(client, businessEntities, { logger });\n encounteredError = encounteredError || !businessEntitySuccess;\n }\n\n // Sync vendors\n if (vendors) {\n const vendorsSuccess = await syncVendors(client, vendors, { logger });\n encounteredError = encounteredError || !vendorsSuccess;\n }\n\n // Sync data categories\n if (dataCategories) {\n const dataCategoriesSuccess = await syncDataCategories(client, dataCategories, { logger });\n encounteredError = encounteredError || !dataCategoriesSuccess;\n }\n\n // Sync processing purposes\n if (processingPurposes) {\n const processingPurposesSuccess = await syncProcessingPurposes(client, processingPurposes, {\n logger,\n });\n encounteredError = encounteredError || !processingPurposesSuccess;\n }\n\n // Sync partitions\n if (partitions) {\n const partitionsSuccess = await syncPartitions(client, partitions, { logger });\n encounteredError = encounteredError || !partitionsSuccess;\n }\n\n // Sync cookies\n if (cookies) {\n const cookiesSuccess = await syncCookies(client, cookies, { logger });\n encounteredError = encounteredError || !cookiesSuccess;\n }\n\n // Sync action item collections\n if (actionItemCollections) {\n const actionItemCollectionsSuccess = await syncActionItemCollections(\n client,\n actionItemCollections,\n { logger },\n );\n encounteredError = encounteredError || !actionItemCollectionsSuccess;\n }\n\n // Sync attributes\n if (attributes) {\n // Fetch existing\n logger.info(colors.magenta(`Syncing \"${attributes.length}\" attributes...`));\n const existingAttributes = await fetchAllAttributes(client, { logger });\n await map(\n attributes,\n async (attribute) => {\n const existing = existingAttributes.find((attr) => attr.name === attribute.name);\n\n logger.info(colors.magenta(`Syncing attribute \"${attribute.name}\"...`));\n try {\n await syncAttribute(client, attribute, {\n existingAttribute: existing,\n deleteExtraAttributeValues,\n logger,\n });\n logger.info(colors.green(`Successfully synced attribute \"${attribute.name}\"!`));\n } catch (err) {\n encounteredError = true;\n logger.error(\n colors.red(`Failed to sync attribute \"${attribute.name}\"! - ${err.message}`),\n );\n }\n },\n {\n concurrency: CONCURRENCY,\n },\n );\n logger.info(colors.green(`Synced \"${attributes.length}\" attributes!`));\n }\n\n // Sync action items\n if (actionItems) {\n const actionItemsSuccess = await syncActionItems(client, actionItems, { logger });\n encounteredError = encounteredError || !actionItemsSuccess;\n }\n\n // Sync enrichers\n if (enrichers) {\n logger.info(colors.magenta(`Syncing \"${enrichers.length}\" enrichers...`));\n await map(\n enrichers,\n async (enricher) => {\n logger.info(colors.magenta(`Syncing enricher \"${enricher.title}\"...`));\n try {\n await syncEnricher(client, {\n input: enricher,\n identifierByName,\n dataSubjectsByName,\n logger,\n });\n logger.info(colors.green(`Successfully synced enricher \"${enricher.title}\"!`));\n } catch (err) {\n encounteredError = true;\n logger.error(colors.red(`Failed to sync enricher \"${enricher.title}\"! - ${err.message}`));\n }\n },\n {\n concurrency: CONCURRENCY,\n },\n );\n logger.info(colors.green(`Synced \"${enrichers.length}\" enrichers!`));\n }\n\n // Sync identifiers\n if (identifiers) {\n // Fetch existing\n logger.info(colors.magenta(`Syncing \"${identifiers.length}\" identifiers...`));\n await map(\n identifiers,\n async (identifier) => {\n const existing = identifierByName[identifier.name];\n if (!existing) {\n throw new Error(\n `Failed to find identifier with name: ${identifier.type}. Should have been auto-created by cli.`,\n );\n }\n\n logger.info(colors.magenta(`Syncing identifier \"${identifier.type}\"...`));\n try {\n await syncIdentifier(client, {\n input: identifier,\n dataSubjectsByName,\n identifierId: existing.id,\n skipPublish: !publishToPrivacyCenter,\n logger,\n });\n logger.info(colors.green(`Successfully synced identifier \"${identifier.type}\"!`));\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(`Failed to sync identifier \"${identifier.type}\"! - ${err.message}`),\n );\n }\n },\n {\n concurrency: CONCURRENCY,\n },\n );\n logger.info(colors.green(`Synced \"${identifiers.length}\" identifiers!`));\n }\n\n // Sync actions\n if (actions) {\n // Fetch existing\n logger.info(colors.magenta(`Syncing \"${actions.length}\" actions...`));\n const existingActions = await fetchAllActions(client, { logger });\n await map(\n actions,\n async (action) => {\n const existing = existingActions.find((act) => act.type === action.type);\n if (!existing) {\n throw new Error(\n `Failed to find action with type: ${action.type}. Should have already existing in the organization.`,\n );\n }\n\n logger.info(colors.magenta(`Syncing action \"${action.type}\"...`));\n try {\n await syncAction(\n client,\n {\n action,\n actionId: existing.id,\n skipPublish: !publishToPrivacyCenter,\n },\n { logger },\n );\n logger.info(colors.green(`Successfully synced action \"${action.type}\"!`));\n } catch (err) {\n encounteredError = true;\n logger.error(colors.red(`Failed to sync action \"${action.type}\"! - ${err.message}`));\n }\n },\n {\n concurrency: CONCURRENCY,\n },\n );\n logger.info(colors.green(`Synced \"${actions.length}\" actions!`));\n }\n\n // Sync data subjects\n if (dataSubjects) {\n // Fetch existing\n logger.info(colors.magenta(`Syncing \"${dataSubjects.length}\" data subjects...`));\n const existingDataSubjects = await fetchAllDataSubjects(client, { logger });\n await map(\n dataSubjects,\n async (dataSubject) => {\n const existing = existingDataSubjects.find((subj) => subj.type === dataSubject.type);\n if (!existing) {\n throw new Error(\n `Failed to find data subject with type: ${dataSubject.type}. Should have already existing in the organization.`,\n );\n }\n\n logger.info(colors.magenta(`Syncing data subject \"${dataSubject.type}\"...`));\n try {\n await syncDataSubject(client, {\n input: dataSubject,\n dataSubjectId: existing.id,\n skipPublish: !publishToPrivacyCenter,\n logger,\n });\n logger.info(colors.green(`Successfully synced data subject \"${dataSubject.type}\"!`));\n } catch (err) {\n encounteredError = true;\n // supportsAuthorizedAgent is gated on the Authorized Agents feature being\n // enabled for the organization; surface a clearer hint than the raw API error\n const hint =\n dataSubject.supportsAuthorizedAgent !== undefined &&\n /authorized.agent/i.test(err.message)\n ? ' (enable the Authorized Agents feature for this organization before setting \"supportsAuthorizedAgent\")'\n : '';\n logger.info(\n colors.red(\n `Failed to sync data subject \"${dataSubject.type}\"! - ${err.message}${hint}`,\n ),\n );\n }\n },\n {\n concurrency: CONCURRENCY,\n },\n );\n logger.info(colors.green(`Synced \"${dataSubjects.length}\" data subjects!`));\n }\n\n // Sync data flows\n if (dataFlows) {\n const syncedDataFlows = await syncDataFlows(client, dataFlows, { classifyService, logger });\n encounteredError = encounteredError || !syncedDataFlows;\n }\n\n // Sync privacy center\n if (privacyCenter) {\n try {\n const privacyCenterSuccess = await syncPrivacyCenter(client, privacyCenter, {\n logger,\n skipPublish: !publishToPrivacyCenter,\n });\n if (!privacyCenterSuccess) {\n recordError('privacy-center', 'Failed to sync privacy center');\n }\n } catch (err) {\n recordError('privacy-center', (err as Error).message);\n }\n }\n\n // Sync messages\n if (messages) {\n const messagesSuccess = await syncIntlMessages(client, messages, { logger });\n encounteredError = encounteredError || !messagesSuccess;\n }\n\n // Sync policies\n if (policies) {\n const policiesSuccess = await syncPolicies(client, policies, { logger });\n encounteredError = encounteredError || !policiesSuccess;\n }\n\n // Store dependency updates\n const dependencyUpdates: [string, DependedOnDataSiloInput[]][] = [];\n // Sync data silos\n if (dataSilos) {\n const { success, dataSiloTitleToId } = await syncDataSilos(dataSilos, client, {\n dataSubjectsByName,\n apiKeysByTitle: apiKeyTitleMap,\n pageSize,\n });\n dataSilos?.forEach((dataSilo) => {\n // Queue up dependency update\n const dependencies = dataSilo['deletion-dependencies'];\n if (dependencies) {\n try {\n dependencyUpdates.push([\n dataSiloTitleToId[dataSilo.title],\n normalizeDeletionDependencies(dependencies, dataSilo.title),\n ]);\n } catch (err) {\n recordError('data-silos', (err as Error).message, dataSilo.title);\n activeLogger.error(colors.red((err as Error).message));\n }\n }\n });\n encounteredError = encounteredError || !success;\n }\n\n // Dependencies updated at the end after all data silos are created\n if (dependencyUpdates.length > 0) {\n const dependenciesSuccess = await syncDataSiloDependencies(client, {\n input: dependencyUpdates,\n logger,\n });\n encounteredError = encounteredError || !dependenciesSuccess;\n }\n\n // Update processing activities\n if (processingActivities) {\n const processingActivitySuccess = await syncProcessingActivities(client, processingActivities, {\n logger,\n });\n encounteredError = encounteredError || !processingActivitySuccess;\n }\n\n if (publishToPrivacyCenter) {\n // TODO: https://transcend.height.app/T-23779\n }\n\n return {\n success: !encounteredError,\n errors,\n warnings: warnings.length > 0 ? warnings : undefined,\n };\n}\n/* eslint-enable max-lines */\n","import { getEntries } from '@transcend-io/type-utils';\n\nimport { TranscendInput } from '../codecs.js';\n\n/**\n * Combine a set of TranscendInput yaml files into a single yaml\n *\n * @param base - Base input\n * @param inputs - The list of inputs\n * @returns Merged input\n */\nexport function mergeTranscendInputs(\n base: TranscendInput,\n ...inputs: TranscendInput[]\n): TranscendInput {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const cloned: any = JSON.parse(JSON.stringify(base));\n inputs.forEach((input) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n getEntries(input).forEach(([key, value]: [any, any]) => {\n if (cloned[key] === undefined) {\n cloned[key] = value;\n } else if (Array.isArray(value)) {\n cloned[key] = [...cloned[key], ...value];\n } else {\n cloned[key] = value;\n }\n });\n });\n return cloned;\n}\n"],"mappings":"yvCAGA,MAAa,EAAwB,cAQrC,SAAgB,GAAkC,EAAiC,CACjF,IAAM,EAAmB,EAAE,CAErB,GAAgB,EAAc,IAA0B,CACvD,EAAsB,KAAK,EAAK,EACnC,EAAO,KACL,GAAG,EAAQ,UAAU,EAAK,sNAG3B,EAIL,IAAK,IAAM,KAAU,EAAM,uBAAyB,EAAE,CACpD,EAAa,EAAO,KAAM,qBAAqB,CAGjD,IAAK,IAAM,KAAW,EAAM,UAAY,EAAE,CACxC,IAAK,IAAM,KAAS,EAAQ,sBAAwB,EAAE,CAAE,CACtD,EAAa,EAAM,KAAM,oBAAoB,EAAM,MAAM,IAAI,CAC7D,IAAK,IAAM,KAAU,EAAM,SAAW,EAAE,CACtC,EAAa,EAAO,KAAM,oBAAoB,EAAM,MAAM,YAAY,EAAO,MAAM,IAAI,CAK7F,OAAO,ECrBT,eAAsB,EACpB,CACE,aAAc,EAAY,EAAE,CAC5B,gBAAiB,EAAe,EAAE,CAClC,wBAAyB,EAAuB,EAAE,CAClD,YAAY,EAAE,EAEhB,EACA,EAAW,GACiC,CAC5C,IAAM,EAAuB,EAAK,CAChC,GAAG,EAAQ,EAAU,IAAK,GAAS,EAAK,kBAAoB,EAAE,CAAC,EAAI,EAAE,CAAC,CACtE,GAAG,EAAQ,EAAqB,KAAK,CAAE,sBAAuB,GAAoB,EAAE,CAAC,EAAI,EAAE,CAAC,CAC5F,GAAG,EAAQ,EAAU,IAAK,GAAa,EAAS,kBAAoB,EAAE,CAAC,EAAI,EAAE,CAAC,CAC9E,GAAG,EAAa,IAAK,GAAY,EAAQ,KAAK,CAC/C,CAAC,CACF,GAAI,EAAqB,SAAW,GAAK,CAAC,EACxC,MAAO,EAAE,CAGX,IAAM,EAAmB,MAAM,EAAqB,EAAQ,CAAE,SAAQ,CAAC,CACjE,EAAoB,EAAM,EAAkB,OAAO,CAEnD,EAAsB,EAC1B,EACA,EAAiB,KAAK,CAAE,UAAW,EAAK,CACzC,CAED,GAAI,EAAoB,OAAS,EAAG,CAClC,EAAO,KAAK,EAAO,QAAQ,YAAY,EAAoB,OAAO,uBAAuB,CAAC,CAC1F,IAAK,IAAM,KAAmB,EAAqB,CACjD,EAAO,KAAK,EAAO,QAAQ,yBAAyB,EAAgB,KAAK,CAAC,CAC1E,IAAM,EAAU,MAAM,EAAkB,EAAQ,CAAE,MAAO,EAAiB,SAAQ,CAAC,CACnF,EAAO,KAAK,EAAO,MAAM,wBAAwB,EAAgB,GAAG,CAAC,CACrE,EAAkB,GAAmB,GAIzC,OAAO,ECrCT,SAAgB,GACd,EACA,EAC2B,CAC3B,GAAI,EAAa,SAAW,EAC1B,MAAO,EAAE,CAIX,GAAI,OAAO,EAAa,IAAO,SAC7B,MAAO,CAAC,CAAE,OAAQ,EAAK,EAAyB,CAAE,CAAC,CAGrD,IAAI,EACE,EAA+C,EAAE,CACjD,EAAgB,IAAI,IASpB,GACJ,EACA,IACS,CACT,GAAI,EAAc,IAAI,EAAS,CAC7B,MAAU,MACR,cAAc,EAAc,6DACtB,EAAS,sCAChB,CAEH,EAAc,IAAI,EAAS,CAC3B,EAAkB,KAAK,CAAE,2BAA4B,EAAU,GAAG,EAAU,CAAC,EAkC/E,OA/BC,EAA2C,QAAS,GAAe,CAGlE,GAAI,oBAAqB,GAAc,WAAY,EACjD,MAAU,MACR,cAAc,EAAc,oDACtB,EAAW,SAAS,mMAG3B,CAGH,GAAI,oBAAqB,EAAY,CACnC,EAAoB,EAAW,SAAU,CAAE,cAAe,GAAM,CAAC,CACjE,OAGF,GAAI,EAAW,SAAU,CACvB,EAAoB,EAAW,SAAU,CAAE,OAAQ,EAAW,OAAQ,CAAC,CACvE,OAGF,GAAI,IAAiB,IAAA,GACnB,MAAU,MACR,cAAc,EAAc,8GAE7B,CAEH,EAAe,EAAW,QAC1B,CAEK,CACL,GAAI,IAAiB,IAAA,GAA+C,EAAE,CAArC,CAAC,CAAE,OAAQ,EAAK,EAAa,CAAE,CAAC,CACjE,GAAG,EACJ,CCzDH,eAAsB,EACpB,EACA,EACA,CACE,WACA,qBACA,kBAcD,CACD,IAAI,EAAmB,GAGjB,EAAK,IAAI,MAAM,CAAC,SAAS,CAC/B,EAAO,KAAK,EAAO,QAAQ,YAAY,EAAU,OAAO,iBAAiB,CAAC,CAU1E,IAAM,EAA0B,EAAsC,MAPtC,EAAkB,EAAQ,CACxD,OAAQ,EAAU,KAAK,CAAE,WAAY,EAAM,CAC3C,WACA,SACD,CAAC,CAGuF,QAAQ,CAG3F,EAAoB,EAAU,QAAQ,CAAE,WAAY,CAAC,EAAwB,GAAO,CACtF,EAAkB,OAAS,IAC7B,EAAO,KACL,EAAO,QAAQ,aAAa,EAAkB,OAAO,oCAAoC,CAC1F,CAID,MAAM,EADU,EAAM,EAAmB,GAClB,CAAE,KAAO,IAA0B,CACxD,GAAM,CACJ,gBAAiB,CAAE,cACjB,MAAM,EAMP,EAAQ,EAAmB,CAC5B,UAAW,CACT,MAAO,EAAsB,IAAK,IAAW,CAC3C,KAAM,EAAM,eAAiB,EAAM,gBACnC,MAAO,EAAM,MACb,QAAS,EAAM,QACf,mBAAoB,EAAM,mBAC1B,SAAU,EAAM,aACjB,EAAE,CACJ,CACD,SACD,CAAC,CAGF,EAAU,QAAS,GAAS,CAC1B,EAAwB,EAAK,OAAS,GACtC,EACF,CAEF,EAAO,KAAK,EAAO,MAAM,yBAAyB,EAAkB,OAAO,eAAe,CAAC,EAI7F,IAAM,EAAiB,EAAM,EAAW,GAAkB,CAC1D,MAAM,EAAU,EAAgB,MAAO,EAAqB,IAAQ,CAClE,EAAO,KACL,EAAO,QACL,UAAU,EAAM,EAAE,GAAG,EAAe,OAAO,aACzC,EAAoB,OACrB,cACF,CACF,CACD,MAAM,EAMH,EAAQ,EAAmB,CAC5B,UAAW,CACT,MAAO,CACL,UAAW,EAAoB,IAAK,IAAW,CAC7C,GAAI,EAAwB,EAAM,OAAO,GACzC,QAAS,EAAM,QACf,mBAAoB,EAAM,mBAC1B,IAAK,EAAM,IACX,QAAS,EAAM,QACf,YAAa,EAAM,YACnB,YAAa,EAAM,iBACnB,OAAQ,CAAC,EAAM,SACf,YAAa,EAAM,OACnB,UAAW,EAAM,MAGjB,oBAAqB,EAAM,yBAA2B,IAAA,GAAY,CAAC,CAAE,OAAQ,EAAE,CAAE,CAAC,CAClF,SAAU,EAAM,iBACZ,EAAe,EAAM,kBAAkB,GACvC,IAAA,GACJ,wBAAyB,EAAM,iBAC3B,EAA8B,EAAM,iBAAkB,EAAmB,CACzE,IAAA,GACJ,WAAY,EAAM,WAClB,qBAAsB,EAAM,qBAC5B,SAAU,EAAM,aAEhB,mBAAoB,EAAM,oBAAoB,wBAC9C,gCAAiC,EAAM,oBAAoB,kBAC3D,2BAA4B,EAAM,oBAAoB,aACtD,+CACE,EAAM,oBAAoB,kCAC5B,qCAAsC,EAAM,oBAAoB,wBAChE,yBAA0B,EAAM,oBAAoB,+BACrD,EAAE,CACJ,CACF,CACD,SACD,CAAC,CACF,EAAO,KACL,EAAO,MACL,UAAU,EAAM,EAAE,GAAG,EAAe,OAAO,YACzC,EAAoB,OACrB,eACF,CACF,EACD,CAKF,IAAM,EAAc,IAAI,EAAY,UAAU,EAAE,CAAE,EAAY,QAAQ,eAAe,CAC/E,EAA0B,EAAU,QAAQ,CAAE,aAAa,EAAE,IAAO,EAAW,OAAS,EAAE,CAC1F,EAAkB,EACrB,KAAK,CAAE,aAAa,EAAE,IAAO,EAAW,OAAO,CAC/C,QAAQ,EAAK,IAAU,EAAM,EAAO,EAAE,CACzC,EAAO,KACL,EAAO,QACL,YAAY,EAAgB,qBAAqB,EAAwB,OAAO,iBACjF,CACF,CACD,EAAY,MAAM,EAAiB,EAAE,CACrC,IAAI,EAAQ,EAEZ,MAAM,EACJ,EACA,MAAO,CAAE,aAAY,WAAY,CAC3B,GACF,MAAM,EAAU,EAAY,KAAO,IAAc,CAC/C,IAAM,EAAS,EAAU,OACrB,EAAU,OAAO,KACd,CAAE,MAAK,cAAa,aAAY,WAAU,aAAY,GAAG,MAEvD,CACC,KAAM,EACN,cACA,WAAa,EAET,EAAW,IAAK,IAAc,CAC5B,GAAG,EACH,KAAM,EAAS,MAAQ,QACxB,EAAE,CAJH,IAAA,GAKJ,SAAW,EAEP,EAAS,IAAK,IAAa,CACzB,GAAG,EACH,KAAM,EAAQ,MAAQ,QACvB,EAAE,CAJH,IAAA,GAKJ,aACA,+BAAgC,EAAK,qCACrC,+BAAgC,EAAK,qCACtC,EACJ,CACD,IAAA,GAEE,EAAU,CACd,WAAY,EAAwB,GAAO,GAC3C,KAAM,EAAU,KAChB,KAAM,EAAU,IAChB,MAAO,EAAU,MACjB,YAAa,EAAU,YACvB,GAAI,EAAU,OACV,CACE,YAAa,EAAU,OACxB,CACD,EAAE,CACN,GAAI,EAAU,MACV,CACE,UAAW,EAAU,MACtB,CACD,EAAE,CACN,GAAI,EAAU,uBACV,CAAE,kBAAmB,EAAU,uBAAwB,CACvD,EAAE,CACN,iBAAmB,EAAU,0BAEzB,OAAO,QAAQ,EAAU,0BAA0B,CAAC,KAAK,CAAC,EAAK,MAAY,CACzE,YAAa,EACb,eAAgB,EACjB,EAAE,CAJH,IAAA,GAKJ,eAAgB,EAAU,oBAAsB,EAAE,CAClD,cAAe,EAChB,CAGK,GAAyB,EAAQ,eAAiB,EAAE,EAAE,KAAK,CAAE,UAAW,EAAK,CAC7E,EAAsB,EAAsB,QAC/C,EAAM,IAAU,EAAsB,QAAQ,EAAK,GAAK,EAC1D,CACD,GAAI,EAAoB,OAAS,EAC/B,EAAO,KACL,EAAO,IACL,8BACE,EAAU,IACX,6DAA6D,EAAoB,KAChF;EACD,GACF,CACF,CACD,EAAmB,QAEnB,GAAI,CACF,MAAM,EAAmB,EAAQ,EAA6B,CAC5D,UAAW,EACX,SACD,CAAC,OACK,EAAK,CACZ,EAAO,KACL,EAAO,IACL,iCAAiC,EAAU,IAAI,mBAAmB,EAAM,SAAS,EAAI,UACtF,CACF,CACD,EAAmB,GAGvB,GAAS,EACT,EAAY,OAAO,EAAM,EACzB,EAGN,CACE,YAAa,GACd,CACF,CAED,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SACF,CAAG,EASvB,OAPA,EAAO,KACL,EAAO,MACL,WAAW,EAAU,OAAO,oBAAoB,EAAgB,mBAC9D,EAAY,IACb,YACF,CACF,CACM,CACL,QAAS,CAAC,EACV,kBAAmB,EAAM,GAA0B,CAAE,QAAS,EAAG,CAClE,CCtPH,eAAsB,EACpB,EACA,EACA,CACE,WAAW,GAEX,yBAAyB,GACzB,kBAAkB,GAClB,6BAA6B,GAC7B,OAAQ,EACR,WAAW,EAAE,EAeM,CACrB,IAAM,EAAe,GAAc,EAC7B,EAAsB,EAAE,CAC1B,EAAmB,GAEjB,GAAe,EAAkB,EAAiB,IAAwB,CAC9E,EAAO,KAAK,CAAE,WAAU,OAAM,UAAS,CAAC,CACxC,EAAmB,IAGrB,EAAa,KAAK,EAAO,QAAQ,gCAAgC,EAAS,KAAK,CAAC,CAEhF,GAAM,CACJ,YACA,aACA,UACA,cACA,gBAAiB,EACjB,oBAAqB,EACrB,YACA,UACA,kBAAmB,EACnB,aAAc,EACd,aAAc,EACd,UACA,kBAAmB,EACnB,wBAAyB,EACzB,sBAAuB,EACvB,eAAgB,EAChB,0BAA2B,EAC3B,QACA,iBAAkB,EAClB,WACA,WACA,aACA,8BAA+B,GAC/B,mBAAoB,GAClB,EAEE,GAAoB,EAAM,sBAC1B,EAAW,EAAM,SAEjB,GAAuB,GAAkC,EAAM,CACrE,GAAI,GAAqB,OAAS,EAAG,CACnC,IAAK,IAAM,KAAW,GACpB,EAAY,mBAAoB,EAAQ,CAE1C,MAAO,CACL,QAAS,GACT,SACA,SAAU,EAAS,OAAS,EAAI,EAAW,IAAA,GAC5C,CAGH,GAAM,CAAC,EAAkB,EAAoB,IAAkB,MAAM,QAAQ,IAAI,CAE/E,GAAa,EACT,EAAiC,EAAQ,CACvC,QACA,YAAa,CAAC,EACd,SACD,CAAC,CACD,EAAE,CAEP,GAAa,GAAgB,GAAa,EACtC,EAA2B,EAAO,EAAO,CACzC,EAAE,CAEN,GACA,EACG,IAAK,GAAa,EAAS,kBAAoB,EAAE,CAAC,CAClD,QAAQ,EAAK,IAAQ,EAAM,EAAI,OAAQ,EAAE,CAAG,EAC3C,EAAa,EAAQ,CAAE,aAAc,EAAO,SAAQ,CAAC,CACrD,EAAE,CACP,CAAC,CAqCF,GAnCI,IAA2B,SASxB,MAR0C,GAC7C,EACA,GACA,CACE,OAAQ,EACR,WACD,CACF,EAEC,EAAY,8BAA+B,6CAA6C,EAIxF,GAAiB,SAId,MAHgC,GAAoB,EAAQ,EAAiB,CAChF,OAAQ,EACT,CAAC,EAEA,EAAY,mBAAoB,kCAAkC,EAIlE,IAAmB,SAIhB,MAHkC,GAA2B,EAAQ,GAAmB,CAC3F,OAAQ,EACT,CAAC,EAEA,EAAY,qBAAsB,0CAA0C,EAO5E,GAAU,OAAQ,CACpB,GAAM,CAAE,QAAS,EAAiB,2BAA4B,MAAM,GAClE,EACA,EACA,CAAE,OAAQ,EAAc,CACzB,CACI,GACH,EAAY,WAAY,sCAAsC,CAGhE,IAAM,EAAS,EAAS,QAAS,IAC9B,EAAQ,sBAAwB,EAAE,EAAE,IAAK,IAAW,CACnD,GAAG,EACH,gBAAiB,EAAQ,aAC1B,EAAE,CACJ,CACG,EAAO,OAAS,IAKb,MAJuB,GAAqB,EAAQ,EAAQ,CAC/D,OAAQ,EACR,0BACD,CAAC,EAEA,EAAY,oBAAqB,+CAA+C,EAMtF,GAAI,EAAgB,CAClB,EAAa,KAAK,EAAO,QAAQ,6BAA6B,CAAC,CAC/D,GAAI,CACF,MAAM,GAAmB,EAAQ,EAAgB,CAAE,OAAQ,EAAc,CAAC,CAC1E,EAAa,KAAK,EAAO,MAAM,uCAAuC,CAAC,OAChE,EAAK,CACZ,EAAY,kBAAoB,EAAc,QAAQ,CACtD,EAAa,MAAM,EAAO,IAAI,qCAAsC,EAAc,UAAU,CAAC,EAIjG,GAAI,EAAO,CACT,IAAM,EAAe,MAAM,GAAU,EAAQ,EAAO,CAAE,SAAQ,CAAC,CAC/D,IAAuC,CAAC,EA0B1C,GAtBI,IACF,EAAO,KAAK,EAAO,QAAQ,YAAY,EAAU,OAAO,sBAAsB,CAAC,CAC/E,MAAM,EACJ,EACA,KAAO,IAAa,CAClB,EAAO,KAAK,EAAO,QAAQ,qBAAqB,EAAS,MAAM,MAAM,CAAC,CACtE,GAAI,CACF,MAAM,GAAa,EAAQ,EAAU,CAAE,SAAQ,CAAC,CAChD,EAAO,KAAK,EAAO,MAAM,iCAAiC,EAAS,MAAM,IAAI,CAAC,OACvE,EAAK,CACZ,EAAmB,GACnB,EAAO,MAAM,EAAO,IAAI,4BAA4B,EAAS,MAAM,OAAO,EAAI,UAAU,CAAC,GAG7F,CACE,YAAa,GACd,CACF,CACD,EAAO,KAAK,EAAO,MAAM,WAAW,EAAU,OAAO,oBAAoB,CAAC,EAIxE,EAAkB,CACpB,IAAM,EAAwB,MAAM,EAAqB,EAAQ,EAAkB,CAAE,SAAQ,CAAC,CAC9F,IAAuC,CAAC,EAI1C,GAAI,EAAS,CACX,IAAM,EAAiB,MAAM,GAAY,EAAQ,EAAS,CAAE,SAAQ,CAAC,CACrE,IAAuC,CAAC,EAI1C,GAAI,EAAgB,CAClB,IAAM,EAAwB,MAAM,GAAmB,EAAQ,EAAgB,CAAE,SAAQ,CAAC,CAC1F,IAAuC,CAAC,EAI1C,GAAI,EAAoB,CACtB,IAAM,EAA4B,MAAM,GAAuB,EAAQ,EAAoB,CACzF,SACD,CAAC,CACF,IAAuC,CAAC,EAI1C,GAAI,EAAY,CACd,IAAM,EAAoB,MAAM,GAAe,EAAQ,EAAY,CAAE,SAAQ,CAAC,CAC9E,IAAuC,CAAC,EAI1C,GAAI,EAAS,CACX,IAAM,EAAiB,MAAM,GAAY,EAAQ,EAAS,CAAE,SAAQ,CAAC,CACrE,IAAuC,CAAC,EAI1C,GAAI,EAAuB,CACzB,IAAM,EAA+B,MAAM,EACzC,EACA,EACA,CAAE,SAAQ,CACX,CACD,IAAuC,CAAC,EAI1C,GAAI,EAAY,CAEd,EAAO,KAAK,EAAO,QAAQ,YAAY,EAAW,OAAO,iBAAiB,CAAC,CAC3E,IAAM,EAAqB,MAAM,EAAmB,EAAQ,CAAE,SAAQ,CAAC,CACvE,MAAM,EACJ,EACA,KAAO,IAAc,CACnB,IAAM,EAAW,EAAmB,KAAM,GAAS,EAAK,OAAS,EAAU,KAAK,CAEhF,EAAO,KAAK,EAAO,QAAQ,sBAAsB,EAAU,KAAK,MAAM,CAAC,CACvE,GAAI,CACF,MAAM,EAAc,EAAQ,EAAW,CACrC,kBAAmB,EACnB,6BACA,SACD,CAAC,CACF,EAAO,KAAK,EAAO,MAAM,kCAAkC,EAAU,KAAK,IAAI,CAAC,OACxE,EAAK,CACZ,EAAmB,GACnB,EAAO,MACL,EAAO,IAAI,6BAA6B,EAAU,KAAK,OAAO,EAAI,UAAU,CAC7E,GAGL,CACE,YAAa,GACd,CACF,CACD,EAAO,KAAK,EAAO,MAAM,WAAW,EAAW,OAAO,eAAe,CAAC,CAIxE,GAAI,EAAa,CACf,IAAM,EAAqB,MAAM,EAAgB,EAAQ,EAAa,CAAE,SAAQ,CAAC,CACjF,IAAuC,CAAC,EAqE1C,GAjEI,IACF,EAAO,KAAK,EAAO,QAAQ,YAAY,EAAU,OAAO,gBAAgB,CAAC,CACzE,MAAM,EACJ,EACA,KAAO,IAAa,CAClB,EAAO,KAAK,EAAO,QAAQ,qBAAqB,EAAS,MAAM,MAAM,CAAC,CACtE,GAAI,CACF,MAAM,GAAa,EAAQ,CACzB,MAAO,EACP,mBACA,qBACA,SACD,CAAC,CACF,EAAO,KAAK,EAAO,MAAM,iCAAiC,EAAS,MAAM,IAAI,CAAC,OACvE,EAAK,CACZ,EAAmB,GACnB,EAAO,MAAM,EAAO,IAAI,4BAA4B,EAAS,MAAM,OAAO,EAAI,UAAU,CAAC,GAG7F,CACE,YAAa,GACd,CACF,CACD,EAAO,KAAK,EAAO,MAAM,WAAW,EAAU,OAAO,cAAc,CAAC,EAIlE,IAEF,EAAO,KAAK,EAAO,QAAQ,YAAY,EAAY,OAAO,kBAAkB,CAAC,CAC7E,MAAM,EACJ,EACA,KAAO,IAAe,CACpB,IAAM,EAAW,EAAiB,EAAW,MAC7C,GAAI,CAAC,EACH,MAAU,MACR,wCAAwC,EAAW,KAAK,yCACzD,CAGH,EAAO,KAAK,EAAO,QAAQ,uBAAuB,EAAW,KAAK,MAAM,CAAC,CACzE,GAAI,CACF,MAAM,GAAe,EAAQ,CAC3B,MAAO,EACP,qBACA,aAAc,EAAS,GACvB,YAAa,CAAC,EACd,SACD,CAAC,CACF,EAAO,KAAK,EAAO,MAAM,mCAAmC,EAAW,KAAK,IAAI,CAAC,OAC1E,EAAK,CACZ,EAAmB,GACnB,EAAO,KACL,EAAO,IAAI,8BAA8B,EAAW,KAAK,OAAO,EAAI,UAAU,CAC/E,GAGL,CACE,YAAa,GACd,CACF,CACD,EAAO,KAAK,EAAO,MAAM,WAAW,EAAY,OAAO,gBAAgB,CAAC,EAItE,EAAS,CAEX,EAAO,KAAK,EAAO,QAAQ,YAAY,EAAQ,OAAO,cAAc,CAAC,CACrE,IAAM,EAAkB,MAAM,EAAgB,EAAQ,CAAE,SAAQ,CAAC,CACjE,MAAM,EACJ,EACA,KAAO,IAAW,CAChB,IAAM,EAAW,EAAgB,KAAM,GAAQ,EAAI,OAAS,EAAO,KAAK,CACxE,GAAI,CAAC,EACH,MAAU,MACR,oCAAoC,EAAO,KAAK,qDACjD,CAGH,EAAO,KAAK,EAAO,QAAQ,mBAAmB,EAAO,KAAK,MAAM,CAAC,CACjE,GAAI,CACF,MAAM,EACJ,EACA,CACE,SACA,SAAU,EAAS,GACnB,YAAa,CAAC,EACf,CACD,CAAE,SAAQ,CACX,CACD,EAAO,KAAK,EAAO,MAAM,+BAA+B,EAAO,KAAK,IAAI,CAAC,OAClE,EAAK,CACZ,EAAmB,GACnB,EAAO,MAAM,EAAO,IAAI,0BAA0B,EAAO,KAAK,OAAO,EAAI,UAAU,CAAC,GAGxF,CACE,YAAa,GACd,CACF,CACD,EAAO,KAAK,EAAO,MAAM,WAAW,EAAQ,OAAO,YAAY,CAAC,CAIlE,GAAI,EAAc,CAEhB,EAAO,KAAK,EAAO,QAAQ,YAAY,EAAa,OAAO,oBAAoB,CAAC,CAChF,IAAM,EAAuB,MAAM,EAAqB,EAAQ,CAAE,SAAQ,CAAC,CAC3E,MAAM,EACJ,EACA,KAAO,IAAgB,CACrB,IAAM,EAAW,EAAqB,KAAM,GAAS,EAAK,OAAS,EAAY,KAAK,CACpF,GAAI,CAAC,EACH,MAAU,MACR,0CAA0C,EAAY,KAAK,qDAC5D,CAGH,EAAO,KAAK,EAAO,QAAQ,yBAAyB,EAAY,KAAK,MAAM,CAAC,CAC5E,GAAI,CACF,MAAM,GAAgB,EAAQ,CAC5B,MAAO,EACP,cAAe,EAAS,GACxB,YAAa,CAAC,EACd,SACD,CAAC,CACF,EAAO,KAAK,EAAO,MAAM,qCAAqC,EAAY,KAAK,IAAI,CAAC,OAC7E,EAAK,CACZ,EAAmB,GAGnB,IAAM,EACJ,EAAY,0BAA4B,IAAA,IACxC,oBAAoB,KAAK,EAAI,QAAQ,CACjC,yGACA,GACN,EAAO,KACL,EAAO,IACL,gCAAgC,EAAY,KAAK,OAAO,EAAI,UAAU,IACvE,CACF,GAGL,CACE,YAAa,GACd,CACF,CACD,EAAO,KAAK,EAAO,MAAM,WAAW,EAAa,OAAO,kBAAkB,CAAC,CAI7E,GAAI,EAAW,CACb,IAAM,EAAkB,MAAM,GAAc,EAAQ,EAAW,CAAE,kBAAiB,SAAQ,CAAC,CAC3F,IAAuC,CAAC,EAI1C,GAAI,EACF,GAAI,CAKG,MAJ8B,GAAkB,EAAQ,EAAe,CAC1E,SACA,YAAa,CAAC,EACf,CAAC,EAEA,EAAY,iBAAkB,gCAAgC,OAEzD,EAAK,CACZ,EAAY,iBAAmB,EAAc,QAAQ,CAKzD,GAAI,EAAU,CACZ,IAAM,EAAkB,MAAM,GAAiB,EAAQ,EAAU,CAAE,SAAQ,CAAC,CAC5E,IAAuC,CAAC,EAI1C,GAAI,EAAU,CACZ,IAAM,EAAkB,MAAM,GAAa,EAAQ,EAAU,CAAE,SAAQ,CAAC,CACxE,IAAuC,CAAC,EAI1C,IAAM,EAA2D,EAAE,CAEnE,GAAI,EAAW,CACb,GAAM,CAAE,UAAS,qBAAsB,MAAM,EAAc,EAAW,EAAQ,CAC5E,qBACA,eAAgB,GAChB,WACD,CAAC,CACF,GAAW,QAAS,GAAa,CAE/B,IAAM,EAAe,EAAS,yBAC9B,GAAI,EACF,GAAI,CACF,EAAkB,KAAK,CACrB,EAAkB,EAAS,OAC3B,GAA8B,EAAc,EAAS,MAAM,CAC5D,CAAC,OACK,EAAK,CACZ,EAAY,aAAe,EAAc,QAAS,EAAS,MAAM,CACjE,EAAa,MAAM,EAAO,IAAK,EAAc,QAAQ,CAAC,GAG1D,CACF,IAAuC,CAAC,EAI1C,GAAI,EAAkB,OAAS,EAAG,CAChC,IAAM,EAAsB,MAAM,GAAyB,EAAQ,CACjE,MAAO,EACP,SACD,CAAC,CACF,IAAuC,CAAC,EAI1C,GAAI,EAAsB,CACxB,IAAM,EAA4B,MAAM,GAAyB,EAAQ,EAAsB,CAC7F,SACD,CAAC,CACF,IAAuC,CAAC,EAO1C,MAAO,CACL,QAAS,CAAC,EACV,SACA,SAAU,EAAS,OAAS,EAAI,EAAW,IAAA,GAC5C,CC3jBH,SAAgB,EACd,EACA,GAAG,EACa,CAEhB,IAAM,EAAc,KAAK,MAAM,KAAK,UAAU,EAAK,CAAC,CAapD,OAZA,EAAO,QAAS,GAAU,CAExB,EAAW,EAAM,CAAC,SAAS,CAAC,EAAK,KAAuB,CAClD,EAAO,KAAS,IAAA,GAClB,EAAO,GAAO,EACL,MAAM,QAAQ,EAAM,CAC7B,EAAO,GAAO,CAAC,GAAG,EAAO,GAAM,GAAG,EAAM,CAExC,EAAO,GAAO,GAEhB,EACF,CACK"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{h as e}from"./deno-runtime-QqwBDKXX.mjs";import{dirname as t,relative as n}from"node:path";function r(r){let{command:i,cwd:a,manifestPath:o}=r,s=n(a,o)||`transcend-functions.yml`,c=r.discoveredManifestPaths.filter(e=>e!==o);return c.length===1?`Custom Function manifest does not exist at ${s}. Did you mean \`transcend custom-functions ${i} ${e(n(a,t(c[0]))||`.`)}\`?`:c.length>1?`Custom Function manifest does not exist at ${s}. Found manifests at: ${c.map(e=>n(a,e)).join(`, `)}. Pass a directory or --manifest explicitly.`:`Custom Function manifest does not exist at ${s}. Run \`transcend custom-functions init\` to create the default project.`}export{r as t};
|
|
2
|
-
//# sourceMappingURL=missing-manifest-BKj1j-jg.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"missing-manifest-BKj1j-jg.mjs","names":[],"sources":["../src/lib/custom-functions/missing-manifest.ts"],"sourcesContent":["import { dirname, relative } from 'node:path';\n\nimport { quoteCliArgument } from './paths.js';\n\n/** Command that can be redirected to a discovered Custom Function project. */\nexport type ManifestConsumerCommand = 'check' | 'new' | 'run';\n\n/**\n * Format actionable guidance when a requested Custom Function manifest is absent.\n *\n * @param options - Requested and discovered manifest paths\n * @returns Missing-manifest explanation\n */\nexport function formatMissingManifestMessage(options: {\n /** Command working directory. */\n cwd: string;\n /** Requested absolute manifest path. */\n manifestPath: string;\n /** Other absolute manifests discovered in the surrounding project. */\n discoveredManifestPaths: readonly string[];\n /** Command the user originally invoked. */\n command: ManifestConsumerCommand;\n}): string {\n const { command, cwd, manifestPath } = options;\n const requested = relative(cwd, manifestPath) || 'transcend-functions.yml';\n const discovered = options.discoveredManifestPaths.filter(\n (candidate) => candidate !== manifestPath,\n );\n if (discovered.length === 1) {\n const directory = relative(cwd, dirname(discovered[0]!)) || '.';\n return (\n `Custom Function manifest does not exist at ${requested}. ` +\n `Did you mean \\`transcend custom-functions ${command} ${quoteCliArgument(directory)}\\`?`\n );\n }\n if (discovered.length > 1) {\n const paths = discovered.map((path) => relative(cwd, path)).join(', ');\n return (\n `Custom Function manifest does not exist at ${requested}. ` +\n `Found manifests at: ${paths}. Pass a directory or --manifest explicitly.`\n );\n }\n return (\n `Custom Function manifest does not exist at ${requested}. ` +\n 'Run `transcend custom-functions init` to create the default project.'\n );\n}\n"],"mappings":"kGAaA,SAAgB,EAA6B,EASlC,CACT,GAAM,CAAE,UAAS,MAAK,gBAAiB,EACjC,EAAY,EAAS,EAAK,EAAa,EAAI,0BAC3C,EAAa,EAAQ,wBAAwB,OAChD,GAAc,IAAc,EAC9B,CAeD,OAdI,EAAW,SAAW,EAGtB,8CAA8C,EAAU,8CACX,EAAQ,GAAG,EAHxC,EAAS,EAAK,EAAQ,EAAW,GAAI,CAAC,EAAI,IAGyB,CAAC,KAGpF,EAAW,OAAS,EAGpB,8CAA8C,EAAU,wBAF5C,EAAW,IAAK,GAAS,EAAS,EAAK,EAAK,CAAC,CAAC,KAAK,KAGnC,CAAC,8CAI/B,8CAA8C,EAAU"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"printResult-esxW3HhT.mjs","names":[],"sources":["../src/commands/policy/helpers/buildPolicyEngineClient.ts","../src/commands/policy/helpers/formatPolicyEngineRequestError.ts","../src/commands/policy/helpers/printResult.ts"],"sourcesContent":["import got, { type Got } from 'got';\n\n/**\n * Creates a got client for Policy Engine REST endpoints on the monolith.\n *\n * The CLI appends `v1/...` paths to this base URL, so callers must NOT include\n * a trailing `/v1` (that would produce `/v1/v1/...` and an opaque `400`). We\n * detect and reject that mistake with a clear hint.\n *\n * @param transcendUrl - Transcend API base URL (without `/v1`)\n * @param auth - Transcend API key\n * @returns Configured got instance\n */\nexport function buildPolicyEngineClient(transcendUrl: string, auth: string): Got {\n const normalized = transcendUrl.replace(/\\/$/, '');\n if (/(^|\\/)v1$/i.test(normalized)) {\n throw new Error(\n `--transcend-url must not include a trailing \"/v1\" (the CLI appends it automatically). ` +\n `Got \"${transcendUrl}\"; use \"${normalized.replace(/\\/v1$/i, '')}\" instead.`,\n );\n }\n return got.extend({\n prefixUrl: normalized,\n headers: {\n Authorization: `Bearer ${auth}`,\n accept: 'application/json',\n },\n });\n}\n","import { PolicyEngineCliError } from './policyEngineCliError.js';\n\n/** Parsed JSON error body from a Policy Engine API response. */\ninterface PolicyEngineErrorBody {\n /** Human-readable error message */\n message?: string;\n}\n\n/** HTTP response metadata on a got HTTPError. */\ninterface PolicyEngineHttpResponse {\n /** HTTP status code */\n statusCode?: number;\n /** Response body (JSON or raw text) */\n body?: unknown;\n /** Response headers */\n headers?: Record<string, string | string[] | undefined>;\n}\n\n/** Shape of a got HTTPError with response metadata. */\ninterface PolicyEngineHttpError {\n /** HTTP response metadata */\n response?: PolicyEngineHttpResponse;\n}\n\nconst AUTH_ERROR_MESSAGE = `Authentication failed (401 Unauthorized).\n\nYour Transcend API key is missing, invalid, or does not have permission for this command.\n\nFix:\n- Set a valid API key: export TRANSCEND_API_KEY=<your-key>\n or pass --auth=<your-key>\n- Ensure the key has the required Policy Engine scopes (e.g. View/Manage/Activate Policy)\n- Confirm you are pointing at the correct environment (--transcend-url)`;\n\nconst NOT_FOUND_MESSAGE = `Resource not found (404 Not Found).\n\nThe requested policy bundle or version does not exist.\n\nFix:\n- Check the --bundle-name value\n- Run \\`transcend policy bundles\\` to see available bundles\n- Run \\`transcend policy versions --bundle-name=<name>\\` to see available versions`;\n\nconst PAYLOAD_TOO_LARGE_MESSAGE = `Policy bundle upload is too large (413 Payload Too Large).\n\nUploaded bundles must be at most 5 KiB compressed and 50 KiB decompressed gzip tarballs containing only manifest.json and .rego files.\n\nFix:\n- Remove unnecessary files from the bundle directory before publishing\n- Ensure the compiled .tar.gz stays within the upload limits`;\n\nconst NETWORK_ERROR_MESSAGE = `Connection to Transcend failed.\n\nThe Policy Engine API could not be reached.\n\nFix:\n- Check your network connection\n- Confirm --transcend-url points at the correct environment\n- Retry the command in a few moments`;\n\n/**\n * Extracts a human-readable message from a Policy Engine API error body.\n *\n * @param body - Raw or parsed response body\n * @returns API message when present\n */\nfunction extractApiMessage(body: unknown): string | undefined {\n if (typeof body === 'string') {\n try {\n const parsed = JSON.parse(body) as PolicyEngineErrorBody;\n return parsed.message;\n } catch {\n return body.length > 0 ? body : undefined;\n }\n }\n\n if (body && typeof body === 'object' && 'message' in body) {\n const message = (body as PolicyEngineErrorBody).message;\n if (typeof message === 'string' && message.length > 0) {\n return message;\n }\n }\n\n return undefined;\n}\n\n/**\n * Reads a single response header value.\n *\n * @param headers - Response headers\n * @param name - Header name\n * @returns Header value when present\n */\nfunction readResponseHeader(\n headers: Record<string, string | string[] | undefined> | undefined,\n name: string,\n): string | undefined {\n if (!headers) {\n return undefined;\n }\n\n const value = headers[name] ?? headers[name.toLowerCase()];\n if (Array.isArray(value)) {\n return value[0];\n }\n\n return value;\n}\n\n/**\n * Builds a rate-limit error message using response headers when available.\n *\n * @param apiMessage - Message from the response body, when present\n * @param headers - Response headers\n * @returns User-readable rate-limit text\n */\nfunction formatRateLimitMessage(\n apiMessage: string | undefined,\n headers: Record<string, string | string[] | undefined> | undefined,\n): string {\n if (apiMessage) {\n return apiMessage;\n }\n\n const retryAfter = readResponseHeader(headers, 'retry-after');\n const resetAt = readResponseHeader(headers, 'x-ratelimit-reset');\n\n let message = `Rate limit exceeded (429 Too Many Requests).\n\nFix:\n- Wait and retry the command`;\n\n if (retryAfter) {\n message += `\\n- Retry after ${retryAfter} second(s)`;\n } else if (resetAt) {\n message += `\\n- Retry after ${resetAt}`;\n }\n\n return message;\n}\n\n/**\n * Maps common HTTP status codes to actionable CLI messages.\n *\n * @param statusCode - HTTP status code\n * @param apiMessage - Message from the API response body, when present\n * @param headers - Response headers\n * @returns User-readable error text\n */\nfunction formatHttpStatusError(\n statusCode: number,\n apiMessage?: string,\n headers?: Record<string, string | string[] | undefined>,\n): string {\n switch (statusCode) {\n case 401:\n return AUTH_ERROR_MESSAGE;\n case 403:\n return (\n apiMessage ??\n 'Access was denied (403 Forbidden). If this persists, contact your Transcend admin.'\n );\n case 404:\n return NOT_FOUND_MESSAGE;\n case 400:\n return apiMessage ?? 'The request was invalid. Check your command flags and try again.';\n case 409:\n return apiMessage ?? 'The request conflicted with the current policy bundle state.';\n case 413:\n return apiMessage ?? PAYLOAD_TOO_LARGE_MESSAGE;\n case 429:\n return formatRateLimitMessage(apiMessage, headers);\n default:\n if (statusCode >= 500) {\n return `Transcend server error (${statusCode}). Try again in a few moments. If the problem persists, contact Transcend support.`;\n }\n return apiMessage ?? `Request failed with status code ${statusCode}.`;\n }\n}\n\n/**\n * Returns true when the error looks like a network or timeout failure.\n *\n * @param error - Thrown error\n * @returns Whether the error is likely a connectivity issue\n */\nfunction isNetworkError(error: unknown): boolean {\n if (!(error instanceof Error)) {\n return false;\n }\n\n const code = (error as NodeJS.ErrnoException).code;\n if (\n code === 'ECONNREFUSED' ||\n code === 'ENOTFOUND' ||\n code === 'ETIMEDOUT' ||\n code === 'ECONNRESET'\n ) {\n return true;\n }\n\n const message = error.message.toLowerCase();\n return (\n message.includes('network') ||\n message.includes('timeout') ||\n message.includes('econnrefused') ||\n message.includes('enotfound') ||\n message.includes('etimedout')\n );\n}\n\n/**\n * Extracts a useful error message from a failed Policy Engine HTTP request.\n *\n * @param error - The thrown error, typically a got `HTTPError`\n * @returns A message suitable for CLI output\n */\nexport function formatPolicyEngineRequestError(error: unknown): string {\n if (isNetworkError(error)) {\n return NETWORK_ERROR_MESSAGE;\n }\n\n if (error && typeof error === 'object' && 'response' in error) {\n const response = (error as PolicyEngineHttpError).response;\n const statusCode = response?.statusCode;\n const apiMessage = extractApiMessage(response?.body);\n\n if (statusCode) {\n return formatHttpStatusError(statusCode, apiMessage, response?.headers);\n }\n\n if (apiMessage) {\n return apiMessage;\n }\n }\n\n return error instanceof Error ? error.message : String(error);\n}\n\n/**\n * Rethrows a Policy Engine request failure with a user-readable message.\n *\n * @param error - The thrown error, typically a got `HTTPError`\n */\nexport function throwPolicyEngineRequestError(error: unknown): never {\n throw new PolicyEngineCliError(formatPolicyEngineRequestError(error), { cause: error });\n}\n\n/**\n * Awaits a Policy Engine HTTP request and maps failures to user-readable errors.\n *\n * @param request - Promise returned by a got client call (e.g. `.json()`)\n * @returns Parsed response body\n */\nexport async function policyEngineRequest<T>(request: Promise<T>): Promise<T> {\n try {\n return await request;\n } catch (error) {\n throwPolicyEngineRequestError(error);\n }\n}\n","/** Options for printing CLI command output. */\nexport interface PrintResultOptions {\n /** When true, print raw JSON */\n json: boolean;\n /** JSON-serializable payload */\n data: unknown;\n /** Table renderer used when json is false */\n renderTable?: () => string;\n}\n\n/**\n * Prints JSON or a human-readable table to stdout.\n *\n * @param stdout - Process stdout stream\n * @param options - Output options\n */\nexport function printResult(stdout: NodeJS.WriteStream, options: PrintResultOptions): void {\n if (options.json) {\n stdout.write(`${JSON.stringify(options.data, null, 2)}\\n`);\n return;\n }\n\n if (options.renderTable) {\n stdout.write(`${options.renderTable()}\\n`);\n }\n}\n"],"mappings":"2EAaA,SAAgB,EAAwB,EAAsB,EAAmB,CAC/E,IAAM,EAAa,EAAa,QAAQ,MAAO,GAAG,CAClD,GAAI,aAAa,KAAK,EAAW,CAC/B,MAAU,MACR,8FACU,EAAa,UAAU,EAAW,QAAQ,SAAU,GAAG,CAAC,YACnE,CAEH,OAAO,EAAI,OAAO,CAChB,UAAW,EACX,QAAS,CACP,cAAe,UAAU,IACzB,OAAQ,mBACT,CACF,CAAC,CCuCJ,SAAS,EAAkB,EAAmC,CAC5D,GAAI,OAAO,GAAS,SAClB,GAAI,CAEF,OADe,KAAK,MAAM,EACb,CAAC,aACR,CACN,OAAO,EAAK,OAAS,EAAI,EAAO,IAAA,GAIpC,GAAI,GAAQ,OAAO,GAAS,UAAY,YAAa,EAAM,CACzD,IAAM,EAAW,EAA+B,QAChD,GAAI,OAAO,GAAY,UAAY,EAAQ,OAAS,EAClD,OAAO,GAcb,SAAS,EACP,EACA,EACoB,CACpB,GAAI,CAAC,EACH,OAGF,IAAM,EAAQ,EAAQ,IAAS,EAAQ,EAAK,aAAa,EAKzD,OAJI,MAAM,QAAQ,EAAM,CACf,EAAM,GAGR,EAUT,SAAS,EACP,EACA,EACQ,CACR,GAAI,EACF,OAAO,EAGT,IAAM,EAAa,EAAmB,EAAS,cAAc,CACvD,EAAU,EAAmB,EAAS,oBAAoB,CAE5D,EAAU;;;8BAWd,OANI,EACF,GAAW,mBAAmB,EAAW,YAChC,IACT,GAAW,mBAAmB,KAGzB,EAWT,SAAS,EACP,EACA,EACA,EACQ,CACR,OAAQ,EAAR,CACE,IAAK,KACH,MAAO;;;;;;;;yEACT,IAAK,KACH,OACE,GACA,qFAEJ,IAAK,KACH,MAAO;;;;;;;oFACT,IAAK,KACH,OAAO,GAAc,mEACvB,IAAK,KACH,OAAO,GAAc,+DACvB,IAAK,KACH,OAAO,GAAc;;;;;;8DACvB,IAAK,KACH,OAAO,EAAuB,EAAY,EAAQ,CACpD,QAIE,OAHI,GAAc,IACT,2BAA2B,EAAW,oFAExC,GAAc,mCAAmC,EAAW,IAUzE,SAAS,EAAe,EAAyB,CAC/C,GAAI,EAAE,aAAiB,OACrB,MAAO,GAGT,IAAM,EAAQ,EAAgC,KAC9C,GACE,IAAS,gBACT,IAAS,aACT,IAAS,aACT,IAAS,aAET,MAAO,GAGT,IAAM,EAAU,EAAM,QAAQ,aAAa,CAC3C,OACE,EAAQ,SAAS,UAAU,EAC3B,EAAQ,SAAS,UAAU,EAC3B,EAAQ,SAAS,eAAe,EAChC,EAAQ,SAAS,YAAY,EAC7B,EAAQ,SAAS,YAAY,CAUjC,SAAgB,EAA+B,EAAwB,CACrE,GAAI,EAAe,EAAM,CACvB,MAAO;;;;;;;sCAGT,GAAI,GAAS,OAAO,GAAU,UAAY,aAAc,EAAO,CAC7D,IAAM,EAAY,EAAgC,SAC5C,EAAa,GAAU,WACvB,EAAa,EAAkB,GAAU,KAAK,CAEpD,GAAI,EACF,OAAO,EAAsB,EAAY,EAAY,GAAU,QAAQ,CAGzE,GAAI,EACF,OAAO,EAIX,OAAO,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,CAQ/D,SAAgB,EAA8B,EAAuB,CACnE,MAAM,IAAI,EAAqB,EAA+B,EAAM,CAAE,CAAE,MAAO,EAAO,CAAC,CASzF,eAAsB,EAAuB,EAAiC,CAC5E,GAAI,CACF,OAAO,MAAM,QACN,EAAO,CACd,EAA8B,EAAM,EClPxC,SAAgB,EAAY,EAA4B,EAAmC,CACzF,GAAI,EAAQ,KAAM,CAChB,EAAO,MAAM,GAAG,KAAK,UAAU,EAAQ,KAAM,KAAM,EAAE,CAAC,IAAI,CAC1D,OAGE,EAAQ,aACV,EAAO,MAAM,GAAG,EAAQ,aAAa,CAAC,IAAI"}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import{c as e}from"./manifest-DVuW_vvO.mjs";import{basename as t,dirname as n,join as r}from"node:path";const i={Deno:`deno`,Editor:`editor`,Skill:`skill`,Ci:`ci`};function a(e,t){try{return e.fs.lstatSync(t),!0}catch(e){if(e.code===`ENOENT`)return!1;throw e}}function o(e,t){if(!a(e,t))return{kind:`absent`,path:t};let n=e.fs.lstatSync(t);if(n.isSymbolicLink())return{kind:`link`,path:t,target:e.fs.readlinkSync(t)};if(!n.isFile())throw Error(`Cannot transactionally replace non-file path: ${t}`);return{kind:`file`,path:t,contents:e.fs.readFileSync(t,`utf8`),mode:n.mode}}function s(e,i,o,s){e.fs.mkdirSync(n(i),{recursive:!0});let c=r(n(i),`.${t(i)}.${e.process.pid}.${Date.now()}.tmp`);try{e.fs.writeFileSync(c,o,s===void 0?void 0:{mode:s&511}),e.fs.renameSync(c,i)}finally{a(e,c)&&e.fs.rmSync(c,{force:!0})}}function c(e,i,o,s){e.fs.mkdirSync(n(i),{recursive:!0});let c=r(n(i),`.${t(i)}.${e.process.pid}.${Date.now()}.tmp`);try{e.fs.writeFileSync(c,o,s===void 0?void 0:{mode:s&511}),e.fs.linkSync(c,i)}finally{a(e,c)&&e.fs.rmSync(c,{force:!0})}}function l(e,t){if(t.kind===`absent`){a(e,t.path)&&e.fs.rmSync(t.path,{recursive:!0,force:!0});return}if(e.fs.mkdirSync(n(t.path),{recursive:!0}),t.kind===`link`){a(e,t.path)&&e.fs.rmSync(t.path,{recursive:!0,force:!0}),e.fs.symlinkSync(t.target,t.path,`dir`);return}a(e,t.path)&&!e.fs.lstatSync(t.path).isFile()&&e.fs.rmSync(t.path,{recursive:!0,force:!0}),s(e,t.path,t.contents,t.mode)}function u(e,t){let n=a(e,t.path);if(t.before===null){if(n)throw Error(`File appeared after preview: ${t.path}`);return}if(!n||e.fs.readFileSync(t.path,`utf8`)!==t.before)throw Error(`File changed after preview: ${t.path}`);if(t.createOnly)throw Error(`Refusing to overwrite existing file: ${t.path}`)}function d(t,i,a){try{t.fs.symlinkSync(i.target,i.path,`dir`)}catch(o){let s=o.code;if(![`EPERM`,`EACCES`,`ENOTSUP`,`UNKNOWN`].includes(s??``))throw o;i.fallbackFiles.forEach(o=>{let s=r(i.path,o.path);e(t,a,s),t.fs.mkdirSync(n(s),{recursive:!0}),t.fs.writeFileSync(s,o.contents)})}}async function f(t,n){for(let r of n.changes)if(e(t,n.rootDirectory,r.path),r.kind===`file`)u(t,r);else if(a(t,r.path))throw Error(`Skill target appeared after preview: ${r.path}`);let r=[];try{for(let i of n.changes)if(e(t,n.rootDirectory,i.path),i.kind===`file`){u(t,i);let e=o(t,i.path);i.before===null?c(t,i.path,i.after,i.mode):s(t,i.path,i.after,i.mode),r.push(e)}else{if(a(t,i.path))throw Error(`Skill target appeared after preview: ${i.path}`);r.push({kind:`absent`,path:i.path}),d(t,i,n.rootDirectory)}}catch(e){let n=[];for(let e of r.reverse())try{l(t,e)}catch(t){n.push(`${e.path}: ${t.message}`)}throw n.length>0?Error(`${e.message}\nRollback also failed:\n${n.join(`
|
|
2
|
-
`)}`):e}}export{i as n,f as t};
|
|
3
|
-
//# sourceMappingURL=project-plan-apply-C2DfikVN.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"project-plan-apply-C2DfikVN.mjs","names":[],"sources":["../src/lib/custom-functions/scaffold-model.ts","../src/lib/scaffolding/project-plan-apply.ts"],"sourcesContent":["import type { ExistingProjectSkillDirectory } from '../scaffolding/agent-skill.js';\nimport type { ProjectPlan } from '../scaffolding/project-plan.js';\n\n/** Version of the stable scaffold/check JSON result contract. */\nexport const CUSTOM_FUNCTION_RESULT_VERSION = 1 as const;\n\n/** One repository setup capability. */\nexport const CustomFunctionSetupFeature = {\n /** Deno import map and strict compiler configuration. */\n Deno: 'deno',\n /** Target-scoped editor configuration. */\n Editor: 'editor',\n /** Coding-agent authoring skill. */\n Skill: 'skill',\n /** GitHub Actions validation workflow. */\n Ci: 'ci',\n} as const;\n\n/** One repository setup capability. */\nexport type CustomFunctionSetupFeature =\n (typeof CustomFunctionSetupFeature)[keyof typeof CustomFunctionSetupFeature];\n\n/** Repository and target state collected before planning. */\nexport interface CustomFunctionProjectState {\n /** Directory from which the CLI was invoked. */\n invocationDirectory: string;\n /** Absolute user-selected target directory. */\n targetDirectory: string;\n /** Root that owns repository-level editor and agent setup. */\n projectRoot: string;\n /** Directory relative to which manifest file references resolve. */\n manifestDirectory: string;\n /** Absolute manifest path. */\n manifestPath: string;\n /** Nearest repository root, when present. */\n repositoryRoot?: string;\n /** Existing Deno configuration path, or desired deno.json path. */\n denoConfigPath: string;\n /** Existing project-level skill directories; home state is deliberately ignored. */\n existingSkillDirectories: ExistingProjectSkillDirectory[];\n /** Whether the repository appears to use GitHub. */\n usesGithub: boolean;\n /** Case-preserving relative paths below the manifest directory. */\n relativePaths: string[];\n}\n\n/** A complete, validated scaffold plan. */\nexport interface CustomFunctionProjectPlan extends ProjectPlan {\n /** JSON contract version. */\n version: typeof CUSTOM_FUNCTION_RESULT_VERSION;\n /** Command that produced the plan. */\n command: 'init' | 'new';\n /** Absolute project target directory. */\n targetDirectory: string;\n /** Absolute manifest path. */\n manifestPath: string;\n /** Files inspected and deliberately left unchanged. */\n unchanged: string[];\n /** Non-fatal plan warnings. */\n warnings: string[];\n /** Commands shown after a successful apply. */\n nextSteps: string[];\n}\n","import { basename, dirname, join } from 'node:path';\n\nimport type { LocalContext } from '../../context.js';\nimport { assertPathPhysicallyContained } from './path-safety.js';\nimport type { PlannedFileChange, PlannedLinkChange, ProjectPlan } from './project-plan.js';\n\n/** Original state retained for rollback. */\ntype RollbackSnapshot =\n | {\n /** Snapshot kind. */\n kind: 'absent';\n /** Absolute path. */\n path: string;\n }\n | {\n /** Snapshot kind. */\n kind: 'file';\n /** Absolute path. */\n path: string;\n /** Original UTF-8 contents. */\n contents: string;\n /** Original mode. */\n mode: number;\n }\n | {\n /** Snapshot kind. */\n kind: 'link';\n /** Absolute path. */\n path: string;\n /** Original link target. */\n target: string;\n };\n\n/**\n * Check a path without following its final symbolic link.\n *\n * @param context - CLI context\n * @param path - Candidate path\n * @returns Whether any filesystem entry exists\n */\nfunction pathExists(context: LocalContext, path: string): boolean {\n try {\n context.fs.lstatSync(path);\n return true;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return false;\n }\n throw error;\n }\n}\n\n/**\n * Read one path for rollback.\n *\n * @param context - CLI context\n * @param path - Absolute path\n * @returns Original state\n */\nfunction snapshotPath(context: LocalContext, path: string): RollbackSnapshot {\n if (!pathExists(context, path)) {\n return { kind: 'absent', path };\n }\n const stat = context.fs.lstatSync(path);\n if (stat.isSymbolicLink()) {\n return { kind: 'link', path, target: context.fs.readlinkSync(path) };\n }\n if (!stat.isFile()) {\n throw new Error(`Cannot transactionally replace non-file path: ${path}`);\n }\n return {\n kind: 'file',\n path,\n contents: context.fs.readFileSync(path, 'utf8'),\n mode: stat.mode,\n };\n}\n\n/**\n * Write a regular file through a temporary sibling and rename.\n *\n * @param context - CLI context\n * @param path - Destination\n * @param contents - Desired contents\n * @param mode - Optional mode to preserve\n */\nfunction writeAtomic(context: LocalContext, path: string, contents: string, mode?: number): void {\n context.fs.mkdirSync(dirname(path), { recursive: true });\n const temporaryPath = join(\n dirname(path),\n `.${basename(path)}.${context.process.pid}.${Date.now()}.tmp`,\n );\n try {\n context.fs.writeFileSync(\n temporaryPath,\n contents,\n mode === undefined ? undefined : { mode: mode & 0o777 },\n );\n context.fs.renameSync(temporaryPath, path);\n } finally {\n if (pathExists(context, temporaryPath)) {\n context.fs.rmSync(temporaryPath, { force: true });\n }\n }\n}\n\n/**\n * Create a file atomically without replacing a destination that appeared.\n *\n * @param context - CLI context\n * @param path - Destination path\n * @param contents - UTF-8 contents\n * @param mode - Optional file mode\n */\nfunction writeAtomicCreateOnly(\n context: LocalContext,\n path: string,\n contents: string,\n mode?: number,\n): void {\n context.fs.mkdirSync(dirname(path), { recursive: true });\n const temporaryPath = join(\n dirname(path),\n `.${basename(path)}.${context.process.pid}.${Date.now()}.tmp`,\n );\n try {\n context.fs.writeFileSync(\n temporaryPath,\n contents,\n mode === undefined ? undefined : { mode: mode & 0o777 },\n );\n context.fs.linkSync(temporaryPath, path);\n } finally {\n if (pathExists(context, temporaryPath)) {\n context.fs.rmSync(temporaryPath, { force: true });\n }\n }\n}\n\n/**\n * Restore one path.\n *\n * @param context - CLI context\n * @param snapshot - Original state\n */\nfunction restoreSnapshot(context: LocalContext, snapshot: RollbackSnapshot): void {\n if (snapshot.kind === 'absent') {\n if (pathExists(context, snapshot.path)) {\n context.fs.rmSync(snapshot.path, { recursive: true, force: true });\n }\n return;\n }\n context.fs.mkdirSync(dirname(snapshot.path), { recursive: true });\n if (snapshot.kind === 'link') {\n if (pathExists(context, snapshot.path)) {\n context.fs.rmSync(snapshot.path, { recursive: true, force: true });\n }\n context.fs.symlinkSync(snapshot.target, snapshot.path, 'dir');\n return;\n }\n if (pathExists(context, snapshot.path) && !context.fs.lstatSync(snapshot.path).isFile()) {\n context.fs.rmSync(snapshot.path, { recursive: true, force: true });\n }\n writeAtomic(context, snapshot.path, snapshot.contents, snapshot.mode);\n}\n\n/**\n * Verify a planned regular-file precondition.\n *\n * @param context - CLI context\n * @param change - Planned file\n */\nfunction preflightFile(context: LocalContext, change: PlannedFileChange): void {\n const exists = pathExists(context, change.path);\n if (change.before === null) {\n if (exists) {\n throw new Error(`File appeared after preview: ${change.path}`);\n }\n return;\n }\n if (!exists || context.fs.readFileSync(change.path, 'utf8') !== change.before) {\n throw new Error(`File changed after preview: ${change.path}`);\n }\n if (change.createOnly) {\n throw new Error(`Refusing to overwrite existing file: ${change.path}`);\n }\n}\n\n/**\n * Install a project-local skill link, copying on platforms where links fail.\n *\n * @param context - CLI context\n * @param change - Planned link\n * @param rootDirectory - Approved mutation root\n */\nfunction applyLink(context: LocalContext, change: PlannedLinkChange, rootDirectory: string): void {\n try {\n context.fs.symlinkSync(change.target, change.path, 'dir');\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (!['EPERM', 'EACCES', 'ENOTSUP', 'UNKNOWN'].includes(code ?? '')) {\n throw error;\n }\n change.fallbackFiles.forEach((file) => {\n const path = join(change.path, file.path);\n assertPathPhysicallyContained(context, rootDirectory, path);\n context.fs.mkdirSync(dirname(path), { recursive: true });\n context.fs.writeFileSync(path, file.contents);\n });\n }\n}\n\n/**\n * Apply an approved project plan and restore source-controlled files on error.\n *\n * @param context - CLI context\n * @param plan - Approved plan\n */\nexport async function applyProjectPlan(context: LocalContext, plan: ProjectPlan): Promise<void> {\n for (const change of plan.changes) {\n assertPathPhysicallyContained(context, plan.rootDirectory, change.path);\n if (change.kind === 'file') {\n preflightFile(context, change);\n } else {\n if (pathExists(context, change.path)) {\n throw new Error(`Skill target appeared after preview: ${change.path}`);\n }\n }\n }\n\n const applied: RollbackSnapshot[] = [];\n try {\n for (const change of plan.changes) {\n assertPathPhysicallyContained(context, plan.rootDirectory, change.path);\n if (change.kind === 'file') {\n preflightFile(context, change);\n const snapshot = snapshotPath(context, change.path);\n if (change.before === null) {\n writeAtomicCreateOnly(context, change.path, change.after, change.mode);\n } else {\n writeAtomic(context, change.path, change.after, change.mode);\n }\n applied.push(snapshot);\n } else {\n if (pathExists(context, change.path)) {\n throw new Error(`Skill target appeared after preview: ${change.path}`);\n }\n applied.push({ kind: 'absent', path: change.path });\n applyLink(context, change, plan.rootDirectory);\n }\n }\n } catch (error) {\n const rollbackErrors: string[] = [];\n for (const snapshot of applied.reverse()) {\n try {\n restoreSnapshot(context, snapshot);\n } catch (rollbackError) {\n rollbackErrors.push(`${snapshot.path}: ${(rollbackError as Error).message}`);\n }\n }\n if (rollbackErrors.length > 0) {\n throw new Error(\n `${(error as Error).message}\\nRollback also failed:\\n${rollbackErrors.join('\\n')}`,\n );\n }\n throw error;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import{dt as e}from"./codecs-BsQFAFGT.mjs";import{readFileSync as t,writeFileSync as n}from"node:fs";import{decodeCodec as r}from"@transcend-io/type-utils";import i from"js-yaml";const a=/<<parameters\.(.+?)>>/,o=`parameters`;function s(e,t,n=``){let r=Object.entries(t).reduce((e,[t,n])=>e.split(`<<${o}.${t}>>`).join(n),e);if(a.test(r)){let[,e]=a.exec(r)||[];throw Error(`Found variable that was not set: ${e}.
|
|
2
|
-
Make sure you are passing all variables through the --variables=${e}:value-for-variable flag.
|
|
3
|
-
${n}`)}return r}function c(t,n={},a){let o=s(t,n,a?`Also check that there are no extra variables defined in your yaml: ${a}`:``);return r(e,i.load(o))}function l(t){return i.dump(r(e,t))}function u(e,n={}){return c(t(e,`utf-8`),n,e)}function d(e,t){n(e,l(t))}export{s as a,u as i,a as n,l as o,c as r,d as s,o as t};
|
|
4
|
-
//# sourceMappingURL=readTranscendYaml-STYnRzq-.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"readTranscendYaml-STYnRzq-.mjs","names":[],"sources":["../src/lib/readTranscendYaml.ts"],"sourcesContent":["import { readFileSync, writeFileSync } from 'node:fs';\n\nimport { decodeCodec, ObjByString } from '@transcend-io/type-utils';\nimport yaml from 'js-yaml';\n\nimport { TranscendInput } from '../codecs.js';\n\nexport const VARIABLE_PARAMETERS_REGEXP = /<<parameters\\.(.+?)>>/;\nexport const VARIABLE_PARAMETERS_NAME = 'parameters';\n\n/**\n * Function that replaces variables in a text file.\n * Throws error if there are variables that have not been replaced\n *\n * @param input - Input text\n * @param variables - Variables to replace\n * @param extraErrorMessage - Additional error message text\n * @returns Output text\n */\nexport function replaceVariablesInYaml(\n input: string,\n variables: ObjByString,\n extraErrorMessage = '',\n): string {\n const contents = Object.entries(variables).reduce(\n (replaced, [name, value]) =>\n replaced.split(`<<${VARIABLE_PARAMETERS_NAME}.${name}>>`).join(value),\n input,\n );\n\n // Throw error if unfilled parameters\n if (VARIABLE_PARAMETERS_REGEXP.test(contents)) {\n const [, name] = VARIABLE_PARAMETERS_REGEXP.exec(contents) || [];\n throw new Error(\n `Found variable that was not set: ${name}.\nMake sure you are passing all variables through the --variables=${name}:value-for-variable flag.\n${extraErrorMessage}`,\n );\n }\n\n return contents;\n}\n\n/**\n * Parse YAML contents and validate that their shape matches the codec API.\n *\n * @param contents - YAML contents.\n * @param variables - Variables to fill in\n * @param sourcePath - Optional source path included in parameter errors.\n * @returns The parsed contents, type-checked.\n */\nexport function parseTranscendYaml(\n contents: string,\n variables: ObjByString = {},\n sourcePath?: string,\n): TranscendInput {\n const replacedVariables = replaceVariablesInYaml(\n contents,\n variables,\n sourcePath\n ? `Also check that there are no extra variables defined in your yaml: ${sourcePath}`\n : '',\n );\n\n return decodeCodec(TranscendInput, yaml.load(replacedVariables));\n}\n\n/**\n * Serialize a validated Transcend configuration as YAML.\n *\n * @param input - The input to serialize.\n * @returns YAML contents.\n */\nexport function serializeTranscendYaml(input: TranscendInput): string {\n return yaml.dump(decodeCodec(TranscendInput, input));\n}\n\n/**\n * Read in the contents of a YAML file and validate that its shape matches the codec API.\n *\n * @param filePath - Path to YAML file.\n * @param variables - Variables to fill in.\n * @returns The parsed contents, type-checked.\n */\nexport function readTranscendYaml(filePath: string, variables: ObjByString = {}): TranscendInput {\n return parseTranscendYaml(readFileSync(filePath, 'utf-8'), variables, filePath);\n}\n\n/**\n * Write a Transcend configuration to disk.\n *\n * @param filePath - Path to YAML file.\n * @param input - The input to write out.\n */\nexport function writeTranscendYaml(filePath: string, input: TranscendInput): void {\n writeFileSync(filePath, serializeTranscendYaml(input));\n}\n"],"mappings":"mLAOA,MAAa,EAA6B,wBAC7B,EAA2B,aAWxC,SAAgB,EACd,EACA,EACA,EAAoB,GACZ,CACR,IAAM,EAAW,OAAO,QAAQ,EAAU,CAAC,QACxC,EAAU,CAAC,EAAM,KAChB,EAAS,MAAM,KAAK,EAAyB,GAAG,EAAK,IAAI,CAAC,KAAK,EAAM,CACvE,EACD,CAGD,GAAI,EAA2B,KAAK,EAAS,CAAE,CAC7C,GAAM,EAAG,GAAQ,EAA2B,KAAK,EAAS,EAAI,EAAE,CAChE,MAAU,MACR,oCAAoC,EAAK;kEACmB,EAAK;EACrE,IACG,CAGH,OAAO,EAWT,SAAgB,EACd,EACA,EAAyB,EAAE,CAC3B,EACgB,CAChB,IAAM,EAAoB,EACxB,EACA,EACA,EACI,sEAAsE,IACtE,GACL,CAED,OAAO,EAAY,EAAgB,EAAK,KAAK,EAAkB,CAAC,CASlE,SAAgB,EAAuB,EAA+B,CACpE,OAAO,EAAK,KAAK,EAAY,EAAgB,EAAM,CAAC,CAUtD,SAAgB,EAAkB,EAAkB,EAAyB,EAAE,CAAkB,CAC/F,OAAO,EAAmB,EAAa,EAAU,QAAQ,CAAE,EAAW,EAAS,CASjF,SAAgB,EAAmB,EAAkB,EAA6B,CAChF,EAAc,EAAU,EAAuB,EAAM,CAAC"}
|
package/dist/runOpa-CkKAwsvB.mjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{r as e}from"./constants-BMAOvdcA.mjs";import{spawn as t,spawnSync as n}from"node:child_process";function r(t=n){let r=t(`opa`,[`version`],{stdio:`ignore`});if(r.error||r.status!==0)throw Error(e)}function i(n,r={}){return new Promise((i,a)=>{let o=t(`opa`,n,{cwd:r.cwd,stdio:`inherit`});o.on(`error`,t=>{if(t.code===`ENOENT`){a(Error(e));return}a(t)}),o.on(`close`,e=>i(e??1))})}function a(n,r={}){return new Promise((i,a)=>{let o=t(`opa`,n,{cwd:r.cwd,stdio:[`ignore`,`pipe`,`pipe`]}),s=``,c=``;o.stdout?.on(`data`,e=>{s+=e.toString()}),o.stderr?.on(`data`,e=>{c+=e.toString()}),o.on(`error`,t=>{if(t.code===`ENOENT`){a(Error(e));return}a(t)}),o.on(`close`,e=>i({code:e??1,stdout:s,stderr:c}))})}export{i as n,r,a as t};
|
|
2
|
-
//# sourceMappingURL=runOpa-CkKAwsvB.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"runOpa-CkKAwsvB.mjs","names":[],"sources":["../src/commands/policy/helpers/assertOpaInstalled.ts","../src/commands/policy/helpers/runOpa.ts"],"sourcesContent":["import { spawnSync } from 'node:child_process';\n\nimport { OPA_INSTALL_HINT } from '../constants.js';\n\n/** Options used to suppress output from the availability check. */\ninterface OpaSpawnOptions {\n /** Discard child process output. */\n stdio: 'ignore';\n}\n\n/** Synchronously invokes a command for availability checks. */\ntype SpawnSync = (\n command: string,\n args: string[],\n options: OpaSpawnOptions,\n) => Pick<ReturnType<typeof spawnSync>, 'error' | 'status'>;\n\n/**\n * Ensures the `opa` binary is available on PATH.\n *\n * @param runSpawnSync - Child process runner dependency\n * @throws Error when `opa` is not installed\n */\nexport function assertOpaInstalled(runSpawnSync: SpawnSync = spawnSync): void {\n const result = runSpawnSync('opa', ['version'], { stdio: 'ignore' });\n if (result.error || result.status !== 0) {\n throw new Error(OPA_INSTALL_HINT);\n }\n}\n","import { spawn } from 'node:child_process';\n\nimport { OPA_INSTALL_HINT } from '../constants.js';\n\n/** Result of an OPA CLI invocation with captured output. */\nexport interface RunOpaCaptureResult {\n /** Child process exit code */\n code: number;\n /** Captured stdout */\n stdout: string;\n /** Captured stderr */\n stderr: string;\n}\n\n/**\n * Runs an OPA CLI command and streams stdout/stderr to the current process.\n *\n * @param args - Arguments passed to the `opa` binary\n * @param options - Optional working directory\n * @returns The child process exit code\n */\nexport function runOpa(args: string[], options: { cwd?: string } = {}): Promise<number> {\n return new Promise<number>((resolve, reject) => {\n const child = spawn('opa', args, {\n cwd: options.cwd,\n stdio: 'inherit',\n });\n\n child.on('error', (err) => {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n reject(new Error(OPA_INSTALL_HINT));\n return;\n }\n reject(err);\n });\n child.on('close', (code) => resolve(code ?? 1));\n });\n}\n\n/**\n * Runs an OPA CLI command and captures stdout/stderr.\n *\n * @param args - Arguments passed to the `opa` binary\n * @param options - Optional working directory\n * @returns Exit code and captured output\n */\nexport function runOPACapture(\n args: string[],\n options: { cwd?: string } = {},\n): Promise<RunOpaCaptureResult> {\n return new Promise<RunOpaCaptureResult>((resolve, reject) => {\n const child = spawn('opa', args, {\n cwd: options.cwd,\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n\n let stdout = '';\n let stderr = '';\n\n child.stdout?.on('data', (chunk: Buffer) => {\n stdout += chunk.toString();\n });\n child.stderr?.on('data', (chunk: Buffer) => {\n stderr += chunk.toString();\n });\n\n child.on('error', (err) => {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n reject(new Error(OPA_INSTALL_HINT));\n return;\n }\n reject(err);\n });\n child.on('close', (code) => resolve({ code: code ?? 1, stdout, stderr }));\n });\n}\n"],"mappings":"uGAuBA,SAAgB,EAAmB,EAA0B,EAAiB,CAC5E,IAAM,EAAS,EAAa,MAAO,CAAC,UAAU,CAAE,CAAE,MAAO,SAAU,CAAC,CACpE,GAAI,EAAO,OAAS,EAAO,SAAW,EACpC,MAAU,MAAM,EAAiB,CCLrC,SAAgB,EAAO,EAAgB,EAA4B,EAAE,CAAmB,CACtF,OAAO,IAAI,SAAiB,EAAS,IAAW,CAC9C,IAAM,EAAQ,EAAM,MAAO,EAAM,CAC/B,IAAK,EAAQ,IACb,MAAO,UACR,CAAC,CAEF,EAAM,GAAG,QAAU,GAAQ,CACzB,GAAK,EAA8B,OAAS,SAAU,CACpD,EAAW,MAAM,EAAiB,CAAC,CACnC,OAEF,EAAO,EAAI,EACX,CACF,EAAM,GAAG,QAAU,GAAS,EAAQ,GAAQ,EAAE,CAAC,EAC/C,CAUJ,SAAgB,EACd,EACA,EAA4B,EAAE,CACA,CAC9B,OAAO,IAAI,SAA8B,EAAS,IAAW,CAC3D,IAAM,EAAQ,EAAM,MAAO,EAAM,CAC/B,IAAK,EAAQ,IACb,MAAO,CAAC,SAAU,OAAQ,OAAO,CAClC,CAAC,CAEE,EAAS,GACT,EAAS,GAEb,EAAM,QAAQ,GAAG,OAAS,GAAkB,CAC1C,GAAU,EAAM,UAAU,EAC1B,CACF,EAAM,QAAQ,GAAG,OAAS,GAAkB,CAC1C,GAAU,EAAM,UAAU,EAC1B,CAEF,EAAM,GAAG,QAAU,GAAQ,CACzB,GAAK,EAA8B,OAAS,SAAU,CACpD,EAAW,MAAM,EAAiB,CAAC,CACnC,OAEF,EAAO,EAAI,EACX,CACF,EAAM,GAAG,QAAU,GAAS,EAAQ,CAAE,KAAM,GAAQ,EAAG,SAAQ,SAAQ,CAAC,CAAC,EACzE"}
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import{n as e}from"./scaffold-templates-CsHM1y80.mjs";import{d as t,f as n,h as r,l as i,m as a,n as o,p as s,u as c}from"./deno-runtime-QqwBDKXX.mjs";import{r as l,t as u}from"./manifest-DVuW_vvO.mjs";import{n as d}from"./project-plan-apply-C2DfikVN.mjs";import{basename as f,dirname as p,isAbsolute as m,join as h,relative as g,resolve as _,sep as v}from"node:path";import y from"colors";import{createHash as b}from"node:crypto";import{createTwoFilesPatch as x}from"diff";import{applyEdits as S,createScanner as C,modify as w,parse as T}from"jsonc-parser";var E=`# Project setup and CI
|
|
2
|
-
|
|
3
|
-
## Initialize
|
|
4
|
-
|
|
5
|
-
Run:
|
|
6
|
-
|
|
7
|
-
\`\`\`sh
|
|
8
|
-
transcend custom-functions init
|
|
9
|
-
\`\`\`
|
|
10
|
-
|
|
11
|
-
The default target is \`transcend/custom-functions\`. Interactive setup offers:
|
|
12
|
-
|
|
13
|
-
- \`transcend-functions.yml\`
|
|
14
|
-
- strict, target-scoped Deno configuration and a check task
|
|
15
|
-
- target-scoped VS Code Deno settings and extension recommendation
|
|
16
|
-
- this Agent Skill
|
|
17
|
-
- credential-free GitHub Actions validation
|
|
18
|
-
|
|
19
|
-
Review the complete plan before applying it. Existing JSONC settings and comments should be preserved. Do not overwrite unrelated repository configuration.
|
|
20
|
-
|
|
21
|
-
## Deno
|
|
22
|
-
|
|
23
|
-
Local validation requires Deno 2 (2.4.5 recommended). The generated \`custom-functions:check\` Deno task delegates to the CLI so it runs the same manifest, export, type, lint, and format checks. A different Deno 2 version may produce a production-parity warning; other major versions are unsupported. If Deno is missing or unsupported, direct the developer to the official installation instructions; do not install or switch runtimes without permission.
|
|
24
|
-
|
|
25
|
-
## CI
|
|
26
|
-
|
|
27
|
-
The generated GitHub Actions workflow is a secure reference implementation: it uses read-only repository permissions, pinned actions, a tested Deno 2.4.5 version, a pinned Transcend CLI version, and no Transcend credentials.
|
|
28
|
-
|
|
29
|
-
Adapt it to existing repository conventions instead of creating a parallel CI system. For another CI provider, preserve this validation recipe:
|
|
30
|
-
|
|
31
|
-
1. Trigger when the Custom Function manifest, source, payloads, or Deno configuration changes.
|
|
32
|
-
2. Install Deno 2.
|
|
33
|
-
3. Install a pinned \`@transcend-io/cli\` version.
|
|
34
|
-
4. Run:
|
|
35
|
-
|
|
36
|
-
\`\`\`sh
|
|
37
|
-
transcend custom-functions check "<custom-function-directory>" \\
|
|
38
|
-
--manifest="<manifest-path>" \\
|
|
39
|
-
--noInteractive \\
|
|
40
|
-
--json
|
|
41
|
-
\`\`\`
|
|
42
|
-
|
|
43
|
-
Do not add deployment credentials to validation-only jobs.
|
|
44
|
-
`,ee='# Writing Custom Functions\n\n## Add a function\n\nInitialize the project first, then scaffold a function:\n\n```sh\ntranscend custom-functions new\n```\n\nChoose the smallest matching template:\n\n- `general` for a General Custom Function\n- `dsr-datapoint` for the DSR data-point handler\n- `dsr-enricher` for the DSR request enricher\n- `dsr-both` when both DSR exports are required\n\nInspect the generated source, manifest entry, and payloads before implementing. Keep the generated export shape unless the manifest and fixtures change with it.\n\n## Type contracts\n\nImport `CustomFunction` as a type from `@transcend-io/custom-function-types`:\n\n- General functions default-export a handler using `CustomFunction.GeneralArgument`.\n- DSR data-point functions default-export a handler using `CustomFunction.Argument`.\n- DSR request enrichers export `enricher` using `CustomFunction.EnricherArgument`.\n\nHandlers receive `payload`, `environment`, `sdk`, and `kv`. Use:\n\n- `payload` for trigger data\n- `environment` for configured values\n- `sdk` for Transcend and external HTTP calls\n- `kv` for small persistent strings\n\nCheck `response.ok` for every `sdk.fetch` call. Include the response status and useful response details in failures without exposing secrets.\n\n## Manifest and fixtures\n\n- Use `<<parameters.ENV_NAME>>` placeholders for secret values, matching each placeholder name to its environment key.\n- Add every external network destination to `allowed-hosts`. Transcend SDK routes do not require an allowed-host entry.\n- Set `allow-third-party-imports` only when the implementation needs undeclared third-party modules.\n- Keep each function self-contained in its entry source file. Local runtime imports are not deployed; remote and `npm:` imports follow `allow-third-party-imports`.\n- Keep fixtures minimal but realistic, with at least one case for every implemented export.\n- Match DSR fixtures to `DATA_POINT` and `REQUEST_ENRICHER`. Do not hardcode values such as the data silo identity that the push workflow supplies.\n\n## Run locally\n\nExercise every configured fixture and show `console.log` output:\n\n```sh\ntranscend custom-functions run "<custom-function-directory>" \\\n --function="<function-name>" \\\n --variables=TRANSCEND_API_KEY:placeholder\n```\n\nThe local simulator mirrors Deno permissions, payload preparation, export selection, timeouts, environment isolation, and KV limits. It starts KV empty for each fixture and simulates `sdk.fetch` with a logged HTTP 200 response without making a request. Pass every `<<parameters.name>>` value through `--variables="name:value"`. Native network calls are denied unless the user explicitly passes `--allowNetwork`; those real requests can have side effects. Treat the simulator as a fast development loop, not proof of production behavior.\n\n## Validate and deploy\n\nRun:\n\n```sh\ntranscend custom-functions check "<custom-function-directory>" \\\n --variables=TRANSCEND_API_KEY:placeholder\ntranscend custom-functions push \\\n --file="<custom-function-directory>/transcend-functions.yml" \\\n --auth="$TRANSCEND_API_KEY" \\\n --variables="TRANSCEND_API_KEY:$TRANSCEND_API_KEY" \\\n --dryRun\n```\n\nRun, check, and push require every manifest variable. Placeholder values are sufficient for local validation; pass real secrets only when they are needed for authenticated push tests or deployment. Fix every check failure before pushing. Keep a revision as a draft with `--promote=false`. After the first successful push, use `--updateManifest` to record assigned IDs for stable future matching.\n',D=`---
|
|
45
|
-
name: transcend-custom-functions
|
|
46
|
-
description: Sets up, implements, validates, and deploys Transcend Custom Functions. Use when working with transcend-functions.yml, General or DSR handlers, test payloads, Deno configuration, Custom Function CI, or transcend custom-functions CLI commands.
|
|
47
|
-
compatibility: Requires Deno 2.x (2.4.5 recommended) for local validation and the Transcend CLI.
|
|
48
|
-
---
|
|
49
|
-
|
|
50
|
-
# Transcend Custom Functions
|
|
51
|
-
|
|
52
|
-
Use the CLI for deterministic scaffolding and validation. Use this skill for the repository-specific implementation and integration decisions that remain.
|
|
53
|
-
|
|
54
|
-
## Workflow
|
|
55
|
-
|
|
56
|
-
1. Locate \`transcend-functions.yml\`. The default project is \`transcend/custom-functions\`.
|
|
57
|
-
2. For project setup, Deno, editor support, or CI, read [references/setup.md](references/setup.md).
|
|
58
|
-
3. For handlers, manifest entries, test payloads, validation, or deployment, read [references/writing-custom-functions.md](references/writing-custom-functions.md).
|
|
59
|
-
4. Follow existing repository conventions and preserve unrelated configuration.
|
|
60
|
-
5. Use \`transcend custom-functions run <custom-function-directory>\` while developing, then run \`transcend custom-functions check <custom-function-directory>\` before considering the work complete.
|
|
61
|
-
|
|
62
|
-
## Documentation
|
|
63
|
-
|
|
64
|
-
- Every Transcend CLI command and subcommand provides contextual help with \`transcend <command> --help\`.
|
|
65
|
-
- Use the [Transcend CLI README](https://github.com/transcend-io/tools/tree/main/packages/cli#readme) for command documentation and examples.
|
|
66
|
-
- Use the [Transcend documentation index](https://docs.transcend.io/llms.txt) to find current product documentation.
|
|
67
|
-
|
|
68
|
-
## Guardrails
|
|
69
|
-
|
|
70
|
-
- Never commit credentials. Keep secrets in parameter placeholders and the repository's secret store.
|
|
71
|
-
- Do not invent third-party API endpoints, authentication behavior, or field mappings. Inspect available documentation and existing code; ask for missing requirements.
|
|
72
|
-
- Keep source and test-payload paths relative to the manifest.
|
|
73
|
-
- Custom Functions run on Deno 2.4.5. Avoid Node-only APIs.
|
|
74
|
-
`;const O=`transcend-custom-functions`,k=[{path:`SKILL.md`,contents:D},{path:`references/setup.md`,contents:E},{path:`references/writing-custom-functions.md`,contents:ee}];function A(e){let t=e.hasSkill?`Use the \`${O}\` skill to`:`Ask your coding agent to`,r=`transcend custom-functions check ${n(e.targetDirectory,e.manifestPath)} --noInteractive`;return e.hasGithubWorkflow?`${t} review the Custom Function setup in \`${e.targetDirectory}\`, adapt the generated GitHub Actions workflow to this repository's conventions, and run \`${r}\`.`:`${t} review the Custom Function setup in \`${e.targetDirectory}\` and add equivalent CI for this repository: install Deno 2 and \`@transcend-io/cli@${e.cliVersion}\`, then run \`${r}\`.`}function j(e){let t=e.hasSkill?`Use the \`${O}\` skill to`:`Ask your coding agent to`,i=s(e.variableNames),a=`transcend custom-functions check ${n(e.targetDirectory,e.manifestPath)}${i}`,o=`transcend custom-functions run ${n(e.targetDirectory,e.manifestPath)} --function=${r(e.displayName)}${i}`;return`${t} implement \`${e.displayName}\` in \`${e.sourcePath}\`, replace the example fixtures with realistic cases, run \`${o}\` to exercise it locally, and finish with \`${a}\`.`}function M(e,t){return a(e,t)}function N(e,t){return t.kind===`link`?{kind:`link`,target:`${M(e,t.path)} -> ${t.target}`,description:t.description}:{kind:t.before===null?`create`:`merge`,target:M(e,t.path),description:t.description}}function te(e,t){return{version:e.version,command:e.command,applied:t.applied,dryRun:t.dryRun,targetDirectory:e.targetDirectory,manifestPath:e.manifestPath,changes:e.changes.map(e=>N(t.cwd,e)),warnings:e.warnings,nextSteps:e.nextSteps,aiHandoff:t.aiHandoff}}function ne(e,t){let n=[y.bold(`Custom Function plan`),` ${y.dim(`Target:`)} ${y.cyan(M(t,e.targetDirectory))}`,` ${y.dim(`Manifest:`)} ${y.cyan(M(t,e.manifestPath))}`,``];return e.changes.length===0?n.push(y.dim(`No changes needed.`)):(n.push(y.bold(`Changes`)),e.changes.forEach(e=>{let r=N(t,e),i={create:y.green(r.kind.padEnd(7)),merge:y.cyan(r.kind.padEnd(7)),link:y.magenta(r.kind.padEnd(7))}[r.kind];if(n.push(` ${i} ${r.target}`),e.kind===`file`&&e.before!==null){let r=M(t,e.path),i=x(r,r,e.before,e.after,``,``,{context:3});n.push(...i.trimEnd().split(`
|
|
75
|
-
`).map(e=>` ${e}`))}})),e.unchanged.length>0&&(n.push(``,y.bold(`Left unchanged`)),e.unchanged.forEach(e=>n.push(` ${y.dim(M(t,e))}`))),e.warnings.length>0&&(n.push(``,y.bold(y.yellow(`Warnings`))),e.warnings.forEach(e=>n.push(` ${y.yellow(e)}`))),`${n.join(`
|
|
76
|
-
`)}\n`}function re(e){let{snapshot:t,after:n,description:r,createOnly:i}=e;if(i&&t.contents!==null)throw Error(`Refusing to overwrite existing file: ${t.path}`);if(t.contents!==n)return{kind:`file`,path:t.path,before:t.contents,after:n,description:r,...t.mode===void 0?{}:{mode:t.mode},...i===void 0?{}:{createOnly:i}}}function P(e){return e.replace(/([!*?[\]\\])/gu,`\\$1`)}function ie(e){let t=e.match(/# managed-by: @transcend-io\/cli; content-sha256: ([a-f0-9]{64})\s*$/u);if(!t||t.index===void 0)return!1;let n=e.slice(0,t.index).trimEnd();return b(`sha256`).update(n).digest(`hex`)===t[1]}function ae(e){let{cliVersion:t,targetDirectory:n,manifestPath:r}=e,i=e.contentDirectory??n,a=i===`.`?``:`${P(i.replace(/\/+$/u,``))}/`,s=[`${a}functions/**`,`${a}test-payloads/**`,P(r),`${a}deno.json*`,...(e.watchedPaths??[]).map(P)].filter((e,t,n)=>n.indexOf(e)===t).map(e=>` - ${JSON.stringify(e)}`).join(`
|
|
77
|
-
`),c=`# Generated by transcend custom-functions init.
|
|
78
|
-
name: Transcend Custom Functions
|
|
79
|
-
|
|
80
|
-
on:
|
|
81
|
-
pull_request:
|
|
82
|
-
paths:
|
|
83
|
-
${s}
|
|
84
|
-
push:
|
|
85
|
-
paths:
|
|
86
|
-
${s}
|
|
87
|
-
|
|
88
|
-
permissions:
|
|
89
|
-
contents: read
|
|
90
|
-
|
|
91
|
-
jobs:
|
|
92
|
-
check:
|
|
93
|
-
runs-on: ubuntu-latest
|
|
94
|
-
steps:
|
|
95
|
-
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
|
|
96
|
-
- uses: denoland/setup-deno@22d081ff2d3a40755e97629de92e3bcbfa7cf2ed # v2.0.5
|
|
97
|
-
with:
|
|
98
|
-
deno-version: ${o}
|
|
99
|
-
- name: Install the Transcend CLI
|
|
100
|
-
run: npm install --global @transcend-io/cli@${t}
|
|
101
|
-
- name: Validate Custom Functions
|
|
102
|
-
env:
|
|
103
|
-
CUSTOM_FUNCTION_DIRECTORY: ${JSON.stringify(n)}
|
|
104
|
-
CUSTOM_FUNCTION_MANIFEST: ${JSON.stringify(r)}
|
|
105
|
-
run: >-
|
|
106
|
-
transcend custom-functions check "$CUSTOM_FUNCTION_DIRECTORY"
|
|
107
|
-
--manifest="$CUSTOM_FUNCTION_MANIFEST"
|
|
108
|
-
--variables=TRANSCEND_API_KEY:placeholder
|
|
109
|
-
--noInteractive
|
|
110
|
-
--json
|
|
111
|
-
`,l=b(`sha256`).update(c.trimEnd()).digest(`hex`);return`${c.trimEnd()}\n\n# managed-by: @transcend-io/cli; content-sha256: ${l}\n`}const F={CloseBraceToken:2,CloseBracketToken:4,LineCommentTrivia:12,BlockCommentTrivia:13,LineBreakTrivia:14,Trivia:15,EOF:17};function I(e,t){let n=[],r=T(e,n,{allowTrailingComma:!0,disallowComments:!1});if(n.length>0||typeof r!=`object`||!r||Array.isArray(r))throw Error(`Cannot safely merge ${t}; fix its JSONC syntax or apply the patch manually.`);return r}function L(e){let t=e.match(/\n([ \t]+)"/)?.[1]??` `;return{tabSize:t.includes(` `)?1:t.length,insertSpaces:!t.includes(` `),eol:e.includes(`\r
|
|
112
|
-
`)?`\r
|
|
113
|
-
`:`
|
|
114
|
-
`}}function R(e){let t=C(e,!1),n=[],r=t.scan();for(;r!==F.EOF;)(r===F.LineCommentTrivia||r===F.BlockCommentTrivia)&&n.push(e.slice(t.getTokenOffset(),t.getTokenOffset()+t.getTokenLength())),r=t.scan();return n}function z(e){let t=C(e,!1),n=-1,r=t.scan();for(;r!==F.EOF;){if(r===F.LineCommentTrivia){let e=n===t.getTokenStartLine(),i=t.scan();for(;i===F.Trivia||i===F.LineBreakTrivia||i===F.LineCommentTrivia||i===F.BlockCommentTrivia;)i=t.scan();if(e&&(i===F.CloseBraceToken||i===F.CloseBracketToken))return!0;r=i;continue}r!==F.Trivia&&r!==F.LineBreakTrivia&&r!==F.BlockCommentTrivia&&(n=t.getTokenStartLine()),r=t.scan()}return!1}function B(e,t,n){let r=e??`{}
|
|
115
|
-
`;if(I(r,n),e!==null&&z(e))throw Error(`Cannot prove comment-preserving edits for ${n}; apply the displayed patch manually.`);let i=R(r),a=L(r);t.forEach(({path:e,value:t})=>{r=S(r,w(r,e,t,{formattingOptions:{...a,insertFinalNewline:!0,keepLines:!0}}))});let o=R(r);if(i.length!==o.length||i.some((e,t)=>o[t]!==e))throw Error(`A comment would move or disappear in ${n}; apply the patch manually.`);return I(r,n),r.endsWith(a.eol)?r:`${r}${a.eol}`}function V(e,t){let n=Array.isArray(e)?e.filter(e=>typeof e==`string`):[];return[...n,...t.filter(e=>!n.includes(e))]}function H(e,t,r=`transcend-functions.yml`,i={}){let a=I(e??`{}
|
|
116
|
-
`,`Deno configuration`),o=a.compilerOptions&&typeof a.compilerOptions==`object`&&!Array.isArray(a.compilerOptions)?a.compilerOptions:{},s=a.lint&&typeof a.lint==`object`&&!Array.isArray(a.lint)?a.lint:{},c=a.fmt&&typeof a.fmt==`object`&&!Array.isArray(a.fmt)?a.fmt:{},l=a.tasks&&typeof a.tasks==`object`&&!Array.isArray(a.tasks)?a.tasks:{},u=`custom-functions:check`,d=`transcend custom-functions check ${n(`.`,r)} --noInteractive`,f=`transcend custom-functions check ${n(`.`,r)} --variables=TRANSCEND_API_KEY:placeholder --noInteractive`;if(l[u]!==void 0&&l[u]!==`deno check functions/**/*.ts && deno lint functions/ && deno fmt --check functions/ test-payloads/`&&l[u]!==d&&l[u]!==f)throw Error(`Deno task "${u}" already has a different command; apply the patch manually.`);return B(e,[{path:[`imports`,`@transcend-io/custom-function-types`],value:`npm:@transcend-io/custom-function-types@${t}`},{path:[`compilerOptions`,`strict`],value:!0},{path:[`compilerOptions`,`lib`],value:V(o.lib,[`deno.ns`,`dom`,`dom.iterable`,`esnext`])},{path:[`lint`,`include`],value:V(s.include,[`functions/`,...i.sources??[]])},{path:[`fmt`,`include`],value:V(c.include,[`functions/`,`test-payloads/`,r,...i.sources??[],...i.payloads??[]])},{path:[`fmt`,`singleQuote`],value:!0},{path:[`fmt`,`lineWidth`],value:100},{path:[`tasks`,u],value:f}],`Deno configuration`)}function U(e,t,n){let r=I(e??`{}
|
|
117
|
-
`,`editor settings`),i=g(t,n).split(v).join(`/`)||`.`;return B(e,[{path:[`deno.enable`],value:!0},{path:[`deno.enablePaths`],value:V(r[`deno.enablePaths`],[i])}],`editor settings`)}function W(e){return B(e,[{path:[`recommendations`],value:V(I(e??`{}
|
|
118
|
-
`,`editor extension recommendations`).recommendations,[`denoland.vscode-deno`])}],`editor extension recommendations`)}function G(e){let t=JSON.stringify(e)??``;return[...new Set(Array.from(t.matchAll(/<<parameters\.([^>]+)>>/gu),e=>e[1]))]}function K(e){return e.projectRoot}function q(e,n){let r=K(e),i=new Set([e.manifestPath]),a=new Set(n.features);if(a.has(d.Deno)&&i.add(e.denoConfigPath),a.has(d.Editor)&&(i.add(h(r,`.vscode`,`settings.json`)),i.add(h(r,`.vscode`,`extensions.json`))),a.has(d.Skill)){let n=t(e.existingSkillDirectories);k.forEach(({path:e})=>{i.add(h(r,n.canonical,O,e))}),n.aliases.forEach(e=>{let t=h(r,e,O);i.add(t),k.forEach(({path:e})=>{i.add(h(t,e))})}),e.existingSkillDirectories.forEach(({path:e})=>{k.forEach(({path:t})=>{i.add(h(r,e,O,t))})})}return a.has(d.Ci)&&i.add(h(r,`.github`,`workflows`,`transcend-custom-functions.yml`)),[...i].sort((e,t)=>e.localeCompare(t))}function oe(e,t){return[e.manifestPath,h(e.manifestDirectory,t.sourceFile.path),...t.payloadFiles.map(t=>h(e.manifestDirectory,t.path))].sort((e,t)=>e.localeCompare(t))}function J(e,t){let n=e.snapshots[t];if(!n)throw Error(`Missing preflight snapshot for ${t}`);return n}function Y(e,t){let n=J(e,t);if(n.kind===`directory`||n.kind===`link`)throw Error(`Expected a regular file or absent path: ${t}`);return n.kind===`file`?{path:t,contents:n.contents,mode:n.mode}:{path:t,contents:null}}function X(e,t){let n=g(e,t);if(n===`..`||n.startsWith(`..${v}`)||m(n))throw Error(`Refusing to modify path outside project root: ${t}`)}function Z(e,t){let n=K(e);X(e.targetDirectory,e.manifestPath),t.forEach(e=>X(n,e));let r=new Map(e.relativePaths.map(e=>[e.toLocaleLowerCase(`en-US`),e]));t.forEach(t=>{let n=g(e.manifestDirectory,t).split(v).join(`/`);if(n.startsWith(`../`))return;let i=n.split(`/`);for(let e=1;e<=i.length;e+=1){let t=i.slice(0,e).join(`/`),n=r.get(t.toLocaleLowerCase(`en-US`));if(n&&n!==t)throw Error(`Case-insensitive path collision: "${t}" conflicts with "${n}".`)}})}function Q(e,t,n){let r=re({snapshot:Y(t,n.path),after:n.contents,description:n.description,...n.createOnly===void 0?{}:{createOnly:n.createOnly}});r?e.changes.push(r):e.unchanged.push(n.path)}function se(e,n){let r=K(n.state),a=t(n.state.existingSkillDirectories),o=h(r,a.canonical,O),s=k.map(e=>({path:e.path,contents:i(e.contents,`@transcend-io/cli`)})),l=(t,r)=>{s.forEach(i=>{let a=h(t,i.path),o=Y(n,a);if(o.contents!==null&&o.contents!==i.contents&&!c(o.contents,`@transcend-io/cli`))throw Error(`Refusing to replace user-managed skill: ${a}. Apply the skill update manually.`);Q(e,n,{path:a,contents:i.contents,description:`${r}: ${i.path}`})})};l(o,`Install Custom Function skill file`),a.aliases.forEach(t=>{let i=h(r,t,O),a=J(n,i),c=g(p(i),o);if(a.kind===`link`&&a.target===c){e.unchanged.push(i);return}if(a.kind===`directory`){l(i,`Update Custom Function skill copy in ${t}`);return}if(a.kind!==`absent`)throw Error(`Refusing to replace unexpected skill target: ${i}`);let u={kind:`link`,path:i,target:c,fallbackFiles:s,description:`Expose the canonical skill in ${t}`};e.changes.push(u)}),n.state.existingSkillDirectories.map(({path:e})=>e).filter(e=>e!==a.canonical&&!a.aliases.includes(e)).forEach(t=>{let i=h(r,t,O),a=Y(n,h(i,`SKILL.md`));a.contents!==null&&c(a.contents,`@transcend-io/cli`)?l(i,`Update existing managed skill in ${t}`):a.contents?.includes(`managed-by: @transcend-io/cli`)&&(e.unchanged.push(h(i,`SKILL.md`)),e.warnings.push(`Existing customized managed skill was left unchanged: ${i}`))})}function ce(e,t){let{state:r}=e,i=n(r.targetDirectory,r.manifestPath,r.invocationDirectory),a={version:1,command:`init`,rootDirectory:K(r),targetDirectory:r.targetDirectory,manifestPath:r.manifestPath,changes:[],unchanged:[],warnings:[],nextSteps:[`transcend custom-functions new ${i}`,`transcend custom-functions check ${i}`]},o=Y(e,r.manifestPath),s=o.contents===null?void 0:l(o.contents);o.contents===null?Q(a,e,{path:r.manifestPath,contents:`# Custom Functions managed as code.
|
|
119
|
-
functions: []
|
|
120
|
-
`,description:`Create the Custom Function manifest`}):a.unchanged.push(r.manifestPath);let c=new Set(t.features);if(c.has(d.Deno)){let t=Y(e,r.denoConfigPath),n=(s?.functions??[]).map(({code:e})=>e).filter(e=>!e.includes(`<<parameters.`)),i=(s?.functions??[]).flatMap(e=>[...e[`test-payload`]?[e[`test-payload`]]:[],...(e[`test-payloads`]??[]).map(({payload:e})=>e)]).filter(e=>!e.includes(`<<parameters.`));Q(a,e,{path:r.denoConfigPath,contents:H(t.contents,e.contractVersion,f(r.manifestPath),{sources:n,payloads:i}),description:`Merge strict target-scoped Deno authoring configuration`})}let u=K(r);if(c.has(d.Editor)){let t=h(u,`.vscode`,`settings.json`),n=h(u,`.vscode`,`extensions.json`),i=Y(e,t),o=Y(e,n);Q(a,e,{path:t,contents:U(i.contents,u,r.targetDirectory),description:`Scope Deno language support to Custom Functions`}),Q(a,e,{path:n,contents:W(o.contents),description:`Recommend the Deno editor extension`})}if(c.has(d.Skill)&&se(a,e),c.has(d.Ci))if(!r.repositoryRoot||!r.usesGithub)a.warnings.push(`GitHub Actions setup was selected, but this target is not inside a detected GitHub repository.`);else{let t=h(r.repositoryRoot,`.github`,`workflows`,`transcend-custom-functions.yml`),n=g(r.repositoryRoot,r.targetDirectory).split(v).join(`/`)||`.`,i=g(r.repositoryRoot,r.manifestDirectory).split(v).join(`/`)||`.`,o=g(r.repositoryRoot,r.manifestPath).split(v).join(`/`),c=(s?.functions??[]).flatMap(e=>[e.code,...e[`test-payload`]?[e[`test-payload`]]:[],...(e[`test-payloads`]??[]).map(({payload:e})=>e)]).filter(e=>!e.includes(`<<parameters.`)).map(e=>g(r.repositoryRoot,_(r.manifestDirectory,e)).split(v).join(`/`)),l=ae({cliVersion:e.cliVersion,targetDirectory:n,contentDirectory:i,manifestPath:o,watchedPaths:c}),u=Y(e,t);u.contents===null?Q(a,e,{path:t,contents:l,description:`Add credential-free Custom Function checks`,createOnly:!0}):u.contents===l?a.unchanged.push(t):ie(u.contents)?Q(a,e,{path:t,contents:l,description:`Update managed Custom Function checks`}):(a.unchanged.push(t),a.warnings.push(`Existing GitHub Actions workflow was left unchanged: ${t}`))}return Z(r,a.changes.map(({path:e})=>e)),a}function le(e,t){let{state:i}=e,o=Y(e,i.manifestPath).contents;if(o===null)throw Error(`Custom Function manifest does not exist: ${i.manifestPath}`);let c=t.generated.sourceFile.path.split(v).join(`/`),d=i.relativePaths.find(e=>e.toLocaleLowerCase(`en-US`)===c.toLocaleLowerCase(`en-US`));if(d)throw Error(`Custom Function name "${t.generated.displayName}" maps to ${c}, which conflicts with existing path ${d}. Choose another name.`);let f=l(o).functions.find(e=>_(i.manifestDirectory,e.code)===_(i.manifestDirectory,c));if(f)throw Error(`Custom Function name "${t.generated.displayName}" maps to source used by "${f.name}". Choose another name.`);let p={version:1,command:`new`,rootDirectory:i.manifestDirectory,targetDirectory:i.targetDirectory,manifestPath:i.manifestPath,changes:[],unchanged:[],warnings:[],nextSteps:[]},m=u(o,t.generated.manifestEntry);Q(p,e,{path:i.manifestPath,contents:m,description:`Register ${t.generated.displayName} in the manifest`}),[t.generated.sourceFile,...t.generated.payloadFiles].forEach(n=>{Q(p,e,{path:h(i.manifestDirectory,n.path),contents:n.contents,description:n===t.generated.sourceFile?`Create ${t.generated.displayName} source`:`Create ${t.generated.displayName} test payload`,createOnly:!0})});let g=h(i.manifestDirectory,t.generated.sourceFile.path),y=n(i.targetDirectory,i.manifestPath,i.invocationDirectory),b=G(t.generated.manifestEntry),x=s(b);return p.nextSteps=[`Edit ${r(a(i.invocationDirectory,g))}`,`transcend custom-functions run ${y} --function=${r(t.generated.displayName)}${x}`,`transcend custom-functions check ${y}${x}`,`transcend custom-functions push --file=${r(a(i.invocationDirectory,i.manifestPath))} --dryRun${x}`],b.length>0&&p.warnings.push(`Supply ${b.join(`, `)} through --variables when running or pushing; never commit secret values.`),Z(i,p.changes.map(({path:e})=>e)),p}function $(t,n){return e(t,n)}export{G as a,M as c,j as d,O as f,q as i,ne as l,ce as n,$ as o,oe as r,te as s,le as t,A as u};
|
|
121
|
-
//# sourceMappingURL=scaffold-planning-DMACXSnX.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold-planning-DMACXSnX.mjs","names":["CUSTOM_FUNCTION_SKILL_MD","CUSTOM_FUNCTION_SETUP_REFERENCE_MD","CUSTOM_FUNCTION_WRITING_REFERENCE_MD","parse"],"sources":["../../../skills/transcend-custom-functions/references/setup.md","../../../skills/transcend-custom-functions/references/writing-custom-functions.md","../../../skills/transcend-custom-functions/SKILL.md","../src/lib/custom-functions/custom-function-skill.ts","../src/lib/custom-functions/ai-handoff.ts","../src/lib/custom-functions/scaffold-output.ts","../src/lib/scaffolding/project-plan.ts","../src/lib/custom-functions/scaffold-artifacts.ts","../src/lib/custom-functions/scaffold-config.ts","../src/lib/custom-functions/scaffold-planning.ts"],"sourcesContent":[null,null,null,"import CUSTOM_FUNCTION_SETUP_REFERENCE_MD from '../../../../../skills/transcend-custom-functions/references/setup.md';\nimport CUSTOM_FUNCTION_WRITING_REFERENCE_MD from '../../../../../skills/transcend-custom-functions/references/writing-custom-functions.md';\nimport CUSTOM_FUNCTION_SKILL_MD from '../../../../../skills/transcend-custom-functions/SKILL.md';\n\n/** Namespaced directory and frontmatter name for the installed Agent Skill. */\nexport const CUSTOM_FUNCTION_SKILL_NAME = 'transcend-custom-functions';\n\nexport {\n CUSTOM_FUNCTION_SETUP_REFERENCE_MD,\n CUSTOM_FUNCTION_SKILL_MD,\n CUSTOM_FUNCTION_WRITING_REFERENCE_MD,\n};\n\n/** One generated file in the installed Agent Skill. */\nexport interface CustomFunctionSkillFile {\n /** Path relative to the skill directory. */\n path: string;\n /** Complete Markdown contents. */\n contents: string;\n}\n\n/** Complete portable Agent Skill file set. */\nexport const CUSTOM_FUNCTION_SKILL_FILES: readonly CustomFunctionSkillFile[] = [\n { path: 'SKILL.md', contents: CUSTOM_FUNCTION_SKILL_MD },\n { path: 'references/setup.md', contents: CUSTOM_FUNCTION_SETUP_REFERENCE_MD },\n {\n path: 'references/writing-custom-functions.md',\n contents: CUSTOM_FUNCTION_WRITING_REFERENCE_MD,\n },\n];\n","import { CUSTOM_FUNCTION_SKILL_NAME } from './custom-function-skill.js';\nimport { SUPPORTED_DENO_MAJOR_VERSION } from './deno-runtime.js';\nimport {\n buildCustomFunctionProjectArguments,\n buildPlaceholderVariablesArgument,\n quoteCliArgument,\n} from './paths.js';\n\n/**\n * Build a compact AI handoff after project initialization.\n *\n * @param options - Generated setup context\n * @returns Copyable agent instruction\n */\nexport function buildInitAiHandoff(options: {\n /** Display path to the Custom Function project. */\n targetDirectory: string;\n /** Display path to the manifest. */\n manifestPath: string;\n /** Exact CLI version used by generated CI. */\n cliVersion: string;\n /** Whether the authoring skill was installed. */\n hasSkill: boolean;\n /** Whether a GitHub Actions workflow was generated. */\n hasGithubWorkflow: boolean;\n}): string {\n const prefix = options.hasSkill\n ? `Use the \\`${CUSTOM_FUNCTION_SKILL_NAME}\\` skill to`\n : 'Ask your coding agent to';\n const checkCommand = `transcend custom-functions check ${buildCustomFunctionProjectArguments(\n options.targetDirectory,\n options.manifestPath,\n )} --noInteractive`;\n if (options.hasGithubWorkflow) {\n return `${prefix} review the Custom Function setup in \\`${options.targetDirectory}\\`, adapt the generated GitHub Actions workflow to this repository's conventions, and run \\`${checkCommand}\\`.`;\n }\n return `${prefix} review the Custom Function setup in \\`${options.targetDirectory}\\` and add equivalent CI for this repository: install Deno ${SUPPORTED_DENO_MAJOR_VERSION} and \\`@transcend-io/cli@${options.cliVersion}\\`, then run \\`${checkCommand}\\`.`;\n}\n\n/**\n * Build a compact AI handoff after adding one function.\n *\n * @param options - Generated function context\n * @returns Copyable agent instruction\n */\nexport function buildNewFunctionAiHandoff(options: {\n /** Customer-visible function name. */\n displayName: string;\n /** Display path to the generated source. */\n sourcePath: string;\n /** Display path to the Custom Function project. */\n targetDirectory: string;\n /** Display path to the selected manifest. */\n manifestPath: string;\n /** Whether the authoring skill is expected in this project. */\n hasSkill: boolean;\n /** Manifest variables required by this function. */\n variableNames: readonly string[];\n}): string {\n const prefix = options.hasSkill\n ? `Use the \\`${CUSTOM_FUNCTION_SKILL_NAME}\\` skill to`\n : 'Ask your coding agent to';\n const variablesArgument = buildPlaceholderVariablesArgument(options.variableNames);\n const checkCommand = `transcend custom-functions check ${buildCustomFunctionProjectArguments(\n options.targetDirectory,\n options.manifestPath,\n )}${variablesArgument}`;\n const runCommand =\n `transcend custom-functions run ` +\n `${buildCustomFunctionProjectArguments(options.targetDirectory, options.manifestPath)} ` +\n `--function=${quoteCliArgument(options.displayName)}${variablesArgument}`;\n return `${prefix} implement \\`${options.displayName}\\` in \\`${options.sourcePath}\\`, replace the example fixtures with realistic cases, run \\`${runCommand}\\` to exercise it locally, and finish with \\`${checkCommand}\\`.`;\n}\n","import colors from 'colors';\nimport { createTwoFilesPatch } from 'diff';\n\nimport type { PlannedChange } from '../scaffolding/project-plan.js';\nimport { displayCliPath } from './paths.js';\nimport type { CustomFunctionProjectPlan } from './scaffold-model.js';\n\n/** Stable public description of one planned mutation. */\nexport interface PublicPlannedChange {\n /** Create, merge, or link. */\n kind: 'create' | 'merge' | 'link';\n /** Display path. */\n target: string;\n /** Human-readable reason. */\n description: string;\n}\n\n/** Stable JSON scaffold result. */\nexport interface CustomFunctionPlanResult {\n /** JSON contract version. */\n version: number;\n /** Command that produced the plan. */\n command: 'init' | 'new';\n /** Whether the plan was applied. */\n applied: boolean;\n /** Whether this was a dry run. */\n dryRun: boolean;\n /** Absolute target directory. */\n targetDirectory: string;\n /** Absolute manifest path. */\n manifestPath: string;\n /** Planned mutations without file contents. */\n changes: PublicPlannedChange[];\n /** Non-fatal warnings. */\n warnings: string[];\n /** Suggested next commands. */\n nextSteps: string[];\n /** Compact prompt for continuing with a coding agent. */\n aiHandoff: string;\n}\n\n/**\n * Make a path relative for terminal output.\n *\n * @param cwd - Working directory\n * @param path - Absolute path\n * @returns Portable display path\n */\nexport function displayPath(cwd: string, path: string): string {\n return displayCliPath(cwd, path);\n}\n\n/**\n * Convert an internal mutation to its stable public shape.\n *\n * @param cwd - Working directory\n * @param change - Internal mutation\n * @returns Public mutation\n */\nfunction publicChange(cwd: string, change: PlannedChange): PublicPlannedChange {\n if (change.kind === 'link') {\n return {\n kind: 'link',\n target: `${displayPath(cwd, change.path)} -> ${change.target}`,\n description: change.description,\n };\n }\n return {\n kind: change.before === null ? 'create' : 'merge',\n target: displayPath(cwd, change.path),\n description: change.description,\n };\n}\n\n/**\n * Build the stable machine-readable scaffold result.\n *\n * @param plan - Project plan\n * @param options - Apply state\n * @returns JSON result\n */\nexport function buildPlanResult(\n plan: CustomFunctionProjectPlan,\n options: {\n /** Whether the plan was applied. */\n applied: boolean;\n /** Whether the invocation was a dry run. */\n dryRun: boolean;\n /** Working directory for portable paths. */\n cwd: string;\n /** Compact prompt for continuing with a coding agent. */\n aiHandoff: string;\n },\n): CustomFunctionPlanResult {\n return {\n version: plan.version,\n command: plan.command,\n applied: options.applied,\n dryRun: options.dryRun,\n targetDirectory: plan.targetDirectory,\n manifestPath: plan.manifestPath,\n changes: plan.changes.map((change) => publicChange(options.cwd, change)),\n warnings: plan.warnings,\n nextSteps: plan.nextSteps,\n aiHandoff: options.aiHandoff,\n };\n}\n\n/**\n * Render a human-readable complete project plan.\n *\n * @param plan - Project plan\n * @param cwd - Working directory\n * @returns Preview text\n */\nexport function renderProjectPlan(plan: CustomFunctionProjectPlan, cwd: string): string {\n const lines = [\n colors.bold('Custom Function plan'),\n ` ${colors.dim('Target:')} ${colors.cyan(displayPath(cwd, plan.targetDirectory))}`,\n ` ${colors.dim('Manifest:')} ${colors.cyan(displayPath(cwd, plan.manifestPath))}`,\n '',\n ];\n if (plan.changes.length === 0) {\n lines.push(colors.dim('No changes needed.'));\n } else {\n lines.push(colors.bold('Changes'));\n plan.changes.forEach((change) => {\n const item = publicChange(cwd, change);\n const kind = {\n create: colors.green(item.kind.padEnd(7)),\n merge: colors.cyan(item.kind.padEnd(7)),\n link: colors.magenta(item.kind.padEnd(7)),\n }[item.kind];\n lines.push(` ${kind} ${item.target}`);\n if (change.kind === 'file' && change.before !== null) {\n const path = displayPath(cwd, change.path);\n const patch = createTwoFilesPatch(path, path, change.before, change.after, '', '', {\n context: 3,\n });\n lines.push(\n ...patch\n .trimEnd()\n .split('\\n')\n .map((line) => ` ${line}`),\n );\n }\n });\n }\n if (plan.unchanged.length > 0) {\n lines.push('', colors.bold('Left unchanged'));\n plan.unchanged.forEach((path) => lines.push(` ${colors.dim(displayPath(cwd, path))}`));\n }\n if (plan.warnings.length > 0) {\n lines.push('', colors.bold(colors.yellow('Warnings')));\n plan.warnings.forEach((warning) => lines.push(` ${colors.yellow(warning)}`));\n }\n return `${lines.join('\\n')}\\n`;\n}\n","/** A file observed while collecting project state. */\nexport interface ProjectFileSnapshot {\n /** Absolute path. */\n path: string;\n /** Existing UTF-8 contents, or null when absent. */\n contents: string | null;\n /** Existing file mode, when present. */\n mode?: number;\n}\n\n/** A planned regular-file create or update. */\nexport interface PlannedFileChange {\n /** Discriminator. */\n kind: 'file';\n /** Absolute destination path. */\n path: string;\n /** Existing contents expected immediately before apply. */\n before: string | null;\n /** Complete desired contents. */\n after: string;\n /** Human-readable reason. */\n description: string;\n /** Existing file mode to preserve. */\n mode?: number;\n /** Whether an existing destination must always be rejected. */\n createOnly?: boolean;\n}\n\n/** A planned project-local symbolic link with a copy fallback. */\nexport interface PlannedLinkChange {\n /** Discriminator. */\n kind: 'link';\n /** Absolute link path. */\n path: string;\n /** Relative link target. */\n target: string;\n /** Managed files to copy when links are unavailable. */\n fallbackFiles: {\n /** Destination relative to the link path. */\n path: string;\n /** Complete desired contents. */\n contents: string;\n }[];\n /** Human-readable reason. */\n description: string;\n}\n\n/** One staged project mutation. */\nexport type PlannedChange = PlannedFileChange | PlannedLinkChange;\n\n/** Minimal plan consumed by the transactional filesystem applicator. */\nexport interface ProjectPlan {\n /** Approved physical root for every planned mutation. */\n rootDirectory: string;\n /** Ordered staged mutations. */\n changes: PlannedChange[];\n}\n\n/**\n * Stage a file only when its desired content differs.\n *\n * @param input - File change input\n * @returns A file change, or undefined for a no-op\n */\nexport function planFileChange(input: {\n /** File snapshot. */\n snapshot: ProjectFileSnapshot;\n /** Desired contents. */\n after: string;\n /** Human-readable reason. */\n description: string;\n /** Refuse every existing file. */\n createOnly?: boolean;\n}): PlannedFileChange | undefined {\n const { snapshot, after, description, createOnly } = input;\n if (createOnly && snapshot.contents !== null) {\n throw new Error(`Refusing to overwrite existing file: ${snapshot.path}`);\n }\n if (snapshot.contents === after) {\n return undefined;\n }\n return {\n kind: 'file',\n path: snapshot.path,\n before: snapshot.contents,\n after,\n description,\n ...(snapshot.mode === undefined ? {} : { mode: snapshot.mode }),\n ...(createOnly === undefined ? {} : { createOnly }),\n };\n}\n","import { createHash } from 'node:crypto';\n\nimport { RECOMMENDED_DENO_VERSION } from './deno-runtime.js';\n\n/** Immutable actions/checkout v6 release commit. */\nconst ACTIONS_CHECKOUT_SHA = 'd23441a48e516b6c34aea4fa41551a30e30af803';\n\n/** Immutable denoland/setup-deno v2.0.5 release commit. */\nconst SETUP_DENO_SHA = '22d081ff2d3a40755e97629de92e3bcbfa7cf2ed';\n\n/**\n * Escape a repository path before embedding intentional GitHub glob syntax.\n *\n * @param path - Literal repository-relative path\n * @returns Path with GitHub glob metacharacters escaped\n */\nfunction escapeGithubPath(path: string): string {\n return path.replace(/([!*?[\\]\\\\])/gu, '\\\\$1');\n}\n\n/**\n * Check whether a generated workflow still matches its ownership digest.\n *\n * @param contents - Existing workflow\n * @returns Whether automatic replacement is safe\n */\nexport function isUnmodifiedCustomFunctionWorkflow(contents: string): boolean {\n const marker = contents.match(\n /# managed-by: @transcend-io\\/cli; content-sha256: ([a-f0-9]{64})\\s*$/u,\n );\n if (!marker || marker.index === undefined) {\n return false;\n }\n const body = contents.slice(0, marker.index).trimEnd();\n return createHash('sha256').update(body).digest('hex') === marker[1];\n}\n\n/**\n * Generate the conservative Custom Function GitHub Actions workflow.\n *\n * @param options - Workflow paths and pinned CLI version\n * @returns Workflow YAML\n */\nexport function generateGithubActionsWorkflow(options: {\n /** Exact released CLI version. */\n cliVersion: string;\n /** Target directory relative to the repository root. */\n targetDirectory: string;\n /** Manifest directory where generated source, payload, and Deno files live. */\n contentDirectory?: string;\n /** Manifest path relative to the repository root. */\n manifestPath: string;\n /** Additional manifest-referenced files that should trigger validation. */\n watchedPaths?: readonly string[];\n}): string {\n const { cliVersion, targetDirectory, manifestPath } = options;\n const contentDirectory = options.contentDirectory ?? targetDirectory;\n const pathPrefix =\n contentDirectory === '.' ? '' : `${escapeGithubPath(contentDirectory.replace(/\\/+$/u, ''))}/`;\n const watchedPaths = [\n `${pathPrefix}functions/**`,\n `${pathPrefix}test-payloads/**`,\n escapeGithubPath(manifestPath),\n `${pathPrefix}deno.json*`,\n ...(options.watchedPaths ?? []).map(escapeGithubPath),\n ].filter((path, index, paths) => paths.indexOf(path) === index);\n const pathFilters = watchedPaths.map((path) => ` - ${JSON.stringify(path)}`).join('\\n');\n const body = `# Generated by transcend custom-functions init.\nname: Transcend Custom Functions\n\non:\n pull_request:\n paths:\n${pathFilters}\n push:\n paths:\n${pathFilters}\n\npermissions:\n contents: read\n\njobs:\n check:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@${ACTIONS_CHECKOUT_SHA} # v6\n - uses: denoland/setup-deno@${SETUP_DENO_SHA} # v2.0.5\n with:\n deno-version: ${RECOMMENDED_DENO_VERSION}\n - name: Install the Transcend CLI\n run: npm install --global @transcend-io/cli@${cliVersion}\n - name: Validate Custom Functions\n env:\n CUSTOM_FUNCTION_DIRECTORY: ${JSON.stringify(targetDirectory)}\n CUSTOM_FUNCTION_MANIFEST: ${JSON.stringify(manifestPath)}\n run: >-\n transcend custom-functions check \"$CUSTOM_FUNCTION_DIRECTORY\"\n --manifest=\"$CUSTOM_FUNCTION_MANIFEST\"\n --variables=TRANSCEND_API_KEY:placeholder\n --noInteractive\n --json\n`;\n const digest = createHash('sha256').update(body.trimEnd()).digest('hex');\n return `${body.trimEnd()}\\n\\n# managed-by: @transcend-io/cli; content-sha256: ${digest}\\n`;\n}\n","import { relative, sep } from 'node:path';\n\nimport { applyEdits, createScanner, modify, parse, type ParseError } from 'jsonc-parser';\n\nimport { buildCustomFunctionProjectArguments } from './paths.js';\n\n/**\n * Runtime values of jsonc-parser's ambient const enum, repeated locally\n * because isolated modules cannot access that enum directly.\n */\nconst JSONC_SYNTAX_KIND = {\n /** Closing object delimiter. */\n CloseBraceToken: 2,\n /** Closing array delimiter. */\n CloseBracketToken: 4,\n /** Single-line comment. */\n LineCommentTrivia: 12,\n /** Block comment. */\n BlockCommentTrivia: 13,\n /** Line break. */\n LineBreakTrivia: 14,\n /** Whitespace. */\n Trivia: 15,\n /** End of input. */\n EOF: 17,\n} as const;\n\n/** One JSONC path update. */\ninterface JsoncUpdate {\n /** Object path. */\n path: (string | number)[];\n /** Desired value. */\n value: unknown;\n}\n\n/**\n * Parse JSONC and fail with a manual-patch-oriented error.\n *\n * @param contents - JSON or JSONC text\n * @param label - Configuration label\n * @returns Parsed value\n */\nfunction parseJsonc(contents: string, label: string): Record<string, unknown> {\n const errors: ParseError[] = [];\n const value = parse(contents, errors, {\n allowTrailingComma: true,\n disallowComments: false,\n }) as unknown;\n if (errors.length > 0 || value === null || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error(\n `Cannot safely merge ${label}; fix its JSONC syntax or apply the patch manually.`,\n );\n }\n return value as Record<string, unknown>;\n}\n\n/**\n * Infer formatting without reformatting existing content.\n *\n * @param contents - Existing JSONC\n * @returns Formatting settings\n */\nfunction inferFormatting(contents: string): {\n /** Number of spaces per indent. */\n tabSize: number;\n /** Whether indentation uses spaces. */\n insertSpaces: boolean;\n /** Existing line ending. */\n eol: string;\n} {\n const indent = contents.match(/\\n([ \\t]+)\"/)?.[1] ?? ' ';\n return {\n tabSize: indent.includes('\\t') ? 1 : indent.length,\n insertSpaces: !indent.includes('\\t'),\n eol: contents.includes('\\r\\n') ? '\\r\\n' : '\\n',\n };\n}\n\n/**\n * Capture comment text in order.\n *\n * @param contents - JSONC text\n * @returns Comments\n */\nfunction extractComments(contents: string): string[] {\n const scanner = createScanner(contents, false);\n const comments: string[] = [];\n let token = scanner.scan();\n while (token !== JSONC_SYNTAX_KIND.EOF) {\n if (\n token === JSONC_SYNTAX_KIND.LineCommentTrivia ||\n token === JSONC_SYNTAX_KIND.BlockCommentTrivia\n ) {\n comments.push(\n contents.slice(\n scanner.getTokenOffset(),\n scanner.getTokenOffset() + scanner.getTokenLength(),\n ),\n );\n }\n token = scanner.scan();\n }\n return comments;\n}\n\n/**\n * Detect the jsonc-parser insertion edge case that can reattach an inline\n * comment from the previous final property.\n *\n * @param contents - Existing JSONC text\n * @returns Whether a guarded manual patch is required\n */\nfunction hasTrailingPropertyComment(contents: string): boolean {\n const scanner = createScanner(contents, false);\n let previousSignificantLine = -1;\n let token = scanner.scan();\n while (token !== JSONC_SYNTAX_KIND.EOF) {\n if (token === JSONC_SYNTAX_KIND.LineCommentTrivia) {\n const hasInlineValue = previousSignificantLine === scanner.getTokenStartLine();\n let next = scanner.scan();\n while (\n next === JSONC_SYNTAX_KIND.Trivia ||\n next === JSONC_SYNTAX_KIND.LineBreakTrivia ||\n next === JSONC_SYNTAX_KIND.LineCommentTrivia ||\n next === JSONC_SYNTAX_KIND.BlockCommentTrivia\n ) {\n next = scanner.scan();\n }\n if (\n hasInlineValue &&\n (next === JSONC_SYNTAX_KIND.CloseBraceToken || next === JSONC_SYNTAX_KIND.CloseBracketToken)\n ) {\n return true;\n }\n token = next;\n continue;\n }\n if (\n token !== JSONC_SYNTAX_KIND.Trivia &&\n token !== JSONC_SYNTAX_KIND.LineBreakTrivia &&\n token !== JSONC_SYNTAX_KIND.BlockCommentTrivia\n ) {\n previousSignificantLine = scanner.getTokenStartLine();\n }\n token = scanner.scan();\n }\n return false;\n}\n\n/**\n * Apply surgical JSONC updates while retaining every existing comment.\n *\n * @param contents - Existing contents, or null for a new file\n * @param updates - Ordered updates\n * @param label - Configuration label\n * @returns Updated contents\n */\nexport function mergeJsonc(\n contents: string | null,\n updates: readonly JsoncUpdate[],\n label: string,\n): string {\n let next = contents ?? '{}\\n';\n parseJsonc(next, label);\n if (contents !== null && hasTrailingPropertyComment(contents)) {\n throw new Error(\n `Cannot prove comment-preserving edits for ${label}; apply the displayed patch manually.`,\n );\n }\n const originalComments = extractComments(next);\n const formattingOptions = inferFormatting(next);\n updates.forEach(({ path, value }) => {\n next = applyEdits(\n next,\n modify(next, path, value, {\n formattingOptions: {\n ...formattingOptions,\n insertFinalNewline: true,\n keepLines: true,\n },\n }),\n );\n });\n const finalComments = extractComments(next);\n if (\n originalComments.length !== finalComments.length ||\n originalComments.some((comment, index) => finalComments[index] !== comment)\n ) {\n throw new Error(`A comment would move or disappear in ${label}; apply the patch manually.`);\n }\n parseJsonc(next, label);\n return next.endsWith(formattingOptions.eol) ? next : `${next}${formattingOptions.eol}`;\n}\n\n/**\n * Merge unique string values without reordering existing entries.\n *\n * @param current - Existing value\n * @param additions - Values to append\n * @returns Merged strings\n */\nfunction mergeStringArray(current: unknown, additions: readonly string[]): string[] {\n const values = Array.isArray(current)\n ? current.filter((value): value is string => typeof value === 'string')\n : [];\n return [...values, ...additions.filter((value) => !values.includes(value))];\n}\n\n/**\n * Build target-scoped Deno authoring configuration.\n *\n * @param contents - Existing deno.json/jsonc contents\n * @param contractVersion - Exact authoring-contract version\n * @param manifestFileName - Manifest path relative to this Deno configuration\n * @param referencedPaths - Existing manifest-relative source and payload paths\n * @returns Merged configuration\n */\nexport function mergeDenoConfiguration(\n contents: string | null,\n contractVersion: string,\n manifestFileName = 'transcend-functions.yml',\n referencedPaths: {\n /** Existing source paths. */\n sources?: readonly string[];\n /** Existing payload paths. */\n payloads?: readonly string[];\n } = {},\n): string {\n const current = parseJsonc(contents ?? '{}\\n', 'Deno configuration');\n const compilerOptions =\n current.compilerOptions &&\n typeof current.compilerOptions === 'object' &&\n !Array.isArray(current.compilerOptions)\n ? (current.compilerOptions as Record<string, unknown>)\n : {};\n const lint =\n current.lint && typeof current.lint === 'object' && !Array.isArray(current.lint)\n ? (current.lint as Record<string, unknown>)\n : {};\n const fmt =\n current.fmt && typeof current.fmt === 'object' && !Array.isArray(current.fmt)\n ? (current.fmt as Record<string, unknown>)\n : {};\n const tasks =\n current.tasks && typeof current.tasks === 'object' && !Array.isArray(current.tasks)\n ? (current.tasks as Record<string, unknown>)\n : {};\n const taskName = 'custom-functions:check';\n const legacyTaskCommand =\n 'deno check functions/**/*.ts && deno lint functions/ && deno fmt --check functions/ test-payloads/';\n const previousTaskCommand = `transcend custom-functions check ${buildCustomFunctionProjectArguments(\n '.',\n manifestFileName,\n )} --noInteractive`;\n const taskCommand = `transcend custom-functions check ${buildCustomFunctionProjectArguments(\n '.',\n manifestFileName,\n )} --variables=TRANSCEND_API_KEY:placeholder --noInteractive`;\n if (\n tasks[taskName] !== undefined &&\n tasks[taskName] !== legacyTaskCommand &&\n tasks[taskName] !== previousTaskCommand &&\n tasks[taskName] !== taskCommand\n ) {\n throw new Error(\n `Deno task \"${taskName}\" already has a different command; apply the patch manually.`,\n );\n }\n const updates: JsoncUpdate[] = [\n {\n path: ['imports', '@transcend-io/custom-function-types'],\n value: `npm:@transcend-io/custom-function-types@${contractVersion}`,\n },\n { path: ['compilerOptions', 'strict'], value: true },\n {\n path: ['compilerOptions', 'lib'],\n value: mergeStringArray(compilerOptions.lib, ['deno.ns', 'dom', 'dom.iterable', 'esnext']),\n },\n {\n path: ['lint', 'include'],\n value: mergeStringArray(lint.include, ['functions/', ...(referencedPaths.sources ?? [])]),\n },\n {\n path: ['fmt', 'include'],\n value: mergeStringArray(fmt.include, [\n 'functions/',\n 'test-payloads/',\n manifestFileName,\n ...(referencedPaths.sources ?? []),\n ...(referencedPaths.payloads ?? []),\n ]),\n },\n { path: ['fmt', 'singleQuote'], value: true },\n { path: ['fmt', 'lineWidth'], value: 100 },\n { path: ['tasks', taskName], value: taskCommand },\n ];\n return mergeJsonc(contents, updates, 'Deno configuration');\n}\n\n/**\n * Merge VS Code-compatible Deno settings scoped to the target.\n *\n * @param contents - Existing settings JSONC\n * @param repositoryRoot - Repository root\n * @param targetDirectory - Custom Function project directory\n * @returns Merged settings\n */\nexport function mergeEditorSettings(\n contents: string | null,\n repositoryRoot: string,\n targetDirectory: string,\n): string {\n const current = parseJsonc(contents ?? '{}\\n', 'editor settings');\n const target = relative(repositoryRoot, targetDirectory).split(sep).join('/') || '.';\n return mergeJsonc(\n contents,\n [\n { path: ['deno.enable'], value: true },\n {\n path: ['deno.enablePaths'],\n value: mergeStringArray(current['deno.enablePaths'], [target]),\n },\n ],\n 'editor settings',\n );\n}\n\n/**\n * Merge the recommended Deno editor extension.\n *\n * @param contents - Existing extensions JSONC\n * @returns Merged extensions\n */\nexport function mergeEditorExtensions(contents: string | null): string {\n const current = parseJsonc(contents ?? '{}\\n', 'editor extension recommendations');\n return mergeJsonc(\n contents,\n [\n {\n path: ['recommendations'],\n value: mergeStringArray(current.recommendations, ['denoland.vscode-deno']),\n },\n ],\n 'editor extension recommendations',\n );\n}\n","import { basename, dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';\n\nimport {\n buildManagedAgentSkill,\n isUnmodifiedManagedAgentSkill,\n resolveAgentSkillDirectories,\n} from '../scaffolding/agent-skill.js';\nimport {\n planFileChange,\n type PlannedLinkChange,\n type ProjectFileSnapshot,\n} from '../scaffolding/project-plan.js';\nimport {\n CUSTOM_FUNCTION_SKILL_FILES,\n CUSTOM_FUNCTION_SKILL_NAME,\n} from './custom-function-skill.js';\nimport { insertCustomFunctionManifestEntry, parseCustomFunctionsManifest } from './manifest.js';\nimport {\n buildCustomFunctionProjectArguments,\n buildPlaceholderVariablesArgument,\n displayCliPath,\n quoteCliArgument,\n} from './paths.js';\nimport {\n generateGithubActionsWorkflow,\n isUnmodifiedCustomFunctionWorkflow,\n} from './scaffold-artifacts.js';\nimport {\n mergeDenoConfiguration,\n mergeEditorExtensions,\n mergeEditorSettings,\n} from './scaffold-config.js';\nimport {\n CUSTOM_FUNCTION_RESULT_VERSION,\n CustomFunctionSetupFeature,\n type CustomFunctionProjectPlan,\n type CustomFunctionProjectState,\n type CustomFunctionSetupFeature as CustomFunctionSetupFeatureType,\n} from './scaffold-model.js';\nimport {\n generateCustomFunctionTemplate,\n type GeneratedCustomFunctionTemplate,\n} from './scaffold-templates.js';\n\n/** Empty manifest used for first initialization. */\nexport const EMPTY_CUSTOM_FUNCTION_MANIFEST = `# Custom Functions managed as code.\nfunctions: []\n`;\n\n/** State of one potentially mutated path. */\nexport type PlanningPathSnapshot =\n | {\n /** Snapshot kind. */\n kind: 'absent';\n /** Absolute path. */\n path: string;\n }\n | {\n /** Snapshot kind. */\n kind: 'file';\n /** Absolute path. */\n path: string;\n /** UTF-8 contents. */\n contents: string;\n /** File mode. */\n mode: number;\n }\n | {\n /** Snapshot kind. */\n kind: 'link';\n /** Absolute path. */\n path: string;\n /** Link target. */\n target: string;\n }\n | {\n /** Snapshot kind. */\n kind: 'directory';\n /** Absolute path. */\n path: string;\n };\n\n/** In-memory input consumed by pure project planners. */\nexport interface CustomFunctionPlanningInput {\n /** Project discovery state. */\n state: CustomFunctionProjectState;\n /** Potential mutation paths keyed by absolute path. */\n snapshots: Readonly<Record<string, PlanningPathSnapshot>>;\n}\n\n/**\n * Find parameter placeholders in a generated manifest value.\n *\n * @param value - Generated manifest entry\n * @returns Unique parameter names in encounter order\n */\nexport function parameterNamesInManifestValue(value: unknown): string[] {\n const serialized = JSON.stringify(value) ?? '';\n return [\n ...new Set(Array.from(serialized.matchAll(/<<parameters\\.([^>]+)>>/gu), (match) => match[1]!)),\n ];\n}\n\n/** In-memory input required only by project initialization. */\nexport interface CustomFunctionInitPlanningInput extends CustomFunctionPlanningInput {\n /** Exact authoring contract version. */\n contractVersion: string;\n /** Exact CLI version. */\n cliVersion: string;\n}\n\n/** Options shared by init and implicit init. */\nexport interface InitPlanOptions {\n /** Selected setup features. */\n features: readonly CustomFunctionSetupFeatureType[];\n}\n\n/**\n * Determine the repository-owned base for optional setup.\n *\n * @param state - Discovery state\n * @returns Repository root or target\n */\nfunction setupRoot(state: CustomFunctionProjectState): string {\n return state.projectRoot;\n}\n\n/**\n * Enumerate all paths that could be included in a plan.\n *\n * @param state - Discovery state\n * @param options - Selected setup and optional scaffold\n * @returns Absolute candidate paths\n */\nexport function getInitPlanningCandidatePaths(\n state: CustomFunctionProjectState,\n options: {\n /** Selected setup features. */\n features: readonly CustomFunctionSetupFeatureType[];\n },\n): string[] {\n const root = setupRoot(state);\n const paths = new Set<string>([state.manifestPath]);\n const selected = new Set(options.features);\n if (selected.has(CustomFunctionSetupFeature.Deno)) {\n paths.add(state.denoConfigPath);\n }\n if (selected.has(CustomFunctionSetupFeature.Editor)) {\n paths.add(join(root, '.vscode', 'settings.json'));\n paths.add(join(root, '.vscode', 'extensions.json'));\n }\n if (selected.has(CustomFunctionSetupFeature.Skill)) {\n const directories = resolveAgentSkillDirectories(state.existingSkillDirectories);\n CUSTOM_FUNCTION_SKILL_FILES.forEach(({ path }) => {\n paths.add(join(root, directories.canonical, CUSTOM_FUNCTION_SKILL_NAME, path));\n });\n directories.aliases.forEach((directory) => {\n const aliasDirectory = join(root, directory, CUSTOM_FUNCTION_SKILL_NAME);\n paths.add(aliasDirectory);\n CUSTOM_FUNCTION_SKILL_FILES.forEach(({ path }) => {\n paths.add(join(aliasDirectory, path));\n });\n });\n state.existingSkillDirectories.forEach(({ path: directory }) => {\n CUSTOM_FUNCTION_SKILL_FILES.forEach(({ path }) => {\n paths.add(join(root, directory, CUSTOM_FUNCTION_SKILL_NAME, path));\n });\n });\n }\n if (selected.has(CustomFunctionSetupFeature.Ci)) {\n paths.add(join(root, '.github', 'workflows', 'transcend-custom-functions.yml'));\n }\n return [...paths].sort((left, right) => left.localeCompare(right));\n}\n\n/**\n * Enumerate paths touched when adding one function to an initialized project.\n *\n * @param state - Project discovery state\n * @param generated - Generated function files\n * @returns Absolute candidate paths\n */\nexport function getAddFunctionPlanningCandidatePaths(\n state: CustomFunctionProjectState,\n generated: GeneratedCustomFunctionTemplate,\n): string[] {\n return [\n state.manifestPath,\n join(state.manifestDirectory, generated.sourceFile.path),\n ...generated.payloadFiles.map((file) => join(state.manifestDirectory, file.path)),\n ].sort((left, right) => left.localeCompare(right));\n}\n\n/**\n * Read a required candidate snapshot.\n *\n * @param input - Planning input\n * @param path - Absolute path\n * @returns Snapshot\n */\nfunction snapshotAt(input: CustomFunctionPlanningInput, path: string): PlanningPathSnapshot {\n const snapshot = input.snapshots[path];\n if (!snapshot) {\n throw new Error(`Missing preflight snapshot for ${path}`);\n }\n return snapshot;\n}\n\n/**\n * Adapt a generic snapshot to a regular-file plan input.\n *\n * @param input - Planning input\n * @param path - Absolute file path\n * @returns File snapshot\n */\nfunction fileSnapshotAt(input: CustomFunctionPlanningInput, path: string): ProjectFileSnapshot {\n const snapshot = snapshotAt(input, path);\n if (snapshot.kind === 'directory' || snapshot.kind === 'link') {\n throw new Error(`Expected a regular file or absent path: ${path}`);\n }\n return snapshot.kind === 'file'\n ? { path, contents: snapshot.contents, mode: snapshot.mode }\n : { path, contents: null };\n}\n\n/**\n * Ensure a mutation stays below an approved project root.\n *\n * @param root - Approved root\n * @param path - Candidate path\n */\nfunction assertContained(root: string, path: string): void {\n const child = relative(root, path);\n if (child === '..' || child.startsWith(`..${sep}`) || isAbsolute(child)) {\n throw new Error(`Refusing to modify path outside project root: ${path}`);\n }\n}\n\n/**\n * Validate roots and case-insensitive destinations.\n *\n * @param state - Discovery state\n * @param paths - Planned destination paths\n */\nfunction validatePlanDestinations(\n state: CustomFunctionProjectState,\n paths: readonly string[],\n): void {\n const root = setupRoot(state);\n assertContained(state.targetDirectory, state.manifestPath);\n paths.forEach((path) => assertContained(root, path));\n const existing = new Map(\n state.relativePaths.map((path) => [path.toLocaleLowerCase('en-US'), path]),\n );\n paths.forEach((path) => {\n const relativePath = relative(state.manifestDirectory, path).split(sep).join('/');\n if (relativePath.startsWith('../')) {\n return;\n }\n const components = relativePath.split('/');\n for (let length = 1; length <= components.length; length += 1) {\n const candidate = components.slice(0, length).join('/');\n const collision = existing.get(candidate.toLocaleLowerCase('en-US'));\n if (collision && collision !== candidate) {\n throw new Error(\n `Case-insensitive path collision: \"${candidate}\" conflicts with \"${collision}\".`,\n );\n }\n }\n });\n}\n\n/**\n * Add or classify a regular-file mutation.\n *\n * @param plan - Plan being assembled\n * @param input - Planning input\n * @param options - Desired file\n */\nfunction addFileChange(\n plan: CustomFunctionProjectPlan,\n input: CustomFunctionPlanningInput,\n options: {\n /** Absolute path. */\n path: string;\n /** Complete desired contents. */\n contents: string;\n /** Human-readable reason. */\n description: string;\n /** Refuse existing contents. */\n createOnly?: boolean;\n },\n): void {\n const change = planFileChange({\n snapshot: fileSnapshotAt(input, options.path),\n after: options.contents,\n description: options.description,\n ...(options.createOnly === undefined ? {} : { createOnly: options.createOnly }),\n });\n if (change) {\n plan.changes.push(change);\n } else {\n plan.unchanged.push(options.path);\n }\n}\n\n/**\n * Plan one direct skill installation and links into other existing directories.\n *\n * @param plan - Plan being assembled\n * @param input - Planning input\n */\nfunction planSkill(plan: CustomFunctionProjectPlan, input: CustomFunctionPlanningInput): void {\n const root = setupRoot(input.state);\n const directories = resolveAgentSkillDirectories(input.state.existingSkillDirectories);\n const canonicalDirectory = join(root, directories.canonical, CUSTOM_FUNCTION_SKILL_NAME);\n const managedFiles = CUSTOM_FUNCTION_SKILL_FILES.map((file) => ({\n path: file.path,\n contents: buildManagedAgentSkill(file.contents, '@transcend-io/cli'),\n }));\n const planManagedFiles = (directory: string, description: string): void => {\n managedFiles.forEach((file) => {\n const path = join(directory, file.path);\n const snapshot = fileSnapshotAt(input, path);\n if (\n snapshot.contents !== null &&\n snapshot.contents !== file.contents &&\n !isUnmodifiedManagedAgentSkill(snapshot.contents, '@transcend-io/cli')\n ) {\n throw new Error(\n `Refusing to replace user-managed skill: ${path}. Apply the skill update manually.`,\n );\n }\n addFileChange(plan, input, {\n path,\n contents: file.contents,\n description: `${description}: ${file.path}`,\n });\n });\n };\n planManagedFiles(canonicalDirectory, 'Install Custom Function skill file');\n\n directories.aliases.forEach((directory) => {\n const targetDirectory = join(root, directory, CUSTOM_FUNCTION_SKILL_NAME);\n const snapshot = snapshotAt(input, targetDirectory);\n const relativeTarget = relative(dirname(targetDirectory), canonicalDirectory);\n if (snapshot.kind === 'link' && snapshot.target === relativeTarget) {\n plan.unchanged.push(targetDirectory);\n return;\n }\n if (snapshot.kind === 'directory') {\n planManagedFiles(targetDirectory, `Update Custom Function skill copy in ${directory}`);\n return;\n }\n if (snapshot.kind !== 'absent') {\n throw new Error(`Refusing to replace unexpected skill target: ${targetDirectory}`);\n }\n const change: PlannedLinkChange = {\n kind: 'link',\n path: targetDirectory,\n target: relativeTarget,\n fallbackFiles: managedFiles,\n description: `Expose the canonical skill in ${directory}`,\n };\n plan.changes.push(change);\n });\n\n input.state.existingSkillDirectories\n .map(({ path }) => path)\n .filter(\n (directory) =>\n directory !== directories.canonical && !directories.aliases.includes(directory),\n )\n .forEach((directory) => {\n const existingDirectory = join(root, directory, CUSTOM_FUNCTION_SKILL_NAME);\n const skillSnapshot = fileSnapshotAt(input, join(existingDirectory, 'SKILL.md'));\n if (\n skillSnapshot.contents !== null &&\n isUnmodifiedManagedAgentSkill(skillSnapshot.contents, '@transcend-io/cli')\n ) {\n planManagedFiles(existingDirectory, `Update existing managed skill in ${directory}`);\n } else if (skillSnapshot.contents?.includes('managed-by: @transcend-io/cli')) {\n plan.unchanged.push(join(existingDirectory, 'SKILL.md'));\n plan.warnings.push(\n `Existing customized managed skill was left unchanged: ${existingDirectory}`,\n );\n }\n });\n}\n\n/**\n * Create the base plan and optional repository setup.\n *\n * @param input - Collected project state\n * @param options - Selected setup\n * @returns Validated project plan\n */\nexport function buildInitPlan(\n input: CustomFunctionInitPlanningInput,\n options: InitPlanOptions,\n): CustomFunctionProjectPlan {\n const { state } = input;\n const projectArguments = buildCustomFunctionProjectArguments(\n state.targetDirectory,\n state.manifestPath,\n state.invocationDirectory,\n );\n const plan: CustomFunctionProjectPlan = {\n version: CUSTOM_FUNCTION_RESULT_VERSION,\n command: 'init',\n rootDirectory: setupRoot(state),\n targetDirectory: state.targetDirectory,\n manifestPath: state.manifestPath,\n changes: [],\n unchanged: [],\n warnings: [],\n nextSteps: [\n `transcend custom-functions new ${projectArguments}`,\n `transcend custom-functions check ${projectArguments}`,\n ],\n };\n const manifestSnapshot = fileSnapshotAt(input, state.manifestPath);\n const existingManifest =\n manifestSnapshot.contents === null\n ? undefined\n : parseCustomFunctionsManifest(manifestSnapshot.contents);\n if (manifestSnapshot.contents === null) {\n addFileChange(plan, input, {\n path: state.manifestPath,\n contents: EMPTY_CUSTOM_FUNCTION_MANIFEST,\n description: 'Create the Custom Function manifest',\n });\n } else {\n plan.unchanged.push(state.manifestPath);\n }\n\n const selected = new Set(options.features);\n if (selected.has(CustomFunctionSetupFeature.Deno)) {\n const snapshot = fileSnapshotAt(input, state.denoConfigPath);\n const sourcePaths = (existingManifest?.functions ?? [])\n .map(({ code }) => code)\n .filter((path) => !path.includes('<<parameters.'));\n const payloadPaths = (existingManifest?.functions ?? [])\n .flatMap((entry) => [\n ...(entry['test-payload'] ? [entry['test-payload']] : []),\n ...(entry['test-payloads'] ?? []).map(({ payload }) => payload),\n ])\n .filter((path) => !path.includes('<<parameters.'));\n addFileChange(plan, input, {\n path: state.denoConfigPath,\n contents: mergeDenoConfiguration(\n snapshot.contents,\n input.contractVersion,\n basename(state.manifestPath),\n { sources: sourcePaths, payloads: payloadPaths },\n ),\n description: 'Merge strict target-scoped Deno authoring configuration',\n });\n }\n\n const root = setupRoot(state);\n if (selected.has(CustomFunctionSetupFeature.Editor)) {\n const settingsPath = join(root, '.vscode', 'settings.json');\n const extensionsPath = join(root, '.vscode', 'extensions.json');\n const settingsSnapshot = fileSnapshotAt(input, settingsPath);\n const extensionsSnapshot = fileSnapshotAt(input, extensionsPath);\n addFileChange(plan, input, {\n path: settingsPath,\n contents: mergeEditorSettings(settingsSnapshot.contents, root, state.targetDirectory),\n description: 'Scope Deno language support to Custom Functions',\n });\n addFileChange(plan, input, {\n path: extensionsPath,\n contents: mergeEditorExtensions(extensionsSnapshot.contents),\n description: 'Recommend the Deno editor extension',\n });\n }\n\n if (selected.has(CustomFunctionSetupFeature.Skill)) {\n planSkill(plan, input);\n }\n if (selected.has(CustomFunctionSetupFeature.Ci)) {\n if (!state.repositoryRoot || !state.usesGithub) {\n plan.warnings.push(\n 'GitHub Actions setup was selected, but this target is not inside a detected GitHub repository.',\n );\n } else {\n const workflowPath = join(\n state.repositoryRoot,\n '.github',\n 'workflows',\n 'transcend-custom-functions.yml',\n );\n const target =\n relative(state.repositoryRoot, state.targetDirectory).split(sep).join('/') || '.';\n const contentDirectory =\n relative(state.repositoryRoot, state.manifestDirectory).split(sep).join('/') || '.';\n const manifest = relative(state.repositoryRoot, state.manifestPath).split(sep).join('/');\n const watchedPaths = (existingManifest?.functions ?? [])\n .flatMap((entry) => [\n entry.code,\n ...(entry['test-payload'] ? [entry['test-payload']] : []),\n ...(entry['test-payloads'] ?? []).map(({ payload }) => payload),\n ])\n .filter((path) => !path.includes('<<parameters.'))\n .map((path) =>\n relative(state.repositoryRoot!, resolve(state.manifestDirectory, path))\n .split(sep)\n .join('/'),\n );\n const workflowContents = generateGithubActionsWorkflow({\n cliVersion: input.cliVersion,\n targetDirectory: target,\n contentDirectory,\n manifestPath: manifest,\n watchedPaths,\n });\n const workflowSnapshot = fileSnapshotAt(input, workflowPath);\n if (workflowSnapshot.contents === null) {\n addFileChange(plan, input, {\n path: workflowPath,\n contents: workflowContents,\n description: 'Add credential-free Custom Function checks',\n createOnly: true,\n });\n } else if (workflowSnapshot.contents === workflowContents) {\n plan.unchanged.push(workflowPath);\n } else if (isUnmodifiedCustomFunctionWorkflow(workflowSnapshot.contents)) {\n addFileChange(plan, input, {\n path: workflowPath,\n contents: workflowContents,\n description: 'Update managed Custom Function checks',\n });\n } else {\n plan.unchanged.push(workflowPath);\n plan.warnings.push(`Existing GitHub Actions workflow was left unchanged: ${workflowPath}`);\n }\n }\n }\n validatePlanDestinations(\n state,\n plan.changes.map(({ path }) => path),\n );\n return plan;\n}\n\n/**\n * Add a new function to an initialized project in one transaction.\n *\n * @param input - Collected project state\n * @param options - Generated function\n * @returns Validated project plan\n */\nexport function buildAddFunctionPlan(\n input: CustomFunctionPlanningInput,\n options: {\n /** Generated function scaffold. */\n generated: GeneratedCustomFunctionTemplate;\n },\n): CustomFunctionProjectPlan {\n const { state } = input;\n const currentManifest = fileSnapshotAt(input, state.manifestPath).contents;\n if (currentManifest === null) {\n throw new Error(`Custom Function manifest does not exist: ${state.manifestPath}`);\n }\n const sourceRelativePath = options.generated.sourceFile.path.split(sep).join('/');\n const sourceCollision = state.relativePaths.find(\n (path) => path.toLocaleLowerCase('en-US') === sourceRelativePath.toLocaleLowerCase('en-US'),\n );\n if (sourceCollision) {\n throw new Error(\n `Custom Function name \"${options.generated.displayName}\" maps to ${sourceRelativePath}, ` +\n `which conflicts with existing path ${sourceCollision}. Choose another name.`,\n );\n }\n const existingSourceEntry = parseCustomFunctionsManifest(currentManifest).functions.find(\n (entry) =>\n resolve(state.manifestDirectory, entry.code) ===\n resolve(state.manifestDirectory, sourceRelativePath),\n );\n if (existingSourceEntry) {\n throw new Error(\n `Custom Function name \"${options.generated.displayName}\" maps to source used by ` +\n `\"${existingSourceEntry.name}\". Choose another name.`,\n );\n }\n const plan: CustomFunctionProjectPlan = {\n version: CUSTOM_FUNCTION_RESULT_VERSION,\n command: 'new',\n rootDirectory: state.manifestDirectory,\n targetDirectory: state.targetDirectory,\n manifestPath: state.manifestPath,\n changes: [],\n unchanged: [],\n warnings: [],\n nextSteps: [],\n };\n const updatedManifest = insertCustomFunctionManifestEntry(\n currentManifest,\n options.generated.manifestEntry,\n );\n addFileChange(plan, input, {\n path: state.manifestPath,\n contents: updatedManifest,\n description: `Register ${options.generated.displayName} in the manifest`,\n });\n\n const generatedFiles = [options.generated.sourceFile, ...options.generated.payloadFiles];\n generatedFiles.forEach((file) => {\n addFileChange(plan, input, {\n path: join(state.manifestDirectory, file.path),\n contents: file.contents,\n description:\n file === options.generated.sourceFile\n ? `Create ${options.generated.displayName} source`\n : `Create ${options.generated.displayName} test payload`,\n createOnly: true,\n });\n });\n const sourcePath = join(state.manifestDirectory, options.generated.sourceFile.path);\n const projectArguments = buildCustomFunctionProjectArguments(\n state.targetDirectory,\n state.manifestPath,\n state.invocationDirectory,\n );\n const variableNames = parameterNamesInManifestValue(options.generated.manifestEntry);\n const variablesArgument = buildPlaceholderVariablesArgument(variableNames);\n plan.nextSteps = [\n `Edit ${quoteCliArgument(displayCliPath(state.invocationDirectory, sourcePath))}`,\n `transcend custom-functions run ${projectArguments} --function=${quoteCliArgument(\n options.generated.displayName,\n )}${variablesArgument}`,\n `transcend custom-functions check ${projectArguments}${variablesArgument}`,\n `transcend custom-functions push --file=${quoteCliArgument(\n displayCliPath(state.invocationDirectory, state.manifestPath),\n )} --dryRun${variablesArgument}`,\n ];\n if (variableNames.length > 0) {\n plan.warnings.push(\n `Supply ${variableNames.join(', ')} through --variables when running or pushing; never commit secret values.`,\n );\n }\n validatePlanDestinations(\n state,\n plan.changes.map(({ path }) => path),\n );\n return plan;\n}\n\n/**\n * Generate the template before collecting its destination snapshots.\n *\n * @param displayName - Custom Function display name\n * @param template - Template name\n * @returns Pure template output\n */\nexport function prepareGeneratedCustomFunction(\n displayName: string,\n template: Parameters<typeof generateCustomFunctionTemplate>[1],\n): GeneratedCustomFunctionTemplate {\n return generateCustomFunctionTemplate(displayName, template);\n}\n"],"mappings":"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"}
|