@maycombhq/atticus 2.0.0-beta.23 → 2.0.0-beta.25
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 +3 -3
- package/dist/{chunk-S7GUZ45I.js → chunk-23QHP4JJ.js} +5 -3
- package/dist/{chunk-73V2OONC.js → chunk-2RABF6RT.js} +17 -15
- package/dist/{chunk-ENH6Z4TY.js → chunk-2ULVUSIP.js} +17 -17
- package/dist/{chunk-G6EFXTUO.js → chunk-2VN4TLGI.js} +7 -5
- package/dist/{chunk-ZSNOILL5.js → chunk-2Y5FJQSF.js} +1 -1
- package/dist/{chunk-YDCOZOER.js → chunk-334N6EI2.js} +20 -18
- package/dist/chunk-3D74UADA.js +22 -0
- package/dist/{chunk-63NFFAGI.js → chunk-3NA2VE45.js} +14 -12
- package/dist/{chunk-CJEBRJBS.js → chunk-3VC2XJ53.js} +6 -4
- package/dist/{chunk-7NQAGYK4.js → chunk-3WO7ASU7.js} +8 -8
- package/dist/{chunk-GM4EFHUX.js → chunk-4GWQVT2C.js} +19 -16
- package/dist/{chunk-SVGGMBJI.js → chunk-4PW5SRKJ.js} +15 -13
- package/dist/{chunk-27AJAKX7.js → chunk-4SS5ZK47.js} +3 -3
- package/dist/{chunk-PQQKZPBU.js → chunk-4U3JLIRC.js} +1 -1
- package/dist/{chunk-Z3H27OMV.js → chunk-4WIVTPGE.js} +6 -4
- package/dist/{chunk-XF6TSZW2.js → chunk-5267F4BS.js} +6 -4
- package/dist/chunk-5CPZIWIN.js +38 -0
- package/dist/{chunk-PWXB5GBB.js → chunk-5GLGLWAJ.js} +18 -16
- package/dist/{chunk-2QPJ4E4Z.js → chunk-5K6ZKHZR.js} +4 -2
- package/dist/{chunk-QZWRPQTI.js → chunk-5OVSDV77.js} +8 -6
- package/dist/{chunk-FJVUHQPS.js → chunk-5P4PNGPL.js} +26 -23
- package/dist/{chunk-M3EOFSPY.js → chunk-5R3FRI6H.js} +33 -29
- package/dist/{chunk-PNSSE7JM.js → chunk-5RDKQOY3.js} +25 -23
- package/dist/{chunk-KDJ2YKAZ.js → chunk-5RKN5QIX.js} +9 -7
- package/dist/{chunk-3EX5HCZD.js → chunk-5UJ7C7IH.js} +16 -14
- package/dist/{chunk-ZLQEQR3D.js → chunk-5WZV37WS.js} +8 -6
- package/dist/{chunk-OBUB3H72.js → chunk-62FMA437.js} +14 -12
- package/dist/{chunk-UALE35WK.js → chunk-6576X5BJ.js} +5 -3
- package/dist/{chunk-TXNSQ24G.js → chunk-6WYOJCB4.js} +3 -3
- package/dist/{chunk-TV56QLLV.js → chunk-77REYYY5.js} +5 -3
- package/dist/{chunk-QLQIFJP3.js → chunk-7AKJ2XTW.js} +19 -16
- package/dist/{chunk-2WUTCPPJ.js → chunk-7E3G5NCH.js} +17 -13
- package/dist/{chunk-FVYZ4Y52.js → chunk-7EAH2MFY.js} +5 -3
- package/dist/{chunk-PXW2RZGQ.js → chunk-7F4GZ7U2.js} +3 -3
- package/dist/{chunk-6RQOINER.js → chunk-7FUQAT2R.js} +6 -4
- package/dist/{chunk-AQRUQNFB.js → chunk-7HW2CMIN.js} +10 -8
- package/dist/{chunk-AGOLEMHK.js → chunk-7NLYSTEK.js} +10 -8
- package/dist/{chunk-YHMPDIRG.js → chunk-7QZDGM5V.js} +6 -4
- package/dist/{chunk-MEJ63LDG.js → chunk-7U6PBBXG.js} +11 -9
- package/dist/{chunk-UTPIFH4I.js → chunk-7UYRN4ON.js} +5 -3
- package/dist/{chunk-5OXKCH4Z.js → chunk-7X3WLAKP.js} +93 -40
- package/dist/{chunk-7IFTSAHP.js → chunk-7YFUNWFM.js} +10 -8
- package/dist/chunk-7YSMZEO3.js +55 -0
- package/dist/{chunk-RPQITJNX.js → chunk-A3AADMM2.js} +10 -8
- package/dist/{chunk-VK7WYA64.js → chunk-A3J75BO2.js} +14 -12
- package/dist/chunk-AENMOZMM.js +42 -0
- package/dist/{chunk-7K5OH45X.js → chunk-AGAFNUYZ.js} +87 -10
- package/dist/{chunk-VKTXFFOZ.js → chunk-AYWJMHSX.js} +5 -3
- package/dist/{chunk-3UHV76UD.js → chunk-B2U4AOZ5.js} +41 -38
- package/dist/chunk-BDKYHCGI.js +71 -0
- package/dist/{chunk-RQQYEDAC.js → chunk-BEDZNT62.js} +12 -9
- package/dist/{chunk-PGAMTKBI.js → chunk-BIQNPWGX.js} +6 -4
- package/dist/{chunk-LSHSDC6S.js → chunk-BJDVI5W6.js} +19 -17
- package/dist/{chunk-PFULMC2D.js → chunk-BMMTWRWE.js} +22 -20
- package/dist/{chunk-KT6Q44CA.js → chunk-BPDS7KUR.js} +27 -25
- package/dist/{chunk-7XYLNQFO.js → chunk-BS52P2CM.js} +13 -5
- package/dist/{chunk-TABH4RBZ.js → chunk-C5LX54QK.js} +16 -14
- package/dist/{chunk-NCLZJCXA.js → chunk-CB6H7MH2.js} +23 -21
- package/dist/{chunk-CZ2ZS7AT.js → chunk-CGVRLQAY.js} +2166 -326
- package/dist/{chunk-HJQVUOUL.js → chunk-CMUJSPP4.js} +13 -11
- package/dist/{chunk-CT6NINGR.js → chunk-CNF7D3A7.js} +3 -3
- package/dist/{chunk-BP33TBLI.js → chunk-CPFAWYVC.js} +9 -7
- package/dist/chunk-CQRFCWQV.js +45 -0
- package/dist/chunk-CTJHEG6A.js +97 -0
- package/dist/{chunk-SCT4CEF7.js → chunk-CVWKS6GO.js} +22 -20
- package/dist/chunk-D2CGJ7RR.js +46 -0
- package/dist/{chunk-K757G7AD.js → chunk-D45K3XKK.js} +19 -16
- package/dist/chunk-D7QIZLWB.js +38 -0
- package/dist/{chunk-YERAAEO4.js → chunk-DAHKLVHU.js} +15 -13
- package/dist/{chunk-OPWGPQ2N.js → chunk-DBVQEPZB.js} +8 -6
- package/dist/{chunk-T33TPFGI.js → chunk-DCPI3ETH.js} +24 -22
- package/dist/{chunk-RRQUQAXP.js → chunk-DJ4C5ELF.js} +5 -2
- package/dist/{chunk-RCG5IAAT.js → chunk-DLNQ3HUM.js} +12 -10
- package/dist/chunk-DM3H4V2G.js +62 -0
- package/dist/{chunk-EVTI22PQ.js → chunk-DMQJDHXG.js} +7 -4
- package/dist/{chunk-5VTIWEWP.js → chunk-DPZD7WVX.js} +4 -2
- package/dist/{chunk-WF3RCZNO.js → chunk-DYVUNT4O.js} +9 -7
- package/dist/{chunk-2UMSHYCB.js → chunk-E2OP6JNF.js} +26 -24
- package/dist/{chunk-6Y4FXOMI.js → chunk-E7PR4WMM.js} +24 -22
- package/dist/{chunk-TNCF26JK.js → chunk-EAGSM3XY.js} +14 -12
- package/dist/{chunk-X5ZHDSLU.js → chunk-EJGUEUXG.js} +25 -23
- package/dist/chunk-ELKTDXV3.js +67 -0
- package/dist/{chunk-T3FNG2H2.js → chunk-ELNIQYLR.js} +14 -12
- package/dist/{chunk-DHKDH464.js → chunk-ELNLHU7Y.js} +6 -4
- package/dist/{chunk-CA3DKO4D.js → chunk-EM7F6XEU.js} +4 -2
- package/dist/{chunk-K4OXYSGS.js → chunk-EP7ZBZLT.js} +7 -5
- package/dist/chunk-EPXYFJTY.js +278 -0
- package/dist/{chunk-MBYYQHPM.js → chunk-EUCATH2U.js} +6 -4
- package/dist/{chunk-73CC73I4.js → chunk-EXCXNDTQ.js} +1 -1
- package/dist/{chunk-SRTUETF5.js → chunk-EXGXCVWC.js} +24 -22
- package/dist/{chunk-BYBU2EIB.js → chunk-F36DIKJ3.js} +23 -21
- package/dist/{chunk-P22EPEBR.js → chunk-F4WKGX7K.js} +18 -16
- package/dist/{chunk-ZJGCGKA4.js → chunk-F56DNMDD.js} +5 -3
- package/dist/chunk-FJS2FZFZ.js +41 -0
- package/dist/{chunk-2YSD6E6V.js → chunk-FNP4M4VL.js} +42 -33
- package/dist/{chunk-B4AEL3RF.js → chunk-G3ZFEHCX.js} +21 -107
- package/dist/{chunk-XOMEQVLK.js → chunk-G5P7F6RQ.js} +5 -3
- package/dist/chunk-GAU2IFIC.js +33 -0
- package/dist/{chunk-XNFM6WUK.js → chunk-GAVEIYKH.js} +21 -18
- package/dist/{chunk-TUM52SOE.js → chunk-GD6FXN6R.js} +17 -15
- package/dist/{chunk-D6BVLTDV.js → chunk-GDGE7ZHC.js} +28 -26
- package/dist/{chunk-SYP56T2D.js → chunk-GIOOA2ZO.js} +7 -4
- package/dist/chunk-GLISHJ4G.js +21345 -0
- package/dist/chunk-GPOL5H3B.js +55 -0
- package/dist/{chunk-ZFHFC74B.js → chunk-GVOQJPKA.js} +20 -18
- package/dist/{chunk-G7VBMOZH.js → chunk-GX67TNFA.js} +3 -3
- package/dist/{chunk-VNIN7Q6Q.js → chunk-H75SPCAW.js} +18 -16
- package/dist/{chunk-J4CPHJUL.js → chunk-H7GAPNGQ.js} +29 -18
- package/dist/{chunk-X7ZKNSK4.js → chunk-HD72AL3L.js} +20 -18
- package/dist/{chunk-FBCVC2GJ.js → chunk-HHZ2ZKUD.js} +16 -13
- package/dist/{chunk-K4RNVDR4.js → chunk-HHZEXF7V.js} +8 -6
- package/dist/{chunk-OK6JGLE7.js → chunk-HR34F2AJ.js} +14 -12
- package/dist/{chunk-3MYBT62N.js → chunk-HU7VXMFV.js} +9 -7
- package/dist/{chunk-LPDTDFKA.js → chunk-HV3KPEFH.js} +18 -16
- package/dist/{chunk-4ETO2FXE.js → chunk-I2M7MXSV.js} +14 -12
- package/dist/{chunk-W3AZE7LN.js → chunk-IDTVBZQI.js} +3 -3
- package/dist/{chunk-BFL4PO64.js → chunk-IFDCCCEN.js} +6 -4
- package/dist/{chunk-3ZA3AK2D.js → chunk-IKRM64KR.js} +12 -10
- package/dist/{chunk-JMEWJPF2.js → chunk-IMTAHDME.js} +7 -7
- package/dist/{chunk-DCRYOMTM.js → chunk-IP6TSICI.js} +14 -12
- package/dist/{chunk-PT4USJNN.js → chunk-IW3QMW3X.js} +10 -8
- package/dist/{chunk-MLGWSBF4.js → chunk-IWQEZFVV.js} +261 -62
- package/dist/{chunk-C6ORPLCN.js → chunk-J65TN6QU.js} +7 -5
- package/dist/{chunk-QBMLBCQH.js → chunk-JCKKAELC.js} +16 -13
- package/dist/{chunk-XGO74QWR.js → chunk-JJEPU4VS.js} +7 -5
- package/dist/{chunk-BFMTGNAQ.js → chunk-JKEUPSCE.js} +5 -3
- package/dist/{chunk-HMZ2DRBC.js → chunk-JMOZ6K5A.js} +16 -5
- package/dist/{chunk-WZYM5M4U.js → chunk-JQGWP3SC.js} +19 -17
- package/dist/{chunk-ZR6J4QFQ.js → chunk-JWLABUXL.js} +13 -11
- package/dist/{chunk-EXJZBL5N.js → chunk-JXLUHMTC.js} +23 -21
- package/dist/{chunk-DSHRA72L.js → chunk-K373N5U6.js} +13 -11
- package/dist/{chunk-WYGTSZHR.js → chunk-K3OIBTCV.js} +16 -14
- package/dist/{chunk-BAY4K55I.js → chunk-K4C2DWOZ.js} +16 -13
- package/dist/{chunk-GOZLTLRY.js → chunk-K77ILFUQ.js} +4 -4
- package/dist/{chunk-4R3TO4VL.js → chunk-KFDOL2Y4.js} +19 -17
- package/dist/{chunk-T6MX7WXM.js → chunk-KGT5RIGE.js} +30 -13
- package/dist/{chunk-SWNKO4C4.js → chunk-KJPKIU2R.js} +29 -26
- package/dist/{chunk-T7IIEDA3.js → chunk-KN4UQJ7R.js} +6 -4
- package/dist/{chunk-AVMWESFZ.js → chunk-KW4DIXUL.js} +6 -3
- package/dist/{chunk-FRAEQVYN.js → chunk-KY3BUZYI.js} +24 -22
- package/dist/{chunk-FMJYKLDY.js → chunk-LGE6H4UP.js} +15 -8
- package/dist/{chunk-XAPXKFIS.js → chunk-LKRMVWXB.js} +33 -24
- package/dist/{chunk-BUUJ7N4O.js → chunk-LMNCRSER.js} +31 -11
- package/dist/{chunk-TMFMXQEN.js → chunk-LNGFTPU7.js} +22 -19
- package/dist/{chunk-N2YX6JMY.js → chunk-LOJGNSPA.js} +28 -23
- package/dist/{chunk-6ZSYLZ7O.js → chunk-LP5QGTCR.js} +3 -3
- package/dist/{chunk-S35DIFJH.js → chunk-LPXH2DA4.js} +19 -17
- package/dist/{chunk-FRCOKUU4.js → chunk-LQD3R6NZ.js} +9 -7
- package/dist/{chunk-FPBUTZI5.js → chunk-LZFKJ2BR.js} +3233 -22921
- package/dist/{chunk-TDSCKP3V.js → chunk-M6HI36T3.js} +2 -2
- package/dist/{chunk-SK5RVP7X.js → chunk-M7XNX5IC.js} +11 -9
- package/dist/{chunk-RGZFOKVO.js → chunk-MELS6T5J.js} +6 -4
- package/dist/{chunk-6NN36LVK.js → chunk-MJAIBPI5.js} +3 -3
- package/dist/{chunk-Y2H7X3VI.js → chunk-MJMEF7SD.js} +10 -8
- package/dist/{chunk-FTLYXMHA.js → chunk-MJOIMGS4.js} +7 -5
- package/dist/chunk-MLUHBVCI.js +45 -0
- package/dist/{chunk-JXAKYP45.js → chunk-MM5OAVSW.js} +27 -25
- package/dist/{chunk-6ZFF7XSL.js → chunk-MM7YWUBB.js} +6 -6
- package/dist/{chunk-S5GSQPIN.js → chunk-MN2XDLDM.js} +18 -16
- package/dist/{chunk-MNIPPBCT.js → chunk-MWOPED6I.js} +7 -5
- package/dist/{chunk-JFFKHIM6.js → chunk-MXPKXCGP.js} +1 -1
- package/dist/{chunk-IYNCSYU4.js → chunk-MZTU5L6S.js} +6 -4
- package/dist/{chunk-NAPHHWW2.js → chunk-N3OEBQTA.js} +3 -3
- package/dist/{chunk-PCCLVIDP.js → chunk-N6SSI6XO.js} +25 -22
- package/dist/{chunk-POSDBRKV.js → chunk-NB664KWQ.js} +28 -25
- package/dist/{chunk-Z3RAFU5B.js → chunk-NL6GIEJU.js} +17 -15
- package/dist/{chunk-ISG547IS.js → chunk-NMBHFSJQ.js} +24 -22
- package/dist/{chunk-CFUDAW3R.js → chunk-NMGFXT4S.js} +17 -15
- package/dist/{chunk-ZENHDXRZ.js → chunk-NPZ4KXIV.js} +20 -18
- package/dist/{chunk-CQ7RF4QN.js → chunk-NQLTWGF4.js} +6 -4
- package/dist/{chunk-KTNOBTV5.js → chunk-O6DJMDBR.js} +6 -4
- package/dist/{chunk-MH2ZK67S.js → chunk-OEUTV6EL.js} +15 -12
- package/dist/{chunk-CKVBDVIW.js → chunk-OMSH46JK.js} +6 -4
- package/dist/chunk-ONB7M2AF.js +52 -0
- package/dist/{chunk-QX4MAMUG.js → chunk-OOU4N2JQ.js} +136 -30
- package/dist/{chunk-4MYHETJ3.js → chunk-OW53P52N.js} +20 -18
- package/dist/{chunk-APDN6UOR.js → chunk-P4QTTCVK.js} +20 -18
- package/dist/{chunk-JSP73CDW.js → chunk-P56N3NPT.js} +8 -5
- package/dist/{chunk-CS4BMJLL.js → chunk-PCZ4C2V7.js} +7 -5
- package/dist/{chunk-A4JXVO5O.js → chunk-PGKCRK77.js} +10 -8
- package/dist/{chunk-RLZFL76D.js → chunk-PYVFLITV.js} +15 -13
- package/dist/{chunk-Z2D4P3R3.js → chunk-Q52KWTG5.js} +14 -12
- package/dist/{chunk-YD3KTW4H.js → chunk-Q6UYUCNS.js} +14 -12
- package/dist/chunk-QBK33722.js +51 -0
- package/dist/{chunk-L3RCQWVQ.js → chunk-QE444DZ2.js} +53 -26
- package/dist/{chunk-Y5IE6YKD.js → chunk-QEP4HTJE.js} +6 -4
- package/dist/{chunk-FSN6JFXB.js → chunk-QFOJ3UPU.js} +25 -19
- package/dist/{chunk-3424TLIJ.js → chunk-QQD25YNF.js} +12 -10
- package/dist/{chunk-HRS5O7VV.js → chunk-QSKY7FE3.js} +21 -17
- package/dist/{chunk-LO6Y7OTG.js → chunk-R6HJ4SDB.js} +10 -7
- package/dist/{chunk-QLWDIKO4.js → chunk-RFQW7XT3.js} +20 -17
- package/dist/{chunk-4GAB5ZOZ.js → chunk-RL7PETU6.js} +30 -26
- package/dist/{chunk-66AQ2JIU.js → chunk-ROVOAF2O.js} +13 -11
- package/dist/{chunk-UJF7PIMP.js → chunk-RSA5JJMN.js} +58 -34
- package/dist/{chunk-J32IPTVQ.js → chunk-RX56MZLX.js} +22 -20
- package/dist/chunk-S7I7SLZN.js +59 -0
- package/dist/{chunk-S6W3D5GS.js → chunk-S7UQFI4B.js} +29 -26
- package/dist/{chunk-TVQSXWWV.js → chunk-SBNBVUOF.js} +35 -33
- package/dist/{chunk-POEMZECG.js → chunk-SD3PGZSR.js} +1 -1
- package/dist/{chunk-EMVZIOOD.js → chunk-SEBBJQWK.js} +17 -15
- package/dist/{chunk-MWF4PXQR.js → chunk-SGTAQNOP.js} +37 -34
- package/dist/{chunk-HUGQZQ2K.js → chunk-SHWHRCMU.js} +9 -7
- package/dist/{chunk-POSZFDSQ.js → chunk-SRLUADSY.js} +6 -4
- package/dist/{chunk-J25YOUIZ.js → chunk-SXF66YNZ.js} +6 -4
- package/dist/{chunk-PRMUQUWN.js → chunk-T5QYYB5L.js} +16 -14
- package/dist/{chunk-OSYHGGL3.js → chunk-TAIYQDIV.js} +20 -18
- package/dist/{chunk-NROSSWMS.js → chunk-TIOYZDRB.js} +8 -6
- package/dist/{chunk-S6LW2RRC.js → chunk-TKCNJJ2S.js} +10 -8
- package/dist/{chunk-T6MAWL5P.js → chunk-TVFADTAT.js} +6 -4
- package/dist/{chunk-FMR2D3AZ.js → chunk-U4HZ5CXL.js} +8 -6
- package/dist/{chunk-XMUWPA56.js → chunk-U7F6E5M3.js} +27 -24
- package/dist/{chunk-FL344WQD.js → chunk-U7YZ3IRI.js} +6 -4
- package/dist/{chunk-OCQWSFJD.js → chunk-UCKG6UE7.js} +14 -12
- package/dist/{chunk-LM45GMMB.js → chunk-UCQB6NKS.js} +7 -7
- package/dist/{chunk-6SNTHK43.js → chunk-UI7ID4HG.js} +24 -19
- package/dist/{chunk-S5XFO4GY.js → chunk-UJ535VWR.js} +6 -4
- package/dist/chunk-UKMA5JFE.js +52 -0
- package/dist/{chunk-E3PDCQRH.js → chunk-UR6JGVX2.js} +299 -247
- package/dist/{chunk-IMZFOMVX.js → chunk-USH4VU5D.js} +5 -3
- package/dist/{chunk-V7PEHQZU.js → chunk-UTYL4XVA.js} +21 -19
- package/dist/{chunk-NC755EKE.js → chunk-UTZMF5CV.js} +1 -1
- package/dist/{chunk-FQVSLBTV.js → chunk-UVKJVTKX.js} +3 -3
- package/dist/{chunk-Q367UGYN.js → chunk-V7T6URII.js} +10 -8
- package/dist/{chunk-6RYB3EET.js → chunk-VAZYNF6I.js} +14 -12
- package/dist/{chunk-J2H7YG3K.js → chunk-VBJHIRKV.js} +5 -3
- package/dist/{chunk-QVVGJVVX.js → chunk-VOBG7BLB.js} +18 -16
- package/dist/{chunk-7XWJ6ED2.js → chunk-W2W7YCFL.js} +16 -13
- package/dist/{chunk-XFDDJQT7.js → chunk-WA644MUQ.js} +15 -13
- package/dist/{chunk-6NCPLIIP.js → chunk-WDJGJ3HV.js} +441 -365
- package/dist/chunk-WGOQZ4PQ.js +488 -0
- package/dist/{chunk-3EWKO457.js → chunk-WS7KBKP4.js} +8 -6
- package/dist/chunk-X7QLAUNS.js +47 -0
- package/dist/{chunk-4FLNCK6Q.js → chunk-XC5ZDFW7.js} +13 -11
- package/dist/{chunk-VRO7KSGL.js → chunk-XF5UMMQL.js} +23 -21
- package/dist/{chunk-WOMQQWTO.js → chunk-XM3JE4QY.js} +7 -5
- package/dist/{chunk-73GFVW2L.js → chunk-XP5DF5MC.js} +51 -14
- package/dist/{chunk-W5VYJWOG.js → chunk-XUCHGEF5.js} +25 -23
- package/dist/{chunk-AFBCNZRZ.js → chunk-XVQQ3BQS.js} +26 -24
- package/dist/{chunk-VJFXQISZ.js → chunk-XXJSGCDO.js} +13 -9
- package/dist/{chunk-WXVTYLVH.js → chunk-XY6FVBBV.js} +4 -4
- package/dist/{chunk-QAVRDONY.js → chunk-XZQBFF65.js} +121 -119
- package/dist/{chunk-LZVHP7CT.js → chunk-Y3J365UC.js} +7 -5
- package/dist/{chunk-GUGQSIQM.js → chunk-Y6KPWRZJ.js} +11 -9
- package/dist/{chunk-ZNHQGG7J.js → chunk-YAUMNRCB.js} +4 -4
- package/dist/{chunk-6R5VHR3N.js → chunk-YEGGQG5E.js} +9 -7
- package/dist/{chunk-LHH5KG5A.js → chunk-YGNQUFVZ.js} +3 -3
- package/dist/{chunk-CMB7FXHJ.js → chunk-YGS2YVF2.js} +16 -14
- package/dist/{chunk-IKAW2KJU.js → chunk-YRKAJ42V.js} +525 -287
- package/dist/{chunk-7YQBDE5W.js → chunk-Z3KEX7ON.js} +6 -4
- package/dist/{chunk-ZNTTW4IT.js → chunk-Z4N7BKLN.js} +7 -5
- package/dist/{chunk-75OMRKY2.js → chunk-ZD64ZR64.js} +7 -5
- package/dist/{chunk-3ASYYMOX.js → chunk-ZJQ64T6M.js} +10 -8
- package/dist/files.json +563 -547
- package/dist/packages/sdk/npm/index.js +5530 -4902
- package/dist/packages/ui/dist/assets/{elk-api-DxfAMOJq.js → elk-api-ts8TigYQ.js} +2 -2
- package/dist/packages/ui/dist/assets/index-CIfmX7DJ.css +1 -0
- package/dist/packages/ui/dist/assets/index-DNtpSfZS.js +63 -0
- package/dist/packages/ui/dist/index.html +2 -2
- package/package.json +3 -3
- package/dist/chunk-5MYE42AP.js +0 -43
- package/dist/chunk-5O7U67UA.js +0 -57
- package/dist/chunk-6JVPBGQG.js +0 -50
- package/dist/chunk-AHFQHPFF.js +0 -49
- package/dist/chunk-CXTG6AWM.js +0 -40
- package/dist/chunk-GPNMSX5H.js +0 -36
- package/dist/chunk-HMWJWYE2.js +0 -31
- package/dist/chunk-ICBGVVRI.js +0 -317
- package/dist/chunk-J2CDBSFP.js +0 -69
- package/dist/chunk-NKJDO4UC.js +0 -39
- package/dist/chunk-NOYOFYAJ.js +0 -59
- package/dist/chunk-OXXZZ7HQ.js +0 -50
- package/dist/chunk-P4YUT7W7.js +0 -45
- package/dist/chunk-RQSLHZ7T.js +0 -36
- package/dist/chunk-RYQ4JCFT.js +0 -65
- package/dist/chunk-UMCDODBX.js +0 -53
- package/dist/chunk-VJZI6KFP.js +0 -47
- package/dist/chunk-W4TNCEI4.js +0 -44
- package/dist/chunk-XLZAAAPX.js +0 -43
- package/dist/packages/ui/dist/assets/index-Buit9TfP.js +0 -62
- package/dist/packages/ui/dist/assets/index-Jyc9dFeZ.css +0 -1
|
@@ -5,30 +5,35 @@ var __atticusUrl = (p) => new URL("./" + p, import.meta.url).href;
|
|
|
5
5
|
var __atticusPath = (p) => __atticusFileURLToPath(__atticusUrl(p));
|
|
6
6
|
import {
|
|
7
7
|
readOpenApiDocument
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-2VN4TLGI.js";
|
|
9
9
|
import {
|
|
10
10
|
globToRegExp
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-4U3JLIRC.js";
|
|
12
12
|
import {
|
|
13
13
|
DECLARED_TOPIC,
|
|
14
|
-
DEFAULT_CONVENTIONS,
|
|
15
14
|
Fact,
|
|
16
15
|
FactId,
|
|
17
16
|
JOINED_BY_AI,
|
|
17
|
+
JOINED_BY_BASE_PATH,
|
|
18
|
+
JOINED_BY_PATH,
|
|
19
|
+
JOINED_BY_PATH_OVERLAP,
|
|
18
20
|
JOINED_BY_PERSON,
|
|
19
21
|
JOINED_TO_SHARED_MAP,
|
|
22
|
+
JOIN_GUESS_FLAGS,
|
|
20
23
|
JOIN_HOW_FLAGS,
|
|
21
24
|
LINK_EVIDENCE_NOT_GAPS,
|
|
22
25
|
MOCK_FILE,
|
|
23
|
-
NEVER_CHECKED_STEPS,
|
|
24
26
|
SHARED_MAP_EVIDENCE,
|
|
25
27
|
citedFiles,
|
|
26
28
|
claimOnLines,
|
|
27
29
|
clusterServiceAddress,
|
|
30
|
+
configSecretField,
|
|
31
|
+
credentialLike,
|
|
28
32
|
decodeText,
|
|
33
|
+
dependencyLinkId,
|
|
29
34
|
factIdPart,
|
|
30
35
|
forwardSlashes,
|
|
31
|
-
|
|
36
|
+
hasSecretShape,
|
|
32
37
|
isBinaryText,
|
|
33
38
|
isLfsPointer,
|
|
34
39
|
isPatternPath,
|
|
@@ -36,11 +41,11 @@ import {
|
|
|
36
41
|
lineNamesClaim,
|
|
37
42
|
linksFor,
|
|
38
43
|
listRepoFilesSync,
|
|
39
|
-
|
|
40
|
-
notDeviceName,
|
|
44
|
+
looksLikeSecret,
|
|
41
45
|
noteProblem,
|
|
42
46
|
partsBuildWord,
|
|
43
47
|
partsNamePath,
|
|
48
|
+
placedComponentOf,
|
|
44
49
|
plainPathPrefix,
|
|
45
50
|
quoteHoldsSecret,
|
|
46
51
|
quoteMatches,
|
|
@@ -48,9 +53,17 @@ import {
|
|
|
48
53
|
redactSecrets,
|
|
49
54
|
staleCite,
|
|
50
55
|
toCanonicalYaml,
|
|
51
|
-
tokenUnits
|
|
56
|
+
tokenUnits
|
|
57
|
+
} from "./chunk-GLISHJ4G.js";
|
|
58
|
+
import {
|
|
59
|
+
DEFAULT_CONVENTIONS,
|
|
60
|
+
DEFAULT_GATEWAY_BUNDLE_FOLDERS,
|
|
61
|
+
NEVER_CHECKED_STEPS,
|
|
62
|
+
gatewayBundleTest,
|
|
63
|
+
normalizePath,
|
|
64
|
+
notDeviceName,
|
|
52
65
|
underFolders
|
|
53
|
-
} from "./chunk-
|
|
66
|
+
} from "./chunk-LZFKJ2BR.js";
|
|
54
67
|
|
|
55
68
|
// packages/verify/dist/source.js
|
|
56
69
|
import { lstatSync, readFileSync, realpathSync, statSync } from "node:fs";
|
|
@@ -166,6 +179,1046 @@ function tooBigToRead(source, path) {
|
|
|
166
179
|
return n !== void 0 && n > MAX_SOURCE_BYTES;
|
|
167
180
|
}
|
|
168
181
|
|
|
182
|
+
// packages/verify/dist/build-coords.js
|
|
183
|
+
var POM = /(^|\/)([^/]*[-_.])?pom\.xml$|\.pom$/i;
|
|
184
|
+
var GENERATED_POM = /(^|\/)(dependency-reduced-pom\.xml|\.flattened-pom\.xml)$/i;
|
|
185
|
+
var GRADLE_BUILD = /(^|\/)build\.gradle(\.kts)?$/i;
|
|
186
|
+
var GRADLE_SETTINGS = /(^|\/)settings\.gradle(\.kts)?$/i;
|
|
187
|
+
var VERSION_CATALOG = /(^|\/)gradle\/([\w-]+)\.versions\.toml$/i;
|
|
188
|
+
var slash = (p) => p.replace(/\\/g, "/");
|
|
189
|
+
var isPomFile = (p) => POM.test(slash(p)) && !GENERATED_POM.test(slash(p));
|
|
190
|
+
var isGradleBuildFile = (p) => GRADLE_BUILD.test(slash(p));
|
|
191
|
+
var isGradleSettingsFile = (p) => GRADLE_SETTINGS.test(slash(p));
|
|
192
|
+
var isVersionCatalogFile = (p) => VERSION_CATALOG.test(slash(p));
|
|
193
|
+
var isGradleFile = (p) => isGradleBuildFile(p) || isGradleSettingsFile(p) || isVersionCatalogFile(p);
|
|
194
|
+
var isBuildFile = (p) => isPomFile(p) || isGradleFile(p);
|
|
195
|
+
var isPomFileIn = (p, named) => isPomFile(p) || !!named?.has(slash(p)) && !GENERATED_POM.test(slash(p));
|
|
196
|
+
var isBuildFileIn = (p, named) => isBuildFile(p) || isPomFileIn(p, named);
|
|
197
|
+
var COORDINATE = /^[A-Za-z0-9_][A-Za-z0-9._-]*$/;
|
|
198
|
+
function lineIndex(text) {
|
|
199
|
+
const starts = [0];
|
|
200
|
+
for (let i = 0; i < text.length; i++)
|
|
201
|
+
if (text.charCodeAt(i) === 10)
|
|
202
|
+
starts.push(i + 1);
|
|
203
|
+
return (offset) => {
|
|
204
|
+
let lo = 0;
|
|
205
|
+
let hi = starts.length - 1;
|
|
206
|
+
while (lo < hi) {
|
|
207
|
+
const mid = lo + hi + 1 >> 1;
|
|
208
|
+
if (starts[mid] <= offset)
|
|
209
|
+
lo = mid;
|
|
210
|
+
else
|
|
211
|
+
hi = mid - 1;
|
|
212
|
+
}
|
|
213
|
+
return lo + 1;
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
function xmlTokens(text) {
|
|
217
|
+
const lineAt = lineIndex(text);
|
|
218
|
+
const out = [];
|
|
219
|
+
const pushText = (from, to, value = text.slice(from, to)) => {
|
|
220
|
+
const lead = value.length - value.trimStart().length;
|
|
221
|
+
if (value.trim())
|
|
222
|
+
out.push({ type: "text", value: value.trim(), line: lineAt(from + lead) });
|
|
223
|
+
};
|
|
224
|
+
let i = 0;
|
|
225
|
+
let textFrom = 0;
|
|
226
|
+
while (i < text.length) {
|
|
227
|
+
const lt = text.indexOf("<", i);
|
|
228
|
+
if (lt < 0)
|
|
229
|
+
break;
|
|
230
|
+
if (text.startsWith("<!--", lt)) {
|
|
231
|
+
pushText(textFrom, lt);
|
|
232
|
+
const end = text.indexOf("-->", lt + 4);
|
|
233
|
+
i = textFrom = end < 0 ? text.length : end + 3;
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
if (text.startsWith("<![CDATA[", lt)) {
|
|
237
|
+
pushText(textFrom, lt);
|
|
238
|
+
const end = text.indexOf("]]>", lt + 9);
|
|
239
|
+
const stop = end < 0 ? text.length : end;
|
|
240
|
+
pushText(lt + 9, stop);
|
|
241
|
+
i = textFrom = end < 0 ? text.length : end + 3;
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
if (text.startsWith("<?", lt) || text.startsWith("<!", lt)) {
|
|
245
|
+
pushText(textFrom, lt);
|
|
246
|
+
const end = text.indexOf(text.startsWith("<?", lt) ? "?>" : ">", lt + 2);
|
|
247
|
+
i = textFrom = end < 0 ? text.length : end + (text.startsWith("<?", lt) ? 2 : 1);
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
const m = /^<(\/?)([A-Za-z_][\w.:-]*)/.exec(text.slice(lt, lt + 200));
|
|
251
|
+
if (!m) {
|
|
252
|
+
i = lt + 1;
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
let j = lt + m[0].length;
|
|
256
|
+
let quote = "";
|
|
257
|
+
for (; j < text.length; j++) {
|
|
258
|
+
const c = text[j];
|
|
259
|
+
if (quote) {
|
|
260
|
+
if (c === quote)
|
|
261
|
+
quote = "";
|
|
262
|
+
} else if (c === '"' || c === "'")
|
|
263
|
+
quote = c;
|
|
264
|
+
else if (c === ">")
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
267
|
+
pushText(textFrom, lt);
|
|
268
|
+
const close = m[1] === "/";
|
|
269
|
+
const self = !close && text[j - 1] === "/";
|
|
270
|
+
out.push({ type: close ? "close" : self ? "self" : "open", name: m[2], line: lineAt(lt) });
|
|
271
|
+
i = textFrom = j + 1;
|
|
272
|
+
}
|
|
273
|
+
pushText(textFrom, text.length);
|
|
274
|
+
return out;
|
|
275
|
+
}
|
|
276
|
+
var leaf = (frame, name) => frame.leaves.get(name);
|
|
277
|
+
function pomCoordinates(lines) {
|
|
278
|
+
const held = POMS.get(lines);
|
|
279
|
+
if (held)
|
|
280
|
+
return held;
|
|
281
|
+
const out = readPom(lines);
|
|
282
|
+
POMS.set(lines, out);
|
|
283
|
+
return out;
|
|
284
|
+
}
|
|
285
|
+
var POMS = /* @__PURE__ */ new WeakMap();
|
|
286
|
+
function readPom(lines) {
|
|
287
|
+
const out = { dependencies: [], modules: [], properties: /* @__PURE__ */ new Map() };
|
|
288
|
+
const text = lines.map((l, i) => {
|
|
289
|
+
const t = l.endsWith("\r") ? l.slice(0, -1) : l;
|
|
290
|
+
return i === 0 && t.charCodeAt(0) === 65279 ? t.slice(1) : t;
|
|
291
|
+
}).join("\n");
|
|
292
|
+
const stack = [];
|
|
293
|
+
const names = () => stack.map((f) => f.name);
|
|
294
|
+
for (const t of xmlTokens(text)) {
|
|
295
|
+
const top = stack[stack.length - 1];
|
|
296
|
+
if (t.type === "text") {
|
|
297
|
+
if (top && !top.text) {
|
|
298
|
+
top.text = t.value;
|
|
299
|
+
top.textLine = t.line;
|
|
300
|
+
}
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
if (t.type !== "close") {
|
|
304
|
+
if (top)
|
|
305
|
+
top.children = true;
|
|
306
|
+
if (t.type === "self") {
|
|
307
|
+
if (t.name === "relativePath" && top?.name === "parent")
|
|
308
|
+
top.leaves.set("relativePath", { value: "", line: t.line });
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
stack.push({ name: t.name, leaves: /* @__PURE__ */ new Map(), children: false, text: "", textLine: t.line });
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
314
|
+
const at = names().lastIndexOf(t.name);
|
|
315
|
+
if (at < 0)
|
|
316
|
+
continue;
|
|
317
|
+
while (stack.length > at + 1)
|
|
318
|
+
stack.pop();
|
|
319
|
+
const done = stack.pop();
|
|
320
|
+
const parent = stack[stack.length - 1];
|
|
321
|
+
const value = !done.children && done.text ? { value: done.text, line: done.textLine } : void 0;
|
|
322
|
+
if (value && parent)
|
|
323
|
+
parent.leaves.set(done.name, value);
|
|
324
|
+
const path = [...names(), done.name];
|
|
325
|
+
if (done.name === "dependency") {
|
|
326
|
+
const g = leaf(done, "groupId");
|
|
327
|
+
const a = leaf(done, "artifactId");
|
|
328
|
+
const v = leaf(done, "version");
|
|
329
|
+
const s = leaf(done, "scope");
|
|
330
|
+
out.dependencies.push({
|
|
331
|
+
...g ? { group: g } : {},
|
|
332
|
+
...a ? { artifact: a } : {},
|
|
333
|
+
...v ? { version: v } : {},
|
|
334
|
+
...s ? { scope: s } : {},
|
|
335
|
+
managed: path.includes("dependencyManagement"),
|
|
336
|
+
plugin: path.includes("plugin") || path.includes("extension")
|
|
337
|
+
});
|
|
338
|
+
} else if (done.name === "module" && value && path[0] === "project") {
|
|
339
|
+
const p = path.join("/");
|
|
340
|
+
if (p === "project/modules/module" || p === "project/profiles/profile/modules/module")
|
|
341
|
+
out.modules.push(value);
|
|
342
|
+
} else if (done.name === "properties" && path.length === 2 && path[0] === "project") {
|
|
343
|
+
for (const [k, v] of done.leaves)
|
|
344
|
+
out.properties.set(k, v);
|
|
345
|
+
} else if (done.name === "parent" && path.length === 2 && path[0] === "project") {
|
|
346
|
+
if (leaf(done, "groupId"))
|
|
347
|
+
out.parentGroup = leaf(done, "groupId");
|
|
348
|
+
if (leaf(done, "artifactId"))
|
|
349
|
+
out.parentArtifact = leaf(done, "artifactId");
|
|
350
|
+
if (leaf(done, "version"))
|
|
351
|
+
out.parentVersion = leaf(done, "version");
|
|
352
|
+
if (leaf(done, "relativePath"))
|
|
353
|
+
out.parentRelativePath = leaf(done, "relativePath");
|
|
354
|
+
} else if (done.name === "project" && path.length === 1) {
|
|
355
|
+
if (leaf(done, "groupId"))
|
|
356
|
+
out.group = leaf(done, "groupId");
|
|
357
|
+
if (leaf(done, "artifactId"))
|
|
358
|
+
out.artifact = leaf(done, "artifactId");
|
|
359
|
+
if (leaf(done, "version"))
|
|
360
|
+
out.version = leaf(done, "version");
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
return out;
|
|
364
|
+
}
|
|
365
|
+
var PROPERTY = /^\$\{([^}]+)\}$/;
|
|
366
|
+
function resolvePomValue(at, pom, o = {}, depth = 0) {
|
|
367
|
+
const m = PROPERTY.exec(at.value.trim());
|
|
368
|
+
if (!m)
|
|
369
|
+
return { value: at.value, line: at.line };
|
|
370
|
+
const key = m[1].trim();
|
|
371
|
+
const own = {
|
|
372
|
+
"project.groupId": pom.group ?? pom.parentGroup,
|
|
373
|
+
"pom.groupId": pom.group ?? pom.parentGroup,
|
|
374
|
+
groupId: pom.group ?? pom.parentGroup,
|
|
375
|
+
"project.artifactId": pom.artifact,
|
|
376
|
+
"pom.artifactId": pom.artifact,
|
|
377
|
+
artifactId: pom.artifact,
|
|
378
|
+
"project.version": pom.version ?? pom.parentVersion,
|
|
379
|
+
"pom.version": pom.version ?? pom.parentVersion,
|
|
380
|
+
"project.parent.groupId": pom.parentGroup,
|
|
381
|
+
"parent.groupId": pom.parentGroup,
|
|
382
|
+
"project.parent.artifactId": pom.parentArtifact,
|
|
383
|
+
"parent.artifactId": pom.parentArtifact,
|
|
384
|
+
"project.parent.version": pom.parentVersion,
|
|
385
|
+
"parent.version": pom.parentVersion
|
|
386
|
+
};
|
|
387
|
+
const builtin = Object.hasOwn(own, key);
|
|
388
|
+
let to;
|
|
389
|
+
if (builtin) {
|
|
390
|
+
const b = own[key];
|
|
391
|
+
if (b)
|
|
392
|
+
to = { at: b, file: o.file ?? "" };
|
|
393
|
+
} else {
|
|
394
|
+
const mine = pom.properties.get(key);
|
|
395
|
+
if (mine)
|
|
396
|
+
to = { at: mine, file: o.file ?? "" };
|
|
397
|
+
else
|
|
398
|
+
for (const p of o.parents ?? []) {
|
|
399
|
+
const theirs = p.pom.properties.get(key);
|
|
400
|
+
if (theirs) {
|
|
401
|
+
to = { at: theirs, file: p.file };
|
|
402
|
+
break;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
if (!to || to.at === at || depth > 4)
|
|
407
|
+
return { missing: key };
|
|
408
|
+
const next = resolvePomValue(to.at, pom, o, depth + 1);
|
|
409
|
+
if ("missing" in next)
|
|
410
|
+
return next;
|
|
411
|
+
const via = [...builtin ? [] : [{ file: to.file, line: to.at.line }], ...next.via ?? []];
|
|
412
|
+
return { value: next.value, line: at.line, ...via.length ? { via } : {} };
|
|
413
|
+
}
|
|
414
|
+
function pomTarget(dir, rel) {
|
|
415
|
+
const to = joinDir(dir, rel.trim());
|
|
416
|
+
if (/\.(xml|pom)$/i.test(rel.trim()))
|
|
417
|
+
return to;
|
|
418
|
+
return to ? `${to}/pom.xml` : "pom.xml";
|
|
419
|
+
}
|
|
420
|
+
function pomFilesNamed(files, linesOf2) {
|
|
421
|
+
const held = NAMED.get(files);
|
|
422
|
+
if (held)
|
|
423
|
+
return held;
|
|
424
|
+
const all2 = new Set(files.map(slash));
|
|
425
|
+
const out = /* @__PURE__ */ new Set();
|
|
426
|
+
let next = files.map(slash).filter(isPomFile);
|
|
427
|
+
for (let round = 0; round < 5 && next.length; round++) {
|
|
428
|
+
const found = [];
|
|
429
|
+
for (const f of next) {
|
|
430
|
+
const lines = linesOf2(f);
|
|
431
|
+
const rel = lines ? pomCoordinates(lines).parentRelativePath?.value.trim() : void 0;
|
|
432
|
+
if (!rel)
|
|
433
|
+
continue;
|
|
434
|
+
const to = pomTarget(dirOf(f), rel);
|
|
435
|
+
if (all2.has(to) && !isPomFile(to) && !out.has(to) && !GENERATED_POM.test(to)) {
|
|
436
|
+
out.add(to);
|
|
437
|
+
found.push(to);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
next = found;
|
|
441
|
+
}
|
|
442
|
+
NAMED.set(files, out);
|
|
443
|
+
return out;
|
|
444
|
+
}
|
|
445
|
+
var NAMED = /* @__PURE__ */ new WeakMap();
|
|
446
|
+
function moduleParentsOf(files, linesOf2) {
|
|
447
|
+
const held = LISTED.get(files);
|
|
448
|
+
if (held)
|
|
449
|
+
return held;
|
|
450
|
+
const named = pomFilesNamed(files, linesOf2);
|
|
451
|
+
const out = /* @__PURE__ */ new Map();
|
|
452
|
+
for (const f of files.map(slash).sort()) {
|
|
453
|
+
if (!isPomFileIn(f, named))
|
|
454
|
+
continue;
|
|
455
|
+
const lines = linesOf2(f);
|
|
456
|
+
if (!lines)
|
|
457
|
+
continue;
|
|
458
|
+
for (const m of pomCoordinates(lines).modules) {
|
|
459
|
+
const dir = dirOf(pomTarget(dirOf(f), m.value));
|
|
460
|
+
if (!out.has(dir))
|
|
461
|
+
out.set(dir, f);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
LISTED.set(files, out);
|
|
465
|
+
return out;
|
|
466
|
+
}
|
|
467
|
+
var LISTED = /* @__PURE__ */ new WeakMap();
|
|
468
|
+
function pomParents(file, linesOf2, files) {
|
|
469
|
+
const out = [];
|
|
470
|
+
const seen = /* @__PURE__ */ new Set([slash(file)]);
|
|
471
|
+
let at = slash(file);
|
|
472
|
+
let lines = linesOf2(at);
|
|
473
|
+
for (let n = 0; n < 6 && lines; n++) {
|
|
474
|
+
const pom = pomCoordinates(lines);
|
|
475
|
+
if (!pom.parentArtifact)
|
|
476
|
+
break;
|
|
477
|
+
const rel = pom.parentRelativePath?.value.trim();
|
|
478
|
+
if (rel === "")
|
|
479
|
+
break;
|
|
480
|
+
const dir = dirOf(at);
|
|
481
|
+
const candidates = rel ? [pomTarget(dir, rel)] : [
|
|
482
|
+
...files ? [moduleParentsOf(files, linesOf2).get(dir)] : [],
|
|
483
|
+
...dir ? [pomTarget(dir, "..")] : []
|
|
484
|
+
];
|
|
485
|
+
const want = pom.parentArtifact.value.trim();
|
|
486
|
+
let found;
|
|
487
|
+
for (const c of candidates) {
|
|
488
|
+
if (!c || seen.has(c))
|
|
489
|
+
continue;
|
|
490
|
+
const ls = linesOf2(c);
|
|
491
|
+
if (!ls)
|
|
492
|
+
continue;
|
|
493
|
+
const theirs = pomCoordinates(ls);
|
|
494
|
+
const name = theirs.artifact?.value.trim();
|
|
495
|
+
if (name !== void 0 && !PROPERTY.test(name) && !PROPERTY.test(want) && name !== want)
|
|
496
|
+
continue;
|
|
497
|
+
found = { file: c, pom: theirs };
|
|
498
|
+
break;
|
|
499
|
+
}
|
|
500
|
+
if (!found)
|
|
501
|
+
break;
|
|
502
|
+
out.push(found);
|
|
503
|
+
seen.add(found.file);
|
|
504
|
+
at = found.file;
|
|
505
|
+
lines = linesOf2(at);
|
|
506
|
+
}
|
|
507
|
+
return out;
|
|
508
|
+
}
|
|
509
|
+
var CONFIGURATION = `(?:(["'])([A-Za-z]\\w*)\\1\\s*(?=\\()|([A-Za-z]\\w*))`;
|
|
510
|
+
var GRADLE_DEP = new RegExp(`^\\s*${CONFIGURATION}\\s*\\(?\\s*(?:(platform|enforcedPlatform)\\s*\\(\\s*)?(['"])([^'"\\s]+)\\5`);
|
|
511
|
+
var GRADLE_MAP_DEP = new RegExp(`^\\s*${CONFIGURATION}\\s*\\(?\\s*group\\s*[:=]\\s*(['"])([^'"]+)\\4\\s*,\\s*name\\s*[:=]\\s*(['"])([^'"]+)\\6(?:\\s*,\\s*version\\s*[:=]\\s*(['"])([^'"]+)\\8)?`);
|
|
512
|
+
var NOT_A_CONFIGURATION = /* @__PURE__ */ new Set([
|
|
513
|
+
"id",
|
|
514
|
+
"apply",
|
|
515
|
+
"plugin",
|
|
516
|
+
"include",
|
|
517
|
+
"includeBuild",
|
|
518
|
+
"classpath",
|
|
519
|
+
"group",
|
|
520
|
+
"version",
|
|
521
|
+
"url",
|
|
522
|
+
"uri",
|
|
523
|
+
"dependency",
|
|
524
|
+
"dependencySet",
|
|
525
|
+
"entry",
|
|
526
|
+
"mavenBom",
|
|
527
|
+
"imports",
|
|
528
|
+
"force",
|
|
529
|
+
"exclude",
|
|
530
|
+
"module",
|
|
531
|
+
"substitute",
|
|
532
|
+
"because",
|
|
533
|
+
"strictly",
|
|
534
|
+
"require",
|
|
535
|
+
"prefer",
|
|
536
|
+
"reject",
|
|
537
|
+
"alias",
|
|
538
|
+
"from",
|
|
539
|
+
"maven",
|
|
540
|
+
"mainClass",
|
|
541
|
+
"println",
|
|
542
|
+
"description"
|
|
543
|
+
]);
|
|
544
|
+
var TOOL_CONFIGURATIONS = /* @__PURE__ */ new Set([
|
|
545
|
+
"checkstyle",
|
|
546
|
+
"pmd",
|
|
547
|
+
"spotbugs",
|
|
548
|
+
"spotbugsPlugins",
|
|
549
|
+
"spotbugsSlf4j",
|
|
550
|
+
"jacocoAgent",
|
|
551
|
+
"jacocoAnt",
|
|
552
|
+
"detekt",
|
|
553
|
+
"detektPlugins",
|
|
554
|
+
"ktlint",
|
|
555
|
+
"ktlintRuleset",
|
|
556
|
+
"codenarc",
|
|
557
|
+
"errorprone",
|
|
558
|
+
"pitest"
|
|
559
|
+
]);
|
|
560
|
+
function gradleToolConfigurationOn(line) {
|
|
561
|
+
const c = /^\s*(["']?)([A-Za-z]\w*)\1\s*[\s(]/.exec(line)?.[2];
|
|
562
|
+
return c && TOOL_CONFIGURATIONS.has(c) ? c : void 0;
|
|
563
|
+
}
|
|
564
|
+
var TEST_CONFIGURATION = /^(test|testFixtures|\w+Test)(Implementation|Api|CompileOnly|RuntimeOnly|Compile|Runtime|AnnotationProcessor|CompileClasspath|RuntimeClasspath)$/;
|
|
565
|
+
function scopeOfConfiguration(c, platform) {
|
|
566
|
+
if (platform)
|
|
567
|
+
return "import";
|
|
568
|
+
if (TEST_CONFIGURATION.test(c))
|
|
569
|
+
return "test";
|
|
570
|
+
if (/^(compileOnly|annotationProcessor|kapt|ksp|compileOnlyApi|providedCompile|providedRuntime)$/.test(c))
|
|
571
|
+
return "provided";
|
|
572
|
+
if (/^(runtimeOnly|runtime|developmentOnly|testAndDevelopmentOnly)$/.test(c))
|
|
573
|
+
return "runtime";
|
|
574
|
+
return "compile";
|
|
575
|
+
}
|
|
576
|
+
function gradleDependencyOn(line) {
|
|
577
|
+
if (gradleToolConfigurationOn(line))
|
|
578
|
+
return void 0;
|
|
579
|
+
const map = GRADLE_MAP_DEP.exec(line);
|
|
580
|
+
const mapConf = map ? map[2] ?? map[3] : "";
|
|
581
|
+
if (map && !NOT_A_CONFIGURATION.has(mapConf)) {
|
|
582
|
+
if (!COORDINATE.test(map[5]) || !COORDINATE.test(map[7]))
|
|
583
|
+
return void 0;
|
|
584
|
+
return {
|
|
585
|
+
configuration: mapConf,
|
|
586
|
+
group: map[5],
|
|
587
|
+
name: map[7],
|
|
588
|
+
...map[9] ? { version: map[9] } : {},
|
|
589
|
+
scope: scopeOfConfiguration(mapConf, false)
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
const m = GRADLE_DEP.exec(line);
|
|
593
|
+
const conf = m ? m[2] ?? m[3] : "";
|
|
594
|
+
if (!m || NOT_A_CONFIGURATION.has(conf))
|
|
595
|
+
return void 0;
|
|
596
|
+
const parts = m[6].split(":");
|
|
597
|
+
if (parts.length < 2 || !COORDINATE.test(parts[0]) || !COORDINATE.test(parts[1]))
|
|
598
|
+
return void 0;
|
|
599
|
+
return {
|
|
600
|
+
configuration: conf,
|
|
601
|
+
group: parts[0],
|
|
602
|
+
name: parts[1],
|
|
603
|
+
...parts[2] ? { version: parts[2] } : {},
|
|
604
|
+
scope: scopeOfConfiguration(conf, !!m[4])
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
function gradleBlocks(lines) {
|
|
608
|
+
const held = BLOCKS.get(lines);
|
|
609
|
+
if (held)
|
|
610
|
+
return held;
|
|
611
|
+
const out = readBlocks(lines);
|
|
612
|
+
BLOCKS.set(lines, out);
|
|
613
|
+
return out;
|
|
614
|
+
}
|
|
615
|
+
var BLOCKS = /* @__PURE__ */ new WeakMap();
|
|
616
|
+
function readBlocks(lines) {
|
|
617
|
+
const out = [];
|
|
618
|
+
const stack = [];
|
|
619
|
+
let triple = "";
|
|
620
|
+
let block = false;
|
|
621
|
+
let previous = "";
|
|
622
|
+
for (const raw of lines) {
|
|
623
|
+
out.push([...stack]);
|
|
624
|
+
let code2 = "";
|
|
625
|
+
for (let i = 0; i < raw.length; i++) {
|
|
626
|
+
const c = raw[i];
|
|
627
|
+
if (block) {
|
|
628
|
+
if (raw.startsWith("*/", i)) {
|
|
629
|
+
block = false;
|
|
630
|
+
i++;
|
|
631
|
+
}
|
|
632
|
+
continue;
|
|
633
|
+
}
|
|
634
|
+
if (triple) {
|
|
635
|
+
if (raw.startsWith(triple, i)) {
|
|
636
|
+
code2 += triple;
|
|
637
|
+
i += 2;
|
|
638
|
+
triple = "";
|
|
639
|
+
}
|
|
640
|
+
continue;
|
|
641
|
+
}
|
|
642
|
+
if (raw.startsWith("//", i))
|
|
643
|
+
break;
|
|
644
|
+
if (raw.startsWith("/*", i)) {
|
|
645
|
+
block = true;
|
|
646
|
+
i++;
|
|
647
|
+
continue;
|
|
648
|
+
}
|
|
649
|
+
if (raw.startsWith("'''", i) || raw.startsWith('"""', i)) {
|
|
650
|
+
triple = raw.slice(i, i + 3);
|
|
651
|
+
code2 += triple;
|
|
652
|
+
i += 2;
|
|
653
|
+
continue;
|
|
654
|
+
}
|
|
655
|
+
if (c === "'" || c === '"') {
|
|
656
|
+
let j = i + 1;
|
|
657
|
+
for (; j < raw.length && raw[j] !== c; j++)
|
|
658
|
+
if (raw[j] === "\\")
|
|
659
|
+
j++;
|
|
660
|
+
code2 += raw.slice(i, j + 1).replace(/[{}]/g, " ");
|
|
661
|
+
i = j;
|
|
662
|
+
continue;
|
|
663
|
+
}
|
|
664
|
+
if (c === "{") {
|
|
665
|
+
const before = code2.trim() || previous;
|
|
666
|
+
const m = /([A-Za-z_][\w.]*)\s*(?:\(\s*([^()]*?)\s*\))?\s*(?:\w+\s*->\s*)?$/.exec(before);
|
|
667
|
+
const name = m?.[1] ?? "";
|
|
668
|
+
stack.push(name === "project" && m?.[2] ? `project(${m[2].replace(/['"]/g, "")})` : name);
|
|
669
|
+
code2 = "";
|
|
670
|
+
continue;
|
|
671
|
+
}
|
|
672
|
+
if (c === "}") {
|
|
673
|
+
stack.pop();
|
|
674
|
+
code2 = "";
|
|
675
|
+
continue;
|
|
676
|
+
}
|
|
677
|
+
code2 += c;
|
|
678
|
+
}
|
|
679
|
+
if (code2.trim())
|
|
680
|
+
previous = code2.trim();
|
|
681
|
+
}
|
|
682
|
+
return out;
|
|
683
|
+
}
|
|
684
|
+
var PROJECT_BLOCK = (b) => b === "subprojects" || b === "allprojects" || /^project\(:?[^)]*\)$/.test(b);
|
|
685
|
+
var projectOf = (b) => /^project\(:?([^)]*)\)$/.exec(b)?.[1];
|
|
686
|
+
function gradleDependencyAt(lines, line, blocks = gradleBlocks(lines)) {
|
|
687
|
+
const d = gradleDependencyOn(lines[line - 1] ?? "");
|
|
688
|
+
if (!d)
|
|
689
|
+
return void 0;
|
|
690
|
+
const at = projectDependenciesAt(blocks, line);
|
|
691
|
+
return "none" in at ? at : { dependency: d, ...at };
|
|
692
|
+
}
|
|
693
|
+
function projectDependenciesAt(blocks, line) {
|
|
694
|
+
const stack = blocks[line - 1] ?? [];
|
|
695
|
+
const outer = stack.slice(0, -1);
|
|
696
|
+
if (stack[stack.length - 1] !== "dependencies" || !outer.every(PROJECT_BLOCK)) {
|
|
697
|
+
const inside = stack.filter((b) => !PROJECT_BLOCK(b)).join(" { ");
|
|
698
|
+
return { none: inside ? `${inside} { }` : "no dependencies { } block" };
|
|
699
|
+
}
|
|
700
|
+
const proj = outer.map(projectOf).find((x) => x !== void 0);
|
|
701
|
+
return {
|
|
702
|
+
...proj !== void 0 ? { project: proj } : {},
|
|
703
|
+
...outer.some((b) => b === "subprojects" || b === "allprojects") ? { all: true } : {}
|
|
704
|
+
};
|
|
705
|
+
}
|
|
706
|
+
function catalogVersions(lines) {
|
|
707
|
+
const out = /* @__PURE__ */ new Map();
|
|
708
|
+
let section = "";
|
|
709
|
+
lines.forEach((raw, i) => {
|
|
710
|
+
const l = raw.replace(/\r$/, "");
|
|
711
|
+
const s = /^\s*\[\s*([^\]]+?)\s*\]\s*(#.*)?$/.exec(l);
|
|
712
|
+
if (s)
|
|
713
|
+
return void (section = s[1]);
|
|
714
|
+
if (section !== "versions")
|
|
715
|
+
return;
|
|
716
|
+
const m = /^\s*(["']?)([A-Za-z][\w.-]*)\1\s*=\s*(["'])([^"']+)\3\s*(#.*)?$/.exec(l);
|
|
717
|
+
if (m)
|
|
718
|
+
out.set(m[2], { value: m[4], line: i + 1 });
|
|
719
|
+
});
|
|
720
|
+
return out;
|
|
721
|
+
}
|
|
722
|
+
var catalogNameOf = (file) => VERSION_CATALOG.exec(slash(file))?.[2];
|
|
723
|
+
var accessorOf = (alias) => alias.replace(/[-_.]+/g, ".");
|
|
724
|
+
function catalogLibraryAt(lines, line) {
|
|
725
|
+
let section = "";
|
|
726
|
+
for (let i = 0; i < line && i < lines.length; i++) {
|
|
727
|
+
const m2 = /^\s*\[\s*([^\]]+?)\s*\]\s*(#.*)?$/.exec((lines[i] ?? "").replace(/\r$/, ""));
|
|
728
|
+
if (m2)
|
|
729
|
+
section = m2[1];
|
|
730
|
+
}
|
|
731
|
+
if (section !== "libraries")
|
|
732
|
+
return void 0;
|
|
733
|
+
const text = (lines[line - 1] ?? "").replace(/\r$/, "");
|
|
734
|
+
const m = /^\s*(["']?)([A-Za-z][\w.-]*)\1\s*=\s*(.+)$/.exec(text);
|
|
735
|
+
if (!m)
|
|
736
|
+
return void 0;
|
|
737
|
+
const alias = m[2];
|
|
738
|
+
const body = m[3].replace(/\s+#.*$/, "").trim();
|
|
739
|
+
const str = (key) => new RegExp(`(?:^|[{,\\s])${key.replace(".", "\\.")}\\s*=\\s*(["'])([^"']+)\\1`).exec(body)?.[2];
|
|
740
|
+
let group;
|
|
741
|
+
let name;
|
|
742
|
+
let version;
|
|
743
|
+
const whole = /^(["'])([^"']+)\1$/.exec(body);
|
|
744
|
+
if (whole)
|
|
745
|
+
[group, name, version] = whole[2].split(":");
|
|
746
|
+
else if (body.startsWith("{")) {
|
|
747
|
+
const module = str("module");
|
|
748
|
+
if (module)
|
|
749
|
+
[group, name] = module.split(":");
|
|
750
|
+
else {
|
|
751
|
+
group = str("group");
|
|
752
|
+
name = str("name");
|
|
753
|
+
}
|
|
754
|
+
version = str("version");
|
|
755
|
+
}
|
|
756
|
+
const versionRef = body.startsWith("{") ? str("version.ref") : void 0;
|
|
757
|
+
if (!group || !name || !COORDINATE.test(group) || !COORDINATE.test(name))
|
|
758
|
+
return void 0;
|
|
759
|
+
return {
|
|
760
|
+
alias,
|
|
761
|
+
accessor: accessorOf(alias),
|
|
762
|
+
group,
|
|
763
|
+
name,
|
|
764
|
+
...version ? { version } : {},
|
|
765
|
+
...versionRef ? { versionRef } : {}
|
|
766
|
+
};
|
|
767
|
+
}
|
|
768
|
+
function gradleCatalogUseOn(line) {
|
|
769
|
+
const m = new RegExp(`^\\s*${CONFIGURATION}\\s*\\(?\\s*(?:(platform|enforcedPlatform)\\s*\\(\\s*)?([A-Za-z]\\w*)\\.([A-Za-z][\\w.]*?)\\s*\\)?\\s*\\)?\\s*(?:\\{.*)?(?:\\/\\/.*)?\\r?$`).exec(line);
|
|
770
|
+
const conf = m ? m[2] ?? m[3] : "";
|
|
771
|
+
if (!m || NOT_A_CONFIGURATION.has(conf) || TOOL_CONFIGURATIONS.has(conf))
|
|
772
|
+
return void 0;
|
|
773
|
+
if (/^(bundles|plugins|versions)\./.test(m[6]) || m[5] === "project")
|
|
774
|
+
return void 0;
|
|
775
|
+
return {
|
|
776
|
+
configuration: conf,
|
|
777
|
+
catalog: m[5],
|
|
778
|
+
accessor: m[6],
|
|
779
|
+
scope: scopeOfConfiguration(conf, !!m[4])
|
|
780
|
+
};
|
|
781
|
+
}
|
|
782
|
+
function gradleGroupOn(line) {
|
|
783
|
+
return /^\s*(?:(?:allprojects|subprojects)\s*\{\s*)?(?:project\.)?group\s*=?\s*(['"])([^'"]+)\1\s*\}?\s*$/.exec(line)?.[2];
|
|
784
|
+
}
|
|
785
|
+
function gradleNameOn(line) {
|
|
786
|
+
return /^\s*(?:rootProject\.name|archivesBaseName|(?:base\.)?archivesName(?:\.set)?)\s*[=(]?\s*(['"])([^'"]+)\1\s*\)?\s*$/.exec(line)?.[2];
|
|
787
|
+
}
|
|
788
|
+
function gradleProjectsOn(line) {
|
|
789
|
+
const rename = /^\s*project\s*\(\s*(['"]):?([^'"]+)\1\s*\)\.name\s*=\s*(['"])([^'"]+)\3\s*$/.exec(line);
|
|
790
|
+
if (rename)
|
|
791
|
+
return [{ path: rename[2], name: rename[4], renamed: true }];
|
|
792
|
+
const inc = /^\s*include\s*\(?\s*((?:(['"])[^'"]+\2\s*,?\s*)+)\)?\s*$/.exec(line);
|
|
793
|
+
if (!inc)
|
|
794
|
+
return [];
|
|
795
|
+
return [...inc[1].matchAll(/(['"]):?([^'"]+)\1/g)].map((m) => ({
|
|
796
|
+
path: m[2],
|
|
797
|
+
name: m[2].split(":").pop()
|
|
798
|
+
}));
|
|
799
|
+
}
|
|
800
|
+
function gradleProjects(lines) {
|
|
801
|
+
const held = PROJECTS.get(lines);
|
|
802
|
+
if (held)
|
|
803
|
+
return held;
|
|
804
|
+
const out = [];
|
|
805
|
+
let open = "";
|
|
806
|
+
const names = (text, line) => {
|
|
807
|
+
for (const m of text.matchAll(/(['"]):?([^'"]+)\1/g))
|
|
808
|
+
out.push({ path: m[2], name: m[2].split(":").pop(), line });
|
|
809
|
+
};
|
|
810
|
+
lines.forEach((raw, i) => {
|
|
811
|
+
const code2 = raw.replace(/\r$/, "").replace(/\s\/\/.*$|^\s*\/\/.*$/, "");
|
|
812
|
+
if (open) {
|
|
813
|
+
names(code2, i + 1);
|
|
814
|
+
if (open === "paren" ? code2.includes(")") : !/,\s*$/.test(code2))
|
|
815
|
+
open = "";
|
|
816
|
+
return;
|
|
817
|
+
}
|
|
818
|
+
const rename = gradleProjectsOn(code2);
|
|
819
|
+
if (rename.length && rename[0].renamed)
|
|
820
|
+
return void out.push({ ...rename[0], line: i + 1 });
|
|
821
|
+
const inc = /^\s*include(?!\w)\s*(\(?)\s*(.*)$/.exec(code2);
|
|
822
|
+
if (!inc)
|
|
823
|
+
return;
|
|
824
|
+
names(inc[2], i + 1);
|
|
825
|
+
if (inc[1] === "(" && !inc[2].includes(")"))
|
|
826
|
+
open = "paren";
|
|
827
|
+
else if (inc[1] !== "(" && /,\s*$/.test(inc[2]))
|
|
828
|
+
open = "comma";
|
|
829
|
+
});
|
|
830
|
+
PROJECTS.set(lines, out);
|
|
831
|
+
return out;
|
|
832
|
+
}
|
|
833
|
+
var PROJECTS = /* @__PURE__ */ new WeakMap();
|
|
834
|
+
function projectDirs(settings) {
|
|
835
|
+
const dirs = /* @__PURE__ */ new Map();
|
|
836
|
+
for (const l of settings ?? []) {
|
|
837
|
+
const m = /^\s*project\s*\(\s*(['"]):?([^'"]+)\1\s*\)\.projectDir\s*=\s*(?:file\s*\(|new\s+File\s*\(\s*(?:settingsDir|rootDir)\s*,)\s*(['"])([^'"]+)\3\s*\)\s*$/.exec(l);
|
|
838
|
+
if (m)
|
|
839
|
+
dirs.set(m[2], normDir(m[4]));
|
|
840
|
+
}
|
|
841
|
+
return dirs;
|
|
842
|
+
}
|
|
843
|
+
var normDir = (p) => slash(p).replace(/^\.\//, "").replace(/\/(pom\.xml|build\.gradle(\.kts)?)$/i, "").replace(/\/+$/, "");
|
|
844
|
+
var dirOf = (file) => {
|
|
845
|
+
const f = slash(file);
|
|
846
|
+
return f.includes("/") ? f.slice(0, f.lastIndexOf("/")) : "";
|
|
847
|
+
};
|
|
848
|
+
var joinDir = (base2, rel) => {
|
|
849
|
+
const parts = base2 ? base2.split("/") : [];
|
|
850
|
+
for (const s of normDir(rel).split("/")) {
|
|
851
|
+
if (!s || s === ".")
|
|
852
|
+
continue;
|
|
853
|
+
if (s === "..")
|
|
854
|
+
parts.pop();
|
|
855
|
+
else
|
|
856
|
+
parts.push(s);
|
|
857
|
+
}
|
|
858
|
+
return parts.join("/");
|
|
859
|
+
};
|
|
860
|
+
var settingsOf = (linesOf2) => {
|
|
861
|
+
for (const f of ["settings.gradle", "settings.gradle.kts"]) {
|
|
862
|
+
const l = linesOf2(f);
|
|
863
|
+
if (l)
|
|
864
|
+
return { file: f, lines: l };
|
|
865
|
+
}
|
|
866
|
+
return void 0;
|
|
867
|
+
};
|
|
868
|
+
function buildLineOf(f) {
|
|
869
|
+
if (!isVersionCatalogFile(f.cite.file))
|
|
870
|
+
return f.cite;
|
|
871
|
+
return (f.cite.with ?? []).find((p) => isGradleBuildFile(p.file));
|
|
872
|
+
}
|
|
873
|
+
var ENVS = /* @__PURE__ */ new WeakMap();
|
|
874
|
+
function gradleEnvOf(linesOf2) {
|
|
875
|
+
const held = ENVS.get(linesOf2);
|
|
876
|
+
if (held)
|
|
877
|
+
return held;
|
|
878
|
+
const settings = settingsOf(linesOf2);
|
|
879
|
+
const env = {
|
|
880
|
+
...settings ? { settings } : {},
|
|
881
|
+
dirs: projectDirs(settings?.lines),
|
|
882
|
+
projects: settings ? gradleProjects(settings.lines) : []
|
|
883
|
+
};
|
|
884
|
+
ENVS.set(linesOf2, env);
|
|
885
|
+
return env;
|
|
886
|
+
}
|
|
887
|
+
var projectDirOf = (env, project) => env.dirs.get(project) ?? project.replace(/:/g, "/");
|
|
888
|
+
function gradleProjectOf(f, at, linesOf2) {
|
|
889
|
+
const lines = linesOf2(at.file);
|
|
890
|
+
if (!lines)
|
|
891
|
+
return void 0;
|
|
892
|
+
if (isGradleSettingsFile(at.file)) {
|
|
893
|
+
const ps = gradleProjects(lines).filter((p) => p.line === at.line);
|
|
894
|
+
return ps.find((p) => p.name === f.name)?.path ?? (ps.length === 1 ? ps[0].path : void 0);
|
|
895
|
+
}
|
|
896
|
+
if (f.kind === "dependency" && isGradleBuildFile(at.file)) {
|
|
897
|
+
const d = projectDependenciesAt(gradleBlocks(lines), at.line);
|
|
898
|
+
return "project" in d ? d.project : void 0;
|
|
899
|
+
}
|
|
900
|
+
return void 0;
|
|
901
|
+
}
|
|
902
|
+
function isBuildModuleDir(dir, linesOf2) {
|
|
903
|
+
const want = normDir(dir);
|
|
904
|
+
const pom = linesOf2("pom.xml");
|
|
905
|
+
if (pom && pomCoordinates(pom).modules.some((m) => normDir(m.value) === want))
|
|
906
|
+
return true;
|
|
907
|
+
for (const f of ["settings.gradle", "settings.gradle.kts"]) {
|
|
908
|
+
const lines = linesOf2(f);
|
|
909
|
+
if (!lines)
|
|
910
|
+
continue;
|
|
911
|
+
for (const p of gradleProjects(lines))
|
|
912
|
+
if (normDir(p.path.replace(/^:/, "").replace(/:/g, "/")) === want)
|
|
913
|
+
return true;
|
|
914
|
+
}
|
|
915
|
+
return false;
|
|
916
|
+
}
|
|
917
|
+
function buildModuleOf(f, linesOf2, modules = [], repoComponent) {
|
|
918
|
+
const listed2 = modules.map((m) => ({ path: normDir(m.path), component: m.component })).filter((m) => m.path).sort((a, b) => b.path.length - a.path.length);
|
|
919
|
+
const repo = () => repoComponent ? { path: "", component: repoComponent, names: [repoComponent], from: "repo" } : void 0;
|
|
920
|
+
const of = (dir) => {
|
|
921
|
+
const m = listed2.find((x) => dir === x.path || dir.startsWith(`${x.path}/`));
|
|
922
|
+
return m ? { path: m.path, component: m.component, names: [m.component], from: "manifest" } : repo();
|
|
923
|
+
};
|
|
924
|
+
const at = buildLineOf(f);
|
|
925
|
+
if (!at)
|
|
926
|
+
return repo();
|
|
927
|
+
if (!listed2.length)
|
|
928
|
+
return repo();
|
|
929
|
+
const env = gradleEnvOf(linesOf2);
|
|
930
|
+
if (f.kind === "dependency" && isGradleBuildFile(at.file) && dirOf(at.file) === "") {
|
|
931
|
+
const lines = linesOf2(at.file);
|
|
932
|
+
const stack = lines ? gradleBlocks(lines)[at.line - 1] ?? [] : [];
|
|
933
|
+
const sub = stack.includes("subprojects");
|
|
934
|
+
const all2 = stack.includes("allprojects");
|
|
935
|
+
if ((sub || all2) && !stack.some((b) => projectOf(b) !== void 0)) {
|
|
936
|
+
const dirs = env.projects.length ? env.projects.filter((p) => !p.renamed).map((p) => projectDirOf(env, p.path)) : listed2.map((m) => m.path);
|
|
937
|
+
const mods = [...all2 ? [""] : [], ...dirs].flatMap((d) => {
|
|
938
|
+
const m = of(d);
|
|
939
|
+
return m ? [m] : [];
|
|
940
|
+
});
|
|
941
|
+
const names = [...new Set(mods.map((m) => m.component))].sort();
|
|
942
|
+
if (names.length === 1)
|
|
943
|
+
return mods.find((m) => m.component === names[0]);
|
|
944
|
+
if (names.length > 1)
|
|
945
|
+
return { path: "", names, from: "manifest", every: true };
|
|
946
|
+
return repo();
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
const project = gradleProjectOf(f, at, linesOf2);
|
|
950
|
+
return of(project !== void 0 ? projectDirOf(env, project) : dirOf(at.file));
|
|
951
|
+
}
|
|
952
|
+
function buildModuleProblem(f, mod) {
|
|
953
|
+
if (!mod)
|
|
954
|
+
return void 0;
|
|
955
|
+
if (mod.every) {
|
|
956
|
+
const names = mod.names.join(", ");
|
|
957
|
+
if (f.component === void 0)
|
|
958
|
+
return `${f.kind} ${f.id} cites ${f.cite.file}:${f.cite.line}, a dependency every subproject's build takes (components ${names}): write one dependency fact for each, each naming its component`;
|
|
959
|
+
const c2 = factIdPart(f.component);
|
|
960
|
+
if (mod.names.some((n) => factIdPart(n) === c2))
|
|
961
|
+
return void 0;
|
|
962
|
+
return `${f.kind} ${f.id} names component "${f.component}", and ${f.cite.file}:${f.cite.line} is a dependency of every subproject (components ${names}): name one of them`;
|
|
963
|
+
}
|
|
964
|
+
if (f.component === void 0)
|
|
965
|
+
return void 0;
|
|
966
|
+
const c = factIdPart(f.component);
|
|
967
|
+
if (mod.names.some((n) => factIdPart(n) === c))
|
|
968
|
+
return void 0;
|
|
969
|
+
if (mod.from === "repo")
|
|
970
|
+
return `${f.kind} ${f.id} names component "${f.component}", and ${f.cite.file} is a build file of ${mod.component} (repos.manifest.yaml lists no module of the repo there, so it ships as ${mod.component}): a module is a component only when the manifest lists it; name ${mod.component}, or leave component out`;
|
|
971
|
+
return `${f.kind} ${f.id} names component "${f.component}", and ${f.cite.file} is the build file of module ${mod.component} (${mod.path}/, repos.manifest.yaml's modules): a dependency belongs to the module whose build file declares it; name ${mod.component}, or leave component out`;
|
|
972
|
+
}
|
|
973
|
+
var citedLine = (f, file, line) => f.cite.file === file && f.cite.line === line || (f.cite.with ?? []).some((p) => p.file === file && p.line === line);
|
|
974
|
+
function buildCoordinatesProblem(f, linesOf2, files) {
|
|
975
|
+
const file = f.cite.file;
|
|
976
|
+
const label = `${f.kind} ${f.id}`;
|
|
977
|
+
const lines = linesOf2(file);
|
|
978
|
+
if (!lines)
|
|
979
|
+
return void 0;
|
|
980
|
+
const where = `${file}:${f.cite.line}`;
|
|
981
|
+
const named = files ? pomFilesNamed(files, linesOf2) : void 0;
|
|
982
|
+
if (isPomFileIn(file, named))
|
|
983
|
+
return pomProblem(f, label, where, {
|
|
984
|
+
file,
|
|
985
|
+
pom: pomCoordinates(lines),
|
|
986
|
+
parents: pomParents(file, linesOf2, files)
|
|
987
|
+
});
|
|
988
|
+
if (isGradleFile(file))
|
|
989
|
+
return gradleProblem(f, label, where, lines, linesOf2);
|
|
990
|
+
return `${label} cites ${file}, which is no build file Atticus reads coordinates from: cite the pom.xml, build.gradle or settings.gradle line that writes them`;
|
|
991
|
+
}
|
|
992
|
+
function pomValue(f, label, file, at, ctx, what) {
|
|
993
|
+
const r = resolvePomValue(at, ctx.pom, { file: ctx.file, parents: ctx.parents });
|
|
994
|
+
if ("missing" in r)
|
|
995
|
+
return {
|
|
996
|
+
problem: `${label}: ${what} at ${file}:${at.line} is \${${r.missing}}, which no <properties> entry or <parent> of ${file}${ctx.parents.length ? ` or of its parent poms (${ctx.parents.map((p) => p.file).join(", ")})` : ""} sets: Atticus can't say what it resolves to`
|
|
997
|
+
};
|
|
998
|
+
const uncited = (r.via ?? []).find((l) => !citedLine(f, l.file, l.line));
|
|
999
|
+
if (uncited !== void 0)
|
|
1000
|
+
return {
|
|
1001
|
+
problem: `${label}: ${what} at ${file}:${at.line} is ${at.value}, written as "${r.value}" through ${uncited.file}:${uncited.line}; cite that line in cite.with`
|
|
1002
|
+
};
|
|
1003
|
+
return { value: r.value };
|
|
1004
|
+
}
|
|
1005
|
+
var DEPS = /* @__PURE__ */ new WeakMap();
|
|
1006
|
+
function dependencyOnLine(pom, line) {
|
|
1007
|
+
let byLine = DEPS.get(pom);
|
|
1008
|
+
if (!byLine) {
|
|
1009
|
+
byLine = /* @__PURE__ */ new Map();
|
|
1010
|
+
for (const d of pom.dependencies)
|
|
1011
|
+
if (d.artifact && !byLine.has(d.artifact.line))
|
|
1012
|
+
byLine.set(d.artifact.line, d);
|
|
1013
|
+
DEPS.set(pom, byLine);
|
|
1014
|
+
}
|
|
1015
|
+
return byLine.get(line);
|
|
1016
|
+
}
|
|
1017
|
+
var pomScopeOf = (declared) => declared === void 0 ? "compile" : declared.trim() === "system" ? "provided" : declared.trim();
|
|
1018
|
+
function pomProblem(f, label, where, ctx) {
|
|
1019
|
+
const pom = ctx.pom;
|
|
1020
|
+
const line = f.cite.line;
|
|
1021
|
+
const file = f.cite.file;
|
|
1022
|
+
if (f.kind === "artifact") {
|
|
1023
|
+
if (pom.artifact?.line !== line) {
|
|
1024
|
+
const dep2 = dependencyOnLine(pom, line);
|
|
1025
|
+
const what = dep2 ? `a dependency's <artifactId> (${dep2.artifact.value})` : pom.parentArtifact?.line === line ? `the <parent>'s <artifactId> (${pom.parentArtifact.value})` : "not the project's own <artifactId>";
|
|
1026
|
+
return `${label} says ${where} is the coordinates the build publishes, and that line is ${what}${pom.artifact ? `: the project's own is at line ${pom.artifact.line}` : ""}`;
|
|
1027
|
+
}
|
|
1028
|
+
const name2 = pomValue(f, label, file, pom.artifact, ctx, "the project's <artifactId>");
|
|
1029
|
+
if ("problem" in name2)
|
|
1030
|
+
return name2.problem;
|
|
1031
|
+
if (name2.value !== f.name)
|
|
1032
|
+
return `${label} names "${f.name}", and ${where} writes the project's artifactId as "${name2.value}"`;
|
|
1033
|
+
const at = pom.group ?? pom.parentGroup;
|
|
1034
|
+
if (!at)
|
|
1035
|
+
return `${label} names group "${f.group}", and ${file} writes no groupId of the project or its <parent>`;
|
|
1036
|
+
const inherited = pom.group ? "" : " (the <parent>'s, which the project inherits)";
|
|
1037
|
+
const group2 = pomValue(f, label, file, at, ctx, `the group${inherited}`);
|
|
1038
|
+
if ("problem" in group2)
|
|
1039
|
+
return group2.problem;
|
|
1040
|
+
if (group2.value !== f.group)
|
|
1041
|
+
return `${label} names group "${f.group}", and ${file}:${at.line} writes "${group2.value}"${inherited}`;
|
|
1042
|
+
if (!citedLine(f, file, at.line))
|
|
1043
|
+
return `${label}: the group is written at ${file}:${at.line}${pom.group ? "" : " (the <parent>'s)"}; cite that line in cite.with`;
|
|
1044
|
+
return void 0;
|
|
1045
|
+
}
|
|
1046
|
+
const dep = dependencyOnLine(pom, line);
|
|
1047
|
+
if (!dep) {
|
|
1048
|
+
const what = pom.artifact?.line === line ? "the project's own <artifactId>" : pom.parentArtifact?.line === line ? "the <parent>'s <artifactId>" : "no dependency's <artifactId>";
|
|
1049
|
+
return `${label} says ${where} declares a dependency, and that line is ${what}: cite the <artifactId> line of the <dependency> in <dependencies>`;
|
|
1050
|
+
}
|
|
1051
|
+
if (dep.managed)
|
|
1052
|
+
return `${label} cites ${where}, a <dependencyManagement> entry, which only pins a version: cite the dependency where <dependencies> declares it`;
|
|
1053
|
+
if (dep.plugin)
|
|
1054
|
+
return `${label} cites ${where}, a dependency of a build plugin, not of the component: leave it out`;
|
|
1055
|
+
const name = pomValue(f, label, file, dep.artifact, ctx, "the dependency's <artifactId>");
|
|
1056
|
+
if ("problem" in name)
|
|
1057
|
+
return name.problem;
|
|
1058
|
+
if (name.value !== f.name)
|
|
1059
|
+
return `${label} names "${f.name}", and ${where} declares "${name.value}"`;
|
|
1060
|
+
if (!dep.group)
|
|
1061
|
+
return `${label}: the <dependency> at ${where} writes no <groupId>`;
|
|
1062
|
+
const group = pomValue(f, label, file, dep.group, ctx, "the dependency's <groupId>");
|
|
1063
|
+
if ("problem" in group)
|
|
1064
|
+
return group.problem;
|
|
1065
|
+
if (group.value !== f.group)
|
|
1066
|
+
return `${label} names group "${f.group}", and the <dependency> at ${where} writes "${dep.group.value}"${group.value !== dep.group.value ? ` (${group.value})` : ""}`;
|
|
1067
|
+
if (!citedLine(f, file, dep.group.line))
|
|
1068
|
+
return `${label}: the dependency's group is written at ${file}:${dep.group.line}; cite that line in cite.with`;
|
|
1069
|
+
const declared = pomScopeOf(dep.scope?.value);
|
|
1070
|
+
if (declared !== (f.scope ?? "compile"))
|
|
1071
|
+
return `${label} says scope ${f.scope ?? "compile"}, and the <dependency> at ${where} declares ${dep.scope?.value.trim() === "system" ? "system, which is recorded as provided" : declared}${dep.scope ? ` (${file}:${dep.scope.line})` : ""}`;
|
|
1072
|
+
return void 0;
|
|
1073
|
+
}
|
|
1074
|
+
function gradleProblem(f, label, where, lines, linesOf2) {
|
|
1075
|
+
const text = lines[f.cite.line - 1] ?? "";
|
|
1076
|
+
const file = f.cite.file;
|
|
1077
|
+
if (f.kind === "dependency" && isVersionCatalogFile(file))
|
|
1078
|
+
return catalogProblem(f, label, where, lines, linesOf2);
|
|
1079
|
+
if (f.kind === "dependency") {
|
|
1080
|
+
const at = isGradleBuildFile(file) ? gradleDependencyAt(lines, f.cite.line) : void 0;
|
|
1081
|
+
const tool = gradleToolConfigurationOn(text);
|
|
1082
|
+
if (!at && tool)
|
|
1083
|
+
return `${label} cites ${where}, the ${tool} tool's own configuration: what it names runs the tool, and is no dependency of the component`;
|
|
1084
|
+
if (!at)
|
|
1085
|
+
return `${label} says ${where} declares a dependency, and that line declares none: cite the line in dependencies { } that names it`;
|
|
1086
|
+
if ("none" in at)
|
|
1087
|
+
return `${label} cites ${where}, which is in ${at.none}, not a project's dependencies { }: a version pinned, a constraint or the build's own class path is no dependency of the component`;
|
|
1088
|
+
const d = at.dependency;
|
|
1089
|
+
if (d.group !== f.group || d.name !== f.name)
|
|
1090
|
+
return `${label} names "${f.group}:${f.name}", and ${where} declares "${d.group}:${d.name}"`;
|
|
1091
|
+
if (d.scope !== (f.scope ?? "compile"))
|
|
1092
|
+
return `${label} says scope ${f.scope ?? "compile"}, and ${where} declares it with ${d.configuration} (${d.scope})`;
|
|
1093
|
+
return void 0;
|
|
1094
|
+
}
|
|
1095
|
+
let project;
|
|
1096
|
+
if (isGradleSettingsFile(file)) {
|
|
1097
|
+
const root = gradleNameOn(text);
|
|
1098
|
+
if (root !== void 0) {
|
|
1099
|
+
if (root !== f.name)
|
|
1100
|
+
return `${label} names "${f.name}", and ${where} sets "${root}"`;
|
|
1101
|
+
} else {
|
|
1102
|
+
const all2 = gradleProjects(lines);
|
|
1103
|
+
const ps = all2.filter((x) => x.line === f.cite.line);
|
|
1104
|
+
if (!ps.length)
|
|
1105
|
+
return `${label} says ${where} is the coordinates the build publishes, and that line sets no project name: cite rootProject.name, an include, or a project(':x').name line`;
|
|
1106
|
+
const p = ps.find((x) => x.name === f.name);
|
|
1107
|
+
if (!p)
|
|
1108
|
+
return `${label} names "${f.name}", and ${where} names ${ps.map((x) => `"${x.name}"`).join(", ")}`;
|
|
1109
|
+
const renamed = all2.find((x) => x.renamed && x.path === p.path);
|
|
1110
|
+
if (!p.renamed && renamed)
|
|
1111
|
+
return `${label} names "${f.name}", and ${file}:${renamed.line} names that project "${renamed.name}": cite that line`;
|
|
1112
|
+
project = p.path;
|
|
1113
|
+
}
|
|
1114
|
+
} else {
|
|
1115
|
+
const name = gradleNameOn(text);
|
|
1116
|
+
if (name === void 0)
|
|
1117
|
+
return `${label} says ${where} is the coordinates the build publishes, and that line sets no project name: cite rootProject.name in settings.gradle, or archivesBaseName`;
|
|
1118
|
+
if (name !== f.name)
|
|
1119
|
+
return `${label} names "${f.name}", and ${where} sets "${name}"`;
|
|
1120
|
+
const dir = dirOf(file);
|
|
1121
|
+
if (dir) {
|
|
1122
|
+
const dirs2 = projectDirs(settingsOf(linesOf2)?.lines);
|
|
1123
|
+
project = [...dirs2].find(([, d]) => d === dir)?.[0] ?? dir.replace(/\//g, ":");
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
const dirs = projectDirs(settingsOf(linesOf2)?.lines);
|
|
1127
|
+
const ownDir = project === void 0 ? "" : dirs.get(project) ?? project.replace(/:/g, "/");
|
|
1128
|
+
const parts = [{ file, line: f.cite.line }, ...f.cite.with ?? []];
|
|
1129
|
+
const groups = parts.flatMap((p) => {
|
|
1130
|
+
const ls = linesOf2(p.file);
|
|
1131
|
+
const g2 = gradleGroupOn(ls?.[p.line - 1] ?? "");
|
|
1132
|
+
if (g2 === void 0 || !ls || !isGradleBuildFile(p.file))
|
|
1133
|
+
return [];
|
|
1134
|
+
const stack = gradleBlocks(ls)[p.line - 1] ?? [];
|
|
1135
|
+
const pDir = dirOf(p.file);
|
|
1136
|
+
const applies = pDir === ownDir && pDir !== "" ? stack.length === 0 : pDir === "" && (stack.length === 0 ? project === void 0 : stack.length === 1 && (stack[0] === "allprojects" || project !== void 0 && (stack[0] === "subprojects" || projectOf(stack[0]) === project)));
|
|
1137
|
+
return [{ ...p, group: g2, applies }];
|
|
1138
|
+
});
|
|
1139
|
+
const g = groups.find((x) => x.applies);
|
|
1140
|
+
if (!g) {
|
|
1141
|
+
const other = groups[0];
|
|
1142
|
+
if (other)
|
|
1143
|
+
return `${label}: ${other.file}:${other.line} sets the group of another project than ${f.name}; cite the line that sets ${f.name}'s (group = '${f.group}') in cite.with`;
|
|
1144
|
+
return `${label}: no line it cites sets the group; cite the build.gradle line that does (group = '${f.group}') in cite.with`;
|
|
1145
|
+
}
|
|
1146
|
+
if (g.group !== f.group)
|
|
1147
|
+
return `${label} names group "${f.group}", and ${g.file}:${g.line} sets "${g.group}"`;
|
|
1148
|
+
return void 0;
|
|
1149
|
+
}
|
|
1150
|
+
function catalogProblem(f, label, where, lines, linesOf2) {
|
|
1151
|
+
const lib = catalogLibraryAt(lines, f.cite.line);
|
|
1152
|
+
if (!lib)
|
|
1153
|
+
return `${label} cites ${where}, which is no [libraries] entry of the version catalog: cite the entry that gives its coordinates`;
|
|
1154
|
+
if (lib.group !== f.group || lib.name !== f.name)
|
|
1155
|
+
return `${label} names "${f.group}:${f.name}", and ${where} gives ${lib.alias} as "${lib.group}:${lib.name}"`;
|
|
1156
|
+
if (f.version !== void 0) {
|
|
1157
|
+
const v = lib.version ?? (lib.versionRef ? catalogVersions(lines).get(lib.versionRef)?.value : void 0);
|
|
1158
|
+
if (v !== f.version)
|
|
1159
|
+
return `${label} says version ${f.version}, and ${where} gives ${v === void 0 ? "no version Atticus can read" : `"${v}"`}${lib.versionRef ? ` (version.ref = "${lib.versionRef}")` : ""}`;
|
|
1160
|
+
}
|
|
1161
|
+
const catalog = catalogNameOf(f.cite.file);
|
|
1162
|
+
const use = `${catalog}.${lib.accessor}`;
|
|
1163
|
+
let problem;
|
|
1164
|
+
for (const p of f.cite.with ?? []) {
|
|
1165
|
+
if (!isGradleBuildFile(p.file))
|
|
1166
|
+
continue;
|
|
1167
|
+
const ls = linesOf2(p.file);
|
|
1168
|
+
const u = ls ? gradleCatalogUseOn(ls[p.line - 1] ?? "") : void 0;
|
|
1169
|
+
if (!ls || !u || u.catalog !== catalog || u.accessor !== lib.accessor)
|
|
1170
|
+
continue;
|
|
1171
|
+
const at = projectDependenciesAt(gradleBlocks(ls), p.line);
|
|
1172
|
+
if ("none" in at) {
|
|
1173
|
+
problem ??= `${label}: ${p.file}:${p.line} is in ${at.none}, not a project's dependencies { }: a version pinned, a constraint or the build's own class path is no dependency of the component`;
|
|
1174
|
+
continue;
|
|
1175
|
+
}
|
|
1176
|
+
if (u.scope !== (f.scope ?? "compile")) {
|
|
1177
|
+
problem ??= `${label} says scope ${f.scope ?? "compile"}, and ${p.file}:${p.line} declares it with ${u.configuration} (${u.scope})`;
|
|
1178
|
+
continue;
|
|
1179
|
+
}
|
|
1180
|
+
return void 0;
|
|
1181
|
+
}
|
|
1182
|
+
return problem ?? `${label}: ${where} is the catalog's entry, which only names the library; cite the build line in dependencies { } that declares it (${use}) in cite.with`;
|
|
1183
|
+
}
|
|
1184
|
+
function buildUnrecorded(files, linesOf2, kept, all2) {
|
|
1185
|
+
const named = all2 ? pomFilesNamed(all2, linesOf2) : void 0;
|
|
1186
|
+
const cited = new Set(kept.filter((f) => f.kind === "artifact" || f.kind === "dependency").map((f) => `${f.cite.file}:${f.cite.line}`));
|
|
1187
|
+
const out = [];
|
|
1188
|
+
const add = (file, line, kind, c) => {
|
|
1189
|
+
if (!cited.has(`${file}:${line}`))
|
|
1190
|
+
out.push({ cite: `${file}:${line}`, kind, coordinates: c });
|
|
1191
|
+
};
|
|
1192
|
+
for (const file of [...files].sort()) {
|
|
1193
|
+
const lines = linesOf2(file);
|
|
1194
|
+
if (!lines)
|
|
1195
|
+
continue;
|
|
1196
|
+
if (isPomFileIn(file, named)) {
|
|
1197
|
+
const pom = pomCoordinates(lines);
|
|
1198
|
+
const parents = pomParents(file, linesOf2, all2);
|
|
1199
|
+
const said = (at) => {
|
|
1200
|
+
if (!at)
|
|
1201
|
+
return "?";
|
|
1202
|
+
const r = resolvePomValue(at, pom, { file, parents });
|
|
1203
|
+
return "value" in r ? r.value : at.value;
|
|
1204
|
+
};
|
|
1205
|
+
if (pom.artifact)
|
|
1206
|
+
add(file, pom.artifact.line, "artifact", `${said(pom.group ?? pom.parentGroup)}:${said(pom.artifact)}`);
|
|
1207
|
+
for (const d of pom.dependencies)
|
|
1208
|
+
if (!d.managed && !d.plugin && d.artifact)
|
|
1209
|
+
add(file, d.artifact.line, "dependency", `${said(d.group)}:${said(d.artifact)}`);
|
|
1210
|
+
} else if (isGradleBuildFile(file)) {
|
|
1211
|
+
const blocks = gradleBlocks(lines);
|
|
1212
|
+
lines.forEach((_, i) => {
|
|
1213
|
+
const at = gradleDependencyAt(lines, i + 1, blocks);
|
|
1214
|
+
if (at && "dependency" in at && at.dependency.scope !== "import")
|
|
1215
|
+
add(file, i + 1, "dependency", `${at.dependency.group}:${at.dependency.name}`);
|
|
1216
|
+
});
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1219
|
+
return out;
|
|
1220
|
+
}
|
|
1221
|
+
|
|
169
1222
|
// packages/verify/dist/frameworks.js
|
|
170
1223
|
var FRAMEWORKS = [
|
|
171
1224
|
"spring",
|
|
@@ -424,6 +1477,7 @@ function rulesOf(c) {
|
|
|
424
1477
|
notProduct: underFolders(c.notProductFolders),
|
|
425
1478
|
notRead: notReadTest(c.notReadFolders),
|
|
426
1479
|
gatewayBundle: gatewayBundleTest(c.gatewayBundleFolders),
|
|
1480
|
+
gatewayBundleFolders: c.gatewayBundleFolders,
|
|
427
1481
|
frameworks: c.frameworks
|
|
428
1482
|
};
|
|
429
1483
|
}
|
|
@@ -581,7 +1635,8 @@ function correctionFor(f, all2) {
|
|
|
581
1635
|
const byCite = corrections.filter((c) => at(c) && c.target.value === f.cite.value);
|
|
582
1636
|
const edited = corrections.filter((c) => c.fact === f.id && c.action === "edit");
|
|
583
1637
|
const moved = edited.filter((c) => (c.line ?? c.target.line) === f.cite.line);
|
|
584
|
-
|
|
1638
|
+
const pos = new Map(all2.map((c, i) => [c, i]));
|
|
1639
|
+
return [.../* @__PURE__ */ new Set([...byId, ...byCite, ...moved])].sort((a, b) => a.at < b.at ? 1 : a.at > b.at ? -1 : pos.get(b) - pos.get(a))[0];
|
|
585
1640
|
}
|
|
586
1641
|
function outsidePairingFor(f, all2) {
|
|
587
1642
|
const newest = linksFor(f, all2)[0];
|
|
@@ -1530,201 +2585,110 @@ function pageRouteMatches(file, lines, exists, path) {
|
|
|
1530
2585
|
const route = pageRouteOf(file, lines, exists);
|
|
1531
2586
|
if (route === void 0)
|
|
1532
2587
|
return false;
|
|
1533
|
-
const
|
|
1534
|
-
return
|
|
2588
|
+
const norm2 = (p) => normalizePath(p.replace(/\{([^}:?]*)[^}]*\}/g, "{$1}")).toLowerCase() || "/";
|
|
2589
|
+
return norm2(route) === norm2(path);
|
|
1535
2590
|
}
|
|
1536
2591
|
|
|
1537
|
-
// packages/verify/dist/
|
|
1538
|
-
var
|
|
1539
|
-
var
|
|
1540
|
-
var
|
|
1541
|
-
var
|
|
1542
|
-
var
|
|
1543
|
-
var
|
|
1544
|
-
var
|
|
1545
|
-
var
|
|
1546
|
-
var
|
|
1547
|
-
var
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
function
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
if (!CODE.test(path) || readingRank(path) === 5 || isModelFile(path))
|
|
1564
|
-
return false;
|
|
1565
|
-
return ENTRY_POINT_NAME.test(stem(path)) || ENTRY_POINT_DIR.test(path) || ENTRY_POINT_PART.test(path);
|
|
2592
|
+
// packages/verify/dist/secrets.js
|
|
2593
|
+
var CONFIG_FILE = /\.(ya?ml|properties|json|xml|config|env|ini|toml|conf|cfg)$|(^|\/)\.env(\.[^/]*)?$|(^|\/)credentials?$/i;
|
|
2594
|
+
var isConfigFile = (path) => CONFIG_FILE.test(path.replace(/\\/g, "/"));
|
|
2595
|
+
var PLACEHOLDER = /^(<[^>]*>|\*+|x{3,}|changeme|change-me|secret|password|todo|tbd|none|null|nil|dummy|example|sample|test|redacted|your[-_ ].*)$/i;
|
|
2596
|
+
var KEY_VALUE = /^\s*(?:-\s+)?(?:export\s+)?["']?([A-Za-z0-9_.\-[\]]+)["']?\s*[:=]\s*(.*?)\s*,?\s*$/;
|
|
2597
|
+
var XML_ELEMENT = /<([A-Za-z_][\w.-]*)>([^<]+)<\/\1>/g;
|
|
2598
|
+
var XML_NAMED = /\b(?:key|name)\s*=\s*"([^"]+)"\s+value\s*=\s*"([^"]*)"/g;
|
|
2599
|
+
var XML_NAMED_AFTER = /\bvalue\s*=\s*"([^"]*)"\s+(?:key|name)\s*=\s*"([^"]+)"/g;
|
|
2600
|
+
var CONNECTION_PAIR = /(?:^|[;"'])\s*([A-Za-z][A-Za-z0-9 _.-]*?)\s*=\s*([^;"'<>\s][^;"'<>]*)/g;
|
|
2601
|
+
var TOKEN_VALUE_KEY = /^(value|val)$/i;
|
|
2602
|
+
var TOKEN_NAME = /^\s*"(xpath|name|key)"\s*:\s*"([^"]+)"/;
|
|
2603
|
+
function isReference(value) {
|
|
2604
|
+
return /^(vault|env|secret|ref|arn|kms|sm|gcp-sm|azure-kv|classpath\*?|file):/i.test(value) || /\$\{|\{\{/.test(value) || /^(~|\.{1,2})?\/[\w.\-/]+$/.test(value) || /^[\w.-]+(\/[\w.-]+)+\.[A-Za-z0-9]{1,10}$/.test(value);
|
|
2605
|
+
}
|
|
2606
|
+
var unquote = (v) => v.replace(/\s+#.*$/, "").replace(/^["']|["']$/g, "").trim();
|
|
2607
|
+
function tokenKeyNear(lines, i) {
|
|
2608
|
+
for (const step of [-1, 1])
|
|
2609
|
+
for (let j = i + step; j >= 0 && j < lines.length && Math.abs(j - i) <= 4; j += step) {
|
|
2610
|
+
const l = lines[j];
|
|
2611
|
+
const m = TOKEN_NAME.exec(l);
|
|
2612
|
+
if (m)
|
|
2613
|
+
return m[2];
|
|
2614
|
+
if (/[{}]/.test(l))
|
|
2615
|
+
break;
|
|
2616
|
+
}
|
|
2617
|
+
return void 0;
|
|
1566
2618
|
}
|
|
1567
|
-
function
|
|
1568
|
-
if (
|
|
2619
|
+
function keyIsSecret(key) {
|
|
2620
|
+
if (hasSecretShape(key))
|
|
2621
|
+
return true;
|
|
2622
|
+
for (const run of key.match(/[0-9a-f]{24,}|[0-9A-F]{24,}/g) ?? [])
|
|
2623
|
+
if (/\d/.test(run) && /[a-f]/i.test(run))
|
|
2624
|
+
return true;
|
|
2625
|
+
const digitsAndLetters = /\d/.test(key) && /[A-Za-z]/.test(key);
|
|
2626
|
+
if (key.length >= 32 && /^[A-Za-z0-9+/=]+$/.test(key) && digitsAndLetters)
|
|
2627
|
+
return true;
|
|
2628
|
+
if (key.length >= 32 && /^[A-Za-z0-9_-]+$/.test(key) && /\d/.test(key) && /[a-z]/.test(key) && /[A-Z]/.test(key))
|
|
2629
|
+
return true;
|
|
2630
|
+
if (key.length < 16 || !/^[A-Za-z0-9+/=]+$/.test(key) || !/\d/.test(key))
|
|
1569
2631
|
return false;
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
for (
|
|
1580
|
-
const
|
|
1581
|
-
if (
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
if (!texts.has(p))
|
|
1594
|
-
texts.set(p, o.read(p) ?? "");
|
|
1595
|
-
return texts.get(p);
|
|
1596
|
-
};
|
|
1597
|
-
const ordered = readingOrder(o.paths);
|
|
1598
|
-
const models = ordered.filter((p) => isModelFile(p, textOf(p))).sort();
|
|
1599
|
-
const isModel = new Set(models);
|
|
1600
|
-
const byName = /* @__PURE__ */ new Map();
|
|
1601
|
-
const declared = /* @__PURE__ */ new Map();
|
|
1602
|
-
for (const p of models) {
|
|
1603
|
-
const names = declaredTypes(p, textOf(p));
|
|
1604
|
-
declared.set(p, names);
|
|
1605
|
-
for (const n of names)
|
|
1606
|
-
byName.set(n, [...byName.get(n) ?? [], p]);
|
|
1607
|
-
}
|
|
1608
|
-
const known = new Set(o.paths);
|
|
1609
|
-
const roots = [];
|
|
1610
|
-
const addRoot = (p) => {
|
|
1611
|
-
if (known.has(p) && !isModel.has(p) && !roots.includes(p))
|
|
1612
|
-
roots.push(p);
|
|
1613
|
-
};
|
|
1614
|
-
const facts = o.facts ?? [];
|
|
1615
|
-
const entries = o.from === "entries";
|
|
1616
|
-
const calls2 = new Set(facts.filter((f) => f.kind === "call").map((f) => f.id));
|
|
1617
|
-
for (const f of facts)
|
|
1618
|
-
if (f.kind === "entry" || f.kind === "call" && !entries)
|
|
1619
|
-
for (const p of citedFiles(f))
|
|
1620
|
-
addRoot(p);
|
|
1621
|
-
for (const p of ordered)
|
|
1622
|
-
if (entries ? isEntryPointFile(p) : isRootFile(p))
|
|
1623
|
-
addRoot(p);
|
|
1624
|
-
const reached = /* @__PURE__ */ new Map();
|
|
1625
|
-
const queue = [];
|
|
1626
|
-
const reach = (names, from, own = []) => {
|
|
1627
|
-
for (const n of names) {
|
|
1628
|
-
if (own.includes(n))
|
|
1629
|
-
continue;
|
|
1630
|
-
for (const p of byName.get(n) ?? []) {
|
|
1631
|
-
const r = reached.get(p);
|
|
1632
|
-
if (r) {
|
|
1633
|
-
if (r.from === from && !r.types.includes(n))
|
|
1634
|
-
r.types.push(n);
|
|
1635
|
-
continue;
|
|
1636
|
-
}
|
|
1637
|
-
reached.set(p, { path: p, types: [n], from });
|
|
1638
|
-
queue.push(p);
|
|
1639
|
-
}
|
|
1640
|
-
}
|
|
1641
|
-
};
|
|
1642
|
-
for (const p of roots)
|
|
1643
|
-
reach(identifiers(textOf(p)), p);
|
|
1644
|
-
for (const f of facts) {
|
|
1645
|
-
for (const p of citedFiles(f))
|
|
1646
|
-
if (isModel.has(p) && !reached.has(p)) {
|
|
1647
|
-
reached.set(p, { path: p, types: [...(declared.get(p) ?? []).slice(0, 1)], from: f.id });
|
|
1648
|
-
queue.push(p);
|
|
1649
|
-
}
|
|
1650
|
-
if (f.kind === "field" && !(entries && calls2.has(f.owner)))
|
|
1651
|
-
reach(identifiers([f.type ?? "", f.transform === "message type" ? f.name : ""].join(" ")), f.id);
|
|
1652
|
-
}
|
|
1653
|
-
const rooted = roots.length > 0 || reached.size > 0;
|
|
1654
|
-
if (!rooted)
|
|
1655
|
-
return {
|
|
1656
|
-
rooted,
|
|
1657
|
-
roots,
|
|
1658
|
-
reached: models.map((p) => ({ path: p, types: declared.get(p) ?? [], from: "" })),
|
|
1659
|
-
notReached: [],
|
|
1660
|
-
models: models.length
|
|
1661
|
-
};
|
|
1662
|
-
for (let i = 0; i < queue.length; i++) {
|
|
1663
|
-
const p = queue[i];
|
|
1664
|
-
reach(identifiers(textOf(p)), p, declared.get(p));
|
|
2632
|
+
const kind = (c) => /\d/.test(c) ? 0 : /[a-z]/.test(c) ? 1 : 2;
|
|
2633
|
+
let switches = 0;
|
|
2634
|
+
for (let i = 1; i < key.length; i++)
|
|
2635
|
+
if (kind(key[i]) !== kind(key[i - 1]))
|
|
2636
|
+
switches++;
|
|
2637
|
+
return switches >= key.length / 2;
|
|
2638
|
+
}
|
|
2639
|
+
function itemNameAbove(lines, i) {
|
|
2640
|
+
const col = /^\s*/.exec(lines[i])[0].length;
|
|
2641
|
+
for (let j = i - 1; j >= 0 && i - j <= 6; j--) {
|
|
2642
|
+
const l = lines[j];
|
|
2643
|
+
if (!l.trim())
|
|
2644
|
+
continue;
|
|
2645
|
+
const lead = /^\s*/.exec(l)[0].length;
|
|
2646
|
+
const item = /^(\s*)-\s+(.*)$/.exec(l);
|
|
2647
|
+
const keyCol = item ? item[1].length + (l.length - item[1].length - item[2].length) : lead;
|
|
2648
|
+
if (keyCol !== col)
|
|
2649
|
+
return void 0;
|
|
2650
|
+
const m = /^(?:\s*-\s+|\s*)(name|key)\s*:\s*["']?([^"'\s#]+)["']?\s*$/.exec(l);
|
|
2651
|
+
if (m)
|
|
2652
|
+
return m[2];
|
|
2653
|
+
if (item)
|
|
2654
|
+
return void 0;
|
|
1665
2655
|
}
|
|
1666
|
-
return
|
|
1667
|
-
rooted,
|
|
1668
|
-
roots,
|
|
1669
|
-
reached: queue.map((p) => reached.get(p)),
|
|
1670
|
-
notReached: models.filter((p) => !reached.has(p)),
|
|
1671
|
-
models: models.length
|
|
1672
|
-
};
|
|
1673
|
-
}
|
|
1674
|
-
|
|
1675
|
-
// packages/verify/dist/method.js
|
|
1676
|
-
var HTTP_METHODS = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
|
|
1677
|
-
function wordsOf(line) {
|
|
1678
|
-
return line.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").toLowerCase().split(/[^a-z]+/).filter(Boolean);
|
|
1679
|
-
}
|
|
1680
|
-
function methodOnLines(method, lines) {
|
|
1681
|
-
const m = method.toLowerCase();
|
|
1682
|
-
return lines.some((l) => wordsOf(l).includes(m));
|
|
2656
|
+
return void 0;
|
|
1683
2657
|
}
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
const at = (n) => file?.[n - 1];
|
|
1688
|
-
const cited = at(line);
|
|
1689
|
-
if (cited === void 0)
|
|
2658
|
+
function liveSecretsIn(file, lines) {
|
|
2659
|
+
const shownKey = (key) => keyIsSecret(key) ? "" : key;
|
|
2660
|
+
if (!isConfigFile(file))
|
|
1690
2661
|
return [];
|
|
1691
|
-
const out = [
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
2662
|
+
const out = [];
|
|
2663
|
+
lines.forEach((text, i) => {
|
|
2664
|
+
if (/^\s*(#|\/\/|;|<!--)/.test(text))
|
|
2665
|
+
return;
|
|
2666
|
+
const pairs = [];
|
|
2667
|
+
const kv = KEY_VALUE.exec(text);
|
|
2668
|
+
if (kv) {
|
|
2669
|
+
const key = TOKEN_VALUE_KEY.test(kv[1]) ? tokenKeyNear(lines, i) ?? (/\.ya?ml$/i.test(file) ? itemNameAbove(lines, i) : void 0) ?? kv[1] : kv[1];
|
|
2670
|
+
pairs.push({ key, value: unquote(kv[2]) });
|
|
2671
|
+
}
|
|
2672
|
+
for (const m of text.matchAll(XML_ELEMENT))
|
|
2673
|
+
pairs.push({ key: m[1], value: m[2].trim() });
|
|
2674
|
+
for (const m of text.matchAll(XML_NAMED))
|
|
2675
|
+
pairs.push({ key: m[1], value: m[2].trim() });
|
|
2676
|
+
for (const m of text.matchAll(XML_NAMED_AFTER))
|
|
2677
|
+
pairs.push({ key: m[2], value: m[1].trim() });
|
|
2678
|
+
if (text.includes(";"))
|
|
2679
|
+
for (const m of text.matchAll(CONNECTION_PAIR))
|
|
2680
|
+
pairs.push({ key: m[1].trim(), value: m[2].trim() });
|
|
2681
|
+
const named = pairs.find(({ key, value }) => value && !PLACEHOLDER.test(value) && // a key with a nested map under it, or an encrypted value (`{cipher}…`), sets nothing here
|
|
2682
|
+
!/^[{[]/.test(value) && !isReference(value) && looksLikeSecret(key, value));
|
|
2683
|
+
if (named) {
|
|
2684
|
+
out.push({ file, line: i + 1, key: shownKey(named.key) });
|
|
2685
|
+
return;
|
|
2686
|
+
}
|
|
2687
|
+
if (hasSecretShape(text))
|
|
2688
|
+
out.push({ file, line: i + 1, key: pairs[0] ? shownKey(pairs[0].key) : "(token)" });
|
|
2689
|
+
});
|
|
1700
2690
|
return out;
|
|
1701
2691
|
}
|
|
1702
|
-
function methodUnseenOf(f, lines, factOf) {
|
|
1703
|
-
if (f.kind !== "entry" && f.kind !== "call")
|
|
1704
|
-
return void 0;
|
|
1705
|
-
if (!f.method || !HTTP_METHODS.has(f.method.toUpperCase()))
|
|
1706
|
-
return void 0;
|
|
1707
|
-
const at = (file, line) => lines(file)?.[line - 1];
|
|
1708
|
-
const route = f.kind === "call" && f.from ? factOf?.(f.from) : void 0;
|
|
1709
|
-
const forwards = route?.kind === "entry" && route.method?.toUpperCase() === f.method.toUpperCase();
|
|
1710
|
-
const looked = [
|
|
1711
|
-
...chainOf(lines(f.cite.file), f.cite.line),
|
|
1712
|
-
at(f.cite.file, f.cite.line + 1),
|
|
1713
|
-
...(f.cite.with ?? []).map((p) => at(p.file, p.line)),
|
|
1714
|
-
...forwards ? [at(route.cite.file, route.cite.line), at(route.cite.file, route.cite.line + 1)] : []
|
|
1715
|
-
].filter((l) => l !== void 0);
|
|
1716
|
-
if (methodOnLines(f.method, looked))
|
|
1717
|
-
return void 0;
|
|
1718
|
-
const cite2 = `${f.cite.file}:${f.cite.line}`;
|
|
1719
|
-
const method = f.method.toUpperCase();
|
|
1720
|
-
return {
|
|
1721
|
-
id: f.id,
|
|
1722
|
-
kind: f.kind,
|
|
1723
|
-
method,
|
|
1724
|
-
cite: cite2,
|
|
1725
|
-
message: `${f.id} claims ${method}, which neither ${cite2}, the chain it is in, the next line, a cite.with line nor the route it forwards writes`
|
|
1726
|
-
};
|
|
1727
|
-
}
|
|
1728
2692
|
|
|
1729
2693
|
// packages/verify/dist/skipped.js
|
|
1730
2694
|
function notReadForSkipped(path, rules = DEFAULT_READ_RULES) {
|
|
@@ -1745,9 +2709,9 @@ var NOT_TOPIC_FIRST = new Set("com org net io java javax jakarta android android
|
|
|
1745
2709
|
var DOTTED_TOPIC = /^[a-z][a-z0-9_-]*(\.[a-z][a-z0-9_-]*){2,}$/;
|
|
1746
2710
|
var SEPARATED_NAME = /^[A-Za-z][A-Za-z0-9_]*([._:-][A-Za-z0-9_]+)+$/;
|
|
1747
2711
|
var QUOTED = /(["'`])((?:\\.|(?!\1)[^\\\n])*)\1/g;
|
|
1748
|
-
var
|
|
2712
|
+
var KEY_VALUE2 = /^\s*-?\s*["']?([A-Za-z0-9_.\-[\]]+)["']?\s*[:=]\s*([^\s"'#]+)\s*$/;
|
|
1749
2713
|
var ELEMENT_TEXT = /<([A-Za-z][\w:.-]*)[^>]*>([^<\s]+)<\/\1>/g;
|
|
1750
|
-
var
|
|
2714
|
+
var wordsOf = (line) => line.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").toLowerCase().split(/[^a-z]+/).filter(Boolean);
|
|
1751
2715
|
var TOPIC_WORDS = /* @__PURE__ */ new Set([
|
|
1752
2716
|
"topic",
|
|
1753
2717
|
"topics",
|
|
@@ -1761,7 +2725,7 @@ var TOPIC_WORDS = /* @__PURE__ */ new Set([
|
|
|
1761
2725
|
"exchanges"
|
|
1762
2726
|
]);
|
|
1763
2727
|
var topicContext = (line) => {
|
|
1764
|
-
const w =
|
|
2728
|
+
const w = wordsOf(line);
|
|
1765
2729
|
return w.some((x) => TOPIC_WORDS.has(x)) || w.join(" ").includes("routing key");
|
|
1766
2730
|
};
|
|
1767
2731
|
var BUILD_KEY_WORDS = new Set("scm git gitlab github bitbucket repository repositories repo registry mirror mirrors nexus artifactory snapshot snapshots distribution maven npm nuget pypi sonar sonarqube jenkins ci".split(" "));
|
|
@@ -1772,7 +2736,7 @@ var keysBefore = (prefix) => [
|
|
|
1772
2736
|
...[...prefix.matchAll(/["']?([A-Za-z][\w.-]*)["']?\s*[:=]/g)].map((m) => m[1]),
|
|
1773
2737
|
...[...prefix.matchAll(/\b([A-Za-z]\w*)\s*\{/g)].map((m) => m[1])
|
|
1774
2738
|
];
|
|
1775
|
-
var isBuildUrl = (u, prefix) => /\.git\/?$/i.test(u) || /\bscm:\w+:$/i.test(prefix) || keysBefore(prefix).some((k) =>
|
|
2739
|
+
var isBuildUrl = (u, prefix) => /\.git\/?$/i.test(u) || /\bscm:\w+:$/i.test(prefix) || keysBefore(prefix).some((k) => wordsOf(k).some((w) => BUILD_KEY_WORDS.has(w)));
|
|
1776
2740
|
var HEADER_ARG = /header\w*\s*(?:\.\s*\w+\s*)?\(\s*(?:(?:value|name)\s*=\s*)?$/i;
|
|
1777
2741
|
var isHeaderName = (s, prefix) => /^x-/i.test(s) || HEADER_ARG.test(prefix.replace(/["'`]$/, ""));
|
|
1778
2742
|
var cleanUrl = (u) => u.replace(/[.:]+$/, "").replace(/^([a-z0-9+.-]+:\/\/)[^/@\s]+@/i, "$1<redacted>@");
|
|
@@ -1867,7 +2831,7 @@ function candidatesIn(path, lines) {
|
|
|
1867
2831
|
s: m[2],
|
|
1868
2832
|
before: code2.slice(0, m.index + 1)
|
|
1869
2833
|
}));
|
|
1870
|
-
const kv =
|
|
2834
|
+
const kv = KEY_VALUE2.exec(code2);
|
|
1871
2835
|
if (kv)
|
|
1872
2836
|
strings2.push({ s: kv[2], before: "" });
|
|
1873
2837
|
for (const m of code2.matchAll(ELEMENT_TEXT))
|
|
@@ -1907,102 +2871,747 @@ function indexFacts(facts) {
|
|
|
1907
2871
|
Object.values(o).forEach(walk);
|
|
1908
2872
|
}
|
|
1909
2873
|
};
|
|
1910
|
-
facts.forEach(walk);
|
|
1911
|
-
const paths = /* @__PURE__ */ new Set();
|
|
1912
|
-
for (const s of strings2) {
|
|
1913
|
-
if (/\s/.test(s))
|
|
1914
|
-
continue;
|
|
1915
|
-
const u = /^[a-z0-9+.-]+:\/\/[^/]+(\/.*)?$/i.exec(s);
|
|
1916
|
-
const p = u ? u[1] : s.includes("/") ? s : void 0;
|
|
1917
|
-
if (p && p.length > 1)
|
|
1918
|
-
paths.add(`${normPath(p)}/`);
|
|
2874
|
+
facts.forEach(walk);
|
|
2875
|
+
const paths = /* @__PURE__ */ new Set();
|
|
2876
|
+
for (const s of strings2) {
|
|
2877
|
+
if (/\s/.test(s))
|
|
2878
|
+
continue;
|
|
2879
|
+
const u = /^[a-z0-9+.-]+:\/\/[^/]+(\/.*)?$/i.exec(s);
|
|
2880
|
+
const p = u ? u[1] : s.includes("/") ? s : void 0;
|
|
2881
|
+
if (p && p.length > 1)
|
|
2882
|
+
paths.add(`${normPath(p)}/`);
|
|
2883
|
+
}
|
|
2884
|
+
return { at, strings: [...strings2].map((s) => s.toLowerCase()), paths: [...paths] };
|
|
2885
|
+
}
|
|
2886
|
+
function factsCover(file, c, ix) {
|
|
2887
|
+
if ([c.line - 1, c.line, c.line + 1].some((n) => ix.at.has(`${file}:${n}`)))
|
|
2888
|
+
return true;
|
|
2889
|
+
if (c.kind === "path") {
|
|
2890
|
+
const p = `${normPath(c.value)}/`;
|
|
2891
|
+
return ix.paths.some((f) => f.includes(p));
|
|
2892
|
+
}
|
|
2893
|
+
const v = c.value.toLowerCase().replace(/\/+$/, "");
|
|
2894
|
+
return ix.strings.some((s) => s.includes(v));
|
|
2895
|
+
}
|
|
2896
|
+
var skippedOf = (file, c) => ({
|
|
2897
|
+
cite: `${file}:${c.line}`,
|
|
2898
|
+
kind: c.kind,
|
|
2899
|
+
value: c.value,
|
|
2900
|
+
text: c.text
|
|
2901
|
+
});
|
|
2902
|
+
var SPEC_MARK = /^\s*["']?(openapi|swagger)["']?\s*:/m;
|
|
2903
|
+
var SPEC_EXT = /\.(ya?ml|json)$/i;
|
|
2904
|
+
function specOpsUncoveredIn(file, text, facts) {
|
|
2905
|
+
if (!SPEC_EXT.test(file) || !SPEC_MARK.test(text.slice(0, 4e3)))
|
|
2906
|
+
return void 0;
|
|
2907
|
+
let doc;
|
|
2908
|
+
try {
|
|
2909
|
+
doc = readOpenApiDocument(text);
|
|
2910
|
+
} catch {
|
|
2911
|
+
return void 0;
|
|
2912
|
+
}
|
|
2913
|
+
if (!doc || !doc.operations.length)
|
|
2914
|
+
return void 0;
|
|
2915
|
+
const server = (() => {
|
|
2916
|
+
const s = doc.servers[0];
|
|
2917
|
+
if (!s)
|
|
2918
|
+
return "";
|
|
2919
|
+
const p = /^[a-z0-9+.-]+:\/\/[^/]+(\/.*)?$/i.exec(s)?.[1] ?? (s.startsWith("/") ? s : "");
|
|
2920
|
+
return p.replace(/\/+$/, "");
|
|
2921
|
+
})();
|
|
2922
|
+
const entries = facts.filter((f) => f.kind === "entry");
|
|
2923
|
+
const atLines = /* @__PURE__ */ new Set();
|
|
2924
|
+
for (const e of entries)
|
|
2925
|
+
for (const k of indexFacts([e]).at)
|
|
2926
|
+
atLines.add(k);
|
|
2927
|
+
const out = [];
|
|
2928
|
+
for (const op of doc.operations) {
|
|
2929
|
+
const lines = [op.methodLine, op.line].filter((n) => n !== void 0);
|
|
2930
|
+
if (lines.some((n) => [n - 1, n, n + 1].some((x) => atLines.has(`${file}:${x}`))))
|
|
2931
|
+
continue;
|
|
2932
|
+
const method = op.method.toUpperCase();
|
|
2933
|
+
const own = normPath(op.path);
|
|
2934
|
+
const full = normPath(`${server}${op.path}`);
|
|
2935
|
+
const covered = entries.some((e) => {
|
|
2936
|
+
if (e.method && e.method.toUpperCase() !== method)
|
|
2937
|
+
return false;
|
|
2938
|
+
const p = normPath(e.path);
|
|
2939
|
+
return p === own || p === full || p.endsWith(own) || p.split("/").length > 2 && own.endsWith(p);
|
|
2940
|
+
});
|
|
2941
|
+
if (covered)
|
|
2942
|
+
continue;
|
|
2943
|
+
const opId = op.node?.get?.("operationId");
|
|
2944
|
+
const line = op.methodLine ?? op.line ?? 1;
|
|
2945
|
+
out.push({
|
|
2946
|
+
spec: file,
|
|
2947
|
+
method,
|
|
2948
|
+
path: op.path,
|
|
2949
|
+
...typeof opId === "string" ? { operationId: opId } : {},
|
|
2950
|
+
cite: `${file}:${line}`,
|
|
2951
|
+
message: `${file}:${line} declares ${method} ${op.path}${typeof opId === "string" ? ` (${opId})` : ""}, which no entry covers`
|
|
2952
|
+
});
|
|
2953
|
+
}
|
|
2954
|
+
return out;
|
|
2955
|
+
}
|
|
2956
|
+
var REVIEWED_HOLDS_SHOWN = 5;
|
|
2957
|
+
function reviewedHoldsOf(r, skipped) {
|
|
2958
|
+
const n = skipped.length;
|
|
2959
|
+
const first = skipped.slice(0, 3).map((s) => `${s.cite} (${s.value})`);
|
|
2960
|
+
return {
|
|
2961
|
+
path: r.path,
|
|
2962
|
+
why: r.why,
|
|
2963
|
+
count: n,
|
|
2964
|
+
skipped: skipped.slice(0, REVIEWED_HOLDS_SHOWN),
|
|
2965
|
+
message: `${r.line !== void 0 ? `line ${r.line}: ` : ""}${r.path} is reviewed as holding nothing to record, but ${n} ${n === 1 ? "line in it writes" : "lines in it write"} a path, URL or topic: ${first.join(", ")}${n > 3 ? ` and ${n - 3} more` : ""}`
|
|
2966
|
+
};
|
|
2967
|
+
}
|
|
2968
|
+
|
|
2969
|
+
// packages/verify/dist/settings-path.js
|
|
2970
|
+
var SETTINGS_FILE = /\.(ya?ml|properties|json|xml|config|conf|ini|toml|cfg|env)$|(^|\/)\.env(\.[^/]*)?$/i;
|
|
2971
|
+
var isSettingsFile = (path) => SETTINGS_FILE.test(path);
|
|
2972
|
+
var isYaml = (path) => /\.ya?ml$/i.test(path);
|
|
2973
|
+
var DOC_FILE = /\.(md|markdown|mdx|adoc|asciidoc|txt|text|rst|html?|textile|org|rtf|wiki)$/i;
|
|
2974
|
+
var isProperties = (path) => /\.properties$/i.test(path);
|
|
2975
|
+
var escape = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2976
|
+
var YAML_KEY = /^(["']?)([^\s"'#:{}[\],&*!|>][^"'#:]*?)\1\s*:(?:\s+(.*))?$/;
|
|
2977
|
+
function yamlLine(text) {
|
|
2978
|
+
if (!text.trim() || /^\s*#/.test(text) || /^\s*(---|\.\.\.)\s*$/.test(text))
|
|
2979
|
+
return void 0;
|
|
2980
|
+
const lead = /^ */.exec(text)[0].length;
|
|
2981
|
+
const dash = /^ *-(\s+|$)/.exec(text);
|
|
2982
|
+
const col = dash ? dash[0].length : lead;
|
|
2983
|
+
const body = text.slice(col);
|
|
2984
|
+
const m = YAML_KEY.exec(body.trimEnd());
|
|
2985
|
+
const rest = m?.[3]?.trim();
|
|
2986
|
+
return {
|
|
2987
|
+
lead,
|
|
2988
|
+
col,
|
|
2989
|
+
item: !!dash,
|
|
2990
|
+
key: m?.[2]?.trim(),
|
|
2991
|
+
// a comment or an anchor after the key sets nothing
|
|
2992
|
+
rest: rest && !/^[#&]/.test(rest) ? rest : void 0
|
|
2993
|
+
};
|
|
2994
|
+
}
|
|
2995
|
+
function yamlPathAt(lines, line) {
|
|
2996
|
+
const at = yamlLine(lines[line - 1] ?? "");
|
|
2997
|
+
if (!at?.key)
|
|
2998
|
+
return void 0;
|
|
2999
|
+
const path = [at.key];
|
|
3000
|
+
let col = at.item ? at.lead : at.col;
|
|
3001
|
+
let seq = at.item;
|
|
3002
|
+
for (let j = line - 2; j >= 0 && (col > 0 || seq); j--) {
|
|
3003
|
+
const l = lines[j];
|
|
3004
|
+
if (/^\s*(---|\.\.\.)\s*$/.test(l))
|
|
3005
|
+
break;
|
|
3006
|
+
const y = yamlLine(l);
|
|
3007
|
+
if (!y)
|
|
3008
|
+
continue;
|
|
3009
|
+
if (y.item && y.col === col) {
|
|
3010
|
+
col = y.lead;
|
|
3011
|
+
seq = true;
|
|
3012
|
+
continue;
|
|
3013
|
+
}
|
|
3014
|
+
if (seq && !y.item && y.col === col && y.key && !y.rest) {
|
|
3015
|
+
path.unshift(y.key);
|
|
3016
|
+
seq = false;
|
|
3017
|
+
continue;
|
|
3018
|
+
}
|
|
3019
|
+
if (y.col >= col)
|
|
3020
|
+
continue;
|
|
3021
|
+
seq = false;
|
|
3022
|
+
if (!y.key || y.rest)
|
|
3023
|
+
return void 0;
|
|
3024
|
+
path.unshift(y.key);
|
|
3025
|
+
col = y.lead;
|
|
3026
|
+
}
|
|
3027
|
+
if (col > 0)
|
|
3028
|
+
return void 0;
|
|
3029
|
+
return path.flatMap((k) => k.split("."));
|
|
3030
|
+
}
|
|
3031
|
+
function yamlChildren(lines, line) {
|
|
3032
|
+
const at = yamlLine(lines[line - 1] ?? "");
|
|
3033
|
+
if (!at?.key)
|
|
3034
|
+
return [];
|
|
3035
|
+
const out = [];
|
|
3036
|
+
let childCol;
|
|
3037
|
+
for (let j = line; j < lines.length; j++) {
|
|
3038
|
+
const y = yamlLine(lines[j]);
|
|
3039
|
+
if (!y)
|
|
3040
|
+
continue;
|
|
3041
|
+
if (y.lead <= at.col)
|
|
3042
|
+
break;
|
|
3043
|
+
childCol ??= y.col;
|
|
3044
|
+
if (y.col < childCol)
|
|
3045
|
+
break;
|
|
3046
|
+
if (y.col === childCol && y.key && !y.item)
|
|
3047
|
+
out.push(y.key);
|
|
3048
|
+
}
|
|
3049
|
+
return out;
|
|
3050
|
+
}
|
|
3051
|
+
function propertiesKeyAt(lines, line) {
|
|
3052
|
+
const l = lines[line - 1] ?? "";
|
|
3053
|
+
if (/^\s*[#!]/.test(l))
|
|
3054
|
+
return void 0;
|
|
3055
|
+
return /^\s*((?:\\.|[^\s=:\\])+)\s*[=:\s]/.exec(l)?.[1];
|
|
3056
|
+
}
|
|
3057
|
+
var sameSegs = (a, b) => a.length === b.length && a.every((s, i) => s === b[i]);
|
|
3058
|
+
var keySegments = (key) => key.trim().split(".").map((s) => s.replace(/\[[^\]]*\]$/, "")).filter(Boolean);
|
|
3059
|
+
var fieldNames = (seg) => [
|
|
3060
|
+
seg,
|
|
3061
|
+
seg.replace(/-([a-z0-9])/g, (_, c) => c.toUpperCase())
|
|
3062
|
+
];
|
|
3063
|
+
var CONFIG_PROPS = /@ConfigurationProperties\s*\(\s*(?:(?:prefix|value)\s*=\s*)?"([^"]+)"/;
|
|
3064
|
+
function helperBuildsKey(key, cite2, linesOf2) {
|
|
3065
|
+
if (isSettingsFile(cite2.file) || DOC_FILE.test(cite2.file))
|
|
3066
|
+
return false;
|
|
3067
|
+
const segs = keySegments(key);
|
|
3068
|
+
if (segs.length < 2 || segs.join(".") !== key.trim())
|
|
3069
|
+
return false;
|
|
3070
|
+
const last = segs[segs.length - 1];
|
|
3071
|
+
const prefix = segs.slice(0, -1);
|
|
3072
|
+
const line = linesOf2(cite2.file)?.[cite2.line - 1];
|
|
3073
|
+
if (line === void 0)
|
|
3074
|
+
return false;
|
|
3075
|
+
const code2 = isCommentLine(line) ? line : line.replace(/\/\*.*?\*\//g, "").replace(/(^|\s)\/\/.*$/, "");
|
|
3076
|
+
const literals = [];
|
|
3077
|
+
const bare2 = code2.replace(/(["'`])((?:(?!\1)[^\\]|\\.)*)\1/g, (_all, _q, text) => {
|
|
3078
|
+
literals.push(text);
|
|
3079
|
+
return '""';
|
|
3080
|
+
});
|
|
3081
|
+
if (!literals.includes(last) && !new RegExp(`(^|[^A-Za-z0-9_$-])${escape(last)}($|[^A-Za-z0-9_$-])`).test(bare2))
|
|
3082
|
+
return false;
|
|
3083
|
+
const parts = cite2.with ?? [];
|
|
3084
|
+
const files = [...new Set(parts.map((p) => p.file))];
|
|
3085
|
+
return files.some((file) => {
|
|
3086
|
+
const ls = linesOf2(file);
|
|
3087
|
+
if (!ls)
|
|
3088
|
+
return false;
|
|
3089
|
+
const here = parts.filter((p) => p.file === file);
|
|
3090
|
+
if (isYaml(file))
|
|
3091
|
+
return here.some((p) => {
|
|
3092
|
+
const at = yamlPathAt(ls, p.line);
|
|
3093
|
+
if (!at)
|
|
3094
|
+
return false;
|
|
3095
|
+
if (sameSegs(at, segs))
|
|
3096
|
+
return true;
|
|
3097
|
+
return sameSegs(at, prefix) && yamlChildren(ls, p.line).includes(last);
|
|
3098
|
+
});
|
|
3099
|
+
if (isProperties(file))
|
|
3100
|
+
return here.some((p) => propertiesKeyAt(ls, p.line) === segs.join("."));
|
|
3101
|
+
if (isSettingsFile(file))
|
|
3102
|
+
return false;
|
|
3103
|
+
return here.some((p) => {
|
|
3104
|
+
const m = CONFIG_PROPS.exec(ls[p.line - 1] ?? "");
|
|
3105
|
+
if (!m)
|
|
3106
|
+
return false;
|
|
3107
|
+
const pre = m[1].split(".");
|
|
3108
|
+
if (pre.length > prefix.length || !pre.every((s, i) => s === prefix[i]))
|
|
3109
|
+
return false;
|
|
3110
|
+
return prefix.slice(pre.length).every((seg) => here.some((q) => q.line > p.line && q.line <= p.line + 40 && fieldNames(seg).some((n) => new RegExp(`(^|[^A-Za-z0-9_$])${escape(n)}($|[^A-Za-z0-9_$])`).test(ls[q.line - 1] ?? ""))));
|
|
3111
|
+
});
|
|
3112
|
+
});
|
|
3113
|
+
}
|
|
3114
|
+
var norm = (s) => s.replace(/[‘’‚'"“”„`]/g, "").replace(/\s+/g, " ").trim();
|
|
3115
|
+
function yamlScalar(rest) {
|
|
3116
|
+
const t = rest.trim().replace(/^!!?[\w/:.-]*\s+/, "");
|
|
3117
|
+
const q = /^(["'])((?:(?!\1).|\1\1)*)\1/.exec(t);
|
|
3118
|
+
if (q)
|
|
3119
|
+
return q[1] === "'" ? q[2].replace(/''/g, "'") : q[2];
|
|
3120
|
+
return t.replace(/\s+#.*$/, "").trim();
|
|
3121
|
+
}
|
|
3122
|
+
function propertiesValues(line, key, next = []) {
|
|
3123
|
+
let v = line.slice(line.indexOf(key) + key.length).replace(/^\s*[=:]?\s*/, "");
|
|
3124
|
+
for (let i = 0; /(^|[^\\])(\\\\)*\\$/.test(v) && i < next.length; i++)
|
|
3125
|
+
v = v.slice(0, -1) + next[i].replace(/^\s+/, "");
|
|
3126
|
+
return [v.trim(), decodeProperties(v)];
|
|
3127
|
+
}
|
|
3128
|
+
function decodeProperties(v) {
|
|
3129
|
+
return v.replace(/\\(u[0-9a-fA-F]{4}|.)/g, (_, c) => c.length === 5 ? String.fromCharCode(parseInt(c.slice(1), 16)) : c === "t" ? " " : c === "n" ? "\n" : c).trim();
|
|
3130
|
+
}
|
|
3131
|
+
function jsonValueOn(line) {
|
|
3132
|
+
const m = /"value"\s*:\s*("(?:[^"\\]|\\.)*"|[^,}\]\s]+)/.exec(line);
|
|
3133
|
+
if (!m)
|
|
3134
|
+
return void 0;
|
|
3135
|
+
if (!m[1].startsWith('"'))
|
|
3136
|
+
return m[1];
|
|
3137
|
+
try {
|
|
3138
|
+
return JSON.parse(m[1]);
|
|
3139
|
+
} catch {
|
|
3140
|
+
return m[1].slice(1, -1);
|
|
3141
|
+
}
|
|
3142
|
+
}
|
|
3143
|
+
function jsonFrames(lines) {
|
|
3144
|
+
const out = [];
|
|
3145
|
+
const stack = [];
|
|
3146
|
+
for (let ln = 0; ln < lines.length; ln++) {
|
|
3147
|
+
const l = lines[ln];
|
|
3148
|
+
for (let i = 0; i < l.length; i++) {
|
|
3149
|
+
const ch = l[i];
|
|
3150
|
+
const top = stack[stack.length - 1];
|
|
3151
|
+
if (ch === '"') {
|
|
3152
|
+
let j = i + 1;
|
|
3153
|
+
let text = "";
|
|
3154
|
+
for (; j < l.length && l[j] !== '"'; j++) {
|
|
3155
|
+
if (l[j] === "\\" && j + 1 < l.length)
|
|
3156
|
+
j++;
|
|
3157
|
+
text += l[j];
|
|
3158
|
+
}
|
|
3159
|
+
const isKey = top?.type === "{" && !top.afterColon && /^\s*:/.test(l.slice(j + 1));
|
|
3160
|
+
if (top?.type === "{") {
|
|
3161
|
+
if (isKey)
|
|
3162
|
+
top.pending = text;
|
|
3163
|
+
else if (top.afterColon && top.pending === "name" && top.name === void 0)
|
|
3164
|
+
top.name = text;
|
|
3165
|
+
}
|
|
3166
|
+
i = j;
|
|
3167
|
+
continue;
|
|
3168
|
+
}
|
|
3169
|
+
if (ch === ":" && top?.type === "{")
|
|
3170
|
+
top.afterColon = true;
|
|
3171
|
+
else if (ch === "," && top?.type === "{") {
|
|
3172
|
+
top.afterColon = false;
|
|
3173
|
+
top.pending = void 0;
|
|
3174
|
+
} else if (ch === "{" || ch === "[") {
|
|
3175
|
+
const under4 = top?.type === "{" ? top.pending : top?.under;
|
|
3176
|
+
stack.push({ type: ch, start: ln + 1, end: lines.length, ...under4 ? { under: under4 } : {} });
|
|
3177
|
+
} else if (ch === "}" || ch === "]") {
|
|
3178
|
+
const f = stack.pop();
|
|
3179
|
+
if (f) {
|
|
3180
|
+
out.push({
|
|
3181
|
+
type: f.type,
|
|
3182
|
+
start: f.start,
|
|
3183
|
+
end: ln + 1,
|
|
3184
|
+
...f.under ? { under: f.under } : {},
|
|
3185
|
+
...f.name !== void 0 ? { name: f.name } : {}
|
|
3186
|
+
});
|
|
3187
|
+
}
|
|
3188
|
+
}
|
|
3189
|
+
}
|
|
3190
|
+
}
|
|
3191
|
+
return out;
|
|
3192
|
+
}
|
|
3193
|
+
var noExt = (s) => s.trim().toLowerCase().replace(/\.[^.]*$/, "");
|
|
3194
|
+
function enclosingObject(lines, line) {
|
|
3195
|
+
let depth = 0;
|
|
3196
|
+
let start = -1;
|
|
3197
|
+
for (let j = line - 1; j >= 0; j--) {
|
|
3198
|
+
const l = lines[j];
|
|
3199
|
+
for (let k = l.length - 1; k >= 0; k--) {
|
|
3200
|
+
if (l[k] === "}" && j !== line - 1)
|
|
3201
|
+
depth++;
|
|
3202
|
+
if (l[k] === "{") {
|
|
3203
|
+
if (depth === 0) {
|
|
3204
|
+
start = j;
|
|
3205
|
+
break;
|
|
3206
|
+
}
|
|
3207
|
+
depth--;
|
|
3208
|
+
}
|
|
3209
|
+
}
|
|
3210
|
+
if (start >= 0)
|
|
3211
|
+
break;
|
|
3212
|
+
}
|
|
3213
|
+
if (start < 0)
|
|
3214
|
+
return void 0;
|
|
3215
|
+
depth = 0;
|
|
3216
|
+
for (let j = start; j < lines.length; j++) {
|
|
3217
|
+
for (const ch of lines[j]) {
|
|
3218
|
+
if (ch === "{")
|
|
3219
|
+
depth++;
|
|
3220
|
+
if (ch === "}" && --depth === 0)
|
|
3221
|
+
return lines.slice(start, j + 1);
|
|
3222
|
+
}
|
|
3223
|
+
}
|
|
3224
|
+
return void 0;
|
|
3225
|
+
}
|
|
3226
|
+
function configLineProblem(f, linesOf2, listed2, bundleFolders = DEFAULT_GATEWAY_BUNDLE_FOLDERS) {
|
|
3227
|
+
const lines = linesOf2(f.cite.file);
|
|
3228
|
+
if (!lines)
|
|
3229
|
+
return void 0;
|
|
3230
|
+
const at = lines[f.cite.line - 1] ?? "";
|
|
3231
|
+
const where = `${f.cite.file}:${f.cite.line}`;
|
|
3232
|
+
const segs = keySegments(f.key);
|
|
3233
|
+
const value = f.value === void 0 ? void 0 : norm(f.value);
|
|
3234
|
+
const same = (v) => value !== void 0 && v !== void 0 && norm(v) === value;
|
|
3235
|
+
const has = (l) => value !== void 0 && norm(l).includes(value);
|
|
3236
|
+
if (f.key.trim().startsWith("/") && /(^|\/)config\.json$/i.test(f.cite.file)) {
|
|
3237
|
+
const dir = f.cite.file.replace(/[^/]*$/, "");
|
|
3238
|
+
if (!listed2().some((p) => bundleFolders.some((b) => p.startsWith(`${dir}${b}/`))))
|
|
3239
|
+
return `config ${where} is a config.json beside no gateway bundle (no ${bundleFolders.map((b) => `${dir}${b}/`).join(" or ")}); a token's setting is read only from the bundle's own`;
|
|
3240
|
+
const obj = enclosingObject(lines, f.cite.line);
|
|
3241
|
+
const xpathRe = new RegExp(`"xpath"\\s*:\\s*"${escape(f.key.trim())}"`);
|
|
3242
|
+
if (!obj || !obj.some((l) => xpathRe.test(l)))
|
|
3243
|
+
return `the token at ${where} has no "xpath" of ${f.key}`;
|
|
3244
|
+
if (value !== void 0 && !obj.some((l) => same(jsonValueOn(l))))
|
|
3245
|
+
return `the token at ${where} sets no such value; cite the token whose "value" it is`;
|
|
3246
|
+
const around = jsonFrames(lines).filter((x) => x.type === "{" && x.start <= f.cite.line && x.end >= f.cite.line).sort((a, b) => b.start - a.start);
|
|
3247
|
+
if (f.target !== void 0) {
|
|
3248
|
+
const file = around.find((x) => /^(targets|policies|proxies)$/i.test(x.under ?? ""));
|
|
3249
|
+
if (!file?.name || noExt(file.name) !== noExt(f.target))
|
|
3250
|
+
return `the token at ${where} is ${file?.name ? `${file.name}'s` : "in no file's list"}, not ${f.target}'s; give the target the token's file is named`;
|
|
3251
|
+
}
|
|
3252
|
+
if (f.env !== void 0) {
|
|
3253
|
+
const conf = around.find((x) => /^configurations$/i.test(x.under ?? ""));
|
|
3254
|
+
if (!conf?.name || conf.name.trim() !== f.env.trim())
|
|
3255
|
+
return `the token at ${where} is in ${conf?.name ? `the ${conf.name} configuration` : "no named configuration"}, not ${f.env}; give the env its configuration is named`;
|
|
3256
|
+
}
|
|
3257
|
+
return void 0;
|
|
3258
|
+
}
|
|
3259
|
+
if (isYaml(f.cite.file)) {
|
|
3260
|
+
const y = yamlLine(at);
|
|
3261
|
+
const path = yamlPathAt(lines, f.cite.line);
|
|
3262
|
+
if (y?.key && path && segs.length && keySegments(y.key).at(-1) === segs.at(-1)) {
|
|
3263
|
+
const tail = path.slice(path.length - segs.length);
|
|
3264
|
+
if (path.length < segs.length || !sameSegs(tail, segs))
|
|
3265
|
+
return `${where} sets ${path.join(".")}, not ${f.key}: the key's parents are not the lines above it`;
|
|
3266
|
+
if (value !== void 0 && y.rest && !/^[|>]/.test(y.rest)) {
|
|
3267
|
+
if (!same(yamlScalar(y.rest)))
|
|
3268
|
+
return `${where} sets ${y.key} to something other than the value claimed`;
|
|
3269
|
+
return void 0;
|
|
3270
|
+
}
|
|
3271
|
+
}
|
|
3272
|
+
}
|
|
3273
|
+
if (isProperties(f.cite.file)) {
|
|
3274
|
+
const k = propertiesKeyAt(lines, f.cite.line);
|
|
3275
|
+
if (k && k.split(".").at(-1) === segs.at(-1)) {
|
|
3276
|
+
if (k !== segs.join(".") && !k.endsWith(`.${segs.join(".")}`))
|
|
3277
|
+
return `${where} sets ${k}, not ${f.key}`;
|
|
3278
|
+
if (value !== void 0) {
|
|
3279
|
+
if (!propertiesValues(at, k, lines.slice(f.cite.line)).some(same))
|
|
3280
|
+
return `${where} sets ${k} to something other than the value claimed`;
|
|
3281
|
+
return void 0;
|
|
3282
|
+
}
|
|
3283
|
+
}
|
|
3284
|
+
}
|
|
3285
|
+
if (value === void 0 || value === "")
|
|
3286
|
+
return void 0;
|
|
3287
|
+
const near = [f.cite.line - 1, f.cite.line, f.cite.line + 1].map((n) => lines[n - 1] ?? "");
|
|
3288
|
+
const partLines = (f.cite.with ?? []).map((p) => linesOf2(p.file)?.[p.line - 1] ?? "");
|
|
3289
|
+
if ([...near, ...partLines].some(has))
|
|
3290
|
+
return void 0;
|
|
3291
|
+
const hp = /^([^\s:/]+):(\d{1,5})$/.exec(f.value.trim());
|
|
3292
|
+
if (hp) {
|
|
3293
|
+
const parts = f.cite.with ?? [];
|
|
3294
|
+
const written = (want) => parts.some((p) => {
|
|
3295
|
+
if (p.value.trim() !== want)
|
|
3296
|
+
return false;
|
|
3297
|
+
const l = linesOf2(p.file)?.[p.line - 1] ?? "";
|
|
3298
|
+
return new RegExp(`(^|[^A-Za-z0-9.-])${escape(want)}($|[^A-Za-z0-9.-])`).test(l);
|
|
3299
|
+
});
|
|
3300
|
+
if (written(hp[1]) && written(hp[2]))
|
|
3301
|
+
return void 0;
|
|
3302
|
+
}
|
|
3303
|
+
return `${where} (or the line either side) and its parts don't write the value claimed`;
|
|
3304
|
+
}
|
|
3305
|
+
|
|
3306
|
+
// packages/verify/dist/reachable.js
|
|
3307
|
+
var CODE = /\.(java|kt|kts|scala|groovy|cs|vb|fs|py|rb|go|rs|php|swift|ts|tsx|js|mjs|cjs|dart)$/i;
|
|
3308
|
+
var MODEL_DIR = /(^|\/)(models?|dtos?|payloads?|schemas?|pojos?|beans|viewmodels?)\//i;
|
|
3309
|
+
var MODEL_NAME = /(dto|request|response|payload|model|body)$/i;
|
|
3310
|
+
var MODEL_PART = /[._-](dto|model|schema|payload|request|response)\.[^/.]+$/i;
|
|
3311
|
+
var MAPS_TABLE = /@Entity\b|@Table\b|@Document\b|\[Table\(|__tablename__|models\.Model\b|@Entity\(|\bgorm\.Model\b/;
|
|
3312
|
+
var ROOT_PART = /[._-](controller|resolver|gateway|handlers?|router|routes?|consumer|listener|subscriber|client|publisher|producer|endpoints?)\.[^/.]+$/i;
|
|
3313
|
+
var CLIENT_NAME = /(client|gateway|publisher|producer|sender|feign|proxy|connector)$/i;
|
|
3314
|
+
var CLIENT_DIR = /(^|\/)(clients?|gateways?|integrations?|publishers?|producers?|outbound)\//i;
|
|
3315
|
+
var base = (path) => path.slice(path.lastIndexOf("/") + 1);
|
|
3316
|
+
var stem = (path) => {
|
|
3317
|
+
const b = base(path);
|
|
3318
|
+
const dot = b.indexOf(".");
|
|
3319
|
+
return dot > 0 ? b.slice(0, dot) : b;
|
|
3320
|
+
};
|
|
3321
|
+
function isModelFile(path, text) {
|
|
3322
|
+
if (!CODE.test(path) || readingRank(path) === 5)
|
|
3323
|
+
return false;
|
|
3324
|
+
if (!MODEL_DIR.test(path) && !MODEL_NAME.test(stem(path)) && !MODEL_PART.test(path))
|
|
3325
|
+
return false;
|
|
3326
|
+
return text === void 0 || !MAPS_TABLE.test(text);
|
|
3327
|
+
}
|
|
3328
|
+
var ENTRY_POINT_NAME = /(controller|resource|router|routes?|handlers?|listener|consumer|subscriber|endpoints?|servlet|webhook|resolver)$/i;
|
|
3329
|
+
var ENTRY_POINT_DIR = /(^|\/)(controllers?|routes|routers|handlers|endpoints|listeners|consumers)\//i;
|
|
3330
|
+
var ENTRY_POINT_PART = /[._-](controller|resolver|handlers?|router|routes?|consumer|listener|subscriber|endpoints?)\.[^/.]+$/i;
|
|
3331
|
+
function isEntryPointFile(path) {
|
|
3332
|
+
if (!CODE.test(path) || readingRank(path) === 5 || isModelFile(path))
|
|
3333
|
+
return false;
|
|
3334
|
+
return ENTRY_POINT_NAME.test(stem(path)) || ENTRY_POINT_DIR.test(path) || ENTRY_POINT_PART.test(path);
|
|
3335
|
+
}
|
|
3336
|
+
function isRootFile(path) {
|
|
3337
|
+
if (!CODE.test(path) || readingRank(path) === 5 || isModelFile(path))
|
|
3338
|
+
return false;
|
|
3339
|
+
return readingRank(path) === 2 || isEntryPointFile(path) || ROOT_PART.test(path) || CLIENT_NAME.test(stem(path)) || CLIENT_DIR.test(path);
|
|
3340
|
+
}
|
|
3341
|
+
var DECLARES = /\b(?:class|record|interface|struct|enum|object)\s+([A-Za-z_][A-Za-z0-9_]*)|^\s*(?:export\s+)?(?:declare\s+)?type\s+([A-Za-z_][A-Za-z0-9_]*)/gm;
|
|
3342
|
+
var IDENT = /[A-Za-z_][A-Za-z0-9_]*/g;
|
|
3343
|
+
function declaredTypes(path, text) {
|
|
3344
|
+
const out = [];
|
|
3345
|
+
const s = stem(path);
|
|
3346
|
+
if (/^[A-Z][A-Za-z0-9_]*$/.test(s))
|
|
3347
|
+
out.push(s);
|
|
3348
|
+
for (const m of text.matchAll(DECLARES)) {
|
|
3349
|
+
const n = m[1] ?? m[2];
|
|
3350
|
+
if (n && !out.includes(n))
|
|
3351
|
+
out.push(n);
|
|
3352
|
+
}
|
|
3353
|
+
return out;
|
|
3354
|
+
}
|
|
3355
|
+
function identifiers(text) {
|
|
3356
|
+
return [...new Set(text.match(IDENT) ?? [])];
|
|
3357
|
+
}
|
|
3358
|
+
var NOT_REACHED_WHY = "model classes no entry point, call or field fact reaches (ADR 0169): left out of the read; atticus map <repo> --models all reads them";
|
|
3359
|
+
function reachableModels(o) {
|
|
3360
|
+
const texts = /* @__PURE__ */ new Map();
|
|
3361
|
+
const textOf = (p) => {
|
|
3362
|
+
if (!texts.has(p))
|
|
3363
|
+
texts.set(p, o.read(p) ?? "");
|
|
3364
|
+
return texts.get(p);
|
|
3365
|
+
};
|
|
3366
|
+
const ordered = readingOrder(o.paths);
|
|
3367
|
+
const models = ordered.filter((p) => isModelFile(p, textOf(p))).sort();
|
|
3368
|
+
const isModel = new Set(models);
|
|
3369
|
+
const byName = /* @__PURE__ */ new Map();
|
|
3370
|
+
const declared = /* @__PURE__ */ new Map();
|
|
3371
|
+
for (const p of models) {
|
|
3372
|
+
const names = declaredTypes(p, textOf(p));
|
|
3373
|
+
declared.set(p, names);
|
|
3374
|
+
for (const n of names)
|
|
3375
|
+
byName.set(n, [...byName.get(n) ?? [], p]);
|
|
3376
|
+
}
|
|
3377
|
+
const known = new Set(o.paths);
|
|
3378
|
+
const roots = [];
|
|
3379
|
+
const addRoot = (p) => {
|
|
3380
|
+
if (known.has(p) && !isModel.has(p) && !roots.includes(p))
|
|
3381
|
+
roots.push(p);
|
|
3382
|
+
};
|
|
3383
|
+
const facts = o.facts ?? [];
|
|
3384
|
+
const entries = o.from === "entries";
|
|
3385
|
+
const calls2 = new Set(facts.filter((f) => f.kind === "call").map((f) => f.id));
|
|
3386
|
+
for (const f of facts)
|
|
3387
|
+
if (f.kind === "entry" || f.kind === "call" && !entries)
|
|
3388
|
+
for (const p of citedFiles(f))
|
|
3389
|
+
addRoot(p);
|
|
3390
|
+
for (const p of ordered)
|
|
3391
|
+
if (entries ? isEntryPointFile(p) : isRootFile(p))
|
|
3392
|
+
addRoot(p);
|
|
3393
|
+
const reached = /* @__PURE__ */ new Map();
|
|
3394
|
+
const queue = [];
|
|
3395
|
+
const reach = (names, from, own = []) => {
|
|
3396
|
+
for (const n of names) {
|
|
3397
|
+
if (own.includes(n))
|
|
3398
|
+
continue;
|
|
3399
|
+
for (const p of byName.get(n) ?? []) {
|
|
3400
|
+
const r = reached.get(p);
|
|
3401
|
+
if (r) {
|
|
3402
|
+
if (r.from === from && !r.types.includes(n))
|
|
3403
|
+
r.types.push(n);
|
|
3404
|
+
continue;
|
|
3405
|
+
}
|
|
3406
|
+
reached.set(p, { path: p, types: [n], from });
|
|
3407
|
+
queue.push(p);
|
|
3408
|
+
}
|
|
3409
|
+
}
|
|
3410
|
+
};
|
|
3411
|
+
for (const p of roots)
|
|
3412
|
+
reach(identifiers(textOf(p)), p);
|
|
3413
|
+
for (const f of facts) {
|
|
3414
|
+
for (const p of citedFiles(f))
|
|
3415
|
+
if (isModel.has(p) && !reached.has(p)) {
|
|
3416
|
+
reached.set(p, { path: p, types: [...(declared.get(p) ?? []).slice(0, 1)], from: f.id });
|
|
3417
|
+
queue.push(p);
|
|
3418
|
+
}
|
|
3419
|
+
if (f.kind === "field" && !(entries && calls2.has(f.owner)))
|
|
3420
|
+
reach(identifiers([f.type ?? "", f.transform === "message type" ? f.name : ""].join(" ")), f.id);
|
|
1919
3421
|
}
|
|
1920
|
-
|
|
3422
|
+
const rooted = roots.length > 0 || reached.size > 0;
|
|
3423
|
+
if (!rooted)
|
|
3424
|
+
return {
|
|
3425
|
+
rooted,
|
|
3426
|
+
roots,
|
|
3427
|
+
reached: models.map((p) => ({ path: p, types: declared.get(p) ?? [], from: "" })),
|
|
3428
|
+
notReached: [],
|
|
3429
|
+
models: models.length
|
|
3430
|
+
};
|
|
3431
|
+
for (let i = 0; i < queue.length; i++) {
|
|
3432
|
+
const p = queue[i];
|
|
3433
|
+
reach(identifiers(textOf(p)), p, declared.get(p));
|
|
3434
|
+
}
|
|
3435
|
+
return {
|
|
3436
|
+
rooted,
|
|
3437
|
+
roots,
|
|
3438
|
+
reached: queue.map((p) => reached.get(p)),
|
|
3439
|
+
notReached: models.filter((p) => !reached.has(p)),
|
|
3440
|
+
models: models.length
|
|
3441
|
+
};
|
|
1921
3442
|
}
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
3443
|
+
|
|
3444
|
+
// packages/verify/dist/method.js
|
|
3445
|
+
var HTTP_METHODS = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
|
|
3446
|
+
function wordsOf2(line) {
|
|
3447
|
+
return line.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").toLowerCase().split(/[^a-z]+/).filter(Boolean);
|
|
3448
|
+
}
|
|
3449
|
+
function methodOnLines(method, lines) {
|
|
3450
|
+
const m = method.toLowerCase();
|
|
3451
|
+
return lines.some((l) => wordsOf2(l).includes(m));
|
|
3452
|
+
}
|
|
3453
|
+
var CHAIN_LINES = 8;
|
|
3454
|
+
var CONTINUES = /^\s*\??\./;
|
|
3455
|
+
function chainOf(file, line) {
|
|
3456
|
+
const at = (n) => file?.[n - 1];
|
|
3457
|
+
const cited = at(line);
|
|
3458
|
+
if (cited === void 0)
|
|
3459
|
+
return [];
|
|
3460
|
+
const out = [cited];
|
|
3461
|
+
for (let n = line, k = 0; k < CHAIN_LINES && CONTINUES.test(at(n) ?? ""); k++, n--) {
|
|
3462
|
+
const above = at(n - 1);
|
|
3463
|
+
if (above === void 0)
|
|
3464
|
+
break;
|
|
3465
|
+
out.push(above);
|
|
1928
3466
|
}
|
|
1929
|
-
|
|
1930
|
-
|
|
3467
|
+
for (let n = line + 1, k = 0; k < CHAIN_LINES && CONTINUES.test(at(n) ?? ""); k++, n++)
|
|
3468
|
+
out.push(at(n));
|
|
3469
|
+
return out;
|
|
1931
3470
|
}
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
kind: c.kind,
|
|
1935
|
-
value: c.value,
|
|
1936
|
-
text: c.text
|
|
1937
|
-
});
|
|
1938
|
-
var SPEC_MARK = /^\s*["']?(openapi|swagger)["']?\s*:/m;
|
|
1939
|
-
var SPEC_EXT = /\.(ya?ml|json)$/i;
|
|
1940
|
-
function specOpsUncoveredIn(file, text, facts) {
|
|
1941
|
-
if (!SPEC_EXT.test(file) || !SPEC_MARK.test(text.slice(0, 4e3)))
|
|
3471
|
+
function methodUnseenOf(f, lines, factOf) {
|
|
3472
|
+
if (f.kind !== "entry" && f.kind !== "call")
|
|
1942
3473
|
return void 0;
|
|
1943
|
-
|
|
1944
|
-
try {
|
|
1945
|
-
doc = readOpenApiDocument(text);
|
|
1946
|
-
} catch {
|
|
3474
|
+
if (!f.method || !HTTP_METHODS.has(f.method.toUpperCase()))
|
|
1947
3475
|
return void 0;
|
|
1948
|
-
|
|
1949
|
-
|
|
3476
|
+
const at = (file, line) => lines(file)?.[line - 1];
|
|
3477
|
+
const route = f.kind === "call" && f.from ? factOf?.(f.from) : void 0;
|
|
3478
|
+
const forwards = route?.kind === "entry" && route.method?.toUpperCase() === f.method.toUpperCase();
|
|
3479
|
+
const looked = [
|
|
3480
|
+
...chainOf(lines(f.cite.file), f.cite.line),
|
|
3481
|
+
at(f.cite.file, f.cite.line + 1),
|
|
3482
|
+
...(f.cite.with ?? []).map((p) => at(p.file, p.line)),
|
|
3483
|
+
...forwards ? [at(route.cite.file, route.cite.line), at(route.cite.file, route.cite.line + 1)] : []
|
|
3484
|
+
].filter((l) => l !== void 0);
|
|
3485
|
+
if (methodOnLines(f.method, looked))
|
|
1950
3486
|
return void 0;
|
|
1951
|
-
const
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
3487
|
+
const cite2 = `${f.cite.file}:${f.cite.line}`;
|
|
3488
|
+
const method = f.method.toUpperCase();
|
|
3489
|
+
return {
|
|
3490
|
+
id: f.id,
|
|
3491
|
+
kind: f.kind,
|
|
3492
|
+
method,
|
|
3493
|
+
cite: cite2,
|
|
3494
|
+
message: `${f.id} claims ${method}, which neither ${cite2}, the chain it is in, the next line, a cite.with line nor the route it forwards writes`
|
|
3495
|
+
};
|
|
3496
|
+
}
|
|
3497
|
+
|
|
3498
|
+
// packages/verify/dist/verify.js
|
|
3499
|
+
var LINE_KEY_VALUE = /^\s*(?:-\s+)?(?:export\s+)?["']?([A-Za-z0-9_.\-[\]]+)["']?\s*[:=]\s*(.*?)\s*,?\s*$/;
|
|
3500
|
+
var LINE_XML = [
|
|
3501
|
+
/<([A-Za-z_][\w.-]*)>([^<]+)<\/\1>/g,
|
|
3502
|
+
/\b(?:key|name)\s*=\s*"([^"]+)"\s+value\s*=\s*"([^"]*)"/g
|
|
3503
|
+
];
|
|
3504
|
+
var unquoted = (v) => v.replace(/^["'`]|["'`]$/g, "").trim();
|
|
3505
|
+
function pairsOf(t) {
|
|
1963
3506
|
const out = [];
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
const
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
3507
|
+
const kv = LINE_KEY_VALUE.exec(t);
|
|
3508
|
+
if (kv)
|
|
3509
|
+
out.push({ key: kv[1], value: unquoted(kv[2]) });
|
|
3510
|
+
for (const re of LINE_XML)
|
|
3511
|
+
for (const m of t.matchAll(re))
|
|
3512
|
+
out.push({ key: m[1], value: unquoted(m[2]) });
|
|
3513
|
+
return out;
|
|
3514
|
+
}
|
|
3515
|
+
function lineSecrets(line) {
|
|
3516
|
+
const t = line.trim();
|
|
3517
|
+
if (!t)
|
|
3518
|
+
return [];
|
|
3519
|
+
const pairs = pairsOf(t);
|
|
3520
|
+
const words = t.split(/[\s"'`=:,;()<>{}[\]/@]+/).filter((w) => w.length >= 6 && credentialLike(w));
|
|
3521
|
+
const holds = redactSecrets(t) !== t || hasSecretShape(t) || quoteHoldsSecret(t) || words.length > 0 || pairs.some((p) => looksLikeSecret(p.key, "x") || p.value && credentialLike(p.value));
|
|
3522
|
+
if (!holds)
|
|
3523
|
+
return [];
|
|
3524
|
+
const literals = [...t.matchAll(/(["'`])((?:(?!\1).){3,})\1/g)].map((m) => m[2]);
|
|
3525
|
+
return [t, t.slice(0, 200), ...pairs.map((p) => p.value), ...literals, ...words].filter((s) => s.length >= 3);
|
|
3526
|
+
}
|
|
3527
|
+
function citesIn(x, out = []) {
|
|
3528
|
+
if (Array.isArray(x))
|
|
3529
|
+
for (const v of x)
|
|
3530
|
+
citesIn(v, out);
|
|
3531
|
+
else if (x && typeof x === "object") {
|
|
3532
|
+
const o = x;
|
|
3533
|
+
if (typeof o.file === "string" && typeof o.line === "number")
|
|
3534
|
+
out.push(o);
|
|
3535
|
+
for (const v of Object.values(o))
|
|
3536
|
+
if (v && typeof v === "object")
|
|
3537
|
+
citesIn(v, out);
|
|
1989
3538
|
}
|
|
1990
3539
|
return out;
|
|
1991
3540
|
}
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
3541
|
+
function quietFact(f, lineAt) {
|
|
3542
|
+
if (f.kind !== "config")
|
|
3543
|
+
return false;
|
|
3544
|
+
if (looksLikeSecret(f.key, "x") || configSecretField(f))
|
|
3545
|
+
return true;
|
|
3546
|
+
if ([f.value, f.source, f.cite.quote, ...(f.cite.with ?? []).map((w) => w.value)].some((t) => t !== void 0 && (hasSecretShape(t) || credentialLike(t) || redactSecrets(t) !== t)))
|
|
3547
|
+
return true;
|
|
3548
|
+
return lineAt !== void 0 && [f.cite, ...f.cite.with ?? []].some((c) => lineSecrets(lineAt(c.file, c.line) ?? "").length);
|
|
3549
|
+
}
|
|
3550
|
+
function sanitised(f, message, lineAt, quiet) {
|
|
3551
|
+
let out = redactSecrets(message);
|
|
3552
|
+
const texts = /* @__PURE__ */ new Set();
|
|
3553
|
+
for (const c of citesIn(f))
|
|
3554
|
+
for (const n of [c.line - 1, c.line, c.line + 1])
|
|
3555
|
+
for (const s of lineSecrets(lineAt(c.file, n) ?? ""))
|
|
3556
|
+
texts.add(s);
|
|
3557
|
+
for (const t of [...texts].sort((a, b) => b.length - a.length))
|
|
3558
|
+
out = out.split(t).join("<redacted>");
|
|
3559
|
+
out = out.replace(/"([^"]*)"/g, (all2, inner) => lineSecrets(inner).length ? '"<redacted>"' : all2);
|
|
3560
|
+
return quiet ? scrubbed(f, out) : out;
|
|
3561
|
+
}
|
|
3562
|
+
function shownFact(f, quiet, lineAt) {
|
|
3563
|
+
if (quiet)
|
|
3564
|
+
return withoutSecret(f);
|
|
3565
|
+
const cites = citesIn(f).filter((c) => c.quote !== void 0);
|
|
3566
|
+
const bad = (c) => {
|
|
3567
|
+
const q = c.quote;
|
|
3568
|
+
if (lineSecrets(q).length)
|
|
3569
|
+
return true;
|
|
3570
|
+
return [c.line - 1, c.line, c.line + 1].some((n) => lineSecrets(lineAt(c.file, n) ?? "").some((s) => s !== "" && q.includes(s)));
|
|
3571
|
+
};
|
|
3572
|
+
if (!cites.some(bad))
|
|
3573
|
+
return f;
|
|
3574
|
+
const strip = (x) => {
|
|
3575
|
+
if (Array.isArray(x))
|
|
3576
|
+
return x.map(strip);
|
|
3577
|
+
if (!x || typeof x !== "object")
|
|
3578
|
+
return x;
|
|
3579
|
+
const o = Object.fromEntries(Object.entries(x).map(([k, v]) => [k, strip(v)]));
|
|
3580
|
+
const c = x;
|
|
3581
|
+
if (typeof c.file === "string" && typeof c.line === "number" && typeof c.quote === "string" && bad(c))
|
|
3582
|
+
delete o.quote;
|
|
3583
|
+
return o;
|
|
3584
|
+
};
|
|
3585
|
+
return strip(f);
|
|
3586
|
+
}
|
|
3587
|
+
function scrubbed(f, message) {
|
|
3588
|
+
if (f.kind !== "config")
|
|
3589
|
+
return message;
|
|
3590
|
+
const names = new Set([f.key, f.target, f.env, f.cite.file, ...(f.cite.with ?? []).map((w) => w.file)].filter((x) => x !== void 0));
|
|
3591
|
+
const texts = [f.value, f.source, f.cite.quote, ...(f.cite.with ?? []).map((w) => w.value)].flatMap((t) => t === void 0 ? [] : [t, t.trim()]).filter((t) => t.length >= 3 && !names.has(t)).sort((a, b) => b.length - a.length);
|
|
3592
|
+
let out = message;
|
|
3593
|
+
for (const t of texts)
|
|
3594
|
+
out = out.split(t).join("<redacted>");
|
|
3595
|
+
return out;
|
|
3596
|
+
}
|
|
3597
|
+
var asRead = /* @__PURE__ */ new WeakMap();
|
|
3598
|
+
function factAsRead(f) {
|
|
3599
|
+
return asRead.get(f) ?? f;
|
|
3600
|
+
}
|
|
3601
|
+
function withoutSecret(f) {
|
|
3602
|
+
if (f.kind !== "config")
|
|
3603
|
+
return f;
|
|
3604
|
+
const { quote: _q, ...cite2 } = f.cite;
|
|
1996
3605
|
return {
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
3606
|
+
...f,
|
|
3607
|
+
...f.value !== void 0 ? { value: "<redacted>" } : {},
|
|
3608
|
+
...f.source !== void 0 ? { source: "<redacted>" } : {},
|
|
3609
|
+
cite: {
|
|
3610
|
+
...cite2,
|
|
3611
|
+
...f.cite.with ? { with: f.cite.with.map((w) => ({ ...w, value: "<redacted>" })) } : {}
|
|
3612
|
+
}
|
|
2002
3613
|
};
|
|
2003
3614
|
}
|
|
2004
|
-
|
|
2005
|
-
// packages/verify/dist/verify.js
|
|
2006
3615
|
var FOLLOWED_TYPES = ["event-topic", "mq-queue", "rest", "grpc"];
|
|
2007
3616
|
function entriesNoFlowFollows(facts, rules = DEFAULT_READ_RULES) {
|
|
2008
3617
|
const started = new Set(facts.flatMap((f) => f.kind === "flow" ? [f.entry] : []));
|
|
@@ -2029,6 +3638,8 @@ var LINES_HELD = 64;
|
|
|
2029
3638
|
var SOURCE_EXT = /\.(java|kt|kts|scala|groovy|cs|vb|fs|ts|tsx|js|jsx|mjs|cjs|py|rb|go|rs|php|swift|m|mm|c|cc|cpp|h|hpp|sql|graphql|gql|proto|ya?ml|json|xml|properties|toml|ini|conf|tf|tfvars|hcl|bicep|sh|ps1|bat|cmd|gradle|html?|vue|svelte|cshtml|razor|aspx|jsp|ftl|hbs|cob|cbl|cpy|jcl|avsc|wsdl|xsd|csproj|sln|config)$/i;
|
|
2030
3639
|
var SOURCE_NAME = /(^|\/)(Dockerfile[^/]*|Makefile|Jenkinsfile|Procfile|Containerfile)$/;
|
|
2031
3640
|
var LOCKFILE = /(^|\/)(package-lock\.json|npm-shrinkwrap\.json|yarn\.lock|pnpm-lock\.yaml|composer\.lock|Gemfile\.lock|Cargo\.lock|poetry\.lock|go\.sum|packages\.lock\.json)$/;
|
|
3641
|
+
var ENV_FOLDER = /(^|\/)(env|envs|environments?|overlays|stages?)\/[^/]+(?=\/)/gi;
|
|
3642
|
+
var testFileOf = (rules, p) => rules.notProduct.test(p.replace(ENV_FOLDER, "$1$2/_"));
|
|
2032
3643
|
var NOT_PRODUCT = [
|
|
2033
3644
|
/(\.|_|-)(test|spec|tests|specs)\.[a-z0-9]+$/i,
|
|
2034
3645
|
/(Test|Tests|IT|Spec)\.(java|kt|scala|groovy|cs|vb)$/,
|
|
@@ -2076,12 +3687,16 @@ var repoModule = (exposes) => {
|
|
|
2076
3687
|
const m = /^([^/]+)\/([^/]+)$/.exec(exposes.trim());
|
|
2077
3688
|
return m ? { repo: m[1], module: m[2] } : void 0;
|
|
2078
3689
|
};
|
|
3690
|
+
var PLACEHOLDER_KEY = /^\$\{([A-Za-z_][A-Za-z0-9_.-]*)\}$/;
|
|
2079
3691
|
var routeOrWord = (v) => v.includes("/") ? { kind: "route", value: v } : { kind: "word", value: v };
|
|
2080
3692
|
function claimsOf(f) {
|
|
2081
3693
|
switch (f.kind) {
|
|
3694
|
+
// A call whose path is a setting's placeholder a helper puts together is checked apart
|
|
3695
|
+
// (`helperBuildsKey`): its bare key is never a claim, or a settings line would be a call.
|
|
2082
3696
|
case "entry":
|
|
2083
|
-
case "call":
|
|
2084
3697
|
return [routeOrWord(f.path)];
|
|
3698
|
+
case "call":
|
|
3699
|
+
return f.path.trim() === "/" && /^[a-z][a-z0-9+.-]*:\/\/[^/\s?#]+\/?$/i.test(f.cite.value.trim()) ? [routeOrWord(f.path), { kind: "word", value: f.cite.value.trim() }] : [routeOrWord(f.path)];
|
|
2085
3700
|
case "store":
|
|
2086
3701
|
return [
|
|
2087
3702
|
{ kind: "word", value: f.name },
|
|
@@ -2117,6 +3732,14 @@ function claimsOf(f) {
|
|
|
2117
3732
|
// ADR 0180: the signal the type rests on, as written on its line.
|
|
2118
3733
|
case "component":
|
|
2119
3734
|
return [{ kind: "word", value: f.cite.value }];
|
|
3735
|
+
// ADR 0192: the coordinates as the build file writes them on the line (the name, or a
|
|
3736
|
+
// Gradle line's whole `group:name:version`); `buildCoordinatesProblem` reads the rest.
|
|
3737
|
+
case "artifact":
|
|
3738
|
+
case "dependency":
|
|
3739
|
+
return [
|
|
3740
|
+
{ kind: "word", value: f.cite.value },
|
|
3741
|
+
{ kind: "word", value: f.name }
|
|
3742
|
+
];
|
|
2120
3743
|
}
|
|
2121
3744
|
}
|
|
2122
3745
|
var sameCommit = (a, b) => a.startsWith(b) || b.startsWith(a);
|
|
@@ -2225,7 +3848,8 @@ async function verifyFacts(o) {
|
|
|
2225
3848
|
return lines;
|
|
2226
3849
|
};
|
|
2227
3850
|
const deriveEnv = { lines: linesOf2, files: listed2 };
|
|
2228
|
-
const
|
|
3851
|
+
const lineAt = (file, n) => n >= 1 ? linesOf2(file)?.[n - 1] : void 0;
|
|
3852
|
+
const checkCite = (cite2, claims, label, withHint = true, alsoHolds, quiet = false) => {
|
|
2229
3853
|
const where = `${cite2.file}:${cite2.line}`;
|
|
2230
3854
|
if (!insideRepo(cite2.file))
|
|
2231
3855
|
return {
|
|
@@ -2278,7 +3902,7 @@ async function verifyFacts(o) {
|
|
|
2278
3902
|
!partsNamePath(near(ls, p.line), p.value))
|
|
2279
3903
|
return {
|
|
2280
3904
|
code: "claim-not-on-line",
|
|
2281
|
-
message: `${pl} says "${p.value}" is written at ${p.file}:${p.line} (or the line either side), and it isn't`
|
|
3905
|
+
message: quiet ? `${pl} is not written at ${p.file}:${p.line} (or the line either side); cite the line that writes it (its text is not repeated here: it may be a secret)` : `${pl} says "${p.value}" is written at ${p.file}:${p.line} (or the line either side), and it isn't`
|
|
2282
3906
|
};
|
|
2283
3907
|
partLines.push(...near(ls, p.line));
|
|
2284
3908
|
}
|
|
@@ -2295,6 +3919,11 @@ async function verifyFacts(o) {
|
|
|
2295
3919
|
code: "claim-not-on-line",
|
|
2296
3920
|
message: `${label} claims ${claims.map((c) => `"${c.value}"`).join(" or ")}, which ${where} (or the line either side)${parts.length ? " and its parts" : ""} does not name${parts.length || !withHint ? "" : "; if it is put together from other lines (a base URL, a prefix, a context path), cite them in cite.with"}`
|
|
2297
3921
|
};
|
|
3922
|
+
if (claims && parts.length && isCommentLine(lines[cite2.line - 1] ?? "") && !/(^|\/)_redirects$/.test(cite2.file))
|
|
3923
|
+
return {
|
|
3924
|
+
code: "claim-in-comment",
|
|
3925
|
+
message: `${label} cites ${where}, which is a comment; cite the code that does it`
|
|
3926
|
+
};
|
|
2298
3927
|
if (claims && !parts.length) {
|
|
2299
3928
|
const naming = [cite2.line - 1, cite2.line, cite2.line + 1].map((n) => lines[n - 1]).filter((l) => l !== void 0 && claims.some((c) => lineNamesClaim(l, c)));
|
|
2300
3929
|
if (naming.length && !/(^|\/)_redirects$/.test(cite2.file) && naming.every(isCommentLine))
|
|
@@ -2309,7 +3938,7 @@ async function verifyFacts(o) {
|
|
|
2309
3938
|
if (!near2.some((l) => quoteMatches(l, cite2.quote)))
|
|
2310
3939
|
return {
|
|
2311
3940
|
code: "quote-mismatch",
|
|
2312
|
-
message: `${label} quotes "${cite2.quote}", but ${where} reads "${line.trim().slice(0, 200)}"`
|
|
3941
|
+
message: quiet ? `${label}'s quote is not what ${where} (or the line either side) reads; neither is repeated here, as either may hold a secret` : `${label} quotes "${cite2.quote}", but ${where} reads "${line.trim().slice(0, 200)}"`
|
|
2313
3942
|
};
|
|
2314
3943
|
}
|
|
2315
3944
|
return void 0;
|
|
@@ -2328,6 +3957,8 @@ async function verifyFacts(o) {
|
|
|
2328
3957
|
};
|
|
2329
3958
|
const estate = o.estate ? new Set(o.estate.components.map(factIdPart)) : void 0;
|
|
2330
3959
|
const serves2 = facts.some((f) => f.kind === "entry");
|
|
3960
|
+
const moduleOf = /* @__PURE__ */ new Map();
|
|
3961
|
+
const placedFrom = /* @__PURE__ */ new Map();
|
|
2331
3962
|
const repoComponents = new Map(Object.entries(o.estate?.repoComponents ?? {}).map(([r, cs]) => [factIdPart(r), new Set(cs.map(factIdPart))]));
|
|
2332
3963
|
for (const f of facts) {
|
|
2333
3964
|
const label = `${f.kind} ${f.id}`;
|
|
@@ -2342,7 +3973,21 @@ async function verifyFacts(o) {
|
|
|
2342
3973
|
problem(f, "wrong-commit", `${label} was read at ${f.commit}, not at ${o.commit}; read it again`);
|
|
2343
3974
|
continue;
|
|
2344
3975
|
}
|
|
2345
|
-
add(f, checkCite(f.cite, claimsOf(f), label, true, f.kind === "entry" || f.kind === "call" ? (ls, n) => apigeePassThrough({ kind: f.kind, forwards: f.kind === "call" && !!f.from }, f.cite.file, ls, n, f.path)
|
|
3976
|
+
add(f, checkCite(f.cite, claimsOf(f), label, true, f.kind === "entry" || f.kind === "call" ? (ls, n) => apigeePassThrough({ kind: f.kind, forwards: f.kind === "call" && !!f.from }, f.cite.file, ls, n, f.path) || // A path written as a setting's placeholder that no line writes whole (ADR 0172,
|
|
3977
|
+
// beta.24): a helper puts the key together (a `@ConfigurationProperties` prefix, a
|
|
3978
|
+
// map field, the name passed to a lookup). The cited line is code naming the key's
|
|
3979
|
+
// last segment, and one file among the parts proves the rest of the key nests so.
|
|
3980
|
+
f.kind === "call" && PLACEHOLDER_KEY.test(f.path.trim()) && helperBuildsKey(PLACEHOLDER_KEY.exec(f.path.trim())[1], f.cite, linesOf2) : void 0, quietFact(f, lineAt)));
|
|
3981
|
+
if (f.kind === "config" && !found.has(f.id)) {
|
|
3982
|
+
const bad = configLineProblem(f, linesOf2, listed2, rules.gatewayBundleFolders);
|
|
3983
|
+
if (bad)
|
|
3984
|
+
problem(f, "claim-not-on-line", `${label}: ${bad}`);
|
|
3985
|
+
}
|
|
3986
|
+
if (f.kind === "config") {
|
|
3987
|
+
const field = configSecretField(f);
|
|
3988
|
+
if (field)
|
|
3989
|
+
problem(f, "secret-value", `${label}: "${f.key}" carries a secret in its ${field}; cite the line that names the setting and give its source (env:NAME, vault:path), never its value`);
|
|
3990
|
+
}
|
|
2346
3991
|
if (f.kind === "entry" && f.authCite)
|
|
2347
3992
|
add(f, checkCite({ ...f.authCite }, [{ kind: "word", value: f.authCite.value }], `${label} authCite${f.auth ? ` (auth ${f.auth})` : ""}`, false));
|
|
2348
3993
|
if (f.kind === "entry" && f.authCite && f.auth) {
|
|
@@ -2433,6 +4078,32 @@ async function verifyFacts(o) {
|
|
|
2433
4078
|
if (f.version !== void 0)
|
|
2434
4079
|
add(f, checkCite(f.cite, [{ kind: "word", value: f.version }], `${label} version`, false));
|
|
2435
4080
|
}
|
|
4081
|
+
const own = o.estate?.repoComponent?.[f.repo];
|
|
4082
|
+
if (own !== void 0 && o.estate) {
|
|
4083
|
+
const to = placedComponentOf(f, {
|
|
4084
|
+
component: own,
|
|
4085
|
+
modules: o.estate.modules?.[f.repo],
|
|
4086
|
+
components: o.estate.components,
|
|
4087
|
+
prototype: o.estate.prototypes?.includes(f.repo)
|
|
4088
|
+
});
|
|
4089
|
+
const top = f.cite?.file?.split("/")[0];
|
|
4090
|
+
if (to !== void 0 && top !== void 0 && isBuildModuleDir(top, linesOf2)) {
|
|
4091
|
+
moduleOf.set(f.id, to);
|
|
4092
|
+
placedFrom.set(f.id, f.component);
|
|
4093
|
+
}
|
|
4094
|
+
}
|
|
4095
|
+
if ((f.kind === "artifact" || f.kind === "dependency") && !found.has(f.id)) {
|
|
4096
|
+
const mod = buildModuleOf(f, linesOf2, o.estate?.modules?.[f.repo] ?? [], o.estate?.repoComponent?.[f.repo]);
|
|
4097
|
+
const bad = buildCoordinatesProblem(f, linesOf2, listed2()) ?? buildModuleProblem(f, mod);
|
|
4098
|
+
if (bad)
|
|
4099
|
+
problem(f, "build-coordinates", bad);
|
|
4100
|
+
else {
|
|
4101
|
+
if (mod?.from === "manifest" && mod.component && f.component === void 0)
|
|
4102
|
+
moduleOf.set(f.id, mod.component);
|
|
4103
|
+
if (f.version !== void 0 && !isVersionCatalogFile(f.cite.file))
|
|
4104
|
+
add(f, checkCite(f.cite, [{ kind: "word", value: f.version }], `${label} version`, false));
|
|
4105
|
+
}
|
|
4106
|
+
}
|
|
2436
4107
|
if (f.kind === "flow") {
|
|
2437
4108
|
f.steps.forEach((s, i) => add(f, checkCite(s.cite, stepClaims(s.kind, s.cite.value), `${label} step ${i + 1}`)));
|
|
2438
4109
|
f.errors.forEach((e, i) => add(f, checkCite(e.cite, [routeOrWord(e.cite.value)], `${label} error ${i + 1}`)));
|
|
@@ -2478,11 +4149,17 @@ async function verifyFacts(o) {
|
|
|
2478
4149
|
}
|
|
2479
4150
|
const rejected = /* @__PURE__ */ new Map();
|
|
2480
4151
|
for (const f of facts) {
|
|
2481
|
-
|
|
4152
|
+
let ps = found.get(f.id);
|
|
2482
4153
|
if (!ps?.length)
|
|
2483
4154
|
continue;
|
|
2484
|
-
|
|
2485
|
-
|
|
4155
|
+
const isOther = other.has(f.id);
|
|
4156
|
+
const quiet = ps.some((p) => p.code === "secret-value") || quietFact(f, isOther ? void 0 : lineAt);
|
|
4157
|
+
ps = ps.map((p) => ({ ...p, message: sanitised(f, p.message, lineAt, quiet) }));
|
|
4158
|
+
const shown = isOther ? f.kind === "config" && configSecretField(f) || citesIn(f).some((c) => c.quote && lineSecrets(c.quote).length) ? withoutSecret(f) : f : shownFact(f, quiet, lineAt);
|
|
4159
|
+
if (isOther && shown !== f)
|
|
4160
|
+
asRead.set(shown, f);
|
|
4161
|
+
rejected.set(f.id, ps.length === 1 ? { fact: shown, ...ps[0] } : {
|
|
4162
|
+
fact: shown,
|
|
2486
4163
|
code: ps[0].code,
|
|
2487
4164
|
message: ps.map((p, i) => `(${i + 1}) ${p.message}`).join(" "),
|
|
2488
4165
|
problems: ps
|
|
@@ -2495,10 +4172,11 @@ async function verifyFacts(o) {
|
|
|
2495
4172
|
continue;
|
|
2496
4173
|
const r = refsOf(f).find((x) => rejected.has(x.id));
|
|
2497
4174
|
if (r) {
|
|
4175
|
+
const quiet = quietFact(f, lineAt);
|
|
2498
4176
|
rejected.set(f.id, {
|
|
2499
|
-
fact: f,
|
|
4177
|
+
fact: shownFact(f, quiet, lineAt),
|
|
2500
4178
|
code: "ref-rejected",
|
|
2501
|
-
message: `${f.kind} ${f.id} names ${r.field} "${r.id}", which was rejected (${rejected.get(r.id).code})
|
|
4179
|
+
message: sanitised(f, `${f.kind} ${f.id} names ${r.field} "${r.id}", which was rejected (${rejected.get(r.id).code})`, lineAt, quiet)
|
|
2502
4180
|
});
|
|
2503
4181
|
changed = true;
|
|
2504
4182
|
}
|
|
@@ -2532,7 +4210,13 @@ async function verifyFacts(o) {
|
|
|
2532
4210
|
const accepted = facts.filter((f) => !rejected.has(f.id)).map((f) => {
|
|
2533
4211
|
o.room?.();
|
|
2534
4212
|
const verified = f.by === "person" && f.verified !== "none" ? f.verified : "line";
|
|
2535
|
-
const
|
|
4213
|
+
const module = moduleOf.get(f.id);
|
|
4214
|
+
const base2 = {
|
|
4215
|
+
...f,
|
|
4216
|
+
...module !== void 0 ? { component: module } : {},
|
|
4217
|
+
verified,
|
|
4218
|
+
cite: fixQuote(f.cite)
|
|
4219
|
+
};
|
|
2536
4220
|
if (base2.kind === "entry" && base2.auth !== void 0 && !base2.authCite && f.by !== "person")
|
|
2537
4221
|
authUncited.push({
|
|
2538
4222
|
id: base2.id,
|
|
@@ -2553,17 +4237,41 @@ async function verifyFacts(o) {
|
|
|
2553
4237
|
const excludeRes = (o.exclude ?? []).map(globToRegExp);
|
|
2554
4238
|
const sources = [];
|
|
2555
4239
|
const excluded = [];
|
|
4240
|
+
const secrets = [];
|
|
2556
4241
|
for (const p of o.source.list()) {
|
|
2557
4242
|
o.room?.();
|
|
2558
|
-
if (
|
|
4243
|
+
if (isSecretPath(p)) {
|
|
4244
|
+
if (insideRepo(p) && isConfigFile(p) && !testFileOf(rules, p) && !tooBigToRead(o.source, p)) {
|
|
4245
|
+
const text = o.source.read(p);
|
|
4246
|
+
const ls2 = text === void 0 ? void 0 : text.replace(/\r\n?/g, "\n").split("\n");
|
|
4247
|
+
if (ls2 && !binaryLines(ls2))
|
|
4248
|
+
secrets.push(...liveSecretsIn(p, ls2));
|
|
4249
|
+
}
|
|
4250
|
+
continue;
|
|
4251
|
+
}
|
|
4252
|
+
const scanOnly = () => {
|
|
4253
|
+
if (!insideRepo(p) || !isConfigFile(p) || LOCKFILE.test(p) || testFileOf(rules, p) || tooBigToRead(o.source, p))
|
|
4254
|
+
return;
|
|
4255
|
+
const ls2 = readLines(p);
|
|
4256
|
+
if (ls2 && !binaryLines(ls2))
|
|
4257
|
+
secrets.push(...liveSecretsIn(p, ls2));
|
|
4258
|
+
};
|
|
4259
|
+
if (!isSourceFile(p, "", void 0, rules) || tooBigToRead(o.source, p)) {
|
|
4260
|
+
scanOnly();
|
|
2559
4261
|
continue;
|
|
4262
|
+
}
|
|
2560
4263
|
const ls = readLines(p) ?? [""];
|
|
2561
|
-
if (!isSourceFile(p, ls[0] ?? "", ls, rules))
|
|
4264
|
+
if (!isSourceFile(p, ls[0] ?? "", ls, rules)) {
|
|
4265
|
+
if (isConfigFile(p) && !LOCKFILE.test(p) && !testFileOf(rules, p) && !binaryLines(ls))
|
|
4266
|
+
secrets.push(...liveSecretsIn(p, ls));
|
|
2562
4267
|
continue;
|
|
4268
|
+
}
|
|
2563
4269
|
if (excludeRes.some((re) => re.test(p)))
|
|
2564
4270
|
excluded.push(p);
|
|
2565
|
-
else
|
|
4271
|
+
else {
|
|
2566
4272
|
sources.push(p);
|
|
4273
|
+
secrets.push(...liveSecretsIn(p, ls));
|
|
4274
|
+
}
|
|
2567
4275
|
}
|
|
2568
4276
|
const touched = new Set(o.routed ?? []);
|
|
2569
4277
|
for (const f of accepted)
|
|
@@ -2664,6 +4372,14 @@ async function verifyFacts(o) {
|
|
|
2664
4372
|
const held = files.flatMap(skippedIn);
|
|
2665
4373
|
return held.length ? [reviewedHoldsOf(entry, held)] : [];
|
|
2666
4374
|
});
|
|
4375
|
+
const namedPoms = [...touched].some((p) => isBuildFile(p)) ? pomFilesNamed(listed2(), linesOf2) : void 0;
|
|
4376
|
+
const placed = accepted.filter((f) => placedFrom.has(f.id)).map((f) => ({
|
|
4377
|
+
id: f.id,
|
|
4378
|
+
named: placedFrom.get(f.id),
|
|
4379
|
+
component: f.component,
|
|
4380
|
+
cite: `${f.cite.file}:${f.cite.line}`
|
|
4381
|
+
})).sort((a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0);
|
|
4382
|
+
const unrecorded = buildUnrecorded([...touched].filter((p) => isBuildFileIn(p, namedPoms) && insideRepo(p) && !isSecretPath(p)), (p) => linesOf2(p), accepted, listed2());
|
|
2667
4383
|
return {
|
|
2668
4384
|
accepted,
|
|
2669
4385
|
// a rejected fact goes back as it was read, at its own commit, even one that was carried
|
|
@@ -2677,6 +4393,7 @@ async function verifyFacts(o) {
|
|
|
2677
4393
|
ratio
|
|
2678
4394
|
},
|
|
2679
4395
|
redacted,
|
|
4396
|
+
secrets: secrets.sort((a, b) => a.file < b.file ? -1 : a.file > b.file ? 1 : a.line - b.line),
|
|
2680
4397
|
quotesDropped,
|
|
2681
4398
|
carried: accepted.flatMap((f) => carriedFrom.has(f.id) ? [{ id: f.id, from: carriedFrom.get(f.id) }] : []),
|
|
2682
4399
|
corrections: { applied: corrected.applied, stale: corrected.stale },
|
|
@@ -2689,12 +4406,14 @@ async function verifyFacts(o) {
|
|
|
2689
4406
|
skipped,
|
|
2690
4407
|
reviewedHolds,
|
|
2691
4408
|
specOpsUncovered,
|
|
2692
|
-
frameworkGaps: frameworkGaps(accepted, rules.frameworks)
|
|
4409
|
+
frameworkGaps: frameworkGaps(accepted, rules.frameworks),
|
|
4410
|
+
...unrecorded.length ? { buildUnrecorded: unrecorded } : {},
|
|
4411
|
+
...placed.length ? { componentsPlaced: placed } : {}
|
|
2693
4412
|
};
|
|
2694
4413
|
}
|
|
2695
4414
|
|
|
2696
4415
|
// packages/verify/dist/batches.js
|
|
2697
|
-
var BUILD = /(^|\/)(pom\.xml|build\.gradle(\.kts)?|settings\.gradle(\.kts)?|package\.json|go\.mod|Cargo\.toml|pyproject\.toml|setup\.py|requirements[^/]*\.txt|Gemfile|[^/]+\.gemspec|composer\.json|[^/]+\.(csproj|sln|tf|tfvars|bicep|hcl)|Dockerfile[^/]*|Containerfile|Jenkinsfile|Makefile|Procfile|(docker-)?compose[^/]*\.ya?ml|Chart\.yaml|values[^/]*\.ya?ml|azure-pipelines[^/]*\.ya?ml|\.gitlab-ci\.yml|bitbucket-pipelines\.yml|serverless\.ya?ml|template\.ya?ml|manifest\.ya?ml)$/;
|
|
4416
|
+
var BUILD = /(^|\/)(pom\.xml|[^/]+[-_.]pom\.xml|[^/]+\.pom|gradle\/[\w-]+\.versions\.toml|build\.gradle(\.kts)?|settings\.gradle(\.kts)?|package\.json|go\.mod|Cargo\.toml|pyproject\.toml|setup\.py|requirements[^/]*\.txt|Gemfile|[^/]+\.gemspec|composer\.json|[^/]+\.(csproj|sln|tf|tfvars|bicep|hcl)|Dockerfile[^/]*|Containerfile|Jenkinsfile|Makefile|Procfile|(docker-)?compose[^/]*\.ya?ml|Chart\.yaml|values[^/]*\.ya?ml|azure-pipelines[^/]*\.ya?ml|\.gitlab-ci\.yml|bitbucket-pipelines\.yml|serverless\.ya?ml|template\.ya?ml|manifest\.ya?ml)$/;
|
|
2698
4417
|
var DEPLOY_DIR = /(^|\/)(\.github\/workflows|\.circleci|k8s|kubernetes|helm|charts|deploy|deployment|deployments|manifests|infra|terraform|pipelines?)\//;
|
|
2699
4418
|
var CONFIG = /(^|\/)((application|bootstrap)[^/]*\.(ya?ml|properties)|appsettings[^/]*\.json|[^/]+\.(properties|conf|ini|toml)|web\.config|config\/[^/]+\.(ya?ml|json))$/;
|
|
2700
4419
|
var ENTRY_NAME = /(^|[._-])(main|app|application|server|program|startup|index|lambda|handler|function|cli)$|(controller|resource|router|routes?|handlers?|listener|consumer|subscriber|endpoints?|api|job|scheduler|worker|webhook|servlet|page|screen|view)$/i;
|
|
@@ -2953,7 +4672,7 @@ var BUILD_FILE = /^(pom\.xml|build\.gradle(\.kts)?|settings\.gradle(\.kts)?|pack
|
|
|
2953
4672
|
var AGGREGATOR = /^(pom\.xml|settings\.gradle(\.kts)?|package\.json|pnpm-workspace\.yaml|lerna\.json|Cargo\.toml|go\.work)$/;
|
|
2954
4673
|
var byPath = (a, b) => a < b ? -1 : a > b ? 1 : 0;
|
|
2955
4674
|
var nameOf = (path) => path.slice(path.lastIndexOf("/") + 1);
|
|
2956
|
-
var
|
|
4675
|
+
var dirOf2 = (path) => path.includes("/") ? path.slice(0, path.lastIndexOf("/")) : "";
|
|
2957
4676
|
var under = (path, dir) => !dir || path.startsWith(`${dir}/`);
|
|
2958
4677
|
var quoted = (s) => [...s.matchAll(/["']([^"'\n]+)["']/g)].map((m) => m[1]);
|
|
2959
4678
|
var clean = (m) => m.trim().replace(/^\.\//, "").replace(/\/pom\.xml$/, "").replace(/\/+$/, "");
|
|
@@ -2967,7 +4686,7 @@ function json(text) {
|
|
|
2967
4686
|
var strings = (v) => Array.isArray(v) ? v.filter((x) => typeof x === "string") : [];
|
|
2968
4687
|
function buildModules(path, text) {
|
|
2969
4688
|
const name = nameOf(path);
|
|
2970
|
-
const dir =
|
|
4689
|
+
const dir = dirOf2(path);
|
|
2971
4690
|
let found = [];
|
|
2972
4691
|
if (name === "pom.xml")
|
|
2973
4692
|
found = [...text.matchAll(/<module>\s*([^<]+?)\s*<\/module>/g)].map((m) => m[1]);
|
|
@@ -3023,11 +4742,11 @@ function packageRoots(paths, inits, read) {
|
|
|
3023
4742
|
let readCount = 0;
|
|
3024
4743
|
for (const p of paths) {
|
|
3025
4744
|
if (/\.py$/i.test(p)) {
|
|
3026
|
-
let d =
|
|
4745
|
+
let d = dirOf2(p);
|
|
3027
4746
|
let top;
|
|
3028
4747
|
while (d && inits.has(d)) {
|
|
3029
4748
|
top = d;
|
|
3030
|
-
d =
|
|
4749
|
+
d = dirOf2(d);
|
|
3031
4750
|
}
|
|
3032
4751
|
if (top)
|
|
3033
4752
|
roots.add(nameOf(top).toLowerCase());
|
|
@@ -3046,7 +4765,7 @@ function vendoredProjects(all2, read) {
|
|
|
3046
4765
|
const licenses = /* @__PURE__ */ new Map();
|
|
3047
4766
|
const builds = /* @__PURE__ */ new Map();
|
|
3048
4767
|
for (const p of files) {
|
|
3049
|
-
const d =
|
|
4768
|
+
const d = dirOf2(p);
|
|
3050
4769
|
if (LICENSE_FILE.test(nameOf(p)) && !licenses.has(d))
|
|
3051
4770
|
licenses.set(d, p);
|
|
3052
4771
|
if (BUILD_FILE.test(nameOf(p)))
|
|
@@ -3057,7 +4776,7 @@ function vendoredProjects(all2, read) {
|
|
|
3057
4776
|
for (const p of files)
|
|
3058
4777
|
if (AGGREGATOR.test(nameOf(p)))
|
|
3059
4778
|
for (const m of buildModules(p, read(p) ?? ""))
|
|
3060
|
-
modules.push({ from:
|
|
4779
|
+
modules.push({ from: dirOf2(p), re: globToRegExp(m) });
|
|
3061
4780
|
}
|
|
3062
4781
|
const included = (dir) => modules.some((m) => m.from !== dir && under(dir, m.from) && m.re.test(dir));
|
|
3063
4782
|
const nested = [];
|
|
@@ -3077,7 +4796,7 @@ function vendoredProjects(all2, read) {
|
|
|
3077
4796
|
}
|
|
3078
4797
|
const out = [...nested];
|
|
3079
4798
|
if (copied.length) {
|
|
3080
|
-
const inits = new Set(files.filter((p) => nameOf(p) === "__init__.py").map(
|
|
4799
|
+
const inits = new Set(files.filter((p) => nameOf(p) === "__init__.py").map(dirOf2));
|
|
3081
4800
|
const apart = [...copied, ...nested.map((n) => n.dir)];
|
|
3082
4801
|
const text = read ?? (() => void 0);
|
|
3083
4802
|
const mine = packageRoots(files.filter((p) => !apart.some((d) => under(p, d))), inits, text);
|
|
@@ -3238,11 +4957,11 @@ function unitsOf(dir, fs, room) {
|
|
|
3238
4957
|
const children = /* @__PURE__ */ new Map();
|
|
3239
4958
|
for (const f of fs) {
|
|
3240
4959
|
const rest = f.path.slice(prefix.length);
|
|
3241
|
-
const
|
|
3242
|
-
if (
|
|
4960
|
+
const slash2 = rest.indexOf("/");
|
|
4961
|
+
if (slash2 < 0)
|
|
3243
4962
|
direct.push(f);
|
|
3244
4963
|
else {
|
|
3245
|
-
const child = prefix + rest.slice(0,
|
|
4964
|
+
const child = prefix + rest.slice(0, slash2);
|
|
3246
4965
|
children.set(child, [...children.get(child) ?? [], f]);
|
|
3247
4966
|
}
|
|
3248
4967
|
}
|
|
@@ -3259,11 +4978,11 @@ function groupUnits(dir, fs, room, holds) {
|
|
|
3259
4978
|
const children = /* @__PURE__ */ new Map();
|
|
3260
4979
|
for (const f of fs) {
|
|
3261
4980
|
const rest = f.path.slice(prefix.length);
|
|
3262
|
-
const
|
|
3263
|
-
if (
|
|
4981
|
+
const slash2 = rest.indexOf("/");
|
|
4982
|
+
if (slash2 < 0)
|
|
3264
4983
|
direct.push(f);
|
|
3265
4984
|
else {
|
|
3266
|
-
const child = prefix + rest.slice(0,
|
|
4985
|
+
const child = prefix + rest.slice(0, slash2);
|
|
3267
4986
|
children.set(child, [...children.get(child) ?? [], f]);
|
|
3268
4987
|
}
|
|
3269
4988
|
}
|
|
@@ -3891,7 +5610,8 @@ function lineLegend(marks) {
|
|
|
3891
5610
|
}
|
|
3892
5611
|
return "modify";
|
|
3893
5612
|
}
|
|
3894
|
-
function changeView(records2, change, flows, known = []) {
|
|
5613
|
+
function changeView(records2, change, flows, known = [], retired = []) {
|
|
5614
|
+
const gone = new Set(retired);
|
|
3895
5615
|
const c = new Catalog(records2);
|
|
3896
5616
|
const inSpecs = new Set(known);
|
|
3897
5617
|
const isKnown = (id) => c.components.has(id) || c.isSystem(id) || inSpecs.has(id);
|
|
@@ -3928,6 +5648,9 @@ function changeView(records2, change, flows, known = []) {
|
|
|
3928
5648
|
}
|
|
3929
5649
|
}
|
|
3930
5650
|
}
|
|
5651
|
+
for (const id of gone)
|
|
5652
|
+
if (comps.has(id))
|
|
5653
|
+
legends.set(id, "retire");
|
|
3931
5654
|
const withMark = (id) => {
|
|
3932
5655
|
const l = legends.get(id);
|
|
3933
5656
|
return l ? { legend: l } : {};
|
|
@@ -4446,8 +6169,25 @@ var LENS_KINDS = {
|
|
|
4446
6169
|
infrastructure: /* @__PURE__ */ new Set(["estate", "system", "repo", "component", "deployment", "environment"])
|
|
4447
6170
|
};
|
|
4448
6171
|
var LENS_EDGES = {
|
|
4449
|
-
architecture: /* @__PURE__ */ new Set([
|
|
4450
|
-
|
|
6172
|
+
architecture: /* @__PURE__ */ new Set([
|
|
6173
|
+
"calls",
|
|
6174
|
+
"publishes",
|
|
6175
|
+
"subscribes",
|
|
6176
|
+
"uses",
|
|
6177
|
+
"depends-on",
|
|
6178
|
+
"reads",
|
|
6179
|
+
"writes"
|
|
6180
|
+
]),
|
|
6181
|
+
repo: /* @__PURE__ */ new Set([
|
|
6182
|
+
"calls",
|
|
6183
|
+
"publishes",
|
|
6184
|
+
"subscribes",
|
|
6185
|
+
"uses",
|
|
6186
|
+
"depends-on",
|
|
6187
|
+
"reads",
|
|
6188
|
+
"writes",
|
|
6189
|
+
"references"
|
|
6190
|
+
]),
|
|
4451
6191
|
data: /* @__PURE__ */ new Set(["reads", "writes", "references"]),
|
|
4452
6192
|
integration: /* @__PURE__ */ new Set(["calls", "publishes", "subscribes"]),
|
|
4453
6193
|
infrastructure: /* @__PURE__ */ new Set(["deployed-to"])
|
|
@@ -4510,30 +6250,71 @@ var HOW_OF_FLAG = {
|
|
|
4510
6250
|
"joined-by-name": "named",
|
|
4511
6251
|
"joined-by-repo": "repo",
|
|
4512
6252
|
"joined-by-host": "host",
|
|
6253
|
+
// beta.24: a call whose host nothing resolves, by the one proxy BasePath its path starts with.
|
|
6254
|
+
[JOINED_BY_BASE_PATH]: "base-path",
|
|
4513
6255
|
"declared-caller": "declared",
|
|
4514
6256
|
// ADR 0162 §6 (F8): a topic or queue the profile names as an outside system's: a person's word.
|
|
4515
6257
|
[DECLARED_TOPIC]: "declared",
|
|
4516
6258
|
// ADR 0160 (O3): answered by an entry of another team's shared map.
|
|
4517
6259
|
[JOINED_TO_SHARED_MAP]: "shared"
|
|
4518
6260
|
};
|
|
6261
|
+
var NOT_VERIFYING_FLAGS = /* @__PURE__ */ new Set([
|
|
6262
|
+
...JOIN_GUESS_FLAGS,
|
|
6263
|
+
JOINED_BY_PERSON,
|
|
6264
|
+
JOINED_BY_AI,
|
|
6265
|
+
JOINED_BY_PATH_OVERLAP
|
|
6266
|
+
]);
|
|
6267
|
+
var ALSO_OF_FLAG = {
|
|
6268
|
+
...HOW_OF_FLAG,
|
|
6269
|
+
[JOINED_BY_PATH_OVERLAP]: "path"
|
|
6270
|
+
};
|
|
4519
6271
|
function joinHow(i) {
|
|
4520
|
-
|
|
6272
|
+
const flags = i.flags ?? [];
|
|
6273
|
+
const topic = i.via === "event-bus" || i.via === "mq";
|
|
6274
|
+
if (i.confidence === "verified") {
|
|
6275
|
+
for (const f of flags)
|
|
6276
|
+
if (HOW_OF_FLAG[f] && !NOT_VERIFYING_FLAGS.has(f))
|
|
6277
|
+
return HOW_OF_FLAG[f];
|
|
6278
|
+
if (topic)
|
|
6279
|
+
return "topic";
|
|
6280
|
+
}
|
|
6281
|
+
for (const f of flags)
|
|
4521
6282
|
if (HOW_OF_FLAG[f])
|
|
4522
6283
|
return HOW_OF_FLAG[f];
|
|
4523
|
-
if (
|
|
6284
|
+
if (topic)
|
|
4524
6285
|
return "topic";
|
|
4525
6286
|
return "unknown";
|
|
4526
6287
|
}
|
|
6288
|
+
var GUESS_HOWS = new Set([...NOT_VERIFYING_FLAGS].map((f) => HOW_OF_FLAG[f]).filter(Boolean));
|
|
6289
|
+
function alsoOf(i, how) {
|
|
6290
|
+
if (i.confidence !== "verified" || GUESS_HOWS.has(how))
|
|
6291
|
+
return [];
|
|
6292
|
+
const flags = i.flags ?? [];
|
|
6293
|
+
const byBase = how !== "base-path" && flags.includes(JOINED_BY_BASE_PATH);
|
|
6294
|
+
return [
|
|
6295
|
+
...new Set(flags.flatMap((f) => {
|
|
6296
|
+
const also = byBase && f === JOINED_BY_PATH ? "base-path" : ALSO_OF_FLAG[f];
|
|
6297
|
+
return NOT_VERIFYING_FLAGS.has(f) && also && also !== how ? [also] : [];
|
|
6298
|
+
}))
|
|
6299
|
+
];
|
|
6300
|
+
}
|
|
4527
6301
|
function joinOf(i) {
|
|
4528
6302
|
const side = (s) => evidenceOf(i.evidence.filter((e) => e.side === s));
|
|
4529
6303
|
const sided = /* @__PURE__ */ new Set(["caller", "callee", "gateway"]);
|
|
6304
|
+
const how = joinHow(i);
|
|
6305
|
+
const also = alsoOf(i, how);
|
|
4530
6306
|
return {
|
|
4531
6307
|
interface: i.id,
|
|
4532
6308
|
from: i.from,
|
|
4533
6309
|
to: i.to,
|
|
4534
|
-
how
|
|
6310
|
+
how,
|
|
4535
6311
|
gateway: i.via === "gateway",
|
|
4536
|
-
verified:
|
|
6312
|
+
// A link is verified when one of its calls is (ADR 0135 section 5): its how is that call's,
|
|
6313
|
+
// and the guesses its other calls rest on are `also`, never the reason. One with no how but
|
|
6314
|
+
// a guess has no call that wasn't guessed to show, so it is never shown verified beside the
|
|
6315
|
+
// guess's words (beta.24).
|
|
6316
|
+
verified: i.confidence === "verified" && !GUESS_HOWS.has(how),
|
|
6317
|
+
...also.length ? { also } : {},
|
|
4537
6318
|
...i.method ? { method: i.method } : {},
|
|
4538
6319
|
...i.normalizedPath ? { path: i.normalizedPath } : {},
|
|
4539
6320
|
caller: side("caller"),
|
|
@@ -4565,12 +6346,12 @@ function sharedOf(i) {
|
|
|
4565
6346
|
}
|
|
4566
6347
|
};
|
|
4567
6348
|
}
|
|
4568
|
-
function mergeJoins(a, b) {
|
|
6349
|
+
function mergeJoins(a, b, cap = MAX_JOINS) {
|
|
4569
6350
|
const by = new Map(a.map((j) => [j.interface, j]));
|
|
4570
6351
|
for (const j of b)
|
|
4571
6352
|
if (!by.has(j.interface))
|
|
4572
6353
|
by.set(j.interface, j);
|
|
4573
|
-
return [...by.values()].sort((x, y) => x.interface < y.interface ? -1 : x.interface > y.interface ? 1 : 0).slice(0,
|
|
6354
|
+
return [...by.values()].sort((x, y) => x.interface < y.interface ? -1 : x.interface > y.interface ? 1 : 0).slice(0, cap);
|
|
4574
6355
|
}
|
|
4575
6356
|
var props = (o) => {
|
|
4576
6357
|
const out = {};
|
|
@@ -4586,7 +6367,50 @@ var props = (o) => {
|
|
|
4586
6367
|
return out;
|
|
4587
6368
|
};
|
|
4588
6369
|
var all = (rs, k) => rs.filter((r) => r.kind === k).sort((a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0);
|
|
4589
|
-
function
|
|
6370
|
+
function dependencyJoin(l) {
|
|
6371
|
+
const lines = (end) => end.lines.map((at) => ({ source: "code", repo: end.repo, at }));
|
|
6372
|
+
const facts = l.facts?.length ? l.facts : [l.from];
|
|
6373
|
+
const caller = [];
|
|
6374
|
+
for (const f of facts)
|
|
6375
|
+
for (const e of lines(f))
|
|
6376
|
+
if (!caller.some((x) => x.repo === e.repo && x.at === e.at))
|
|
6377
|
+
caller.push(e);
|
|
6378
|
+
const callee = [];
|
|
6379
|
+
for (const p of l.published?.length ? l.published : [l.to])
|
|
6380
|
+
for (const e of lines(p))
|
|
6381
|
+
if (!callee.some((x) => x.repo === e.repo && x.at === e.at))
|
|
6382
|
+
callee.push(e);
|
|
6383
|
+
return {
|
|
6384
|
+
interface: dependencyLinkId(l),
|
|
6385
|
+
from: l.from.component,
|
|
6386
|
+
to: l.to.component,
|
|
6387
|
+
how: "coordinates",
|
|
6388
|
+
gateway: false,
|
|
6389
|
+
// code at both ends, each claim checked on its line, and nobody had to guess
|
|
6390
|
+
verified: true,
|
|
6391
|
+
caller,
|
|
6392
|
+
callee,
|
|
6393
|
+
hops: [],
|
|
6394
|
+
other: [],
|
|
6395
|
+
dependency: {
|
|
6396
|
+
group: l.group,
|
|
6397
|
+
name: l.name,
|
|
6398
|
+
...l.version ? { version: l.version } : {},
|
|
6399
|
+
...l.scope ? { scope: l.scope } : {},
|
|
6400
|
+
facts: facts.map((f) => ({
|
|
6401
|
+
repo: f.repo,
|
|
6402
|
+
fact: f.fact,
|
|
6403
|
+
at: f.at,
|
|
6404
|
+
lines: f.lines,
|
|
6405
|
+
...f.group !== void 0 ? { group: f.group } : {},
|
|
6406
|
+
...f.name !== void 0 ? { name: f.name } : {},
|
|
6407
|
+
...f.version !== void 0 ? { version: f.version } : {},
|
|
6408
|
+
...f.scope !== void 0 ? { scope: f.scope } : {}
|
|
6409
|
+
}))
|
|
6410
|
+
}
|
|
6411
|
+
};
|
|
6412
|
+
}
|
|
6413
|
+
function buildEstate(records2, o = {}) {
|
|
4590
6414
|
const nodes = /* @__PURE__ */ new Map();
|
|
4591
6415
|
const atoms = [];
|
|
4592
6416
|
const add = (n) => {
|
|
@@ -4897,6 +6721,19 @@ function buildEstate(records2) {
|
|
|
4897
6721
|
evidence: evidenceOf(c.evidence),
|
|
4898
6722
|
gaps: recordGaps(c)
|
|
4899
6723
|
});
|
|
6724
|
+
for (const l of o.dependsOn ?? []) {
|
|
6725
|
+
if (!components.has(l.from.component) || !components.has(l.to.component))
|
|
6726
|
+
continue;
|
|
6727
|
+
const join2 = dependencyJoin(l);
|
|
6728
|
+
atoms.push({
|
|
6729
|
+
from: `component:${l.from.component}`,
|
|
6730
|
+
to: `component:${l.to.component}`,
|
|
6731
|
+
type: "depends-on",
|
|
6732
|
+
evidence: mergeEvidence(join2.caller.slice(0, 1), join2.callee.slice(0, 1)),
|
|
6733
|
+
gaps: [],
|
|
6734
|
+
join: join2
|
|
6735
|
+
});
|
|
6736
|
+
}
|
|
4900
6737
|
for (const t of tables) {
|
|
4901
6738
|
const ev = evidenceOf(t.evidence);
|
|
4902
6739
|
const part = (ref) => {
|
|
@@ -5049,7 +6886,7 @@ function need(est, lens, id) {
|
|
|
5049
6886
|
if (!est.visible.get(lens).has(id))
|
|
5050
6887
|
throw new NoSuchNode(`There is no node ${id} in the ${lens} lens.`);
|
|
5051
6888
|
}
|
|
5052
|
-
function merge(mapped) {
|
|
6889
|
+
function merge(mapped, cap = MAX_JOINS) {
|
|
5053
6890
|
const by = /* @__PURE__ */ new Map();
|
|
5054
6891
|
for (const { from, to, atom } of mapped) {
|
|
5055
6892
|
const id = `${atom.type}:${from}>${to}`;
|
|
@@ -5071,7 +6908,7 @@ function merge(mapped) {
|
|
|
5071
6908
|
continue;
|
|
5072
6909
|
}
|
|
5073
6910
|
if (atom.join)
|
|
5074
|
-
e.joins = mergeJoins(e.joins ?? [], [atom.join]);
|
|
6911
|
+
e.joins = mergeJoins(e.joins ?? [], [atom.join], cap);
|
|
5075
6912
|
e.count++;
|
|
5076
6913
|
if (atom.sync && e.sync !== atom.sync)
|
|
5077
6914
|
e.sync = "mixed";
|
|
@@ -5160,7 +6997,7 @@ function nodeView(est, id, o) {
|
|
|
5160
6997
|
continue;
|
|
5161
6998
|
mapped.push({ from, to, atom });
|
|
5162
6999
|
}
|
|
5163
|
-
let edges = merge(mapped);
|
|
7000
|
+
let edges = merge(mapped, o.everyJoin ? Infinity : MAX_JOINS);
|
|
5164
7001
|
let hidden = 0;
|
|
5165
7002
|
if (!o.all)
|
|
5166
7003
|
({ edges, hidden } = reduceUses(edges));
|
|
@@ -5205,7 +7042,7 @@ function focusView(est, id, o) {
|
|
|
5205
7042
|
node: toNode(est, lens, id),
|
|
5206
7043
|
path: ancestors(est, id).map((n) => toNode(est, lens, n)),
|
|
5207
7044
|
neighbours: [...near].sort().map((n) => toNode(est, lens, n)),
|
|
5208
|
-
edges: merge(ends.filter((e) => set.has(e.from) && set.has(e.to)))
|
|
7045
|
+
edges: merge(ends.filter((e) => set.has(e.from) && set.has(e.to)), o.everyJoin ? Infinity : MAX_JOINS)
|
|
5209
7046
|
};
|
|
5210
7047
|
}
|
|
5211
7048
|
|
|
@@ -6096,6 +7933,7 @@ function houseImportsUntaught(source, o) {
|
|
|
6096
7933
|
export {
|
|
6097
7934
|
insideRepo,
|
|
6098
7935
|
dirSource,
|
|
7936
|
+
isBuildFile,
|
|
6099
7937
|
correctionFor,
|
|
6100
7938
|
outsidePairingFor,
|
|
6101
7939
|
correctedFact,
|
|
@@ -6106,6 +7944,7 @@ export {
|
|
|
6106
7944
|
frameworkGaps,
|
|
6107
7945
|
frameworksToLearn,
|
|
6108
7946
|
readRulesOf,
|
|
7947
|
+
keyIsSecret,
|
|
6109
7948
|
lineRangeOf,
|
|
6110
7949
|
parseReviewed,
|
|
6111
7950
|
readingRank,
|
|
@@ -6118,6 +7957,7 @@ export {
|
|
|
6118
7957
|
isEntryPointFile,
|
|
6119
7958
|
NOT_REACHED_WHY,
|
|
6120
7959
|
reachableModels,
|
|
7960
|
+
factAsRead,
|
|
6121
7961
|
sameCommit,
|
|
6122
7962
|
staleMessage,
|
|
6123
7963
|
verifyFacts,
|