@open-wxa/wxa-runner-core 0.7.0 → 0.8.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 +22 -9
- package/dist/index.d.ts +22 -9
- package/dist/index.js +358 -54
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +354 -50
- package/dist/index.mjs.map +1 -1
- package/dist/runtime/frame.js +44 -2
- package/dist/runtime/frame.js.map +1 -1
- package/dist/runtime/host.js +357 -161
- package/dist/runtime/host.js.map +1 -1
- package/dist/runtime/sw.js +56 -0
- package/dist/runtime/sw.js.map +1 -0
- package/dist/{setup-DZ5FeKay.d.mts → setup-Bac8XdhR.d.mts} +5 -1
- package/dist/{setup-DZ5FeKay.d.ts → setup-Bac8XdhR.d.ts} +5 -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-BLozOgCt.d.ts → testApi-BOZSXSnV.d.ts} +3 -3
- package/dist/{testApi-CnZOLyWw.d.mts → testApi-DHuEW5Cl.d.mts} +3 -3
- package/package.json +4 -4
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
(() => {
|
|
3
|
+
// src/runtime/networkPanel.ts
|
|
4
|
+
var MOCK_PREFIX = "/__wxa__/mock/";
|
|
5
|
+
var MOCK_ID_HEADER = "x-wxa-mock-id";
|
|
6
|
+
function toHeaders(header) {
|
|
7
|
+
const headers = new Headers();
|
|
8
|
+
for (const [name, value] of Object.entries(header)) {
|
|
9
|
+
if (value === void 0 || value === null) continue;
|
|
10
|
+
try {
|
|
11
|
+
headers.set(name, String(value));
|
|
12
|
+
} catch {
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return headers;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// src/runtime/sw.ts
|
|
19
|
+
var scope = self;
|
|
20
|
+
var NULL_BODY_STATUSES = /* @__PURE__ */ new Set([204, 205, 304]);
|
|
21
|
+
var URLPatternClass = globalThis.URLPattern;
|
|
22
|
+
scope.addEventListener("install", (event) => {
|
|
23
|
+
scope.skipWaiting();
|
|
24
|
+
if (!event.addRoutes || !URLPatternClass) return;
|
|
25
|
+
const others = { not: { urlPattern: new URLPatternClass({ pathname: `${MOCK_PREFIX}*` }) } };
|
|
26
|
+
try {
|
|
27
|
+
event.waitUntil(event.addRoutes([{ condition: others, source: "network" }]).catch(() => void 0));
|
|
28
|
+
} catch {
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
scope.addEventListener("activate", (event) => event.waitUntil(scope.clients.claim()));
|
|
32
|
+
scope.addEventListener("fetch", (event) => {
|
|
33
|
+
const id = event.request.headers.get(MOCK_ID_HEADER);
|
|
34
|
+
if (!id || !new URL(event.request.url).pathname.startsWith(MOCK_PREFIX)) return;
|
|
35
|
+
event.respondWith(mockedResponse(event.clientId, id));
|
|
36
|
+
});
|
|
37
|
+
async function mockedResponse(clientId, id) {
|
|
38
|
+
const client = await scope.clients.get(clientId);
|
|
39
|
+
if (!client) return Response.error();
|
|
40
|
+
const reply = await new Promise((resolve) => {
|
|
41
|
+
const channel = new MessageChannel();
|
|
42
|
+
channel.port1.onmessage = (event) => resolve(event.data);
|
|
43
|
+
client.postMessage({ type: "wxa-mock-response", id }, [channel.port2]);
|
|
44
|
+
});
|
|
45
|
+
if (!reply) return Response.error();
|
|
46
|
+
try {
|
|
47
|
+
return new Response(NULL_BODY_STATUSES.has(reply.statusCode) ? null : reply.body, {
|
|
48
|
+
status: reply.statusCode,
|
|
49
|
+
headers: toHeaders(reply.header)
|
|
50
|
+
});
|
|
51
|
+
} catch {
|
|
52
|
+
return Response.error();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
})();
|
|
56
|
+
//# sourceMappingURL=sw.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/runtime/networkPanel.ts","../../src/runtime/sw.ts"],"sourcesContent":["/**\n * 小程序的请求在浏览器 Network 面板里的样子,宿主、Service Worker 和开发服务器共用\n *\n * 原地址放在路径里:/__wxa__/proxy/https/api.example.com/user/info?id=1。Name 列显示接口名(info?id=1),\n * 按域名、路径过滤也直接可用;放在查询参数里时每一行都是 proxy?url=https%3A%2F%2F…,分不出是哪个接口。\n *\n * - 经开发服务器转发的请求:/__wxa__/proxy/…\n * - 被拦截规则拦下的请求:/__wxa__/mock/…,由 Service Worker 返回规则给出的响应,只用于显示(见 sw.ts)\n */\n\nimport type { MockedResponse } from './host/api/routes';\n\nexport const PROXY_PREFIX = '/__wxa__/proxy/';\nexport const MOCK_PREFIX = '/__wxa__/mock/';\n\n/** 显示被拦截请求的 fetch 带上这个头,Service Worker 凭它向宿主要对应的响应 */\nexport const MOCK_ID_HEADER = 'x-wxa-mock-id';\n\n/** Service Worker 向宿主要响应时发的消息,附带一个 MessagePort,宿主从这个端口回复 MockReply */\nexport interface MockQuery {\n type: 'wxa-mock-response';\n id: string;\n}\n\n/** 请求被取消、拦截规则出错,或宿主已经不认识这个 id 时为 null,Network 面板里显示为失败 */\nexport type MockReply = MockedResponse | null;\n\n/**\n * 原地址在开发服务器上对应的路径,prefix 是 PROXY_PREFIX 或 MOCK_PREFIX。不是 http(s) 地址时返回 null\n *\n * 先按 URL 规范化:路径里的 .. 要在拼接前解析掉,否则浏览器会在代理路径上解析,把域名那一段也吃掉\n */\nexport function toServerPath(prefix: string, url: string): string | null {\n let target: URL;\n try {\n target = new URL(url);\n } catch {\n return null;\n }\n if (target.protocol !== 'http:' && target.protocol !== 'https:') return null;\n return `${prefix}${target.protocol.slice(0, -1)}/${target.host}${target.pathname}${target.search}`;\n}\n\n/**\n * toServerPath 的逆运算,格式不对或还原出的地址不合法时返回 null\n *\n * 只校验不规范化,返回拼出的原样字符串:路径里的 %2F 等编码要原样转发\n */\nexport function fromServerPath(prefix: string, serverPath: string): string | null {\n if (!serverPath.startsWith(prefix)) return null;\n const match = /^(https?)\\/([^/?#]+)(.*)$/.exec(serverPath.slice(prefix.length));\n if (!match) return null;\n const url = `${match[1]}://${match[2]}${match[3]}`;\n try {\n new URL(url);\n return url;\n } catch {\n return null;\n }\n}\n\n/**\n * 用于显示的请求、响应头。浏览器不允许设置的(cookie、set-cookie 等)会被忽略,\n * 名字或值不合法的(如值里有中文)跳过:它们只影响 Network 面板里的显示,小程序拿到的头不受影响。\n * 值为 undefined、null 的和代理一样不发\n */\nexport function toHeaders(header: Record<string, unknown>): Headers {\n const headers = new Headers();\n for (const [name, value] of Object.entries(header)) {\n if (value === undefined || value === null) continue;\n try {\n headers.set(name, String(value));\n } catch {\n // 跳过\n }\n }\n return headers;\n}\n","/**\n * Service Worker(打包为 /__wxa__/runtime/sw.js):让被拦截的 wx.request 也出现在 Network 面板里\n *\n * 宿主照原请求向 /__wxa__/mock/… 发一个带 x-wxa-mock-id 头的 fetch(见 host/mockMirror.ts),\n * 这里拦下它,向发出请求的页面要拦截规则给出的响应。其余请求一律不处理,照常走网络。\n */\n\nimport { MOCK_ID_HEADER, MOCK_PREFIX, MockQuery, MockReply, toHeaders } from './networkPanel';\n\n// tsconfig 只带 DOM 的类型,这里只声明用到的 Service Worker 接口\ninterface ExtendableEvent extends Event {\n waitUntil(promise: Promise<unknown>): void;\n}\ninterface InstallEvent extends ExtendableEvent {\n /** Static Routing API,Chrome 123 起支持 */\n addRoutes?(rules: object[]): Promise<void>;\n}\ninterface FetchEvent extends ExtendableEvent {\n request: Request;\n clientId: string;\n respondWith(response: Promise<Response>): void;\n}\ninterface WorkerScope {\n skipWaiting(): Promise<void>;\n clients: {\n claim(): Promise<void>;\n get(id: string): Promise<{ postMessage(message: MockQuery, transfer: Transferable[]): void } | undefined>;\n };\n addEventListener(type: 'install', listener: (event: InstallEvent) => void): void;\n addEventListener(type: 'activate', listener: (event: ExtendableEvent) => void): void;\n addEventListener(type: 'fetch', listener: (event: FetchEvent) => void): void;\n}\n\nconst scope = self as unknown as WorkerScope;\n\n/** 这些状态码的响应不能带响应体,带了 Response 构造函数会报错 */\nconst NULL_BODY_STATUSES = new Set([204, 205, 304]);\n\nconst URLPatternClass = (globalThis as { URLPattern?: new (init: { pathname: string }) => object }).URLPattern;\n\nscope.addEventListener('install', event => {\n // 新版本装好后立即接替旧版本,不用等所有标签页关闭\n scope.skipWaiting();\n // 其余请求不唤起 Service Worker,直接走网络。不支持的浏览器里照样能用,只是每个请求都先经过 fetch 事件\n if (!event.addRoutes || !URLPatternClass) return;\n const others = { not: { urlPattern: new URLPatternClass({ pathname: `${MOCK_PREFIX}*` }) } };\n try {\n event.waitUntil(event.addRoutes([{ condition: others, source: 'network' }]).catch(() => undefined));\n } catch {\n // 早期版本不支持 not 条件,同上\n }\n});\n\n// 第一次打开页面时就接管它,不用刷新\nscope.addEventListener('activate', event => event.waitUntil(scope.clients.claim()));\n\nscope.addEventListener('fetch', event => {\n const id = event.request.headers.get(MOCK_ID_HEADER);\n if (!id || !new URL(event.request.url).pathname.startsWith(MOCK_PREFIX)) return;\n event.respondWith(mockedResponse(event.clientId, id));\n});\n\nasync function mockedResponse(clientId: string, id: string): Promise<Response> {\n const client = await scope.clients.get(clientId);\n if (!client) return Response.error();\n const reply = await new Promise<MockReply>(resolve => {\n const channel = new MessageChannel();\n channel.port1.onmessage = event => resolve(event.data);\n client.postMessage({ type: 'wxa-mock-response', id }, [channel.port2]);\n });\n if (!reply) return Response.error();\n try {\n return new Response(NULL_BODY_STATUSES.has(reply.statusCode) ? null : reply.body, {\n status: reply.statusCode,\n headers: toHeaders(reply.header)\n });\n } catch {\n // 状态码不在 200~599:小程序照样拿得到,浏览器的 Response 表示不了\n return Response.error();\n }\n}\n"],"mappings":";;;AAaO,MAAM,cAAc;AAGpB,MAAM,iBAAiB;AAkDvB,WAAS,UAAU,QAA0C;AAClE,UAAM,UAAU,IAAI,QAAQ;AAC5B,eAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AAClD,UAAI,UAAU,UAAa,UAAU,KAAM;AAC3C,UAAI;AACF,gBAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAAA,MACjC,QAAQ;AAAA,MAER;AAAA,IACF;AACA,WAAO;AAAA,EACT;;;AC5CA,MAAM,QAAQ;AAGd,MAAM,qBAAqB,oBAAI,IAAI,CAAC,KAAK,KAAK,GAAG,CAAC;AAElD,MAAM,kBAAmB,WAA2E;AAEpG,QAAM,iBAAiB,WAAW,WAAS;AAEzC,UAAM,YAAY;AAElB,QAAI,CAAC,MAAM,aAAa,CAAC,gBAAiB;AAC1C,UAAM,SAAS,EAAE,KAAK,EAAE,YAAY,IAAI,gBAAgB,EAAE,UAAU,GAAG,WAAW,IAAI,CAAC,EAAE,EAAE;AAC3F,QAAI;AACF,YAAM,UAAU,MAAM,UAAU,CAAC,EAAE,WAAW,QAAQ,QAAQ,UAAU,CAAC,CAAC,EAAE,MAAM,MAAM,MAAS,CAAC;AAAA,IACpG,QAAQ;AAAA,IAER;AAAA,EACF,CAAC;AAGD,QAAM,iBAAiB,YAAY,WAAS,MAAM,UAAU,MAAM,QAAQ,MAAM,CAAC,CAAC;AAElF,QAAM,iBAAiB,SAAS,WAAS;AACvC,UAAM,KAAK,MAAM,QAAQ,QAAQ,IAAI,cAAc;AACnD,QAAI,CAAC,MAAM,CAAC,IAAI,IAAI,MAAM,QAAQ,GAAG,EAAE,SAAS,WAAW,WAAW,EAAG;AACzE,UAAM,YAAY,eAAe,MAAM,UAAU,EAAE,CAAC;AAAA,EACtD,CAAC;AAED,iBAAe,eAAe,UAAkB,IAA+B;AAC7E,UAAM,SAAS,MAAM,MAAM,QAAQ,IAAI,QAAQ;AAC/C,QAAI,CAAC,OAAQ,QAAO,SAAS,MAAM;AACnC,UAAM,QAAQ,MAAM,IAAI,QAAmB,aAAW;AACpD,YAAM,UAAU,IAAI,eAAe;AACnC,cAAQ,MAAM,YAAY,WAAS,QAAQ,MAAM,IAAI;AACrD,aAAO,YAAY,EAAE,MAAM,qBAAqB,GAAG,GAAG,CAAC,QAAQ,KAAK,CAAC;AAAA,IACvE,CAAC;AACD,QAAI,CAAC,MAAO,QAAO,SAAS,MAAM;AAClC,QAAI;AACF,aAAO,IAAI,SAAS,mBAAmB,IAAI,MAAM,UAAU,IAAI,OAAO,MAAM,MAAM;AAAA,QAChF,QAAQ,MAAM;AAAA,QACd,SAAS,UAAU,MAAM,MAAM;AAAA,MACjC,CAAC;AAAA,IACH,QAAQ;AAEN,aAAO,SAAS,MAAM;AAAA,IACxB;AAAA,EACF;","names":[]}
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
* 不经过 postMessage:同步 API(如 getStorageSync)因此可以同步返回。
|
|
6
6
|
*/
|
|
7
7
|
type FrameKind = 'service' | 'webview';
|
|
8
|
+
/** 把浏览器里的报错转发到开发服务器的终端:errors 只转发报错,all 再加上 console.warn / console.error,false 不转发 */
|
|
9
|
+
type ForwardConsole = 'errors' | 'all' | false;
|
|
8
10
|
interface DeviceProfile {
|
|
9
11
|
model: string;
|
|
10
12
|
screenWidth: number;
|
|
@@ -32,6 +34,8 @@ interface AppInfo {
|
|
|
32
34
|
env: Record<string, string>;
|
|
33
35
|
error?: string;
|
|
34
36
|
};
|
|
37
|
+
/** 没有时不转发 */
|
|
38
|
+
forwardConsole?: ForwardConsole;
|
|
35
39
|
}
|
|
36
40
|
|
|
37
41
|
/**
|
|
@@ -196,4 +200,4 @@ interface SetupApi {
|
|
|
196
200
|
/** 只用于获得类型提示,原样返回传入的配置 */
|
|
197
201
|
declare function defineSetup<T extends SetupDefinition>(setup: T): T;
|
|
198
202
|
|
|
199
|
-
export { type ApiContext as A, type DeviceProfile as D, type
|
|
203
|
+
export { type ApiContext as A, type DeviceProfile as D, type ForwardConsole as F, type KnownMocks as K, type MockConfig as M, type NetworkConfig as N, type RouteHandler as R, type SetupApi as S, type UserInfo as U, type ApiHandler as a, type ApiResult as b, type AppInfo as c, type MockRequest as d, type MockResponse as e, type MockValue as f, type SetupConfig as g, type SetupContext as h, type SetupDefinition as i, type FrameKind as j, type SetupEnv as k, defineSetup as l };
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
* 不经过 postMessage:同步 API(如 getStorageSync)因此可以同步返回。
|
|
6
6
|
*/
|
|
7
7
|
type FrameKind = 'service' | 'webview';
|
|
8
|
+
/** 把浏览器里的报错转发到开发服务器的终端:errors 只转发报错,all 再加上 console.warn / console.error,false 不转发 */
|
|
9
|
+
type ForwardConsole = 'errors' | 'all' | false;
|
|
8
10
|
interface DeviceProfile {
|
|
9
11
|
model: string;
|
|
10
12
|
screenWidth: number;
|
|
@@ -32,6 +34,8 @@ interface AppInfo {
|
|
|
32
34
|
env: Record<string, string>;
|
|
33
35
|
error?: string;
|
|
34
36
|
};
|
|
37
|
+
/** 没有时不转发 */
|
|
38
|
+
forwardConsole?: ForwardConsole;
|
|
35
39
|
}
|
|
36
40
|
|
|
37
41
|
/**
|
|
@@ -196,4 +200,4 @@ interface SetupApi {
|
|
|
196
200
|
/** 只用于获得类型提示,原样返回传入的配置 */
|
|
197
201
|
declare function defineSetup<T extends SetupDefinition>(setup: T): T;
|
|
198
202
|
|
|
199
|
-
export { type ApiContext as A, type DeviceProfile as D, type
|
|
203
|
+
export { type ApiContext as A, type DeviceProfile as D, type ForwardConsole as F, type KnownMocks as K, type MockConfig as M, type NetworkConfig as N, type RouteHandler as R, type SetupApi as S, type UserInfo as U, type ApiHandler as a, type ApiResult as b, type AppInfo as c, type MockRequest as d, type MockResponse as e, type MockValue as f, type SetupConfig as g, type SetupContext as h, type SetupDefinition as i, type FrameKind as j, type SetupEnv as k, defineSetup as l };
|
package/dist/setup.d.mts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { K as KnownMocks, 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,
|
|
1
|
+
export { K as KnownMocks, 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, k as SetupEnv, U as UserInfo, l as defineSetup } from './setup-Bac8XdhR.mjs';
|
package/dist/setup.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { K as KnownMocks, 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,
|
|
1
|
+
export { K as KnownMocks, 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, k as SetupEnv, U as UserInfo, l as defineSetup } from './setup-Bac8XdhR.js';
|
package/dist/test-api.d.mts
CHANGED
package/dist/test-api.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { d as MockRequest,
|
|
1
|
+
import { d as MockRequest, j as FrameKind, a as ApiHandler, b as ApiResult, R as RouteHandler } from './setup-Bac8XdhR.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* 网络 API:wx.request / downloadFile / uploadFile / connectSocket
|
|
5
5
|
*
|
|
6
6
|
* 基础库 3.x 的协议是「创建任务同步返回 taskId,结果通过 on<Type>TaskStateChange 事件推送」。
|
|
7
|
-
* HTTP 请求经开发服务器的 /__wxa__/proxy 转发:既绕开 CORS,也能携带浏览器禁止设置的
|
|
8
|
-
* cookie / referer
|
|
7
|
+
* HTTP 请求经开发服务器的 /__wxa__/proxy/ 转发:既绕开 CORS,也能携带浏览器禁止设置的
|
|
8
|
+
* cookie / referer 等请求头。地址的写法见 networkPanel.ts
|
|
9
9
|
*
|
|
10
10
|
* 基础库自己的请求(数据上报、配置拉取等)不发出,只放行 InnerAudioContext 下载音频,见 byCaller。
|
|
11
11
|
*/
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { d as MockRequest,
|
|
1
|
+
import { d as MockRequest, j as FrameKind, a as ApiHandler, b as ApiResult, R as RouteHandler } from './setup-Bac8XdhR.mjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* 网络 API:wx.request / downloadFile / uploadFile / connectSocket
|
|
5
5
|
*
|
|
6
6
|
* 基础库 3.x 的协议是「创建任务同步返回 taskId,结果通过 on<Type>TaskStateChange 事件推送」。
|
|
7
|
-
* HTTP 请求经开发服务器的 /__wxa__/proxy 转发:既绕开 CORS,也能携带浏览器禁止设置的
|
|
8
|
-
* cookie / referer
|
|
7
|
+
* HTTP 请求经开发服务器的 /__wxa__/proxy/ 转发:既绕开 CORS,也能携带浏览器禁止设置的
|
|
8
|
+
* cookie / referer 等请求头。地址的写法见 networkPanel.ts
|
|
9
9
|
*
|
|
10
10
|
* 基础库自己的请求(数据上报、配置拉取等)不发出,只放行 InnerAudioContext 下载音频,见 byCaller。
|
|
11
11
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-wxa/wxa-runner-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Dev server and browser runtime that run WeChat mini-programs on the official base library",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "open-wxa",
|
|
@@ -46,11 +46,11 @@
|
|
|
46
46
|
],
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"chokidar": "^3.5.3",
|
|
49
|
-
"esbuild": "^0.
|
|
49
|
+
"esbuild": "^0.28.2",
|
|
50
50
|
"express": "^4.18.2",
|
|
51
51
|
"ws": "^8.14.2",
|
|
52
|
-
"@open-wxa/wxa-runner-
|
|
53
|
-
"@open-wxa/wxa-runner-
|
|
52
|
+
"@open-wxa/wxa-runner-extractor": "0.8.0",
|
|
53
|
+
"@open-wxa/wxa-runner-compiler": "0.8.0"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"@types/express": "^4.17.21",
|