@open-wxa/wxa-runner-core 0.6.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 +15 -6
- package/dist/index.d.ts +15 -6
- package/dist/index.js +280 -78
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +274 -72
- package/dist/index.mjs.map +1 -1
- package/dist/runtime/host.js +30 -12
- package/dist/runtime/host.js.map +1 -1
- 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.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ResolvedBaseLib } from '@open-wxa/wxa-runner-extractor';
|
|
2
|
-
import { D as DeviceProfile } from './setup-
|
|
3
|
-
export { A as ApiContext, a as ApiHandler, b as ApiResult, c as AppInfo, M as MockConfig, d as MockRequest, e as MockResponse, f as MockValue, N as NetworkConfig, R as RouteHandler, S as SetupApi, g as SetupConfig, h as SetupContext, i as SetupDefinition } from './setup-
|
|
4
|
-
export { F as FrameError, P as PageSnapshot, R as RecordedRequest, W as WxaTestApi } from './testApi-
|
|
2
|
+
import { D as DeviceProfile } from './setup-DZ5FeKay.mjs';
|
|
3
|
+
export { A as ApiContext, a as ApiHandler, b as ApiResult, c as AppInfo, M as MockConfig, d as MockRequest, e as MockResponse, f as MockValue, N as NetworkConfig, R as RouteHandler, S as SetupApi, g as SetupConfig, h as SetupContext, i as SetupDefinition } from './setup-DZ5FeKay.mjs';
|
|
4
|
+
export { F as FrameError, P as PageSnapshot, R as RecordedRequest, W as WxaTestApi } from './testApi-CnZOLyWw.mjs';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* 小程序项目结构解析
|
|
@@ -170,7 +170,7 @@ declare class AppBuilder {
|
|
|
170
170
|
* /__wxa__/proxy?url= 网络代理
|
|
171
171
|
* /__wxa__/tmp 临时文件:POST ?type=png 保存,返回可直接访问的地址(GET 支持分段请求);对该地址 HEAD 查大小、DELETE 删除
|
|
172
172
|
* /__wxa__/region/<kind> 地区选择器用的行政区划数据(districts / streets),取自本机开发者工具
|
|
173
|
-
* /__wxa__/api/*
|
|
173
|
+
* /__wxa__/api/* --devtools-login:wx.login 的 code、手机号,服务市场、插件的请求转发,只允许本机访问
|
|
174
174
|
* /__wxa__/ws 文件变化通知:热更新(hot)或整页刷新(reload)
|
|
175
175
|
* 其余路径 小程序目录下的静态资源
|
|
176
176
|
*/
|
|
@@ -192,7 +192,12 @@ interface DevServerOptions {
|
|
|
192
192
|
setup?: string | false;
|
|
193
193
|
/** 浏览器端运行时(host.js / frame.js)所在目录,默认取构建产物 */
|
|
194
194
|
runtimeDir?: string;
|
|
195
|
-
/**
|
|
195
|
+
/**
|
|
196
|
+
* 借本机微信开发者工具的登录态访问微信后台:真实的 wx.login code 和手机号、服务市场、插件。
|
|
197
|
+
* 要先登录开发者工具,会真实请求微信
|
|
198
|
+
*/
|
|
199
|
+
devtoolsLogin?: boolean;
|
|
200
|
+
/** @deprecated 改名为 devtoolsLogin */
|
|
196
201
|
realLogin?: boolean;
|
|
197
202
|
logger?: Pick<Console, 'log' | 'warn' | 'error'>;
|
|
198
203
|
}
|
|
@@ -214,8 +219,10 @@ declare class DevServer {
|
|
|
214
219
|
private address;
|
|
215
220
|
/** 运行时生成的临时文件(canvas 导出、拍照等),随服务器进程存在 */
|
|
216
221
|
private readonly tempFiles;
|
|
217
|
-
|
|
222
|
+
private readonly devtoolsLogin;
|
|
223
|
+
/** 开启 --devtools-login 时才有 */
|
|
218
224
|
private readonly ticketSource;
|
|
225
|
+
private readonly plugins;
|
|
219
226
|
constructor(options: DevServerOptions);
|
|
220
227
|
get url(): string;
|
|
221
228
|
start(): Promise<string>;
|
|
@@ -223,6 +230,8 @@ declare class DevServer {
|
|
|
223
230
|
private createApp;
|
|
224
231
|
/** 先编译一遍 setup:编译错误随 app-info 交给宿主显示,而不是让浏览器 import 失败 */
|
|
225
232
|
private setupInfo;
|
|
233
|
+
/** 构建结果并入这次打开小程序时决定用的插件 */
|
|
234
|
+
private currentBuild;
|
|
226
235
|
/** 需要构建结果的路由;构建失败时返回错误文本 */
|
|
227
236
|
private withBuild;
|
|
228
237
|
private runtimeDir;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ResolvedBaseLib } from '@open-wxa/wxa-runner-extractor';
|
|
2
|
-
import { D as DeviceProfile } from './setup-
|
|
3
|
-
export { A as ApiContext, a as ApiHandler, b as ApiResult, c as AppInfo, M as MockConfig, d as MockRequest, e as MockResponse, f as MockValue, N as NetworkConfig, R as RouteHandler, S as SetupApi, g as SetupConfig, h as SetupContext, i as SetupDefinition } from './setup-
|
|
4
|
-
export { F as FrameError, P as PageSnapshot, R as RecordedRequest, W as WxaTestApi } from './testApi-
|
|
2
|
+
import { D as DeviceProfile } from './setup-DZ5FeKay.js';
|
|
3
|
+
export { A as ApiContext, a as ApiHandler, b as ApiResult, c as AppInfo, M as MockConfig, d as MockRequest, e as MockResponse, f as MockValue, N as NetworkConfig, R as RouteHandler, S as SetupApi, g as SetupConfig, h as SetupContext, i as SetupDefinition } from './setup-DZ5FeKay.js';
|
|
4
|
+
export { F as FrameError, P as PageSnapshot, R as RecordedRequest, W as WxaTestApi } from './testApi-BLozOgCt.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* 小程序项目结构解析
|
|
@@ -170,7 +170,7 @@ declare class AppBuilder {
|
|
|
170
170
|
* /__wxa__/proxy?url= 网络代理
|
|
171
171
|
* /__wxa__/tmp 临时文件:POST ?type=png 保存,返回可直接访问的地址(GET 支持分段请求);对该地址 HEAD 查大小、DELETE 删除
|
|
172
172
|
* /__wxa__/region/<kind> 地区选择器用的行政区划数据(districts / streets),取自本机开发者工具
|
|
173
|
-
* /__wxa__/api/*
|
|
173
|
+
* /__wxa__/api/* --devtools-login:wx.login 的 code、手机号,服务市场、插件的请求转发,只允许本机访问
|
|
174
174
|
* /__wxa__/ws 文件变化通知:热更新(hot)或整页刷新(reload)
|
|
175
175
|
* 其余路径 小程序目录下的静态资源
|
|
176
176
|
*/
|
|
@@ -192,7 +192,12 @@ interface DevServerOptions {
|
|
|
192
192
|
setup?: string | false;
|
|
193
193
|
/** 浏览器端运行时(host.js / frame.js)所在目录,默认取构建产物 */
|
|
194
194
|
runtimeDir?: string;
|
|
195
|
-
/**
|
|
195
|
+
/**
|
|
196
|
+
* 借本机微信开发者工具的登录态访问微信后台:真实的 wx.login code 和手机号、服务市场、插件。
|
|
197
|
+
* 要先登录开发者工具,会真实请求微信
|
|
198
|
+
*/
|
|
199
|
+
devtoolsLogin?: boolean;
|
|
200
|
+
/** @deprecated 改名为 devtoolsLogin */
|
|
196
201
|
realLogin?: boolean;
|
|
197
202
|
logger?: Pick<Console, 'log' | 'warn' | 'error'>;
|
|
198
203
|
}
|
|
@@ -214,8 +219,10 @@ declare class DevServer {
|
|
|
214
219
|
private address;
|
|
215
220
|
/** 运行时生成的临时文件(canvas 导出、拍照等),随服务器进程存在 */
|
|
216
221
|
private readonly tempFiles;
|
|
217
|
-
|
|
222
|
+
private readonly devtoolsLogin;
|
|
223
|
+
/** 开启 --devtools-login 时才有 */
|
|
218
224
|
private readonly ticketSource;
|
|
225
|
+
private readonly plugins;
|
|
219
226
|
constructor(options: DevServerOptions);
|
|
220
227
|
get url(): string;
|
|
221
228
|
start(): Promise<string>;
|
|
@@ -223,6 +230,8 @@ declare class DevServer {
|
|
|
223
230
|
private createApp;
|
|
224
231
|
/** 先编译一遍 setup:编译错误随 app-info 交给宿主显示,而不是让浏览器 import 失败 */
|
|
225
232
|
private setupInfo;
|
|
233
|
+
/** 构建结果并入这次打开小程序时决定用的插件 */
|
|
234
|
+
private currentBuild;
|
|
226
235
|
/** 需要构建结果的路由;构建失败时返回错误文本 */
|
|
227
236
|
private withBuild;
|
|
228
237
|
private runtimeDir;
|
package/dist/index.js
CHANGED
|
@@ -45,7 +45,7 @@ var import_http = __toESM(require("http"));
|
|
|
45
45
|
var import_path4 = __toESM(require("path"));
|
|
46
46
|
var import_express2 = __toESM(require("express"));
|
|
47
47
|
var import_ws2 = require("ws");
|
|
48
|
-
var
|
|
48
|
+
var import_wxa_runner_extractor5 = require("@open-wxa/wxa-runner-extractor");
|
|
49
49
|
|
|
50
50
|
// src/project/AppBuilder.ts
|
|
51
51
|
var import_wxa_runner_compiler = require("@open-wxa/wxa-runner-compiler");
|
|
@@ -481,6 +481,178 @@ function readJsonFile(file) {
|
|
|
481
481
|
}
|
|
482
482
|
}
|
|
483
483
|
|
|
484
|
+
// src/server/plugins.ts
|
|
485
|
+
var import_wxa_runner_extractor2 = require("@open-wxa/wxa-runner-extractor");
|
|
486
|
+
|
|
487
|
+
// src/server/wechatDev.ts
|
|
488
|
+
var import_wxa_runner_extractor = require("@open-wxa/wxa-runner-extractor");
|
|
489
|
+
var BASE_URL = "https://servicewechat.com";
|
|
490
|
+
var CLIENT_VERSION = "1021810240";
|
|
491
|
+
var DEFAULT_TIMEOUT = 1e4;
|
|
492
|
+
var ERROR_HINTS = {
|
|
493
|
+
// 40001:开发者工具刷新过 ticket,旧的随即作废
|
|
494
|
+
40001: "\uFF08\u767B\u5F55\u6001\u5DF2\u5931\u6548\uFF0C\u8BF7\u5728\u5FAE\u4FE1\u5F00\u53D1\u8005\u5DE5\u5177\u91CC\u91CD\u65B0\u767B\u5F55\uFF09",
|
|
495
|
+
40029: "\uFF08\u767B\u5F55\u6001\u5DF2\u5931\u6548\uFF0C\u8BF7\u5728\u5FAE\u4FE1\u5F00\u53D1\u8005\u5DE5\u5177\u91CC\u91CD\u65B0\u767B\u5F55\uFF09",
|
|
496
|
+
85023: "\uFF08\u5F53\u524D\u5FAE\u4FE1\u8D26\u53F7\u4E0D\u662F\u8BE5\u5C0F\u7A0B\u5E8F\u7684\u5F00\u53D1\u8005\uFF09"
|
|
497
|
+
};
|
|
498
|
+
function requireUsableTicket(ticket) {
|
|
499
|
+
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 ${import_wxa_runner_extractor.TICKET_ENV}`);
|
|
500
|
+
if (ticket.expiredAt !== void 0 && ticket.expiredAt <= Date.now()) {
|
|
501
|
+
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");
|
|
502
|
+
}
|
|
503
|
+
return ticket.newticket;
|
|
504
|
+
}
|
|
505
|
+
function explainErrcode(errcode) {
|
|
506
|
+
return errcode !== void 0 && ERROR_HINTS[errcode] || "";
|
|
507
|
+
}
|
|
508
|
+
function requireOk(body, action) {
|
|
509
|
+
const errcode = body.baseresponse?.errcode;
|
|
510
|
+
if (errcode !== 0) throw new Error(`${action} ${errcode}: ${body.baseresponse?.errmsg || "\u672A\u77E5\u9519\u8BEF"}${explainErrcode(errcode)}`);
|
|
511
|
+
return body;
|
|
512
|
+
}
|
|
513
|
+
var WechatDevClient = class {
|
|
514
|
+
/**
|
|
515
|
+
* @param findTicket 每次请求都重新取:开发者工具重新登录、切换账号后不用重启服务器
|
|
516
|
+
*/
|
|
517
|
+
constructor(appid, findTicket) {
|
|
518
|
+
this.appid = appid;
|
|
519
|
+
this.findTicket = findTicket;
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* POST JSON 到 path(如 wxa-dev-logic/jslogin),带上 appid 和开发者 ticket
|
|
523
|
+
*
|
|
524
|
+
* @throws 没有可用的登录态、超时、连不上、HTTP 状态不是 2xx 时,消息是给用户看的原因
|
|
525
|
+
*/
|
|
526
|
+
async post(path5, body, timeout = DEFAULT_TIMEOUT) {
|
|
527
|
+
const query = new URLSearchParams({ appid: this.appid, newticket: requireUsableTicket(await this.findTicket()), clientversion: CLIENT_VERSION });
|
|
528
|
+
const response = await fetch(`${BASE_URL}/${path5}?${query}`, {
|
|
529
|
+
method: "POST",
|
|
530
|
+
headers: { "Content-Type": "application/json" },
|
|
531
|
+
body: JSON.stringify(body),
|
|
532
|
+
signal: AbortSignal.timeout(timeout)
|
|
533
|
+
}).catch((error) => {
|
|
534
|
+
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}`);
|
|
535
|
+
});
|
|
536
|
+
if (!response.ok) throw new Error(`\u5FAE\u4FE1\u670D\u52A1\u5668\u8FD4\u56DE HTTP ${response.status}`);
|
|
537
|
+
return response;
|
|
538
|
+
}
|
|
539
|
+
/** 同 post,返回解析后的 JSON */
|
|
540
|
+
async postJson(path5, body) {
|
|
541
|
+
return (await this.post(path5, body)).json();
|
|
542
|
+
}
|
|
543
|
+
};
|
|
544
|
+
|
|
545
|
+
// src/server/plugins.ts
|
|
546
|
+
var DOWNLOAD_TIMEOUT = 3e4;
|
|
547
|
+
var PACKAGE_MAGIC = 190;
|
|
548
|
+
var PluginStore = class {
|
|
549
|
+
/**
|
|
550
|
+
* @param wechat 开启 --devtools-login 时才有,没有时不下载插件
|
|
551
|
+
*/
|
|
552
|
+
constructor(wechat, logger) {
|
|
553
|
+
this.wechat = wechat;
|
|
554
|
+
this.logger = logger;
|
|
555
|
+
/** provider@version → 下载结果;失败的不留,下次打开小程序时重试 */
|
|
556
|
+
this.downloads = /* @__PURE__ */ new Map();
|
|
557
|
+
/**
|
|
558
|
+
* 这次打开小程序时决定用哪些插件。同一次打开的逻辑层、业务模块、渲染层等请求都按它处理:
|
|
559
|
+
* 各自去下载的话,下载失败时每个请求都会重试,结果还可能前后不一,页面列表和逻辑层对不上
|
|
560
|
+
*/
|
|
561
|
+
this.selection = null;
|
|
562
|
+
/** 没开 --devtools-login 的提示每个插件只说一次 */
|
|
563
|
+
this.warned = /* @__PURE__ */ new Set();
|
|
564
|
+
}
|
|
565
|
+
/** 打开小程序时(宿主取 app-info)调用:重新决定用哪些插件,下载过的直接用,上次失败的重试 */
|
|
566
|
+
async refresh(build2) {
|
|
567
|
+
this.selection = this.select(build2);
|
|
568
|
+
return withPlugins(build2, await this.selection);
|
|
569
|
+
}
|
|
570
|
+
/** 其余请求沿用这次打开时的决定,不触发下载;还没决定过时(如直接请求逻辑层)先决定一次 */
|
|
571
|
+
async current(build2) {
|
|
572
|
+
this.selection ??= this.select(build2);
|
|
573
|
+
return withPlugins(build2, await this.selection);
|
|
574
|
+
}
|
|
575
|
+
/** app.json 声明的插件;下载不了的跳过,在终端说明原因,小程序自己的页面照常可用 */
|
|
576
|
+
async select(build2) {
|
|
577
|
+
const declared = build2.wxConfig.plugins || {};
|
|
578
|
+
const results = await Promise.all(Object.entries(declared).map(
|
|
579
|
+
([alias, { provider, version }]) => provider && version ? this.load(alias, provider, version) : null
|
|
580
|
+
));
|
|
581
|
+
return results.filter((plugin) => !!plugin);
|
|
582
|
+
}
|
|
583
|
+
async load(alias, provider, version) {
|
|
584
|
+
const label = `\u63D2\u4EF6 ${alias}\uFF08${provider}@${version}\uFF09`;
|
|
585
|
+
if (!this.wechat) {
|
|
586
|
+
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`);
|
|
587
|
+
return null;
|
|
588
|
+
}
|
|
589
|
+
const key = `${provider}@${version}`;
|
|
590
|
+
let download = this.downloads.get(key);
|
|
591
|
+
if (!download) {
|
|
592
|
+
download = this.download(this.wechat, alias, provider, version);
|
|
593
|
+
this.downloads.set(key, download);
|
|
594
|
+
download.catch(() => this.downloads.delete(key));
|
|
595
|
+
}
|
|
596
|
+
try {
|
|
597
|
+
return await download;
|
|
598
|
+
} catch (error) {
|
|
599
|
+
this.logger.warn(`[wxa-runner] ${label} \u4E0B\u8F7D\u5931\u8D25\uFF1A${error.message}`);
|
|
600
|
+
return null;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
/** @throws 没有登录态、连不上、微信拒绝或返回的不是插件代码包时,消息是原因 */
|
|
604
|
+
async download(wechat, alias, provider, version) {
|
|
605
|
+
const response = await wechat.post("wxa-dev/getplugincode", { plugin_id: provider, plugin_version: version }, DOWNLOAD_TIMEOUT);
|
|
606
|
+
const data = Buffer.from(await response.arrayBuffer());
|
|
607
|
+
if (data[0] !== PACKAGE_MAGIC) {
|
|
608
|
+
let body = {};
|
|
609
|
+
try {
|
|
610
|
+
body = JSON.parse(data.toString("utf8"));
|
|
611
|
+
} catch {
|
|
612
|
+
}
|
|
613
|
+
if (body.baseresponse?.errcode) requireOk(body, "\u5FAE\u4FE1\u62D2\u7EDD\u4E0B\u8F7D");
|
|
614
|
+
throw new Error("\u5FAE\u4FE1\u6CA1\u6709\u8FD4\u56DE\u63D2\u4EF6\u4EE3\u7801");
|
|
615
|
+
}
|
|
616
|
+
const files = new Map((0, import_wxa_runner_extractor2.readWxvpkgIndex)(data).map((entry) => [entry.name, Buffer.from((0, import_wxa_runner_extractor2.readWxvpkgFile)(data, entry))]));
|
|
617
|
+
const pluginJson = JSON.parse(files.get("/plugin.json")?.toString("utf8") || "{}");
|
|
618
|
+
return {
|
|
619
|
+
alias,
|
|
620
|
+
provider,
|
|
621
|
+
version,
|
|
622
|
+
files,
|
|
623
|
+
pages: Object.values(pluginJson.pages || {}),
|
|
624
|
+
pageConfigs: pluginJson.page || {}
|
|
625
|
+
};
|
|
626
|
+
}
|
|
627
|
+
warnOnce(key, message) {
|
|
628
|
+
if (this.warned.has(key)) return;
|
|
629
|
+
this.warned.add(key);
|
|
630
|
+
this.logger.warn(message);
|
|
631
|
+
}
|
|
632
|
+
};
|
|
633
|
+
function withPlugins(build2, plugins) {
|
|
634
|
+
if (!plugins.length) return { ...build2, plugins };
|
|
635
|
+
return {
|
|
636
|
+
...build2,
|
|
637
|
+
plugins,
|
|
638
|
+
pages: [...build2.pages, ...plugins.flatMap((plugin) => plugin.pages)],
|
|
639
|
+
wxConfig: {
|
|
640
|
+
...build2.wxConfig,
|
|
641
|
+
page: { ...build2.wxConfig.page, ...Object.assign({}, ...plugins.map((plugin) => plugin.pageConfigs)) }
|
|
642
|
+
}
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
function findPluginPage(build2, pagePath) {
|
|
646
|
+
for (const plugin of build2.plugins) {
|
|
647
|
+
const prefix = `__plugin__/${plugin.provider}/`;
|
|
648
|
+
if (plugin.pages.includes(pagePath)) return { plugin, innerPath: pagePath.slice(prefix.length) };
|
|
649
|
+
}
|
|
650
|
+
return null;
|
|
651
|
+
}
|
|
652
|
+
function pluginScriptUrl(plugin, file) {
|
|
653
|
+
return `/__wxa__/plugin/${encodeURIComponent(plugin.provider)}/${encodeURIComponent(plugin.version)}/${file}`;
|
|
654
|
+
}
|
|
655
|
+
|
|
484
656
|
// src/server/html.ts
|
|
485
657
|
function hostHtml() {
|
|
486
658
|
return `<!DOCTYPE html>
|
|
@@ -507,10 +679,11 @@ function appserviceHtml(build2, launch, options) {
|
|
|
507
679
|
...options.isolated ? { isIsolateContext: true } : {}
|
|
508
680
|
};
|
|
509
681
|
const v = build2.version;
|
|
682
|
+
const pluginUrls = build2.plugins.map((plugin) => pluginScriptUrl(plugin, "appservice.js"));
|
|
510
683
|
const moduleUrls = build2.modules.map((id) => `/__wxa__/module/${encodeURI(id)}?v=${v}`);
|
|
511
684
|
const bootstrapUrl = `/__wxa__/service-bootstrap.js?v=${v}`;
|
|
512
685
|
if (options.isolated) {
|
|
513
|
-
const scripts = [...moduleUrls, bootstrapUrl];
|
|
686
|
+
const scripts = [...pluginUrls, ...moduleUrls, bootstrapUrl];
|
|
514
687
|
return `<!DOCTYPE html>
|
|
515
688
|
<html>
|
|
516
689
|
<head>
|
|
@@ -523,7 +696,7 @@ function appserviceHtml(build2, launch, options) {
|
|
|
523
696
|
<body></body>
|
|
524
697
|
</html>`;
|
|
525
698
|
}
|
|
526
|
-
const modules = moduleUrls.map((src) => `<script src="${src}"></script>`).join("\n");
|
|
699
|
+
const modules = [...pluginUrls, ...moduleUrls].map((src) => `<script src="${src}"></script>`).join("\n");
|
|
527
700
|
return `<!DOCTYPE html>
|
|
528
701
|
<html>
|
|
529
702
|
<head>
|
|
@@ -557,29 +730,13 @@ ${empty ? "" : '<script src="/__baselib__/WASubContext.js"></script>\n'}<script>
|
|
|
557
730
|
</html>`;
|
|
558
731
|
}
|
|
559
732
|
function webviewHtml(build2, pagePath, webviewId, options) {
|
|
560
|
-
const pageConfig = build2.wxConfig.page?.[pagePath + ".html"];
|
|
561
|
-
const window = { ...build2.wxConfig.global?.window, ...pageConfig?.window };
|
|
562
|
-
const wxConfig = { ...build2.wxConfig, window };
|
|
563
733
|
const id = Number(webviewId) || 0;
|
|
564
734
|
return `<!DOCTYPE html>
|
|
565
735
|
<html>
|
|
566
736
|
<head>
|
|
567
|
-
|
|
568
|
-
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
|
569
|
-
<title>${escapeHtml(pagePath)}</title>
|
|
570
|
-
<!-- \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 -->
|
|
571
|
-
<style>html{font-size:16px}</style>
|
|
572
|
-
<!-- \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
|
|
573
|
-
scrollbar-width \u4F18\u5148\u4E8E ::-webkit-scrollbar\uFF0C\u9875\u9762\u6837\u5F0F\u4E0D\u4F1A\u518D\u628A\u6EDA\u52A8\u6761\u52A0\u56DE\u6765 -->
|
|
574
|
-
<style>*{scrollbar-width:none}::-webkit-scrollbar{display:none}</style>
|
|
575
|
-
<!-- \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
|
|
576
|
-
\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 -->
|
|
577
|
-
<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>
|
|
578
|
-
<script>var __wxConfig = ${toJs(wxConfig)};</script>
|
|
579
|
-
<script src="/__wxa__/runtime/frame.js" data-kind="webview" data-webview-id="${id}"></script>
|
|
580
|
-
<script src="/__baselib__/WAWebview.js"></script>
|
|
737
|
+
${webviewHead(build2, pagePath, id)}
|
|
581
738
|
${enableHotUpdate(options.hot)}<script src="/__wxa__/page-frame.js?v=${build2.version}"></script>
|
|
582
|
-
${
|
|
739
|
+
${pageWindow(build2, pagePath).disableScroll ? "<style>body{overflow-y:hidden}</style>" : ""}
|
|
583
740
|
</head>
|
|
584
741
|
<body>
|
|
585
742
|
<script>
|
|
@@ -615,6 +772,42 @@ self.console = __wxaConsole;
|
|
|
615
772
|
importScripts(${modules.map((url) => toJs(url)).join(", ")});
|
|
616
773
|
`;
|
|
617
774
|
}
|
|
775
|
+
function pluginWebviewHtml(build2, plugin, innerPath, pagePath, webviewId) {
|
|
776
|
+
const id = Number(webviewId) || 0;
|
|
777
|
+
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>`;
|
|
778
|
+
return `<!DOCTYPE html>
|
|
779
|
+
<html>
|
|
780
|
+
<head>
|
|
781
|
+
${webviewHead(build2, pagePath, id)}
|
|
782
|
+
<script src="${pluginScriptUrl(plugin, "pageframe.js")}"></script>
|
|
783
|
+
${pageWindow(build2, pagePath).disableScroll ? "<style>body{overflow-y:hidden}</style>" : ""}
|
|
784
|
+
</head>
|
|
785
|
+
<body>
|
|
786
|
+
${page}
|
|
787
|
+
<script>parent.__wxaHost.frameLoaded('webview', ${id});</script>
|
|
788
|
+
</body>
|
|
789
|
+
</html>`;
|
|
790
|
+
}
|
|
791
|
+
function pageWindow(build2, pagePath) {
|
|
792
|
+
return { ...build2.wxConfig.global?.window, ...build2.wxConfig.page?.[pagePath + ".html"]?.window };
|
|
793
|
+
}
|
|
794
|
+
function webviewHead(build2, pagePath, id) {
|
|
795
|
+
const wxConfig = { ...build2.wxConfig, window: pageWindow(build2, pagePath) };
|
|
796
|
+
return `<meta charset="utf-8">
|
|
797
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
|
798
|
+
<title>${escapeHtml(pagePath)}</title>
|
|
799
|
+
<!-- \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 -->
|
|
800
|
+
<style>html{font-size:16px}</style>
|
|
801
|
+
<!-- \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
|
|
802
|
+
scrollbar-width \u4F18\u5148\u4E8E ::-webkit-scrollbar\uFF0C\u9875\u9762\u6837\u5F0F\u4E0D\u4F1A\u518D\u628A\u6EDA\u52A8\u6761\u52A0\u56DE\u6765 -->
|
|
803
|
+
<style>*{scrollbar-width:none}::-webkit-scrollbar{display:none}</style>
|
|
804
|
+
<!-- \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
|
|
805
|
+
\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 -->
|
|
806
|
+
<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>
|
|
807
|
+
<script>var __wxConfig = ${toJs(wxConfig)};</script>
|
|
808
|
+
<script src="/__wxa__/runtime/frame.js" data-kind="webview" data-webview-id="${id}"></script>
|
|
809
|
+
<script src="/__baselib__/WAWebview.js"></script>`;
|
|
810
|
+
}
|
|
618
811
|
function escapeHtml(text) {
|
|
619
812
|
return text.replace(/[&<>"]/g, (ch) => ({ "&": "&", "<": "<", ">": ">", '"': """ })[ch]);
|
|
620
813
|
}
|
|
@@ -720,20 +913,20 @@ var import_child_process = require("child_process");
|
|
|
720
913
|
var import_crypto = require("crypto");
|
|
721
914
|
var import_promises = require("timers/promises");
|
|
722
915
|
var import_ws = require("ws");
|
|
723
|
-
var
|
|
916
|
+
var import_wxa_runner_extractor3 = require("@open-wxa/wxa-runner-extractor");
|
|
724
917
|
var AUTO_PORT = 9420;
|
|
725
918
|
var CLI_TIMEOUT = 6e4;
|
|
726
919
|
var AUTOMATOR_TIMEOUT = 5e3;
|
|
727
920
|
var WINDOW_TIMEOUT = 1e4;
|
|
728
921
|
var WINDOW_RETRY_INTERVAL = 500;
|
|
729
922
|
function developerTicketSource(projectPath, logger) {
|
|
730
|
-
const cli = (0,
|
|
731
|
-
if (!cli) return async () => (0,
|
|
923
|
+
const cli = (0, import_wxa_runner_extractor3.findElectronDevtoolsCli)();
|
|
924
|
+
if (!cli) return async () => (0, import_wxa_runner_extractor3.findDeveloperTicket)();
|
|
732
925
|
let automatorPort = null;
|
|
733
926
|
const startOnce = () => {
|
|
734
927
|
if (!automatorPort) {
|
|
735
928
|
const starting = startAutomation(cli, projectPath).then((port) => {
|
|
736
|
-
logger.log(`[wxa-runner] \
|
|
929
|
+
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`);
|
|
737
930
|
return port;
|
|
738
931
|
});
|
|
739
932
|
starting.catch(() => {
|
|
@@ -744,7 +937,7 @@ function developerTicketSource(projectPath, logger) {
|
|
|
744
937
|
return automatorPort;
|
|
745
938
|
};
|
|
746
939
|
return async () => {
|
|
747
|
-
if (process.env[
|
|
940
|
+
if (process.env[import_wxa_runner_extractor3.TICKET_ENV]) return { newticket: process.env[import_wxa_runner_extractor3.TICKET_ENV] };
|
|
748
941
|
const port = startOnce();
|
|
749
942
|
try {
|
|
750
943
|
return await requestTicketOnceWindowReady(await port, projectPath);
|
|
@@ -849,74 +1042,62 @@ function explainAutomatorError(message) {
|
|
|
849
1042
|
return new Error(`\u5FAE\u4FE1\u5F00\u53D1\u8005\u5DE5\u5177\u8FD4\u56DE\u9519\u8BEF\uFF1A${message}`);
|
|
850
1043
|
}
|
|
851
1044
|
|
|
852
|
-
// src/server/
|
|
1045
|
+
// src/server/devtoolsLogin.ts
|
|
853
1046
|
var import_express = __toESM(require("express"));
|
|
854
|
-
var
|
|
855
|
-
var DEV_LOGIC = "https://servicewechat.com/wxa-dev-logic";
|
|
856
|
-
var CLIENT_VERSION = "1021810240";
|
|
857
|
-
var UPSTREAM_TIMEOUT = 1e4;
|
|
1047
|
+
var import_wxa_runner_extractor4 = require("@open-wxa/wxa-runner-extractor");
|
|
858
1048
|
var LOOPBACK_ADDRESSES = ["127.0.0.1", "::1", "::ffff:127.0.0.1"];
|
|
859
1049
|
var LOOPBACK_HOSTS = ["localhost", "127.0.0.1", "[::1]"];
|
|
860
|
-
var
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
40029: "\uFF08\u767B\u5F55\u6001\u5DF2\u5931\u6548\uFF0C\u8BF7\u5728\u5FAE\u4FE1\u5F00\u53D1\u8005\u5DE5\u5177\u91CC\u91CD\u65B0\u767B\u5F55\uFF09",
|
|
864
|
-
85023: "\uFF08\u5F53\u524D\u5FAE\u4FE1\u8D26\u53F7\u4E0D\u662F\u8BE5\u5C0F\u7A0B\u5E8F\u7684\u5F00\u53D1\u8005\uFF09"
|
|
865
|
-
};
|
|
866
|
-
function requireUsableTicket(ticket) {
|
|
867
|
-
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 ${import_wxa_runner_extractor2.TICKET_ENV}`);
|
|
868
|
-
if (ticket.expiredAt !== void 0 && ticket.expiredAt <= Date.now()) {
|
|
869
|
-
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");
|
|
870
|
-
}
|
|
871
|
-
return ticket.newticket;
|
|
872
|
-
}
|
|
873
|
-
function realLoginRouter(appid, findTicket = import_wxa_runner_extractor2.findDeveloperTicket) {
|
|
874
|
-
const callDevLogic = async (endpoint, body) => {
|
|
875
|
-
const query = new URLSearchParams({ appid, newticket: requireUsableTicket(await findTicket()), clientversion: CLIENT_VERSION });
|
|
876
|
-
const response = await fetch(`${DEV_LOGIC}/${endpoint}?${query}`, {
|
|
877
|
-
method: "POST",
|
|
878
|
-
headers: { "Content-Type": "application/json" },
|
|
879
|
-
body: JSON.stringify(body),
|
|
880
|
-
signal: AbortSignal.timeout(UPSTREAM_TIMEOUT)
|
|
881
|
-
}).catch((error) => {
|
|
882
|
-
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}`);
|
|
883
|
-
});
|
|
884
|
-
if (!response.ok) throw new Error(`\u5FAE\u4FE1\u670D\u52A1\u5668\u8FD4\u56DE HTTP ${response.status}`);
|
|
885
|
-
return response.json();
|
|
886
|
-
};
|
|
1050
|
+
var FORWARDED_WX_DATA_APIS = ["webapi_servicemarket_jsapi_comm"];
|
|
1051
|
+
function devtoolsLoginRouter(appid, findTicket = import_wxa_runner_extractor4.findDeveloperTicket) {
|
|
1052
|
+
const wechat = new WechatDevClient(appid, findTicket);
|
|
887
1053
|
const router = import_express.default.Router();
|
|
888
1054
|
router.use(onlyLoopback);
|
|
889
1055
|
router.post("/login", respond(async () => {
|
|
890
|
-
const body = await
|
|
891
|
-
|
|
892
|
-
if (errcode !== 0 || !body.code) {
|
|
893
|
-
throw new Error(`\u5FAE\u4FE1\u767B\u5F55\u5931\u8D25 ${errcode}: ${body.baseresponse?.errmsg || "\u672A\u77E5\u9519\u8BEF"}${ERROR_HINTS[errcode] ?? ""}`);
|
|
894
|
-
}
|
|
1056
|
+
const body = requireOk(await wechat.postJson("wxa-dev-logic/jslogin", { scope: ["snsapi_base"] }), "\u5FAE\u4FE1\u767B\u5F55\u5931\u8D25");
|
|
1057
|
+
if (!body.code) throw new Error("\u5FAE\u4FE1\u767B\u5F55\u5931\u8D25\uFF1A\u5FAE\u4FE1\u6CA1\u6709\u8FD4\u56DE code");
|
|
895
1058
|
return { code: body.code };
|
|
896
1059
|
}));
|
|
897
1060
|
router.post("/phone-number", respond(async () => {
|
|
898
|
-
const body = await
|
|
1061
|
+
const body = await wechat.postJson("wxa-dev-logic/jsgetuserwxphone", { appid });
|
|
899
1062
|
const errcode = body.jsapi_baseresponse?.errcode ?? body.BaseResponse?.Ret;
|
|
900
1063
|
if (errcode !== 0 || typeof body.data !== "string") {
|
|
901
1064
|
const errmsg = body.jsapi_baseresponse?.errmsg || body.BaseResponse?.ErrMsg?.String || "\u672A\u77E5\u9519\u8BEF";
|
|
902
|
-
throw new Error(`\u83B7\u53D6\u624B\u673A\u53F7\u5931\u8D25 ${errcode}: ${errmsg}${
|
|
1065
|
+
throw new Error(`\u83B7\u53D6\u624B\u673A\u53F7\u5931\u8D25 ${errcode}: ${errmsg}${explainErrcode(errcode)}`);
|
|
903
1066
|
}
|
|
904
1067
|
const { encryptedData, iv } = JSON.parse(body.data);
|
|
905
1068
|
return { data: body.data, encryptedData, iv };
|
|
906
1069
|
}));
|
|
1070
|
+
router.post("/operate-wx-data", import_express.default.json({ limit: "10mb" }), (req, res, next) => {
|
|
1071
|
+
const apiName = req.body?.data?.api_name;
|
|
1072
|
+
if (FORWARDED_WX_DATA_APIS.includes(apiName)) return next();
|
|
1073
|
+
res.status(403).json({ error: `operateWXData \u53EA\u8F6C\u53D1\u670D\u52A1\u5E02\u573A\u7684\u8BF7\u6C42\uFF0C\u4E0D\u8F6C\u53D1 ${apiName}` });
|
|
1074
|
+
}, respond(async (req) => {
|
|
1075
|
+
const body = requireOk(await wechat.postJson("wxa-dev-logic/jsoperatewxdata", { data: JSON.stringify(req.body.data) }), "\u670D\u52A1\u5E02\u573A\u8C03\u7528\u5931\u8D25");
|
|
1076
|
+
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");
|
|
1077
|
+
return { data: JSON.parse(body.data) };
|
|
1078
|
+
}));
|
|
1079
|
+
router.post("/verify-plugin", import_express.default.json(), respond(async (req) => {
|
|
1080
|
+
const body = requireOk(await wechat.postJson("wxa-dev-logic/verifyplugin", { ext_info: JSON.stringify(req.body?.data || {}) }), "\u63D2\u4EF6\u6821\u9A8C\u5931\u8D25");
|
|
1081
|
+
return { data: { list: body.list || [] } };
|
|
1082
|
+
}));
|
|
1083
|
+
router.post("/batch-get-contact", import_express.default.json(), respond(async (req) => {
|
|
1084
|
+
const body = requireOk(await wechat.postJson("wxa-dev-logic/batchgetcontact", { appid_list: req.body?.appIds || [] }), "\u83B7\u53D6\u63D2\u4EF6\u4FE1\u606F\u5931\u8D25");
|
|
1085
|
+
const contacts = body.contact_list || [];
|
|
1086
|
+
return { contactList: contacts.filter((contact) => contact.plugin_info).map((contact) => ({ appId: contact.appid, plugin_list: contact.plugin_info.plugin_list })) };
|
|
1087
|
+
}));
|
|
907
1088
|
return router;
|
|
908
1089
|
}
|
|
909
1090
|
function onlyLoopback(req, res, next) {
|
|
910
1091
|
if (!LOOPBACK_ADDRESSES.includes(req.socket.remoteAddress || "") || !LOOPBACK_HOSTS.includes(req.hostname)) {
|
|
911
|
-
res.status(403).json({ error: "\
|
|
1092
|
+
res.status(403).json({ error: "\u5F00\u53D1\u8005\u767B\u5F55\u6001\u63A5\u53E3\u53EA\u5141\u8BB8\u672C\u673A\u8BBF\u95EE" });
|
|
912
1093
|
return;
|
|
913
1094
|
}
|
|
914
1095
|
next();
|
|
915
1096
|
}
|
|
916
1097
|
function respond(action) {
|
|
917
|
-
return async (
|
|
1098
|
+
return async (req, res) => {
|
|
918
1099
|
try {
|
|
919
|
-
res.json(await action());
|
|
1100
|
+
res.json(await action(req));
|
|
920
1101
|
} catch (error) {
|
|
921
1102
|
res.status(500).json({ error: error.message });
|
|
922
1103
|
}
|
|
@@ -1047,11 +1228,16 @@ var DevServer = class {
|
|
|
1047
1228
|
this.tempFiles = /* @__PURE__ */ new Map();
|
|
1048
1229
|
this.logger = options.logger || console;
|
|
1049
1230
|
this.project = new MiniProgram(import_path4.default.resolve(options.projectPath));
|
|
1050
|
-
this.baseLib = (0,
|
|
1231
|
+
this.baseLib = (0, import_wxa_runner_extractor5.resolveBaseLib)({ version: options.baseLibVersion, cacheDir: options.baseLibCacheDir });
|
|
1051
1232
|
if (!this.baseLib.compatible) {
|
|
1052
1233
|
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`);
|
|
1053
1234
|
}
|
|
1054
|
-
|
|
1235
|
+
if (options.realLogin !== void 0 && options.devtoolsLogin === void 0) {
|
|
1236
|
+
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");
|
|
1237
|
+
}
|
|
1238
|
+
this.devtoolsLogin = (options.devtoolsLogin ?? options.realLogin) === true;
|
|
1239
|
+
this.ticketSource = this.devtoolsLogin ? developerTicketSource(this.project.projectPath, this.logger) : null;
|
|
1240
|
+
this.plugins = new PluginStore(this.ticketSource && new WechatDevClient(this.project.appid, this.ticketSource), this.logger);
|
|
1055
1241
|
this.device = { ...DEFAULT_DEVICE, ...options.device };
|
|
1056
1242
|
this.builder = new AppBuilder(this.project);
|
|
1057
1243
|
this.setupFile = resolveSetupFile(options.setup, this.project.projectPath);
|
|
@@ -1087,7 +1273,7 @@ ${error.message}`);
|
|
|
1087
1273
|
const { port } = server.address();
|
|
1088
1274
|
this.address = `http://${host}:${port}`;
|
|
1089
1275
|
if (this.options.watch !== false) this.startWatching();
|
|
1090
|
-
this.ticketSource?.().then(requireUsableTicket).catch((error) => this.logger.warn(`[wxa-runner] \
|
|
1276
|
+
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}`));
|
|
1091
1277
|
return this.address;
|
|
1092
1278
|
}
|
|
1093
1279
|
async close() {
|
|
@@ -1114,9 +1300,9 @@ ${error.message}`);
|
|
|
1114
1300
|
});
|
|
1115
1301
|
app.get("/__wxa__/app-info.json", async (_req, res) => {
|
|
1116
1302
|
noStore(res);
|
|
1117
|
-
const base = { appid: this.project.appid, baseLibVersion: this.baseLib.version, device: this.device,
|
|
1303
|
+
const base = { appid: this.project.appid, baseLibVersion: this.baseLib.version, device: this.device, devtoolsLogin: this.devtoolsLogin };
|
|
1118
1304
|
try {
|
|
1119
|
-
const build2 = await this.builder.build();
|
|
1305
|
+
const build2 = await this.plugins.refresh(await this.builder.build());
|
|
1120
1306
|
const info = { ...base, version: build2.version, wxConfig: build2.wxConfig, pages: build2.pages };
|
|
1121
1307
|
if (this.setupFile) info.setup = await this.setupInfo(this.setupFile);
|
|
1122
1308
|
res.json(info);
|
|
@@ -1139,7 +1325,7 @@ ${error.message}`);
|
|
|
1139
1325
|
app.get("/__wxa__/appservice.html", this.withBuild((build2, req, res) => {
|
|
1140
1326
|
const launchPath = String(req.query.path || "").replace(/^\//, "");
|
|
1141
1327
|
const launch = build2.pages.includes(launchPath) ? { path: launchPath, query: Object.fromEntries(new URLSearchParams(String(req.query.query || ""))) } : { path: build2.pages[0], query: {} };
|
|
1142
|
-
res.type("html").send(appserviceHtml(build2, launch, { hot: this.hotEnabled, isolated: (0,
|
|
1328
|
+
res.type("html").send(appserviceHtml(build2, launch, { hot: this.hotEnabled, isolated: (0, import_wxa_runner_extractor5.usesIsolatedContext)(this.baseLib.version) }));
|
|
1143
1329
|
}));
|
|
1144
1330
|
app.get("/__wxa__/subcontext.html", (req, res) => {
|
|
1145
1331
|
const id = Number(req.query.id);
|
|
@@ -1152,7 +1338,19 @@ ${error.message}`);
|
|
|
1152
1338
|
app.get(/^\/__wxa__\/webview\/(.+)\.html$/, this.withBuild((build2, req, res, next) => {
|
|
1153
1339
|
const pagePath = decodeURIComponent(req.params[0]);
|
|
1154
1340
|
if (!build2.pages.includes(pagePath)) return next();
|
|
1155
|
-
|
|
1341
|
+
const pluginPage = findPluginPage(build2, pagePath);
|
|
1342
|
+
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 }));
|
|
1343
|
+
}));
|
|
1344
|
+
app.get("/__wxa__/plugin/:provider/:version/:file(appservice.js|pageframe.js)", this.withBuild((build2, req, res, next) => {
|
|
1345
|
+
const { provider, version, file } = req.params;
|
|
1346
|
+
const code = build2.plugins.find((plugin) => plugin.provider === provider && plugin.version === version)?.files.get(`/${file}`);
|
|
1347
|
+
if (!code) return next();
|
|
1348
|
+
res.type("js").send(code);
|
|
1349
|
+
}));
|
|
1350
|
+
app.get(/^\/__plugin__\/([^/]+)(\/.+)$/, this.withBuild((build2, req, res, next) => {
|
|
1351
|
+
const file = build2.plugins.find((plugin) => plugin.provider === req.params[0])?.files.get(decodeURIComponent(req.params[1]));
|
|
1352
|
+
if (!file) return next();
|
|
1353
|
+
res.type(import_path4.default.extname(req.params[1]) || "application/octet-stream").send(file);
|
|
1156
1354
|
}));
|
|
1157
1355
|
app.get(/^\/__wxa__\/module\/(.+\.js)$/, this.withBuild((build2, req, res) => {
|
|
1158
1356
|
const id = decodeURIComponent(req.params[0]);
|
|
@@ -1208,7 +1406,7 @@ ${error.message}`);
|
|
|
1208
1406
|
});
|
|
1209
1407
|
app.get("/__wxa__/region/:kind", (req, res) => {
|
|
1210
1408
|
const kind = req.params.kind;
|
|
1211
|
-
const data = kind === "districts" || kind === "streets" ? (0,
|
|
1409
|
+
const data = kind === "districts" || kind === "streets" ? (0, import_wxa_runner_extractor5.readRegionData)(kind) : null;
|
|
1212
1410
|
if (!data) {
|
|
1213
1411
|
res.status(404).end();
|
|
1214
1412
|
return;
|
|
@@ -1241,7 +1439,7 @@ ${error.message}`);
|
|
|
1241
1439
|
app.delete("/__wxa__/tmp/:name", (req, res) => {
|
|
1242
1440
|
res.status(this.tempFiles.delete(req.params.name) ? 204 : 404).end();
|
|
1243
1441
|
});
|
|
1244
|
-
if (this.ticketSource) app.use("/__wxa__/api",
|
|
1442
|
+
if (this.ticketSource) app.use("/__wxa__/api", devtoolsLoginRouter(this.project.appid, this.ticketSource));
|
|
1245
1443
|
app.use("/__wxa__/webview", import_express2.default.static(root));
|
|
1246
1444
|
app.use(import_express2.default.static(root));
|
|
1247
1445
|
app.use((error, _req, res, _next) => {
|
|
@@ -1259,13 +1457,17 @@ ${error.message}`);
|
|
|
1259
1457
|
return { env: this.setupEnv, error: error.message };
|
|
1260
1458
|
}
|
|
1261
1459
|
}
|
|
1460
|
+
/** 构建结果并入这次打开小程序时决定用的插件 */
|
|
1461
|
+
async currentBuild() {
|
|
1462
|
+
return this.plugins.current(await this.builder.build());
|
|
1463
|
+
}
|
|
1262
1464
|
/** 需要构建结果的路由;构建失败时返回错误文本 */
|
|
1263
1465
|
withBuild(handler) {
|
|
1264
1466
|
return async (req, res, next) => {
|
|
1265
1467
|
res.setHeader("Cache-Control", "no-store");
|
|
1266
1468
|
let build2;
|
|
1267
1469
|
try {
|
|
1268
|
-
build2 = await this.
|
|
1470
|
+
build2 = await this.currentBuild();
|
|
1269
1471
|
} catch (error) {
|
|
1270
1472
|
res.status(500).type("text").send(error.message);
|
|
1271
1473
|
return;
|