@weapp-vite/miniprogram-automator 1.2.23 → 1.4.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/README.md +96 -0
- package/dist/index.d.mts +76 -8
- package/dist/index.mjs +996 -212
- package/dist/{launch-CSjvON-f.mjs → launch-ElaGbFxh.mjs} +2373 -621
- package/dist/operation.d.mts +64 -0
- package/dist/operation.mjs +233 -0
- package/package.json +15 -4
package/README.md
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
- 提供 `Launcher` 用于启动、连接和复用 DevTools 会话
|
|
17
17
|
- 支持按平台选择自动化后端,默认微信,百度智能小程序提供轻量 TypeScript runtime
|
|
18
18
|
- 支持截图、输入、滚动、点击、页面跳转等自动化操作
|
|
19
|
+
- 对齐官方 0.13.0 的公开 `send()`、`CDP()` 和可等待断开接口
|
|
19
20
|
- 默认输出现代 ESM 与完整类型声明
|
|
20
21
|
- 内置二维码打印与解码辅助能力,便于配合登录、连接流程调试
|
|
21
22
|
- 支持 headless 自动化启动入口
|
|
@@ -141,6 +142,93 @@ await miniProgram.flushConsole()
|
|
|
141
142
|
|
|
142
143
|
先用 `addListener` 被动注册,再显式等待 `enableLog`,可以记录初始化期间的日志。`flushConsole()` 等待调用时已收到的错误属性检查完成;每次查询最多等待 1 秒,失败会在原参数上保留 `inspectionError`。断开连接时尚未完成的日志也会携带该诊断发布。只有宿主明确返回 CDP 命令不支持时才回退 SDK 格式;其他初始化错误仍然抛出。重复调用 `enableLog` 会刷新 Runtime 订阅,并保留已选择的格式。
|
|
143
144
|
|
|
145
|
+
### 4.7 AppService 堆内存探测
|
|
146
|
+
|
|
147
|
+
`getAppServiceHeapUsage({ timeout })` 通过现有 `App.CDPCommand` 调用 `Runtime.getHeapUsage`,默认超时 2500ms。支持时返回 `{ status: 'available', source: 'appservice-cdp-runtime', usedSize, totalSize }`,两个值均为字节。仅当宿主明确不支持该协议或方法时,返回 `status: 'unsupported'` 及 `protocol-unimplemented` / `method-not-found` 原因。
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
const heap = await miniProgram.getAppServiceHeapUsage({ timeout: 2_500 })
|
|
151
|
+
if (heap.status === 'available') {
|
|
152
|
+
console.log({ usedBytes: heap.usedSize, allocatedBytes: heap.totalSize })
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
console.log({ unsupported: heap.reason })
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
空结果、缺失字段、字符串、负数、非有限数值或已用量超过分配量都会报错;连接超时与其他协议错误原样传播,不会转换为不支持或零内存。每次调用重新探测,不缓存旧会话的能力结果,也不主动触发 GC。该指标仅覆盖 AppService JS 堆,不是 renderer/native 内存、进程 RSS、峰值或可归因的组件独占内存。实际可用性取决于连接的 DevTools/基础库,仍须在目标宿主确认;headless 不提供真实 IDE 堆证据。
|
|
160
|
+
|
|
161
|
+
### 4.8 原始协议与 CDP
|
|
162
|
+
|
|
163
|
+
`send(method, params?, { timeout }?)` 公开原始自动化协议入口,返回宿主原始结果;超时、断开和协议错误继续抛出。错误消息为对象时会序列化展示,错误对象保留原始协议信息。
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
const info = await miniProgram.send('Tool.getInfo', {}, { timeout: 3_000 })
|
|
167
|
+
console.log(info)
|
|
168
|
+
|
|
169
|
+
const cdp = miniProgram.CDP()
|
|
170
|
+
await cdp.enable({ timeout: 3_000 })
|
|
171
|
+
const protocol = await cdp.listProtocol()
|
|
172
|
+
console.log(protocol)
|
|
173
|
+
await cdp.sendCommand('Runtime', 'enable')
|
|
174
|
+
const unsubscribe = cdp.onEvent((domain, event, params) => {
|
|
175
|
+
if (domain === 'Runtime' && event === 'consoleAPICalled') {
|
|
176
|
+
console.log(params)
|
|
177
|
+
}
|
|
178
|
+
})
|
|
179
|
+
try {
|
|
180
|
+
console.log(await cdp.sendCommand('Runtime', 'evaluate', {
|
|
181
|
+
expression: '40 + 2',
|
|
182
|
+
returnByValue: true,
|
|
183
|
+
}, { timeout: 3_000 }))
|
|
184
|
+
}
|
|
185
|
+
finally {
|
|
186
|
+
unsubscribe()
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
同一连接的 `CDP()` 共享启用状态,并发启用只发起一次初始化,失败后可重试。`sendCommand` 和 `listProtocol` 自动等待启用;可选超时包含初始化所用时间。`onEvent` 返回可重复调用的取消订阅函数,断开连接自动移除本连接注册的监听。结构化日志和堆探测复用同一 CDP 通道;重复 `enableLog` 仍会刷新日志订阅。实际域、命令和结果由目标 DevTools 决定,可先用 `listProtocol()` 查询。
|
|
191
|
+
|
|
192
|
+
### 4.9 触摸事件字段
|
|
193
|
+
|
|
194
|
+
`touchstart`、`touchmove`、`touchend` 和 `dispatchEvent` 均接受标准字段 `changedTouches`,会将触点坐标和触点数组交给页面事件处理器。
|
|
195
|
+
|
|
196
|
+
```ts
|
|
197
|
+
const point = { identifier: 1, pageX: 40, pageY: 60, clientX: 40, clientY: 60 }
|
|
198
|
+
await button?.touchstart({ touches: [point], changedTouches: [point] })
|
|
199
|
+
await button?.touchend({ touches: [], changedTouches: [point] })
|
|
200
|
+
await button?.dispatchEvent({ eventName: 'touchstart', touches: [point], changedTouches: [point] })
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
旧拼写 `changeTouches` 保留为 deprecated 别名,发送前统一转换为 `changedTouches`;同时传入时以 `changedTouches` 为准。
|
|
204
|
+
|
|
205
|
+
### 4.10 异步断开与迁移
|
|
206
|
+
|
|
207
|
+
`MiniProgram.disconnect()`、`Connection.dispose()` 和 `Transport.close()` 现在返回 `Promise<void>`。调用时立即拒绝未完成 RPC、停止事件订阅并终止本连接,Promise 等待 socket 实际关闭;独立关闭默认最多等待 2 秒。并发调用共享同次清理结果,超时会报告关闭未确认,后续可重新确认迟到的关闭。启动失败清理仍使用启动操作剩余的总预算。
|
|
208
|
+
|
|
209
|
+
原来在同步清理回调或 `finally` 中直接调用 `disconnect()` 的代码,应迁移到可等待的调用链,返回或等待 Promise。`process.on('exit')` 无法等待异步清理,应在主动退出或信号处理流程中先 `await disconnect()`:
|
|
210
|
+
|
|
211
|
+
```ts
|
|
212
|
+
try {
|
|
213
|
+
console.log(await miniProgram.currentPage())
|
|
214
|
+
}
|
|
215
|
+
finally {
|
|
216
|
+
await miniProgram.disconnect()
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
`disconnect()` 只断开连接;关闭受管项目窗口仍由持有窗口 owner 的会话 `close()` 负责。重连复用已有窗口的 endpoint,不重新启动 IDE。清理失败会抛出,调用方不能据此记录端口租约、窗口或快照已释放。
|
|
221
|
+
|
|
222
|
+
headless provider 保留同名 `CDP()` 入口,调用会明确报告 `HEADLESS_PROTOCOL_UNSUPPORTED`,不提供 inspector 后端。原始 `send` 仅支持 `Tool.getInfo`、`App.getCurrentPage`、`App.getPageStack`、`App.callFunction`、`App.callWxMethod`;其他协议明确报不支持。headless 的异步断开释放独占运行时,其结果不能证明真实 IDE 窗口已关闭。
|
|
223
|
+
|
|
224
|
+
### 4.11 Headless 原生控件边界
|
|
225
|
+
|
|
226
|
+
`Launcher.launch({ platform: 'wechat', runtimeProvider: 'headless', projectPath })` 使用 simulator 的真实渲染树与原生事件模型。未禁用的 `button form-type="submit"` 可以触发表单默认提交,无需额外调用业务 submit 方法;`rich-text` 的结构化节点和 HTML 内容可以通过通用 `text()` 观察,更新和清空均反映在渲染结果中。
|
|
227
|
+
|
|
228
|
+
一次原生分发在后续监听器同步失败时,仍等待此前已启动的异步处理。单一错误原样抛出;同步和异步处理同时失败时,以 `AggregateError.errors` 保留各错误,并以原同步错误作为 `cause`。
|
|
229
|
+
|
|
230
|
+
表单保留组件/插槽归属,字段值来自当前渲染绑定;未绑定输入的宿主状态、自定义 `wx://form-field` 值导出、reset、真实 `formId` 上报不在此能力范围内。富文本内容保持惰性,不作为 WXML 执行;`attr('nodes')` 仍返回字符串表示。Headless 通过不等于微信 IDE 或真机通过,不能替代目标宿主验收。
|
|
231
|
+
|
|
144
232
|
## 5. 主要导出
|
|
145
233
|
|
|
146
234
|
| 导出 | 说明 |
|
|
@@ -164,3 +252,11 @@ pnpm --filter @weapp-vite/miniprogram-automator typecheck
|
|
|
164
252
|
|
|
165
253
|
- 仓库:https://github.com/weapp-vite/weapp-vite
|
|
166
254
|
- `weapp-ide-cli`:[../weapp-ide-cli/README.md](../weapp-ide-cli/README.md)
|
|
255
|
+
|
|
256
|
+
## 启动预算与取消
|
|
257
|
+
|
|
258
|
+
微信 DevTools 的 `launch` / `connect` 使用一次总 `timeout`(默认 30 秒)。路径准备、端口租约、HTTP 适配、WebSocket、版本与 App ready 均消耗剩余预算,自动重试不重置 deadline。可传 `signal` 取消;成功后连接归调用方管理。
|
|
259
|
+
|
|
260
|
+
失败保留 `cause`,`error.operation` 包含阶段、最后成功阶段、耗时、剩余预算、尝试次数、未退出操作数量及本次资源清理状态。清理 `pending` 表示在预算内未确认退出,不能当作资源已释放。迟到连接只断开自身 WebSocket;启动器只终止持有句柄的 CLI 子进程,不据此认领 IDE 宿主或清理其他项目。无需在 App ready 后再固定等待五秒。
|
|
261
|
+
|
|
262
|
+
启动失败还会附加捕获的 CLI stdout/stderr 尾部输出,最多保留 32,768 个字符,截断时明确标记,并隐藏凭据。输出诊断保留原始 `cause`、错误分类和总预算信息。
|
package/dist/index.d.mts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { OPERATION_TIMEOUT_CODE, OperationDiagnostics, OperationErrorCategory, OperationLifecycle, OperationStepOptions, classifyOperationError, isRecoverableOperationError, readWechatLoginState } from "./operation.mjs";
|
|
1
2
|
import { EventEmitter } from "node:events";
|
|
2
3
|
import WebSocket from "ws";
|
|
3
4
|
import { Buffer } from "node:buffer";
|
|
@@ -31,13 +32,45 @@ declare function get(label?: string): SmartappLogger;
|
|
|
31
32
|
declare function currentTimestamp(): number;
|
|
32
33
|
declare function delay(ms: number): Promise<void>;
|
|
33
34
|
//#endregion
|
|
35
|
+
//#region src/appServiceHeap.d.ts
|
|
36
|
+
interface AppServiceHeapUsageOptions {
|
|
37
|
+
/** 单次协议请求的超时预算,单位毫秒。 */
|
|
38
|
+
timeout?: number;
|
|
39
|
+
}
|
|
40
|
+
type AppServiceHeapUsage = {
|
|
41
|
+
status: 'available';
|
|
42
|
+
source: 'appservice-cdp-runtime';
|
|
43
|
+
usedSize: number;
|
|
44
|
+
totalSize: number;
|
|
45
|
+
} | {
|
|
46
|
+
status: 'unsupported';
|
|
47
|
+
source: 'appservice-cdp-runtime';
|
|
48
|
+
reason: 'protocol-unimplemented' | 'method-not-found';
|
|
49
|
+
};
|
|
50
|
+
//#endregion
|
|
51
|
+
//#region src/cdp/index.d.ts
|
|
52
|
+
interface CDPCommandOptions {
|
|
53
|
+
/** 启用通道与执行命令共享的超时预算,单位毫秒。 */
|
|
54
|
+
timeout?: number;
|
|
55
|
+
}
|
|
56
|
+
type CDPEventListener = (domain: string, event: string, params: any) => void;
|
|
57
|
+
interface CDPSession {
|
|
58
|
+
enable: (options?: CDPCommandOptions) => Promise<unknown>;
|
|
59
|
+
sendCommand: <T = any>(domain: string, method: string, params?: Record<string, unknown>, options?: CDPCommandOptions) => Promise<T>;
|
|
60
|
+
listProtocol: (options?: CDPCommandOptions) => Promise<any>;
|
|
61
|
+
onEvent: (listener: CDPEventListener) => () => void;
|
|
62
|
+
}
|
|
63
|
+
//#endregion
|
|
34
64
|
//#region src/Transport.d.ts
|
|
35
65
|
/** Transport 的实现。 */
|
|
36
66
|
declare class Transport extends EventEmitter {
|
|
37
67
|
private ws;
|
|
68
|
+
private closed;
|
|
69
|
+
private terminating;
|
|
70
|
+
private closing?;
|
|
38
71
|
constructor(ws: WebSocket);
|
|
39
72
|
send(message: string): void;
|
|
40
|
-
close(): void
|
|
73
|
+
close(): Promise<void>;
|
|
41
74
|
}
|
|
42
75
|
//#endregion
|
|
43
76
|
//#region src/Connection.d.ts
|
|
@@ -46,24 +79,31 @@ interface SendOptions {
|
|
|
46
79
|
}
|
|
47
80
|
interface ToolInfo {
|
|
48
81
|
version?: string;
|
|
82
|
+
SDKVersion?: string;
|
|
49
83
|
}
|
|
50
84
|
/** Connection 的实现。 */
|
|
51
85
|
declare class Connection extends EventEmitter {
|
|
52
86
|
private transport;
|
|
87
|
+
private disposed;
|
|
88
|
+
private disposing?;
|
|
53
89
|
private callbacks;
|
|
54
90
|
private useAppServicePageProtocol;
|
|
55
91
|
private useAppServicePageMethod;
|
|
92
|
+
private useComponentCallerBridge;
|
|
56
93
|
constructor(transport: Transport);
|
|
57
94
|
send(method: string, params?: Record<string, any>, options?: SendOptions): Promise<any>;
|
|
58
|
-
dispose(): void
|
|
95
|
+
dispose(): Promise<void>;
|
|
96
|
+
private closeTransport;
|
|
59
97
|
/** 根据 DevTools 版本选择稳定的 Page 协议实现。 */
|
|
60
98
|
configureToolInfo(info: ToolInfo): void;
|
|
61
99
|
get prefersAppServicePageProtocol(): boolean;
|
|
62
100
|
/** 页面方法调用独立选择协议,不影响节点查询及其组件作用域。 */
|
|
63
101
|
get prefersAppServicePageMethod(): boolean;
|
|
102
|
+
/** 仅为实测存在跨上下文 token 错绑的 IDE 与基础库启用真实 caller 桥接。 */
|
|
103
|
+
get prefersComponentCallerBridge(): boolean;
|
|
64
104
|
private onMessage;
|
|
65
105
|
private onClose;
|
|
66
|
-
static create(url: string, timeout?: number): Promise<Connection>;
|
|
106
|
+
static create(url: string, timeout?: number, signal?: AbortSignal): Promise<Connection>;
|
|
67
107
|
}
|
|
68
108
|
//#endregion
|
|
69
109
|
//#region src/structuredConsole.d.ts
|
|
@@ -138,6 +178,8 @@ interface ITouch {
|
|
|
138
178
|
/** ITouchEventOptions 的类型定义。 */
|
|
139
179
|
interface ITouchEventOptions {
|
|
140
180
|
touches?: ITouch[];
|
|
181
|
+
changedTouches?: ITouch[];
|
|
182
|
+
/** @deprecated 请使用 changedTouches,发送时会自动转换旧字段。 */
|
|
141
183
|
changeTouches?: ITouch[];
|
|
142
184
|
}
|
|
143
185
|
/** IEventOptions 的类型定义。 */
|
|
@@ -145,6 +187,8 @@ interface IEventOptions {
|
|
|
145
187
|
eventName: string;
|
|
146
188
|
$?: string;
|
|
147
189
|
touches?: ITouch[];
|
|
190
|
+
changedTouches?: ITouch[];
|
|
191
|
+
/** @deprecated 请使用 changedTouches,发送时会自动转换旧字段。 */
|
|
148
192
|
changeTouches?: ITouch[];
|
|
149
193
|
detail?: Record<string, any>;
|
|
150
194
|
}
|
|
@@ -160,7 +204,7 @@ declare class Element {
|
|
|
160
204
|
protected nodeId: string | null;
|
|
161
205
|
private videoId;
|
|
162
206
|
private id;
|
|
163
|
-
|
|
207
|
+
protected pageId: number;
|
|
164
208
|
private publicProps?;
|
|
165
209
|
constructor(connection: Connection, options: IElementOptions, elementMap: ElementMap);
|
|
166
210
|
$(selector: string, options?: ElementQueryOptions): Promise<Element | null>;
|
|
@@ -358,8 +402,11 @@ declare class MiniProgram extends EventEmitter {
|
|
|
358
402
|
private logEnabling?;
|
|
359
403
|
private structuredLogs;
|
|
360
404
|
private structuredConsole;
|
|
405
|
+
private readonly cdp;
|
|
361
406
|
private pageMap;
|
|
362
407
|
private nativeIns?;
|
|
408
|
+
private disconnecting?;
|
|
409
|
+
private closing?;
|
|
363
410
|
constructor(connection: Connection);
|
|
364
411
|
pageStack(): Promise<any>;
|
|
365
412
|
navigateTo(url: string): Promise<Page>;
|
|
@@ -381,10 +428,13 @@ declare class MiniProgram extends EventEmitter {
|
|
|
381
428
|
restorePluginWxMethod(pluginId: string, method: string): Promise<void>;
|
|
382
429
|
evaluate(appFunction: AutomatorCallable | string, ...args: any[]): Promise<any>;
|
|
383
430
|
evaluateWithOptions(appFunction: AutomatorCallable | string, options?: EvaluateOptions, ...args: any[]): Promise<any>;
|
|
431
|
+
/** 探测并读取 AppService JS 堆;明确不支持时返回原因,连接故障与无效响应继续抛出。 */
|
|
432
|
+
getAppServiceHeapUsage(options?: AppServiceHeapUsageOptions): Promise<AppServiceHeapUsage>;
|
|
384
433
|
pageScrollTo(scrollTop: number): Promise<void>;
|
|
385
434
|
close(): Promise<void>;
|
|
386
435
|
remote(auto?: boolean): Promise<void>;
|
|
387
|
-
disconnect(): void
|
|
436
|
+
disconnect(): Promise<void>;
|
|
437
|
+
private stopSubscriptions;
|
|
388
438
|
/** 等待已接收的结构化日志完成 Error 属性检查并发布。 */
|
|
389
439
|
flushConsole(): Promise<void>;
|
|
390
440
|
enableLog(timeout?: number, options?: ConsoleLogOptions): Promise<void>;
|
|
@@ -392,7 +442,7 @@ declare class MiniProgram extends EventEmitter {
|
|
|
392
442
|
exposeFunction(name: string, bindingFunction: AutomatorCallable): Promise<void>;
|
|
393
443
|
checkVersion(timeout?: number): Promise<void>;
|
|
394
444
|
/**
|
|
395
|
-
* @description
|
|
445
|
+
* @description 等待原生协议返回真实页面标识和路径,避免返回半就绪自动化会话。
|
|
396
446
|
*/
|
|
397
447
|
waitForAppReady(timeout?: number): Promise<void>;
|
|
398
448
|
screenshot(options?: IScreenshotOptions): Promise<string | undefined>;
|
|
@@ -425,7 +475,12 @@ declare class MiniProgram extends EventEmitter {
|
|
|
425
475
|
private createPageFromPayload;
|
|
426
476
|
private createPagesFromPayloads;
|
|
427
477
|
private readAppFunctionPageStack;
|
|
428
|
-
|
|
478
|
+
/** 返回当前连接共享的 CDP 调试入口。 */
|
|
479
|
+
CDP(): CDPSession;
|
|
480
|
+
/** 发送原始自动化协议,沿用连接的请求超时及清理契约。 */
|
|
481
|
+
send(method: string, params?: Record<string, any>, options?: {
|
|
482
|
+
timeout?: number;
|
|
483
|
+
}): Promise<any>;
|
|
429
484
|
private onLogAdded;
|
|
430
485
|
private onBindingCalled;
|
|
431
486
|
private onExceptionThrown;
|
|
@@ -605,11 +660,13 @@ export declare function normalizePlatform(platform?: MiniprogramAutomatorPlatfor
|
|
|
605
660
|
//#region src/Launcher.d.ts
|
|
606
661
|
export interface IConnectOptions {
|
|
607
662
|
wsEndpoint: string;
|
|
663
|
+
signal?: AbortSignal;
|
|
608
664
|
timeout?: number;
|
|
609
665
|
platform?: MiniprogramAutomatorPlatform;
|
|
610
666
|
}
|
|
611
667
|
/** ILaunchOptions 的类型定义。 */
|
|
612
668
|
export interface ILaunchOptions {
|
|
669
|
+
signal?: AbortSignal;
|
|
613
670
|
platform?: MiniprogramAutomatorPlatform;
|
|
614
671
|
cliPath?: string;
|
|
615
672
|
connectType?: string;
|
|
@@ -669,6 +726,17 @@ declare class Automator {
|
|
|
669
726
|
launch(options: ILaunchOptions): Promise<any>;
|
|
670
727
|
}
|
|
671
728
|
//#endregion
|
|
729
|
+
//#region src/launcher/portLease.d.ts
|
|
730
|
+
interface AutomatorPortLease {
|
|
731
|
+
path?: string;
|
|
732
|
+
port: number;
|
|
733
|
+
release: () => Promise<void>;
|
|
734
|
+
}
|
|
735
|
+
/**
|
|
736
|
+
* @description 选择并短暂租约一个自动化端口,避免并发启动选择到同一端口。
|
|
737
|
+
*/
|
|
738
|
+
export declare function acquireAutomatorPortLease(preferredPort?: number): Promise<AutomatorPortLease>;
|
|
739
|
+
//#endregion
|
|
672
740
|
//#region src/util.d.ts
|
|
673
741
|
/** decodeQrCode 的方法封装。 */
|
|
674
742
|
export declare function decodeQrCode(qrCode: string): Promise<string>;
|
|
@@ -705,4 +773,4 @@ export declare const SmartappAutomator: {
|
|
|
705
773
|
};
|
|
706
774
|
};
|
|
707
775
|
//#endregion
|
|
708
|
-
export { Automator, Connection, type ConsoleLogOptions, type ConsoleRemoteObject, Element, Launcher, MiniProgram, Native, Page, type StructuredConsoleEntry, Transport };
|
|
776
|
+
export { type AppServiceHeapUsage, type AppServiceHeapUsageOptions, Automator, type AutomatorPortLease, type CDPCommandOptions, type CDPEventListener, type CDPSession, Connection, type ConsoleLogOptions, type ConsoleRemoteObject, Element, type IEventOptions, type ITouch, type ITouchEventOptions, Launcher, MiniProgram, Native, OPERATION_TIMEOUT_CODE, OperationDiagnostics, OperationErrorCategory, OperationLifecycle, OperationStepOptions, Page, type StructuredConsoleEntry, Transport, classifyOperationError, isRecoverableOperationError, readWechatLoginState };
|