@prisma/sdk
Version:
293 lines (290 loc) • 11.1 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 __name = (target, value) => __defProp(target, "name", { value, configurable: true });
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
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(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var IntrospectionEngine_exports = {};
__export(IntrospectionEngine_exports, {
IntrospectionEngine: () => IntrospectionEngine,
IntrospectionError: () => IntrospectionError,
IntrospectionPanic: () => IntrospectionPanic
});
module.exports = __toCommonJS(IntrospectionEngine_exports);
var import_debug = __toESM(require("@prisma/debug"));
var import_fetch_engine = require("@prisma/fetch-engine");
var import_chalk = __toESM(require("chalk"));
var import_child_process = require("child_process");
var import_panic = require("./panic");
var import_resolveBinary = require("./resolveBinary");
var import_byline = __toESM(require("./utils/byline"));
const debugCli = (0, import_debug.default)("prisma:introspectionEngine:cli");
const debugRpc = (0, import_debug.default)("prisma:introspectionEngine:rpc");
const debugStderr = (0, import_debug.default)("prisma:introspectionEngine:stderr");
const debugStdin = (0, import_debug.default)("prisma:introspectionEngine:stdin");
class IntrospectionPanic extends Error {
constructor(message, rustStack, request) {
super(message);
this.rustStack = rustStack;
this.request = request;
}
}
__name(IntrospectionPanic, "IntrospectionPanic");
class IntrospectionError extends Error {
constructor(message, code) {
super(message);
this.code = code;
}
}
__name(IntrospectionError, "IntrospectionError");
let messageId = 1;
class IntrospectionEngine {
constructor({ debug, cwd } = {
debug: false,
cwd: process.cwd()
}) {
this.listeners = {};
this.messages = [];
this.isRunning = false;
if (debug) {
import_debug.default.enable("IntrospectionEngine*");
}
this.debug = Boolean(debug);
this.cwd = cwd || process.cwd();
}
stop() {
if (this.child) {
this.child.kill();
this.isRunning = false;
}
}
rejectAll(err) {
Object.entries(this.listeners).map(([id, listener]) => {
listener(null, err);
delete this.listeners[id];
});
}
registerCallback(id, callback) {
this.listeners[id] = callback;
}
getDatabaseDescription(schema) {
return this.runCommand(this.getRPCPayload("getDatabaseDescription", { schema }));
}
getDatabaseVersion(schema) {
return this.runCommand(this.getRPCPayload("getDatabaseVersion", { schema }));
}
introspect(schema, force, compositeTypeDepth = -1) {
this.lastUrl = schema;
return this.runCommand(this.getRPCPayload("introspect", { schema, force, compositeTypeDepth }));
}
debugPanic() {
return this.runCommand(this.getRPCPayload("debugPanic", void 0));
}
listDatabases(schema) {
this.lastUrl = schema;
return this.runCommand(this.getRPCPayload("listDatabases", { schema }));
}
getDatabaseMetadata(schema) {
this.lastUrl = schema;
return this.runCommand(this.getRPCPayload("getDatabaseMetadata", { schema }));
}
handleResponse(response) {
let result;
try {
result = JSON.parse(response);
} catch (e) {
console.error(`Could not parse introspection engine response: ${response.slice(0, 200)}`);
}
if (result) {
if (result.backtrace) {
console.log(result);
}
if (!result.id) {
console.error(`Response ${JSON.stringify(result)} doesn't have an id and I can't handle that (yet)`);
}
if (!this.listeners[result.id]) {
console.error(`Got result for unknown id ${result.id}`);
}
if (this.listeners[result.id]) {
this.listeners[result.id](result);
delete this.listeners[result.id];
}
}
}
init() {
if (!this.initPromise) {
this.initPromise = this.internalInit();
}
return this.initPromise;
}
internalInit() {
return new Promise(async (resolve, reject) => {
var _a, _b;
try {
const binaryPath = await (0, import_resolveBinary.resolveBinary)(import_fetch_engine.BinaryType.introspectionEngine);
debugRpc("starting introspection engine with binary: " + binaryPath);
this.child = (0, import_child_process.spawn)(binaryPath, {
env: process.env,
cwd: this.cwd,
stdio: ["pipe", "pipe", "pipe"]
});
this.isRunning = true;
this.child.on("error", (err) => {
var _a2;
console.error("[introspection-engine] error: %s", err);
(_a2 = this.child) == null ? void 0 : _a2.kill();
this.rejectAll(err);
reject(err);
});
(_a = this.child.stdin) == null ? void 0 : _a.on("error", (err) => {
var _a2;
console.error(err);
(_a2 = this.child) == null ? void 0 : _a2.kill();
});
this.child.on("exit", (code) => {
this.isRunning = false;
if (code === 255 && this.lastError && this.lastError.is_panic) {
const err2 = new import_panic.RustPanic(this.lastError.message, this.lastError.backtrace, this.lastRequest, import_panic.ErrorArea.INTROSPECTION_CLI, void 0, this.lastUrl);
this.rejectAll(err2);
reject(err2);
return;
}
const messages = this.messages.join("\n");
let err;
if (code !== 0 || messages.includes("panicked at")) {
let errorMessage = import_chalk.default.red.bold("Error in introspection engine: ") + messages;
if (this.lastError && this.lastError.msg === "PANIC") {
errorMessage = serializePanic(this.lastError);
err = new IntrospectionPanic(errorMessage, messages, this.lastRequest);
} else if (messages.includes("panicked at")) {
err = new IntrospectionPanic(errorMessage, messages, this.lastRequest);
}
err = err || new Error(errorMessage);
this.rejectAll(err);
reject(err);
}
});
this.child.stdin.on("error", (err) => {
debugStdin(err);
});
(0, import_byline.default)(this.child.stderr).on("data", (data) => {
const msg = String(data);
this.messages.push(msg);
debugStderr(msg);
try {
const json = JSON.parse(msg);
if (json.backtrace) {
this.lastError = json;
}
if (json.level === "ERRO") {
this.lastError = json;
}
} catch (e) {
debugCli(e);
}
});
(0, import_byline.default)(this.child.stdout).on("data", (line) => {
this.handleResponse(String(line));
});
setImmediate(() => {
resolve();
});
} catch (e) {
(_b = this.child) == null ? void 0 : _b.kill();
reject(e);
}
});
}
async runCommand(request) {
var _a;
await this.init();
if (process.env.FORCE_PANIC_INTROSPECTION_ENGINE) {
request = this.getRPCPayload("debugPanic", void 0);
}
if ((_a = this.child) == null ? void 0 : _a.killed) {
throw new Error(`Can't execute ${JSON.stringify(request)} because introspection engine already exited.`);
}
return new Promise((resolve, reject) => {
this.registerCallback(request.id, (response, err) => {
var _a2, _b, _c, _d, _e, _f, _g;
if (err) {
return reject(err);
}
if (typeof response.result !== "undefined") {
resolve(response.result);
} else {
if (response.error) {
(_a2 = this.child) == null ? void 0 : _a2.kill();
debugRpc(response);
if ((_b = response.error.data) == null ? void 0 : _b.is_panic) {
const message = (_e = (_d = (_c = response.error.data) == null ? void 0 : _c.error) == null ? void 0 : _d.message) != null ? _e : response.error.message;
reject(new import_panic.RustPanic(message, message, request, import_panic.ErrorArea.INTROSPECTION_CLI, void 0, this.lastUrl));
} else if ((_f = response.error.data) == null ? void 0 : _f.message) {
let message = `${response.error.data.message}
`;
if ((_g = response.error.data) == null ? void 0 : _g.error_code) {
message = import_chalk.default.redBright(`${response.error.data.error_code}
`) + message;
reject(new IntrospectionError(message, response.error.data.error_code));
} else {
reject(new Error(message));
}
} else {
reject(new Error(`${import_chalk.default.redBright("Error in RPC")}
Request: ${JSON.stringify(request, null, 2)}
Response: ${JSON.stringify(response, null, 2)}
${response.error.message}
`));
}
} else {
reject(new Error(`Got invalid RPC response without .result property: ${JSON.stringify(response)}`));
}
}
});
if (this.child.stdin.destroyed) {
throw new Error(`Can't execute ${JSON.stringify(request)} because introspection engine is destroyed.`);
}
debugRpc("SENDING RPC CALL", JSON.stringify(request));
this.child.stdin.write(JSON.stringify(request) + "\n");
this.lastRequest = request;
});
}
getRPCPayload(method, params) {
return {
id: messageId++,
jsonrpc: "2.0",
method,
params: params ? [{ ...params }] : void 0
};
}
}
__name(IntrospectionEngine, "IntrospectionEngine");
function serializePanic(log) {
return `${import_chalk.default.red.bold("Error in introspection engine.\nReason: ")}
${log.reason} in ${import_chalk.default.underline(`${log.file}:${log.line}:${log.column}`)}
Please create an issue in the ${import_chalk.default.bold("prisma")} repo with the error \u{1F64F}:
${import_chalk.default.underline("https://github.com/prisma/prisma/issues/new")}
`;
}
__name(serializePanic, "serializePanic");
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
IntrospectionEngine,
IntrospectionError,
IntrospectionPanic
});