@mintlify/cli 4.0.1478 → 4.0.1479
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__/openApiCheck.test.ts +18 -5
- package/bin/cli.js +21 -3
- package/bin/openApiCheck.js +49 -13
- package/bin/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +8 -8
- package/src/cli.tsx +25 -3
- package/src/openApiCheck.tsx +66 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mintlify/cli",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.1479",
|
|
4
4
|
"description": "The Mintlify CLI",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=18.0.0"
|
|
@@ -45,12 +45,12 @@
|
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@inquirer/prompts": "7.9.0",
|
|
48
|
-
"@mintlify/common": "1.0.
|
|
49
|
-
"@mintlify/link-rot": "3.0.
|
|
48
|
+
"@mintlify/common": "1.0.1132",
|
|
49
|
+
"@mintlify/link-rot": "3.0.1334",
|
|
50
50
|
"@mintlify/models": "0.0.353",
|
|
51
|
-
"@mintlify/prebuild": "1.0.
|
|
52
|
-
"@mintlify/previewing": "4.0.
|
|
53
|
-
"@mintlify/validation": "0.1.
|
|
51
|
+
"@mintlify/prebuild": "1.0.1286",
|
|
52
|
+
"@mintlify/previewing": "4.0.1358",
|
|
53
|
+
"@mintlify/validation": "0.1.849",
|
|
54
54
|
"adm-zip": "0.6.0",
|
|
55
55
|
"chalk": "5.2.0",
|
|
56
56
|
"color": "4.2.3",
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"keytar": "7.9.0"
|
|
87
87
|
},
|
|
88
88
|
"devDependencies": {
|
|
89
|
-
"@mintlify/editor": "0.0.
|
|
89
|
+
"@mintlify/editor": "0.0.363",
|
|
90
90
|
"@mintlify/ts-config": "2.0.2",
|
|
91
91
|
"@tsconfig/recommended": "1.0.2",
|
|
92
92
|
"@types/detect-port": "1.3.2",
|
|
@@ -105,5 +105,5 @@
|
|
|
105
105
|
"vitest": "2.1.9",
|
|
106
106
|
"vitest-mock-process": "1.0.4"
|
|
107
107
|
},
|
|
108
|
-
"gitHead": "
|
|
108
|
+
"gitHead": "64f3cb09194b3f7a7259c9a08c4e47b7454bf9e9"
|
|
109
109
|
}
|
package/src/cli.tsx
CHANGED
|
@@ -45,7 +45,11 @@ import { logout } from './logout.js';
|
|
|
45
45
|
import { mdxLinter } from './mdxLinter.js';
|
|
46
46
|
import { createTelemetryMiddleware } from './middlewares/telemetryMiddleware.js';
|
|
47
47
|
import { mintTestHandler } from './mintTest.js';
|
|
48
|
-
import {
|
|
48
|
+
import {
|
|
49
|
+
buildOverlayRegistryForCheck,
|
|
50
|
+
checkOpenApiFile,
|
|
51
|
+
getOpenApiFilenamesFromDocsConfig,
|
|
52
|
+
} from './openApiCheck.js';
|
|
49
53
|
import { resolveExplicitFiles } from './resolveFiles.js';
|
|
50
54
|
import { scoreHandler } from './score/index.js';
|
|
51
55
|
import { signup } from './signup.js';
|
|
@@ -225,8 +229,18 @@ export const cli = ({ packageName = 'mint' }: { packageName?: string }) => {
|
|
|
225
229
|
openApiFilenames = getOpenApiFilenamesFromDocsConfig(JSON.parse(docsJson));
|
|
226
230
|
} catch {}
|
|
227
231
|
|
|
232
|
+
let overlayRegistry;
|
|
233
|
+
try {
|
|
234
|
+
overlayRegistry = await buildOverlayRegistryForCheck(argv['local-schema']);
|
|
235
|
+
} catch (error) {
|
|
236
|
+
addLog(<ErrorLog message={error instanceof Error ? error.message : String(error)} />);
|
|
237
|
+
await terminate(1);
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
228
240
|
const results = await Promise.all(
|
|
229
|
-
openApiFilenames.map((file) =>
|
|
241
|
+
openApiFilenames.map((file) =>
|
|
242
|
+
checkOpenApiFile(file, argv['local-schema'], overlayRegistry)
|
|
243
|
+
)
|
|
230
244
|
);
|
|
231
245
|
|
|
232
246
|
if (results.some((valid) => !valid)) {
|
|
@@ -308,7 +322,15 @@ export const cli = ({ packageName = 'mint' }: { packageName?: string }) => {
|
|
|
308
322
|
addLog(
|
|
309
323
|
<WarningLog message="openapi-check is deprecated, use `mintlify validate` instead" />
|
|
310
324
|
);
|
|
311
|
-
|
|
325
|
+
let overlayRegistry;
|
|
326
|
+
try {
|
|
327
|
+
overlayRegistry = await buildOverlayRegistryForCheck(localSchema);
|
|
328
|
+
} catch (error) {
|
|
329
|
+
addLog(<ErrorLog message={error instanceof Error ? error.message : String(error)} />);
|
|
330
|
+
await terminate(1);
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
const valid = await checkOpenApiFile(filename, localSchema, overlayRegistry);
|
|
312
334
|
await terminate(valid ? 0 : 1);
|
|
313
335
|
}
|
|
314
336
|
)
|
package/src/openApiCheck.tsx
CHANGED
|
@@ -1,24 +1,75 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
applyOverlays,
|
|
3
|
+
createOverlayRegistry,
|
|
4
|
+
getOpenApiDocumentFromUrl,
|
|
5
|
+
isAllowedLocalSchemaUrl,
|
|
6
|
+
resolveOverlaysForSpec,
|
|
7
|
+
validate,
|
|
8
|
+
type OverlayRegistry,
|
|
9
|
+
} from '@mintlify/common';
|
|
10
|
+
import { discoverOverlayFiles, getMintIgnore, resolveFileRefs } from '@mintlify/prebuild';
|
|
2
11
|
import { addLog, ErrorLog, SuccessLog, WarningLog } from '@mintlify/previewing';
|
|
3
|
-
import
|
|
12
|
+
import {
|
|
13
|
+
collectOpenApiOverlayConfig,
|
|
14
|
+
extractOpenApiEntries,
|
|
15
|
+
type DocsConfig,
|
|
16
|
+
} from '@mintlify/validation';
|
|
17
|
+
import { promises as fs } from 'fs';
|
|
18
|
+
import path from 'path';
|
|
4
19
|
|
|
5
|
-
import { readLocalOpenApiFile } from './helpers.js';
|
|
20
|
+
import { CMD_EXEC_PATH, readLocalOpenApiFile } from './helpers.js';
|
|
6
21
|
|
|
7
22
|
export const getOpenApiFilenamesFromDocsConfig = (config: Pick<DocsConfig, 'api'>): string[] => {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
23
|
+
return extractOpenApiEntries(config.api?.openapi).map((entry) => entry.source);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Builds the overlay registry so checks validate specs with overlays applied.
|
|
28
|
+
* Throws when docs.json configures conflicting overlay lists, matching the build.
|
|
29
|
+
*/
|
|
30
|
+
export const buildOverlayRegistryForCheck = async (
|
|
31
|
+
localSchema?: boolean
|
|
32
|
+
): Promise<OverlayRegistry | undefined> => {
|
|
33
|
+
// Discovery failures propagate and fail the check: silently skipping overlays would
|
|
34
|
+
// validate a different document than the one the build produces.
|
|
35
|
+
const mintIgnore = await getMintIgnore(CMD_EXEC_PATH);
|
|
36
|
+
const discovered = await discoverOverlayFiles(CMD_EXEC_PATH, mintIgnore);
|
|
37
|
+
|
|
38
|
+
let rawConfig: unknown;
|
|
39
|
+
try {
|
|
40
|
+
rawConfig = JSON.parse(await fs.readFile(path.join(CMD_EXEC_PATH, 'docs.json'), 'utf-8'));
|
|
41
|
+
} catch {
|
|
42
|
+
rawConfig = undefined;
|
|
43
|
+
}
|
|
44
|
+
if (rawConfig !== undefined) {
|
|
45
|
+
try {
|
|
46
|
+
rawConfig = (await resolveFileRefs(rawConfig, CMD_EXEC_PATH)).resolved;
|
|
47
|
+
} catch {
|
|
48
|
+
// Broken $refs are reported by regular config validation; collect from the root file.
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const explicit = rawConfig == undefined ? undefined : collectOpenApiOverlayConfig(rawConfig);
|
|
52
|
+
|
|
53
|
+
if (explicit == undefined && discovered.length === 0) return undefined;
|
|
54
|
+
|
|
55
|
+
return createOverlayRegistry({
|
|
56
|
+
explicit,
|
|
57
|
+
discovered,
|
|
58
|
+
localSchema,
|
|
59
|
+
loadLocalDocument: (normalizedPath) => readLocalOpenApiFile(normalizedPath),
|
|
60
|
+
});
|
|
13
61
|
};
|
|
14
62
|
|
|
15
63
|
export const checkOpenApiFile = async (
|
|
16
64
|
filename: string,
|
|
17
|
-
localSchema: boolean
|
|
65
|
+
localSchema: boolean,
|
|
66
|
+
overlayRegistry?: OverlayRegistry
|
|
18
67
|
): Promise<boolean> => {
|
|
19
68
|
try {
|
|
69
|
+
const overlays = overlayRegistry ? await resolveOverlaysForSpec(overlayRegistry, filename) : [];
|
|
70
|
+
|
|
20
71
|
if (isAllowedLocalSchemaUrl(filename, localSchema)) {
|
|
21
|
-
await getOpenApiDocumentFromUrl(filename);
|
|
72
|
+
await getOpenApiDocumentFromUrl(filename, { overlays });
|
|
22
73
|
addLog(<SuccessLog message="OpenAPI definition is valid." />);
|
|
23
74
|
return true;
|
|
24
75
|
}
|
|
@@ -37,7 +88,11 @@ export const checkOpenApiFile = async (
|
|
|
37
88
|
'failed to parse OpenAPI spec: could not parse file correctly, please check for any syntax errors.'
|
|
38
89
|
);
|
|
39
90
|
}
|
|
40
|
-
|
|
91
|
+
const overlaid: unknown = overlays.length > 0 ? applyOverlays(document, overlays) : document;
|
|
92
|
+
if (overlaid == undefined || typeof overlaid !== 'object') {
|
|
93
|
+
throw new Error('applying overlays produced an invalid OpenAPI document.');
|
|
94
|
+
}
|
|
95
|
+
await validate(overlaid);
|
|
41
96
|
addLog(<SuccessLog message="OpenAPI definition is valid." />);
|
|
42
97
|
return true;
|
|
43
98
|
} catch (err) {
|