@mintlify/cli 4.0.604 → 4.0.605

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/bin/cli.js CHANGED
@@ -7,164 +7,170 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
10
11
  import { validate, getOpenApiDocumentFromUrl, isAllowedLocalSchemaUrl } from '@mintlify/common';
11
12
  import { getBrokenInternalLinks, renameFilesAndUpdateLinksInContent } from '@mintlify/link-rot';
12
- import { dev } from '@mintlify/previewing';
13
- import Chalk from 'chalk';
14
- import fs from 'fs/promises';
15
- import yaml from 'js-yaml';
13
+ import { addLog, dev, ErrorLog, SpinnerLog, SuccessLog, Logs, clearLogs, BrokenLinksLog, } from '@mintlify/previewing';
14
+ import { render, Text } from 'ink';
16
15
  import path from 'path';
17
16
  import semver from 'semver';
18
17
  import yargs from 'yargs';
19
18
  import { hideBin } from 'yargs/helpers';
20
19
  import { LOCAL_LINKED_VERSION, MINIMUM_CLI_VERSION } from './constants.js';
21
- import { checkPort, checkForMintJson, checkNodeVersion, upgradeConfig, checkForDocsJson, getCliVersion, getVersions, suppressConsoleWarnings, } from './helpers.js';
20
+ import { checkPort, checkForMintJson, checkNodeVersion, upgradeConfig, checkForDocsJson, getCliVersion, getVersions, suppressConsoleWarnings, terminate, readLocalOpenApiFile, } from './helpers.js';
22
21
  import { update } from './update.js';
23
- export const cli = () => yargs(hideBin(process.argv))
24
- .middleware(checkNodeVersion)
25
- .middleware(suppressConsoleWarnings)
26
- .command('dev', 'Runs Mintlify project locally.', (yargs) => yargs
27
- .option('open', {
28
- type: 'boolean',
29
- default: true,
30
- description: 'Open Mintlify in the browser',
31
- })
32
- .option('local-schema', {
33
- type: 'boolean',
34
- default: false,
35
- hidden: true,
36
- description: 'Use a locally hosted schema file (note: only https protocol is supported in production)',
37
- })
38
- .option('client-version', {
39
- type: 'string',
40
- hidden: true,
41
- description: 'The version of the client to use for cli testing',
42
- })
43
- .usage('Usage: mintlify dev [options]')
44
- .example('mintlify dev', 'Run with default settings (opens in browser)')
45
- .example('mintlify dev --no-open', 'Run without opening in browser'), (argv) => __awaiter(void 0, void 0, void 0, function* () {
46
- var _a, _b;
47
- const port = yield checkPort(argv);
48
- const packageName = (_b = (_a = process.argv[1]) === null || _a === void 0 ? void 0 : _a.split('/').pop()) !== null && _b !== void 0 ? _b : 'mintlify';
49
- const cliVersion = getCliVersion();
50
- if (cliVersion &&
51
- cliVersion !== LOCAL_LINKED_VERSION &&
52
- semver.lt(cliVersion, MINIMUM_CLI_VERSION)) {
53
- yield update({ packageName, silent: true });
54
- }
55
- if (port != undefined) {
56
- yield dev(Object.assign(Object.assign({}, argv), { port,
57
- packageName, cliVersion: cli }));
58
- }
59
- else {
60
- console.error(`No available port found.`);
61
- }
62
- }))
63
- .command('openapi-check <openapiFilenameOrUrl>', 'Validate an OpenAPI spec', (yargs) => yargs
64
- .positional('openapiFilenameOrUrl', {
65
- describe: 'The filename of the OpenAPI spec (e.g. ./openapi.yaml) or the URL to the OpenAPI spec (e.g. https://petstore3.swagger.io/api/v3/openapi.json)',
66
- type: 'string',
67
- demandOption: true,
68
- })
69
- .option('local-schema', {
70
- type: 'boolean',
71
- default: false,
72
- description: 'Use a locally hosted schema file (note: only https protocol is supported in production)',
73
- }), (_a) => __awaiter(void 0, [_a], void 0, function* ({ openapiFilenameOrUrl, 'local-schema': localSchema }) {
74
- try {
75
- if (isAllowedLocalSchemaUrl(openapiFilenameOrUrl, localSchema)) {
76
- yield getOpenApiDocumentFromUrl(openapiFilenameOrUrl);
77
- console.log('✅ Your OpenAPI definition is valid.');
78
- process.exit(0);
22
+ export const cli = () => {
23
+ render(_jsx(Logs, {}));
24
+ return (yargs(hideBin(process.argv))
25
+ .middleware(checkNodeVersion)
26
+ .middleware(suppressConsoleWarnings)
27
+ .command('dev', 'initialize a local preview environment', (yargs) => yargs
28
+ .option('open', {
29
+ type: 'boolean',
30
+ default: true,
31
+ description: 'open a local preview in the browser',
32
+ })
33
+ .option('local-schema', {
34
+ type: 'boolean',
35
+ default: false,
36
+ hidden: true,
37
+ description: 'use a locally hosted schema file (note: only https protocol is supported in production)',
38
+ })
39
+ .option('client-version', {
40
+ type: 'string',
41
+ hidden: true,
42
+ description: 'the version of the client to use for cli testing',
43
+ })
44
+ .usage('usage: mintlify dev [options]')
45
+ .example('mintlify dev', 'run with default settings (opens in browser)')
46
+ .example('mintlify dev --no-open', 'run without opening in browser'), (argv) => __awaiter(void 0, void 0, void 0, function* () {
47
+ var _a, _b;
48
+ const port = yield checkPort(argv);
49
+ const packageName = (_b = (_a = process.argv[1]) === null || _a === void 0 ? void 0 : _a.split('/').pop()) !== null && _b !== void 0 ? _b : 'mintlify';
50
+ const cliVersion = getCliVersion();
51
+ if (cliVersion &&
52
+ cliVersion !== LOCAL_LINKED_VERSION &&
53
+ semver.lt(cliVersion, MINIMUM_CLI_VERSION)) {
54
+ yield update({ packageName, silent: true });
79
55
  }
80
- const pathname = path.resolve(process.cwd(), openapiFilenameOrUrl);
81
- const file = yield fs.readFile(pathname, 'utf-8');
82
- const document = yaml.load(file);
83
- if (!document) {
84
- throw new Error('Failed to parse OpenAPI spec: could not parse file correctly, please check for any syntax errors.');
56
+ if (port != undefined) {
57
+ yield dev(Object.assign(Object.assign({}, argv), { port,
58
+ packageName, cliVersion: cli }));
85
59
  }
86
- yield validate(document);
87
- console.log('✅ Your OpenAPI definition is valid.');
88
- }
89
- catch (err) {
90
- console.error(Chalk.red(err));
91
- process.exit(1);
92
- }
93
- }))
94
- .command('broken-links', 'Check for broken links in your Mintlify project.', () => undefined, () => __awaiter(void 0, void 0, void 0, function* () {
95
- const hasMintJson = yield checkForMintJson();
96
- if (!hasMintJson) {
97
- yield checkForDocsJson();
98
- }
99
- console.log(Chalk.bold('Checking for broken links...\n'));
100
- try {
101
- const brokenLinks = yield getBrokenInternalLinks();
102
- if (brokenLinks.length === 0) {
103
- console.log(Chalk.green('No broken links found.'));
104
- return;
60
+ else {
61
+ addLog(_jsx(ErrorLog, { message: "no available port found" }));
62
+ yield terminate(1);
105
63
  }
106
- const brokenLinksByFile = {};
107
- brokenLinks.forEach((mdxPath) => {
108
- const filename = path.join(mdxPath.relativeDir, mdxPath.filename);
109
- const brokenLinksForFile = brokenLinksByFile[filename];
110
- if (brokenLinksForFile) {
111
- brokenLinksForFile.push(mdxPath.originalPath);
64
+ }))
65
+ .command('openapi-check <filename>', 'check if an OpenAPI spec is valid', (yargs) => yargs
66
+ .positional('filename', {
67
+ describe: 'the filename of the OpenAPI spec (e.g. ./openapi.yaml) or the URL to the OpenAPI spec (e.g. https://petstore3.swagger.io/api/v3/openapi.json)',
68
+ type: 'string',
69
+ demandOption: true,
70
+ })
71
+ .option('local-schema', {
72
+ type: 'boolean',
73
+ default: false,
74
+ description: 'use a locally hosted schema file (note: only https protocol is supported in production)',
75
+ }), (_a) => __awaiter(void 0, [_a], void 0, function* ({ filename, 'local-schema': localSchema }) {
76
+ try {
77
+ if (isAllowedLocalSchemaUrl(filename, localSchema)) {
78
+ yield getOpenApiDocumentFromUrl(filename);
79
+ addLog(_jsx(SuccessLog, { message: "OpenAPI definition is valid." }));
80
+ yield terminate(0);
112
81
  }
113
- else {
114
- brokenLinksByFile[filename] = [mdxPath.originalPath];
82
+ const document = yield readLocalOpenApiFile(filename);
83
+ if (!document) {
84
+ throw new Error('failed to parse OpenAPI spec: could not parse file correctly, please check for any syntax errors.');
115
85
  }
116
- });
117
- Object.entries(brokenLinksByFile).forEach(([fileName, brokenLinks]) => {
118
- console.group(`${Chalk.underline(fileName)}`);
119
- console.log(brokenLinks.join('\n'), '\n');
120
- console.groupEnd();
121
- });
122
- console.error(Chalk.yellow(`${brokenLinks.length} broken links found.`));
123
- process.exit(1);
124
- }
125
- catch (err) {
126
- console.error(Chalk.red(err));
127
- process.exit(1);
128
- }
129
- }))
130
- .command('rename <from> <to>', 'Rename file in a Mintlify project and update the internal link references.', (yargs) => yargs
131
- .positional('from', {
132
- describe: 'The file to rename',
133
- type: 'string',
134
- })
135
- .positional('to', {
136
- describe: 'The new name for the file',
137
- type: 'string',
138
- })
139
- .demandOption(['from', 'to'])
140
- .epilog('Example: `mintlify rename introduction.mdx overview.mdx`'), (_a) => __awaiter(void 0, [_a], void 0, function* ({ from, to }) {
141
- const hasMintJson = yield checkForMintJson();
142
- if (!hasMintJson) {
143
- yield checkForDocsJson();
144
- }
145
- yield renameFilesAndUpdateLinksInContent(from, to);
146
- }))
147
- .command('update', 'Update the Mintlify client and cli to the latest version', () => undefined, () => __awaiter(void 0, void 0, void 0, function* () {
148
- var _a, _b;
149
- const packageName = (_b = (_a = process.argv[1]) === null || _a === void 0 ? void 0 : _a.split('/').pop()) !== null && _b !== void 0 ? _b : 'mintlify';
150
- yield update({ packageName });
151
- }))
152
- .command('upgrade', 'Upgrade the mint.json file to v2 (docs.json)', () => undefined, () => __awaiter(void 0, void 0, void 0, function* () {
153
- const hasMintJson = yield checkForMintJson();
154
- if (!hasMintJson) {
155
- yield checkForDocsJson();
156
- }
157
- yield upgradeConfig();
158
- }))
159
- .command(['version', 'v'], 'Print the current version of the Mintlify CLI and client', () => undefined, () => {
160
- const { cli, client } = getVersions();
161
- console.log(`Mintlify CLI version: ${cli}`);
162
- console.log(`Mintlify Client version: ${client}`);
163
- })
164
- // Print the help menu when the user enters an invalid command.
165
- .strictCommands()
166
- .demandCommand(1, 'Unknown command. See above for the list of supported commands.')
167
- // Alias option flags --help = -h, default --version = -v
168
- .alias('h', 'help')
169
- .alias('v', 'version')
170
- .parse();
86
+ yield validate(document);
87
+ addLog(_jsx(SuccessLog, { message: "OpenAPI definition is valid." }));
88
+ }
89
+ catch (err) {
90
+ addLog(_jsx(ErrorLog, { message: err instanceof Error ? err.message : 'unknown error' }));
91
+ yield terminate(1);
92
+ }
93
+ yield terminate(0);
94
+ }))
95
+ .command('broken-links', 'check for invalid internal links', () => undefined, () => __awaiter(void 0, void 0, void 0, function* () {
96
+ const hasMintJson = yield checkForMintJson();
97
+ if (!hasMintJson) {
98
+ yield checkForDocsJson();
99
+ }
100
+ addLog(_jsx(SpinnerLog, { message: "checking for broken links..." }));
101
+ try {
102
+ const brokenLinks = yield getBrokenInternalLinks();
103
+ if (brokenLinks.length === 0) {
104
+ clearLogs();
105
+ addLog(_jsx(SuccessLog, { message: "no broken links found" }));
106
+ yield terminate(0);
107
+ }
108
+ const brokenLinksByFile = {};
109
+ brokenLinks.forEach((mdxPath) => {
110
+ const filename = path.join(mdxPath.relativeDir, mdxPath.filename);
111
+ const brokenLinksForFile = brokenLinksByFile[filename];
112
+ if (brokenLinksForFile) {
113
+ brokenLinksForFile.push(mdxPath.originalPath);
114
+ }
115
+ else {
116
+ brokenLinksByFile[filename] = [mdxPath.originalPath];
117
+ }
118
+ });
119
+ clearLogs();
120
+ addLog(_jsx(BrokenLinksLog, { brokenLinksByFile: brokenLinksByFile }));
121
+ }
122
+ catch (err) {
123
+ addLog(_jsx(ErrorLog, { message: err instanceof Error ? err.message : 'unknown error' }));
124
+ yield terminate(1);
125
+ }
126
+ yield terminate(0);
127
+ }))
128
+ .command('rename <from> <to>', 'rename a file and update all internal link references', (yargs) => yargs
129
+ .positional('from', {
130
+ describe: 'the file to rename',
131
+ type: 'string',
132
+ })
133
+ .positional('to', {
134
+ describe: 'the new name for the file',
135
+ type: 'string',
136
+ })
137
+ .demandOption(['from', 'to'])
138
+ .option('force', {
139
+ type: 'boolean',
140
+ default: false,
141
+ description: 'rename files and skip errors',
142
+ })
143
+ .epilog('example: `mintlify rename introduction.mdx overview.mdx`'), (_a) => __awaiter(void 0, [_a], void 0, function* ({ from, to, force }) {
144
+ const hasMintJson = yield checkForMintJson();
145
+ if (!hasMintJson) {
146
+ yield checkForDocsJson();
147
+ }
148
+ yield renameFilesAndUpdateLinksInContent(from, to, force);
149
+ yield terminate(0);
150
+ }))
151
+ .command('update', 'update the CLI to the latest version', () => undefined, () => __awaiter(void 0, void 0, void 0, function* () {
152
+ var _a, _b;
153
+ const packageName = (_b = (_a = process.argv[1]) === null || _a === void 0 ? void 0 : _a.split('/').pop()) !== null && _b !== void 0 ? _b : 'mintlify';
154
+ yield update({ packageName });
155
+ yield terminate(0);
156
+ }))
157
+ .command('upgrade', 'upgrade mint.json file to docs.json (current format)', () => undefined, () => __awaiter(void 0, void 0, void 0, function* () {
158
+ const hasMintJson = yield checkForMintJson();
159
+ if (!hasMintJson) {
160
+ yield checkForDocsJson();
161
+ }
162
+ yield upgradeConfig();
163
+ }))
164
+ .command(['version', 'v'], 'display the current version of the CLI and client', () => undefined, () => __awaiter(void 0, void 0, void 0, function* () {
165
+ const { cli, client } = getVersions();
166
+ addLog(_jsxs(Text, { children: [_jsx(Text, { bold: true, color: "green", children: "cli version" }), ' ', cli] }));
167
+ addLog(_jsxs(Text, { children: [_jsx(Text, { bold: true, color: "green", children: "client version" }), ' ', client] }));
168
+ }))
169
+ // Print the help menu when the user enters an invalid command.
170
+ .strictCommands()
171
+ .demandCommand(1, 'unknown command. see above for the list of supported commands.')
172
+ // Alias option flags --help = -h, default --version = -v
173
+ .alias('h', 'help')
174
+ .alias('v', 'version')
175
+ .parse());
176
+ };
package/bin/helpers.js CHANGED
@@ -7,17 +7,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
+ import { jsx as _jsx } from "react/jsx-runtime";
10
11
  import { getConfigPath } from '@mintlify/prebuild';
11
12
  import { MintConfigUpdater } from '@mintlify/prebuild';
12
- import { getClientVersion } from '@mintlify/previewing';
13
+ import { addLog, ErrorLog, getClientVersion, SuccessLog, InfoLog, SpinnerLog, removeLastLog, } from '@mintlify/previewing';
13
14
  import { upgradeToDocsConfig } from '@mintlify/validation';
14
- import Chalk from 'chalk';
15
15
  import detect from 'detect-port';
16
16
  import fse from 'fs-extra';
17
17
  import fs from 'fs/promises';
18
18
  import inquirer from 'inquirer';
19
- import { execSync } from 'node:child_process';
20
- import Ora from 'ora';
19
+ import yaml from 'js-yaml';
20
+ import { exec, execSync } from 'node:child_process';
21
+ import { promisify } from 'node:util';
21
22
  import path from 'path';
22
23
  import yargs from 'yargs';
23
24
  import { CMD_EXEC_PATH, LOCAL_LINKED_VERSION } from './constants.js';
@@ -26,7 +27,7 @@ export const checkPort = (argv) => __awaiter(void 0, void 0, void 0, function* (
26
27
  if (initialPort === (yield detect(initialPort)))
27
28
  return initialPort;
28
29
  for (let port = initialPort + 1; port < initialPort + 10; port++) {
29
- console.log(`Port ${port - 1} is already in use. Trying ${port} instead.`);
30
+ addLog(_jsx(InfoLog, { message: `port ${port - 1} is already in use. trying ${port} instead` }));
30
31
  if (port === (yield detect(port)))
31
32
  return port;
32
33
  }
@@ -39,39 +40,33 @@ export const checkNodeVersion = () => __awaiter(void 0, void 0, void 0, function
39
40
  const versionArr = nodeVersionString.split('.');
40
41
  const majorVersion = parseInt(versionArr[0], 10);
41
42
  if (majorVersion < 18) {
42
- const logger = buildLogger();
43
- logger.fail(`Mintlify requires a node version >= 18.0.0 (current version ${nodeVersionString}). Try removing the mintlify package, upgrading node, reinstalling mintlify, and running again.`);
44
- process.exit(1);
43
+ addLog(_jsx(ErrorLog, { message: `mintlify requires a node version >= 18.0.0 (current version ${nodeVersionString}). try removing the mintlify package, upgrading node, reinstalling mintlify, and running again.` }));
45
44
  }
46
45
  });
47
- export const buildLogger = (startText = '') => {
48
- const logger = Ora().start(startText);
49
- return logger;
50
- };
51
46
  export const checkForMintJson = () => __awaiter(void 0, void 0, void 0, function* () {
52
47
  return !!(yield getConfigPath(CMD_EXEC_PATH, 'mint'));
53
48
  });
54
49
  export const checkForDocsJson = () => __awaiter(void 0, void 0, void 0, function* () {
55
50
  const docsJsonPath = path.join(CMD_EXEC_PATH, 'docs.json');
56
51
  if (!(yield fse.pathExists(docsJsonPath))) {
57
- console.log('New docs.json file is available.');
52
+ addLog(_jsx(InfoLog, { message: "new docs.json file is available" }));
58
53
  const promptResult = yield inquirer.prompt([
59
54
  {
60
55
  type: 'list',
61
56
  name: 'action',
62
- message: 'Would you like to upgrade your mint.json to docs.json?',
57
+ message: 'would you like to upgrade your mint.json to docs.json?',
63
58
  choices: [
64
- { name: 'Continue (use existing mint.json)', value: 'continue' },
65
- { name: 'Upgrade (migrate from mint.json -> docs.json)', value: 'upgrade' },
59
+ { name: 'upgrade (migrate from mint.json to docs.json)', value: 'upgrade' },
60
+ { name: 'continue (use existing mint.json)', value: 'continue' },
66
61
  ],
67
62
  },
68
63
  ]);
69
64
  const { action } = promptResult;
70
65
  if (action === 'continue') {
71
- console.log('Proceeding with the existing mint.json...');
66
+ addLog(_jsx(InfoLog, { message: "proceeding with the existing mint.json..." }));
72
67
  }
73
68
  if (action === 'upgrade') {
74
- console.log('Upgrading docs.json...');
69
+ addLog(_jsx(SpinnerLog, { message: "upgrading docs.json..." }));
75
70
  yield upgradeConfig();
76
71
  }
77
72
  }
@@ -87,11 +82,12 @@ export const upgradeConfig = () => __awaiter(void 0, void 0, void 0, function* (
87
82
  shouldUpgradeTheme: true,
88
83
  });
89
84
  yield fs.writeFile(docsJsonPath, JSON.stringify(upgradedDocsConfig, null, 2));
90
- console.log(Chalk.green('✅ Your mint.json file has been upgraded to v2 (docs.json).'));
85
+ removeLastLog();
86
+ addLog(_jsx(SuccessLog, { message: "mint.json file has been upgraded to docs.json." }));
91
87
  }
92
88
  catch (err) {
93
- console.error(Chalk.red(err));
94
- process.exit(1);
89
+ removeLastLog();
90
+ addLog(_jsx(ErrorLog, { message: err instanceof Error ? err.message : 'an unknown error occurred' }));
95
91
  }
96
92
  });
97
93
  export const getCliVersion = () => {
@@ -143,3 +139,15 @@ export const suppressConsoleWarnings = () => {
143
139
  originalConsoleWarn.apply(console, args);
144
140
  };
145
141
  };
142
+ export const readLocalOpenApiFile = (filename) => __awaiter(void 0, void 0, void 0, function* () {
143
+ const pathname = path.resolve(process.cwd(), filename);
144
+ const file = yield fs.readFile(pathname, 'utf-8');
145
+ const document = yaml.load(file);
146
+ return document;
147
+ });
148
+ export const terminate = (code) => __awaiter(void 0, void 0, void 0, function* () {
149
+ // Wait for the logs to be fully rendered before exiting
150
+ yield new Promise((resolve) => setTimeout(resolve, 50));
151
+ process.exit(code);
152
+ });
153
+ export const execAsync = promisify(exec);