@utoo/pack 1.2.13 → 1.3.0-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.
- package/cjs/binding.d.ts +5 -31
- package/cjs/commands/build.js +6 -11
- package/cjs/commands/dev-legacy.d.ts +44 -0
- package/cjs/commands/dev-legacy.js +458 -0
- package/cjs/commands/dev.d.ts +6 -31
- package/cjs/commands/dev.js +142 -365
- package/cjs/core/hmr.d.ts +14 -0
- package/cjs/core/hmr.js +72 -7
- package/cjs/utils/common.d.ts +1 -1
- package/cjs/utils/common.js +1 -2
- package/esm/binding.d.ts +5 -31
- package/esm/commands/build.js +7 -12
- package/esm/commands/dev-legacy.d.ts +44 -0
- package/esm/commands/dev-legacy.js +442 -0
- package/esm/commands/dev.d.ts +6 -31
- package/esm/commands/dev.js +143 -356
- package/esm/core/hmr.d.ts +14 -0
- package/esm/core/hmr.js +73 -8
- package/esm/utils/common.d.ts +1 -1
- package/esm/utils/common.js +1 -1
- package/package.json +13 -9
package/cjs/commands/dev.js
CHANGED
|
@@ -1,24 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Dev server implementation using Hono + @hono/node-server + @hono/node-ws.
|
|
4
|
+
* Keeps the same public API as dev.ts; do not remove dev.ts until this is verified.
|
|
5
|
+
*/
|
|
2
6
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
7
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
8
|
};
|
|
5
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.DetachedPromise = exports.ResponseAborted = exports.ResponseAbortedName = void 0;
|
|
7
10
|
exports.serve = serve;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
exports.createAbortController = createAbortController;
|
|
12
|
-
exports.isAbortError = isAbortError;
|
|
13
|
-
exports.serveStatic = serveStatic;
|
|
14
|
-
exports.formatHostname = formatHostname;
|
|
11
|
+
const node_server_1 = require("@hono/node-server");
|
|
12
|
+
const serve_static_1 = require("@hono/node-server/serve-static");
|
|
13
|
+
const node_ws_1 = require("@hono/node-ws");
|
|
15
14
|
const fs_1 = __importDefault(require("fs"));
|
|
16
|
-
const
|
|
15
|
+
const get_port_1 = __importDefault(require("get-port"));
|
|
16
|
+
const hono_1 = require("hono");
|
|
17
17
|
const https_1 = __importDefault(require("https"));
|
|
18
|
-
const net_1 = require("net");
|
|
19
18
|
const path_1 = __importDefault(require("path"));
|
|
20
|
-
const send_1 = __importDefault(require("send"));
|
|
21
|
-
const url_1 = __importDefault(require("url"));
|
|
22
19
|
const webpackCompat_1 = require("../config/webpackCompat");
|
|
23
20
|
const hmr_1 = require("../core/hmr");
|
|
24
21
|
const common_1 = require("../utils/common");
|
|
@@ -26,6 +23,7 @@ const findRoot_1 = require("../utils/findRoot");
|
|
|
26
23
|
const mkcert_1 = require("../utils/mkcert");
|
|
27
24
|
const printServerInfo_1 = require("../utils/printServerInfo");
|
|
28
25
|
const xcodeProfile_1 = require("../utils/xcodeProfile");
|
|
26
|
+
// --- Path helpers (same logic as dev.ts, not exported) ---
|
|
29
27
|
function parsePath(pathStr) {
|
|
30
28
|
const hashIndex = pathStr.indexOf("#");
|
|
31
29
|
const queryIndex = pathStr.indexOf("?");
|
|
@@ -49,18 +47,13 @@ function pathHasPrefix(pathStr, prefix) {
|
|
|
49
47
|
return pathname === prefix || pathname.startsWith(prefix + "/");
|
|
50
48
|
}
|
|
51
49
|
function removePathPrefix(pathStr, prefix) {
|
|
52
|
-
// If the path doesn't start with the prefix we can return it as is.
|
|
53
50
|
if (!pathHasPrefix(pathStr, prefix)) {
|
|
54
51
|
return pathStr;
|
|
55
52
|
}
|
|
56
|
-
// Remove the prefix from the path via slicing.
|
|
57
53
|
const withoutPrefix = pathStr.slice(prefix.length);
|
|
58
|
-
// If the path without the prefix starts with a `/` we can return it as is.
|
|
59
54
|
if (withoutPrefix.startsWith("/")) {
|
|
60
55
|
return withoutPrefix;
|
|
61
56
|
}
|
|
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
57
|
return `/${withoutPrefix}`;
|
|
65
58
|
}
|
|
66
59
|
function normalizedPublicPath(publicPath) {
|
|
@@ -70,389 +63,173 @@ function normalizedPublicPath(publicPath) {
|
|
|
70
63
|
}
|
|
71
64
|
try {
|
|
72
65
|
if (URL.canParse(escapedPublicPath)) {
|
|
73
|
-
const
|
|
74
|
-
return
|
|
66
|
+
const u = new URL(escapedPublicPath).toString();
|
|
67
|
+
return u.endsWith("/") ? u.slice(0, -1) : u;
|
|
75
68
|
}
|
|
76
69
|
}
|
|
77
70
|
catch (_a) { }
|
|
78
71
|
return `/${escapedPublicPath}`;
|
|
79
72
|
}
|
|
80
|
-
function
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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) {
|
|
73
|
+
async function resolveDevConfig(options, projectPath, rootPath, serverOptions) {
|
|
74
|
+
var _a, _b, _d, _e, _f, _g;
|
|
75
|
+
const cfgDevServer = (_b = (_a = options.config) === null || _a === void 0 ? void 0 : _a.devServer) !== null && _b !== void 0 ? _b : {};
|
|
76
|
+
const port = typeof (serverOptions === null || serverOptions === void 0 ? void 0 : serverOptions.port) !== "undefined"
|
|
77
|
+
? serverOptions.port
|
|
78
|
+
: ((_d = cfgDevServer.port) !== null && _d !== void 0 ? _d : 3000);
|
|
79
|
+
const hostname = (_f = (_e = serverOptions === null || serverOptions === void 0 ? void 0 : serverOptions.hostname) !== null && _e !== void 0 ? _e : cfgDevServer.host) !== null && _f !== void 0 ? _f : "localhost";
|
|
80
|
+
const useHttps = typeof (serverOptions === null || serverOptions === void 0 ? void 0 : serverOptions.https) !== "undefined"
|
|
81
|
+
? serverOptions.https
|
|
82
|
+
: cfgDevServer.https;
|
|
83
|
+
let selfSignedCertificate = serverOptions === null || serverOptions === void 0 ? void 0 : serverOptions.selfSignedCertificate;
|
|
84
|
+
if (useHttps && !selfSignedCertificate) {
|
|
108
85
|
try {
|
|
109
|
-
|
|
110
|
-
const cert = await (0, mkcert_1.createSelfSignedCertificate)(serverOpts.hostname);
|
|
86
|
+
const cert = await (0, mkcert_1.createSelfSignedCertificate)(hostname);
|
|
111
87
|
if (cert)
|
|
112
|
-
|
|
88
|
+
selfSignedCertificate = cert;
|
|
113
89
|
}
|
|
114
|
-
catch (
|
|
115
|
-
//
|
|
90
|
+
catch (_h) {
|
|
91
|
+
// fall back to http
|
|
116
92
|
}
|
|
117
93
|
}
|
|
118
|
-
|
|
94
|
+
const bundleOptions = {
|
|
119
95
|
...options,
|
|
120
96
|
config: {
|
|
121
97
|
...options.config,
|
|
122
98
|
devServer: {
|
|
123
99
|
hot: true,
|
|
124
|
-
...(options.config.devServer || {}),
|
|
100
|
+
...(((_g = options.config) === null || _g === void 0 ? void 0 : _g.devServer) || {}),
|
|
125
101
|
},
|
|
126
102
|
},
|
|
127
103
|
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
104
|
};
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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
|
-
}
|
|
105
|
+
const projectPathResolved = projectPath || process.cwd();
|
|
106
|
+
const rootPathResolved = rootPath !== null && rootPath !== void 0 ? rootPath : projectPathResolved;
|
|
107
|
+
const actualPort = await (0, get_port_1.default)({ port, host: hostname });
|
|
108
|
+
if (actualPort !== port) {
|
|
109
|
+
console.warn(`Port ${port} is in use, using available port ${actualPort} instead.`);
|
|
167
110
|
}
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
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);
|
|
111
|
+
const serveOptsBase = {
|
|
112
|
+
port: actualPort,
|
|
113
|
+
hostname,
|
|
114
|
+
...(useHttps && selfSignedCertificate
|
|
115
|
+
? {
|
|
116
|
+
createServer: https_1.default.createServer,
|
|
117
|
+
serverOptions: {
|
|
118
|
+
key: fs_1.default.readFileSync(selfSignedCertificate.key),
|
|
119
|
+
cert: fs_1.default.readFileSync(selfSignedCertificate.cert),
|
|
120
|
+
},
|
|
257
121
|
}
|
|
258
|
-
|
|
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
|
-
}
|
|
122
|
+
: {}),
|
|
334
123
|
};
|
|
335
124
|
return {
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
},
|
|
125
|
+
bundleOptions,
|
|
126
|
+
projectPathResolved,
|
|
127
|
+
rootPathResolved,
|
|
128
|
+
serveOptsBase,
|
|
341
129
|
};
|
|
342
130
|
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
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;
|
|
131
|
+
// --- Entry ---
|
|
132
|
+
function serve(options, projectPath, rootPath, serverOptions) {
|
|
133
|
+
const bundleOptions = (0, webpackCompat_1.resolveBundleOptions)(options, projectPath, rootPath);
|
|
134
|
+
if (!rootPath) {
|
|
135
|
+
rootPath = (0, findRoot_1.findRootDir)(projectPath || process.cwd());
|
|
375
136
|
}
|
|
137
|
+
return runDev(bundleOptions, projectPath, rootPath, serverOptions);
|
|
376
138
|
}
|
|
377
|
-
|
|
378
|
-
function
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
139
|
+
const HMR_PATH = "/turbopack-hmr";
|
|
140
|
+
async function runDev(options, projectPath, rootPath, serverOptions) {
|
|
141
|
+
var _a, _b, _d, _e;
|
|
142
|
+
(0, common_1.blockStdout)();
|
|
143
|
+
process.title = "utoopack-dev-server";
|
|
144
|
+
if (process.env.XCODE_PROFILE) {
|
|
145
|
+
await (0, xcodeProfile_1.xcodeProfilingReady)();
|
|
383
146
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
const
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
147
|
+
process.env.NODE_ENV = "development";
|
|
148
|
+
const { bundleOptions, projectPathResolved, rootPathResolved, serveOptsBase, } = await resolveDevConfig(options, projectPath, rootPath, serverOptions);
|
|
149
|
+
const hotReloader = await (0, hmr_1.createHotReloader)(bundleOptions, projectPathResolved, rootPathResolved);
|
|
150
|
+
await hotReloader.start();
|
|
151
|
+
const distRoot = path_1.default.resolve(projectPathResolved, ((_b = (_a = options.config) === null || _a === void 0 ? void 0 : _a.output) === null || _b === void 0 ? void 0 : _b.path) || "./dist");
|
|
152
|
+
const publicPath = (_e = (_d = options.config) === null || _d === void 0 ? void 0 : _d.output) === null || _e === void 0 ? void 0 : _e.publicPath;
|
|
153
|
+
// Skip prefix stripping for "runtime" and when publicPath is absent (match dev.ts).
|
|
154
|
+
const normalizedPrefix = publicPath && publicPath !== "runtime"
|
|
155
|
+
? normalizedPublicPath(publicPath)
|
|
156
|
+
: "";
|
|
157
|
+
const app = new hono_1.Hono();
|
|
158
|
+
const { injectWebSocket, upgradeWebSocket } = (0, node_ws_1.createNodeWebSocket)({ app });
|
|
159
|
+
const rewriteRequestPath = (reqPath) => {
|
|
160
|
+
if (!normalizedPrefix)
|
|
161
|
+
return reqPath;
|
|
162
|
+
// Absolute-URL publicPath: do not rewrite (match dev.ts).
|
|
163
|
+
if (normalizedPrefix.startsWith("http://") ||
|
|
164
|
+
normalizedPrefix.startsWith("https://")) {
|
|
165
|
+
return reqPath;
|
|
166
|
+
}
|
|
167
|
+
if (pathHasPrefix(reqPath, normalizedPrefix)) {
|
|
168
|
+
return removePathPrefix(reqPath, normalizedPrefix);
|
|
169
|
+
}
|
|
170
|
+
return reqPath;
|
|
171
|
+
};
|
|
172
|
+
// HMR WebSocket route must be registered before "/*" so it is not handled by serveStatic
|
|
173
|
+
app.get(HMR_PATH, upgradeWebSocket((_c) => ({
|
|
174
|
+
onOpen(_ev, ws) {
|
|
175
|
+
hotReloader.registerClient(ws);
|
|
176
|
+
},
|
|
177
|
+
onMessage(ev, ws) {
|
|
399
178
|
try {
|
|
400
|
-
const
|
|
401
|
-
|
|
402
|
-
res.flush();
|
|
403
|
-
}
|
|
404
|
-
if (!ok) {
|
|
405
|
-
await drained.promise;
|
|
406
|
-
drained = new DetachedPromise();
|
|
407
|
-
}
|
|
179
|
+
const data = typeof ev.data === "string" ? ev.data : ev.data.toString();
|
|
180
|
+
hotReloader.handleClientMessage(ws, data);
|
|
408
181
|
}
|
|
409
182
|
catch (err) {
|
|
410
|
-
|
|
411
|
-
throw new Error("failed to write chunk to response", { cause: err });
|
|
183
|
+
console.error("HMR message error", err);
|
|
412
184
|
}
|
|
413
185
|
},
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
return;
|
|
417
|
-
res.destroy(err);
|
|
186
|
+
onClose(_ev, ws) {
|
|
187
|
+
hotReloader.unregisterClient(ws);
|
|
418
188
|
},
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
await waitUntilForEnd;
|
|
422
|
-
}
|
|
423
|
-
if (res.writableFinished)
|
|
424
|
-
return;
|
|
425
|
-
res.end();
|
|
426
|
-
return finished.promise;
|
|
189
|
+
onError(err) {
|
|
190
|
+
console.error("HMR WebSocket error", err);
|
|
427
191
|
},
|
|
192
|
+
})));
|
|
193
|
+
// GET handles HEAD automatically in Hono; serveStatic serves both
|
|
194
|
+
app.get("/*", (0, serve_static_1.serveStatic)({
|
|
195
|
+
root: distRoot,
|
|
196
|
+
rewriteRequestPath,
|
|
197
|
+
}));
|
|
198
|
+
app.all("*", (c) => c.body(null, 405, { Allow: "GET, HEAD" }));
|
|
199
|
+
const server = (0, node_server_1.serve)({
|
|
200
|
+
...serveOptsBase,
|
|
201
|
+
fetch: app.fetch,
|
|
428
202
|
});
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
reject = rej;
|
|
437
|
-
});
|
|
438
|
-
this.resolve = resolve;
|
|
439
|
-
this.reject = reject;
|
|
203
|
+
injectWebSocket(server);
|
|
204
|
+
if ((serverOptions === null || serverOptions === void 0 ? void 0 : serverOptions.logServerInfo) !== false) {
|
|
205
|
+
const scheme = serveOptsBase.serverOptions ? "https" : "http";
|
|
206
|
+
const displayHost = serveOptsBase.hostname === "0.0.0.0"
|
|
207
|
+
? "localhost"
|
|
208
|
+
: serveOptsBase.hostname;
|
|
209
|
+
(0, printServerInfo_1.printServerInfo)(scheme, displayHost, serveOptsBase.port);
|
|
440
210
|
}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
.
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
|
|
211
|
+
const cleanup = () => {
|
|
212
|
+
hotReloader.close();
|
|
213
|
+
// We always create HTTP/1.1 server (http or https), so closeAllConnections exists; Hono's
|
|
214
|
+
// ServerType union includes HTTP/2, so TS does not narrow. Use runtime check to satisfy types.
|
|
215
|
+
if ("closeAllConnections" in server &&
|
|
216
|
+
typeof server.closeAllConnections === "function") {
|
|
217
|
+
server.closeAllConnections();
|
|
218
|
+
}
|
|
219
|
+
server.close((err) => {
|
|
220
|
+
if (err) {
|
|
221
|
+
console.error(err);
|
|
222
|
+
process.exit(1);
|
|
223
|
+
}
|
|
224
|
+
process.exit(0);
|
|
225
|
+
});
|
|
226
|
+
};
|
|
227
|
+
const exception = (err) => {
|
|
228
|
+
console.error(err);
|
|
229
|
+
};
|
|
230
|
+
process.on("SIGINT", cleanup);
|
|
231
|
+
process.on("SIGTERM", cleanup);
|
|
232
|
+
process.on("rejectionHandled", () => { });
|
|
233
|
+
process.on("uncaughtException", exception);
|
|
234
|
+
process.on("unhandledRejection", exception);
|
|
458
235
|
}
|
package/cjs/core/hmr.d.ts
CHANGED
|
@@ -13,6 +13,11 @@ export interface WebpackStats {
|
|
|
13
13
|
toJson(options?: any): any;
|
|
14
14
|
toString(options?: any): string;
|
|
15
15
|
}
|
|
16
|
+
/** Client handle for HMR: any object with send(data) usable as Set/WeakMap key (e.g. ws WebSocket or hono WSContext). */
|
|
17
|
+
export interface WSLike {
|
|
18
|
+
send(data: string): void;
|
|
19
|
+
close(code?: number, reason?: string): void;
|
|
20
|
+
}
|
|
16
21
|
export interface HotReloaderInterface {
|
|
17
22
|
turbopackProject?: Project;
|
|
18
23
|
serverStats: WebpackStats | null;
|
|
@@ -20,9 +25,18 @@ export interface HotReloaderInterface {
|
|
|
20
25
|
clearHmrServerError(): void;
|
|
21
26
|
start(): Promise<void>;
|
|
22
27
|
send(action: HMR_ACTION_TYPES): void;
|
|
28
|
+
/**
|
|
29
|
+
* @deprecated Used by legacy dev server (dev-legacy.ts). Prefer registerClient / unregisterClient / handleClientMessage (e.g. dev.ts).
|
|
30
|
+
*/
|
|
23
31
|
onHMR(req: IncomingMessage, socket: Duplex, head: Buffer, onUpgrade?: (client: {
|
|
24
32
|
send(data: string): void;
|
|
25
33
|
}) => void): void;
|
|
34
|
+
/** Register a WebSocket client (e.g. from @hono/node-ws upgradeWebSocket). Call unregisterClient on close. */
|
|
35
|
+
registerClient(ws: WSLike): void;
|
|
36
|
+
/** Unregister and cleanup subscriptions for a client. */
|
|
37
|
+
unregisterClient(ws: WSLike): void;
|
|
38
|
+
/** Handle a message from a client (JSON string). */
|
|
39
|
+
handleClientMessage(ws: WSLike, data: string): void;
|
|
26
40
|
buildFallbackError(): Promise<void>;
|
|
27
41
|
close(): void;
|
|
28
42
|
}
|