@open-wxa/wxa-runner-core 0.12.1 → 0.12.3
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/dist/index.d.mts +8 -3
- package/dist/index.d.ts +8 -3
- package/dist/index.js +118 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +118 -13
- package/dist/index.mjs.map +1 -1
- package/dist/runtime/frame.js +28 -2
- package/dist/runtime/frame.js.map +1 -1
- package/dist/runtime/host.js +34 -5
- package/dist/runtime/host.js.map +1 -1
- package/dist/{setup-D0ubZt2C.d.mts → setup--EIOgQvG.d.mts} +2 -0
- package/dist/{setup-D0ubZt2C.d.ts → setup--EIOgQvG.d.ts} +2 -0
- package/dist/setup.d.mts +1 -1
- package/dist/setup.d.ts +1 -1
- package/dist/test-api.d.mts +2 -2
- package/dist/test-api.d.ts +2 -2
- package/dist/{testApi-Df0ltBI6.d.ts → testApi-BfzCTOhg.d.ts} +1 -1
- package/dist/{testApi-x2Yph6M2.d.mts → testApi-CoYw0cPm.d.mts} +1 -1
- package/dist/web.d.mts +3 -0
- package/dist/web.d.ts +3 -0
- package/dist/web.js +20 -0
- package/dist/web.js.map +1 -1
- package/dist/web.mjs +20 -0
- package/dist/web.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -98,6 +98,26 @@ var FileStore = class {
|
|
|
98
98
|
this.write(destPath, this.read(srcPath));
|
|
99
99
|
return {};
|
|
100
100
|
},
|
|
101
|
+
rename: ({ oldPath, newPath }) => {
|
|
102
|
+
const source = this.normalize(oldPath);
|
|
103
|
+
const target = this.normalize(newPath);
|
|
104
|
+
const node = this.existing(oldPath);
|
|
105
|
+
this.assertNotRoot(source);
|
|
106
|
+
this.assertNotRoot(target);
|
|
107
|
+
if (source === target) return {};
|
|
108
|
+
const parent = target.slice(0, target.lastIndexOf("/")) || "/";
|
|
109
|
+
if (!this.nodes.get(parent)?.dir) throw new Error(`no such file or directory ${newPath}`);
|
|
110
|
+
if (node.dir && target.startsWith(source + "/")) throw new Error("invalid argument: directory moved into itself");
|
|
111
|
+
const destination = this.nodes.get(target);
|
|
112
|
+
if (destination) {
|
|
113
|
+
if (destination.dir !== node.dir) throw new Error(`incompatible file type ${newPath}`);
|
|
114
|
+
if (destination.dir && this.readdir(target).length) throw new Error(`directory not empty ${newPath}`);
|
|
115
|
+
}
|
|
116
|
+
const entries = [...this.nodes].filter(([key]) => key === source || node.dir && key.startsWith(source + "/"));
|
|
117
|
+
for (const [key] of entries) this.nodes.delete(key);
|
|
118
|
+
for (const [key, value] of entries) this.nodes.set(target + key.slice(source.length), value);
|
|
119
|
+
return {};
|
|
120
|
+
},
|
|
101
121
|
access: ({ path: path7 }) => {
|
|
102
122
|
this.existing(path7);
|
|
103
123
|
return {};
|
|
@@ -225,7 +245,7 @@ import net from "net";
|
|
|
225
245
|
import os3 from "os";
|
|
226
246
|
import path6 from "path";
|
|
227
247
|
import express2 from "express";
|
|
228
|
-
import { WebSocket as
|
|
248
|
+
import { WebSocket as WebSocket3, WebSocketServer as WebSocketServer2 } from "ws";
|
|
229
249
|
import { readRegionData, resolveBaseLib, usesIsolatedContext } from "@open-wxa/wxa-runner-extractor";
|
|
230
250
|
|
|
231
251
|
// src/project/AppBuilder.ts
|
|
@@ -580,8 +600,8 @@ var AppBuilder = class {
|
|
|
580
600
|
this.pending = { covers: this.changes, result: result2 };
|
|
581
601
|
}
|
|
582
602
|
const { covers, result } = this.pending;
|
|
583
|
-
|
|
584
|
-
|
|
603
|
+
if (covers >= wanted) return result;
|
|
604
|
+
await result.catch(() => void 0);
|
|
585
605
|
}
|
|
586
606
|
}
|
|
587
607
|
/**
|
|
@@ -1411,6 +1431,71 @@ async function handleProxy(req, res) {
|
|
|
1411
1431
|
}
|
|
1412
1432
|
}
|
|
1413
1433
|
|
|
1434
|
+
// src/server/socketProxy.ts
|
|
1435
|
+
import { WebSocket, WebSocketServer } from "ws";
|
|
1436
|
+
function mirrorClose(to, code, reason) {
|
|
1437
|
+
if (code === 1005) to.close();
|
|
1438
|
+
else if (code === 1006 || code === 1015) to.terminate();
|
|
1439
|
+
else to.close(code, reason);
|
|
1440
|
+
}
|
|
1441
|
+
function createSocketProxy() {
|
|
1442
|
+
const server = new WebSocketServer({
|
|
1443
|
+
noServer: true,
|
|
1444
|
+
// 不能让其他网站借本地开发服务器建立任意带凭据的连接。
|
|
1445
|
+
verifyClient: ({ origin, req }) => origin === `http://${req.headers.host}`
|
|
1446
|
+
});
|
|
1447
|
+
server.on("connection", (client) => {
|
|
1448
|
+
let upstream;
|
|
1449
|
+
const timer = setTimeout(() => client.close(1008, "Missing socket request"), 1e4);
|
|
1450
|
+
timer.unref();
|
|
1451
|
+
client.on("error", () => void 0);
|
|
1452
|
+
client.once("message", (data, binary) => {
|
|
1453
|
+
clearTimeout(timer);
|
|
1454
|
+
try {
|
|
1455
|
+
if (binary || data.toString().length > 64 * 1024) throw new Error("Invalid socket request");
|
|
1456
|
+
const { url, header: header2, protocols, timeout } = JSON.parse(data.toString());
|
|
1457
|
+
const target = new URL(url);
|
|
1458
|
+
if (!["ws:", "wss:"].includes(target.protocol) || target.username || target.password) throw new Error("Invalid socket URL");
|
|
1459
|
+
upstream = new WebSocket(target, protocols || [], {
|
|
1460
|
+
headers: header2 || {},
|
|
1461
|
+
handshakeTimeout: typeof timeout === "number" && timeout > 0 ? timeout : 6e4
|
|
1462
|
+
});
|
|
1463
|
+
} catch {
|
|
1464
|
+
client.close(1008, "Invalid socket request");
|
|
1465
|
+
return;
|
|
1466
|
+
}
|
|
1467
|
+
const socket = upstream;
|
|
1468
|
+
let header = {};
|
|
1469
|
+
socket.on("upgrade", (response) => {
|
|
1470
|
+
header = response.headers;
|
|
1471
|
+
});
|
|
1472
|
+
socket.on("open", () => {
|
|
1473
|
+
if (client.readyState !== WebSocket.OPEN) {
|
|
1474
|
+
socket.close();
|
|
1475
|
+
return;
|
|
1476
|
+
}
|
|
1477
|
+
client.send(JSON.stringify({ ready: true, header }));
|
|
1478
|
+
});
|
|
1479
|
+
socket.on("message", (message, isBinary) => {
|
|
1480
|
+
if (client.readyState === WebSocket.OPEN) client.send(message, { binary: isBinary });
|
|
1481
|
+
});
|
|
1482
|
+
client.on("message", (message, isBinary) => {
|
|
1483
|
+
if (socket.readyState === WebSocket.OPEN) socket.send(message, { binary: isBinary });
|
|
1484
|
+
});
|
|
1485
|
+
socket.on("error", () => client.terminate());
|
|
1486
|
+
socket.on("close", (code, reason) => {
|
|
1487
|
+
if (client.readyState === WebSocket.OPEN) mirrorClose(client, code, reason);
|
|
1488
|
+
});
|
|
1489
|
+
});
|
|
1490
|
+
client.on("close", (code, reason) => {
|
|
1491
|
+
clearTimeout(timer);
|
|
1492
|
+
if (upstream?.readyState === WebSocket.OPEN) mirrorClose(upstream, code, reason);
|
|
1493
|
+
else if (upstream) upstream.terminate();
|
|
1494
|
+
});
|
|
1495
|
+
});
|
|
1496
|
+
return server;
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1414
1499
|
// src/server/hmr.ts
|
|
1415
1500
|
var STYLE_FILE = /\.(wxss|less|scss|sass|css)$/;
|
|
1416
1501
|
function planHotUpdate(files, units) {
|
|
@@ -1429,7 +1514,7 @@ function planHotUpdate(files, units) {
|
|
|
1429
1514
|
import { execFile } from "child_process";
|
|
1430
1515
|
import { randomUUID } from "crypto";
|
|
1431
1516
|
import { setTimeout as sleep } from "timers/promises";
|
|
1432
|
-
import { WebSocket } from "ws";
|
|
1517
|
+
import { WebSocket as WebSocket2 } from "ws";
|
|
1433
1518
|
import { findDeveloperTicket, findElectronDevtoolsCli, TICKET_ENV } from "@open-wxa/wxa-runner-extractor";
|
|
1434
1519
|
var AUTO_PORT = 9420;
|
|
1435
1520
|
var CLI_TIMEOUT = 6e4;
|
|
@@ -1520,7 +1605,7 @@ function cliErrorMessage(stdout) {
|
|
|
1520
1605
|
function requestTicket(port) {
|
|
1521
1606
|
return new Promise((resolve, reject) => {
|
|
1522
1607
|
const id = `wxa-runner-${randomUUID()}`;
|
|
1523
|
-
const socket = new
|
|
1608
|
+
const socket = new WebSocket2(`ws://127.0.0.1:${port}`);
|
|
1524
1609
|
const settle = (finish) => {
|
|
1525
1610
|
clearTimeout(timer);
|
|
1526
1611
|
socket.removeAllListeners().on("error", () => void 0).terminate();
|
|
@@ -1906,8 +1991,11 @@ var DevServer = class {
|
|
|
1906
1991
|
constructor(options) {
|
|
1907
1992
|
this.options = options;
|
|
1908
1993
|
this.server = null;
|
|
1994
|
+
this.socketProxy = null;
|
|
1909
1995
|
this.sockets = null;
|
|
1910
1996
|
this.watcher = null;
|
|
1997
|
+
/** 上次编译失败时页面上显示着错误,修好后整页刷新才能清掉 */
|
|
1998
|
+
this.lastBuildFailed = false;
|
|
1911
1999
|
this.address = "";
|
|
1912
2000
|
this.lanAccess = false;
|
|
1913
2001
|
/** 运行时生成的临时文件(canvas 导出、拍照等),随服务器进程存在 */
|
|
@@ -1951,20 +2039,27 @@ var DevServer = class {
|
|
|
1951
2039
|
return Object.values(os3.networkInterfaces()).flat().filter((net2) => net2 && net2.family === "IPv4" && !net2.internal).map((net2) => `http://${net2.address}:${port}`);
|
|
1952
2040
|
}
|
|
1953
2041
|
async start() {
|
|
2042
|
+
if (this.options.watch !== false) await this.startWatching();
|
|
1954
2043
|
try {
|
|
1955
2044
|
const build2 = await this.builder.build();
|
|
1956
2045
|
this.logger.log(`[wxa-runner] \u7F16\u8BD1\u5B8C\u6210\uFF1A${build2.pages.length} \u4E2A\u9875\u9762\uFF0C${build2.components.length} \u4E2A\u7EC4\u4EF6\uFF0C${build2.durationMs}ms`);
|
|
1957
2046
|
} catch (error) {
|
|
2047
|
+
this.lastBuildFailed = true;
|
|
1958
2048
|
this.logger.error(`[wxa-runner] \u7F16\u8BD1\u5931\u8D25\uFF1A
|
|
1959
2049
|
${error.message}`);
|
|
1960
2050
|
}
|
|
1961
2051
|
const server = http.createServer(this.app);
|
|
1962
|
-
this.sockets = new
|
|
2052
|
+
this.sockets = new WebSocketServer2({ noServer: true, maxPayload: 64 * 1024 });
|
|
1963
2053
|
this.sockets.on("connection", (socket) => {
|
|
1964
2054
|
socket.on("error", () => void 0);
|
|
1965
2055
|
if (this.options.forwardConsole) printBrowserReports(socket, this.logger);
|
|
1966
2056
|
});
|
|
2057
|
+
this.socketProxy = createSocketProxy();
|
|
1967
2058
|
server.on("upgrade", (req, socket, head) => {
|
|
2059
|
+
if (req.url === "/__wxa__/socket") {
|
|
2060
|
+
this.socketProxy.handleUpgrade(req, socket, head, (ws) => this.socketProxy.emit("connection", ws, req));
|
|
2061
|
+
return;
|
|
2062
|
+
}
|
|
1968
2063
|
if (req.url?.startsWith("/__wxa__/ws")) {
|
|
1969
2064
|
this.sockets.handleUpgrade(req, socket, head, (ws) => this.sockets.emit("connection", ws, req));
|
|
1970
2065
|
} else {
|
|
@@ -1972,11 +2067,17 @@ ${error.message}`);
|
|
|
1972
2067
|
}
|
|
1973
2068
|
});
|
|
1974
2069
|
const host = this.options.host || "localhost";
|
|
1975
|
-
|
|
2070
|
+
let port;
|
|
2071
|
+
try {
|
|
2072
|
+
port = await listen(server, this.options.port, host, this.logger);
|
|
2073
|
+
} catch (error) {
|
|
2074
|
+
await this.watcher?.close();
|
|
2075
|
+
this.watcher = null;
|
|
2076
|
+
throw error;
|
|
2077
|
+
}
|
|
1976
2078
|
this.server = server;
|
|
1977
2079
|
this.lanAccess = LOCAL_HOST_OF_ANY_ADDRESS.has(host);
|
|
1978
2080
|
this.address = `http://${LOCAL_HOST_OF_ANY_ADDRESS.get(host) ?? host}:${port}`;
|
|
1979
|
-
if (this.options.watch !== false) this.startWatching();
|
|
1980
2081
|
this.ticketSource?.().then(requireUsableTicket).catch((error) => this.logger.warn(`[wxa-runner] \u5F00\u53D1\u8005\u5DE5\u5177\u7684\u767B\u5F55\u6001\u6682\u4E0D\u53EF\u7528\uFF08--devtools-login\uFF09\uFF1A${error.message}`));
|
|
1981
2082
|
return this.address;
|
|
1982
2083
|
}
|
|
@@ -1984,6 +2085,8 @@ ${error.message}`);
|
|
|
1984
2085
|
await this.watcher?.close();
|
|
1985
2086
|
this.sockets?.clients.forEach((client) => client.terminate());
|
|
1986
2087
|
this.sockets?.close();
|
|
2088
|
+
this.socketProxy?.clients.forEach((client) => client.terminate());
|
|
2089
|
+
this.socketProxy?.close();
|
|
1987
2090
|
const server = this.server;
|
|
1988
2091
|
this.server = null;
|
|
1989
2092
|
if (server) {
|
|
@@ -2014,6 +2117,7 @@ ${error.message}`);
|
|
|
2014
2117
|
baseLibVersion: this.baseLib.version,
|
|
2015
2118
|
device: this.device,
|
|
2016
2119
|
devtoolsLogin: this.devtoolsLogin,
|
|
2120
|
+
socketProxy: true,
|
|
2017
2121
|
forwardConsole: this.options.forwardConsole ?? false,
|
|
2018
2122
|
webViewWindow: this.options.webViewWindow ?? false
|
|
2019
2123
|
};
|
|
@@ -2210,36 +2314,37 @@ ${error.message}`);
|
|
|
2210
2314
|
get hotEnabled() {
|
|
2211
2315
|
return this.options.watch !== false;
|
|
2212
2316
|
}
|
|
2317
|
+
/** 返回初次扫描完成的时刻,此前已存在的文件不会作为改动报告 */
|
|
2213
2318
|
startWatching() {
|
|
2214
|
-
let lastBuildFailed = false;
|
|
2215
2319
|
const watched = [this.project.root];
|
|
2216
2320
|
const outsideRoot = (file) => path6.relative(this.project.root, file).startsWith("..");
|
|
2217
2321
|
if (this.setupFile && outsideRoot(this.setupFile)) watched.push(this.setupFile);
|
|
2218
2322
|
const projectConfig = path6.join(this.project.projectPath, "project.config.json");
|
|
2219
2323
|
if (outsideRoot(projectConfig) && fs6.existsSync(projectConfig)) watched.push(projectConfig);
|
|
2220
2324
|
this.watcher = watchProject(this.project.root, watched, async ({ files, structural }) => {
|
|
2221
|
-
const reloadOnly = structural || lastBuildFailed;
|
|
2325
|
+
const reloadOnly = structural || this.lastBuildFailed;
|
|
2222
2326
|
this.builder.invalidate(files);
|
|
2223
2327
|
const label = files.length > 3 ? `${files.slice(0, 3).join(", ")} \u7B49 ${files.length} \u4E2A\u6587\u4EF6` : files.join(", ");
|
|
2224
2328
|
try {
|
|
2225
2329
|
const build2 = await this.builder.build();
|
|
2226
|
-
lastBuildFailed = false;
|
|
2330
|
+
this.lastBuildFailed = false;
|
|
2227
2331
|
const plan = reloadOnly ? null : planHotUpdate(files, build2);
|
|
2228
2332
|
this.logger.log(`[wxa-runner] ${label} \u5DF2\u66F4\u65B0\uFF0C\u91CD\u65B0\u7F16\u8BD1 ${build2.durationMs}ms${plan ? "\uFF0C\u70ED\u66F4\u65B0" : ""}`);
|
|
2229
2333
|
this.broadcast(plan ? { type: "hot", version: build2.version, ...plan } : { type: "reload" });
|
|
2230
2334
|
} catch (error) {
|
|
2231
|
-
lastBuildFailed = true;
|
|
2335
|
+
this.lastBuildFailed = true;
|
|
2232
2336
|
const message = error.message;
|
|
2233
2337
|
this.logger.error(`[wxa-runner] \u7F16\u8BD1\u5931\u8D25\uFF1A
|
|
2234
2338
|
${message}`);
|
|
2235
2339
|
this.broadcast({ type: "error", message });
|
|
2236
2340
|
}
|
|
2237
2341
|
});
|
|
2342
|
+
return this.watcher.ready;
|
|
2238
2343
|
}
|
|
2239
2344
|
broadcast(message) {
|
|
2240
2345
|
const data = JSON.stringify(message);
|
|
2241
2346
|
this.sockets?.clients.forEach((client) => {
|
|
2242
|
-
if (client.readyState ===
|
|
2347
|
+
if (client.readyState === WebSocket3.OPEN) client.send(data);
|
|
2243
2348
|
});
|
|
2244
2349
|
}
|
|
2245
2350
|
};
|