import { join as join$1 } from 'path';
import { resolve as resolve$1, join } from 'node:path';
import { readFile } from 'node:fs/promises';
import config from '../config.json' with { type: 'json' };

const { files, headers, etag } = config;

const handleUncaughtExceptionMonitor = (error) => {
  console.error(`[static-server] uncaught exception ${error}`);
};

const __dirname$1 = import.meta.dirname;

const root = resolve$1(__dirname$1, '..');

const STATIC = join(root, 'static');

const getAbsolutePath = (pathName) => {
  if (pathName === '/') {
    return join$1(STATIC, 'index.html')
  }
  if (pathName === '/favicon.ico') {
    return join$1(STATIC, 'favicon.ico')
  }
  return join(STATIC, pathName)
};

const NotFound = 404;
const MethodNotAllowed = 405;
const Ok = 200;
const ServerError = 500;
const NotModifed = 304;

const IfNotMatch = 'if-none-match';

const matchesEtag = (request, etag) => {
  return request.headers[IfNotMatch] === etag
};

const notFoundResponse = {
  absolutePath: '',
  status: NotFound,
  headers: {},
};

const notModifiedResponse = {
  absolutePath: '',
  status: NotModifed,
  headers: {},
};

const isSupportedMethod = (method) => {
  return method === 'GET' || method === 'HEAD'
};

const getResponseInfo = async ({ request, isImmutable, applicationName = 'lvce-oss' }) => {
  if (!isSupportedMethod(request.method)) {
    return {
      absolutePath: '',
      status: MethodNotAllowed,
      headers: {},
    }
  }
  const pathname = request.url;
  if(!Object.hasOwn(files, pathname)){
    return notFoundResponse
  }
  const index = files[pathname];
  const headers$1 = headers[index];
  const absolutePath = getAbsolutePath(pathname);
  if (matchesEtag(request, etag)) {
    return notModifiedResponse
  }
  return {
    absolutePath,
    status: Ok,
    headers: headers$1,
  }
};

const isImmutable = true;

const getResponse$1 = async (request) => {
  const { absolutePath, status, headers } = await getResponseInfo({ request, isImmutable: isImmutable });
  const hasBody = request.method !== 'HEAD';
  if (status === MethodNotAllowed) {
    return {
      headers,
      status,
      body: 'Method not Allowed',
      hasBody,
    }
  }
  if (status === NotFound) {
    return {
      headers,
      status,
      body: 'Not Found',
      hasBody,
    }
  }
  if (status === NotModifed) {
    return {
      headers,
      status,
      body: '',
      hasBody: false,
    }
  }
  // TODO maybe read content as blob
  // TODO implment buffering
  try {
    const content = await readFile(absolutePath);
    return {
      headers,
      status,
      body: content,
      hasBody,
    }
  } catch (error) {
    console.error(`[static server] response error at ${request.url} ${error}`);
    return {
      headers: {},
      status: ServerError,
      body: 'Server Error',
      hasBody: true,
    }
  }
};

const commandMap = {
  'StaticServer.getResponse': getResponse$1,
};

const normalizeLine = line => {
  if (line.startsWith('Error: ')) {
    return line.slice('Error: '.length);
  }
  if (line.startsWith('VError: ')) {
    return line.slice('VError: '.length);
  }
  return line;
};

const getCombinedMessage = (error, message) => {
  const stringifiedError = normalizeLine(`${error}`);
  if (message) {
    return `${message}: ${stringifiedError}`;
  }
  return stringifiedError;
};

const NewLine$2 = '\n';

const getNewLineIndex$1 = (string, startIndex = undefined) => {
  return string.indexOf(NewLine$2, startIndex);
};

const mergeStacks = (parent, child) => {
  if (!child) {
    return parent;
  }
  const parentNewLineIndex = getNewLineIndex$1(parent);
  const childNewLineIndex = getNewLineIndex$1(child);
  if (childNewLineIndex === -1) {
    return parent;
  }
  const parentFirstLine = parent.slice(0, parentNewLineIndex);
  const childRest = child.slice(childNewLineIndex);
  const childFirstLine = normalizeLine(child.slice(0, childNewLineIndex));
  if (parentFirstLine.includes(childFirstLine)) {
    return parentFirstLine + childRest;
  }
  return child;
};

class VError extends Error {
  constructor(error, message) {
    const combinedMessage = getCombinedMessage(error, message);
    super(combinedMessage);
    this.name = 'VError';
    if (error instanceof Error) {
      this.stack = mergeStacks(this.stack, error.stack);
    }
    if (error.codeFrame) {
      // @ts-ignore
      this.codeFrame = error.codeFrame;
    }
    if (error.code) {
      // @ts-ignore
      this.code = error.code;
    }
  }
}

const isMessagePort = value => {
  return value && value instanceof MessagePort;
};

const isMessagePortMain = value => {
  return value && value.constructor && value.constructor.name === 'MessagePortMain';
};

const isOffscreenCanvas = value => {
  return typeof OffscreenCanvas !== 'undefined' && value instanceof OffscreenCanvas;
};

const isInstanceOf = (value, constructorName) => {
  return value?.constructor?.name === constructorName;
};

const isSocket = value => {
  return isInstanceOf(value, 'Socket');
};

const transferrables = [isMessagePort, isMessagePortMain, isOffscreenCanvas, isSocket];

const isTransferrable = value => {
  for (const fn of transferrables) {
    if (fn(value)) {
      return true;
    }
  }
  return false;
};

const walkValue = (value, transferrables, isTransferrable) => {
  if (!value) {
    return;
  }
  if (isTransferrable(value)) {
    transferrables.push(value);
    return;
  }
  if (Array.isArray(value)) {
    for (const item of value) {
      walkValue(item, transferrables, isTransferrable);
    }
    return;
  }
  if (typeof value === 'object') {
    for (const property of Object.values(value)) {
      walkValue(property, transferrables, isTransferrable);
    }
    return;
  }
};

const getTransferrables = value => {
  const transferrables = [];
  walkValue(value, transferrables, isTransferrable);
  return transferrables;
};

const attachEvents = that => {
  const handleMessage = (...args) => {
    const data = that.getData(...args);
    that.dispatchEvent(new MessageEvent('message', {
      data
    }));
  };
  that.onMessage(handleMessage);
  const handleClose = event => {
    that.dispatchEvent(new Event('close'));
  };
  that.onClose(handleClose);
};

class Ipc extends EventTarget {
  constructor(rawIpc) {
    super();
    this._rawIpc = rawIpc;
    attachEvents(this);
  }
}

const E_INCOMPATIBLE_NATIVE_MODULE = 'E_INCOMPATIBLE_NATIVE_MODULE';
const E_MODULES_NOT_SUPPORTED_IN_ELECTRON = 'E_MODULES_NOT_SUPPORTED_IN_ELECTRON';
const ERR_MODULE_NOT_FOUND = 'ERR_MODULE_NOT_FOUND';

const NewLine$1 = '\n';

const joinLines$1 = lines => {
  return lines.join(NewLine$1);
};

const RE_AT = /^\s+at/;
const RE_AT_PROMISE_INDEX = /^\s*at async Promise.all \(index \d+\)$/;
const isNormalStackLine = line => {
  return RE_AT.test(line) && !RE_AT_PROMISE_INDEX.test(line);
};
const getDetails = lines => {
  const index = lines.findIndex(isNormalStackLine);
  if (index === -1) {
    return {
      actualMessage: joinLines$1(lines),
      rest: []
    };
  }
  let lastIndex = index - 1;
  while (++lastIndex < lines.length) {
    if (!isNormalStackLine(lines[lastIndex])) {
      break;
    }
  }
  return {
    actualMessage: lines[index - 1],
    rest: lines.slice(index, lastIndex)
  };
};

const splitLines$1 = lines => {
  return lines.split(NewLine$1);
};

const RE_MESSAGE_CODE_BLOCK_START = /^Error: The module '.*'$/;
const RE_MESSAGE_CODE_BLOCK_END = /^\s* at/;
const isMessageCodeBlockStartIndex = line => {
  return RE_MESSAGE_CODE_BLOCK_START.test(line);
};
const isMessageCodeBlockEndIndex = line => {
  return RE_MESSAGE_CODE_BLOCK_END.test(line);
};
const getMessageCodeBlock = stderr => {
  const lines = splitLines$1(stderr);
  const startIndex = lines.findIndex(isMessageCodeBlockStartIndex);
  const endIndex = startIndex + lines.slice(startIndex).findIndex(isMessageCodeBlockEndIndex, startIndex);
  const relevantLines = lines.slice(startIndex, endIndex);
  const relevantMessage = relevantLines.join(' ').slice('Error: '.length);
  return relevantMessage;
};

const isModuleNotFoundMessage = line => {
  return line.includes('[ERR_MODULE_NOT_FOUND]');
};
const getModuleNotFoundError = stderr => {
  const lines = splitLines$1(stderr);
  const messageIndex = lines.findIndex(isModuleNotFoundMessage);
  const message = lines[messageIndex];
  return {
    code: ERR_MODULE_NOT_FOUND,
    message
  };
};

const isModuleNotFoundError = stderr => {
  if (!stderr) {
    return false;
  }
  return stderr.includes('ERR_MODULE_NOT_FOUND');
};

const isModulesSyntaxError = stderr => {
  if (!stderr) {
    return false;
  }
  return stderr.includes('SyntaxError: Cannot use import statement outside a module');
};

const RE_NATIVE_MODULE_ERROR = /^innerError Error: Cannot find module '.*.node'/;
const RE_NATIVE_MODULE_ERROR_2 = /was compiled against a different Node.js version/;
const isUnhelpfulNativeModuleError = stderr => {
  return RE_NATIVE_MODULE_ERROR.test(stderr) && RE_NATIVE_MODULE_ERROR_2.test(stderr);
};

const getNativeModuleErrorMessage = stderr => {
  const message = getMessageCodeBlock(stderr);
  return {
    code: E_INCOMPATIBLE_NATIVE_MODULE,
    message: `Incompatible native node module: ${message}`
  };
};
const getModuleSyntaxError = () => {
  return {
    code: E_MODULES_NOT_SUPPORTED_IN_ELECTRON,
    message: `ES Modules are not supported in electron`
  };
};
const getHelpfulChildProcessError = (stdout, stderr) => {
  if (isUnhelpfulNativeModuleError(stderr)) {
    return getNativeModuleErrorMessage(stderr);
  }
  if (isModulesSyntaxError(stderr)) {
    return getModuleSyntaxError();
  }
  if (isModuleNotFoundError(stderr)) {
    return getModuleNotFoundError(stderr);
  }
  const lines = splitLines$1(stderr);
  const {
    actualMessage,
    rest
  } = getDetails(lines);
  return {
    code: '',
    message: actualMessage,
    stack: rest
  };
};

class IpcError extends VError {
  // @ts-ignore
  constructor(betterMessage, stdout = '', stderr = '') {
    if (stdout || stderr) {
      // @ts-ignore
      const {
        code,
        message,
        stack
      } = getHelpfulChildProcessError(stdout, stderr);
      const cause = new Error(message);
      // @ts-ignore
      cause.code = code;
      cause.stack = stack;
      super(cause, betterMessage);
    } else {
      super(betterMessage);
    }
    // @ts-ignore
    this.name = 'IpcError';
    // @ts-ignore
    this.stdout = stdout;
    // @ts-ignore
    this.stderr = stderr;
  }
}

const readyMessage = 'ready';

const getActualData = (message, handle) => {
  if (handle) {
    return {
      ...message,
      params: [handle, ...message.params]
    };
  }
  return message;
};

const getTransferrablesNode = value => {
  const transferrables = getTransferrables(value);
  if (transferrables.length === 0) {
    throw new Error(`no transferrables found`);
  }
  return transferrables[0];
};

const listen$5 = async () => {
  if (!process.send) {
    throw new IpcError('process.send must be defined');
  }
  return process;
};
const signal$7 = process => {
  process.send(readyMessage);
};
class IpcChildWithNodeForkedProcess extends Ipc {
  getData(message, handle) {
    return getActualData(message, handle);
  }
  onClose(callback) {
    this._rawIpc.on('close', callback);
  }
  send(message) {
    this._rawIpc.send(message);
  }
  onMessage(callback) {
    this._rawIpc.on('message', callback);
  }
  sendAndTransfer(message) {
    const transfer = getTransferrablesNode(message);
    this._rawIpc.send(message, transfer);
  }
  dispose() {
    // ignore
  }
}
const wrap$d = process => {
  return new IpcChildWithNodeForkedProcess(process);
};

const IpcChildWithNodeForkedProcess$1 = {
  __proto__: null,
  listen: listen$5,
  signal: signal$7,
  wrap: wrap$d
};

const listen$3 = async () => {
  const {
    parentPort
  } = await import('node:worker_threads');
  if (!parentPort) {
    throw new IpcError('parentPort is required for node worker threads ipc');
  }
  return parentPort;
};
const signal$5 = parentPort => {
  parentPort.postMessage(readyMessage);
};
class IpcChildWithNodeWorker extends Ipc {
  getData(data) {
    return data;
  }
  onClose(callback) {
    this._rawIpc.on('close', callback);
  }
  send(message) {
    this._rawIpc.postMessage(message);
  }
  onMessage(callback) {
    this._rawIpc.on('message', callback);
  }
  sendAndTransfer(message) {
    const transfer = getTransferrablesNode(message);
    this._rawIpc.postMessage(message, transfer);
  }
  dispose() {
    this._rawIpc.close();
  }
}
const wrap$b = parentPort => {
  return new IpcChildWithNodeWorker(parentPort);
};

const IpcChildWithNodeWorker$1 = {
  __proto__: null,
  listen: listen$3,
  signal: signal$5,
  wrap: wrap$b
};

class CommandNotFoundError extends Error {
  constructor(command) {
    super(`Command not found ${command}`);
    this.name = 'CommandNotFoundError';
  }
}

const commands = Object.create(null);
const register = commandMap => {
  Object.assign(commands, commandMap);
};
const getCommand = key => {
  return commands[key];
};

const execute = (command, ...args) => {
  const fn = getCommand(command);
  if (!fn) {
    throw new CommandNotFoundError(command);
  }
  return fn(...args);
};

const Two$1 = '2.0';

const callbacks = Object.create(null);
const get = id => {
  return callbacks[id];
};
const remove = id => {
  delete callbacks[id];
};

class JsonRpcError extends Error {
  constructor(message) {
    super(message);
    this.name = 'JsonRpcError';
  }
}

const NewLine = '\n';

const DomException = 'DOMException';
const ReferenceError$1 = 'ReferenceError';
const SyntaxError$1 = 'SyntaxError';
const TypeError$1 = 'TypeError';

const getErrorConstructor = (message, type) => {
  if (type) {
    switch (type) {
      case DomException:
        return DOMException;
      case ReferenceError$1:
        return ReferenceError;
      case SyntaxError$1:
        return SyntaxError;
      case TypeError$1:
        return TypeError;
      default:
        return Error;
    }
  }
  if (message.startsWith('TypeError: ')) {
    return TypeError;
  }
  if (message.startsWith('SyntaxError: ')) {
    return SyntaxError;
  }
  if (message.startsWith('ReferenceError: ')) {
    return ReferenceError;
  }
  return Error;
};

const constructError = (message, type, name) => {
  const ErrorConstructor = getErrorConstructor(message, type);
  if (ErrorConstructor === DOMException && name) {
    return new ErrorConstructor(message, name);
  }
  if (ErrorConstructor === Error) {
    const error = new Error(message);
    if (name && name !== 'VError') {
      error.name = name;
    }
    return error;
  }
  return new ErrorConstructor(message);
};

const joinLines = lines => {
  return lines.join(NewLine);
};

const splitLines = lines => {
  return lines.split(NewLine);
};

const getCurrentStack = () => {
  const stackLinesToSkip = 3;
  const currentStack = joinLines(splitLines(new Error().stack || '').slice(stackLinesToSkip));
  return currentStack;
};

const getNewLineIndex = (string, startIndex = undefined) => {
  return string.indexOf(NewLine, startIndex);
};

const getParentStack = error => {
  let parentStack = error.stack || error.data || error.message || '';
  if (parentStack.startsWith('    at')) {
    parentStack = error.message + NewLine + parentStack;
  }
  return parentStack;
};

const MethodNotFound = -32601;
const Custom = -32001;

const restoreJsonRpcError = error => {
  const currentStack = getCurrentStack();
  if (error && error instanceof Error) {
    if (typeof error.stack === 'string') {
      error.stack = error.stack + NewLine + currentStack;
    }
    return error;
  }
  if (error && error.code && error.code === MethodNotFound) {
    const restoredError = new JsonRpcError(error.message);
    const parentStack = getParentStack(error);
    restoredError.stack = parentStack + NewLine + currentStack;
    return restoredError;
  }
  if (error && error.message) {
    const restoredError = constructError(error.message, error.type, error.name);
    if (error.data) {
      if (error.data.stack && error.data.type && error.message) {
        restoredError.stack = error.data.type + ': ' + error.message + NewLine + error.data.stack + NewLine + currentStack;
      } else if (error.data.stack) {
        restoredError.stack = error.data.stack;
      }
      if (error.data.codeFrame) {
        // @ts-ignore
        restoredError.codeFrame = error.data.codeFrame;
      }
      if (error.data.code) {
        // @ts-ignore
        restoredError.code = error.data.code;
      }
      if (error.data.type) {
        // @ts-ignore
        restoredError.name = error.data.type;
      }
    } else {
      if (error.stack) {
        const lowerStack = restoredError.stack || '';
        // @ts-ignore
        const indexNewLine = getNewLineIndex(lowerStack);
        const parentStack = getParentStack(error);
        // @ts-ignore
        restoredError.stack = parentStack + lowerStack.slice(indexNewLine);
      }
      if (error.codeFrame) {
        // @ts-ignore
        restoredError.codeFrame = error.codeFrame;
      }
    }
    return restoredError;
  }
  if (typeof error === 'string') {
    return new Error(`JsonRpc Error: ${error}`);
  }
  return new Error(`JsonRpc Error: ${error}`);
};

const unwrapJsonRpcResult = responseMessage => {
  if ('error' in responseMessage) {
    const restoredError = restoreJsonRpcError(responseMessage.error);
    throw restoredError;
  }
  if ('result' in responseMessage) {
    return responseMessage.result;
  }
  throw new JsonRpcError('unexpected response message');
};

const warn = (...args) => {
  console.warn(...args);
};

const resolve = (id, response) => {
  const fn = get(id);
  if (!fn) {
    console.log(response);
    warn(`callback ${id} may already be disposed`);
    return;
  }
  fn(response);
  remove(id);
};

const E_COMMAND_NOT_FOUND = 'E_COMMAND_NOT_FOUND';

const getErrorType = prettyError => {
  if (prettyError && prettyError.type) {
    return prettyError.type;
  }
  if (prettyError && prettyError.constructor && prettyError.constructor.name) {
    return prettyError.constructor.name;
  }
  return undefined;
};

const isAlreadyStack = line => {
  return line.trim().startsWith('at ');
};
const getStack = prettyError => {
  const stackString = prettyError.stack || '';
  const newLineIndex = stackString.indexOf('\n');
  if (newLineIndex !== -1 && !isAlreadyStack(stackString.slice(0, newLineIndex))) {
    return stackString.slice(newLineIndex + 1);
  }
  return stackString;
};
const getErrorProperty = (error, prettyError) => {
  if (error && error.code === E_COMMAND_NOT_FOUND) {
    return {
      code: MethodNotFound,
      data: error.stack,
      message: error.message
    };
  }
  return {
    code: Custom,
    data: {
      code: prettyError.code,
      codeFrame: prettyError.codeFrame,
      name: prettyError.name,
      stack: getStack(prettyError),
      type: getErrorType(prettyError)
    },
    message: prettyError.message
  };
};

const create$1$1 = (id, error) => {
  return {
    error,
    id,
    jsonrpc: Two$1
  };
};

const getErrorResponse = (id, error, preparePrettyError, logError) => {
  const prettyError = preparePrettyError(error);
  logError(error, prettyError);
  const errorProperty = getErrorProperty(error, prettyError);
  return create$1$1(id, errorProperty);
};

const create$5 = (message, result) => {
  return {
    id: message.id,
    jsonrpc: Two$1,
    result: result ?? null
  };
};

const getSuccessResponse = (message, result) => {
  const resultProperty = result ?? null;
  return create$5(message, resultProperty);
};

const getErrorResponseSimple = (id, error) => {
  return {
    error: {
      code: Custom,
      data: error,
      // @ts-ignore
      message: error.message
    },
    id,
    jsonrpc: Two$1
  };
};

const getResponse = async (message, ipc, execute, preparePrettyError, logError, requiresSocket) => {
  try {
    const result = requiresSocket(message.method) ? await execute(message.method, ipc, ...message.params) : await execute(message.method, ...message.params);
    return getSuccessResponse(message, result);
  } catch (error) {
    if (ipc.canUseSimpleErrorResponse) {
      return getErrorResponseSimple(message.id, error);
    }
    return getErrorResponse(message.id, error, preparePrettyError, logError);
  }
};

const defaultPreparePrettyError = error => {
  return error;
};
const defaultLogError = () => {
  // ignore
};
const defaultRequiresSocket = () => {
  return false;
};
const defaultResolve = resolve;

// TODO maybe remove this in v6 or v7, only accept options object to simplify the code
const normalizeParams = args => {
  if (args.length === 1) {
    const options = args[0];
    return {
      execute: options.execute,
      ipc: options.ipc,
      logError: options.logError || defaultLogError,
      message: options.message,
      preparePrettyError: options.preparePrettyError || defaultPreparePrettyError,
      requiresSocket: options.requiresSocket || defaultRequiresSocket,
      resolve: options.resolve || defaultResolve
    };
  }
  return {
    execute: args[2],
    ipc: args[0],
    logError: args[5],
    message: args[1],
    preparePrettyError: args[4],
    requiresSocket: args[6],
    resolve: args[3]
  };
};

const handleJsonRpcMessage = async (...args) => {
  const options = normalizeParams(args);
  const {
    execute,
    ipc,
    logError,
    message,
    preparePrettyError,
    requiresSocket,
    resolve
  } = options;
  if ('id' in message) {
    if ('method' in message) {
      const response = await getResponse(message, ipc, execute, preparePrettyError, logError, requiresSocket);
      try {
        ipc.send(response);
      } catch (error) {
        const errorResponse = getErrorResponse(message.id, error, preparePrettyError, logError);
        ipc.send(errorResponse);
      }
      return;
    }
    resolve(message.id, message);
    return;
  }
  if ('method' in message) {
    await getResponse(message, ipc, execute, preparePrettyError, logError, requiresSocket);
    return;
  }
  throw new JsonRpcError('unexpected message');
};

const Two = '2.0';

const create$4 = (method, params) => {
    return {
        jsonrpc: Two,
        method,
        params,
    };
};

const create$3 = (id, method, params) => {
    const message = {
        id,
        jsonrpc: Two,
        method,
        params,
    };
    return message;
};

let id = 0;
const create$2 = () => {
    return ++id;
};

const registerPromise = (map) => {
    const id = create$2();
    const { promise, resolve } = Promise.withResolvers();
    map[id] = resolve;
    return { id, promise };
};

const invokeHelper = async (callbacks, ipc, method, params, useSendAndTransfer) => {
    const { id, promise } = registerPromise(callbacks);
    const message = create$3(id, method, params);
    if (useSendAndTransfer && ipc.sendAndTransfer) {
        ipc.sendAndTransfer(message);
    }
    else {
        ipc.send(message);
    }
    const responseMessage = await promise;
    return unwrapJsonRpcResult(responseMessage);
};
const createRpc = (ipc) => {
    const callbacks = Object.create(null);
    ipc._resolve = (id, response) => {
        const fn = callbacks[id];
        if (!fn) {
            console.warn(`callback ${id} may already be disposed`);
            return;
        }
        fn(response);
        delete callbacks[id];
    };
    const rpc = {
        async dispose() {
            await ipc?.dispose();
        },
        invoke(method, ...params) {
            return invokeHelper(callbacks, ipc, method, params, false);
        },
        invokeAndTransfer(method, ...params) {
            return invokeHelper(callbacks, ipc, method, params, true);
        },
        // @ts-ignore
        ipc,
        /**
         * @deprecated
         */
        send(method, ...params) {
            const message = create$4(method, params);
            ipc.send(message);
        },
    };
    return rpc;
};

const requiresSocket = () => {
    return false;
};
const preparePrettyError = (error) => {
    return error;
};
const logError = () => {
    // handled by renderer worker
};
const handleMessage = (event) => {
    const actualRequiresSocket = event?.target?.requiresSocket || requiresSocket;
    const actualExecute = event?.target?.execute || execute;
    return handleJsonRpcMessage(event.target, event.data, actualExecute, event.target._resolve, preparePrettyError, logError, actualRequiresSocket);
};

const handleIpc = (ipc) => {
    if ('addEventListener' in ipc) {
        ipc.addEventListener('message', handleMessage);
    }
    else if ('on' in ipc) {
        // deprecated
        ipc.on('message', handleMessage);
    }
};

const listen$2 = async (module, options) => {
    const rawIpc = await module.listen(options);
    if (module.signal) {
        module.signal(rawIpc);
    }
    const ipc = module.wrap(rawIpc);
    return ipc;
};

const create$1 = async ({ commandMap }) => {
    // TODO create a commandMap per rpc instance
    register(commandMap);
    const ipc = await listen$2(IpcChildWithNodeForkedProcess$1);
    handleIpc(ipc);
    const rpc = createRpc(ipc);
    return rpc;
};

const create = async ({ commandMap }) => {
    // TODO create a commandMap per rpc instance
    register(commandMap);
    const ipc = await listen$2(IpcChildWithNodeWorker$1);
    handleIpc(ipc);
    const rpc = createRpc(ipc);
    return rpc;
};

const NodeWorker = 1;
const NodeForkedProcess = 2;
const ElectronUtilityProcess = 3;

const Auto = (argv) => {
  if (argv.includes('--ipc-type=node-worker')) {
    return NodeWorker
  }
  if (argv.includes('--ipc-type=node-forked-process')) {
    return NodeForkedProcess
  }
  if (argv.includes('--ipc-type=electron-utility-process')) {
    return ElectronUtilityProcess
  }
  throw new Error(`[file-system-process] unknown ipc type`)
};

const getModule = (method) => {
  switch (method) {
    case NodeForkedProcess:
      return create$1
    case NodeWorker:
      return create
    default:
      throw new Error('unexpected ipc type')
  }
};

const listen$1 = async ({ method, ...params }) => {
  const create = getModule(method);
  // @ts-ignore
  const rpc = await create(params);
  return rpc
};

const listen = async (argv) => {
  await listen$1({
    method: Auto(argv),
    commandMap: commandMap,
  });
};

const main = async () => {
  process.on('uncaughtExceptionMonitor', handleUncaughtExceptionMonitor);
  await listen(process.argv);
};

main();
