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,17 +1,17 @@
1
- import { Benchmarks } from '../declarations/main/main.did.js';
2
- type ReplicaName = 'dfx' | 'pocket-ic' | 'dfx-pocket-ic';
1
+ import { Benchmarks } from "../declarations/main/main.did.js";
2
+ type ReplicaName = "dfx" | "pocket-ic" | "dfx-pocket-ic";
3
3
  type BenchOptions = {
4
4
  replica: ReplicaName;
5
5
  replicaVersion: string;
6
- compiler: 'moc';
6
+ compiler: "moc";
7
7
  compilerVersion: string;
8
- gc: 'copying' | 'compacting' | 'generational' | 'incremental';
8
+ gc: "copying" | "compacting" | "generational" | "incremental";
9
9
  forceGc: boolean;
10
10
  save: boolean;
11
11
  compare: boolean;
12
12
  verbose: boolean;
13
13
  silent: boolean;
14
- profile: 'Debug' | 'Release';
14
+ profile: "Debug" | "Release";
15
15
  };
16
16
  export declare function bench(filter?: string, optionsArg?: Partial<BenchOptions>): Promise<Benchmarks>;
17
17
  export {};
@@ -1,88 +1,90 @@
1
- import process from 'node:process';
2
- import path from 'node:path';
3
- import fs from 'node:fs';
4
- import os from 'node:os';
5
- import chalk from 'chalk';
6
- import { globSync } from 'glob';
7
- import { markdownTable } from 'markdown-table';
8
- import { createLogUpdate } from 'log-update';
9
- import { execaCommand } from 'execa';
10
- import stringWidth from 'string-width';
11
- import { filesize } from 'filesize';
12
- import terminalSize from 'terminal-size';
13
- import { SemVer } from 'semver';
14
- import { getRootDir, readConfig, readDfxJson } from '../mops.js';
15
- import { parallel } from '../parallel.js';
16
- import { absToRel } from './test/utils.js';
17
- import { getMocVersion } from '../helpers/get-moc-version.js';
18
- import { getDfxVersion } from '../helpers/get-dfx-version.js';
19
- import { getMocPath } from '../helpers/get-moc-path.js';
20
- import { sources } from './sources.js';
21
- import { BenchReplica } from './bench-replica.js';
1
+ import process from "node:process";
2
+ import path from "node:path";
3
+ import fs from "node:fs";
4
+ import os from "node:os";
5
+ import chalk from "chalk";
6
+ import { globSync } from "glob";
7
+ import { markdownTable } from "markdown-table";
8
+ import { createLogUpdate } from "log-update";
9
+ import { execaCommand } from "execa";
10
+ import stringWidth from "string-width";
11
+ import { filesize } from "filesize";
12
+ import terminalSize from "terminal-size";
13
+ import { SemVer } from "semver";
14
+ import { getRootDir, readConfig, readDfxJson } from "../mops.js";
15
+ import { parallel } from "../parallel.js";
16
+ import { absToRel } from "./test/utils.js";
17
+ import { getMocVersion } from "../helpers/get-moc-version.js";
18
+ import { getDfxVersion } from "../helpers/get-dfx-version.js";
19
+ import { getMocPath } from "../helpers/get-moc-path.js";
20
+ import { sources } from "./sources.js";
21
+ import { BenchReplica } from "./bench-replica.js";
22
22
  let ignore = [
23
- '**/node_modules/**',
24
- '**/.mops/**',
25
- '**/.vessel/**',
26
- '**/.git/**',
23
+ "**/node_modules/**",
24
+ "**/.mops/**",
25
+ "**/.vessel/**",
26
+ "**/.git/**",
27
27
  ];
28
28
  let globConfig = {
29
29
  nocase: true,
30
30
  ignore: ignore,
31
31
  };
32
- export async function bench(filter = '', optionsArg = {}) {
32
+ export async function bench(filter = "", optionsArg = {}) {
33
33
  let config = readConfig();
34
34
  let dfxJson = readDfxJson();
35
35
  let defaultOptions = {
36
- replica: config.toolchain?.['pocket-ic'] ? 'pocket-ic' : 'dfx',
37
- replicaVersion: '',
38
- compiler: 'moc',
36
+ replica: config.toolchain?.["pocket-ic"] ? "pocket-ic" : "dfx",
37
+ replicaVersion: "",
38
+ compiler: "moc",
39
39
  compilerVersion: getMocVersion(true),
40
- gc: 'copying',
40
+ gc: "copying",
41
41
  forceGc: true,
42
42
  save: false,
43
43
  compare: false,
44
44
  verbose: false,
45
45
  silent: false,
46
- profile: dfxJson?.profile || 'Release',
46
+ profile: dfxJson?.profile || "Release",
47
47
  };
48
48
  let options = { ...defaultOptions, ...optionsArg };
49
- let replicaType = options.replica ?? (config.toolchain?.['pocket-ic'] ? 'pocket-ic' : 'dfx');
50
- if (replicaType === 'pocket-ic' && !config.toolchain?.['pocket-ic']) {
49
+ let replicaType = options.replica ??
50
+ (config.toolchain?.["pocket-ic"] ? "pocket-ic" : "dfx");
51
+ if (replicaType === "pocket-ic" && !config.toolchain?.["pocket-ic"]) {
51
52
  let dfxVersion = getDfxVersion();
52
- if (!dfxVersion || new SemVer(dfxVersion).compare('0.24.1') < 0) {
53
- console.log(chalk.red('Please update dfx to the version >=0.24.1 or specify pocket-ic version in mops.toml'));
53
+ if (!dfxVersion || new SemVer(dfxVersion).compare("0.24.1") < 0) {
54
+ console.log(chalk.red("Please update dfx to the version >=0.24.1 or specify pocket-ic version in mops.toml"));
54
55
  process.exit(1);
55
56
  }
56
57
  else {
57
- replicaType = 'dfx-pocket-ic';
58
+ replicaType = "dfx-pocket-ic";
58
59
  }
59
60
  }
60
61
  options.replica = replicaType;
61
62
  if (process.env.CI) {
62
- console.log('# Benchmark Results\n\n');
63
+ console.log("# Benchmark Results\n\n");
63
64
  }
64
- if (replicaType == 'dfx') {
65
+ if (replicaType == "dfx") {
65
66
  options.replicaVersion = getDfxVersion();
66
67
  }
67
- else if (replicaType == 'pocket-ic') {
68
- options.replicaVersion = config.toolchain?.['pocket-ic'] || '';
68
+ else if (replicaType == "pocket-ic") {
69
+ options.replicaVersion = config.toolchain?.["pocket-ic"] || "";
69
70
  }
70
71
  options.verbose && console.log(options);
71
72
  let replica = new BenchReplica(replicaType, options.verbose);
72
73
  let rootDir = getRootDir();
73
- let globStr = '**/bench?(mark)/**/*.bench.mo';
74
+ let globStr = "**/bench?(mark)/**/*.bench.mo";
74
75
  if (filter) {
75
76
  globStr = `**/bench?(mark)/**/*${filter}*.mo`;
76
77
  }
77
78
  let files = globSync(path.join(rootDir, globStr), globConfig);
78
79
  if (!files.length) {
79
80
  if (filter) {
80
- options.silent || console.log(`No benchmark files found for filter '${filter}'`);
81
+ options.silent ||
82
+ console.log(`No benchmark files found for filter '${filter}'`);
81
83
  return [];
82
84
  }
83
85
  if (!options.silent) {
84
- console.log('No *.bench.mo files found');
85
- console.log('Put your benchmark code in \'bench\' directory in *.bench.mo files');
86
+ console.log("No *.bench.mo files found");
87
+ console.log("Put your benchmark code in 'bench' directory in *.bench.mo files");
86
88
  }
87
89
  return [];
88
90
  }
@@ -91,26 +93,26 @@ export async function bench(filter = '', optionsArg = {}) {
91
93
  fs.rmSync(benchDir, { recursive: true, force: true });
92
94
  fs.mkdirSync(benchDir, { recursive: true });
93
95
  if (!options.silent && !process.env.CI) {
94
- console.log('Benchmark files:');
96
+ console.log("Benchmark files:");
95
97
  for (let file of files) {
96
98
  console.log(chalk.gray(`• ${absToRel(file)}`));
97
99
  }
98
100
  if (!process.env.CI) {
99
- console.log('');
100
- console.log('='.repeat(50));
101
- console.log('');
101
+ console.log("");
102
+ console.log("=".repeat(50));
103
+ console.log("");
102
104
  }
103
105
  }
104
106
  await replica.start({ silent: options.silent });
105
107
  if (!process.env.CI && !options.silent) {
106
- console.log('Deploying canisters...');
108
+ console.log("Deploying canisters...");
107
109
  }
108
110
  await parallel(os.cpus().length, files, async (file) => {
109
111
  try {
110
112
  await deployBenchFile(file, options, replica);
111
113
  }
112
114
  catch (err) {
113
- console.error('Unexpected error. Stopping replica...');
115
+ console.error("Unexpected error. Stopping replica...");
114
116
  await replica.stop();
115
117
  throw err;
116
118
  }
@@ -118,22 +120,22 @@ export async function bench(filter = '', optionsArg = {}) {
118
120
  let benchResults = [];
119
121
  await parallel(1, files, async (file) => {
120
122
  if (!options.silent && !process.env.CI) {
121
- console.log('\n' + '-'.repeat(50));
123
+ console.log("\n" + "-".repeat(50));
122
124
  console.log(`\nRunning ${chalk.gray(absToRel(file))}...`);
123
- console.log('');
125
+ console.log("");
124
126
  }
125
127
  try {
126
128
  let benchResult = await runBenchFile(file, options, replica);
127
129
  benchResults.push(benchResult);
128
130
  }
129
131
  catch (err) {
130
- console.error('Unexpected error. Stopping replica...');
132
+ console.error("Unexpected error. Stopping replica...");
131
133
  await replica.stop();
132
134
  throw err;
133
135
  }
134
136
  });
135
137
  if (!process.env.CI && !options.silent) {
136
- console.log('Stopping replica...');
138
+ console.log("Stopping replica...");
137
139
  }
138
140
  await replica.stop();
139
141
  fs.rmSync(benchDir, { recursive: true, force: true });
@@ -166,7 +168,12 @@ function computeDiff(results, prevResults, rows, cols, metric) {
166
168
  return count > 0 ? diff / count : 0;
167
169
  }
168
170
  function computeDiffAll(currentResults, prevResults, rows, cols) {
169
- let metrics = ['instructions', 'rts_heap_size', 'rts_logical_stable_memory_size', 'rts_reclaimed'];
171
+ let metrics = [
172
+ "instructions",
173
+ "rts_heap_size",
174
+ "rts_logical_stable_memory_size",
175
+ "rts_reclaimed",
176
+ ];
170
177
  let diff = 0;
171
178
  for (let metric of metrics) {
172
179
  diff += computeDiff(currentResults, prevResults, rows, cols, metric);
@@ -174,60 +181,64 @@ function computeDiffAll(currentResults, prevResults, rows, cols) {
174
181
  return diff;
175
182
  }
176
183
  function getMocArgs(options) {
177
- let args = '';
178
- if (options.compilerVersion && new SemVer(options.compilerVersion).compare('0.15.0') >= 0) {
179
- args += ' --legacy-persistence';
184
+ let args = "";
185
+ if (options.compilerVersion &&
186
+ new SemVer(options.compilerVersion).compare("0.15.0") >= 0) {
187
+ args += " --legacy-persistence";
180
188
  }
181
189
  if (options.forceGc) {
182
- args += ' --force-gc';
190
+ args += " --force-gc";
183
191
  }
184
192
  if (options.gc) {
185
193
  args += ` --${options.gc}-gc`;
186
194
  }
187
- if (options.profile === 'Debug') {
188
- args += ' --debug';
195
+ if (options.profile === "Debug") {
196
+ args += " --debug";
189
197
  }
190
- else if (options.profile === 'Release') {
191
- args += ' --release';
198
+ else if (options.profile === "Release") {
199
+ args += " --release";
192
200
  }
193
201
  return args;
194
202
  }
195
203
  async function deployBenchFile(file, options, replica) {
196
204
  let rootDir = getRootDir();
197
- let tempDir = path.join(rootDir, '.mops/.bench/', path.parse(file).name);
205
+ let tempDir = path.join(rootDir, ".mops/.bench/", path.parse(file).name);
198
206
  let canisterName = path.parse(file).name;
199
207
  // prepare temp files
200
208
  fs.mkdirSync(tempDir, { recursive: true });
201
- fs.writeFileSync(path.join(tempDir, 'dfx.json'), JSON.stringify(replica.dfxJson(canisterName), null, 2));
202
- let benchCanisterData = fs.readFileSync(new URL('./bench/bench-canister.mo', import.meta.url), 'utf8');
203
- benchCanisterData = benchCanisterData.replace('./user-bench', path.relative(tempDir, file).replace(/.mo$/g, ''));
204
- fs.writeFileSync(path.join(tempDir, 'canister.mo'), benchCanisterData);
209
+ fs.writeFileSync(path.join(tempDir, "dfx.json"), JSON.stringify(replica.dfxJson(canisterName), null, 2));
210
+ let benchCanisterData = fs.readFileSync(new URL("./bench/bench-canister.mo", import.meta.url), "utf8");
211
+ benchCanisterData = benchCanisterData.replace("./user-bench", path.relative(tempDir, file).replace(/.mo$/g, ""));
212
+ fs.writeFileSync(path.join(tempDir, "canister.mo"), benchCanisterData);
205
213
  // build canister
206
214
  let mocPath = getMocPath();
207
215
  let mocArgs = getMocArgs(options);
208
216
  options.verbose && console.time(`build ${canisterName}`);
209
- await execaCommand(`${mocPath} -c --idl canister.mo ${mocArgs} ${(await sources({ cwd: tempDir })).join(' ')}`, { cwd: tempDir, stdio: options.verbose ? 'pipe' : ['pipe', 'ignore', 'pipe'] });
217
+ await execaCommand(`${mocPath} -c --idl canister.mo ${mocArgs} ${(await sources({ cwd: tempDir })).join(" ")}`, {
218
+ cwd: tempDir,
219
+ stdio: options.verbose ? "pipe" : ["pipe", "ignore", "pipe"],
220
+ });
210
221
  options.verbose && console.timeEnd(`build ${canisterName}`);
211
222
  // deploy canister
212
- let wasm = path.join(tempDir, 'canister.wasm');
223
+ let wasm = path.join(tempDir, "canister.wasm");
213
224
  options.verbose && console.time(`deploy ${canisterName}`);
214
225
  // await execaCommand(`dfx deploy ${canisterName} --mode reinstall --yes --identity anonymous`, {cwd: tempDir, stdio: options.verbose ? 'pipe' : ['pipe', 'ignore', 'pipe']});
215
226
  await replica.deploy(canisterName, wasm, tempDir);
216
227
  options.verbose && console.timeEnd(`deploy ${canisterName}`);
217
228
  // init bench
218
229
  options.verbose && console.time(`init ${canisterName}`);
219
- let actor = await replica.getActor(canisterName);
230
+ let actor = (await replica.getActor(canisterName));
220
231
  await actor.init();
221
232
  options.verbose && console.timeEnd(`init ${canisterName}`);
222
233
  }
223
234
  async function runBenchFile(file, options, replica) {
224
235
  let rootDir = getRootDir();
225
236
  let canisterName = path.parse(file).name;
226
- let actor = await replica.getActor(canisterName);
237
+ let actor = (await replica.getActor(canisterName));
227
238
  let schema = await actor.getSchema();
228
239
  // load previous results
229
240
  let prevResults;
230
- let resultsJsonFile = path.join(rootDir, '.bench', `${path.parse(file).name}.json`);
241
+ let resultsJsonFile = path.join(rootDir, ".bench", `${path.parse(file).name}.json`);
231
242
  if (options.compare) {
232
243
  if (fs.existsSync(resultsJsonFile)) {
233
244
  let prevResultsJson = JSON.parse(fs.readFileSync(resultsJsonFile).toString());
@@ -243,25 +254,25 @@ async function runBenchFile(file, options, replica) {
243
254
  let logicalStableMemoryCells = Array.from({ length: schema.rows.length }, () => []);
244
255
  let reclaimedCells = Array.from({ length: schema.rows.length }, () => []);
245
256
  let formatNumber = (n) => {
246
- return n.toLocaleString('en-US').replaceAll(',', '_');
257
+ return n.toLocaleString("en-US").replaceAll(",", "_");
247
258
  };
248
259
  let formatSize = (n) => {
249
- return filesize(n, { standard: 'iec', round: 2 });
260
+ return filesize(n, { standard: "iec", round: 2 });
250
261
  };
251
262
  let colorizePercent = (percent, wrapInParens = false) => {
252
- let sign = percent > 0 ? '+' : '';
253
- let percentText = percent == 0 ? '0%' : sign + percent.toFixed(2) + '%';
254
- let color = percent == 0 ? 'gray' : (percent > 0 ? 'red' : 'green');
255
- let parens = wrapInParens ? ['(', ')'] : ['', ''];
263
+ let sign = percent > 0 ? "+" : "";
264
+ let percentText = percent == 0 ? "0%" : sign + percent.toFixed(2) + "%";
265
+ let color = percent == 0 ? "gray" : percent > 0 ? "red" : "green";
266
+ let parens = wrapInParens ? ["(", ")"] : ["", ""];
256
267
  if (process.env.CI) {
257
- return `$${parens[0]}{\\color{${color}}${percentText.replace('%', '\\\\%')}}${parens[1]}$`;
268
+ return `$${parens[0]}{\\color{${color}}${percentText.replace("%", "\\\\%")}}${parens[1]}$`;
258
269
  }
259
270
  else {
260
271
  return `${parens[0]}${chalk[color](percentText)}${parens[1]}`;
261
272
  }
262
273
  };
263
274
  let getTable = (prop) => {
264
- let resArr = [['', ...schema.cols]];
275
+ let resArr = [["", ...schema.cols]];
265
276
  let allZero = true;
266
277
  for (let [_rowIndex, row] of schema.rows.entries()) {
267
278
  let curRow = [row];
@@ -272,26 +283,28 @@ async function runBenchFile(file, options, replica) {
272
283
  allZero = false;
273
284
  }
274
285
  // compare with previous results
275
- let diff = '';
286
+ let diff = "";
276
287
  if (options.compare && prevResults) {
277
288
  let prevRes = prevResults.get(`${row}:${col}`);
278
289
  if (prevRes) {
279
- let percent = (Number(res[prop]) - Number(prevRes[prop])) / Number(prevRes[prop]) * 100;
290
+ let percent = ((Number(res[prop]) - Number(prevRes[prop])) /
291
+ Number(prevRes[prop])) *
292
+ 100;
280
293
  if (Object.is(percent, NaN)) {
281
294
  percent = 0;
282
295
  }
283
- diff = ' ' + colorizePercent(percent, true);
296
+ diff = " " + colorizePercent(percent, true);
284
297
  }
285
298
  else {
286
- diff = chalk.yellow(' (no previous results)');
299
+ diff = chalk.yellow(" (no previous results)");
287
300
  }
288
301
  }
289
302
  // add to table
290
- let value = '';
291
- if (prop == 'rts_logical_stable_memory_size') {
303
+ let value = "";
304
+ if (prop == "rts_logical_stable_memory_size") {
292
305
  value = formatSize(res[prop] * 65536n);
293
306
  }
294
- else if (prop === 'rts_heap_size' || prop == 'rts_reclaimed') {
307
+ else if (prop === "rts_heap_size" || prop == "rts_reclaimed") {
295
308
  value = formatSize(res[prop]);
296
309
  }
297
310
  else {
@@ -300,17 +313,17 @@ async function runBenchFile(file, options, replica) {
300
313
  curRow.push(value + diff);
301
314
  }
302
315
  else {
303
- curRow.push('');
316
+ curRow.push("");
304
317
  }
305
318
  }
306
319
  resArr.push(curRow);
307
320
  }
308
321
  // don't show Stable Memory table if all values are 0
309
- if (allZero && prop == 'rts_logical_stable_memory_size') {
310
- return '';
322
+ if (allZero && prop == "rts_logical_stable_memory_size") {
323
+ return "";
311
324
  }
312
325
  return markdownTable(resArr, {
313
- align: ['l', ...'r'.repeat(schema.cols.length)],
326
+ align: ["l", ..."r".repeat(schema.cols.length)],
314
327
  stringLength: stringWidth,
315
328
  });
316
329
  };
@@ -318,39 +331,41 @@ async function runBenchFile(file, options, replica) {
318
331
  let getOutput = () => {
319
332
  if (process.env.CI) {
320
333
  return [
321
- '\n<details>',
322
- `\n<summary>${absToRel(file)} ${colorizePercent(computeDiffAll(results, prevResults, schema.rows, schema.cols), true).replace('\\\\%', '\\%')}</summary>`,
334
+ "\n<details>",
335
+ `\n<summary>${absToRel(file)} ${colorizePercent(computeDiffAll(results, prevResults, schema.rows, schema.cols), true).replace("\\\\%", "\\%")}</summary>`,
323
336
  `\n${process.env.CI ? `### ${schema.name}` : chalk.bold(schema.name)}`,
324
- `${schema.description ? '\n' + (process.env.CI ? `_${schema.description}_` : chalk.gray(schema.description)) : ''}`,
325
- `\n\nInstructions: ${colorizePercent(computeDiff(results, prevResults, schema.rows, schema.cols, 'instructions'), false)}`,
326
- `Heap: ${colorizePercent(computeDiff(results, prevResults, schema.rows, schema.cols, 'rts_heap_size'), false)}`,
327
- `Stable Memory: ${colorizePercent(computeDiff(results, prevResults, schema.rows, schema.cols, 'rts_logical_stable_memory_size'), false)}`,
328
- `Garbage Collection: ${colorizePercent(computeDiff(results, prevResults, schema.rows, schema.cols, 'rts_reclaimed'), false)}`,
329
- `\n\n**Instructions**\n\n${getTable('instructions')}`,
330
- `\n\n**Heap**\n\n${getTable('rts_heap_size')}`,
331
- `\n\n**Garbage Collection**\n\n${getTable('rts_reclaimed')}`,
332
- `${getTable('rts_logical_stable_memory_size') ? `\n\n**Stable Memory**\n\n${getTable('rts_logical_stable_memory_size')}` : ''}`,
333
- '\n</details>',
334
- ].join('\n');
337
+ `${schema.description ? "\n" + (process.env.CI ? `_${schema.description}_` : chalk.gray(schema.description)) : ""}`,
338
+ `\n\nInstructions: ${colorizePercent(computeDiff(results, prevResults, schema.rows, schema.cols, "instructions"), false)}`,
339
+ `Heap: ${colorizePercent(computeDiff(results, prevResults, schema.rows, schema.cols, "rts_heap_size"), false)}`,
340
+ `Stable Memory: ${colorizePercent(computeDiff(results, prevResults, schema.rows, schema.cols, "rts_logical_stable_memory_size"), false)}`,
341
+ `Garbage Collection: ${colorizePercent(computeDiff(results, prevResults, schema.rows, schema.cols, "rts_reclaimed"), false)}`,
342
+ `\n\n**Instructions**\n\n${getTable("instructions")}`,
343
+ `\n\n**Heap**\n\n${getTable("rts_heap_size")}`,
344
+ `\n\n**Garbage Collection**\n\n${getTable("rts_reclaimed")}`,
345
+ `${getTable("rts_logical_stable_memory_size") ? `\n\n**Stable Memory**\n\n${getTable("rts_logical_stable_memory_size")}` : ""}`,
346
+ "\n</details>",
347
+ ].join("\n");
335
348
  }
336
349
  else {
337
350
  return `
338
351
  \n${chalk.bold(schema.name)}
339
- ${schema.description ? '\n' + chalk.gray(schema.description) : ''}
340
- \n\n${chalk.blue('Instructions')}\n\n${getTable('instructions')}
341
- \n\n${chalk.blue('Heap')}\n\n${getTable('rts_heap_size')}
342
- \n\n${chalk.blue('Garbage Collection')}\n\n${getTable('rts_reclaimed')}
343
- ${getTable('rts_logical_stable_memory_size') ? `\n\n${chalk.blue('Stable Memory')}\n\n${getTable('rts_logical_stable_memory_size')}` : ''}
352
+ ${schema.description ? "\n" + chalk.gray(schema.description) : ""}
353
+ \n\n${chalk.blue("Instructions")}\n\n${getTable("instructions")}
354
+ \n\n${chalk.blue("Heap")}\n\n${getTable("rts_heap_size")}
355
+ \n\n${chalk.blue("Garbage Collection")}\n\n${getTable("rts_reclaimed")}
356
+ ${getTable("rts_logical_stable_memory_size") ? `\n\n${chalk.blue("Stable Memory")}\n\n${getTable("rts_logical_stable_memory_size")}` : ""}
344
357
  `;
345
358
  }
346
359
  };
347
- let canUpdateLog = !process.env.CI && !options.silent && terminalSize().rows > getOutput().split('\n').length;
360
+ let canUpdateLog = !process.env.CI &&
361
+ !options.silent &&
362
+ terminalSize().rows > getOutput().split("\n").length;
348
363
  let log = () => {
349
364
  if (options.silent) {
350
365
  return;
351
366
  }
352
367
  let output = getOutput();
353
- if (process.env.CI || terminalSize().rows <= output.split('\n').length) {
368
+ if (process.env.CI || terminalSize().rows <= output.split("\n").length) {
354
369
  console.log(output);
355
370
  }
356
371
  else {
@@ -370,7 +385,8 @@ async function runBenchFile(file, options, replica) {
370
385
  // @ts-ignore
371
386
  heapCells[rowIndex][colIndex] = res.rts_heap_size;
372
387
  // @ts-ignore
373
- logicalStableMemoryCells[rowIndex][colIndex] = res.rts_logical_stable_memory_size;
388
+ logicalStableMemoryCells[rowIndex][colIndex] =
389
+ res.rts_logical_stable_memory_size;
374
390
  // @ts-ignore
375
391
  reclaimedCells[rowIndex][colIndex] = res.rts_reclaimed;
376
392
  if (canUpdateLog) {
@@ -398,7 +414,7 @@ async function runBenchFile(file, options, replica) {
398
414
  };
399
415
  fs.mkdirSync(path.dirname(resultsJsonFile), { recursive: true });
400
416
  fs.writeFileSync(resultsJsonFile, JSON.stringify(json, (_, val) => {
401
- if (typeof val === 'bigint') {
417
+ if (typeof val === "bigint") {
402
418
  return Number(val);
403
419
  }
404
420
  else {
@@ -420,10 +436,10 @@ async function runBenchFile(file, options, replica) {
420
436
  rows: schema.rows,
421
437
  cols: schema.cols,
422
438
  metrics: [
423
- ['instructions', instructionsCells],
424
- ['rts_heap_size', heapCells],
425
- ['rts_logical_stable_memory_size', logicalStableMemoryCells],
426
- ['rts_reclaimed', reclaimedCells],
439
+ ["instructions", instructionsCells],
440
+ ["rts_heap_size", heapCells],
441
+ ["rts_logical_stable_memory_size", logicalStableMemoryCells],
442
+ ["rts_reclaimed", reclaimedCells],
427
443
  ],
428
444
  };
429
445
  }
@@ -0,0 +1,7 @@
1
+ export interface BuildOptions {
2
+ outputDir: string;
3
+ verbose: boolean;
4
+ extraArgs: string[];
5
+ }
6
+ export declare const DEFAULT_BUILD_OUTPUT_DIR = ".mops/.build";
7
+ export declare function build(canisterNames: string[] | undefined, options: Partial<BuildOptions>): Promise<void>;
@@ -0,0 +1,121 @@
1
+ import chalk from "chalk";
2
+ import { execa } from "execa";
3
+ import { exists } from "fs-extra";
4
+ import { mkdir } from "node:fs/promises";
5
+ import { join } from "node:path";
6
+ import { getMocPath } from "../helpers/get-moc-path.js";
7
+ import { readConfig } from "../mops.js";
8
+ import { sourcesArgs } from "./sources.js";
9
+ import { isCandidCompatible } from "../helpers/is-candid-compatible.js";
10
+ import { cliError } from "../error.js";
11
+ export const DEFAULT_BUILD_OUTPUT_DIR = ".mops/.build";
12
+ export async function build(canisterNames, options) {
13
+ if (canisterNames?.length == 0) {
14
+ cliError("No canisters specified to build");
15
+ }
16
+ let outputDir = options.outputDir ?? DEFAULT_BUILD_OUTPUT_DIR;
17
+ let mocPath = getMocPath();
18
+ let canisters = {};
19
+ let config = readConfig();
20
+ if (config.canisters) {
21
+ canisters =
22
+ Object.fromEntries(Object.entries(config.canisters).map(([name, c]) => typeof c === "string" ? [name, { main: c }] : [name, c])) ?? {};
23
+ }
24
+ if (!Object.keys(canisters).length) {
25
+ cliError(`No Motoko canisters found in mops.toml configuration`);
26
+ }
27
+ if (canisterNames) {
28
+ canisterNames = canisterNames.filter((name) => name in canisters);
29
+ if (canisterNames.length === 0) {
30
+ throw new Error("No valid canister names specified");
31
+ }
32
+ for (let name of canisterNames) {
33
+ if (!(name in canisters)) {
34
+ cliError(`Motoko canister '${name}' not found in mops.toml configuration`);
35
+ }
36
+ }
37
+ }
38
+ if (!(await exists(outputDir))) {
39
+ await mkdir(outputDir, { recursive: true });
40
+ }
41
+ const filteredCanisters = canisterNames
42
+ ? Object.fromEntries(Object.entries(canisters).filter(([name]) => canisterNames.includes(name)))
43
+ : canisters;
44
+ for (let [canisterName, canister] of Object.entries(filteredCanisters)) {
45
+ options.verbose && console.time(`build canister ${canisterName}`);
46
+ console.log(chalk.blue("build canister"), chalk.bold(canisterName));
47
+ let motokoPath = canister.main;
48
+ if (!motokoPath) {
49
+ cliError(`No main file is specified for canister ${canisterName}`);
50
+ }
51
+ let args = [
52
+ "-c",
53
+ "--idl",
54
+ "-o",
55
+ join(outputDir, `${canisterName}.wasm`),
56
+ motokoPath,
57
+ ...(options.extraArgs ?? []),
58
+ ...(await sourcesArgs()).flat(),
59
+ ];
60
+ if (config.build?.args) {
61
+ if (typeof config.build.args === "string") {
62
+ cliError(`[build] config 'args' should be an array of strings in mops.toml config file`);
63
+ }
64
+ args.push(...config.build.args);
65
+ }
66
+ if (canister.args) {
67
+ if (typeof canister.args === "string") {
68
+ cliError(`Canister config 'args' should be an array of strings for canister ${canisterName}`);
69
+ }
70
+ args.push(...canister.args);
71
+ }
72
+ try {
73
+ if (options.verbose) {
74
+ console.log(chalk.gray(mocPath, JSON.stringify(args)));
75
+ }
76
+ const result = await execa(mocPath, args, {
77
+ stdio: options.verbose ? "inherit" : "pipe",
78
+ reject: false,
79
+ });
80
+ if (result.exitCode !== 0) {
81
+ if (!options.verbose) {
82
+ if (result.stderr) {
83
+ console.error(chalk.red(result.stderr));
84
+ }
85
+ if (result.stdout?.trim()) {
86
+ console.error(chalk.yellow("Build output:"));
87
+ console.error(result.stdout);
88
+ }
89
+ }
90
+ cliError(`Build failed for canister ${canisterName} (exit code: ${result.exitCode})`);
91
+ }
92
+ if (options.verbose && result.stdout && result.stdout.trim()) {
93
+ console.log(result.stdout);
94
+ }
95
+ if (canister.candid) {
96
+ const generatedDidPath = join(outputDir, `${canisterName}.did`);
97
+ const originalCandidPath = canister.candid;
98
+ try {
99
+ const compatible = await isCandidCompatible(generatedDidPath, originalCandidPath);
100
+ if (!compatible) {
101
+ cliError(`Candid compatibility check failed for canister ${canisterName}`);
102
+ }
103
+ if (options.verbose) {
104
+ console.log(chalk.green(`Candid compatibility check passed for canister ${canisterName}`));
105
+ }
106
+ }
107
+ catch (candidError) {
108
+ cliError(`Error during Candid compatibility check for canister ${canisterName}`, candidError);
109
+ }
110
+ }
111
+ }
112
+ catch (cliError) {
113
+ if (cliError.message?.includes("Build failed for canister")) {
114
+ throw cliError;
115
+ }
116
+ cliError(`Error while compiling canister ${canisterName}${cliError?.message ? `\n${cliError.message}` : ""}`);
117
+ }
118
+ options.verbose && console.timeEnd(`build canister ${canisterName}`);
119
+ }
120
+ console.log(chalk.green(`\n✓ Built ${Object.keys(filteredCanisters).length} canister${Object.keys(filteredCanisters).length == 1 ? "" : "s"} successfully`));
121
+ }