ic-mops 2.3.2 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/RELEASE.md +13 -118
- package/api/network.ts +11 -3
- package/bundle/cli.tgz +0 -0
- package/cli.ts +2 -5
- package/commands/bench-replica.ts +13 -34
- package/commands/build.ts +62 -19
- package/commands/replica.ts +17 -42
- package/dist/api/network.js +10 -3
- package/dist/cli.js +3 -2
- package/dist/commands/bench-replica.d.ts +3 -4
- package/dist/commands/bench-replica.js +5 -23
- package/dist/commands/build.js +39 -15
- package/dist/commands/replica.d.ts +3 -4
- package/dist/commands/replica.js +9 -29
- package/dist/environments/web/cli.js +9 -0
- package/dist/helpers/pocket-ic-client.d.ts +9 -0
- package/dist/helpers/pocket-ic-client.js +18 -0
- package/dist/package.json +1 -1
- package/dist/parallel.js +9 -1
- package/dist/release-cli.js +6 -2
- package/dist/tests/build.test.js +86 -17
- package/dist/tests/pocket-ic.test.d.ts +1 -0
- package/dist/tests/pocket-ic.test.js +12 -0
- package/environments/web/cli.ts +12 -0
- package/helpers/pocket-ic-client.ts +32 -0
- package/package.json +3 -3
- package/parallel.ts +16 -5
- package/release-cli.ts +7 -2
- package/tests/__snapshots__/build.test.ts.snap +12 -0
- package/tests/build/custom-output/dfx.json +8 -0
- package/tests/build/custom-output/mops.toml +8 -0
- package/tests/build/custom-output/src/Main.mo +5 -0
- package/tests/build.test.ts +96 -21
- package/tests/pocket-ic/mops.toml +3 -0
- package/tests/pocket-ic/test/hello.test.mo +3 -0
- package/tests/pocket-ic.test.ts +19 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
## Next
|
|
4
4
|
|
|
5
|
+
## 2.5.0
|
|
6
|
+
- Add support for `MOPS_REGISTRY_HOST` and `MOPS_REGISTRY_CANISTER_ID` environment variables for custom registry endpoints
|
|
7
|
+
- Fix `mops build` crashing with `__wbindgen_malloc` error in bundled CLI distribution
|
|
8
|
+
- Fix `parallel()` swallowing errors from concurrent tasks (e.g. `mops publish` uploads), which could hang or leave failures unreported
|
|
9
|
+
|
|
10
|
+
## 2.4.0
|
|
11
|
+
- Support `[build].outputDir` config in `mops.toml` for custom build output directory
|
|
12
|
+
- Fix `mops build --output` CLI option being silently ignored
|
|
13
|
+
- Warn when canister `args` contain flags managed by `mops build` (e.g. `-o`, `-c`, `--idl`)
|
|
14
|
+
- Support pocket-ic versions beyond 9.x.x (fixes #410)
|
|
15
|
+
|
|
5
16
|
## 2.3.2
|
|
6
17
|
- Fix `mops check`, `mops build`, and `mops check-stable` failing to find canister entrypoints when run from a subdirectory
|
|
7
18
|
|
package/RELEASE.md
CHANGED
|
@@ -1,20 +1,8 @@
|
|
|
1
1
|
# Mops CLI Release
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 1. Update changelog
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Docker (or OrbStack) must be installed and running. The on-chain release step builds the CLI inside a Docker container (`zenvoich/mops-builder:1.1.0`) for reproducibility.
|
|
8
|
-
|
|
9
|
-
### dfx
|
|
10
|
-
|
|
11
|
-
`dfx` must be installed with the `mops` identity configured (see [Adding the `mops` identity to dfx](#adding-the-mops-identity-to-dfx)).
|
|
12
|
-
|
|
13
|
-
## Release Steps
|
|
14
|
-
|
|
15
|
-
### 1. Update changelog
|
|
16
|
-
|
|
17
|
-
Move items from the `## Next` section in `CHANGELOG.md` into a new version heading:
|
|
5
|
+
Move items from `## Next` in `CHANGELOG.md` into a new version heading:
|
|
18
6
|
|
|
19
7
|
```markdown
|
|
20
8
|
## Next
|
|
@@ -24,16 +12,16 @@ Move items from the `## Next` section in `CHANGELOG.md` into a new version headi
|
|
|
24
12
|
- Change 2
|
|
25
13
|
```
|
|
26
14
|
|
|
27
|
-
The heading must
|
|
15
|
+
The heading must match the exact version string — the release workflow parses it to extract release notes.
|
|
28
16
|
|
|
29
|
-
|
|
17
|
+
## 2. Bump version
|
|
30
18
|
|
|
31
19
|
```bash
|
|
32
20
|
cd cli
|
|
33
|
-
npm version
|
|
21
|
+
npm version patch --no-git-tag-version # or: minor / major
|
|
34
22
|
```
|
|
35
23
|
|
|
36
|
-
|
|
24
|
+
## 3. Create a release PR
|
|
37
25
|
|
|
38
26
|
```bash
|
|
39
27
|
git checkout -b <username>/release-X.Y.Z
|
|
@@ -43,11 +31,9 @@ git push -u origin <username>/release-X.Y.Z
|
|
|
43
31
|
gh pr create --title "release: CLI vX.Y.Z" --body "..."
|
|
44
32
|
```
|
|
45
33
|
|
|
46
|
-
Wait for CI to pass, then merge
|
|
47
|
-
|
|
48
|
-
### 4. Tag and push
|
|
34
|
+
Wait for CI to pass, then merge.
|
|
49
35
|
|
|
50
|
-
|
|
36
|
+
## 4. Tag and push
|
|
51
37
|
|
|
52
38
|
```bash
|
|
53
39
|
git checkout main && git pull
|
|
@@ -55,111 +41,20 @@ git tag cli-vX.Y.Z
|
|
|
55
41
|
git push origin cli-vX.Y.Z
|
|
56
42
|
```
|
|
57
43
|
|
|
58
|
-
This triggers the [`release.yml`](../.github/workflows/release.yml) workflow which
|
|
59
|
-
1. Validates the tag is on `main` and version matches `package.json`
|
|
60
|
-
2. Builds the CLI tarball in Docker (reproducible build)
|
|
61
|
-
3. Computes and reports the SHA256 hash (visible in the workflow Step Summary)
|
|
62
|
-
4. Publishes to npm via OIDC trusted publishing
|
|
63
|
-
5. Creates a GitHub Release with the tarball attached and changelog as release notes
|
|
64
|
-
|
|
65
|
-
Monitor the workflow run at [Actions → Release CLI](https://github.com/caffeinelabs/mops/actions/workflows/release.yml).
|
|
66
|
-
|
|
67
|
-
### 5. Prepare on-chain release
|
|
68
|
-
|
|
69
|
-
Run from the **repo root** (not `cli/`), with Docker running:
|
|
70
|
-
|
|
71
|
-
```bash
|
|
72
|
-
npm run release-cli
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
This runs `cli/release-cli.ts`, which:
|
|
76
|
-
1. Calls `./build.sh` — full Docker build with the real version from `cli/package.json`
|
|
77
|
-
2. Extracts release notes from `CHANGELOG.md` for that version
|
|
78
|
-
3. Computes SHA256 of `bundle/cli.tgz`
|
|
79
|
-
4. Copies the tarball to `cli-releases/versions/<version>.tgz`
|
|
80
|
-
5. Creates tag copies: `latest.tgz` and `<major>.tgz`
|
|
81
|
-
6. Updates `cli-releases/tags/latest` to the new version
|
|
82
|
-
7. Updates `cli-releases/releases.json` with metadata (timestamp, size, hash, commit hash, download URL, release notes)
|
|
83
|
-
|
|
84
|
-
### 6. Deploy the canister
|
|
44
|
+
This triggers the [`release.yml`](../.github/workflows/release.yml) workflow which builds, publishes to npm, creates a GitHub Release, deploys canisters (`cli.mops.one` and `docs.mops.one`), and opens a PR with on-chain release artifacts.
|
|
85
45
|
|
|
86
|
-
|
|
87
|
-
dfx deploy --network ic --no-wallet cli --identity mops
|
|
88
|
-
```
|
|
46
|
+
Monitor at [Actions → Release CLI](https://github.com/caffeinelabs/mops/actions/workflows/release.yml).
|
|
89
47
|
|
|
90
|
-
|
|
48
|
+
## 5. Merge artifacts PR
|
|
91
49
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
```bash
|
|
95
|
-
dfx deploy --network ic --no-wallet docs --identity mops
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
This builds the Docusaurus site (`docs/`) and deploys the `docs` assets canister (serving `docs.mops.one`). Docs are not auto-deployed, so this step ensures any documentation changes from the release are published.
|
|
99
|
-
|
|
100
|
-
### 8. Commit and push release artifacts
|
|
101
|
-
|
|
102
|
-
Step 5 generates files in `cli-releases/` that must be committed and pushed:
|
|
103
|
-
|
|
104
|
-
```bash
|
|
105
|
-
git add cli-releases/
|
|
106
|
-
git commit -m "cli-releases: v<version> artifacts"
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
Since direct pushes to `main` are not allowed, create a branch and PR:
|
|
110
|
-
|
|
111
|
-
```bash
|
|
112
|
-
git checkout -b <username>/release-X.Y.Z-artifacts
|
|
113
|
-
git push -u origin <username>/release-X.Y.Z-artifacts
|
|
114
|
-
gh pr create --title "cli-releases: vX.Y.Z artifacts" --body "Release artifacts generated by \`npm run release-cli\` for CLI vX.Y.Z."
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
Merge this PR after approval.
|
|
50
|
+
After the workflow completes, merge the `cli-releases: vX.Y.Z artifacts` PR.
|
|
118
51
|
|
|
119
52
|
## Verify build
|
|
120
53
|
|
|
121
|
-
Anyone can verify a released version by rebuilding from source.
|
|
54
|
+
Anyone can verify a released version by rebuilding from source. Instructions are included in each [GitHub Release](https://github.com/caffeinelabs/mops/releases).
|
|
122
55
|
|
|
123
56
|
```bash
|
|
124
57
|
cd cli
|
|
125
58
|
docker build . --build-arg COMMIT_HASH=<commit_hash> --build-arg MOPS_VERSION=<mops_version> -t mops
|
|
126
59
|
docker run --rm --env SHASUM=<build_hash> mops
|
|
127
60
|
```
|
|
128
|
-
|
|
129
|
-
## Adding the `mops` identity to dfx
|
|
130
|
-
|
|
131
|
-
Check if the identity already exists:
|
|
132
|
-
```bash
|
|
133
|
-
dfx identity list
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
If `mops` appears, verify it's the correct one:
|
|
137
|
-
```bash
|
|
138
|
-
dfx identity get-principal --identity mops
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
If it doesn't exist, import it from the PEM file stored in Bitwarden (`Mops identity (canisters and packages)`):
|
|
142
|
-
|
|
143
|
-
1. Save the PEM key to a temporary file:
|
|
144
|
-
```bash
|
|
145
|
-
cat > /tmp/mops-identity.pem << 'EOF'
|
|
146
|
-
-----BEGIN EC PRIVATE KEY-----
|
|
147
|
-
<paste key from Bitwarden>
|
|
148
|
-
-----END EC PRIVATE KEY-----
|
|
149
|
-
EOF
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
2. Import into dfx:
|
|
153
|
-
```bash
|
|
154
|
-
dfx identity import mops /tmp/mops-identity.pem
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
3. Delete the temporary file:
|
|
158
|
-
```bash
|
|
159
|
-
rm /tmp/mops-identity.pem
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
4. Verify:
|
|
163
|
-
```bash
|
|
164
|
-
dfx identity get-principal --identity mops
|
|
165
|
-
```
|
package/api/network.ts
CHANGED
|
@@ -3,20 +3,28 @@ export function getNetwork() {
|
|
|
3
3
|
}
|
|
4
4
|
|
|
5
5
|
export function getEndpoint(network: string) {
|
|
6
|
+
let endpoint: { host: string; canisterId: string };
|
|
6
7
|
if (network === "staging") {
|
|
7
|
-
|
|
8
|
+
endpoint = {
|
|
8
9
|
host: "https://icp-api.io",
|
|
9
10
|
canisterId: "2d2zu-vaaaa-aaaak-qb6pq-cai",
|
|
10
11
|
};
|
|
11
12
|
} else if (network === "ic") {
|
|
12
|
-
|
|
13
|
+
endpoint = {
|
|
13
14
|
host: "https://icp-api.io",
|
|
14
15
|
canisterId: "oknww-riaaa-aaaam-qaf6a-cai",
|
|
15
16
|
};
|
|
16
17
|
} else {
|
|
17
|
-
|
|
18
|
+
endpoint = {
|
|
18
19
|
host: "http://127.0.0.1:4943",
|
|
19
20
|
canisterId: "2d2zu-vaaaa-aaaak-qb6pq-cai",
|
|
20
21
|
};
|
|
21
22
|
}
|
|
23
|
+
|
|
24
|
+
const hostOverride = process.env["MOPS_REGISTRY_HOST"]?.trim();
|
|
25
|
+
const canisterOverride = process.env["MOPS_REGISTRY_CANISTER_ID"]?.trim();
|
|
26
|
+
return {
|
|
27
|
+
host: hostOverride || endpoint.host,
|
|
28
|
+
canisterId: canisterOverride || endpoint.canisterId,
|
|
29
|
+
};
|
|
22
30
|
}
|
package/bundle/cli.tgz
CHANGED
|
Binary file
|
package/cli.ts
CHANGED
|
@@ -301,11 +301,7 @@ program
|
|
|
301
301
|
.command("build [canisters...]")
|
|
302
302
|
.description("Build a canister")
|
|
303
303
|
.addOption(new Option("--verbose", "Verbose console output"))
|
|
304
|
-
.addOption(
|
|
305
|
-
new Option("--output, -o <output>", "Output directory").default(
|
|
306
|
-
DEFAULT_BUILD_OUTPUT_DIR,
|
|
307
|
-
),
|
|
308
|
-
)
|
|
304
|
+
.addOption(new Option("--output, -o <output>", "Output directory"))
|
|
309
305
|
.allowUnknownOption(true) // TODO: restrict unknown before "--"
|
|
310
306
|
.action(async (canisters, options) => {
|
|
311
307
|
checkConfigFile(true);
|
|
@@ -317,6 +313,7 @@ program
|
|
|
317
313
|
});
|
|
318
314
|
await build(args.length ? args : undefined, {
|
|
319
315
|
...options,
|
|
316
|
+
outputDir: options.output,
|
|
320
317
|
extraArgs,
|
|
321
318
|
});
|
|
322
319
|
});
|
|
@@ -3,12 +3,13 @@ import { execSync } from "node:child_process";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
import { execaCommand } from "execa";
|
|
6
|
-
import {
|
|
6
|
+
import { getRootDir } from "../mops.js";
|
|
7
7
|
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
type AnyPocketIcServer,
|
|
9
|
+
type AnyPocketIc,
|
|
10
|
+
type AnySetupCanister,
|
|
11
|
+
startPocketIc,
|
|
12
|
+
} from "../helpers/pocket-ic-client.js";
|
|
12
13
|
import { createActor, idlFactory } from "../declarations/bench/index.js";
|
|
13
14
|
import { toolchain } from "./toolchain/index.js";
|
|
14
15
|
import { getDfxVersion } from "../helpers/get-dfx-version.js";
|
|
@@ -18,8 +19,8 @@ export class BenchReplica {
|
|
|
18
19
|
verbose = false;
|
|
19
20
|
canisters: Record<string, { cwd: string; canisterId: string; actor: any }> =
|
|
20
21
|
{};
|
|
21
|
-
pocketIcServer?:
|
|
22
|
-
pocketIc?:
|
|
22
|
+
pocketIcServer?: AnyPocketIcServer;
|
|
23
|
+
pocketIc?: AnyPocketIc;
|
|
23
24
|
|
|
24
25
|
constructor(type: "dfx" | "pocket-ic" | "dfx-pocket-ic", verbose = false) {
|
|
25
26
|
this.type = type;
|
|
@@ -49,30 +50,10 @@ export class BenchReplica {
|
|
|
49
50
|
);
|
|
50
51
|
} else {
|
|
51
52
|
let pocketIcBin = await toolchain.bin("pocket-ic");
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
) {
|
|
57
|
-
console.error(
|
|
58
|
-
"Current Mops CLI only supports pocket-ic 9.x.x and 4.0.0",
|
|
59
|
-
);
|
|
60
|
-
process.exit(1);
|
|
61
|
-
}
|
|
62
|
-
// pocket-ic 9.x.x
|
|
63
|
-
if (config.toolchain?.["pocket-ic"]?.startsWith("9.")) {
|
|
64
|
-
this.pocketIcServer = await PocketIcServerMops.start({
|
|
65
|
-
binPath: pocketIcBin,
|
|
66
|
-
});
|
|
67
|
-
this.pocketIc = await PocketIcMops.create(this.pocketIcServer.getUrl());
|
|
68
|
-
}
|
|
69
|
-
// pocket-ic 4.0.0
|
|
70
|
-
else {
|
|
71
|
-
this.pocketIcServer = await PocketIcServer.start({
|
|
72
|
-
binPath: pocketIcBin,
|
|
73
|
-
});
|
|
74
|
-
this.pocketIc = await PocketIc.create(this.pocketIcServer.getUrl());
|
|
75
|
-
}
|
|
53
|
+
|
|
54
|
+
let pic = await startPocketIc({ binPath: pocketIcBin });
|
|
55
|
+
this.pocketIcServer = pic.server;
|
|
56
|
+
this.pocketIc = pic.client;
|
|
76
57
|
}
|
|
77
58
|
}
|
|
78
59
|
|
|
@@ -105,10 +86,8 @@ export class BenchReplica {
|
|
|
105
86
|
});
|
|
106
87
|
this.canisters[name] = { cwd, canisterId, actor };
|
|
107
88
|
} else if (this.pocketIc) {
|
|
108
|
-
type PocketIcSetupCanister = PocketIcMops["setupCanister"] &
|
|
109
|
-
PocketIc["setupCanister"];
|
|
110
89
|
let { canisterId, actor } = await (
|
|
111
|
-
this.pocketIc.setupCanister as
|
|
90
|
+
this.pocketIc.setupCanister as AnySetupCanister
|
|
112
91
|
)({ idlFactory, wasm });
|
|
113
92
|
this.canisters[name] = {
|
|
114
93
|
cwd,
|
package/commands/build.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { join } from "node:path";
|
|
|
6
6
|
import { cliError } from "../error.js";
|
|
7
7
|
import { isCandidCompatible } from "../helpers/is-candid-compatible.js";
|
|
8
8
|
import { resolveCanisterConfigs } from "../helpers/resolve-canisters.js";
|
|
9
|
+
import { CanisterConfig, Config } from "../types.js";
|
|
9
10
|
import { CustomSection, getWasmBindings } from "../wasm.js";
|
|
10
11
|
import { getGlobalMocArgs, readConfig, resolveConfigPath } from "../mops.js";
|
|
11
12
|
import { sourcesArgs } from "./sources.js";
|
|
@@ -27,9 +28,13 @@ export async function build(
|
|
|
27
28
|
cliError("No canisters specified to build");
|
|
28
29
|
}
|
|
29
30
|
|
|
30
|
-
let outputDir = options.outputDir ?? DEFAULT_BUILD_OUTPUT_DIR;
|
|
31
|
-
let mocPath = await toolchain.bin("moc", { fallback: true });
|
|
32
31
|
let config = readConfig();
|
|
32
|
+
let configOutputDir = config.build?.outputDir
|
|
33
|
+
? resolveConfigPath(config.build.outputDir)
|
|
34
|
+
: undefined;
|
|
35
|
+
let outputDir =
|
|
36
|
+
options.outputDir ?? configOutputDir ?? DEFAULT_BUILD_OUTPUT_DIR;
|
|
37
|
+
let mocPath = await toolchain.bin("moc", { fallback: true });
|
|
33
38
|
let canisters = resolveCanisterConfigs(config);
|
|
34
39
|
if (!Object.keys(canisters).length) {
|
|
35
40
|
cliError(`No Motoko canisters found in mops.toml configuration`);
|
|
@@ -78,23 +83,10 @@ export async function build(
|
|
|
78
83
|
...(await sourcesArgs()).flat(),
|
|
79
84
|
...getGlobalMocArgs(config),
|
|
80
85
|
];
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
);
|
|
86
|
-
}
|
|
87
|
-
args.push(...config.build.args);
|
|
88
|
-
}
|
|
89
|
-
if (canister.args) {
|
|
90
|
-
if (typeof canister.args === "string") {
|
|
91
|
-
cliError(
|
|
92
|
-
`Canister config 'args' should be an array of strings for canister ${canisterName}`,
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
args.push(...canister.args);
|
|
96
|
-
}
|
|
97
|
-
args.push(...(options.extraArgs ?? []));
|
|
86
|
+
args.push(
|
|
87
|
+
...collectExtraArgs(config, canister, canisterName, options.extraArgs),
|
|
88
|
+
);
|
|
89
|
+
|
|
98
90
|
const isPublicCandid = true; // always true for now to reduce corner cases
|
|
99
91
|
const candidVisibility = isPublicCandid ? "icp:public" : "icp:private";
|
|
100
92
|
if (isPublicCandid) {
|
|
@@ -196,3 +188,54 @@ export async function build(
|
|
|
196
188
|
),
|
|
197
189
|
);
|
|
198
190
|
}
|
|
191
|
+
|
|
192
|
+
const managedFlags: Record<string, string> = {
|
|
193
|
+
"-o": "use [build].outputDir in mops.toml or --output flag instead",
|
|
194
|
+
"-c": "this flag is always set by mops build",
|
|
195
|
+
"--idl": "this flag is always set by mops build",
|
|
196
|
+
"--public-metadata": "this flag is managed by mops build",
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
function collectExtraArgs(
|
|
200
|
+
config: Config,
|
|
201
|
+
canister: CanisterConfig,
|
|
202
|
+
canisterName: string,
|
|
203
|
+
extraArgs?: string[],
|
|
204
|
+
): string[] {
|
|
205
|
+
const args: string[] = [];
|
|
206
|
+
|
|
207
|
+
if (config.build?.args) {
|
|
208
|
+
if (typeof config.build.args === "string") {
|
|
209
|
+
cliError(
|
|
210
|
+
`[build] config 'args' should be an array of strings in mops.toml config file`,
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
args.push(...config.build.args);
|
|
214
|
+
}
|
|
215
|
+
if (canister.args) {
|
|
216
|
+
if (typeof canister.args === "string") {
|
|
217
|
+
cliError(
|
|
218
|
+
`Canister config 'args' should be an array of strings for canister ${canisterName}`,
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
args.push(...canister.args);
|
|
222
|
+
}
|
|
223
|
+
if (extraArgs) {
|
|
224
|
+
args.push(...extraArgs);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const warned = new Set<string>();
|
|
228
|
+
for (const arg of args) {
|
|
229
|
+
const hint = managedFlags[arg];
|
|
230
|
+
if (hint && !warned.has(arg)) {
|
|
231
|
+
warned.add(arg);
|
|
232
|
+
console.warn(
|
|
233
|
+
chalk.yellow(
|
|
234
|
+
`Warning: '${arg}' in args for canister ${canisterName} may conflict with mops build — ${hint}`,
|
|
235
|
+
),
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return args;
|
|
241
|
+
}
|
package/commands/replica.ts
CHANGED
|
@@ -11,14 +11,14 @@ import { spawn as spawnAsync } from "promisify-child-process";
|
|
|
11
11
|
|
|
12
12
|
import { IDL } from "@icp-sdk/core/candid";
|
|
13
13
|
import { Actor, HttpAgent } from "@icp-sdk/core/agent";
|
|
14
|
-
import { PocketIc, PocketIcServer } from "pic-ic";
|
|
15
|
-
import {
|
|
16
|
-
PocketIc as PocketIcMops,
|
|
17
|
-
PocketIcServer as PocketIcServerMops,
|
|
18
|
-
} from "pic-js-mops";
|
|
19
14
|
import chalk from "chalk";
|
|
20
15
|
|
|
21
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
type AnyPocketIcServer,
|
|
18
|
+
type AnyPocketIc,
|
|
19
|
+
type AnySetupCanister,
|
|
20
|
+
startPocketIc,
|
|
21
|
+
} from "../helpers/pocket-ic-client.js";
|
|
22
22
|
import { toolchain } from "./toolchain/index.js";
|
|
23
23
|
import { getDfxVersion } from "../helpers/get-dfx-version.js";
|
|
24
24
|
|
|
@@ -36,8 +36,8 @@ export class Replica {
|
|
|
36
36
|
string,
|
|
37
37
|
{ cwd: string; canisterId: string; actor: any; stream: PassThrough }
|
|
38
38
|
> = {};
|
|
39
|
-
pocketIcServer?:
|
|
40
|
-
pocketIc?:
|
|
39
|
+
pocketIcServer?: AnyPocketIcServer;
|
|
40
|
+
pocketIc?: AnyPocketIc;
|
|
41
41
|
dfxProcess?: ChildProcessWithoutNullStreams;
|
|
42
42
|
dir: string = ""; // absolute path (/.../.mops/.test/)
|
|
43
43
|
ttl = 60;
|
|
@@ -114,37 +114,14 @@ export class Replica {
|
|
|
114
114
|
} else {
|
|
115
115
|
let pocketIcBin = await toolchain.bin("pocket-ic");
|
|
116
116
|
|
|
117
|
-
let
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
process.exit(1);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// pocket-ic 9.x.x
|
|
129
|
-
if (config.toolchain?.["pocket-ic"]?.startsWith("9.")) {
|
|
130
|
-
this.pocketIcServer = await PocketIcServerMops.start({
|
|
131
|
-
showRuntimeLogs: false,
|
|
132
|
-
showCanisterLogs: false,
|
|
133
|
-
binPath: pocketIcBin,
|
|
134
|
-
ttl: this.ttl,
|
|
135
|
-
});
|
|
136
|
-
this.pocketIc = await PocketIcMops.create(this.pocketIcServer.getUrl());
|
|
137
|
-
}
|
|
138
|
-
// pocket-ic 4.0.0
|
|
139
|
-
else {
|
|
140
|
-
this.pocketIcServer = await PocketIcServer.start({
|
|
141
|
-
showRuntimeLogs: false,
|
|
142
|
-
showCanisterLogs: false,
|
|
143
|
-
binPath: pocketIcBin,
|
|
144
|
-
ttl: this.ttl,
|
|
145
|
-
});
|
|
146
|
-
this.pocketIc = await PocketIc.create(this.pocketIcServer.getUrl());
|
|
147
|
-
}
|
|
117
|
+
let pic = await startPocketIc({
|
|
118
|
+
binPath: pocketIcBin,
|
|
119
|
+
showRuntimeLogs: false,
|
|
120
|
+
showCanisterLogs: false,
|
|
121
|
+
ttl: this.ttl,
|
|
122
|
+
});
|
|
123
|
+
this.pocketIcServer = pic.server;
|
|
124
|
+
this.pocketIc = pic.client;
|
|
148
125
|
|
|
149
126
|
// process canister logs
|
|
150
127
|
this._attachCanisterLogHandler(
|
|
@@ -305,10 +282,8 @@ export class Replica {
|
|
|
305
282
|
stream: new PassThrough(),
|
|
306
283
|
};
|
|
307
284
|
} else if (this.pocketIc) {
|
|
308
|
-
type PocketIcSetupCanister = PocketIcMops["setupCanister"] &
|
|
309
|
-
PocketIc["setupCanister"];
|
|
310
285
|
let { canisterId, actor } = await (
|
|
311
|
-
this.pocketIc.setupCanister as
|
|
286
|
+
this.pocketIc.setupCanister as AnySetupCanister
|
|
312
287
|
)({
|
|
313
288
|
wasm,
|
|
314
289
|
idlFactory,
|
package/dist/api/network.js
CHANGED
|
@@ -2,22 +2,29 @@ export function getNetwork() {
|
|
|
2
2
|
return globalThis.MOPS_NETWORK || "ic";
|
|
3
3
|
}
|
|
4
4
|
export function getEndpoint(network) {
|
|
5
|
+
let endpoint;
|
|
5
6
|
if (network === "staging") {
|
|
6
|
-
|
|
7
|
+
endpoint = {
|
|
7
8
|
host: "https://icp-api.io",
|
|
8
9
|
canisterId: "2d2zu-vaaaa-aaaak-qb6pq-cai",
|
|
9
10
|
};
|
|
10
11
|
}
|
|
11
12
|
else if (network === "ic") {
|
|
12
|
-
|
|
13
|
+
endpoint = {
|
|
13
14
|
host: "https://icp-api.io",
|
|
14
15
|
canisterId: "oknww-riaaa-aaaam-qaf6a-cai",
|
|
15
16
|
};
|
|
16
17
|
}
|
|
17
18
|
else {
|
|
18
|
-
|
|
19
|
+
endpoint = {
|
|
19
20
|
host: "http://127.0.0.1:4943",
|
|
20
21
|
canisterId: "2d2zu-vaaaa-aaaak-qb6pq-cai",
|
|
21
22
|
};
|
|
22
23
|
}
|
|
24
|
+
const hostOverride = process.env["MOPS_REGISTRY_HOST"]?.trim();
|
|
25
|
+
const canisterOverride = process.env["MOPS_REGISTRY_CANISTER_ID"]?.trim();
|
|
26
|
+
return {
|
|
27
|
+
host: hostOverride || endpoint.host,
|
|
28
|
+
canisterId: canisterOverride || endpoint.canisterId,
|
|
29
|
+
};
|
|
23
30
|
}
|
package/dist/cli.js
CHANGED
|
@@ -7,7 +7,7 @@ import { getNetwork } from "./api/network.js";
|
|
|
7
7
|
import { cacheSize, cleanCache, show } from "./cache.js";
|
|
8
8
|
import { add } from "./commands/add.js";
|
|
9
9
|
import { bench } from "./commands/bench.js";
|
|
10
|
-
import { build
|
|
10
|
+
import { build } from "./commands/build.js";
|
|
11
11
|
import { bump } from "./commands/bump.js";
|
|
12
12
|
import { check } from "./commands/check.js";
|
|
13
13
|
import { checkCandid } from "./commands/check-candid.js";
|
|
@@ -236,7 +236,7 @@ program
|
|
|
236
236
|
.command("build [canisters...]")
|
|
237
237
|
.description("Build a canister")
|
|
238
238
|
.addOption(new Option("--verbose", "Verbose console output"))
|
|
239
|
-
.addOption(new Option("--output, -o <output>", "Output directory")
|
|
239
|
+
.addOption(new Option("--output, -o <output>", "Output directory"))
|
|
240
240
|
.allowUnknownOption(true) // TODO: restrict unknown before "--"
|
|
241
241
|
.action(async (canisters, options) => {
|
|
242
242
|
checkConfigFile(true);
|
|
@@ -248,6 +248,7 @@ program
|
|
|
248
248
|
});
|
|
249
249
|
await build(args.length ? args : undefined, {
|
|
250
250
|
...options,
|
|
251
|
+
outputDir: options.output,
|
|
251
252
|
extraArgs,
|
|
252
253
|
});
|
|
253
254
|
});
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { PocketIc as PocketIcMops, PocketIcServer as PocketIcServerMops } from "pic-js-mops";
|
|
1
|
+
import { type AnyPocketIcServer, type AnyPocketIc } from "../helpers/pocket-ic-client.js";
|
|
3
2
|
export declare class BenchReplica {
|
|
4
3
|
type: "dfx" | "pocket-ic" | "dfx-pocket-ic";
|
|
5
4
|
verbose: boolean;
|
|
@@ -8,8 +7,8 @@ export declare class BenchReplica {
|
|
|
8
7
|
canisterId: string;
|
|
9
8
|
actor: any;
|
|
10
9
|
}>;
|
|
11
|
-
pocketIcServer?:
|
|
12
|
-
pocketIc?:
|
|
10
|
+
pocketIcServer?: AnyPocketIcServer;
|
|
11
|
+
pocketIc?: AnyPocketIc;
|
|
13
12
|
constructor(type: "dfx" | "pocket-ic" | "dfx-pocket-ic", verbose?: boolean);
|
|
14
13
|
start({ silent }?: {
|
|
15
14
|
silent?: boolean | undefined;
|
|
@@ -3,9 +3,8 @@ import { execSync } from "node:child_process";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
import { execaCommand } from "execa";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { getRootDir, readConfig } from "../mops.js";
|
|
6
|
+
import { getRootDir } from "../mops.js";
|
|
7
|
+
import { startPocketIc, } from "../helpers/pocket-ic-client.js";
|
|
9
8
|
import { createActor, idlFactory } from "../declarations/bench/index.js";
|
|
10
9
|
import { toolchain } from "./toolchain/index.js";
|
|
11
10
|
import { getDfxVersion } from "../helpers/get-dfx-version.js";
|
|
@@ -36,26 +35,9 @@ export class BenchReplica {
|
|
|
36
35
|
}
|
|
37
36
|
else {
|
|
38
37
|
let pocketIcBin = await toolchain.bin("pocket-ic");
|
|
39
|
-
let
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
console.error("Current Mops CLI only supports pocket-ic 9.x.x and 4.0.0");
|
|
43
|
-
process.exit(1);
|
|
44
|
-
}
|
|
45
|
-
// pocket-ic 9.x.x
|
|
46
|
-
if (config.toolchain?.["pocket-ic"]?.startsWith("9.")) {
|
|
47
|
-
this.pocketIcServer = await PocketIcServerMops.start({
|
|
48
|
-
binPath: pocketIcBin,
|
|
49
|
-
});
|
|
50
|
-
this.pocketIc = await PocketIcMops.create(this.pocketIcServer.getUrl());
|
|
51
|
-
}
|
|
52
|
-
// pocket-ic 4.0.0
|
|
53
|
-
else {
|
|
54
|
-
this.pocketIcServer = await PocketIcServer.start({
|
|
55
|
-
binPath: pocketIcBin,
|
|
56
|
-
});
|
|
57
|
-
this.pocketIc = await PocketIc.create(this.pocketIcServer.getUrl());
|
|
58
|
-
}
|
|
38
|
+
let pic = await startPocketIc({ binPath: pocketIcBin });
|
|
39
|
+
this.pocketIcServer = pic.server;
|
|
40
|
+
this.pocketIc = pic.client;
|
|
59
41
|
}
|
|
60
42
|
}
|
|
61
43
|
async stop() {
|