ic-mops 1.11.1 → 2.0.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.
Files changed (352) hide show
  1. package/.DS_Store +0 -0
  2. package/.eslintrc.json +7 -7
  3. package/CHANGELOG.md +15 -0
  4. package/api/actors.ts +41 -37
  5. package/api/downloadPackageFiles.ts +75 -61
  6. package/api/getHighestVersion.ts +5 -5
  7. package/api/index.ts +4 -4
  8. package/api/network.ts +19 -21
  9. package/api/resolveVersion.ts +14 -11
  10. package/bin/mops.js +1 -1
  11. package/bun.lock +234 -198
  12. package/bundle/bench/bench-canister.mo +2 -2
  13. package/bundle/bench/user-bench.mo +0 -4
  14. package/bundle/bin/mops.js +1 -1
  15. package/bundle/cli.js +1000 -924
  16. package/bundle/cli.tgz +0 -0
  17. package/bundle/declarations/bench/bench.did +3 -3
  18. package/bundle/declarations/bench/bench.did.d.ts +3 -3
  19. package/bundle/declarations/bench/index.d.ts +3 -3
  20. package/bundle/declarations/bench/index.js +1 -1
  21. package/bundle/declarations/main/index.d.ts +3 -3
  22. package/bundle/declarations/main/index.js +1 -1
  23. package/bundle/declarations/main/main.did +78 -121
  24. package/bundle/declarations/main/main.did.d.ts +48 -98
  25. package/bundle/declarations/main/main.did.js +53 -107
  26. package/bundle/declarations/storage/index.d.ts +3 -3
  27. package/bundle/declarations/storage/index.js +4 -4
  28. package/bundle/declarations/storage/storage.did.d.ts +3 -3
  29. package/bundle/package.json +6 -5
  30. package/bundle/templates/mops-publish.yml +3 -3
  31. package/bundle/templates/mops-test.yml +3 -3
  32. package/bundle-package-json.ts +8 -8
  33. package/cache.ts +80 -65
  34. package/check-requirements.ts +49 -45
  35. package/cli.ts +577 -376
  36. package/commands/add.ts +142 -129
  37. package/commands/available-updates.ts +55 -28
  38. package/commands/bench/bench-canister.mo +114 -108
  39. package/commands/bench/user-bench.mo +6 -6
  40. package/commands/bench-replica.ts +146 -106
  41. package/commands/bench.ts +563 -497
  42. package/commands/build.ts +177 -0
  43. package/commands/bump.ts +68 -57
  44. package/commands/check-candid.ts +24 -0
  45. package/commands/docs-coverage.ts +124 -102
  46. package/commands/docs.ts +118 -108
  47. package/commands/format.ts +171 -155
  48. package/commands/init.ts +301 -275
  49. package/commands/install/install-all.ts +75 -62
  50. package/commands/install/install-dep.ts +43 -28
  51. package/commands/install/install-deps.ts +23 -15
  52. package/commands/install/install-local-dep.ts +42 -34
  53. package/commands/install/install-mops-dep.ts +154 -123
  54. package/commands/install/sync-local-cache.ts +39 -35
  55. package/commands/maintainer.ts +109 -99
  56. package/commands/outdated.ts +31 -18
  57. package/commands/owner.ts +107 -99
  58. package/commands/publish.ts +534 -443
  59. package/commands/remove.ts +119 -89
  60. package/commands/replica.ts +391 -303
  61. package/commands/search.ts +42 -36
  62. package/commands/self.ts +63 -56
  63. package/commands/sources.ts +66 -49
  64. package/commands/sync.ts +92 -75
  65. package/commands/template.ts +145 -102
  66. package/commands/test/mmf1.ts +146 -119
  67. package/commands/test/reporters/compact-reporter.ts +87 -84
  68. package/commands/test/reporters/files-reporter.ts +56 -51
  69. package/commands/test/reporters/reporter.ts +12 -6
  70. package/commands/test/reporters/silent-reporter.ts +58 -59
  71. package/commands/test/reporters/verbose-reporter.ts +66 -54
  72. package/commands/test/test.ts +497 -460
  73. package/commands/test/utils.ts +85 -6
  74. package/commands/toolchain/index.ts +363 -322
  75. package/commands/toolchain/moc.ts +78 -50
  76. package/commands/toolchain/pocket-ic.ts +41 -34
  77. package/commands/toolchain/toolchain-utils.ts +92 -72
  78. package/commands/toolchain/wasmtime.ts +37 -34
  79. package/commands/update.ts +91 -56
  80. package/commands/user.ts +90 -81
  81. package/commands/watch/deployer.ts +188 -152
  82. package/commands/watch/error-checker.ts +90 -80
  83. package/commands/watch/formatter.ts +72 -60
  84. package/commands/watch/generator.ts +116 -96
  85. package/commands/watch/globMoFiles.ts +13 -13
  86. package/commands/watch/parseDfxJson.ts +63 -57
  87. package/commands/watch/tester.ts +83 -65
  88. package/commands/watch/warning-checker.ts +149 -136
  89. package/commands/watch/watch.ts +123 -95
  90. package/declarations/bench/bench.did.d.ts +3 -3
  91. package/declarations/bench/index.d.ts +3 -3
  92. package/declarations/bench/index.js +1 -1
  93. package/declarations/main/index.d.ts +3 -3
  94. package/declarations/main/index.js +1 -1
  95. package/declarations/main/main.did.d.ts +3 -3
  96. package/declarations/storage/index.d.ts +3 -3
  97. package/declarations/storage/index.js +4 -4
  98. package/declarations/storage/storage.did.d.ts +3 -3
  99. package/dist/api/actors.d.ts +4 -4
  100. package/dist/api/actors.js +8 -8
  101. package/dist/api/downloadPackageFiles.d.ts +2 -2
  102. package/dist/api/downloadPackageFiles.js +10 -10
  103. package/dist/api/getHighestVersion.js +1 -1
  104. package/dist/api/index.d.ts +4 -4
  105. package/dist/api/index.js +4 -4
  106. package/dist/api/network.js +9 -9
  107. package/dist/api/resolveVersion.js +3 -3
  108. package/dist/bin/mops.js +1 -1
  109. package/dist/bundle-package-json.js +8 -8
  110. package/dist/cache.js +22 -17
  111. package/dist/check-requirements.js +11 -11
  112. package/dist/cli.js +283 -186
  113. package/dist/commands/add.d.ts +1 -1
  114. package/dist/commands/add.js +41 -38
  115. package/dist/commands/available-updates.d.ts +1 -1
  116. package/dist/commands/available-updates.js +32 -14
  117. package/dist/commands/bench/bench-canister.mo +114 -108
  118. package/dist/commands/bench/user-bench.mo +6 -6
  119. package/dist/commands/bench-replica.d.ts +6 -5
  120. package/dist/commands/bench-replica.js +58 -36
  121. package/dist/commands/bench.d.ts +5 -5
  122. package/dist/commands/bench.js +134 -118
  123. package/dist/commands/build.d.ts +7 -0
  124. package/dist/commands/build.js +121 -0
  125. package/dist/commands/bump.js +27 -18
  126. package/dist/commands/check-candid.d.ts +4 -0
  127. package/dist/commands/check-candid.js +15 -0
  128. package/dist/commands/docs-coverage.d.ts +1 -1
  129. package/dist/commands/docs-coverage.js +45 -31
  130. package/dist/commands/docs.d.ts +1 -1
  131. package/dist/commands/docs.js +39 -38
  132. package/dist/commands/format.js +31 -27
  133. package/dist/commands/init.js +102 -92
  134. package/dist/commands/install/install-all.d.ts +2 -2
  135. package/dist/commands/install/install-all.js +23 -21
  136. package/dist/commands/install/install-dep.d.ts +1 -1
  137. package/dist/commands/install/install-dep.js +21 -8
  138. package/dist/commands/install/install-deps.d.ts +1 -1
  139. package/dist/commands/install/install-deps.js +1 -1
  140. package/dist/commands/install/install-local-dep.js +11 -9
  141. package/dist/commands/install/install-mops-dep.d.ts +1 -1
  142. package/dist/commands/install/install-mops-dep.js +32 -27
  143. package/dist/commands/install/sync-local-cache.js +10 -10
  144. package/dist/commands/maintainer.js +21 -21
  145. package/dist/commands/outdated.js +16 -6
  146. package/dist/commands/owner.js +21 -21
  147. package/dist/commands/publish.js +148 -128
  148. package/dist/commands/remove.d.ts +1 -1
  149. package/dist/commands/remove.js +42 -30
  150. package/dist/commands/replica.d.ts +9 -8
  151. package/dist/commands/replica.js +105 -65
  152. package/dist/commands/search.js +15 -13
  153. package/dist/commands/self.js +31 -28
  154. package/dist/commands/sources.d.ts +5 -1
  155. package/dist/commands/sources.js +23 -17
  156. package/dist/commands/sync.d.ts +1 -1
  157. package/dist/commands/sync.js +38 -25
  158. package/dist/commands/template.js +66 -56
  159. package/dist/commands/test/mmf1.d.ts +3 -3
  160. package/dist/commands/test/mmf1.js +33 -31
  161. package/dist/commands/test/reporters/compact-reporter.d.ts +3 -3
  162. package/dist/commands/test/reporters/compact-reporter.js +19 -15
  163. package/dist/commands/test/reporters/files-reporter.d.ts +3 -3
  164. package/dist/commands/test/reporters/files-reporter.js +18 -14
  165. package/dist/commands/test/reporters/reporter.d.ts +2 -2
  166. package/dist/commands/test/reporters/silent-reporter.d.ts +3 -3
  167. package/dist/commands/test/reporters/silent-reporter.js +4 -4
  168. package/dist/commands/test/reporters/verbose-reporter.d.ts +3 -3
  169. package/dist/commands/test/reporters/verbose-reporter.js +17 -13
  170. package/dist/commands/test/test.d.ts +4 -4
  171. package/dist/commands/test/test.js +151 -181
  172. package/dist/commands/test/utils.d.ts +6 -0
  173. package/dist/commands/test/utils.js +63 -2
  174. package/dist/commands/toolchain/index.d.ts +1 -1
  175. package/dist/commands/toolchain/index.js +81 -69
  176. package/dist/commands/toolchain/moc.d.ts +1 -1
  177. package/dist/commands/toolchain/moc.js +48 -24
  178. package/dist/commands/toolchain/pocket-ic.js +12 -12
  179. package/dist/commands/toolchain/toolchain-utils.d.ts +2 -0
  180. package/dist/commands/toolchain/toolchain-utils.js +32 -23
  181. package/dist/commands/toolchain/wasmtime.js +11 -11
  182. package/dist/commands/update.d.ts +1 -1
  183. package/dist/commands/update.js +30 -12
  184. package/dist/commands/user.js +31 -28
  185. package/dist/commands/watch/deployer.d.ts +4 -4
  186. package/dist/commands/watch/deployer.js +45 -36
  187. package/dist/commands/watch/error-checker.d.ts +2 -2
  188. package/dist/commands/watch/error-checker.js +27 -27
  189. package/dist/commands/watch/formatter.d.ts +4 -4
  190. package/dist/commands/watch/formatter.js +17 -17
  191. package/dist/commands/watch/generator.d.ts +3 -3
  192. package/dist/commands/watch/generator.js +28 -23
  193. package/dist/commands/watch/globMoFiles.js +8 -8
  194. package/dist/commands/watch/parseDfxJson.d.ts +2 -2
  195. package/dist/commands/watch/parseDfxJson.js +9 -9
  196. package/dist/commands/watch/tester.d.ts +4 -4
  197. package/dist/commands/watch/tester.js +23 -21
  198. package/dist/commands/watch/warning-checker.d.ts +3 -3
  199. package/dist/commands/watch/warning-checker.js +36 -36
  200. package/dist/commands/watch/watch.js +45 -32
  201. package/dist/declarations/bench/bench.did.d.ts +3 -3
  202. package/dist/declarations/bench/index.d.ts +3 -3
  203. package/dist/declarations/bench/index.js +1 -1
  204. package/dist/declarations/main/index.d.ts +3 -3
  205. package/dist/declarations/main/index.js +1 -1
  206. package/dist/declarations/main/main.did.d.ts +3 -3
  207. package/dist/declarations/storage/index.d.ts +3 -3
  208. package/dist/declarations/storage/index.js +4 -4
  209. package/dist/declarations/storage/storage.did.d.ts +3 -3
  210. package/dist/environments/nodejs/cli.d.ts +1 -0
  211. package/dist/environments/nodejs/cli.js +4 -0
  212. package/dist/environments/web/cli.d.ts +1 -0
  213. package/dist/environments/web/cli.js +4 -0
  214. package/dist/error.d.ts +1 -0
  215. package/dist/error.js +5 -0
  216. package/dist/fix-dist.js +5 -5
  217. package/dist/helpers/find-changelog-entry.js +8 -5
  218. package/dist/helpers/get-dep-name.d.ts +1 -0
  219. package/dist/helpers/get-dep-name.js +4 -1
  220. package/dist/helpers/get-dfx-version.js +4 -4
  221. package/dist/helpers/get-moc-path.js +8 -7
  222. package/dist/helpers/get-moc-version.js +10 -7
  223. package/dist/helpers/get-package-id.js +2 -2
  224. package/dist/helpers/is-candid-compatible.d.ts +1 -0
  225. package/dist/helpers/is-candid-compatible.js +20 -0
  226. package/dist/integrity.d.ts +1 -1
  227. package/dist/integrity.js +47 -38
  228. package/dist/jest.config.d.ts +11 -0
  229. package/dist/jest.config.js +14 -0
  230. package/dist/mops.d.ts +6 -6
  231. package/dist/mops.js +87 -80
  232. package/dist/notify-installs.js +4 -4
  233. package/dist/package.json +11 -10
  234. package/dist/pem.d.ts +3 -3
  235. package/dist/pem.js +20 -12
  236. package/dist/release-cli.js +20 -20
  237. package/dist/resolve-packages.d.ts +1 -1
  238. package/dist/resolve-packages.js +52 -36
  239. package/dist/templates/mops-publish.yml +3 -3
  240. package/dist/templates/mops-test.yml +3 -3
  241. package/dist/templates/src/lib.mo +13 -13
  242. package/dist/templates/test/lib.test.mo +2 -2
  243. package/dist/templates.js +1 -1
  244. package/dist/tests/cli.test.d.ts +1 -0
  245. package/dist/tests/cli.test.js +63 -0
  246. package/dist/types.d.ts +14 -4
  247. package/dist/vessel.d.ts +2 -2
  248. package/dist/vessel.js +41 -34
  249. package/dist/wasm/pkg/bundler/package.json +20 -0
  250. package/dist/wasm/pkg/bundler/wasm.d.ts +3 -0
  251. package/dist/wasm/pkg/bundler/wasm.js +5 -0
  252. package/dist/wasm/pkg/bundler/wasm_bg.js +93 -0
  253. package/dist/wasm/pkg/bundler/wasm_bg.wasm +0 -0
  254. package/dist/wasm/pkg/bundler/wasm_bg.wasm.d.ts +8 -0
  255. package/dist/wasm/pkg/nodejs/package.json +14 -0
  256. package/dist/wasm/pkg/nodejs/wasm.d.ts +3 -0
  257. package/dist/wasm/pkg/nodejs/wasm.js +98 -0
  258. package/dist/wasm/pkg/nodejs/wasm_bg.wasm +0 -0
  259. package/dist/wasm/pkg/nodejs/wasm_bg.wasm.d.ts +8 -0
  260. package/dist/wasm/pkg/web/package.json +18 -0
  261. package/dist/wasm/pkg/web/wasm.d.ts +35 -0
  262. package/dist/wasm/pkg/web/wasm.js +191 -0
  263. package/dist/wasm/pkg/web/wasm_bg.wasm +0 -0
  264. package/dist/wasm/pkg/web/wasm_bg.wasm.d.ts +8 -0
  265. package/dist/wasm.d.ts +5 -0
  266. package/dist/wasm.js +10 -0
  267. package/environments/nodejs/cli.ts +6 -0
  268. package/environments/web/cli.ts +6 -0
  269. package/error.ts +6 -0
  270. package/fix-dist.ts +5 -5
  271. package/global.d.ts +3 -3
  272. package/helpers/find-changelog-entry.ts +26 -23
  273. package/helpers/get-dep-name.ts +7 -3
  274. package/helpers/get-dfx-version.ts +8 -9
  275. package/helpers/get-moc-path.ts +25 -26
  276. package/helpers/get-moc-version.ts +21 -19
  277. package/helpers/get-package-id.ts +4 -4
  278. package/helpers/is-candid-compatible.ts +22 -0
  279. package/integrity.ts +270 -236
  280. package/jest.config.js +14 -0
  281. package/mops.ts +238 -215
  282. package/notify-installs.ts +16 -17
  283. package/package.json +21 -15
  284. package/parallel.ts +28 -24
  285. package/pem.ts +55 -47
  286. package/release-cli.ts +73 -39
  287. package/resolve-packages.ts +231 -189
  288. package/templates/mops-publish.yml +3 -3
  289. package/templates/mops-test.yml +3 -3
  290. package/templates/src/lib.mo +13 -13
  291. package/templates/test/lib.test.mo +2 -2
  292. package/templates.ts +4 -4
  293. package/tests/__snapshots__/cli.test.ts.snap +202 -0
  294. package/tests/build/error/candid/bar.did +3 -0
  295. package/tests/build/error/dfx.json +12 -0
  296. package/tests/build/error/mops.toml +9 -0
  297. package/tests/build/error/src/Bar.mo +5 -0
  298. package/tests/build/error/src/Foo.mo +5 -0
  299. package/tests/build/success/.dfx/local/canister_ids.json +17 -0
  300. package/tests/build/success/.dfx/local/canisters/bar/bar.did +3 -0
  301. package/tests/build/success/.dfx/local/canisters/bar/bar.most +4 -0
  302. package/tests/build/success/.dfx/local/canisters/bar/bar.wasm +0 -0
  303. package/tests/build/success/.dfx/local/canisters/bar/constructor.did +3 -0
  304. package/tests/build/success/.dfx/local/canisters/bar/index.js +42 -0
  305. package/tests/build/success/.dfx/local/canisters/bar/init_args.txt +1 -0
  306. package/tests/build/success/.dfx/local/canisters/bar/service.did +3 -0
  307. package/tests/build/success/.dfx/local/canisters/bar/service.did.d.ts +7 -0
  308. package/tests/build/success/.dfx/local/canisters/bar/service.did.js +4 -0
  309. package/tests/build/success/.dfx/local/canisters/foo/constructor.did +3 -0
  310. package/tests/build/success/.dfx/local/canisters/foo/foo.did +3 -0
  311. package/tests/build/success/.dfx/local/canisters/foo/foo.most +4 -0
  312. package/tests/build/success/.dfx/local/canisters/foo/foo.wasm +0 -0
  313. package/tests/build/success/.dfx/local/canisters/foo/index.js +42 -0
  314. package/tests/build/success/.dfx/local/canisters/foo/init_args.txt +1 -0
  315. package/tests/build/success/.dfx/local/canisters/foo/service.did +3 -0
  316. package/tests/build/success/.dfx/local/canisters/foo/service.did.d.ts +7 -0
  317. package/tests/build/success/.dfx/local/canisters/foo/service.did.js +4 -0
  318. package/tests/build/success/.dfx/local/lsp/ucwa4-rx777-77774-qaada-cai.did +3 -0
  319. package/tests/build/success/.dfx/local/lsp/ulvla-h7777-77774-qaacq-cai.did +3 -0
  320. package/tests/build/success/.dfx/local/network-id +4 -0
  321. package/tests/build/success/candid/bar.did +3 -0
  322. package/tests/build/success/dfx.json +12 -0
  323. package/tests/build/success/mops.toml +9 -0
  324. package/tests/build/success/src/Bar.mo +5 -0
  325. package/tests/build/success/src/Foo.mo +5 -0
  326. package/tests/check-candid/a.did +3 -0
  327. package/tests/check-candid/b.did +5 -0
  328. package/tests/check-candid/c.did +3 -0
  329. package/tests/cli.test.ts +82 -0
  330. package/tsconfig.json +26 -19
  331. package/types.ts +41 -31
  332. package/vessel.ts +219 -187
  333. package/wasm/Cargo.lock +1475 -0
  334. package/wasm/Cargo.toml +28 -0
  335. package/wasm/pkg/bundler/package.json +20 -0
  336. package/wasm/pkg/bundler/wasm.d.ts +3 -0
  337. package/wasm/pkg/bundler/wasm.js +5 -0
  338. package/wasm/pkg/bundler/wasm_bg.js +93 -0
  339. package/wasm/pkg/bundler/wasm_bg.wasm +0 -0
  340. package/wasm/pkg/bundler/wasm_bg.wasm.d.ts +8 -0
  341. package/wasm/pkg/nodejs/package.json +14 -0
  342. package/wasm/pkg/nodejs/wasm.d.ts +3 -0
  343. package/wasm/pkg/nodejs/wasm.js +98 -0
  344. package/wasm/pkg/nodejs/wasm_bg.wasm +0 -0
  345. package/wasm/pkg/nodejs/wasm_bg.wasm.d.ts +8 -0
  346. package/wasm/pkg/web/package.json +18 -0
  347. package/wasm/pkg/web/wasm.d.ts +35 -0
  348. package/wasm/pkg/web/wasm.js +191 -0
  349. package/wasm/pkg/web/wasm_bg.wasm +0 -0
  350. package/wasm/pkg/web/wasm_bg.wasm.d.ts +8 -0
  351. package/wasm/src/lib.rs +17 -0
  352. package/wasm.ts +16 -0
@@ -1,5 +1,5 @@
1
- import chalk from 'chalk';
2
- import { absToRel } from '../utils.js';
1
+ import chalk from "chalk";
2
+ import { absToRel } from "../utils.js";
3
3
  export class VerboseReporter {
4
4
  passed = 0;
5
5
  failed = 0;
@@ -7,11 +7,11 @@ export class VerboseReporter {
7
7
  #startTime = Date.now();
8
8
  #curFileIndex = 0;
9
9
  addFiles(files) {
10
- console.log('Test files:');
10
+ console.log("Test files:");
11
11
  for (let file of files) {
12
12
  console.log(chalk.gray(`• ${absToRel(file)}`));
13
13
  }
14
- console.log('='.repeat(50));
14
+ console.log("=".repeat(50));
15
15
  }
16
16
  addRun(file, mmf, state, mode, progressive = false) {
17
17
  if (progressive) {
@@ -31,21 +31,25 @@ export class VerboseReporter {
31
31
  });
32
32
  }
33
33
  done() {
34
- console.log('='.repeat(50));
34
+ console.log("=".repeat(50));
35
35
  if (this.failed) {
36
- console.log(chalk.redBright('Tests failed'));
36
+ console.log(chalk.redBright("Tests failed"));
37
37
  }
38
38
  else {
39
- console.log(chalk.greenBright('Tests passed'));
39
+ console.log(chalk.greenBright("Tests passed"));
40
40
  }
41
- console.log(`Done in ${chalk.gray(((Date.now() - this.#startTime) / 1000).toFixed(2) + 's')}`
42
- + `, passed ${chalk.greenBright(this.passed)}`
43
- + (this.skipped ? `, skipped ${chalk[this.skipped ? 'yellowBright' : 'gray'](this.skipped)}` : '')
44
- + (this.failed ? `, failed ${chalk[this.failed ? 'redBright' : 'gray'](this.failed)}` : ''));
41
+ console.log(`Done in ${chalk.gray(((Date.now() - this.#startTime) / 1000).toFixed(2) + "s")}` +
42
+ `, passed ${chalk.greenBright(this.passed)}` +
43
+ (this.skipped
44
+ ? `, skipped ${chalk[this.skipped ? "yellowBright" : "gray"](this.skipped)}`
45
+ : "") +
46
+ (this.failed
47
+ ? `, failed ${chalk[this.failed ? "redBright" : "gray"](this.failed)}`
48
+ : ""));
45
49
  return this.failed === 0;
46
50
  }
47
51
  _printStart(file, mode) {
48
- this.#curFileIndex++ && console.log('-'.repeat(50));
49
- console.log(`Running ${chalk.gray(absToRel(file))} ${mode === 'interpreter' ? '' : chalk.gray(`(${mode})`)}`);
52
+ this.#curFileIndex++ && console.log("-".repeat(50));
53
+ console.log(`Running ${chalk.gray(absToRel(file))} ${mode === "interpreter" ? "" : chalk.gray(`(${mode})`)}`);
50
54
  }
51
55
  }
@@ -1,7 +1,7 @@
1
- import { Reporter } from './reporters/reporter.js';
2
- import { TestMode } from '../../types.js';
3
- type ReporterName = 'verbose' | 'files' | 'compact' | 'silent';
4
- type ReplicaName = 'dfx' | 'pocket-ic' | 'dfx-pocket-ic';
1
+ import { Reporter } from "./reporters/reporter.js";
2
+ import { TestMode } from "../../types.js";
3
+ type ReporterName = "verbose" | "files" | "compact" | "silent";
4
+ type ReplicaName = "dfx" | "pocket-ic" | "dfx-pocket-ic";
5
5
  type TestOptions = {
6
6
  watch: boolean;
7
7
  reporter: ReporterName;
@@ -1,31 +1,31 @@
1
- import process from 'node:process';
2
- import { spawn } from 'node:child_process';
3
- import path from 'node:path';
4
- import fs from 'node:fs';
5
- import os from 'node:os';
6
- import chalk from 'chalk';
7
- import { globSync } from 'glob';
8
- import chokidar from 'chokidar';
9
- import debounce from 'debounce';
10
- import { SemVer } from 'semver';
11
- import { sources } from '../sources.js';
12
- import { getRootDir, readConfig } from '../../mops.js';
13
- import { parallel } from '../../parallel.js';
14
- import { MMF1 } from './mmf1.js';
15
- import { absToRel } from './utils.js';
16
- import { VerboseReporter } from './reporters/verbose-reporter.js';
17
- import { FilesReporter } from './reporters/files-reporter.js';
18
- import { CompactReporter } from './reporters/compact-reporter.js';
19
- import { SilentReporter } from './reporters/silent-reporter.js';
20
- import { toolchain } from '../toolchain/index.js';
21
- import { Replica } from '../replica.js';
22
- import { PassThrough } from 'node:stream';
23
- import { getDfxVersion } from '../../helpers/get-dfx-version.js';
1
+ import process from "node:process";
2
+ import { spawn } from "node:child_process";
3
+ import path from "node:path";
4
+ import fs from "node:fs";
5
+ import os from "node:os";
6
+ import { PassThrough } from "node:stream";
7
+ import chalk from "chalk";
8
+ import { globSync } from "glob";
9
+ import chokidar from "chokidar";
10
+ import debounce from "debounce";
11
+ import { SemVer } from "semver";
12
+ import { sources } from "../sources.js";
13
+ import { getRootDir, readConfig } from "../../mops.js";
14
+ import { parallel } from "../../parallel.js";
15
+ import { MMF1 } from "./mmf1.js";
16
+ import { absToRel, pipeMMF, pipeStderrToMMF, pipeStdoutToMMF, } from "./utils.js";
17
+ import { VerboseReporter } from "./reporters/verbose-reporter.js";
18
+ import { FilesReporter } from "./reporters/files-reporter.js";
19
+ import { CompactReporter } from "./reporters/compact-reporter.js";
20
+ import { SilentReporter } from "./reporters/silent-reporter.js";
21
+ import { toolchain } from "../toolchain/index.js";
22
+ import { Replica } from "../replica.js";
23
+ import { getDfxVersion } from "../../helpers/get-dfx-version.js";
24
24
  let ignore = [
25
- '**/node_modules/**',
26
- '**/.mops/**',
27
- '**/.vessel/**',
28
- '**/.git/**',
25
+ "**/node_modules/**",
26
+ "**/.mops/**",
27
+ "**/.vessel/**",
28
+ "**/.git/**",
29
29
  ];
30
30
  let globConfig = {
31
31
  nocase: true,
@@ -41,18 +41,19 @@ async function startReplicaOnce(replica, type) {
41
41
  }
42
42
  return replicaStartPromise;
43
43
  }
44
- export async function test(filter = '', options = {}) {
44
+ export async function test(filter = "", options = {}) {
45
45
  let config = readConfig();
46
46
  let rootDir = getRootDir();
47
- let replicaType = options.replica ?? (config.toolchain?.['pocket-ic'] ? 'pocket-ic' : 'dfx');
48
- if (replicaType === 'pocket-ic' && !config.toolchain?.['pocket-ic']) {
47
+ let replicaType = options.replica ??
48
+ (config.toolchain?.["pocket-ic"] ? "pocket-ic" : "dfx");
49
+ if (replicaType === "pocket-ic" && !config.toolchain?.["pocket-ic"]) {
49
50
  let dfxVersion = getDfxVersion();
50
- if (!dfxVersion || new SemVer(dfxVersion).compare('0.24.1') < 0) {
51
- console.log(chalk.red('Please update dfx to the version >=0.24.1 or specify pocket-ic version in mops.toml'));
51
+ if (!dfxVersion || new SemVer(dfxVersion).compare("0.24.1") < 0) {
52
+ console.log(chalk.red("Please update dfx to the version >=0.24.1 or specify pocket-ic version in mops.toml"));
52
53
  process.exit(1);
53
54
  }
54
55
  else {
55
- replicaType = 'dfx-pocket-ic';
56
+ replicaType = "dfx-pocket-ic";
56
57
  }
57
58
  }
58
59
  replica.type = replicaType;
@@ -60,14 +61,14 @@ export async function test(filter = '', options = {}) {
60
61
  if (options.watch) {
61
62
  replica.ttl = 60 * 15; // 15 minutes
62
63
  let sigint = false;
63
- process.on('SIGINT', () => {
64
+ process.on("SIGINT", () => {
64
65
  if (sigint) {
65
- console.log('Force exit');
66
+ console.log("Force exit");
66
67
  process.exit(0);
67
68
  }
68
69
  sigint = true;
69
70
  if (replicaStartPromise) {
70
- console.log('Stopping replica...');
71
+ console.log("Stopping replica...");
71
72
  replica.stop(true).then(() => {
72
73
  process.exit(0);
73
74
  });
@@ -84,22 +85,19 @@ export async function test(filter = '', options = {}) {
84
85
  controller.abort();
85
86
  await curRun;
86
87
  console.clear();
87
- process.stdout.write('\x1Bc');
88
+ process.stdout.write("\x1Bc");
88
89
  controller = new AbortController();
89
90
  curRun = runAll(options.reporter, filter, options.mode, replicaType, true, controller.signal);
90
91
  await curRun;
91
- console.log('-'.repeat(50));
92
- console.log('Waiting for file changes...');
93
- console.log(chalk.gray((`Press ${chalk.gray('Ctrl+C')} to exit.`)));
92
+ console.log("-".repeat(50));
93
+ console.log("Waiting for file changes...");
94
+ console.log(chalk.gray(`Press ${chalk.gray("Ctrl+C")} to exit.`));
94
95
  }, 200);
95
- let watcher = chokidar.watch([
96
- path.join(rootDir, '**/*.mo'),
97
- path.join(rootDir, 'mops.toml'),
98
- ], {
96
+ let watcher = chokidar.watch([path.join(rootDir, "**/*.mo"), path.join(rootDir, "mops.toml")], {
99
97
  ignored: ignore,
100
98
  ignoreInitial: true,
101
99
  });
102
- watcher.on('all', () => {
100
+ watcher.on("all", () => {
103
101
  run();
104
102
  });
105
103
  run();
@@ -111,21 +109,21 @@ export async function test(filter = '', options = {}) {
111
109
  }
112
110
  }
113
111
  }
114
- let mocPath = '';
115
- let wasmtimePath = '';
116
- async function runAll(reporterName, filter = '', mode = 'interpreter', replicaType, watch = false, signal) {
112
+ let mocPath = "";
113
+ let wasmtimePath = "";
114
+ async function runAll(reporterName, filter = "", mode = "interpreter", replicaType, watch = false, signal) {
117
115
  let done = await testWithReporter(reporterName, filter, mode, replicaType, watch, signal);
118
116
  return done;
119
117
  }
120
- export async function testWithReporter(reporterName, filter = '', defaultMode = 'interpreter', replicaType, watch = false, signal) {
118
+ export async function testWithReporter(reporterName, filter = "", defaultMode = "interpreter", replicaType, watch = false, signal) {
121
119
  let rootDir = getRootDir();
122
120
  let files = [];
123
- let libFiles = globSync('**/test?(s)/lib.mo', globConfig);
121
+ let libFiles = globSync("**/test?(s)/lib.mo", globConfig);
124
122
  if (libFiles[0]) {
125
123
  files = [libFiles[0]];
126
124
  }
127
125
  else {
128
- let globStr = '**/test?(s)/**/*.test.mo';
126
+ let globStr = "**/test?(s)/**/*.test.mo";
129
127
  if (filter) {
130
128
  globStr = `**/test?(s)/**/*${filter}*.mo`;
131
129
  }
@@ -136,26 +134,26 @@ export async function testWithReporter(reporterName, filter = '', defaultMode =
136
134
  console.log(`No test files found for filter '${filter}'`);
137
135
  return false;
138
136
  }
139
- console.log('No test files found');
140
- console.log('Put your tests in \'test\' directory in *.test.mo files');
137
+ console.log("No test files found");
138
+ console.log("Put your tests in 'test' directory in *.test.mo files");
141
139
  return false;
142
140
  }
143
141
  let reporter;
144
- if (!reporterName || typeof reporterName === 'string') {
142
+ if (!reporterName || typeof reporterName === "string") {
145
143
  if (!reporterName) {
146
- reporterName = files.length > 1 ? 'files' : 'verbose';
144
+ reporterName = files.length > 1 ? "files" : "verbose";
147
145
  }
148
- if (reporterName == 'compact') {
149
- reporter = new CompactReporter;
146
+ if (reporterName == "compact") {
147
+ reporter = new CompactReporter();
150
148
  }
151
- else if (reporterName == 'files') {
152
- reporter = new FilesReporter;
149
+ else if (reporterName == "files") {
150
+ reporter = new FilesReporter();
153
151
  }
154
- else if (reporterName == 'silent') {
155
- reporter = new SilentReporter;
152
+ else if (reporterName == "silent") {
153
+ reporter = new SilentReporter();
156
154
  }
157
155
  else {
158
- reporter = new VerboseReporter;
156
+ reporter = new VerboseReporter();
159
157
  }
160
158
  }
161
159
  else {
@@ -165,45 +163,59 @@ export async function testWithReporter(reporterName, filter = '', defaultMode =
165
163
  let config = readConfig();
166
164
  let sourcesArr = await sources();
167
165
  if (!mocPath) {
168
- mocPath = await toolchain.bin('moc', { fallback: true });
166
+ mocPath = await toolchain.bin("moc", { fallback: true });
169
167
  }
170
- let testTempDir = path.join(getRootDir(), '.mops/.test/');
168
+ let testTempDir = path.join(getRootDir(), ".mops/.test/");
171
169
  replica.dir = testTempDir;
172
170
  fs.rmSync(testTempDir, { recursive: true, force: true });
173
171
  fs.mkdirSync(testTempDir, { recursive: true });
174
- await parallel(os.cpus().length, files, async (file) => {
175
- if (signal?.aborted) {
176
- return;
177
- }
178
- let mmf = new MMF1('store', absToRel(file));
179
- // mode overrides
180
- let lines = fs.readFileSync(file, 'utf8').split('\n');
172
+ let filesWithMode = files.map((file) => {
173
+ let lines = fs.readFileSync(file, "utf8").split("\n");
181
174
  let mode = defaultMode;
182
- if (lines.includes('// @testmode wasi')) {
183
- mode = 'wasi';
175
+ if (lines.includes("// @testmode wasi")) {
176
+ mode = "wasi";
184
177
  }
185
- else if (lines.includes('// @testmode replica') || lines.find(line => line.match(/^(persistent )?actor( class)?/))) {
186
- mode = 'replica';
178
+ else if (lines.includes("// @testmode replica") ||
179
+ lines.find((line) => line.match(/^(persistent )?actor( class)?/))) {
180
+ mode = "replica";
187
181
  }
188
- if (mode === 'wasi' && !wasmtimePath) {
189
- // ensure wasmtime is installed or specified in config
190
- if (config.toolchain?.wasmtime) {
191
- wasmtimePath = await toolchain.bin('wasmtime');
192
- }
193
- // fallback wasmtime to global binary if not specified in config (legacy)
194
- else {
195
- wasmtimePath = 'wasmtime';
196
- console.log(chalk.yellow('Warning:'), 'Wasmtime is not specified in config. Using global binary "wasmtime". This will be removed in the future.');
197
- console.log(`Run ${chalk.green('mops toolchain use wasmtime')} or add ${chalk.green('wasmtime = "<version>"')} in mops.toml to avoid breaking changes with future versions of mops.`);
198
- }
182
+ return { file, mode };
183
+ });
184
+ let hasWasiTests = filesWithMode.some(({ mode }) => mode === "wasi");
185
+ let hasReplicaTests = filesWithMode.some(({ mode }) => mode === "replica");
186
+ // prepare wasmtime path
187
+ if (hasWasiTests && !wasmtimePath) {
188
+ // ensure wasmtime is installed or specified in config
189
+ if (config.toolchain?.wasmtime) {
190
+ wasmtimePath = await toolchain.bin("wasmtime");
191
+ }
192
+ // fallback wasmtime to global binary if not specified in config (legacy)
193
+ else {
194
+ wasmtimePath = "wasmtime";
195
+ console.log(chalk.yellow("Warning:"), 'Wasmtime is not specified in config. Using global binary "wasmtime". This will be removed in the future.');
196
+ console.log(`Run ${chalk.green("mops toolchain use wasmtime")} or add ${chalk.green('wasmtime = "<version>"')} in mops.toml to avoid breaking changes with future versions of mops.`);
197
+ }
198
+ }
199
+ let runTestFile = async ({ file, mode, }) => {
200
+ if (signal?.aborted) {
201
+ return;
199
202
  }
203
+ // print logs immediately for replica tests because we run them one-by-one
204
+ let mmf = new MMF1(mode === "replica" ? "print" : "store", absToRel(file));
200
205
  let promise = new Promise((resolve) => {
201
- let mocArgs = ['--hide-warnings', '--error-detail=2', ...sourcesArr.join(' ').split(' '), file].filter(x => x);
206
+ let mocArgs = [
207
+ "--hide-warnings",
208
+ "--error-detail=2",
209
+ ...sourcesArr.join(" ").split(" "),
210
+ file,
211
+ ].filter((x) => x);
202
212
  // interpret
203
- if (mode === 'interpreter') {
204
- let proc = spawn(mocPath, ['-r', '-ref-system-api', ...mocArgs], { signal });
205
- proc.addListener('error', (error) => {
206
- if (error?.code === 'ABORT_ERR') {
213
+ if (mode === "interpreter") {
214
+ let proc = spawn(mocPath, ["-r", "-ref-system-api", ...mocArgs], {
215
+ signal,
216
+ });
217
+ proc.addListener("error", (error) => {
218
+ if (error?.code === "ABORT_ERR") {
207
219
  return;
208
220
  }
209
221
  throw error;
@@ -211,63 +223,76 @@ export async function testWithReporter(reporterName, filter = '', defaultMode =
211
223
  pipeMMF(proc, mmf).then(resolve);
212
224
  }
213
225
  // build and run wasm
214
- else if (mode === 'wasi') {
226
+ else if (mode === "wasi") {
215
227
  let wasmFile = `${path.join(testTempDir, path.parse(file).name)}.wasm`;
216
228
  // build
217
- let buildProc = spawn(mocPath, [`-o=${wasmFile}`, '-wasi-system-api', ...mocArgs], { signal });
218
- buildProc.addListener('error', (error) => {
219
- if (error?.code === 'ABORT_ERR') {
229
+ let buildProc = spawn(mocPath, [`-o=${wasmFile}`, "-wasi-system-api", ...mocArgs], { signal });
230
+ buildProc.addListener("error", (error) => {
231
+ if (error?.code === "ABORT_ERR") {
220
232
  return;
221
233
  }
222
234
  throw error;
223
235
  });
224
- pipeMMF(buildProc, mmf).then(async () => {
236
+ pipeMMF(buildProc, mmf)
237
+ .then(async () => {
225
238
  if (mmf.failed > 0) {
226
239
  return;
227
240
  }
228
241
  // run
229
242
  let wasmtimeArgs = [];
230
- if (config.toolchain?.wasmtime && config.toolchain?.wasmtime >= '14.0.0') {
243
+ if (config.toolchain?.wasmtime &&
244
+ config.toolchain?.wasmtime >= "14.0.0") {
231
245
  wasmtimeArgs = [
232
- '-S', 'preview2=n',
233
- '-C', 'cache=n',
234
- '-W', 'bulk-memory',
235
- '-W', 'multi-memory',
236
- '-W', 'memory64',
237
- '-W', 'max-wasm-stack=4000000',
238
- '-W', 'nan-canonicalization=y',
246
+ "-S",
247
+ "preview2=n",
248
+ "-C",
249
+ "cache=n",
250
+ "-W",
251
+ "bulk-memory",
252
+ "-W",
253
+ "multi-memory",
254
+ "-W",
255
+ "memory64",
256
+ "-W",
257
+ "max-wasm-stack=4000000",
258
+ "-W",
259
+ "nan-canonicalization=y",
239
260
  wasmFile,
240
261
  ];
241
262
  }
242
263
  else {
243
- console.error(chalk.red('Minimum wasmtime version is 14.0.0. Please update wasmtime to the latest version'));
264
+ console.error(chalk.red("Minimum wasmtime version is 14.0.0. Please update wasmtime to the latest version"));
244
265
  process.exit(1);
245
266
  }
246
267
  let proc = spawn(wasmtimePath, wasmtimeArgs, { signal });
247
- proc.addListener('error', (error) => {
248
- if (error?.code === 'ABORT_ERR') {
268
+ proc.addListener("error", (error) => {
269
+ if (error?.code === "ABORT_ERR") {
249
270
  return;
250
271
  }
251
272
  throw error;
252
273
  });
253
274
  await pipeMMF(proc, mmf);
254
- }).finally(() => {
275
+ })
276
+ .finally(() => {
255
277
  fs.rmSync(wasmFile, { force: true });
256
- }).then(resolve);
278
+ })
279
+ .then(resolve);
257
280
  }
258
281
  // build and execute in replica
259
- else if (mode === 'replica') {
260
- // mmf.strategy = 'print'; // because we run replica tests one-by-one
282
+ else if (mode === "replica") {
261
283
  let wasmFile = `${path.join(testTempDir, path.parse(file).name)}.wasm`;
262
284
  // build
263
- let buildProc = spawn(mocPath, [`-o=${wasmFile}`, ...mocArgs], { signal });
264
- buildProc.addListener('error', (error) => {
265
- if (error?.code === 'ABORT_ERR') {
285
+ let buildProc = spawn(mocPath, [`-o=${wasmFile}`, ...mocArgs], {
286
+ signal,
287
+ });
288
+ buildProc.addListener("error", (error) => {
289
+ if (error?.code === "ABORT_ERR") {
266
290
  return;
267
291
  }
268
292
  throw error;
269
293
  });
270
- pipeMMF(buildProc, mmf).then(async () => {
294
+ pipeMMF(buildProc, mmf)
295
+ .then(async () => {
271
296
  if (mmf.failed > 0) {
272
297
  return;
273
298
  }
@@ -277,14 +302,14 @@ export async function testWithReporter(reporterName, filter = '', defaultMode =
277
302
  }
278
303
  let canisterName = path.parse(file).name;
279
304
  let idlFactory = ({ IDL }) => {
280
- return IDL.Service({ 'runTests': IDL.Func([], [], []) });
305
+ return IDL.Service({ runTests: IDL.Func([], [], []) });
281
306
  };
282
307
  let canister = await replica.deploy(canisterName, wasmFile, idlFactory, undefined, signal);
283
308
  if (signal?.aborted || !canister) {
284
309
  return;
285
310
  }
286
311
  pipeStdoutToMMF(canister.stream, mmf);
287
- let actor = await replica.getActor(canisterName);
312
+ let actor = (await replica.getActor(canisterName));
288
313
  try {
289
314
  if (globalThis.mopsReplicaTestRunning) {
290
315
  await new Promise((resolve) => {
@@ -293,7 +318,7 @@ export async function testWithReporter(reporterName, filter = '', defaultMode =
293
318
  resolve();
294
319
  clearInterval(timerId);
295
320
  }
296
- }, Math.random() * 1000 | 0);
321
+ }, (Math.random() * 1000) | 0);
297
322
  });
298
323
  }
299
324
  if (signal?.aborted) {
@@ -309,10 +334,12 @@ export async function testWithReporter(reporterName, filter = '', defaultMode =
309
334
  pipeStderrToMMF(stderrStream, mmf, path.dirname(file));
310
335
  stderrStream.write(e.message);
311
336
  }
312
- }).finally(async () => {
337
+ })
338
+ .finally(async () => {
313
339
  globalThis.mopsReplicaTestRunning = false;
314
340
  fs.rmSync(wasmFile, { force: true });
315
- }).then(resolve);
341
+ })
342
+ .then(resolve);
316
343
  }
317
344
  });
318
345
  if (signal?.aborted) {
@@ -320,8 +347,10 @@ export async function testWithReporter(reporterName, filter = '', defaultMode =
320
347
  }
321
348
  reporter.addRun(file, mmf, promise, mode);
322
349
  await promise;
323
- });
324
- if (replicaStartPromise && !watch) {
350
+ };
351
+ await parallel(os.cpus().length, filesWithMode.filter(({ mode }) => mode !== "replica"), runTestFile);
352
+ await parallel(1, filesWithMode.filter(({ mode }) => mode === "replica"), runTestFile);
353
+ if (hasReplicaTests && !watch) {
325
354
  await replica.stop();
326
355
  fs.rmSync(testTempDir, { recursive: true, force: true });
327
356
  }
@@ -330,62 +359,3 @@ export async function testWithReporter(reporterName, filter = '', defaultMode =
330
359
  }
331
360
  return reporter.done();
332
361
  }
333
- function pipeStdoutToMMF(stdout, mmf) {
334
- stdout.on('data', (data) => {
335
- for (let line of data.toString().split('\n')) {
336
- line = line.trim();
337
- if (line) {
338
- mmf.parseLine(line);
339
- }
340
- }
341
- });
342
- }
343
- function pipeStderrToMMF(stderr, mmf, dir = '') {
344
- stderr.on('data', (data) => {
345
- let text = data.toString().trim();
346
- let failedLine = '';
347
- text = text.replace(/([\w+._/-]+):(\d+).(\d+)(-\d+.\d+)/g, (_m0, m1, m2, m3) => {
348
- // change absolute file path to relative
349
- // change :line:col-line:col to :line:col to work in vscode
350
- let res = `${absToRel(m1)}:${m2}:${m3}`;
351
- let file = path.join(dir, m1);
352
- if (!fs.existsSync(file)) {
353
- return res;
354
- }
355
- // show failed line
356
- let content = fs.readFileSync(file);
357
- let lines = content.toString().split('\n') || [];
358
- failedLine += chalk.dim('\n ...');
359
- let lineBefore = lines[+m2 - 2];
360
- if (lineBefore) {
361
- failedLine += chalk.dim(`\n ${+m2 - 1}\t| ${lineBefore.replaceAll('\t', ' ')}`);
362
- }
363
- failedLine += `\n${chalk.redBright `->`} ${m2}\t| ${lines[+m2 - 1]?.replaceAll('\t', ' ')}`;
364
- if (lines.length > +m2) {
365
- failedLine += chalk.dim(`\n ${+m2 + 1}\t| ${lines[+m2]?.replaceAll('\t', ' ')}`);
366
- }
367
- failedLine += chalk.dim('\n ...');
368
- return res;
369
- });
370
- if (failedLine) {
371
- text += failedLine;
372
- }
373
- mmf.fail(text);
374
- });
375
- }
376
- function pipeMMF(proc, mmf) {
377
- return new Promise((resolve) => {
378
- pipeStdoutToMMF(proc.stdout, mmf);
379
- pipeStderrToMMF(proc.stderr, mmf);
380
- // exit
381
- proc.on('close', (code) => {
382
- if (code === 0) {
383
- mmf.strategy !== 'print' && mmf.pass();
384
- }
385
- else if (code !== 1) {
386
- mmf.fail(`unknown exit code: ${code}`);
387
- }
388
- resolve();
389
- });
390
- });
391
- }
@@ -1 +1,7 @@
1
+ import { ChildProcessWithoutNullStreams } from "node:child_process";
2
+ import { Readable } from "node:stream";
3
+ import { MMF1 } from "./mmf1.js";
1
4
  export declare function absToRel(p: string): string;
5
+ export declare function pipeStdoutToMMF(stdout: Readable, mmf: MMF1): void;
6
+ export declare function pipeStderrToMMF(stderr: Readable, mmf: MMF1, dir?: string): void;
7
+ export declare function pipeMMF(proc: ChildProcessWithoutNullStreams, mmf: MMF1): Promise<void>;
@@ -1,6 +1,67 @@
1
- import path from 'node:path';
2
- import { getRootDir } from '../../mops.js';
1
+ import path from "node:path";
2
+ import fs from "node:fs";
3
+ import chalk from "chalk";
4
+ import { getRootDir } from "../../mops.js";
3
5
  export function absToRel(p) {
4
6
  let rootDir = getRootDir();
5
7
  return path.relative(rootDir, path.resolve(p));
6
8
  }
9
+ export function pipeStdoutToMMF(stdout, mmf) {
10
+ stdout.on("data", (data) => {
11
+ for (let line of data.toString().split("\n")) {
12
+ line = line.trim();
13
+ if (line) {
14
+ mmf.parseLine(line);
15
+ }
16
+ }
17
+ });
18
+ }
19
+ export function pipeStderrToMMF(stderr, mmf, dir = "") {
20
+ stderr.on("data", (data) => {
21
+ let text = data.toString().trim();
22
+ let failedLine = "";
23
+ text = text.replace(/([\w+._/-]+):(\d+).(\d+)(-\d+.\d+)/g, (_m0, m1, m2, m3) => {
24
+ // change absolute file path to relative
25
+ // change :line:col-line:col to :line:col to work in vscode
26
+ let res = `${absToRel(m1)}:${m2}:${m3}`;
27
+ let file = path.join(dir, m1);
28
+ if (!fs.existsSync(file)) {
29
+ return res;
30
+ }
31
+ // show failed line
32
+ let content = fs.readFileSync(file);
33
+ let lines = content.toString().split("\n") || [];
34
+ failedLine += chalk.dim("\n ...");
35
+ let lineBefore = lines[+m2 - 2];
36
+ if (lineBefore) {
37
+ failedLine += chalk.dim(`\n ${+m2 - 1}\t| ${lineBefore.replaceAll("\t", " ")}`);
38
+ }
39
+ failedLine += `\n${chalk.redBright `->`} ${m2}\t| ${lines[+m2 - 1]?.replaceAll("\t", " ")}`;
40
+ if (lines.length > +m2) {
41
+ failedLine += chalk.dim(`\n ${+m2 + 1}\t| ${lines[+m2]?.replaceAll("\t", " ")}`);
42
+ }
43
+ failedLine += chalk.dim("\n ...");
44
+ return res;
45
+ });
46
+ if (failedLine) {
47
+ text += failedLine;
48
+ }
49
+ mmf.fail(text);
50
+ });
51
+ }
52
+ export function pipeMMF(proc, mmf) {
53
+ return new Promise((resolve) => {
54
+ pipeStdoutToMMF(proc.stdout, mmf);
55
+ pipeStderrToMMF(proc.stderr, mmf);
56
+ // exit
57
+ proc.on("close", (code) => {
58
+ if (code === 0) {
59
+ mmf.strategy !== "print" && mmf.pass();
60
+ }
61
+ else if (code !== 1) {
62
+ mmf.fail(`unknown exit code: ${code}`);
63
+ }
64
+ resolve();
65
+ });
66
+ });
67
+ }