@hawkeyexl/manni 4.10.0 → 4.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/{batch-6NICDKRE.js → batch-UAULUMGH.js} +18 -14
- package/dist/{build-3KP2K3XN.js → build-QSPNK5AL.js} +14 -11
- package/dist/calibrate-KXN4URPM.js +40 -0
- package/dist/{capture-NETOHCB4.js → capture-JHTSUPUC.js} +16 -13
- package/dist/{check-E4QCB7LS.js → check-MDGXEUWL.js} +5 -5
- package/dist/{check-NLL4NRYA.js → check-VELUQAUW.js} +17 -14
- package/dist/{check-NLL4NRYA.js.map → check-VELUQAUW.js.map} +1 -1
- package/dist/check-WOQRKNZK.js +29 -0
- package/dist/{check-7B77ZD2N.js → check-YEOYBFST.js} +14 -11
- package/dist/{chunk-2JV7C4YV.js → chunk-2DRHT73U.js} +7 -7
- package/dist/{chunk-CCWMACJL.js → chunk-2IAZEB45.js} +8 -8
- package/dist/{chunk-ZHRPH52H.js → chunk-2IR4T5PO.js} +2 -2
- package/dist/{chunk-2BV4FBC7.js → chunk-2MJ62AYQ.js} +2 -2
- package/dist/{chunk-2BV4FBC7.js.map → chunk-2MJ62AYQ.js.map} +1 -1
- package/dist/{chunk-RODZ7MB7.js → chunk-4CK6ZSOK.js} +6 -6
- package/dist/{chunk-7Y3N4Y72.js → chunk-4D5IZSXM.js} +3 -3
- package/dist/{chunk-4DLF5SA4.js → chunk-4VBSTXN6.js} +4 -4
- package/dist/{chunk-2YJ5H5E6.js → chunk-54F74XR3.js} +15 -13
- package/dist/{chunk-2YJ5H5E6.js.map → chunk-54F74XR3.js.map} +1 -1
- package/dist/{chunk-2W34HX2U.js → chunk-6HWBRZIN.js} +47 -191
- package/dist/chunk-6HWBRZIN.js.map +1 -0
- package/dist/{chunk-SUTMSDQ2.js → chunk-ADMEPUBT.js} +3 -3
- package/dist/{chunk-VZVEP2OZ.js → chunk-B7XYNRJQ.js} +2 -2
- package/dist/{chunk-GB2XPITA.js → chunk-BBT6AVUG.js} +2 -2
- package/dist/{chunk-PK7EKJ5T.js → chunk-BKVHX6FU.js} +4 -4
- package/dist/{chunk-QBVP3SQP.js → chunk-D4N2V43Z.js} +4 -4
- package/dist/{chunk-6AGESHHM.js → chunk-EFW7CAG4.js} +2 -2
- package/dist/{chunk-H26VDFDS.js → chunk-EIFCP6CZ.js} +2 -2
- package/dist/{chunk-GCKHSBEN.js → chunk-FBMZJEB3.js} +2 -2
- package/dist/{chunk-2UCC26MO.js → chunk-FQXWVS6J.js} +8 -8
- package/dist/{chunk-5REEVKGH.js → chunk-FUCPZVRY.js} +2 -2
- package/dist/{chunk-WN47MNSK.js → chunk-GDVZ5VII.js} +4 -4
- package/dist/{chunk-KBG463UK.js → chunk-GV56WGL2.js} +321 -3308
- package/dist/chunk-GV56WGL2.js.map +1 -0
- package/dist/{chunk-IJ62BB2T.js → chunk-HA6MQMOY.js} +6 -6
- package/dist/{chunk-DNZUBCGZ.js → chunk-HQR2ZBHW.js} +3 -3
- package/dist/{chunk-DFCQ6BMI.js → chunk-IGSHYP74.js} +4 -4
- package/dist/{chunk-ABHG6I3G.js → chunk-J6IDQGJL.js} +4 -4
- package/dist/{chunk-GDLHTI5R.js → chunk-JPQDNYXH.js} +2 -2
- package/dist/{chunk-VVVKBUBO.js → chunk-JROBZ7JA.js} +2 -2
- package/dist/{chunk-BD7IXBWE.js → chunk-KGEQJ5CC.js} +5 -5
- package/dist/{chunk-LQZQ5KGG.js → chunk-LBSCW232.js} +4 -4
- package/dist/{chunk-G6FNWRAI.js → chunk-LKP7QDFN.js} +4 -4
- package/dist/{chunk-55GMOVKW.js → chunk-LPIF5LIE.js} +2 -2
- package/dist/chunk-M42DZCOU.js +164 -0
- package/dist/chunk-M42DZCOU.js.map +1 -0
- package/dist/{chunk-ZXXFP2LA.js → chunk-MSRU4D4P.js} +2 -2
- package/dist/{chunk-QJRQ4BRC.js → chunk-NSBXVPZL.js} +11 -11
- package/dist/{chunk-Z5YHMRLF.js → chunk-ODRPL3WB.js} +2 -2
- package/dist/{chunk-XU73V5XT.js → chunk-OPXWPJDA.js} +10 -10
- package/dist/chunk-PCQ7ELJH.js +3081 -0
- package/dist/chunk-PCQ7ELJH.js.map +1 -0
- package/dist/{chunk-3E2X2RBU.js → chunk-PCS4VJBV.js} +6 -6
- package/dist/{chunk-GXN7RRHR.js → chunk-PWBH7DCQ.js} +3 -3
- package/dist/{chunk-6M5VJOC2.js → chunk-QLWC7MKD.js} +33 -32
- package/dist/chunk-QLWC7MKD.js.map +1 -0
- package/dist/{chunk-EAUIQADY.js → chunk-R4WXQIOZ.js} +6 -6
- package/dist/{chunk-AO5TSDKT.js → chunk-RLT5SEML.js} +5 -5
- package/dist/{chunk-XG6PVB5S.js → chunk-SSQZB5SQ.js} +1 -11
- package/dist/chunk-SSQZB5SQ.js.map +1 -0
- package/dist/chunk-T7JAOYE5.js +393 -0
- package/dist/chunk-T7JAOYE5.js.map +1 -0
- package/dist/chunk-TU2WUBVZ.js +2 -0
- package/dist/{chunk-D2UW3ZCK.js → chunk-U7CTFN2J.js} +12 -10
- package/dist/{chunk-D2UW3ZCK.js.map → chunk-U7CTFN2J.js.map} +1 -1
- package/dist/{chunk-G7XD4QH5.js → chunk-VSEBFHAY.js} +10 -7
- package/dist/{chunk-G7XD4QH5.js.map → chunk-VSEBFHAY.js.map} +1 -1
- package/dist/{chunk-RZVCWX5R.js → chunk-WDWXAYVH.js} +4 -4
- package/dist/{chunk-6LR73NMO.js → chunk-Y6DOMTQD.js} +10 -8
- package/dist/{chunk-6LR73NMO.js.map → chunk-Y6DOMTQD.js.map} +1 -1
- package/dist/chunk-ZPLVANY2.js +15 -0
- package/dist/chunk-ZPLVANY2.js.map +1 -0
- package/dist/{cli-4YYC6LCY.js → cli-3BTCK4AB.js} +18 -15
- package/dist/{cli-4YYC6LCY.js.map → cli-3BTCK4AB.js.map} +1 -1
- package/dist/{cli-BIIUKPTE.js → cli-4MF37HAQ.js} +15 -12
- package/dist/{cli-BIIUKPTE.js.map → cli-4MF37HAQ.js.map} +1 -1
- package/dist/{cli-V2DI3K2R.js → cli-6KZTHWGP.js} +17 -14
- package/dist/{cli-V2DI3K2R.js.map → cli-6KZTHWGP.js.map} +1 -1
- package/dist/{cli-EH3I4IUX.js → cli-DRMZBZLB.js} +38 -33
- package/dist/cli-DRMZBZLB.js.map +1 -0
- package/dist/{cli-HO62TOM2.js → cli-I62SRH3R.js} +10 -8
- package/dist/cli-JJMOVIKS.js +83 -0
- package/dist/cli-JJMOVIKS.js.map +1 -0
- package/dist/{cli-SGVFZOAW.js → cli-O4ABTN4Z.js} +25 -21
- package/dist/{cli-SGVFZOAW.js.map → cli-O4ABTN4Z.js.map} +1 -1
- package/dist/{cli-UETKXHJN.js → cli-ONTC5PKT.js} +3 -3
- package/dist/{cli-TELPAMJO.js → cli-RORDPAPE.js} +17 -14
- package/dist/{cli-TELPAMJO.js.map → cli-RORDPAPE.js.map} +1 -1
- package/dist/{cli-P2X7PNY6.js → cli-VID7PJS3.js} +17 -13
- package/dist/{cli-P2X7PNY6.js.map → cli-VID7PJS3.js.map} +1 -1
- package/dist/{cli-LWST5FQH.js → cli-VUKMWSSF.js} +3 -3
- package/dist/cli.js +18 -12
- package/dist/cli.js.map +1 -1
- package/dist/{config-TYXYQK3I.js → config-XDA42RJL.js} +3 -3
- package/dist/docmeta.js +9 -7
- package/dist/docmeta.js.map +1 -1
- package/dist/github-RY3FRA6P.js +29 -0
- package/dist/github-YKQSH7FS.js +34 -0
- package/dist/index.d.ts +1023 -915
- package/dist/index.js +106 -81
- package/dist/index.js.map +1 -1
- package/dist/{json-QR4G35KA.js → json-BXY44ED7.js} +13 -10
- package/dist/{lint-QTI7XK2A.js → lint-YJ2L22BW.js} +13 -10
- package/dist/list-NSG24VVX.js +31 -0
- package/dist/list-V6EGCSHX.js +34 -0
- package/dist/{page-FSXDXCDD.js → page-EV7OUBAU.js} +12 -9
- package/dist/{prepare-UPIBTFNS.js → prepare-JHJDJB6I.js} +17 -14
- package/dist/{prepare-UPIBTFNS.js.map → prepare-JHJDJB6I.js.map} +1 -1
- package/dist/{pretty-R4BQD2VH.js → pretty-Q5Y2PA64.js} +14 -11
- package/dist/{pretty-4IONWSEP.js → pretty-SCRK66M5.js} +13 -10
- package/dist/{reporters-FPP6JNDP.js → reporters-A5ADKDYR.js} +12 -9
- package/dist/{reporters-DHO2BXAD.js → reporters-RBYTASMI.js} +5 -5
- package/dist/run-BUE2DDXN.js +36 -0
- package/dist/{term-ASM4LVYC.js → term-CQAGNG3Q.js} +17 -14
- package/dist/{term-ASM4LVYC.js.map → term-CQAGNG3Q.js.map} +1 -1
- package/dist/{validate-7JI3H57P.js → validate-ZBW44RHT.js} +6 -5
- package/dist/validate-ZBW44RHT.js.map +1 -0
- package/package.json +1 -1
- package/plugin/manni/.claude-plugin/plugin.json +1 -1
- package/dist/calibrate-LUA3DWKD.js +0 -36
- package/dist/check-PTECPIIB.js +0 -26
- package/dist/chunk-2W34HX2U.js.map +0 -1
- package/dist/chunk-6M5VJOC2.js.map +0 -1
- package/dist/chunk-KBG463UK.js.map +0 -1
- package/dist/chunk-XG6PVB5S.js.map +0 -1
- package/dist/cli-EH3I4IUX.js.map +0 -1
- package/dist/github-ESK45CEZ.js +0 -26
- package/dist/github-WER7JUTN.js +0 -31
- package/dist/list-JO4G3TS3.js +0 -30
- package/dist/list-O2MJUP5V.js +0 -28
- package/dist/run-YH5Z7RJ7.js +0 -32
- /package/dist/{batch-6NICDKRE.js.map → batch-UAULUMGH.js.map} +0 -0
- /package/dist/{build-3KP2K3XN.js.map → build-QSPNK5AL.js.map} +0 -0
- /package/dist/{calibrate-LUA3DWKD.js.map → calibrate-KXN4URPM.js.map} +0 -0
- /package/dist/{capture-NETOHCB4.js.map → capture-JHTSUPUC.js.map} +0 -0
- /package/dist/{check-7B77ZD2N.js.map → check-MDGXEUWL.js.map} +0 -0
- /package/dist/{check-E4QCB7LS.js.map → check-WOQRKNZK.js.map} +0 -0
- /package/dist/{check-PTECPIIB.js.map → check-YEOYBFST.js.map} +0 -0
- /package/dist/{chunk-2JV7C4YV.js.map → chunk-2DRHT73U.js.map} +0 -0
- /package/dist/{chunk-CCWMACJL.js.map → chunk-2IAZEB45.js.map} +0 -0
- /package/dist/{chunk-ZHRPH52H.js.map → chunk-2IR4T5PO.js.map} +0 -0
- /package/dist/{chunk-RODZ7MB7.js.map → chunk-4CK6ZSOK.js.map} +0 -0
- /package/dist/{chunk-7Y3N4Y72.js.map → chunk-4D5IZSXM.js.map} +0 -0
- /package/dist/{chunk-4DLF5SA4.js.map → chunk-4VBSTXN6.js.map} +0 -0
- /package/dist/{chunk-SUTMSDQ2.js.map → chunk-ADMEPUBT.js.map} +0 -0
- /package/dist/{chunk-VZVEP2OZ.js.map → chunk-B7XYNRJQ.js.map} +0 -0
- /package/dist/{chunk-GB2XPITA.js.map → chunk-BBT6AVUG.js.map} +0 -0
- /package/dist/{chunk-PK7EKJ5T.js.map → chunk-BKVHX6FU.js.map} +0 -0
- /package/dist/{chunk-QBVP3SQP.js.map → chunk-D4N2V43Z.js.map} +0 -0
- /package/dist/{chunk-6AGESHHM.js.map → chunk-EFW7CAG4.js.map} +0 -0
- /package/dist/{chunk-H26VDFDS.js.map → chunk-EIFCP6CZ.js.map} +0 -0
- /package/dist/{chunk-GCKHSBEN.js.map → chunk-FBMZJEB3.js.map} +0 -0
- /package/dist/{chunk-2UCC26MO.js.map → chunk-FQXWVS6J.js.map} +0 -0
- /package/dist/{chunk-5REEVKGH.js.map → chunk-FUCPZVRY.js.map} +0 -0
- /package/dist/{chunk-WN47MNSK.js.map → chunk-GDVZ5VII.js.map} +0 -0
- /package/dist/{chunk-IJ62BB2T.js.map → chunk-HA6MQMOY.js.map} +0 -0
- /package/dist/{chunk-DNZUBCGZ.js.map → chunk-HQR2ZBHW.js.map} +0 -0
- /package/dist/{chunk-DFCQ6BMI.js.map → chunk-IGSHYP74.js.map} +0 -0
- /package/dist/{chunk-ABHG6I3G.js.map → chunk-J6IDQGJL.js.map} +0 -0
- /package/dist/{chunk-GDLHTI5R.js.map → chunk-JPQDNYXH.js.map} +0 -0
- /package/dist/{chunk-VVVKBUBO.js.map → chunk-JROBZ7JA.js.map} +0 -0
- /package/dist/{chunk-BD7IXBWE.js.map → chunk-KGEQJ5CC.js.map} +0 -0
- /package/dist/{chunk-LQZQ5KGG.js.map → chunk-LBSCW232.js.map} +0 -0
- /package/dist/{chunk-G6FNWRAI.js.map → chunk-LKP7QDFN.js.map} +0 -0
- /package/dist/{chunk-55GMOVKW.js.map → chunk-LPIF5LIE.js.map} +0 -0
- /package/dist/{chunk-ZXXFP2LA.js.map → chunk-MSRU4D4P.js.map} +0 -0
- /package/dist/{chunk-QJRQ4BRC.js.map → chunk-NSBXVPZL.js.map} +0 -0
- /package/dist/{chunk-Z5YHMRLF.js.map → chunk-ODRPL3WB.js.map} +0 -0
- /package/dist/{chunk-XU73V5XT.js.map → chunk-OPXWPJDA.js.map} +0 -0
- /package/dist/{chunk-3E2X2RBU.js.map → chunk-PCS4VJBV.js.map} +0 -0
- /package/dist/{chunk-GXN7RRHR.js.map → chunk-PWBH7DCQ.js.map} +0 -0
- /package/dist/{chunk-EAUIQADY.js.map → chunk-R4WXQIOZ.js.map} +0 -0
- /package/dist/{chunk-AO5TSDKT.js.map → chunk-RLT5SEML.js.map} +0 -0
- /package/dist/{cli-HO62TOM2.js.map → chunk-TU2WUBVZ.js.map} +0 -0
- /package/dist/{chunk-RZVCWX5R.js.map → chunk-WDWXAYVH.js.map} +0 -0
- /package/dist/{config-TYXYQK3I.js.map → cli-I62SRH3R.js.map} +0 -0
- /package/dist/{cli-UETKXHJN.js.map → cli-ONTC5PKT.js.map} +0 -0
- /package/dist/{cli-LWST5FQH.js.map → cli-VUKMWSSF.js.map} +0 -0
- /package/dist/{github-ESK45CEZ.js.map → config-XDA42RJL.js.map} +0 -0
- /package/dist/{github-WER7JUTN.js.map → github-RY3FRA6P.js.map} +0 -0
- /package/dist/{json-QR4G35KA.js.map → github-YKQSH7FS.js.map} +0 -0
- /package/dist/{lint-QTI7XK2A.js.map → json-BXY44ED7.js.map} +0 -0
- /package/dist/{list-JO4G3TS3.js.map → lint-YJ2L22BW.js.map} +0 -0
- /package/dist/{list-O2MJUP5V.js.map → list-NSG24VVX.js.map} +0 -0
- /package/dist/{page-FSXDXCDD.js.map → list-V6EGCSHX.js.map} +0 -0
- /package/dist/{pretty-4IONWSEP.js.map → page-EV7OUBAU.js.map} +0 -0
- /package/dist/{pretty-R4BQD2VH.js.map → pretty-Q5Y2PA64.js.map} +0 -0
- /package/dist/{reporters-DHO2BXAD.js.map → pretty-SCRK66M5.js.map} +0 -0
- /package/dist/{reporters-FPP6JNDP.js.map → reporters-A5ADKDYR.js.map} +0 -0
- /package/dist/{run-YH5Z7RJ7.js.map → reporters-RBYTASMI.js.map} +0 -0
- /package/dist/{validate-7JI3H57P.js.map → run-BUE2DDXN.js.map} +0 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/shared/exec.ts
|
|
4
|
+
import { realExec } from "@hawkeyexl/inference";
|
|
5
|
+
function outputTail(result, maxChars = 400) {
|
|
6
|
+
const text = (result.stderr.trim() || result.stdout.trim()).trim();
|
|
7
|
+
if (text.length <= maxChars) return text;
|
|
8
|
+
return `\u2026${text.slice(-maxChars)}`;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export {
|
|
12
|
+
outputTail,
|
|
13
|
+
realExec
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=chunk-ZPLVANY2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/shared/exec.ts"],"sourcesContent":["/**\n * Process execution for every grader in the family that runs a program. The\n * implementation lives in `@hawkeyexl/inference`: the judge's subprocess\n * provider and the command graders were running copies of the same\n * cross-spawn wrapper, and the Windows-specific parts (npm `.cmd` shim\n * resolution without `shell: true`, stdin piping past the ~32K command-line\n * limit, and StringDecoder-backed output so multi-byte UTF-8 survives chunk\n * boundaries) are exactly the parts worth having in one place.\n *\n * Shared rather than per domain: `manni docevals` and `manni tracevals` both\n * run `command` evals, and both reach the OS through this one wrapper.\n */\nimport type { ExecResult } from \"@hawkeyexl/inference\";\n\nexport { realExec } from \"@hawkeyexl/inference\";\n\n/** Truncate command output for finding messages. */\nexport function outputTail(result: ExecResult, maxChars = 400): string {\n const text = (result.stderr.trim() || result.stdout.trim()).trim();\n if (text.length <= maxChars) return text;\n return `…${text.slice(-maxChars)}`;\n}\n\n/**\n * How a finished process is described in a finding: \"exited 2\", or the truth\n * when there was no exit code.\n *\n * `code` is null when the process was killed by a signal rather than exiting.\n * \"exited null\" describes nothing a reader can act on, and it is the case a\n * timeout produces — so it is the one worth naming.\n */\nexport function exited(code: number | null): string {\n return code === null ? \"was killed before exiting\" : `exited ${code}`;\n}\n"],"mappings":";;;AAcA,SAAS,gBAAgB;AAGlB,SAAS,WAAW,QAAoB,WAAW,KAAa;AACrE,QAAM,QAAQ,OAAO,OAAO,KAAK,KAAK,OAAO,OAAO,KAAK,GAAG,KAAK;AACjE,MAAI,KAAK,UAAU,SAAU,QAAO;AACpC,SAAO,SAAI,KAAK,MAAM,CAAC,QAAQ,CAAC;AAClC;","names":[]}
|
|
@@ -3,27 +3,30 @@ import {
|
|
|
3
3
|
KeyError,
|
|
4
4
|
runKeyRotate,
|
|
5
5
|
runKeySet
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-NSBXVPZL.js";
|
|
7
|
+
import "./chunk-FQXWVS6J.js";
|
|
8
|
+
import "./chunk-PCS4VJBV.js";
|
|
9
|
+
import "./chunk-ADMEPUBT.js";
|
|
10
|
+
import "./chunk-4D5IZSXM.js";
|
|
11
|
+
import "./chunk-WDWXAYVH.js";
|
|
12
12
|
import "./chunk-PCE7QHXJ.js";
|
|
13
13
|
import "./chunk-77AINBYM.js";
|
|
14
|
-
import "./chunk-
|
|
14
|
+
import "./chunk-BKVHX6FU.js";
|
|
15
15
|
import "./chunk-IKEWBMCN.js";
|
|
16
|
-
import "./chunk-
|
|
17
|
-
import "./chunk-
|
|
16
|
+
import "./chunk-TU2WUBVZ.js";
|
|
17
|
+
import "./chunk-LKP7QDFN.js";
|
|
18
|
+
import "./chunk-6HWBRZIN.js";
|
|
19
|
+
import "./chunk-M42DZCOU.js";
|
|
20
|
+
import "./chunk-PCQ7ELJH.js";
|
|
18
21
|
import {
|
|
19
22
|
collect,
|
|
20
23
|
explicitFalse,
|
|
21
24
|
splitList
|
|
22
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-GV56WGL2.js";
|
|
23
26
|
import {
|
|
24
27
|
COMMON_FORMAT_LIST
|
|
25
|
-
} from "./chunk-
|
|
26
|
-
import "./chunk-
|
|
28
|
+
} from "./chunk-D4N2V43Z.js";
|
|
29
|
+
import "./chunk-VSEBFHAY.js";
|
|
27
30
|
import {
|
|
28
31
|
fail
|
|
29
32
|
} from "./chunk-YEUYKR62.js";
|
|
@@ -32,14 +35,14 @@ import {
|
|
|
32
35
|
shouldColor
|
|
33
36
|
} from "./chunk-RNVYGWIC.js";
|
|
34
37
|
import "./chunk-MNH7QO4Z.js";
|
|
35
|
-
import "./chunk-
|
|
38
|
+
import "./chunk-QLWC7MKD.js";
|
|
36
39
|
import {
|
|
37
40
|
notice
|
|
38
41
|
} from "./chunk-HX44GB4Z.js";
|
|
39
42
|
import "./chunk-QCHVR4ZM.js";
|
|
40
43
|
import {
|
|
41
44
|
package_default
|
|
42
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-2MJ62AYQ.js";
|
|
43
46
|
import "./chunk-OWBRDNRZ.js";
|
|
44
47
|
import "./chunk-G3T47CFV.js";
|
|
45
48
|
import "./chunk-2H7UOFLK.js";
|
|
@@ -228,4 +231,4 @@ function buildProgram() {
|
|
|
228
231
|
export {
|
|
229
232
|
buildProgram
|
|
230
233
|
};
|
|
231
|
-
//# sourceMappingURL=cli-
|
|
234
|
+
//# sourceMappingURL=cli-3BTCK4AB.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/key/cli.ts","../src/key/reporters/json.ts","../src/key/reporters/pretty.ts"],"sourcesContent":["/**\n * The `key` domain's commander program. Mounted by `src/cli.ts` under\n * `manni key`; no entry point of its own. Proposal 0045 extends 0034's\n * grammar: a domain is a tool, or a family resource with verbs. `key` is the\n * second kind, with two verbs, `set` and `rotate`, and no default subcommand.\n *\n * clig.dev as every tool has it: the report to stdout, diagnostics to stderr,\n * colour only on a TTY and never under `NO_COLOR`/`--no-color`, exit `0` done,\n * `1` a value that could not be re-encrypted, `2` operational/usage. Nothing\n * this program prints is ever a key.\n */\nimport { Command } from \"commander\";\nimport pkg from \"../../package.json\" with { type: \"json\" };\nimport { collect, explicitFalse, splitList } from \"../shared/cli-options.js\";\nimport { shouldColor } from \"../shared/color.js\";\nimport { fail } from \"../shared/run.js\";\nimport { notice } from \"../shared/warn.js\";\nimport { COMMON_FORMAT_LIST } from \"../meta/internal.js\";\nimport { runKeyRotate } from \"./commands/rotate.js\";\nimport { runKeySet } from \"./commands/set.js\";\nimport { KeyError } from \"./errors.js\";\nimport { renderRotateJson } from \"./reporters/json.js\";\nimport { BASELINE_NOTICE, renderRotatePretty, setMessage } from \"./reporters/pretty.js\";\n\nconst ROTATE_FORMATS = [\"pretty\", \"json\"] as const;\ntype RotateFormat = (typeof ROTATE_FORMATS)[number];\n\nfunction isRotateFormat(value: string): value is RotateFormat {\n return (ROTATE_FORMATS as readonly string[]).includes(value);\n}\n\n/** What commander hands `set`'s action. */\ninterface SetCliOptions {\n /** `-c, --config <path>`. */\n config?: string;\n dryRun?: boolean;\n}\n\n/**\n * What commander hands `rotate`'s action. The `--no-<thing>` flags are\n * `boolean` and never `undefined`: commander supplies `true` when the flag is\n * absent, so only the explicit `false` travels to the core (`explicitFalse`).\n */\ninterface RotateCliOptions {\n to?: string;\n /** `--collection <name>`, repeatable; commander's default value is `[]`. */\n collection: string[];\n /** `--ext <list>`; the command splits it. */\n ext?: string;\n /** `--exclude <glob>`, repeatable; commander's default value is `[]`. */\n exclude: string[];\n as?: string;\n config?: string;\n allowEmpty?: boolean;\n /** `--no-gitignore`. */\n gitignore: boolean;\n root?: string;\n dryRun?: boolean;\n /** `-f, --format <format>`. Always a string: the declaration has a default. */\n format: string;\n}\n\nexport function buildProgram(): Command {\n const program = new Command();\n program\n .name(\"key\")\n .description(\"Set and rotate the family key that encrypted values are encrypted with.\")\n .version(pkg.version, \"-V, --version\")\n .option(\"--no-color\", \"disable colored output\")\n // A pointer, not the whole help screen: the message that precedes it\n // already names the offending flag.\n .showHelpAfterError(\"(add --help for usage)\")\n // MUST come before the `.command()` calls below. `copyInheritedSettings`\n // copies `_exitCallback` by value at subcommand-creation time, so an\n // `exitOverride()` installed afterwards leaves every subcommand still\n // calling `process.exit(1)`.\n .exitOverride();\n\n /** This domain's `--no-color`, wherever the domain is mounted. */\n const color = (): boolean =>\n shouldColor({ noColor: program.opts().color === false, isTTY: process.stdout.isTTY });\n\n program\n .command(\"set\")\n .description(\"Write the family encryption key to manni.config.yaml; generate one when no value is given\")\n .argument(\"[value]\", \"the key, at least 32 hex or base64url characters (default: 64 random hex)\")\n .option(\n \"-c, --config <path>\",\n \"the config file to write (default: the nearest manni.config.yaml, else a new one at the git root)\",\n )\n .option(\"--dry-run\", \"say what would be written; write nothing\")\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Examples:\",\n \" manni key set # generate 256 bits into manni.config.yaml\",\n \" manni key set --dry-run # name the file, write nothing\",\n \" manni key set -c ops/manni.config.yaml 0123456789abcdef0123456789abcdef\",\n ].join(\"\\n\"),\n )\n .action(async (value: string | undefined, options: SetCliOptions) => {\n try {\n const result = await runKeySet({\n value,\n configPath: options.config,\n dryRun: Boolean(options.dryRun),\n onNotice: notice,\n });\n process.stdout.write(`${setMessage(result)}\\n`);\n process.exitCode = 0;\n } catch (err) {\n fail(err);\n }\n });\n\n program\n .command(\"rotate\")\n .description(\"Re-encrypt every encrypted value under a new key, then write the key\")\n .argument(\"[paths...]\", \"files, directories, or globs (default: every collection)\")\n .option(\n \"--to <value>\",\n \"the new key (default: 64 random hex); required for a narrowed run and a key from MANNI_ENCRYPTION_KEY\",\n )\n .option(\"--collection <name>\", \"configured collection to run over; repeatable\", collect, [])\n .option(\"--ext <list>\", \"comma-separated extensions for directory walks\")\n .option(\"--exclude <glob>\", \"glob to exclude; repeatable\", collect, [])\n .option(\"--as <format>\", \"force an input format for every input\")\n .option(\"-c, --config <path>\", \"path to a manni config file\")\n .option(\"--allow-empty\", \"treat zero matched files as success\")\n .option(\"--no-gitignore\", \"include files .gitignore covers\")\n .option(\n \"--root <dir>\",\n \"directory cited sources resolve from (default: cite.root from config, else the git root)\",\n )\n .option(\"--dry-run\", \"print what would change; write nothing\")\n .option(\"-f, --format <format>\", `output: ${ROTATE_FORMATS.join(\" | \")}`, \"pretty\")\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Examples:\",\n \" manni key rotate # every collection, then the key\",\n \" manni key rotate --dry-run # see every change first\",\n ' manni key rotate --collection site --to \"$NEW_KEY\" # part of the family',\n ' MANNI_ENCRYPTION_KEY=… manni key rotate --to \"$NEW_KEY\"',\n ].join(\"\\n\"),\n )\n .action(async (paths: string[], options: RotateCliOptions) => {\n try {\n const format = options.format;\n if (!isRotateFormat(format)) {\n throw new KeyError(`Unknown --format \"${format}\". Use ${COMMON_FORMAT_LIST}.`);\n }\n const result = await runKeyRotate({\n inputs: paths,\n collection: options.collection,\n to: options.to,\n exts: options.ext ? splitList(options.ext) : undefined,\n exclude: options.exclude,\n as: options.as,\n configPath: options.config,\n // `undefined` rather than `false` when absent.\n allowEmpty: options.allowEmpty ? true : undefined,\n respectGitignore: explicitFalse(options.gitignore),\n root: options.root,\n dryRun: Boolean(options.dryRun),\n onNotice: notice,\n });\n if (format === \"json\") {\n process.stdout.write(`${renderRotateJson(result)}\\n`);\n // stdout is the JSON's; the notice is a diagnostic.\n if (result.baselineStale) notice(BASELINE_NOTICE);\n } else {\n process.stdout.write(`${renderRotatePretty(result, { color: color() })}\\n`);\n }\n process.exitCode = result.exitCode;\n } catch (err) {\n fail(err);\n }\n });\n\n return program;\n}\n","/**\n * JSON output for `key rotate`: every page and every local external-metadata\n * manifest with something encrypted in it, each value's full ciphertext\n * before and after, and the counts. The key is never in it.\n */\nimport type { KeyRotateResult } from \"../types.js\";\n\nexport function renderRotateJson(result: KeyRotateResult): string {\n return JSON.stringify(\n {\n pages: result.pages,\n manifests: result.manifests,\n reencrypted: result.reencrypted,\n skipped: result.skipped,\n keyWritten: result.keyWritten,\n },\n null,\n 2,\n );\n}\n","/**\n * Pretty output for `key set` and `key rotate`. A ciphertext is shown as `~`\n * and its first four characters, then `…`, with a citation's line suffix\n * after it: `~AQx7…`, `~AQm4…:2`. The full values are in `-f json`; the key\n * is in neither. Colour via `shouldColor`; never under `--no-color`/`NO_COLOR`.\n */\nimport { palette } from \"../../shared/color.js\";\nimport type { KeyRotateResult, KeySetResult, RotatedValue, SkippedValue } from \"../types.js\";\n\nexport interface PrettyOptions {\n color: boolean;\n}\n\n/** Said at the end of a writing rotation when a citation baseline exists. */\nexport const BASELINE_NOTICE =\n \"The citation baseline fingerprints id-less encrypted citations by their pin; re-record it with `manni cite check --write-baseline`.\";\n\nconst NARROWED =\n \"Key not written: this run covered part of the family. Finish with a whole run under the same key: `manni key rotate --to <the same value>`.\";\nconst FROM_ENV =\n \"Key not written: it comes from MANNI_ENCRYPTION_KEY. Update the secret to the value you passed.\";\n\nconst plural = (n: number, one: string, many = `${one}s`): string =>\n `${String(n)} ${n === 1 ? one : many}`;\n\n/** What `set` says: the file, never the key. */\nexport function setMessage(result: KeySetResult): string {\n return result.dryRun\n ? `Would write encryptionKey to ${result.source}.`\n : `Encryption key written to ${result.source}.`;\n}\n\n/** `~AQx7…`, and a citation's line suffix after it: `~AQm4…:2`. */\nexport function shortCiphertext(value: string): string {\n // base64url has no `:`, so the first one starts the line suffix.\n const colon = value.indexOf(\":\");\n const token = colon === -1 ? value : value.slice(0, colon);\n const suffix = colon === -1 ? \"\" : value.slice(colon);\n return `${token.slice(0, 5)}…${suffix}`;\n}\n\n/** A metadata value by its pointer; a citation by its id, else where it sits. */\nfunction nameOf(row: RotatedValue | SkippedValue): string {\n if (row.kind === \"metadata\") return row.pointer;\n if (row.id !== undefined) return row.id;\n if (row.index !== undefined) return `/citations/${String(row.index)}`;\n return `line ${String(row.line ?? 0)}`;\n}\n\nfunction closing(result: KeyRotateResult): string | undefined {\n switch (result.outcome) {\n case \"written\":\n return result.configSource === undefined\n ? undefined\n : `Encryption key written to ${result.configSource}.`;\n case \"finished\":\n // Said before the counts: the key was written by the run that stopped.\n return undefined;\n case \"narrowed\":\n return NARROWED;\n case \"env\":\n return FROM_ENV;\n case \"skipped\":\n return result.skipped === 1\n ? \"Key not written: 1 value could not be re-encrypted. Fix it and rotate again.\"\n : `Key not written: ${String(result.skipped)} values could not be re-encrypted. Fix them and rotate again.`;\n case \"dry-run\":\n return \"Dry run: nothing written.\";\n }\n}\n\nexport function renderRotatePretty(result: KeyRotateResult, opts: PrettyOptions): string {\n const c = palette(opts.color);\n const lines: string[] = [];\n for (const page of result.pages) {\n for (const row of page.rewritten) {\n // A metadata value has no line suffix; two spaces keep its arrow in the\n // column a `:L` suffix would take.\n const gap = row.kind === \"metadata\" ? \" \" : \" \";\n lines.push(\n `${page.file}: ${nameOf(row)} ${c.dim(shortCiphertext(row.from))}${gap}-> ${shortCiphertext(row.to)}`,\n );\n }\n for (const row of page.skipped) {\n lines.push(`${page.file}: ${nameOf(row)} ${c.red(\"skipped:\")} ${row.message}`);\n }\n }\n // A manifest value is named by the entry it belongs to and the pointer\n // inside it, so one line says which document's private half moved.\n for (const manifest of result.manifests) {\n for (const row of manifest.rewritten) {\n lines.push(\n `${manifest.file}: ${row.entry}${row.pointer} ${c.dim(shortCiphertext(row.from))} -> ${shortCiphertext(row.to)}`,\n );\n }\n for (const row of manifest.skipped) {\n lines.push(\n `${manifest.file}: ${row.entry}${row.pointer} ${c.red(\"skipped:\")} ${row.message}`,\n );\n }\n }\n if (result.outcome === \"finished\" && result.configSource !== undefined) {\n lines.push(`Finished the interrupted rotation in ${result.configSource}.`);\n }\n const files =\n result.pages.filter((page) => page.rewritten.length > 0).length +\n result.manifests.filter((manifest) => manifest.rewritten.length > 0).length;\n lines.push(\n `${plural(result.reencrypted, \"value\")} re-encrypted in ${plural(files, \"file\")}, ${String(result.skipped)} skipped`,\n );\n const last = closing(result);\n if (last !== undefined) lines.push(result.outcome === \"skipped\" ? c.red(last) : last);\n if (result.baselineStale) lines.push(BASELINE_NOTICE);\n return lines.join(\"\\n\");\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWA,SAAS,eAAe;;;ACJjB,SAAS,iBAAiB,QAAiC;AAChE,SAAO,KAAK;AAAA,IACV;AAAA,MACE,OAAO,OAAO;AAAA,MACd,WAAW,OAAO;AAAA,MAClB,aAAa,OAAO;AAAA,MACpB,SAAS,OAAO;AAAA,MAChB,YAAY,OAAO;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACLO,IAAM,kBACX;AAEF,IAAM,WACJ;AACF,IAAM,WACJ;AAEF,IAAM,SAAS,CAAC,GAAW,KAAa,OAAO,GAAG,GAAG,QACnD,GAAG,OAAO,CAAC,CAAC,IAAI,MAAM,IAAI,MAAM,IAAI;AAG/B,SAAS,WAAW,QAA8B;AACvD,SAAO,OAAO,SACV,gCAAgC,OAAO,MAAM,MAC7C,6BAA6B,OAAO,MAAM;AAChD;AAGO,SAAS,gBAAgB,OAAuB;AAErD,QAAM,QAAQ,MAAM,QAAQ,GAAG;AAC/B,QAAM,QAAQ,UAAU,KAAK,QAAQ,MAAM,MAAM,GAAG,KAAK;AACzD,QAAM,SAAS,UAAU,KAAK,KAAK,MAAM,MAAM,KAAK;AACpD,SAAO,GAAG,MAAM,MAAM,GAAG,CAAC,CAAC,SAAI,MAAM;AACvC;AAGA,SAAS,OAAO,KAA0C;AACxD,MAAI,IAAI,SAAS,WAAY,QAAO,IAAI;AACxC,MAAI,IAAI,OAAO,OAAW,QAAO,IAAI;AACrC,MAAI,IAAI,UAAU,OAAW,QAAO,cAAc,OAAO,IAAI,KAAK,CAAC;AACnE,SAAO,QAAQ,OAAO,IAAI,QAAQ,CAAC,CAAC;AACtC;AAEA,SAAS,QAAQ,QAA6C;AAC5D,UAAQ,OAAO,SAAS;AAAA,IACtB,KAAK;AACH,aAAO,OAAO,iBAAiB,SAC3B,SACA,6BAA6B,OAAO,YAAY;AAAA,IACtD,KAAK;AAEH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO,OAAO,YAAY,IACtB,iFACA,oBAAoB,OAAO,OAAO,OAAO,CAAC;AAAA,IAChD,KAAK;AACH,aAAO;AAAA,EACX;AACF;AAEO,SAAS,mBAAmB,QAAyB,MAA6B;AACvF,QAAM,IAAI,QAAQ,KAAK,KAAK;AAC5B,QAAM,QAAkB,CAAC;AACzB,aAAW,QAAQ,OAAO,OAAO;AAC/B,eAAW,OAAO,KAAK,WAAW;AAGhC,YAAM,MAAM,IAAI,SAAS,aAAa,OAAO;AAC7C,YAAM;AAAA,QACJ,GAAG,KAAK,IAAI,KAAK,OAAO,GAAG,CAAC,KAAK,EAAE,IAAI,gBAAgB,IAAI,IAAI,CAAC,CAAC,GAAG,GAAG,MAAM,gBAAgB,IAAI,EAAE,CAAC;AAAA,MACtG;AAAA,IACF;AACA,eAAW,OAAO,KAAK,SAAS;AAC9B,YAAM,KAAK,GAAG,KAAK,IAAI,KAAK,OAAO,GAAG,CAAC,KAAK,EAAE,IAAI,UAAU,CAAC,IAAI,IAAI,OAAO,EAAE;AAAA,IAChF;AAAA,EACF;AAGA,aAAW,YAAY,OAAO,WAAW;AACvC,eAAW,OAAO,SAAS,WAAW;AACpC,YAAM;AAAA,QACJ,GAAG,SAAS,IAAI,KAAK,IAAI,KAAK,GAAG,IAAI,OAAO,KAAK,EAAE,IAAI,gBAAgB,IAAI,IAAI,CAAC,CAAC,QAAQ,gBAAgB,IAAI,EAAE,CAAC;AAAA,MAClH;AAAA,IACF;AACA,eAAW,OAAO,SAAS,SAAS;AAClC,YAAM;AAAA,QACJ,GAAG,SAAS,IAAI,KAAK,IAAI,KAAK,GAAG,IAAI,OAAO,KAAK,EAAE,IAAI,UAAU,CAAC,IAAI,IAAI,OAAO;AAAA,MACnF;AAAA,IACF;AAAA,EACF;AACA,MAAI,OAAO,YAAY,cAAc,OAAO,iBAAiB,QAAW;AACtE,UAAM,KAAK,wCAAwC,OAAO,YAAY,GAAG;AAAA,EAC3E;AACA,QAAM,QACJ,OAAO,MAAM,OAAO,CAAC,SAAS,KAAK,UAAU,SAAS,CAAC,EAAE,SACzD,OAAO,UAAU,OAAO,CAAC,aAAa,SAAS,UAAU,SAAS,CAAC,EAAE;AACvE,QAAM;AAAA,IACJ,GAAG,OAAO,OAAO,aAAa,OAAO,CAAC,oBAAoB,OAAO,OAAO,MAAM,CAAC,KAAK,OAAO,OAAO,OAAO,CAAC;AAAA,EAC5G;AACA,QAAM,OAAO,QAAQ,MAAM;AAC3B,MAAI,SAAS,OAAW,OAAM,KAAK,OAAO,YAAY,YAAY,EAAE,IAAI,IAAI,IAAI,IAAI;AACpF,MAAI,OAAO,cAAe,OAAM,KAAK,eAAe;AACpD,SAAO,MAAM,KAAK,IAAI;AACxB;;;AF1FA,IAAM,iBAAiB,CAAC,UAAU,MAAM;AAGxC,SAAS,eAAe,OAAsC;AAC5D,SAAQ,eAAqC,SAAS,KAAK;AAC7D;AAiCO,SAAS,eAAwB;AACtC,QAAM,UAAU,IAAI,QAAQ;AAC5B,UACG,KAAK,KAAK,EACV,YAAY,yEAAyE,EACrF,QAAQ,gBAAI,SAAS,eAAe,EACpC,OAAO,cAAc,wBAAwB,EAG7C,mBAAmB,wBAAwB,EAK3C,aAAa;AAGhB,QAAM,QAAQ,MACZ,YAAY,EAAE,SAAS,QAAQ,KAAK,EAAE,UAAU,OAAO,OAAO,QAAQ,OAAO,MAAM,CAAC;AAEtF,UACG,QAAQ,KAAK,EACb,YAAY,2FAA2F,EACvG,SAAS,WAAW,2EAA2E,EAC/F;AAAA,IACC;AAAA,IACA;AAAA,EACF,EACC,OAAO,aAAa,0CAA0C,EAC9D;AAAA,IACC;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE,KAAK,IAAI;AAAA,EACb,EACC,OAAO,OAAO,OAA2B,YAA2B;AACnE,QAAI;AACF,YAAM,SAAS,MAAM,UAAU;AAAA,QAC7B;AAAA,QACA,YAAY,QAAQ;AAAA,QACpB,QAAQ,QAAQ,QAAQ,MAAM;AAAA,QAC9B,UAAU;AAAA,MACZ,CAAC;AACD,cAAQ,OAAO,MAAM,GAAG,WAAW,MAAM,CAAC;AAAA,CAAI;AAC9C,cAAQ,WAAW;AAAA,IACrB,SAAS,KAAK;AACZ,WAAK,GAAG;AAAA,IACV;AAAA,EACF,CAAC;AAEH,UACG,QAAQ,QAAQ,EAChB,YAAY,sEAAsE,EAClF,SAAS,cAAc,0DAA0D,EACjF;AAAA,IACC;AAAA,IACA;AAAA,EACF,EACC,OAAO,uBAAuB,iDAAiD,SAAS,CAAC,CAAC,EAC1F,OAAO,gBAAgB,gDAAgD,EACvE,OAAO,oBAAoB,+BAA+B,SAAS,CAAC,CAAC,EACrE,OAAO,iBAAiB,uCAAuC,EAC/D,OAAO,uBAAuB,6BAA6B,EAC3D,OAAO,iBAAiB,qCAAqC,EAC7D,OAAO,kBAAkB,iCAAiC,EAC1D;AAAA,IACC;AAAA,IACA;AAAA,EACF,EACC,OAAO,aAAa,wCAAwC,EAC5D,OAAO,yBAAyB,WAAW,eAAe,KAAK,KAAK,CAAC,IAAI,QAAQ,EACjF;AAAA,IACC;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE,KAAK,IAAI;AAAA,EACb,EACC,OAAO,OAAO,OAAiB,YAA8B;AAC5D,QAAI;AACF,YAAM,SAAS,QAAQ;AACvB,UAAI,CAAC,eAAe,MAAM,GAAG;AAC3B,cAAM,IAAI,SAAS,qBAAqB,MAAM,UAAU,kBAAkB,GAAG;AAAA,MAC/E;AACA,YAAM,SAAS,MAAM,aAAa;AAAA,QAChC,QAAQ;AAAA,QACR,YAAY,QAAQ;AAAA,QACpB,IAAI,QAAQ;AAAA,QACZ,MAAM,QAAQ,MAAM,UAAU,QAAQ,GAAG,IAAI;AAAA,QAC7C,SAAS,QAAQ;AAAA,QACjB,IAAI,QAAQ;AAAA,QACZ,YAAY,QAAQ;AAAA;AAAA,QAEpB,YAAY,QAAQ,aAAa,OAAO;AAAA,QACxC,kBAAkB,cAAc,QAAQ,SAAS;AAAA,QACjD,MAAM,QAAQ;AAAA,QACd,QAAQ,QAAQ,QAAQ,MAAM;AAAA,QAC9B,UAAU;AAAA,MACZ,CAAC;AACD,UAAI,WAAW,QAAQ;AACrB,gBAAQ,OAAO,MAAM,GAAG,iBAAiB,MAAM,CAAC;AAAA,CAAI;AAEpD,YAAI,OAAO,cAAe,QAAO,eAAe;AAAA,MAClD,OAAO;AACL,gBAAQ,OAAO,MAAM,GAAG,mBAAmB,QAAQ,EAAE,OAAO,MAAM,EAAE,CAAC,CAAC;AAAA,CAAI;AAAA,MAC5E;AACA,cAAQ,WAAW,OAAO;AAAA,IAC5B,SAAS,KAAK;AACZ,WAAK,GAAG;AAAA,IACV;AAAA,EACF,CAAC;AAEH,SAAO;AACT;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/key/cli.ts","../src/key/reporters/json.ts","../src/key/reporters/pretty.ts"],"sourcesContent":["/**\n * The `key` domain's commander program. Mounted by `src/cli.ts` under\n * `manni key`; no entry point of its own. Proposal 0045 extends 0034's\n * grammar: a domain is a tool, or a family resource with verbs. `key` is the\n * second kind, with two verbs, `set` and `rotate`, and no default subcommand.\n *\n * clig.dev as every tool has it: the report to stdout, diagnostics to stderr,\n * colour only on a TTY and never under `NO_COLOR`/`--no-color`, exit `0` done,\n * `1` a value that could not be re-encrypted, `2` operational/usage. Nothing\n * this program prints is ever a key.\n */\nimport { Command } from \"commander\";\nimport pkg from \"../../package.json\" with { type: \"json\" };\nimport { collect, explicitFalse, splitList } from \"../shared/cli-options.js\";\nimport { shouldColor } from \"../shared/color.js\";\nimport { fail } from \"../shared/run.js\";\nimport { notice } from \"../shared/warn.js\";\nimport { COMMON_FORMAT_LIST } from \"../meta/internal.js\";\nimport { runKeyRotate } from \"./commands/rotate.js\";\nimport { runKeySet } from \"./commands/set.js\";\nimport { KeyError } from \"./errors.js\";\nimport { renderRotateJson } from \"./reporters/json.js\";\nimport { BASELINE_NOTICE, renderRotatePretty, setMessage } from \"./reporters/pretty.js\";\n\nconst ROTATE_FORMATS = [\"pretty\", \"json\"] as const;\ntype RotateFormat = (typeof ROTATE_FORMATS)[number];\n\nfunction isRotateFormat(value: string): value is RotateFormat {\n return (ROTATE_FORMATS as readonly string[]).includes(value);\n}\n\n/** What commander hands `set`'s action. */\ninterface SetCliOptions {\n /** `-c, --config <path>`. */\n config?: string;\n dryRun?: boolean;\n}\n\n/**\n * What commander hands `rotate`'s action. The `--no-<thing>` flags are\n * `boolean` and never `undefined`: commander supplies `true` when the flag is\n * absent, so only the explicit `false` travels to the core (`explicitFalse`).\n */\ninterface RotateCliOptions {\n to?: string;\n /** `--collection <name>`, repeatable; commander's default value is `[]`. */\n collection: string[];\n /** `--ext <list>`; the command splits it. */\n ext?: string;\n /** `--exclude <glob>`, repeatable; commander's default value is `[]`. */\n exclude: string[];\n as?: string;\n config?: string;\n allowEmpty?: boolean;\n /** `--no-gitignore`. */\n gitignore: boolean;\n root?: string;\n dryRun?: boolean;\n /** `-f, --format <format>`. Always a string: the declaration has a default. */\n format: string;\n}\n\nexport function buildProgram(): Command {\n const program = new Command();\n program\n .name(\"key\")\n .description(\"Set and rotate the family key that encrypted values are encrypted with.\")\n .version(pkg.version, \"-V, --version\")\n .option(\"--no-color\", \"disable colored output\")\n // A pointer, not the whole help screen: the message that precedes it\n // already names the offending flag.\n .showHelpAfterError(\"(add --help for usage)\")\n // MUST come before the `.command()` calls below. `copyInheritedSettings`\n // copies `_exitCallback` by value at subcommand-creation time, so an\n // `exitOverride()` installed afterwards leaves every subcommand still\n // calling `process.exit(1)`.\n .exitOverride();\n\n /** This domain's `--no-color`, wherever the domain is mounted. */\n const color = (): boolean =>\n shouldColor({ noColor: program.opts().color === false, isTTY: process.stdout.isTTY });\n\n program\n .command(\"set\")\n .description(\"Write the family encryption key to manni.config.yaml; generate one when no value is given\")\n .argument(\"[value]\", \"the key, at least 32 hex or base64url characters (default: 64 random hex)\")\n .option(\n \"-c, --config <path>\",\n \"the config file to write (default: the nearest manni.config.yaml, else a new one at the git root)\",\n )\n .option(\"--dry-run\", \"say what would be written; write nothing\")\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Examples:\",\n \" manni key set # generate 256 bits into manni.config.yaml\",\n \" manni key set --dry-run # name the file, write nothing\",\n \" manni key set -c ops/manni.config.yaml 0123456789abcdef0123456789abcdef\",\n ].join(\"\\n\"),\n )\n .action(async (value: string | undefined, options: SetCliOptions) => {\n try {\n const result = await runKeySet({\n value,\n configPath: options.config,\n dryRun: Boolean(options.dryRun),\n onNotice: notice,\n });\n process.stdout.write(`${setMessage(result)}\\n`);\n process.exitCode = 0;\n } catch (err) {\n fail(err);\n }\n });\n\n program\n .command(\"rotate\")\n .description(\"Re-encrypt every encrypted value under a new key, then write the key\")\n .argument(\"[paths...]\", \"files, directories, or globs (default: every collection)\")\n .option(\n \"--to <value>\",\n \"the new key (default: 64 random hex); required for a narrowed run and a key from MANNI_ENCRYPTION_KEY\",\n )\n .option(\"--collection <name>\", \"configured collection to run over; repeatable\", collect, [])\n .option(\"--ext <list>\", \"comma-separated extensions for directory walks\")\n .option(\"--exclude <glob>\", \"glob to exclude; repeatable\", collect, [])\n .option(\"--as <format>\", \"force an input format for every input\")\n .option(\"-c, --config <path>\", \"path to a manni config file\")\n .option(\"--allow-empty\", \"treat zero matched files as success\")\n .option(\"--no-gitignore\", \"include files .gitignore covers\")\n .option(\n \"--root <dir>\",\n \"directory cited sources resolve from (default: cite.root from config, else the git root)\",\n )\n .option(\"--dry-run\", \"print what would change; write nothing\")\n .option(\"-f, --format <format>\", `output: ${ROTATE_FORMATS.join(\" | \")}`, \"pretty\")\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Examples:\",\n \" manni key rotate # every collection, then the key\",\n \" manni key rotate --dry-run # see every change first\",\n ' manni key rotate --collection site --to \"$NEW_KEY\" # part of the family',\n ' MANNI_ENCRYPTION_KEY=… manni key rotate --to \"$NEW_KEY\"',\n ].join(\"\\n\"),\n )\n .action(async (paths: string[], options: RotateCliOptions) => {\n try {\n const format = options.format;\n if (!isRotateFormat(format)) {\n throw new KeyError(`Unknown --format \"${format}\". Use ${COMMON_FORMAT_LIST}.`);\n }\n const result = await runKeyRotate({\n inputs: paths,\n collection: options.collection,\n to: options.to,\n exts: options.ext ? splitList(options.ext) : undefined,\n exclude: options.exclude,\n as: options.as,\n configPath: options.config,\n // `undefined` rather than `false` when absent.\n allowEmpty: options.allowEmpty ? true : undefined,\n respectGitignore: explicitFalse(options.gitignore),\n root: options.root,\n dryRun: Boolean(options.dryRun),\n onNotice: notice,\n });\n if (format === \"json\") {\n process.stdout.write(`${renderRotateJson(result)}\\n`);\n // stdout is the JSON's; the notice is a diagnostic.\n if (result.baselineStale) notice(BASELINE_NOTICE);\n } else {\n process.stdout.write(`${renderRotatePretty(result, { color: color() })}\\n`);\n }\n process.exitCode = result.exitCode;\n } catch (err) {\n fail(err);\n }\n });\n\n return program;\n}\n","/**\n * JSON output for `key rotate`: every page and every local external-metadata\n * manifest with something encrypted in it, each value's full ciphertext\n * before and after, and the counts. The key is never in it.\n */\nimport type { KeyRotateResult } from \"../types.js\";\n\nexport function renderRotateJson(result: KeyRotateResult): string {\n return JSON.stringify(\n {\n pages: result.pages,\n manifests: result.manifests,\n reencrypted: result.reencrypted,\n skipped: result.skipped,\n keyWritten: result.keyWritten,\n },\n null,\n 2,\n );\n}\n","/**\n * Pretty output for `key set` and `key rotate`. A ciphertext is shown as `~`\n * and its first four characters, then `…`, with a citation's line suffix\n * after it: `~AQx7…`, `~AQm4…:2`. The full values are in `-f json`; the key\n * is in neither. Colour via `shouldColor`; never under `--no-color`/`NO_COLOR`.\n */\nimport { palette } from \"../../shared/color.js\";\nimport type { KeyRotateResult, KeySetResult, RotatedValue, SkippedValue } from \"../types.js\";\n\nexport interface PrettyOptions {\n color: boolean;\n}\n\n/** Said at the end of a writing rotation when a citation baseline exists. */\nexport const BASELINE_NOTICE =\n \"The citation baseline fingerprints id-less encrypted citations by their pin; re-record it with `manni cite check --write-baseline`.\";\n\nconst NARROWED =\n \"Key not written: this run covered part of the family. Finish with a whole run under the same key: `manni key rotate --to <the same value>`.\";\nconst FROM_ENV =\n \"Key not written: it comes from MANNI_ENCRYPTION_KEY. Update the secret to the value you passed.\";\n\nconst plural = (n: number, one: string, many = `${one}s`): string =>\n `${String(n)} ${n === 1 ? one : many}`;\n\n/** What `set` says: the file, never the key. */\nexport function setMessage(result: KeySetResult): string {\n return result.dryRun\n ? `Would write encryptionKey to ${result.source}.`\n : `Encryption key written to ${result.source}.`;\n}\n\n/** `~AQx7…`, and a citation's line suffix after it: `~AQm4…:2`. */\nexport function shortCiphertext(value: string): string {\n // base64url has no `:`, so the first one starts the line suffix.\n const colon = value.indexOf(\":\");\n const token = colon === -1 ? value : value.slice(0, colon);\n const suffix = colon === -1 ? \"\" : value.slice(colon);\n return `${token.slice(0, 5)}…${suffix}`;\n}\n\n/** A metadata value by its pointer; a citation by its id, else where it sits. */\nfunction nameOf(row: RotatedValue | SkippedValue): string {\n if (row.kind === \"metadata\") return row.pointer;\n if (row.id !== undefined) return row.id;\n if (row.index !== undefined) return `/citations/${String(row.index)}`;\n return `line ${String(row.line ?? 0)}`;\n}\n\nfunction closing(result: KeyRotateResult): string | undefined {\n switch (result.outcome) {\n case \"written\":\n return result.configSource === undefined\n ? undefined\n : `Encryption key written to ${result.configSource}.`;\n case \"finished\":\n // Said before the counts: the key was written by the run that stopped.\n return undefined;\n case \"narrowed\":\n return NARROWED;\n case \"env\":\n return FROM_ENV;\n case \"skipped\":\n return result.skipped === 1\n ? \"Key not written: 1 value could not be re-encrypted. Fix it and rotate again.\"\n : `Key not written: ${String(result.skipped)} values could not be re-encrypted. Fix them and rotate again.`;\n case \"dry-run\":\n return \"Dry run: nothing written.\";\n }\n}\n\nexport function renderRotatePretty(result: KeyRotateResult, opts: PrettyOptions): string {\n const c = palette(opts.color);\n const lines: string[] = [];\n for (const page of result.pages) {\n for (const row of page.rewritten) {\n // A metadata value has no line suffix; two spaces keep its arrow in the\n // column a `:L` suffix would take.\n const gap = row.kind === \"metadata\" ? \" \" : \" \";\n lines.push(\n `${page.file}: ${nameOf(row)} ${c.dim(shortCiphertext(row.from))}${gap}-> ${shortCiphertext(row.to)}`,\n );\n }\n for (const row of page.skipped) {\n lines.push(`${page.file}: ${nameOf(row)} ${c.red(\"skipped:\")} ${row.message}`);\n }\n }\n // A manifest value is named by the entry it belongs to and the pointer\n // inside it, so one line says which document's private half moved.\n for (const manifest of result.manifests) {\n for (const row of manifest.rewritten) {\n lines.push(\n `${manifest.file}: ${row.entry}${row.pointer} ${c.dim(shortCiphertext(row.from))} -> ${shortCiphertext(row.to)}`,\n );\n }\n for (const row of manifest.skipped) {\n lines.push(\n `${manifest.file}: ${row.entry}${row.pointer} ${c.red(\"skipped:\")} ${row.message}`,\n );\n }\n }\n if (result.outcome === \"finished\" && result.configSource !== undefined) {\n lines.push(`Finished the interrupted rotation in ${result.configSource}.`);\n }\n const files =\n result.pages.filter((page) => page.rewritten.length > 0).length +\n result.manifests.filter((manifest) => manifest.rewritten.length > 0).length;\n lines.push(\n `${plural(result.reencrypted, \"value\")} re-encrypted in ${plural(files, \"file\")}, ${String(result.skipped)} skipped`,\n );\n const last = closing(result);\n if (last !== undefined) lines.push(result.outcome === \"skipped\" ? c.red(last) : last);\n if (result.baselineStale) lines.push(BASELINE_NOTICE);\n return lines.join(\"\\n\");\n}\n"],"mappings":"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","names":[]}
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
runTemplates,
|
|
6
6
|
runTemplatesInfer,
|
|
7
7
|
runTools
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-GDVZ5VII.js";
|
|
9
9
|
import {
|
|
10
10
|
LINT_JOBS,
|
|
11
11
|
TOOLS_BY_JOB,
|
|
@@ -13,22 +13,25 @@ import {
|
|
|
13
13
|
rebaseConfig,
|
|
14
14
|
resolveStructureTool,
|
|
15
15
|
runLint
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-KGEQJ5CC.js";
|
|
17
17
|
import "./chunk-ZMECS2IJ.js";
|
|
18
|
-
import "./chunk-
|
|
18
|
+
import "./chunk-2IR4T5PO.js";
|
|
19
19
|
import "./chunk-TIUTIOFB.js";
|
|
20
20
|
import {
|
|
21
21
|
render,
|
|
22
22
|
renderTemplates,
|
|
23
23
|
renderTools
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-LBSCW232.js";
|
|
25
25
|
import "./chunk-GLP5PSXB.js";
|
|
26
26
|
import "./chunk-TBAMBLF3.js";
|
|
27
27
|
import {
|
|
28
28
|
LintError
|
|
29
29
|
} from "./chunk-YGFIQ6Y5.js";
|
|
30
|
-
import "./chunk-
|
|
31
|
-
import "./chunk-
|
|
30
|
+
import "./chunk-TU2WUBVZ.js";
|
|
31
|
+
import "./chunk-LKP7QDFN.js";
|
|
32
|
+
import "./chunk-6HWBRZIN.js";
|
|
33
|
+
import "./chunk-M42DZCOU.js";
|
|
34
|
+
import "./chunk-PCQ7ELJH.js";
|
|
32
35
|
import {
|
|
33
36
|
collect,
|
|
34
37
|
configOption,
|
|
@@ -36,16 +39,16 @@ import {
|
|
|
36
39
|
readStdin,
|
|
37
40
|
reportConfig,
|
|
38
41
|
splitList
|
|
39
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-GV56WGL2.js";
|
|
40
43
|
import {
|
|
41
44
|
OMITTED_WHEN_CLEAN,
|
|
42
45
|
REPORT_FORMATS,
|
|
43
46
|
REPORT_FORMAT_LIST,
|
|
44
47
|
isReportFormat
|
|
45
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-D4N2V43Z.js";
|
|
46
49
|
import {
|
|
47
50
|
STDIN_TOKEN
|
|
48
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-VSEBFHAY.js";
|
|
49
52
|
import {
|
|
50
53
|
fail
|
|
51
54
|
} from "./chunk-YEUYKR62.js";
|
|
@@ -53,14 +56,14 @@ import {
|
|
|
53
56
|
shouldColor
|
|
54
57
|
} from "./chunk-RNVYGWIC.js";
|
|
55
58
|
import "./chunk-MNH7QO4Z.js";
|
|
56
|
-
import "./chunk-
|
|
59
|
+
import "./chunk-QLWC7MKD.js";
|
|
57
60
|
import {
|
|
58
61
|
notice
|
|
59
62
|
} from "./chunk-HX44GB4Z.js";
|
|
60
63
|
import "./chunk-QCHVR4ZM.js";
|
|
61
64
|
import {
|
|
62
65
|
package_default
|
|
63
|
-
} from "./chunk-
|
|
66
|
+
} from "./chunk-2MJ62AYQ.js";
|
|
64
67
|
import "./chunk-OWBRDNRZ.js";
|
|
65
68
|
import "./chunk-G3T47CFV.js";
|
|
66
69
|
import "./chunk-2H7UOFLK.js";
|
|
@@ -345,4 +348,4 @@ function buildProgram() {
|
|
|
345
348
|
export {
|
|
346
349
|
buildProgram
|
|
347
350
|
};
|
|
348
|
-
//# sourceMappingURL=cli-
|
|
351
|
+
//# sourceMappingURL=cli-4MF37HAQ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lint/cli.ts"],"sourcesContent":["/**\n * The lint program. Named `lint` because that is where it is mounted\n * (`manni lint …`); `src/cli.ts` adds it to the umbrella and runs it. Thin\n * commander wrapper over the command cores. Follows clig.dev: primary output to\n * stdout, diagnostics to stderr, color only on a TTY (and never under\n * NO_COLOR/--no-color), meaningful exit codes.\n *\n * Grammar per proposal 0034: the verbs are `check`, `structure`, `templates`\n * and `tools`, and there is no default subcommand, so a bare `manni lint` is a\n * usage error that lists them. `check` runs every configured job; `structure`\n * runs one of them, and carries the options that belong to the tool performing\n * it.\n *\n * Exit codes are the contract CI reads:\n * 0 every file linted clean\n * 1 the run produced findings\n * 2 the tool could not do its job - bad usage, missing template, unreadable\n * input. A LintError is always this, never a lint failure.\n *\n * The 1/2 split is what lets a workflow tell \"the docs are wrong\" apart from\n * \"the linter is misconfigured\", which a single non-zero exit cannot.\n */\nimport { Command } from \"commander\";\nimport pkg from \"../../package.json\" with { type: \"json\" };\nimport {\n collect,\n configOption,\n explicitFalse,\n readStdin,\n reportConfig,\n splitList,\n} from \"../shared/cli-options.js\";\nimport { shouldColor } from \"../shared/color.js\";\nimport { fail } from \"../shared/run.js\";\nimport { notice } from \"../shared/warn.js\";\nimport {\n OMITTED_WHEN_CLEAN,\n REPORT_FORMAT_LIST,\n STDIN_TOKEN,\n} from \"../meta/internal.js\";\nimport {\n REPORT_FORMATS,\n isReportFormat,\n type ReportFormat as FamilyFormat,\n} from \"../meta/index.js\";\nimport { LintError } from \"./types.js\";\nimport { runLint } from \"./commands/lint.js\";\nimport { runTemplates, runTemplatesInfer } from \"./commands/templates.js\";\nimport { runTools } from \"./commands/tools.js\";\nimport { INFER_FORMATS, isInferFormat, type InferFormat } from \"./core/infer.js\";\nimport {\n LINT_JOBS,\n TOOLS_BY_JOB,\n loadConfig,\n rebaseConfig,\n} from \"./core/config.js\";\nimport { resolveStructureTool } from \"./tools/index.js\";\nimport {\n render,\n renderTemplates,\n renderTools,\n type ListFormat,\n type ReportFormat,\n} from \"./reporters/index.js\";\n\n/** The options `check` and `structure` share, in the family's spelling. */\ninterface InputCliOptions {\n /** `--collection <name>`, repeatable; commander's default value is `[]`. */\n collection: string[];\n /** `--ext <list>`; the command splits it. */\n ext?: string;\n /** `--exclude <glob>`, repeatable; commander's default value is `[]`. */\n exclude: string[];\n /** `--as <format>`: force a parser. */\n as?: string;\n /**\n * `-c, --config <path>` and `--no-config` share one commander attribute:\n * `undefined` with neither flag, the path with `-c`, `false` with\n * `--no-config`. Split by `configOption`.\n */\n config?: string | boolean;\n allowEmpty?: boolean;\n /** `--no-gitignore`. */\n gitignore: boolean;\n /** `-f, --format <format>`. Always a string: the declaration has a default. */\n format: string;\n}\n\n/** `structure` adds the options of the tool that performs the job. */\ninterface StructureCliOptions extends InputCliOptions {\n tool?: string;\n template?: string;\n /** `--templates <path>`, repeatable; commander's default value is `[]`. */\n templates: string[];\n explain?: boolean;\n}\n\n/** What commander parses for `templates`. */\ninterface TemplatesCommandOptions {\n templates: string[];\n config?: string | boolean;\n format: string;\n}\n\n/** What commander parses for `templates infer`. */\ninterface TemplatesInferCliOptions {\n as?: string;\n name?: string;\n config?: string | boolean;\n format: string;\n out?: string;\n force?: boolean;\n}\n\n/** What commander parses for `tools`. */\ninterface ToolsCommandOptions {\n config?: string | boolean;\n format: string;\n}\n\n// `explain` is reachable through `--explain`, not `-f`: it reports on\n// configuration rather than on documents, and offering it as a format would\n// invite `-f explain` alongside a lint that then never happens. The `-f` set\n// itself is the family's, from meta, rather than a fourth hand-kept copy of\n// the same five words.\nconst LIST_FORMATS = new Set<string>([\"pretty\", \"json\"]);\n\n/** The heading the tool's own options print under, after the shared ones. */\nconst TOOL_OPTIONS_GROUP = \"Tool options:\";\n\nfunction resolveColor(program: Command): boolean {\n // commander maps --no-color to opts.color === false.\n const noColor = program.opts().color === false;\n return shouldColor({ noColor, isTTY: process.stdout.isTTY });\n}\n\nfunction reportFormat(value: unknown): FamilyFormat {\n const format = String(value);\n if (!isReportFormat(format)) {\n throw new LintError(\n `Unknown --format \"${format}\". Use ${REPORT_FORMAT_LIST}.`,\n );\n }\n return format;\n}\n\n/**\n * Whether a clean run may print nothing at all in this format.\n *\n * Only `github` may: an empty annotation stream is a clean check. Every other\n * format owes its envelope - an empty JSON array, a SARIF log with no results,\n * a JUnit suite of passing testcases - because a consumer parsing stdout must\n * not have to treat \"no output\" as a third outcome. `explain` is never clean\n * or dirty; it always has something to say.\n */\nfunction omittedWhenClean(format: ReportFormat): boolean {\n return format !== \"explain\" && OMITTED_WHEN_CLEAN.has(format);\n}\n\nfunction listFormat(value: unknown): ListFormat {\n const format = String(value);\n if (!LIST_FORMATS.has(format)) {\n throw new LintError(\n `Unknown --format \"${format}\". Use pretty or json.`,\n );\n }\n return format as ListFormat;\n}\n\n/**\n * `templates infer -f`: the format a *template file* is written in, which is\n * not the set a report is rendered in. A template is YAML or JSON because those\n * are the two the loader reads back, and `pretty` would name a third thing the\n * tool cannot then load.\n */\nfunction inferFormat(value: unknown): InferFormat {\n const format = String(value);\n if (!isInferFormat(format)) {\n throw new LintError(`Unknown --format \"${format}\". Use yaml or json.`);\n }\n return format;\n}\n\n/**\n * `--tool <name>`: which tool performs the structure job. Refused by name\n * rather than ignored, because falling through to manni's engine would lint\n * with something other than what was asked for and say nothing.\n *\n * The refusal is the registry's, not a second copy of it here. `runLint`\n * refuses the same name with the same sentence for a caller that never touches\n * commander; this one fires first, so a bad `--tool` is reported before the\n * run asks what it was pointed at.\n */\nfunction assertStructureTool(value: string | undefined): void {\n if (value === undefined) return;\n resolveStructureTool(value);\n}\n\n/**\n * `-c/--config` and `--no-config`, in one place.\n *\n * Every verb here takes them, and they had been written out three times. A flag\n * two commands both have carries the same name *and* the same description, so\n * the declaration is shared rather than copied - which is what kept the fourth\n * copy, on `templates infer`, from spelling either of them slightly differently.\n */\nfunction withConfigOptions(command: Command): Command {\n return command\n .option(\"-c, --config <path>\", \"path to a manni config file\")\n .option(\"--no-config\", \"ignore any discovered config file\");\n}\n\n/**\n * The value of a flag a command and its parent both declare.\n *\n * Commander keeps parsing a parent's options past a subcommand name unless\n * `enablePositionalOptions()` is on, so `templates infer page.md -f json` sets\n * `format` on `templates` and leaves `infer` holding its own default. Both\n * commands declare `-f`, `-c` and `--no-config`, because \"commands must have\n * parallel behaviors\" and `infer` must list them in its own `--help`.\n *\n * Turning positional options on would fix it and move every other flag in this\n * program with it: `manni lint structure docs/ --no-color` is a root option\n * written after its command, and there are three more like it. So the lookup\n * changes instead. The nearest command actually *given* the flag wins, and the\n * subcommand's own default is the fallback - which is the reading a person\n * typing the line already has.\n */\nfunction optionValue(command: Command, key: string): unknown {\n for (\n let cmd: Command | null = command;\n cmd !== null;\n cmd = cmd.parent ?? null\n ) {\n if (cmd.getOptionValueSource(key) === \"cli\") return cmd.getOptionValue(key);\n }\n return command.getOptionValue(key);\n}\n\n/** The options every job verb takes, in one place so the two cannot drift. */\nfunction withInputOptions(command: Command): Command {\n command\n .argument(\n \"[paths...]\",\n \"files, directories, or globs to lint (use - for stdin)\",\n )\n .option(\n \"--collection <name>\",\n \"configured collection to run over; repeatable\",\n collect,\n [],\n )\n .option(\"--ext <list>\", \"comma-separated extensions for directory walks\")\n .option(\"--exclude <glob>\", \"glob to exclude; repeatable\", collect, [])\n .option(\"--as <format>\", \"force an input format (e.g. markdown, mdx)\")\n .option(\n \"-f, --format <format>\",\n `output: ${REPORT_FORMATS.join(\" | \")}`,\n \"pretty\",\n );\n return withConfigOptions(command)\n .option(\"--allow-empty\", \"treat zero matched files as success\")\n .option(\"--no-gitignore\", \"lint files .gitignore covers\");\n}\n\n/** The lint options every job verb turns its shared flags into. */\nfunction inputOptions(\n paths: string[],\n options: InputCliOptions,\n): {\n inputs: string[];\n collection: string[];\n exts?: string[];\n exclude: string[];\n as?: string;\n configPath?: string;\n noConfig?: boolean;\n allowEmpty?: boolean;\n respectGitignore?: boolean;\n onNotice: (message: string) => void;\n} {\n return {\n inputs: paths,\n collection: options.collection,\n ...(options.ext ? { exts: splitList(options.ext) } : {}),\n exclude: options.exclude,\n ...(options.as === undefined ? {} : { as: options.as }),\n ...configOption(options.config),\n // `undefined` rather than `false` when absent, so config still wins.\n ...(options.allowEmpty ? { allowEmpty: true } : {}),\n respectGitignore: explicitFalse(options.gitignore),\n onNotice: notice,\n };\n}\n\nexport function buildProgram(): Command {\n const program = new Command();\n program\n .name(\"lint\")\n .description(\n \"Validate document structure against doctype templates. Deterministic, CI-friendly.\",\n )\n .version(pkg.version, \"-V, --version\")\n .option(\"--no-color\", \"disable colored output\")\n .showHelpAfterError()\n // Exit code 1 is reserved for \"the docs are wrong\". Commander exits 1 on a\n // usage error by default, which would make a typo'd flag look exactly like\n // a failing lint to a workflow. With no callback, commander throws the\n // CommanderError instead, and the umbrella's runner maps it: help and\n // --version stay 0, every other usage error becomes 2. Commander has\n // already written its own message. This has to precede .command(), which\n // copies the callback into each subcommand.\n .exitOverride();\n\n /** Run one lint, render it, and settle the exit code. Both job verbs share it. */\n const lint = async (\n paths: string[],\n options: StructureCliOptions | InputCliOptions,\n command: Command,\n job: { tool?: StructureCliOptions } = {},\n ): Promise<void> => {\n const tool = job.tool;\n const format = reportFormat(options.format);\n const explain = tool?.explain === true;\n const stdinContent = paths.includes(STDIN_TOKEN) ? await readStdin() : undefined;\n const cwd = process.cwd();\n\n const run = await runLint({\n ...inputOptions(paths, options),\n ...(tool?.tool === undefined ? {} : { tool: tool.tool }),\n ...(tool?.template === undefined ? {} : { template: tool.template }),\n ...(tool && tool.templates.length > 0 ? { templates: tool.templates } : {}),\n ...(explain ? { explain: true } : {}),\n ...(stdinContent === undefined ? {} : { stdinContent }),\n // Which config governed the run, said where a report cannot be parsed\n // around: discovery walks up to the project boundary, so an unexpected\n // ancestor config is the difference between a five-minute diagnosis and\n // an hour of confusion.\n onConfigLoaded: reportConfig(format === \"pretty\", cwd),\n });\n\n const color = resolveColor(command.parent ?? command);\n const chosen: ReportFormat = explain ? \"explain\" : format;\n const text = render(run, chosen, { color });\n if (text.length > 0 || !omittedWhenClean(chosen)) {\n process.stdout.write(`${text}\\n`);\n }\n // `--explain` answers a question about configuration, so its exit code\n // reports whether it could answer it - not whether the docs are clean.\n //\n // That covers routing failures too: a page whose `type` matches no\n // template is a answered question, not an unanswered one, so it exits 0\n // like everything else here. Automation must not read this code as\n // \"everything routed\" - the ordinary run is what reports that, with exit\n // 1. Said in `--help` and the README, because the distinction is invisible\n // from the exit code alone.\n process.exitCode = explain ? 0 : run.summary.failed > 0 ? 1 : 0;\n };\n\n withInputOptions(\n program\n .command(\"check\")\n .description(\"Run every configured lint job over the given files/dirs/globs\"),\n )\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Jobs: structure.\",\n \"\",\n \"Examples:\",\n \" manni lint check docs/ # every configured job\",\n \" manni lint check # targets from collections:\",\n \" manni lint check --collection guides\",\n ' manni lint check \"**/*.md\" -f github # CI annotations',\n \" cat page.md | manni lint check - --as markdown\",\n ].join(\"\\n\"),\n )\n .action(async (paths: string[], options: InputCliOptions, command: Command) => {\n try {\n // Which jobs this run covered, said once, beside the config line. The\n // full form also names the jobs that exist and are not configured;\n // `structure` is the only job there is, so today it is one word.\n if (options.format === \"pretty\") {\n process.stderr.write(`Checked: ${LINT_JOBS.join(\", \")}.\\n`);\n }\n await lint(paths, options, command);\n } catch (err) {\n fail(err);\n }\n });\n\n const structure = withInputOptions(\n program\n .command(\"structure\")\n .description(\n \"Lint document structure against doctype templates, routing each page by its `type`\",\n ),\n );\n structure\n .optionsGroup(TOOL_OPTIONS_GROUP)\n .option(\n \"--tool <name>\",\n `tool that performs the job: ${TOOLS_BY_JOB.structure.join(\", \")}`,\n )\n .option(\n \"-t, --template <ref>\",\n \"apply this template to every file, overriding type routing\",\n )\n .option(\n \"--templates <path>\",\n \"template file to route by: its `types:` win over built-ins; repeatable\",\n collect,\n [],\n )\n .option(\n \"--explain\",\n \"print how each file's template was chosen, and lint nothing (always exits 0, unrouted pages included)\",\n )\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Examples:\",\n \" manni lint structure docs/ # route each page by its `type`\",\n \" manni lint structure docs/ --templates ./templates.yaml # add your own templates\",\n \" manni lint structure # targets from collections:\",\n \" manni lint structure docs/ --explain # show why each page routed where\",\n \" manni lint structure page.md -t tgdp:how-to:1.6 # force one template\",\n ' manni lint structure \"**/*.md\" -f github # CI annotations',\n \" manni lint structure docs/ --exclude '**/drafts/**'\",\n \" cat page.md | manni lint structure - -t tgdp:how-to:1.6 --as markdown\",\n ].join(\"\\n\"),\n )\n .action(\n async (paths: string[], options: StructureCliOptions, command: Command) => {\n try {\n assertStructureTool(options.tool);\n await lint(paths, options, command, { tool: options });\n } catch (err) {\n fail(err);\n }\n },\n );\n\n const templates = program\n .command(\"templates\")\n .description(\"List the templates that can be applied, and the types they serve\")\n .option(\n \"--templates <path>\",\n \"also list the templates in this file; repeatable\",\n collect,\n [],\n );\n withConfigOptions(templates)\n .option(\"-f, --format <format>\", \"output: pretty | json\", \"pretty\")\n .action(async (options: TemplatesCommandOptions, command: Command) => {\n try {\n const format = listFormat(options.format);\n // The listing answers \"what could route a page?\", so it has to see the\n // same template files a lint would - rebased the same way, or it would\n // answer for a different set of files depending on where it was run.\n const { configPath, noConfig } = configOption(options.config);\n const found = noConfig ? null : await loadConfig(configPath);\n const info = await runTemplates({\n templates:\n options.templates.length > 0\n ? options.templates\n : rebaseConfig(found).templates,\n });\n const color = resolveColor(command.parent ?? command);\n process.stdout.write(`${renderTemplates(info, format, { color })}\\n`);\n } catch (err) {\n fail(err);\n }\n });\n\n const inferCommand = templates\n .command(\"infer\")\n .description(\"Write a first template from a page that already has the shape you want\")\n .argument(\"<page>\", \"one file to infer from (use - for stdin)\")\n .option(\"--as <format>\", \"force an input format (e.g. markdown, mdx)\")\n .option(\n \"--name <name>\",\n \"name for the template; defaults to the page's `type`, else its filename\",\n )\n .option(\"-f, --format <format>\", `output: ${INFER_FORMATS.join(\" | \")}`, \"yaml\")\n .option(\"-o, --out <path>\", \"write the template here instead of to stdout\")\n .option(\"--force\", \"overwrite the --out path\");\n withConfigOptions(inferCommand)\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Examples:\",\n \" manni lint templates infer docs/guides/install.md\",\n \" manni lint templates infer docs/guides/install.md --name how-to\",\n \" manni lint templates infer page.mdx -f json\",\n \" manni lint templates infer page.md -o ./templates.yaml\",\n \" manni lint templates infer page.md -o ./templates.yaml --force\",\n \" cat page.md | manni lint templates infer - --as markdown\",\n \"\",\n \"One page, and every rule it writes is exactly one occurrence: a single\",\n \"page cannot show what varies. Loosening a heading into a list or a\",\n \"pattern, setting `min: 0`, and adding a trailing rule with no heading\",\n \"for the sections that may follow are your edits to make.\",\n ].join(\"\\n\"),\n )\n .action(\n async (\n page: string,\n options: TemplatesInferCliOptions,\n command: Command,\n ) => {\n try {\n // `-f`, `-c` and `--no-config` are read through `optionValue`: the\n // parent `templates` declares all three, and commander hands it any\n // of them typed after `infer`.\n const format = inferFormat(optionValue(command, \"format\"));\n const { configPath, noConfig } = configOption(\n optionValue(command, \"config\"),\n );\n const stdinContent =\n page === STDIN_TOKEN ? await readStdin() : undefined;\n const result = await runTemplatesInfer({\n page,\n format,\n ...(options.as === undefined ? {} : { as: options.as }),\n ...(options.name === undefined ? {} : { name: options.name }),\n ...(options.out === undefined ? {} : { out: options.out }),\n ...(options.force === undefined ? {} : { force: options.force }),\n ...(configPath === undefined ? {} : { configPath }),\n ...(noConfig === undefined ? {} : { noConfig }),\n ...(stdinContent === undefined ? {} : { stdinContent }),\n // The template is the primary output, so with no --out it owns\n // stdout and the config line goes to stderr beside it. With --out\n // stdout is free, and the line still belongs on stderr: a reader\n // piping nothing is not a reason to move a diagnostic.\n onConfigLoaded: reportConfig(false, process.cwd()),\n });\n\n if (result.written === undefined) {\n process.stdout.write(result.text);\n return;\n }\n // Said on stderr, so `-o` leaves stdout empty for a shell that is\n // watching it, and the template file is the whole output.\n process.stderr.write(\n `Wrote template \"${result.name}\" to ${result.written}\\n`,\n );\n } catch (err) {\n fail(err);\n }\n },\n );\n\n withConfigOptions(\n program\n .command(\"tools\")\n .description(\n \"List the lint jobs, the tool that performs each, and what it reads\",\n ),\n )\n .option(\"-f, --format <format>\", \"output: pretty | json\", \"pretty\")\n .action(async (options: ToolsCommandOptions, command: Command) => {\n try {\n const format = listFormat(options.format);\n const tools = await runTools(configOption(options.config));\n const color = resolveColor(command.parent ?? command);\n process.stdout.write(`${renderTools(tools, format, { color })}\\n`);\n } catch (err) {\n fail(err);\n }\n });\n\n return program;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsBA,SAAS,eAAe;AAuGxB,IAAM,eAAe,oBAAI,IAAY,CAAC,UAAU,MAAM,CAAC;AAGvD,IAAM,qBAAqB;AAE3B,SAAS,aAAa,SAA2B;AAE/C,QAAM,UAAU,QAAQ,KAAK,EAAE,UAAU;AACzC,SAAO,YAAY,EAAE,SAAS,OAAO,QAAQ,OAAO,MAAM,CAAC;AAC7D;AAEA,SAAS,aAAa,OAA8B;AAClD,QAAM,SAAS,OAAO,KAAK;AAC3B,MAAI,CAAC,eAAe,MAAM,GAAG;AAC3B,UAAM,IAAI;AAAA,MACR,qBAAqB,MAAM,UAAU,kBAAkB;AAAA,IACzD;AAAA,EACF;AACA,SAAO;AACT;AAWA,SAAS,iBAAiB,QAA+B;AACvD,SAAO,WAAW,aAAa,mBAAmB,IAAI,MAAM;AAC9D;AAEA,SAAS,WAAW,OAA4B;AAC9C,QAAM,SAAS,OAAO,KAAK;AAC3B,MAAI,CAAC,aAAa,IAAI,MAAM,GAAG;AAC7B,UAAM,IAAI;AAAA,MACR,qBAAqB,MAAM;AAAA,IAC7B;AAAA,EACF;AACA,SAAO;AACT;AAQA,SAAS,YAAY,OAA6B;AAChD,QAAM,SAAS,OAAO,KAAK;AAC3B,MAAI,CAAC,cAAc,MAAM,GAAG;AAC1B,UAAM,IAAI,UAAU,qBAAqB,MAAM,sBAAsB;AAAA,EACvE;AACA,SAAO;AACT;AAYA,SAAS,oBAAoB,OAAiC;AAC5D,MAAI,UAAU,OAAW;AACzB,uBAAqB,KAAK;AAC5B;AAUA,SAAS,kBAAkB,SAA2B;AACpD,SAAO,QACJ,OAAO,uBAAuB,6BAA6B,EAC3D,OAAO,eAAe,mCAAmC;AAC9D;AAkBA,SAAS,YAAY,SAAkB,KAAsB;AAC3D,WACM,MAAsB,SAC1B,QAAQ,MACR,MAAM,IAAI,UAAU,MACpB;AACA,QAAI,IAAI,qBAAqB,GAAG,MAAM,MAAO,QAAO,IAAI,eAAe,GAAG;AAAA,EAC5E;AACA,SAAO,QAAQ,eAAe,GAAG;AACnC;AAGA,SAAS,iBAAiB,SAA2B;AACnD,UACG;AAAA,IACC;AAAA,IACA;AAAA,EACF,EACC;AAAA,IACC;AAAA,IACA;AAAA,IACA;AAAA,IACA,CAAC;AAAA,EACH,EACC,OAAO,gBAAgB,gDAAgD,EACvE,OAAO,oBAAoB,+BAA+B,SAAS,CAAC,CAAC,EACrE,OAAO,iBAAiB,4CAA4C,EACpE;AAAA,IACC;AAAA,IACA,WAAW,eAAe,KAAK,KAAK,CAAC;AAAA,IACrC;AAAA,EACF;AACF,SAAO,kBAAkB,OAAO,EAC7B,OAAO,iBAAiB,qCAAqC,EAC7D,OAAO,kBAAkB,8BAA8B;AAC5D;AAGA,SAAS,aACP,OACA,SAYA;AACA,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,YAAY,QAAQ;AAAA,IACpB,GAAI,QAAQ,MAAM,EAAE,MAAM,UAAU,QAAQ,GAAG,EAAE,IAAI,CAAC;AAAA,IACtD,SAAS,QAAQ;AAAA,IACjB,GAAI,QAAQ,OAAO,SAAY,CAAC,IAAI,EAAE,IAAI,QAAQ,GAAG;AAAA,IACrD,GAAG,aAAa,QAAQ,MAAM;AAAA;AAAA,IAE9B,GAAI,QAAQ,aAAa,EAAE,YAAY,KAAK,IAAI,CAAC;AAAA,IACjD,kBAAkB,cAAc,QAAQ,SAAS;AAAA,IACjD,UAAU;AAAA,EACZ;AACF;AAEO,SAAS,eAAwB;AACtC,QAAM,UAAU,IAAI,QAAQ;AAC5B,UACG,KAAK,MAAM,EACX;AAAA,IACC;AAAA,EACF,EACC,QAAQ,gBAAI,SAAS,eAAe,EACpC,OAAO,cAAc,wBAAwB,EAC7C,mBAAmB,EAQnB,aAAa;AAGhB,QAAM,OAAO,OACX,OACA,SACA,SACA,MAAsC,CAAC,MACrB;AAClB,UAAM,OAAO,IAAI;AACjB,UAAM,SAAS,aAAa,QAAQ,MAAM;AAC1C,UAAM,UAAU,MAAM,YAAY;AAClC,UAAM,eAAe,MAAM,SAAS,WAAW,IAAI,MAAM,UAAU,IAAI;AACvE,UAAM,MAAM,QAAQ,IAAI;AAExB,UAAM,MAAM,MAAM,QAAQ;AAAA,MACxB,GAAG,aAAa,OAAO,OAAO;AAAA,MAC9B,GAAI,MAAM,SAAS,SAAY,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK;AAAA,MACtD,GAAI,MAAM,aAAa,SAAY,CAAC,IAAI,EAAE,UAAU,KAAK,SAAS;AAAA,MAClE,GAAI,QAAQ,KAAK,UAAU,SAAS,IAAI,EAAE,WAAW,KAAK,UAAU,IAAI,CAAC;AAAA,MACzE,GAAI,UAAU,EAAE,SAAS,KAAK,IAAI,CAAC;AAAA,MACnC,GAAI,iBAAiB,SAAY,CAAC,IAAI,EAAE,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA,MAKrD,gBAAgB,aAAa,WAAW,UAAU,GAAG;AAAA,IACvD,CAAC;AAED,UAAM,QAAQ,aAAa,QAAQ,UAAU,OAAO;AACpD,UAAM,SAAuB,UAAU,YAAY;AACnD,UAAM,OAAO,OAAO,KAAK,QAAQ,EAAE,MAAM,CAAC;AAC1C,QAAI,KAAK,SAAS,KAAK,CAAC,iBAAiB,MAAM,GAAG;AAChD,cAAQ,OAAO,MAAM,GAAG,IAAI;AAAA,CAAI;AAAA,IAClC;AAUA,YAAQ,WAAW,UAAU,IAAI,IAAI,QAAQ,SAAS,IAAI,IAAI;AAAA,EAChE;AAEA;AAAA,IACE,QACG,QAAQ,OAAO,EACf,YAAY,+DAA+D;AAAA,EAChF,EACG;AAAA,IACC;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE,KAAK,IAAI;AAAA,EACb,EACC,OAAO,OAAO,OAAiB,SAA0B,YAAqB;AAC7E,QAAI;AAIF,UAAI,QAAQ,WAAW,UAAU;AAC/B,gBAAQ,OAAO,MAAM,YAAY,UAAU,KAAK,IAAI,CAAC;AAAA,CAAK;AAAA,MAC5D;AACA,YAAM,KAAK,OAAO,SAAS,OAAO;AAAA,IACpC,SAAS,KAAK;AACZ,WAAK,GAAG;AAAA,IACV;AAAA,EACF,CAAC;AAEH,QAAM,YAAY;AAAA,IAChB,QACG,QAAQ,WAAW,EACnB;AAAA,MACC;AAAA,IACF;AAAA,EACJ;AACA,YACG,aAAa,kBAAkB,EAC/B;AAAA,IACC;AAAA,IACA,+BAA+B,aAAa,UAAU,KAAK,IAAI,CAAC;AAAA,EAClE,EACC;AAAA,IACC;AAAA,IACA;AAAA,EACF,EACC;AAAA,IACC;AAAA,IACA;AAAA,IACA;AAAA,IACA,CAAC;AAAA,EACH,EACC;AAAA,IACC;AAAA,IACA;AAAA,EACF,EACC;AAAA,IACC;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE,KAAK,IAAI;AAAA,EACb,EACC;AAAA,IACC,OAAO,OAAiB,SAA8B,YAAqB;AACzE,UAAI;AACF,4BAAoB,QAAQ,IAAI;AAChC,cAAM,KAAK,OAAO,SAAS,SAAS,EAAE,MAAM,QAAQ,CAAC;AAAA,MACvD,SAAS,KAAK;AACZ,aAAK,GAAG;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAEF,QAAM,YAAY,QACf,QAAQ,WAAW,EACnB,YAAY,kEAAkE,EAC9E;AAAA,IACC;AAAA,IACA;AAAA,IACA;AAAA,IACA,CAAC;AAAA,EACH;AACF,oBAAkB,SAAS,EACxB,OAAO,yBAAyB,yBAAyB,QAAQ,EACjE,OAAO,OAAO,SAAkC,YAAqB;AACpE,QAAI;AACF,YAAM,SAAS,WAAW,QAAQ,MAAM;AAIxC,YAAM,EAAE,YAAY,SAAS,IAAI,aAAa,QAAQ,MAAM;AAC5D,YAAM,QAAQ,WAAW,OAAO,MAAM,WAAW,UAAU;AAC3D,YAAM,OAAO,MAAM,aAAa;AAAA,QAC9B,WACE,QAAQ,UAAU,SAAS,IACvB,QAAQ,YACR,aAAa,KAAK,EAAE;AAAA,MAC5B,CAAC;AACD,YAAM,QAAQ,aAAa,QAAQ,UAAU,OAAO;AACpD,cAAQ,OAAO,MAAM,GAAG,gBAAgB,MAAM,QAAQ,EAAE,MAAM,CAAC,CAAC;AAAA,CAAI;AAAA,IACtE,SAAS,KAAK;AACZ,WAAK,GAAG;AAAA,IACV;AAAA,EACF,CAAC;AAEH,QAAM,eAAe,UAClB,QAAQ,OAAO,EACf,YAAY,wEAAwE,EACpF,SAAS,UAAU,0CAA0C,EAC7D,OAAO,iBAAiB,4CAA4C,EACpE;AAAA,IACC;AAAA,IACA;AAAA,EACF,EACC,OAAO,yBAAyB,WAAW,cAAc,KAAK,KAAK,CAAC,IAAI,MAAM,EAC9E,OAAO,oBAAoB,8CAA8C,EACzE,OAAO,WAAW,0BAA0B;AAC/C,oBAAkB,YAAY,EAC3B;AAAA,IACC;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE,KAAK,IAAI;AAAA,EACb,EACC;AAAA,IACC,OACE,MACA,SACA,YACG;AACH,UAAI;AAIF,cAAM,SAAS,YAAY,YAAY,SAAS,QAAQ,CAAC;AACzD,cAAM,EAAE,YAAY,SAAS,IAAI;AAAA,UAC/B,YAAY,SAAS,QAAQ;AAAA,QAC/B;AACA,cAAM,eACJ,SAAS,cAAc,MAAM,UAAU,IAAI;AAC7C,cAAM,SAAS,MAAM,kBAAkB;AAAA,UACrC;AAAA,UACA;AAAA,UACA,GAAI,QAAQ,OAAO,SAAY,CAAC,IAAI,EAAE,IAAI,QAAQ,GAAG;AAAA,UACrD,GAAI,QAAQ,SAAS,SAAY,CAAC,IAAI,EAAE,MAAM,QAAQ,KAAK;AAAA,UAC3D,GAAI,QAAQ,QAAQ,SAAY,CAAC,IAAI,EAAE,KAAK,QAAQ,IAAI;AAAA,UACxD,GAAI,QAAQ,UAAU,SAAY,CAAC,IAAI,EAAE,OAAO,QAAQ,MAAM;AAAA,UAC9D,GAAI,eAAe,SAAY,CAAC,IAAI,EAAE,WAAW;AAAA,UACjD,GAAI,aAAa,SAAY,CAAC,IAAI,EAAE,SAAS;AAAA,UAC7C,GAAI,iBAAiB,SAAY,CAAC,IAAI,EAAE,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA,UAKrD,gBAAgB,aAAa,OAAO,QAAQ,IAAI,CAAC;AAAA,QACnD,CAAC;AAED,YAAI,OAAO,YAAY,QAAW;AAChC,kBAAQ,OAAO,MAAM,OAAO,IAAI;AAChC;AAAA,QACF;AAGA,gBAAQ,OAAO;AAAA,UACb,mBAAmB,OAAO,IAAI,QAAQ,OAAO,OAAO;AAAA;AAAA,QACtD;AAAA,MACF,SAAS,KAAK;AACZ,aAAK,GAAG;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAEF;AAAA,IACE,QACG,QAAQ,OAAO,EACf;AAAA,MACC;AAAA,IACF;AAAA,EACJ,EACG,OAAO,yBAAyB,yBAAyB,QAAQ,EACjE,OAAO,OAAO,SAA8B,YAAqB;AAChE,QAAI;AACF,YAAM,SAAS,WAAW,QAAQ,MAAM;AACxC,YAAM,QAAQ,MAAM,SAAS,aAAa,QAAQ,MAAM,CAAC;AACzD,YAAM,QAAQ,aAAa,QAAQ,UAAU,OAAO;AACpD,cAAQ,OAAO,MAAM,GAAG,YAAY,OAAO,QAAQ,EAAE,MAAM,CAAC,CAAC;AAAA,CAAI;AAAA,IACnE,SAAS,KAAK;AACZ,WAAK,GAAG;AAAA,IACV;AAAA,EACF,CAAC;AAEH,SAAO;AACT;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/lint/cli.ts"],"sourcesContent":["/**\n * The lint program. Named `lint` because that is where it is mounted\n * (`manni lint …`); `src/cli.ts` adds it to the umbrella and runs it. Thin\n * commander wrapper over the command cores. Follows clig.dev: primary output to\n * stdout, diagnostics to stderr, color only on a TTY (and never under\n * NO_COLOR/--no-color), meaningful exit codes.\n *\n * Grammar per proposal 0034: the verbs are `check`, `structure`, `templates`\n * and `tools`, and there is no default subcommand, so a bare `manni lint` is a\n * usage error that lists them. `check` runs every configured job; `structure`\n * runs one of them, and carries the options that belong to the tool performing\n * it.\n *\n * Exit codes are the contract CI reads:\n * 0 every file linted clean\n * 1 the run produced findings\n * 2 the tool could not do its job - bad usage, missing template, unreadable\n * input. A LintError is always this, never a lint failure.\n *\n * The 1/2 split is what lets a workflow tell \"the docs are wrong\" apart from\n * \"the linter is misconfigured\", which a single non-zero exit cannot.\n */\nimport { Command } from \"commander\";\nimport pkg from \"../../package.json\" with { type: \"json\" };\nimport {\n collect,\n configOption,\n explicitFalse,\n readStdin,\n reportConfig,\n splitList,\n} from \"../shared/cli-options.js\";\nimport { shouldColor } from \"../shared/color.js\";\nimport { fail } from \"../shared/run.js\";\nimport { notice } from \"../shared/warn.js\";\nimport {\n OMITTED_WHEN_CLEAN,\n REPORT_FORMAT_LIST,\n STDIN_TOKEN,\n} from \"../meta/internal.js\";\nimport {\n REPORT_FORMATS,\n isReportFormat,\n type ReportFormat as FamilyFormat,\n} from \"../meta/index.js\";\nimport { LintError } from \"./types.js\";\nimport { runLint } from \"./commands/lint.js\";\nimport { runTemplates, runTemplatesInfer } from \"./commands/templates.js\";\nimport { runTools } from \"./commands/tools.js\";\nimport { INFER_FORMATS, isInferFormat, type InferFormat } from \"./core/infer.js\";\nimport {\n LINT_JOBS,\n TOOLS_BY_JOB,\n loadConfig,\n rebaseConfig,\n} from \"./core/config.js\";\nimport { resolveStructureTool } from \"./tools/index.js\";\nimport {\n render,\n renderTemplates,\n renderTools,\n type ListFormat,\n type ReportFormat,\n} from \"./reporters/index.js\";\n\n/** The options `check` and `structure` share, in the family's spelling. */\ninterface InputCliOptions {\n /** `--collection <name>`, repeatable; commander's default value is `[]`. */\n collection: string[];\n /** `--ext <list>`; the command splits it. */\n ext?: string;\n /** `--exclude <glob>`, repeatable; commander's default value is `[]`. */\n exclude: string[];\n /** `--as <format>`: force a parser. */\n as?: string;\n /**\n * `-c, --config <path>` and `--no-config` share one commander attribute:\n * `undefined` with neither flag, the path with `-c`, `false` with\n * `--no-config`. Split by `configOption`.\n */\n config?: string | boolean;\n allowEmpty?: boolean;\n /** `--no-gitignore`. */\n gitignore: boolean;\n /** `-f, --format <format>`. Always a string: the declaration has a default. */\n format: string;\n}\n\n/** `structure` adds the options of the tool that performs the job. */\ninterface StructureCliOptions extends InputCliOptions {\n tool?: string;\n template?: string;\n /** `--templates <path>`, repeatable; commander's default value is `[]`. */\n templates: string[];\n explain?: boolean;\n}\n\n/** What commander parses for `templates`. */\ninterface TemplatesCommandOptions {\n templates: string[];\n config?: string | boolean;\n format: string;\n}\n\n/** What commander parses for `templates infer`. */\ninterface TemplatesInferCliOptions {\n as?: string;\n name?: string;\n config?: string | boolean;\n format: string;\n out?: string;\n force?: boolean;\n}\n\n/** What commander parses for `tools`. */\ninterface ToolsCommandOptions {\n config?: string | boolean;\n format: string;\n}\n\n// `explain` is reachable through `--explain`, not `-f`: it reports on\n// configuration rather than on documents, and offering it as a format would\n// invite `-f explain` alongside a lint that then never happens. The `-f` set\n// itself is the family's, from meta, rather than a fourth hand-kept copy of\n// the same five words.\nconst LIST_FORMATS = new Set<string>([\"pretty\", \"json\"]);\n\n/** The heading the tool's own options print under, after the shared ones. */\nconst TOOL_OPTIONS_GROUP = \"Tool options:\";\n\nfunction resolveColor(program: Command): boolean {\n // commander maps --no-color to opts.color === false.\n const noColor = program.opts().color === false;\n return shouldColor({ noColor, isTTY: process.stdout.isTTY });\n}\n\nfunction reportFormat(value: unknown): FamilyFormat {\n const format = String(value);\n if (!isReportFormat(format)) {\n throw new LintError(\n `Unknown --format \"${format}\". Use ${REPORT_FORMAT_LIST}.`,\n );\n }\n return format;\n}\n\n/**\n * Whether a clean run may print nothing at all in this format.\n *\n * Only `github` may: an empty annotation stream is a clean check. Every other\n * format owes its envelope - an empty JSON array, a SARIF log with no results,\n * a JUnit suite of passing testcases - because a consumer parsing stdout must\n * not have to treat \"no output\" as a third outcome. `explain` is never clean\n * or dirty; it always has something to say.\n */\nfunction omittedWhenClean(format: ReportFormat): boolean {\n return format !== \"explain\" && OMITTED_WHEN_CLEAN.has(format);\n}\n\nfunction listFormat(value: unknown): ListFormat {\n const format = String(value);\n if (!LIST_FORMATS.has(format)) {\n throw new LintError(\n `Unknown --format \"${format}\". Use pretty or json.`,\n );\n }\n return format as ListFormat;\n}\n\n/**\n * `templates infer -f`: the format a *template file* is written in, which is\n * not the set a report is rendered in. A template is YAML or JSON because those\n * are the two the loader reads back, and `pretty` would name a third thing the\n * tool cannot then load.\n */\nfunction inferFormat(value: unknown): InferFormat {\n const format = String(value);\n if (!isInferFormat(format)) {\n throw new LintError(`Unknown --format \"${format}\". Use yaml or json.`);\n }\n return format;\n}\n\n/**\n * `--tool <name>`: which tool performs the structure job. Refused by name\n * rather than ignored, because falling through to manni's engine would lint\n * with something other than what was asked for and say nothing.\n *\n * The refusal is the registry's, not a second copy of it here. `runLint`\n * refuses the same name with the same sentence for a caller that never touches\n * commander; this one fires first, so a bad `--tool` is reported before the\n * run asks what it was pointed at.\n */\nfunction assertStructureTool(value: string | undefined): void {\n if (value === undefined) return;\n resolveStructureTool(value);\n}\n\n/**\n * `-c/--config` and `--no-config`, in one place.\n *\n * Every verb here takes them, and they had been written out three times. A flag\n * two commands both have carries the same name *and* the same description, so\n * the declaration is shared rather than copied - which is what kept the fourth\n * copy, on `templates infer`, from spelling either of them slightly differently.\n */\nfunction withConfigOptions(command: Command): Command {\n return command\n .option(\"-c, --config <path>\", \"path to a manni config file\")\n .option(\"--no-config\", \"ignore any discovered config file\");\n}\n\n/**\n * The value of a flag a command and its parent both declare.\n *\n * Commander keeps parsing a parent's options past a subcommand name unless\n * `enablePositionalOptions()` is on, so `templates infer page.md -f json` sets\n * `format` on `templates` and leaves `infer` holding its own default. Both\n * commands declare `-f`, `-c` and `--no-config`, because \"commands must have\n * parallel behaviors\" and `infer` must list them in its own `--help`.\n *\n * Turning positional options on would fix it and move every other flag in this\n * program with it: `manni lint structure docs/ --no-color` is a root option\n * written after its command, and there are three more like it. So the lookup\n * changes instead. The nearest command actually *given* the flag wins, and the\n * subcommand's own default is the fallback - which is the reading a person\n * typing the line already has.\n */\nfunction optionValue(command: Command, key: string): unknown {\n for (\n let cmd: Command | null = command;\n cmd !== null;\n cmd = cmd.parent ?? null\n ) {\n if (cmd.getOptionValueSource(key) === \"cli\") return cmd.getOptionValue(key);\n }\n return command.getOptionValue(key);\n}\n\n/** The options every job verb takes, in one place so the two cannot drift. */\nfunction withInputOptions(command: Command): Command {\n command\n .argument(\n \"[paths...]\",\n \"files, directories, or globs to lint (use - for stdin)\",\n )\n .option(\n \"--collection <name>\",\n \"configured collection to run over; repeatable\",\n collect,\n [],\n )\n .option(\"--ext <list>\", \"comma-separated extensions for directory walks\")\n .option(\"--exclude <glob>\", \"glob to exclude; repeatable\", collect, [])\n .option(\"--as <format>\", \"force an input format (e.g. markdown, mdx)\")\n .option(\n \"-f, --format <format>\",\n `output: ${REPORT_FORMATS.join(\" | \")}`,\n \"pretty\",\n );\n return withConfigOptions(command)\n .option(\"--allow-empty\", \"treat zero matched files as success\")\n .option(\"--no-gitignore\", \"lint files .gitignore covers\");\n}\n\n/** The lint options every job verb turns its shared flags into. */\nfunction inputOptions(\n paths: string[],\n options: InputCliOptions,\n): {\n inputs: string[];\n collection: string[];\n exts?: string[];\n exclude: string[];\n as?: string;\n configPath?: string;\n noConfig?: boolean;\n allowEmpty?: boolean;\n respectGitignore?: boolean;\n onNotice: (message: string) => void;\n} {\n return {\n inputs: paths,\n collection: options.collection,\n ...(options.ext ? { exts: splitList(options.ext) } : {}),\n exclude: options.exclude,\n ...(options.as === undefined ? {} : { as: options.as }),\n ...configOption(options.config),\n // `undefined` rather than `false` when absent, so config still wins.\n ...(options.allowEmpty ? { allowEmpty: true } : {}),\n respectGitignore: explicitFalse(options.gitignore),\n onNotice: notice,\n };\n}\n\nexport function buildProgram(): Command {\n const program = new Command();\n program\n .name(\"lint\")\n .description(\n \"Validate document structure against doctype templates. Deterministic, CI-friendly.\",\n )\n .version(pkg.version, \"-V, --version\")\n .option(\"--no-color\", \"disable colored output\")\n .showHelpAfterError()\n // Exit code 1 is reserved for \"the docs are wrong\". Commander exits 1 on a\n // usage error by default, which would make a typo'd flag look exactly like\n // a failing lint to a workflow. With no callback, commander throws the\n // CommanderError instead, and the umbrella's runner maps it: help and\n // --version stay 0, every other usage error becomes 2. Commander has\n // already written its own message. This has to precede .command(), which\n // copies the callback into each subcommand.\n .exitOverride();\n\n /** Run one lint, render it, and settle the exit code. Both job verbs share it. */\n const lint = async (\n paths: string[],\n options: StructureCliOptions | InputCliOptions,\n command: Command,\n job: { tool?: StructureCliOptions } = {},\n ): Promise<void> => {\n const tool = job.tool;\n const format = reportFormat(options.format);\n const explain = tool?.explain === true;\n const stdinContent = paths.includes(STDIN_TOKEN) ? await readStdin() : undefined;\n const cwd = process.cwd();\n\n const run = await runLint({\n ...inputOptions(paths, options),\n ...(tool?.tool === undefined ? {} : { tool: tool.tool }),\n ...(tool?.template === undefined ? {} : { template: tool.template }),\n ...(tool && tool.templates.length > 0 ? { templates: tool.templates } : {}),\n ...(explain ? { explain: true } : {}),\n ...(stdinContent === undefined ? {} : { stdinContent }),\n // Which config governed the run, said where a report cannot be parsed\n // around: discovery walks up to the project boundary, so an unexpected\n // ancestor config is the difference between a five-minute diagnosis and\n // an hour of confusion.\n onConfigLoaded: reportConfig(format === \"pretty\", cwd),\n });\n\n const color = resolveColor(command.parent ?? command);\n const chosen: ReportFormat = explain ? \"explain\" : format;\n const text = render(run, chosen, { color });\n if (text.length > 0 || !omittedWhenClean(chosen)) {\n process.stdout.write(`${text}\\n`);\n }\n // `--explain` answers a question about configuration, so its exit code\n // reports whether it could answer it - not whether the docs are clean.\n //\n // That covers routing failures too: a page whose `type` matches no\n // template is a answered question, not an unanswered one, so it exits 0\n // like everything else here. Automation must not read this code as\n // \"everything routed\" - the ordinary run is what reports that, with exit\n // 1. Said in `--help` and the README, because the distinction is invisible\n // from the exit code alone.\n process.exitCode = explain ? 0 : run.summary.failed > 0 ? 1 : 0;\n };\n\n withInputOptions(\n program\n .command(\"check\")\n .description(\"Run every configured lint job over the given files/dirs/globs\"),\n )\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Jobs: structure.\",\n \"\",\n \"Examples:\",\n \" manni lint check docs/ # every configured job\",\n \" manni lint check # targets from collections:\",\n \" manni lint check --collection guides\",\n ' manni lint check \"**/*.md\" -f github # CI annotations',\n \" cat page.md | manni lint check - --as markdown\",\n ].join(\"\\n\"),\n )\n .action(async (paths: string[], options: InputCliOptions, command: Command) => {\n try {\n // Which jobs this run covered, said once, beside the config line. The\n // full form also names the jobs that exist and are not configured;\n // `structure` is the only job there is, so today it is one word.\n if (options.format === \"pretty\") {\n process.stderr.write(`Checked: ${LINT_JOBS.join(\", \")}.\\n`);\n }\n await lint(paths, options, command);\n } catch (err) {\n fail(err);\n }\n });\n\n const structure = withInputOptions(\n program\n .command(\"structure\")\n .description(\n \"Lint document structure against doctype templates, routing each page by its `type`\",\n ),\n );\n structure\n .optionsGroup(TOOL_OPTIONS_GROUP)\n .option(\n \"--tool <name>\",\n `tool that performs the job: ${TOOLS_BY_JOB.structure.join(\", \")}`,\n )\n .option(\n \"-t, --template <ref>\",\n \"apply this template to every file, overriding type routing\",\n )\n .option(\n \"--templates <path>\",\n \"template file to route by: its `types:` win over built-ins; repeatable\",\n collect,\n [],\n )\n .option(\n \"--explain\",\n \"print how each file's template was chosen, and lint nothing (always exits 0, unrouted pages included)\",\n )\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Examples:\",\n \" manni lint structure docs/ # route each page by its `type`\",\n \" manni lint structure docs/ --templates ./templates.yaml # add your own templates\",\n \" manni lint structure # targets from collections:\",\n \" manni lint structure docs/ --explain # show why each page routed where\",\n \" manni lint structure page.md -t tgdp:how-to:1.6 # force one template\",\n ' manni lint structure \"**/*.md\" -f github # CI annotations',\n \" manni lint structure docs/ --exclude '**/drafts/**'\",\n \" cat page.md | manni lint structure - -t tgdp:how-to:1.6 --as markdown\",\n ].join(\"\\n\"),\n )\n .action(\n async (paths: string[], options: StructureCliOptions, command: Command) => {\n try {\n assertStructureTool(options.tool);\n await lint(paths, options, command, { tool: options });\n } catch (err) {\n fail(err);\n }\n },\n );\n\n const templates = program\n .command(\"templates\")\n .description(\"List the templates that can be applied, and the types they serve\")\n .option(\n \"--templates <path>\",\n \"also list the templates in this file; repeatable\",\n collect,\n [],\n );\n withConfigOptions(templates)\n .option(\"-f, --format <format>\", \"output: pretty | json\", \"pretty\")\n .action(async (options: TemplatesCommandOptions, command: Command) => {\n try {\n const format = listFormat(options.format);\n // The listing answers \"what could route a page?\", so it has to see the\n // same template files a lint would - rebased the same way, or it would\n // answer for a different set of files depending on where it was run.\n const { configPath, noConfig } = configOption(options.config);\n const found = noConfig ? null : await loadConfig(configPath);\n const info = await runTemplates({\n templates:\n options.templates.length > 0\n ? options.templates\n : rebaseConfig(found).templates,\n });\n const color = resolveColor(command.parent ?? command);\n process.stdout.write(`${renderTemplates(info, format, { color })}\\n`);\n } catch (err) {\n fail(err);\n }\n });\n\n const inferCommand = templates\n .command(\"infer\")\n .description(\"Write a first template from a page that already has the shape you want\")\n .argument(\"<page>\", \"one file to infer from (use - for stdin)\")\n .option(\"--as <format>\", \"force an input format (e.g. markdown, mdx)\")\n .option(\n \"--name <name>\",\n \"name for the template; defaults to the page's `type`, else its filename\",\n )\n .option(\"-f, --format <format>\", `output: ${INFER_FORMATS.join(\" | \")}`, \"yaml\")\n .option(\"-o, --out <path>\", \"write the template here instead of to stdout\")\n .option(\"--force\", \"overwrite the --out path\");\n withConfigOptions(inferCommand)\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Examples:\",\n \" manni lint templates infer docs/guides/install.md\",\n \" manni lint templates infer docs/guides/install.md --name how-to\",\n \" manni lint templates infer page.mdx -f json\",\n \" manni lint templates infer page.md -o ./templates.yaml\",\n \" manni lint templates infer page.md -o ./templates.yaml --force\",\n \" cat page.md | manni lint templates infer - --as markdown\",\n \"\",\n \"One page, and every rule it writes is exactly one occurrence: a single\",\n \"page cannot show what varies. Loosening a heading into a list or a\",\n \"pattern, setting `min: 0`, and adding a trailing rule with no heading\",\n \"for the sections that may follow are your edits to make.\",\n ].join(\"\\n\"),\n )\n .action(\n async (\n page: string,\n options: TemplatesInferCliOptions,\n command: Command,\n ) => {\n try {\n // `-f`, `-c` and `--no-config` are read through `optionValue`: the\n // parent `templates` declares all three, and commander hands it any\n // of them typed after `infer`.\n const format = inferFormat(optionValue(command, \"format\"));\n const { configPath, noConfig } = configOption(\n optionValue(command, \"config\"),\n );\n const stdinContent =\n page === STDIN_TOKEN ? await readStdin() : undefined;\n const result = await runTemplatesInfer({\n page,\n format,\n ...(options.as === undefined ? {} : { as: options.as }),\n ...(options.name === undefined ? {} : { name: options.name }),\n ...(options.out === undefined ? {} : { out: options.out }),\n ...(options.force === undefined ? {} : { force: options.force }),\n ...(configPath === undefined ? {} : { configPath }),\n ...(noConfig === undefined ? {} : { noConfig }),\n ...(stdinContent === undefined ? {} : { stdinContent }),\n // The template is the primary output, so with no --out it owns\n // stdout and the config line goes to stderr beside it. With --out\n // stdout is free, and the line still belongs on stderr: a reader\n // piping nothing is not a reason to move a diagnostic.\n onConfigLoaded: reportConfig(false, process.cwd()),\n });\n\n if (result.written === undefined) {\n process.stdout.write(result.text);\n return;\n }\n // Said on stderr, so `-o` leaves stdout empty for a shell that is\n // watching it, and the template file is the whole output.\n process.stderr.write(\n `Wrote template \"${result.name}\" to ${result.written}\\n`,\n );\n } catch (err) {\n fail(err);\n }\n },\n );\n\n withConfigOptions(\n program\n .command(\"tools\")\n .description(\n \"List the lint jobs, the tool that performs each, and what it reads\",\n ),\n )\n .option(\"-f, --format <format>\", \"output: pretty | json\", \"pretty\")\n .action(async (options: ToolsCommandOptions, command: Command) => {\n try {\n const format = listFormat(options.format);\n const tools = await runTools(configOption(options.config));\n const color = resolveColor(command.parent ?? command);\n process.stdout.write(`${renderTools(tools, format, { color })}\\n`);\n } catch (err) {\n fail(err);\n }\n });\n\n return program;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -3,26 +3,26 @@ import {
|
|
|
3
3
|
runAdd,
|
|
4
4
|
runRemove,
|
|
5
5
|
runUpdate
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-FQXWVS6J.js";
|
|
7
7
|
import {
|
|
8
8
|
runCheck
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-PCS4VJBV.js";
|
|
10
10
|
import {
|
|
11
11
|
findingMessage,
|
|
12
12
|
renderCheckGithub
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-ADMEPUBT.js";
|
|
14
14
|
import {
|
|
15
15
|
renderCheckPretty,
|
|
16
16
|
renderRemovePretty,
|
|
17
17
|
renderUpdatePretty
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-4D5IZSXM.js";
|
|
19
19
|
import {
|
|
20
20
|
errorSite,
|
|
21
21
|
shortCommit,
|
|
22
22
|
shortLine,
|
|
23
23
|
shortPin,
|
|
24
24
|
shortSrc
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-WDWXAYVH.js";
|
|
26
26
|
import {
|
|
27
27
|
renderCheckJson,
|
|
28
28
|
renderRemoveJson,
|
|
@@ -35,12 +35,15 @@ import {
|
|
|
35
35
|
asCiteError,
|
|
36
36
|
isCiteRule,
|
|
37
37
|
spellSource
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-BKVHX6FU.js";
|
|
39
39
|
import "./chunk-IKEWBMCN.js";
|
|
40
|
-
import "./chunk-
|
|
40
|
+
import "./chunk-TU2WUBVZ.js";
|
|
41
|
+
import "./chunk-LKP7QDFN.js";
|
|
41
42
|
import {
|
|
42
43
|
terminalConfirm
|
|
43
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-6HWBRZIN.js";
|
|
45
|
+
import "./chunk-M42DZCOU.js";
|
|
46
|
+
import "./chunk-PCQ7ELJH.js";
|
|
44
47
|
import {
|
|
45
48
|
collect,
|
|
46
49
|
configOption,
|
|
@@ -49,7 +52,7 @@ import {
|
|
|
49
52
|
reportConfig,
|
|
50
53
|
splitList,
|
|
51
54
|
splitPageArgument
|
|
52
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-GV56WGL2.js";
|
|
53
56
|
import {
|
|
54
57
|
COMMON_FORMAT_LIST,
|
|
55
58
|
OMITTED_WHEN_CLEAN,
|
|
@@ -59,10 +62,10 @@ import {
|
|
|
59
62
|
isReportFormat,
|
|
60
63
|
renderJunit,
|
|
61
64
|
renderSarif
|
|
62
|
-
} from "./chunk-
|
|
65
|
+
} from "./chunk-D4N2V43Z.js";
|
|
63
66
|
import {
|
|
64
67
|
STDIN_TOKEN
|
|
65
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-VSEBFHAY.js";
|
|
66
69
|
import {
|
|
67
70
|
fail
|
|
68
71
|
} from "./chunk-YEUYKR62.js";
|
|
@@ -70,14 +73,14 @@ import {
|
|
|
70
73
|
shouldColor
|
|
71
74
|
} from "./chunk-RNVYGWIC.js";
|
|
72
75
|
import "./chunk-MNH7QO4Z.js";
|
|
73
|
-
import "./chunk-
|
|
76
|
+
import "./chunk-QLWC7MKD.js";
|
|
74
77
|
import {
|
|
75
78
|
notice
|
|
76
79
|
} from "./chunk-HX44GB4Z.js";
|
|
77
80
|
import "./chunk-QCHVR4ZM.js";
|
|
78
81
|
import {
|
|
79
82
|
package_default
|
|
80
|
-
} from "./chunk-
|
|
83
|
+
} from "./chunk-2MJ62AYQ.js";
|
|
81
84
|
import "./chunk-OWBRDNRZ.js";
|
|
82
85
|
import "./chunk-G3T47CFV.js";
|
|
83
86
|
import "./chunk-2H7UOFLK.js";
|
|
@@ -547,4 +550,4 @@ export {
|
|
|
547
550
|
colorFor,
|
|
548
551
|
splitPageArgument2 as splitPageArgument
|
|
549
552
|
};
|
|
550
|
-
//# sourceMappingURL=cli-
|
|
553
|
+
//# sourceMappingURL=cli-6KZTHWGP.js.map
|