snapshot-checker 0.1.1

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.
Files changed (70) hide show
  1. package/README.md +283 -0
  2. package/dist/commands/context_demo.d.ts +18 -0
  3. package/dist/commands/context_demo.d.ts.map +1 -0
  4. package/dist/commands/context_demo.js +68 -0
  5. package/dist/commands/context_demo.js.map +1 -0
  6. package/dist/commands/forkall.d.ts +54 -0
  7. package/dist/commands/forkall.d.ts.map +1 -0
  8. package/dist/commands/forkall.js +192 -0
  9. package/dist/commands/forkall.js.map +1 -0
  10. package/dist/commands/mac-example.d.ts +23 -0
  11. package/dist/commands/mac-example.d.ts.map +1 -0
  12. package/dist/commands/mac-example.js +39 -0
  13. package/dist/commands/mac-example.js.map +1 -0
  14. package/dist/commands/timeout_demo.d.ts +5 -0
  15. package/dist/commands/timeout_demo.d.ts.map +1 -0
  16. package/dist/commands/timeout_demo.js +48 -0
  17. package/dist/commands/timeout_demo.js.map +1 -0
  18. package/dist/src/cli.d.ts +3 -0
  19. package/dist/src/cli.d.ts.map +1 -0
  20. package/dist/src/cli.js +215 -0
  21. package/dist/src/cli.js.map +1 -0
  22. package/dist/src/executor.d.ts +8 -0
  23. package/dist/src/executor.d.ts.map +1 -0
  24. package/dist/src/executor.js +6 -0
  25. package/dist/src/executor.js.map +1 -0
  26. package/dist/src/groupSpecs.d.ts +7 -0
  27. package/dist/src/groupSpecs.d.ts.map +1 -0
  28. package/dist/src/groupSpecs.js +19 -0
  29. package/dist/src/groupSpecs.js.map +1 -0
  30. package/dist/src/index.d.ts +6 -0
  31. package/dist/src/index.d.ts.map +1 -0
  32. package/dist/src/index.js +5 -0
  33. package/dist/src/index.js.map +1 -0
  34. package/dist/src/lib/programmatic.d.ts +48 -0
  35. package/dist/src/lib/programmatic.d.ts.map +1 -0
  36. package/dist/src/lib/programmatic.js +62 -0
  37. package/dist/src/lib/programmatic.js.map +1 -0
  38. package/dist/src/runCommand.d.ts +67 -0
  39. package/dist/src/runCommand.d.ts.map +1 -0
  40. package/dist/src/runCommand.js +286 -0
  41. package/dist/src/runCommand.js.map +1 -0
  42. package/dist/src/runGroups.d.ts +36 -0
  43. package/dist/src/runGroups.d.ts.map +1 -0
  44. package/dist/src/runGroups.js +123 -0
  45. package/dist/src/runGroups.js.map +1 -0
  46. package/dist/src/runners/builtinFunctionRunner.d.ts +7 -0
  47. package/dist/src/runners/builtinFunctionRunner.d.ts.map +1 -0
  48. package/dist/src/runners/builtinFunctionRunner.js +56 -0
  49. package/dist/src/runners/builtinFunctionRunner.js.map +1 -0
  50. package/dist/src/runners/embedRunner.d.ts +7 -0
  51. package/dist/src/runners/embedRunner.d.ts.map +1 -0
  52. package/dist/src/runners/embedRunner.js +129 -0
  53. package/dist/src/runners/embedRunner.js.map +1 -0
  54. package/dist/src/runners/index.d.ts +5 -0
  55. package/dist/src/runners/index.d.ts.map +1 -0
  56. package/dist/src/runners/index.js +4 -0
  57. package/dist/src/runners/index.js.map +1 -0
  58. package/dist/src/runners/shellRunner.d.ts +8 -0
  59. package/dist/src/runners/shellRunner.d.ts.map +1 -0
  60. package/dist/src/runners/shellRunner.js +142 -0
  61. package/dist/src/runners/shellRunner.js.map +1 -0
  62. package/dist/src/runners/types.d.ts +13 -0
  63. package/dist/src/runners/types.d.ts.map +1 -0
  64. package/dist/src/runners/types.js +2 -0
  65. package/dist/src/runners/types.js.map +1 -0
  66. package/dist/src/types.d.ts +122 -0
  67. package/dist/src/types.d.ts.map +1 -0
  68. package/dist/src/types.js +32 -0
  69. package/dist/src/types.js.map +1 -0
  70. package/package.json +55 -0
package/README.md ADDED
@@ -0,0 +1,283 @@
1
+ # snapshot-checker
2
+
3
+ 按顺序执行 **bat**、**mac**、**shell** 命令的 CLI 工具。支持**命令组**:可为每组命名,用 `--group` 指定执行某一或多个组;不指定时默认执行**当前系统支持的所有命令**(按 `defaultGroupOrder` 顺序)。
4
+
5
+ ## 命令类型
6
+
7
+ | kind | 说明 | 默认执行范围 |
8
+ |--------|------|----------------|
9
+ | `bat` | Windows 下用 `cmd /c` 执行 | 仅 Windows |
10
+ | `mac` | 面向 macOS 的命令 | 仅 macOS |
11
+ | `shell`| 通用 shell,使用当前系统默认 shell | 全平台 |
12
+
13
+ ## 安装与运行
14
+
15
+ ```bash
16
+ npm install
17
+ npm run build
18
+ npm start -- foo # 或: node dist/cli.js foo
19
+ ```
20
+
21
+ 开发时可直接用 tsx 跑(无需 build):
22
+
23
+ ```bash
24
+ npm run dev -- run
25
+ # 或
26
+ npm run run:example
27
+ ```
28
+
29
+ ## 配置命令与组(commands 目录)
30
+
31
+ 所有命令配置均放在项目根目录的 `commands/` 目录中:
32
+
33
+ - `commands/*.ts`:场景配置文件,例如 `foo.ts`、`bar.ts`,通过 `snapshot-checker foo` / `snapshot-checker bar` 等命令使用
34
+
35
+ 一个最简单的配置文件形如:
36
+
37
+ ```ts
38
+ export const groups: Groups = {
39
+ env: [
40
+ { kind: 'shell', description: '打印当前目录', run: 'pwd' },
41
+ { kind: 'shell', description: 'Node 版本', run: 'node -v' },
42
+ ],
43
+ list: [
44
+ { kind: 'shell', description: '列出文件', run: 'ls -la' },
45
+ ],
46
+ };
47
+
48
+ export const defaultGroupOrder: string[] = ['env', 'list'];
49
+ ```
50
+
51
+ - 不指定 `--group` 时:按 `defaultGroupOrder` 依次执行各组,且**只执行当前系统支持**的命令(shell 全平台;bat 仅 Windows;mac 仅 macOS)。
52
+ - 指定 `--group env list` 时:按给定顺序执行这些组内、且当前系统支持的命令。
53
+
54
+ 每条命令可加 `cwd` 指定工作目录。
55
+
56
+ ### 内置指令(embed)
57
+
58
+ 除平台命令外,还支持内置指令(`kind: 'embed'`),由执行器内部实现,不依赖系统 shell。
59
+
60
+ #### `sleep <seconds>`
61
+
62
+ 按指定秒数等待,例如:
63
+
64
+ ```ts
65
+ { kind: 'embed', run: 'sleep 3', description: '等待 3 秒' }
66
+ ```
67
+
68
+ #### `timeout <seconds>`(兼容 `timieout <seconds>`)
69
+
70
+ 最多等待指定秒数,并实时显示剩余时间;在可交互终端下,用户按任意键可立即结束等待。
71
+
72
+ 示例:
73
+
74
+ ```ts
75
+ {
76
+ kind: 'embed',
77
+ run: 'timeout 30',
78
+ description: '最多等待 30 秒,按任意键跳过',
79
+ }
80
+ ```
81
+
82
+ 行为说明:
83
+
84
+ - 使用同一行原地刷新倒计时(`[timeout] 剩余 Ns...`)。
85
+ - 到达超时时间后自动继续后续命令。
86
+ - 若检测到键盘输入则立即结束等待并继续。
87
+ - 在非 TTY 环境(如某些 CI)中会退化为仅按时间等待,不监听按键。
88
+
89
+ 仓库内完整示例见 `commands/timeout_demo.ts`(`npm run dev -- timeout_demo` 或 `node dist/cli.js timeout_demo`)。
90
+
91
+ ### 命令之间传递变量(上下文)
92
+
93
+ 命令执行器内置了一个**简单的上下文对象**,允许前一条命令将自己的输出写入变量,后续命令通过模板占位符引用这些变量。通过 CLI 跑场景时,该上下文在**整个场景执行期间**(含不同 `group`、不同块之间)**同一份共享**,因此可以把变量从 `getUser` 组传到 `greet` 组。仓库内示例见 `commands/context_demo.ts`。
94
+
95
+ - **写入变量:**在命令上增加 `captureToVar` 元数据
96
+ - **读取变量:**在 `run` / `file` / `args` / `cwd` / `description` 中使用 `{{varName}}` 占位符
97
+
98
+ 示例:
99
+
100
+ ```ts
101
+ // commands/example.ts
102
+ import type { Groups } from '../src/types.js';
103
+
104
+ export const groups: Groups = {
105
+ env: [
106
+ {
107
+ kind: 'shell',
108
+ description: '获取当前用户名',
109
+ run: 'whoami',
110
+ // 将整段 stdout 写入变量 user
111
+ // (比如 "alice"),供后续命令使用
112
+ // @ts-expect-error: 由执行器在运行时识别的扩展字段
113
+ captureToVar: {
114
+ name: 'user',
115
+ },
116
+ },
117
+ ],
118
+ greet: [
119
+ {
120
+ kind: 'shell',
121
+ description: '使用上一条命令得到的用户名',
122
+ run: 'echo "hello, {{user}}"',
123
+ },
124
+ ],
125
+ };
126
+
127
+ export const defaultGroupOrder = ['env', 'greet'];
128
+ ```
129
+
130
+ #### 仅提取输出的一部分
131
+
132
+ 如果需要从输出中提取一部分(比如只要第一行的数字),可以使用 `pattern` 和 `groupIndex`:
133
+
134
+ ```ts
135
+ {
136
+ kind: 'shell',
137
+ description: '获取某个进程 pid',
138
+ run: 'pidof my-app',
139
+ // @ts-expect-error: 由执行器在运行时识别的扩展字段
140
+ captureToVar: {
141
+ name: 'pid',
142
+ pattern: '^(\\d+)', // 匹配第一行的数字
143
+ groupIndex: 1, // 取第 1 个捕获组
144
+ },
145
+ },
146
+ {
147
+ kind: 'shell',
148
+ description: '用 pid 做点事',
149
+ run: 'echo "pid is {{pid}}"',
150
+ }
151
+ ```
152
+
153
+ `captureToVar` 字段说明:
154
+
155
+ - **name**: 变量名(如 `pid`、`user`)
156
+ - **from**: 可选,`"stdout"`(默认)或 `"stderr"`,表示从哪个输出中取值
157
+ - **pattern**: 可选,正则表达式字符串;不传时使用整个输出(去掉首尾空白)
158
+ - **groupIndex**: 可选,指定要取的捕获组索引,默认 `1`
159
+
160
+ ### 多场景配置示例:foo / bar
161
+
162
+ - 在 `commands/config.ts` 中定义默认场景(供 `run` 使用)
163
+ - 在 `commands/foo.ts` 中定义 `foo` 场景:
164
+
165
+ ```ts
166
+ // commands/foo.ts
167
+ export const groups: Groups = {
168
+ env: [
169
+ { kind: 'shell', description: '[foo] 打印当前目录', run: 'pwd' },
170
+ { kind: 'shell', description: '[foo] 显示 Node 版本', run: 'node -v' },
171
+ ],
172
+ list: [{ kind: 'shell', description: '[foo] 列出当前目录', run: 'ls -la' }],
173
+ };
174
+
175
+ export const defaultGroupOrder: string[] = ['env', 'list'];
176
+ ```
177
+
178
+ - 在 `commands/bar.ts` 中定义 `bar` 场景:
179
+
180
+ ```ts
181
+ // commands/bar.ts
182
+ export const groups: Groups = {
183
+ env: [
184
+ { kind: 'shell', description: '[bar] 打印当前目录', run: 'pwd' },
185
+ { kind: 'shell', description: '[bar] 显示 Node 版本', run: 'node -v' },
186
+ ],
187
+ list: [{ kind: 'shell', description: '[bar] 列出当前目录', run: 'ls -la' }],
188
+ extra: [{ kind: 'shell', description: '[bar] 额外命令示例', run: 'echo extra from bar' }],
189
+ };
190
+
191
+ export const defaultGroupOrder: string[] = ['env', 'extra', 'list'];
192
+ ```
193
+
194
+ CLI 会自动将 `commands` 目录下除 `config.*` 外的每个文件视为一个**场景命令**,文件名即子命令名:
195
+
196
+ - `commands/foo.ts` → `snapshot-checker foo`
197
+ - `commands/bar.ts` → `snapshot-checker bar`
198
+
199
+ ## CLI 选项
200
+
201
+ - `--wait`:所有**前台**命令跑完后,继续等待**后台**命令(`background: true`)自然退出再结束进程;不加则前台全部结束后会**优雅结束**这些后台子进程并立即退出 CLI。
202
+ - `snapshot-checker <scene>` — 使用 `commands/<scene>.ts` 中的配置执行命令,例如:
203
+ - `snapshot-checker foo` 使用 `commands/foo.ts` 的 `groups` 与 `defaultGroupOrder`
204
+ - `snapshot-checker bar` 使用 `commands/bar.ts` 的 `groups` 与 `defaultGroupOrder`
205
+ - `snapshot-checker foo --list` 仅列出 `foo` 场景中的命令,不执行
206
+ - `snapshot-checker bar --list` 仅列出 `bar` 场景中的命令,不执行
207
+
208
+ ## 简单用例
209
+
210
+ ```bash
211
+ # 使用 foo 场景(commands/foo.ts)执行命令
212
+ node dist/cli.js foo
213
+
214
+ # 仅查看 foo 场景中的命令(不执行)
215
+ node dist/cli.js foo --list
216
+
217
+ # 使用 bar 场景(commands/bar.ts)执行命令
218
+ node dist/cli.js bar --group env,extra
219
+
220
+ # 仅查看 bar 场景中的命令(不执行)
221
+ node dist/cli.js bar --list
222
+ ```
223
+
224
+ ## 项目结构
225
+
226
+ ```
227
+ src/
228
+ cli.ts # CLI 入口,负责解析参数并调用执行逻辑
229
+ runCommand.ts # 单条/多条命令执行(无 group 概念)
230
+ runGroups.ts # 组规格解析、分块、按组执行(含组间间隔)
231
+ executor.ts # 统一导出 runCommand + runGroups
232
+ types.ts # 类型定义
233
+ index.ts # 库导出(从 commands/config.ts 导出默认 groups)
234
+
235
+ commands/
236
+ foo.ts # foo 场景示例:自定义 groups/defaultGroupOrder
237
+ bar.ts # bar 场景示例:自定义 groups/defaultGroupOrder
238
+
239
+ demos/
240
+ consumer-app/ # 独立示例:npm install snapshot-checker 后的调用方式
241
+ ```
242
+
243
+ ## 发布到 npm
244
+
245
+ ```bash
246
+ npm login
247
+ npm run build # prepublishOnly 也会在 publish 时执行
248
+ npm publish
249
+ ```
250
+
251
+ 若包名 `snapshot-checker` 已被占用,请在 `package.json` 中改为作用域包(如 `@your-org/snapshot-checker`)并相应更新下文导入路径。
252
+
253
+ ## 作为库使用(npm install 之后)
254
+
255
+ 安装:
256
+
257
+ ```bash
258
+ npm install snapshot-checker
259
+ ```
260
+
261
+ 在业务项目中调用**运行接口**(入口与源码中 `src/index.ts` 导出一致),并从一个或多个**包内场景模块**生成命令组(发布产物中为 `dist/commands/*.js`,通过 `exports` 暴露):
262
+
263
+ ```ts
264
+ import { resolveScenario, runScenarioGroups } from 'snapshot-checker';
265
+ import * as contextDemo from 'snapshot-checker/commands/context_demo.js';
266
+ import * as forkall from 'snapshot-checker/commands/forkall.js';
267
+
268
+ const { groups, defaultGroupOrder } = resolveScenario(forkall, {
269
+ app: 'com.example.app',
270
+ eventPath: 'snapshot/hmb_forkall_report_image_failure',
271
+ mode: 'monitor',
272
+ });
273
+
274
+ await runScenarioGroups({ groups, defaultGroupOrder, stopOnError: true });
275
+ ```
276
+
277
+ 也可在业务项目自建 `commands/*.ts`,仅使用 `snapshot-checker` 的执行 API(`runScenarioGroups`、`getGroupChunks` 等),不引用包内场景。
278
+
279
+ 独立 Node 示例工程(依赖 registry 上的本包):见 `demos/consumer-app/README.md`。
280
+
281
+ ## License
282
+
283
+ MIT
@@ -0,0 +1,18 @@
1
+ import { type Groups } from '../src/types.js';
2
+ /**
3
+ * 示例场景:演示如何在命令之间传递变量(含跨不同 group)。
4
+ *
5
+ * 使用方式(开发态):
6
+ * npm run dev -- context_demo
7
+ *
8
+ * 使用方式(构建后):
9
+ * node dist/cli.js context_demo
10
+ *
11
+ * 作为 npm 包被外部项目引用时:
12
+ * import { resolveScenario, runScenarioGroups } from 'snapshot-checker';
13
+ * import * as contextDemo from 'snapshot-checker/commands/context_demo.js';
14
+ * 完整示例见 demos/consumer-app(需先发布包并 npm install snapshot-checker)。
15
+ */
16
+ export declare const groups: Groups;
17
+ export declare const defaultGroupOrder: string[];
18
+ //# sourceMappingURL=context_demo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context_demo.d.ts","sourceRoot":"","sources":["../../commands/context_demo.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4D,KAAK,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAYxG;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,MAAM,EAAE,MA0CpB,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,MAAM,EAAqD,CAAC"}
@@ -0,0 +1,68 @@
1
+ import { CommandKind, getCurrentPlatformKind } from '../src/types.js';
2
+ /** 与当前 OS 一致,避免示例在非 macOS 上被整组跳过 */
3
+ const kind = getCurrentPlatformKind();
4
+ async function foo(ctx) {
5
+ const user = ctx.user ?? 'unknown';
6
+ const message = `foo says hi to ${user}`;
7
+ ctx.fromFoo = message;
8
+ console.log(message);
9
+ }
10
+ /**
11
+ * 示例场景:演示如何在命令之间传递变量(含跨不同 group)。
12
+ *
13
+ * 使用方式(开发态):
14
+ * npm run dev -- context_demo
15
+ *
16
+ * 使用方式(构建后):
17
+ * node dist/cli.js context_demo
18
+ *
19
+ * 作为 npm 包被外部项目引用时:
20
+ * import { resolveScenario, runScenarioGroups } from 'snapshot-checker';
21
+ * import * as contextDemo from 'snapshot-checker/commands/context_demo.js';
22
+ * 完整示例见 demos/consumer-app(需先发布包并 npm install snapshot-checker)。
23
+ */
24
+ export const groups = {
25
+ getUser: [
26
+ {
27
+ kind,
28
+ description: '获取当前用户名,并写入变量 user',
29
+ run: 'whoami',
30
+ captureToVar: {
31
+ name: 'user',
32
+ },
33
+ },
34
+ ],
35
+ greet: [
36
+ {
37
+ kind,
38
+ description: '使用上一条命令得到的用户名',
39
+ run: 'echo "hello, {{user}}"',
40
+ },
41
+ ],
42
+ builtinFn: [
43
+ {
44
+ kind: CommandKind.BuiltinFunction,
45
+ description: '执行内置函数 foo,并写入变量 fromFoo',
46
+ func: foo,
47
+ },
48
+ {
49
+ kind,
50
+ description: '读取 foo 写入的变量',
51
+ run: 'echo "{{fromFoo}}"',
52
+ },
53
+ ],
54
+ builtinFail: [
55
+ {
56
+ kind: CommandKind.BuiltinFunction,
57
+ description: '演示:返回 false 表示失败(可配合 --stop-on-error)',
58
+ func: () => false,
59
+ },
60
+ {
61
+ kind,
62
+ description: '这条命令在 --stop-on-error 下不会执行',
63
+ run: 'echo "should not run when stop-on-error is enabled"',
64
+ },
65
+ ],
66
+ };
67
+ export const defaultGroupOrder = ['getUser', 'greet', 'builtinFn', 'builtinFail'];
68
+ //# sourceMappingURL=context_demo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context_demo.js","sourceRoot":"","sources":["../../commands/context_demo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,sBAAsB,EAAoC,MAAM,iBAAiB,CAAC;AAExG,oCAAoC;AACpC,MAAM,IAAI,GAAG,sBAAsB,EAAE,CAAC;AAEtC,KAAK,UAAU,GAAG,CAAC,GAAmB;IACpC,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI,SAAS,CAAC;IACnC,MAAM,OAAO,GAAG,kBAAkB,IAAI,EAAE,CAAC;IACzC,GAAG,CAAC,OAAO,GAAG,OAAO,CAAC;IACtB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACvB,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,MAAM,GAAW;IAC5B,OAAO,EAAE;QACP;YACE,IAAI;YACJ,WAAW,EAAE,oBAAoB;YACjC,GAAG,EAAE,QAAQ;YACb,YAAY,EAAE;gBACZ,IAAI,EAAE,MAAM;aACb;SACF;KACF;IACD,KAAK,EAAE;QACL;YACE,IAAI;YACJ,WAAW,EAAE,eAAe;YAC5B,GAAG,EAAE,wBAAwB;SAC9B;KACF;IACD,SAAS,EAAE;QACT;YACE,IAAI,EAAE,WAAW,CAAC,eAAe;YACjC,WAAW,EAAE,0BAA0B;YACvC,IAAI,EAAE,GAAG;SACV;QACD;YACE,IAAI;YACJ,WAAW,EAAE,cAAc;YAC3B,GAAG,EAAE,oBAAoB;SAC1B;KACF;IACD,WAAW,EAAE;QACX;YACE,IAAI,EAAE,WAAW,CAAC,eAAe;YACjC,WAAW,EAAE,uCAAuC;YACpD,IAAI,EAAE,GAAG,EAAE,CAAC,KAAK;SAClB;QACD;YACE,IAAI;YACJ,WAAW,EAAE,6BAA6B;YAC1C,GAAG,EAAE,qDAAqD;SAC3D;KACF;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAa,CAAC,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,aAAa,CAAC,CAAC"}
@@ -0,0 +1,54 @@
1
+ import type { Groups } from '../src/types.js';
2
+ /**
3
+ * forkall 场景的基础占位配置。
4
+ * 实际要执行的命令会在 applyOptions 中,根据 CLI 传入的参数(eventPath/app 等)动态生成。
5
+ *
6
+ * 作为 npm 包被外部项目引用时:
7
+ * import * as forkall from 'snapshot-checker/commands/forkall.js';
8
+ * resolveScenario(forkall, { app, eventPath, ... })
9
+ * 完整示例见 demos/consumer-app。
10
+ */
11
+ export declare const groups: Groups;
12
+ export declare const defaultGroupOrder: string[];
13
+ export declare const options: ({
14
+ flags: string;
15
+ description: string;
16
+ defaultValue?: undefined;
17
+ } | {
18
+ flags: string;
19
+ description: string;
20
+ defaultValue: string;
21
+ })[];
22
+ interface ForkallOptions {
23
+ eventPath?: string;
24
+ app?: string;
25
+ systemSymbolFilePath?: string;
26
+ logKey?: string;
27
+ duration?: string;
28
+ defaultTimeout?: string;
29
+ bufferSize?: string;
30
+ mode?: string;
31
+ }
32
+ /**
33
+ * 将 CLI 解析出来的参数应用到 forkall 场景,动态生成各阶段命令。
34
+ *
35
+ * 关键映射关系:
36
+ * - eventPath -> dump_stack.bat 中的 event_path
37
+ * - app -> dump_stack.bat 中的 app
38
+ * - systemSymbolFilePath -> dump_stack.bat 中的 system_symbol_file_path
39
+ * - logKey -> dump_stack.bat 中的 log_key(默认 pid)
40
+ * - duration -> dump_stack.bat 中的 duration(默认 70)
41
+ * - defaultTimeout -> dump_stack.bat 中的 default_timeout(默认 90)
42
+ * - bufferSize -> dump_stack.bat 中的 buffer_size(默认 512000)
43
+ * - mode -> dump_stack.bat 中根据参数跳转到 REBOOT 或 MONITOR 的条件分支
44
+ */
45
+ export declare function applyOptions(ctx: {
46
+ groups: Groups;
47
+ defaultGroupOrder: string[];
48
+ options: ForkallOptions;
49
+ }): {
50
+ groups: Groups;
51
+ defaultGroupOrder: string[];
52
+ };
53
+ export {};
54
+ //# sourceMappingURL=forkall.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forkall.d.ts","sourceRoot":"","sources":["../../commands/forkall.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAE9C;;;;;;;;GAQG;AACH,eAAO,MAAM,MAAM,EAAE,MAAW,CAAC;AAEjC,eAAO,MAAM,iBAAiB,EAAE,MAAM,EAAiD,CAAC;AAExF,eAAO,MAAM,OAAO;;;;;;;;IAqBnB,CAAC;AAEF,UAAU,cAAc;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,OAAO,EAAE,cAAc,CAAC;CACzB,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,EAAE,CAAA;CAAE,CAmKlD"}
@@ -0,0 +1,192 @@
1
+ import { CommandKind } from '../src/types.js';
2
+ /**
3
+ * forkall 场景的基础占位配置。
4
+ * 实际要执行的命令会在 applyOptions 中,根据 CLI 传入的参数(eventPath/app 等)动态生成。
5
+ *
6
+ * 作为 npm 包被外部项目引用时:
7
+ * import * as forkall from 'snapshot-checker/commands/forkall.js';
8
+ * resolveScenario(forkall, { app, eventPath, ... })
9
+ * 完整示例见 demos/consumer-app。
10
+ */
11
+ export const groups = {};
12
+ export const defaultGroupOrder = ['reboot', 'monitor', 'collect', 'analysis'];
13
+ export const options = [
14
+ { flags: '--event-path <path>', description: '事件路径' },
15
+ { flags: '--app <app>', description: '应用名' },
16
+ { flags: '--system-symbol-file-path <path>', description: '系统符号文件路径' },
17
+ { flags: '--log-key <key>', description: '日志过滤关键字(默认 pid)', defaultValue: 'pid' },
18
+ { flags: '--duration <seconds>', description: '采样持续时间(秒,默认 70)', defaultValue: '70' },
19
+ {
20
+ flags: '--default-timeout <seconds>',
21
+ description: '默认等待时间(秒,默认 90)',
22
+ defaultValue: '90',
23
+ },
24
+ {
25
+ flags: '--buffer-size <bytes>',
26
+ description: '缓冲区大小(字节,默认 512000)',
27
+ defaultValue: '512000',
28
+ },
29
+ {
30
+ flags: '--mode <mode>',
31
+ description: '执行模式:monitor 或 reboot-monitor',
32
+ defaultValue: 'monitor',
33
+ },
34
+ ];
35
+ /**
36
+ * 将 CLI 解析出来的参数应用到 forkall 场景,动态生成各阶段命令。
37
+ *
38
+ * 关键映射关系:
39
+ * - eventPath -> dump_stack.bat 中的 event_path
40
+ * - app -> dump_stack.bat 中的 app
41
+ * - systemSymbolFilePath -> dump_stack.bat 中的 system_symbol_file_path
42
+ * - logKey -> dump_stack.bat 中的 log_key(默认 pid)
43
+ * - duration -> dump_stack.bat 中的 duration(默认 70)
44
+ * - defaultTimeout -> dump_stack.bat 中的 default_timeout(默认 90)
45
+ * - bufferSize -> dump_stack.bat 中的 buffer_size(默认 512000)
46
+ * - mode -> dump_stack.bat 中根据参数跳转到 REBOOT 或 MONITOR 的条件分支
47
+ */
48
+ export function applyOptions(ctx) {
49
+ const { eventPath = '', app = '', systemSymbolFilePath = '', logKey = 'pid', duration = '70', defaultTimeout = '90', bufferSize = '512000', mode = 'monitor', } = ctx.options ?? {};
50
+ const eventName = eventPath ? eventPath.replace(/\//g, ':') : '';
51
+ const checkStateCommand = "hdc shell hidumper -s 1901 -a '-p libforkall_plugin.z.so --list'";
52
+ const rebootGroup = mode === 'reboot-monitor'
53
+ ? [
54
+ {
55
+ kind: CommandKind.Windows,
56
+ run: 'hdc shell "test ! -f /system/etc/hiview/hitrace_utils.json.bk && mv /system/etc/hiview/hitrace_utils.json /system/etc/hiview/hitrace_utils.json.bk"',
57
+ },
58
+ {
59
+ kind: CommandKind.Windows,
60
+ run: 'hdc shell "test ! -f /bin/hiperf && mv /bin/hiperf /bin/hiperf.bk"',
61
+ },
62
+ {
63
+ kind: CommandKind.Windows,
64
+ description: '上传hitrace配置文件',
65
+ run: 'hdc file send .\config\hitrace\hitrace_utils_snapshot.json /system/etc/hiview/hitrace_utils.json',
66
+ },
67
+ {
68
+ kind: CommandKind.Windows,
69
+ description: '配置自定义trace事件',
70
+ run: String.raw `hdc shell "sed -i 's|<TARGET_EVENT>|${eventPath}'|g /system/etc/hiview/hitrace_utils.json"`,
71
+ },
72
+ {
73
+ kind: CommandKind.Windows,
74
+ description: '配置hiperf权限',
75
+ run: 'hdc shell "chmod 755 /bin/hiperf && chcon u:object_r:hiperf_exec:s0 /bin/hiperf"',
76
+ },
77
+ {
78
+ kind: CommandKind.Windows,
79
+ description: '重启设备',
80
+ run: 'hdc shell reboot',
81
+ },
82
+ {
83
+ kind: CommandKind.Embed,
84
+ description: '等待设备重启',
85
+ run: `sleep ${defaultTimeout}`,
86
+ },
87
+ ]
88
+ : [];
89
+ const monitorGroup = [
90
+ {
91
+ kind: CommandKind.Windows,
92
+ description: '[forkall] 强制停止应用',
93
+ run: app ? `hdc shell aa force-stop ${app}` : 'echo "[forkall] app 未指定,跳过 force-stop"',
94
+ },
95
+ {
96
+ kind: CommandKind.Windows,
97
+ description: '[forkall] 检查当前可用事件列表',
98
+ run: checkStateCommand,
99
+ },
100
+ {
101
+ kind: CommandKind.Windows,
102
+ description: '[forkall] 启动 perf/hitrace 监控',
103
+ run: [
104
+ 'hdc shell "',
105
+ `echo [SnapshotChecker]: Setting Target && `,
106
+ `hitrace custom_event --overwrite -b ${bufferSize} -t ${duration} -o /data/local/tmp/snapshot_hitrace.txt && `,
107
+ eventName
108
+ ? `hiperf record -e ${eventName} --period 1 -s fp --clockid bootime --cpu-limit 100 -o /data/local/tmp/perf.data -a --exclude-hiperf -d ${duration} && `
109
+ : '',
110
+ `echo [SnapshotChecker]: Monitor start, Target: (app=${app}) && `,
111
+ `sleep 5 && `,
112
+ app
113
+ ? `hidumper -s 1901 -a '-p libforkall_plugin.z.so --create 100 ${app}' && `
114
+ : '',
115
+ `${checkStateCommand} && `,
116
+ `wait && `,
117
+ `echo [SnapshotChecker]: Monitor end, App Pid is: \`pidof ${app}\`, Please Check... && `,
118
+ `hiperf dump -i /data/local/tmp/perf.data -o /data/local/tmp/snapshot_perf.data.txt"`,
119
+ ]
120
+ .filter(Boolean)
121
+ .join(''),
122
+ },
123
+ ];
124
+ const collectGroup = [
125
+ {
126
+ kind: CommandKind.Windows,
127
+ description: '[forkall] 清理旧日志',
128
+ run: 'rm ./output/snapshot_log.txt || true',
129
+ },
130
+ {
131
+ kind: CommandKind.Windows,
132
+ description: '[forkall] 收集日志到本地',
133
+ run: [
134
+ 'start "" /b cmd /c "hdc shell ',
135
+ `"hilog -t kmsg ^| grep '${logKey}'" >> ./output/snapshot_log.txt`,
136
+ ].join(''),
137
+ },
138
+ {
139
+ kind: CommandKind.Windows,
140
+ description: '[forkall] 再次检查事件列表',
141
+ run: checkStateCommand,
142
+ },
143
+ {
144
+ kind: CommandKind.Windows,
145
+ description: '[forkall] 拉取 perf / hitrace / log 文件',
146
+ run: [
147
+ 'hdc file recv /data/local/tmp/snapshot_perf.data.txt ./output/ && ',
148
+ 'hdc file recv /data/local/tmp/snapshot_hitrace.txt ./output/ && ',
149
+ 'hdc file recv /data/local/tmp/snapshot_log.txt ./output/',
150
+ ].join(''),
151
+ },
152
+ {
153
+ kind: CommandKind.Windows,
154
+ description: '[forkall] 关闭 hdc 进程',
155
+ run: 'taskkill /IM hdc.exe /F || true',
156
+ },
157
+ ];
158
+ const analysisGroup = [
159
+ {
160
+ kind: CommandKind.Windows,
161
+ description: '[forkall] 分析 perf 数据',
162
+ run: [
163
+ 'cd ./output && ',
164
+ (systemSymbolFilePath
165
+ ? `python ../tools/host/checker/parser_system_stack.py snapshot_perf.data.txt snapshot_perf_data_parsed.data.txt -S "${systemSymbolFilePath}" && `
166
+ : ''),
167
+ 'python ../tools/host/checker/hiperf_txt_filter.py -to_backtrace_stack ',
168
+ '--input_file ',
169
+ systemSymbolFilePath
170
+ ? 'snapshot_perf_data_parsed.data.txt '
171
+ : 'snapshot_perf.data.txt ',
172
+ '--output_file dump_stack.txt ',
173
+ '--output_csv dump_stack.xlsx ',
174
+ '--output_json dump_stack.json',
175
+ ].join(''),
176
+ },
177
+ ];
178
+ const resultGroups = {
179
+ reboot: rebootGroup,
180
+ monitor: monitorGroup,
181
+ collect: collectGroup,
182
+ analysis: analysisGroup,
183
+ };
184
+ const order = mode === 'reboot-monitor'
185
+ ? ['reboot', 'monitor', 'collect', 'analysis']
186
+ : ['monitor', 'collect', 'analysis'];
187
+ return {
188
+ groups: resultGroups,
189
+ defaultGroupOrder: order,
190
+ };
191
+ }
192
+ //# sourceMappingURL=forkall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forkall.js","sourceRoot":"","sources":["../../commands/forkall.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { Groups } from '../src/types.js';
2
+ /**
3
+ * Mac 示例场景:仅在 macOS 下执行,接收 --app 参数,参数不为空时打印 app。
4
+ */
5
+ export declare const groups: Groups;
6
+ export declare const defaultGroupOrder: string[];
7
+ export declare const options: {
8
+ flags: string;
9
+ description: string;
10
+ }[];
11
+ interface MacExampleOptions {
12
+ app?: string;
13
+ }
14
+ export declare function applyOptions(ctx: {
15
+ groups: Groups;
16
+ defaultGroupOrder: string[];
17
+ options: MacExampleOptions;
18
+ }): {
19
+ groups: Groups;
20
+ defaultGroupOrder: string[];
21
+ };
22
+ export {};
23
+ //# sourceMappingURL=mac-example.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mac-example.d.ts","sourceRoot":"","sources":["../../commands/mac-example.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAE9C;;GAEG;AACH,eAAO,MAAM,MAAM,EAAE,MAQpB,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,MAAM,EAAoB,CAAC;AAE3D,eAAO,MAAM,OAAO;;;GAEnB,CAAC;AAEF,UAAU,iBAAiB;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,OAAO,EAAE,iBAAiB,CAAC;CAC5B,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,EAAE,CAAA;CAAE,CAuBlD"}