ic-mops 2.0.0 → 2.1.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 +13 -0
- package/RELEASE.md +179 -0
- package/bundle/cli.tgz +0 -0
- package/check-requirements.ts +3 -8
- package/cli.ts +79 -11
- package/commands/bench/bench-canister.mo +17 -6
- package/commands/bench.ts +2 -13
- package/commands/build.ts +42 -17
- package/commands/check.ts +117 -0
- package/commands/format.ts +3 -18
- package/commands/lint.ts +92 -0
- package/commands/sync.ts +2 -8
- package/commands/test/test.ts +7 -19
- package/commands/toolchain/index.ts +21 -8
- package/commands/toolchain/lintoko.ts +54 -0
- package/commands/toolchain/toolchain-utils.ts +2 -0
- package/constants.ts +23 -0
- package/dist/check-requirements.js +3 -8
- package/dist/cli.js +60 -10
- package/dist/commands/bench/bench-canister.mo +17 -6
- package/dist/commands/bench.js +2 -11
- package/dist/commands/build.js +38 -16
- package/dist/commands/check.d.ts +6 -0
- package/dist/commands/check.js +78 -0
- package/dist/commands/format.js +3 -16
- package/dist/commands/lint.d.ts +7 -0
- package/dist/commands/lint.js +69 -0
- package/dist/commands/sync.js +2 -7
- package/dist/commands/test/test.js +7 -17
- package/dist/commands/toolchain/index.d.ts +2 -2
- package/dist/commands/toolchain/index.js +18 -7
- package/dist/commands/toolchain/lintoko.d.ts +8 -0
- package/dist/commands/toolchain/lintoko.js +36 -0
- package/dist/commands/toolchain/toolchain-utils.d.ts +1 -0
- package/dist/commands/toolchain/toolchain-utils.js +1 -0
- package/dist/constants.d.ts +15 -0
- package/dist/constants.js +21 -0
- package/dist/environments/nodejs/cli.js +6 -1
- package/dist/helpers/autofix-motoko.d.ts +26 -0
- package/dist/helpers/autofix-motoko.js +105 -0
- package/dist/helpers/get-moc-version.d.ts +2 -0
- package/dist/helpers/get-moc-version.js +10 -1
- package/dist/mops.js +2 -1
- package/dist/package.json +4 -3
- package/dist/tests/build-no-dfx.test.d.ts +1 -0
- package/dist/tests/build-no-dfx.test.js +9 -0
- package/dist/tests/build.test.d.ts +1 -0
- package/dist/tests/build.test.js +18 -0
- package/dist/tests/check-candid.test.d.ts +1 -0
- package/dist/tests/check-candid.test.js +20 -0
- package/dist/tests/check-fix.test.d.ts +1 -0
- package/dist/tests/check-fix.test.js +73 -0
- package/dist/tests/check.test.d.ts +1 -0
- package/dist/tests/check.test.js +33 -0
- package/dist/tests/cli.test.js +4 -57
- package/dist/tests/helpers.d.ts +22 -0
- package/dist/tests/helpers.js +43 -0
- package/dist/tests/lint.test.d.ts +1 -0
- package/dist/tests/lint.test.js +15 -0
- package/dist/tests/toolchain.test.d.ts +1 -0
- package/dist/tests/toolchain.test.js +11 -0
- package/dist/types.d.ts +6 -1
- package/dist/wasm/pkg/nodejs/wasm.d.ts +3 -0
- package/dist/wasm/pkg/nodejs/wasm.js +323 -17
- package/dist/wasm/pkg/nodejs/wasm_bg.wasm +0 -0
- package/dist/wasm/pkg/nodejs/wasm_bg.wasm.d.ts +6 -1
- package/dist/wasm/pkg/web/wasm.d.ts +10 -1
- package/dist/wasm/pkg/web/wasm.js +300 -21
- package/dist/wasm/pkg/web/wasm_bg.wasm +0 -0
- package/dist/wasm/pkg/web/wasm_bg.wasm.d.ts +6 -1
- package/dist/wasm.d.ts +6 -1
- package/environments/nodejs/cli.ts +7 -1
- package/helpers/autofix-motoko.ts +170 -0
- package/helpers/get-moc-version.ts +12 -1
- package/mops.ts +2 -1
- package/package.json +4 -3
- package/tests/__snapshots__/build-no-dfx.test.ts.snap +11 -0
- package/tests/__snapshots__/build.test.ts.snap +77 -0
- package/tests/__snapshots__/check-candid.test.ts.snap +73 -0
- package/tests/__snapshots__/check-fix.test.ts.snap +242 -0
- package/tests/__snapshots__/check.test.ts.snap +72 -0
- package/tests/__snapshots__/lint.test.ts.snap +78 -0
- package/tests/build/error/src/Bar.mo +2 -2
- package/tests/build/no-dfx/mops.toml +5 -0
- package/tests/build/no-dfx/src/Main.mo +5 -0
- package/tests/build/success/candid/bar.did +1 -0
- package/tests/build/success/mops.toml +8 -3
- package/tests/build-no-dfx.test.ts +10 -0
- package/tests/build.test.ts +24 -0
- package/tests/check/error/Error.mo +7 -0
- package/tests/check/error/mops.toml +2 -0
- package/tests/check/fix/M0223.mo +11 -0
- package/tests/check/fix/M0236.mo +11 -0
- package/tests/check/fix/M0237.mo +11 -0
- package/tests/check/fix/Ok.mo +7 -0
- package/tests/check/fix/edit-suggestions.mo +143 -0
- package/tests/check/fix/mops.toml +5 -0
- package/tests/check/fix/transitive-lib.mo +9 -0
- package/tests/check/fix/transitive-main.mo +9 -0
- package/tests/check/success/Ok.mo +5 -0
- package/tests/check/success/Warning.mo +5 -0
- package/tests/check/success/mops.toml +2 -0
- package/tests/check-candid.test.ts +22 -0
- package/tests/check-fix.test.ts +111 -0
- package/tests/check.test.ts +46 -0
- package/tests/cli.test.ts +4 -74
- package/tests/helpers.ts +58 -0
- package/tests/lint/lints/no-bool-switch.toml +9 -0
- package/tests/lint/mops.toml +4 -0
- package/tests/lint/src/NoBoolSwitch.mo +8 -0
- package/tests/lint/src/Ok.mo +5 -0
- package/tests/lint.test.ts +17 -0
- package/tests/toolchain/mock +2 -0
- package/tests/toolchain/mops.toml +2 -0
- package/tests/toolchain.test.ts +12 -0
- package/types.ts +6 -1
- package/wasm/Cargo.lock +101 -54
- package/wasm/Cargo.toml +2 -5
- package/wasm/pkg/nodejs/wasm.d.ts +3 -0
- package/wasm/pkg/nodejs/wasm.js +323 -17
- package/wasm/pkg/nodejs/wasm_bg.wasm +0 -0
- package/wasm/pkg/nodejs/wasm_bg.wasm.d.ts +6 -1
- package/wasm/pkg/web/wasm.d.ts +10 -1
- package/wasm/pkg/web/wasm.js +300 -21
- package/wasm/pkg/web/wasm_bg.wasm +0 -0
- package/wasm/pkg/web/wasm_bg.wasm.d.ts +6 -1
- package/wasm/src/lib.rs +10 -5
- package/wasm/src/utils.rs +15 -0
- package/wasm/src/wasm_utils.rs +79 -0
- package/wasm.ts +10 -1
- package/.DS_Store +0 -0
- package/bundle/bench/bench-canister.mo +0 -121
- package/bundle/bench/user-bench.mo +0 -10
- package/bundle/bin/moc-wrapper.sh +0 -40
- package/bundle/bin/mops.js +0 -3
- package/bundle/cli.js +0 -2144
- package/bundle/declarations/bench/bench.did +0 -30
- package/bundle/declarations/bench/bench.did.d.ts +0 -33
- package/bundle/declarations/bench/bench.did.js +0 -30
- package/bundle/declarations/bench/index.d.ts +0 -50
- package/bundle/declarations/bench/index.js +0 -40
- package/bundle/declarations/main/index.d.ts +0 -50
- package/bundle/declarations/main/index.js +0 -40
- package/bundle/declarations/main/main.did +0 -428
- package/bundle/declarations/main/main.did.d.ts +0 -348
- package/bundle/declarations/main/main.did.js +0 -406
- package/bundle/declarations/storage/index.d.ts +0 -50
- package/bundle/declarations/storage/index.js +0 -30
- package/bundle/declarations/storage/storage.did +0 -46
- package/bundle/declarations/storage/storage.did.d.ts +0 -40
- package/bundle/declarations/storage/storage.did.js +0 -38
- package/bundle/package.json +0 -36
- package/bundle/templates/README.md +0 -13
- package/bundle/templates/licenses/Apache-2.0 +0 -202
- package/bundle/templates/licenses/Apache-2.0-NOTICE +0 -13
- package/bundle/templates/licenses/MIT +0 -21
- package/bundle/templates/mops-publish.yml +0 -17
- package/bundle/templates/mops-test.yml +0 -24
- package/bundle/templates/src/lib.mo +0 -15
- package/bundle/templates/test/lib.test.mo +0 -4
- package/bundle/wasm_bg.wasm +0 -0
- package/bundle/xhr-sync-worker.js +0 -59
- package/dist/wasm/pkg/bundler/package.json +0 -20
- package/dist/wasm/pkg/bundler/wasm.d.ts +0 -3
- package/dist/wasm/pkg/bundler/wasm.js +0 -5
- package/dist/wasm/pkg/bundler/wasm_bg.js +0 -93
- package/dist/wasm/pkg/bundler/wasm_bg.wasm +0 -0
- package/dist/wasm/pkg/bundler/wasm_bg.wasm.d.ts +0 -8
- package/tests/__snapshots__/cli.test.ts.snap +0 -202
- package/tests/build/success/.dfx/local/canister_ids.json +0 -17
- package/tests/build/success/.dfx/local/canisters/bar/bar.did +0 -3
- package/tests/build/success/.dfx/local/canisters/bar/bar.most +0 -4
- package/tests/build/success/.dfx/local/canisters/bar/bar.wasm +0 -0
- package/tests/build/success/.dfx/local/canisters/bar/constructor.did +0 -3
- package/tests/build/success/.dfx/local/canisters/bar/index.js +0 -42
- package/tests/build/success/.dfx/local/canisters/bar/init_args.txt +0 -1
- package/tests/build/success/.dfx/local/canisters/bar/service.did +0 -3
- package/tests/build/success/.dfx/local/canisters/bar/service.did.d.ts +0 -7
- package/tests/build/success/.dfx/local/canisters/bar/service.did.js +0 -4
- package/tests/build/success/.dfx/local/canisters/foo/constructor.did +0 -3
- package/tests/build/success/.dfx/local/canisters/foo/foo.did +0 -3
- package/tests/build/success/.dfx/local/canisters/foo/foo.most +0 -4
- package/tests/build/success/.dfx/local/canisters/foo/foo.wasm +0 -0
- package/tests/build/success/.dfx/local/canisters/foo/index.js +0 -42
- package/tests/build/success/.dfx/local/canisters/foo/init_args.txt +0 -1
- package/tests/build/success/.dfx/local/canisters/foo/service.did +0 -3
- package/tests/build/success/.dfx/local/canisters/foo/service.did.d.ts +0 -7
- package/tests/build/success/.dfx/local/canisters/foo/service.did.js +0 -4
- package/tests/build/success/.dfx/local/lsp/ucwa4-rx777-77774-qaada-cai.did +0 -3
- package/tests/build/success/.dfx/local/lsp/ulvla-h7777-77774-qaacq-cai.did +0 -3
- package/tests/build/success/.dfx/local/network-id +0 -4
- package/wasm/pkg/bundler/package.json +0 -20
- package/wasm/pkg/bundler/wasm.d.ts +0 -3
- package/wasm/pkg/bundler/wasm.js +0 -5
- package/wasm/pkg/bundler/wasm_bg.js +0 -93
- package/wasm/pkg/bundler/wasm_bg.wasm +0 -0
- package/wasm/pkg/bundler/wasm_bg.wasm.d.ts +0 -8
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { relative } from "node:path";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { execa } from "execa";
|
|
4
|
+
import { cliError } from "../error.js";
|
|
5
|
+
import { autofixMotoko } from "../helpers/autofix-motoko.js";
|
|
6
|
+
import { getMocSemVer } from "../helpers/get-moc-version.js";
|
|
7
|
+
import { sourcesArgs } from "./sources.js";
|
|
8
|
+
import { toolchain } from "./toolchain/index.js";
|
|
9
|
+
|
|
10
|
+
const MOC_ALL_LIBS_MIN_VERSION = "1.3.0";
|
|
11
|
+
|
|
12
|
+
function supportsAllLibsFlag(): boolean {
|
|
13
|
+
const version = getMocSemVer();
|
|
14
|
+
return version ? version.compare(MOC_ALL_LIBS_MIN_VERSION) >= 0 : false;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface CheckOptions {
|
|
18
|
+
verbose: boolean;
|
|
19
|
+
fix: boolean;
|
|
20
|
+
extraArgs: string[];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export async function check(
|
|
24
|
+
files: string | string[],
|
|
25
|
+
options: Partial<CheckOptions> = {},
|
|
26
|
+
): Promise<void> {
|
|
27
|
+
const fileList = Array.isArray(files) ? files : [files];
|
|
28
|
+
|
|
29
|
+
if (fileList.length === 0) {
|
|
30
|
+
cliError("No Motoko files specified for checking");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const mocPath = await toolchain.bin("moc", { fallback: true });
|
|
34
|
+
const sources = await sourcesArgs();
|
|
35
|
+
|
|
36
|
+
// --all-libs enables richer diagnostics with edit suggestions from moc (requires moc >= 1.3.0)
|
|
37
|
+
const allLibs = supportsAllLibsFlag();
|
|
38
|
+
|
|
39
|
+
if (!allLibs) {
|
|
40
|
+
console.log(
|
|
41
|
+
chalk.yellow(
|
|
42
|
+
`moc < ${MOC_ALL_LIBS_MIN_VERSION}: some diagnostic hints may be missing`,
|
|
43
|
+
),
|
|
44
|
+
);
|
|
45
|
+
} else if (options.verbose) {
|
|
46
|
+
console.log(
|
|
47
|
+
chalk.blue("check"),
|
|
48
|
+
chalk.gray("Using --all-libs for richer diagnostics"),
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const mocArgs = [
|
|
53
|
+
"--check",
|
|
54
|
+
...(allLibs ? ["--all-libs"] : []),
|
|
55
|
+
...sources.flat(),
|
|
56
|
+
...(options.extraArgs ?? []),
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
if (options.fix) {
|
|
60
|
+
if (options.verbose) {
|
|
61
|
+
console.log(chalk.blue("check"), chalk.gray("Attempting to fix files"));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const fixResult = await autofixMotoko(mocPath, fileList, mocArgs);
|
|
65
|
+
if (fixResult) {
|
|
66
|
+
for (const [file, codes] of fixResult.fixedFiles) {
|
|
67
|
+
const unique = [...new Set(codes)].sort();
|
|
68
|
+
const n = codes.length;
|
|
69
|
+
const rel = relative(process.cwd(), file);
|
|
70
|
+
console.log(
|
|
71
|
+
chalk.green(
|
|
72
|
+
`Fixed ${rel} (${n} ${n === 1 ? "fix" : "fixes"}: ${unique.join(", ")})`,
|
|
73
|
+
),
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
const fileCount = fixResult.fixedFiles.size;
|
|
77
|
+
console.log(
|
|
78
|
+
chalk.green(
|
|
79
|
+
`\n✓ ${fixResult.totalFixCount} ${fixResult.totalFixCount === 1 ? "fix" : "fixes"} applied to ${fileCount} ${fileCount === 1 ? "file" : "files"}`,
|
|
80
|
+
),
|
|
81
|
+
);
|
|
82
|
+
} else {
|
|
83
|
+
if (options.verbose) {
|
|
84
|
+
console.log(chalk.yellow("No fixes were needed"));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
for (const file of fileList) {
|
|
90
|
+
try {
|
|
91
|
+
const args = [file, ...mocArgs];
|
|
92
|
+
if (options.verbose) {
|
|
93
|
+
console.log(chalk.blue("check"), chalk.gray("Running moc:"));
|
|
94
|
+
console.log(chalk.gray(mocPath, JSON.stringify(args)));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const result = await execa(mocPath, args, {
|
|
98
|
+
stdio: "inherit",
|
|
99
|
+
reject: false,
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
if (result.exitCode !== 0) {
|
|
103
|
+
cliError(
|
|
104
|
+
`✗ Check failed for file ${file} (exit code: ${result.exitCode})`,
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (!options.fix) {
|
|
109
|
+
console.log(chalk.green(`✓ ${file}`));
|
|
110
|
+
}
|
|
111
|
+
} catch (err: any) {
|
|
112
|
+
cliError(
|
|
113
|
+
`Error while checking ${file}${err?.message ? `\n${err.message}` : ""}`,
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
package/commands/format.ts
CHANGED
|
@@ -8,19 +8,7 @@ import motokoPlugin from "prettier-plugin-motoko";
|
|
|
8
8
|
import { getRootDir } from "../mops.js";
|
|
9
9
|
import { absToRel } from "./test/utils.js";
|
|
10
10
|
import { parallel } from "../parallel.js";
|
|
11
|
-
|
|
12
|
-
let ignore = [
|
|
13
|
-
"**/node_modules/**",
|
|
14
|
-
"**/.mops/**",
|
|
15
|
-
"**/.vessel/**",
|
|
16
|
-
"**/.git/**",
|
|
17
|
-
"**/dist/**",
|
|
18
|
-
];
|
|
19
|
-
|
|
20
|
-
let globConfig = {
|
|
21
|
-
nocase: true,
|
|
22
|
-
ignore: ignore,
|
|
23
|
-
};
|
|
11
|
+
import { MOTOKO_GLOB_CONFIG } from "../constants.js";
|
|
24
12
|
|
|
25
13
|
type FormatOptions = {
|
|
26
14
|
check: boolean;
|
|
@@ -45,13 +33,10 @@ export async function format(
|
|
|
45
33
|
let startTime = Date.now();
|
|
46
34
|
|
|
47
35
|
let rootDir = getRootDir();
|
|
48
|
-
let globStr = "**/*.mo";
|
|
49
|
-
if (filter) {
|
|
50
|
-
globStr = `**/*${filter}*.mo`;
|
|
51
|
-
}
|
|
36
|
+
let globStr = filter ? `**/*${filter}*.mo` : "**/*.mo";
|
|
52
37
|
|
|
53
38
|
let files = globSync(path.join(rootDir, globStr), {
|
|
54
|
-
...
|
|
39
|
+
...MOTOKO_GLOB_CONFIG,
|
|
55
40
|
cwd: rootDir,
|
|
56
41
|
});
|
|
57
42
|
let invalidFiles = 0;
|
package/commands/lint.ts
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { execa } from "execa";
|
|
3
|
+
import { globSync } from "glob";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { cliError } from "../error.js";
|
|
6
|
+
import { getRootDir, readConfig } from "../mops.js";
|
|
7
|
+
import { toolchain } from "./toolchain/index.js";
|
|
8
|
+
import { MOTOKO_GLOB_CONFIG } from "../constants.js";
|
|
9
|
+
import { existsSync } from "node:fs";
|
|
10
|
+
|
|
11
|
+
export interface LintOptions {
|
|
12
|
+
verbose: boolean;
|
|
13
|
+
fix: boolean;
|
|
14
|
+
rules?: string[];
|
|
15
|
+
extraArgs: string[];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export async function lint(
|
|
19
|
+
filter: string | undefined,
|
|
20
|
+
options: Partial<LintOptions>,
|
|
21
|
+
): Promise<void> {
|
|
22
|
+
let config = readConfig();
|
|
23
|
+
let rootDir = getRootDir();
|
|
24
|
+
let lintokoBinPath = config.toolchain?.lintoko
|
|
25
|
+
? await toolchain.bin("lintoko")
|
|
26
|
+
: "lintoko";
|
|
27
|
+
|
|
28
|
+
let globStr = filter ? `**/*${filter}*.mo` : "**/*.mo";
|
|
29
|
+
let filesToLint = globSync(path.join(rootDir, globStr), {
|
|
30
|
+
...MOTOKO_GLOB_CONFIG,
|
|
31
|
+
cwd: rootDir,
|
|
32
|
+
});
|
|
33
|
+
if (filesToLint.length === 0) {
|
|
34
|
+
cliError(`No files found for filter '${filter}'`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let args: string[] = [];
|
|
38
|
+
if (options.verbose) {
|
|
39
|
+
args.push("--verbose");
|
|
40
|
+
}
|
|
41
|
+
if (options.fix) {
|
|
42
|
+
args.push("--fix");
|
|
43
|
+
}
|
|
44
|
+
const rules =
|
|
45
|
+
options.rules && options.rules.length > 0
|
|
46
|
+
? options.rules
|
|
47
|
+
: ["lint", "lints"].filter((d) => existsSync(path.join(rootDir, d)));
|
|
48
|
+
rules.forEach((rule) => args.push("--rules", rule));
|
|
49
|
+
|
|
50
|
+
if (config.lint?.args) {
|
|
51
|
+
if (typeof config.lint.args === "string") {
|
|
52
|
+
cliError(
|
|
53
|
+
`[lint] config 'args' should be an array of strings in mops.toml config file`,
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
args.push(...config.lint.args);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (options.extraArgs && options.extraArgs.length > 0) {
|
|
60
|
+
args.push(...options.extraArgs);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
args.push(...filesToLint);
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
if (options.verbose) {
|
|
67
|
+
console.log(chalk.blue("lint"), chalk.gray("Running lintoko:"));
|
|
68
|
+
console.log(chalk.gray(lintokoBinPath));
|
|
69
|
+
console.log(chalk.gray(JSON.stringify(args)));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const result = await execa(lintokoBinPath, args, {
|
|
73
|
+
cwd: rootDir,
|
|
74
|
+
stdio: "inherit",
|
|
75
|
+
reject: false,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
if (result.exitCode !== 0) {
|
|
79
|
+
cliError(`Lint failed with exit code ${result.exitCode}`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (options.fix) {
|
|
83
|
+
console.log(chalk.green("✓ Lint fixes applied"));
|
|
84
|
+
} else {
|
|
85
|
+
console.log(chalk.green("✓ Lint succeeded"));
|
|
86
|
+
}
|
|
87
|
+
} catch (err: any) {
|
|
88
|
+
cliError(
|
|
89
|
+
`Error while running lintoko${err?.message ? `\n${err.message}` : ""}`,
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
}
|
package/commands/sync.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { add } from "./add.js";
|
|
|
7
7
|
import { remove } from "./remove.js";
|
|
8
8
|
import { checkIntegrity } from "../integrity.js";
|
|
9
9
|
import { getMocPath } from "../helpers/get-moc-path.js";
|
|
10
|
+
import { MOTOKO_IGNORE_PATTERNS } from "../constants.js";
|
|
10
11
|
|
|
11
12
|
type SyncOptions = {
|
|
12
13
|
lock?: "update" | "ignore";
|
|
@@ -43,13 +44,6 @@ export async function sync({ lock }: SyncOptions = {}) {
|
|
|
43
44
|
await checkIntegrity(lock);
|
|
44
45
|
}
|
|
45
46
|
|
|
46
|
-
let ignore = [
|
|
47
|
-
"**/node_modules/**",
|
|
48
|
-
"**/.vessel/**",
|
|
49
|
-
"**/.git/**",
|
|
50
|
-
"**/.mops/**",
|
|
51
|
-
];
|
|
52
|
-
|
|
53
47
|
async function getUsedPackages(): Promise<string[]> {
|
|
54
48
|
let rootDir = getRootDir();
|
|
55
49
|
let mocPath = getMocPath();
|
|
@@ -57,7 +51,7 @@ async function getUsedPackages(): Promise<string[]> {
|
|
|
57
51
|
let files = globSync("**/*.mo", {
|
|
58
52
|
cwd: rootDir,
|
|
59
53
|
nocase: true,
|
|
60
|
-
ignore:
|
|
54
|
+
ignore: MOTOKO_IGNORE_PATTERNS,
|
|
61
55
|
});
|
|
62
56
|
|
|
63
57
|
let packages: Set<string> = new Set();
|
package/commands/test/test.ts
CHANGED
|
@@ -32,18 +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
|
-
|
|
36
|
-
let ignore = [
|
|
37
|
-
"**/node_modules/**",
|
|
38
|
-
"**/.mops/**",
|
|
39
|
-
"**/.vessel/**",
|
|
40
|
-
"**/.git/**",
|
|
41
|
-
];
|
|
42
|
-
|
|
43
|
-
let globConfig = {
|
|
44
|
-
nocase: true,
|
|
45
|
-
ignore: ignore,
|
|
46
|
-
};
|
|
35
|
+
import { MOTOKO_GLOB_CONFIG, MOTOKO_IGNORE_PATTERNS } from "../../constants.js";
|
|
47
36
|
|
|
48
37
|
type ReporterName = "verbose" | "files" | "compact" | "silent";
|
|
49
38
|
type ReplicaName = "dfx" | "pocket-ic" | "dfx-pocket-ic";
|
|
@@ -146,7 +135,7 @@ export async function test(filter = "", options: Partial<TestOptions> = {}) {
|
|
|
146
135
|
let watcher = chokidar.watch(
|
|
147
136
|
[path.join(rootDir, "**/*.mo"), path.join(rootDir, "mops.toml")],
|
|
148
137
|
{
|
|
149
|
-
ignored:
|
|
138
|
+
ignored: MOTOKO_IGNORE_PATTERNS,
|
|
150
139
|
ignoreInitial: true,
|
|
151
140
|
},
|
|
152
141
|
);
|
|
@@ -200,15 +189,14 @@ export async function testWithReporter(
|
|
|
200
189
|
): Promise<boolean> {
|
|
201
190
|
let rootDir = getRootDir();
|
|
202
191
|
let files: string[] = [];
|
|
203
|
-
let libFiles = globSync("**/test?(s)/lib.mo",
|
|
192
|
+
let libFiles = globSync("**/test?(s)/lib.mo", MOTOKO_GLOB_CONFIG);
|
|
204
193
|
if (libFiles[0]) {
|
|
205
194
|
files = [libFiles[0]];
|
|
206
195
|
} else {
|
|
207
|
-
let globStr =
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
files = globSync(path.join(rootDir, globStr), globConfig);
|
|
196
|
+
let globStr = filter
|
|
197
|
+
? `**/test?(s)/**/*${filter}*.mo`
|
|
198
|
+
: "**/test?(s)/**/*.test.mo";
|
|
199
|
+
files = globSync(path.join(rootDir, globStr), MOTOKO_GLOB_CONFIG);
|
|
212
200
|
}
|
|
213
201
|
if (!files.length) {
|
|
214
202
|
if (filter) {
|
|
@@ -19,6 +19,8 @@ import { checkRequirements } from "../../check-requirements.js";
|
|
|
19
19
|
import * as moc from "./moc.js";
|
|
20
20
|
import * as pocketIc from "./pocket-ic.js";
|
|
21
21
|
import * as wasmtime from "./wasmtime.js";
|
|
22
|
+
import * as lintoko from "./lintoko.js";
|
|
23
|
+
import { FILE_PATH_REGEX } from "../../constants.js";
|
|
22
24
|
|
|
23
25
|
function getToolUtils(tool: Tool) {
|
|
24
26
|
if (tool === "moc") {
|
|
@@ -27,13 +29,15 @@ function getToolUtils(tool: Tool) {
|
|
|
27
29
|
return pocketIc;
|
|
28
30
|
} else if (tool === "wasmtime") {
|
|
29
31
|
return wasmtime;
|
|
32
|
+
} else if (tool === "lintoko") {
|
|
33
|
+
return lintoko;
|
|
30
34
|
} else {
|
|
31
35
|
console.error(`Unknown tool '${tool}'`);
|
|
32
36
|
process.exit(1);
|
|
33
37
|
}
|
|
34
38
|
}
|
|
35
39
|
|
|
36
|
-
async function
|
|
40
|
+
async function checkToolchainInited({ strict = false } = {}): Promise<boolean> {
|
|
37
41
|
// auto init in CI
|
|
38
42
|
if (process.env.CI) {
|
|
39
43
|
await init({ silent: true });
|
|
@@ -57,10 +61,12 @@ async function ensureToolchainInited({ strict = true } = {}) {
|
|
|
57
61
|
return true;
|
|
58
62
|
}
|
|
59
63
|
} catch {}
|
|
60
|
-
|
|
61
|
-
|
|
64
|
+
process.stderr.write(
|
|
65
|
+
`${chalk.yellow(
|
|
66
|
+
'Toolchain management is not initialized. Run "mops toolchain init" to use with dfx.',
|
|
67
|
+
)}\n`,
|
|
62
68
|
);
|
|
63
|
-
|
|
69
|
+
return false;
|
|
64
70
|
}
|
|
65
71
|
|
|
66
72
|
// update shell config files to set DFX_MOC_PATH to moc-wrapper
|
|
@@ -216,6 +222,9 @@ async function installAll({ silent = false, verbose = false } = {}) {
|
|
|
216
222
|
verbose,
|
|
217
223
|
});
|
|
218
224
|
}
|
|
225
|
+
if (config.toolchain?.lintoko) {
|
|
226
|
+
await download("lintoko", config.toolchain.lintoko, { silent, verbose });
|
|
227
|
+
}
|
|
219
228
|
|
|
220
229
|
if (!silent) {
|
|
221
230
|
logUpdate.clear();
|
|
@@ -265,7 +274,7 @@ async function promptVersion(tool: Tool): Promise<string> {
|
|
|
265
274
|
// download binary and set version in mops.toml
|
|
266
275
|
async function use(tool: Tool, version?: string) {
|
|
267
276
|
if (tool === "moc") {
|
|
268
|
-
await
|
|
277
|
+
await checkToolchainInited();
|
|
269
278
|
}
|
|
270
279
|
if (!version) {
|
|
271
280
|
version = await promptVersion(tool);
|
|
@@ -299,7 +308,7 @@ async function use(tool: Tool, version?: string) {
|
|
|
299
308
|
// download latest binary and set version in mops.toml
|
|
300
309
|
async function update(tool?: Tool) {
|
|
301
310
|
if (tool === "moc") {
|
|
302
|
-
await
|
|
311
|
+
await checkToolchainInited();
|
|
303
312
|
}
|
|
304
313
|
|
|
305
314
|
let config = readConfig();
|
|
@@ -353,8 +362,12 @@ async function bin(tool: Tool, { fallback = false } = {}): Promise<string> {
|
|
|
353
362
|
let version = config.toolchain?.[tool];
|
|
354
363
|
|
|
355
364
|
if (version) {
|
|
365
|
+
if (version.match(FILE_PATH_REGEX)) {
|
|
366
|
+
return version;
|
|
367
|
+
}
|
|
368
|
+
|
|
356
369
|
if (tool === "moc") {
|
|
357
|
-
await
|
|
370
|
+
await checkToolchainInited();
|
|
358
371
|
}
|
|
359
372
|
|
|
360
373
|
await download(tool, version, { silent: true });
|
|
@@ -385,5 +398,5 @@ export let toolchain = {
|
|
|
385
398
|
update,
|
|
386
399
|
bin,
|
|
387
400
|
installAll,
|
|
388
|
-
|
|
401
|
+
checkToolchainInited,
|
|
389
402
|
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import process from "node:process";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
|
|
5
|
+
import { globalCacheDir } from "../../mops.js";
|
|
6
|
+
import * as toolchainUtils from "./toolchain-utils.js";
|
|
7
|
+
|
|
8
|
+
let cacheDir = path.join(globalCacheDir, "lintoko");
|
|
9
|
+
|
|
10
|
+
export let repo = "caffeinelabs/lintoko";
|
|
11
|
+
|
|
12
|
+
export let getLatestReleaseTag = async () => {
|
|
13
|
+
return toolchainUtils.getLatestReleaseTag(repo);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export let getReleases = async () => {
|
|
17
|
+
return toolchainUtils.getReleases(repo);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export let isCached = (version: string) => {
|
|
21
|
+
let dir = path.join(cacheDir, version);
|
|
22
|
+
return fs.existsSync(dir) && fs.existsSync(path.join(dir, "lintoko"));
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export let download = async (
|
|
26
|
+
version: string,
|
|
27
|
+
{ silent = false, verbose = false } = {},
|
|
28
|
+
) => {
|
|
29
|
+
if (!version) {
|
|
30
|
+
console.error("version is not defined");
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
if (isCached(version)) {
|
|
34
|
+
if (verbose) {
|
|
35
|
+
console.log(`lintoko ${version} is already installed`);
|
|
36
|
+
}
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
let platform =
|
|
41
|
+
process.platform == "darwin" ? "apple-darwin" : "unknown-linux-gnu";
|
|
42
|
+
let arch = process.arch.startsWith("arm") ? "aarch64" : "x86_64";
|
|
43
|
+
let url = `https://github.com/caffeinelabs/lintoko/releases/download/v${version}/lintoko-${arch}-${platform}.tar.xz`;
|
|
44
|
+
|
|
45
|
+
if (verbose && !silent) {
|
|
46
|
+
console.log(`Downloading ${url}`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
await toolchainUtils.downloadAndExtract(
|
|
50
|
+
url,
|
|
51
|
+
path.join(cacheDir, version),
|
|
52
|
+
"lintoko",
|
|
53
|
+
);
|
|
54
|
+
};
|
|
@@ -12,6 +12,8 @@ import { extract as extractTar } from "tar";
|
|
|
12
12
|
|
|
13
13
|
import { getRootDir } from "../../mops.js";
|
|
14
14
|
|
|
15
|
+
export const TOOLCHAINS = ["moc", "wasmtime", "pocket-ic", "lintoko"];
|
|
16
|
+
|
|
15
17
|
export let tryDownloadFile = async (url: string): Promise<Buffer | null> => {
|
|
16
18
|
let res = await fetch(url);
|
|
17
19
|
|
package/constants.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common ignore patterns for glob operations across Motoko files.
|
|
3
|
+
*/
|
|
4
|
+
export const MOTOKO_IGNORE_PATTERNS = [
|
|
5
|
+
"**/node_modules/**",
|
|
6
|
+
"**/.mops/**",
|
|
7
|
+
"**/.vessel/**",
|
|
8
|
+
"**/.git/**",
|
|
9
|
+
"**/dist/**",
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Common glob configuration for Motoko file operations
|
|
14
|
+
*/
|
|
15
|
+
export const MOTOKO_GLOB_CONFIG = {
|
|
16
|
+
nocase: true,
|
|
17
|
+
ignore: MOTOKO_IGNORE_PATTERNS,
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Regex to match a file path for dependency and toolchain versions
|
|
22
|
+
*/
|
|
23
|
+
export const FILE_PATH_REGEX = /^(\.?\.)?\//;
|
|
@@ -3,18 +3,13 @@ import { SemVer } from "semver";
|
|
|
3
3
|
import chalk from "chalk";
|
|
4
4
|
import { getDependencyType, getRootDir, readConfig } from "./mops.js";
|
|
5
5
|
import { resolvePackages } from "./resolve-packages.js";
|
|
6
|
-
import {
|
|
6
|
+
import { getMocSemVer } from "./helpers/get-moc-version.js";
|
|
7
7
|
import { getPackageId } from "./helpers/get-package-id.js";
|
|
8
8
|
export async function checkRequirements({ verbose = false } = {}) {
|
|
9
|
-
let
|
|
10
|
-
|
|
11
|
-
if (!mocVersion) {
|
|
12
|
-
mocVersion = getMocVersion(false);
|
|
13
|
-
}
|
|
14
|
-
if (!mocVersion) {
|
|
9
|
+
let installedMoc = getMocSemVer();
|
|
10
|
+
if (!installedMoc) {
|
|
15
11
|
return;
|
|
16
12
|
}
|
|
17
|
-
let installedMoc = new SemVer(mocVersion);
|
|
18
13
|
let highestRequiredMoc = new SemVer("0.0.0");
|
|
19
14
|
let highestRequiredMocPkgId = "";
|
|
20
15
|
let rootDir = getRootDir();
|
package/dist/cli.js
CHANGED
|
@@ -9,11 +9,13 @@ import { add } from "./commands/add.js";
|
|
|
9
9
|
import { bench } from "./commands/bench.js";
|
|
10
10
|
import { build, DEFAULT_BUILD_OUTPUT_DIR } from "./commands/build.js";
|
|
11
11
|
import { bump } from "./commands/bump.js";
|
|
12
|
+
import { check } from "./commands/check.js";
|
|
12
13
|
import { checkCandid } from "./commands/check-candid.js";
|
|
13
14
|
import { docsCoverage } from "./commands/docs-coverage.js";
|
|
14
15
|
import { docs } from "./commands/docs.js";
|
|
15
16
|
import { format } from "./commands/format.js";
|
|
16
17
|
import { init } from "./commands/init.js";
|
|
18
|
+
import { lint } from "./commands/lint.js";
|
|
17
19
|
import { installAll } from "./commands/install/install-all.js";
|
|
18
20
|
import { addMaintainer, printMaintainers, removeMaintainer, } from "./commands/maintainer.js";
|
|
19
21
|
import { outdated } from "./commands/outdated.js";
|
|
@@ -32,6 +34,7 @@ import { getPrincipal, getUserProp, importPem, setUserProp, } from "./commands/u
|
|
|
32
34
|
import { watch } from "./commands/watch/watch.js";
|
|
33
35
|
import { apiVersion, checkApiCompatibility, checkConfigFile, getNetworkFile, setNetwork, version, } from "./mops.js";
|
|
34
36
|
import { resolvePackages } from "./resolve-packages.js";
|
|
37
|
+
import { TOOLCHAINS } from "./commands/toolchain/toolchain-utils.js";
|
|
35
38
|
events.setMaxListeners(20);
|
|
36
39
|
// Change working directory for `npm run mops`
|
|
37
40
|
let cwd = process.env["MOPS_CWD"];
|
|
@@ -43,6 +46,17 @@ if (fs.existsSync(networkFile)) {
|
|
|
43
46
|
globalThis.MOPS_NETWORK = fs.readFileSync(networkFile).toString() || "ic";
|
|
44
47
|
}
|
|
45
48
|
let program = new Command();
|
|
49
|
+
function parseExtraArgs(variadicArgs) {
|
|
50
|
+
const rawArgs = process.argv.slice(2);
|
|
51
|
+
const dashDashIndex = rawArgs.indexOf("--");
|
|
52
|
+
const extraArgs = dashDashIndex !== -1 ? rawArgs.slice(dashDashIndex + 1) : [];
|
|
53
|
+
const args = variadicArgs
|
|
54
|
+
? extraArgs.length > 0
|
|
55
|
+
? variadicArgs.slice(0, variadicArgs.length - extraArgs.length)
|
|
56
|
+
: variadicArgs
|
|
57
|
+
: [];
|
|
58
|
+
return { extraArgs, args };
|
|
59
|
+
}
|
|
46
60
|
program.name("mops");
|
|
47
61
|
// --version
|
|
48
62
|
program.version(`CLI ${version()}\nAPI ${apiVersion}`, "-v --version");
|
|
@@ -109,7 +123,7 @@ program
|
|
|
109
123
|
return;
|
|
110
124
|
}
|
|
111
125
|
if (options.toolchain) {
|
|
112
|
-
await toolchain.
|
|
126
|
+
await toolchain.checkToolchainInited({ strict: false });
|
|
113
127
|
}
|
|
114
128
|
let ok = await installAll(options);
|
|
115
129
|
if (options.toolchain) {
|
|
@@ -175,7 +189,7 @@ program
|
|
|
175
189
|
installFromLockFile: true,
|
|
176
190
|
});
|
|
177
191
|
}
|
|
178
|
-
await toolchain.
|
|
192
|
+
await toolchain.checkToolchainInited({ strict: false });
|
|
179
193
|
let sourcesArr = await sources(options);
|
|
180
194
|
console.log(sourcesArr.join("\n"));
|
|
181
195
|
});
|
|
@@ -211,17 +225,37 @@ program
|
|
|
211
225
|
.addOption(new Option("--verbose", "Verbose console output"))
|
|
212
226
|
.addOption(new Option("--output, -o <output>", "Output directory").default(DEFAULT_BUILD_OUTPUT_DIR))
|
|
213
227
|
.allowUnknownOption(true) // TODO: restrict unknown before "--"
|
|
214
|
-
.action(async (canisters, options
|
|
228
|
+
.action(async (canisters, options) => {
|
|
215
229
|
checkConfigFile(true);
|
|
216
|
-
const
|
|
230
|
+
const { extraArgs, args } = parseExtraArgs(canisters);
|
|
217
231
|
await installAll({
|
|
218
232
|
silent: true,
|
|
219
233
|
lock: "ignore",
|
|
220
234
|
installFromLockFile: true,
|
|
221
235
|
});
|
|
222
|
-
await build(
|
|
236
|
+
await build(args.length ? args : undefined, {
|
|
223
237
|
...options,
|
|
224
|
-
extraArgs
|
|
238
|
+
extraArgs,
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
// check
|
|
242
|
+
program
|
|
243
|
+
.command("check <files...>")
|
|
244
|
+
.description("Check Motoko entrypoint files for syntax errors and type issues (including transitively imported files)")
|
|
245
|
+
.option("--verbose", "Verbose console output")
|
|
246
|
+
.addOption(new Option("--fix", "Apply autofixes to all files, including transitively imported ones"))
|
|
247
|
+
.allowUnknownOption(true)
|
|
248
|
+
.action(async (files, options) => {
|
|
249
|
+
checkConfigFile(true);
|
|
250
|
+
const { extraArgs, args: fileList } = parseExtraArgs(files);
|
|
251
|
+
await installAll({
|
|
252
|
+
silent: true,
|
|
253
|
+
lock: "ignore",
|
|
254
|
+
installFromLockFile: true,
|
|
255
|
+
});
|
|
256
|
+
await check(fileList, {
|
|
257
|
+
...options,
|
|
258
|
+
extraArgs,
|
|
225
259
|
});
|
|
226
260
|
});
|
|
227
261
|
// check-candid
|
|
@@ -446,7 +480,7 @@ toolchainCommand
|
|
|
446
480
|
toolchainCommand
|
|
447
481
|
.command("use")
|
|
448
482
|
.description("Install specified tool version and update mops.toml")
|
|
449
|
-
.addArgument(new Argument("<tool>").choices(
|
|
483
|
+
.addArgument(new Argument("<tool>").choices(TOOLCHAINS))
|
|
450
484
|
.addArgument(new Argument("[version]"))
|
|
451
485
|
.action(async (tool, version) => {
|
|
452
486
|
if (!checkConfigFile()) {
|
|
@@ -457,7 +491,7 @@ toolchainCommand
|
|
|
457
491
|
toolchainCommand
|
|
458
492
|
.command("update")
|
|
459
493
|
.description("Update specified tool or all tools to the latest version and update mops.toml")
|
|
460
|
-
.addArgument(new Argument("[tool]").choices(
|
|
494
|
+
.addArgument(new Argument("[tool]").choices(TOOLCHAINS))
|
|
461
495
|
.action(async (tool) => {
|
|
462
496
|
if (!checkConfigFile()) {
|
|
463
497
|
process.exit(1);
|
|
@@ -466,8 +500,8 @@ toolchainCommand
|
|
|
466
500
|
});
|
|
467
501
|
toolchainCommand
|
|
468
502
|
.command("bin")
|
|
469
|
-
.description(
|
|
470
|
-
.addArgument(new Argument("<tool>").choices(
|
|
503
|
+
.description(`Get path to the tool binary\n<tool> can be one of ${TOOLCHAINS.map((s) => `"${s}"`).join(", ")}`)
|
|
504
|
+
.addArgument(new Argument("<tool>").choices(TOOLCHAINS))
|
|
471
505
|
.addOption(new Option("--fallback", "Fallback to the moc that comes with dfx if moc is not specified in the [toolchain] section"))
|
|
472
506
|
.action(async (tool, options) => {
|
|
473
507
|
let bin = await toolchain.bin(tool, options);
|
|
@@ -516,6 +550,22 @@ program
|
|
|
516
550
|
process.exit(1);
|
|
517
551
|
}
|
|
518
552
|
});
|
|
553
|
+
// lint
|
|
554
|
+
program
|
|
555
|
+
.command("lint [filter]")
|
|
556
|
+
.description("Lint Motoko code")
|
|
557
|
+
.addOption(new Option("--verbose", "Verbose output"))
|
|
558
|
+
.addOption(new Option("--fix", "Apply fixes"))
|
|
559
|
+
.addOption(new Option("-r, --rules <directory...>", "Directories containing rules (can be used multiple times)"))
|
|
560
|
+
.allowUnknownOption(true)
|
|
561
|
+
.action(async (filter, options) => {
|
|
562
|
+
checkConfigFile(true);
|
|
563
|
+
const { extraArgs } = parseExtraArgs();
|
|
564
|
+
await lint(filter, {
|
|
565
|
+
...options,
|
|
566
|
+
extraArgs,
|
|
567
|
+
});
|
|
568
|
+
});
|
|
519
569
|
// docs
|
|
520
570
|
const docsCommand = new Command("docs").description("Documentation management");
|
|
521
571
|
docsCommand
|