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.
- package/CHANGELOG.md +9 -0
- package/RELEASE.md +16 -162
- package/bundle/cli.tgz +0 -0
- package/cli.ts +2 -5
- package/commands/bench-replica.ts +13 -34
- package/commands/build.ts +70 -24
- package/commands/check-stable.ts +2 -2
- package/commands/check.ts +9 -8
- package/commands/replica.ts +17 -42
- 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 +47 -20
- package/dist/commands/check-stable.js +2 -2
- package/dist/commands/check.js +9 -8
- package/dist/commands/replica.d.ts +3 -4
- package/dist/commands/replica.js +9 -29
- package/dist/helpers/pocket-ic-client.d.ts +9 -0
- package/dist/helpers/pocket-ic-client.js +18 -0
- package/dist/mops.d.ts +5 -0
- package/dist/mops.js +7 -0
- package/dist/package.json +1 -1
- package/dist/release-cli.js +6 -2
- package/dist/tests/build.test.js +83 -16
- package/dist/tests/check.test.js +7 -0
- package/dist/tests/pocket-ic.test.d.ts +1 -0
- package/dist/tests/pocket-ic.test.js +12 -0
- package/dist/wasm/pkg/nodejs/wasm_bg.wasm +0 -0
- package/dist/wasm/pkg/nodejs/wasm_bg.wasm.d.ts +1 -1
- package/dist/wasm/pkg/web/wasm.d.ts +1 -1
- package/dist/wasm/pkg/web/wasm_bg.wasm +0 -0
- package/dist/wasm/pkg/web/wasm_bg.wasm.d.ts +1 -1
- package/helpers/pocket-ic-client.ts +32 -0
- package/mops.ts +8 -0
- package/package.json +1 -1
- 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 +92 -20
- package/tests/check/canisters-subdir/mops.toml +8 -0
- package/tests/check/canisters-subdir/src/backend/main.mo +5 -0
- package/tests/check.test.ts +11 -0
- 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/wasm/pkg/nodejs/wasm_bg.wasm +0 -0
- package/wasm/pkg/nodejs/wasm_bg.wasm.d.ts +1 -1
- package/wasm/pkg/web/wasm.d.ts +1 -1
- package/wasm/pkg/web/wasm_bg.wasm +0 -0
- package/wasm/pkg/web/wasm_bg.wasm.d.ts +1 -1
|
@@ -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() {
|
package/dist/commands/build.js
CHANGED
|
@@ -7,7 +7,7 @@ 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
9
|
import { getWasmBindings } from "../wasm.js";
|
|
10
|
-
import { getGlobalMocArgs, readConfig } from "../mops.js";
|
|
10
|
+
import { getGlobalMocArgs, readConfig, resolveConfigPath } from "../mops.js";
|
|
11
11
|
import { sourcesArgs } from "./sources.js";
|
|
12
12
|
import { toolchain } from "./toolchain/index.js";
|
|
13
13
|
export const DEFAULT_BUILD_OUTPUT_DIR = ".mops/.build";
|
|
@@ -15,9 +15,12 @@ export async function build(canisterNames, options) {
|
|
|
15
15
|
if (canisterNames?.length == 0) {
|
|
16
16
|
cliError("No canisters specified to build");
|
|
17
17
|
}
|
|
18
|
-
let outputDir = options.outputDir ?? DEFAULT_BUILD_OUTPUT_DIR;
|
|
19
|
-
let mocPath = await toolchain.bin("moc", { fallback: true });
|
|
20
18
|
let config = readConfig();
|
|
19
|
+
let configOutputDir = config.build?.outputDir
|
|
20
|
+
? resolveConfigPath(config.build.outputDir)
|
|
21
|
+
: undefined;
|
|
22
|
+
let outputDir = options.outputDir ?? configOutputDir ?? DEFAULT_BUILD_OUTPUT_DIR;
|
|
23
|
+
let mocPath = await toolchain.bin("moc", { fallback: true });
|
|
21
24
|
let canisters = resolveCanisterConfigs(config);
|
|
22
25
|
if (!Object.keys(canisters).length) {
|
|
23
26
|
cliError(`No Motoko canisters found in mops.toml configuration`);
|
|
@@ -45,6 +48,7 @@ export async function build(canisterNames, options) {
|
|
|
45
48
|
if (!motokoPath) {
|
|
46
49
|
cliError(`No main file is specified for canister ${canisterName}`);
|
|
47
50
|
}
|
|
51
|
+
motokoPath = resolveConfigPath(motokoPath);
|
|
48
52
|
const wasmPath = join(outputDir, `${canisterName}.wasm`);
|
|
49
53
|
let args = [
|
|
50
54
|
"-c",
|
|
@@ -55,19 +59,7 @@ export async function build(canisterNames, options) {
|
|
|
55
59
|
...(await sourcesArgs()).flat(),
|
|
56
60
|
...getGlobalMocArgs(config),
|
|
57
61
|
];
|
|
58
|
-
|
|
59
|
-
if (typeof config.build.args === "string") {
|
|
60
|
-
cliError(`[build] config 'args' should be an array of strings in mops.toml config file`);
|
|
61
|
-
}
|
|
62
|
-
args.push(...config.build.args);
|
|
63
|
-
}
|
|
64
|
-
if (canister.args) {
|
|
65
|
-
if (typeof canister.args === "string") {
|
|
66
|
-
cliError(`Canister config 'args' should be an array of strings for canister ${canisterName}`);
|
|
67
|
-
}
|
|
68
|
-
args.push(...canister.args);
|
|
69
|
-
}
|
|
70
|
-
args.push(...(options.extraArgs ?? []));
|
|
62
|
+
args.push(...collectExtraArgs(config, canister, canisterName, options.extraArgs));
|
|
71
63
|
const isPublicCandid = true; // always true for now to reduce corner cases
|
|
72
64
|
const candidVisibility = isPublicCandid ? "icp:public" : "icp:private";
|
|
73
65
|
if (isPublicCandid) {
|
|
@@ -98,10 +90,12 @@ export async function build(canisterNames, options) {
|
|
|
98
90
|
console.log(result.stdout);
|
|
99
91
|
}
|
|
100
92
|
const generatedDidPath = join(outputDir, `${canisterName}.did`);
|
|
101
|
-
|
|
102
|
-
|
|
93
|
+
const resolvedCandidPath = canister.candid
|
|
94
|
+
? resolveConfigPath(canister.candid)
|
|
95
|
+
: null;
|
|
96
|
+
if (resolvedCandidPath) {
|
|
103
97
|
try {
|
|
104
|
-
const compatible = await isCandidCompatible(generatedDidPath,
|
|
98
|
+
const compatible = await isCandidCompatible(generatedDidPath, resolvedCandidPath);
|
|
105
99
|
if (!compatible) {
|
|
106
100
|
cliError(`Candid compatibility check failed for canister ${canisterName}`);
|
|
107
101
|
}
|
|
@@ -115,7 +109,7 @@ export async function build(canisterNames, options) {
|
|
|
115
109
|
}
|
|
116
110
|
options.verbose &&
|
|
117
111
|
console.log(chalk.gray(`Adding metadata to ${wasmPath}`));
|
|
118
|
-
const candidPath =
|
|
112
|
+
const candidPath = resolvedCandidPath ?? generatedDidPath;
|
|
119
113
|
const candidText = await readFile(candidPath, "utf-8");
|
|
120
114
|
const customSections = [
|
|
121
115
|
{ name: `${candidVisibility} candid:service`, data: candidText },
|
|
@@ -139,3 +133,36 @@ export async function build(canisterNames, options) {
|
|
|
139
133
|
}
|
|
140
134
|
console.log(chalk.green(`\n✓ Built ${Object.keys(filteredCanisters).length} canister${Object.keys(filteredCanisters).length == 1 ? "" : "s"} successfully`));
|
|
141
135
|
}
|
|
136
|
+
const managedFlags = {
|
|
137
|
+
"-o": "use [build].outputDir in mops.toml or --output flag instead",
|
|
138
|
+
"-c": "this flag is always set by mops build",
|
|
139
|
+
"--idl": "this flag is always set by mops build",
|
|
140
|
+
"--public-metadata": "this flag is managed by mops build",
|
|
141
|
+
};
|
|
142
|
+
function collectExtraArgs(config, canister, canisterName, extraArgs) {
|
|
143
|
+
const args = [];
|
|
144
|
+
if (config.build?.args) {
|
|
145
|
+
if (typeof config.build.args === "string") {
|
|
146
|
+
cliError(`[build] config 'args' should be an array of strings in mops.toml config file`);
|
|
147
|
+
}
|
|
148
|
+
args.push(...config.build.args);
|
|
149
|
+
}
|
|
150
|
+
if (canister.args) {
|
|
151
|
+
if (typeof canister.args === "string") {
|
|
152
|
+
cliError(`Canister config 'args' should be an array of strings for canister ${canisterName}`);
|
|
153
|
+
}
|
|
154
|
+
args.push(...canister.args);
|
|
155
|
+
}
|
|
156
|
+
if (extraArgs) {
|
|
157
|
+
args.push(...extraArgs);
|
|
158
|
+
}
|
|
159
|
+
const warned = new Set();
|
|
160
|
+
for (const arg of args) {
|
|
161
|
+
const hint = managedFlags[arg];
|
|
162
|
+
if (hint && !warned.has(arg)) {
|
|
163
|
+
warned.add(arg);
|
|
164
|
+
console.warn(chalk.yellow(`Warning: '${arg}' in args for canister ${canisterName} may conflict with mops build — ${hint}`));
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return args;
|
|
168
|
+
}
|
|
@@ -4,7 +4,7 @@ import { rename, rm } from "node:fs/promises";
|
|
|
4
4
|
import chalk from "chalk";
|
|
5
5
|
import { execa } from "execa";
|
|
6
6
|
import { cliError } from "../error.js";
|
|
7
|
-
import { getGlobalMocArgs, readConfig } from "../mops.js";
|
|
7
|
+
import { getGlobalMocArgs, readConfig, resolveConfigPath } from "../mops.js";
|
|
8
8
|
import { resolveSingleCanister } from "../helpers/resolve-canisters.js";
|
|
9
9
|
import { sourcesArgs } from "./sources.js";
|
|
10
10
|
import { toolchain } from "./toolchain/index.js";
|
|
@@ -19,7 +19,7 @@ export async function checkStable(oldFile, canisterName, options = {}) {
|
|
|
19
19
|
const globalMocArgs = getGlobalMocArgs(config);
|
|
20
20
|
await runStableCheck({
|
|
21
21
|
oldFile,
|
|
22
|
-
canisterMain: canister.main,
|
|
22
|
+
canisterMain: resolveConfigPath(canister.main),
|
|
23
23
|
canisterName: name,
|
|
24
24
|
mocPath,
|
|
25
25
|
globalMocArgs,
|
package/dist/commands/check.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import path from "node:path";
|
|
2
2
|
import { existsSync } from "node:fs";
|
|
3
3
|
import chalk from "chalk";
|
|
4
4
|
import { execa } from "execa";
|
|
5
5
|
import { cliError } from "../error.js";
|
|
6
|
-
import { getGlobalMocArgs, readConfig } from "../mops.js";
|
|
6
|
+
import { getGlobalMocArgs, readConfig, resolveConfigPath } from "../mops.js";
|
|
7
7
|
import { autofixMotoko } from "../helpers/autofix-motoko.js";
|
|
8
8
|
import { getMocSemVer } from "../helpers/get-moc-version.js";
|
|
9
9
|
import { resolveCanisterConfigs, resolveCanisterEntrypoints, } from "../helpers/resolve-canisters.js";
|
|
@@ -19,7 +19,7 @@ export async function check(files, options = {}) {
|
|
|
19
19
|
let fileList = Array.isArray(files) ? files : files ? [files] : [];
|
|
20
20
|
const config = readConfig();
|
|
21
21
|
if (fileList.length === 0) {
|
|
22
|
-
fileList = resolveCanisterEntrypoints(config);
|
|
22
|
+
fileList = resolveCanisterEntrypoints(config).map(resolveConfigPath);
|
|
23
23
|
}
|
|
24
24
|
if (fileList.length === 0) {
|
|
25
25
|
cliError("No Motoko files specified and no canisters defined in mops.toml.\n" +
|
|
@@ -55,7 +55,7 @@ export async function check(files, options = {}) {
|
|
|
55
55
|
for (const [file, codes] of fixResult.fixedFiles) {
|
|
56
56
|
const unique = [...new Set(codes)].sort();
|
|
57
57
|
const n = codes.length;
|
|
58
|
-
const rel = relative(process.cwd(), file);
|
|
58
|
+
const rel = path.relative(process.cwd(), file);
|
|
59
59
|
console.log(chalk.green(`Fixed ${rel} (${n} ${n === 1 ? "fix" : "fixes"}: ${unique.join(", ")})`));
|
|
60
60
|
}
|
|
61
61
|
const fileCount = fixResult.fixedFiles.size;
|
|
@@ -96,18 +96,19 @@ export async function check(files, options = {}) {
|
|
|
96
96
|
if (!canister.main) {
|
|
97
97
|
cliError(`No main file specified for canister '${name}' in mops.toml`);
|
|
98
98
|
}
|
|
99
|
-
|
|
99
|
+
const stablePath = resolveConfigPath(stableConfig.path);
|
|
100
|
+
if (!existsSync(stablePath)) {
|
|
100
101
|
if (stableConfig.skipIfMissing) {
|
|
101
102
|
continue;
|
|
102
103
|
}
|
|
103
|
-
cliError(`Deployed file not found: ${
|
|
104
|
+
cliError(`Deployed file not found: ${stablePath} (canister '${name}')\n` +
|
|
104
105
|
"Set skipIfMissing = true in [canisters." +
|
|
105
106
|
name +
|
|
106
107
|
".check-stable] to skip this check when the file is missing.");
|
|
107
108
|
}
|
|
108
109
|
await runStableCheck({
|
|
109
|
-
oldFile:
|
|
110
|
-
canisterMain: canister.main,
|
|
110
|
+
oldFile: stablePath,
|
|
111
|
+
canisterMain: resolveConfigPath(canister.main),
|
|
111
112
|
canisterName: name,
|
|
112
113
|
mocPath,
|
|
113
114
|
globalMocArgs,
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { ChildProcessWithoutNullStreams } from "node:child_process";
|
|
2
2
|
import { PassThrough } from "node:stream";
|
|
3
3
|
import { IDL } from "@icp-sdk/core/candid";
|
|
4
|
-
import {
|
|
5
|
-
import { PocketIc as PocketIcMops, PocketIcServer as PocketIcServerMops } from "pic-js-mops";
|
|
4
|
+
import { type AnyPocketIcServer, type AnyPocketIc } from "../helpers/pocket-ic-client.js";
|
|
6
5
|
type StartOptions = {
|
|
7
6
|
type?: "dfx" | "pocket-ic" | "dfx-pocket-ic";
|
|
8
7
|
dir?: string;
|
|
@@ -18,8 +17,8 @@ export declare class Replica {
|
|
|
18
17
|
actor: any;
|
|
19
18
|
stream: PassThrough;
|
|
20
19
|
}>;
|
|
21
|
-
pocketIcServer?:
|
|
22
|
-
pocketIc?:
|
|
20
|
+
pocketIcServer?: AnyPocketIcServer;
|
|
21
|
+
pocketIc?: AnyPocketIc;
|
|
23
22
|
dfxProcess?: ChildProcessWithoutNullStreams;
|
|
24
23
|
dir: string;
|
|
25
24
|
ttl: number;
|
package/dist/commands/replica.js
CHANGED
|
@@ -5,10 +5,8 @@ import fs from "node:fs";
|
|
|
5
5
|
import { PassThrough } from "node:stream";
|
|
6
6
|
import { spawn as spawnAsync } from "promisify-child-process";
|
|
7
7
|
import { Actor, HttpAgent } from "@icp-sdk/core/agent";
|
|
8
|
-
import { PocketIc, PocketIcServer } from "pic-ic";
|
|
9
|
-
import { PocketIc as PocketIcMops, PocketIcServer as PocketIcServerMops, } from "pic-js-mops";
|
|
10
8
|
import chalk from "chalk";
|
|
11
|
-
import {
|
|
9
|
+
import { startPocketIc, } from "../helpers/pocket-ic-client.js";
|
|
12
10
|
import { toolchain } from "./toolchain/index.js";
|
|
13
11
|
import { getDfxVersion } from "../helpers/get-dfx-version.js";
|
|
14
12
|
export class Replica {
|
|
@@ -74,32 +72,14 @@ export class Replica {
|
|
|
74
72
|
}
|
|
75
73
|
else {
|
|
76
74
|
let pocketIcBin = await toolchain.bin("pocket-ic");
|
|
77
|
-
let
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
this.pocketIcServer = await PocketIcServerMops.start({
|
|
86
|
-
showRuntimeLogs: false,
|
|
87
|
-
showCanisterLogs: false,
|
|
88
|
-
binPath: pocketIcBin,
|
|
89
|
-
ttl: this.ttl,
|
|
90
|
-
});
|
|
91
|
-
this.pocketIc = await PocketIcMops.create(this.pocketIcServer.getUrl());
|
|
92
|
-
}
|
|
93
|
-
// pocket-ic 4.0.0
|
|
94
|
-
else {
|
|
95
|
-
this.pocketIcServer = await PocketIcServer.start({
|
|
96
|
-
showRuntimeLogs: false,
|
|
97
|
-
showCanisterLogs: false,
|
|
98
|
-
binPath: pocketIcBin,
|
|
99
|
-
ttl: this.ttl,
|
|
100
|
-
});
|
|
101
|
-
this.pocketIc = await PocketIc.create(this.pocketIcServer.getUrl());
|
|
102
|
-
}
|
|
75
|
+
let pic = await startPocketIc({
|
|
76
|
+
binPath: pocketIcBin,
|
|
77
|
+
showRuntimeLogs: false,
|
|
78
|
+
showCanisterLogs: false,
|
|
79
|
+
ttl: this.ttl,
|
|
80
|
+
});
|
|
81
|
+
this.pocketIcServer = pic.server;
|
|
82
|
+
this.pocketIc = pic.client;
|
|
103
83
|
// process canister logs
|
|
104
84
|
this._attachCanisterLogHandler(this.pocketIcServer.serverProcess);
|
|
105
85
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { PocketIc, PocketIcServer } from "pic-ic";
|
|
2
|
+
import { PocketIc as PocketIcModern, PocketIcServer as PocketIcServerModern, type StartServerOptions } from "pic-js-mops";
|
|
3
|
+
export type AnyPocketIcServer = PocketIcServer | PocketIcServerModern;
|
|
4
|
+
export type AnyPocketIc = PocketIc | PocketIcModern;
|
|
5
|
+
export type AnySetupCanister = PocketIc["setupCanister"] & PocketIcModern["setupCanister"];
|
|
6
|
+
export declare function startPocketIc(options: StartServerOptions): Promise<{
|
|
7
|
+
server: AnyPocketIcServer;
|
|
8
|
+
client: AnyPocketIc;
|
|
9
|
+
}>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import semver from "semver";
|
|
2
|
+
import { PocketIc, PocketIcServer } from "pic-ic";
|
|
3
|
+
import { PocketIc as PocketIcModern, PocketIcServer as PocketIcServerModern, } from "pic-js-mops";
|
|
4
|
+
import { readConfig } from "../mops.js";
|
|
5
|
+
function isLegacy() {
|
|
6
|
+
let version = readConfig().toolchain?.["pocket-ic"];
|
|
7
|
+
return !!version && !!semver.valid(version) && semver.lt(version, "9.0.0");
|
|
8
|
+
}
|
|
9
|
+
export async function startPocketIc(options) {
|
|
10
|
+
if (isLegacy()) {
|
|
11
|
+
let server = await PocketIcServer.start(options);
|
|
12
|
+
let client = await PocketIc.create(server.getUrl());
|
|
13
|
+
return { server, client };
|
|
14
|
+
}
|
|
15
|
+
let server = await PocketIcServerModern.start(options);
|
|
16
|
+
let client = await PocketIcModern.create(server.getUrl());
|
|
17
|
+
return { server, client };
|
|
18
|
+
}
|
package/dist/mops.d.ts
CHANGED
|
@@ -11,6 +11,11 @@ export declare function setNetwork(network: string): void;
|
|
|
11
11
|
export declare let getIdentity: () => Promise<Identity | undefined>;
|
|
12
12
|
export declare function getClosestConfigFile(dir?: string): string;
|
|
13
13
|
export declare function getRootDir(): string;
|
|
14
|
+
/**
|
|
15
|
+
* Resolve a path from mops.toml config (relative to project root)
|
|
16
|
+
* into a path relative to the current working directory.
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolveConfigPath(configPath: string): string;
|
|
14
19
|
export declare function checkConfigFile(exit?: boolean): boolean;
|
|
15
20
|
export declare function progressBar(step: number, total: number): string;
|
|
16
21
|
export declare function parseGithubURL(href: string): {
|
package/dist/mops.js
CHANGED
|
@@ -87,6 +87,13 @@ export function getRootDir() {
|
|
|
87
87
|
}
|
|
88
88
|
return path.dirname(configFile);
|
|
89
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Resolve a path from mops.toml config (relative to project root)
|
|
92
|
+
* into a path relative to the current working directory.
|
|
93
|
+
*/
|
|
94
|
+
export function resolveConfigPath(configPath) {
|
|
95
|
+
return path.relative(process.cwd(), path.resolve(getRootDir(), configPath));
|
|
96
|
+
}
|
|
90
97
|
export function checkConfigFile(exit = false) {
|
|
91
98
|
let configFile = getClosestConfigFile();
|
|
92
99
|
if (!configFile) {
|
package/dist/package.json
CHANGED
package/dist/release-cli.js
CHANGED
|
@@ -8,8 +8,12 @@ import { sha256 } from "@noble/hashes/sha256";
|
|
|
8
8
|
import { bytesToHex } from "@noble/hashes/utils";
|
|
9
9
|
import { findChangelogEntry } from "./helpers/find-changelog-entry.js";
|
|
10
10
|
let __dirname = new URL(".", import.meta.url).pathname;
|
|
11
|
-
|
|
12
|
-
execSync("./build.sh", { stdio: "inherit", cwd: __dirname });
|
|
11
|
+
if (!process.env.SKIP_BUILD) {
|
|
12
|
+
execSync("./build.sh", { stdio: "inherit", cwd: __dirname });
|
|
13
|
+
}
|
|
14
|
+
else if (!fs.existsSync(path.resolve(__dirname, "bundle/cli.tgz"))) {
|
|
15
|
+
throw new Error("SKIP_BUILD is set but bundle/cli.tgz does not exist. Run build.sh first.");
|
|
16
|
+
}
|
|
13
17
|
let commitHash = process.env.COMMIT_HASH || execSync("git rev-parse HEAD").toString().trim();
|
|
14
18
|
let version = JSON.parse(fs.readFileSync(path.resolve(__dirname, "package.json"), "utf8")).version;
|
|
15
19
|
let major = semver.parse(version)?.major;
|
package/dist/tests/build.test.js
CHANGED
|
@@ -1,22 +1,84 @@
|
|
|
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
|
const distBin = path.resolve(import.meta.dirname, "../dist/bin/mops.js");
|
|
7
|
+
function cleanFixture(cwd, ...extras) {
|
|
8
|
+
rmSync(path.join(cwd, ".mops"), { recursive: true, force: true });
|
|
9
|
+
for (const p of extras) {
|
|
10
|
+
rmSync(p, { recursive: true, force: true });
|
|
11
|
+
}
|
|
12
|
+
}
|
|
7
13
|
describe("build", () => {
|
|
8
14
|
test("ok", async () => {
|
|
9
15
|
const cwd = path.join(import.meta.dirname, "build/success");
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
16
|
+
try {
|
|
17
|
+
await cliSnapshot(["build", "--verbose"], { cwd }, 0);
|
|
18
|
+
await cliSnapshot(["build", "foo"], { cwd }, 0);
|
|
19
|
+
await cliSnapshot(["build", "bar"], { cwd }, 0);
|
|
20
|
+
await cliSnapshot(["build", "foo", "bar"], { cwd }, 0);
|
|
21
|
+
}
|
|
22
|
+
finally {
|
|
23
|
+
cleanFixture(cwd);
|
|
24
|
+
}
|
|
14
25
|
});
|
|
15
26
|
test("error", async () => {
|
|
16
27
|
const cwd = path.join(import.meta.dirname, "build/error");
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
28
|
+
try {
|
|
29
|
+
await cliSnapshot(["build", "foo", "--verbose"], { cwd }, 0);
|
|
30
|
+
expect((await cliSnapshot(["build", "bar"], { cwd }, 1)).stderr).toMatch("Candid compatibility check failed for canister bar");
|
|
31
|
+
expect((await cliSnapshot(["build", "foo", "bar"], { cwd }, 1)).stderr).toMatch("Candid compatibility check failed for canister bar");
|
|
32
|
+
}
|
|
33
|
+
finally {
|
|
34
|
+
cleanFixture(cwd);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
// [build].outputDir in mops.toml should control where build output goes
|
|
38
|
+
test("custom output path via config outputDir", async () => {
|
|
39
|
+
const cwd = path.join(import.meta.dirname, "build/custom-output");
|
|
40
|
+
const customOut = path.join(cwd, "custom-out");
|
|
41
|
+
const customWasm = path.join(customOut, "main.wasm");
|
|
42
|
+
const customDid = path.join(customOut, "main.did");
|
|
43
|
+
const defaultDid = path.join(cwd, ".mops/.build/main.did");
|
|
44
|
+
try {
|
|
45
|
+
const result = await cli(["build"], { cwd });
|
|
46
|
+
expect(result.exitCode).toBe(0);
|
|
47
|
+
expect(existsSync(customWasm)).toBe(true);
|
|
48
|
+
expect(existsSync(customDid)).toBe(true);
|
|
49
|
+
expect(existsSync(defaultDid)).toBe(false);
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
cleanFixture(cwd, customOut);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
// Regression: --output CLI option was silently ignored due to
|
|
56
|
+
// Commander storing it as options.output while build() read options.outputDir
|
|
57
|
+
test("--output CLI option", async () => {
|
|
58
|
+
const cwd = path.join(import.meta.dirname, "build/success");
|
|
59
|
+
const outputDir = path.join(cwd, "cli-output-test");
|
|
60
|
+
try {
|
|
61
|
+
const result = await cli(["build", "foo", "--output", outputDir], {
|
|
62
|
+
cwd,
|
|
63
|
+
});
|
|
64
|
+
expect(result.exitCode).toBe(0);
|
|
65
|
+
expect(existsSync(path.join(outputDir, "foo.wasm"))).toBe(true);
|
|
66
|
+
expect(existsSync(path.join(outputDir, "foo.did"))).toBe(true);
|
|
67
|
+
}
|
|
68
|
+
finally {
|
|
69
|
+
cleanFixture(cwd, outputDir);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
test("warns when args contain managed flags", async () => {
|
|
73
|
+
const cwd = path.join(import.meta.dirname, "build/success");
|
|
74
|
+
const artifact = path.join(cwd, "x");
|
|
75
|
+
const artifactDid = path.join(cwd, "x.did");
|
|
76
|
+
try {
|
|
77
|
+
await cliSnapshot(["build", "foo", "--", "-o", "x", "-c", "--idl"], { cwd }, 1);
|
|
78
|
+
}
|
|
79
|
+
finally {
|
|
80
|
+
cleanFixture(cwd, artifact, artifactDid);
|
|
81
|
+
}
|
|
20
82
|
});
|
|
21
83
|
// Regression: bin/mops.js must route through environments/nodejs/cli.js
|
|
22
84
|
// so that setWasmBindings() is called before any command runs.
|
|
@@ -25,12 +87,17 @@ describe("build", () => {
|
|
|
25
87
|
const hasDistBin = existsSync(distBin);
|
|
26
88
|
(hasDistBin ? test : test.skip)("wasm bindings initialized via dist entry point", async () => {
|
|
27
89
|
const cwd = path.join(import.meta.dirname, "build/success");
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
90
|
+
try {
|
|
91
|
+
const result = await execa("node", [distBin, "build", "foo"], {
|
|
92
|
+
cwd,
|
|
93
|
+
stdio: "pipe",
|
|
94
|
+
reject: false,
|
|
95
|
+
});
|
|
96
|
+
expect(result.stderr).not.toContain("Wasm bindings have not been set");
|
|
97
|
+
expect(result.exitCode).toBe(0);
|
|
98
|
+
}
|
|
99
|
+
finally {
|
|
100
|
+
cleanFixture(cwd);
|
|
101
|
+
}
|
|
35
102
|
});
|
|
36
103
|
});
|
package/dist/tests/check.test.js
CHANGED
|
@@ -38,6 +38,13 @@ describe("check", () => {
|
|
|
38
38
|
const cwd = path.join(import.meta.dirname, "check/canisters");
|
|
39
39
|
await cliSnapshot(["check"], { cwd }, 0);
|
|
40
40
|
});
|
|
41
|
+
test("canister entrypoint resolved relative to config root when run from subdirectory", async () => {
|
|
42
|
+
const fixtureRoot = path.join(import.meta.dirname, "check/canisters-subdir");
|
|
43
|
+
const subdir = path.join(fixtureRoot, "src/backend");
|
|
44
|
+
const result = await cli(["check"], { cwd: subdir });
|
|
45
|
+
expect(result.exitCode).toBe(0);
|
|
46
|
+
expect(result.stdout).toMatch(/✓/);
|
|
47
|
+
});
|
|
41
48
|
test("[moc] args applied when using canister fallback", async () => {
|
|
42
49
|
const cwd = path.join(import.meta.dirname, "check/canisters-moc-args");
|
|
43
50
|
const result = await cli(["check"], { cwd });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { describe, test, expect } from "@jest/globals";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { cli } from "./helpers";
|
|
4
|
+
describe("pocket-ic", () => {
|
|
5
|
+
test("runs tests with pocket-ic 12.0.0", async () => {
|
|
6
|
+
const cwd = path.join(import.meta.dirname, "pocket-ic");
|
|
7
|
+
const result = await cli(["test", "--reporter", "verbose", "--replica", "pocket-ic"], { cwd });
|
|
8
|
+
expect(result.stderr).not.toContain("is not supported");
|
|
9
|
+
expect(result.stderr).not.toContain("only supports pocket-ic 9.x.x and 4.0.0");
|
|
10
|
+
expect(result.exitCode).toBe(0);
|
|
11
|
+
});
|
|
12
|
+
});
|
|
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;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import semver from "semver";
|
|
2
|
+
import { PocketIc, PocketIcServer } from "pic-ic";
|
|
3
|
+
import {
|
|
4
|
+
PocketIc as PocketIcModern,
|
|
5
|
+
PocketIcServer as PocketIcServerModern,
|
|
6
|
+
type StartServerOptions,
|
|
7
|
+
} from "pic-js-mops";
|
|
8
|
+
import { readConfig } from "../mops.js";
|
|
9
|
+
|
|
10
|
+
export type AnyPocketIcServer = PocketIcServer | PocketIcServerModern;
|
|
11
|
+
export type AnyPocketIc = PocketIc | PocketIcModern;
|
|
12
|
+
export type AnySetupCanister = PocketIc["setupCanister"] &
|
|
13
|
+
PocketIcModern["setupCanister"];
|
|
14
|
+
|
|
15
|
+
function isLegacy(): boolean {
|
|
16
|
+
let version = readConfig().toolchain?.["pocket-ic"];
|
|
17
|
+
return !!version && !!semver.valid(version) && semver.lt(version, "9.0.0");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export async function startPocketIc(
|
|
21
|
+
options: StartServerOptions,
|
|
22
|
+
): Promise<{ server: AnyPocketIcServer; client: AnyPocketIc }> {
|
|
23
|
+
if (isLegacy()) {
|
|
24
|
+
let server = await PocketIcServer.start(options);
|
|
25
|
+
let client = await PocketIc.create(server.getUrl());
|
|
26
|
+
return { server, client };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
let server = await PocketIcServerModern.start(options);
|
|
30
|
+
let client = await PocketIcModern.create(server.getUrl());
|
|
31
|
+
return { server, client };
|
|
32
|
+
}
|
package/mops.ts
CHANGED
|
@@ -100,6 +100,14 @@ export function getRootDir() {
|
|
|
100
100
|
return path.dirname(configFile);
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
+
/**
|
|
104
|
+
* Resolve a path from mops.toml config (relative to project root)
|
|
105
|
+
* into a path relative to the current working directory.
|
|
106
|
+
*/
|
|
107
|
+
export function resolveConfigPath(configPath: string): string {
|
|
108
|
+
return path.relative(process.cwd(), path.resolve(getRootDir(), configPath));
|
|
109
|
+
}
|
|
110
|
+
|
|
103
111
|
export function checkConfigFile(exit = false) {
|
|
104
112
|
let configFile = getClosestConfigFile();
|
|
105
113
|
if (!configFile) {
|