ic-mops 2.13.2 → 2.14.1
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 +22 -0
- package/bun.lock +24 -12
- package/bundle/cli.tgz +0 -0
- package/cache.ts +101 -20
- package/cli.ts +40 -14
- package/commands/available-updates.ts +4 -2
- package/commands/bench.ts +3 -0
- package/commands/check.ts +33 -22
- package/commands/init.ts +15 -2
- package/commands/install/install-mops-dep.ts +14 -9
- package/commands/install/sync-local-cache.ts +7 -1
- package/commands/lint.ts +11 -0
- package/commands/outdated.ts +5 -2
- package/commands/publish.ts +0 -1
- package/commands/test/test.ts +14 -0
- package/commands/update.ts +3 -2
- package/commands/watch/tester.ts +5 -1
- package/dist/cache.d.ts +3 -0
- package/dist/cache.js +98 -18
- package/dist/cli.js +16 -12
- package/dist/commands/available-updates.d.ts +1 -1
- package/dist/commands/available-updates.js +4 -1
- package/dist/commands/bench.js +2 -0
- package/dist/commands/check.js +27 -18
- package/dist/commands/init.js +9 -2
- package/dist/commands/install/install-mops-dep.js +12 -9
- package/dist/commands/install/sync-local-cache.js +2 -1
- package/dist/commands/lint.js +7 -0
- package/dist/commands/outdated.d.ts +2 -1
- package/dist/commands/outdated.js +2 -2
- package/dist/commands/publish.js +0 -1
- package/dist/commands/test/test.d.ts +1 -1
- package/dist/commands/test/test.js +10 -5
- package/dist/commands/update.d.ts +2 -1
- package/dist/commands/update.js +2 -2
- package/dist/commands/watch/tester.js +4 -1
- package/dist/helpers/autofix-motoko.d.ts +1 -1
- package/dist/helpers/autofix-motoko.js +10 -8
- package/dist/helpers/deprecate-dfx-replica.d.ts +2 -0
- package/dist/helpers/deprecate-dfx-replica.js +20 -0
- package/dist/helpers/fix-lock.d.ts +1 -0
- package/dist/helpers/fix-lock.js +93 -0
- package/dist/integrity.d.ts +2 -2
- package/dist/integrity.js +22 -6
- package/dist/mops.js +1 -1
- package/dist/package.json +3 -3
- package/dist/tests/check-fix.test.js +40 -0
- package/dist/tests/check.test.js +6 -0
- package/dist/tests/cli.test.js +136 -1
- package/dist/vessel.js +21 -13
- package/dist/wasm/pkg/nodejs/package.json +1 -1
- package/dist/wasm/pkg/nodejs/wasm_bg.wasm +0 -0
- package/dist/wasm/pkg/web/package.json +1 -1
- package/dist/wasm/pkg/web/wasm_bg.wasm +0 -0
- package/helpers/autofix-motoko.ts +16 -14
- package/helpers/deprecate-dfx-replica.ts +32 -0
- package/helpers/fix-lock.ts +101 -0
- package/integrity.ts +30 -9
- package/mops.ts +1 -1
- package/package.json +3 -3
- package/tests/__snapshots__/check.test.ts.snap +17 -4
- package/tests/check-fix.test.ts +46 -0
- package/tests/check.test.ts +11 -0
- package/tests/cli.test.ts +180 -1
- package/tests/install/update-bound-patch/mops.toml +2 -0
- package/vessel.ts +31 -14
- package/wasm/pkg/nodejs/package.json +1 -1
- package/wasm/pkg/nodejs/wasm_bg.wasm +0 -0
- package/wasm/pkg/web/package.json +1 -1
- package/wasm/pkg/web/wasm_bg.wasm +0 -0
|
@@ -4,15 +4,17 @@ import path from "node:path";
|
|
|
4
4
|
import { Buffer } from "node:buffer";
|
|
5
5
|
import { createLogUpdate } from "log-update";
|
|
6
6
|
import chalk from "chalk";
|
|
7
|
-
import { deleteSync } from "del";
|
|
8
7
|
import { checkConfigFile, progressBar, readConfig } from "../../mops.js";
|
|
9
8
|
import { getHighestVersion } from "../../api/getHighestVersion.js";
|
|
10
9
|
import { storageActor } from "../../api/actors.js";
|
|
11
10
|
import { parallel } from "../../parallel.js";
|
|
12
11
|
import {
|
|
12
|
+
commitStagingDir,
|
|
13
|
+
createStagingDir,
|
|
13
14
|
getDepCacheDir,
|
|
14
15
|
getMopsDepCacheName,
|
|
15
16
|
isDepCached,
|
|
17
|
+
sweepStaleStagingDirs,
|
|
16
18
|
} from "../../cache.js";
|
|
17
19
|
import {
|
|
18
20
|
downloadFile,
|
|
@@ -69,6 +71,8 @@ export async function installMopsDep(
|
|
|
69
71
|
version = versionRes.ok;
|
|
70
72
|
}
|
|
71
73
|
|
|
74
|
+
sweepStaleStagingDirs();
|
|
75
|
+
|
|
72
76
|
let cacheName = getMopsDepCacheName(depName, version);
|
|
73
77
|
let cacheDir = getDepCacheDir(cacheName);
|
|
74
78
|
|
|
@@ -100,33 +104,34 @@ export async function installMopsDep(
|
|
|
100
104
|
progress();
|
|
101
105
|
});
|
|
102
106
|
|
|
107
|
+
let stagingDir = createStagingDir(cacheDir);
|
|
103
108
|
let onSigInt = () => {
|
|
104
|
-
|
|
105
|
-
process.exit();
|
|
109
|
+
fs.rmSync(stagingDir, { recursive: true, force: true });
|
|
110
|
+
process.exit(130);
|
|
106
111
|
};
|
|
107
112
|
process.on("SIGINT", onSigInt);
|
|
108
113
|
|
|
109
|
-
// write files to global cache
|
|
110
114
|
try {
|
|
111
115
|
await Promise.all(
|
|
112
116
|
Array.from(filesData.entries()).map(async ([filePath, data]) => {
|
|
113
117
|
await fs.promises.mkdir(
|
|
114
|
-
path.join(
|
|
118
|
+
path.join(stagingDir, path.dirname(filePath)),
|
|
115
119
|
{ recursive: true },
|
|
116
120
|
);
|
|
117
121
|
await fs.promises.writeFile(
|
|
118
|
-
path.join(
|
|
122
|
+
path.join(stagingDir, filePath),
|
|
119
123
|
Buffer.from(data),
|
|
120
124
|
);
|
|
121
125
|
}),
|
|
122
126
|
);
|
|
127
|
+
commitStagingDir(stagingDir, cacheDir);
|
|
123
128
|
} catch (err) {
|
|
124
129
|
console.error(chalk.red("Error: ") + err);
|
|
125
|
-
|
|
130
|
+
fs.rmSync(stagingDir, { recursive: true, force: true });
|
|
126
131
|
return false;
|
|
132
|
+
} finally {
|
|
133
|
+
process.off("SIGINT", onSigInt);
|
|
127
134
|
}
|
|
128
|
-
|
|
129
|
-
process.off("SIGINT", onSigInt);
|
|
130
135
|
} catch (err) {
|
|
131
136
|
console.error(chalk.red("Error: ") + err);
|
|
132
137
|
return false;
|
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
copyCache,
|
|
5
|
+
getDepCacheName,
|
|
6
|
+
sweepStaleStagingDirs,
|
|
7
|
+
} from "../../cache.js";
|
|
4
8
|
import { getDependencyType, getRootDir } from "../../mops.js";
|
|
5
9
|
import { resolvePackages } from "../../resolve-packages.js";
|
|
6
10
|
|
|
7
11
|
export async function syncLocalCache({ verbose = false } = {}): Promise<
|
|
8
12
|
Record<string, string>
|
|
9
13
|
> {
|
|
14
|
+
sweepStaleStagingDirs();
|
|
15
|
+
|
|
10
16
|
let resolvedPackages = await resolvePackages();
|
|
11
17
|
let rootDir = getRootDir();
|
|
12
18
|
|
package/commands/lint.ts
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
readConfig,
|
|
12
12
|
} from "../mops.js";
|
|
13
13
|
import { resolvePackages } from "../resolve-packages.js";
|
|
14
|
+
import { withFixLock } from "../helpers/fix-lock.js";
|
|
14
15
|
import { toolchain } from "./toolchain/index.js";
|
|
15
16
|
import { MOTOKO_GLOB_CONFIG } from "../constants.js";
|
|
16
17
|
import { existsSync } from "node:fs";
|
|
@@ -174,6 +175,16 @@ async function runLintoko(
|
|
|
174
175
|
export async function lint(
|
|
175
176
|
filter: string | undefined,
|
|
176
177
|
options: Partial<LintOptions>,
|
|
178
|
+
): Promise<void> {
|
|
179
|
+
if (options.fix) {
|
|
180
|
+
return withFixLock(() => lintImpl(filter, options));
|
|
181
|
+
}
|
|
182
|
+
return lintImpl(filter, options);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
async function lintImpl(
|
|
186
|
+
filter: string | undefined,
|
|
187
|
+
options: Partial<LintOptions>,
|
|
177
188
|
): Promise<void> {
|
|
178
189
|
let config = readConfig();
|
|
179
190
|
let rootDir = getRootDir();
|
package/commands/outdated.ts
CHANGED
|
@@ -3,7 +3,10 @@ import { checkConfigFile, readConfig } from "../mops.js";
|
|
|
3
3
|
import { getAvailableUpdates } from "./available-updates.js";
|
|
4
4
|
import { getDepName, getDepPinnedVersion } from "../helpers/get-dep-name.js";
|
|
5
5
|
|
|
6
|
-
export async function outdated({
|
|
6
|
+
export async function outdated({
|
|
7
|
+
major,
|
|
8
|
+
patch,
|
|
9
|
+
}: { major?: boolean; patch?: boolean } = {}) {
|
|
7
10
|
if (!checkConfigFile()) {
|
|
8
11
|
return;
|
|
9
12
|
}
|
|
@@ -12,7 +15,7 @@ export async function outdated({ major }: { major?: boolean } = {}) {
|
|
|
12
15
|
let available = await getAvailableUpdates(
|
|
13
16
|
config,
|
|
14
17
|
undefined,
|
|
15
|
-
major ? "major" : "caret",
|
|
18
|
+
major ? "major" : patch ? "patch" : "caret",
|
|
16
19
|
);
|
|
17
20
|
|
|
18
21
|
if (available.length === 0) {
|
package/commands/publish.ts
CHANGED
package/commands/test/test.ts
CHANGED
|
@@ -32,6 +32,7 @@ import { toolchain } from "../toolchain/index.js";
|
|
|
32
32
|
import { Replica } from "../replica.js";
|
|
33
33
|
import { TestMode } from "../../types.js";
|
|
34
34
|
import { getDfxVersion } from "../../helpers/get-dfx-version.js";
|
|
35
|
+
import { warnIfDfxReplica } from "../../helpers/deprecate-dfx-replica.js";
|
|
35
36
|
import { MOTOKO_GLOB_CONFIG, MOTOKO_IGNORE_PATTERNS } from "../../constants.js";
|
|
36
37
|
|
|
37
38
|
type ReporterName = "verbose" | "files" | "compact" | "silent";
|
|
@@ -79,6 +80,8 @@ export async function test(filter = "", options: Partial<TestOptions> = {}) {
|
|
|
79
80
|
}
|
|
80
81
|
}
|
|
81
82
|
|
|
83
|
+
let explicitReplica = options.replica === "dfx";
|
|
84
|
+
|
|
82
85
|
replica.type = replicaType;
|
|
83
86
|
replica.verbose = !!options.verbose;
|
|
84
87
|
|
|
@@ -124,6 +127,7 @@ export async function test(filter = "", options: Partial<TestOptions> = {}) {
|
|
|
124
127
|
replicaType,
|
|
125
128
|
true,
|
|
126
129
|
controller.signal,
|
|
130
|
+
explicitReplica,
|
|
127
131
|
);
|
|
128
132
|
await curRun;
|
|
129
133
|
|
|
@@ -150,6 +154,9 @@ export async function test(filter = "", options: Partial<TestOptions> = {}) {
|
|
|
150
154
|
filter,
|
|
151
155
|
options.mode,
|
|
152
156
|
replicaType,
|
|
157
|
+
false,
|
|
158
|
+
undefined,
|
|
159
|
+
explicitReplica,
|
|
153
160
|
);
|
|
154
161
|
if (!passed) {
|
|
155
162
|
process.exit(1);
|
|
@@ -167,6 +174,7 @@ async function runAll(
|
|
|
167
174
|
replicaType: ReplicaName,
|
|
168
175
|
watch = false,
|
|
169
176
|
signal?: AbortSignal,
|
|
177
|
+
explicitReplica = false,
|
|
170
178
|
): Promise<boolean> {
|
|
171
179
|
let done = await testWithReporter(
|
|
172
180
|
reporterName,
|
|
@@ -175,6 +183,7 @@ async function runAll(
|
|
|
175
183
|
replicaType,
|
|
176
184
|
watch,
|
|
177
185
|
signal,
|
|
186
|
+
explicitReplica,
|
|
178
187
|
);
|
|
179
188
|
return done;
|
|
180
189
|
}
|
|
@@ -186,6 +195,7 @@ export async function testWithReporter(
|
|
|
186
195
|
replicaType: ReplicaName,
|
|
187
196
|
watch = false,
|
|
188
197
|
signal?: AbortSignal,
|
|
198
|
+
explicitReplica = false,
|
|
189
199
|
): Promise<boolean> {
|
|
190
200
|
let rootDir = getRootDir();
|
|
191
201
|
let files: string[] = [];
|
|
@@ -261,6 +271,10 @@ export async function testWithReporter(
|
|
|
261
271
|
let hasWasiTests = filesWithMode.some(({ mode }) => mode === "wasi");
|
|
262
272
|
let hasReplicaTests = filesWithMode.some(({ mode }) => mode === "replica");
|
|
263
273
|
|
|
274
|
+
if (hasReplicaTests) {
|
|
275
|
+
warnIfDfxReplica(replicaType, explicitReplica);
|
|
276
|
+
}
|
|
277
|
+
|
|
264
278
|
// prepare wasmtime path
|
|
265
279
|
if (hasWasiTests && !wasmtimePath) {
|
|
266
280
|
// ensure wasmtime is installed or specified in config
|
package/commands/update.ts
CHANGED
|
@@ -15,11 +15,12 @@ type UpdateOptions = {
|
|
|
15
15
|
dev?: boolean;
|
|
16
16
|
lock?: "update" | "ignore";
|
|
17
17
|
major?: boolean;
|
|
18
|
+
patch?: boolean;
|
|
18
19
|
};
|
|
19
20
|
|
|
20
21
|
export async function update(
|
|
21
22
|
pkg?: string,
|
|
22
|
-
{ lock, major }: UpdateOptions = {},
|
|
23
|
+
{ lock, major, patch }: UpdateOptions = {},
|
|
23
24
|
) {
|
|
24
25
|
if (!checkConfigFile()) {
|
|
25
26
|
return;
|
|
@@ -66,7 +67,7 @@ export async function update(
|
|
|
66
67
|
let available = await getAvailableUpdates(
|
|
67
68
|
config,
|
|
68
69
|
pkg,
|
|
69
|
-
major ? "major" : "caret",
|
|
70
|
+
major ? "major" : patch ? "patch" : "caret",
|
|
70
71
|
);
|
|
71
72
|
|
|
72
73
|
if (available.length === 0) {
|
package/commands/watch/tester.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { readConfig } from "../../mops.js";
|
|
|
3
3
|
import { ErrorChecker } from "./error-checker.js";
|
|
4
4
|
import { testWithReporter } from "../test/test.js";
|
|
5
5
|
import { SilentReporter } from "../test/reporters/silent-reporter.js";
|
|
6
|
+
import { type ReplicaName } from "../../helpers/deprecate-dfx-replica.js";
|
|
6
7
|
|
|
7
8
|
export class Tester {
|
|
8
9
|
verbose = false;
|
|
@@ -53,12 +54,15 @@ export class Tester {
|
|
|
53
54
|
this.controller = new AbortController();
|
|
54
55
|
|
|
55
56
|
let config = readConfig();
|
|
57
|
+
let replicaType: ReplicaName = config.toolchain?.["pocket-ic"]
|
|
58
|
+
? "pocket-ic"
|
|
59
|
+
: "dfx";
|
|
56
60
|
|
|
57
61
|
this.currentRun = testWithReporter(
|
|
58
62
|
this.reporter,
|
|
59
63
|
"",
|
|
60
64
|
"interpreter",
|
|
61
|
-
|
|
65
|
+
replicaType,
|
|
62
66
|
true,
|
|
63
67
|
this.controller.signal,
|
|
64
68
|
);
|
package/dist/cache.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
export declare function createStagingDir(dest: string): string;
|
|
2
|
+
export declare function commitStagingDir(staging: string, dest: string): boolean;
|
|
3
|
+
export declare function sweepStaleStagingDirs(): void;
|
|
1
4
|
export declare let show: () => string;
|
|
2
5
|
export declare let getDepCacheDir: (cacheName: string) => string;
|
|
3
6
|
export declare let isDepCached: (cacheName: string) => boolean;
|
package/dist/cache.js
CHANGED
|
@@ -8,6 +8,72 @@ let getGlobalCacheDir = () => {
|
|
|
8
8
|
let network = getNetwork();
|
|
9
9
|
return path.join(globalCacheDir, network === "ic" ? "" : network);
|
|
10
10
|
};
|
|
11
|
+
// Cache writes stage into a sibling `<dest>/../.staging-<rand>` and atomic-
|
|
12
|
+
// rename onto `dest` so concurrent processes never observe a partial cache.
|
|
13
|
+
const STAGING_PREFIX = ".staging-";
|
|
14
|
+
export function createStagingDir(dest) {
|
|
15
|
+
let parent = path.dirname(dest);
|
|
16
|
+
fs.mkdirSync(parent, { recursive: true });
|
|
17
|
+
return fs.mkdtempSync(path.join(parent, STAGING_PREFIX));
|
|
18
|
+
}
|
|
19
|
+
// Returns false if another process committed first (race lost) — `staging`
|
|
20
|
+
// is removed and the existing `dest` is left intact. We only swallow
|
|
21
|
+
// `EPERM` (Windows) when `dest` exists; otherwise it's likely AV / open
|
|
22
|
+
// handles and bubbles up.
|
|
23
|
+
export function commitStagingDir(staging, dest) {
|
|
24
|
+
try {
|
|
25
|
+
fs.renameSync(staging, dest);
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
let raceLost = (err.code === "ENOTEMPTY" ||
|
|
30
|
+
err.code === "EEXIST" ||
|
|
31
|
+
err.code === "EPERM") &&
|
|
32
|
+
fs.existsSync(dest);
|
|
33
|
+
if (raceLost) {
|
|
34
|
+
fs.rmSync(staging, { recursive: true, force: true });
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
throw err;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// Sweep leftover `.staging-*` from interrupted runs. Mtime cutoff avoids
|
|
41
|
+
// clobbering siblings that are mid-staging right now. Runs at most once
|
|
42
|
+
// per process.
|
|
43
|
+
const STAGING_STALE_MS = 60 * 60 * 1000;
|
|
44
|
+
let swept = false;
|
|
45
|
+
export function sweepStaleStagingDirs() {
|
|
46
|
+
if (swept) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
swept = true;
|
|
50
|
+
let cutoff = Date.now() - STAGING_STALE_MS;
|
|
51
|
+
let parents = [
|
|
52
|
+
path.join(getGlobalCacheDir(), "packages"),
|
|
53
|
+
path.join(getGlobalCacheDir(), "packages", "_github"),
|
|
54
|
+
path.join(getRootDir(), ".mops"),
|
|
55
|
+
path.join(getRootDir(), ".mops", "_github"),
|
|
56
|
+
];
|
|
57
|
+
for (let parent of parents) {
|
|
58
|
+
if (!fs.existsSync(parent)) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
for (let entry of fs.readdirSync(parent)) {
|
|
62
|
+
if (!entry.startsWith(STAGING_PREFIX)) {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
let full = path.join(parent, entry);
|
|
66
|
+
try {
|
|
67
|
+
if (fs.statSync(full).mtimeMs < cutoff) {
|
|
68
|
+
fs.rmSync(full, { recursive: true, force: true });
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// raced with another sweeper; ignore
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
11
77
|
export let show = () => {
|
|
12
78
|
return getGlobalCacheDir();
|
|
13
79
|
};
|
|
@@ -32,29 +98,43 @@ export function getGithubDepCacheName(name, repo) {
|
|
|
32
98
|
return (`_github/${name}#${branch.replaceAll("/", "___")}` +
|
|
33
99
|
(commitHash ? `@${commitHash}` : ""));
|
|
34
100
|
}
|
|
35
|
-
export let addCache = (cacheName, source) => {
|
|
101
|
+
export let addCache = async (cacheName, source) => {
|
|
36
102
|
let dest = path.join(getGlobalCacheDir(), "packages", cacheName);
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
103
|
+
let staging = createStagingDir(dest);
|
|
104
|
+
try {
|
|
105
|
+
await new Promise((resolve, reject) => {
|
|
106
|
+
ncp.ncp(source, staging, { stopOnErr: true }, (err) => {
|
|
107
|
+
if (err) {
|
|
108
|
+
reject(err);
|
|
109
|
+
}
|
|
110
|
+
resolve();
|
|
111
|
+
});
|
|
44
112
|
});
|
|
45
|
-
|
|
113
|
+
commitStagingDir(staging, dest);
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
fs.rmSync(staging, { recursive: true, force: true });
|
|
117
|
+
throw err;
|
|
118
|
+
}
|
|
46
119
|
};
|
|
47
|
-
export let copyCache = (cacheName, dest) => {
|
|
120
|
+
export let copyCache = async (cacheName, dest) => {
|
|
48
121
|
let source = path.join(getGlobalCacheDir(), "packages", cacheName);
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
122
|
+
let staging = createStagingDir(dest);
|
|
123
|
+
try {
|
|
124
|
+
await new Promise((resolve, reject) => {
|
|
125
|
+
ncp.ncp(source, staging, { stopOnErr: true }, (err) => {
|
|
126
|
+
if (err) {
|
|
127
|
+
reject(err);
|
|
128
|
+
}
|
|
129
|
+
resolve();
|
|
130
|
+
});
|
|
56
131
|
});
|
|
57
|
-
|
|
132
|
+
commitStagingDir(staging, dest);
|
|
133
|
+
}
|
|
134
|
+
catch (err) {
|
|
135
|
+
fs.rmSync(staging, { recursive: true, force: true });
|
|
136
|
+
throw err;
|
|
137
|
+
}
|
|
58
138
|
};
|
|
59
139
|
export let cacheSize = async () => {
|
|
60
140
|
let dir = path.join(getGlobalCacheDir());
|
package/dist/cli.js
CHANGED
|
@@ -327,7 +327,7 @@ program
|
|
|
327
327
|
.addOption(new Option("--mode <mode>", "Test mode")
|
|
328
328
|
.choices(["interpreter", "wasi", "replica"])
|
|
329
329
|
.default("interpreter"))
|
|
330
|
-
.addOption(new Option("--replica <replica>", "Which replica to use to run tests in replica mode").choices(["dfx", "pocket-ic"]))
|
|
330
|
+
.addOption(new Option("--replica <replica>", "Which replica to use to run tests in replica mode (`dfx` is deprecated; prefer `pocket-ic`)").choices(["dfx", "pocket-ic"]))
|
|
331
331
|
.option("-w, --watch", "Enable watch mode")
|
|
332
332
|
.option("--verbose", "Verbose output")
|
|
333
333
|
.action(async (filter, options) => {
|
|
@@ -343,7 +343,7 @@ program
|
|
|
343
343
|
program
|
|
344
344
|
.command("bench [filter]")
|
|
345
345
|
.description("Run benchmarks")
|
|
346
|
-
.addOption(new Option("--replica <replica>", "Which replica to use to run benchmarks").choices(["dfx", "pocket-ic"]))
|
|
346
|
+
.addOption(new Option("--replica <replica>", "Which replica to use to run benchmarks (`dfx` is deprecated; prefer `pocket-ic`)").choices(["dfx", "pocket-ic"]))
|
|
347
347
|
.addOption(new Option("--gc <gc>", "Garbage collector")
|
|
348
348
|
.choices(["copying", "compacting", "generational", "incremental"])
|
|
349
349
|
.default("copying"))
|
|
@@ -491,16 +491,18 @@ program
|
|
|
491
491
|
// outdated
|
|
492
492
|
program
|
|
493
493
|
.command("outdated")
|
|
494
|
-
.description("Print outdated dependencies
|
|
495
|
-
.addOption(new Option("--major", "Allow updates that cross the caret bound (major versions, or for 0.x.y packages, minor versions)"))
|
|
494
|
+
.description("Print outdated dependencies in mops.toml within the caret bound (does not cross major versions, or pre-1.0 minor versions)")
|
|
495
|
+
.addOption(new Option("--major", "Allow updates that cross the caret bound (major versions, or for 0.x.y packages, minor versions)").conflicts("patch"))
|
|
496
|
+
.addOption(new Option("--patch", "Restrict updates to patch versions only (e.g. 1.2.3 -> 1.2.4, never 1.2.3 -> 1.3.0)"))
|
|
496
497
|
.action(async (options) => {
|
|
497
498
|
await outdated(options);
|
|
498
499
|
});
|
|
499
500
|
// update
|
|
500
501
|
program
|
|
501
502
|
.command("update [pkg]")
|
|
502
|
-
.description("Update dependencies
|
|
503
|
-
.addOption(new Option("--major", "Allow updates that cross the caret bound (major versions, or for 0.x.y packages, minor versions)"))
|
|
503
|
+
.description("Update dependencies in mops.toml to the highest semver-compatible version within the caret bound (does not cross major versions, or pre-1.0 minor versions)")
|
|
504
|
+
.addOption(new Option("--major", "Allow updates that cross the caret bound (major versions, or for 0.x.y packages, minor versions)").conflicts("patch"))
|
|
505
|
+
.addOption(new Option("--patch", "Restrict updates to patch versions only (e.g. 1.2.3 -> 1.2.4, never 1.2.3 -> 1.3.0)"))
|
|
504
506
|
.addOption(new Option("--lock <action>", "Lockfile action").choices([
|
|
505
507
|
"update",
|
|
506
508
|
"ignore",
|
|
@@ -509,7 +511,9 @@ program
|
|
|
509
511
|
await update(pkg, options);
|
|
510
512
|
});
|
|
511
513
|
// toolchain
|
|
512
|
-
const toolchainCommand = new Command("toolchain")
|
|
514
|
+
const toolchainCommand = new Command("toolchain")
|
|
515
|
+
.description(`Toolchain management for ${TOOLCHAINS.map((s) => `"${s}"`).join(", ")}`)
|
|
516
|
+
.showHelpAfterError();
|
|
513
517
|
toolchainCommand
|
|
514
518
|
.command("init")
|
|
515
519
|
.description("One-time initialization of toolchain management")
|
|
@@ -525,8 +529,8 @@ toolchainCommand
|
|
|
525
529
|
toolchainCommand
|
|
526
530
|
.command("use")
|
|
527
531
|
.description("Install specified tool version and update mops.toml")
|
|
528
|
-
.addArgument(new Argument("<tool>").choices(TOOLCHAINS))
|
|
529
|
-
.addArgument(new Argument("[version]"))
|
|
532
|
+
.addArgument(new Argument("<tool>", "tool to install").choices(TOOLCHAINS))
|
|
533
|
+
.addArgument(new Argument("[version]", "version to install (defaults to interactive picker)"))
|
|
530
534
|
.action(async (tool, version) => {
|
|
531
535
|
if (!checkConfigFile()) {
|
|
532
536
|
process.exit(1);
|
|
@@ -536,7 +540,7 @@ toolchainCommand
|
|
|
536
540
|
toolchainCommand
|
|
537
541
|
.command("update")
|
|
538
542
|
.description("Update specified tool or all tools to the latest version and update mops.toml")
|
|
539
|
-
.addArgument(new Argument("[tool]").choices(TOOLCHAINS))
|
|
543
|
+
.addArgument(new Argument("[tool]", "tool to update (defaults to all configured tools)").choices(TOOLCHAINS))
|
|
540
544
|
.action(async (tool) => {
|
|
541
545
|
if (!checkConfigFile()) {
|
|
542
546
|
process.exit(1);
|
|
@@ -545,8 +549,8 @@ toolchainCommand
|
|
|
545
549
|
});
|
|
546
550
|
toolchainCommand
|
|
547
551
|
.command("bin")
|
|
548
|
-
.description(
|
|
549
|
-
.addArgument(new Argument("<tool>").choices(TOOLCHAINS))
|
|
552
|
+
.description("Get path to the tool binary")
|
|
553
|
+
.addArgument(new Argument("<tool>", "tool to look up").choices(TOOLCHAINS))
|
|
550
554
|
.addOption(new Option("--fallback", "Fallback to the moc that comes with dfx if moc is not specified in the [toolchain] section"))
|
|
551
555
|
.action(async (tool, options) => {
|
|
552
556
|
let bin = await toolchain.bin(tool, options);
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { Config } from "../types.js";
|
|
2
|
-
export type UpdateBound = "caret" | "major";
|
|
2
|
+
export type UpdateBound = "patch" | "caret" | "major";
|
|
3
3
|
export declare function getAvailableUpdates(config: Config, pkg?: string, bound?: UpdateBound): Promise<Array<[string, string, string]>>;
|
|
@@ -29,7 +29,10 @@ export async function getAvailableUpdates(config, pkg, bound = "caret") {
|
|
|
29
29
|
let semverPart = { major: null };
|
|
30
30
|
let name = getDepName(dep.name);
|
|
31
31
|
let pinnedVersion = getDepPinnedVersion(dep.name);
|
|
32
|
-
if (
|
|
32
|
+
if (bound === "patch") {
|
|
33
|
+
semverPart = { patch: null };
|
|
34
|
+
}
|
|
35
|
+
else if (pinnedVersion) {
|
|
33
36
|
semverPart =
|
|
34
37
|
pinnedVersion.split(".").length === 1
|
|
35
38
|
? { minor: null }
|
package/dist/commands/bench.js
CHANGED
|
@@ -16,6 +16,7 @@ import { parallel } from "../parallel.js";
|
|
|
16
16
|
import { absToRel } from "./test/utils.js";
|
|
17
17
|
import { getMocVersion } from "../helpers/get-moc-version.js";
|
|
18
18
|
import { getDfxVersion } from "../helpers/get-dfx-version.js";
|
|
19
|
+
import { warnIfDfxReplica } from "../helpers/deprecate-dfx-replica.js";
|
|
19
20
|
import { getMocPath } from "../helpers/get-moc-path.js";
|
|
20
21
|
import { sources } from "./sources.js";
|
|
21
22
|
import { MOTOKO_GLOB_CONFIG } from "../constants.js";
|
|
@@ -59,6 +60,7 @@ export async function bench(filter = "", optionsArg = {}) {
|
|
|
59
60
|
else if (replicaType == "pocket-ic") {
|
|
60
61
|
options.replicaVersion = config.toolchain?.["pocket-ic"] || "";
|
|
61
62
|
}
|
|
63
|
+
warnIfDfxReplica(replicaType, optionsArg.replica === "dfx");
|
|
62
64
|
options.verbose && console.log(options);
|
|
63
65
|
let replica = new BenchReplica(replicaType, options.verbose);
|
|
64
66
|
let rootDir = getRootDir();
|
package/dist/commands/check.js
CHANGED
|
@@ -4,6 +4,7 @@ import { execa } from "execa";
|
|
|
4
4
|
import { cliError } from "../error.js";
|
|
5
5
|
import { getGlobalMocArgs, getRootDir, readConfig, resolveConfigPath, } from "../mops.js";
|
|
6
6
|
import { autofixMotoko } from "../helpers/autofix-motoko.js";
|
|
7
|
+
import { withFixLock } from "../helpers/fix-lock.js";
|
|
7
8
|
import { getMocSemVer } from "../helpers/get-moc-version.js";
|
|
8
9
|
import { filterCanisters, looksLikeFile, resolveCanisterConfigs, validateCanisterArgs, } from "../helpers/resolve-canisters.js";
|
|
9
10
|
import { prepareMigrationArgs } from "../helpers/migrations.js";
|
|
@@ -42,6 +43,12 @@ function logAutofixResult(fixResult, verbose) {
|
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
45
|
export async function check(args, options = {}) {
|
|
46
|
+
if (options.fix) {
|
|
47
|
+
return withFixLock(() => checkImpl(args, options));
|
|
48
|
+
}
|
|
49
|
+
return checkImpl(args, options);
|
|
50
|
+
}
|
|
51
|
+
async function checkImpl(args, options = {}) {
|
|
45
52
|
const config = readConfig();
|
|
46
53
|
const canisters = resolveCanisterConfigs(config);
|
|
47
54
|
const hasCanisters = Object.keys(canisters).length > 0;
|
|
@@ -164,24 +171,26 @@ async function checkFiles(config, files, options) {
|
|
|
164
171
|
const fixResult = await autofixMotoko(mocPath, files, mocArgs);
|
|
165
172
|
logAutofixResult(fixResult, options.verbose);
|
|
166
173
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
}
|
|
181
|
-
console.log(chalk.green(`✓ ${file}`));
|
|
182
|
-
}
|
|
183
|
-
catch (err) {
|
|
184
|
-
cliError(`Error while checking ${file}${err?.message ? `\n${err.message}` : ""}`);
|
|
174
|
+
// Check all files in a single moc invocation so shared transitive imports
|
|
175
|
+
// are chased and type-checked once, not re-checked for every file.
|
|
176
|
+
const args = [...files, ...mocArgs];
|
|
177
|
+
if (options.verbose) {
|
|
178
|
+
console.log(chalk.blue("check"), chalk.gray("Running moc:"));
|
|
179
|
+
console.log(chalk.gray(mocPath, JSON.stringify(args)));
|
|
180
|
+
}
|
|
181
|
+
try {
|
|
182
|
+
const result = await execa(mocPath, args, {
|
|
183
|
+
stdio: "inherit",
|
|
184
|
+
reject: false,
|
|
185
|
+
});
|
|
186
|
+
if (result.exitCode !== 0) {
|
|
187
|
+
cliError(`✗ Check failed (exit code: ${result.exitCode})`);
|
|
185
188
|
}
|
|
186
189
|
}
|
|
190
|
+
catch (err) {
|
|
191
|
+
cliError(`Error while checking files${err?.message ? `\n${err.message}` : ""}`);
|
|
192
|
+
}
|
|
193
|
+
for (const file of files) {
|
|
194
|
+
console.log(chalk.green(`✓ ${file}`));
|
|
195
|
+
}
|
|
187
196
|
}
|
package/dist/commands/init.js
CHANGED
|
@@ -19,6 +19,14 @@ export async function init({ yes = false } = {}) {
|
|
|
19
19
|
}
|
|
20
20
|
console.log("Initializing...");
|
|
21
21
|
let config = {};
|
|
22
|
+
let vesselFile = path.join(process.cwd(), "vessel.dhall");
|
|
23
|
+
let vesselExists = existsSync(vesselFile);
|
|
24
|
+
// Warn before the --yes early-return so scripted/CI users get the heads-up
|
|
25
|
+
// even though `mops init --yes` skips the vessel migration entirely.
|
|
26
|
+
if (vesselExists) {
|
|
27
|
+
console.warn(chalk.yellow("WARN: vessel.dhall auto-migration is deprecated and will be removed in mops v3. " +
|
|
28
|
+
"Before then, copy your dependencies into mops.toml manually and delete vessel.dhall / package-set.dhall."));
|
|
29
|
+
}
|
|
22
30
|
if (yes) {
|
|
23
31
|
await applyInit({
|
|
24
32
|
type: "project",
|
|
@@ -30,9 +38,8 @@ export async function init({ yes = false } = {}) {
|
|
|
30
38
|
return;
|
|
31
39
|
}
|
|
32
40
|
// migrate from vessel
|
|
33
|
-
let vesselFile = path.join(process.cwd(), "vessel.dhall");
|
|
34
41
|
let vesselConfig = { dependencies: [], "dev-dependencies": [] };
|
|
35
|
-
if (
|
|
42
|
+
if (vesselExists) {
|
|
36
43
|
console.log("Reading vessel.dhall file");
|
|
37
44
|
let res = await readVesselConfig(process.cwd(), { cache: false });
|
|
38
45
|
if (res) {
|