var __create = Object.create;
var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
  for (var prop in b || (b = {}))
    if (__hasOwnProp.call(b, prop))
      __defNormalProp(a, prop, b[prop]);
  if (__getOwnPropSymbols)
    for (var prop of __getOwnPropSymbols(b)) {
      if (__propIsEnum.call(b, prop))
        __defNormalProp(a, prop, b[prop]);
    }
  return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
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);

// src/server/server.ts
var server_exports = {};
__export(server_exports, {
  createServer: () => createServer
});
module.exports = __toCommonJS(server_exports);
var import_bundler_utils = require("@umijs/bundler-utils");
var import_express = __toESM(require("@umijs/bundler-utils/compiled/express"));
var import_http_proxy_middleware = require("@umijs/bundler-webpack/compiled/http-proxy-middleware");
var import_webpack = __toESM(require("@umijs/bundler-webpack/compiled/webpack"));
var import_utils = require("@umijs/utils");
var import_assert = __toESM(require("assert"));
var import_cors = __toESM(require("cors"));
var import_fs = require("fs");
var import_http = __toESM(require("http"));
var import_path = require("path");
var import_constants = require("../constants");
var import_ws = require("./ws");
async function createServer(opts) {
  const { webpackConfig, userConfig } = opts;
  const { proxy } = userConfig;
  const app = (0, import_express.default)();
  let ws;
  app.use((0, import_cors.default)({
    origin: true,
    methods: ["GET", "HEAD", "PUT", "POST", "PATCH", "DELETE", "OPTIONS"],
    credentials: true
  }));
  app.use(require("@umijs/bundler-webpack/compiled/compression")());
  app.use((req, res, next) => {
    const file = req.path;
    const filePath = (0, import_path.join)(opts.cwd, file);
    const ext = (0, import_path.extname)(filePath);
    if (ext === ".js" && (0, import_fs.existsSync)(filePath)) {
      import_utils.logger.info("[dev]", `${file} is responded with ${filePath}, remove it to use original file`);
      res.sendFile(filePath);
    } else {
      next();
    }
  });
  (opts.beforeMiddlewares || []).forEach((m) => app.use(m));
  const configs = Array.isArray(webpackConfig) ? webpackConfig : [webpackConfig];
  const progresses = [];
  if (opts.onProgress) {
    configs.forEach((config) => {
      const progress = {
        percent: 0,
        status: "waiting"
      };
      progresses.push(progress);
      config.plugins.push(new import_webpack.default.ProgressPlugin((percent, msg) => {
        progress.percent = percent;
        progress.status = msg;
        opts.onProgress({ progresses });
      }));
    });
  }
  const compiler = (0, import_webpack.default)(configs);
  const webpackDevMiddleware = require("@umijs/bundler-webpack/compiled/webpack-dev-middleware");
  const compilerMiddleware = webpackDevMiddleware(compiler, {
    publicPath: userConfig.publicPath || "/",
    writeToDisk: userConfig.writeToDisk,
    stats: "none"
  });
  app.use(compilerMiddleware);
  let stats;
  let isFirstCompile = true;
  compiler.compilers.forEach(addHooks);
  function addHooks(compiler2) {
    compiler2.hooks.invalid.tap("server", () => {
      sendMessage(import_constants.MESSAGE_TYPE.invalid);
    });
    compiler2.hooks.done.tap("server", (_stats) => {
      var _a;
      stats = _stats;
      sendStats(getStats(stats));
      (_a = opts.onDevCompileDone) == null ? void 0 : _a.call(opts, {
        stats,
        isFirstCompile,
        time: stats.endTime - stats.startTime
      });
      isFirstCompile = false;
    });
  }
  function sendStats(stats2, force, sender) {
    const shouldEmit = !force && stats2 && (!stats2.errors || stats2.errors.length === 0) && (!stats2.warnings || stats2.warnings.length === 0) && stats2.assets && stats2.assets.every((asset) => !asset.emitted);
    if (shouldEmit) {
      sendMessage(import_constants.MESSAGE_TYPE.stillOk, null, sender);
      return;
    }
    sendMessage(import_constants.MESSAGE_TYPE.hash, stats2.hash, sender);
    if (stats2.errors && stats2.errors.length > 0 || stats2.warnings && stats2.warnings.length > 0) {
      if (stats2.warnings && stats2.warnings.length > 0) {
        sendMessage(import_constants.MESSAGE_TYPE.warnings, stats2.warnings, sender);
      }
      if (stats2.errors && stats2.errors.length > 0) {
        sendMessage(import_constants.MESSAGE_TYPE.errors, stats2.errors, sender);
      }
    } else {
      sendMessage(import_constants.MESSAGE_TYPE.ok, null, sender);
    }
  }
  function getStats(stats2) {
    return stats2.toJson({
      all: false,
      hash: true,
      assets: true,
      warnings: true,
      errors: true,
      errorDetails: false
    });
  }
  function sendMessage(type, data, sender) {
    var _a;
    (_a = sender || ws) == null ? void 0 : _a.send(JSON.stringify({ type, data }));
  }
  if (proxy) {
    const proxyArr = Array.isArray(proxy) ? proxy : proxy.target ? [proxy] : Object.keys(proxy).map((key) => {
      return __spreadProps(__spreadValues({}, proxy[key]), {
        context: key
      });
    });
    proxyArr.forEach((proxy2) => {
      let middleware;
      if (proxy2.target) {
        (0, import_assert.default)(typeof proxy2.target === "string", "proxy.target must be string");
        (0, import_assert.default)(proxy2.context, "proxy.context must be supplied");
        middleware = (0, import_http_proxy_middleware.createProxyMiddleware)(proxy2.context, __spreadProps(__spreadValues({}, proxy2), {
          onProxyReq(proxyReq, req, res) {
            var _a, _b;
            if (proxyReq.getHeader("origin")) {
              proxyReq.setHeader("origin", ((_a = new URL(proxy2.target)) == null ? void 0 : _a.href) || "");
            }
            (_b = proxy2.onProxyReq) == null ? void 0 : _b.call(proxy2, proxyReq, req, res, proxy2);
          },
          onProxyRes(proxyRes, req, res) {
            var _a, _b;
            proxyRes.headers["x-real-url"] = ((_a = new URL(req.url || "", proxy2.target)) == null ? void 0 : _a.href) || "";
            (_b = proxy2.onProxyRes) == null ? void 0 : _b.call(proxy2, proxyRes, req, res);
          }
        }));
      }
      app.use((req, res, next) => {
        const bypassUrl = typeof proxy2.bypass === "function" ? proxy2.bypass(req, res, proxy2) : null;
        if (typeof bypassUrl === "string") {
          req.url = bypassUrl;
          return next();
        } else if (bypassUrl === false) {
          return res.end(404);
        } else if ((bypassUrl === null || bypassUrl === void 0) && middleware) {
          return middleware(req, res, next);
        } else {
          next();
        }
      });
    });
  }
  (opts.afterMiddlewares || []).forEach((m) => {
    app.use(m.toString().includes(`{ compiler }`) ? m({ compiler }) : m);
  });
  app.use(require("@umijs/bundler-webpack/compiled/connect-history-api-fallback")({
    index: "/"
  }));
  app.use("/__umi_ping", (_, res) => {
    res.end("pong");
  });
  app.get("/", (_req, res, next) => {
    res.set("Content-Type", "text/html");
    const htmlPath = (0, import_path.join)(opts.cwd, "index.html");
    if ((0, import_fs.existsSync)(htmlPath)) {
      (0, import_fs.createReadStream)(htmlPath).on("error", next).pipe(res);
    } else {
      next();
    }
  });
  let server;
  if (userConfig.https) {
    const httpsOpts = userConfig.https;
    if (!httpsOpts.hosts) {
      httpsOpts.hosts = import_utils.lodash.uniq([
        ...httpsOpts.hosts || [],
        "127.0.0.1",
        "localhost",
        opts.ip,
        opts.host !== "0.0.0.0" && opts.host
      ].filter(Boolean));
    }
    server = await (0, import_bundler_utils.createHttpsServer)(app, httpsOpts);
  } else {
    server = import_http.default.createServer(app);
  }
  if (!server) {
    return null;
  }
  ws = (0, import_ws.createWebSocketServer)(server);
  ws.wss.on("connection", (socket) => {
    if (stats) {
      sendStats(getStats(stats), false, socket);
    }
  });
  const protocol = userConfig.https ? "https:" : "http:";
  const port = opts.port || 8e3;
  server.listen(port, () => {
    const banner = (0, import_utils.getDevBanner)(protocol, opts.host, port);
    console.log(banner.before);
    import_utils.logger.ready(banner.main);
    console.log(banner.after);
  });
  return server;
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  createServer
});
