@open-wxa/wxa-runner-core 0.5.0 → 0.7.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/dist/index.d.mts +26 -8
- package/dist/index.d.ts +26 -8
- package/dist/index.js +316 -87
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +310 -81
- package/dist/index.mjs.map +1 -1
- package/dist/runtime/frame.js +50 -1
- package/dist/runtime/frame.js.map +1 -1
- package/dist/runtime/host.js +32 -12
- package/dist/runtime/host.js.map +1 -1
- package/dist/runtime/worker.js +42 -0
- package/dist/runtime/worker.js.map +1 -0
- package/dist/{setup-Cv340Lvj.d.mts → setup-DZ5FeKay.d.mts} +2 -1
- package/dist/{setup-Cv340Lvj.d.ts → setup-DZ5FeKay.d.ts} +2 -1
- 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-nKsjjEhz.d.ts → testApi-BLozOgCt.d.ts} +1 -1
- package/dist/{testApi-DO2FyR78.d.mts → testApi-CnZOLyWw.d.mts} +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -190,8 +190,10 @@ var AppBuilder = class {
|
|
|
190
190
|
]);
|
|
191
191
|
this.wxmlCache = wxml;
|
|
192
192
|
this.wxssCache = wxss;
|
|
193
|
-
const workersDir =
|
|
194
|
-
const
|
|
193
|
+
const workersDir = this.project.workersDir(app);
|
|
194
|
+
const inWorkers = (file) => workersDir !== null && file.startsWith(workersDir + "/");
|
|
195
|
+
const scripts = this.project.listFiles([".js"]);
|
|
196
|
+
const modules = scripts.filter((file) => !inWorkers(file));
|
|
195
197
|
const serviceTemplates = this.createTemplates(app, units, unitJson, wxml.cut);
|
|
196
198
|
const pageTemplates = this.createTemplates(app, units, unitJson, wxml.full);
|
|
197
199
|
const pageStyles = createStyles(units, wxss);
|
|
@@ -205,6 +207,7 @@ var AppBuilder = class {
|
|
|
205
207
|
subPackages: this.project.subPackages(app)
|
|
206
208
|
}),
|
|
207
209
|
modules,
|
|
210
|
+
workerModules: scripts.filter(inWorkers),
|
|
208
211
|
serviceTemplates,
|
|
209
212
|
serviceBootstrap: this.createServiceBootstrap(serviceTemplates, units, modules),
|
|
210
213
|
pageFrame: `${pageTemplates}
|
|
@@ -226,7 +229,7 @@ ${pageStyles}`,
|
|
|
226
229
|
const files = this.project.listFiles([".wxml", ".wxs"]).map((f) => "./" + f);
|
|
227
230
|
const components = units.filter((id) => this.project.exists(id + ".wxml")).map((id) => {
|
|
228
231
|
const json = unitJson.get(id);
|
|
229
|
-
return { path: id, tags: Object.keys({ ...json.usingComponents, ...json.componentGenerics
|
|
232
|
+
return { path: id, tags: Object.keys({ ...json.usingComponents, ...json.componentGenerics }) };
|
|
230
233
|
});
|
|
231
234
|
const cwd = this.project.root;
|
|
232
235
|
const [full, cut] = await Promise.all([
|
|
@@ -319,6 +322,11 @@ var MiniProgram = class {
|
|
|
319
322
|
subPackages(app) {
|
|
320
323
|
return app.subPackages || app.subpackages || [];
|
|
321
324
|
}
|
|
325
|
+
/** Worker 代码所在目录,不带首尾的 /;没有配置 workers 时为 null */
|
|
326
|
+
workersDir(app) {
|
|
327
|
+
const dir = typeof app.workers === "string" ? app.workers : app.workers?.path;
|
|
328
|
+
return dir ? path.posix.normalize(dir).replace(/^\/+|\/+$/g, "") : null;
|
|
329
|
+
}
|
|
322
330
|
/** 主包页面 + 分包页面(带 root 前缀) */
|
|
323
331
|
allPages(app) {
|
|
324
332
|
const pages = [...app.pages];
|
|
@@ -332,8 +340,8 @@ var MiniProgram = class {
|
|
|
332
340
|
}
|
|
333
341
|
/** 读取并预处理页面/组件 json,id 不带扩展名 */
|
|
334
342
|
readUnitJson(id, app) {
|
|
335
|
-
const json = { ...readJsonFile(path.join(this.root, id + ".json"))
|
|
336
|
-
json.usingComponents = { ...json.usingComponents
|
|
343
|
+
const json = { ...readJsonFile(path.join(this.root, id + ".json")) };
|
|
344
|
+
json.usingComponents = { ...json.usingComponents };
|
|
337
345
|
if (!id.startsWith("miniprogram_npm/") && !this.isInIndependentSubPackage(id, app)) {
|
|
338
346
|
for (const [tag, ref] of Object.entries(app.usingComponents || {})) {
|
|
339
347
|
if (json.usingComponents[tag]) continue;
|
|
@@ -400,15 +408,14 @@ var MiniProgram = class {
|
|
|
400
408
|
return { pages, components };
|
|
401
409
|
}
|
|
402
410
|
/** 列出代码根目录下指定扩展名的文件,返回 posix 风格的相对路径 */
|
|
403
|
-
listFiles(extensions
|
|
411
|
+
listFiles(extensions) {
|
|
404
412
|
const result = [];
|
|
405
|
-
const excluded = new Set(excludeDirs.map((dir) => dir.replace(/^\/|\/$/g, "")));
|
|
406
413
|
const walk = (dir, rel) => {
|
|
407
414
|
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
408
415
|
if (entry.name.startsWith(".") || IGNORED_DIRS.has(entry.name)) continue;
|
|
409
416
|
const childRel = rel ? `${rel}/${entry.name}` : entry.name;
|
|
410
417
|
if (entry.isDirectory()) {
|
|
411
|
-
|
|
418
|
+
walk(path.join(dir, entry.name), childRel);
|
|
412
419
|
} else if (extensions.some((ext) => entry.name.endsWith(ext))) {
|
|
413
420
|
if (!rel && PROJECT_FILES.has(entry.name)) continue;
|
|
414
421
|
result.push(childRel);
|
|
@@ -438,6 +445,178 @@ function readJsonFile(file) {
|
|
|
438
445
|
}
|
|
439
446
|
}
|
|
440
447
|
|
|
448
|
+
// src/server/plugins.ts
|
|
449
|
+
import { readWxvpkgFile, readWxvpkgIndex } from "@open-wxa/wxa-runner-extractor";
|
|
450
|
+
|
|
451
|
+
// src/server/wechatDev.ts
|
|
452
|
+
import { TICKET_ENV } from "@open-wxa/wxa-runner-extractor";
|
|
453
|
+
var BASE_URL = "https://servicewechat.com";
|
|
454
|
+
var CLIENT_VERSION = "1021810240";
|
|
455
|
+
var DEFAULT_TIMEOUT = 1e4;
|
|
456
|
+
var ERROR_HINTS = {
|
|
457
|
+
// 40001:开发者工具刷新过 ticket,旧的随即作废
|
|
458
|
+
40001: "\uFF08\u767B\u5F55\u6001\u5DF2\u5931\u6548\uFF0C\u8BF7\u5728\u5FAE\u4FE1\u5F00\u53D1\u8005\u5DE5\u5177\u91CC\u91CD\u65B0\u767B\u5F55\uFF09",
|
|
459
|
+
40029: "\uFF08\u767B\u5F55\u6001\u5DF2\u5931\u6548\uFF0C\u8BF7\u5728\u5FAE\u4FE1\u5F00\u53D1\u8005\u5DE5\u5177\u91CC\u91CD\u65B0\u767B\u5F55\uFF09",
|
|
460
|
+
85023: "\uFF08\u5F53\u524D\u5FAE\u4FE1\u8D26\u53F7\u4E0D\u662F\u8BE5\u5C0F\u7A0B\u5E8F\u7684\u5F00\u53D1\u8005\uFF09"
|
|
461
|
+
};
|
|
462
|
+
function requireUsableTicket(ticket) {
|
|
463
|
+
if (!ticket) throw new Error(`\u672A\u627E\u5230\u5FAE\u4FE1\u5F00\u53D1\u8005\u5DE5\u5177\u7684\u767B\u5F55\u6001\uFF0C\u8BF7\u767B\u5F55\u5F00\u53D1\u8005\u5DE5\u5177\uFF0C\u6216\u8BBE\u7F6E\u73AF\u5883\u53D8\u91CF ${TICKET_ENV}`);
|
|
464
|
+
if (ticket.expiredAt !== void 0 && ticket.expiredAt <= Date.now()) {
|
|
465
|
+
throw new Error("\u5FAE\u4FE1\u5F00\u53D1\u8005\u5DE5\u5177\u7684\u767B\u5F55\u6001\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u6253\u5F00\u5F00\u53D1\u8005\u5DE5\u5177\u5237\u65B0\u767B\u5F55\u6001");
|
|
466
|
+
}
|
|
467
|
+
return ticket.newticket;
|
|
468
|
+
}
|
|
469
|
+
function explainErrcode(errcode) {
|
|
470
|
+
return errcode !== void 0 && ERROR_HINTS[errcode] || "";
|
|
471
|
+
}
|
|
472
|
+
function requireOk(body, action) {
|
|
473
|
+
const errcode = body.baseresponse?.errcode;
|
|
474
|
+
if (errcode !== 0) throw new Error(`${action} ${errcode}: ${body.baseresponse?.errmsg || "\u672A\u77E5\u9519\u8BEF"}${explainErrcode(errcode)}`);
|
|
475
|
+
return body;
|
|
476
|
+
}
|
|
477
|
+
var WechatDevClient = class {
|
|
478
|
+
/**
|
|
479
|
+
* @param findTicket 每次请求都重新取:开发者工具重新登录、切换账号后不用重启服务器
|
|
480
|
+
*/
|
|
481
|
+
constructor(appid, findTicket) {
|
|
482
|
+
this.appid = appid;
|
|
483
|
+
this.findTicket = findTicket;
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* POST JSON 到 path(如 wxa-dev-logic/jslogin),带上 appid 和开发者 ticket
|
|
487
|
+
*
|
|
488
|
+
* @throws 没有可用的登录态、超时、连不上、HTTP 状态不是 2xx 时,消息是给用户看的原因
|
|
489
|
+
*/
|
|
490
|
+
async post(path5, body, timeout = DEFAULT_TIMEOUT) {
|
|
491
|
+
const query = new URLSearchParams({ appid: this.appid, newticket: requireUsableTicket(await this.findTicket()), clientversion: CLIENT_VERSION });
|
|
492
|
+
const response = await fetch(`${BASE_URL}/${path5}?${query}`, {
|
|
493
|
+
method: "POST",
|
|
494
|
+
headers: { "Content-Type": "application/json" },
|
|
495
|
+
body: JSON.stringify(body),
|
|
496
|
+
signal: AbortSignal.timeout(timeout)
|
|
497
|
+
}).catch((error) => {
|
|
498
|
+
throw new Error(error.name === "TimeoutError" ? `\u8BF7\u6C42\u5FAE\u4FE1\u670D\u52A1\u5668\u8D85\u65F6\uFF08${timeout / 1e3}s\uFF09` : `\u8BF7\u6C42\u5FAE\u4FE1\u670D\u52A1\u5668\u5931\u8D25\uFF1A${error.cause?.message ?? error.message}`);
|
|
499
|
+
});
|
|
500
|
+
if (!response.ok) throw new Error(`\u5FAE\u4FE1\u670D\u52A1\u5668\u8FD4\u56DE HTTP ${response.status}`);
|
|
501
|
+
return response;
|
|
502
|
+
}
|
|
503
|
+
/** 同 post,返回解析后的 JSON */
|
|
504
|
+
async postJson(path5, body) {
|
|
505
|
+
return (await this.post(path5, body)).json();
|
|
506
|
+
}
|
|
507
|
+
};
|
|
508
|
+
|
|
509
|
+
// src/server/plugins.ts
|
|
510
|
+
var DOWNLOAD_TIMEOUT = 3e4;
|
|
511
|
+
var PACKAGE_MAGIC = 190;
|
|
512
|
+
var PluginStore = class {
|
|
513
|
+
/**
|
|
514
|
+
* @param wechat 开启 --devtools-login 时才有,没有时不下载插件
|
|
515
|
+
*/
|
|
516
|
+
constructor(wechat, logger) {
|
|
517
|
+
this.wechat = wechat;
|
|
518
|
+
this.logger = logger;
|
|
519
|
+
/** provider@version → 下载结果;失败的不留,下次打开小程序时重试 */
|
|
520
|
+
this.downloads = /* @__PURE__ */ new Map();
|
|
521
|
+
/**
|
|
522
|
+
* 这次打开小程序时决定用哪些插件。同一次打开的逻辑层、业务模块、渲染层等请求都按它处理:
|
|
523
|
+
* 各自去下载的话,下载失败时每个请求都会重试,结果还可能前后不一,页面列表和逻辑层对不上
|
|
524
|
+
*/
|
|
525
|
+
this.selection = null;
|
|
526
|
+
/** 没开 --devtools-login 的提示每个插件只说一次 */
|
|
527
|
+
this.warned = /* @__PURE__ */ new Set();
|
|
528
|
+
}
|
|
529
|
+
/** 打开小程序时(宿主取 app-info)调用:重新决定用哪些插件,下载过的直接用,上次失败的重试 */
|
|
530
|
+
async refresh(build2) {
|
|
531
|
+
this.selection = this.select(build2);
|
|
532
|
+
return withPlugins(build2, await this.selection);
|
|
533
|
+
}
|
|
534
|
+
/** 其余请求沿用这次打开时的决定,不触发下载;还没决定过时(如直接请求逻辑层)先决定一次 */
|
|
535
|
+
async current(build2) {
|
|
536
|
+
this.selection ??= this.select(build2);
|
|
537
|
+
return withPlugins(build2, await this.selection);
|
|
538
|
+
}
|
|
539
|
+
/** app.json 声明的插件;下载不了的跳过,在终端说明原因,小程序自己的页面照常可用 */
|
|
540
|
+
async select(build2) {
|
|
541
|
+
const declared = build2.wxConfig.plugins || {};
|
|
542
|
+
const results = await Promise.all(Object.entries(declared).map(
|
|
543
|
+
([alias, { provider, version }]) => provider && version ? this.load(alias, provider, version) : null
|
|
544
|
+
));
|
|
545
|
+
return results.filter((plugin) => !!plugin);
|
|
546
|
+
}
|
|
547
|
+
async load(alias, provider, version) {
|
|
548
|
+
const label = `\u63D2\u4EF6 ${alias}\uFF08${provider}@${version}\uFF09`;
|
|
549
|
+
if (!this.wechat) {
|
|
550
|
+
this.warnOnce(label, `[wxa-runner] ${label} \u7684\u4EE3\u7801\u8981\u7528\u5F00\u53D1\u8005\u7684\u767B\u5F55\u6001\u5411\u5FAE\u4FE1\u4E0B\u8F7D\uFF0C\u542F\u52A8\u65F6\u52A0 --devtools-login`);
|
|
551
|
+
return null;
|
|
552
|
+
}
|
|
553
|
+
const key = `${provider}@${version}`;
|
|
554
|
+
let download = this.downloads.get(key);
|
|
555
|
+
if (!download) {
|
|
556
|
+
download = this.download(this.wechat, alias, provider, version);
|
|
557
|
+
this.downloads.set(key, download);
|
|
558
|
+
download.catch(() => this.downloads.delete(key));
|
|
559
|
+
}
|
|
560
|
+
try {
|
|
561
|
+
return await download;
|
|
562
|
+
} catch (error) {
|
|
563
|
+
this.logger.warn(`[wxa-runner] ${label} \u4E0B\u8F7D\u5931\u8D25\uFF1A${error.message}`);
|
|
564
|
+
return null;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
/** @throws 没有登录态、连不上、微信拒绝或返回的不是插件代码包时,消息是原因 */
|
|
568
|
+
async download(wechat, alias, provider, version) {
|
|
569
|
+
const response = await wechat.post("wxa-dev/getplugincode", { plugin_id: provider, plugin_version: version }, DOWNLOAD_TIMEOUT);
|
|
570
|
+
const data = Buffer.from(await response.arrayBuffer());
|
|
571
|
+
if (data[0] !== PACKAGE_MAGIC) {
|
|
572
|
+
let body = {};
|
|
573
|
+
try {
|
|
574
|
+
body = JSON.parse(data.toString("utf8"));
|
|
575
|
+
} catch {
|
|
576
|
+
}
|
|
577
|
+
if (body.baseresponse?.errcode) requireOk(body, "\u5FAE\u4FE1\u62D2\u7EDD\u4E0B\u8F7D");
|
|
578
|
+
throw new Error("\u5FAE\u4FE1\u6CA1\u6709\u8FD4\u56DE\u63D2\u4EF6\u4EE3\u7801");
|
|
579
|
+
}
|
|
580
|
+
const files = new Map(readWxvpkgIndex(data).map((entry) => [entry.name, Buffer.from(readWxvpkgFile(data, entry))]));
|
|
581
|
+
const pluginJson = JSON.parse(files.get("/plugin.json")?.toString("utf8") || "{}");
|
|
582
|
+
return {
|
|
583
|
+
alias,
|
|
584
|
+
provider,
|
|
585
|
+
version,
|
|
586
|
+
files,
|
|
587
|
+
pages: Object.values(pluginJson.pages || {}),
|
|
588
|
+
pageConfigs: pluginJson.page || {}
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
warnOnce(key, message) {
|
|
592
|
+
if (this.warned.has(key)) return;
|
|
593
|
+
this.warned.add(key);
|
|
594
|
+
this.logger.warn(message);
|
|
595
|
+
}
|
|
596
|
+
};
|
|
597
|
+
function withPlugins(build2, plugins) {
|
|
598
|
+
if (!plugins.length) return { ...build2, plugins };
|
|
599
|
+
return {
|
|
600
|
+
...build2,
|
|
601
|
+
plugins,
|
|
602
|
+
pages: [...build2.pages, ...plugins.flatMap((plugin) => plugin.pages)],
|
|
603
|
+
wxConfig: {
|
|
604
|
+
...build2.wxConfig,
|
|
605
|
+
page: { ...build2.wxConfig.page, ...Object.assign({}, ...plugins.map((plugin) => plugin.pageConfigs)) }
|
|
606
|
+
}
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
function findPluginPage(build2, pagePath) {
|
|
610
|
+
for (const plugin of build2.plugins) {
|
|
611
|
+
const prefix = `__plugin__/${plugin.provider}/`;
|
|
612
|
+
if (plugin.pages.includes(pagePath)) return { plugin, innerPath: pagePath.slice(prefix.length) };
|
|
613
|
+
}
|
|
614
|
+
return null;
|
|
615
|
+
}
|
|
616
|
+
function pluginScriptUrl(plugin, file) {
|
|
617
|
+
return `/__wxa__/plugin/${encodeURIComponent(plugin.provider)}/${encodeURIComponent(plugin.version)}/${file}`;
|
|
618
|
+
}
|
|
619
|
+
|
|
441
620
|
// src/server/html.ts
|
|
442
621
|
function hostHtml() {
|
|
443
622
|
return `<!DOCTYPE html>
|
|
@@ -464,10 +643,11 @@ function appserviceHtml(build2, launch, options) {
|
|
|
464
643
|
...options.isolated ? { isIsolateContext: true } : {}
|
|
465
644
|
};
|
|
466
645
|
const v = build2.version;
|
|
646
|
+
const pluginUrls = build2.plugins.map((plugin) => pluginScriptUrl(plugin, "appservice.js"));
|
|
467
647
|
const moduleUrls = build2.modules.map((id) => `/__wxa__/module/${encodeURI(id)}?v=${v}`);
|
|
468
648
|
const bootstrapUrl = `/__wxa__/service-bootstrap.js?v=${v}`;
|
|
469
649
|
if (options.isolated) {
|
|
470
|
-
const scripts = [...moduleUrls, bootstrapUrl];
|
|
650
|
+
const scripts = [...pluginUrls, ...moduleUrls, bootstrapUrl];
|
|
471
651
|
return `<!DOCTYPE html>
|
|
472
652
|
<html>
|
|
473
653
|
<head>
|
|
@@ -480,7 +660,7 @@ function appserviceHtml(build2, launch, options) {
|
|
|
480
660
|
<body></body>
|
|
481
661
|
</html>`;
|
|
482
662
|
}
|
|
483
|
-
const modules = moduleUrls.map((src) => `<script src="${src}"></script>`).join("\n");
|
|
663
|
+
const modules = [...pluginUrls, ...moduleUrls].map((src) => `<script src="${src}"></script>`).join("\n");
|
|
484
664
|
return `<!DOCTYPE html>
|
|
485
665
|
<html>
|
|
486
666
|
<head>
|
|
@@ -514,29 +694,13 @@ ${empty ? "" : '<script src="/__baselib__/WASubContext.js"></script>\n'}<script>
|
|
|
514
694
|
</html>`;
|
|
515
695
|
}
|
|
516
696
|
function webviewHtml(build2, pagePath, webviewId, options) {
|
|
517
|
-
const pageConfig = build2.wxConfig.page?.[pagePath + ".html"];
|
|
518
|
-
const window = { ...build2.wxConfig.global?.window, ...pageConfig?.window };
|
|
519
|
-
const wxConfig = { ...build2.wxConfig, window };
|
|
520
697
|
const id = Number(webviewId) || 0;
|
|
521
698
|
return `<!DOCTYPE html>
|
|
522
699
|
<html>
|
|
523
700
|
<head>
|
|
524
|
-
|
|
525
|
-
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
|
526
|
-
<title>${escapeHtml(pagePath)}</title>
|
|
527
|
-
<!-- \u5C0F\u7A0B\u5E8F\u6E32\u67D3\u5C42\u7684\u9ED8\u8BA4\u5B57\u53F7\u662F 16px\uFF1B\u4E0D\u58F0\u660E\u7684\u8BDD\u4F1A\u7EE7\u627F\u6D4F\u89C8\u5668\u8BBE\u7F6E\u91CC\u7684\u9ED8\u8BA4\u5B57\u53F7\u3002\u653E\u5728\u6700\u524D\u9762\uFF0C\u57FA\u7840\u5E93\u548C\u9875\u9762\u6837\u5F0F\u90FD\u80FD\u8986\u76D6\u5B83 -->
|
|
528
|
-
<style>html{font-size:16px}</style>
|
|
529
|
-
<!-- \u771F\u673A\u7684\u6EDA\u52A8\u6761\u662F\u4E0D\u5360\u5E03\u5C40\u7684\u6D6E\u5C42\uFF1B\u684C\u9762\u6D4F\u89C8\u5668\u7684\u5E38\u89C4\u6EDA\u52A8\u6761\u548C\u81EA\u5B9A\u4E49 ::-webkit-scrollbar \u4F1A\u6324\u7A84\u9875\u9762\uFF0C\u4E00\u5F8B\u9690\u85CF\u3002
|
|
530
|
-
scrollbar-width \u4F18\u5148\u4E8E ::-webkit-scrollbar\uFF0C\u9875\u9762\u6837\u5F0F\u4E0D\u4F1A\u518D\u628A\u6EDA\u52A8\u6761\u52A0\u56DE\u6765 -->
|
|
531
|
-
<style>*{scrollbar-width:none}::-webkit-scrollbar{display:none}</style>
|
|
532
|
-
<!-- \u903B\u8F91\u5C42\u5EFA\u7684 2d\u3001webgl \u753B\u5E03\u642C\u8FDB wx-canvas \u540E\u94FA\u6EE1\u5B83\uFF08\u89C1 frame.ts \u7684 moveCanvasesIntoPages\uFF09\u3002
|
|
533
|
-
\u57FA\u7840\u5E93\u8FD8\u4F1A\u6309\u903B\u8F91\u5C42\u91CC\u7684\u5E03\u5C40\u6539\u5B83\u7684\u4F4D\u7F6E\u548C\u663E\u9690\uFF0C\u8FD9\u91CC\u4E00\u5F8B\u538B\u4F4F\uFF1B\u89E6\u6478\u7167\u5E38\u4EA4\u7ED9 wx-canvas \u81EA\u5DF1\u7684 canvas -->
|
|
534
|
-
<style>.wxa-service-canvas{position:absolute!important;left:0!important;top:0!important;width:100%!important;height:100%!important;visibility:inherit!important;pointer-events:none}</style>
|
|
535
|
-
<script>var __wxConfig = ${toJs(wxConfig)};</script>
|
|
536
|
-
<script src="/__wxa__/runtime/frame.js" data-kind="webview" data-webview-id="${id}"></script>
|
|
537
|
-
<script src="/__baselib__/WAWebview.js"></script>
|
|
701
|
+
${webviewHead(build2, pagePath, id)}
|
|
538
702
|
${enableHotUpdate(options.hot)}<script src="/__wxa__/page-frame.js?v=${build2.version}"></script>
|
|
539
|
-
${
|
|
703
|
+
${pageWindow(build2, pagePath).disableScroll ? "<style>body{overflow-y:hidden}</style>" : ""}
|
|
540
704
|
</head>
|
|
541
705
|
<body>
|
|
542
706
|
<script>
|
|
@@ -556,6 +720,58 @@ ${window.disableScroll ? "<style>body{overflow-y:hidden}</style>" : ""}
|
|
|
556
720
|
</body>
|
|
557
721
|
</html>`;
|
|
558
722
|
}
|
|
723
|
+
function workerScript(build2, baseLib) {
|
|
724
|
+
const modules = build2.workerModules.map((id) => `/__wxa__/module/${encodeURI(id)}?v=${build2.version}`);
|
|
725
|
+
const prelude = `var __wxConfig = ${toJs(build2.wxConfig)};
|
|
726
|
+
importScripts('/__wxa__/runtime/worker.js');
|
|
727
|
+
`;
|
|
728
|
+
if (!baseLib.hasWorker) {
|
|
729
|
+
const message = `[wxa-runner] \u57FA\u7840\u5E93 ${baseLib.version} \u91CC\u6CA1\u6709 WAWorker.js\uFF0CWorker \u4E0D\u80FD\u8FD0\u884C\u3002\u6362\u7528\u5F00\u53D1\u8005\u5DE5\u5177\u4E0B\u8F7D\u7684\u57FA\u7840\u5E93\uFF0C\u6216\u5347\u7EA7 wxa-runner \u5E26\u4E0A\u65B0\u7684\u5185\u7F6E\u57FA\u7840\u5E93`;
|
|
730
|
+
return `${prelude}throw new Error(${toJs(message)});
|
|
731
|
+
`;
|
|
732
|
+
}
|
|
733
|
+
return `${prelude}var __wxaConsole = self.console;
|
|
734
|
+
importScripts('/__baselib__/WAWorker.js');
|
|
735
|
+
self.console = __wxaConsole;
|
|
736
|
+
importScripts(${modules.map((url) => toJs(url)).join(", ")});
|
|
737
|
+
`;
|
|
738
|
+
}
|
|
739
|
+
function pluginWebviewHtml(build2, plugin, innerPath, pagePath, webviewId) {
|
|
740
|
+
const id = Number(webviewId) || 0;
|
|
741
|
+
const page = plugin.files.get(`/${innerPath}.html`)?.toString("utf8") ?? `<script>console.error(${JSON.stringify(`[wxa-runner] \u63D2\u4EF6 ${plugin.alias} \u91CC\u6CA1\u6709\u9875\u9762 ${innerPath}`)})</script>`;
|
|
742
|
+
return `<!DOCTYPE html>
|
|
743
|
+
<html>
|
|
744
|
+
<head>
|
|
745
|
+
${webviewHead(build2, pagePath, id)}
|
|
746
|
+
<script src="${pluginScriptUrl(plugin, "pageframe.js")}"></script>
|
|
747
|
+
${pageWindow(build2, pagePath).disableScroll ? "<style>body{overflow-y:hidden}</style>" : ""}
|
|
748
|
+
</head>
|
|
749
|
+
<body>
|
|
750
|
+
${page}
|
|
751
|
+
<script>parent.__wxaHost.frameLoaded('webview', ${id});</script>
|
|
752
|
+
</body>
|
|
753
|
+
</html>`;
|
|
754
|
+
}
|
|
755
|
+
function pageWindow(build2, pagePath) {
|
|
756
|
+
return { ...build2.wxConfig.global?.window, ...build2.wxConfig.page?.[pagePath + ".html"]?.window };
|
|
757
|
+
}
|
|
758
|
+
function webviewHead(build2, pagePath, id) {
|
|
759
|
+
const wxConfig = { ...build2.wxConfig, window: pageWindow(build2, pagePath) };
|
|
760
|
+
return `<meta charset="utf-8">
|
|
761
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
|
762
|
+
<title>${escapeHtml(pagePath)}</title>
|
|
763
|
+
<!-- \u5C0F\u7A0B\u5E8F\u6E32\u67D3\u5C42\u7684\u9ED8\u8BA4\u5B57\u53F7\u662F 16px\uFF1B\u4E0D\u58F0\u660E\u7684\u8BDD\u4F1A\u7EE7\u627F\u6D4F\u89C8\u5668\u8BBE\u7F6E\u91CC\u7684\u9ED8\u8BA4\u5B57\u53F7\u3002\u653E\u5728\u6700\u524D\u9762\uFF0C\u57FA\u7840\u5E93\u548C\u9875\u9762\u6837\u5F0F\u90FD\u80FD\u8986\u76D6\u5B83 -->
|
|
764
|
+
<style>html{font-size:16px}</style>
|
|
765
|
+
<!-- \u771F\u673A\u7684\u6EDA\u52A8\u6761\u662F\u4E0D\u5360\u5E03\u5C40\u7684\u6D6E\u5C42\uFF1B\u684C\u9762\u6D4F\u89C8\u5668\u7684\u5E38\u89C4\u6EDA\u52A8\u6761\u548C\u81EA\u5B9A\u4E49 ::-webkit-scrollbar \u4F1A\u6324\u7A84\u9875\u9762\uFF0C\u4E00\u5F8B\u9690\u85CF\u3002
|
|
766
|
+
scrollbar-width \u4F18\u5148\u4E8E ::-webkit-scrollbar\uFF0C\u9875\u9762\u6837\u5F0F\u4E0D\u4F1A\u518D\u628A\u6EDA\u52A8\u6761\u52A0\u56DE\u6765 -->
|
|
767
|
+
<style>*{scrollbar-width:none}::-webkit-scrollbar{display:none}</style>
|
|
768
|
+
<!-- \u903B\u8F91\u5C42\u5EFA\u7684 2d\u3001webgl \u753B\u5E03\u642C\u8FDB wx-canvas \u540E\u94FA\u6EE1\u5B83\uFF08\u89C1 frame.ts \u7684 moveCanvasesIntoPages\uFF09\u3002
|
|
769
|
+
\u57FA\u7840\u5E93\u8FD8\u4F1A\u6309\u903B\u8F91\u5C42\u91CC\u7684\u5E03\u5C40\u6539\u5B83\u7684\u4F4D\u7F6E\u548C\u663E\u9690\uFF0C\u8FD9\u91CC\u4E00\u5F8B\u538B\u4F4F\uFF1B\u89E6\u6478\u7167\u5E38\u4EA4\u7ED9 wx-canvas \u81EA\u5DF1\u7684 canvas -->
|
|
770
|
+
<style>.wxa-service-canvas{position:absolute!important;left:0!important;top:0!important;width:100%!important;height:100%!important;visibility:inherit!important;pointer-events:none}</style>
|
|
771
|
+
<script>var __wxConfig = ${toJs(wxConfig)};</script>
|
|
772
|
+
<script src="/__wxa__/runtime/frame.js" data-kind="webview" data-webview-id="${id}"></script>
|
|
773
|
+
<script src="/__baselib__/WAWebview.js"></script>`;
|
|
774
|
+
}
|
|
559
775
|
function escapeHtml(text) {
|
|
560
776
|
return text.replace(/[&<>"]/g, (ch) => ({ "&": "&", "<": "<", ">": ">", '"': """ })[ch]);
|
|
561
777
|
}
|
|
@@ -661,7 +877,7 @@ import { execFile } from "child_process";
|
|
|
661
877
|
import { randomUUID } from "crypto";
|
|
662
878
|
import { setTimeout as sleep } from "timers/promises";
|
|
663
879
|
import { WebSocket } from "ws";
|
|
664
|
-
import { findDeveloperTicket, findElectronDevtoolsCli, TICKET_ENV } from "@open-wxa/wxa-runner-extractor";
|
|
880
|
+
import { findDeveloperTicket, findElectronDevtoolsCli, TICKET_ENV as TICKET_ENV2 } from "@open-wxa/wxa-runner-extractor";
|
|
665
881
|
var AUTO_PORT = 9420;
|
|
666
882
|
var CLI_TIMEOUT = 6e4;
|
|
667
883
|
var AUTOMATOR_TIMEOUT = 5e3;
|
|
@@ -674,7 +890,7 @@ function developerTicketSource(projectPath, logger) {
|
|
|
674
890
|
const startOnce = () => {
|
|
675
891
|
if (!automatorPort) {
|
|
676
892
|
const starting = startAutomation(cli, projectPath).then((port) => {
|
|
677
|
-
logger.log(`[wxa-runner] \
|
|
893
|
+
logger.log(`[wxa-runner] --devtools-login\uFF1A\u5DF2\u5728\u5FAE\u4FE1\u5F00\u53D1\u8005\u5DE5\u5177\u91CC\u4E3A\u9879\u76EE\u5F00\u542F\u81EA\u52A8\u5316\u63A5\u53E3\uFF08\u7AEF\u53E3 ${port}\uFF09\uFF0Cticket \u4ECE\u5F00\u53D1\u8005\u5DE5\u5177\u5B9E\u65F6\u83B7\u53D6`);
|
|
678
894
|
return port;
|
|
679
895
|
});
|
|
680
896
|
starting.catch(() => {
|
|
@@ -685,7 +901,7 @@ function developerTicketSource(projectPath, logger) {
|
|
|
685
901
|
return automatorPort;
|
|
686
902
|
};
|
|
687
903
|
return async () => {
|
|
688
|
-
if (process.env[
|
|
904
|
+
if (process.env[TICKET_ENV2]) return { newticket: process.env[TICKET_ENV2] };
|
|
689
905
|
const port = startOnce();
|
|
690
906
|
try {
|
|
691
907
|
return await requestTicketOnceWindowReady(await port, projectPath);
|
|
@@ -790,74 +1006,62 @@ function explainAutomatorError(message) {
|
|
|
790
1006
|
return new Error(`\u5FAE\u4FE1\u5F00\u53D1\u8005\u5DE5\u5177\u8FD4\u56DE\u9519\u8BEF\uFF1A${message}`);
|
|
791
1007
|
}
|
|
792
1008
|
|
|
793
|
-
// src/server/
|
|
1009
|
+
// src/server/devtoolsLogin.ts
|
|
794
1010
|
import express from "express";
|
|
795
|
-
import { findDeveloperTicket as findDeveloperTicket2
|
|
796
|
-
var DEV_LOGIC = "https://servicewechat.com/wxa-dev-logic";
|
|
797
|
-
var CLIENT_VERSION = "1021810240";
|
|
798
|
-
var UPSTREAM_TIMEOUT = 1e4;
|
|
1011
|
+
import { findDeveloperTicket as findDeveloperTicket2 } from "@open-wxa/wxa-runner-extractor";
|
|
799
1012
|
var LOOPBACK_ADDRESSES = ["127.0.0.1", "::1", "::ffff:127.0.0.1"];
|
|
800
1013
|
var LOOPBACK_HOSTS = ["localhost", "127.0.0.1", "[::1]"];
|
|
801
|
-
var
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
40029: "\uFF08\u767B\u5F55\u6001\u5DF2\u5931\u6548\uFF0C\u8BF7\u5728\u5FAE\u4FE1\u5F00\u53D1\u8005\u5DE5\u5177\u91CC\u91CD\u65B0\u767B\u5F55\uFF09",
|
|
805
|
-
85023: "\uFF08\u5F53\u524D\u5FAE\u4FE1\u8D26\u53F7\u4E0D\u662F\u8BE5\u5C0F\u7A0B\u5E8F\u7684\u5F00\u53D1\u8005\uFF09"
|
|
806
|
-
};
|
|
807
|
-
function requireUsableTicket(ticket) {
|
|
808
|
-
if (!ticket) throw new Error(`\u672A\u627E\u5230\u5FAE\u4FE1\u5F00\u53D1\u8005\u5DE5\u5177\u7684\u767B\u5F55\u6001\uFF0C\u8BF7\u767B\u5F55\u5F00\u53D1\u8005\u5DE5\u5177\uFF0C\u6216\u8BBE\u7F6E\u73AF\u5883\u53D8\u91CF ${TICKET_ENV2}`);
|
|
809
|
-
if (ticket.expiredAt !== void 0 && ticket.expiredAt <= Date.now()) {
|
|
810
|
-
throw new Error("\u5FAE\u4FE1\u5F00\u53D1\u8005\u5DE5\u5177\u7684\u767B\u5F55\u6001\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u6253\u5F00\u5F00\u53D1\u8005\u5DE5\u5177\u5237\u65B0\u767B\u5F55\u6001");
|
|
811
|
-
}
|
|
812
|
-
return ticket.newticket;
|
|
813
|
-
}
|
|
814
|
-
function realLoginRouter(appid, findTicket = findDeveloperTicket2) {
|
|
815
|
-
const callDevLogic = async (endpoint, body) => {
|
|
816
|
-
const query = new URLSearchParams({ appid, newticket: requireUsableTicket(await findTicket()), clientversion: CLIENT_VERSION });
|
|
817
|
-
const response = await fetch(`${DEV_LOGIC}/${endpoint}?${query}`, {
|
|
818
|
-
method: "POST",
|
|
819
|
-
headers: { "Content-Type": "application/json" },
|
|
820
|
-
body: JSON.stringify(body),
|
|
821
|
-
signal: AbortSignal.timeout(UPSTREAM_TIMEOUT)
|
|
822
|
-
}).catch((error) => {
|
|
823
|
-
throw new Error(error.name === "TimeoutError" ? `\u8BF7\u6C42\u5FAE\u4FE1\u670D\u52A1\u5668\u8D85\u65F6\uFF08${UPSTREAM_TIMEOUT / 1e3}s\uFF09` : `\u8BF7\u6C42\u5FAE\u4FE1\u670D\u52A1\u5668\u5931\u8D25\uFF1A${error.cause?.message ?? error.message}`);
|
|
824
|
-
});
|
|
825
|
-
if (!response.ok) throw new Error(`\u5FAE\u4FE1\u670D\u52A1\u5668\u8FD4\u56DE HTTP ${response.status}`);
|
|
826
|
-
return response.json();
|
|
827
|
-
};
|
|
1014
|
+
var FORWARDED_WX_DATA_APIS = ["webapi_servicemarket_jsapi_comm"];
|
|
1015
|
+
function devtoolsLoginRouter(appid, findTicket = findDeveloperTicket2) {
|
|
1016
|
+
const wechat = new WechatDevClient(appid, findTicket);
|
|
828
1017
|
const router = express.Router();
|
|
829
1018
|
router.use(onlyLoopback);
|
|
830
1019
|
router.post("/login", respond(async () => {
|
|
831
|
-
const body = await
|
|
832
|
-
|
|
833
|
-
if (errcode !== 0 || !body.code) {
|
|
834
|
-
throw new Error(`\u5FAE\u4FE1\u767B\u5F55\u5931\u8D25 ${errcode}: ${body.baseresponse?.errmsg || "\u672A\u77E5\u9519\u8BEF"}${ERROR_HINTS[errcode] ?? ""}`);
|
|
835
|
-
}
|
|
1020
|
+
const body = requireOk(await wechat.postJson("wxa-dev-logic/jslogin", { scope: ["snsapi_base"] }), "\u5FAE\u4FE1\u767B\u5F55\u5931\u8D25");
|
|
1021
|
+
if (!body.code) throw new Error("\u5FAE\u4FE1\u767B\u5F55\u5931\u8D25\uFF1A\u5FAE\u4FE1\u6CA1\u6709\u8FD4\u56DE code");
|
|
836
1022
|
return { code: body.code };
|
|
837
1023
|
}));
|
|
838
1024
|
router.post("/phone-number", respond(async () => {
|
|
839
|
-
const body = await
|
|
1025
|
+
const body = await wechat.postJson("wxa-dev-logic/jsgetuserwxphone", { appid });
|
|
840
1026
|
const errcode = body.jsapi_baseresponse?.errcode ?? body.BaseResponse?.Ret;
|
|
841
1027
|
if (errcode !== 0 || typeof body.data !== "string") {
|
|
842
1028
|
const errmsg = body.jsapi_baseresponse?.errmsg || body.BaseResponse?.ErrMsg?.String || "\u672A\u77E5\u9519\u8BEF";
|
|
843
|
-
throw new Error(`\u83B7\u53D6\u624B\u673A\u53F7\u5931\u8D25 ${errcode}: ${errmsg}${
|
|
1029
|
+
throw new Error(`\u83B7\u53D6\u624B\u673A\u53F7\u5931\u8D25 ${errcode}: ${errmsg}${explainErrcode(errcode)}`);
|
|
844
1030
|
}
|
|
845
1031
|
const { encryptedData, iv } = JSON.parse(body.data);
|
|
846
1032
|
return { data: body.data, encryptedData, iv };
|
|
847
1033
|
}));
|
|
1034
|
+
router.post("/operate-wx-data", express.json({ limit: "10mb" }), (req, res, next) => {
|
|
1035
|
+
const apiName = req.body?.data?.api_name;
|
|
1036
|
+
if (FORWARDED_WX_DATA_APIS.includes(apiName)) return next();
|
|
1037
|
+
res.status(403).json({ error: `operateWXData \u53EA\u8F6C\u53D1\u670D\u52A1\u5E02\u573A\u7684\u8BF7\u6C42\uFF0C\u4E0D\u8F6C\u53D1 ${apiName}` });
|
|
1038
|
+
}, respond(async (req) => {
|
|
1039
|
+
const body = requireOk(await wechat.postJson("wxa-dev-logic/jsoperatewxdata", { data: JSON.stringify(req.body.data) }), "\u670D\u52A1\u5E02\u573A\u8C03\u7528\u5931\u8D25");
|
|
1040
|
+
if (typeof body.data !== "string") throw new Error("\u670D\u52A1\u5E02\u573A\u8C03\u7528\u5931\u8D25\uFF1A\u5FAE\u4FE1\u6CA1\u6709\u8FD4\u56DE\u7ED3\u679C");
|
|
1041
|
+
return { data: JSON.parse(body.data) };
|
|
1042
|
+
}));
|
|
1043
|
+
router.post("/verify-plugin", express.json(), respond(async (req) => {
|
|
1044
|
+
const body = requireOk(await wechat.postJson("wxa-dev-logic/verifyplugin", { ext_info: JSON.stringify(req.body?.data || {}) }), "\u63D2\u4EF6\u6821\u9A8C\u5931\u8D25");
|
|
1045
|
+
return { data: { list: body.list || [] } };
|
|
1046
|
+
}));
|
|
1047
|
+
router.post("/batch-get-contact", express.json(), respond(async (req) => {
|
|
1048
|
+
const body = requireOk(await wechat.postJson("wxa-dev-logic/batchgetcontact", { appid_list: req.body?.appIds || [] }), "\u83B7\u53D6\u63D2\u4EF6\u4FE1\u606F\u5931\u8D25");
|
|
1049
|
+
const contacts = body.contact_list || [];
|
|
1050
|
+
return { contactList: contacts.filter((contact) => contact.plugin_info).map((contact) => ({ appId: contact.appid, plugin_list: contact.plugin_info.plugin_list })) };
|
|
1051
|
+
}));
|
|
848
1052
|
return router;
|
|
849
1053
|
}
|
|
850
1054
|
function onlyLoopback(req, res, next) {
|
|
851
1055
|
if (!LOOPBACK_ADDRESSES.includes(req.socket.remoteAddress || "") || !LOOPBACK_HOSTS.includes(req.hostname)) {
|
|
852
|
-
res.status(403).json({ error: "\
|
|
1056
|
+
res.status(403).json({ error: "\u5F00\u53D1\u8005\u767B\u5F55\u6001\u63A5\u53E3\u53EA\u5141\u8BB8\u672C\u673A\u8BBF\u95EE" });
|
|
853
1057
|
return;
|
|
854
1058
|
}
|
|
855
1059
|
next();
|
|
856
1060
|
}
|
|
857
1061
|
function respond(action) {
|
|
858
|
-
return async (
|
|
1062
|
+
return async (req, res) => {
|
|
859
1063
|
try {
|
|
860
|
-
res.json(await action());
|
|
1064
|
+
res.json(await action(req));
|
|
861
1065
|
} catch (error) {
|
|
862
1066
|
res.status(500).json({ error: error.message });
|
|
863
1067
|
}
|
|
@@ -992,7 +1196,12 @@ var DevServer = class {
|
|
|
992
1196
|
if (!this.baseLib.compatible) {
|
|
993
1197
|
this.logger.warn(`[wxa-runner] \u57FA\u7840\u5E93 ${this.baseLib.version} \u9AD8\u4E8E\u5DF2\u9A8C\u8BC1\u7684\u7248\u672C\u8303\u56F4\uFF0C\u53EF\u80FD\u65E0\u6CD5\u6B63\u5E38\u8FD0\u884C`);
|
|
994
1198
|
}
|
|
995
|
-
|
|
1199
|
+
if (options.realLogin !== void 0 && options.devtoolsLogin === void 0) {
|
|
1200
|
+
this.logger.warn("[wxa-runner] realLogin\uFF08--real-login\uFF09\u5DF2\u6539\u540D\u4E3A devtoolsLogin\uFF08--devtools-login\uFF09\uFF0C\u65E7\u540D\u4EE5\u540E\u4F1A\u79FB\u9664");
|
|
1201
|
+
}
|
|
1202
|
+
this.devtoolsLogin = (options.devtoolsLogin ?? options.realLogin) === true;
|
|
1203
|
+
this.ticketSource = this.devtoolsLogin ? developerTicketSource(this.project.projectPath, this.logger) : null;
|
|
1204
|
+
this.plugins = new PluginStore(this.ticketSource && new WechatDevClient(this.project.appid, this.ticketSource), this.logger);
|
|
996
1205
|
this.device = { ...DEFAULT_DEVICE, ...options.device };
|
|
997
1206
|
this.builder = new AppBuilder(this.project);
|
|
998
1207
|
this.setupFile = resolveSetupFile(options.setup, this.project.projectPath);
|
|
@@ -1028,7 +1237,7 @@ ${error.message}`);
|
|
|
1028
1237
|
const { port } = server.address();
|
|
1029
1238
|
this.address = `http://${host}:${port}`;
|
|
1030
1239
|
if (this.options.watch !== false) this.startWatching();
|
|
1031
|
-
this.ticketSource?.().then(requireUsableTicket).catch((error) => this.logger.warn(`[wxa-runner] \
|
|
1240
|
+
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}`));
|
|
1032
1241
|
return this.address;
|
|
1033
1242
|
}
|
|
1034
1243
|
async close() {
|
|
@@ -1055,9 +1264,9 @@ ${error.message}`);
|
|
|
1055
1264
|
});
|
|
1056
1265
|
app.get("/__wxa__/app-info.json", async (_req, res) => {
|
|
1057
1266
|
noStore(res);
|
|
1058
|
-
const base = { appid: this.project.appid, baseLibVersion: this.baseLib.version, device: this.device,
|
|
1267
|
+
const base = { appid: this.project.appid, baseLibVersion: this.baseLib.version, device: this.device, devtoolsLogin: this.devtoolsLogin };
|
|
1059
1268
|
try {
|
|
1060
|
-
const build2 = await this.builder.build();
|
|
1269
|
+
const build2 = await this.plugins.refresh(await this.builder.build());
|
|
1061
1270
|
const info = { ...base, version: build2.version, wxConfig: build2.wxConfig, pages: build2.pages };
|
|
1062
1271
|
if (this.setupFile) info.setup = await this.setupInfo(this.setupFile);
|
|
1063
1272
|
res.json(info);
|
|
@@ -1093,16 +1302,32 @@ ${error.message}`);
|
|
|
1093
1302
|
app.get(/^\/__wxa__\/webview\/(.+)\.html$/, this.withBuild((build2, req, res, next) => {
|
|
1094
1303
|
const pagePath = decodeURIComponent(req.params[0]);
|
|
1095
1304
|
if (!build2.pages.includes(pagePath)) return next();
|
|
1096
|
-
|
|
1305
|
+
const pluginPage = findPluginPage(build2, pagePath);
|
|
1306
|
+
res.type("html").send(pluginPage ? pluginWebviewHtml(build2, pluginPage.plugin, pluginPage.innerPath, pagePath, Number(req.query.id)) : webviewHtml(build2, pagePath, Number(req.query.id), { hot: this.hotEnabled }));
|
|
1307
|
+
}));
|
|
1308
|
+
app.get("/__wxa__/plugin/:provider/:version/:file(appservice.js|pageframe.js)", this.withBuild((build2, req, res, next) => {
|
|
1309
|
+
const { provider, version, file } = req.params;
|
|
1310
|
+
const code = build2.plugins.find((plugin) => plugin.provider === provider && plugin.version === version)?.files.get(`/${file}`);
|
|
1311
|
+
if (!code) return next();
|
|
1312
|
+
res.type("js").send(code);
|
|
1313
|
+
}));
|
|
1314
|
+
app.get(/^\/__plugin__\/([^/]+)(\/.+)$/, this.withBuild((build2, req, res, next) => {
|
|
1315
|
+
const file = build2.plugins.find((plugin) => plugin.provider === req.params[0])?.files.get(decodeURIComponent(req.params[1]));
|
|
1316
|
+
if (!file) return next();
|
|
1317
|
+
res.type(path4.extname(req.params[1]) || "application/octet-stream").send(file);
|
|
1097
1318
|
}));
|
|
1098
1319
|
app.get(/^\/__wxa__\/module\/(.+\.js)$/, this.withBuild((build2, req, res) => {
|
|
1099
1320
|
const id = decodeURIComponent(req.params[0]);
|
|
1100
|
-
if (!build2.modules.includes(id)) {
|
|
1321
|
+
if (!build2.modules.includes(id) && !build2.workerModules.includes(id)) {
|
|
1101
1322
|
res.status(404).type("js").send(`console.error(${JSON.stringify(`[wxa-runner] \u6A21\u5757 ${id} \u4E0D\u5B58\u5728`)})`);
|
|
1102
1323
|
return;
|
|
1103
1324
|
}
|
|
1104
1325
|
res.type("js").send(this.builder.getModuleScript(id));
|
|
1105
1326
|
}));
|
|
1327
|
+
app.get("/__wxa__/worker.js", this.withBuild((build2, _req, res) => {
|
|
1328
|
+
const hasWorker = fs4.existsSync(path4.join(this.baseLib.dir, "WAWorker.js"));
|
|
1329
|
+
res.type("js").send(workerScript(build2, { version: this.baseLib.version, hasWorker }));
|
|
1330
|
+
}));
|
|
1106
1331
|
app.get("/__wxa__/service-bootstrap.js", this.withBuild((build2, _req, res) => {
|
|
1107
1332
|
res.type("js").send(build2.serviceBootstrap);
|
|
1108
1333
|
}));
|
|
@@ -1178,7 +1403,7 @@ ${error.message}`);
|
|
|
1178
1403
|
app.delete("/__wxa__/tmp/:name", (req, res) => {
|
|
1179
1404
|
res.status(this.tempFiles.delete(req.params.name) ? 204 : 404).end();
|
|
1180
1405
|
});
|
|
1181
|
-
if (this.ticketSource) app.use("/__wxa__/api",
|
|
1406
|
+
if (this.ticketSource) app.use("/__wxa__/api", devtoolsLoginRouter(this.project.appid, this.ticketSource));
|
|
1182
1407
|
app.use("/__wxa__/webview", express2.static(root));
|
|
1183
1408
|
app.use(express2.static(root));
|
|
1184
1409
|
app.use((error, _req, res, _next) => {
|
|
@@ -1196,13 +1421,17 @@ ${error.message}`);
|
|
|
1196
1421
|
return { env: this.setupEnv, error: error.message };
|
|
1197
1422
|
}
|
|
1198
1423
|
}
|
|
1424
|
+
/** 构建结果并入这次打开小程序时决定用的插件 */
|
|
1425
|
+
async currentBuild() {
|
|
1426
|
+
return this.plugins.current(await this.builder.build());
|
|
1427
|
+
}
|
|
1199
1428
|
/** 需要构建结果的路由;构建失败时返回错误文本 */
|
|
1200
1429
|
withBuild(handler) {
|
|
1201
1430
|
return async (req, res, next) => {
|
|
1202
1431
|
res.setHeader("Cache-Control", "no-store");
|
|
1203
1432
|
let build2;
|
|
1204
1433
|
try {
|
|
1205
|
-
build2 = await this.
|
|
1434
|
+
build2 = await this.currentBuild();
|
|
1206
1435
|
} catch (error) {
|
|
1207
1436
|
res.status(500).type("text").send(error.message);
|
|
1208
1437
|
return;
|