text: "use strict";
  var __importDefault = (this && this.__importDefault) || function (mod) {
      return (mod && mod.__esModule) ? mod : { "default": mod };
  };
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.NodeEngine = void 0;
  const Engine_1 = require("./Engine");
  const debug_1 = __importDefault(require("debug"));
  const get_platform_1 = require("@prisma/get-platform");
  const path_1 = __importDefault(require("path"));
  const net_1 = __importDefault(require("net"));
  const fs_1 = __importDefault(require("fs"));
  const chalk_1 = __importDefault(require("chalk"));
  const printGeneratorConfig_1 = require("./printGeneratorConfig");
  const util_1 = require("./util");
  const util_2 = require("util");
  const events_1 = __importDefault(require("events"));
  const log_1 = require("./log");
  const child_process_1 = require("child_process");
  const byline_1 = __importDefault(require("./byline"));
  const h1client_1 = require("./h1client");
  const p_retry_1 = __importDefault(require("p-retry"));
  const debug = debug_1.default('engine');
  const exists = util_2.promisify(fs_1.default.exists);
  const readdir = util_2.promisify(fs_1.default.readdir);
  /**
   * Node.js based wrapper to run the Prisma binary
   */
  const knownPlatforms = [
      'native',
      'darwin',
      'debian-openssl-1.0.x',
      'debian-openssl-1.1.x',
      'rhel-openssl-1.0.x',
      'rhel-openssl-1.1.x',
      'linux-musl',
      'linux-nixos',
      'windows',
      'freebsd',
      'openbsd',
      'netbsd',
      'arm',
  ];
  const engines = [];
  class NodeEngine {
      constructor({ cwd, datamodelPath, prismaPath, generator, datasources, showColors, logLevel, logQueries, env, flags, clientVersion, ...args }) {
          this.restartCount = 0;
          this.queryEngineStarted = false;
          /**
           * exiting is used to tell the .on('exit') hook, if the exit came from our script.
           * As soon as the Prisma binary returns a correct return code (like 1 or 0), we don't need this anymore
           */
          this.queryEngineKilled = false;
          this.managementApiEnabled = false;
          this.ready = false;
          this.stderrLogs = '';
          this.stdoutLogs = '';
          this.handleRequestError = (error) => {
              var _a, _b, _c, _d;
              debug({ error });
              let err;
              if (this.currentRequestPromise.isCanceled && this.lastError) {
                  // TODO: Replace these errors with known or unknown request errors
                  if (this.lastError.is_panic) {
                      err = new Engine_1.PrismaClientRustPanicError(Engine_1.getErrorMessageWithLink({
                          platform: this.platform,
                          title: Engine_1.getMessage(this.lastError),
                          version: this.clientVersion,
                      }));
                      this.lastPanic = err;
                  }
                  else {
                      err = new Engine_1.PrismaClientUnknownRequestError(Engine_1.getErrorMessageWithLink({
                          platform: this.platform,
                          title: Engine_1.getMessage(this.lastError),
                          version: this.clientVersion,
                      }));
                  }
              }
              else if (this.currentRequestPromise.isCanceled && this.lastErrorLog) {
                  if (((_b = (_a = this.lastErrorLog) === null || _a === void 0 ? void 0 : _a.fields) === null || _b === void 0 ? void 0 : _b.message) === 'PANIC') {
                      err = new Engine_1.PrismaClientRustPanicError(Engine_1.getErrorMessageWithLink({
                          platform: this.platform,
                          title: Engine_1.getMessage(this.lastErrorLog),
                          version: this.clientVersion,
                      }));
                      this.lastPanic = err;
                  }
                  else {
                      err = new Engine_1.PrismaClientUnknownRequestError(Engine_1.getErrorMessageWithLink({
                          platform: this.platform,
                          title: Engine_1.getMessage(this.lastErrorLog),
                          version: this.clientVersion,
                      }));
                  }
              }
              else if ((error.code && error.code === 'ECONNRESET') ||
                  error.code === 'ECONNREFUSED') {
                  if (this.globalKillSignalReceived && !this.child.connected) {
                      throw new Engine_1.PrismaClientUnknownRequestError(`The Node.js process already received a ${this.globalKillSignalReceived} signal, therefore the Prisma query engine exited
  and your request can't be processed.
  You probably have some open handle that prevents your process from exiting.
  It could be an open http server or stream that didn't close yet.
  We recommend using the \`wtfnode\` package to debug open handles.`);
                  }
                  if (this.restartCount > 4) {
                      throw new Error(`Query engine is trying to restart, but can't.
  Please look into the logs or turn on the env var DEBUG=* to debug the constantly restarting query engine.`);
                  }
                  if (this.lastError) {
                      if (this.lastError.is_panic) {
                          err = new Engine_1.PrismaClientRustPanicError(Engine_1.getErrorMessageWithLink({
                              platform: this.platform,
                              title: Engine_1.getMessage(this.lastError),
                              version: this.clientVersion,
                          }));
                          this.lastPanic = err;
                      }
                      else {
                          err = new Engine_1.PrismaClientUnknownRequestError(Engine_1.getErrorMessageWithLink({
                              platform: this.platform,
                              title: Engine_1.getMessage(this.lastError),
                              version: this.clientVersion,
                          }));
                      }
                  }
                  else if (this.lastErrorLog) {
                      if (((_d = (_c = this.lastErrorLog) === null || _c === void 0 ? void 0 : _c.fields) === null || _d === void 0 ? void 0 : _d.message) === 'PANIC') {
                          err = new Engine_1.PrismaClientRustPanicError(Engine_1.getErrorMessageWithLink({
                              platform: this.platform,
                              title: Engine_1.getMessage(this.lastErrorLog),
                              version: this.clientVersion,
                          }));
                          this.lastPanic = err;
                      }
                      else {
                          err = new Engine_1.PrismaClientUnknownRequestError(Engine_1.getErrorMessageWithLink({
                              platform: this.platform,
                              title: Engine_1.getMessage(this.lastErrorLog),
                              version: this.clientVersion,
                          }));
                      }
                  }
                  if (!err) {
                      const logs = this.stderrLogs || this.stdoutLogs;
                      err = new Engine_1.PrismaClientUnknownRequestError(Engine_1.getErrorMessageWithLink({
                          platform: this.platform,
                          title: `Unknown error in Prisma Client`,
                          version: this.clientVersion,
                          description: logs,
                      }));
                  }
              }
              if (err) {
                  throw err;
              }
              throw error;
          };
          this.env = env;
          this.cwd = this.resolveCwd(cwd);
          this.debug = args.debug || false;
          this.datamodelPath = datamodelPath;
          this.prismaPath = process.env.PRISMA_QUERY_ENGINE_BINARY || prismaPath;
          this.generator = generator;
          this.datasources = datasources;
          this.logEmitter = new events_1.default();
          this.showColors = showColors || false;
          this.logLevel = logLevel;
          this.logQueries = logQueries || false;
          this.clientVersion = clientVersion;
          this.flags = flags || [];
          this.h1Client = new h1client_1.H1Client();
          this.logEmitter.on('error', (log) => {
              if (this.debug) {
                  debug_1.default('engine:log')(log);
              }
              if (log instanceof Error) {
                  debug_1.default('engine:error')(log);
              }
              else {
                  this.lastErrorLog = log;
                  if (log.fields.message === 'PANIC') {
                      this.handlePanic(log);
                  }
              }
          });
          if (this.platform) {
              if (!knownPlatforms.includes(this.platform) &&
                  !fs_1.default.existsSync(this.platform)) {
                  throw new Engine_1.PrismaClientInitializationError(`Unknown ${chalk_1.default.red('PRISMA_QUERY_ENGINE_BINARY')} ${chalk_1.default.redBright.bold(this.platform)}. Possible binaryTargets: ${chalk_1.default.greenBright(knownPlatforms.join(', '))} or a path to the query engine binary.
  You may have to run ${chalk_1.default.greenBright('prisma generate')} for your changes to take effect.`);
              }
          }
          else {
              this.getPlatform();
          }
          if (this.debug) {
              debug_1.default.enable('*');
          }
          engines.push(this);
      }
      resolveCwd(cwd) {
          if (cwd && fs_1.default.existsSync(cwd) && fs_1.default.lstatSync(cwd).isDirectory()) {
              return cwd;
          }
          return process.cwd();
      }
      on(event, listener) {
          this.logEmitter.on(event, listener);
      }
      async getPlatform() {
          // eslint-disable-next-line @typescript-eslint/no-misused-promises
          if (this.platformPromise) {
              return this.platformPromise;
          }
          this.platformPromise = get_platform_1.getPlatform();
          return this.platformPromise;
      }
      getQueryEnginePath(platform, prefix = __dirname) {
          let queryEnginePath = path_1.default.join(prefix, `query-engine-${platform}`);
          if (platform === 'windows') {
              queryEnginePath = `${queryEnginePath}.exe`;
          }
          return queryEnginePath;
      }
      // eslint-disable-next-line @typescript-eslint/no-unused-vars
      handlePanic(log) {
          var _a;
          (_a = this.child) === null || _a === void 0 ? void 0 : _a.kill();
          if (this.currentRequestPromise) {
              this.currentRequestPromise.cancel();
          }
      }
      async resolvePrismaPath() {
          if (this.prismaPath) {
              return this.prismaPath;
          }
          const platform = await this.getPlatform();
          if (this.platform && this.platform !== platform) {
              this.incorrectlyPinnedPlatform = this.platform;
          }
          this.platform = this.platform || platform;
          const fileName = eval(`require('path').basename(__filename)`);
          if (fileName === 'NodeEngine.js') {
              return this.getQueryEnginePath(this.platform, path_1.default.resolve(__dirname, `..`));
          }
          else {
              const dotPrismaPath = await this.getQueryEnginePath(this.platform, eval(`require('path').join(__dirname, '../../../.prisma/client')`));
              debug({ dotPrismaPath });
              if (fs_1.default.existsSync(dotPrismaPath)) {
                  return dotPrismaPath;
              }
              const dirnamePath = await this.getQueryEnginePath(this.platform, eval('__dirname'));
              debug({ dirnamePath });
              if (fs_1.default.existsSync(dirnamePath)) {
                  return dirnamePath;
              }
              const parentDirName = await this.getQueryEnginePath(this.platform, path_1.default.join(eval('__dirname'), '..'));
              debug({ parentDirName });
              if (fs_1.default.existsSync(parentDirName)) {
                  return parentDirName;
              }
              const datamodelDirName = await this.getQueryEnginePath(this.platform, path_1.default.dirname(this.datamodelPath));
              if (fs_1.default.existsSync(datamodelDirName)) {
                  return datamodelDirName;
              }
              const cwdPath = await this.getQueryEnginePath(this.platform, this.cwd);
              if (fs_1.default.existsSync(cwdPath)) {
                  return cwdPath;
              }
              const prismaPath = await this.getQueryEnginePath(this.platform);
              debug({ prismaPath });
              return prismaPath;
          }
      }
      // get prisma path
      async getPrismaPath() {
          const prismaPath = await this.resolvePrismaPath();
          const platform = await this.getPlatform();
          // If path to query engine doesn't exist, throw
          if (!(await exists(prismaPath))) {
              const pinnedStr = this.incorrectlyPinnedPlatform
                  ? `\nYou incorrectly pinned it to ${chalk_1.default.redBright.bold(`${this.incorrectlyPinnedPlatform}`)}\n`
                  : '';
              const dir = path_1.default.dirname(prismaPath);
              const dirExists = fs_1.default.existsSync(dir);
              let files = [];
              if (dirExists) {
                  files = await readdir(dir);
              }
              let errorText = `Query engine binary for current platform "${chalk_1.default.bold(platform)}" could not be found.${pinnedStr}
  This probably happens, because you built Prisma Client on a different platform.
  (Prisma Client looked in "${chalk_1.default.underline(prismaPath)}")
  
  Files in ${dir}:
  
  ${files.map((f) => `  ${f}`).join('\n')}\n`;
              // The generator should always be there during normal usage
              if (this.generator) {
                  // The user already added it, but it still doesn't work 🤷‍♀️
                  // That means, that some build system just deleted the files 🤔
                  if (this.generator.binaryTargets.includes(this.platform) ||
                      this.generator.binaryTargets.includes('native')) {
                      errorText += `
  You already added the platform${this.generator.binaryTargets.length > 1 ? 's' : ''} ${this.generator.binaryTargets
                          .map((t) => `"${chalk_1.default.bold(t)}"`)
                          .join(', ')} to the "${chalk_1.default.underline('generator')}" block
  in the "schema.prisma" file as described in https://pris.ly/d/client-generator,
  but something went wrong. That's suboptimal.
  
  Please create an issue at https://github.com/prisma/prisma-client-js/issues/new`;
                  }
                  else {
                      // If they didn't even have the current running platform in the schema.prisma file, it's easy
                      // Just add it
                      errorText += `\n\nTo solve this problem, add the platform "${this.platform}" to the "${chalk_1.default.underline('generator')}" block in the "schema.prisma" file:
  ${chalk_1.default.greenBright(this.getFixedGenerator())}
  
  Then run "${chalk_1.default.greenBright('prisma generate')}" for your changes to take effect.
  Read more about deploying Prisma Client: https://pris.ly/d/client-generator`;
                  }
              }
              else {
                  errorText += `\n\nRead more about deploying Prisma Client: https://pris.ly/d/client-generator\n`;
              }
              throw new Engine_1.PrismaClientInitializationError(errorText);
          }
          if (this.incorrectlyPinnedPlatform) {
              console.error(`${chalk_1.default.yellow('Warning:')} You pinned the platform ${chalk_1.default.bold(this.incorrectlyPinnedPlatform)}, but Prisma Client detects ${chalk_1.default.bold(await this.getPlatform())}.
  This means you should very likely pin the platform ${chalk_1.default.greenBright(await this.getPlatform())} instead.
  ${chalk_1.default.dim("In case we're mistaken, please report this to us 🙏.")}`);
          }
          if (process.platform !== 'win32') {
              util_1.plusX(prismaPath);
          }
          return prismaPath;
      }
      getFixedGenerator() {
          const fixedGenerator = {
              ...this.generator,
              binaryTargets: util_1.fixPlatforms(this.generator.binaryTargets, this.platform),
          };
          return printGeneratorConfig_1.printGeneratorConfig(fixedGenerator);
      }
      printDatasources() {
          if (this.datasources) {
              return JSON.stringify(this.datasources);
          }
          return '[]';
      }
      /**
       * Starts the engine, returns the url that it runs on
       */
      async start() {
          // eslint-disable-next-line @typescript-eslint/no-misused-promises
          if (!this.startPromise) {
              this.startPromise = this.internalStart();
          }
          return this.startPromise;
      }
      internalStart() {
          // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor
          return new Promise(async (resolve, reject) => {
              var _a, _b, _c;
              try {
                  if ((_a = this.child) === null || _a === void 0 ? void 0 : _a.connected) {
                      debug(`There is a child that still runs and we want to start again. We're killing that child process now.`);
                      this.queryEngineKilled = true;
                      (_b = this.child) === null || _b === void 0 ? void 0 : _b.kill();
                  }
                  this.queryEngineStarted = false;
                  // reset last panic
                  this.lastError = undefined;
                  this.lastErrorLog = undefined;
                  this.lastPanic = undefined;
                  this.queryEngineKilled = false;
                  this.globalKillSignalReceived = undefined;
                  this.port = await this.getFreePort();
                  const env = {
                      PRISMA_DML_PATH: this.datamodelPath,
                      PORT: String(this.port),
                      RUST_BACKTRACE: '1',
                      RUST_LOG: 'info',
                  };
                  if (this.logQueries || this.logLevel === 'info') {
                      env.RUST_LOG = 'info';
                      if (this.logQueries) {
                          env.LOG_QUERIES = 'true';
                      }
                  }
                  if (this.logLevel === 'warn') {
                      env.RUST_LOG = 'warn';
                  }
                  if (this.datasources) {
                      env.OVERWRITE_DATASOURCES = this.printDatasources();
                  }
                  if (!process.env.NO_COLOR && this.showColors) {
                      env.CLICOLOR_FORCE = '1';
                  }
                  debug({ cwd: this.cwd });
                  const prismaPath = await this.getPrismaPath();
                  const flags = ['--enable-raw-queries', ...this.flags];
                  debug({ flags });
                  this.child = child_process_1.spawn(prismaPath, flags, {
                      env: {
                          ...this.env,
                          ...process.env,
                          ...env,
                      },
                      cwd: this.cwd,
                      stdio: ['ignore', 'pipe', 'pipe'],
                  });
                  byline_1.default(this.child.stderr).on('data', (msg) => {
                      const data = String(msg);
                      debug('stderr', data);
                      try {
                          const json = JSON.parse(data);
                          if (typeof json.is_panic !== 'undefined') {
                              debug(json);
                              this.lastError = json;
                              if (this.engineStartDeferred) {
                                  const err = new Engine_1.PrismaClientInitializationError(this.lastError.message);
                                  this.engineStartDeferred.reject(err);
                              }
                          }
                      }
                      catch (e) {
                          if (!data.includes('Printing to stderr') &&
                              !data.includes('Listening on ')) {
                              this.stderrLogs += '\n' + data;
                          }
                      }
                  });
                  byline_1.default(this.child.stdout).on('data', (msg) => {
                      var _a;
                      const data = String(msg);
                      try {
                          const json = JSON.parse(data);
                          debug('stdout', json);
                          if (this.engineStartDeferred &&
                              json.level === 'INFO' &&
                              json.target === 'query_engine::server' && ((_a = json.fields) === null || _a === void 0 ? void 0 : _a.message.startsWith('Started http server'))) {
                              // TODO: Add debug statement
                              this.engineStartDeferred.resolve();
                              this.engineStartDeferred = undefined;
                              this.queryEngineStarted = true;
                          }
                          if (typeof json.is_panic === 'undefined') {
                              const log = log_1.convertLog(json);
                              this.logEmitter.emit(log.level, log);
                          }
                          else {
                              this.lastError = json;
                          }
                      }
                      catch (e) {
                          // debug(e, data)
                      }
                  });
                  this.child.on('exit', (code) => {
                      this.h1Client.close();
                      this.exitCode = code;
                      if (!this.queryEngineKilled &&
                          this.queryEngineStarted &&
                          this.restartCount < 5) {
                          p_retry_1.default(async (attempt) => {
                              debug(`Restart attempt ${attempt}. Waiting for backoff`);
                              if (this.backoffPromise) {
                                  await this.backoffPromise;
                              }
                              debug(`Restart attempt ${attempt}. Backoff done`);
                              this.restartCount++;
                              const wait = Math.random() * 2 * Math.pow(Math.E, this.restartCount);
                              this.startPromise = undefined;
                              this.backoffPromise = new Promise((r) => setTimeout(r, wait));
                              return this.start();
                          }, {
                              retries: 4,
                              randomize: true,
                              minTimeout: 1000,
                              maxTimeout: 60 * 1000,
                              factor: Math.E,
                              onFailedAttempt: (e) => {
                                  debug(e);
                              },
                          });
                          return;
                      }
                      if (code !== 0 && this.engineStartDeferred) {
                          const err = new Engine_1.PrismaClientInitializationError(this.stderrLogs);
                          this.engineStartDeferred.reject(err);
                      }
                      if (!this.child) {
                          return;
                      }
                      if (this.lastError) {
                          return;
                      }
                      if (this.lastErrorLog) {
                          this.lastErrorLog.target = 'exit';
                          return;
                      }
                      if (code === 126) {
                          this.lastErrorLog = {
                              timestamp: new Date(),
                              target: 'exit',
                              level: 'error',
                              fields: {
                                  message: `Couldn't start query engine as it's not executable on this operating system.
  You very likely have the wrong "binaryTarget" defined in the schema.prisma file.`,
                              },
                          };
                      }
                      else {
                          this.lastErrorLog = {
                              target: 'exit',
                              timestamp: new Date(),
                              level: 'error',
                              fields: {
                                  message: (this.stderrLogs || '') +
                                      (this.stdoutLogs || '') +
                                      `\nExit code: ${code}`,
                              },
                          };
                      }
                  });
                  this.child.on('error', (err) => {
                      this.lastError = {
                          message: err.message,
                          backtrace: 'Could not start query engine',
                          is_panic: false,
                      };
                      reject(err);
                  });
                  this.child.on('close', (code, signal) => {
                      var _a;
                      this.h1Client.close();
                      if (code === null && signal === 'SIGABRT' && this.child) {
                          const error = new Engine_1.PrismaClientRustPanicError(Engine_1.getErrorMessageWithLink({
                              platform: this.platform,
                              title: `Panic in Query Engine with SIGABRT signal`,
                              description: this.stderrLogs,
                              version: this.clientVersion,
                          }));
                          this.logEmitter.emit('error', error);
                      }
                      else if (code === 255 &&
                          signal === null &&
                          // if there is a "this.lastPanic", the panic has already been handled, so we don't need
                          // to look into it anymore
                          ((_a = this.lastErrorLog) === null || _a === void 0 ? void 0 : _a.fields.message) === 'PANIC' &&
                          !this.lastPanic) {
                          const error = new Engine_1.PrismaClientRustPanicError(Engine_1.getErrorMessageWithLink({
                              platform: this.platform,
                              title: `${this.lastErrorLog.fields.message}: ${this.lastErrorLog.fields.reason} in
  ${this.lastErrorLog.fields.file}:${this.lastErrorLog.fields.line}:${this.lastErrorLog.fields.column}`,
                              version: this.clientVersion,
                          }));
                          this.logEmitter.emit('error', error);
                      }
                  });
                  if (this.lastError) {
                      return reject(new Engine_1.PrismaClientInitializationError(Engine_1.getMessage(this.lastError)));
                  }
                  if (this.lastErrorLog) {
                      return reject(new Engine_1.PrismaClientInitializationError(Engine_1.getMessage(this.lastErrorLog)));
                  }
                  try {
                      await new Promise((resolve, reject) => {
                          this.engineStartDeferred = { resolve, reject };
                      });
                  }
                  catch (err) {
                      (_c = this.child) === null || _c === void 0 ? void 0 : _c.kill();
                      throw err;
                  }
                  this.url = `http://localhost:${this.port}`;
                  resolve();
              }
              catch (e) {
                  reject(e);
              }
          });
      }
      /**
       * If Prisma runs, stop it
       */
      async stop() {
          var _a, _b;
          await this.start();
          if (this.currentRequestPromise) {
              try {
                  await this.currentRequestPromise;
              }
              catch (e) {
                  //
              }
          }
          if (this.child) {
              debug(`Stopping Prisma engine`);
              this.queryEngineKilled = true;
              (_a = this.h1Client) === null || _a === void 0 ? void 0 : _a.close();
              (_b = this.child) === null || _b === void 0 ? void 0 : _b.kill();
              delete this.child;
          }
      }
      async kill(signal) {
          var _a, _b;
          this.globalKillSignalReceived = signal;
          this.queryEngineKilled = true;
          (_a = this.h1Client) === null || _a === void 0 ? void 0 : _a.close();
          (_b = this.child) === null || _b === void 0 ? void 0 : _b.kill();
      }
      /**
       * Use the port 0 trick to get a new port
       */
      getFreePort() {
          return new Promise((resolve, reject) => {
              const server = net_1.default.createServer((s) => s.end(''));
              server.unref();
              server.on('error', reject);
              server.listen(0, () => {
                  const address = server.address();
                  const port = typeof address === 'string'
                      ? parseInt(address.split(':').slice(-1)[0], 10)
                      : address.port;
                  server.close((e) => {
                      if (e) {
                          reject(e);
                      }
                      resolve(port);
                  });
              });
          });
      }
      async request(query) {
          await this.start();
          if (!this.child) {
              throw new Engine_1.PrismaClientUnknownRequestError(`Can't perform request, as the Engine has already been stopped`);
          }
          this.currentRequestPromise = this.h1Client.request(this.port, stringifyQuery(query));
          return this.currentRequestPromise
              .then(({ data, headers }) => {
              if (data.errors) {
                  if (data.errors.length === 1) {
                      throw this.graphQLToJSError(data.errors[0]);
                  }
                  // this case should not happen, as the query engine only returns one error
                  throw new Error(JSON.stringify(data.errors));
              }
              const elapsed = parseInt(headers['x-elapsed']) / 1000;
              // reset restart count after successful request
              if (this.restartCount > 0) {
                  this.restartCount = 0;
              }
              return { data, elapsed };
          })
              .catch(this.handleRequestError);
      }
      async requestBatch(queries) {
          await this.start();
          if (!this.child) {
              throw new Engine_1.PrismaClientUnknownRequestError(`Can't perform request, as the Engine has already been stopped`);
          }
          const variables = {};
          const body = {
              batch: queries.map((query) => ({ query, variables })),
          };
          this.currentRequestPromise = this.h1Client.request(this.port, JSON.stringify(body));
          return this.currentRequestPromise
              .then(({ data, headers }) => {
              const elapsed = parseInt(headers['x-elapsed']) / 1000;
              if (Array.isArray(data)) {
                  return data.map((result) => {
                      if (result.errors) {
                          return this.graphQLToJSError(result.errors[0]);
                      }
                      return {
                          data: result,
                          elapsed,
                      };
                  });
              }
              else {
                  if (data.errors && data.errors.length === 1) {
                      throw new Error(data.errors[0].error);
                  }
                  throw new Error(JSON.stringify(data));
              }
          })
              .catch(this.handleRequestError);
      }
      graphQLToJSError(error) {
          if (error.user_facing_error.error_code) {
              return new Engine_1.PrismaClientKnownRequestError(error.user_facing_error.message, error.user_facing_error.error_code, error.user_facing_error.meta);
          }
          return new Engine_1.PrismaClientUnknownRequestError(error.user_facing_error.message);
      }
  }
  exports.NodeEngine = NodeEngine;
  // faster than creating a new object and JSON.stringify it all the time
  function stringifyQuery(q) {
      return `{"variables":{},"query":${JSON.stringify(q)}}`;
  }
  function hookProcess(handler, exit = false) {
      process.once(handler, () => {
          for (const engine of engines) {
              engine.kill(handler);
          }
          engines.splice(0, engines.length);
          if (exit) {
              process.exit();
          }
      });
  }
  hookProcess('beforeExit');
  hookProcess('exit');
  hookProcess('SIGINT', true);
  hookProcess('SIGUSR1', true);
  hookProcess('SIGUSR2', true);
  hookProcess('SIGTERM', true);
  //# sourceMappingURL=NodeEngine.js.map