prisma-erd-generator
Version:
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section --> [](#contributors-) <!-- ALL-CONTRIBUTORS-BADGE:END -->
726 lines (721 loc) • 28.3 kB
JavaScript
;
(() => {
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
}) : x)(function(x) {
if (typeof require !== "undefined") return require.apply(this, arguments);
throw Error('Dynamic require of "' + x + '" is not supported');
});
var __commonJS = (cb, mod) => function __require2() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
// node_modules/.pnpm/dotenv@16.4.7/node_modules/dotenv/package.json
var require_package = __commonJS({
"node_modules/.pnpm/dotenv@16.4.7/node_modules/dotenv/package.json"(exports, module) {
module.exports = {
name: "dotenv",
version: "16.4.7",
description: "Loads environment variables from .env file",
main: "lib/main.js",
types: "lib/main.d.ts",
exports: {
".": {
types: "./lib/main.d.ts",
require: "./lib/main.js",
default: "./lib/main.js"
},
"./config": "./config.js",
"./config.js": "./config.js",
"./lib/env-options": "./lib/env-options.js",
"./lib/env-options.js": "./lib/env-options.js",
"./lib/cli-options": "./lib/cli-options.js",
"./lib/cli-options.js": "./lib/cli-options.js",
"./package.json": "./package.json"
},
scripts: {
"dts-check": "tsc --project tests/types/tsconfig.json",
lint: "standard",
pretest: "npm run lint && npm run dts-check",
test: "tap run --allow-empty-coverage --disable-coverage --timeout=60000",
"test:coverage": "tap run --show-full-coverage --timeout=60000 --coverage-report=lcov",
prerelease: "npm test",
release: "standard-version"
},
repository: {
type: "git",
url: "git://github.com/motdotla/dotenv.git"
},
funding: "https://dotenvx.com",
keywords: [
"dotenv",
"env",
".env",
"environment",
"variables",
"config",
"settings"
],
readmeFilename: "README.md",
license: "BSD-2-Clause",
devDependencies: {
"@types/node": "^18.11.3",
decache: "^4.6.2",
sinon: "^14.0.1",
standard: "^17.0.0",
"standard-version": "^9.5.0",
tap: "^19.2.0",
typescript: "^4.8.4"
},
engines: {
node: ">=12"
},
browser: {
fs: false
}
};
}
});
// node_modules/.pnpm/dotenv@16.4.7/node_modules/dotenv/lib/main.js
var require_main = __commonJS({
"node_modules/.pnpm/dotenv@16.4.7/node_modules/dotenv/lib/main.js"(exports, module) {
"use strict";
var fs2 = __require("fs");
var path2 = __require("path");
var os2 = __require("os");
var crypto = __require("crypto");
var packageJson = require_package();
var version = packageJson.version;
var LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg;
function parse(src) {
const obj = {};
let lines = src.toString();
lines = lines.replace(/\r\n?/mg, "\n");
let match;
while ((match = LINE.exec(lines)) != null) {
const key = match[1];
let value = match[2] || "";
value = value.trim();
const maybeQuote = value[0];
value = value.replace(/^(['"`])([\s\S]*)\1$/mg, "$2");
if (maybeQuote === '"') {
value = value.replace(/\\n/g, "\n");
value = value.replace(/\\r/g, "\r");
}
obj[key] = value;
}
return obj;
}
function _parseVault(options) {
const vaultPath = _vaultPath(options);
const result = DotenvModule.configDotenv({ path: vaultPath });
if (!result.parsed) {
const err = new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`);
err.code = "MISSING_DATA";
throw err;
}
const keys = _dotenvKey(options).split(",");
const length = keys.length;
let decrypted;
for (let i = 0; i < length; i++) {
try {
const key = keys[i].trim();
const attrs = _instructions(result, key);
decrypted = DotenvModule.decrypt(attrs.ciphertext, attrs.key);
break;
} catch (error) {
if (i + 1 >= length) {
throw error;
}
}
}
return DotenvModule.parse(decrypted);
}
function _log(message) {
console.log(`[dotenv@${version}][INFO] ${message}`);
}
function _warn(message) {
console.log(`[dotenv@${version}][WARN] ${message}`);
}
function _debug(message) {
console.log(`[dotenv@${version}][DEBUG] ${message}`);
}
function _dotenvKey(options) {
if (options && options.DOTENV_KEY && options.DOTENV_KEY.length > 0) {
return options.DOTENV_KEY;
}
if (process.env.DOTENV_KEY && process.env.DOTENV_KEY.length > 0) {
return process.env.DOTENV_KEY;
}
return "";
}
function _instructions(result, dotenvKey) {
let uri;
try {
uri = new URL(dotenvKey);
} catch (error) {
if (error.code === "ERR_INVALID_URL") {
const err = new Error("INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=development");
err.code = "INVALID_DOTENV_KEY";
throw err;
}
throw error;
}
const key = uri.password;
if (!key) {
const err = new Error("INVALID_DOTENV_KEY: Missing key part");
err.code = "INVALID_DOTENV_KEY";
throw err;
}
const environment = uri.searchParams.get("environment");
if (!environment) {
const err = new Error("INVALID_DOTENV_KEY: Missing environment part");
err.code = "INVALID_DOTENV_KEY";
throw err;
}
const environmentKey = `DOTENV_VAULT_${environment.toUpperCase()}`;
const ciphertext = result.parsed[environmentKey];
if (!ciphertext) {
const err = new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file.`);
err.code = "NOT_FOUND_DOTENV_ENVIRONMENT";
throw err;
}
return { ciphertext, key };
}
function _vaultPath(options) {
let possibleVaultPath = null;
if (options && options.path && options.path.length > 0) {
if (Array.isArray(options.path)) {
for (const filepath of options.path) {
if (fs2.existsSync(filepath)) {
possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
}
}
} else {
possibleVaultPath = options.path.endsWith(".vault") ? options.path : `${options.path}.vault`;
}
} else {
possibleVaultPath = path2.resolve(process.cwd(), ".env.vault");
}
if (fs2.existsSync(possibleVaultPath)) {
return possibleVaultPath;
}
return null;
}
function _resolveHome(envPath) {
return envPath[0] === "~" ? path2.join(os2.homedir(), envPath.slice(1)) : envPath;
}
function _configVault(options) {
_log("Loading env from encrypted .env.vault");
const parsed = DotenvModule._parseVault(options);
let processEnv = process.env;
if (options && options.processEnv != null) {
processEnv = options.processEnv;
}
DotenvModule.populate(processEnv, parsed, options);
return { parsed };
}
function configDotenv(options) {
const dotenvPath = path2.resolve(process.cwd(), ".env");
let encoding = "utf8";
const debug = Boolean(options && options.debug);
if (options && options.encoding) {
encoding = options.encoding;
} else {
if (debug) {
_debug("No encoding is specified. UTF-8 is used by default");
}
}
let optionPaths = [dotenvPath];
if (options && options.path) {
if (!Array.isArray(options.path)) {
optionPaths = [_resolveHome(options.path)];
} else {
optionPaths = [];
for (const filepath of options.path) {
optionPaths.push(_resolveHome(filepath));
}
}
}
let lastError;
const parsedAll = {};
for (const path3 of optionPaths) {
try {
const parsed = DotenvModule.parse(fs2.readFileSync(path3, { encoding }));
DotenvModule.populate(parsedAll, parsed, options);
} catch (e) {
if (debug) {
_debug(`Failed to load ${path3} ${e.message}`);
}
lastError = e;
}
}
let processEnv = process.env;
if (options && options.processEnv != null) {
processEnv = options.processEnv;
}
DotenvModule.populate(processEnv, parsedAll, options);
if (lastError) {
return { parsed: parsedAll, error: lastError };
} else {
return { parsed: parsedAll };
}
}
function config2(options) {
if (_dotenvKey(options).length === 0) {
return DotenvModule.configDotenv(options);
}
const vaultPath = _vaultPath(options);
if (!vaultPath) {
_warn(`You set DOTENV_KEY but you are missing a .env.vault file at ${vaultPath}. Did you forget to build it?`);
return DotenvModule.configDotenv(options);
}
return DotenvModule._configVault(options);
}
function decrypt(encrypted, keyStr) {
const key = Buffer.from(keyStr.slice(-64), "hex");
let ciphertext = Buffer.from(encrypted, "base64");
const nonce = ciphertext.subarray(0, 12);
const authTag = ciphertext.subarray(-16);
ciphertext = ciphertext.subarray(12, -16);
try {
const aesgcm = crypto.createDecipheriv("aes-256-gcm", key, nonce);
aesgcm.setAuthTag(authTag);
return `${aesgcm.update(ciphertext)}${aesgcm.final()}`;
} catch (error) {
const isRange = error instanceof RangeError;
const invalidKeyLength = error.message === "Invalid key length";
const decryptionFailed = error.message === "Unsupported state or unable to authenticate data";
if (isRange || invalidKeyLength) {
const err = new Error("INVALID_DOTENV_KEY: It must be 64 characters long (or more)");
err.code = "INVALID_DOTENV_KEY";
throw err;
} else if (decryptionFailed) {
const err = new Error("DECRYPTION_FAILED: Please check your DOTENV_KEY");
err.code = "DECRYPTION_FAILED";
throw err;
} else {
throw error;
}
}
}
function populate(processEnv, parsed, options = {}) {
const debug = Boolean(options && options.debug);
const override = Boolean(options && options.override);
if (typeof parsed !== "object") {
const err = new Error("OBJECT_REQUIRED: Please check the processEnv argument being passed to populate");
err.code = "OBJECT_REQUIRED";
throw err;
}
for (const key of Object.keys(parsed)) {
if (Object.prototype.hasOwnProperty.call(processEnv, key)) {
if (override === true) {
processEnv[key] = parsed[key];
}
if (debug) {
if (override === true) {
_debug(`"${key}" is already defined and WAS overwritten`);
} else {
_debug(`"${key}" is already defined and was NOT overwritten`);
}
}
} else {
processEnv[key] = parsed[key];
}
}
}
var DotenvModule = {
configDotenv,
_configVault,
_parseVault,
config: config2,
decrypt,
parse,
populate
};
module.exports.configDotenv = DotenvModule.configDotenv;
module.exports._configVault = DotenvModule._configVault;
module.exports._parseVault = DotenvModule._parseVault;
module.exports.config = DotenvModule.config;
module.exports.decrypt = DotenvModule.decrypt;
module.exports.parse = DotenvModule.parse;
module.exports.populate = DotenvModule.populate;
module.exports = DotenvModule;
}
});
// src/generate.ts
var path = __toESM(__require("node:path"));
var child_process = __toESM(__require("node:child_process"));
var import_node_fs = __toESM(__require("node:fs"));
var import_node_os = __toESM(__require("node:os"));
var dotenv = __toESM(require_main());
dotenv.config();
function getDataModelFieldWithoutParsing(parsed) {
const startOfField = parsed.indexOf('"datamodel"');
const openingBracket = parsed.indexOf("{", startOfField);
let numberOfOpeningBrackets = 0;
let closingBracket = openingBracket;
while (closingBracket < parsed.length) {
const char = parsed[closingBracket++];
if (char === "{") {
numberOfOpeningBrackets++;
} else if (char === "}") {
numberOfOpeningBrackets--;
if (numberOfOpeningBrackets === 0) {
break;
}
}
}
return parsed.slice(openingBracket, closingBracket);
}
async function parseDatamodel(engine, model, tmpDir) {
const tmpSchema = path.resolve(path.join(tmpDir, "schema.prisma"));
import_node_fs.default.writeFileSync(tmpSchema, model);
const parsed = await new Promise((resolve2, reject) => {
const process2 = child_process.exec(
`"${engine}" --datamodel-path="${tmpSchema}" cli dmmf`
);
let output = "";
process2.stderr?.on("data", (l) => {
if (l.includes("error:")) {
reject(l.slice(l.indexOf("error:"), l.indexOf("\\n")));
}
});
process2.stdout?.on("data", (d) => {
output += d;
});
process2.on("exit", () => {
resolve2(output);
});
});
return getDataModelFieldWithoutParsing(parsed);
}
function renderDml(dml, options) {
const {
tableOnly = false,
ignoreEnums = false,
includeRelationFromFields = false,
disableEmoji = false
} = options ?? {};
const diagram = "erDiagram";
const modellikes = dml.models.concat(dml.types);
const enums = tableOnly || ignoreEnums ? "" : dml.enums.map(
(model) => `
${model.dbName || model.name} {
${model.values.map(
(value) => `${value.name || value.dbName} ${value.dbName || value.name}`
).join("\n")}
}
`
).join("\n\n");
const pkSigil = disableEmoji ? '"PK"' : '"\u{1F5DD}\uFE0F"';
const nullableSigil = disableEmoji ? '"nullable"' : '"\u2753"';
const classes = modellikes.map(
(model) => ` "${model.dbName || model.name}" {
${tableOnly ? "" : model.fields.filter(isFieldShownInSchema(model, includeRelationFromFields)).map((field) => {
return ` ${field.type.trimStart()} ${field.name.replace(
/^_/,
"z_"
)} ${field.isId || model.primaryKey?.fields?.includes(field.name) ? pkSigil : ""}${field.isRequired ? "" : nullableSigil}`;
}).join("\n")}
}
`
).join("\n\n");
let relationships = "";
for (const model of modellikes) {
for (const field of model.fields) {
const isEnum = field.kind === "enum";
if (isEnum && (tableOnly || ignoreEnums)) {
continue;
}
const relationshipName = `${isEnum ? "enum:" : ""}${field.name}`;
const thisSide = `"${model.dbName || model.name}"`;
const otherSide = `"${modellikes.find((ml) => ml.name === field.type)?.dbName || field.type}"`;
if (field.relationFromFields && field.relationFromFields.length > 0 || isEnum) {
let thisSideMultiplicity = "||";
if (field.isList) {
thisSideMultiplicity = "}o";
} else if (!field.isRequired) {
thisSideMultiplicity = "|o";
}
const otherModel = modellikes.find(
(model2) => model2.name === otherSide
);
const otherField = otherModel?.fields.find(
({ relationName }) => relationName === field.relationName
);
const otherSideMultiplicity = thisSideMultiplicity;
if (otherField?.isList) {
thisSideMultiplicity = "o{";
} else if (!otherField?.isRequired) {
thisSideMultiplicity = "o|";
}
relationships += ` ${thisSide} ${thisSideMultiplicity}--${otherSideMultiplicity} ${otherModel?.dbName || otherSide} : "${relationshipName}"
`;
} else if (modellikes.find(
(m) => m.name === field.type || m.dbName === field.type
) && field.relationFromFields?.length === 0) {
relationships += ` ${thisSide} o{--}o ${otherSide} : "${field.name}"
`;
} else if (field.kind === "object") {
const otherSideCompositeType = dml.types.find(
(model2) => model2.name.replace(/^_/, "z_").replace(/\s/g, "")
// remove spaces === otherSide
);
console.log(otherSide, otherSideCompositeType);
if (otherSideCompositeType) {
let thisSideMultiplicity = "||";
if (field.isList) {
thisSideMultiplicity = "}o";
} else if (!field.isRequired) {
thisSideMultiplicity = "|o";
}
const otherField = otherSideCompositeType?.fields.find(
({ relationName }) => relationName === field.relationName
);
const otherSideMultiplicity = thisSideMultiplicity;
if (otherField?.isList) {
thisSideMultiplicity = "o{";
} else if (!otherField?.isRequired) {
thisSideMultiplicity = "o|";
}
relationships += ` ${thisSide} ${thisSideMultiplicity}--${otherSideMultiplicity} ${otherSideCompositeType.dbName || otherSide} : "${relationshipName}"
`;
}
}
}
}
return `${diagram}
${enums}
${classes}
${relationships}`;
}
var isFieldShownInSchema = (model, includeRelationFromFields) => (field) => {
if (includeRelationFromFields) {
return field.kind !== "object";
}
return field.kind !== "object" && !model.fields.find(
({ relationFromFields }) => relationFromFields?.includes(field.name)
);
};
var mapPrismaToDb = (dmlModels, dataModel) => {
const splitDataModel = dataModel?.split("\n").filter((line) => line.includes("@map") || line.includes("model ")).map((line) => line.trim());
return dmlModels.map((model) => {
return {
...model,
fields: model.fields.map((field) => {
let filterStatus = "None";
const lineInDataModel = splitDataModel.filter((line) => {
if (filterStatus === "Match" && line.includes("model ")) {
filterStatus = "End";
}
if (filterStatus === "None" && line.includes(`model ${model.name} `)) {
filterStatus = "Match";
}
return filterStatus === "Match";
}).find(
(line) => line.includes(`${field.name} `) && line.includes("@map")
);
if (lineInDataModel) {
const regex = new RegExp(/@map\(\"(.*?)\"\)/, "g");
const match = regex.exec(lineInDataModel);
if (match?.[1]) {
const name = match[1].replace(/^_/, "z_").replace(/\s/g, "");
field.name = name;
}
}
return field;
})
};
});
};
var generate_default = async (options) => {
try {
const output = options.generator.output?.value || "./prisma/ERD.svg";
const config2 = options.generator.config;
const theme = config2.theme ?? "forest";
let mermaidCliNodePath = path.resolve(
path.join(config2.mmdcPath || "node_modules/.bin", "mmdc")
);
const tableOnly = config2.tableOnly === "true";
const disableEmoji = config2.disableEmoji === "true";
const ignoreEnums = config2.ignoreEnums === "true";
const includeRelationFromFields = config2.includeRelationFromFields === "true";
const disabled = process.env.DISABLE_ERD === "true" || config2.disabled === "true";
const debug = config2.erdDebug === "true" || Boolean(process.env.ERD_DEBUG);
if (debug) {
console.log("debug mode enabled");
console.log("config", config2);
}
if (disabled) {
return console.log("ERD generator is disabled");
}
const queryEngines = Object.values(options.binaryPaths?.queryEngine || {});
if (!queryEngines[0])
throw new Error("no query engine found");
const queryEngine = queryEngines[0];
const tmpDir = import_node_fs.default.mkdtempSync(`${import_node_os.default.tmpdir() + path.sep}prisma-erd-`);
const datamodelString = await parseDatamodel(
queryEngine,
options.datamodel,
tmpDir
);
if (!datamodelString) {
throw new Error("could not parse datamodel");
}
if (debug && datamodelString) {
import_node_fs.default.mkdirSync(path.resolve("prisma/debug"), { recursive: true });
const dataModelFile = path.resolve("prisma/debug/1-datamodel.json");
import_node_fs.default.writeFileSync(dataModelFile, datamodelString);
console.log(`data model written to ${dataModelFile}`);
}
const dml = JSON.parse(datamodelString);
dml.models = mapPrismaToDb(dml.models, options.datamodel);
if (!dml.types) {
dml.types = [];
}
if (debug && dml.models) {
const mapAppliedFile = path.resolve(
"prisma/debug/2-datamodel-map-applied.json"
);
import_node_fs.default.writeFileSync(mapAppliedFile, JSON.stringify(dml, null, 2));
console.log(`applied @map to fields written to ${mapAppliedFile}`);
}
const mermaid = renderDml(dml, {
tableOnly,
ignoreEnums,
includeRelationFromFields,
disableEmoji
});
if (debug && mermaid) {
const mermaidFile = path.resolve("prisma/debug/3-mermaid.mmd");
import_node_fs.default.writeFileSync(mermaidFile, mermaid);
console.log(`mermaid written to ${mermaidFile}`);
}
if (!mermaid)
throw new Error("failed to construct mermaid instance from dml");
if (output.endsWith(".md"))
return import_node_fs.default.writeFileSync(output, `\`\`\`mermaid
${mermaid}\`\`\`
`);
const tempMermaidFile = path.resolve(path.join(tmpDir, "prisma.mmd"));
import_node_fs.default.writeFileSync(tempMermaidFile, mermaid);
const defaultMermaidConfig = {
deterministicIds: true,
maxTextSize: 9e4,
er: {
useMaxWidth: true
},
theme
};
let mermaidConfig = defaultMermaidConfig;
if (config2?.mermaidConfig) {
const importedMermaidConfig = await import(path.resolve(config2.mermaidConfig));
if (debug) {
console.log("imported mermaid config: ", importedMermaidConfig);
}
mermaidConfig = {
...defaultMermaidConfig,
...importedMermaidConfig
};
}
const tempConfigFile = path.resolve(path.join(tmpDir, "config.json"));
import_node_fs.default.writeFileSync(tempConfigFile, JSON.stringify(mermaidConfig));
let puppeteerConfig = config2.puppeteerConfig;
if (puppeteerConfig && !import_node_fs.default.existsSync(puppeteerConfig)) {
throw new Error(
`Puppeteer config file "${puppeteerConfig}" does not exist`
);
}
if (!puppeteerConfig) {
const tempPuppeteerConfigFile = path.resolve(
path.join(tmpDir, "puppeteerConfig.json")
);
let executablePath;
const puppeteerConfigJson = {
logLevel: debug ? "warn" : "error",
executablePath
};
if (import_node_os.default.platform() === "darwin" && import_node_os.default.arch() === "arm64") {
try {
const executablePath2 = child_process.execSync("which chromium").toString().replace("\n", "");
if (!executablePath2) {
throw new Error(
"Could not find chromium executable. Refer to https://github.com/keonik/prisma-erd-generator#issues for next steps."
);
}
puppeteerConfigJson.executablePath = executablePath2;
puppeteerConfigJson.args = ["--no-sandbox"];
} catch (error) {
console.error(error);
console.log(
`
Prisma ERD Generator: Unable to find chromium path for you MacOS arm64 machine. Attempting to use the default at ${executablePath}. To learn more visit https://github.com/keonik/prisma-erd-generator#-arm64-users-
`
);
executablePath = "/usr/bin/chromium-browser";
}
}
import_node_fs.default.writeFileSync(
tempPuppeteerConfigFile,
JSON.stringify(puppeteerConfigJson)
);
puppeteerConfig = tempPuppeteerConfigFile;
}
if (config2.mmdcPath) {
if (!import_node_fs.default.existsSync(mermaidCliNodePath)) {
throw new Error(
`
Mermaid CLI provided path does not exist.
${mermaidCliNodePath}`
);
}
} else if (!import_node_fs.default.existsSync(mermaidCliNodePath)) {
const findMermaidCli = child_process.execSync("find ../.. -name mmdc").toString().split("\n").filter((path2) => path2).pop();
if (!findMermaidCli || !import_node_fs.default.existsSync(findMermaidCli)) {
throw new Error(
`Expected mermaid CLI at
${mermaidCliNodePath}
or
${findMermaidCli}
but this package was not found.`
);
}
mermaidCliNodePath = path.resolve(findMermaidCli);
}
const mermaidCommand = `"${mermaidCliNodePath}" -i "${tempMermaidFile}" -o "${output}" -c "${tempConfigFile}" -p "${puppeteerConfig}"`;
if (debug && mermaidCommand)
console.log("mermaid command: ", mermaidCommand);
child_process.execSync(mermaidCommand);
if (!import_node_fs.default.existsSync(output)) {
throw new Error(
`Issue generating ER Diagram. Expected ${output} to be created`
);
}
} catch (error) {
console.error(error);
throw error;
}
};
})();