@maycombhq/atticus 2.0.0-beta.10 → 2.0.0-beta.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +3 -3
- package/dist/{chunk-AY2IUF4K.js → chunk-22GLUHGE.js} +659 -73
- package/dist/{chunk-CIUHAHM6.js → chunk-2A24BNRZ.js} +8 -8
- package/dist/{chunk-2RX7PI2Y.js → chunk-2ELFEKOO.js} +4 -4
- package/dist/{chunk-QKEFZRHS.js → chunk-2P6IHSRO.js} +17 -17
- package/dist/chunk-2Q2YBAR5.js +40 -0
- package/dist/{chunk-7DUDLVFJ.js → chunk-2VQLFNBO.js} +20 -20
- package/dist/{chunk-E3Z67HRK.js → chunk-3256EDLL.js} +4 -4
- package/dist/{chunk-OIU657QQ.js → chunk-34BCKMBS.js} +4 -4
- package/dist/{chunk-UR7RMZ3R.js → chunk-34NWVIBC.js} +2 -2
- package/dist/{chunk-6VBXAGJX.js → chunk-36KD4OGC.js} +14 -14
- package/dist/{chunk-I7IWQIEB.js → chunk-3CFBU2O6.js} +4 -4
- package/dist/{chunk-OSGQW2Z6.js → chunk-3JLTN3Y7.js} +8 -8
- package/dist/{chunk-FOGG4AUR.js → chunk-3M7QBKKG.js} +25 -7
- package/dist/{chunk-UF7TAFJM.js → chunk-3RP34PYV.js} +18 -18
- package/dist/{chunk-YLAJAI2W.js → chunk-3ZKLWM5Y.js} +11 -11
- package/dist/{chunk-LTQANUDH.js → chunk-47HPZ34V.js} +25 -25
- package/dist/chunk-4BPROPGG.js +45 -0
- package/dist/{chunk-Y4BRGOJR.js → chunk-4G56W6H7.js} +13 -10
- package/dist/{chunk-YXJ4XOHF.js → chunk-4HIQ2FTI.js} +4 -4
- package/dist/{chunk-AJJK7GLO.js → chunk-4HTILEXW.js} +3 -3
- package/dist/{chunk-OJLRFGBP.js → chunk-4Q2PGM5T.js} +78 -15
- package/dist/{chunk-GR6YKM55.js → chunk-4RDW2X43.js} +108 -14
- package/dist/{chunk-23M2LUYM.js → chunk-4VOG5H2K.js} +1 -1
- package/dist/chunk-5CSZTVXH.js +34 -0
- package/dist/{chunk-65C57N7P.js → chunk-5FFMJMVH.js} +19 -19
- package/dist/{chunk-XNYNEEBR.js → chunk-5GGGAI5C.js} +18 -18
- package/dist/{chunk-IUD3ME4E.js → chunk-5H46QFSL.js} +4 -4
- package/dist/{chunk-KIHOIVST.js → chunk-5ION6STH.js} +3 -3
- package/dist/chunk-5M3CLAOV.js +39 -0
- package/dist/chunk-5OACMWWI.js +886 -0
- package/dist/{chunk-2HMWX4T6.js → chunk-6ENDKY52.js} +11 -11
- package/dist/{chunk-OS7PQ35Z.js → chunk-6FG7QKJC.js} +22 -22
- package/dist/{chunk-FEZE6NIA.js → chunk-6JV3YHRR.js} +18 -18
- package/dist/{chunk-WGZWR4RF.js → chunk-6ROZRBWH.js} +5 -5
- package/dist/{chunk-WARBF2KY.js → chunk-6S27MUQQ.js} +10 -6
- package/dist/{chunk-TZDSDDSV.js → chunk-72DY5NCN.js} +2 -2
- package/dist/chunk-76QVBNEM.js +37 -0
- package/dist/{chunk-N4QZJJVB.js → chunk-77UOXZVM.js} +5 -5
- package/dist/{chunk-LVGBKKSM.js → chunk-7AXMUE2U.js} +15 -15
- package/dist/{chunk-FJCFYKVO.js → chunk-7TEQF64E.js} +196 -76
- package/dist/{chunk-IDGSU7JF.js → chunk-7TH6I6TL.js} +9 -9
- package/dist/{chunk-ZONE6E3Z.js → chunk-7UKETVPW.js} +2 -2
- package/dist/{chunk-XKS6THI5.js → chunk-7VNEDDCC.js} +2 -2
- package/dist/{chunk-BMHGA7WD.js → chunk-A5GY2EWH.js} +12 -12
- package/dist/{chunk-E3JYO547.js → chunk-AEZ3EICK.js} +20 -20
- package/dist/{chunk-7F2RUWPU.js → chunk-ARLH2ZMD.js} +1 -1
- package/dist/{chunk-VKMTFIWS.js → chunk-AYVLEB55.js} +18 -18
- package/dist/chunk-B6X5PJSA.js +320 -0
- package/dist/{chunk-JMSEEBN4.js → chunk-BRCDEGNE.js} +1 -1
- package/dist/{chunk-67J3VZBA.js → chunk-BSVTNNUK.js} +5 -5
- package/dist/{chunk-3GTZ2OON.js → chunk-BTOGAUWX.js} +20 -11
- package/dist/{chunk-4SVJNVEE.js → chunk-BXBCMGIQ.js} +2 -0
- package/dist/chunk-BXP2Q4TD.js +48 -0
- package/dist/{chunk-XPEEICAO.js → chunk-BZRWJUB4.js} +15 -15
- package/dist/{chunk-MH5OCRUM.js → chunk-CH6LUQLD.js} +2 -2
- package/dist/{chunk-T6USVBEJ.js → chunk-CIIRPLI6.js} +5 -5
- package/dist/chunk-CJXM6SG4.js +339 -0
- package/dist/{chunk-5XDNUJ4P.js → chunk-CQD26SMZ.js} +4 -2
- package/dist/{chunk-7TGYNOXD.js → chunk-CW5SEPUT.js} +7 -7
- package/dist/{chunk-5KTOPOEP.js → chunk-CWSZP2LU.js} +25 -25
- package/dist/chunk-CXK27ZUY.js +32 -0
- package/dist/{chunk-YGKYFMSL.js → chunk-CXY4YDXS.js} +3 -3
- package/dist/{chunk-R64GLVBO.js → chunk-DDZZXVQ5.js} +10 -10
- package/dist/{chunk-7YYEKTYF.js → chunk-DGZXJO5I.js} +8 -8
- package/dist/{chunk-IV7BCWWN.js → chunk-DONCF2XC.js} +3 -3
- package/dist/{chunk-RRVT4MPS.js → chunk-DPNCAFMB.js} +18 -18
- package/dist/{chunk-UBWCUP3G.js → chunk-DQKNOHUZ.js} +2 -2
- package/dist/{chunk-NGPU2ARF.js → chunk-DW4BM73R.js} +1 -1
- package/dist/{chunk-PEF5OEMB.js → chunk-DWN7RSNQ.js} +4 -4
- package/dist/{chunk-KC5DROFC.js → chunk-DWYPYVPJ.js} +14 -14
- package/dist/{chunk-B7434AE2.js → chunk-E73QLYK7.js} +24 -3
- package/dist/{chunk-EX6ZXS5K.js → chunk-EE3UNC44.js} +4 -4
- package/dist/chunk-EJDZEK22.js +53 -0
- package/dist/{chunk-ISNZYKAS.js → chunk-ENZWVTTN.js} +21 -21
- package/dist/{chunk-ROTY5J2L.js → chunk-EREL3TQG.js} +1 -1
- package/dist/{chunk-ZZXF6OOJ.js → chunk-ESGIBN3S.js} +2 -2
- package/dist/{chunk-YGR6OCHQ.js → chunk-EU7VTBAI.js} +8 -14
- package/dist/chunk-F5GA6G3U.js +48 -0
- package/dist/{chunk-JAA53T23.js → chunk-F6FGIYPT.js} +20 -20
- package/dist/{chunk-NPCD54I7.js → chunk-FAET4BB6.js} +8 -5
- package/dist/{chunk-YPBQNJHA.js → chunk-FBFSTYAB.js} +8 -8
- package/dist/{chunk-OEI7LVRP.js → chunk-FEBYMFZA.js} +24 -24
- package/dist/chunk-FMV6IZ3P.js +54 -0
- package/dist/{chunk-F7UQR4ZX.js → chunk-FQ6IBYFC.js} +3 -3
- package/dist/{chunk-J5LHDJU4.js → chunk-FSJMFPA3.js} +7 -7
- package/dist/chunk-GFZ5MIQG.js +47 -0
- package/dist/{chunk-LK44ULGI.js → chunk-GHSVJNVL.js} +104 -11
- package/dist/{chunk-LRS573EX.js → chunk-GKPOCUQR.js} +12 -7
- package/dist/{chunk-LDKUC2QJ.js → chunk-GLSNVC67.js} +17 -17
- package/dist/{chunk-47QE246J.js → chunk-GMDOXWIS.js} +5 -5
- package/dist/{chunk-5MI2SEV5.js → chunk-GN5ZLSLD.js} +3 -3
- package/dist/{chunk-JQ7XQPQS.js → chunk-GUNBOZ75.js} +4 -4
- package/dist/{chunk-HHUFVJF7.js → chunk-GYS64N6F.js} +6 -6
- package/dist/{chunk-AKJTKMXU.js → chunk-HIQWJ6JZ.js} +5 -5
- package/dist/{chunk-6GNS32SI.js → chunk-HJ52XDST.js} +4 -4
- package/dist/{chunk-2KDSXJFJ.js → chunk-HJUEQERG.js} +34 -7
- package/dist/chunk-HKGQUOQ3.js +88 -0
- package/dist/chunk-HP32HUWR.js +41 -0
- package/dist/{chunk-R4TBNKKC.js → chunk-HY2VVVFZ.js} +1249 -610
- package/dist/{chunk-G5SFOH7P.js → chunk-I2PNEG3M.js} +38 -23
- package/dist/{chunk-Y5PZHS4K.js → chunk-INCECZ2E.js} +5 -5
- package/dist/{chunk-RK6MKKKP.js → chunk-ISXNWUG7.js} +1 -1
- package/dist/{chunk-73VPWF5R.js → chunk-ITJ7ST5E.js} +4 -4
- package/dist/{chunk-5IALSMZ2.js → chunk-J3VAFDEX.js} +14 -14
- package/dist/chunk-JGLZUQVN.js +29 -0
- package/dist/{chunk-5XN76FTF.js → chunk-JLIEAQP4.js} +5 -5
- package/dist/{chunk-MGVYVW7Q.js → chunk-JQG4VO47.js} +1 -1
- package/dist/chunk-JXXQHETS.js +130 -0
- package/dist/{chunk-APSVL2AI.js → chunk-KNGESBFW.js} +15 -15
- package/dist/{chunk-7UKVYFQ2.js → chunk-KUYA2E7M.js} +8 -8
- package/dist/{chunk-WLIIQ2A4.js → chunk-KY2ZHTBJ.js} +7 -7
- package/dist/{chunk-YPIEYQF4.js → chunk-L4UIKAWD.js} +6 -6
- package/dist/chunk-LDUJ6NIT.js +247 -0
- package/dist/{chunk-5YIBJXGB.js → chunk-LTLR4JZJ.js} +10 -10
- package/dist/{chunk-IZNSAEBX.js → chunk-MFRPLAOH.js} +2 -2
- package/dist/{chunk-6GWHKMQR.js → chunk-MH7UBG47.js} +4 -4
- package/dist/{chunk-4GZXS6S2.js → chunk-MLAACAES.js} +278 -17
- package/dist/{chunk-D3PO4DOZ.js → chunk-MMB2OHUY.js} +4 -2
- package/dist/{chunk-DDAHCPGA.js → chunk-MNCQ2GL7.js} +12 -12
- package/dist/{chunk-UYYN2IUZ.js → chunk-MNUZX67F.js} +6 -6
- package/dist/{chunk-YFSSNGLR.js → chunk-MQHYCS6A.js} +32 -29
- package/dist/{chunk-MKRBG5EF.js → chunk-MRLCNXXR.js} +1 -1
- package/dist/{chunk-BUYJL3GJ.js → chunk-NBQO75XT.js} +1 -1
- package/dist/{chunk-GXJVY6WT.js → chunk-NCONDPHH.js} +5 -5
- package/dist/{chunk-ZP4FJHR4.js → chunk-NHS55U7T.js} +18 -18
- package/dist/{chunk-CRE4BJHM.js → chunk-NL6XQZSV.js} +23 -23
- package/dist/{chunk-YVLMBAYE.js → chunk-NSJ6ZR2A.js} +3 -3
- package/dist/{chunk-XRO65C7V.js → chunk-NTNJNRHW.js} +8 -6
- package/dist/{chunk-FTV6I76U.js → chunk-NTTXTLCQ.js} +25 -25
- package/dist/chunk-NWL7XEQ4.js +37 -0
- package/dist/{chunk-CNKGYDMG.js → chunk-NWXY3B4R.js} +23 -23
- package/dist/{chunk-52R2YXP5.js → chunk-O5W4ECUY.js} +16 -16
- package/dist/{chunk-OGRWQ562.js → chunk-O6ILVBYB.js} +2 -2
- package/dist/{chunk-BJPMKJTL.js → chunk-OJAJXU65.js} +102 -2
- package/dist/{chunk-FZL2HNWP.js → chunk-OMH3I5BH.js} +3 -3
- package/dist/{chunk-MF7QH4AX.js → chunk-P6UJ22XR.js} +5 -5
- package/dist/{chunk-HE4ZQXZM.js → chunk-P76AW3PA.js} +309 -15
- package/dist/{chunk-GZ4TKR3Q.js → chunk-PCCPXWJC.js} +48 -139
- package/dist/{chunk-6TJCUYC5.js → chunk-PGFRXGHA.js} +3 -3
- package/dist/{chunk-NIXVDQVO.js → chunk-PJRMMWU4.js} +2 -2
- package/dist/{chunk-X4W4XXWP.js → chunk-PKJ3K3GM.js} +5 -5
- package/dist/{chunk-KM2FBM3T.js → chunk-PVW2N63M.js} +302 -55
- package/dist/{chunk-Y7KBQ4BD.js → chunk-Q55UP5EZ.js} +22 -22
- package/dist/{chunk-7URGP4DD.js → chunk-QAFMLBPF.js} +12 -12
- package/dist/{chunk-KIAI6PWL.js → chunk-QEZSA2O7.js} +17 -17
- package/dist/{chunk-PKCMRPPB.js → chunk-QJ3OX7OC.js} +33 -27
- package/dist/{chunk-6EDQE7GO.js → chunk-QL4VNY4U.js} +2 -2
- package/dist/{chunk-6JLPXDWN.js → chunk-QR65C3DV.js} +5 -5
- package/dist/{chunk-ILFKECGI.js → chunk-QXGOEP44.js} +4 -4
- package/dist/chunk-QY7RGTUP.js +326 -0
- package/dist/{chunk-PGKHJYOB.js → chunk-RA64IK43.js} +1 -1
- package/dist/{chunk-XB5RFZHH.js → chunk-RLJDYLID.js} +12 -12
- package/dist/{chunk-AWECWW5Y.js → chunk-RMLUZYEA.js} +13 -11
- package/dist/chunk-RSVBX6A3.js +54 -0
- package/dist/chunk-RZWZO2JQ.js +42 -0
- package/dist/chunk-S5LSDXV4.js +40 -0
- package/dist/{chunk-TM7LC37P.js → chunk-SAC6FNKR.js} +181 -117
- package/dist/{chunk-DPHCFZ7W.js → chunk-SCBU46AJ.js} +3 -3
- package/dist/{chunk-EZIUFEN6.js → chunk-SGNHNN3G.js} +12 -12
- package/dist/{chunk-XKZHAD6Y.js → chunk-SHAAGH3T.js} +15 -15
- package/dist/chunk-SK5OYWIY.js +122 -0
- package/dist/{chunk-FR7JPYBD.js → chunk-SNSFQ47W.js} +12 -12
- package/dist/{chunk-FV5YFR6I.js → chunk-SSL6JMPA.js} +9 -9
- package/dist/{chunk-XEG3FE2R.js → chunk-TA2ZNDYD.js} +1 -1
- package/dist/{chunk-JF2NSTFO.js → chunk-TEHH47TG.js} +3 -3
- package/dist/{chunk-W5OYJMBT.js → chunk-TEZSZ24W.js} +5 -5
- package/dist/{chunk-SS66Q4VE.js → chunk-TH526O6E.js} +12 -12
- package/dist/{chunk-R6B6XAKK.js → chunk-TIAPEYWI.js} +4 -4
- package/dist/chunk-TLCRIAU3.js +44 -0
- package/dist/{chunk-FMKKVWZD.js → chunk-TQYBXDVH.js} +2 -2
- package/dist/chunk-TV4CGNEY.js +43 -0
- package/dist/{chunk-QICFHVRW.js → chunk-TVSNWIAM.js} +8 -6
- package/dist/{chunk-CHC5FKTU.js → chunk-TWHZU36X.js} +1 -1
- package/dist/{chunk-BMCKL3VQ.js → chunk-TXV2AYZB.js} +24 -24
- package/dist/{chunk-577AJVRS.js → chunk-U25OX22K.js} +2039 -289
- package/dist/{chunk-7EKESFWV.js → chunk-U4NNG3ES.js} +11 -11
- package/dist/{chunk-XQ3YIV5R.js → chunk-U5T4A2QV.js} +6 -6
- package/dist/{chunk-2XM6PYQQ.js → chunk-UT5OA7KA.js} +43 -11
- package/dist/{chunk-BXIX7S7O.js → chunk-V3VCUSQ6.js} +15 -15
- package/dist/{chunk-4QUQEBFT.js → chunk-V5XV3JSP.js} +6 -6
- package/dist/{chunk-F7YL2RZ4.js → chunk-VF4VOPMB.js} +23 -23
- package/dist/{chunk-3QAKDIEU.js → chunk-VLDM4QZM.js} +23 -23
- package/dist/chunk-VP5H6DII.js +34 -0
- package/dist/{chunk-N3NBWIYQ.js → chunk-VRYQJZFL.js} +10 -9
- package/dist/{chunk-FQSRHTTC.js → chunk-VS6FS472.js} +15 -15
- package/dist/{chunk-YMOJD5BO.js → chunk-VTMIRRIZ.js} +3 -3
- package/dist/{chunk-4PJADZRR.js → chunk-VXSJKWB7.js} +16 -16
- package/dist/{chunk-MTAUZW2Z.js → chunk-WE5VMPUP.js} +216 -106
- package/dist/{chunk-ZE3P35DA.js → chunk-WEG7DY5K.js} +9 -9
- package/dist/{chunk-V2TH46ZY.js → chunk-WIF7A6JU.js} +12 -12
- package/dist/{chunk-GFXLPJWY.js → chunk-WM4N2L4T.js} +2 -2
- package/dist/{chunk-XIWYUQZQ.js → chunk-X64BFQ3R.js} +9 -9
- package/dist/{chunk-QWVBEK4P.js → chunk-XJRC3ZDI.js} +13 -13
- package/dist/{chunk-F2FOQLJ7.js → chunk-XVIVWG7B.js} +6 -6
- package/dist/{chunk-XTVDAHH2.js → chunk-Y3ZKT6IF.js} +5 -5
- package/dist/{chunk-62YMDXY6.js → chunk-YURIUFKF.js} +16 -16
- package/dist/{chunk-HKTUIMH4.js → chunk-YY2WGL6S.js} +3 -3
- package/dist/{chunk-BDEKREZH.js → chunk-Z2BA4NNR.js} +3 -3
- package/dist/{chunk-MTEBM4Y4.js → chunk-Z47YGBUY.js} +19 -12
- package/dist/chunk-Z4JSRKNR.js +41 -0
- package/dist/{chunk-G2E5MNYP.js → chunk-Z53ZB34U.js} +7 -7
- package/dist/{chunk-NNUASOAA.js → chunk-ZBOPIYOY.js} +12 -12
- package/dist/{chunk-7GB4ZRE2.js → chunk-ZBQCLKTH.js} +12 -12
- package/dist/chunk-ZGI7DNJ6.js +38 -0
- package/dist/{chunk-P3TKKBAH.js → chunk-ZPT4QX3J.js} +4 -4
- package/dist/chunk-ZS47PQ3O.js +41 -0
- package/dist/{chunk-PIVKU64W.js → chunk-ZTIMXVV5.js} +2 -2
- package/dist/{chunk-T4RTWMJD.js → chunk-ZYASEL7K.js} +5 -5
- package/dist/files.json +469 -417
- package/dist/packages/sdk/npm/index.js +2309 -1983
- package/dist/packages/ui/dist/assets/{elk-api-Mo5w5xCa.js → elk-api-D2NcYpUJ.js} +2 -2
- package/dist/packages/ui/dist/assets/{index-Bp3XhPHX.css → index-C0JEkXyN.css} +1 -1
- package/dist/packages/ui/dist/assets/index-CT7skl01.js +29 -0
- package/dist/packages/ui/dist/index.html +2 -2
- package/package.json +4 -4
- package/dist/chunk-26PLPSQW.js +0 -48
- package/dist/chunk-2G4DFUWJ.js +0 -43
- package/dist/chunk-2M6WXO73.js +0 -38
- package/dist/chunk-5F3RJCHB.js +0 -45
- package/dist/chunk-B2VSVN4P.js +0 -34
- package/dist/chunk-B3O52AUQ.js +0 -275
- package/dist/chunk-CITDNDIZ.js +0 -53
- package/dist/chunk-DAQBIK5G.js +0 -47
- package/dist/chunk-DZRQDNPT.js +0 -34
- package/dist/chunk-FLOEZA6K.js +0 -29
- package/dist/chunk-FNHSVBRA.js +0 -48
- package/dist/chunk-FPGVOSOG.js +0 -41
- package/dist/chunk-FZ2E5LGK.js +0 -54
- package/dist/chunk-HB6XSGI6.js +0 -131
- package/dist/chunk-HUZQDKQK.js +0 -48
- package/dist/chunk-L4VJ4ETL.js +0 -41
- package/dist/chunk-XPCWQXTY.js +0 -37
- package/dist/chunk-YIEOFHOL.js +0 -30
- package/dist/packages/ui/dist/assets/index-DM212ZbV.js +0 -29
|
@@ -7,18 +7,18 @@ import {
|
|
|
7
7
|
featuresForScan,
|
|
8
8
|
namingHint,
|
|
9
9
|
syncSources
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-QR65C3DV.js";
|
|
11
11
|
import {
|
|
12
12
|
dirSource,
|
|
13
13
|
sameCommit,
|
|
14
14
|
verifyFacts
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-MLAACAES.js";
|
|
16
16
|
import {
|
|
17
17
|
scanInputs
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-HY2VVVFZ.js";
|
|
19
19
|
import {
|
|
20
20
|
listIngestors
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-PJRMMWU4.js";
|
|
22
22
|
import {
|
|
23
23
|
BUILT_IN_EXTRACTORS,
|
|
24
24
|
MODEL_READERS,
|
|
@@ -33,12 +33,12 @@ import {
|
|
|
33
33
|
runDialectTests,
|
|
34
34
|
runFrameworkTests,
|
|
35
35
|
unmodelledFrameworks
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-34NWVIBC.js";
|
|
37
37
|
import {
|
|
38
38
|
baseClonePath,
|
|
39
39
|
changesSince,
|
|
40
40
|
checkoutState
|
|
41
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-RA64IK43.js";
|
|
42
42
|
import {
|
|
43
43
|
DEFAULT_IGNORES,
|
|
44
44
|
configHash,
|
|
@@ -50,11 +50,11 @@ import {
|
|
|
50
50
|
sandboxedExtractor,
|
|
51
51
|
scanRepo,
|
|
52
52
|
withParseCache
|
|
53
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-MRLCNXXR.js";
|
|
54
54
|
import {
|
|
55
55
|
buildContextPack,
|
|
56
56
|
toRunSummary
|
|
57
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-CQD26SMZ.js";
|
|
58
58
|
import {
|
|
59
59
|
AgentDefinition,
|
|
60
60
|
DECLARED_CALLER,
|
|
@@ -69,8 +69,11 @@ import {
|
|
|
69
69
|
REPO_TYPE_SCHEMA_VERSION,
|
|
70
70
|
RecordId,
|
|
71
71
|
SCAN_SETTINGS_SCHEMA_VERSION,
|
|
72
|
+
TARGETS_ANOTHER_LABEL,
|
|
72
73
|
TARGETS_SPLIT_LABEL,
|
|
73
74
|
TARGETS_STEP_ID,
|
|
75
|
+
TOPICS_OUTSIDE_LABEL,
|
|
76
|
+
TOPICS_STEP_ID,
|
|
74
77
|
applyCurated,
|
|
75
78
|
applyLinkEvidence,
|
|
76
79
|
applySharedMaps,
|
|
@@ -101,6 +104,7 @@ import {
|
|
|
101
104
|
joinGuessesOf,
|
|
102
105
|
joinRecords,
|
|
103
106
|
joinSharedMaps,
|
|
107
|
+
joinTerms,
|
|
104
108
|
lineNamesField,
|
|
105
109
|
lineNamesRoute,
|
|
106
110
|
lineNamesWord,
|
|
@@ -126,14 +130,16 @@ import {
|
|
|
126
130
|
stackHelpersOff,
|
|
127
131
|
stripLinkEvidence,
|
|
128
132
|
stripSharedMaps,
|
|
133
|
+
termGrantRecords,
|
|
129
134
|
throwIfCancelled,
|
|
130
135
|
toCanonicalYaml,
|
|
136
|
+
topicQuestionText,
|
|
131
137
|
urlHostPort
|
|
132
|
-
} from "./chunk-
|
|
138
|
+
} from "./chunk-U25OX22K.js";
|
|
133
139
|
import {
|
|
134
140
|
SCHEMA_VERSION,
|
|
135
141
|
writeFileAtomic
|
|
136
|
-
} from "./chunk-
|
|
142
|
+
} from "./chunk-MMB2OHUY.js";
|
|
137
143
|
import {
|
|
138
144
|
__toESM
|
|
139
145
|
} from "./chunk-TV45EUGM.js";
|
|
@@ -1484,6 +1490,332 @@ import { join as join6 } from "node:path";
|
|
|
1484
1490
|
|
|
1485
1491
|
// packages/scanner/dist/facts-catalog.js
|
|
1486
1492
|
import { createHash as createHash2 } from "node:crypto";
|
|
1493
|
+
|
|
1494
|
+
// packages/scanner/dist/target-suggest.js
|
|
1495
|
+
var TARGETS_MAX_SUGGESTED = 5;
|
|
1496
|
+
var TARGETS_ANOTHER = TARGETS_ANOTHER_LABEL;
|
|
1497
|
+
var TARGETS_NO_EVIDENCE = "no evidence; listed so you can pick it";
|
|
1498
|
+
var STOP = new Set("url uri base host client clients service services svc api apis http https rest endpoint endpoints impl java kt ts js py cs go src main test get post put delete patch the and for com www internal example config configs properties yaml yml env app apps application new call calls feign template web request requests response gateway proxy remote adapter port".split(" "));
|
|
1499
|
+
function nameWords(s) {
|
|
1500
|
+
if (!s)
|
|
1501
|
+
return [];
|
|
1502
|
+
return [
|
|
1503
|
+
...new Set(s.replace(/([a-z0-9])([A-Z])/g, "$1 $2").toLowerCase().split(/[^a-z0-9]+/).filter((w) => w.length >= 3 && !STOP.has(w) && !/^v?\d+$/.test(w)).map((w) => w.length > 4 && w.endsWith("s") && !w.endsWith("ss") ? w.slice(0, -1) : w))
|
|
1504
|
+
];
|
|
1505
|
+
}
|
|
1506
|
+
var segs = (p) => p.split(/[?#]/)[0].split("/").filter(Boolean).map((x) => /^[{:<$]/.test(x) ? "{}" : x);
|
|
1507
|
+
var sameSeg = (a, b) => a === "{}" || b === "{}" || a === b;
|
|
1508
|
+
var under = (path, prefix) => {
|
|
1509
|
+
const a = segs(prefix);
|
|
1510
|
+
const b = segs(path);
|
|
1511
|
+
return a.length > 0 && a.length <= b.length && a.every((x, i) => x === b[i]);
|
|
1512
|
+
};
|
|
1513
|
+
function serves(entry, call, bases) {
|
|
1514
|
+
const e = segs(entry);
|
|
1515
|
+
const tries = [
|
|
1516
|
+
segs(call),
|
|
1517
|
+
...bases.filter((b) => under(call, b)).map((b) => segs(call).slice(segs(b).length))
|
|
1518
|
+
];
|
|
1519
|
+
return tries.some((c) => c.length === e.length && c.every((x, i) => sameSeg(x, e[i])));
|
|
1520
|
+
}
|
|
1521
|
+
function clientOf(f) {
|
|
1522
|
+
const q = f.cite.quote ?? "";
|
|
1523
|
+
const named2 = /\b([A-Z][A-Za-z0-9]*(?:Client|Service|Api|Feign|Gateway|Proxy))\b/.exec(q)?.[1];
|
|
1524
|
+
if (named2)
|
|
1525
|
+
return named2;
|
|
1526
|
+
const file = f.cite.file.split("/").pop().replace(/\.[^.]+$/, "");
|
|
1527
|
+
return /(Client|Service|Api|Feign|Gateway|Proxy)$/.test(file) ? file : void 0;
|
|
1528
|
+
}
|
|
1529
|
+
function hostOf(f, facts) {
|
|
1530
|
+
const fromUrl = (u) => /^[a-z][a-z0-9+.-]*:\/\/([^/:?#]+)/i.exec(u)?.[1];
|
|
1531
|
+
if (f.host)
|
|
1532
|
+
return fromUrl(f.host) ?? f.host.split(/[/:]/)[0];
|
|
1533
|
+
if (f.base) {
|
|
1534
|
+
const cfg = facts.find((x) => x.kind === "config" && x.key === f.base && !!x.value);
|
|
1535
|
+
if (!cfg?.value)
|
|
1536
|
+
return void 0;
|
|
1537
|
+
return fromUrl(cfg.value) ?? (/^[a-z0-9-]+(\.[a-z0-9-]+)+(:\d+)?$/i.test(cfg.value) ? cfg.value.split(":")[0] : void 0);
|
|
1538
|
+
}
|
|
1539
|
+
return void 0;
|
|
1540
|
+
}
|
|
1541
|
+
var answerLabel = (q) => q.answer?.option !== void 0 ? q.options[q.answer.option - 1]?.label : q.answer?.text;
|
|
1542
|
+
var NOT_A_TARGET = /* @__PURE__ */ new Set(["None of these", TARGETS_SPLIT_LABEL, TARGETS_ANOTHER_LABEL]);
|
|
1543
|
+
function candidates(callerRepo, ctx) {
|
|
1544
|
+
const manifest = estateRepos(ctx.op).filter((r) => r.id !== callerRepo || !!ctx.only);
|
|
1545
|
+
const systems = ctx.op.profiles.flatMap((p) => p.profile?.systems ?? []);
|
|
1546
|
+
const reposOfSystem = /* @__PURE__ */ new Map();
|
|
1547
|
+
for (const r of estateRepos(ctx.op))
|
|
1548
|
+
if (r.system)
|
|
1549
|
+
reposOfSystem.set(r.system, (reposOfSystem.get(r.system) ?? 0) + 1);
|
|
1550
|
+
const read = new Set((ctx.estate ?? []).filter((x) => x.facts.length > 0).map((x) => x.repo));
|
|
1551
|
+
const repoOf = /* @__PURE__ */ new Map();
|
|
1552
|
+
for (const r of ctx.records)
|
|
1553
|
+
if (r.kind === "Component" && r.repo)
|
|
1554
|
+
repoOf.set(r.id, r.repo);
|
|
1555
|
+
if (!ctx.estate)
|
|
1556
|
+
for (const repo of repoOf.values())
|
|
1557
|
+
read.add(repo);
|
|
1558
|
+
const endpoints = ctx.records.filter((r) => r.kind === "Endpoint");
|
|
1559
|
+
const deploys = (ctx.estate ?? []).flatMap((x) => x.facts.filter((f) => f.kind === "deploy" && !!f.basePath));
|
|
1560
|
+
const out = [];
|
|
1561
|
+
for (const m of manifest) {
|
|
1562
|
+
const own2 = new Set([m.id, m.component, ...m.modules.map((x) => x.component)].filter((x) => !!x).map(factIdPart));
|
|
1563
|
+
const sys = m.system && reposOfSystem.get(m.system) === 1 ? systems.find((s) => s.id === m.system) : void 0;
|
|
1564
|
+
const names = /* @__PURE__ */ new Map();
|
|
1565
|
+
for (const n of [m.id, m.component, ...m.modules.map((x) => x.component)])
|
|
1566
|
+
for (const w of nameWords(n))
|
|
1567
|
+
if (!names.has(w))
|
|
1568
|
+
names.set(w, n);
|
|
1569
|
+
for (const a of sys ? [sys.id, ...sys.aliases] : [])
|
|
1570
|
+
for (const w of nameWords(a))
|
|
1571
|
+
if (!names.has(w))
|
|
1572
|
+
names.set(w, a);
|
|
1573
|
+
const bases = [];
|
|
1574
|
+
if (m.basePath)
|
|
1575
|
+
bases.push({ path: m.basePath, from: "the manifest's basePath" });
|
|
1576
|
+
for (const x of m.modules)
|
|
1577
|
+
if (x.basePath)
|
|
1578
|
+
bases.push({ path: x.basePath, from: `the basePath of its module ${x.component}` });
|
|
1579
|
+
for (const d of deploys) {
|
|
1580
|
+
const reaches = d.exposes ? factIdPart(d.exposes) : d.repo === m.id ? m.id : void 0;
|
|
1581
|
+
if (!reaches || !(own2.has(reaches) || d.repo === m.id && !d.exposes))
|
|
1582
|
+
continue;
|
|
1583
|
+
const what2 = d.platform === "apigee" ? "its proxy's BasePath" : `the ${d.resourceType ?? "route"} ${d.resourceName ?? d.id}`;
|
|
1584
|
+
bases.push({ path: d.basePath, from: `${what2} (${d.repo} ${d.cite.file}:${d.cite.line})` });
|
|
1585
|
+
}
|
|
1586
|
+
const comps = [
|
|
1587
|
+
...new Set(endpoints.filter((e) => repoOf.get(e.component) === m.id).map((e) => e.component))
|
|
1588
|
+
].sort();
|
|
1589
|
+
const isRead = read.has(m.id);
|
|
1590
|
+
const forLabel = comps.length ? comps : [m.id];
|
|
1591
|
+
for (const label2 of forLabel) {
|
|
1592
|
+
const mine = endpoints.filter((e) => e.component === label2);
|
|
1593
|
+
const entries = (ctx.estate ?? []).filter((x) => x.repo === m.id).flatMap((x) => x.facts.filter((f) => f.kind === "entry" && (!comps.length || factIdPart(f.component ?? m.component ?? m.id) === label2 || comps.length === 1))).map((f) => ({
|
|
1594
|
+
...f.method ? { method: f.method.toUpperCase() } : {},
|
|
1595
|
+
path: f.path,
|
|
1596
|
+
at: `${f.cite.file}:${f.cite.line}`
|
|
1597
|
+
}));
|
|
1598
|
+
for (const e of mine)
|
|
1599
|
+
if (!entries.some((x) => x.path === e.pathOrTopic))
|
|
1600
|
+
entries.push({
|
|
1601
|
+
...e.method ? { method: e.method.toUpperCase() } : {},
|
|
1602
|
+
path: e.pathOrTopic,
|
|
1603
|
+
at: e.id
|
|
1604
|
+
});
|
|
1605
|
+
out.push({
|
|
1606
|
+
s: { label: label2, kind: "repo", repo: m.id, read: isRead, score: 0, why: [] },
|
|
1607
|
+
names,
|
|
1608
|
+
bases,
|
|
1609
|
+
entries,
|
|
1610
|
+
...m.description?.text ? { description: m.description.text } : {},
|
|
1611
|
+
hosts: m.hosts.map((h) => h.toLowerCase())
|
|
1612
|
+
});
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
for (const c of ctx.only ?? [])
|
|
1616
|
+
if (!out.some((x) => x.s.label === c))
|
|
1617
|
+
out.push({
|
|
1618
|
+
s: {
|
|
1619
|
+
label: c,
|
|
1620
|
+
kind: "repo",
|
|
1621
|
+
repo: repoOf.get(c) ?? callerRepo,
|
|
1622
|
+
read: true,
|
|
1623
|
+
score: 0,
|
|
1624
|
+
why: []
|
|
1625
|
+
},
|
|
1626
|
+
names: /* @__PURE__ */ new Map(),
|
|
1627
|
+
bases: [],
|
|
1628
|
+
entries: [],
|
|
1629
|
+
hosts: []
|
|
1630
|
+
});
|
|
1631
|
+
const own = new Set(estateRepos(ctx.op).flatMap((r) => r.system ? [r.system] : []));
|
|
1632
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1633
|
+
for (const s of systems) {
|
|
1634
|
+
if (!(s.boundary === "vendor" || !own.has(s.id)) || seen.has(s.id))
|
|
1635
|
+
continue;
|
|
1636
|
+
seen.add(s.id);
|
|
1637
|
+
const names = /* @__PURE__ */ new Map();
|
|
1638
|
+
for (const n of [s.id, s.name, ...s.aliases])
|
|
1639
|
+
for (const w of nameWords(n))
|
|
1640
|
+
if (!names.has(w))
|
|
1641
|
+
names.set(w, n);
|
|
1642
|
+
out.push({
|
|
1643
|
+
s: {
|
|
1644
|
+
label: s.id,
|
|
1645
|
+
kind: "outside",
|
|
1646
|
+
read: false,
|
|
1647
|
+
name: s.name,
|
|
1648
|
+
boundary: s.boundary,
|
|
1649
|
+
score: 0,
|
|
1650
|
+
why: []
|
|
1651
|
+
},
|
|
1652
|
+
names,
|
|
1653
|
+
bases: [],
|
|
1654
|
+
entries: [],
|
|
1655
|
+
hosts: s.aliases.map((a) => a.toLowerCase())
|
|
1656
|
+
});
|
|
1657
|
+
}
|
|
1658
|
+
return out;
|
|
1659
|
+
}
|
|
1660
|
+
function targetSuggestions(f, ctx) {
|
|
1661
|
+
const all = candidates(f.repo, ctx);
|
|
1662
|
+
const df = /* @__PURE__ */ new Map();
|
|
1663
|
+
for (const c of all)
|
|
1664
|
+
for (const w of c.names.keys())
|
|
1665
|
+
df.set(w, (df.get(w) ?? 0) + 1);
|
|
1666
|
+
const telling = (w) => (df.get(w) ?? 0) <= Math.max(2, Math.floor(all.length / 3));
|
|
1667
|
+
const host = hostOf(f, ctx.facts)?.toLowerCase();
|
|
1668
|
+
const client = clientOf(f);
|
|
1669
|
+
const said = [
|
|
1670
|
+
{ from: f.base ? `the config key ${f.base}` : "", words: nameWords(f.base), weight: 4 },
|
|
1671
|
+
{ from: client ? `the client ${client}` : "", words: nameWords(client), weight: 4 },
|
|
1672
|
+
{
|
|
1673
|
+
from: host ? `the host label ${host.split(".")[0]} (${host})` : "",
|
|
1674
|
+
words: host ? nameWords(host.split(".")[0]) : [],
|
|
1675
|
+
weight: 4
|
|
1676
|
+
},
|
|
1677
|
+
{
|
|
1678
|
+
from: `the path ${f.path}`,
|
|
1679
|
+
words: nameWords(segs(f.path).filter((x) => x !== "{}").join(" ")),
|
|
1680
|
+
weight: 2
|
|
1681
|
+
}
|
|
1682
|
+
].filter((x) => x.from && x.words.length);
|
|
1683
|
+
const method = f.method?.toUpperCase();
|
|
1684
|
+
const earlier = (ctx.questions ?? []).filter((q) => q.askedBy?.step === TARGETS_STEP_ID && q.state === "answered" && q.repo === f.repo && !q.evidence.includes(`${f.cite.file}:${f.cite.line}`));
|
|
1685
|
+
const only = ctx.only ? new Set(ctx.only) : void 0;
|
|
1686
|
+
const out = [];
|
|
1687
|
+
for (const c of all) {
|
|
1688
|
+
if (only && c.s.kind === "repo" && !only.has(c.s.label))
|
|
1689
|
+
continue;
|
|
1690
|
+
const s = { ...c.s, why: [] };
|
|
1691
|
+
const add = (n, why) => {
|
|
1692
|
+
s.score += n;
|
|
1693
|
+
s.why.push(why);
|
|
1694
|
+
};
|
|
1695
|
+
if (only?.has(c.s.label))
|
|
1696
|
+
add(6, "the join found an entry of it that serves the call");
|
|
1697
|
+
const hit = c.entries.find((e) => (!method || !e.method || e.method === method || e.method === "ANY") && serves(e.path, f.path, c.bases.map((b) => b.path)));
|
|
1698
|
+
if (hit && !only) {
|
|
1699
|
+
const what2 = [hit.method, hit.path].filter(Boolean).join(" ");
|
|
1700
|
+
add(6, `serves ${what2} (${hit.at})`);
|
|
1701
|
+
s.serves = [what2];
|
|
1702
|
+
}
|
|
1703
|
+
const base2 = c.bases.find((b) => under(f.path, b.path));
|
|
1704
|
+
if (base2)
|
|
1705
|
+
add(5, `its basePath ${base2.path} matches: ${base2.from}`);
|
|
1706
|
+
if (host && c.hosts.includes(host))
|
|
1707
|
+
add(8, `it lists ${host} under hosts`);
|
|
1708
|
+
for (const x of said) {
|
|
1709
|
+
const w = x.words.find((y) => c.names.has(y) && telling(y));
|
|
1710
|
+
if (w)
|
|
1711
|
+
add(x.weight, `named like ${x.from}`);
|
|
1712
|
+
}
|
|
1713
|
+
if (c.description) {
|
|
1714
|
+
const d = new Set(nameWords(c.description));
|
|
1715
|
+
const w = said.flatMap((x) => x.words).find((y) => d.has(y) && telling(y));
|
|
1716
|
+
if (w)
|
|
1717
|
+
add(2, `its description mentions ${w}`);
|
|
1718
|
+
}
|
|
1719
|
+
const named2 = earlier.filter((q) => {
|
|
1720
|
+
const l = answerLabel(q);
|
|
1721
|
+
if (!l || NOT_A_TARGET.has(l))
|
|
1722
|
+
return false;
|
|
1723
|
+
const t = slugify(l);
|
|
1724
|
+
return t === slugify(c.s.label) || !!c.s.repo && t === slugify(c.s.repo);
|
|
1725
|
+
}).length;
|
|
1726
|
+
if (named2)
|
|
1727
|
+
add(3, `picked for ${named2} other ${named2 === 1 ? "call" : "calls"} of ${f.repo}`);
|
|
1728
|
+
if (!s.score)
|
|
1729
|
+
s.why.push(TARGETS_NO_EVIDENCE);
|
|
1730
|
+
s.why = [...new Set(s.why)];
|
|
1731
|
+
out.push(s);
|
|
1732
|
+
}
|
|
1733
|
+
return out.sort((a, b) => b.score - a.score || Number(b.read) - Number(a.read) || (a.kind === b.kind ? 0 : a.kind === "repo" ? -1 : 1) || a.label.localeCompare(b.label));
|
|
1734
|
+
}
|
|
1735
|
+
function offeredSuggestions(ranked, o) {
|
|
1736
|
+
const max = o.max ?? TARGETS_MAX_SUGGESTED;
|
|
1737
|
+
const strong = ranked.filter((s) => s.score >= 2);
|
|
1738
|
+
const fill = ranked.filter((s) => s.score < 2 && (s.kind === "outside" || s.read && o.serving.has(s.label)));
|
|
1739
|
+
return [...strong, ...fill].slice(0, max);
|
|
1740
|
+
}
|
|
1741
|
+
function targetPicker(op, read = /* @__PURE__ */ new Set()) {
|
|
1742
|
+
const repos = estateRepos(op).map((r) => ({
|
|
1743
|
+
id: r.id,
|
|
1744
|
+
kind: "repo",
|
|
1745
|
+
name: r.component && r.component !== r.id ? `${r.id} (${r.component})` : r.id,
|
|
1746
|
+
read: read.has(r.id)
|
|
1747
|
+
})).sort((a, b) => a.id.localeCompare(b.id));
|
|
1748
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1749
|
+
const systems = op.profiles.flatMap((p) => p.profile?.systems ?? []).filter((s) => !seen.has(s.id) && !!seen.add(s.id)).map((s) => ({ id: s.id, kind: "system", name: s.name, boundary: s.boundary })).sort((a, b) => a.id.localeCompare(b.id));
|
|
1750
|
+
const owned = new Set(op.profiles.flatMap((p) => (p.profile?.systems ?? []).flatMap((s) => s.owner ? [s.owner] : [])));
|
|
1751
|
+
const teams = (op.roles?.teams ?? []).map((t) => {
|
|
1752
|
+
const name = t.name ?? t.id;
|
|
1753
|
+
const has = owned.has(t.id);
|
|
1754
|
+
return {
|
|
1755
|
+
id: t.id,
|
|
1756
|
+
kind: "team",
|
|
1757
|
+
name,
|
|
1758
|
+
...has ? {} : {
|
|
1759
|
+
adds: {
|
|
1760
|
+
id: slugify(`${t.id}-system`),
|
|
1761
|
+
name: `${name}'s system`,
|
|
1762
|
+
boundary: "internal",
|
|
1763
|
+
owner: t.id
|
|
1764
|
+
}
|
|
1765
|
+
}
|
|
1766
|
+
};
|
|
1767
|
+
}).sort((a, b) => a.id.localeCompare(b.id));
|
|
1768
|
+
return [...repos, ...systems, ...teams];
|
|
1769
|
+
}
|
|
1770
|
+
function pickerLines(picks) {
|
|
1771
|
+
const of = (k) => picks.filter((p) => p.kind === k);
|
|
1772
|
+
return [
|
|
1773
|
+
`Repos (${of("repo").length}): ${of("repo").map((p) => `${p.id}${p.read ? "" : " (not read yet)"}`).join(", ") || "none"}`,
|
|
1774
|
+
`Systems (${of("system").length}): ${of("system").map((p) => `${p.id} (${p.boundary})`).join(", ") || "none"}`,
|
|
1775
|
+
`Teams (${of("team").length}): ${of("team").map((p) => `${p.id}${p.adds ? " (no system yet)" : ""}`).join(", ") || "none"}`
|
|
1776
|
+
];
|
|
1777
|
+
}
|
|
1778
|
+
function topicQuestionDrafts(repo, records) {
|
|
1779
|
+
const out = /* @__PURE__ */ new Map();
|
|
1780
|
+
for (const r of records) {
|
|
1781
|
+
if (r.kind !== "Unresolved")
|
|
1782
|
+
continue;
|
|
1783
|
+
const x = r;
|
|
1784
|
+
if (x.unresolvedKind !== "event-publish" && x.unresolvedKind !== "event-subscribe")
|
|
1785
|
+
continue;
|
|
1786
|
+
const topic = String(x.raw);
|
|
1787
|
+
if (!topic || topic.includes("${") || /\s/.test(topic))
|
|
1788
|
+
continue;
|
|
1789
|
+
const ev = x.evidence.filter((e) => e.repo === repo && e.path && e.line && !/[\s:]/.test(e.path)).map((e) => `${e.path}:${e.line}`).sort();
|
|
1790
|
+
if (!ev.length)
|
|
1791
|
+
continue;
|
|
1792
|
+
const side = x.unresolvedKind === "event-publish" ? "publish" : "listen";
|
|
1793
|
+
const question = topicQuestionText(topic, x.owner ?? repo, side);
|
|
1794
|
+
const draft = {
|
|
1795
|
+
question,
|
|
1796
|
+
options: [
|
|
1797
|
+
{
|
|
1798
|
+
label: TOPICS_OUTSIDE_LABEL,
|
|
1799
|
+
means: `${topic} belongs to another team's system or a vendor's: name it, or the team, from the list`,
|
|
1800
|
+
changes: `${topic} is added under that system's topics in the profile (or the system is added, owner the team), as a file change for review; the next write ${side === "publish" ? "sends the publish to it" : "takes the listener's messages from it"}, marked as your word`
|
|
1801
|
+
},
|
|
1802
|
+
{
|
|
1803
|
+
label: "None of these",
|
|
1804
|
+
means: `Nothing outside the estate owns ${topic}, or a repo not read yet serves it`,
|
|
1805
|
+
changes: `It stays a loose end, and this isn't asked again`
|
|
1806
|
+
}
|
|
1807
|
+
],
|
|
1808
|
+
evidence: [...new Set(ev)],
|
|
1809
|
+
scope: "repo"
|
|
1810
|
+
};
|
|
1811
|
+
const id = questionId({ step: TOPICS_STEP_ID, repo, question, evidence: draft.evidence });
|
|
1812
|
+
if (!out.has(id))
|
|
1813
|
+
out.set(id, { topic, id, draft });
|
|
1814
|
+
}
|
|
1815
|
+
return [...out.values()].sort((a, b) => a.topic.localeCompare(b.topic));
|
|
1816
|
+
}
|
|
1817
|
+
|
|
1818
|
+
// packages/scanner/dist/facts-catalog.js
|
|
1487
1819
|
var TARGETS_STEP = TARGETS_STEP_ID;
|
|
1488
1820
|
var TARGETS_NONE = "None of these";
|
|
1489
1821
|
var byKindId = (a, b) => a.kind === b.kind ? a.id.localeCompare(b.id) : a.kind.localeCompare(b.kind);
|
|
@@ -1556,27 +1888,88 @@ function targetAsks(facts, records, asks) {
|
|
|
1556
1888
|
}
|
|
1557
1889
|
return { list, repoOf };
|
|
1558
1890
|
}
|
|
1559
|
-
var vendorsOf = (op) => outsideProfileSystems(op);
|
|
1560
1891
|
var outsideAs = (s) => s.boundary === "vendor" ? "an outside system" : "another team's system";
|
|
1561
1892
|
var callWhat = (f) => [f.method?.toUpperCase(), f.path].filter(Boolean).join(" ");
|
|
1562
|
-
function
|
|
1563
|
-
const
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
const
|
|
1893
|
+
function suggestionWhy(s, prefix) {
|
|
1894
|
+
const served = s.serves ?? [];
|
|
1895
|
+
let why = s.why;
|
|
1896
|
+
if (prefix !== void 0 && served.length > 1) {
|
|
1897
|
+
const under2 = prefix === "/" ? "" : ` under ${prefix}`;
|
|
1898
|
+
why = [
|
|
1899
|
+
`serves ${served[0]} and ${served.length - 1} more${under2}`,
|
|
1900
|
+
...why.filter((w) => !w.startsWith("serves "))
|
|
1901
|
+
];
|
|
1902
|
+
}
|
|
1903
|
+
return (why.length ? why : [TARGETS_NO_EVIDENCE]).slice(0, 3).join("; ");
|
|
1904
|
+
}
|
|
1905
|
+
function suggestionOption(s, callerRepo, n, prefix) {
|
|
1906
|
+
const why = suggestionWhy(s, prefix);
|
|
1907
|
+
if (s.kind === "outside")
|
|
1908
|
+
return {
|
|
1909
|
+
label: s.label,
|
|
1910
|
+
means: `${s.name}, ${outsideAs({ boundary: s.boundary ?? "vendor" })}: ${why}`,
|
|
1911
|
+
changes: n ? `The ${n} calls go to ${s.name} when the facts are next written` : `The call goes to ${s.name} when the facts are next written`
|
|
1912
|
+
};
|
|
1913
|
+
const who = s.label === s.repo ? `${s.repo}${s.read ? "" : " (not read yet)"}` : `${s.label}, built in ${s.repo}${s.read ? "" : " (not read yet)"}`;
|
|
1914
|
+
const them = n ? `The ${n} calls` : "The call";
|
|
1915
|
+
return {
|
|
1916
|
+
label: s.label,
|
|
1917
|
+
means: `${who}: ${why}`,
|
|
1918
|
+
changes: s.read ? `${them} ${n ? "join" : "joins"} ${s.label} when the facts are next written (atticus verify ${callerRepo} --write)` : `${them} ${n ? "go" : "goes"} to ${s.repo} when the facts are next written (atticus verify ${callerRepo} --write), and ${n ? "join" : "joins"} its route once ${s.repo} is read and verified (/atticus-map ${s.repo}); if no route of it serves ${n ? "them" : "it"}, the question opens again`
|
|
1919
|
+
};
|
|
1920
|
+
}
|
|
1921
|
+
var anotherOption = (op) => {
|
|
1922
|
+
const repos = estateRepos(op).length;
|
|
1923
|
+
const systems = new Set(op.profiles.flatMap((p) => (p.profile?.systems ?? []).map((s) => s.id))).size;
|
|
1924
|
+
const teams = op.roles?.teams?.length ?? 0;
|
|
1925
|
+
return {
|
|
1926
|
+
label: TARGETS_ANOTHER,
|
|
1927
|
+
means: `A repo, system or team not listed here: the manifest's ${repos} repos (read or not), the profiles' ${systems} systems and the ${teams} teams in roles.yaml`,
|
|
1928
|
+
changes: "Nothing until you name one: atticus questions answer <id> --target <repo, system or team id> lists them and takes the one you name (the app's Questions page lists them too); naming a vendor or a team with no system adds that system to the profile for review"
|
|
1929
|
+
};
|
|
1930
|
+
};
|
|
1931
|
+
function offered(members, facts, records, op, asks, ctx) {
|
|
1932
|
+
const merged = /* @__PURE__ */ new Map();
|
|
1933
|
+
for (const m of members) {
|
|
1934
|
+
const ambiguous = asks?.some((a) => a.reason === "ambiguous" && a.call.repo === m.f.repo && a.call.fact === m.f.id);
|
|
1935
|
+
for (const s of targetSuggestions(m.f, {
|
|
1936
|
+
op,
|
|
1937
|
+
records,
|
|
1938
|
+
facts,
|
|
1939
|
+
...ctx.estate ? { estate: ctx.estate } : {},
|
|
1940
|
+
...ctx.questions ? { questions: ctx.questions } : {},
|
|
1941
|
+
...ambiguous ? { only: m.servers } : {}
|
|
1942
|
+
})) {
|
|
1943
|
+
const x = merged.get(s.label);
|
|
1944
|
+
if (!x)
|
|
1945
|
+
merged.set(s.label, { ...s, why: [...s.why], serves: [...s.serves ?? []] });
|
|
1946
|
+
else {
|
|
1947
|
+
x.score += s.score;
|
|
1948
|
+
for (const w of s.why)
|
|
1949
|
+
if (!x.why.includes(w))
|
|
1950
|
+
x.why.push(w);
|
|
1951
|
+
for (const w of s.serves ?? [])
|
|
1952
|
+
if (!x.serves.includes(w))
|
|
1953
|
+
x.serves.push(w);
|
|
1954
|
+
if (x.why.length > 1)
|
|
1955
|
+
x.why = x.why.filter((w) => w !== TARGETS_NO_EVIDENCE);
|
|
1956
|
+
}
|
|
1957
|
+
}
|
|
1958
|
+
}
|
|
1959
|
+
const ranked = [...merged.values()].sort((a, b) => b.score - a.score || Number(b.read) - Number(a.read) || (a.kind === b.kind ? 0 : a.kind === "repo" ? -1 : 1) || a.label.localeCompare(b.label));
|
|
1960
|
+
const serving = new Set(members.flatMap((m) => m.servers));
|
|
1961
|
+
const types = new Set(members.flatMap((m) => SERVES[m.f.callType] ?? []));
|
|
1962
|
+
return offeredSuggestions(ranked, { types, serving });
|
|
1963
|
+
}
|
|
1964
|
+
function targetQuestionDrafts(facts, records, op, asks, ctx = {}) {
|
|
1965
|
+
const { list } = targetAsks(facts, records, asks);
|
|
1966
|
+
return list.map((m) => {
|
|
1967
|
+
const { f, q } = m;
|
|
1567
1968
|
const draft = {
|
|
1568
1969
|
question: q.question,
|
|
1569
1970
|
options: [
|
|
1570
|
-
...
|
|
1571
|
-
|
|
1572
|
-
means: `${c}${repoOf.get(c) ? `, built in ${repoOf.get(c)},` : ""} answers ${what2}`,
|
|
1573
|
-
changes: `The call joins ${c} when the facts are next written (atticus verify ${f.repo} --write)`
|
|
1574
|
-
})),
|
|
1575
|
-
...vendors.map((s) => ({
|
|
1576
|
-
label: s.id,
|
|
1577
|
-
means: `${s.name}, ${outsideAs(s)}, answers ${what2}`,
|
|
1578
|
-
changes: `The call goes to ${s.name} when the facts are next written`
|
|
1579
|
-
})),
|
|
1971
|
+
...offered([m], facts, records, op, asks, ctx).map((s) => suggestionOption(s, f.repo)),
|
|
1972
|
+
anotherOption(op),
|
|
1580
1973
|
{
|
|
1581
1974
|
label: TARGETS_NONE,
|
|
1582
1975
|
means: "Nothing in the estate or the org pack's systems answers it",
|
|
@@ -1622,28 +2015,51 @@ function groupVia(f) {
|
|
|
1622
2015
|
return ` through ${f.base}`;
|
|
1623
2016
|
return "";
|
|
1624
2017
|
}
|
|
1625
|
-
function targetGroupQuestion(repo, f) {
|
|
2018
|
+
function targetGroupQuestion(repo, f, facts) {
|
|
2019
|
+
const proxy = facts ? proxyOf(f, facts) : void 0;
|
|
2020
|
+
const through = f.base ?? f.host ?? f.to;
|
|
2021
|
+
if (proxy && through) {
|
|
2022
|
+
const p = targetPathPrefix(f.path);
|
|
2023
|
+
return `Which repo serves the routes under ${p === "/" ? "" : p}/** that ${proxy} forwards to ${through}?`;
|
|
2024
|
+
}
|
|
1626
2025
|
return `Which repo or system answers the calls ${repo} makes under ${targetPathPrefix(f.path)}${groupVia(f)}?`;
|
|
1627
2026
|
}
|
|
2027
|
+
function proxyOf(f, facts) {
|
|
2028
|
+
if (!f.from)
|
|
2029
|
+
return void 0;
|
|
2030
|
+
const from = facts.find((x) => x.id === f.from);
|
|
2031
|
+
if (!from || from.kind !== "entry")
|
|
2032
|
+
return void 0;
|
|
2033
|
+
const proxy = facts.find((x) => x.kind === "deploy" && x.repo === f.repo && x.platform === "apigee" && !!x.basePath);
|
|
2034
|
+
return proxy ? proxy.resourceName ?? f.repo : void 0;
|
|
2035
|
+
}
|
|
2036
|
+
function targetGroupWordings(repo, f, facts) {
|
|
2037
|
+
return [.../* @__PURE__ */ new Set([targetGroupQuestion(repo, f, facts), targetGroupQuestion(repo, f)])];
|
|
2038
|
+
}
|
|
2039
|
+
var repo0 = (members) => members[0].f.repo;
|
|
1628
2040
|
var byLine = (a, b) => a.localeCompare(b, "en", { numeric: true });
|
|
1629
|
-
var
|
|
2041
|
+
var answerLabel2 = (q) => q.answer?.option !== void 0 ? q.options[q.answer.option - 1]?.label : q.answer?.text;
|
|
1630
2042
|
function splitTargetGroups(questions) {
|
|
1631
|
-
return new Set(questions.filter((q) => q.askedBy?.step === TARGETS_STEP && q.state === "answered" &&
|
|
2043
|
+
return new Set(questions.filter((q) => q.askedBy?.step === TARGETS_STEP && q.state === "answered" && answerLabel2(q) === TARGETS_SPLIT).map((q) => q.question.trim()));
|
|
1632
2044
|
}
|
|
1633
2045
|
function groupedTargetDrafts(facts, records, op, asks, o) {
|
|
1634
|
-
const { list
|
|
1635
|
-
const
|
|
2046
|
+
const { list } = targetAsks(facts, records, asks);
|
|
2047
|
+
const ctx = {
|
|
2048
|
+
...o.estate ? { estate: o.estate } : {},
|
|
2049
|
+
...o.questions ? { questions: o.questions } : {}
|
|
2050
|
+
};
|
|
2051
|
+
const own = new Map(targetQuestionDrafts(facts, records, op, asks, ctx).map((d) => [d.factId, d]));
|
|
1636
2052
|
const groups = /* @__PURE__ */ new Map();
|
|
1637
2053
|
for (const a of list) {
|
|
1638
2054
|
if (!o.ask.has(a.f.id))
|
|
1639
2055
|
continue;
|
|
1640
|
-
const k = targetGroupQuestion(a.f.repo, a.f);
|
|
2056
|
+
const k = targetGroupQuestion(a.f.repo, a.f, facts);
|
|
1641
2057
|
groups.set(k, [...groups.get(k) ?? [], a]);
|
|
1642
2058
|
}
|
|
1643
|
-
const vendors = vendorsOf(op);
|
|
1644
2059
|
const out = [];
|
|
1645
2060
|
for (const [question, members] of groups) {
|
|
1646
|
-
|
|
2061
|
+
const split = targetGroupWordings(repo0(members), members[0].f, facts).some((w) => o.split?.has(w));
|
|
2062
|
+
if (members.length === 1 || split) {
|
|
1647
2063
|
for (const m of members)
|
|
1648
2064
|
out.push({ ...own.get(m.f.id), factIds: [m.f.id] });
|
|
1649
2065
|
continue;
|
|
@@ -1652,21 +2068,12 @@ function groupedTargetDrafts(facts, records, op, asks, o) {
|
|
|
1652
2068
|
const whats = [...new Set(members.map((m) => callWhat(m.f)))];
|
|
1653
2069
|
const listed = whats.length > 5 ? `${whats.slice(0, 5).join(", ")} and ${whats.length - 5} more` : whats.join(", ");
|
|
1654
2070
|
const n = members.length;
|
|
1655
|
-
const servers = [...new Set(members.flatMap((m) => m.servers))].sort();
|
|
1656
2071
|
const evidence = [...new Set(members.flatMap((m) => m.q.evidence))].sort(byLine);
|
|
1657
2072
|
const draft = {
|
|
1658
2073
|
question,
|
|
1659
2074
|
options: [
|
|
1660
|
-
...
|
|
1661
|
-
|
|
1662
|
-
means: `${c}${repoOf.get(c) ? `, built in ${repoOf.get(c)},` : ""} answers all ${n} calls: ${listed}`,
|
|
1663
|
-
changes: `The ${n} calls join ${c} when the facts are next written (atticus verify ${repo} --write)`
|
|
1664
|
-
})),
|
|
1665
|
-
...vendors.map((s) => ({
|
|
1666
|
-
label: s.id,
|
|
1667
|
-
means: `${s.name}, ${outsideAs(s)}, answers all ${n} calls: ${listed}`,
|
|
1668
|
-
changes: `The ${n} calls go to ${s.name} when the facts are next written`
|
|
1669
|
-
})),
|
|
2075
|
+
...offered(members, facts, records, op, asks, ctx).map((s) => suggestionOption(s, repo, n, targetPathPrefix(members[0].f.path))),
|
|
2076
|
+
anotherOption(op),
|
|
1670
2077
|
{
|
|
1671
2078
|
label: TARGETS_SPLIT,
|
|
1672
2079
|
means: `The ${n} calls (${listed}) don't all go to one place`,
|
|
@@ -1691,6 +2098,40 @@ function groupedTargetDrafts(facts, records, op, asks, o) {
|
|
|
1691
2098
|
}
|
|
1692
2099
|
return out.sort((a, b) => a.factId.localeCompare(b.factId));
|
|
1693
2100
|
}
|
|
2101
|
+
function targetRuleOffers(questions, factsOf) {
|
|
2102
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
2103
|
+
for (const q of questions) {
|
|
2104
|
+
if (q.state !== "open" || q.askedBy?.step !== TARGETS_STEP)
|
|
2105
|
+
continue;
|
|
2106
|
+
const facts = factsOf(q.repo) ?? [];
|
|
2107
|
+
const at3 = new Set(q.evidence);
|
|
2108
|
+
const calls = facts.filter((f) => f.kind === "call" && f.repo === q.repo && at3.has(`${f.cite.file}:${f.cite.line}`));
|
|
2109
|
+
if (!calls.length)
|
|
2110
|
+
continue;
|
|
2111
|
+
const prefixes = new Set(calls.map((c) => targetPathPrefix(c.path)));
|
|
2112
|
+
const hosts = new Set(calls.map((c) => c.host?.replace(/^[a-z][a-z0-9+.-]*:\/\//i, "").split(/[/:]/)[0]));
|
|
2113
|
+
const [prefix] = prefixes;
|
|
2114
|
+
const [host] = hosts;
|
|
2115
|
+
const match = prefixes.size === 1 && prefix !== "/" ? `${prefix}/**` : hosts.size === 1 && host ? host : void 0;
|
|
2116
|
+
if (!match)
|
|
2117
|
+
continue;
|
|
2118
|
+
const key = `${q.repo}
|
|
2119
|
+
${match}`;
|
|
2120
|
+
const x = byKey.get(key) ?? { match, ids: [], calls: 0 };
|
|
2121
|
+
x.ids.push(q.id);
|
|
2122
|
+
x.calls += calls.length;
|
|
2123
|
+
byKey.set(key, x);
|
|
2124
|
+
}
|
|
2125
|
+
const out = /* @__PURE__ */ new Map();
|
|
2126
|
+
for (const x of byKey.values()) {
|
|
2127
|
+
if (x.ids.length < 2)
|
|
2128
|
+
continue;
|
|
2129
|
+
const ids = [...x.ids].sort();
|
|
2130
|
+
for (const id of ids)
|
|
2131
|
+
out.set(id, { match: x.match, ids, calls: x.calls });
|
|
2132
|
+
}
|
|
2133
|
+
return out;
|
|
2134
|
+
}
|
|
1694
2135
|
var segmentsOf = (p) => p.split(/[?#]/)[0].split("/").filter(Boolean).map((x) => /^[{:<]/.test(x) ? "{}" : x);
|
|
1695
2136
|
function ruleCoversCall(match, f, facts) {
|
|
1696
2137
|
if (isPathMatch(match)) {
|
|
@@ -1711,7 +2152,7 @@ function ruledTargets(repo, facts, questions, o = {}) {
|
|
|
1711
2152
|
if (!needsTarget(f, facts))
|
|
1712
2153
|
continue;
|
|
1713
2154
|
const q = rules.find((r) => ruleCoversCall(r.answer.match, f, facts));
|
|
1714
|
-
const label2 = q ?
|
|
2155
|
+
const label2 = q ? answerLabel2(q) : void 0;
|
|
1715
2156
|
if (q && label2 && label2 !== TARGETS_SPLIT)
|
|
1716
2157
|
out.set(f.id, { id: q.id, match: q.answer.match, label: label2 });
|
|
1717
2158
|
}
|
|
@@ -1732,13 +2173,13 @@ function targetsFromAnswers(repo, facts, questions, o = {}) {
|
|
|
1732
2173
|
continue;
|
|
1733
2174
|
let asked = byId.get(questionId({ step: TARGETS_STEP, repo, ...q }));
|
|
1734
2175
|
if (!asked || asked.state !== "answered" || !asked.answer) {
|
|
1735
|
-
const g = groups.get(
|
|
2176
|
+
const g = targetGroupWordings(repo, f, facts).map((w) => groups.get(w)).find((x) => !!x);
|
|
1736
2177
|
asked = g && (needsTarget(f, facts) || g.evidence.includes(q.evidence[0])) ? g : void 0;
|
|
1737
2178
|
}
|
|
1738
|
-
let label2 = asked && asked.state === "answered" && asked.answer ?
|
|
1739
|
-
if (!label2 || label2 === TARGETS_SPLIT)
|
|
2179
|
+
let label2 = asked && asked.state === "answered" && asked.answer ? answerLabel2(asked) : void 0;
|
|
2180
|
+
if (!label2 || label2 === TARGETS_SPLIT || label2 === TARGETS_ANOTHER)
|
|
1740
2181
|
label2 = ruled.get(f.id)?.label;
|
|
1741
|
-
if (!label2 || label2 === TARGETS_SPLIT)
|
|
2182
|
+
if (!label2 || label2 === TARGETS_SPLIT || label2 === TARGETS_ANOTHER)
|
|
1742
2183
|
continue;
|
|
1743
2184
|
if (label2 === TARGETS_NONE) {
|
|
1744
2185
|
out[f.id] = NO_TARGET;
|
|
@@ -1750,6 +2191,23 @@ function targetsFromAnswers(repo, facts, questions, o = {}) {
|
|
|
1750
2191
|
}
|
|
1751
2192
|
return out;
|
|
1752
2193
|
}
|
|
2194
|
+
function answeredQuestionOfCall(repo, facts, questions, factId) {
|
|
2195
|
+
const f = facts.find((x) => x.id === factId);
|
|
2196
|
+
if (!f || f.kind !== "call")
|
|
2197
|
+
return void 0;
|
|
2198
|
+
const own = targetQuestionFor(f);
|
|
2199
|
+
const ownId = questionId({ step: TARGETS_STEP, repo, ...own });
|
|
2200
|
+
const answered = questions.filter((q2) => q2.askedBy?.step === TARGETS_STEP && q2.state === "answered" && q2.repo === repo);
|
|
2201
|
+
const q = answered.find((x) => x.id === ownId) ?? answered.find((x) => targetGroupWordings(repo, f, facts).includes(x.question.trim()) && x.evidence.includes(own.evidence[0]));
|
|
2202
|
+
return q?.answer?.match ? void 0 : q;
|
|
2203
|
+
}
|
|
2204
|
+
function answerReconfirmed(q) {
|
|
2205
|
+
if (!q.answer || !q.reopened)
|
|
2206
|
+
return false;
|
|
2207
|
+
const now2 = answerLabel2(q);
|
|
2208
|
+
const was = answerLabel2({ ...q, answer: q.reopened.answer });
|
|
2209
|
+
return !!now2 && !!was && slugify(now2) === slugify(was);
|
|
2210
|
+
}
|
|
1753
2211
|
var JOINED_BY = {
|
|
1754
2212
|
named: "the call names it",
|
|
1755
2213
|
repo: "the call names its repo",
|
|
@@ -1763,7 +2221,7 @@ function callsOfTargetQuestion(repo, facts, q) {
|
|
|
1763
2221
|
const own = targetQuestionFor(f);
|
|
1764
2222
|
if (questionId({ step: TARGETS_STEP, repo, ...own }) === q.id)
|
|
1765
2223
|
return true;
|
|
1766
|
-
return
|
|
2224
|
+
return targetGroupWordings(repo, f, facts).includes(q.question.trim()) && q.evidence.includes(own.evidence[0]);
|
|
1767
2225
|
});
|
|
1768
2226
|
}
|
|
1769
2227
|
function staleTargetQuestions(input) {
|
|
@@ -2055,7 +2513,9 @@ function catalogWithFacts(given) {
|
|
|
2055
2513
|
const remap = /* @__PURE__ */ new Map();
|
|
2056
2514
|
const stepTo = /* @__PURE__ */ new Map();
|
|
2057
2515
|
let join10;
|
|
2516
|
+
let answerMisses;
|
|
2058
2517
|
let estateJoin;
|
|
2518
|
+
let terms;
|
|
2059
2519
|
let records0 = [...kept2, ...newRecords];
|
|
2060
2520
|
if (input.estate) {
|
|
2061
2521
|
const repos = joinReposOf(op, [{ repo, facts }, ...others], renames);
|
|
@@ -2069,6 +2529,16 @@ function catalogWithFacts(given) {
|
|
|
2069
2529
|
});
|
|
2070
2530
|
join10 = joinAbout(whole, repo);
|
|
2071
2531
|
estateJoin = { whole, repos };
|
|
2532
|
+
const named2 = { ...input.estateTargets, [repo]: input.targets ?? {} };
|
|
2533
|
+
const mine2 = /* @__PURE__ */ new Set([
|
|
2534
|
+
factIdPart(repo),
|
|
2535
|
+
...repos.filter((r) => r.repo === repo).flatMap((r) => [r.component, ...(r.modules ?? []).map((m) => m.component)]).filter((x) => !!x).map(factIdPart),
|
|
2536
|
+
...facts.flatMap((f) => f.component ? [factIdPart(f.component)] : [])
|
|
2537
|
+
]);
|
|
2538
|
+
answerMisses = whole.misses.filter((m) => {
|
|
2539
|
+
const t = named2[m.call.repo]?.[m.call.fact];
|
|
2540
|
+
return !!t && t !== NO_TARGET && (m.call.repo === repo || mine2.has(factIdPart(m.target)));
|
|
2541
|
+
});
|
|
2072
2542
|
records0 = applyFactJoins(records0, join10, repos, {
|
|
2073
2543
|
callers: joinCallers({
|
|
2074
2544
|
repos,
|
|
@@ -2079,6 +2549,8 @@ function catalogWithFacts(given) {
|
|
|
2079
2549
|
join: whole,
|
|
2080
2550
|
only: [repo]
|
|
2081
2551
|
});
|
|
2552
|
+
terms = joinTerms({ repos, join: whole, bundleFolders: joinConventions(op).bundleFolders });
|
|
2553
|
+
records0 = [...records0, ...termGrantRecords(terms, repos, { only: [repo] })];
|
|
2082
2554
|
for (const j of join10.joins) {
|
|
2083
2555
|
const id = j.call.repo === repo ? projected.ids[j.call.fact] : void 0;
|
|
2084
2556
|
if (!id || remap.has(id))
|
|
@@ -2185,7 +2657,9 @@ function catalogWithFacts(given) {
|
|
|
2185
2657
|
notes: merged.notes,
|
|
2186
2658
|
...join10 ? { join: join10 } : {},
|
|
2187
2659
|
...linkEvidence ? { linkEvidence } : {},
|
|
2188
|
-
...sharedWhole ? { shared: sharedJoinAbout(sharedWhole, repo) } : {}
|
|
2660
|
+
...sharedWhole ? { shared: sharedJoinAbout(sharedWhole, repo) } : {},
|
|
2661
|
+
...terms ? { terms } : {},
|
|
2662
|
+
...answerMisses?.length ? { answerMisses } : {}
|
|
2189
2663
|
};
|
|
2190
2664
|
}
|
|
2191
2665
|
function prototypeLeftOut(input) {
|
|
@@ -2238,6 +2712,61 @@ function estateFromFacts(input) {
|
|
|
2238
2712
|
});
|
|
2239
2713
|
return { records, specs, join: join10, invalid };
|
|
2240
2714
|
}
|
|
2715
|
+
function answerRuleOffers(input) {
|
|
2716
|
+
const ruled = input.questions.filter((q) => q.askedBy?.step === TARGETS_STEP && q.state === "answered" && !!q.answer?.match);
|
|
2717
|
+
const groups = /* @__PURE__ */ new Map();
|
|
2718
|
+
for (const r of input.repos)
|
|
2719
|
+
for (const f of r.facts) {
|
|
2720
|
+
if (f.kind !== "call")
|
|
2721
|
+
continue;
|
|
2722
|
+
const q = answeredQuestionOfCall(r.repo, r.facts, input.questions, f.id);
|
|
2723
|
+
const label2 = q ? answerLabel2(q) : void 0;
|
|
2724
|
+
if (!q || !label2 || label2 === TARGETS_NONE || label2 === TARGETS_SPLIT || label2 === TARGETS_ANOTHER)
|
|
2725
|
+
continue;
|
|
2726
|
+
const url = urlOf(f, r.facts);
|
|
2727
|
+
const host = url ? urlHostPort(url)?.host : void 0;
|
|
2728
|
+
const via = host ? `on ${host.toLowerCase()}` : f.base ? `through ${f.base}` : void 0;
|
|
2729
|
+
if (!via)
|
|
2730
|
+
continue;
|
|
2731
|
+
groups.set(via, [
|
|
2732
|
+
...groups.get(via) ?? [],
|
|
2733
|
+
{ repo: r.repo, q, label: label2, f, facts: r.facts, ...r.type ? { type: r.type } : {} }
|
|
2734
|
+
]);
|
|
2735
|
+
}
|
|
2736
|
+
const out = [];
|
|
2737
|
+
for (const [via, xs] of [...groups].sort(([a], [b]) => a.localeCompare(b))) {
|
|
2738
|
+
const repos = [...new Set(xs.map((x) => x.repo))].sort();
|
|
2739
|
+
const labels = new Set(xs.map((x) => slugify(x.label)));
|
|
2740
|
+
if (repos.length < 2 || labels.size !== 1)
|
|
2741
|
+
continue;
|
|
2742
|
+
if (xs.every((x) => ruled.some((q) => ruleCoversCall(q.answer.match, x.f, x.facts))))
|
|
2743
|
+
continue;
|
|
2744
|
+
const label2 = xs[0].label;
|
|
2745
|
+
const prefixes = new Set(xs.map((x) => targetPathPrefix(x.f.path)));
|
|
2746
|
+
const prefix = prefixes.size === 1 ? [...prefixes][0] : void 0;
|
|
2747
|
+
const match = via.startsWith("on ") ? via.slice(3) : prefix && prefix !== "/" ? `${prefix}/**` : void 0;
|
|
2748
|
+
const types = new Set(xs.map((x) => x.type));
|
|
2749
|
+
const type = types.size === 1 ? xs[0].type : void 0;
|
|
2750
|
+
const questions = [...new Set(xs.map((x) => x.q.id))].sort();
|
|
2751
|
+
const first = xs.find((x) => x.q.id === questions[0]).q;
|
|
2752
|
+
const n = first.options.findIndex((o) => o.label === label2);
|
|
2753
|
+
const pick = n >= 0 ? `--option ${n + 1}` : `--text "${label2}"`;
|
|
2754
|
+
if (!match || !type)
|
|
2755
|
+
continue;
|
|
2756
|
+
const command = `atticus questions answer ${first.id} ${pick} --match ${match} --scope repo-type --type ${type}`;
|
|
2757
|
+
out.push({
|
|
2758
|
+
via,
|
|
2759
|
+
label: label2,
|
|
2760
|
+
repos,
|
|
2761
|
+
questions,
|
|
2762
|
+
match,
|
|
2763
|
+
type,
|
|
2764
|
+
command,
|
|
2765
|
+
line: `${repos.length} repos (${repos.join(", ")}) answer the calls ${via} the same way, ${label2} (${questions.join(", ")}): one answer can say it for every ${type} repo. As a rule: ${command}.`
|
|
2766
|
+
});
|
|
2767
|
+
}
|
|
2768
|
+
return out;
|
|
2769
|
+
}
|
|
2241
2770
|
|
|
2242
2771
|
// packages/scanner/dist/facts-scan.js
|
|
2243
2772
|
async function factsForScan(root, op, repo, commit, readerRecords, at3 = {}) {
|
|
@@ -2422,8 +2951,8 @@ async function checkScanSettings(s, repo) {
|
|
|
2422
2951
|
if (!(isConfigFile(file) && names)) {
|
|
2423
2952
|
const dropped = code.filter((f) => re.test(f));
|
|
2424
2953
|
const root = mainRoots.find((d) => {
|
|
2425
|
-
const
|
|
2426
|
-
return
|
|
2954
|
+
const under2 = code.filter((f) => f.startsWith(`${d}/`));
|
|
2955
|
+
return under2.length && under2.every((f) => re.test(f));
|
|
2427
2956
|
});
|
|
2428
2957
|
const why = " so it is still read; only a build or config file that leaves it out itself can say so";
|
|
2429
2958
|
if (dropped.length * 2 > code.length) {
|
|
@@ -3329,8 +3858,8 @@ async function resolveSettingsTemplate(t, repo, repoId) {
|
|
|
3329
3858
|
out.exclude.push({ path: e.path, why: e.why, at: `${first}:1` });
|
|
3330
3859
|
}
|
|
3331
3860
|
for (const rule of t.settings.prefixes) {
|
|
3332
|
-
const
|
|
3333
|
-
for (const f of
|
|
3861
|
+
const candidates2 = (await files.matching(rule.files)).sort((a, b) => a.length - b.length || a.localeCompare(b));
|
|
3862
|
+
for (const f of candidates2) {
|
|
3334
3863
|
const hit = await readRule(rule, f, files);
|
|
3335
3864
|
if (!hit)
|
|
3336
3865
|
continue;
|
|
@@ -4054,7 +4583,7 @@ function parseEntry(s) {
|
|
|
4054
4583
|
const m = /^([A-Za-z]+)\s+(\S+)$/.exec(s.trim());
|
|
4055
4584
|
return m ? { method: m[1].toUpperCase(), path: m[2] } : { path: s.trim() };
|
|
4056
4585
|
}
|
|
4057
|
-
var
|
|
4586
|
+
var segs2 = (p) => normalizePath(p).toLowerCase().split("/").filter(Boolean);
|
|
4058
4587
|
var sameMethod = (a, b) => !a || !b || a.toUpperCase() === b.toUpperCase();
|
|
4059
4588
|
async function joinEstate(o) {
|
|
4060
4589
|
const byId = new Map(o.records.map((r) => [r.id, r]));
|
|
@@ -4066,8 +4595,8 @@ async function joinEstate(o) {
|
|
|
4066
4595
|
const out = [i.normalizedPath];
|
|
4067
4596
|
const route = i.route ? byId.get(i.route) : void 0;
|
|
4068
4597
|
if (route?.kind === "GatewayRoute") {
|
|
4069
|
-
const base2 =
|
|
4070
|
-
const p =
|
|
4598
|
+
const base2 = segs2(route.basepath);
|
|
4599
|
+
const p = segs2(i.normalizedPath);
|
|
4071
4600
|
if (base2.length && base2.every((s, k) => p[k] === s))
|
|
4072
4601
|
out.push(`/${p.slice(base2.length).join("/")}`);
|
|
4073
4602
|
}
|
|
@@ -4182,27 +4711,27 @@ async function joinEstate(o) {
|
|
|
4182
4711
|
within = "estate";
|
|
4183
4712
|
hits = servingExactly(flow.component, want);
|
|
4184
4713
|
}
|
|
4185
|
-
const
|
|
4186
|
-
if (
|
|
4714
|
+
const candidates2 = [...new Set(hits.map((e) => e.component))].sort();
|
|
4715
|
+
if (candidates2.length === 0) {
|
|
4187
4716
|
miss({
|
|
4188
4717
|
reason: "no-target",
|
|
4189
4718
|
message: `${s.to.component} isn't a component in the catalog, and neither an Interface from ${flow.component} nor an entry point of the estate serves ${s.to.entry}`
|
|
4190
4719
|
});
|
|
4191
4720
|
continue;
|
|
4192
4721
|
}
|
|
4193
|
-
if (
|
|
4194
|
-
const repos = [...new Set(
|
|
4722
|
+
if (candidates2.length > 1) {
|
|
4723
|
+
const repos = [...new Set(candidates2.map(repoOfComponent))];
|
|
4195
4724
|
const of = repos.length === 1 && repos[0] ? repos[0] : "the estate";
|
|
4196
4725
|
miss({
|
|
4197
4726
|
reason: "no-target",
|
|
4198
|
-
message: `${s.to.component} isn't a component in the catalog, and ${
|
|
4727
|
+
message: `${s.to.component} isn't a component in the catalog, and ${candidates2.length} components of ${of} serve ${s.to.entry} (${candidates2.join(", ")}): a person says which`
|
|
4199
4728
|
});
|
|
4200
4729
|
asks.push({
|
|
4201
4730
|
from,
|
|
4202
4731
|
caller: flow.component,
|
|
4203
4732
|
named: s.to.component,
|
|
4204
4733
|
what: s.to.entry,
|
|
4205
|
-
candidates
|
|
4734
|
+
candidates: candidates2
|
|
4206
4735
|
});
|
|
4207
4736
|
continue;
|
|
4208
4737
|
}
|
|
@@ -4430,6 +4959,17 @@ function fieldLineage(f, field) {
|
|
|
4430
4959
|
}
|
|
4431
4960
|
|
|
4432
4961
|
// packages/scanner/dist/hosts-asked.js
|
|
4962
|
+
var segs3 = (p) => p.split(/[?#]/)[0].split("/").filter(Boolean).map((x) => /^[{:<$]/.test(x) ? "{}" : x);
|
|
4963
|
+
var underPath = (path, base2) => {
|
|
4964
|
+
const b = segs3(base2);
|
|
4965
|
+
const c = segs3(path);
|
|
4966
|
+
return b.length > 0 && b.length <= c.length && b.every((x, i) => x === c[i]);
|
|
4967
|
+
};
|
|
4968
|
+
var servesPath = (entry, path) => {
|
|
4969
|
+
const e = segs3(entry);
|
|
4970
|
+
const c = segs3(path);
|
|
4971
|
+
return e.length === c.length && e.every((x, i) => x === "{}" || c[i] === "{}" || x === c[i]);
|
|
4972
|
+
};
|
|
4433
4973
|
var HTTP_TYPES = /* @__PURE__ */ new Set(["rest", "graphql", "soap", "websocket", "sse", "webhook"]);
|
|
4434
4974
|
var CONFIG_FILES = [
|
|
4435
4975
|
"**/application*.properties",
|
|
@@ -4492,8 +5032,12 @@ async function unknownHosts(o) {
|
|
|
4492
5032
|
const entry = byHost.get(h.label) ?? {
|
|
4493
5033
|
...h.port !== void 0 ? { port: h.port } : {},
|
|
4494
5034
|
explicit: h.label !== h.host,
|
|
4495
|
-
calls: []
|
|
5035
|
+
calls: [],
|
|
5036
|
+
paths: /* @__PURE__ */ new Set()
|
|
4496
5037
|
};
|
|
5038
|
+
const path = /^[a-z][a-z0-9+.-]*:\/\/[^/?#]*(\/[^?#]*)?/i.exec(url)?.[1];
|
|
5039
|
+
if (path)
|
|
5040
|
+
entry.paths.add(path);
|
|
4497
5041
|
const at3 = `${e.path}:${e.line}`;
|
|
4498
5042
|
if (!entry.calls.some((c) => c.repo === repo && c.at === at3))
|
|
4499
5043
|
entry.calls.push({ repo, at: at3 });
|
|
@@ -4546,6 +5090,25 @@ async function unknownHosts(o) {
|
|
|
4546
5090
|
}
|
|
4547
5091
|
const suggest = hits.length === 1 ? hits[0] : void 0;
|
|
4548
5092
|
const calls = entry.calls.sort((a, b) => a.repo.localeCompare(b.repo) || a.at.localeCompare(b.at, "en", { numeric: true }));
|
|
5093
|
+
const byPath = [];
|
|
5094
|
+
for (const g of o.records) {
|
|
5095
|
+
if (g.kind !== "GatewayRoute")
|
|
5096
|
+
continue;
|
|
5097
|
+
const repo = g.evidence.find((e) => e.repo)?.repo;
|
|
5098
|
+
if (!repo || byPath.some((b) => b.repo === repo))
|
|
5099
|
+
continue;
|
|
5100
|
+
const under2 = [...entry.paths].filter((p) => underPath(p, g.basepath));
|
|
5101
|
+
if (!under2.length)
|
|
5102
|
+
continue;
|
|
5103
|
+
const comps = new Set([...compRepo].filter(([, r]) => r === repo).map(([c]) => c));
|
|
5104
|
+
const hit = o.records.find((r) => r.kind === "Endpoint" && comps.has(r.component) && under2.some((p) => servesPath(r.pathOrTopic, p)));
|
|
5105
|
+
byPath.push({
|
|
5106
|
+
repo,
|
|
5107
|
+
serves: hit ? [hit.method?.toUpperCase(), hit.pathOrTopic].filter(Boolean).join(" ") : `the routes under ${g.basepath}`
|
|
5108
|
+
});
|
|
5109
|
+
}
|
|
5110
|
+
byPath.sort((a, b) => a.repo.localeCompare(b.repo));
|
|
5111
|
+
const first = suggest ? [suggest.repo] : byPath.map((b) => b.repo).filter((x) => servers.includes(x));
|
|
4549
5112
|
const about = Object.fromEntries(servers.flatMap((s) => {
|
|
4550
5113
|
const d = o.repos.find((r) => r.id === s)?.description;
|
|
4551
5114
|
return d ? [[s, { text: d.text, trust: d.trust }]] : [];
|
|
@@ -4553,9 +5116,10 @@ async function unknownHosts(o) {
|
|
|
4553
5116
|
asks.push({
|
|
4554
5117
|
host,
|
|
4555
5118
|
calls,
|
|
4556
|
-
servers:
|
|
5119
|
+
servers: [...first, ...servers.filter((s) => !first.includes(s))],
|
|
4557
5120
|
...suggest ? { suggest } : {},
|
|
4558
|
-
...Object.keys(about).length ? { about } : {}
|
|
5121
|
+
...Object.keys(about).length ? { about } : {},
|
|
5122
|
+
...byPath.length ? { byPath } : {}
|
|
4559
5123
|
});
|
|
4560
5124
|
}
|
|
4561
5125
|
return asks;
|
|
@@ -4566,18 +5130,24 @@ function aboutOf(a, repo) {
|
|
|
4566
5130
|
return "";
|
|
4567
5131
|
return d.trust === "suggested" ? `. What it is, as your assistant drafted it (unconfirmed): ${d.text}` : `. What it is: ${d.text}`;
|
|
4568
5132
|
}
|
|
5133
|
+
function gatewayHostFix(host, byPath) {
|
|
5134
|
+
const repos = byPath.map((b) => b.repo);
|
|
5135
|
+
return `${repos.length === 1 ? `${repos[0]}'s routes serve` : `The routes of ${repos.join(", ")} serve`} the paths the calls to ${host} make, and no repo lists ${host}: it looks like a shared gateway's host. Once, not per call: list ${host} under hosts: on each proxy repo in repos.manifest.yaml (${repos.join(", ")}, and any other proxy on it); the path then picks the proxy, and this question retires itself`;
|
|
5136
|
+
}
|
|
4569
5137
|
function hostQuestionDrafts(asks) {
|
|
4570
5138
|
return asks.map((a) => {
|
|
4571
5139
|
const repo = a.calls[0].repo;
|
|
5140
|
+
const byPath = new Map((a.byPath ?? []).map((b) => [b.repo, b.serves]));
|
|
4572
5141
|
return {
|
|
4573
5142
|
repo,
|
|
5143
|
+
...a.byPath?.length ? { byPath: a.byPath } : {},
|
|
4574
5144
|
draft: {
|
|
4575
5145
|
question: hostQuestionText(a.host),
|
|
4576
5146
|
options: [
|
|
4577
5147
|
...a.servers.map((s) => ({
|
|
4578
5148
|
label: s,
|
|
4579
|
-
means: (a.suggest?.repo === s ? `${s} serves HTTP, and its ${a.suggest.at} sets the port ${a.host.split(":").pop()} (${a.suggest.line})` : `${s} serves HTTP`) + aboutOf(a, s),
|
|
4580
|
-
changes: `${a.host} goes under hosts for ${s} in repos.manifest.yaml, and the calls to it join ${s} on the next scan`
|
|
5149
|
+
means: (a.suggest?.repo === s ? `${s} serves HTTP, and its ${a.suggest.at} sets the port ${a.host.split(":").pop()} (${a.suggest.line})` : byPath.has(s) ? `${s} serves ${byPath.get(s)}, a path the calls to ${a.host} make` : `${s} serves HTTP`) + aboutOf(a, s),
|
|
5150
|
+
changes: byPath.has(s) ? `${a.host} goes under hosts for ${s} in repos.manifest.yaml, and the calls to it join ${s} on the next scan; on a shared gateway host, list it on each proxy repo instead (${[...byPath.keys()].join(", ")}, and any other proxy on it), and the path picks the proxy` : `${a.host} goes under hosts for ${s} in repos.manifest.yaml, and the calls to it join ${s} on the next scan`
|
|
4581
5151
|
})),
|
|
4582
5152
|
// O1: a system outside the estate, declared in the profile with the host as its alias.
|
|
4583
5153
|
...[
|
|
@@ -4696,12 +5266,12 @@ function parseLinkReference(source) {
|
|
|
4696
5266
|
return { ok: true, reference: { ...estate ? { estate } : {}, repos } };
|
|
4697
5267
|
}
|
|
4698
5268
|
var stripped = (o) => Object.fromEntries(Object.entries(o).filter(([, v]) => v !== void 0));
|
|
4699
|
-
function
|
|
5269
|
+
function segs4(path) {
|
|
4700
5270
|
return path.split(/[?#]/)[0].split("/").filter(Boolean).map((s) => /^(\{[^}]*\}|:\w+|\*)$/.test(s) ? "{}" : s.toLowerCase());
|
|
4701
5271
|
}
|
|
4702
5272
|
function pathMatch(a, b) {
|
|
4703
|
-
const x =
|
|
4704
|
-
const y =
|
|
5273
|
+
const x = segs4(a);
|
|
5274
|
+
const y = segs4(b);
|
|
4705
5275
|
if (x.length === y.length && x.every((s, i) => s === y[i]))
|
|
4706
5276
|
return 2;
|
|
4707
5277
|
const [short, long] = x.length < y.length ? [x, y] : [y, x];
|
|
@@ -4996,19 +5566,33 @@ export {
|
|
|
4996
5566
|
estateMergeInput,
|
|
4997
5567
|
mergeEstate,
|
|
4998
5568
|
curatedDirOf,
|
|
5569
|
+
TARGETS_MAX_SUGGESTED,
|
|
5570
|
+
TARGETS_ANOTHER,
|
|
5571
|
+
TARGETS_NO_EVIDENCE,
|
|
5572
|
+
nameWords,
|
|
5573
|
+
targetSuggestions,
|
|
5574
|
+
offeredSuggestions,
|
|
5575
|
+
targetPicker,
|
|
5576
|
+
pickerLines,
|
|
5577
|
+
topicQuestionDrafts,
|
|
4999
5578
|
TARGETS_STEP,
|
|
5000
5579
|
TARGETS_NONE,
|
|
5001
5580
|
remapIds,
|
|
5002
5581
|
targetQuestionFor,
|
|
5582
|
+
suggestionWhy,
|
|
5003
5583
|
targetQuestionDrafts,
|
|
5004
5584
|
TARGETS_SPLIT,
|
|
5005
5585
|
targetPathPrefix,
|
|
5006
5586
|
targetGroupQuestion,
|
|
5587
|
+
targetGroupWordings,
|
|
5007
5588
|
splitTargetGroups,
|
|
5008
5589
|
groupedTargetDrafts,
|
|
5590
|
+
targetRuleOffers,
|
|
5009
5591
|
ruleCoversCall,
|
|
5010
5592
|
ruledTargets,
|
|
5011
5593
|
targetsFromAnswers,
|
|
5594
|
+
answeredQuestionOfCall,
|
|
5595
|
+
answerReconfirmed,
|
|
5012
5596
|
staleTargetQuestions,
|
|
5013
5597
|
componentRenames,
|
|
5014
5598
|
factsRecords,
|
|
@@ -5020,6 +5604,7 @@ export {
|
|
|
5020
5604
|
catalogWithFacts,
|
|
5021
5605
|
prototypeLeftOut,
|
|
5022
5606
|
estateFromFacts,
|
|
5607
|
+
answerRuleOffers,
|
|
5023
5608
|
factsForScan,
|
|
5024
5609
|
estateFacts,
|
|
5025
5610
|
NO_SETTINGS,
|
|
@@ -5063,6 +5648,7 @@ export {
|
|
|
5063
5648
|
fieldLineage,
|
|
5064
5649
|
lineSetsPort,
|
|
5065
5650
|
unknownHosts,
|
|
5651
|
+
gatewayHostFix,
|
|
5066
5652
|
hostQuestionDrafts,
|
|
5067
5653
|
parseLinkReference,
|
|
5068
5654
|
measureLinks,
|