@maycombhq/atticus 2.0.0-beta.2 → 2.0.0-beta.22
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/dist/bin.js +8 -4
- package/dist/chunk-23XVSEV5.js +49 -0
- package/dist/{chunk-ZDPAS56H.js → chunk-24OXGB3P.js} +8 -2
- package/dist/{chunk-7EOBHUMC.js → chunk-24XLDU72.js} +4 -3
- package/dist/{chunk-CR3MTH32.js → chunk-2F4CYZKJ.js} +86 -11
- package/dist/{chunk-6IU67AEK.js → chunk-2GF7OLF3.js} +23 -15
- package/dist/chunk-2IIMFOPM.js +41 -0
- package/dist/chunk-2LGRMVCA.js +617 -0
- package/dist/{chunk-XPCM366L.js → chunk-2MMCFP5C.js} +10 -8
- package/dist/{chunk-JBTK5OP2.js → chunk-2Q56PQPS.js} +6 -4
- package/dist/{chunk-Z6LF7HQN.js → chunk-2Q5EDGEO.js} +7 -5
- package/dist/{chunk-3USYZGRF.js → chunk-2RLKFUUL.js} +38 -27
- package/dist/chunk-2SKB4O2E.js +59 -0
- package/dist/{chunk-SP2I63OO.js → chunk-34S2WGOB.js} +87 -4
- package/dist/{chunk-GQ4N4WKF.js → chunk-3NFFJL5D.js} +33 -27
- package/dist/{chunk-SJRGMG6A.js → chunk-3NWDLGG6.js} +28 -25
- package/dist/{chunk-4WBVUHXN.js → chunk-3RM4UK6W.js} +20 -18
- package/dist/chunk-42SIDKEU.js +583 -0
- package/dist/{chunk-GLUX4EEP.js → chunk-4EURQWQD.js} +20 -15
- package/dist/chunk-4U276ICE.js +39 -0
- package/dist/{chunk-ZMFPW66A.js → chunk-53T4O55J.js} +4 -3
- package/dist/{chunk-6J5OKA4Y.js → chunk-57TDNMI3.js} +17 -15
- package/dist/chunk-5BD2KYLE.js +57 -0
- package/dist/{chunk-7EFILTCI.js → chunk-5F7GFN2F.js} +28 -0
- package/dist/chunk-5NMKONLP.js +95 -0
- package/dist/{chunk-7ZUIMTOU.js → chunk-5SJZW52K.js} +26 -24
- package/dist/{chunk-4RS5KZQD.js → chunk-63YRMR6J.js} +6 -5
- package/dist/chunk-66PPNOON.js +62 -0
- package/dist/chunk-6H3Z5JHH.js +64 -0
- package/dist/{chunk-CEXSU4S6.js → chunk-6MUGR4LS.js} +775 -89
- package/dist/{chunk-QSXK2RGH.js → chunk-6OJQOPUN.js} +5 -3
- package/dist/{chunk-MVZVGYXH.js → chunk-6PPOWY5E.js} +84 -14
- package/dist/{chunk-7EKXJZ2Y.js → chunk-6ZGLAACW.js} +299 -38
- package/dist/chunk-6ZJ5A7AF.js +222 -0
- package/dist/{chunk-L24C55VN.js → chunk-745DAZ4L.js} +142 -30
- package/dist/{chunk-Q4D5X7QB.js → chunk-7ASNL4Q4.js} +46 -24
- package/dist/chunk-7BR7IPOH.js +35 -0
- package/dist/{chunk-7WD63HU2.js → chunk-7DOR27HL.js} +6 -6
- package/dist/chunk-7FTTA3HD.js +341 -0
- package/dist/{chunk-OLQJTJJU.js → chunk-7GJS6DNX.js} +12 -3
- package/dist/{chunk-7JUKDRSZ.js → chunk-7IGKHZ4Z.js} +347 -226
- package/dist/{chunk-G2B4ZQGH.js → chunk-7IOWA5D5.js} +11 -6
- package/dist/{chunk-EBEW3XXQ.js → chunk-7JITZFJC.js} +7 -5
- package/dist/chunk-7MJSQTL5.js +174 -0
- package/dist/{chunk-I4JRCD6M.js → chunk-7UOMVMFG.js} +25 -17
- package/dist/{chunk-YY6ZQQBP.js → chunk-AFWUDXEM.js} +19 -7
- package/dist/chunk-AFZ3QA6W.js +47 -0
- package/dist/chunk-AJQ72EBM.js +420 -0
- package/dist/chunk-AJYXNTNZ.js +317 -0
- package/dist/chunk-AVTBS4OW.js +49 -0
- package/dist/{chunk-FHH4I4ZV.js → chunk-BDKC6H5P.js} +12 -6
- package/dist/{chunk-IPKHE5D6.js → chunk-BEVTIBRH.js} +1526 -875
- package/dist/chunk-BHT7QK4G.js +162 -0
- package/dist/{chunk-6JUBZBMW.js → chunk-BIGDQDHD.js} +6 -4
- package/dist/{chunk-2BFCZ3RK.js → chunk-BO4KX37X.js} +20 -18
- package/dist/chunk-BPK5P77O.js +115 -0
- package/dist/chunk-BQ4SQQC6.js +59 -0
- package/dist/chunk-BQGDB6ZL.js +7342 -0
- package/dist/{chunk-2ANOROX3.js → chunk-BTGPE6CR.js} +11 -9
- package/dist/chunk-BTY3HZBO.js +93 -0
- package/dist/{chunk-DPZHZQKE.js → chunk-BXYMYEJ4.js} +44 -10
- package/dist/{chunk-2RMYG36Q.js → chunk-C3RY6KU6.js} +309 -346
- package/dist/chunk-C4R4JLHE.js +40 -0
- package/dist/chunk-CADWLE2T.js +18 -0
- package/dist/chunk-CBGGOQWU.js +82 -0
- package/dist/chunk-CMDXGQTS.js +47 -0
- package/dist/{chunk-MC3H7736.js → chunk-CQDGOPGH.js} +58 -18
- package/dist/{chunk-HFQCFSJR.js → chunk-CX4RZ2KS.js} +4 -3
- package/dist/{chunk-PAMPPUR6.js → chunk-CXJ6FUKN.js} +1852 -207
- package/dist/{chunk-ABWHYWNI.js → chunk-D73UEXYW.js} +3 -3
- package/dist/chunk-DCZWQLYT.js +1205 -0
- package/dist/chunk-DLOBCJL6.js +48 -0
- package/dist/{chunk-4BN53TG3.js → chunk-DOBQKHIF.js} +31 -23
- package/dist/chunk-E3ISYXO3.js +423 -0
- package/dist/{chunk-7SW2QWLU.js → chunk-E6ZIEVOI.js} +16 -13
- package/dist/chunk-EBL2R3YG.js +43 -0
- package/dist/{chunk-AIOQPLA5.js → chunk-EGQRREQH.js} +41 -15
- package/dist/chunk-EHA7RMZ3.js +58 -0
- package/dist/{chunk-M766ZJ6W.js → chunk-EIPTLPFC.js} +38 -27
- package/dist/chunk-EMRIQUND.js +517 -0
- package/dist/{chunk-DFBCSHVT.js → chunk-EPCJQQWD.js} +6 -4
- package/dist/{chunk-RZPYKDWS.js → chunk-F3P7N7SF.js} +1 -1
- package/dist/{chunk-R77KLRB3.js → chunk-FFLNS6VP.js} +21 -18
- package/dist/chunk-FFTRTL6R.js +26 -0
- package/dist/{chunk-IHMLFRVV.js → chunk-FPJPLKDW.js} +62 -16
- package/dist/{chunk-JCZIKA4C.js → chunk-FSMSFDLD.js} +5 -4
- package/dist/{chunk-AVJDSJ2F.js → chunk-FUJM6RTF.js} +8 -7
- package/dist/chunk-FZOJFH7Q.js +132 -0
- package/dist/{chunk-QRAOANID.js → chunk-G6X77UJZ.js} +23 -21
- package/dist/{chunk-3ALD2W2A.js → chunk-GCWRWSU7.js} +10 -4
- package/dist/chunk-GIW4ZVDB.js +39 -0
- package/dist/{chunk-B2WLAWNJ.js → chunk-GUX3PTYM.js} +3 -3
- package/dist/{chunk-DPUYDDQG.js → chunk-GZY6RUZ6.js} +25 -3
- package/dist/chunk-H4VO6WG3.js +10 -0
- package/dist/{chunk-MMOSZPWJ.js → chunk-H5HBGNXU.js} +5 -4
- package/dist/chunk-H7KM7LZE.js +229 -0
- package/dist/{chunk-AA6YULYB.js → chunk-HNM2YQT2.js} +7 -7
- package/dist/{chunk-3C7EYRFZ.js → chunk-HYU5VLGA.js} +1 -1
- package/dist/{chunk-XY3P7JW7.js → chunk-IDKCWSM5.js} +1032 -172
- package/dist/chunk-IFKEI4SA.js +237 -0
- package/dist/{chunk-F7HYOUFF.js → chunk-IGOE6KPG.js} +67 -22
- package/dist/{chunk-TDD55CJH.js → chunk-IH2XURVQ.js} +6 -5
- package/dist/chunk-INQHESFB.js +38 -0
- package/dist/chunk-IP74LCOQ.js +57 -0
- package/dist/chunk-IPHHDDC6.js +45 -0
- package/dist/{chunk-T6AIP7H5.js → chunk-ISUAAMGS.js} +110 -153
- package/dist/{chunk-A7UPUQFY.js → chunk-IUPG3UKI.js} +624 -319
- package/dist/{chunk-L6SGQIR3.js → chunk-IVBOQAGB.js} +7 -3
- package/dist/{chunk-27NKUS3X.js → chunk-J2JAKCIW.js} +2205 -796
- package/dist/{chunk-V2YTAIQO.js → chunk-J3IOLXWM.js} +24 -7
- package/dist/chunk-JA5FI3QV.js +142 -0
- package/dist/chunk-JAVI7JSP.js +49 -0
- package/dist/{chunk-HLJAXMM4.js → chunk-JB5LINEM.js} +6 -2
- package/dist/{chunk-2VHF7OXM.js → chunk-JENSEMXF.js} +1 -1
- package/dist/{chunk-6BVONWJ7.js → chunk-JJF6HALY.js} +4 -3
- package/dist/chunk-JLUCKAEL.js +38 -0
- package/dist/chunk-JRBFANFE.js +221 -0
- package/dist/{chunk-R6XF6UR3.js → chunk-KDNTAPLX.js} +4 -4
- package/dist/chunk-KFAVQZSX.js +33 -0
- package/dist/chunk-KJXD4PNL.js +50 -0
- package/dist/chunk-KN5BXMWN.js +44 -0
- package/dist/{chunk-PCVDV3UZ.js → chunk-KQGURXFU.js} +9 -7
- package/dist/{chunk-WY6PP6AA.js → chunk-KXITGYLF.js} +40 -6
- package/dist/{chunk-66YVAGGM.js → chunk-L27SV425.js} +22 -20
- package/dist/{chunk-NE2W3OO7.js → chunk-LDLL7LB3.js} +24 -22
- package/dist/chunk-LFGTYX5U.js +379 -0
- package/dist/{chunk-EYWIDJFU.js → chunk-LGBMTVNT.js} +7 -5
- package/dist/{chunk-Q5AMFEWD.js → chunk-LGFL54FP.js} +3 -2
- package/dist/{chunk-6TACQN3N.js → chunk-LJXMYKZJ.js} +7 -5
- package/dist/{chunk-BKVWTZ6A.js → chunk-LKOR5UET.js} +29 -26
- package/dist/chunk-LNBQOP7D.js +294 -0
- package/dist/{chunk-O3WI5KWW.js → chunk-LO6P2VYG.js} +2 -2
- package/dist/chunk-LQJPN536.js +122 -0
- package/dist/{chunk-YEDDOYSC.js → chunk-LYBNHMVZ.js} +29 -5
- package/dist/{chunk-A3GY6SOA.js → chunk-LZ7NUC62.js} +20 -18
- package/dist/chunk-M32BLWDH.js +37 -0
- package/dist/{chunk-VYDBJ73M.js → chunk-M3NANSDZ.js} +17 -15
- package/dist/chunk-MFHL5URL.js +31 -0
- package/dist/chunk-MFR5OPBD.js +109 -0
- package/dist/{chunk-DE76JROX.js → chunk-MG4ZL5RW.js} +32 -20
- package/dist/{chunk-N7IXEHK3.js → chunk-MO6P2JZH.js} +10 -8
- package/dist/{chunk-65NYPGRC.js → chunk-MUWDB4R4.js} +1 -1
- package/dist/chunk-MZCGSXVR.js +34 -0
- package/dist/{chunk-MGYZM27B.js → chunk-N3XIYPU3.js} +51 -23
- package/dist/chunk-NDCF4R6S.js +172 -0
- package/dist/{chunk-DHPACDG7.js → chunk-NR2UJWOC.js} +10 -8
- package/dist/chunk-NXJ5URP6.js +51 -0
- package/dist/{chunk-UNM6ZOKP.js → chunk-NY2XSR5K.js} +147 -18
- package/dist/{chunk-5GDRCDQB.js → chunk-O45HFTFS.js} +3 -2
- package/dist/{chunk-ONLS5QA5.js → chunk-O4GXGGBX.js} +14 -12
- package/dist/chunk-O5PXQR67.js +249 -0
- package/dist/{chunk-PRPPGYZG.js → chunk-O66DM6DJ.js} +6 -4
- package/dist/{chunk-KEM4SDDP.js → chunk-O7FDLW7L.js} +11 -8
- package/dist/{chunk-T2UYZSCQ.js → chunk-O7XLYEFA.js} +169 -29
- package/dist/{chunk-FITWGOJ2.js → chunk-OHNCWBKF.js} +4 -4
- package/dist/{chunk-652QWTLZ.js → chunk-OHVTTOPS.js} +3 -3
- package/dist/chunk-OMI6FPPN.js +43 -0
- package/dist/chunk-ONUPY3H6.js +53 -0
- package/dist/chunk-OTLDSZDV.js +69 -0
- package/dist/chunk-OUBGGKDU.js +22 -0
- package/dist/chunk-OWNCM4ZN.js +330 -0
- package/dist/{chunk-YISXLPHN.js → chunk-P2V7QW4D.js} +235 -35
- package/dist/{chunk-CNUKCS2T.js → chunk-P32RUW3B.js} +1632 -93
- package/dist/{chunk-BWZ77RQT.js → chunk-PAQ2AS5E.js} +1 -1
- package/dist/{chunk-ZMAINWBW.js → chunk-PBPBMP2B.js} +4 -3
- package/dist/{chunk-ZVM6AKKM.js → chunk-PJSJPMJI.js} +3 -3
- package/dist/{chunk-EFHQ3TWP.js → chunk-PKBHS4AA.js} +233 -56
- package/dist/{chunk-GT4I4ZWM.js → chunk-PMUAJGLI.js} +20 -16
- package/dist/chunk-PPD7HTDP.js +152 -0
- package/dist/chunk-PSOFBQWB.js +42 -0
- package/dist/{chunk-S2A7YC3Q.js → chunk-Q2TECDIT.js} +10694 -8896
- package/dist/chunk-Q4K5WB2W.js +42 -0
- package/dist/{chunk-UGLN7QHV.js → chunk-Q6DFNVRJ.js} +14 -12
- package/dist/chunk-QA4O2GGC.js +265 -0
- package/dist/chunk-QAXW2N3B.js +1216 -0
- package/dist/chunk-QBNWF5ZU.js +19 -0
- package/dist/chunk-QFWA2DPH.js +224 -0
- package/dist/{chunk-23W7VWKR.js → chunk-QKUJMING.js} +1363 -114
- package/dist/{chunk-NXFPS2LR.js → chunk-R44CYFPV.js} +16 -13
- package/dist/{chunk-CKSITVS4.js → chunk-R7NYHMUU.js} +2687 -786
- package/dist/chunk-REWWDVQB.js +162 -0
- package/dist/{chunk-JMSCMUCA.js → chunk-RGERPOIV.js} +145 -21
- package/dist/{chunk-6JCPI55B.js → chunk-RLDGWLQ7.js} +49 -7
- package/dist/chunk-RUGXBPWI.js +384 -0
- package/dist/{chunk-CPA6HPVR.js → chunk-RXPJMEOW.js} +18 -12
- package/dist/{chunk-3HI6Z55Y.js → chunk-S4PMJU6H.js} +339 -43
- package/dist/chunk-S5LSDXV4.js +40 -0
- package/dist/chunk-S7FCV7S5.js +51 -0
- package/dist/{chunk-5GGOLAKC.js → chunk-SDKLKB6I.js} +28 -26
- package/dist/chunk-SFSPGFCV.js +62 -0
- package/dist/{chunk-ZNCEKR4J.js → chunk-SFUP7TTO.js} +12 -8
- package/dist/{chunk-64EQYWCA.js → chunk-SLXZOMA6.js} +69 -19
- package/dist/chunk-SQV37XO2.js +273 -0
- package/dist/{chunk-K65BJIMT.js → chunk-SU74NDMQ.js} +19 -17
- package/dist/chunk-SYV5LHML.js +165 -0
- package/dist/chunk-T4YPZIQN.js +36 -0
- package/dist/chunk-T6DQR5TV.js +323 -0
- package/dist/{chunk-JIITQXFB.js → chunk-THDMSZ3R.js} +3075 -802
- package/dist/{chunk-JGZCG5VM.js → chunk-TNR75OXT.js} +7 -7
- package/dist/{chunk-D3PO4DOZ.js → chunk-TUULXQRW.js} +174 -15
- package/dist/chunk-TYQBFTBR.js +516 -0
- package/dist/chunk-U76OWS3Q.js +49 -0
- package/dist/{chunk-YYQN46FY.js → chunk-UCROWG2D.js} +27 -24
- package/dist/{chunk-6M5NK3K3.js → chunk-UF4AZOZB.js} +50 -10
- package/dist/chunk-UF4GLFBX.js +345 -0
- package/dist/{chunk-OT2O76OS.js → chunk-UGUP3ZM6.js} +240 -39
- package/dist/chunk-UNAGJYET.js +45 -0
- package/dist/{chunk-5WG5YP4T.js → chunk-UOR2DTHH.js} +16 -14
- package/dist/{chunk-S3QNRWYR.js → chunk-UPOY4YSQ.js} +14 -12
- package/dist/{chunk-EPTBZ3GP.js → chunk-UPS2DGFC.js} +1 -1
- package/dist/{chunk-4AK7IBVP.js → chunk-UUU4CLJG.js} +4 -2
- package/dist/{chunk-W3BQAZ3Q.js → chunk-UWMJKX5U.js} +14 -12
- package/dist/{chunk-QZSX3F7C.js → chunk-UWOJLHFT.js} +27 -23
- package/dist/chunk-VBTP56CE.js +535 -0
- package/dist/chunk-VCTWPLAO.js +211 -0
- package/dist/chunk-VNU26RCO.js +1215 -0
- package/dist/{chunk-CSZ4C5N6.js → chunk-VTZMAJ3W.js} +93 -10
- package/dist/{chunk-TXLH6WHQ.js → chunk-VW62D6QE.js} +14 -12
- package/dist/{chunk-CAQZUNOH.js → chunk-VY72R2XZ.js} +610 -3
- package/dist/{chunk-2DIQQJCB.js → chunk-VZALIKIF.js} +18 -15
- package/dist/{chunk-TYAID7B7.js → chunk-W62H2XSO.js} +25 -23
- package/dist/{chunk-HVUPKCGJ.js → chunk-W7VWI2YH.js} +9 -6
- package/dist/{chunk-TANFV3MZ.js → chunk-WERM6KPJ.js} +7 -4
- package/dist/{chunk-BOHJZTEQ.js → chunk-WF7B67YE.js} +208 -87
- package/dist/{chunk-7FBGJFEE.js → chunk-WG5U3F5V.js} +14 -12
- package/dist/{chunk-4NDAAFQT.js → chunk-WJF2CS6M.js} +8 -5
- package/dist/{chunk-XAKWMCXI.js → chunk-WKUJ3KPV.js} +4 -4
- package/dist/chunk-WMTRHUI5.js +103 -0
- package/dist/chunk-WNKPRSGI.js +36 -0
- package/dist/chunk-WXFLMQSR.js +223 -0
- package/dist/{chunk-RRTKKSLQ.js → chunk-X3WY6MN3.js} +8 -6
- package/dist/{chunk-ZCJDOK2S.js → chunk-X4CXA2IL.js} +47 -23
- package/dist/{chunk-UBBC2XSG.js → chunk-X5F3Q5LV.js} +560 -105
- package/dist/{chunk-C6EKFH7J.js → chunk-XD75VZIH.js} +9 -7
- package/dist/chunk-XERYFDB5.js +297 -0
- package/dist/chunk-XI2LCCYQ.js +420 -0
- package/dist/chunk-Y2EQNWKV.js +933 -0
- package/dist/{chunk-LR3R6Z2A.js → chunk-YHCMZC2J.js} +7 -7
- package/dist/chunk-YYY3AZFE.js +122 -0
- package/dist/{chunk-GDLULHTC.js → chunk-Z5IA3WDR.js} +19 -31
- package/dist/{chunk-T6XQL73F.js → chunk-ZFFYNRIO.js} +63 -23
- package/dist/{chunk-EDS2L2LD.js → chunk-ZFL7NY4F.js} +56 -27
- package/dist/{chunk-YMZ3TNYB.js → chunk-ZGULQAPZ.js} +7 -4
- package/dist/{chunk-4SKZDI62.js → chunk-ZIUFM5HT.js} +3 -1
- package/dist/{chunk-DKJA76CJ.js → chunk-ZJFRMSJT.js} +15 -13
- package/dist/chunk-ZJXLNDH4.js +239 -0
- package/dist/chunk-ZQ3ON2VQ.js +252 -0
- package/dist/{chunk-HITVBIJS.js → chunk-ZQ7SKESZ.js} +150 -415
- package/dist/{chunk-6QSERWXH.js → chunk-ZQXZ2SES.js} +24 -21
- package/dist/chunk-ZX57KSEQ.js +39 -0
- package/dist/{chunk-I3E7CX4H.js → chunk-ZZK56BLP.js} +5 -3
- package/dist/files.json +664 -368
- package/dist/packages/naysayer/constitution/constitution.yaml +19 -0
- package/dist/packages/sdk/npm/index.js +6194 -2542
- package/dist/packages/ui/dist/assets/{elk-api-tma0MCuh.js → elk-api-CIf-0gz5.js} +2 -2
- package/dist/packages/ui/dist/assets/index-CoK_Dl0D.js +47 -0
- package/dist/packages/ui/dist/assets/index-Dw20IRhQ.css +1 -0
- package/dist/packages/ui/dist/index.html +3 -2
- package/package.json +5 -5
- package/dist/chunk-2BF2EYJV.js +0 -174
- package/dist/chunk-42EVSKME.js +0 -37
- package/dist/chunk-4BKGMUIK.js +0 -53
- package/dist/chunk-5KLGBXG5.js +0 -48
- package/dist/chunk-6BNC6EQ4.js +0 -41
- package/dist/chunk-6D2CQ5II.js +0 -41
- package/dist/chunk-7AVHLZGD.js +0 -45
- package/dist/chunk-D46WUV3T.js +0 -33
- package/dist/chunk-E36QOJMD.js +0 -47
- package/dist/chunk-FQXYPF7E.js +0 -147
- package/dist/chunk-GBRFVT63.js +0 -45
- package/dist/chunk-ICY36XCH.js +0 -34
- package/dist/chunk-J4K3KVLD.js +0 -131
- package/dist/chunk-JZU3H6UQ.js +0 -54
- package/dist/chunk-NN2ZQEB4.js +0 -38
- package/dist/chunk-PCOCACY3.js +0 -385
- package/dist/chunk-RTEYOSJY.js +0 -29
- package/dist/chunk-RUVFXE2L.js +0 -666
- package/dist/chunk-RVH5SUW5.js +0 -69
- package/dist/chunk-VN3DP4LQ.js +0 -43
- package/dist/chunk-W5BVQF44.js +0 -36
- package/dist/chunk-WVPJSRRJ.js +0 -52
- package/dist/chunk-XPTOBS2D.js +0 -48
- package/dist/packages/ui/dist/assets/index-B54fm9FQ.js +0 -29
- package/dist/packages/ui/dist/assets/index-DD_hufQz.css +0 -1
|
@@ -7,27 +7,30 @@ import {
|
|
|
7
7
|
documentFormat,
|
|
8
8
|
drawioIngestor,
|
|
9
9
|
officeFormat,
|
|
10
|
+
parseCsv,
|
|
10
11
|
readDocument,
|
|
11
12
|
readDrawio,
|
|
12
13
|
readMermaid,
|
|
13
14
|
resolveNames
|
|
14
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-6ZGLAACW.js";
|
|
15
16
|
import {
|
|
16
17
|
openapiExtractor,
|
|
17
18
|
readOpenApiDocument
|
|
18
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-CQDGOPGH.js";
|
|
19
20
|
import {
|
|
20
21
|
combine,
|
|
21
22
|
formatOf,
|
|
22
23
|
screenDiagramXml,
|
|
23
24
|
screenOfficeXml,
|
|
24
25
|
screenText
|
|
25
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-P32RUW3B.js";
|
|
26
27
|
import {
|
|
28
|
+
TrafficFile,
|
|
27
29
|
endpointId,
|
|
28
30
|
entryEndpointId,
|
|
29
31
|
factIdPart,
|
|
30
32
|
fieldNameKey,
|
|
33
|
+
interfaceId,
|
|
31
34
|
joinFacts,
|
|
32
35
|
joinVendorOperations,
|
|
33
36
|
loadOrgPack,
|
|
@@ -35,12 +38,16 @@ import {
|
|
|
35
38
|
orgPackDirOf,
|
|
36
39
|
parseRecord,
|
|
37
40
|
readZip,
|
|
38
|
-
|
|
39
|
-
toCanonicalYaml
|
|
40
|
-
|
|
41
|
+
routeScore,
|
|
42
|
+
toCanonicalYaml,
|
|
43
|
+
trafficFileText
|
|
44
|
+
} from "./chunk-Q2TECDIT.js";
|
|
41
45
|
import {
|
|
42
46
|
writeFileAtomic
|
|
43
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-TUULXQRW.js";
|
|
48
|
+
import {
|
|
49
|
+
require_dist
|
|
50
|
+
} from "./chunk-BQGDB6ZL.js";
|
|
44
51
|
import {
|
|
45
52
|
__toESM
|
|
46
53
|
} from "./chunk-TV45EUGM.js";
|
|
@@ -122,6 +129,151 @@ function fromData(data) {
|
|
|
122
129
|
}
|
|
123
130
|
return void 0;
|
|
124
131
|
}
|
|
132
|
+
var STRICT_ALIASES = 100;
|
|
133
|
+
var LENIENT_ALIASES = 1e4;
|
|
134
|
+
var LENIENT = { uniqueKeys: false, maxAliasCount: LENIENT_ALIASES };
|
|
135
|
+
var reasonOf = (e) => e.message.split("\n")[0].replace(/\s+at line \d+, column \d+:?\s*$/, "").trim();
|
|
136
|
+
var unreadableOf = (e) => ({
|
|
137
|
+
reason: reasonOf(e),
|
|
138
|
+
...e.linePos?.[0] ? { line: e.linePos[0].line, column: e.linePos[0].col } : {}
|
|
139
|
+
});
|
|
140
|
+
function duplicateKeys(text3) {
|
|
141
|
+
const lines = text3.split(/\r?\n/);
|
|
142
|
+
return (0, import_yaml.parseDocument)(text3).errors.filter((e) => e.code === "DUPLICATE_KEY" && e.linePos?.[0]).map((e) => {
|
|
143
|
+
const { line, col } = e.linePos[0];
|
|
144
|
+
const key3 = /^\s*["']?([^"':]+)["']?\s*:/.exec((lines[line - 1] ?? "").slice(col - 1))?.[1];
|
|
145
|
+
return `duplicate key ${key3 ? `"${key3.trim()}" ` : ""}at ${line}:${col}: the last one is kept`;
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
function braceBalance(line) {
|
|
149
|
+
let n = 0;
|
|
150
|
+
let quote;
|
|
151
|
+
for (let i = 0; i < line.length; i++) {
|
|
152
|
+
const c = line[i];
|
|
153
|
+
if (quote) {
|
|
154
|
+
if (c === "\\" && quote === '"')
|
|
155
|
+
i++;
|
|
156
|
+
else if (c === quote)
|
|
157
|
+
quote = void 0;
|
|
158
|
+
} else if (c === '"' || c === "'")
|
|
159
|
+
quote = c;
|
|
160
|
+
else if (c === "#" && (i === 0 || /\s/.test(line[i - 1])))
|
|
161
|
+
return NaN;
|
|
162
|
+
else if (c === "{")
|
|
163
|
+
n++;
|
|
164
|
+
else if (c === "}")
|
|
165
|
+
n--;
|
|
166
|
+
}
|
|
167
|
+
return quote ? NaN : n;
|
|
168
|
+
}
|
|
169
|
+
var indentOf = (l) => /^\s*/.exec(l)[0].length;
|
|
170
|
+
var blank = (l) => !l.trim() || /^\s*#/.test(l);
|
|
171
|
+
function joinServerVariables(text3) {
|
|
172
|
+
const lines = text3.split(/\r?\n/);
|
|
173
|
+
const at = [];
|
|
174
|
+
let servers;
|
|
175
|
+
let vars;
|
|
176
|
+
for (let i = 0; i < lines.length; i++) {
|
|
177
|
+
const l = lines[i];
|
|
178
|
+
if (blank(l))
|
|
179
|
+
continue;
|
|
180
|
+
const ind = indentOf(l);
|
|
181
|
+
if (vars !== void 0 && ind <= vars)
|
|
182
|
+
vars = void 0;
|
|
183
|
+
if (servers !== void 0 && ind <= servers && !/^\s*-(\s|$)/.test(l))
|
|
184
|
+
servers = void 0;
|
|
185
|
+
if (servers !== void 0 && ind < servers)
|
|
186
|
+
servers = void 0;
|
|
187
|
+
if (/^\s*["']?servers["']?\s*:\s*$/.test(l)) {
|
|
188
|
+
servers = ind;
|
|
189
|
+
vars = void 0;
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
if (servers === void 0)
|
|
193
|
+
continue;
|
|
194
|
+
const v = /^(\s*)(-\s+)?["']?variables["']?\s*:\s*$/.exec(l);
|
|
195
|
+
if (v) {
|
|
196
|
+
vars = v[1].length + (v[2]?.length ?? 0);
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
if (vars === void 0)
|
|
200
|
+
continue;
|
|
201
|
+
const m = /^(\s*)(["']?[\w.-]+["']?)\s*:\s*(\{.*)$/.exec(l);
|
|
202
|
+
if (!m)
|
|
203
|
+
continue;
|
|
204
|
+
let balance = braceBalance(m[3]);
|
|
205
|
+
if (Number.isNaN(balance))
|
|
206
|
+
return void 0;
|
|
207
|
+
const parts = [m[3].trim()];
|
|
208
|
+
let j = i;
|
|
209
|
+
while (balance > 0) {
|
|
210
|
+
j++;
|
|
211
|
+
if (j >= lines.length || j - i > 200)
|
|
212
|
+
return void 0;
|
|
213
|
+
const b = braceBalance(lines[j]);
|
|
214
|
+
if (Number.isNaN(b))
|
|
215
|
+
return void 0;
|
|
216
|
+
balance += b;
|
|
217
|
+
parts.push(lines[j].trim());
|
|
218
|
+
}
|
|
219
|
+
if (balance < 0)
|
|
220
|
+
return void 0;
|
|
221
|
+
const joined = `${m[1]}${m[2]}: ${parts.filter(Boolean).join(" ")}`;
|
|
222
|
+
if (joined === l && j === i)
|
|
223
|
+
continue;
|
|
224
|
+
lines[i] = joined;
|
|
225
|
+
for (let k = i + 1; k <= j; k++)
|
|
226
|
+
lines[k] = "";
|
|
227
|
+
at.push(i + 1);
|
|
228
|
+
i = j;
|
|
229
|
+
}
|
|
230
|
+
return at.length ? { text: lines.join("\n"), at } : void 0;
|
|
231
|
+
}
|
|
232
|
+
var SPEC_KINDS = ["openapi", "swagger", "asyncapi"];
|
|
233
|
+
function readYaml(text3) {
|
|
234
|
+
let first;
|
|
235
|
+
try {
|
|
236
|
+
return { data: (0, import_yaml.parse)(text3) };
|
|
237
|
+
} catch (e) {
|
|
238
|
+
first = e;
|
|
239
|
+
}
|
|
240
|
+
const notes = [];
|
|
241
|
+
const dup = first.code === "DUPLICATE_KEY";
|
|
242
|
+
const aliases = /alias count/i.test(first.message);
|
|
243
|
+
const lenient = (t) => {
|
|
244
|
+
try {
|
|
245
|
+
return { data: (0, import_yaml.parse)(t, LENIENT) };
|
|
246
|
+
} catch (e) {
|
|
247
|
+
return { error: e };
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
const notesOf = (t) => {
|
|
251
|
+
const out = duplicateKeys(t);
|
|
252
|
+
try {
|
|
253
|
+
(0, import_yaml.parse)(t, { uniqueKeys: false });
|
|
254
|
+
} catch (e) {
|
|
255
|
+
if (/alias count/i.test(e.message))
|
|
256
|
+
out.push(`more aliases than the strict parser allows (${STRICT_ALIASES}): read with a higher limit (${LENIENT_ALIASES})`);
|
|
257
|
+
}
|
|
258
|
+
return out;
|
|
259
|
+
};
|
|
260
|
+
if (dup || aliases) {
|
|
261
|
+
const r = lenient(text3);
|
|
262
|
+
if ("data" in r)
|
|
263
|
+
return { data: r.data, notes: notesOf(text3) };
|
|
264
|
+
}
|
|
265
|
+
const fixed = joinServerVariables(text3);
|
|
266
|
+
if (fixed) {
|
|
267
|
+
const r = lenient(fixed.text);
|
|
268
|
+
if ("data" in r && SPEC_KINDS.includes(fromData(r.data)?.classification ?? "unknown")) {
|
|
269
|
+
notes.push(...notesOf(fixed.text));
|
|
270
|
+
const lines = fixed.at.length === 1 ? `line ${fixed.at[0]} is a flow mapping` : `lines ${fixed.at.slice(0, -1).join(", ")} and ${fixed.at.at(-1)} are flow mappings`;
|
|
271
|
+
notes.push(`servers[].variables at ${lines} written over several lines, not indented past ${fixed.at.length === 1 ? "its key: read as if it were" : "their key: read as if each were"} on one line`);
|
|
272
|
+
return { data: r.data, notes, text: fixed.text };
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
return { error: first };
|
|
276
|
+
}
|
|
125
277
|
function classify(fileName, bytes) {
|
|
126
278
|
const name = fileName.toLowerCase();
|
|
127
279
|
const ext = name.includes(".") ? name.slice(name.lastIndexOf(".") + 1) : "";
|
|
@@ -163,19 +315,26 @@ function classify(fileName, bytes) {
|
|
|
163
315
|
return { classification: "diagram" };
|
|
164
316
|
if (/^<(!doctype html|html)\b/i.test(head))
|
|
165
317
|
return { classification: "document" };
|
|
318
|
+
if (ext === "proto" || /^(syntax\s*=\s*["']proto[23]["']|package\s+[\w.]+\s*;)/m.test(head))
|
|
319
|
+
return { classification: "protobuf" };
|
|
320
|
+
if (ext === "avsc" || /^\{/.test(head) && /"type"\s*:\s*"record"/.test(head) && /"fields"\s*:/.test(head))
|
|
321
|
+
return { classification: "avro" };
|
|
166
322
|
if (["json", "yaml", "yml"].includes(ext) || /^[[{]/.test(head)) {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
323
|
+
const r = readYaml(text3);
|
|
324
|
+
const named = ["json", "yaml", "yml"].includes(ext);
|
|
325
|
+
if ("error" in r && named)
|
|
326
|
+
return { classification: "unknown", unreadable: unreadableOf(r.error) };
|
|
327
|
+
const data = "data" in r ? r.data : void 0;
|
|
328
|
+
const lenient = {
|
|
329
|
+
..."notes" in r && r.notes?.length ? { notes: r.notes } : {},
|
|
330
|
+
..."text" in r && r.text !== void 0 ? { text: r.text } : {}
|
|
331
|
+
};
|
|
173
332
|
const known = fromData(data);
|
|
174
333
|
if (known)
|
|
175
|
-
return known;
|
|
334
|
+
return { ...known, ...lenient };
|
|
176
335
|
if (ext === "json" || /^[[{]/.test(head)) {
|
|
177
336
|
if (isObj(data) || Array.isArray(data))
|
|
178
|
-
return { classification: "payload", data };
|
|
337
|
+
return { classification: "payload", data, ...lenient };
|
|
179
338
|
}
|
|
180
339
|
if (ext === "yaml" || ext === "yml")
|
|
181
340
|
return { classification: "unknown" };
|
|
@@ -195,7 +354,10 @@ import { createHash } from "node:crypto";
|
|
|
195
354
|
var READERS = {
|
|
196
355
|
openapi: `${openapiExtractor.id}@${openapiExtractor.version}`,
|
|
197
356
|
asyncapi: "asyncapi@0.1.0",
|
|
198
|
-
payload: "payload@0.1.0"
|
|
357
|
+
payload: "payload@0.1.0",
|
|
358
|
+
// ADR 0164: a topic's message spec.
|
|
359
|
+
protobuf: "protobuf@0.1.0",
|
|
360
|
+
avro: "avro@0.1.0"
|
|
199
361
|
};
|
|
200
362
|
var short = (s) => createHash("sha256").update(s).digest("hex").slice(0, 6);
|
|
201
363
|
function oneFile(path, text3) {
|
|
@@ -365,8 +527,8 @@ var KIND_ORDER = [
|
|
|
365
527
|
"needs-reading"
|
|
366
528
|
];
|
|
367
529
|
var slug = (s) => s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
368
|
-
function boundedId(prefix,
|
|
369
|
-
const id = `${prefix}${
|
|
530
|
+
function boundedId(prefix, key3) {
|
|
531
|
+
const id = `${prefix}${key3}`;
|
|
370
532
|
if (id.length <= 120)
|
|
371
533
|
return id;
|
|
372
534
|
return `${id.slice(0, 110)}-${createHash2("sha256").update(id).digest("hex").slice(0, 8)}`;
|
|
@@ -411,9 +573,9 @@ var opt = {
|
|
|
411
573
|
};
|
|
412
574
|
|
|
413
575
|
// packages/intake/dist/scan-inputs.js
|
|
414
|
-
import { createHash as
|
|
415
|
-
import { readdir, readFile, stat } from "node:fs/promises";
|
|
416
|
-
import { join, relative, resolve, sep } from "node:path";
|
|
576
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
577
|
+
import { readdir as readdir2, readFile as readFile2, stat as stat2 } from "node:fs/promises";
|
|
578
|
+
import { join as join2, relative, resolve, sep } from "node:path";
|
|
417
579
|
|
|
418
580
|
// packages/intake/dist/screen-file.js
|
|
419
581
|
var PK = (b) => b[0] === 80 && b[1] === 75;
|
|
@@ -455,10 +617,314 @@ function screenFile(path, bytes) {
|
|
|
455
617
|
}
|
|
456
618
|
}
|
|
457
619
|
|
|
620
|
+
// packages/intake/dist/contract-specs.js
|
|
621
|
+
var import_yaml4 = __toESM(require_dist(), 1);
|
|
622
|
+
import { readdir, readFile, stat } from "node:fs/promises";
|
|
623
|
+
import { join } from "node:path";
|
|
624
|
+
|
|
625
|
+
// packages/intake/dist/traffic.js
|
|
626
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
627
|
+
var cmp = (a, b) => a < b ? -1 : a > b ? 1 : 0;
|
|
628
|
+
var key = (s) => s.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
629
|
+
var sha = (s) => createHash3("sha256").update(s, "utf8").digest("hex");
|
|
630
|
+
var IPV4 = /\b\d{1,3}(?:\.\d{1,3}){3}\b/;
|
|
631
|
+
var IPV6 = /[0-9a-f]{0,4}::[0-9a-f]{0,4}|\b[0-9a-f]{1,4}(?::[0-9a-f]{1,4}){2,7}\b/i;
|
|
632
|
+
var EMAIL = /[^\s@/]+@[^\s@/]+/;
|
|
633
|
+
var JWT = /\beyJ[A-Za-z0-9_-]{6,}/;
|
|
634
|
+
var OPAQUE = /\b(?=[A-Za-z0-9+_-]*\d)(?=[A-Za-z0-9+_-]*[A-Za-z])[A-Za-z0-9+_-]{24,}={0,2}/;
|
|
635
|
+
var UUID = /\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/i;
|
|
636
|
+
var HEX = /\b[0-9a-f]{16,}\b/i;
|
|
637
|
+
function looksSensitive(v) {
|
|
638
|
+
return [IPV4, IPV6, EMAIL, JWT, OPAQUE, UUID, HEX].some((re) => re.test(v));
|
|
639
|
+
}
|
|
640
|
+
function rowsOf(text3) {
|
|
641
|
+
const t = text3.replace(/^\uFEFF/, "").trim();
|
|
642
|
+
if (!t)
|
|
643
|
+
return void 0;
|
|
644
|
+
if (t.startsWith("[") || t.startsWith("{")) {
|
|
645
|
+
let v;
|
|
646
|
+
try {
|
|
647
|
+
v = JSON.parse(t);
|
|
648
|
+
} catch {
|
|
649
|
+
return void 0;
|
|
650
|
+
}
|
|
651
|
+
const list2 = Array.isArray(v) ? v : v && typeof v === "object" ? ["rows", "data", "records", "items"].map((k) => v[k]).find((x) => Array.isArray(x)) : void 0;
|
|
652
|
+
if (!Array.isArray(list2) || !list2.length)
|
|
653
|
+
return void 0;
|
|
654
|
+
const out = [];
|
|
655
|
+
for (const r of list2) {
|
|
656
|
+
if (!r || typeof r !== "object" || Array.isArray(r))
|
|
657
|
+
return void 0;
|
|
658
|
+
const row = {};
|
|
659
|
+
for (const [k, x] of Object.entries(r))
|
|
660
|
+
if (typeof x === "string" || typeof x === "number")
|
|
661
|
+
row[k] = String(x);
|
|
662
|
+
out.push(row);
|
|
663
|
+
}
|
|
664
|
+
return out;
|
|
665
|
+
}
|
|
666
|
+
const recs = parseCsv(t);
|
|
667
|
+
if (recs.length < 2)
|
|
668
|
+
return void 0;
|
|
669
|
+
const head = recs[0].cells.map((c) => c.trim());
|
|
670
|
+
if (head.length < 2)
|
|
671
|
+
return void 0;
|
|
672
|
+
return recs.slice(1).map((r) => {
|
|
673
|
+
const row = {};
|
|
674
|
+
head.forEach((h, i) => row[h] = (r.cells[i] ?? "").trim());
|
|
675
|
+
return row;
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
function dayOf(v) {
|
|
679
|
+
const m = /^(\d{4}-\d{2}-\d{2})/.exec(v.trim());
|
|
680
|
+
if (m)
|
|
681
|
+
return m[1];
|
|
682
|
+
if (/^\d{12,13}$/.test(v.trim()))
|
|
683
|
+
return new Date(Number(v)).toISOString().slice(0, 10);
|
|
684
|
+
return void 0;
|
|
685
|
+
}
|
|
686
|
+
var VERSION = /^v\d+(?:\.\d+)*$/i;
|
|
687
|
+
var PARAM = /^(?:\{[A-Za-z_][A-Za-z0-9_.-]{0,40}\}|:[A-Za-z_][A-Za-z0-9_]{0,40}|<[A-Za-z_][A-Za-z0-9_:]{0,40}>)$/;
|
|
688
|
+
var segmentOf = (s) => VERSION.test(s) || PARAM.test(s) || /^[a-z][a-z._-]*$/.test(s) && s.length <= 20 && /[aeiou]/.test(s) && !looksSensitive(s) ? s : "{id}";
|
|
689
|
+
function barePath(path) {
|
|
690
|
+
let p = path.trim().split(/[?#]/, 1)[0] ?? "";
|
|
691
|
+
p = p.replace(/^[a-z][a-z0-9+.-]*:\/\/[^/]*/i, "");
|
|
692
|
+
return p.replace(/;[^/]*/g, "");
|
|
693
|
+
}
|
|
694
|
+
function safePathOf(path) {
|
|
695
|
+
const p = barePath(path);
|
|
696
|
+
if (!p.startsWith("/"))
|
|
697
|
+
return void 0;
|
|
698
|
+
return `/${p.split("/").filter(Boolean).map(segmentOf).join("/")}`;
|
|
699
|
+
}
|
|
700
|
+
var MATCH = 100;
|
|
701
|
+
function pathTemplateOf(path, templates) {
|
|
702
|
+
const p = barePath(path);
|
|
703
|
+
if (!p.startsWith("/"))
|
|
704
|
+
return void 0;
|
|
705
|
+
const sorted2 = [...templates].sort();
|
|
706
|
+
let best;
|
|
707
|
+
let score = 0;
|
|
708
|
+
for (const t of sorted2) {
|
|
709
|
+
const s = routeScore(p, t);
|
|
710
|
+
if (s > MATCH && s > score) {
|
|
711
|
+
score = s;
|
|
712
|
+
best = t;
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
if (best)
|
|
716
|
+
return best;
|
|
717
|
+
const segs = p.split("/").filter(Boolean);
|
|
718
|
+
let prefix;
|
|
719
|
+
let len = 0;
|
|
720
|
+
score = 0;
|
|
721
|
+
for (const t of sorted2) {
|
|
722
|
+
const n = t.split("/").filter(Boolean).length;
|
|
723
|
+
if (n === 0 || n >= segs.length || n < len)
|
|
724
|
+
continue;
|
|
725
|
+
const s = routeScore(`/${segs.slice(0, n).join("/")}`, t);
|
|
726
|
+
if (s <= MATCH)
|
|
727
|
+
continue;
|
|
728
|
+
if (n > len || s > score) {
|
|
729
|
+
len = n;
|
|
730
|
+
score = s;
|
|
731
|
+
prefix = t;
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
return prefix ? `${prefix.replace(/\/+$/, "")}/**` : void 0;
|
|
735
|
+
}
|
|
736
|
+
var appLabelOf = (name) => `app-${sha(name).slice(0, 8)}`;
|
|
737
|
+
function denyListHits(text3, hashes) {
|
|
738
|
+
const hits = [];
|
|
739
|
+
text3.toLowerCase().split("\n").forEach((line, i) => {
|
|
740
|
+
const w = line.match(/[a-z0-9]+/g) ?? [];
|
|
741
|
+
for (let k = 0; k < w.length; k++)
|
|
742
|
+
if (hashes.has(sha(w[k])) || k + 1 < w.length && hashes.has(sha(`${w[k]} ${w[k + 1]}`))) {
|
|
743
|
+
hits.push(i + 1);
|
|
744
|
+
break;
|
|
745
|
+
}
|
|
746
|
+
});
|
|
747
|
+
return hits;
|
|
748
|
+
}
|
|
749
|
+
function aggregateTraffic(input) {
|
|
750
|
+
const text3 = Buffer.from(input.bytes).toString("utf8");
|
|
751
|
+
const rows = rowsOf(text3);
|
|
752
|
+
const shape = `a CSV with a header row, or a JSON list of rows, with an app, a method and a path column (${input.source}: app ${input.columns.app.join("/")}; method ${input.columns.method.join("/")}; path ${[...input.columns.path, ...input.columns.basepath].join("/")})`;
|
|
753
|
+
if (!rows)
|
|
754
|
+
return { ok: false, message: `The file doesn't read as a traffic export: give ${shape}.` };
|
|
755
|
+
const names = [...new Set(rows.flatMap((r) => Object.keys(r)))];
|
|
756
|
+
const col = (aliases) => {
|
|
757
|
+
for (const a of aliases) {
|
|
758
|
+
const hit = names.find((n) => key(n) === key(a));
|
|
759
|
+
if (hit)
|
|
760
|
+
return hit;
|
|
761
|
+
}
|
|
762
|
+
return void 0;
|
|
763
|
+
};
|
|
764
|
+
const c = {
|
|
765
|
+
app: col(input.columns.app),
|
|
766
|
+
method: col(input.columns.method),
|
|
767
|
+
basepath: col(input.columns.basepath),
|
|
768
|
+
suffix: col(input.columns.suffix),
|
|
769
|
+
proxy: col(input.columns.proxy),
|
|
770
|
+
count: col(input.columns.count),
|
|
771
|
+
time: col(input.columns.time),
|
|
772
|
+
path: void 0
|
|
773
|
+
};
|
|
774
|
+
if (!c.basepath || !c.suffix)
|
|
775
|
+
c.path = col(input.columns.path);
|
|
776
|
+
const missing = [
|
|
777
|
+
!c.app ? "app" : "",
|
|
778
|
+
!c.method ? "method" : "",
|
|
779
|
+
!c.path && !(c.basepath && c.suffix) ? "path" : ""
|
|
780
|
+
].filter(Boolean);
|
|
781
|
+
if (missing.length)
|
|
782
|
+
return {
|
|
783
|
+
ok: false,
|
|
784
|
+
message: `The file has no ${missing.join(", ")} column, so it can't be kept as aggregates: give ${shape}.`
|
|
785
|
+
};
|
|
786
|
+
const range = (v) => v && /^\d{4}-\d{2}-\d{2}$/.test(v) ? v : void 0;
|
|
787
|
+
if (input.from && !range(input.from) || input.to && !range(input.to))
|
|
788
|
+
return { ok: false, message: "--from and --to are days: YYYY-MM-DD." };
|
|
789
|
+
if ((!input.from || !input.to) && !c.time)
|
|
790
|
+
return {
|
|
791
|
+
ok: false,
|
|
792
|
+
message: "The export has no date column: give --from and --to (YYYY-MM-DD) for the range it covers."
|
|
793
|
+
};
|
|
794
|
+
const kept = new Set(Object.values(c).filter((x) => !!x));
|
|
795
|
+
const dropped = names.filter((n) => !kept.has(n)).sort();
|
|
796
|
+
const secrets = /* @__PURE__ */ new Set();
|
|
797
|
+
const keptValues = /* @__PURE__ */ new Set();
|
|
798
|
+
const agg = /* @__PURE__ */ new Map();
|
|
799
|
+
let outOfRange = 0;
|
|
800
|
+
let skipped2 = 0;
|
|
801
|
+
let unmatched = 0;
|
|
802
|
+
const known = /* @__PURE__ */ new Map();
|
|
803
|
+
for (const a of input.apps ?? [])
|
|
804
|
+
if (a.trim() && !known.has(key(a)))
|
|
805
|
+
known.set(key(a), a.trim());
|
|
806
|
+
const days = [];
|
|
807
|
+
for (const r of rows) {
|
|
808
|
+
for (const n of dropped) {
|
|
809
|
+
const v = (r[n] ?? "").trim();
|
|
810
|
+
const q = /^(?:[a-z][a-z0-9+.-]*:\/\/|\/)/i.test(v) ? v.split(/[?#]/)[1] ?? "" : v;
|
|
811
|
+
if (q.length >= 6)
|
|
812
|
+
secrets.add(q);
|
|
813
|
+
}
|
|
814
|
+
for (const n of [c.path, c.suffix, c.basepath]) {
|
|
815
|
+
const v = n ? r[n] ?? "" : "";
|
|
816
|
+
const q = v.split(/[?#]/)[1] ?? "";
|
|
817
|
+
if (q.length >= 4)
|
|
818
|
+
secrets.add(q);
|
|
819
|
+
for (const m of (v.split(/[?#]/, 1)[0] ?? "").match(/;[^/]*/g) ?? [])
|
|
820
|
+
if (m.length >= 5)
|
|
821
|
+
secrets.add(m.slice(1));
|
|
822
|
+
}
|
|
823
|
+
if (c.time) {
|
|
824
|
+
const d = dayOf(r[c.time] ?? "");
|
|
825
|
+
if (d) {
|
|
826
|
+
if (input.from && d < input.from || input.to && d > input.to) {
|
|
827
|
+
outOfRange++;
|
|
828
|
+
continue;
|
|
829
|
+
}
|
|
830
|
+
days.push(d);
|
|
831
|
+
} else if (!input.from || !input.to) {
|
|
832
|
+
skipped2++;
|
|
833
|
+
continue;
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
const method = (r[c.method] ?? "").trim().toUpperCase();
|
|
837
|
+
const rawPath = c.path ? r[c.path] ?? "" : `${(r[c.basepath] ?? "").replace(/\/+$/, "")}/${(r[c.suffix] ?? "").replace(/^\/+/, "")}`;
|
|
838
|
+
const countText = c.count ? (r[c.count] ?? "").trim() : "1";
|
|
839
|
+
const count = Number(countText);
|
|
840
|
+
if (!/^[A-Z]{3,10}$/.test(method) || !barePath(rawPath).startsWith("/") || !Number.isInteger(count) || count < 0) {
|
|
841
|
+
skipped2++;
|
|
842
|
+
continue;
|
|
843
|
+
}
|
|
844
|
+
const path = pathTemplateOf(rawPath, input.templates);
|
|
845
|
+
if (!path) {
|
|
846
|
+
unmatched++;
|
|
847
|
+
continue;
|
|
848
|
+
}
|
|
849
|
+
if (count === 0)
|
|
850
|
+
continue;
|
|
851
|
+
const appRaw = (r[c.app] ?? "").trim();
|
|
852
|
+
const app = !appRaw ? "(none)" : known.get(key(appRaw)) ?? appLabelOf(appRaw);
|
|
853
|
+
const proxyRaw = c.proxy ? (r[c.proxy] ?? "").trim() : "";
|
|
854
|
+
const proxy = proxyRaw && !looksSensitive(proxyRaw) ? proxyRaw : void 0;
|
|
855
|
+
const baseRaw = c.basepath ? (r[c.basepath] ?? "").trim() : "";
|
|
856
|
+
const basepath = baseRaw ? safePathOf(baseRaw) : void 0;
|
|
857
|
+
for (const v of [app, proxy, basepath, path])
|
|
858
|
+
if (v)
|
|
859
|
+
keptValues.add(v);
|
|
860
|
+
const k = [app, method, path, proxy ?? "", basepath ?? ""].join("\0");
|
|
861
|
+
const row = agg.get(k) ?? {
|
|
862
|
+
app,
|
|
863
|
+
method,
|
|
864
|
+
path,
|
|
865
|
+
...proxy ? { proxy } : {},
|
|
866
|
+
...basepath ? { basepath } : {},
|
|
867
|
+
count: 0
|
|
868
|
+
};
|
|
869
|
+
row.count += count;
|
|
870
|
+
agg.set(k, row);
|
|
871
|
+
}
|
|
872
|
+
if (!agg.size)
|
|
873
|
+
return {
|
|
874
|
+
ok: false,
|
|
875
|
+
message: `No row of the file is a request in the range to a route of the estate (${rows.length} read, ${outOfRange} outside it, ${skipped2} without a method, path or count, ${unmatched} matching no route template of the estate): nothing to keep.`
|
|
876
|
+
};
|
|
877
|
+
days.sort();
|
|
878
|
+
const from = input.from ?? days[0];
|
|
879
|
+
const to = input.to ?? days[days.length - 1];
|
|
880
|
+
if (!from || !to)
|
|
881
|
+
return { ok: false, message: "The rows carry no dates: give --from and --to (YYYY-MM-DD)." };
|
|
882
|
+
const parsed = TrafficFile.safeParse({
|
|
883
|
+
schemaVersion: 1,
|
|
884
|
+
source: input.source,
|
|
885
|
+
from,
|
|
886
|
+
to,
|
|
887
|
+
inputSha256: createHash3("sha256").update(input.bytes).digest("hex"),
|
|
888
|
+
rows: [...agg.values()].sort((a, b) => cmp(a.app, b.app) || cmp(a.proxy ?? "", b.proxy ?? "") || cmp(a.path, b.path) || cmp(a.method, b.method))
|
|
889
|
+
});
|
|
890
|
+
if (!parsed.success)
|
|
891
|
+
return { ok: false, message: `The aggregate isn't valid: ${parsed.error.issues[0]?.message}.` };
|
|
892
|
+
const out = trafficFileText(parsed.data);
|
|
893
|
+
const lower = out.toLowerCase();
|
|
894
|
+
const leaked = [...secrets].filter((s) => !keptValues.has(s) && lower.includes(s.toLowerCase()));
|
|
895
|
+
if (leaked.length)
|
|
896
|
+
return {
|
|
897
|
+
ok: false,
|
|
898
|
+
message: `Refused: ${leaked.length} value${leaked.length === 1 ? "" : "s"} of the export's dropped columns would be written. Nothing was written.`
|
|
899
|
+
};
|
|
900
|
+
const body = out.replace(/^inputSha256: .*$/m, "");
|
|
901
|
+
if ([IPV4, IPV6, EMAIL, JWT, OPAQUE, UUID, HEX].some((re) => re.test(body)))
|
|
902
|
+
return {
|
|
903
|
+
ok: false,
|
|
904
|
+
message: "Refused: the aggregate would hold an IP, an email or a token-looking value. Nothing was written."
|
|
905
|
+
};
|
|
906
|
+
const hits = input.denyHashes?.size ? denyListHits(out, input.denyHashes) : [];
|
|
907
|
+
if (hits.length)
|
|
908
|
+
return {
|
|
909
|
+
ok: false,
|
|
910
|
+
message: `Refused: the deny-list names a word on line${hits.length === 1 ? "" : "s"} ${hits.join(", ")} of the aggregate. Nothing was written.`
|
|
911
|
+
};
|
|
912
|
+
return {
|
|
913
|
+
ok: true,
|
|
914
|
+
file: parsed.data,
|
|
915
|
+
text: out,
|
|
916
|
+
read: rows.length,
|
|
917
|
+
outOfRange,
|
|
918
|
+
skipped: skipped2,
|
|
919
|
+
unmatched,
|
|
920
|
+
dropped
|
|
921
|
+
};
|
|
922
|
+
}
|
|
923
|
+
|
|
458
924
|
// packages/intake/dist/vendor-ops.js
|
|
459
925
|
var import_yaml3 = __toESM(require_dist(), 1);
|
|
460
|
-
import { createHash as
|
|
461
|
-
var short2 = (s) =>
|
|
926
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
927
|
+
var short2 = (s) => createHash4("sha256").update(s).digest("hex").slice(0, 6);
|
|
462
928
|
function specEndpointIds(component, ops) {
|
|
463
929
|
const ids = ops.map((o) => endpointId(component, o.method, o.normalizedPath));
|
|
464
930
|
const count = /* @__PURE__ */ new Map();
|
|
@@ -507,7 +973,8 @@ function readVendorSpec(path, text3, system) {
|
|
|
507
973
|
scopes: op.scopes,
|
|
508
974
|
cite: `${path}:${op.methodLine ?? op.line ?? 1}`,
|
|
509
975
|
request: requestFields(ctx, op, swagger2),
|
|
510
|
-
response: responseFields(ctx, op, swagger2)
|
|
976
|
+
response: responseFields(ctx, op, swagger2),
|
|
977
|
+
...errorsOf(ctx, op, swagger2)
|
|
511
978
|
};
|
|
512
979
|
});
|
|
513
980
|
const ids = specEndpointIds(system, ops);
|
|
@@ -522,6 +989,56 @@ function readVendorSpec(path, text3, system) {
|
|
|
522
989
|
operations: ops.map((o, i) => ({ id: ids[i], ...o }))
|
|
523
990
|
};
|
|
524
991
|
}
|
|
992
|
+
function errorsOf(ctx, op, swagger2) {
|
|
993
|
+
const responses = (0, import_yaml3.isMap)(op.node) ? op.node.get("responses") : void 0;
|
|
994
|
+
if (!(0, import_yaml3.isMap)(responses))
|
|
995
|
+
return {};
|
|
996
|
+
const errors = responses.items.flatMap((p) => {
|
|
997
|
+
const status = (0, import_yaml3.isScalar)(p.key) ? String(p.key.value) : "";
|
|
998
|
+
if (!/^[45]\d\d$/.test(status))
|
|
999
|
+
return [];
|
|
1000
|
+
const cite = ctx.at((0, import_yaml3.isScalar)(p.key) ? p.key.range?.[0] : void 0);
|
|
1001
|
+
if (!cite)
|
|
1002
|
+
return [];
|
|
1003
|
+
const fields = [];
|
|
1004
|
+
schemaFields(ctx, bodySchema(ctx, p.value, swagger2), "body", "", 0, /* @__PURE__ */ new Set(), fields);
|
|
1005
|
+
return [{ status, cite, ...fields.length ? { fields } : {} }];
|
|
1006
|
+
});
|
|
1007
|
+
return errors.length ? { errors } : {};
|
|
1008
|
+
}
|
|
1009
|
+
function bodySchema(ctx, response, swagger2) {
|
|
1010
|
+
if (!swagger2)
|
|
1011
|
+
return contentSchema(ctx, response);
|
|
1012
|
+
const r = deref(ctx, response);
|
|
1013
|
+
return (0, import_yaml3.isMap)(r) ? r.get("schema", true) : void 0;
|
|
1014
|
+
}
|
|
1015
|
+
function responseHeaders(ctx, response, swagger2) {
|
|
1016
|
+
const r = deref(ctx, response);
|
|
1017
|
+
const headers = (0, import_yaml3.isMap)(r) ? r.get("headers") : void 0;
|
|
1018
|
+
if (!(0, import_yaml3.isMap)(headers))
|
|
1019
|
+
return [];
|
|
1020
|
+
const out = [];
|
|
1021
|
+
for (const pair of headers.items) {
|
|
1022
|
+
if (!(0, import_yaml3.isScalar)(pair.key))
|
|
1023
|
+
continue;
|
|
1024
|
+
const h = deref(ctx, pair.value);
|
|
1025
|
+
if (!(0, import_yaml3.isMap)(h))
|
|
1026
|
+
continue;
|
|
1027
|
+
const schema = swagger2 ? h : deref(ctx, h.get("schema", true));
|
|
1028
|
+
const sm = (0, import_yaml3.isMap)(schema) ? schema : void 0;
|
|
1029
|
+
const type = sm ? typeOf2(sm) : void 0;
|
|
1030
|
+
const values = sm ? strings(sm.get("enum")) : void 0;
|
|
1031
|
+
out.push({
|
|
1032
|
+
name: String(pair.key.value),
|
|
1033
|
+
in: "header",
|
|
1034
|
+
...type ? { type } : {},
|
|
1035
|
+
...swagger2 ? {} : { required: h.get("required") === true },
|
|
1036
|
+
...values ? { enum: values } : {},
|
|
1037
|
+
cite: ctx.at(pair.key.range?.[0]) ?? `${ctx.path}:1`
|
|
1038
|
+
});
|
|
1039
|
+
}
|
|
1040
|
+
return out;
|
|
1041
|
+
}
|
|
525
1042
|
function deref(ctx, node, seen = /* @__PURE__ */ new Set()) {
|
|
526
1043
|
let n = node;
|
|
527
1044
|
for (let i = 0; i < 8 && (0, import_yaml3.isMap)(n); i++) {
|
|
@@ -536,8 +1053,8 @@ function deref(ctx, node, seen = /* @__PURE__ */ new Set()) {
|
|
|
536
1053
|
}
|
|
537
1054
|
return n;
|
|
538
1055
|
}
|
|
539
|
-
var offsetOfKey = (map,
|
|
540
|
-
const pair = map.items.find((p) => (0, import_yaml3.isScalar)(p.key) && String(p.key.value) ===
|
|
1056
|
+
var offsetOfKey = (map, key3) => {
|
|
1057
|
+
const pair = map.items.find((p) => (0, import_yaml3.isScalar)(p.key) && String(p.key.value) === key3);
|
|
541
1058
|
return pair && (0, import_yaml3.isScalar)(pair.key) ? pair.key.range?.[0] : void 0;
|
|
542
1059
|
};
|
|
543
1060
|
var strings = (n) => (0, import_yaml3.isSeq)(n) ? n.items.filter(import_yaml3.isScalar).map((s) => String(s.value)) : void 0;
|
|
@@ -587,13 +1104,13 @@ function schemaFields(ctx, node, where, prefix, depth, seen, out) {
|
|
|
587
1104
|
for (const pair of props.items) {
|
|
588
1105
|
if (!(0, import_yaml3.isScalar)(pair.key))
|
|
589
1106
|
continue;
|
|
590
|
-
const
|
|
591
|
-
const name = prefix ? `${prefix}.${
|
|
1107
|
+
const key3 = String(pair.key.value);
|
|
1108
|
+
const name = prefix ? `${prefix}.${key3}` : key3;
|
|
592
1109
|
const prop = deref(ctx, pair.value, new Set(refs));
|
|
593
1110
|
const p = (0, import_yaml3.isMap)(prop) ? prop : void 0;
|
|
594
1111
|
const type = p ? typeOf2(p) : void 0;
|
|
595
1112
|
const values = p ? strings(p.get("enum")) : void 0;
|
|
596
|
-
const req = required.has(
|
|
1113
|
+
const req = required.has(key3);
|
|
597
1114
|
out.push({
|
|
598
1115
|
name,
|
|
599
1116
|
in: where,
|
|
@@ -601,7 +1118,7 @@ function schemaFields(ctx, node, where, prefix, depth, seen, out) {
|
|
|
601
1118
|
...objectLike ? { required: req } : {},
|
|
602
1119
|
...values ? { enum: values } : {},
|
|
603
1120
|
cite: ctx.at(pair.key.range?.[0]) ?? `${ctx.path}:1`,
|
|
604
|
-
...req && required.get(
|
|
1121
|
+
...req && required.get(key3) !== void 0 ? { requiredCite: ctx.at(required.get(key3)) } : {}
|
|
605
1122
|
});
|
|
606
1123
|
if (p && (type === "object" || type === "array"))
|
|
607
1124
|
schemaFields(ctx, pair.value, where, name, depth + 1, refs, out);
|
|
@@ -683,11 +1200,8 @@ function responseFields(ctx, op, swagger2) {
|
|
|
683
1200
|
if (!ok)
|
|
684
1201
|
return [];
|
|
685
1202
|
const out = [];
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
return (0, import_yaml3.isMap)(r) ? r.get("schema", true) : void 0;
|
|
689
|
-
})() : contentSchema(ctx, ok.value);
|
|
690
|
-
schemaFields(ctx, schema, "body", "", 0, /* @__PURE__ */ new Set(), out);
|
|
1203
|
+
schemaFields(ctx, bodySchema(ctx, ok.value, swagger2), "body", "", 0, /* @__PURE__ */ new Set(), out);
|
|
1204
|
+
out.push(...responseHeaders(ctx, ok.value, swagger2));
|
|
691
1205
|
return out;
|
|
692
1206
|
}
|
|
693
1207
|
var pointer = (s) => s.replace(/~/g, "~0").replace(/\//g, "~1");
|
|
@@ -722,12 +1236,442 @@ function operationSchemas(spec) {
|
|
|
722
1236
|
});
|
|
723
1237
|
}
|
|
724
1238
|
|
|
1239
|
+
// packages/intake/dist/contract-specs.js
|
|
1240
|
+
var MAX_BYTES = 1024 * 1024;
|
|
1241
|
+
var SKIP = /* @__PURE__ */ new Set([
|
|
1242
|
+
".git",
|
|
1243
|
+
"node_modules",
|
|
1244
|
+
"vendor",
|
|
1245
|
+
"target",
|
|
1246
|
+
"build",
|
|
1247
|
+
"dist",
|
|
1248
|
+
"out",
|
|
1249
|
+
"bin",
|
|
1250
|
+
"obj",
|
|
1251
|
+
".gradle",
|
|
1252
|
+
".idea",
|
|
1253
|
+
".venv",
|
|
1254
|
+
"__pycache__"
|
|
1255
|
+
]);
|
|
1256
|
+
var cmp2 = (a, b) => a < b ? -1 : a > b ? 1 : 0;
|
|
1257
|
+
function readProtoSpecs(path, text3) {
|
|
1258
|
+
const proto3 = /^\s*syntax\s*=\s*["']proto3["']/m.test(text3);
|
|
1259
|
+
let pkg = "";
|
|
1260
|
+
const out = [];
|
|
1261
|
+
const stack = [];
|
|
1262
|
+
let inComment = false;
|
|
1263
|
+
text3.split(/\r?\n/).forEach((raw, i) => {
|
|
1264
|
+
let line = raw;
|
|
1265
|
+
if (inComment) {
|
|
1266
|
+
const end = line.indexOf("*/");
|
|
1267
|
+
if (end < 0)
|
|
1268
|
+
return;
|
|
1269
|
+
line = line.slice(end + 2);
|
|
1270
|
+
inComment = false;
|
|
1271
|
+
}
|
|
1272
|
+
line = line.replace(/\/\*.*?\*\//g, "").replace(/\/\/.*$/, "");
|
|
1273
|
+
const open = line.indexOf("/*");
|
|
1274
|
+
if (open >= 0) {
|
|
1275
|
+
inComment = true;
|
|
1276
|
+
line = line.slice(0, open);
|
|
1277
|
+
}
|
|
1278
|
+
const n = i + 1;
|
|
1279
|
+
const p = /^\s*package\s+([\w.]+)\s*;/.exec(line);
|
|
1280
|
+
if (p)
|
|
1281
|
+
pkg = p[1];
|
|
1282
|
+
const message = /^\s*message\s+(\w+)\s*\{/.exec(line);
|
|
1283
|
+
const oneof = /^\s*oneof\s+(\w+)\s*\{/.exec(line);
|
|
1284
|
+
const other = /^\s*(enum|service|extend|extensions)\b[^{]*\{/.exec(line);
|
|
1285
|
+
let rest = line;
|
|
1286
|
+
if (message) {
|
|
1287
|
+
const outer = stack.filter((f) => f.kind === "message").map((f) => f.name);
|
|
1288
|
+
const name = [...outer, message[1]].join(".");
|
|
1289
|
+
const spec = {
|
|
1290
|
+
kind: "message",
|
|
1291
|
+
format: "protobuf",
|
|
1292
|
+
role: "schema",
|
|
1293
|
+
file: path,
|
|
1294
|
+
line: n,
|
|
1295
|
+
name: pkg ? `${pkg}.${name}` : name,
|
|
1296
|
+
fields: []
|
|
1297
|
+
};
|
|
1298
|
+
out.push(spec);
|
|
1299
|
+
stack.push({ kind: "message", name: message[1], spec });
|
|
1300
|
+
rest = line.slice(line.indexOf("{") + 1);
|
|
1301
|
+
} else if (oneof || other) {
|
|
1302
|
+
stack.push({ kind: oneof ? "oneof" : "other", name: "" });
|
|
1303
|
+
rest = line.slice(line.indexOf("{") + 1);
|
|
1304
|
+
} else {
|
|
1305
|
+
const top = stack.at(-1);
|
|
1306
|
+
const owner = top?.kind === "message" ? top : top?.kind === "oneof" ? stack.at(-2) : void 0;
|
|
1307
|
+
const f = /^\s*(optional|required|repeated)?\s*(map\s*<[^>]+>|[\w.]+)\s+(\w+)\s*=\s*(\d+)\s*(\[[^\]]*\])?\s*;/.exec(line);
|
|
1308
|
+
if (f && owner?.kind === "message" && owner.spec && !["reserved", "option"].includes(f[2])) {
|
|
1309
|
+
const label = f[1];
|
|
1310
|
+
owner.spec.fields.push({
|
|
1311
|
+
side: "message",
|
|
1312
|
+
name: f[3],
|
|
1313
|
+
type: label === "repeated" ? `repeated ${f[2]}` : f[2].replace(/\s+/g, ""),
|
|
1314
|
+
// proto2's `required` must be there; anything else may be left out (proto3 has no required).
|
|
1315
|
+
required: label === "required" && !proto3,
|
|
1316
|
+
number: Number(f[4]),
|
|
1317
|
+
at: `${path}:${n}`
|
|
1318
|
+
});
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
for (const _ of rest.matchAll(/\}/g))
|
|
1322
|
+
stack.pop();
|
|
1323
|
+
});
|
|
1324
|
+
return out;
|
|
1325
|
+
}
|
|
1326
|
+
function lineOfName(lines, from, name) {
|
|
1327
|
+
const re = new RegExp(`"name"\\s*:\\s*"${name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}"`);
|
|
1328
|
+
for (let i = Math.max(0, from); i < lines.length; i++)
|
|
1329
|
+
if (re.test(lines[i]))
|
|
1330
|
+
return i + 1;
|
|
1331
|
+
return from + 1;
|
|
1332
|
+
}
|
|
1333
|
+
function readAvroSpecs(path, text3) {
|
|
1334
|
+
let data;
|
|
1335
|
+
try {
|
|
1336
|
+
data = JSON.parse(text3);
|
|
1337
|
+
} catch {
|
|
1338
|
+
return [];
|
|
1339
|
+
}
|
|
1340
|
+
const lines = text3.split(/\r?\n/);
|
|
1341
|
+
const out = [];
|
|
1342
|
+
let cursor = 0;
|
|
1343
|
+
const typeName = (t) => {
|
|
1344
|
+
if (typeof t === "string")
|
|
1345
|
+
return t;
|
|
1346
|
+
if (Array.isArray(t))
|
|
1347
|
+
return t.map(typeName).join("|");
|
|
1348
|
+
if (t && typeof t === "object") {
|
|
1349
|
+
const o = t;
|
|
1350
|
+
if (o.type === "array")
|
|
1351
|
+
return `repeated ${typeName(o.items)}`;
|
|
1352
|
+
if (o.type === "map")
|
|
1353
|
+
return `map<string,${typeName(o.values)}>`;
|
|
1354
|
+
if (typeof o.logicalType === "string")
|
|
1355
|
+
return String(o.type);
|
|
1356
|
+
if (typeof o.name === "string")
|
|
1357
|
+
return o.name;
|
|
1358
|
+
return typeName(o.type);
|
|
1359
|
+
}
|
|
1360
|
+
return "";
|
|
1361
|
+
};
|
|
1362
|
+
const record = (r, ns) => {
|
|
1363
|
+
if (r.type !== "record" || typeof r.name !== "string" || !Array.isArray(r.fields))
|
|
1364
|
+
return;
|
|
1365
|
+
const space = typeof r.namespace === "string" ? r.namespace : ns;
|
|
1366
|
+
const line = lineOfName(lines, cursor, r.name);
|
|
1367
|
+
cursor = line;
|
|
1368
|
+
const spec = {
|
|
1369
|
+
kind: "message",
|
|
1370
|
+
format: "avro",
|
|
1371
|
+
role: "schema",
|
|
1372
|
+
file: path,
|
|
1373
|
+
line,
|
|
1374
|
+
name: space ? `${space}.${r.name}` : r.name,
|
|
1375
|
+
fields: []
|
|
1376
|
+
};
|
|
1377
|
+
out.push(spec);
|
|
1378
|
+
r.fields.forEach((f, i) => {
|
|
1379
|
+
if (!f || typeof f !== "object")
|
|
1380
|
+
return;
|
|
1381
|
+
const x = f;
|
|
1382
|
+
if (typeof x.name !== "string")
|
|
1383
|
+
return;
|
|
1384
|
+
const at = lineOfName(lines, cursor, x.name);
|
|
1385
|
+
cursor = at;
|
|
1386
|
+
const nullable = Array.isArray(x.type) && x.type.includes("null");
|
|
1387
|
+
const type = typeName(Array.isArray(x.type) ? x.type.filter((t) => t !== "null") : x.type);
|
|
1388
|
+
spec.fields.push({
|
|
1389
|
+
side: "message",
|
|
1390
|
+
name: x.name,
|
|
1391
|
+
...type ? { type } : {},
|
|
1392
|
+
required: !nullable && !("default" in x),
|
|
1393
|
+
number: i,
|
|
1394
|
+
at: `${path}:${at}`
|
|
1395
|
+
});
|
|
1396
|
+
const inner = Array.isArray(x.type) ? x.type : [x.type];
|
|
1397
|
+
for (const t of inner)
|
|
1398
|
+
if (t && typeof t === "object")
|
|
1399
|
+
record(t, space);
|
|
1400
|
+
});
|
|
1401
|
+
};
|
|
1402
|
+
for (const r of Array.isArray(data) ? data : [data])
|
|
1403
|
+
if (r && typeof r === "object")
|
|
1404
|
+
record(r, "");
|
|
1405
|
+
return out;
|
|
1406
|
+
}
|
|
1407
|
+
var lineAt = (d, node) => {
|
|
1408
|
+
const r = node?.range;
|
|
1409
|
+
return r ? d.lc.linePos(r[0]).line : 1;
|
|
1410
|
+
};
|
|
1411
|
+
function deref2(d, node, depth = 0) {
|
|
1412
|
+
if (!(0, import_yaml4.isMap)(node) || depth > 8)
|
|
1413
|
+
return node;
|
|
1414
|
+
const ref = node.get("$ref");
|
|
1415
|
+
if (typeof ref !== "string" || !ref.startsWith("#/"))
|
|
1416
|
+
return node;
|
|
1417
|
+
let at = d.root;
|
|
1418
|
+
for (const p of ref.slice(2).split("/"))
|
|
1419
|
+
at = (0, import_yaml4.isMap)(at) ? at.get(p.replace(/~1/g, "/").replace(/~0/g, "~"), true) : void 0;
|
|
1420
|
+
return deref2(d, at, depth + 1);
|
|
1421
|
+
}
|
|
1422
|
+
function propsOf(d, schema, prefix, depth, out) {
|
|
1423
|
+
const s = deref2(d, schema);
|
|
1424
|
+
if (!(0, import_yaml4.isMap)(s) || depth > 6)
|
|
1425
|
+
return;
|
|
1426
|
+
const props = s.get("properties", true);
|
|
1427
|
+
const req = s.get("required", true);
|
|
1428
|
+
const required = new Set((0, import_yaml4.isSeq)(req) ? req.items.map((x) => (0, import_yaml4.isScalar)(x) ? String(x.value) : "") : []);
|
|
1429
|
+
if (!(0, import_yaml4.isMap)(props))
|
|
1430
|
+
return;
|
|
1431
|
+
for (const p of props.items) {
|
|
1432
|
+
if (!(0, import_yaml4.isScalar)(p.key))
|
|
1433
|
+
continue;
|
|
1434
|
+
const name = prefix ? `${prefix}.${String(p.key.value)}` : String(p.key.value);
|
|
1435
|
+
const v = deref2(d, p.value);
|
|
1436
|
+
const type = (0, import_yaml4.isMap)(v) ? v.get("type") : void 0;
|
|
1437
|
+
out.push({
|
|
1438
|
+
side: "message",
|
|
1439
|
+
name,
|
|
1440
|
+
...typeof type === "string" ? { type } : {},
|
|
1441
|
+
required: required.has(String(p.key.value)),
|
|
1442
|
+
at: `${d.path}:${lineAt(d, p.key)}`
|
|
1443
|
+
});
|
|
1444
|
+
if ((0, import_yaml4.isMap)(v)) {
|
|
1445
|
+
if (type === "array")
|
|
1446
|
+
propsOf(d, v.get("items", true), `${name}[]`, depth + 1, out);
|
|
1447
|
+
else
|
|
1448
|
+
propsOf(d, v, name, depth + 1, out);
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
function docOf(path, text3) {
|
|
1453
|
+
const lc = new import_yaml4.LineCounter();
|
|
1454
|
+
const doc = (0, import_yaml4.parseDocument)(text3, { lineCounter: lc });
|
|
1455
|
+
return (0, import_yaml4.isMap)(doc.contents) ? { path, lc, root: doc.contents } : void 0;
|
|
1456
|
+
}
|
|
1457
|
+
function readJsonSchemaSpecs(path, text3) {
|
|
1458
|
+
const d = docOf(path, text3);
|
|
1459
|
+
if (!d)
|
|
1460
|
+
return [];
|
|
1461
|
+
const title = d.root.get("title");
|
|
1462
|
+
const id = d.root.get("$id");
|
|
1463
|
+
const fields = [];
|
|
1464
|
+
propsOf(d, d.root, "", 0, fields);
|
|
1465
|
+
if (!fields.length)
|
|
1466
|
+
return [];
|
|
1467
|
+
const name = typeof title === "string" && title ? title : typeof id === "string" && id ? (id.split("/").pop() ?? id).replace(/\.json$/, "") : (path.split("/").pop() ?? path).replace(/\.(schema\.)?json$|\.ya?ml$/i, "");
|
|
1468
|
+
return [
|
|
1469
|
+
{ kind: "message", format: "json-schema", role: "schema", file: path, line: 1, name, fields }
|
|
1470
|
+
];
|
|
1471
|
+
}
|
|
1472
|
+
function readAsyncApiSpecs(path, text3) {
|
|
1473
|
+
const d = docOf(path, text3);
|
|
1474
|
+
if (!d || d.root.get("asyncapi") === void 0)
|
|
1475
|
+
return [];
|
|
1476
|
+
const out = [];
|
|
1477
|
+
const channels = d.root.get("channels", true);
|
|
1478
|
+
if (!(0, import_yaml4.isMap)(channels))
|
|
1479
|
+
return out;
|
|
1480
|
+
const add = (topic, message) => {
|
|
1481
|
+
const m = deref2(d, message);
|
|
1482
|
+
if (!(0, import_yaml4.isMap)(m))
|
|
1483
|
+
return;
|
|
1484
|
+
const oneOf = m.get("oneOf", true);
|
|
1485
|
+
if ((0, import_yaml4.isSeq)(oneOf)) {
|
|
1486
|
+
for (const x of oneOf.items)
|
|
1487
|
+
add(topic, x);
|
|
1488
|
+
return;
|
|
1489
|
+
}
|
|
1490
|
+
const payload = m.get("payload", true);
|
|
1491
|
+
const fields = [];
|
|
1492
|
+
propsOf(d, payload, "", 0, fields);
|
|
1493
|
+
const p = deref2(d, payload);
|
|
1494
|
+
const title = (0, import_yaml4.isMap)(p) ? p.get("title") : void 0;
|
|
1495
|
+
const name = m.get("name") ?? m.get("title") ?? title;
|
|
1496
|
+
out.push({
|
|
1497
|
+
kind: "message",
|
|
1498
|
+
format: "asyncapi",
|
|
1499
|
+
role: "schema",
|
|
1500
|
+
file: path,
|
|
1501
|
+
line: lineAt(d, m),
|
|
1502
|
+
topic,
|
|
1503
|
+
...typeof name === "string" && name ? { name } : {},
|
|
1504
|
+
fields
|
|
1505
|
+
});
|
|
1506
|
+
};
|
|
1507
|
+
for (const c of channels.items) {
|
|
1508
|
+
if (!(0, import_yaml4.isScalar)(c.key))
|
|
1509
|
+
continue;
|
|
1510
|
+
const ch = deref2(d, c.value);
|
|
1511
|
+
if (!(0, import_yaml4.isMap)(ch))
|
|
1512
|
+
continue;
|
|
1513
|
+
const address = ch.get("address");
|
|
1514
|
+
const topic = typeof address === "string" && address ? address : String(c.key.value);
|
|
1515
|
+
for (const op of ["publish", "subscribe"]) {
|
|
1516
|
+
const o = ch.get(op, true);
|
|
1517
|
+
if ((0, import_yaml4.isMap)(o))
|
|
1518
|
+
add(topic, o.get("message", true));
|
|
1519
|
+
}
|
|
1520
|
+
const msgs = ch.get("messages", true);
|
|
1521
|
+
if ((0, import_yaml4.isMap)(msgs))
|
|
1522
|
+
for (const m of msgs.items)
|
|
1523
|
+
add(topic, m.value);
|
|
1524
|
+
}
|
|
1525
|
+
return out;
|
|
1526
|
+
}
|
|
1527
|
+
function openApiContractSpecs(spec) {
|
|
1528
|
+
return spec.operations.map((o) => {
|
|
1529
|
+
const [file, line] = splitAt(o.cite, spec.path);
|
|
1530
|
+
const field2 = (side) => (f) => ({
|
|
1531
|
+
side,
|
|
1532
|
+
name: f.name,
|
|
1533
|
+
...f.type ? { type: f.type } : {},
|
|
1534
|
+
...f.required !== void 0 ? { required: f.required } : {},
|
|
1535
|
+
...f.in ? { in: f.in } : {},
|
|
1536
|
+
at: f.cite
|
|
1537
|
+
});
|
|
1538
|
+
return {
|
|
1539
|
+
kind: "operation",
|
|
1540
|
+
format: "openapi",
|
|
1541
|
+
role: "consumer",
|
|
1542
|
+
file,
|
|
1543
|
+
line,
|
|
1544
|
+
method: o.method,
|
|
1545
|
+
path: o.fullPath,
|
|
1546
|
+
id: o.id,
|
|
1547
|
+
fields: [...o.request.map(field2("request")), ...o.response.map(field2("response"))],
|
|
1548
|
+
...o.errors?.length ? { errors: o.errors.map((e) => ({ status: e.status, at: e.cite })) } : {}
|
|
1549
|
+
};
|
|
1550
|
+
});
|
|
1551
|
+
}
|
|
1552
|
+
function splitAt(cite, path) {
|
|
1553
|
+
const m = /^(.*):(\d+)$/.exec(cite);
|
|
1554
|
+
return m ? [m[1], Number(m[2])] : [path, 1];
|
|
1555
|
+
}
|
|
1556
|
+
function specFormatOf(name, text3) {
|
|
1557
|
+
const lower = name.toLowerCase();
|
|
1558
|
+
if (lower.endsWith(".proto"))
|
|
1559
|
+
return "protobuf";
|
|
1560
|
+
if (lower.endsWith(".avsc"))
|
|
1561
|
+
return "avro";
|
|
1562
|
+
if (!/\.(ya?ml|json)$/.test(lower))
|
|
1563
|
+
return void 0;
|
|
1564
|
+
const head = text3.slice(0, 4e3);
|
|
1565
|
+
if (/^\s*["']?(openapi|swagger)["']?\s*:/m.test(head))
|
|
1566
|
+
return "openapi";
|
|
1567
|
+
if (/^\s*["']?asyncapi["']?\s*:/m.test(head))
|
|
1568
|
+
return "asyncapi";
|
|
1569
|
+
if (/"type"\s*:\s*"record"/.test(head) && /"fields"\s*:/.test(head))
|
|
1570
|
+
return "avro";
|
|
1571
|
+
if (/["']?\$schema["']?\s*:/.test(head) && /json-schema\.org/.test(head))
|
|
1572
|
+
return "json-schema";
|
|
1573
|
+
return void 0;
|
|
1574
|
+
}
|
|
1575
|
+
function readContractSpecs(path, text3) {
|
|
1576
|
+
switch (specFormatOf(path, text3)) {
|
|
1577
|
+
case "protobuf":
|
|
1578
|
+
return readProtoSpecs(path, text3);
|
|
1579
|
+
case "avro":
|
|
1580
|
+
return readAvroSpecs(path, text3);
|
|
1581
|
+
case "json-schema":
|
|
1582
|
+
return readJsonSchemaSpecs(path, text3);
|
|
1583
|
+
case "asyncapi":
|
|
1584
|
+
return readAsyncApiSpecs(path, text3);
|
|
1585
|
+
case "openapi": {
|
|
1586
|
+
const spec = readVendorSpec(path, text3, "spec");
|
|
1587
|
+
return spec ? openApiContractSpecs(spec) : [];
|
|
1588
|
+
}
|
|
1589
|
+
default:
|
|
1590
|
+
return [];
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1593
|
+
var sameShape = (a, b) => normalizePath(a).replace(/\{[^}]*\}/g, "{}") === normalizePath(b).replace(/\{[^}]*\}/g, "{}");
|
|
1594
|
+
var SPEC_FILE = /\.(proto|avsc|ya?ml|json)$/i;
|
|
1595
|
+
function cmpPath(a, b) {
|
|
1596
|
+
const x = a.split("/");
|
|
1597
|
+
const y = b.split("/");
|
|
1598
|
+
for (let i = 0; i < Math.min(x.length, y.length); i++) {
|
|
1599
|
+
const c = cmp2(x[i], y[i]);
|
|
1600
|
+
if (c)
|
|
1601
|
+
return c;
|
|
1602
|
+
}
|
|
1603
|
+
return x.length - y.length;
|
|
1604
|
+
}
|
|
1605
|
+
var skipped = (p) => p.split("/").slice(0, -1).some((d) => SKIP.has(d) || d.startsWith("."));
|
|
1606
|
+
function folderTree(dir) {
|
|
1607
|
+
return {
|
|
1608
|
+
async files() {
|
|
1609
|
+
const out = [];
|
|
1610
|
+
const walk2 = async (rel) => {
|
|
1611
|
+
const entries = await readdir(join(dir, ...rel.split("/").filter(Boolean)), {
|
|
1612
|
+
withFileTypes: true
|
|
1613
|
+
}).catch(() => []);
|
|
1614
|
+
for (const e of [...entries].sort((a, b) => cmp2(a.name, b.name))) {
|
|
1615
|
+
const p = rel ? `${rel}/${e.name}` : e.name;
|
|
1616
|
+
if (e.isDirectory()) {
|
|
1617
|
+
if (!SKIP.has(e.name) && !e.name.startsWith("."))
|
|
1618
|
+
await walk2(p);
|
|
1619
|
+
} else if (e.isFile() && SPEC_FILE.test(e.name)) {
|
|
1620
|
+
const size = (await stat(join(dir, ...p.split("/"))).catch(() => void 0))?.size;
|
|
1621
|
+
out.push({ path: p, size: size ?? 0 });
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
};
|
|
1625
|
+
await walk2("");
|
|
1626
|
+
return out;
|
|
1627
|
+
},
|
|
1628
|
+
read: (p) => readFile(join(dir, ...p.split("/")), "utf8").catch(() => void 0)
|
|
1629
|
+
};
|
|
1630
|
+
}
|
|
1631
|
+
async function readRepoSpecs(dir, o) {
|
|
1632
|
+
const tree = o.tree ?? folderTree(dir);
|
|
1633
|
+
const files = (await tree.files()).filter((f) => SPEC_FILE.test(f.path) && !skipped(f.path) && f.size > 0 && f.size <= MAX_BYTES).sort((a, b) => cmpPath(a.path, b.path)).map((f) => f.path);
|
|
1634
|
+
const own = o.facts.filter((f) => f.kind === "entry" && f.entryType === "rest");
|
|
1635
|
+
const specs = [];
|
|
1636
|
+
for (const p of files) {
|
|
1637
|
+
const text3 = await tree.read(p);
|
|
1638
|
+
if (text3 === void 0 || !specFormatOf(p, text3))
|
|
1639
|
+
continue;
|
|
1640
|
+
const got = readContractSpecs(p, text3);
|
|
1641
|
+
if (!got.length)
|
|
1642
|
+
continue;
|
|
1643
|
+
if (o.denyHashes?.size && denyListHits(text3, o.denyHashes).length) {
|
|
1644
|
+
o.onRefused?.(`${p}: the deny-list names a word in it, so its specs are left out.`);
|
|
1645
|
+
continue;
|
|
1646
|
+
}
|
|
1647
|
+
for (const s of got) {
|
|
1648
|
+
if (s.kind !== "operation") {
|
|
1649
|
+
specs.push(s);
|
|
1650
|
+
continue;
|
|
1651
|
+
}
|
|
1652
|
+
const vendorPath = readVendorSpec(p, text3, "spec")?.operations.find((x) => x.id === s.id);
|
|
1653
|
+
const paths = [s.path ?? "", vendorPath?.path ?? ""].filter(Boolean);
|
|
1654
|
+
const entry = own.filter((e) => (!e.method || !s.method || e.method.toUpperCase() === s.method) && paths.some((x) => sameShape(x, e.path))).sort((a, b) => cmp2(a.id, b.id))[0];
|
|
1655
|
+
const { id: _id, ...rest } = s;
|
|
1656
|
+
specs.push(entry ? { ...rest, role: "own", entry: entry.id } : rest);
|
|
1657
|
+
}
|
|
1658
|
+
}
|
|
1659
|
+
return {
|
|
1660
|
+
schemaVersion: 1,
|
|
1661
|
+
repo: o.repo,
|
|
1662
|
+
...o.commit ? { commit: o.commit } : {},
|
|
1663
|
+
specs
|
|
1664
|
+
};
|
|
1665
|
+
}
|
|
1666
|
+
|
|
725
1667
|
// packages/intake/dist/scan-inputs.js
|
|
726
1668
|
var SPECS = ["openapi", "swagger", "asyncapi"];
|
|
727
1669
|
var EVIDENCE_SOURCE = {
|
|
728
1670
|
openapi: "spec",
|
|
729
1671
|
swagger: "spec",
|
|
730
1672
|
asyncapi: "spec",
|
|
1673
|
+
protobuf: "spec",
|
|
1674
|
+
avro: "spec",
|
|
731
1675
|
diagram: "diagram",
|
|
732
1676
|
image: "document",
|
|
733
1677
|
document: "document",
|
|
@@ -745,14 +1689,14 @@ async function walk(dir, skip) {
|
|
|
745
1689
|
return;
|
|
746
1690
|
let entries;
|
|
747
1691
|
try {
|
|
748
|
-
entries = await
|
|
1692
|
+
entries = await readdir2(d, { withFileTypes: true });
|
|
749
1693
|
} catch {
|
|
750
1694
|
return;
|
|
751
1695
|
}
|
|
752
1696
|
for (const e of entries.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0)) {
|
|
753
1697
|
if (e.name.startsWith("."))
|
|
754
1698
|
continue;
|
|
755
|
-
const full =
|
|
1699
|
+
const full = join2(d, e.name);
|
|
756
1700
|
if (e.isDirectory())
|
|
757
1701
|
await go(full);
|
|
758
1702
|
else if (e.isFile())
|
|
@@ -763,7 +1707,7 @@ async function walk(dir, skip) {
|
|
|
763
1707
|
return out;
|
|
764
1708
|
}
|
|
765
1709
|
var DATE = /(?:^|[-_ .])((\d{4})-?(\d{2})-?(\d{2}))(?=$|[-_ .])/;
|
|
766
|
-
var
|
|
1710
|
+
var VERSION2 = /(?:^|[-_ .])v(\d+(?:[._]\d+)*)(?=$|[-_ .])/i;
|
|
767
1711
|
function nameParts(stem) {
|
|
768
1712
|
let rest = stem;
|
|
769
1713
|
let date;
|
|
@@ -776,7 +1720,7 @@ function nameParts(stem) {
|
|
|
776
1720
|
}
|
|
777
1721
|
}
|
|
778
1722
|
let version;
|
|
779
|
-
const v =
|
|
1723
|
+
const v = VERSION2.exec(rest);
|
|
780
1724
|
if (v) {
|
|
781
1725
|
version = v[1].replace(/_/g, ".");
|
|
782
1726
|
rest = rest.replace(v[0], "");
|
|
@@ -802,23 +1746,23 @@ function systemsInName(stem, systems) {
|
|
|
802
1746
|
return systems.filter((sys) => [sys.id, sys.name, ...sys.aliases].some((n) => slug(n) && s.includes(`-${slug(n)}-`))).map((sys) => sys.id).sort();
|
|
803
1747
|
}
|
|
804
1748
|
async function scanInputs(o) {
|
|
805
|
-
const orgPackDir = typeof o.orgPack === "string" ? o.orgPack :
|
|
1749
|
+
const orgPackDir = typeof o.orgPack === "string" ? o.orgPack : join2(orgPackDirOf(o.root));
|
|
806
1750
|
const op = typeof o.orgPack === "object" ? o.orgPack : await loadOrgPack(orgPackDir);
|
|
807
1751
|
const systems = op.profiles.flatMap((p) => p.profile?.systems ?? []);
|
|
808
1752
|
const legend = op.profiles.find((p) => p.profile?.legend)?.profile?.legend;
|
|
809
1753
|
const records = o.records ?? [];
|
|
810
1754
|
const ingestors = o.ingestors ?? [drawioIngestor];
|
|
811
1755
|
const scannedAt = o.scannedAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
812
|
-
const inputsDir = o.inputsDir ??
|
|
1756
|
+
const inputsDir = o.inputsDir ?? join2(o.root, "inputs");
|
|
813
1757
|
const problems = [];
|
|
814
1758
|
const triage = [];
|
|
815
1759
|
const authors = /* @__PURE__ */ new Map();
|
|
816
1760
|
const wikiDirs = op.sources.wikis.flatMap((w) => /^[a-z][a-z0-9+.-]*:\/\//i.test(w.location) ? [] : [resolve(orgPackDir, w.location), resolve(o.root, w.location)]);
|
|
817
|
-
const st = await
|
|
1761
|
+
const st = await stat2(inputsDir).catch(() => void 0);
|
|
818
1762
|
const paths = st?.isDirectory() ? await walk(inputsDir, wikiDirs) : [];
|
|
819
1763
|
const files = [];
|
|
820
1764
|
for (const abs of paths) {
|
|
821
|
-
const bytes = new Uint8Array(await
|
|
1765
|
+
const bytes = new Uint8Array(await readFile2(abs));
|
|
822
1766
|
const path = `inputs/${posix(relative(inputsDir, abs))}`;
|
|
823
1767
|
const name = path.split("/").pop();
|
|
824
1768
|
const c = classify(name, bytes);
|
|
@@ -826,14 +1770,19 @@ async function scanInputs(o) {
|
|
|
826
1770
|
abs,
|
|
827
1771
|
path,
|
|
828
1772
|
bytes,
|
|
829
|
-
hash:
|
|
1773
|
+
hash: createHash5("sha256").update(bytes).digest("hex"),
|
|
830
1774
|
stem: name.includes(".") ? name.slice(0, name.lastIndexOf(".")) : name,
|
|
831
1775
|
inbox: path.startsWith("inputs/inbox/"),
|
|
832
1776
|
...c.data !== void 0 ? { data: c.data } : {},
|
|
1777
|
+
...c.text !== void 0 ? { text: c.text } : {},
|
|
833
1778
|
doc: {
|
|
834
1779
|
path,
|
|
835
1780
|
classification: c.classification,
|
|
836
|
-
status: "no-reader",
|
|
1781
|
+
status: c.unreadable ? "unreadable" : "no-reader",
|
|
1782
|
+
...c.unreadable ? {
|
|
1783
|
+
reason: `${c.unreadable.reason}${c.unreadable.line !== void 0 ? ` at ${c.unreadable.line}:${c.unreadable.column}` : ""}`
|
|
1784
|
+
} : {},
|
|
1785
|
+
...c.notes?.length ? { notes: c.notes } : {},
|
|
837
1786
|
hash: "",
|
|
838
1787
|
...c.title ? { title: c.title } : {},
|
|
839
1788
|
...c.version ? { version: c.version } : {},
|
|
@@ -896,7 +1845,7 @@ async function scanInputs(o) {
|
|
|
896
1845
|
const heads = members.filter((m) => !m.doc.supersededBy);
|
|
897
1846
|
if (heads.length < 2)
|
|
898
1847
|
continue;
|
|
899
|
-
const distinct = (vals,
|
|
1848
|
+
const distinct = (vals, cmp5) => vals.every((v) => v !== void 0) && vals.every((v, i) => vals.every((w, j) => i === j || cmp5(v, w) !== 0));
|
|
900
1849
|
const byVersion = distinct(heads.map((h) => h.doc.version), compareVersions);
|
|
901
1850
|
const byDate = !byVersion && distinct(heads.map((h) => h.doc.date), (a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
902
1851
|
if (byVersion || byDate) {
|
|
@@ -939,7 +1888,7 @@ async function scanInputs(o) {
|
|
|
939
1888
|
for (const f of kept) {
|
|
940
1889
|
const cls = f.doc.classification;
|
|
941
1890
|
const current = !f.doc.supersededBy;
|
|
942
|
-
const text3 = () => new TextDecoder().decode(f.bytes);
|
|
1891
|
+
const text3 = () => f.text ?? new TextDecoder().decode(f.bytes);
|
|
943
1892
|
const linked = /* @__PURE__ */ new Set();
|
|
944
1893
|
const unknown = /* @__PURE__ */ new Set();
|
|
945
1894
|
if (SPECS.includes(cls)) {
|
|
@@ -1053,6 +2002,43 @@ async function scanInputs(o) {
|
|
|
1053
2002
|
} catch {
|
|
1054
2003
|
}
|
|
1055
2004
|
}
|
|
2005
|
+
if (cls === "protobuf" || cls === "avro") {
|
|
2006
|
+
const specs = cls === "protobuf" ? readProtoSpecs(f.path, text3()) : readAvroSpecs(f.path, text3());
|
|
2007
|
+
const named = new Set(systemsInName(f.stem, systems));
|
|
2008
|
+
for (const s of specs) {
|
|
2009
|
+
const res = s.name ? resolveName(s.name.split(".").slice(0, -1).join(" ")) : void 0;
|
|
2010
|
+
if (res?.id && !named.size)
|
|
2011
|
+
named.add(systemOf(res.id));
|
|
2012
|
+
}
|
|
2013
|
+
for (const s of named)
|
|
2014
|
+
linked.add(s);
|
|
2015
|
+
if (current && specs.length) {
|
|
2016
|
+
for (const s of specs) {
|
|
2017
|
+
const p = parseRecord({
|
|
2018
|
+
schemaVersion: 1,
|
|
2019
|
+
kind: "Schema",
|
|
2020
|
+
id: boundedId("schema.", slug(s.name ?? f.stem)),
|
|
2021
|
+
status: "current",
|
|
2022
|
+
confidence: "verified",
|
|
2023
|
+
format: cls,
|
|
2024
|
+
ref: `${f.path}#${s.name ?? ""}`,
|
|
2025
|
+
fields: s.fields.map((x) => ({
|
|
2026
|
+
name: x.name,
|
|
2027
|
+
...x.type ? { type: x.type } : {},
|
|
2028
|
+
...x.required !== void 0 ? { required: x.required } : {}
|
|
2029
|
+
})),
|
|
2030
|
+
evidence: [{ source: "spec", path: f.path, line: s.line, side: "definition" }]
|
|
2031
|
+
});
|
|
2032
|
+
if (!p.ok)
|
|
2033
|
+
continue;
|
|
2034
|
+
const schema = p.record;
|
|
2035
|
+
out.push(schema);
|
|
2036
|
+
f.doc.records.push(schema.id);
|
|
2037
|
+
}
|
|
2038
|
+
f.doc.status = "read";
|
|
2039
|
+
f.doc.reader = cls === "protobuf" ? READERS.protobuf : READERS.avro;
|
|
2040
|
+
}
|
|
2041
|
+
}
|
|
1056
2042
|
if (current && cls === "payload" && f.data !== void 0) {
|
|
1057
2043
|
const schema = readPayload(f.path, boundedId("payload.", f.doc.id.slice(4)), f.data);
|
|
1058
2044
|
out.push(schema);
|
|
@@ -1249,9 +2235,9 @@ function safeSniff(ing, path, head) {
|
|
|
1249
2235
|
return 0;
|
|
1250
2236
|
}
|
|
1251
2237
|
}
|
|
1252
|
-
function lineOf(text3,
|
|
2238
|
+
function lineOf(text3, key3) {
|
|
1253
2239
|
const lines = text3.split(/\r?\n/);
|
|
1254
|
-
const re = new RegExp(`(^|[\\s{,])"?${
|
|
2240
|
+
const re = new RegExp(`(^|[\\s{,])"?${key3}"?\\s*:`);
|
|
1255
2241
|
const i = lines.findIndex((l) => re.test(l));
|
|
1256
2242
|
return i >= 0 ? { line: i + 1 } : {};
|
|
1257
2243
|
}
|
|
@@ -1362,11 +2348,11 @@ function imageItems(records) {
|
|
|
1362
2348
|
};
|
|
1363
2349
|
});
|
|
1364
2350
|
}
|
|
1365
|
-
var
|
|
2351
|
+
var key2 = (action, target, value) => `${action}|${target}|${JSON.stringify(value ?? null)}`;
|
|
1366
2352
|
function buildTriage(input) {
|
|
1367
2353
|
const decisions = (input.decisions ?? []).filter((d) => d.kind === "CuratedDecision" && d.status === "current");
|
|
1368
2354
|
const decidedIds = new Set(decisions.map((d) => d.id));
|
|
1369
|
-
const decidedKeys = new Set(decisions.map((d) =>
|
|
2355
|
+
const decidedKeys = new Set(decisions.map((d) => key2(d.action, d.target, d.value)));
|
|
1370
2356
|
const docs = new Map((input.inputs?.documents ?? []).map((d) => [d.path, d.id]));
|
|
1371
2357
|
const docIdOf = (path) => docs.get(path) ?? boundedId("doc.", slug(path.split("/").pop().replace(/\.[^.]+$/, "")));
|
|
1372
2358
|
const records = input.records;
|
|
@@ -1379,7 +2365,7 @@ function buildTriage(input) {
|
|
|
1379
2365
|
...imageItems([...records, ...inputRecords]),
|
|
1380
2366
|
...readingItems(input)
|
|
1381
2367
|
];
|
|
1382
|
-
const open = all.filter((i) => !i.options.some((o) => decidedIds.has(o.decision.id) || decidedKeys.has(
|
|
2368
|
+
const open = all.filter((i) => !i.options.some((o) => decidedIds.has(o.decision.id) || decidedKeys.has(key2(o.decision.action, o.decision.target, o.decision.value))));
|
|
1383
2369
|
const items = sortItems(open);
|
|
1384
2370
|
return {
|
|
1385
2371
|
items,
|
|
@@ -1420,9 +2406,9 @@ function buildTriage(input) {
|
|
|
1420
2406
|
}
|
|
1421
2407
|
|
|
1422
2408
|
// packages/intake/dist/work-items.js
|
|
1423
|
-
var
|
|
1424
|
-
import { readdir as
|
|
1425
|
-
import { join as
|
|
2409
|
+
var import_yaml5 = __toESM(require_dist(), 1);
|
|
2410
|
+
import { readdir as readdir3, readFile as readFile3 } from "node:fs/promises";
|
|
2411
|
+
import { join as join3, relative as relative2, sep as sep2 } from "node:path";
|
|
1426
2412
|
var WORK_ITEM_READER = "work-items@0.1.0";
|
|
1427
2413
|
var isObj3 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
1428
2414
|
var text = (v) => {
|
|
@@ -1528,7 +2514,7 @@ function itemOf(o, path, lineOf2) {
|
|
|
1528
2514
|
source: { path, ...line ? { line } : {} }
|
|
1529
2515
|
};
|
|
1530
2516
|
}
|
|
1531
|
-
function
|
|
2517
|
+
function parseCsv2(s) {
|
|
1532
2518
|
const rows = [];
|
|
1533
2519
|
let row = [];
|
|
1534
2520
|
let cell = "";
|
|
@@ -1572,7 +2558,7 @@ function parseCsv(s) {
|
|
|
1572
2558
|
return rows;
|
|
1573
2559
|
}
|
|
1574
2560
|
function fromCsv(textIn, path) {
|
|
1575
|
-
const rows =
|
|
2561
|
+
const rows = parseCsv2(textIn.replace(/^\uFEFF/, ""));
|
|
1576
2562
|
const header = rows[0]?.cells.map((h) => h.trim());
|
|
1577
2563
|
if (!header)
|
|
1578
2564
|
return void 0;
|
|
@@ -1601,7 +2587,7 @@ function readWorkItemExport(path, bytes) {
|
|
|
1601
2587
|
return void 0;
|
|
1602
2588
|
let data;
|
|
1603
2589
|
try {
|
|
1604
|
-
data = (0,
|
|
2590
|
+
data = (0, import_yaml5.parse)(content);
|
|
1605
2591
|
} catch {
|
|
1606
2592
|
return void 0;
|
|
1607
2593
|
}
|
|
@@ -1624,22 +2610,22 @@ function readWorkItemExport(path, bytes) {
|
|
|
1624
2610
|
return items;
|
|
1625
2611
|
}
|
|
1626
2612
|
async function readWorkItemExports(o) {
|
|
1627
|
-
const dir = o.inputsDir ??
|
|
2613
|
+
const dir = o.inputsDir ?? join3(o.root, "inputs");
|
|
1628
2614
|
const files = [];
|
|
1629
2615
|
async function walk2(d) {
|
|
1630
2616
|
let entries;
|
|
1631
2617
|
try {
|
|
1632
|
-
entries = await
|
|
2618
|
+
entries = await readdir3(d, { withFileTypes: true });
|
|
1633
2619
|
} catch {
|
|
1634
2620
|
return;
|
|
1635
2621
|
}
|
|
1636
2622
|
for (const e of entries.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0)) {
|
|
1637
2623
|
if (e.name.startsWith("."))
|
|
1638
2624
|
continue;
|
|
1639
|
-
const full =
|
|
2625
|
+
const full = join3(d, e.name);
|
|
1640
2626
|
if (e.isDirectory())
|
|
1641
2627
|
await walk2(full);
|
|
1642
|
-
else if (/\.(json|ya?ml|csv)$/i.test(e.name))
|
|
2628
|
+
else if (e.isFile() && /\.(json|ya?ml|csv)$/i.test(e.name))
|
|
1643
2629
|
files.push(full);
|
|
1644
2630
|
}
|
|
1645
2631
|
}
|
|
@@ -1653,7 +2639,7 @@ async function readWorkItemExports(o) {
|
|
|
1653
2639
|
const path = `inputs/${relative2(dir, full).split(sep2).join("/")}`;
|
|
1654
2640
|
let bytes;
|
|
1655
2641
|
try {
|
|
1656
|
-
bytes = new Uint8Array(await
|
|
2642
|
+
bytes = new Uint8Array(await readFile3(full));
|
|
1657
2643
|
} catch (e) {
|
|
1658
2644
|
out.problems.push({ path, message: `can't read it: ${e.message}` });
|
|
1659
2645
|
continue;
|
|
@@ -1668,9 +2654,9 @@ async function readWorkItemExports(o) {
|
|
|
1668
2654
|
}
|
|
1669
2655
|
|
|
1670
2656
|
// packages/intake/dist/service-requests.js
|
|
1671
|
-
var
|
|
1672
|
-
import { readdir as
|
|
1673
|
-
import { join as
|
|
2657
|
+
var import_yaml6 = __toESM(require_dist(), 1);
|
|
2658
|
+
import { readdir as readdir4, readFile as readFile4 } from "node:fs/promises";
|
|
2659
|
+
import { join as join4, relative as relative3, sep as sep3 } from "node:path";
|
|
1674
2660
|
var SERVICE_REQUEST_READER = "service-requests@0.1.0";
|
|
1675
2661
|
var isObj4 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
1676
2662
|
var text2 = (v) => {
|
|
@@ -1821,7 +2807,7 @@ function readServiceRequestExport(path, bytes) {
|
|
|
1821
2807
|
return void 0;
|
|
1822
2808
|
let data;
|
|
1823
2809
|
try {
|
|
1824
|
-
data = (0,
|
|
2810
|
+
data = (0, import_yaml6.parse)(content);
|
|
1825
2811
|
} catch {
|
|
1826
2812
|
return void 0;
|
|
1827
2813
|
}
|
|
@@ -1851,22 +2837,22 @@ function readServiceRequestExport(path, bytes) {
|
|
|
1851
2837
|
return out;
|
|
1852
2838
|
}
|
|
1853
2839
|
async function readServiceRequestExports(o) {
|
|
1854
|
-
const dir = o.inputsDir ??
|
|
2840
|
+
const dir = o.inputsDir ?? join4(o.root, "inputs");
|
|
1855
2841
|
const found = [];
|
|
1856
2842
|
async function walk2(d) {
|
|
1857
2843
|
let entries;
|
|
1858
2844
|
try {
|
|
1859
|
-
entries = await
|
|
2845
|
+
entries = await readdir4(d, { withFileTypes: true });
|
|
1860
2846
|
} catch {
|
|
1861
2847
|
return;
|
|
1862
2848
|
}
|
|
1863
2849
|
for (const e of entries.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0)) {
|
|
1864
2850
|
if (e.name.startsWith("."))
|
|
1865
2851
|
continue;
|
|
1866
|
-
const full =
|
|
2852
|
+
const full = join4(d, e.name);
|
|
1867
2853
|
if (e.isDirectory())
|
|
1868
2854
|
await walk2(full);
|
|
1869
|
-
else if (/\.(json|ya?ml|csv)$/i.test(e.name))
|
|
2855
|
+
else if (e.isFile() && /\.(json|ya?ml|csv)$/i.test(e.name))
|
|
1870
2856
|
found.push(full);
|
|
1871
2857
|
}
|
|
1872
2858
|
}
|
|
@@ -1880,7 +2866,7 @@ async function readServiceRequestExports(o) {
|
|
|
1880
2866
|
const path = `inputs/${relative3(dir, full).split(sep3).join("/")}`;
|
|
1881
2867
|
let bytes;
|
|
1882
2868
|
try {
|
|
1883
|
-
bytes = new Uint8Array(await
|
|
2869
|
+
bytes = new Uint8Array(await readFile4(full));
|
|
1884
2870
|
} catch (e) {
|
|
1885
2871
|
out.problems.push({ path, message: `can't read it: ${e.message}` });
|
|
1886
2872
|
continue;
|
|
@@ -1895,15 +2881,15 @@ async function readServiceRequestExports(o) {
|
|
|
1895
2881
|
}
|
|
1896
2882
|
|
|
1897
2883
|
// packages/intake/dist/change-inputs.js
|
|
1898
|
-
var
|
|
1899
|
-
import { createHash as
|
|
1900
|
-
import { mkdir, readdir as
|
|
1901
|
-
import { join as
|
|
2884
|
+
var import_yaml7 = __toESM(require_dist(), 1);
|
|
2885
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
2886
|
+
import { mkdir, readdir as readdir5, readFile as readFile5 } from "node:fs/promises";
|
|
2887
|
+
import { join as join5 } from "node:path";
|
|
1902
2888
|
var INPUTS_DIR = "inputs";
|
|
1903
2889
|
var INPUTS_INDEX = "inputs/index.yaml";
|
|
1904
2890
|
var INPUTS_READ_DIR = "inputs/read";
|
|
1905
2891
|
var CHANGE_INPUTS_SCHEMA_VERSION = 1;
|
|
1906
|
-
var sha256 = (b) =>
|
|
2892
|
+
var sha256 = (b) => createHash6("sha256").update(b).digest("hex");
|
|
1907
2893
|
var KEYS = [
|
|
1908
2894
|
"path",
|
|
1909
2895
|
"name",
|
|
@@ -1923,10 +2909,10 @@ var KEYS = [
|
|
|
1923
2909
|
"defences"
|
|
1924
2910
|
];
|
|
1925
2911
|
async function readChangeInputs(dir) {
|
|
1926
|
-
const text3 = await
|
|
2912
|
+
const text3 = await readFile5(join5(dir, ...INPUTS_INDEX.split("/")), "utf8").catch(() => "");
|
|
1927
2913
|
let data;
|
|
1928
2914
|
try {
|
|
1929
|
-
data = text3 ? (0,
|
|
2915
|
+
data = text3 ? (0, import_yaml7.parse)(text3) : void 0;
|
|
1930
2916
|
} catch {
|
|
1931
2917
|
data = void 0;
|
|
1932
2918
|
}
|
|
@@ -1947,7 +2933,7 @@ async function writeIndex(dir, index) {
|
|
|
1947
2933
|
o[k] = f[k];
|
|
1948
2934
|
return o;
|
|
1949
2935
|
});
|
|
1950
|
-
await writeFileAtomic(
|
|
2936
|
+
await writeFileAtomic(join5(dir, ...INPUTS_INDEX.split("/")), `# Files attached to this change (ADR 0113): atticus change attach writes this file.
|
|
1951
2937
|
${toCanonicalYaml({ schemaVersion: index.schemaVersion, files }, ["schemaVersion", "files"])}`);
|
|
1952
2938
|
}
|
|
1953
2939
|
var isText = (b) => {
|
|
@@ -2038,7 +3024,7 @@ function readText(input, bytes, older) {
|
|
|
2038
3024
|
async function attachToChange(dir, files, o) {
|
|
2039
3025
|
const index = await readChangeInputs(dir);
|
|
2040
3026
|
const out = { added: [], refused: [], notes: [] };
|
|
2041
|
-
const taken = new Set(await
|
|
3027
|
+
const taken = new Set((await readdir5(join5(dir, INPUTS_DIR)).catch(() => [])).map((n) => n.toLowerCase()));
|
|
2042
3028
|
taken.add("index.yaml").add("read");
|
|
2043
3029
|
const replaced = o.replaces ? index.files.find((x) => x.path === o.replaces.trim().replace(/\\/g, "/")) : void 0;
|
|
2044
3030
|
let changed = false;
|
|
@@ -2076,9 +3062,9 @@ async function attachToChange(dir, files, o) {
|
|
|
2076
3062
|
const dot = safe.lastIndexOf(".");
|
|
2077
3063
|
const [stem, ext] = dot > 0 ? [safe.slice(0, dot), safe.slice(dot)] : [safe, ""];
|
|
2078
3064
|
let target = safe;
|
|
2079
|
-
for (let n = 2; taken.has(target); n++)
|
|
3065
|
+
for (let n = 2; taken.has(target.toLowerCase()); n++)
|
|
2080
3066
|
target = `${stem}-${n}${ext}`;
|
|
2081
|
-
taken.add(target);
|
|
3067
|
+
taken.add(target.toLowerCase());
|
|
2082
3068
|
const found = classify(target, f.bytes).classification;
|
|
2083
3069
|
const { format, citeBy } = formatOf2(target, f.bytes, found);
|
|
2084
3070
|
const kind = found === "unknown" && citeBy ? "document" : found;
|
|
@@ -2125,11 +3111,11 @@ async function attachToChange(dir, files, o) {
|
|
|
2125
3111
|
const where = o.elsewhere?.(hash);
|
|
2126
3112
|
if (where)
|
|
2127
3113
|
out.notes.push(`${name} is also in the metarepo's inputs as ${where}.`);
|
|
2128
|
-
await mkdir(
|
|
2129
|
-
await writeFileAtomic(
|
|
3114
|
+
await mkdir(join5(dir, INPUTS_DIR), { recursive: true });
|
|
3115
|
+
await writeFileAtomic(join5(dir, INPUTS_DIR, target), f.bytes);
|
|
2130
3116
|
const text3 = readText(input, f.bytes, older);
|
|
2131
3117
|
if (text3 !== void 0)
|
|
2132
|
-
await writeFileAtomic(
|
|
3118
|
+
await writeFileAtomic(join5(dir, ...input.readAs.split("/")), text3);
|
|
2133
3119
|
index.files.push(input);
|
|
2134
3120
|
out.added.push(input);
|
|
2135
3121
|
}
|
|
@@ -2155,7 +3141,7 @@ async function changeInputSources(dir, rel) {
|
|
|
2155
3141
|
for (const f of (await readChangeInputs(dir)).files) {
|
|
2156
3142
|
if (f.supersededBy || f.defences?.risk === "high")
|
|
2157
3143
|
continue;
|
|
2158
|
-
const read = f.readAs ? await
|
|
3144
|
+
const read = f.readAs ? await readFile5(join5(dir, ...f.readAs.split("/")), "utf8").catch(() => void 0) : void 0;
|
|
2159
3145
|
const text3 = read ?? `${f.path} (${f.name}) is ${f.kind === "image" ? "a picture; Atticus doesn't read pictures" : `a ${f.format} file no reader takes`}. Open it to see it; say what you rely on from it, citing ${f.path}.`;
|
|
2160
3146
|
out.push({
|
|
2161
3147
|
id: f.path,
|
|
@@ -2179,9 +3165,12 @@ var KIND_ORDER2 = [
|
|
|
2179
3165
|
"field-added",
|
|
2180
3166
|
"field-required",
|
|
2181
3167
|
"field-type",
|
|
2182
|
-
"field-enum"
|
|
3168
|
+
"field-enum",
|
|
3169
|
+
"error-added",
|
|
3170
|
+
"error-schema",
|
|
3171
|
+
"error-removed"
|
|
2183
3172
|
];
|
|
2184
|
-
var
|
|
3173
|
+
var cmp3 = (a, b) => a < b ? -1 : a > b ? 1 : 0;
|
|
2185
3174
|
var opKey = (o) => `${o.method} ${normalizePath(o.fullPath)}`;
|
|
2186
3175
|
var opName = (o) => `${o.method} ${o.path}`;
|
|
2187
3176
|
var list = (xs) => xs.length <= 1 ? xs[0] ?? "" : `${xs.slice(0, -1).join(", ")} and ${xs.at(-1)}`;
|
|
@@ -2246,16 +3235,21 @@ function diffVendorSpecs(older, newer) {
|
|
|
2246
3235
|
});
|
|
2247
3236
|
for (const [o, n] of pairs)
|
|
2248
3237
|
out.push(...operationChanges(o, n));
|
|
2249
|
-
return out.sort((a, b) =>
|
|
3238
|
+
return out.sort((a, b) => cmp3(a.severity === "breaking" ? "0" : "1", b.severity === "breaking" ? "0" : "1") || cmp3(a.operation.path, b.operation.path) || cmp3(a.operation.method, b.operation.method) || KIND_ORDER2.indexOf(a.kind) - KIND_ORDER2.indexOf(b.kind) || cmp3(a.side ?? "", b.side ?? "") || cmp3(a.field ?? "", b.field ?? ""));
|
|
2250
3239
|
}
|
|
2251
3240
|
var opOf = (o) => ({
|
|
2252
3241
|
method: o.method,
|
|
2253
3242
|
path: o.path,
|
|
2254
3243
|
...o.operationId ? { operationId: o.operationId } : {}
|
|
2255
3244
|
});
|
|
2256
|
-
function changeId(kind, o, side, field2) {
|
|
3245
|
+
function changeId(kind, o, side, field2, status) {
|
|
2257
3246
|
const op = slug(`${o.method} ${o.path}`);
|
|
2258
|
-
return [
|
|
3247
|
+
return [
|
|
3248
|
+
kind,
|
|
3249
|
+
op,
|
|
3250
|
+
...status ? [status] : [],
|
|
3251
|
+
...side && field2 ? [side, slug(field2)] : []
|
|
3252
|
+
].join(".");
|
|
2259
3253
|
}
|
|
2260
3254
|
function operationChanges(o, n) {
|
|
2261
3255
|
const out = [];
|
|
@@ -2291,15 +3285,61 @@ function operationChanges(o, n) {
|
|
|
2291
3285
|
}
|
|
2292
3286
|
for (const side of ["request", "response"])
|
|
2293
3287
|
out.push(...fieldChanges(o[side], n[side], side, at, base));
|
|
3288
|
+
out.push(...errorChanges(o, n, at));
|
|
3289
|
+
return out;
|
|
3290
|
+
}
|
|
3291
|
+
function errorChanges(o, n, at) {
|
|
3292
|
+
const out = [];
|
|
3293
|
+
const olds = new Map((o.errors ?? []).map((e) => [e.status, e]));
|
|
3294
|
+
const news = new Map((n.errors ?? []).map((e) => [e.status, e]));
|
|
3295
|
+
const head = (kind, status) => ({
|
|
3296
|
+
id: changeId(kind, n, void 0, void 0, status),
|
|
3297
|
+
kind,
|
|
3298
|
+
operation: opOf(n),
|
|
3299
|
+
endpoints: { older: o.id, newer: n.id },
|
|
3300
|
+
status
|
|
3301
|
+
});
|
|
3302
|
+
for (const [status, e] of news)
|
|
3303
|
+
if (!olds.has(status))
|
|
3304
|
+
out.push({
|
|
3305
|
+
...head("error-added", status),
|
|
3306
|
+
severity: "breaking",
|
|
3307
|
+
after: { value: status, cite: e.cite },
|
|
3308
|
+
says: `${at}: it may now answer ${status}; a caller that doesn't handle ${status} must.`
|
|
3309
|
+
});
|
|
3310
|
+
for (const [status, e] of olds)
|
|
3311
|
+
if (!news.has(status))
|
|
3312
|
+
out.push({
|
|
3313
|
+
...head("error-removed", status),
|
|
3314
|
+
severity: "additive",
|
|
3315
|
+
before: { value: status, cite: e.cite },
|
|
3316
|
+
says: `${at}: it no longer answers ${status}; no caller has to change.`
|
|
3317
|
+
});
|
|
3318
|
+
for (const [status, a] of olds) {
|
|
3319
|
+
const b = news.get(status);
|
|
3320
|
+
if (!b)
|
|
3321
|
+
continue;
|
|
3322
|
+
const base = (_kind, side, field2) => ({
|
|
3323
|
+
id: changeId("error-schema", n, side, field2, status),
|
|
3324
|
+
kind: "error-schema",
|
|
3325
|
+
operation: opOf(n),
|
|
3326
|
+
endpoints: { older: o.id, newer: n.id },
|
|
3327
|
+
...side ? { side } : {},
|
|
3328
|
+
...field2 ? { field: field2 } : {},
|
|
3329
|
+
status
|
|
3330
|
+
});
|
|
3331
|
+
out.push(...fieldChanges(a.fields ?? [], b.fields ?? [], "response", `${at} (its ${status} response)`, base));
|
|
3332
|
+
}
|
|
2294
3333
|
return out;
|
|
2295
3334
|
}
|
|
2296
3335
|
function fieldChanges(olds, news, side, at, base) {
|
|
2297
3336
|
const out = [];
|
|
2298
|
-
const
|
|
2299
|
-
const
|
|
2300
|
-
const
|
|
2301
|
-
|
|
2302
|
-
let
|
|
3337
|
+
const what = (f) => `${side} ${f.in === "header" ? "header" : "field"}`;
|
|
3338
|
+
const key3 = (f) => `${f.in}|${f.name}`;
|
|
3339
|
+
const byOld = new Map(olds.map((f) => [key3(f), f]));
|
|
3340
|
+
const byNew = new Map(news.map((f) => [key3(f), f]));
|
|
3341
|
+
let removed = olds.filter((f) => !byNew.has(key3(f)));
|
|
3342
|
+
let added = news.filter((f) => !byOld.has(key3(f)));
|
|
2303
3343
|
const req = side === "request";
|
|
2304
3344
|
const parent = (f) => `${f.in}|${f.name.includes(".") ? f.name.slice(0, f.name.lastIndexOf(".")) : ""}`;
|
|
2305
3345
|
const renamed = [];
|
|
@@ -2317,7 +3357,7 @@ function fieldChanges(olds, news, side, at, base) {
|
|
|
2317
3357
|
severity: "breaking",
|
|
2318
3358
|
before: { value: r.name, cite: r.cite },
|
|
2319
3359
|
after: { value: a.name, cite: a.cite },
|
|
2320
|
-
says: `${at}: the ${
|
|
3360
|
+
says: `${at}: the ${what(r)} ${r.name} is now ${a.name}; ${req ? `a caller that still sends ${r.name} no longer sets it` : `a caller that reads ${r.name} gets nothing`}.`
|
|
2321
3361
|
});
|
|
2322
3362
|
}
|
|
2323
3363
|
removed = removed.filter((f) => !renamed.some(([r]) => r === f));
|
|
@@ -2329,7 +3369,7 @@ function fieldChanges(olds, news, side, at, base) {
|
|
|
2329
3369
|
...base("field-removed", side, f.name),
|
|
2330
3370
|
severity: "breaking",
|
|
2331
3371
|
before: { value: f.name, cite: f.cite },
|
|
2332
|
-
says: req ? `${at}: the
|
|
3372
|
+
says: req ? `${at}: the ${what(f)} ${f.name} is gone; a caller that sends it may be refused, and what it meant is lost.` : `${at}: the ${what(f)} ${f.name} is gone; a caller that reads it gets nothing.`
|
|
2333
3373
|
});
|
|
2334
3374
|
for (const f of topAdded) {
|
|
2335
3375
|
const breaks = req && f.required === true;
|
|
@@ -2337,7 +3377,7 @@ function fieldChanges(olds, news, side, at, base) {
|
|
|
2337
3377
|
...base("field-added", side, f.name),
|
|
2338
3378
|
severity: breaks ? "breaking" : "additive",
|
|
2339
3379
|
after: { value: f.name, cite: f.requiredCite ?? f.cite },
|
|
2340
|
-
says: !req ? `${at}: the response has a new field ${f.name}; no caller has to change.` : breaks ? `${at}: the request needs a new field ${f.name}; a caller that doesn't send it is refused.` : `${at}: the request takes a new optional field ${f.name}; no caller has to change.`
|
|
3380
|
+
says: !req ? `${at}: the response has a new ${f.in === "header" ? "header" : "field"} ${f.name}; no caller has to change.` : breaks ? `${at}: the request needs a new ${f.in === "header" ? "header" : "field"} ${f.name}; a caller that doesn't send it is refused.` : `${at}: the request takes a new optional ${f.in === "header" ? "header" : "field"} ${f.name}; no caller has to change.`
|
|
2341
3381
|
});
|
|
2342
3382
|
}
|
|
2343
3383
|
for (const [k, a] of byOld) {
|
|
@@ -2352,7 +3392,7 @@ function fieldChanges(olds, news, side, at, base) {
|
|
|
2352
3392
|
severity: breaks ? "breaking" : "additive",
|
|
2353
3393
|
before: { value: a.required ? "required" : "optional", cite: a.requiredCite ?? a.cite },
|
|
2354
3394
|
after: { value: b.required ? "required" : "optional", cite: b.requiredCite ?? b.cite },
|
|
2355
|
-
says: req ? nowRequired ? `${at}: the
|
|
3395
|
+
says: req ? nowRequired ? `${at}: the ${what(a)} ${a.name} is now required; a caller that leaves it out is refused.` : `${at}: the ${what(a)} ${a.name} is now optional; no caller has to change.` : nowRequired ? `${at}: the ${what(a)} ${a.name} is now always there; no caller has to change.` : `${at}: the ${what(a)} ${a.name} may now be left out; a caller that counts on it must allow for that.`
|
|
2356
3396
|
});
|
|
2357
3397
|
}
|
|
2358
3398
|
if (a.type && b.type && a.type !== b.type)
|
|
@@ -2361,7 +3401,7 @@ function fieldChanges(olds, news, side, at, base) {
|
|
|
2361
3401
|
severity: "breaking",
|
|
2362
3402
|
before: { value: a.type, cite: a.cite },
|
|
2363
3403
|
after: { value: b.type, cite: b.cite },
|
|
2364
|
-
says: `${at}: the ${
|
|
3404
|
+
says: `${at}: the ${what(a)} ${a.name} was ${a.type} and is now ${b.type}; a caller that ${req ? "sends" : "reads"} it must change.`
|
|
2365
3405
|
});
|
|
2366
3406
|
if (a.enum || b.enum) {
|
|
2367
3407
|
const was = a.enum ?? [];
|
|
@@ -2371,7 +3411,7 @@ function fieldChanges(olds, news, side, at, base) {
|
|
|
2371
3411
|
if (!gained.length && !lost.length)
|
|
2372
3412
|
continue;
|
|
2373
3413
|
const breaks = req ? lost.length > 0 : gained.length > 0;
|
|
2374
|
-
const words = req ? lost.length ? `${at}: the
|
|
3414
|
+
const words = req ? lost.length ? `${at}: the ${what(a)} ${a.name} no longer takes ${list(lost)}${gained.length ? ` and now takes ${list(gained)}` : ""}; a caller that sends a value it no longer takes is refused.` : `${at}: the ${what(a)} ${a.name} now also takes ${list(gained)}; no caller has to change.` : gained.length ? `${at}: the ${what(a)} ${a.name} may now be ${orList(gained)}; a caller that reads it must handle the new value${gained.length > 1 ? "s" : ""}.` : `${at}: the ${what(a)} ${a.name} no longer returns ${list(lost)}; no caller has to change.`;
|
|
2375
3415
|
out.push({
|
|
2376
3416
|
...base("field-enum", side, a.name),
|
|
2377
3417
|
severity: breaks ? "breaking" : "additive",
|
|
@@ -2386,12 +3426,13 @@ function fieldChanges(olds, news, side, at, base) {
|
|
|
2386
3426
|
|
|
2387
3427
|
// packages/intake/dist/vendor-impact.js
|
|
2388
3428
|
var MAX_UPSTREAM = 4;
|
|
2389
|
-
var
|
|
3429
|
+
var cmp4 = (a, b) => a < b ? -1 : a > b ? 1 : 0;
|
|
2390
3430
|
var sorted = (xs) => [...new Set(xs)].sort();
|
|
2391
3431
|
var joinVendorOf = (input, spec) => ({
|
|
2392
3432
|
system: input.vendor.system,
|
|
2393
3433
|
names: input.vendor.names,
|
|
2394
3434
|
hosts: [.../* @__PURE__ */ new Set([...spec.hosts, ...input.vendor.hosts ?? []])],
|
|
3435
|
+
...input.vendor.boundary ? { boundary: input.vendor.boundary } : {},
|
|
2395
3436
|
operations: spec.operations.map((o) => ({
|
|
2396
3437
|
id: o.id,
|
|
2397
3438
|
method: o.method,
|
|
@@ -2407,20 +3448,24 @@ var versionOf = (v) => ({
|
|
|
2407
3448
|
});
|
|
2408
3449
|
function vendorImpact(input) {
|
|
2409
3450
|
const diff = diffVendorSpecs(input.older.spec, input.newer.spec);
|
|
2410
|
-
const
|
|
3451
|
+
const bundle = input.bundleFolders ? { bundleFolders: input.bundleFolders } : {};
|
|
3452
|
+
const join7 = joinFacts({
|
|
2411
3453
|
repos: input.repos,
|
|
2412
3454
|
...input.targets ? { targets: input.targets } : {},
|
|
2413
|
-
...input.facing ? { facing: input.facing } : {}
|
|
3455
|
+
...input.facing ? { facing: input.facing } : {},
|
|
3456
|
+
...bundle
|
|
2414
3457
|
});
|
|
2415
3458
|
const today = joinVendorOperations({
|
|
2416
3459
|
repos: input.repos,
|
|
2417
3460
|
vendors: [joinVendorOf(input, input.older.spec)],
|
|
2418
|
-
...input.targets ? { targets: input.targets } : {}
|
|
3461
|
+
...input.targets ? { targets: input.targets } : {},
|
|
3462
|
+
...bundle
|
|
2419
3463
|
});
|
|
2420
3464
|
const next = joinVendorOperations({
|
|
2421
3465
|
repos: input.repos,
|
|
2422
3466
|
vendors: [joinVendorOf(input, input.newer.spec)],
|
|
2423
|
-
...input.targets ? { targets: input.targets } : {}
|
|
3467
|
+
...input.targets ? { targets: input.targets } : {},
|
|
3468
|
+
...bundle
|
|
2424
3469
|
});
|
|
2425
3470
|
const k = (e) => `${e.repo}\0${e.fact}`;
|
|
2426
3471
|
const facts = /* @__PURE__ */ new Map();
|
|
@@ -2444,8 +3489,8 @@ function vendorImpact(input) {
|
|
|
2444
3489
|
const f = facts.get(k(call))?.fact;
|
|
2445
3490
|
return f?.kind === "call" && f.from ? endOf(call.repo, f.from) : void 0;
|
|
2446
3491
|
};
|
|
2447
|
-
const hops = new Set(
|
|
2448
|
-
const joins =
|
|
3492
|
+
const hops = new Set(join7.joins.flatMap((j) => (j.gateway ?? []).map((h) => k(h.call))));
|
|
3493
|
+
const joins = join7.joins.filter((j) => j.how !== "topic" && !hops.has(k(j.call)));
|
|
2449
3494
|
const via = (j) => j.gateway?.length ? { via: j.gateway.map((h) => h.route) } : {};
|
|
2450
3495
|
const upstreamOf = (start) => {
|
|
2451
3496
|
const out = [];
|
|
@@ -2475,10 +3520,10 @@ function vendorImpact(input) {
|
|
|
2475
3520
|
return out;
|
|
2476
3521
|
};
|
|
2477
3522
|
const fieldUse = (call, change) => {
|
|
2478
|
-
if (!change.side || !change.field)
|
|
3523
|
+
if (!change.side || !change.field || change.status)
|
|
2479
3524
|
return void 0;
|
|
2480
3525
|
const side = change.side;
|
|
2481
|
-
const mine = (input.repos.find((r) => r.repo === call.repo)?.facts ?? []).filter((f) => f.kind === "field" && f.owner === call.fact && (f.side ?? "request") === side).sort((a, b) =>
|
|
3526
|
+
const mine = (input.repos.find((r) => r.repo === call.repo)?.facts ?? []).filter((f) => f.kind === "field" && f.owner === call.fact && (f.side ?? "request") === side).sort((a, b) => cmp4(a.id, b.id));
|
|
2482
3527
|
if (!mine.length)
|
|
2483
3528
|
return void 0;
|
|
2484
3529
|
const want = fieldNameKey(change.field);
|
|
@@ -2490,6 +3535,24 @@ function vendorImpact(input) {
|
|
|
2490
3535
|
const older = c.endpoints.older;
|
|
2491
3536
|
const matches = older ? today.matches.filter((m) => m.operation === older) : next.matches.filter((m) => m.operation === c.endpoints.newer);
|
|
2492
3537
|
const forwards = matches.map((m) => {
|
|
3538
|
+
if (m.direct) {
|
|
3539
|
+
const f = facts.get(k(m.call))?.fact;
|
|
3540
|
+
const field2 = fieldUse(m.call, c);
|
|
3541
|
+
const self = {
|
|
3542
|
+
call: m.call,
|
|
3543
|
+
interface: interfaceId(m.call.component, factIdPart(f?.to ?? input.vendor.system), m.method, m.path),
|
|
3544
|
+
...field2 ? { field: field2 } : {},
|
|
3545
|
+
...m.route ? { under: m.route } : {},
|
|
3546
|
+
upstream: upstreamOf(m.route)
|
|
3547
|
+
};
|
|
3548
|
+
return {
|
|
3549
|
+
call: m.call,
|
|
3550
|
+
...m.route ? { route: m.route } : {},
|
|
3551
|
+
operation: m.operation,
|
|
3552
|
+
direct: true,
|
|
3553
|
+
callers: [self]
|
|
3554
|
+
};
|
|
3555
|
+
}
|
|
2493
3556
|
const callers = m.route ? joins.filter((j) => k(j.entry) === k(m.route) || (j.gateway ?? []).some((h) => k(h.entry) === k(m.route))).map((j) => {
|
|
2494
3557
|
const u = under(j.call);
|
|
2495
3558
|
const field2 = fieldUse(j.call, c);
|
|
@@ -2540,7 +3603,7 @@ function vendorImpact(input) {
|
|
|
2540
3603
|
if (got?.fact.kind === "entry")
|
|
2541
3604
|
endpointIds.add(entryEndpointId(got.fact, componentOf(got.repo, got.fact)));
|
|
2542
3605
|
}
|
|
2543
|
-
const flows = (input.flows ?? []).filter((f) => f.trigger && endpointIds.has(f.trigger) || (f.refs ?? []).some((r) => endpointIds.has(r))).map((f) => ({ id: f.id, repo: f.repo })).sort((a, b) =>
|
|
3606
|
+
const flows = (input.flows ?? []).filter((f) => f.trigger && endpointIds.has(f.trigger) || (f.refs ?? []).some((r) => endpointIds.has(r))).map((f) => ({ id: f.id, repo: f.repo })).sort((a, b) => cmp4(a.id, b.id));
|
|
2544
3607
|
for (const f of flows)
|
|
2545
3608
|
repos.add(f.repo);
|
|
2546
3609
|
const systems = /* @__PURE__ */ new Set([input.vendor.system]);
|
|
@@ -2567,7 +3630,174 @@ function vendorImpact(input) {
|
|
|
2567
3630
|
};
|
|
2568
3631
|
}
|
|
2569
3632
|
|
|
3633
|
+
// packages/intake/dist/contract-files.js
|
|
3634
|
+
var import_yaml8 = __toESM(require_dist(), 1);
|
|
3635
|
+
import { readdir as readdir6, readFile as readFile6, stat as stat3 } from "node:fs/promises";
|
|
3636
|
+
import { join as join6 } from "node:path";
|
|
3637
|
+
function safeServerUrl(url) {
|
|
3638
|
+
const m = /^([a-z][a-z0-9+.-]*:\/\/)([^/?#]*)(.*)$/i.exec(url.trim());
|
|
3639
|
+
if (!m) {
|
|
3640
|
+
const p = safePathOf(url);
|
|
3641
|
+
return p === "/" ? void 0 : p;
|
|
3642
|
+
}
|
|
3643
|
+
const host = m[2].replace(/^.*@/, "");
|
|
3644
|
+
if (!host)
|
|
3645
|
+
return void 0;
|
|
3646
|
+
const rest = (m[3] ?? "").split(/[?#]/, 1)[0] ?? "";
|
|
3647
|
+
const path = rest && rest !== "/" ? safePathOf(rest) : "";
|
|
3648
|
+
return `${m[1].toLowerCase()}${host}${path === "/" ? "" : path ?? ""}`;
|
|
3649
|
+
}
|
|
3650
|
+
var str2 = (m, key3) => {
|
|
3651
|
+
const v = m?.get(key3);
|
|
3652
|
+
return typeof v === "string" && v.trim() ? v.trim() : void 0;
|
|
3653
|
+
};
|
|
3654
|
+
var mapAt = (m, key3) => {
|
|
3655
|
+
const v = (0, import_yaml8.isMap)(m) ? m.get(key3, true) : void 0;
|
|
3656
|
+
return (0, import_yaml8.isMap)(v) ? v : void 0;
|
|
3657
|
+
};
|
|
3658
|
+
function readPactFile(text3, file) {
|
|
3659
|
+
const lc = new import_yaml8.LineCounter();
|
|
3660
|
+
let doc;
|
|
3661
|
+
try {
|
|
3662
|
+
doc = (0, import_yaml8.parseDocument)(text3, { lineCounter: lc });
|
|
3663
|
+
} catch {
|
|
3664
|
+
return void 0;
|
|
3665
|
+
}
|
|
3666
|
+
if (doc.errors.length || !(0, import_yaml8.isMap)(doc.contents))
|
|
3667
|
+
return void 0;
|
|
3668
|
+
const root = doc.contents;
|
|
3669
|
+
const consumer = str2(mapAt(root, "consumer"), "name");
|
|
3670
|
+
const provider = str2(mapAt(root, "provider"), "name");
|
|
3671
|
+
const list2 = root.get("interactions", true);
|
|
3672
|
+
if (!consumer || !provider || !(0, import_yaml8.isSeq)(list2))
|
|
3673
|
+
return void 0;
|
|
3674
|
+
const out = [];
|
|
3675
|
+
for (const it of list2.items) {
|
|
3676
|
+
if (!(0, import_yaml8.isMap)(it))
|
|
3677
|
+
continue;
|
|
3678
|
+
const type = str2(it, "type");
|
|
3679
|
+
if (type && !/http/i.test(type))
|
|
3680
|
+
continue;
|
|
3681
|
+
const req = mapAt(it, "request");
|
|
3682
|
+
if (!req)
|
|
3683
|
+
continue;
|
|
3684
|
+
const method = str2(req, "method");
|
|
3685
|
+
const pair = req.items.find((p) => (0, import_yaml8.isScalar)(p.key) && p.key.value === "path");
|
|
3686
|
+
const path = pair && (0, import_yaml8.isScalar)(pair.value) ? String(pair.value.value) : void 0;
|
|
3687
|
+
const safe = path?.startsWith("/") ? safePathOf(path) : void 0;
|
|
3688
|
+
if (!safe)
|
|
3689
|
+
continue;
|
|
3690
|
+
const range = pair.key.range;
|
|
3691
|
+
out.push({
|
|
3692
|
+
format: "pact",
|
|
3693
|
+
file,
|
|
3694
|
+
line: range ? lc.linePos(range[0]).line : 1,
|
|
3695
|
+
consumer,
|
|
3696
|
+
provider,
|
|
3697
|
+
...method ? { method: method.toUpperCase() } : {},
|
|
3698
|
+
path: safe
|
|
3699
|
+
});
|
|
3700
|
+
}
|
|
3701
|
+
return out;
|
|
3702
|
+
}
|
|
3703
|
+
function readConsumerOpenApi(text3, file, own) {
|
|
3704
|
+
let read;
|
|
3705
|
+
try {
|
|
3706
|
+
read = readOpenApiDocument(text3);
|
|
3707
|
+
} catch {
|
|
3708
|
+
return void 0;
|
|
3709
|
+
}
|
|
3710
|
+
if (!read)
|
|
3711
|
+
return void 0;
|
|
3712
|
+
const served = read.operations.some((op) => own.some((e) => (!e.method || e.method.toUpperCase() === op.method.toUpperCase()) && routeScore(op.path, e.path) >= 500));
|
|
3713
|
+
if (served)
|
|
3714
|
+
return [];
|
|
3715
|
+
const title = read.doc.getIn(["info", "title"]);
|
|
3716
|
+
const provider = typeof title === "string" && title.trim() ? title.trim() : void 0;
|
|
3717
|
+
const hosts = [...new Set(read.servers.map(safeServerUrl).filter((h) => !!h))];
|
|
3718
|
+
return read.operations.flatMap((op) => {
|
|
3719
|
+
const path = safePathOf(op.path);
|
|
3720
|
+
return path ? [
|
|
3721
|
+
{
|
|
3722
|
+
format: "openapi",
|
|
3723
|
+
file,
|
|
3724
|
+
line: op.methodLine ?? op.line ?? 1,
|
|
3725
|
+
...provider ? { provider } : {},
|
|
3726
|
+
...hosts.length ? { hosts } : {},
|
|
3727
|
+
method: op.method.toUpperCase(),
|
|
3728
|
+
path
|
|
3729
|
+
}
|
|
3730
|
+
] : [];
|
|
3731
|
+
});
|
|
3732
|
+
}
|
|
3733
|
+
var SKIP2 = /* @__PURE__ */ new Set([
|
|
3734
|
+
".git",
|
|
3735
|
+
"node_modules",
|
|
3736
|
+
"vendor",
|
|
3737
|
+
"target",
|
|
3738
|
+
"build",
|
|
3739
|
+
"dist",
|
|
3740
|
+
"out",
|
|
3741
|
+
".venv",
|
|
3742
|
+
"venv",
|
|
3743
|
+
"__pycache__",
|
|
3744
|
+
".gradle",
|
|
3745
|
+
".idea",
|
|
3746
|
+
".atticus"
|
|
3747
|
+
]);
|
|
3748
|
+
var MAX_BYTES2 = 5 * 1024 * 1024;
|
|
3749
|
+
var PACT = /pact/i;
|
|
3750
|
+
var SPEC = /(openapi|swagger)/i;
|
|
3751
|
+
async function readContractFiles(dir, o) {
|
|
3752
|
+
const files = [];
|
|
3753
|
+
const walk2 = async (rel) => {
|
|
3754
|
+
const entries2 = await readdir6(join6(dir, ...rel.split("/").filter(Boolean)), {
|
|
3755
|
+
withFileTypes: true
|
|
3756
|
+
}).catch(() => []);
|
|
3757
|
+
for (const e of [...entries2].sort((a, b) => a.name < b.name ? -1 : 1)) {
|
|
3758
|
+
const p = rel ? `${rel}/${e.name}` : e.name;
|
|
3759
|
+
if (e.isDirectory()) {
|
|
3760
|
+
if (!SKIP2.has(e.name))
|
|
3761
|
+
await walk2(p);
|
|
3762
|
+
} else if (e.isFile()) {
|
|
3763
|
+
if (/\.json$/i.test(e.name) && PACT.test(p))
|
|
3764
|
+
files.push(p);
|
|
3765
|
+
else if (/\.(ya?ml|json)$/i.test(e.name) && SPEC.test(e.name))
|
|
3766
|
+
files.push(p);
|
|
3767
|
+
}
|
|
3768
|
+
}
|
|
3769
|
+
};
|
|
3770
|
+
await walk2("");
|
|
3771
|
+
const entries = [];
|
|
3772
|
+
for (const p of files) {
|
|
3773
|
+
const full = join6(dir, ...p.split("/"));
|
|
3774
|
+
const size = (await stat3(full).catch(() => void 0))?.size ?? 0;
|
|
3775
|
+
if (size === 0 || size > MAX_BYTES2)
|
|
3776
|
+
continue;
|
|
3777
|
+
const text3 = await readFile6(full, "utf8");
|
|
3778
|
+
const got = (/\.json$/i.test(p) && PACT.test(p) ? readPactFile(text3, p) : void 0) ?? (SPEC.test(p) ? readConsumerOpenApi(text3, p, o.own ?? []) : void 0);
|
|
3779
|
+
if (!got?.length)
|
|
3780
|
+
continue;
|
|
3781
|
+
if (o.denyHashes?.size) {
|
|
3782
|
+
const text4 = got.map((e) => [e.file, e.consumer, e.provider, ...e.hosts ?? [], e.method, e.path].join("\n")).join("\n");
|
|
3783
|
+
if (denyListHits(text4, o.denyHashes).length) {
|
|
3784
|
+
o.onRefused?.(`${p}: the deny-list names a word in it, so its requests are left out.`);
|
|
3785
|
+
continue;
|
|
3786
|
+
}
|
|
3787
|
+
}
|
|
3788
|
+
entries.push(...got);
|
|
3789
|
+
}
|
|
3790
|
+
entries.sort((a, b) => a.file < b.file ? -1 : a.file > b.file ? 1 : a.line - b.line);
|
|
3791
|
+
return {
|
|
3792
|
+
schemaVersion: 1,
|
|
3793
|
+
repo: o.repo,
|
|
3794
|
+
...o.commit ? { commit: o.commit } : {},
|
|
3795
|
+
entries
|
|
3796
|
+
};
|
|
3797
|
+
}
|
|
3798
|
+
|
|
2570
3799
|
export {
|
|
3800
|
+
joinServerVariables,
|
|
2571
3801
|
classify,
|
|
2572
3802
|
READERS,
|
|
2573
3803
|
readOpenApiSpec,
|
|
@@ -2580,9 +3810,24 @@ export {
|
|
|
2580
3810
|
sortItems,
|
|
2581
3811
|
opt,
|
|
2582
3812
|
screenFile,
|
|
3813
|
+
looksSensitive,
|
|
3814
|
+
segmentOf,
|
|
3815
|
+
safePathOf,
|
|
3816
|
+
pathTemplateOf,
|
|
3817
|
+
appLabelOf,
|
|
3818
|
+
denyListHits,
|
|
3819
|
+
aggregateTraffic,
|
|
2583
3820
|
specEndpointIds,
|
|
2584
3821
|
readVendorSpec,
|
|
2585
3822
|
operationSchemas,
|
|
3823
|
+
readProtoSpecs,
|
|
3824
|
+
readAvroSpecs,
|
|
3825
|
+
readJsonSchemaSpecs,
|
|
3826
|
+
readAsyncApiSpecs,
|
|
3827
|
+
openApiContractSpecs,
|
|
3828
|
+
specFormatOf,
|
|
3829
|
+
readContractSpecs,
|
|
3830
|
+
readRepoSpecs,
|
|
2586
3831
|
nameParts,
|
|
2587
3832
|
compareVersions,
|
|
2588
3833
|
scanInputs,
|
|
@@ -2605,5 +3850,9 @@ export {
|
|
|
2605
3850
|
changeInputSources,
|
|
2606
3851
|
diffVendorSpecs,
|
|
2607
3852
|
MAX_UPSTREAM,
|
|
2608
|
-
vendorImpact
|
|
3853
|
+
vendorImpact,
|
|
3854
|
+
safeServerUrl,
|
|
3855
|
+
readPactFile,
|
|
3856
|
+
readConsumerOpenApi,
|
|
3857
|
+
readContractFiles
|
|
2609
3858
|
};
|