@utoo/pack 1.3.2 → 1.3.3-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,6 +17,7 @@ const findRoot_1 = require("../utils/findRoot");
17
17
  const getInitialAssets_1 = require("../utils/getInitialAssets");
18
18
  const htmlEntry_1 = require("../utils/htmlEntry");
19
19
  const normalize_path_1 = require("../utils/normalize-path");
20
+ const runtimePluginStratety_1 = require("../utils/runtimePluginStratety");
20
21
  const validateEntry_1 = require("../utils/validateEntry");
21
22
  const xcodeProfile_1 = require("../utils/xcodeProfile");
22
23
  function build(options, projectPath, rootPath) {
@@ -28,7 +29,7 @@ function build(options, projectPath, rootPath) {
28
29
  return buildInternal(bundleOptions, projectPath, rootPath);
29
30
  }
30
31
  async function buildInternal(bundleOptions, projectPath, rootPath) {
31
- var _a, _b, _c, _d, _e, _f;
32
+ var _a, _b, _c, _d, _e, _f, _g, _h;
32
33
  (0, common_1.blockStdout)();
33
34
  if (process.env.XCODE_PROFILE) {
34
35
  await (0, xcodeProfile_1.xcodeProfilingReady)();
@@ -49,12 +50,13 @@ async function buildInternal(bundleOptions, projectPath, rootPath) {
49
50
  stats: Boolean(process.env.ANALYZE) ||
50
51
  bundleOptions.config.stats ||
51
52
  bundleOptions.config.entry.some((e) => !!e.html),
53
+ pluginRuntimeStrategy: (_d = (_c = bundleOptions === null || bundleOptions === void 0 ? void 0 : bundleOptions.config) === null || _c === void 0 ? void 0 : _c.pluginRuntimeStrategy) !== null && _d !== void 0 ? _d : ((0, runtimePluginStratety_1.useWorkerThreads)() ? "workerThreads" : "childProcesses"),
52
54
  },
53
55
  projectPath: (0, normalize_path_1.normalizePath)(resolvedProjectPath),
54
56
  rootPath: rootPath || projectPath || process.cwd(),
55
57
  packPath: (0, common_1.getPackPath)(),
56
58
  }, {
57
- persistentCaching: (_c = bundleOptions.config.persistentCaching) !== null && _c !== void 0 ? _c : false,
59
+ persistentCaching: (_e = bundleOptions.config.persistentCaching) !== null && _e !== void 0 ? _e : false,
58
60
  });
59
61
  const entrypoints = await project.writeAllEntrypointsToDisk();
60
62
  (0, pack_shared_1.handleIssues)(entrypoints.issues);
@@ -70,20 +72,20 @@ async function buildInternal(bundleOptions, projectPath, rootPath) {
70
72
  ];
71
73
  if (htmlConfigs.length > 0) {
72
74
  const assets = { js: [], css: [] };
73
- const outputDir = ((_d = bundleOptions.config.output) === null || _d === void 0 ? void 0 : _d.path) || path_1.default.join(process.cwd(), "dist");
75
+ const outputDir = ((_f = bundleOptions.config.output) === null || _f === void 0 ? void 0 : _f.path) || path_1.default.join(process.cwd(), "dist");
74
76
  if (assets.js.length === 0 && assets.css.length === 0) {
75
77
  const discovered = (0, getInitialAssets_1.getInitialAssetsFromStats)(outputDir);
76
78
  assets.js.push(...discovered.js);
77
79
  assets.css.push(...discovered.css);
78
80
  }
79
- const publicPath = (_e = bundleOptions.config.output) === null || _e === void 0 ? void 0 : _e.publicPath;
81
+ const publicPath = (_g = bundleOptions.config.output) === null || _g === void 0 ? void 0 : _g.publicPath;
80
82
  for (const config of htmlConfigs) {
81
83
  const plugin = new HtmlPlugin_1.HtmlPlugin(config);
82
84
  await plugin.generate(outputDir, assets, publicPath);
83
85
  }
84
86
  }
85
87
  if (process.env.ANALYZE) {
86
- await analyzeBundle(((_f = bundleOptions.config.output) === null || _f === void 0 ? void 0 : _f.path) || "dist");
88
+ await analyzeBundle(((_h = bundleOptions.config.output) === null || _h === void 0 ? void 0 : _h.path) || "dist");
87
89
  }
88
90
  await project.shutdown();
89
91
  // TODO: Maybe run tasks in worker is a better way, see
package/cjs/core/hmr.js CHANGED
@@ -14,6 +14,7 @@ const common_1 = require("../utils/common");
14
14
  const getInitialAssets_1 = require("../utils/getInitialAssets");
15
15
  const htmlEntry_1 = require("../utils/htmlEntry");
16
16
  const normalize_path_1 = require("../utils/normalize-path");
17
+ const runtimePluginStratety_1 = require("../utils/runtimePluginStratety");
17
18
  const validateEntry_1 = require("../utils/validateEntry");
18
19
  const project_1 = require("./project");
19
20
  const wsServer = new ws_1.WebSocketServer({ noServer: true });
@@ -23,7 +24,7 @@ var pack_shared_2 = require("@utoo/pack-shared");
23
24
  Object.defineProperty(exports, "HMR_ACTIONS_SENT_TO_BROWSER", { enumerable: true, get: function () { return pack_shared_2.HMR_ACTIONS_SENT_TO_BROWSER; } });
24
25
  exports.FAST_REFRESH_RUNTIME_RELOAD = "Fast Refresh had to perform a full reload due to a runtime error.";
25
26
  async function createHotReloader(bundleOptions, projectPath, rootPath) {
26
- var _a, _b;
27
+ var _a, _b, _c, _d;
27
28
  const resolvedProjectPath = projectPath || process.cwd();
28
29
  (0, htmlEntry_1.processHtmlEntry)(bundleOptions.config, resolvedProjectPath);
29
30
  (0, validateEntry_1.validateEntryPaths)(bundleOptions.config, resolvedProjectPath);
@@ -46,12 +47,13 @@ async function createHotReloader(bundleOptions, projectPath, rootPath) {
46
47
  minify: false,
47
48
  moduleIds: "named",
48
49
  },
50
+ pluginRuntimeStrategy: (_c = (_b = bundleOptions === null || bundleOptions === void 0 ? void 0 : bundleOptions.config) === null || _b === void 0 ? void 0 : _b.pluginRuntimeStrategy) !== null && _c !== void 0 ? _c : ((0, runtimePluginStratety_1.useWorkerThreads)() ? "workerThreads" : "childProcesses"),
49
51
  },
50
52
  projectPath: (0, normalize_path_1.normalizePath)(resolvedProjectPath),
51
53
  rootPath: rootPath || projectPath || process.cwd(),
52
54
  packPath: (0, common_1.getPackPath)(),
53
55
  }, {
54
- persistentCaching: (_b = bundleOptions.config.persistentCaching) !== null && _b !== void 0 ? _b : false,
56
+ persistentCaching: (_d = bundleOptions.config.persistentCaching) !== null && _d !== void 0 ? _d : false,
55
57
  });
56
58
  const entrypointsSubscription = project.entrypointsSubscribe();
57
59
  let currentEntriesHandlingResolve;
@@ -0,0 +1 @@
1
+ export declare function useWorkerThreads(): boolean;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.useWorkerThreads = useWorkerThreads;
7
+ const semver_1 = __importDefault(require("semver"));
8
+ function useWorkerThreads() {
9
+ const WORKER_THREADS_SAFE_RANGE = ">=24.13.1 <25.0.0 || >=25.4.0";
10
+ return semver_1.default.satisfies(process.version, WORKER_THREADS_SAFE_RANGE, {
11
+ includePrerelease: true,
12
+ });
13
+ }
@@ -11,6 +11,7 @@ import { findRootDir } from "../utils/findRoot.js";
11
11
  import { getInitialAssetsFromStats } from "../utils/getInitialAssets.js";
12
12
  import { processHtmlEntry } from "../utils/htmlEntry.js";
13
13
  import { normalizePath } from "../utils/normalize-path.js";
14
+ import { useWorkerThreads } from "../utils/runtimePluginStratety.js";
14
15
  import { validateEntryPaths } from "../utils/validateEntry.js";
15
16
  import { xcodeProfilingReady } from "../utils/xcodeProfile.js";
16
17
  export function build(options, projectPath, rootPath) {
@@ -22,7 +23,7 @@ export function build(options, projectPath, rootPath) {
22
23
  return buildInternal(bundleOptions, projectPath, rootPath);
23
24
  }
24
25
  async function buildInternal(bundleOptions, projectPath, rootPath) {
25
- var _a, _b, _c, _d, _e, _f;
26
+ var _a, _b, _c, _d, _e, _f, _g, _h;
26
27
  blockStdout();
27
28
  if (process.env.XCODE_PROFILE) {
28
29
  await xcodeProfilingReady();
@@ -43,12 +44,13 @@ async function buildInternal(bundleOptions, projectPath, rootPath) {
43
44
  stats: Boolean(process.env.ANALYZE) ||
44
45
  bundleOptions.config.stats ||
45
46
  bundleOptions.config.entry.some((e) => !!e.html),
47
+ pluginRuntimeStrategy: (_d = (_c = bundleOptions === null || bundleOptions === void 0 ? void 0 : bundleOptions.config) === null || _c === void 0 ? void 0 : _c.pluginRuntimeStrategy) !== null && _d !== void 0 ? _d : (useWorkerThreads() ? "workerThreads" : "childProcesses"),
46
48
  },
47
49
  projectPath: normalizePath(resolvedProjectPath),
48
50
  rootPath: rootPath || projectPath || process.cwd(),
49
51
  packPath: getPackPath(),
50
52
  }, {
51
- persistentCaching: (_c = bundleOptions.config.persistentCaching) !== null && _c !== void 0 ? _c : false,
53
+ persistentCaching: (_e = bundleOptions.config.persistentCaching) !== null && _e !== void 0 ? _e : false,
52
54
  });
53
55
  const entrypoints = await project.writeAllEntrypointsToDisk();
54
56
  handleIssues(entrypoints.issues);
@@ -64,20 +66,20 @@ async function buildInternal(bundleOptions, projectPath, rootPath) {
64
66
  ];
65
67
  if (htmlConfigs.length > 0) {
66
68
  const assets = { js: [], css: [] };
67
- const outputDir = ((_d = bundleOptions.config.output) === null || _d === void 0 ? void 0 : _d.path) || path.join(process.cwd(), "dist");
69
+ const outputDir = ((_f = bundleOptions.config.output) === null || _f === void 0 ? void 0 : _f.path) || path.join(process.cwd(), "dist");
68
70
  if (assets.js.length === 0 && assets.css.length === 0) {
69
71
  const discovered = getInitialAssetsFromStats(outputDir);
70
72
  assets.js.push(...discovered.js);
71
73
  assets.css.push(...discovered.css);
72
74
  }
73
- const publicPath = (_e = bundleOptions.config.output) === null || _e === void 0 ? void 0 : _e.publicPath;
75
+ const publicPath = (_g = bundleOptions.config.output) === null || _g === void 0 ? void 0 : _g.publicPath;
74
76
  for (const config of htmlConfigs) {
75
77
  const plugin = new HtmlPlugin(config);
76
78
  await plugin.generate(outputDir, assets, publicPath);
77
79
  }
78
80
  }
79
81
  if (process.env.ANALYZE) {
80
- await analyzeBundle(((_f = bundleOptions.config.output) === null || _f === void 0 ? void 0 : _f.path) || "dist");
82
+ await analyzeBundle(((_h = bundleOptions.config.output) === null || _h === void 0 ? void 0 : _h.path) || "dist");
81
83
  }
82
84
  await project.shutdown();
83
85
  // TODO: Maybe run tasks in worker is a better way, see
package/esm/core/hmr.js CHANGED
@@ -7,6 +7,7 @@ import { debounce, getPackPath, processIssues } from "../utils/common.js";
7
7
  import { getInitialAssetsFromStats } from "../utils/getInitialAssets.js";
8
8
  import { processHtmlEntry } from "../utils/htmlEntry.js";
9
9
  import { normalizePath } from "../utils/normalize-path.js";
10
+ import { useWorkerThreads } from "../utils/runtimePluginStratety.js";
10
11
  import { validateEntryPaths } from "../utils/validateEntry.js";
11
12
  import { projectFactory } from "./project.js";
12
13
  const wsServer = new WebSocketServer({ noServer: true });
@@ -15,7 +16,7 @@ const sessionId = Math.floor(Number.MAX_SAFE_INTEGER * Math.random());
15
16
  export { HMR_ACTIONS_SENT_TO_BROWSER, } from "@utoo/pack-shared";
16
17
  export const FAST_REFRESH_RUNTIME_RELOAD = "Fast Refresh had to perform a full reload due to a runtime error.";
17
18
  export async function createHotReloader(bundleOptions, projectPath, rootPath) {
18
- var _a, _b;
19
+ var _a, _b, _c, _d;
19
20
  const resolvedProjectPath = projectPath || process.cwd();
20
21
  processHtmlEntry(bundleOptions.config, resolvedProjectPath);
21
22
  validateEntryPaths(bundleOptions.config, resolvedProjectPath);
@@ -38,12 +39,13 @@ export async function createHotReloader(bundleOptions, projectPath, rootPath) {
38
39
  minify: false,
39
40
  moduleIds: "named",
40
41
  },
42
+ pluginRuntimeStrategy: (_c = (_b = bundleOptions === null || bundleOptions === void 0 ? void 0 : bundleOptions.config) === null || _b === void 0 ? void 0 : _b.pluginRuntimeStrategy) !== null && _c !== void 0 ? _c : (useWorkerThreads() ? "workerThreads" : "childProcesses"),
41
43
  },
42
44
  projectPath: normalizePath(resolvedProjectPath),
43
45
  rootPath: rootPath || projectPath || process.cwd(),
44
46
  packPath: getPackPath(),
45
47
  }, {
46
- persistentCaching: (_b = bundleOptions.config.persistentCaching) !== null && _b !== void 0 ? _b : false,
48
+ persistentCaching: (_d = bundleOptions.config.persistentCaching) !== null && _d !== void 0 ? _d : false,
47
49
  });
48
50
  const entrypointsSubscription = project.entrypointsSubscribe();
49
51
  let currentEntriesHandlingResolve;
@@ -0,0 +1 @@
1
+ export declare function useWorkerThreads(): boolean;
@@ -0,0 +1,7 @@
1
+ import semver from "semver";
2
+ export function useWorkerThreads() {
3
+ const WORKER_THREADS_SAFE_RANGE = ">=24.13.1 <25.0.0 || >=25.4.0";
4
+ return semver.satisfies(process.version, WORKER_THREADS_SAFE_RANGE, {
5
+ includePrerelease: true,
6
+ });
7
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@utoo/pack",
3
- "version": "1.3.2",
3
+ "version": "1.3.3-alpha.0",
4
4
  "main": "cjs/index.js",
5
5
  "module": "esm/index.js",
6
6
  "types": "esm/index.d.ts",
@@ -41,13 +41,14 @@
41
41
  "@hono/node-server": "^1.19.11",
42
42
  "@hono/node-ws": "^1.3.0",
43
43
  "@swc/helpers": "0.5.15",
44
- "@utoo/pack-shared": "1.3.2",
44
+ "@utoo/pack-shared": "1.3.3-alpha.0",
45
45
  "domparser-rs": "^0.0.7",
46
46
  "find-up": "4.1.0",
47
47
  "get-port": "^7.1.0",
48
48
  "hono": "^4.12.5",
49
49
  "nanoid": "^3.3.11",
50
50
  "picocolors": "^1.1.1",
51
+ "semver": "^7.7.1",
51
52
  "send": "0.17.1",
52
53
  "ws": "^8.18.1"
53
54
  },
@@ -57,7 +58,8 @@
57
58
  "postcss": "8.4.31",
58
59
  "resolve-url-loader": "^5.0.0",
59
60
  "sass": "1.54.0",
60
- "sass-loader": "^13.2.0"
61
+ "sass-loader": "^13.2.0",
62
+ "styled-jsx": "^5.1.6"
61
63
  },
62
64
  "devDependencies": {
63
65
  "@napi-rs/cli": "^2.18.0",
@@ -65,9 +67,9 @@
65
67
  "@types/mime": "^3.0.4",
66
68
  "@types/mime-types": "3.0.1",
67
69
  "@types/node": "^20.3.0",
70
+ "@types/semver": "^7.7.1",
68
71
  "@types/send": "0.14.4",
69
72
  "@types/ws": "^8.18.1",
70
- "styled-jsx": "^5.1.6",
71
73
  "typescript": "^5.8.3"
72
74
  },
73
75
  "engines": {
@@ -89,12 +91,12 @@
89
91
  },
90
92
  "repository": "git@github.com:utooland/utoo.git",
91
93
  "optionalDependencies": {
92
- "@utoo/pack-darwin-arm64": "1.3.2",
93
- "@utoo/pack-darwin-x64": "1.3.2",
94
- "@utoo/pack-linux-arm64-gnu": "1.3.2",
95
- "@utoo/pack-linux-arm64-musl": "1.3.2",
96
- "@utoo/pack-linux-x64-gnu": "1.3.2",
97
- "@utoo/pack-linux-x64-musl": "1.3.2",
98
- "@utoo/pack-win32-x64-msvc": "1.3.2"
94
+ "@utoo/pack-darwin-arm64": "1.3.3-alpha.0",
95
+ "@utoo/pack-darwin-x64": "1.3.3-alpha.0",
96
+ "@utoo/pack-linux-arm64-gnu": "1.3.3-alpha.0",
97
+ "@utoo/pack-linux-arm64-musl": "1.3.3-alpha.0",
98
+ "@utoo/pack-linux-x64-gnu": "1.3.3-alpha.0",
99
+ "@utoo/pack-linux-x64-musl": "1.3.3-alpha.0",
100
+ "@utoo/pack-win32-x64-msvc": "1.3.3-alpha.0"
99
101
  }
100
102
  }
@@ -1,44 +0,0 @@
1
- import { IncomingMessage, ServerResponse } from "http";
2
- import send from "send";
3
- import { Duplex, Writable } from "stream";
4
- import { BundleOptions } from "../config/types";
5
- import { WebpackConfig } from "../config/webpackCompat";
6
- export declare function serve(options: BundleOptions | WebpackConfig, projectPath?: string, rootPath?: string, serverOptions?: StartServerOptions): Promise<void>;
7
- export interface SelfSignedCertificate {
8
- key: string;
9
- cert: string;
10
- rootCA?: string;
11
- }
12
- export interface StartServerOptions {
13
- port: number;
14
- https?: boolean;
15
- hostname?: string;
16
- logServerInfo?: boolean;
17
- selfSignedCertificate?: SelfSignedCertificate;
18
- }
19
- export type RequestHandler = (req: IncomingMessage, res: ServerResponse) => Promise<void>;
20
- export type UpgradeHandler = (req: IncomingMessage, socket: Duplex, head: Buffer) => Promise<void>;
21
- export type ServerInitResult = {
22
- requestHandler: RequestHandler;
23
- upgradeHandler: UpgradeHandler;
24
- closeUpgraded: () => void;
25
- };
26
- export declare function startServer(serverOptions: StartServerOptions, bundleOptions: BundleOptions, projectPath: string, rootPath?: string): Promise<void>;
27
- export declare function initialize(bundleOptions: BundleOptions, projectPath: string, rootPath?: string): Promise<ServerInitResult>;
28
- export declare function pipeToNodeResponse(readable: ReadableStream<Uint8Array>, res: ServerResponse, waitUntilForEnd?: Promise<unknown>): Promise<void>;
29
- export declare function createAbortController(response: Writable): AbortController;
30
- export declare function isAbortError(e: any): e is Error & {
31
- name: "AbortError";
32
- };
33
- export declare const ResponseAbortedName = "ResponseAborted";
34
- export declare class ResponseAborted extends Error {
35
- readonly name = "ResponseAborted";
36
- }
37
- export declare class DetachedPromise<T = any> {
38
- readonly resolve: (value: T | PromiseLike<T>) => void;
39
- readonly reject: (reason: any) => void;
40
- readonly promise: Promise<T>;
41
- constructor();
42
- }
43
- export declare function serveStatic(req: IncomingMessage, res: ServerResponse, path: string, opts?: Parameters<typeof send>[2]): Promise<void>;
44
- export declare function formatHostname(hostname: string): string;
@@ -1,458 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.DetachedPromise = exports.ResponseAborted = exports.ResponseAbortedName = void 0;
7
- exports.serve = serve;
8
- exports.startServer = startServer;
9
- exports.initialize = initialize;
10
- exports.pipeToNodeResponse = pipeToNodeResponse;
11
- exports.createAbortController = createAbortController;
12
- exports.isAbortError = isAbortError;
13
- exports.serveStatic = serveStatic;
14
- exports.formatHostname = formatHostname;
15
- const fs_1 = __importDefault(require("fs"));
16
- const http_1 = __importDefault(require("http"));
17
- const https_1 = __importDefault(require("https"));
18
- const net_1 = require("net");
19
- const path_1 = __importDefault(require("path"));
20
- const send_1 = __importDefault(require("send"));
21
- const url_1 = __importDefault(require("url"));
22
- const webpackCompat_1 = require("../config/webpackCompat");
23
- const hmr_1 = require("../core/hmr");
24
- const common_1 = require("../utils/common");
25
- const findRoot_1 = require("../utils/findRoot");
26
- const mkcert_1 = require("../utils/mkcert");
27
- const printServerInfo_1 = require("../utils/printServerInfo");
28
- const xcodeProfile_1 = require("../utils/xcodeProfile");
29
- function parsePath(pathStr) {
30
- const hashIndex = pathStr.indexOf("#");
31
- const queryIndex = pathStr.indexOf("?");
32
- const hasQuery = queryIndex > -1 && (hashIndex < 0 || queryIndex < hashIndex);
33
- if (hasQuery || hashIndex > -1) {
34
- return {
35
- pathname: pathStr.substring(0, hasQuery ? queryIndex : hashIndex),
36
- query: hasQuery
37
- ? pathStr.substring(queryIndex, hashIndex > -1 ? hashIndex : undefined)
38
- : "",
39
- hash: hashIndex > -1 ? pathStr.slice(hashIndex) : "",
40
- };
41
- }
42
- return { pathname: pathStr, query: "", hash: "" };
43
- }
44
- function pathHasPrefix(pathStr, prefix) {
45
- if (typeof pathStr !== "string") {
46
- return false;
47
- }
48
- const { pathname } = parsePath(pathStr);
49
- return pathname === prefix || pathname.startsWith(prefix + "/");
50
- }
51
- function removePathPrefix(pathStr, prefix) {
52
- // If the path doesn't start with the prefix we can return it as is.
53
- if (!pathHasPrefix(pathStr, prefix)) {
54
- return pathStr;
55
- }
56
- // Remove the prefix from the path via slicing.
57
- const withoutPrefix = pathStr.slice(prefix.length);
58
- // If the path without the prefix starts with a `/` we can return it as is.
59
- if (withoutPrefix.startsWith("/")) {
60
- return withoutPrefix;
61
- }
62
- // If the path without the prefix doesn't start with a `/` we need to add it
63
- // back to the path to make sure it's a valid path.
64
- return `/${withoutPrefix}`;
65
- }
66
- function normalizedPublicPath(publicPath) {
67
- const escapedPublicPath = (publicPath === null || publicPath === void 0 ? void 0 : publicPath.replace(/^\/+|\/+$/g, "")) || false;
68
- if (!escapedPublicPath) {
69
- return "";
70
- }
71
- try {
72
- if (URL.canParse(escapedPublicPath)) {
73
- const url = new URL(escapedPublicPath).toString();
74
- return url.endsWith("/") ? url.slice(0, -1) : url;
75
- }
76
- }
77
- catch (_a) { }
78
- return `/${escapedPublicPath}`;
79
- }
80
- function serve(options, projectPath, rootPath, serverOptions) {
81
- const bundleOptions = (0, webpackCompat_1.resolveBundleOptions)(options, projectPath, rootPath);
82
- if (!rootPath) {
83
- rootPath = (0, findRoot_1.findRootDir)(projectPath || process.cwd());
84
- }
85
- return serveInternal(bundleOptions, projectPath, rootPath, serverOptions);
86
- }
87
- async function serveInternal(options, projectPath, rootPath, serverOptions) {
88
- var _a;
89
- (0, common_1.blockStdout)();
90
- if (process.env.XCODE_PROFILE) {
91
- await (0, xcodeProfile_1.xcodeProfilingReady)();
92
- }
93
- // FIXME: fix any type
94
- const cfgDevServer = (((_a = options.config) === null || _a === void 0 ? void 0 : _a.devServer) || {});
95
- const serverOpts = {
96
- hostname: (serverOptions === null || serverOptions === void 0 ? void 0 : serverOptions.hostname) || cfgDevServer.host || "localhost",
97
- port: typeof (serverOptions === null || serverOptions === void 0 ? void 0 : serverOptions.port) !== "undefined"
98
- ? serverOptions.port
99
- : cfgDevServer.port || 3000,
100
- https: typeof (serverOptions === null || serverOptions === void 0 ? void 0 : serverOptions.https) !== "undefined"
101
- ? serverOptions.https
102
- : cfgDevServer.https,
103
- logServerInfo: serverOptions === null || serverOptions === void 0 ? void 0 : serverOptions.logServerInfo,
104
- selfSignedCertificate: serverOptions === null || serverOptions === void 0 ? void 0 : serverOptions.selfSignedCertificate,
105
- };
106
- // If HTTPS is requested and no certificate provided, attempt to generate one.
107
- if (serverOpts.https && !serverOpts.selfSignedCertificate) {
108
- try {
109
- // createSelfSignedCertificate may return undefined on failure
110
- const cert = await (0, mkcert_1.createSelfSignedCertificate)(serverOpts.hostname);
111
- if (cert)
112
- serverOpts.selfSignedCertificate = cert;
113
- }
114
- catch (e) {
115
- // ignore and fall back to http if certificate generation fails
116
- }
117
- }
118
- await startServer(serverOpts, {
119
- ...options,
120
- config: {
121
- ...options.config,
122
- devServer: {
123
- hot: true,
124
- ...(options.config.devServer || {}),
125
- },
126
- },
127
- packPath: (0, common_1.getPackPath)(),
128
- }, projectPath || process.cwd(), rootPath);
129
- }
130
- async function startServer(serverOptions, bundleOptions, projectPath, rootPath) {
131
- let { port, hostname, selfSignedCertificate } = serverOptions;
132
- process.title = "utoopack-dev-server";
133
- let handlersReady = () => { };
134
- let handlersError = () => { };
135
- let handlersPromise = new Promise((resolve, reject) => {
136
- handlersReady = resolve;
137
- handlersError = reject;
138
- });
139
- let requestHandler = async (req, res) => {
140
- if (handlersPromise) {
141
- await handlersPromise;
142
- return requestHandler(req, res);
143
- }
144
- throw new Error("Invariant request handler was not setup");
145
- };
146
- let upgradeHandler = async (req, socket, head) => {
147
- if (handlersPromise) {
148
- await handlersPromise;
149
- return upgradeHandler(req, socket, head);
150
- }
151
- throw new Error("Invariant upgrade handler was not setup");
152
- };
153
- async function requestListener(req, res) {
154
- try {
155
- if (handlersPromise) {
156
- await handlersPromise;
157
- handlersPromise = undefined;
158
- }
159
- await requestHandler(req, res);
160
- }
161
- catch (err) {
162
- res.statusCode = 500;
163
- res.end("Internal Server Error");
164
- console.error(`Failed to handle request for ${req.url}`);
165
- console.error(err);
166
- }
167
- }
168
- const server = selfSignedCertificate
169
- ? https_1.default.createServer({
170
- key: fs_1.default.readFileSync(selfSignedCertificate.key),
171
- cert: fs_1.default.readFileSync(selfSignedCertificate.cert),
172
- }, requestListener)
173
- : http_1.default.createServer(requestListener);
174
- server.on("upgrade", async (req, socket, head) => {
175
- try {
176
- await upgradeHandler(req, socket, head);
177
- }
178
- catch (err) {
179
- socket.destroy();
180
- console.error(`Failed to handle request for ${req.url}`);
181
- console.error(err);
182
- }
183
- });
184
- let portRetryCount = 0;
185
- const originalPort = port;
186
- server.on("error", (err) => {
187
- if (port && err.code === "EADDRINUSE" && portRetryCount < 10) {
188
- port += 1;
189
- portRetryCount += 1;
190
- server.listen(port, hostname);
191
- }
192
- else {
193
- console.error(`Failed to start server`);
194
- console.error(err);
195
- process.exit(1);
196
- }
197
- });
198
- await new Promise((resolve) => {
199
- server.on("listening", async () => {
200
- const addr = server.address();
201
- const actualHostname = formatHostname(typeof addr === "object"
202
- ? (addr === null || addr === void 0 ? void 0 : addr.address) || hostname || "localhost"
203
- : addr);
204
- const formattedHostname = !hostname || actualHostname === "0.0.0.0"
205
- ? "localhost"
206
- : actualHostname === "[::]"
207
- ? "[::1]"
208
- : formatHostname(hostname);
209
- port = typeof addr === "object" ? (addr === null || addr === void 0 ? void 0 : addr.port) || port : port;
210
- if (portRetryCount) {
211
- console.warn(`Port ${originalPort} is in use, using available port ${port} instead.`);
212
- }
213
- if (serverOptions.logServerInfo !== false) {
214
- (0, printServerInfo_1.printServerInfo)(serverOptions.https ? "https" : "http", formattedHostname, port);
215
- }
216
- try {
217
- let cleanupStarted = false;
218
- let closeUpgraded = null;
219
- const cleanup = () => {
220
- if (cleanupStarted) {
221
- return;
222
- }
223
- cleanupStarted = true;
224
- (async () => {
225
- console.debug("start-server process cleanup");
226
- await new Promise((res) => {
227
- server.close((err) => {
228
- if (err)
229
- console.error(err);
230
- res();
231
- });
232
- server.closeAllConnections();
233
- closeUpgraded === null || closeUpgraded === void 0 ? void 0 : closeUpgraded();
234
- });
235
- console.debug("start-server process cleanup finished");
236
- process.exit(0);
237
- })();
238
- };
239
- const exception = (err) => {
240
- console.error(err);
241
- };
242
- process.on("SIGINT", cleanup);
243
- process.on("SIGTERM", cleanup);
244
- process.on("rejectionHandled", () => { });
245
- process.on("uncaughtException", exception);
246
- process.on("unhandledRejection", exception);
247
- const initResult = await initialize(bundleOptions, projectPath, rootPath);
248
- requestHandler = initResult.requestHandler;
249
- upgradeHandler = initResult.upgradeHandler;
250
- closeUpgraded = initResult.closeUpgraded;
251
- handlersReady();
252
- }
253
- catch (err) {
254
- handlersError();
255
- console.error(err);
256
- process.exit(1);
257
- }
258
- resolve();
259
- });
260
- server.listen(port, hostname);
261
- });
262
- }
263
- async function initialize(bundleOptions, projectPath, rootPath) {
264
- process.env.NODE_ENV = "development";
265
- const hotReloader = await (0, hmr_1.createHotReloader)(bundleOptions, projectPath, rootPath);
266
- await hotReloader.start();
267
- const requestHandlerImpl = async (req, res) => {
268
- req.on("error", console.error);
269
- res.on("error", console.error);
270
- const handleRequest = async () => {
271
- var _a, _b;
272
- if (!(req.method === "GET" || req.method === "HEAD")) {
273
- res.setHeader("Allow", ["GET", "HEAD"]);
274
- res.statusCode = 405;
275
- res.end();
276
- }
277
- const distRoot = path_1.default.resolve(projectPath, ((_a = bundleOptions.config.output) === null || _a === void 0 ? void 0 : _a.path) || "./dist");
278
- const publicPath = (_b = bundleOptions.config.output) === null || _b === void 0 ? void 0 : _b.publicPath;
279
- try {
280
- const reqUrl = req.url || "";
281
- let requestPath = url_1.default.parse(reqUrl).pathname || "";
282
- if (publicPath && publicPath !== "runtime") {
283
- const normalizedPrefix = normalizedPublicPath(publicPath);
284
- const isAbsoluteUrl = normalizedPrefix.startsWith("http://") ||
285
- normalizedPrefix.startsWith("https://");
286
- if (!isAbsoluteUrl && normalizedPrefix) {
287
- if (pathHasPrefix(requestPath, normalizedPrefix)) {
288
- requestPath = removePathPrefix(requestPath, normalizedPrefix);
289
- }
290
- }
291
- }
292
- return await serveStatic(req, res, requestPath, { root: distRoot });
293
- }
294
- catch (err) {
295
- res.setHeader("Cache-Control", "private, no-cache, no-store, max-age=0, must-revalidate");
296
- res.statusCode = 404;
297
- res.end();
298
- }
299
- };
300
- try {
301
- await handleRequest();
302
- }
303
- catch (err) {
304
- res.statusCode = 500;
305
- res.end("Internal Server Error");
306
- }
307
- };
308
- let requestHandler = requestHandlerImpl;
309
- const logError = async (type, err) => {
310
- if (type === "unhandledRejection") {
311
- console.error("unhandledRejection: ", err);
312
- }
313
- else if (type === "uncaughtException") {
314
- console.error("uncaughtException: ", err);
315
- }
316
- };
317
- process.on("uncaughtException", logError.bind(null, "uncaughtException"));
318
- process.on("unhandledRejection", logError.bind(null, "unhandledRejection"));
319
- const upgradeHandler = async (req, socket, head) => {
320
- var _a;
321
- try {
322
- const isHMRRequest = (_a = req.url) === null || _a === void 0 ? void 0 : _a.includes("turbopack-hmr");
323
- if (isHMRRequest) {
324
- hotReloader.onHMR(req, socket, head);
325
- }
326
- else {
327
- socket.end();
328
- }
329
- }
330
- catch (err) {
331
- console.error("Error handling upgrade request", err);
332
- socket.end();
333
- }
334
- };
335
- return {
336
- requestHandler,
337
- upgradeHandler,
338
- closeUpgraded() {
339
- hotReloader.close();
340
- },
341
- };
342
- }
343
- async function pipeToNodeResponse(readable, res, waitUntilForEnd) {
344
- try {
345
- const { errored, destroyed } = res;
346
- if (errored || destroyed)
347
- return;
348
- const controller = createAbortController(res);
349
- const writer = createWriterFromResponse(res, waitUntilForEnd);
350
- await readable.pipeTo(writer, { signal: controller.signal });
351
- }
352
- catch (err) {
353
- if (isAbortError(err))
354
- return;
355
- throw new Error("failed to pipe response", { cause: err });
356
- }
357
- }
358
- function createAbortController(response) {
359
- const controller = new AbortController();
360
- response.once("close", () => {
361
- if (response.writableFinished)
362
- return;
363
- controller.abort(new ResponseAborted());
364
- });
365
- return controller;
366
- }
367
- function isAbortError(e) {
368
- return (e === null || e === void 0 ? void 0 : e.name) === "AbortError" || (e === null || e === void 0 ? void 0 : e.name) === exports.ResponseAbortedName;
369
- }
370
- exports.ResponseAbortedName = "ResponseAborted";
371
- class ResponseAborted extends Error {
372
- constructor() {
373
- super(...arguments);
374
- this.name = exports.ResponseAbortedName;
375
- }
376
- }
377
- exports.ResponseAborted = ResponseAborted;
378
- function createWriterFromResponse(res, waitUntilForEnd) {
379
- let started = false;
380
- let drained = new DetachedPromise();
381
- function onDrain() {
382
- drained.resolve();
383
- }
384
- res.on("drain", onDrain);
385
- res.once("close", () => {
386
- res.off("drain", onDrain);
387
- drained.resolve();
388
- });
389
- const finished = new DetachedPromise();
390
- res.once("finish", () => {
391
- finished.resolve();
392
- });
393
- return new WritableStream({
394
- write: async (chunk) => {
395
- if (!started) {
396
- started = true;
397
- res.flushHeaders();
398
- }
399
- try {
400
- const ok = res.write(chunk);
401
- if ("flush" in res && typeof res.flush === "function") {
402
- res.flush();
403
- }
404
- if (!ok) {
405
- await drained.promise;
406
- drained = new DetachedPromise();
407
- }
408
- }
409
- catch (err) {
410
- res.end();
411
- throw new Error("failed to write chunk to response", { cause: err });
412
- }
413
- },
414
- abort: (err) => {
415
- if (res.writableFinished)
416
- return;
417
- res.destroy(err);
418
- },
419
- close: async () => {
420
- if (waitUntilForEnd) {
421
- await waitUntilForEnd;
422
- }
423
- if (res.writableFinished)
424
- return;
425
- res.end();
426
- return finished.promise;
427
- },
428
- });
429
- }
430
- class DetachedPromise {
431
- constructor() {
432
- let resolve;
433
- let reject;
434
- this.promise = new Promise((res, rej) => {
435
- resolve = res;
436
- reject = rej;
437
- });
438
- this.resolve = resolve;
439
- this.reject = reject;
440
- }
441
- }
442
- exports.DetachedPromise = DetachedPromise;
443
- function serveStatic(req, res, path, opts) {
444
- return new Promise((resolve, reject) => {
445
- (0, send_1.default)(req, path, opts)
446
- .on("directory", () => {
447
- const err = new Error("No directory access");
448
- err.code = "ENOENT";
449
- reject(err);
450
- })
451
- .on("error", reject)
452
- .pipe(res)
453
- .on("finish", resolve);
454
- });
455
- }
456
- function formatHostname(hostname) {
457
- return (0, net_1.isIPv6)(hostname) ? `[${hostname}]` : hostname;
458
- }
@@ -1,44 +0,0 @@
1
- import { IncomingMessage, ServerResponse } from "http";
2
- import send from "send";
3
- import { Duplex, Writable } from "stream";
4
- import { BundleOptions } from "../config/types";
5
- import { WebpackConfig } from "../config/webpackCompat";
6
- export declare function serve(options: BundleOptions | WebpackConfig, projectPath?: string, rootPath?: string, serverOptions?: StartServerOptions): Promise<void>;
7
- export interface SelfSignedCertificate {
8
- key: string;
9
- cert: string;
10
- rootCA?: string;
11
- }
12
- export interface StartServerOptions {
13
- port: number;
14
- https?: boolean;
15
- hostname?: string;
16
- logServerInfo?: boolean;
17
- selfSignedCertificate?: SelfSignedCertificate;
18
- }
19
- export type RequestHandler = (req: IncomingMessage, res: ServerResponse) => Promise<void>;
20
- export type UpgradeHandler = (req: IncomingMessage, socket: Duplex, head: Buffer) => Promise<void>;
21
- export type ServerInitResult = {
22
- requestHandler: RequestHandler;
23
- upgradeHandler: UpgradeHandler;
24
- closeUpgraded: () => void;
25
- };
26
- export declare function startServer(serverOptions: StartServerOptions, bundleOptions: BundleOptions, projectPath: string, rootPath?: string): Promise<void>;
27
- export declare function initialize(bundleOptions: BundleOptions, projectPath: string, rootPath?: string): Promise<ServerInitResult>;
28
- export declare function pipeToNodeResponse(readable: ReadableStream<Uint8Array>, res: ServerResponse, waitUntilForEnd?: Promise<unknown>): Promise<void>;
29
- export declare function createAbortController(response: Writable): AbortController;
30
- export declare function isAbortError(e: any): e is Error & {
31
- name: "AbortError";
32
- };
33
- export declare const ResponseAbortedName = "ResponseAborted";
34
- export declare class ResponseAborted extends Error {
35
- readonly name = "ResponseAborted";
36
- }
37
- export declare class DetachedPromise<T = any> {
38
- readonly resolve: (value: T | PromiseLike<T>) => void;
39
- readonly reject: (reason: any) => void;
40
- readonly promise: Promise<T>;
41
- constructor();
42
- }
43
- export declare function serveStatic(req: IncomingMessage, res: ServerResponse, path: string, opts?: Parameters<typeof send>[2]): Promise<void>;
44
- export declare function formatHostname(hostname: string): string;
@@ -1,442 +0,0 @@
1
- import fs from "fs";
2
- import http from "http";
3
- import https from "https";
4
- import { isIPv6 } from "net";
5
- import path from "path";
6
- import send from "send";
7
- import url from "url";
8
- import { resolveBundleOptions } from "../config/webpackCompat.js";
9
- import { createHotReloader } from "../core/hmr.js";
10
- import { blockStdout, getPackPath } from "../utils/common.js";
11
- import { findRootDir } from "../utils/findRoot.js";
12
- import { createSelfSignedCertificate } from "../utils/mkcert.js";
13
- import { printServerInfo } from "../utils/printServerInfo.js";
14
- import { xcodeProfilingReady } from "../utils/xcodeProfile.js";
15
- function parsePath(pathStr) {
16
- const hashIndex = pathStr.indexOf("#");
17
- const queryIndex = pathStr.indexOf("?");
18
- const hasQuery = queryIndex > -1 && (hashIndex < 0 || queryIndex < hashIndex);
19
- if (hasQuery || hashIndex > -1) {
20
- return {
21
- pathname: pathStr.substring(0, hasQuery ? queryIndex : hashIndex),
22
- query: hasQuery
23
- ? pathStr.substring(queryIndex, hashIndex > -1 ? hashIndex : undefined)
24
- : "",
25
- hash: hashIndex > -1 ? pathStr.slice(hashIndex) : "",
26
- };
27
- }
28
- return { pathname: pathStr, query: "", hash: "" };
29
- }
30
- function pathHasPrefix(pathStr, prefix) {
31
- if (typeof pathStr !== "string") {
32
- return false;
33
- }
34
- const { pathname } = parsePath(pathStr);
35
- return pathname === prefix || pathname.startsWith(prefix + "/");
36
- }
37
- function removePathPrefix(pathStr, prefix) {
38
- // If the path doesn't start with the prefix we can return it as is.
39
- if (!pathHasPrefix(pathStr, prefix)) {
40
- return pathStr;
41
- }
42
- // Remove the prefix from the path via slicing.
43
- const withoutPrefix = pathStr.slice(prefix.length);
44
- // If the path without the prefix starts with a `/` we can return it as is.
45
- if (withoutPrefix.startsWith("/")) {
46
- return withoutPrefix;
47
- }
48
- // If the path without the prefix doesn't start with a `/` we need to add it
49
- // back to the path to make sure it's a valid path.
50
- return `/${withoutPrefix}`;
51
- }
52
- function normalizedPublicPath(publicPath) {
53
- const escapedPublicPath = (publicPath === null || publicPath === void 0 ? void 0 : publicPath.replace(/^\/+|\/+$/g, "")) || false;
54
- if (!escapedPublicPath) {
55
- return "";
56
- }
57
- try {
58
- if (URL.canParse(escapedPublicPath)) {
59
- const url = new URL(escapedPublicPath).toString();
60
- return url.endsWith("/") ? url.slice(0, -1) : url;
61
- }
62
- }
63
- catch (_a) { }
64
- return `/${escapedPublicPath}`;
65
- }
66
- export function serve(options, projectPath, rootPath, serverOptions) {
67
- const bundleOptions = resolveBundleOptions(options, projectPath, rootPath);
68
- if (!rootPath) {
69
- rootPath = findRootDir(projectPath || process.cwd());
70
- }
71
- return serveInternal(bundleOptions, projectPath, rootPath, serverOptions);
72
- }
73
- async function serveInternal(options, projectPath, rootPath, serverOptions) {
74
- var _a;
75
- blockStdout();
76
- if (process.env.XCODE_PROFILE) {
77
- await xcodeProfilingReady();
78
- }
79
- // FIXME: fix any type
80
- const cfgDevServer = (((_a = options.config) === null || _a === void 0 ? void 0 : _a.devServer) || {});
81
- const serverOpts = {
82
- hostname: (serverOptions === null || serverOptions === void 0 ? void 0 : serverOptions.hostname) || cfgDevServer.host || "localhost",
83
- port: typeof (serverOptions === null || serverOptions === void 0 ? void 0 : serverOptions.port) !== "undefined"
84
- ? serverOptions.port
85
- : cfgDevServer.port || 3000,
86
- https: typeof (serverOptions === null || serverOptions === void 0 ? void 0 : serverOptions.https) !== "undefined"
87
- ? serverOptions.https
88
- : cfgDevServer.https,
89
- logServerInfo: serverOptions === null || serverOptions === void 0 ? void 0 : serverOptions.logServerInfo,
90
- selfSignedCertificate: serverOptions === null || serverOptions === void 0 ? void 0 : serverOptions.selfSignedCertificate,
91
- };
92
- // If HTTPS is requested and no certificate provided, attempt to generate one.
93
- if (serverOpts.https && !serverOpts.selfSignedCertificate) {
94
- try {
95
- // createSelfSignedCertificate may return undefined on failure
96
- const cert = await createSelfSignedCertificate(serverOpts.hostname);
97
- if (cert)
98
- serverOpts.selfSignedCertificate = cert;
99
- }
100
- catch (e) {
101
- // ignore and fall back to http if certificate generation fails
102
- }
103
- }
104
- await startServer(serverOpts, {
105
- ...options,
106
- config: {
107
- ...options.config,
108
- devServer: {
109
- hot: true,
110
- ...(options.config.devServer || {}),
111
- },
112
- },
113
- packPath: getPackPath(),
114
- }, projectPath || process.cwd(), rootPath);
115
- }
116
- export async function startServer(serverOptions, bundleOptions, projectPath, rootPath) {
117
- let { port, hostname, selfSignedCertificate } = serverOptions;
118
- process.title = "utoopack-dev-server";
119
- let handlersReady = () => { };
120
- let handlersError = () => { };
121
- let handlersPromise = new Promise((resolve, reject) => {
122
- handlersReady = resolve;
123
- handlersError = reject;
124
- });
125
- let requestHandler = async (req, res) => {
126
- if (handlersPromise) {
127
- await handlersPromise;
128
- return requestHandler(req, res);
129
- }
130
- throw new Error("Invariant request handler was not setup");
131
- };
132
- let upgradeHandler = async (req, socket, head) => {
133
- if (handlersPromise) {
134
- await handlersPromise;
135
- return upgradeHandler(req, socket, head);
136
- }
137
- throw new Error("Invariant upgrade handler was not setup");
138
- };
139
- async function requestListener(req, res) {
140
- try {
141
- if (handlersPromise) {
142
- await handlersPromise;
143
- handlersPromise = undefined;
144
- }
145
- await requestHandler(req, res);
146
- }
147
- catch (err) {
148
- res.statusCode = 500;
149
- res.end("Internal Server Error");
150
- console.error(`Failed to handle request for ${req.url}`);
151
- console.error(err);
152
- }
153
- }
154
- const server = selfSignedCertificate
155
- ? https.createServer({
156
- key: fs.readFileSync(selfSignedCertificate.key),
157
- cert: fs.readFileSync(selfSignedCertificate.cert),
158
- }, requestListener)
159
- : http.createServer(requestListener);
160
- server.on("upgrade", async (req, socket, head) => {
161
- try {
162
- await upgradeHandler(req, socket, head);
163
- }
164
- catch (err) {
165
- socket.destroy();
166
- console.error(`Failed to handle request for ${req.url}`);
167
- console.error(err);
168
- }
169
- });
170
- let portRetryCount = 0;
171
- const originalPort = port;
172
- server.on("error", (err) => {
173
- if (port && err.code === "EADDRINUSE" && portRetryCount < 10) {
174
- port += 1;
175
- portRetryCount += 1;
176
- server.listen(port, hostname);
177
- }
178
- else {
179
- console.error(`Failed to start server`);
180
- console.error(err);
181
- process.exit(1);
182
- }
183
- });
184
- await new Promise((resolve) => {
185
- server.on("listening", async () => {
186
- const addr = server.address();
187
- const actualHostname = formatHostname(typeof addr === "object"
188
- ? (addr === null || addr === void 0 ? void 0 : addr.address) || hostname || "localhost"
189
- : addr);
190
- const formattedHostname = !hostname || actualHostname === "0.0.0.0"
191
- ? "localhost"
192
- : actualHostname === "[::]"
193
- ? "[::1]"
194
- : formatHostname(hostname);
195
- port = typeof addr === "object" ? (addr === null || addr === void 0 ? void 0 : addr.port) || port : port;
196
- if (portRetryCount) {
197
- console.warn(`Port ${originalPort} is in use, using available port ${port} instead.`);
198
- }
199
- if (serverOptions.logServerInfo !== false) {
200
- printServerInfo(serverOptions.https ? "https" : "http", formattedHostname, port);
201
- }
202
- try {
203
- let cleanupStarted = false;
204
- let closeUpgraded = null;
205
- const cleanup = () => {
206
- if (cleanupStarted) {
207
- return;
208
- }
209
- cleanupStarted = true;
210
- (async () => {
211
- console.debug("start-server process cleanup");
212
- await new Promise((res) => {
213
- server.close((err) => {
214
- if (err)
215
- console.error(err);
216
- res();
217
- });
218
- server.closeAllConnections();
219
- closeUpgraded === null || closeUpgraded === void 0 ? void 0 : closeUpgraded();
220
- });
221
- console.debug("start-server process cleanup finished");
222
- process.exit(0);
223
- })();
224
- };
225
- const exception = (err) => {
226
- console.error(err);
227
- };
228
- process.on("SIGINT", cleanup);
229
- process.on("SIGTERM", cleanup);
230
- process.on("rejectionHandled", () => { });
231
- process.on("uncaughtException", exception);
232
- process.on("unhandledRejection", exception);
233
- const initResult = await initialize(bundleOptions, projectPath, rootPath);
234
- requestHandler = initResult.requestHandler;
235
- upgradeHandler = initResult.upgradeHandler;
236
- closeUpgraded = initResult.closeUpgraded;
237
- handlersReady();
238
- }
239
- catch (err) {
240
- handlersError();
241
- console.error(err);
242
- process.exit(1);
243
- }
244
- resolve();
245
- });
246
- server.listen(port, hostname);
247
- });
248
- }
249
- export async function initialize(bundleOptions, projectPath, rootPath) {
250
- process.env.NODE_ENV = "development";
251
- const hotReloader = await createHotReloader(bundleOptions, projectPath, rootPath);
252
- await hotReloader.start();
253
- const requestHandlerImpl = async (req, res) => {
254
- req.on("error", console.error);
255
- res.on("error", console.error);
256
- const handleRequest = async () => {
257
- var _a, _b;
258
- if (!(req.method === "GET" || req.method === "HEAD")) {
259
- res.setHeader("Allow", ["GET", "HEAD"]);
260
- res.statusCode = 405;
261
- res.end();
262
- }
263
- const distRoot = path.resolve(projectPath, ((_a = bundleOptions.config.output) === null || _a === void 0 ? void 0 : _a.path) || "./dist");
264
- const publicPath = (_b = bundleOptions.config.output) === null || _b === void 0 ? void 0 : _b.publicPath;
265
- try {
266
- const reqUrl = req.url || "";
267
- let requestPath = url.parse(reqUrl).pathname || "";
268
- if (publicPath && publicPath !== "runtime") {
269
- const normalizedPrefix = normalizedPublicPath(publicPath);
270
- const isAbsoluteUrl = normalizedPrefix.startsWith("http://") ||
271
- normalizedPrefix.startsWith("https://");
272
- if (!isAbsoluteUrl && normalizedPrefix) {
273
- if (pathHasPrefix(requestPath, normalizedPrefix)) {
274
- requestPath = removePathPrefix(requestPath, normalizedPrefix);
275
- }
276
- }
277
- }
278
- return await serveStatic(req, res, requestPath, { root: distRoot });
279
- }
280
- catch (err) {
281
- res.setHeader("Cache-Control", "private, no-cache, no-store, max-age=0, must-revalidate");
282
- res.statusCode = 404;
283
- res.end();
284
- }
285
- };
286
- try {
287
- await handleRequest();
288
- }
289
- catch (err) {
290
- res.statusCode = 500;
291
- res.end("Internal Server Error");
292
- }
293
- };
294
- let requestHandler = requestHandlerImpl;
295
- const logError = async (type, err) => {
296
- if (type === "unhandledRejection") {
297
- console.error("unhandledRejection: ", err);
298
- }
299
- else if (type === "uncaughtException") {
300
- console.error("uncaughtException: ", err);
301
- }
302
- };
303
- process.on("uncaughtException", logError.bind(null, "uncaughtException"));
304
- process.on("unhandledRejection", logError.bind(null, "unhandledRejection"));
305
- const upgradeHandler = async (req, socket, head) => {
306
- var _a;
307
- try {
308
- const isHMRRequest = (_a = req.url) === null || _a === void 0 ? void 0 : _a.includes("turbopack-hmr");
309
- if (isHMRRequest) {
310
- hotReloader.onHMR(req, socket, head);
311
- }
312
- else {
313
- socket.end();
314
- }
315
- }
316
- catch (err) {
317
- console.error("Error handling upgrade request", err);
318
- socket.end();
319
- }
320
- };
321
- return {
322
- requestHandler,
323
- upgradeHandler,
324
- closeUpgraded() {
325
- hotReloader.close();
326
- },
327
- };
328
- }
329
- export async function pipeToNodeResponse(readable, res, waitUntilForEnd) {
330
- try {
331
- const { errored, destroyed } = res;
332
- if (errored || destroyed)
333
- return;
334
- const controller = createAbortController(res);
335
- const writer = createWriterFromResponse(res, waitUntilForEnd);
336
- await readable.pipeTo(writer, { signal: controller.signal });
337
- }
338
- catch (err) {
339
- if (isAbortError(err))
340
- return;
341
- throw new Error("failed to pipe response", { cause: err });
342
- }
343
- }
344
- export function createAbortController(response) {
345
- const controller = new AbortController();
346
- response.once("close", () => {
347
- if (response.writableFinished)
348
- return;
349
- controller.abort(new ResponseAborted());
350
- });
351
- return controller;
352
- }
353
- export function isAbortError(e) {
354
- return (e === null || e === void 0 ? void 0 : e.name) === "AbortError" || (e === null || e === void 0 ? void 0 : e.name) === ResponseAbortedName;
355
- }
356
- export const ResponseAbortedName = "ResponseAborted";
357
- export class ResponseAborted extends Error {
358
- constructor() {
359
- super(...arguments);
360
- this.name = ResponseAbortedName;
361
- }
362
- }
363
- function createWriterFromResponse(res, waitUntilForEnd) {
364
- let started = false;
365
- let drained = new DetachedPromise();
366
- function onDrain() {
367
- drained.resolve();
368
- }
369
- res.on("drain", onDrain);
370
- res.once("close", () => {
371
- res.off("drain", onDrain);
372
- drained.resolve();
373
- });
374
- const finished = new DetachedPromise();
375
- res.once("finish", () => {
376
- finished.resolve();
377
- });
378
- return new WritableStream({
379
- write: async (chunk) => {
380
- if (!started) {
381
- started = true;
382
- res.flushHeaders();
383
- }
384
- try {
385
- const ok = res.write(chunk);
386
- if ("flush" in res && typeof res.flush === "function") {
387
- res.flush();
388
- }
389
- if (!ok) {
390
- await drained.promise;
391
- drained = new DetachedPromise();
392
- }
393
- }
394
- catch (err) {
395
- res.end();
396
- throw new Error("failed to write chunk to response", { cause: err });
397
- }
398
- },
399
- abort: (err) => {
400
- if (res.writableFinished)
401
- return;
402
- res.destroy(err);
403
- },
404
- close: async () => {
405
- if (waitUntilForEnd) {
406
- await waitUntilForEnd;
407
- }
408
- if (res.writableFinished)
409
- return;
410
- res.end();
411
- return finished.promise;
412
- },
413
- });
414
- }
415
- export class DetachedPromise {
416
- constructor() {
417
- let resolve;
418
- let reject;
419
- this.promise = new Promise((res, rej) => {
420
- resolve = res;
421
- reject = rej;
422
- });
423
- this.resolve = resolve;
424
- this.reject = reject;
425
- }
426
- }
427
- export function serveStatic(req, res, path, opts) {
428
- return new Promise((resolve, reject) => {
429
- send(req, path, opts)
430
- .on("directory", () => {
431
- const err = new Error("No directory access");
432
- err.code = "ENOENT";
433
- reject(err);
434
- })
435
- .on("error", reject)
436
- .pipe(res)
437
- .on("finish", resolve);
438
- });
439
- }
440
- export function formatHostname(hostname) {
441
- return isIPv6(hostname) ? `[${hostname}]` : hostname;
442
- }