@mintlify/previewing
Version:
Preview Mintlify docs locally
106 lines (105 loc) • 4.29 kB
JavaScript
import { jsx as _jsx } from "react/jsx-runtime";
import { getFileListSync, prebuild } from '@mintlify/prebuild';
import fse, { pathExists } from 'fs-extra';
import isOnline from 'is-online';
import pathUtil from 'path';
import { CLIENT_PATH, DOT_MINTLIFY, CMD_EXEC_PATH, VERSION_PATH, NEXT_PUBLIC_PATH, NEXT_PROPS_PATH, } from '../constants.js';
import { addLog, clearLogs } from '../logging-state.js';
import { ErrorLog, SpinnerLog } from '../logs.js';
import { timeDev, timeDevSync } from './dev-timing.js';
import { run } from './run.js';
import { silentUpdateClient } from './update.js';
const PRUNE_EXEMPT_PREFIXES = ['favicons/', '.mint-content-source'];
const prunePublicOrphans = () => {
let publicFiles;
try {
publicFiles = getFileListSync(NEXT_PUBLIC_PATH);
}
catch {
return;
}
for (const relativePath of publicFiles) {
if (PRUNE_EXEMPT_PREFIXES.some((prefix) => relativePath.startsWith(prefix))) {
continue;
}
if (!fse.existsSync(pathUtil.join(CMD_EXEC_PATH, relativePath))) {
fse.removeSync(pathUtil.join(NEXT_PUBLIC_PATH, relativePath));
}
}
};
const dev = async (argv) => {
const hasInternet = await timeDev('check internet', () => isOnline());
const localSchema = argv['local-schema'];
const clientVersion = argv['client-version'];
const localClientVersion = argv['local-client-version'];
const packageName = argv.packageName;
const groups = argv.groups;
const cliVersion = argv.cliVersion;
const disableOpenApi = argv.disableOpenapi;
await timeDev('ensure .mintlify directory', () => fse.ensureDir(DOT_MINTLIFY));
const versionString = await timeDev('read local client version', async () => {
return (await pathExists(VERSION_PATH)) ? fse.readFileSync(VERSION_PATH, 'utf8') : null;
});
if (!versionString && !localClientVersion && !hasInternet) {
clearLogs();
addLog(_jsx(ErrorLog, { message: `running ${packageName} dev after updating requires an internet connection.` }));
await new Promise((resolve) => setTimeout(resolve, 50));
process.exit(1);
}
addLog(_jsx(SpinnerLog, { message: "preparing local preview..." }));
const { needsUpdate, error } = await timeDev('update local client', () => silentUpdateClient({
versionString,
clientVersion,
localClientVersion,
cliVersion,
}));
if (error) {
clearLogs();
addLog(_jsx(ErrorLog, { message: error }));
await new Promise((resolve) => setTimeout(resolve, 50));
process.exit(1);
}
// clear preexisting prebuild files
timeDevSync('clear prebuild output', () => {
fse.emptyDirSync(NEXT_PROPS_PATH);
// only clear public/ when previewing a different docs repo, so unchanged
// static files can be skipped on warm starts; on warm starts, prune files
// whose source no longer exists so deleted assets stop being served
const markerPath = pathUtil.join(NEXT_PUBLIC_PATH, '.mint-content-source');
let previousSource;
try {
previousSource = fse.readFileSync(markerPath, 'utf8');
}
catch { }
if (previousSource !== CMD_EXEC_PATH) {
fse.emptyDirSync(NEXT_PUBLIC_PATH);
fse.outputFileSync(markerPath, CMD_EXEC_PATH);
}
else {
prunePublicOrphans();
}
});
timeDevSync('switch to local client directory', () => {
process.chdir(CLIENT_PATH);
});
let fileImportsMap;
try {
const result = await timeDev('prebuild content', () => prebuild(CMD_EXEC_PATH, {
localSchema,
groups,
disableOpenApi,
allowSourceRefs: true,
lazyPages: true,
}));
fileImportsMap = result?.fileImportsMap;
}
catch (err) {
clearLogs();
const errorText = err instanceof Error && err.message ? err.message : 'prebuild step failed';
addLog(_jsx(ErrorLog, { message: errorText }));
await new Promise((resolve) => setTimeout(resolve, 50));
process.exit(1);
}
await timeDev('start preview runtime', () => run({ ...argv, needsUpdate, fileImportsMap }));
};
export default dev;