@mintlify/cli
Version:
The Mintlify CLI
131 lines (130 loc) • 5.8 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { validate, getOpenApiDocumentFromUrl } from '@mintlify/common';
import { getBrokenInternalLinks, renameFilesAndUpdateLinksInContent } from '@mintlify/link-rot';
import { dev } from '@mintlify/previewing';
import Chalk from 'chalk';
import fs from 'fs/promises';
import yaml from 'js-yaml';
import path from 'path';
import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';
import { checkPort, checkForMintJson, checkNodeVersion, upgradeConfig, checkForDocsJson, } from './helpers.js';
export const cli = () => yargs(hideBin(process.argv))
.middleware(checkNodeVersion)
.command('dev', 'Runs Mintlify project locally.', (yargs) => yargs
.option('open', {
type: 'boolean',
default: true,
description: 'Open 🌿 Mintlify in the browser',
})
.usage('Usage: mintlify dev [options]')
.example('mintlify dev', 'Run with default settings (opens in browser)')
.example('mintlify dev --no-open', 'Run without opening in browser'), (argv) => __awaiter(void 0, void 0, void 0, function* () {
const port = yield checkPort(argv);
if (port != undefined) {
yield dev(Object.assign(Object.assign({}, argv), { port }));
}
else {
console.error(`No available port found.`);
}
}))
.command('openapi-check <openapiFilenameOrUrl>', 'Validate an OpenAPI spec', (yargs) => yargs.positional('openapiFilenameOrUrl', {
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)',
type: 'string',
demandOption: true,
}), (_a) => __awaiter(void 0, [_a], void 0, function* ({ openapiFilenameOrUrl }) {
try {
if (openapiFilenameOrUrl.startsWith('https://')) {
yield getOpenApiDocumentFromUrl(openapiFilenameOrUrl);
console.log('✅ Your OpenAPI definition is valid.');
process.exit(0);
}
const pathname = path.resolve(process.cwd(), openapiFilenameOrUrl);
const file = yield fs.readFile(pathname, 'utf-8');
const document = yaml.load(file);
if (!document) {
throw new Error('Failed to parse OpenAPI spec: could not parse file correctly, please check for any syntax errors.');
}
yield validate(document);
console.log('✅ Your OpenAPI definition is valid.');
}
catch (err) {
console.error(Chalk.red(err));
process.exit(1);
}
}))
.command('broken-links', 'Check for broken links in your Mintlify project.', () => undefined, () => __awaiter(void 0, void 0, void 0, function* () {
const hasMintJson = yield checkForMintJson();
if (!hasMintJson) {
yield checkForDocsJson();
}
console.log(Chalk.bold('Checking for broken links...\n'));
try {
const brokenLinks = yield getBrokenInternalLinks();
if (brokenLinks.length === 0) {
console.log(Chalk.green('No broken links found.'));
return;
}
const brokenLinksByFile = {};
brokenLinks.forEach((mdxPath) => {
const filename = path.join(mdxPath.relativeDir, mdxPath.filename);
const brokenLinksForFile = brokenLinksByFile[filename];
if (brokenLinksForFile) {
brokenLinksForFile.push(mdxPath.originalPath);
}
else {
brokenLinksByFile[filename] = [mdxPath.originalPath];
}
});
Object.entries(brokenLinksByFile).forEach(([fileName, brokenLinks]) => {
console.group(`${Chalk.underline(fileName)}`);
console.log(brokenLinks.join('\n'), '\n');
console.groupEnd();
});
console.error(Chalk.yellow(`${brokenLinks.length} broken links found.`));
process.exit(1);
}
catch (err) {
console.error(Chalk.red(err));
process.exit(1);
}
}))
.command('rename <from> <to>', 'Rename file in a Mintlify project and update the internal link references.', (yargs) => yargs
.positional('from', {
describe: 'The file to rename',
type: 'string',
})
.positional('to', {
describe: 'The new name for the file',
type: 'string',
})
.demandOption(['from', 'to'])
.epilog('Example: `mintlify rename introduction.mdx overview.mdx`'), (_a) => __awaiter(void 0, [_a], void 0, function* ({ from, to }) {
const hasMintJson = yield checkForMintJson();
if (!hasMintJson) {
yield checkForDocsJson();
}
yield renameFilesAndUpdateLinksInContent(from, to);
}))
.command('upgrade', 'Upgrade the mint.json file to v2 (docs.json)', () => undefined, () => __awaiter(void 0, void 0, void 0, function* () {
const hasMintJson = yield checkForMintJson();
if (!hasMintJson) {
yield checkForDocsJson();
}
yield upgradeConfig();
}))
// Print the help menu when the user enters an invalid command.
.strictCommands()
.demandCommand(1, 'Unknown command. See above for the list of supported commands.')
// Alias option flags --help = -h, --version = -v
.alias('h', 'help')
.alias('v', 'version')
.parse();