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