UNPKG

@mintlify/cli

Version:

The Mintlify CLI

182 lines (181 loc) 8.9 kB
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 { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { validate, getOpenApiDocumentFromUrl, isAllowedLocalSchemaUrl } from '@mintlify/common'; import { getBrokenInternalLinks, renameFilesAndUpdateLinksInContent } from '@mintlify/link-rot'; import { addLog, dev, ErrorLog, SpinnerLog, SuccessLog, Logs, clearLogs, BrokenLinksLog, } from '@mintlify/previewing'; import { render, Text } from 'ink'; import path from 'path'; import semver from 'semver'; import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; import { LOCAL_LINKED_VERSION, MINIMUM_CLI_VERSION } from './constants.js'; import { checkPort, checkForMintJson, checkNodeVersion, upgradeConfig, checkForDocsJson, getCliVersion, getVersions, suppressConsoleWarnings, terminate, readLocalOpenApiFile, } from './helpers.js'; import { update } from './update.js'; export const cli = () => { render(_jsx(Logs, {})); return (yargs(hideBin(process.argv)) .middleware(checkNodeVersion) .middleware(suppressConsoleWarnings) .command('dev', 'initialize a local preview environment', (yargs) => yargs .option('open', { type: 'boolean', default: true, description: 'open a local preview in the browser', }) .option('local-schema', { type: 'boolean', default: false, hidden: true, description: 'use a locally hosted schema file (note: only https protocol is supported in production)', }) .option('client-version', { type: 'string', hidden: true, description: 'the version of the client to use for cli testing', }) .option('groups', { type: 'array', description: 'Mock user groups for local development and testing', example: '--groups admin user', }) .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* () { var _a, _b; const port = yield checkPort(argv); const packageName = (_b = (_a = process.argv[1]) === null || _a === void 0 ? void 0 : _a.split('/').pop()) !== null && _b !== void 0 ? _b : 'mintlify'; const cliVersion = getCliVersion(); if (cliVersion && cliVersion !== LOCAL_LINKED_VERSION && semver.lt(cliVersion, MINIMUM_CLI_VERSION)) { yield update({ packageName, silent: true }); } if (port != undefined) { yield dev(Object.assign(Object.assign({}, argv), { port, packageName, cliVersion: cli })); } else { addLog(_jsx(ErrorLog, { message: "no available port found" })); yield terminate(1); } })) .command('openapi-check <filename>', 'check if an OpenAPI spec is valid', (yargs) => yargs .positional('filename', { 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, }) .option('local-schema', { type: 'boolean', default: false, description: 'use a locally hosted schema file (note: only https protocol is supported in production)', }), (_a) => __awaiter(void 0, [_a], void 0, function* ({ filename, 'local-schema': localSchema }) { try { if (isAllowedLocalSchemaUrl(filename, localSchema)) { yield getOpenApiDocumentFromUrl(filename); addLog(_jsx(SuccessLog, { message: "OpenAPI definition is valid." })); yield terminate(0); } const document = yield readLocalOpenApiFile(filename); if (!document) { throw new Error('failed to parse OpenAPI spec: could not parse file correctly, please check for any syntax errors.'); } yield validate(document); addLog(_jsx(SuccessLog, { message: "OpenAPI definition is valid." })); } catch (err) { addLog(_jsx(ErrorLog, { message: err instanceof Error ? err.message : 'unknown error' })); yield terminate(1); } yield terminate(0); })) .command('broken-links', 'check for invalid internal links', () => undefined, () => __awaiter(void 0, void 0, void 0, function* () { const hasMintJson = yield checkForMintJson(); if (!hasMintJson) { yield checkForDocsJson(); } addLog(_jsx(SpinnerLog, { message: "checking for broken links..." })); try { const brokenLinks = yield getBrokenInternalLinks(); if (brokenLinks.length === 0) { clearLogs(); addLog(_jsx(SuccessLog, { message: "no broken links found" })); yield terminate(0); } 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]; } }); clearLogs(); addLog(_jsx(BrokenLinksLog, { brokenLinksByFile: brokenLinksByFile })); } catch (err) { addLog(_jsx(ErrorLog, { message: err instanceof Error ? err.message : 'unknown error' })); yield terminate(1); } yield terminate(0); })) .command('rename <from> <to>', 'rename a file and update all 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']) .option('force', { type: 'boolean', default: false, description: 'rename files and skip errors', }) .epilog('example: `mintlify rename introduction.mdx overview.mdx`'), (_a) => __awaiter(void 0, [_a], void 0, function* ({ from, to, force }) { const hasMintJson = yield checkForMintJson(); if (!hasMintJson) { yield checkForDocsJson(); } yield renameFilesAndUpdateLinksInContent(from, to, force); yield terminate(0); })) .command('update', 'update the CLI to the latest version', () => undefined, () => __awaiter(void 0, void 0, void 0, function* () { var _a, _b; const packageName = (_b = (_a = process.argv[1]) === null || _a === void 0 ? void 0 : _a.split('/').pop()) !== null && _b !== void 0 ? _b : 'mintlify'; yield update({ packageName }); yield terminate(0); })) .command('upgrade', 'upgrade mint.json file to docs.json (current format)', () => undefined, () => __awaiter(void 0, void 0, void 0, function* () { const hasMintJson = yield checkForMintJson(); if (!hasMintJson) { yield checkForDocsJson(); } yield upgradeConfig(); })) .command(['version', 'v'], 'display the current version of the CLI and client', () => undefined, () => __awaiter(void 0, void 0, void 0, function* () { const { cli, client } = getVersions(); addLog(_jsxs(Text, { children: [_jsx(Text, { bold: true, color: "green", children: "cli version" }), ' ', cli] })); addLog(_jsxs(Text, { children: [_jsx(Text, { bold: true, color: "green", children: "client version" }), ' ', client] })); })) // 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, default --version = -v .alias('h', 'help') .alias('v', 'version') .parse()); };