@mintlify/cli 4.0.1741 → 4.0.1742
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/__test__/validateCommand.test.ts +106 -27
- package/bin/cli.js +7 -0
- package/bin/tsconfig.build.tsbuildinfo +1 -1
- package/bin/validate/command.js +45 -8
- package/package.json +4 -4
- package/src/cli.tsx +11 -0
- package/src/validate/command.tsx +44 -7
package/bin/validate/command.js
CHANGED
|
@@ -21,6 +21,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
21
21
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
22
22
|
import { addLog, checkBuild, clearLogs, ErrorLog, SpinnerLog } from '@mintlify/previewing';
|
|
23
23
|
import path from 'node:path';
|
|
24
|
+
import { format } from 'node:util';
|
|
24
25
|
import { CMD_EXEC_PATH, errorMessage, getVersions, terminate } from '../helpers.js';
|
|
25
26
|
import { resolveExplicitFiles } from '../resolveFiles.js';
|
|
26
27
|
import { sendPublishPrompt } from '../signup.js';
|
|
@@ -32,6 +33,26 @@ export const splitList = (values) => values.flatMap((value) => value
|
|
|
32
33
|
.split(',')
|
|
33
34
|
.map((item) => item.trim())
|
|
34
35
|
.filter(Boolean));
|
|
36
|
+
const write = (text) => new Promise((resolve) => {
|
|
37
|
+
process.stdout.write(text, () => resolve());
|
|
38
|
+
});
|
|
39
|
+
/**
|
|
40
|
+
* Writes console output straight to stderr, so --format json leaves stdout to the report. Ink
|
|
41
|
+
* patches console and redraws on stdout, so redirecting to console.error isn't enough.
|
|
42
|
+
*/
|
|
43
|
+
const consoleToStderr = () => {
|
|
44
|
+
const original = {
|
|
45
|
+
log: console.log,
|
|
46
|
+
info: console.info,
|
|
47
|
+
warn: console.warn,
|
|
48
|
+
error: console.error,
|
|
49
|
+
};
|
|
50
|
+
const toStderr = (...args) => {
|
|
51
|
+
process.stderr.write(`${format(...args)}\n`);
|
|
52
|
+
};
|
|
53
|
+
console.log = console.info = console.warn = console.error = toStderr;
|
|
54
|
+
return () => Object.assign(console, original);
|
|
55
|
+
};
|
|
35
56
|
const resolveSelection = (baseDir, values) => __awaiter(void 0, void 0, void 0, function* () {
|
|
36
57
|
const args = (values !== null && values !== void 0 ? values : []).map(String).filter(Boolean);
|
|
37
58
|
if (args.length === 0)
|
|
@@ -42,13 +63,16 @@ const resolveSelection = (baseDir, values) => __awaiter(void 0, void 0, void 0,
|
|
|
42
63
|
/** mint validate: one pass over every selected rule, then the strict build when nothing failed. */
|
|
43
64
|
export const validateHandler = (argv_1, packageName_1, ...args_1) => __awaiter(void 0, [argv_1, packageName_1, ...args_1], void 0, function* (argv, packageName, baseDir = CMD_EXEC_PATH) {
|
|
44
65
|
var _a;
|
|
66
|
+
const json = argv.format === 'json';
|
|
67
|
+
const restoreConsole = json ? consoleToStderr() : undefined;
|
|
45
68
|
try {
|
|
46
69
|
const rules = selectRules({
|
|
47
70
|
enable: argv.enable,
|
|
48
71
|
disable: (_a = argv.disable) !== null && _a !== void 0 ? _a : [],
|
|
49
72
|
});
|
|
50
73
|
const selected = yield resolveSelection(baseDir, argv.files);
|
|
51
|
-
|
|
74
|
+
if (!json)
|
|
75
|
+
addLog(_jsx(SpinnerLog, { message: "validating..." }));
|
|
52
76
|
const _b = yield checkSite(baseDir, rules, {
|
|
53
77
|
selected,
|
|
54
78
|
localSchema: argv['local-schema'],
|
|
@@ -67,7 +91,8 @@ export const validateHandler = (argv_1, packageName_1, ...args_1) => __awaiter(v
|
|
|
67
91
|
build = { ran: false, reason: 'errors found' };
|
|
68
92
|
}
|
|
69
93
|
else {
|
|
70
|
-
|
|
94
|
+
if (!json)
|
|
95
|
+
addLog(_jsx(SpinnerLog, { message: "building..." }));
|
|
71
96
|
const { cli: cliVersion } = getVersions(packageName);
|
|
72
97
|
site.build = yield checkBuild(Object.assign(Object.assign({}, argv), { _: [], $0: packageName, packageName,
|
|
73
98
|
cliVersion, disableOpenapi: !rules.some(({ group }) => group === 'openapi') }));
|
|
@@ -75,16 +100,28 @@ export const validateHandler = (argv_1, packageName_1, ...args_1) => __awaiter(v
|
|
|
75
100
|
build = { ran: true, passed: site.build.passed };
|
|
76
101
|
}
|
|
77
102
|
const report = toReport(diagnostics, build, argv.fix ? fixed : undefined);
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
103
|
+
if (json) {
|
|
104
|
+
restoreConsole === null || restoreConsole === void 0 ? void 0 : restoreConsole();
|
|
105
|
+
yield write(`${JSON.stringify(report)}\n`);
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
clearLogs();
|
|
109
|
+
logReport(report);
|
|
110
|
+
if (report.passed && build.ran && build.passed)
|
|
111
|
+
yield sendPublishPrompt();
|
|
112
|
+
}
|
|
82
113
|
yield terminate(report.passed ? EXIT.passed : EXIT.failed);
|
|
83
114
|
}
|
|
84
115
|
catch (error) {
|
|
85
116
|
// Bad arguments and crashes alike mean validate could not run
|
|
86
|
-
|
|
87
|
-
|
|
117
|
+
if (json) {
|
|
118
|
+
restoreConsole === null || restoreConsole === void 0 ? void 0 : restoreConsole();
|
|
119
|
+
process.stderr.write(`Error: ${errorMessage(error)}\n`);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
clearLogs();
|
|
123
|
+
addLog(_jsx(ErrorLog, { message: errorMessage(error) }));
|
|
124
|
+
}
|
|
88
125
|
yield terminate(EXIT.crashed);
|
|
89
126
|
}
|
|
90
127
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mintlify/cli",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.1742",
|
|
4
4
|
"description": "The Mintlify CLI",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=18.0.0"
|
|
@@ -46,11 +46,11 @@
|
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@inquirer/prompts": "7.9.0",
|
|
48
48
|
"@mintlify/common": "1.0.1307",
|
|
49
|
-
"@mintlify/link-rot": "3.0.
|
|
49
|
+
"@mintlify/link-rot": "3.0.1538",
|
|
50
50
|
"@mintlify/models": "0.0.379",
|
|
51
51
|
"@mintlify/og": "0.0.106",
|
|
52
52
|
"@mintlify/prebuild": "1.0.1474",
|
|
53
|
-
"@mintlify/previewing": "4.0.
|
|
53
|
+
"@mintlify/previewing": "4.0.1556",
|
|
54
54
|
"@mintlify/validation": "0.1.944",
|
|
55
55
|
"adm-zip": "0.6.0",
|
|
56
56
|
"chalk": "5.2.0",
|
|
@@ -101,5 +101,5 @@
|
|
|
101
101
|
"vitest": "2.1.9",
|
|
102
102
|
"vitest-mock-process": "1.0.4"
|
|
103
103
|
},
|
|
104
|
-
"gitHead": "
|
|
104
|
+
"gitHead": "d186b90eab824aece48724f71d3b71f2cdebdbe2"
|
|
105
105
|
}
|
package/src/cli.tsx
CHANGED
|
@@ -406,6 +406,13 @@ export const cli = ({ packageName = 'mint' }: { packageName?: string }) => {
|
|
|
406
406
|
default: false,
|
|
407
407
|
description: 'Apply the fixes and check again',
|
|
408
408
|
})
|
|
409
|
+
.option('format', {
|
|
410
|
+
type: 'string',
|
|
411
|
+
choices: ['text', 'json'] as const,
|
|
412
|
+
default: 'text' as const,
|
|
413
|
+
description:
|
|
414
|
+
'Output format; json prints one report ({ passed, summary, diagnostics, build }) and nothing else on stdout, and errors to stderr',
|
|
415
|
+
})
|
|
409
416
|
.usage('usage: mint validate [options]')
|
|
410
417
|
.epilogue(
|
|
411
418
|
[
|
|
@@ -415,6 +422,10 @@ export const cli = ({ packageName = 'mint' }: { packageName?: string }) => {
|
|
|
415
422
|
].join('\n')
|
|
416
423
|
)
|
|
417
424
|
.example('mint validate', 'run every check and the build')
|
|
425
|
+
.example(
|
|
426
|
+
'mint validate --no-build --format json',
|
|
427
|
+
'fast offline check for scripts and agents'
|
|
428
|
+
)
|
|
418
429
|
.example(
|
|
419
430
|
'mint validate --files "guides/**/*.mdx" --fix',
|
|
420
431
|
'check some pages and apply fixes'
|
package/src/validate/command.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { addLog, checkBuild, clearLogs, ErrorLog, SpinnerLog } from '@mintlify/previewing';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
+
import { format } from 'node:util';
|
|
3
4
|
|
|
4
5
|
import { CMD_EXEC_PATH, errorMessage, getVersions, terminate } from '../helpers.js';
|
|
5
6
|
import { resolveExplicitFiles } from '../resolveFiles.js';
|
|
@@ -17,6 +18,7 @@ export type ValidateArgs = {
|
|
|
17
18
|
enable?: string[];
|
|
18
19
|
disable?: string[];
|
|
19
20
|
fix: boolean;
|
|
21
|
+
format: 'text' | 'json';
|
|
20
22
|
};
|
|
21
23
|
|
|
22
24
|
export const EXIT = { passed: 0, failed: 1, crashed: 2 } as const;
|
|
@@ -29,6 +31,29 @@ export const splitList = (values: string[]) =>
|
|
|
29
31
|
.filter(Boolean)
|
|
30
32
|
);
|
|
31
33
|
|
|
34
|
+
const write = (text: string) =>
|
|
35
|
+
new Promise<void>((resolve) => {
|
|
36
|
+
process.stdout.write(text, () => resolve());
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Writes console output straight to stderr, so --format json leaves stdout to the report. Ink
|
|
41
|
+
* patches console and redraws on stdout, so redirecting to console.error isn't enough.
|
|
42
|
+
*/
|
|
43
|
+
const consoleToStderr = () => {
|
|
44
|
+
const original = {
|
|
45
|
+
log: console.log,
|
|
46
|
+
info: console.info,
|
|
47
|
+
warn: console.warn,
|
|
48
|
+
error: console.error,
|
|
49
|
+
};
|
|
50
|
+
const toStderr = (...args: unknown[]) => {
|
|
51
|
+
process.stderr.write(`${format(...args)}\n`);
|
|
52
|
+
};
|
|
53
|
+
console.log = console.info = console.warn = console.error = toStderr;
|
|
54
|
+
return () => Object.assign(console, original);
|
|
55
|
+
};
|
|
56
|
+
|
|
32
57
|
const resolveSelection = async (baseDir: string, values: (string | number)[] | undefined) => {
|
|
33
58
|
const args = (values ?? []).map(String).filter(Boolean);
|
|
34
59
|
if (args.length === 0) return undefined;
|
|
@@ -46,13 +71,15 @@ export const validateHandler = async (
|
|
|
46
71
|
packageName: string,
|
|
47
72
|
baseDir = CMD_EXEC_PATH
|
|
48
73
|
) => {
|
|
74
|
+
const json = argv.format === 'json';
|
|
75
|
+
const restoreConsole = json ? consoleToStderr() : undefined;
|
|
49
76
|
try {
|
|
50
77
|
const rules = selectRules({
|
|
51
78
|
enable: argv.enable,
|
|
52
79
|
disable: argv.disable ?? [],
|
|
53
80
|
});
|
|
54
81
|
const selected = await resolveSelection(baseDir, argv.files);
|
|
55
|
-
addLog(<SpinnerLog message="validating..." />);
|
|
82
|
+
if (!json) addLog(<SpinnerLog message="validating..." />);
|
|
56
83
|
|
|
57
84
|
const { site, fixed, ...checked } = await checkSite(baseDir, rules, {
|
|
58
85
|
selected,
|
|
@@ -70,7 +97,7 @@ export const validateHandler = async (
|
|
|
70
97
|
} else if (diagnostics.some(({ severity }) => severity === 'error')) {
|
|
71
98
|
build = { ran: false, reason: 'errors found' };
|
|
72
99
|
} else {
|
|
73
|
-
addLog(<SpinnerLog message="building..." />);
|
|
100
|
+
if (!json) addLog(<SpinnerLog message="building..." />);
|
|
74
101
|
const { cli: cliVersion } = getVersions(packageName);
|
|
75
102
|
site.build = await checkBuild({
|
|
76
103
|
...argv,
|
|
@@ -85,14 +112,24 @@ export const validateHandler = async (
|
|
|
85
112
|
}
|
|
86
113
|
|
|
87
114
|
const report = toReport(diagnostics, build, argv.fix ? fixed : undefined);
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
115
|
+
if (json) {
|
|
116
|
+
restoreConsole?.();
|
|
117
|
+
await write(`${JSON.stringify(report)}\n`);
|
|
118
|
+
} else {
|
|
119
|
+
clearLogs();
|
|
120
|
+
logReport(report);
|
|
121
|
+
if (report.passed && build.ran && build.passed) await sendPublishPrompt();
|
|
122
|
+
}
|
|
91
123
|
await terminate(report.passed ? EXIT.passed : EXIT.failed);
|
|
92
124
|
} catch (error) {
|
|
93
125
|
// Bad arguments and crashes alike mean validate could not run
|
|
94
|
-
|
|
95
|
-
|
|
126
|
+
if (json) {
|
|
127
|
+
restoreConsole?.();
|
|
128
|
+
process.stderr.write(`Error: ${errorMessage(error)}\n`);
|
|
129
|
+
} else {
|
|
130
|
+
clearLogs();
|
|
131
|
+
addLog(<ErrorLog message={errorMessage(error)} />);
|
|
132
|
+
}
|
|
96
133
|
await terminate(EXIT.crashed);
|
|
97
134
|
}
|
|
98
135
|
};
|