@mintlify/prebuild
Version:
Helpful functions for Mintlify's prebuild step
124 lines (123 loc) • 5.32 kB
JavaScript
import { validateMintConfig, validateDocsConfig, formatIssue, } from '@mintlify/validation';
import Chalk from 'chalk';
import { promises as _promises } from 'fs';
import { outputFile } from 'fs-extra';
import { join } from 'path';
import { resolveFileRefs } from '../resolveRefs.js';
const { readFile } = _promises;
export class ConfigUpdater {
constructor(type) {
this.validateConfigJsonString = async (configContents, strict, onError) => {
const configObj = this.parseConfigJson(configContents, onError);
return this.validateConfigObj(configObj, strict, onError);
};
this.validateConfigObj = async (configObj, strict, onError) => {
const validationResults = this.type === 'mint' ? validateMintConfig(configObj) : validateDocsConfig(configObj);
if (!validationResults.success) {
const errorMsg = `🚨 Invalid ${this.type}.json:`;
const issues = validationResults.error.issues.map((issue) => formatIssue(issue));
if (onError) {
onError(errorMsg);
issues.forEach((issue) => onError(issue));
}
else {
console.error(Chalk.red(errorMsg));
issues.forEach((issue) => console.error(Chalk.red(issue)));
}
throw Error();
}
if ('warnings' in validationResults && validationResults.warnings.length > 0) {
const warnMsg = `⚠️ Warnings found in ${this.type}.json:`;
const warnings = validationResults.warnings.map((issue) => formatIssue(issue));
if (onError) {
onError(warnMsg);
warnings.forEach((warning) => onError(warning));
}
else {
console.warn(Chalk.yellow(warnMsg));
warnings.forEach((warning) => console.warn(Chalk.yellow(warning)));
if (strict) {
throw Error('Validation warnings treated as errors in strict mode');
}
}
}
return { ...validationResults, data: validationResults.data };
};
this.readConfigFile = async (configPath) => {
let configContents;
try {
configContents = await readFile(configPath, 'utf-8');
}
catch (err) {
throw Error(`Unable to read ${this.type}.json: ${err}`);
}
return configContents;
};
this.writeConfigFile = async (config, targetDir) => {
try {
await outputFile(join(targetDir ?? '', `src/_props/${this.type}.json`), JSON.stringify(config, null, 2), {
flag: 'w',
});
}
catch (err) {
throw Error(`Unable to write ${this.type}.json: ${err}`);
}
};
this.parseConfigJson = (configContents, onError) => {
let configObj;
try {
configObj = JSON.parse(configContents);
}
catch (e) {
if (typeof e === 'object' && e != null) {
if ('name' in e && e.name === 'SyntaxError') {
const msg = `🚨 ${this.type}.json has invalid JSON. You are likely missing a comma or a bracket. You can paste your ${this.type}.json file into https://jsonlint.com/ to get a more specific error message.`;
if (onError) {
onError(msg);
}
else {
console.error(Chalk.red(msg));
}
}
else if ('message' in e) {
const msg = `🚨 ${e.message}`;
if (onError) {
onError(msg);
}
else {
console.error(Chalk.red(msg));
}
}
}
throw Error();
}
return configObj;
};
this.type = type;
}
getConfigType() {
return this.type;
}
async getConfig(configPath, strict, contentDirectoryPath, onError) {
const configContents = await this.readConfigFile(configPath);
const configObj = this.parseConfigJson(configContents, onError);
let resolvedObj = configObj;
if (contentDirectoryPath) {
try {
const { resolved } = await resolveFileRefs(configObj, contentDirectoryPath);
resolvedObj = resolved;
}
catch (e) {
const msg = `Error resolving $ref in ${this.type}.json: ${e instanceof Error ? e.message : String(e)}`;
if (onError) {
onError(msg);
}
throw Error(msg);
}
}
const { data: config } = await this.validateConfigObj(resolvedObj, strict, onError);
return config;
}
}
export const MintConfigUpdater = new ConfigUpdater('mint');
export const DocsConfigUpdater = new ConfigUpdater('docs');