ic-mops 2.3.1 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/RELEASE.md +16 -162
  3. package/bundle/cli.tgz +0 -0
  4. package/cli.ts +2 -5
  5. package/commands/bench-replica.ts +13 -34
  6. package/commands/build.ts +70 -24
  7. package/commands/check-stable.ts +2 -2
  8. package/commands/check.ts +9 -8
  9. package/commands/replica.ts +17 -42
  10. package/dist/cli.js +3 -2
  11. package/dist/commands/bench-replica.d.ts +3 -4
  12. package/dist/commands/bench-replica.js +5 -23
  13. package/dist/commands/build.js +47 -20
  14. package/dist/commands/check-stable.js +2 -2
  15. package/dist/commands/check.js +9 -8
  16. package/dist/commands/replica.d.ts +3 -4
  17. package/dist/commands/replica.js +9 -29
  18. package/dist/helpers/pocket-ic-client.d.ts +9 -0
  19. package/dist/helpers/pocket-ic-client.js +18 -0
  20. package/dist/mops.d.ts +5 -0
  21. package/dist/mops.js +7 -0
  22. package/dist/package.json +1 -1
  23. package/dist/release-cli.js +6 -2
  24. package/dist/tests/build.test.js +83 -16
  25. package/dist/tests/check.test.js +7 -0
  26. package/dist/tests/pocket-ic.test.d.ts +1 -0
  27. package/dist/tests/pocket-ic.test.js +12 -0
  28. package/dist/wasm/pkg/nodejs/wasm_bg.wasm +0 -0
  29. package/dist/wasm/pkg/nodejs/wasm_bg.wasm.d.ts +1 -1
  30. package/dist/wasm/pkg/web/wasm.d.ts +1 -1
  31. package/dist/wasm/pkg/web/wasm_bg.wasm +0 -0
  32. package/dist/wasm/pkg/web/wasm_bg.wasm.d.ts +1 -1
  33. package/helpers/pocket-ic-client.ts +32 -0
  34. package/mops.ts +8 -0
  35. package/package.json +1 -1
  36. package/release-cli.ts +7 -2
  37. package/tests/__snapshots__/build.test.ts.snap +12 -0
  38. package/tests/build/custom-output/dfx.json +8 -0
  39. package/tests/build/custom-output/mops.toml +8 -0
  40. package/tests/build/custom-output/src/Main.mo +5 -0
  41. package/tests/build.test.ts +92 -20
  42. package/tests/check/canisters-subdir/mops.toml +8 -0
  43. package/tests/check/canisters-subdir/src/backend/main.mo +5 -0
  44. package/tests/check.test.ts +11 -0
  45. package/tests/pocket-ic/mops.toml +3 -0
  46. package/tests/pocket-ic/test/hello.test.mo +3 -0
  47. package/tests/pocket-ic.test.ts +19 -0
  48. package/wasm/pkg/nodejs/wasm_bg.wasm +0 -0
  49. package/wasm/pkg/nodejs/wasm_bg.wasm.d.ts +1 -1
  50. package/wasm/pkg/web/wasm.d.ts +1 -1
  51. package/wasm/pkg/web/wasm_bg.wasm +0 -0
  52. package/wasm/pkg/web/wasm_bg.wasm.d.ts +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ic-mops",
3
- "version": "2.3.1",
3
+ "version": "2.4.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "mops": "dist/bin/mops.js",
package/release-cli.ts CHANGED
@@ -11,8 +11,13 @@ import { findChangelogEntry } from "./helpers/find-changelog-entry.js";
11
11
 
12
12
  let __dirname = new URL(".", import.meta.url).pathname;
13
13
 
14
- // build using Docker
15
- execSync("./build.sh", { stdio: "inherit", cwd: __dirname });
14
+ if (!process.env.SKIP_BUILD) {
15
+ execSync("./build.sh", { stdio: "inherit", cwd: __dirname });
16
+ } else if (!fs.existsSync(path.resolve(__dirname, "bundle/cli.tgz"))) {
17
+ throw new Error(
18
+ "SKIP_BUILD is set but bundle/cli.tgz does not exist. Run build.sh first.",
19
+ );
20
+ }
16
21
 
17
22
  let commitHash =
18
23
  process.env.COMMIT_HASH || execSync("git rev-parse HEAD").toString().trim();
@@ -75,3 +75,15 @@ build canister bar
75
75
  ✓ Built 2 canisters successfully",
76
76
  }
77
77
  `;
78
+
79
+ exports[`build warns when args contain managed flags 1`] = `
80
+ {
81
+ "exitCode": 1,
82
+ "stderr": "Warning: '-o' in args for canister foo may conflict with mops build — use [build].outputDir in mops.toml or --output flag instead
83
+ Warning: '-c' in args for canister foo may conflict with mops build — this flag is always set by mops build
84
+ Warning: '--idl' in args for canister foo may conflict with mops build — this flag is always set by mops build
85
+ Error while compiling canister foo
86
+ ENOENT: no such file or directory, open '.mops/.build/foo.did'",
87
+ "stdout": "build canister foo",
88
+ }
89
+ `;
@@ -0,0 +1,8 @@
1
+ {
2
+ "canisters": {
3
+ "main": {
4
+ "type": "motoko",
5
+ "main": "src/Main.mo"
6
+ }
7
+ }
8
+ }
@@ -0,0 +1,8 @@
1
+ [dependencies]
2
+ core = "1.0.0"
3
+
4
+ [canisters.main]
5
+ main = "src/Main.mo"
6
+
7
+ [build]
8
+ outputDir = "custom-out"
@@ -0,0 +1,5 @@
1
+ persistent actor {
2
+ public func greet(name : Text) : async Text {
3
+ "Hello, " # name # "!";
4
+ };
5
+ };
@@ -1,29 +1,97 @@
1
1
  import { describe, expect, test } from "@jest/globals";
2
2
  import { execa } from "execa";
3
- import { existsSync } from "node:fs";
3
+ import { existsSync, rmSync } from "node:fs";
4
4
  import path from "path";
5
- import { cliSnapshot } from "./helpers";
5
+ import { cli, cliSnapshot } from "./helpers";
6
6
 
7
7
  const distBin = path.resolve(import.meta.dirname, "../dist/bin/mops.js");
8
8
 
9
+ function cleanFixture(cwd: string, ...extras: string[]) {
10
+ rmSync(path.join(cwd, ".mops"), { recursive: true, force: true });
11
+ for (const p of extras) {
12
+ rmSync(p, { recursive: true, force: true });
13
+ }
14
+ }
15
+
9
16
  describe("build", () => {
10
17
  test("ok", async () => {
11
18
  const cwd = path.join(import.meta.dirname, "build/success");
12
- await cliSnapshot(["build", "--verbose"], { cwd }, 0);
13
- await cliSnapshot(["build", "foo"], { cwd }, 0);
14
- await cliSnapshot(["build", "bar"], { cwd }, 0);
15
- await cliSnapshot(["build", "foo", "bar"], { cwd }, 0);
19
+ try {
20
+ await cliSnapshot(["build", "--verbose"], { cwd }, 0);
21
+ await cliSnapshot(["build", "foo"], { cwd }, 0);
22
+ await cliSnapshot(["build", "bar"], { cwd }, 0);
23
+ await cliSnapshot(["build", "foo", "bar"], { cwd }, 0);
24
+ } finally {
25
+ cleanFixture(cwd);
26
+ }
16
27
  });
17
28
 
18
29
  test("error", async () => {
19
30
  const cwd = path.join(import.meta.dirname, "build/error");
20
- await cliSnapshot(["build", "foo", "--verbose"], { cwd }, 0);
21
- expect((await cliSnapshot(["build", "bar"], { cwd }, 1)).stderr).toMatch(
22
- "Candid compatibility check failed for canister bar",
23
- );
24
- expect(
25
- (await cliSnapshot(["build", "foo", "bar"], { cwd }, 1)).stderr,
26
- ).toMatch("Candid compatibility check failed for canister bar");
31
+ try {
32
+ await cliSnapshot(["build", "foo", "--verbose"], { cwd }, 0);
33
+ expect((await cliSnapshot(["build", "bar"], { cwd }, 1)).stderr).toMatch(
34
+ "Candid compatibility check failed for canister bar",
35
+ );
36
+ expect(
37
+ (await cliSnapshot(["build", "foo", "bar"], { cwd }, 1)).stderr,
38
+ ).toMatch("Candid compatibility check failed for canister bar");
39
+ } finally {
40
+ cleanFixture(cwd);
41
+ }
42
+ });
43
+
44
+ // [build].outputDir in mops.toml should control where build output goes
45
+ test("custom output path via config outputDir", async () => {
46
+ const cwd = path.join(import.meta.dirname, "build/custom-output");
47
+ const customOut = path.join(cwd, "custom-out");
48
+ const customWasm = path.join(customOut, "main.wasm");
49
+ const customDid = path.join(customOut, "main.did");
50
+ const defaultDid = path.join(cwd, ".mops/.build/main.did");
51
+
52
+ try {
53
+ const result = await cli(["build"], { cwd });
54
+ expect(result.exitCode).toBe(0);
55
+ expect(existsSync(customWasm)).toBe(true);
56
+ expect(existsSync(customDid)).toBe(true);
57
+ expect(existsSync(defaultDid)).toBe(false);
58
+ } finally {
59
+ cleanFixture(cwd, customOut);
60
+ }
61
+ });
62
+
63
+ // Regression: --output CLI option was silently ignored due to
64
+ // Commander storing it as options.output while build() read options.outputDir
65
+ test("--output CLI option", async () => {
66
+ const cwd = path.join(import.meta.dirname, "build/success");
67
+ const outputDir = path.join(cwd, "cli-output-test");
68
+
69
+ try {
70
+ const result = await cli(["build", "foo", "--output", outputDir], {
71
+ cwd,
72
+ });
73
+ expect(result.exitCode).toBe(0);
74
+ expect(existsSync(path.join(outputDir, "foo.wasm"))).toBe(true);
75
+ expect(existsSync(path.join(outputDir, "foo.did"))).toBe(true);
76
+ } finally {
77
+ cleanFixture(cwd, outputDir);
78
+ }
79
+ });
80
+
81
+ test("warns when args contain managed flags", async () => {
82
+ const cwd = path.join(import.meta.dirname, "build/success");
83
+ const artifact = path.join(cwd, "x");
84
+ const artifactDid = path.join(cwd, "x.did");
85
+
86
+ try {
87
+ await cliSnapshot(
88
+ ["build", "foo", "--", "-o", "x", "-c", "--idl"],
89
+ { cwd },
90
+ 1,
91
+ );
92
+ } finally {
93
+ cleanFixture(cwd, artifact, artifactDid);
94
+ }
27
95
  });
28
96
 
29
97
  // Regression: bin/mops.js must route through environments/nodejs/cli.js
@@ -35,14 +103,18 @@ describe("build", () => {
35
103
  "wasm bindings initialized via dist entry point",
36
104
  async () => {
37
105
  const cwd = path.join(import.meta.dirname, "build/success");
38
- const result = await execa("node", [distBin, "build", "foo"], {
39
- cwd,
40
- stdio: "pipe",
41
- reject: false,
42
- });
106
+ try {
107
+ const result = await execa("node", [distBin, "build", "foo"], {
108
+ cwd,
109
+ stdio: "pipe",
110
+ reject: false,
111
+ });
43
112
 
44
- expect(result.stderr).not.toContain("Wasm bindings have not been set");
45
- expect(result.exitCode).toBe(0);
113
+ expect(result.stderr).not.toContain("Wasm bindings have not been set");
114
+ expect(result.exitCode).toBe(0);
115
+ } finally {
116
+ cleanFixture(cwd);
117
+ }
46
118
  },
47
119
  );
48
120
  });
@@ -0,0 +1,8 @@
1
+ [toolchain]
2
+ moc = "1.3.0"
3
+
4
+ [moc]
5
+ args = ["--default-persistent-actors"]
6
+
7
+ [canisters.backend]
8
+ main = "src/backend/main.mo"
@@ -0,0 +1,5 @@
1
+ actor {
2
+ public func hello() : async Text {
3
+ "Hello, World!";
4
+ };
5
+ };
@@ -54,6 +54,17 @@ describe("check", () => {
54
54
  await cliSnapshot(["check"], { cwd }, 0);
55
55
  });
56
56
 
57
+ test("canister entrypoint resolved relative to config root when run from subdirectory", async () => {
58
+ const fixtureRoot = path.join(
59
+ import.meta.dirname,
60
+ "check/canisters-subdir",
61
+ );
62
+ const subdir = path.join(fixtureRoot, "src/backend");
63
+ const result = await cli(["check"], { cwd: subdir });
64
+ expect(result.exitCode).toBe(0);
65
+ expect(result.stdout).toMatch(/✓/);
66
+ });
67
+
57
68
  test("[moc] args applied when using canister fallback", async () => {
58
69
  const cwd = path.join(import.meta.dirname, "check/canisters-moc-args");
59
70
  const result = await cli(["check"], { cwd });
@@ -0,0 +1,3 @@
1
+ [toolchain]
2
+ moc = "1.3.0"
3
+ pocket-ic = "12.0.0"
@@ -0,0 +1,3 @@
1
+ persistent actor {
2
+ public func runTests() : async () {};
3
+ };
@@ -0,0 +1,19 @@
1
+ import { describe, test, expect } from "@jest/globals";
2
+ import path from "path";
3
+ import { cli } from "./helpers";
4
+
5
+ describe("pocket-ic", () => {
6
+ test("runs tests with pocket-ic 12.0.0", async () => {
7
+ const cwd = path.join(import.meta.dirname, "pocket-ic");
8
+ const result = await cli(
9
+ ["test", "--reporter", "verbose", "--replica", "pocket-ic"],
10
+ { cwd },
11
+ );
12
+
13
+ expect(result.stderr).not.toContain("is not supported");
14
+ expect(result.stderr).not.toContain(
15
+ "only supports pocket-ic 9.x.x and 4.0.0",
16
+ );
17
+ expect(result.exitCode).toBe(0);
18
+ });
19
+ });
Binary file
@@ -1,8 +1,8 @@
1
1
  /* tslint:disable */
2
2
  /* eslint-disable */
3
3
  export const memory: WebAssembly.Memory;
4
- export const is_candid_compatible: (a: number, b: number, c: number, d: number) => number;
5
4
  export const add_custom_sections: (a: number, b: number, c: any) => [number, number, number, number];
5
+ export const is_candid_compatible: (a: number, b: number, c: number, d: number) => number;
6
6
  export const __wbindgen_malloc: (a: number, b: number) => number;
7
7
  export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
8
8
  export const __wbindgen_exn_store: (a: number) => void;
@@ -9,8 +9,8 @@ export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembl
9
9
 
10
10
  export interface InitOutput {
11
11
  readonly memory: WebAssembly.Memory;
12
- readonly is_candid_compatible: (a: number, b: number, c: number, d: number) => number;
13
12
  readonly add_custom_sections: (a: number, b: number, c: any) => [number, number, number, number];
13
+ readonly is_candid_compatible: (a: number, b: number, c: number, d: number) => number;
14
14
  readonly __wbindgen_malloc: (a: number, b: number) => number;
15
15
  readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
16
16
  readonly __wbindgen_exn_store: (a: number) => void;
Binary file
@@ -1,8 +1,8 @@
1
1
  /* tslint:disable */
2
2
  /* eslint-disable */
3
3
  export const memory: WebAssembly.Memory;
4
- export const is_candid_compatible: (a: number, b: number, c: number, d: number) => number;
5
4
  export const add_custom_sections: (a: number, b: number, c: any) => [number, number, number, number];
5
+ export const is_candid_compatible: (a: number, b: number, c: number, d: number) => number;
6
6
  export const __wbindgen_malloc: (a: number, b: number) => number;
7
7
  export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
8
8
  export const __wbindgen_exn_store: (a: number) => void;