ic-mops 0.45.4-pre.0 → 1.0.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 +19 -1
- package/README.md +1 -1
- package/api/actors.ts +1 -1
- package/bundle/cli.tgz +0 -0
- package/cache.ts +15 -10
- package/cli.ts +27 -27
- package/commands/add.ts +4 -0
- package/commands/bench/bench-canister.mo +34 -8
- package/commands/bench-replica.ts +11 -6
- package/commands/bench.ts +29 -3
- package/commands/publish.ts +1 -1
- package/commands/replica.ts +239 -0
- package/commands/sources.ts +2 -3
- package/commands/test/mmf1.ts +10 -6
- package/commands/test/reporters/compact-reporter.ts +2 -1
- package/commands/test/reporters/files-reporter.ts +3 -2
- package/commands/test/reporters/reporter.ts +2 -1
- package/commands/test/reporters/silent-reporter.ts +2 -1
- package/commands/test/reporters/verbose-reporter.ts +14 -4
- package/commands/test/test.ts +214 -81
- package/commands/user.ts +71 -1
- package/declarations/bench/bench.did +6 -2
- package/declarations/bench/bench.did.d.ts +6 -2
- package/declarations/bench/bench.did.js +6 -2
- package/dist/cache.js +14 -10
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +23 -27
- package/dist/commands/add.js +3 -0
- package/dist/commands/bench/bench-canister.mo +34 -8
- package/dist/commands/bench-replica.d.ts +2 -1
- package/dist/commands/bench-replica.js +10 -6
- package/dist/commands/bench.js +27 -3
- package/dist/commands/publish.js +1 -1
- package/dist/commands/replica.d.ts +59 -0
- package/dist/commands/replica.js +195 -0
- package/dist/commands/sources.d.ts +2 -2
- package/dist/commands/sources.js +2 -3
- package/dist/commands/test/mmf1.d.ts +2 -2
- package/dist/commands/test/mmf1.js +9 -5
- package/dist/commands/test/reporters/compact-reporter.d.ts +2 -1
- package/dist/commands/test/reporters/compact-reporter.js +1 -1
- package/dist/commands/test/reporters/files-reporter.d.ts +2 -1
- package/dist/commands/test/reporters/files-reporter.js +2 -2
- package/dist/commands/test/reporters/reporter.d.ts +2 -1
- package/dist/commands/test/reporters/silent-reporter.d.ts +2 -1
- package/dist/commands/test/reporters/silent-reporter.js +1 -1
- package/dist/commands/test/reporters/verbose-reporter.d.ts +3 -1
- package/dist/commands/test/reporters/verbose-reporter.js +12 -4
- package/dist/commands/test/test.d.ts +10 -8
- package/dist/commands/test/test.js +171 -78
- package/dist/commands/user.d.ts +6 -0
- package/dist/commands/user.js +59 -1
- package/dist/declarations/bench/bench.did +6 -2
- package/dist/declarations/bench/bench.did.d.ts +6 -2
- package/dist/declarations/bench/bench.did.js +6 -2
- package/dist/mops.d.ts +1 -1
- package/dist/mops.js +5 -29
- package/dist/package.json +20 -21
- package/dist/release-cli.js +5 -2
- package/dist/resolve-packages.d.ts +2 -2
- package/dist/resolve-packages.js +29 -7
- package/dist/types.d.ts +1 -0
- package/dist/vessel.js +1 -1
- package/mops.ts +5 -32
- package/package.json +24 -24
- package/release-cli.ts +7 -2
- package/resolve-packages.ts +39 -8
- package/types.ts +3 -1
- package/vessel.ts +1 -1
- package/DEVELOPMENT.md +0 -25
- package/commands/import-identity.ts +0 -62
- package/commands/whoami.ts +0 -12
- package/dist/commands/import-identity.d.ts +0 -5
- package/dist/commands/import-identity.js +0 -51
- package/dist/commands/whoami.d.ts +0 -1
- package/dist/commands/whoami.js +0 -11
package/commands/test/test.ts
CHANGED
|
@@ -3,6 +3,7 @@ import {spawn, ChildProcessWithoutNullStreams} from 'node:child_process';
|
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import fs from 'node:fs';
|
|
5
5
|
import os from 'node:os';
|
|
6
|
+
|
|
6
7
|
import chalk from 'chalk';
|
|
7
8
|
import {globSync} from 'glob';
|
|
8
9
|
import chokidar from 'chokidar';
|
|
@@ -20,6 +21,10 @@ import {FilesReporter} from './reporters/files-reporter.js';
|
|
|
20
21
|
import {CompactReporter} from './reporters/compact-reporter.js';
|
|
21
22
|
import {SilentReporter} from './reporters/silent-reporter.js';
|
|
22
23
|
import {toolchain} from '../toolchain/index.js';
|
|
24
|
+
import {Replica} from '../replica.js';
|
|
25
|
+
import {ActorMethod} from '@dfinity/agent';
|
|
26
|
+
import {PassThrough, Readable} from 'node:stream';
|
|
27
|
+
import {TestMode} from '../../types.js';
|
|
23
28
|
|
|
24
29
|
let ignore = [
|
|
25
30
|
'**/node_modules/**',
|
|
@@ -34,18 +39,60 @@ let globConfig = {
|
|
|
34
39
|
};
|
|
35
40
|
|
|
36
41
|
type ReporterName = 'verbose' | 'files' | 'compact' | 'silent';
|
|
37
|
-
type
|
|
42
|
+
type ReplicaName = 'dfx' | 'pocket-ic';
|
|
43
|
+
|
|
44
|
+
type TestOptions = {
|
|
45
|
+
watch : boolean;
|
|
46
|
+
reporter : ReporterName;
|
|
47
|
+
mode : TestMode;
|
|
48
|
+
replica : ReplicaName;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
let replica = new Replica();
|
|
53
|
+
let replicaStartPromise : Promise<void> | undefined;
|
|
54
|
+
|
|
55
|
+
async function startReplicaOnce(replica : Replica, type : ReplicaName) {
|
|
56
|
+
if (!replicaStartPromise) {
|
|
57
|
+
replicaStartPromise = new Promise((resolve) => {
|
|
58
|
+
replica.start({type, silent: true}).then(resolve);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return replicaStartPromise;
|
|
62
|
+
}
|
|
38
63
|
|
|
39
|
-
export async function test(filter = '',
|
|
64
|
+
export async function test(filter = '', options : Partial<TestOptions> = {}) {
|
|
65
|
+
let config = readConfig();
|
|
40
66
|
let rootDir = getRootDir();
|
|
41
67
|
|
|
42
|
-
|
|
68
|
+
let replicaType = options.replica ?? (config.toolchain?.['pocket-ic'] ? 'pocket-ic' : 'dfx' as ReplicaName);
|
|
69
|
+
replica.type = replicaType;
|
|
70
|
+
|
|
71
|
+
if (options.watch) {
|
|
72
|
+
replica.ttl = 60 * 15; // 15 minutes
|
|
73
|
+
|
|
74
|
+
let sigint = false;
|
|
75
|
+
process.on('SIGINT', () => {
|
|
76
|
+
if (sigint) {
|
|
77
|
+
console.log('Force exit');
|
|
78
|
+
process.exit(0);
|
|
79
|
+
}
|
|
80
|
+
sigint = true;
|
|
81
|
+
|
|
82
|
+
if (replicaStartPromise) {
|
|
83
|
+
console.log('Stopping replica...');
|
|
84
|
+
replica.stop(true).then(() => {
|
|
85
|
+
process.exit(0);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
|
|
43
90
|
// todo: run only changed for *.test.mo?
|
|
44
91
|
// todo: run all for *.mo?
|
|
45
92
|
let run = debounce(async () => {
|
|
46
93
|
console.clear();
|
|
47
94
|
process.stdout.write('\x1Bc');
|
|
48
|
-
await runAll(reporter, filter, mode);
|
|
95
|
+
await runAll(options.reporter, filter, options.mode, replicaType, true);
|
|
49
96
|
console.log('-'.repeat(50));
|
|
50
97
|
console.log('Waiting for file changes...');
|
|
51
98
|
console.log(chalk.gray((`Press ${chalk.gray('Ctrl+C')} to exit.`)));
|
|
@@ -65,7 +112,7 @@ export async function test(filter = '', {watch = false, reporter = 'verbose' as
|
|
|
65
112
|
run();
|
|
66
113
|
}
|
|
67
114
|
else {
|
|
68
|
-
let passed = await runAll(reporter, filter, mode);
|
|
115
|
+
let passed = await runAll(options.reporter, filter, options.mode, replicaType);
|
|
69
116
|
if (!passed) {
|
|
70
117
|
process.exit(1);
|
|
71
118
|
}
|
|
@@ -75,25 +122,12 @@ export async function test(filter = '', {watch = false, reporter = 'verbose' as
|
|
|
75
122
|
let mocPath = '';
|
|
76
123
|
let wasmtimePath = '';
|
|
77
124
|
|
|
78
|
-
|
|
79
|
-
let
|
|
80
|
-
if (reporterName == 'compact') {
|
|
81
|
-
reporter = new CompactReporter;
|
|
82
|
-
}
|
|
83
|
-
else if (reporterName == 'files') {
|
|
84
|
-
reporter = new FilesReporter;
|
|
85
|
-
}
|
|
86
|
-
else if (reporterName == 'silent') {
|
|
87
|
-
reporter = new SilentReporter;
|
|
88
|
-
}
|
|
89
|
-
else {
|
|
90
|
-
reporter = new VerboseReporter;
|
|
91
|
-
}
|
|
92
|
-
let done = await testWithReporter(reporter, filter, mode);
|
|
125
|
+
async function runAll(reporterName : ReporterName | undefined, filter = '', mode : TestMode = 'interpreter', replicaType : ReplicaName, watch = false) : Promise<boolean> {
|
|
126
|
+
let done = await testWithReporter(reporterName, filter, mode, replicaType, watch);
|
|
93
127
|
return done;
|
|
94
128
|
}
|
|
95
129
|
|
|
96
|
-
export async function testWithReporter(
|
|
130
|
+
export async function testWithReporter(reporterName : ReporterName | Reporter | undefined, filter = '', defaultMode : TestMode = 'interpreter', replicaType : ReplicaName, watch = false) : Promise<boolean> {
|
|
97
131
|
let rootDir = getRootDir();
|
|
98
132
|
let files : string[] = [];
|
|
99
133
|
let libFiles = globSync('**/test?(s)/lib.mo', globConfig);
|
|
@@ -117,6 +151,31 @@ export async function testWithReporter(reporter : Reporter, filter = '', mode :
|
|
|
117
151
|
return false;
|
|
118
152
|
}
|
|
119
153
|
|
|
154
|
+
|
|
155
|
+
let reporter : Reporter;
|
|
156
|
+
|
|
157
|
+
if (!reporterName || typeof reporterName === 'string') {
|
|
158
|
+
if (!reporterName) {
|
|
159
|
+
reporterName = files.length > 1 ? 'files' : 'verbose';
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (reporterName == 'compact') {
|
|
163
|
+
reporter = new CompactReporter;
|
|
164
|
+
}
|
|
165
|
+
else if (reporterName == 'files') {
|
|
166
|
+
reporter = new FilesReporter;
|
|
167
|
+
}
|
|
168
|
+
else if (reporterName == 'silent') {
|
|
169
|
+
reporter = new SilentReporter;
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
reporter = new VerboseReporter;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
reporter = reporterName;
|
|
177
|
+
}
|
|
178
|
+
|
|
120
179
|
reporter.addFiles(files);
|
|
121
180
|
|
|
122
181
|
let config = readConfig();
|
|
@@ -126,14 +185,25 @@ export async function testWithReporter(reporter : Reporter, filter = '', mode :
|
|
|
126
185
|
mocPath = await toolchain.bin('moc', {fallback: true});
|
|
127
186
|
}
|
|
128
187
|
|
|
129
|
-
let
|
|
130
|
-
|
|
188
|
+
let testTempDir = path.join(getRootDir(), '.mops/.test/');
|
|
189
|
+
replica.dir = testTempDir;
|
|
190
|
+
|
|
191
|
+
fs.mkdirSync(testTempDir, {recursive: true});
|
|
131
192
|
|
|
132
193
|
await parallel(os.cpus().length, files, async (file : string) => {
|
|
133
194
|
let mmf = new MMF1('store', absToRel(file));
|
|
134
|
-
let wasiMode = mode === 'wasi' || fs.readFileSync(file, 'utf8').startsWith('// @testmode wasi');
|
|
135
195
|
|
|
136
|
-
|
|
196
|
+
// mode overrides
|
|
197
|
+
let lines = fs.readFileSync(file, 'utf8').split('\n');
|
|
198
|
+
let mode = defaultMode;
|
|
199
|
+
if (lines.includes('// @testmode wasi')) {
|
|
200
|
+
mode = 'wasi';
|
|
201
|
+
}
|
|
202
|
+
else if (lines.includes('actor {') || lines.includes('// @testmode replica')) {
|
|
203
|
+
mode = 'replica';
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (mode === 'wasi' && !wasmtimePath) {
|
|
137
207
|
// ensure wasmtime is installed or specified in config
|
|
138
208
|
if (config.toolchain?.wasmtime) {
|
|
139
209
|
wasmtimePath = await toolchain.bin('wasmtime');
|
|
@@ -149,9 +219,14 @@ export async function testWithReporter(reporter : Reporter, filter = '', mode :
|
|
|
149
219
|
let promise = new Promise<void>((resolve) => {
|
|
150
220
|
let mocArgs = ['--hide-warnings', '--error-detail=2', ...sourcesArr.join(' ').split(' '), file].filter(x => x);
|
|
151
221
|
|
|
222
|
+
// interpret
|
|
223
|
+
if (mode === 'interpreter') {
|
|
224
|
+
let proc = spawn(mocPath, ['-r', '-ref-system-api', ...mocArgs]);
|
|
225
|
+
pipeMMF(proc, mmf).then(resolve);
|
|
226
|
+
}
|
|
152
227
|
// build and run wasm
|
|
153
|
-
if (
|
|
154
|
-
let wasmFile = `${path.join(
|
|
228
|
+
else if (mode === 'wasi') {
|
|
229
|
+
let wasmFile = `${path.join(testTempDir, path.parse(file).name)}.wasm`;
|
|
155
230
|
|
|
156
231
|
// build
|
|
157
232
|
let buildProc = spawn(mocPath, [`-o=${wasmFile}`, '-wasi-system-api', ...mocArgs]);
|
|
@@ -173,13 +248,8 @@ export async function testWithReporter(reporter : Reporter, filter = '', mode :
|
|
|
173
248
|
];
|
|
174
249
|
}
|
|
175
250
|
else {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
'--enable-cranelift-nan-canonicalization',
|
|
179
|
-
'--wasm-features',
|
|
180
|
-
'multi-memory,bulk-memory',
|
|
181
|
-
wasmFile,
|
|
182
|
-
];
|
|
251
|
+
console.error(chalk.red('Minimum wasmtime version is 14.0.0. Please update wasmtime to the latest version'));
|
|
252
|
+
process.exit(1);
|
|
183
253
|
}
|
|
184
254
|
|
|
185
255
|
let proc = spawn(wasmtimePath, wasmtimeArgs);
|
|
@@ -188,72 +258,135 @@ export async function testWithReporter(reporter : Reporter, filter = '', mode :
|
|
|
188
258
|
fs.rmSync(wasmFile, {force: true});
|
|
189
259
|
}).then(resolve);
|
|
190
260
|
}
|
|
191
|
-
//
|
|
192
|
-
else {
|
|
193
|
-
|
|
194
|
-
|
|
261
|
+
// build and execute in replica
|
|
262
|
+
else if (mode === 'replica') {
|
|
263
|
+
// mmf.strategy = 'print'; // because we run replica tests one-by-one
|
|
264
|
+
|
|
265
|
+
let wasmFile = `${path.join(testTempDir, path.parse(file).name)}.wasm`;
|
|
266
|
+
|
|
267
|
+
// build
|
|
268
|
+
let buildProc = spawn(mocPath, [`-o=${wasmFile}`, ...mocArgs]);
|
|
269
|
+
|
|
270
|
+
pipeMMF(buildProc, mmf).then(async () => {
|
|
271
|
+
if (mmf.failed > 0) {
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
await startReplicaOnce(replica, replicaType);
|
|
276
|
+
|
|
277
|
+
let canisterName = path.parse(file).name;
|
|
278
|
+
let idlFactory = ({IDL} : any) => {
|
|
279
|
+
return IDL.Service({'runTests': IDL.Func([], [], [])});
|
|
280
|
+
};
|
|
281
|
+
interface _SERVICE {'runTests' : ActorMethod<[], undefined>;}
|
|
282
|
+
|
|
283
|
+
let {stream} = await replica.deploy(canisterName, wasmFile, idlFactory);
|
|
284
|
+
|
|
285
|
+
pipeStdoutToMMF(stream, mmf);
|
|
286
|
+
|
|
287
|
+
let actor = await replica.getActor(canisterName) as _SERVICE;
|
|
288
|
+
|
|
289
|
+
try {
|
|
290
|
+
if (globalThis.mopsReplicaTestRunning) {
|
|
291
|
+
await new Promise<void>((resolve) => {
|
|
292
|
+
let timerId = setInterval(() => {
|
|
293
|
+
if (!globalThis.mopsReplicaTestRunning) {
|
|
294
|
+
resolve();
|
|
295
|
+
clearInterval(timerId);
|
|
296
|
+
}
|
|
297
|
+
}, Math.random() * 1000 |0);
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
globalThis.mopsReplicaTestRunning = true;
|
|
302
|
+
await actor.runTests();
|
|
303
|
+
globalThis.mopsReplicaTestRunning = false;
|
|
304
|
+
|
|
305
|
+
mmf.pass();
|
|
306
|
+
}
|
|
307
|
+
catch (e : any) {
|
|
308
|
+
let stderrStream = new PassThrough();
|
|
309
|
+
pipeStderrToMMF(stderrStream, mmf, path.dirname(file));
|
|
310
|
+
stderrStream.write(e.message);
|
|
311
|
+
}
|
|
312
|
+
}).finally(async () => {
|
|
313
|
+
fs.rmSync(wasmFile, {force: true});
|
|
314
|
+
}).then(resolve);
|
|
195
315
|
}
|
|
196
316
|
});
|
|
197
317
|
|
|
198
|
-
reporter.addRun(file, mmf, promise,
|
|
318
|
+
reporter.addRun(file, mmf, promise, mode);
|
|
199
319
|
|
|
200
320
|
await promise;
|
|
201
321
|
});
|
|
202
322
|
|
|
203
|
-
|
|
323
|
+
if (replicaStartPromise && !watch) {
|
|
324
|
+
await replica.stop();
|
|
325
|
+
fs.rmSync(testTempDir, {recursive: true, force: true});
|
|
326
|
+
}
|
|
327
|
+
|
|
204
328
|
return reporter.done();
|
|
205
329
|
}
|
|
206
330
|
|
|
207
|
-
function
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
if (line) {
|
|
214
|
-
mmf.parseLine(line);
|
|
215
|
-
}
|
|
331
|
+
function pipeStdoutToMMF(stdout : Readable, mmf : MMF1) {
|
|
332
|
+
stdout.on('data', (data) => {
|
|
333
|
+
for (let line of data.toString().split('\n')) {
|
|
334
|
+
line = line.trim();
|
|
335
|
+
if (line) {
|
|
336
|
+
mmf.parseLine(line);
|
|
216
337
|
}
|
|
217
|
-
}
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
function pipeStderrToMMF(stderr : Readable, mmf : MMF1, dir = '') {
|
|
343
|
+
stderr.on('data', (data) => {
|
|
344
|
+
let text : string = data.toString().trim();
|
|
345
|
+
let failedLine = '';
|
|
346
|
+
|
|
347
|
+
text = text.replace(/([\w+._/-]+):(\d+).(\d+)(-\d+.\d+)/g, (_m0, m1 : string, m2 : string, m3 : string) => {
|
|
348
|
+
// change absolute file path to relative
|
|
349
|
+
// change :line:col-line:col to :line:col to work in vscode
|
|
350
|
+
let res = `${absToRel(m1)}:${m2}:${m3}`;
|
|
351
|
+
let file = path.join(dir, m1);
|
|
218
352
|
|
|
219
|
-
|
|
220
|
-
proc.stderr.on('data', (data) => {
|
|
221
|
-
let text : string = data.toString().trim();
|
|
222
|
-
let failedLine = '';
|
|
223
|
-
text = text.replace(/([\w+._/-]+):(\d+).(\d+)(-\d+.\d+)/g, (_m0, m1 : string, m2 : string, m3 : string) => {
|
|
224
|
-
// change absolute file path to relative
|
|
225
|
-
// change :line:col-line:col to :line:col to work in vscode
|
|
226
|
-
let res = `${absToRel(m1)}:${m2}:${m3}`;
|
|
227
|
-
|
|
228
|
-
if (!fs.existsSync(m1)) {
|
|
229
|
-
return res;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// show failed line
|
|
233
|
-
let content = fs.readFileSync(m1);
|
|
234
|
-
let lines = content.toString().split('\n') || [];
|
|
235
|
-
failedLine += chalk.dim('\n ...');
|
|
236
|
-
let lineBefore = lines[+m2 - 2];
|
|
237
|
-
if (lineBefore) {
|
|
238
|
-
failedLine += chalk.dim(`\n ${+m2 - 1}\t| ${lineBefore.replaceAll('\t', ' ')}`);
|
|
239
|
-
}
|
|
240
|
-
failedLine += `\n${chalk.redBright`->`} ${m2}\t| ${lines[+m2 - 1]?.replaceAll('\t', ' ')}`;
|
|
241
|
-
if (lines.length > +m2) {
|
|
242
|
-
failedLine += chalk.dim(`\n ${+m2 + 1}\t| ${lines[+m2]?.replaceAll('\t', ' ')}`);
|
|
243
|
-
}
|
|
244
|
-
failedLine += chalk.dim('\n ...');
|
|
353
|
+
if (!fs.existsSync(file)) {
|
|
245
354
|
return res;
|
|
246
|
-
});
|
|
247
|
-
if (failedLine) {
|
|
248
|
-
text += failedLine;
|
|
249
355
|
}
|
|
250
|
-
|
|
356
|
+
|
|
357
|
+
// show failed line
|
|
358
|
+
let content = fs.readFileSync(file);
|
|
359
|
+
let lines = content.toString().split('\n') || [];
|
|
360
|
+
|
|
361
|
+
failedLine += chalk.dim('\n ...');
|
|
362
|
+
|
|
363
|
+
let lineBefore = lines[+m2 - 2];
|
|
364
|
+
if (lineBefore) {
|
|
365
|
+
failedLine += chalk.dim(`\n ${+m2 - 1}\t| ${lineBefore.replaceAll('\t', ' ')}`);
|
|
366
|
+
}
|
|
367
|
+
failedLine += `\n${chalk.redBright`->`} ${m2}\t| ${lines[+m2 - 1]?.replaceAll('\t', ' ')}`;
|
|
368
|
+
if (lines.length > +m2) {
|
|
369
|
+
failedLine += chalk.dim(`\n ${+m2 + 1}\t| ${lines[+m2]?.replaceAll('\t', ' ')}`);
|
|
370
|
+
}
|
|
371
|
+
failedLine += chalk.dim('\n ...');
|
|
372
|
+
return res;
|
|
251
373
|
});
|
|
374
|
+
if (failedLine) {
|
|
375
|
+
text += failedLine;
|
|
376
|
+
}
|
|
377
|
+
mmf.fail(text);
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
function pipeMMF(proc : ChildProcessWithoutNullStreams, mmf : MMF1) {
|
|
382
|
+
return new Promise<void>((resolve) => {
|
|
383
|
+
pipeStdoutToMMF(proc.stdout, mmf);
|
|
384
|
+
pipeStderrToMMF(proc.stderr, mmf);
|
|
252
385
|
|
|
253
386
|
// exit
|
|
254
387
|
proc.on('close', (code) => {
|
|
255
388
|
if (code === 0) {
|
|
256
|
-
mmf.pass();
|
|
389
|
+
mmf.strategy !== 'print' && mmf.pass();
|
|
257
390
|
}
|
|
258
391
|
else if (code !== 1) {
|
|
259
392
|
mmf.fail(`unknown exit code: ${code}`);
|
package/commands/user.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import process from 'node:process';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
-
import
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import {Buffer} from 'node:buffer';
|
|
6
|
+
import prompts from 'prompts';
|
|
7
|
+
import {deleteSync} from 'del';
|
|
4
8
|
import {mainActor} from '../api/actors.js';
|
|
9
|
+
import {getIdentity, globalConfigDir} from '../mops.js';
|
|
10
|
+
import {encrypt} from '../pem.js';
|
|
5
11
|
|
|
6
12
|
export async function getUserProp(prop : string) {
|
|
7
13
|
let actor = await mainActor();
|
|
@@ -26,4 +32,68 @@ export async function setUserProp(prop : string, value : string) {
|
|
|
26
32
|
else {
|
|
27
33
|
console.log(chalk.red('Error: ') + res.err);
|
|
28
34
|
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function getPrincipal() {
|
|
38
|
+
let identity = await getIdentity();
|
|
39
|
+
if (identity) {
|
|
40
|
+
console.log(identity.getPrincipal().toText());
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
console.log(chalk.red('Error: ') + 'identity not found. Run ' + chalk.greenBright('mops user import') + ' command.');
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
type ImportIdentityOptions = {
|
|
48
|
+
encrypt : boolean;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export async function importPem(data : string, options : ImportIdentityOptions = {encrypt: true}) {
|
|
52
|
+
try {
|
|
53
|
+
if (!fs.existsSync(globalConfigDir)) {
|
|
54
|
+
fs.mkdirSync(globalConfigDir);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let password = '';
|
|
58
|
+
|
|
59
|
+
if (options.encrypt) {
|
|
60
|
+
let res = await prompts({
|
|
61
|
+
type: 'invisible',
|
|
62
|
+
name: 'password',
|
|
63
|
+
message: 'Enter password to encrypt identity.pem',
|
|
64
|
+
});
|
|
65
|
+
password = res.password;
|
|
66
|
+
|
|
67
|
+
if (!password) {
|
|
68
|
+
let res = await prompts({
|
|
69
|
+
type: 'confirm',
|
|
70
|
+
name: 'ok',
|
|
71
|
+
message: 'Are you sure you don\'t want to protect your identity.pem with a password?',
|
|
72
|
+
});
|
|
73
|
+
if (!res.ok) {
|
|
74
|
+
console.log('aborted');
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
let identityPem = path.resolve(globalConfigDir, 'identity.pem');
|
|
81
|
+
let identityPemEncrypted = path.resolve(globalConfigDir, 'identity.pem.encrypted');
|
|
82
|
+
|
|
83
|
+
deleteSync([identityPem, identityPemEncrypted], {force: true});
|
|
84
|
+
|
|
85
|
+
// encrypted
|
|
86
|
+
if (password) {
|
|
87
|
+
let encrypted = await encrypt(Buffer.from(data), password);
|
|
88
|
+
fs.writeFileSync(identityPemEncrypted, encrypted);
|
|
89
|
+
}
|
|
90
|
+
// unencrypted
|
|
91
|
+
else {
|
|
92
|
+
fs.writeFileSync(identityPem, data);
|
|
93
|
+
}
|
|
94
|
+
console.log(chalk.green('Success'));
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
console.log(chalk.red('Error: ') + err);
|
|
98
|
+
}
|
|
29
99
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
type
|
|
1
|
+
type _anon_class_13_1 =
|
|
2
2
|
service {
|
|
3
3
|
getSchema: () -> (BenchSchema) query;
|
|
4
4
|
getStats: () -> (BenchResult) query;
|
|
@@ -19,8 +19,12 @@ type BenchResult =
|
|
|
19
19
|
instructions: int;
|
|
20
20
|
rts_collector_instructions: int;
|
|
21
21
|
rts_heap_size: int;
|
|
22
|
+
rts_logical_stable_memory_size: int;
|
|
22
23
|
rts_memory_size: int;
|
|
23
24
|
rts_mutator_instructions: int;
|
|
25
|
+
rts_reclaimed: int;
|
|
26
|
+
rts_stable_memory_size: int;
|
|
24
27
|
rts_total_allocation: int;
|
|
28
|
+
stable_memory_size: int;
|
|
25
29
|
};
|
|
26
|
-
service : () ->
|
|
30
|
+
service : () -> _anon_class_13_1
|
|
@@ -3,12 +3,16 @@ import type { ActorMethod } from '@dfinity/agent';
|
|
|
3
3
|
import type { IDL } from '@dfinity/candid';
|
|
4
4
|
|
|
5
5
|
export interface BenchResult {
|
|
6
|
+
'rts_stable_memory_size' : bigint,
|
|
7
|
+
'stable_memory_size' : bigint,
|
|
6
8
|
'instructions' : bigint,
|
|
7
9
|
'rts_memory_size' : bigint,
|
|
8
10
|
'rts_total_allocation' : bigint,
|
|
9
11
|
'rts_collector_instructions' : bigint,
|
|
10
12
|
'rts_mutator_instructions' : bigint,
|
|
13
|
+
'rts_logical_stable_memory_size' : bigint,
|
|
11
14
|
'rts_heap_size' : bigint,
|
|
15
|
+
'rts_reclaimed' : bigint,
|
|
12
16
|
}
|
|
13
17
|
export interface BenchSchema {
|
|
14
18
|
'cols' : Array<string>,
|
|
@@ -16,7 +20,7 @@ export interface BenchSchema {
|
|
|
16
20
|
'rows' : Array<string>,
|
|
17
21
|
'description' : string,
|
|
18
22
|
}
|
|
19
|
-
export interface
|
|
23
|
+
export interface _anon_class_13_1 {
|
|
20
24
|
'getSchema' : ActorMethod<[], BenchSchema>,
|
|
21
25
|
'getStats' : ActorMethod<[], BenchResult>,
|
|
22
26
|
'init' : ActorMethod<[], BenchSchema>,
|
|
@@ -24,6 +28,6 @@ export interface _anon_class_10_1 {
|
|
|
24
28
|
'runCellUpdate' : ActorMethod<[bigint, bigint], BenchResult>,
|
|
25
29
|
'runCellUpdateAwait' : ActorMethod<[bigint, bigint], BenchResult>,
|
|
26
30
|
}
|
|
27
|
-
export interface _SERVICE extends
|
|
31
|
+
export interface _SERVICE extends _anon_class_13_1 {}
|
|
28
32
|
export declare const idlFactory: IDL.InterfaceFactory;
|
|
29
33
|
export declare const init: (args: { IDL: typeof IDL }) => IDL.Type[];
|
|
@@ -6,14 +6,18 @@ export const idlFactory = ({ IDL }) => {
|
|
|
6
6
|
'description' : IDL.Text,
|
|
7
7
|
});
|
|
8
8
|
const BenchResult = IDL.Record({
|
|
9
|
+
'rts_stable_memory_size' : IDL.Int,
|
|
10
|
+
'stable_memory_size' : IDL.Int,
|
|
9
11
|
'instructions' : IDL.Int,
|
|
10
12
|
'rts_memory_size' : IDL.Int,
|
|
11
13
|
'rts_total_allocation' : IDL.Int,
|
|
12
14
|
'rts_collector_instructions' : IDL.Int,
|
|
13
15
|
'rts_mutator_instructions' : IDL.Int,
|
|
16
|
+
'rts_logical_stable_memory_size' : IDL.Int,
|
|
14
17
|
'rts_heap_size' : IDL.Int,
|
|
18
|
+
'rts_reclaimed' : IDL.Int,
|
|
15
19
|
});
|
|
16
|
-
const
|
|
20
|
+
const _anon_class_13_1 = IDL.Service({
|
|
17
21
|
'getSchema' : IDL.Func([], [BenchSchema], ['query']),
|
|
18
22
|
'getStats' : IDL.Func([], [BenchResult], ['query']),
|
|
19
23
|
'init' : IDL.Func([], [BenchSchema], []),
|
|
@@ -21,6 +25,6 @@ export const idlFactory = ({ IDL }) => {
|
|
|
21
25
|
'runCellUpdate' : IDL.Func([IDL.Nat, IDL.Nat], [BenchResult], []),
|
|
22
26
|
'runCellUpdateAwait' : IDL.Func([IDL.Nat, IDL.Nat], [BenchResult], []),
|
|
23
27
|
});
|
|
24
|
-
return
|
|
28
|
+
return _anon_class_13_1;
|
|
25
29
|
};
|
|
26
30
|
export const init = ({ IDL }) => { return []; };
|
package/dist/cache.js
CHANGED
|
@@ -2,13 +2,17 @@ import fs from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import ncp from 'ncp';
|
|
4
4
|
import getFolderSize from 'get-folder-size';
|
|
5
|
-
import { getDependencyType, getRootDir, globalCacheDir, parseGithubURL } from './mops.js';
|
|
5
|
+
import { getDependencyType, getNetwork, getRootDir, globalCacheDir, parseGithubURL } from './mops.js';
|
|
6
6
|
import { getPackageId } from './helpers/get-package-id.js';
|
|
7
|
+
let getGlobalCacheDir = () => {
|
|
8
|
+
let network = getNetwork();
|
|
9
|
+
return path.join(globalCacheDir, network === 'ic' ? '' : network);
|
|
10
|
+
};
|
|
7
11
|
export let show = () => {
|
|
8
|
-
return
|
|
12
|
+
return getGlobalCacheDir();
|
|
9
13
|
};
|
|
10
14
|
export let getDepCacheDir = (cacheName) => {
|
|
11
|
-
return path.join(
|
|
15
|
+
return path.join(getGlobalCacheDir(), 'packages', cacheName);
|
|
12
16
|
};
|
|
13
17
|
export let isDepCached = (cacheName) => {
|
|
14
18
|
let dir = getDepCacheDir(cacheName);
|
|
@@ -23,10 +27,10 @@ export function getMopsDepCacheName(name, version) {
|
|
|
23
27
|
}
|
|
24
28
|
export function getGithubDepCacheName(name, repo) {
|
|
25
29
|
const { branch, commitHash } = parseGithubURL(repo);
|
|
26
|
-
return `_github/${name}#${branch}` + (commitHash ? `@${commitHash}` : '');
|
|
30
|
+
return `_github/${name}#${branch.replaceAll('/', '___')}` + (commitHash ? `@${commitHash}` : '');
|
|
27
31
|
}
|
|
28
32
|
export let addCache = (cacheName, source) => {
|
|
29
|
-
let dest = path.join(
|
|
33
|
+
let dest = path.join(getGlobalCacheDir(), 'packages', cacheName);
|
|
30
34
|
fs.mkdirSync(dest, { recursive: true });
|
|
31
35
|
return new Promise((resolve, reject) => {
|
|
32
36
|
ncp.ncp(source, dest, { stopOnErr: true }, (err) => {
|
|
@@ -38,7 +42,7 @@ export let addCache = (cacheName, source) => {
|
|
|
38
42
|
});
|
|
39
43
|
};
|
|
40
44
|
export let copyCache = (cacheName, dest) => {
|
|
41
|
-
let source = path.join(
|
|
45
|
+
let source = path.join(getGlobalCacheDir(), 'packages', cacheName);
|
|
42
46
|
fs.mkdirSync(dest, { recursive: true });
|
|
43
47
|
return new Promise((resolve, reject) => {
|
|
44
48
|
ncp.ncp(source, dest, { stopOnErr: true }, (err) => {
|
|
@@ -50,7 +54,7 @@ export let copyCache = (cacheName, dest) => {
|
|
|
50
54
|
});
|
|
51
55
|
};
|
|
52
56
|
export let cacheSize = async () => {
|
|
53
|
-
let dir = path.join(
|
|
57
|
+
let dir = path.join(getGlobalCacheDir());
|
|
54
58
|
fs.mkdirSync(dir, { recursive: true });
|
|
55
59
|
let size = await getFolderSize.strict(dir);
|
|
56
60
|
if (size < 1024 * 1024) {
|
|
@@ -59,11 +63,11 @@ export let cacheSize = async () => {
|
|
|
59
63
|
return (size / 1024 / 1024).toFixed(2) + ' MB';
|
|
60
64
|
};
|
|
61
65
|
export let cleanCache = async () => {
|
|
62
|
-
if (!
|
|
63
|
-
throw new Error('Invalid cache directory: ' +
|
|
66
|
+
if (!getGlobalCacheDir().endsWith('mops/cache') && !getGlobalCacheDir().endsWith('/mops') && !getGlobalCacheDir().endsWith('/mops/' + getNetwork())) {
|
|
67
|
+
throw new Error('Invalid cache directory: ' + getGlobalCacheDir());
|
|
64
68
|
}
|
|
65
69
|
// local cache
|
|
66
70
|
fs.rmSync(path.join(getRootDir(), '.mops'), { recursive: true, force: true });
|
|
67
71
|
// global cache
|
|
68
|
-
fs.rmSync(
|
|
72
|
+
fs.rmSync(getGlobalCacheDir(), { recursive: true, force: true });
|
|
69
73
|
};
|