ic-mops 0.35.0 → 0.36.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/cli.ts +2 -1
- package/commands/bench-replica.ts +99 -0
- package/commands/bench.ts +57 -90
- package/dist/cli.js +2 -1
- package/dist/commands/bench-replica.d.ts +32 -0
- package/dist/commands/bench-replica.js +87 -0
- package/dist/commands/bench.d.ts +9 -8
- package/dist/commands/bench.js +44 -76
- package/dist/package.json +17 -9
- package/package.json +17 -9
package/cli.ts
CHANGED
|
@@ -218,9 +218,10 @@ program
|
|
|
218
218
|
program
|
|
219
219
|
.command('bench [filter]')
|
|
220
220
|
.description('Run benchmarks')
|
|
221
|
+
.addOption(new Option('--replica <replica>', 'Which replica to use to run benchmarks').choices(['dfx', 'pocket-ic']).default('dfx'))
|
|
222
|
+
.addOption(new Option('--gc <gc>', 'Garbage collector').choices(['copying', 'compacting', 'generational', 'incremental']).default('copying'))
|
|
221
223
|
.addOption(new Option('--save', 'Save benchmark results to .bench/<filename>.json'))
|
|
222
224
|
.addOption(new Option('--compare', 'Run benchmark and compare results with .bench/<filename>.json'))
|
|
223
|
-
.addOption(new Option('--gc <gc>', 'Garbage collector').choices(['copying', 'compacting', 'generational', 'incremental']).default('incremental'))
|
|
224
225
|
// .addOption(new Option('--force-gc', 'Force GC'))
|
|
225
226
|
.addOption(new Option('--verbose', 'Show more information'))
|
|
226
227
|
.action(async (filter, options) => {
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import {execSync} from 'node:child_process';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import {execaCommand} from 'execa';
|
|
5
|
+
import {PocketIc} from '@hadronous/pic';
|
|
6
|
+
import {getRootDir} from '../mops.js';
|
|
7
|
+
import {createActor, idlFactory} from '../declarations/bench/index.js';
|
|
8
|
+
|
|
9
|
+
export class BenchReplica {
|
|
10
|
+
type : 'dfx' | 'pocket-ic';
|
|
11
|
+
verbose = false;
|
|
12
|
+
canisters: Record<string, {cwd: string; canisterId: string; actor: any;}> = {};
|
|
13
|
+
pocketIc?: PocketIc;
|
|
14
|
+
|
|
15
|
+
constructor(type: 'dfx' | 'pocket-ic', verbose = false) {
|
|
16
|
+
this.type = type;
|
|
17
|
+
this.verbose = verbose;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async start() {
|
|
21
|
+
console.log(`Starting ${this.type} replica...`);
|
|
22
|
+
|
|
23
|
+
if (this.type == 'dfx') {
|
|
24
|
+
await this.stop();
|
|
25
|
+
let dir = path.join(getRootDir(), '.mops/.bench');
|
|
26
|
+
fs.writeFileSync(path.join(dir, 'dfx.json'), JSON.stringify(this.dfxJson(''), null, 2));
|
|
27
|
+
execSync('dfx start --background --clean --artificial-delay 0' + (this.verbose ? '' : ' -qqqq'), {cwd: dir, stdio: ['inherit', this.verbose ? 'inherit' : 'ignore', 'inherit']});
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
this.pocketIc = await PocketIc.create();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async stop() {
|
|
35
|
+
if (this.type == 'dfx') {
|
|
36
|
+
let dir = path.join(getRootDir(), '.mops/.bench');
|
|
37
|
+
execSync('dfx stop' + (this.verbose ? '' : ' -qqqq'), {cwd: dir, stdio: ['pipe', this.verbose ? 'inherit' : 'ignore', 'pipe']});
|
|
38
|
+
}
|
|
39
|
+
else if (this.pocketIc) {
|
|
40
|
+
this.pocketIc.tearDown();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async deploy(name: string, wasm: string, cwd: string = process.cwd()) {
|
|
45
|
+
if (this.type === 'dfx') {
|
|
46
|
+
await execaCommand(`dfx deploy ${name} --mode reinstall --yes --identity anonymous`, {cwd, stdio: this.verbose ? 'pipe' : ['pipe', 'ignore', 'pipe']});
|
|
47
|
+
let canisterId = execSync(`dfx canister id ${name}`, {cwd}).toString().trim();
|
|
48
|
+
let actor = await createActor(canisterId, {
|
|
49
|
+
agentOptions: {
|
|
50
|
+
host: 'http://127.0.0.1:4944',
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
this.canisters[name] = {cwd, canisterId, actor};
|
|
54
|
+
}
|
|
55
|
+
else if (this.pocketIc) {
|
|
56
|
+
let {canisterId, actor} = await this.pocketIc.setupCanister(idlFactory, wasm);
|
|
57
|
+
this.canisters[name] = {
|
|
58
|
+
cwd,
|
|
59
|
+
canisterId: canisterId.toText(),
|
|
60
|
+
actor,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
getActor(name: string): unknown {
|
|
66
|
+
return this.canisters[name]?.actor;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
getCanisterId(name: string): string {
|
|
70
|
+
return this.canisters[name]?.canisterId || '';
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
dfxJson(canisterName: string) {
|
|
74
|
+
let canisters: Record<string, any> = {};
|
|
75
|
+
if (canisterName) {
|
|
76
|
+
canisters[canisterName] = {
|
|
77
|
+
type: 'custom',
|
|
78
|
+
wasm: 'canister.wasm',
|
|
79
|
+
candid: 'canister.did',
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
version: 1,
|
|
85
|
+
canisters,
|
|
86
|
+
defaults: {
|
|
87
|
+
build: {
|
|
88
|
+
packtool: 'mops sources',
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
networks: {
|
|
92
|
+
local: {
|
|
93
|
+
type: 'ephemeral',
|
|
94
|
+
bind: '127.0.0.1:4944',
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
}
|
package/commands/bench.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import {execSync} from 'node:child_process';
|
|
2
1
|
import path from 'node:path';
|
|
3
2
|
import fs from 'node:fs';
|
|
4
3
|
import os from 'node:os';
|
|
@@ -6,17 +5,19 @@ import chalk from 'chalk';
|
|
|
6
5
|
import {globSync} from 'glob';
|
|
7
6
|
import {markdownTable} from 'markdown-table';
|
|
8
7
|
import logUpdate from 'log-update';
|
|
8
|
+
import {execaCommand} from 'execa';
|
|
9
|
+
import stringWidth from 'string-width';
|
|
9
10
|
|
|
10
11
|
import {getRootDir} from '../mops.js';
|
|
11
12
|
import {parallel} from '../parallel.js';
|
|
12
|
-
import {createActor} from '../declarations/bench/index.js';
|
|
13
|
-
import {BenchResult, BenchSchema, _SERVICE} from '../declarations/bench/bench.did.js';
|
|
14
13
|
import {absToRel} from './test/utils.js';
|
|
15
14
|
import {getMocVersion} from '../helpers/get-moc-version.js';
|
|
16
15
|
import {getDfxVersion} from '../helpers/get-dfx-version.js';
|
|
17
16
|
import {getMocPath} from '../helpers/get-moc-path.js';
|
|
18
17
|
import {sources} from './sources.js';
|
|
19
|
-
|
|
18
|
+
|
|
19
|
+
import {BenchResult, BenchSchema, _SERVICE} from '../declarations/bench/bench.did.js';
|
|
20
|
+
import {BenchReplica} from './bench-replica.js';
|
|
20
21
|
|
|
21
22
|
let ignore = [
|
|
22
23
|
'**/node_modules/**',
|
|
@@ -31,30 +32,36 @@ let globConfig = {
|
|
|
31
32
|
};
|
|
32
33
|
|
|
33
34
|
type BenchOptions = {
|
|
34
|
-
dfx
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
replica: 'dfx' | 'pocket-ic',
|
|
36
|
+
replicaVersion: string,
|
|
37
|
+
moc: string,
|
|
38
|
+
gc: 'copying' | 'compacting' | 'generational' | 'incremental',
|
|
39
|
+
forceGc: boolean,
|
|
40
|
+
save: boolean,
|
|
41
|
+
compare: boolean,
|
|
42
|
+
verbose: boolean,
|
|
41
43
|
};
|
|
42
44
|
|
|
43
|
-
export async function bench(filter = '',
|
|
45
|
+
export async function bench(filter = '', optionsArg: Partial<BenchOptions> = {}): Promise<boolean> {
|
|
44
46
|
let defaultOptions: BenchOptions = {
|
|
47
|
+
replica: 'dfx',
|
|
45
48
|
moc: getMocVersion(),
|
|
46
|
-
|
|
47
|
-
gc: '
|
|
49
|
+
replicaVersion: '0.0.0',
|
|
50
|
+
gc: 'copying',
|
|
48
51
|
forceGc: true,
|
|
49
52
|
save: false,
|
|
50
53
|
compare: false,
|
|
51
54
|
verbose: false,
|
|
52
55
|
};
|
|
53
56
|
|
|
54
|
-
options = {...defaultOptions, ...
|
|
57
|
+
let options: BenchOptions = {...defaultOptions, ...optionsArg};
|
|
58
|
+
|
|
59
|
+
options.replicaVersion = options.replica == 'dfx' ? getDfxVersion() : '1.0.0';
|
|
55
60
|
|
|
56
61
|
options.verbose && console.log(options);
|
|
57
62
|
|
|
63
|
+
let replica = new BenchReplica(options.replica, options.verbose);
|
|
64
|
+
|
|
58
65
|
let rootDir = getRootDir();
|
|
59
66
|
let globStr = '**/bench?(mark)/**/*.bench.mo';
|
|
60
67
|
if (filter) {
|
|
@@ -85,17 +92,16 @@ export async function bench(filter = '', options: BenchOptions = {}): Promise<bo
|
|
|
85
92
|
console.log('='.repeat(50));
|
|
86
93
|
console.log('');
|
|
87
94
|
|
|
88
|
-
|
|
89
|
-
startDfx(options.verbose);
|
|
95
|
+
await replica.start();
|
|
90
96
|
|
|
91
97
|
console.log('Deploying canisters...');
|
|
92
98
|
await parallel(os.cpus().length, files, async (file: string) => {
|
|
93
99
|
try {
|
|
94
|
-
await deployBenchFile(file, options);
|
|
100
|
+
await deployBenchFile(file, options, replica);
|
|
95
101
|
}
|
|
96
102
|
catch (err) {
|
|
97
|
-
console.error('Unexpected error. Stopping
|
|
98
|
-
|
|
103
|
+
console.error('Unexpected error. Stopping replica...');
|
|
104
|
+
await replica.stop();
|
|
99
105
|
throw err;
|
|
100
106
|
}
|
|
101
107
|
});
|
|
@@ -105,17 +111,17 @@ export async function bench(filter = '', options: BenchOptions = {}): Promise<bo
|
|
|
105
111
|
console.log(`\nRunning ${chalk.gray(absToRel(file))}...`);
|
|
106
112
|
console.log('');
|
|
107
113
|
try {
|
|
108
|
-
await runBenchFile(file, options);
|
|
114
|
+
await runBenchFile(file, options, replica);
|
|
109
115
|
}
|
|
110
116
|
catch (err) {
|
|
111
|
-
console.error('Unexpected error. Stopping
|
|
112
|
-
|
|
117
|
+
console.error('Unexpected error. Stopping replica...');
|
|
118
|
+
await replica.stop();
|
|
113
119
|
throw err;
|
|
114
120
|
}
|
|
115
121
|
});
|
|
116
122
|
|
|
117
|
-
console.log('Stopping
|
|
118
|
-
|
|
123
|
+
console.log('Stopping replica...');
|
|
124
|
+
await replica.stop();
|
|
119
125
|
|
|
120
126
|
fs.rmSync(benchDir, {recursive: true, force: true});
|
|
121
127
|
|
|
@@ -133,55 +139,14 @@ function getMocArgs(options: BenchOptions): string {
|
|
|
133
139
|
return args;
|
|
134
140
|
}
|
|
135
141
|
|
|
136
|
-
function
|
|
137
|
-
options || console.log(options);
|
|
138
|
-
|
|
139
|
-
let canisters: Record<string, any> = {};
|
|
140
|
-
if (canisterName) {
|
|
141
|
-
canisters[canisterName] = {
|
|
142
|
-
type: 'custom',
|
|
143
|
-
wasm: 'canister.wasm',
|
|
144
|
-
candid: 'canister.did',
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
return {
|
|
149
|
-
version: 1,
|
|
150
|
-
canisters,
|
|
151
|
-
defaults: {
|
|
152
|
-
build: {
|
|
153
|
-
packtool: 'mops sources',
|
|
154
|
-
},
|
|
155
|
-
},
|
|
156
|
-
networks: {
|
|
157
|
-
local: {
|
|
158
|
-
type: 'ephemeral',
|
|
159
|
-
bind: '127.0.0.1:4944',
|
|
160
|
-
},
|
|
161
|
-
},
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
function startDfx(verbose = false) {
|
|
166
|
-
stopDfx(verbose);
|
|
167
|
-
let dir = path.join(getRootDir(), '.mops/.bench');
|
|
168
|
-
fs.writeFileSync(path.join(dir, 'dfx.json'), JSON.stringify(dfxJson(''), null, 2));
|
|
169
|
-
execSync('dfx start --background --clean --artificial-delay 0' + (verbose ? '' : ' -qqqq'), {cwd: dir, stdio: ['inherit', verbose ? 'inherit' : 'ignore', 'inherit']});
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
function stopDfx(verbose = false) {
|
|
173
|
-
let dir = path.join(getRootDir(), '.mops/.bench');
|
|
174
|
-
execSync('dfx stop' + (verbose ? '' : ' -qqqq'), {cwd: dir, stdio: ['pipe', verbose ? 'inherit' : 'ignore', 'pipe']});
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
async function deployBenchFile(file: string, options: BenchOptions = {}): Promise<void> {
|
|
142
|
+
async function deployBenchFile(file: string, options: BenchOptions, replica: BenchReplica): Promise<void> {
|
|
178
143
|
let rootDir = getRootDir();
|
|
179
144
|
let tempDir = path.join(rootDir, '.mops/.bench/', path.parse(file).name);
|
|
180
145
|
let canisterName = path.parse(file).name;
|
|
181
146
|
|
|
182
147
|
// prepare temp files
|
|
183
148
|
fs.mkdirSync(tempDir, {recursive: true});
|
|
184
|
-
fs.writeFileSync(path.join(tempDir, 'dfx.json'), JSON.stringify(dfxJson(canisterName
|
|
149
|
+
fs.writeFileSync(path.join(tempDir, 'dfx.json'), JSON.stringify(replica.dfxJson(canisterName), null, 2));
|
|
185
150
|
|
|
186
151
|
let benchCanisterData = fs.readFileSync(new URL('./bench/bench-canister.mo', import.meta.url), 'utf8');
|
|
187
152
|
benchCanisterData = benchCanisterData.replace('./user-bench', path.relative(tempDir, file).replace(/.mo$/g, ''));
|
|
@@ -195,18 +160,15 @@ async function deployBenchFile(file: string, options: BenchOptions = {}): Promis
|
|
|
195
160
|
options.verbose && console.timeEnd(`build ${canisterName}`);
|
|
196
161
|
|
|
197
162
|
// deploy canister
|
|
163
|
+
let wasm = path.join(tempDir, 'canister.wasm');
|
|
198
164
|
options.verbose && console.time(`deploy ${canisterName}`);
|
|
199
|
-
await execaCommand(`dfx deploy ${canisterName} --mode reinstall --yes --identity anonymous`, {cwd: tempDir, stdio: options.verbose ? 'pipe' : ['pipe', 'ignore', 'pipe']});
|
|
165
|
+
// await execaCommand(`dfx deploy ${canisterName} --mode reinstall --yes --identity anonymous`, {cwd: tempDir, stdio: options.verbose ? 'pipe' : ['pipe', 'ignore', 'pipe']});
|
|
166
|
+
await replica.deploy(canisterName, wasm, tempDir);
|
|
200
167
|
options.verbose && console.timeEnd(`deploy ${canisterName}`);
|
|
201
168
|
|
|
202
169
|
// init bench
|
|
203
170
|
options.verbose && console.time(`init ${canisterName}`);
|
|
204
|
-
let
|
|
205
|
-
let actor: _SERVICE = await createActor(canisterId, {
|
|
206
|
-
agentOptions: {
|
|
207
|
-
host: 'http://127.0.0.1:4944',
|
|
208
|
-
},
|
|
209
|
-
});
|
|
171
|
+
let actor = await replica.getActor(canisterName) as _SERVICE;
|
|
210
172
|
await actor.init();
|
|
211
173
|
options.verbose && console.timeEnd(`init ${canisterName}`);
|
|
212
174
|
}
|
|
@@ -216,18 +178,11 @@ type RunBenchFileResult = {
|
|
|
216
178
|
results: Map<string, BenchResult>,
|
|
217
179
|
};
|
|
218
180
|
|
|
219
|
-
async function runBenchFile(file: string, options: BenchOptions
|
|
181
|
+
async function runBenchFile(file: string, options: BenchOptions, replica: BenchReplica): Promise<RunBenchFileResult> {
|
|
220
182
|
let rootDir = getRootDir();
|
|
221
|
-
let tempDir = path.join(rootDir, '.mops/.bench/', path.parse(file).name);
|
|
222
183
|
let canisterName = path.parse(file).name;
|
|
223
184
|
|
|
224
|
-
let
|
|
225
|
-
let actor: _SERVICE = await createActor(canisterId, {
|
|
226
|
-
agentOptions: {
|
|
227
|
-
host: 'http://127.0.0.1:4944',
|
|
228
|
-
},
|
|
229
|
-
});
|
|
230
|
-
|
|
185
|
+
let actor = await replica.getActor(canisterName) as _SERVICE;
|
|
231
186
|
let schema = await actor.getSchema();
|
|
232
187
|
|
|
233
188
|
// load previous results
|
|
@@ -267,8 +222,8 @@ async function runBenchFile(file: string, options: BenchOptions = {}): Promise<R
|
|
|
267
222
|
let percent = (Number(res[prop]) - Number(prevRes[prop])) / Number(prevRes[prop]) * 100;
|
|
268
223
|
let sign = percent > 0 ? '+' : '';
|
|
269
224
|
let percentText = percent == 0 ? '0%' : sign + percent.toFixed(2) + '%';
|
|
270
|
-
|
|
271
|
-
diff =
|
|
225
|
+
let color: keyof typeof chalk = percent == 0 ? 'gray' : (percent > 0 ? 'red' : 'green');
|
|
226
|
+
diff = ` (${chalk[color](percentText)})`;
|
|
272
227
|
}
|
|
273
228
|
else {
|
|
274
229
|
diff = chalk.yellow(' (no previous results)');
|
|
@@ -285,7 +240,10 @@ async function runBenchFile(file: string, options: BenchOptions = {}): Promise<R
|
|
|
285
240
|
resArr.push(curRow);
|
|
286
241
|
}
|
|
287
242
|
|
|
288
|
-
return markdownTable(resArr, {
|
|
243
|
+
return markdownTable(resArr, {
|
|
244
|
+
align: ['l', ...'r'.repeat(schema.cols.length)],
|
|
245
|
+
stringLength: stringWidth,
|
|
246
|
+
});
|
|
289
247
|
};
|
|
290
248
|
|
|
291
249
|
let printResults = () => {
|
|
@@ -297,7 +255,9 @@ async function runBenchFile(file: string, options: BenchOptions = {}): Promise<R
|
|
|
297
255
|
`);
|
|
298
256
|
};
|
|
299
257
|
|
|
300
|
-
|
|
258
|
+
if (!process.env.CI) {
|
|
259
|
+
printResults();
|
|
260
|
+
}
|
|
301
261
|
|
|
302
262
|
// run all cells
|
|
303
263
|
for (let [rowIndex, row] of schema.rows.entries()) {
|
|
@@ -306,9 +266,15 @@ async function runBenchFile(file: string, options: BenchOptions = {}): Promise<R
|
|
|
306
266
|
// let res = await actor.runCellUpdate(BigInt(rowIndex), BigInt(colIndex));
|
|
307
267
|
let res = await actor.runCellUpdateAwait(BigInt(rowIndex), BigInt(colIndex));
|
|
308
268
|
results.set(`${row}:${col}`, res);
|
|
309
|
-
|
|
269
|
+
if (!process.env.CI) {
|
|
270
|
+
printResults();
|
|
271
|
+
}
|
|
310
272
|
}
|
|
311
273
|
}
|
|
274
|
+
|
|
275
|
+
if (process.env.CI) {
|
|
276
|
+
printResults();
|
|
277
|
+
}
|
|
312
278
|
logUpdate.done();
|
|
313
279
|
|
|
314
280
|
// save results
|
|
@@ -317,7 +283,8 @@ async function runBenchFile(file: string, options: BenchOptions = {}): Promise<R
|
|
|
317
283
|
let json: Record<any, any> = {
|
|
318
284
|
version: 1,
|
|
319
285
|
moc: options.moc,
|
|
320
|
-
|
|
286
|
+
replica: options.replica,
|
|
287
|
+
replicaVersion: options.replicaVersion,
|
|
321
288
|
gc: options.gc,
|
|
322
289
|
forceGc: options.forceGc,
|
|
323
290
|
results: Array.from(results.entries()),
|
package/dist/cli.js
CHANGED
|
@@ -190,9 +190,10 @@ program
|
|
|
190
190
|
program
|
|
191
191
|
.command('bench [filter]')
|
|
192
192
|
.description('Run benchmarks')
|
|
193
|
+
.addOption(new Option('--replica <replica>', 'Which replica to use to run benchmarks').choices(['dfx', 'pocket-ic']).default('dfx'))
|
|
194
|
+
.addOption(new Option('--gc <gc>', 'Garbage collector').choices(['copying', 'compacting', 'generational', 'incremental']).default('copying'))
|
|
193
195
|
.addOption(new Option('--save', 'Save benchmark results to .bench/<filename>.json'))
|
|
194
196
|
.addOption(new Option('--compare', 'Run benchmark and compare results with .bench/<filename>.json'))
|
|
195
|
-
.addOption(new Option('--gc <gc>', 'Garbage collector').choices(['copying', 'compacting', 'generational', 'incremental']).default('incremental'))
|
|
196
197
|
// .addOption(new Option('--force-gc', 'Force GC'))
|
|
197
198
|
.addOption(new Option('--verbose', 'Show more information'))
|
|
198
199
|
.action(async (filter, options) => {
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { PocketIc } from '@hadronous/pic';
|
|
2
|
+
export declare class BenchReplica {
|
|
3
|
+
type: 'dfx' | 'pocket-ic';
|
|
4
|
+
verbose: boolean;
|
|
5
|
+
canisters: Record<string, {
|
|
6
|
+
cwd: string;
|
|
7
|
+
canisterId: string;
|
|
8
|
+
actor: any;
|
|
9
|
+
}>;
|
|
10
|
+
pocketIc?: PocketIc;
|
|
11
|
+
constructor(type: 'dfx' | 'pocket-ic', verbose?: boolean);
|
|
12
|
+
start(): Promise<void>;
|
|
13
|
+
stop(): Promise<void>;
|
|
14
|
+
deploy(name: string, wasm: string, cwd?: string): Promise<void>;
|
|
15
|
+
getActor(name: string): unknown;
|
|
16
|
+
getCanisterId(name: string): string;
|
|
17
|
+
dfxJson(canisterName: string): {
|
|
18
|
+
version: number;
|
|
19
|
+
canisters: Record<string, any>;
|
|
20
|
+
defaults: {
|
|
21
|
+
build: {
|
|
22
|
+
packtool: string;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
networks: {
|
|
26
|
+
local: {
|
|
27
|
+
type: string;
|
|
28
|
+
bind: string;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import { execaCommand } from 'execa';
|
|
5
|
+
import { PocketIc } from '@hadronous/pic';
|
|
6
|
+
import { getRootDir } from '../mops.js';
|
|
7
|
+
import { createActor, idlFactory } from '../declarations/bench/index.js';
|
|
8
|
+
export class BenchReplica {
|
|
9
|
+
constructor(type, verbose = false) {
|
|
10
|
+
this.verbose = false;
|
|
11
|
+
this.canisters = {};
|
|
12
|
+
this.type = type;
|
|
13
|
+
this.verbose = verbose;
|
|
14
|
+
}
|
|
15
|
+
async start() {
|
|
16
|
+
console.log(`Starting ${this.type} replica...`);
|
|
17
|
+
if (this.type == 'dfx') {
|
|
18
|
+
await this.stop();
|
|
19
|
+
let dir = path.join(getRootDir(), '.mops/.bench');
|
|
20
|
+
fs.writeFileSync(path.join(dir, 'dfx.json'), JSON.stringify(this.dfxJson(''), null, 2));
|
|
21
|
+
execSync('dfx start --background --clean --artificial-delay 0' + (this.verbose ? '' : ' -qqqq'), { cwd: dir, stdio: ['inherit', this.verbose ? 'inherit' : 'ignore', 'inherit'] });
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
this.pocketIc = await PocketIc.create();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
async stop() {
|
|
28
|
+
if (this.type == 'dfx') {
|
|
29
|
+
let dir = path.join(getRootDir(), '.mops/.bench');
|
|
30
|
+
execSync('dfx stop' + (this.verbose ? '' : ' -qqqq'), { cwd: dir, stdio: ['pipe', this.verbose ? 'inherit' : 'ignore', 'pipe'] });
|
|
31
|
+
}
|
|
32
|
+
else if (this.pocketIc) {
|
|
33
|
+
this.pocketIc.tearDown();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async deploy(name, wasm, cwd = process.cwd()) {
|
|
37
|
+
if (this.type === 'dfx') {
|
|
38
|
+
await execaCommand(`dfx deploy ${name} --mode reinstall --yes --identity anonymous`, { cwd, stdio: this.verbose ? 'pipe' : ['pipe', 'ignore', 'pipe'] });
|
|
39
|
+
let canisterId = execSync(`dfx canister id ${name}`, { cwd }).toString().trim();
|
|
40
|
+
let actor = await createActor(canisterId, {
|
|
41
|
+
agentOptions: {
|
|
42
|
+
host: 'http://127.0.0.1:4944',
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
this.canisters[name] = { cwd, canisterId, actor };
|
|
46
|
+
}
|
|
47
|
+
else if (this.pocketIc) {
|
|
48
|
+
let { canisterId, actor } = await this.pocketIc.setupCanister(idlFactory, wasm);
|
|
49
|
+
this.canisters[name] = {
|
|
50
|
+
cwd,
|
|
51
|
+
canisterId: canisterId.toText(),
|
|
52
|
+
actor,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
getActor(name) {
|
|
57
|
+
return this.canisters[name]?.actor;
|
|
58
|
+
}
|
|
59
|
+
getCanisterId(name) {
|
|
60
|
+
return this.canisters[name]?.canisterId || '';
|
|
61
|
+
}
|
|
62
|
+
dfxJson(canisterName) {
|
|
63
|
+
let canisters = {};
|
|
64
|
+
if (canisterName) {
|
|
65
|
+
canisters[canisterName] = {
|
|
66
|
+
type: 'custom',
|
|
67
|
+
wasm: 'canister.wasm',
|
|
68
|
+
candid: 'canister.did',
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
version: 1,
|
|
73
|
+
canisters,
|
|
74
|
+
defaults: {
|
|
75
|
+
build: {
|
|
76
|
+
packtool: 'mops sources',
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
networks: {
|
|
80
|
+
local: {
|
|
81
|
+
type: 'ephemeral',
|
|
82
|
+
bind: '127.0.0.1:4944',
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
package/dist/commands/bench.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
type BenchOptions = {
|
|
2
|
-
dfx
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
replica: 'dfx' | 'pocket-ic';
|
|
3
|
+
replicaVersion: string;
|
|
4
|
+
moc: string;
|
|
5
|
+
gc: 'copying' | 'compacting' | 'generational' | 'incremental';
|
|
6
|
+
forceGc: boolean;
|
|
7
|
+
save: boolean;
|
|
8
|
+
compare: boolean;
|
|
9
|
+
verbose: boolean;
|
|
9
10
|
};
|
|
10
|
-
export declare function bench(filter?: string,
|
|
11
|
+
export declare function bench(filter?: string, optionsArg?: Partial<BenchOptions>): Promise<boolean>;
|
|
11
12
|
export {};
|
package/dist/commands/bench.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { execSync } from 'node:child_process';
|
|
2
1
|
import path from 'node:path';
|
|
3
2
|
import fs from 'node:fs';
|
|
4
3
|
import os from 'node:os';
|
|
@@ -6,15 +5,16 @@ import chalk from 'chalk';
|
|
|
6
5
|
import { globSync } from 'glob';
|
|
7
6
|
import { markdownTable } from 'markdown-table';
|
|
8
7
|
import logUpdate from 'log-update';
|
|
8
|
+
import { execaCommand } from 'execa';
|
|
9
|
+
import stringWidth from 'string-width';
|
|
9
10
|
import { getRootDir } from '../mops.js';
|
|
10
11
|
import { parallel } from '../parallel.js';
|
|
11
|
-
import { createActor } from '../declarations/bench/index.js';
|
|
12
12
|
import { absToRel } from './test/utils.js';
|
|
13
13
|
import { getMocVersion } from '../helpers/get-moc-version.js';
|
|
14
14
|
import { getDfxVersion } from '../helpers/get-dfx-version.js';
|
|
15
15
|
import { getMocPath } from '../helpers/get-moc-path.js';
|
|
16
16
|
import { sources } from './sources.js';
|
|
17
|
-
import {
|
|
17
|
+
import { BenchReplica } from './bench-replica.js';
|
|
18
18
|
let ignore = [
|
|
19
19
|
'**/node_modules/**',
|
|
20
20
|
'**/.mops/**',
|
|
@@ -25,18 +25,21 @@ let globConfig = {
|
|
|
25
25
|
nocase: true,
|
|
26
26
|
ignore: ignore,
|
|
27
27
|
};
|
|
28
|
-
export async function bench(filter = '',
|
|
28
|
+
export async function bench(filter = '', optionsArg = {}) {
|
|
29
29
|
let defaultOptions = {
|
|
30
|
+
replica: 'dfx',
|
|
30
31
|
moc: getMocVersion(),
|
|
31
|
-
|
|
32
|
-
gc: '
|
|
32
|
+
replicaVersion: '0.0.0',
|
|
33
|
+
gc: 'copying',
|
|
33
34
|
forceGc: true,
|
|
34
35
|
save: false,
|
|
35
36
|
compare: false,
|
|
36
37
|
verbose: false,
|
|
37
38
|
};
|
|
38
|
-
options = { ...defaultOptions, ...
|
|
39
|
+
let options = { ...defaultOptions, ...optionsArg };
|
|
40
|
+
options.replicaVersion = options.replica == 'dfx' ? getDfxVersion() : '1.0.0';
|
|
39
41
|
options.verbose && console.log(options);
|
|
42
|
+
let replica = new BenchReplica(options.replica, options.verbose);
|
|
40
43
|
let rootDir = getRootDir();
|
|
41
44
|
let globStr = '**/bench?(mark)/**/*.bench.mo';
|
|
42
45
|
if (filter) {
|
|
@@ -63,16 +66,15 @@ export async function bench(filter = '', options = {}) {
|
|
|
63
66
|
console.log('');
|
|
64
67
|
console.log('='.repeat(50));
|
|
65
68
|
console.log('');
|
|
66
|
-
|
|
67
|
-
startDfx(options.verbose);
|
|
69
|
+
await replica.start();
|
|
68
70
|
console.log('Deploying canisters...');
|
|
69
71
|
await parallel(os.cpus().length, files, async (file) => {
|
|
70
72
|
try {
|
|
71
|
-
await deployBenchFile(file, options);
|
|
73
|
+
await deployBenchFile(file, options, replica);
|
|
72
74
|
}
|
|
73
75
|
catch (err) {
|
|
74
|
-
console.error('Unexpected error. Stopping
|
|
75
|
-
|
|
76
|
+
console.error('Unexpected error. Stopping replica...');
|
|
77
|
+
await replica.stop();
|
|
76
78
|
throw err;
|
|
77
79
|
}
|
|
78
80
|
});
|
|
@@ -81,16 +83,16 @@ export async function bench(filter = '', options = {}) {
|
|
|
81
83
|
console.log(`\nRunning ${chalk.gray(absToRel(file))}...`);
|
|
82
84
|
console.log('');
|
|
83
85
|
try {
|
|
84
|
-
await runBenchFile(file, options);
|
|
86
|
+
await runBenchFile(file, options, replica);
|
|
85
87
|
}
|
|
86
88
|
catch (err) {
|
|
87
|
-
console.error('Unexpected error. Stopping
|
|
88
|
-
|
|
89
|
+
console.error('Unexpected error. Stopping replica...');
|
|
90
|
+
await replica.stop();
|
|
89
91
|
throw err;
|
|
90
92
|
}
|
|
91
93
|
});
|
|
92
|
-
console.log('Stopping
|
|
93
|
-
|
|
94
|
+
console.log('Stopping replica...');
|
|
95
|
+
await replica.stop();
|
|
94
96
|
fs.rmSync(benchDir, { recursive: true, force: true });
|
|
95
97
|
return true;
|
|
96
98
|
}
|
|
@@ -104,49 +106,13 @@ function getMocArgs(options) {
|
|
|
104
106
|
}
|
|
105
107
|
return args;
|
|
106
108
|
}
|
|
107
|
-
function
|
|
108
|
-
options || console.log(options);
|
|
109
|
-
let canisters = {};
|
|
110
|
-
if (canisterName) {
|
|
111
|
-
canisters[canisterName] = {
|
|
112
|
-
type: 'custom',
|
|
113
|
-
wasm: 'canister.wasm',
|
|
114
|
-
candid: 'canister.did',
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
return {
|
|
118
|
-
version: 1,
|
|
119
|
-
canisters,
|
|
120
|
-
defaults: {
|
|
121
|
-
build: {
|
|
122
|
-
packtool: 'mops sources',
|
|
123
|
-
},
|
|
124
|
-
},
|
|
125
|
-
networks: {
|
|
126
|
-
local: {
|
|
127
|
-
type: 'ephemeral',
|
|
128
|
-
bind: '127.0.0.1:4944',
|
|
129
|
-
},
|
|
130
|
-
},
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
function startDfx(verbose = false) {
|
|
134
|
-
stopDfx(verbose);
|
|
135
|
-
let dir = path.join(getRootDir(), '.mops/.bench');
|
|
136
|
-
fs.writeFileSync(path.join(dir, 'dfx.json'), JSON.stringify(dfxJson(''), null, 2));
|
|
137
|
-
execSync('dfx start --background --clean --artificial-delay 0' + (verbose ? '' : ' -qqqq'), { cwd: dir, stdio: ['inherit', verbose ? 'inherit' : 'ignore', 'inherit'] });
|
|
138
|
-
}
|
|
139
|
-
function stopDfx(verbose = false) {
|
|
140
|
-
let dir = path.join(getRootDir(), '.mops/.bench');
|
|
141
|
-
execSync('dfx stop' + (verbose ? '' : ' -qqqq'), { cwd: dir, stdio: ['pipe', verbose ? 'inherit' : 'ignore', 'pipe'] });
|
|
142
|
-
}
|
|
143
|
-
async function deployBenchFile(file, options = {}) {
|
|
109
|
+
async function deployBenchFile(file, options, replica) {
|
|
144
110
|
let rootDir = getRootDir();
|
|
145
111
|
let tempDir = path.join(rootDir, '.mops/.bench/', path.parse(file).name);
|
|
146
112
|
let canisterName = path.parse(file).name;
|
|
147
113
|
// prepare temp files
|
|
148
114
|
fs.mkdirSync(tempDir, { recursive: true });
|
|
149
|
-
fs.writeFileSync(path.join(tempDir, 'dfx.json'), JSON.stringify(dfxJson(canisterName
|
|
115
|
+
fs.writeFileSync(path.join(tempDir, 'dfx.json'), JSON.stringify(replica.dfxJson(canisterName), null, 2));
|
|
150
116
|
let benchCanisterData = fs.readFileSync(new URL('./bench/bench-canister.mo', import.meta.url), 'utf8');
|
|
151
117
|
benchCanisterData = benchCanisterData.replace('./user-bench', path.relative(tempDir, file).replace(/.mo$/g, ''));
|
|
152
118
|
fs.writeFileSync(path.join(tempDir, 'canister.mo'), benchCanisterData);
|
|
@@ -157,30 +123,21 @@ async function deployBenchFile(file, options = {}) {
|
|
|
157
123
|
await execaCommand(`${mocPath} -c --idl canister.mo ${mocArgs} ${(await sources({ cwd: tempDir })).join(' ')}`, { cwd: tempDir, stdio: options.verbose ? 'pipe' : ['pipe', 'ignore', 'pipe'] });
|
|
158
124
|
options.verbose && console.timeEnd(`build ${canisterName}`);
|
|
159
125
|
// deploy canister
|
|
126
|
+
let wasm = path.join(tempDir, 'canister.wasm');
|
|
160
127
|
options.verbose && console.time(`deploy ${canisterName}`);
|
|
161
|
-
await execaCommand(`dfx deploy ${canisterName} --mode reinstall --yes --identity anonymous`, {
|
|
128
|
+
// await execaCommand(`dfx deploy ${canisterName} --mode reinstall --yes --identity anonymous`, {cwd: tempDir, stdio: options.verbose ? 'pipe' : ['pipe', 'ignore', 'pipe']});
|
|
129
|
+
await replica.deploy(canisterName, wasm, tempDir);
|
|
162
130
|
options.verbose && console.timeEnd(`deploy ${canisterName}`);
|
|
163
131
|
// init bench
|
|
164
132
|
options.verbose && console.time(`init ${canisterName}`);
|
|
165
|
-
let
|
|
166
|
-
let actor = await createActor(canisterId, {
|
|
167
|
-
agentOptions: {
|
|
168
|
-
host: 'http://127.0.0.1:4944',
|
|
169
|
-
},
|
|
170
|
-
});
|
|
133
|
+
let actor = await replica.getActor(canisterName);
|
|
171
134
|
await actor.init();
|
|
172
135
|
options.verbose && console.timeEnd(`init ${canisterName}`);
|
|
173
136
|
}
|
|
174
|
-
async function runBenchFile(file, options
|
|
137
|
+
async function runBenchFile(file, options, replica) {
|
|
175
138
|
let rootDir = getRootDir();
|
|
176
|
-
let tempDir = path.join(rootDir, '.mops/.bench/', path.parse(file).name);
|
|
177
139
|
let canisterName = path.parse(file).name;
|
|
178
|
-
let
|
|
179
|
-
let actor = await createActor(canisterId, {
|
|
180
|
-
agentOptions: {
|
|
181
|
-
host: 'http://127.0.0.1:4944',
|
|
182
|
-
},
|
|
183
|
-
});
|
|
140
|
+
let actor = await replica.getActor(canisterName);
|
|
184
141
|
let schema = await actor.getSchema();
|
|
185
142
|
// load previous results
|
|
186
143
|
let prevResults;
|
|
@@ -213,8 +170,8 @@ async function runBenchFile(file, options = {}) {
|
|
|
213
170
|
let percent = (Number(res[prop]) - Number(prevRes[prop])) / Number(prevRes[prop]) * 100;
|
|
214
171
|
let sign = percent > 0 ? '+' : '';
|
|
215
172
|
let percentText = percent == 0 ? '0%' : sign + percent.toFixed(2) + '%';
|
|
216
|
-
|
|
217
|
-
diff =
|
|
173
|
+
let color = percent == 0 ? 'gray' : (percent > 0 ? 'red' : 'green');
|
|
174
|
+
diff = ` (${chalk[color](percentText)})`;
|
|
218
175
|
}
|
|
219
176
|
else {
|
|
220
177
|
diff = chalk.yellow(' (no previous results)');
|
|
@@ -229,7 +186,10 @@ async function runBenchFile(file, options = {}) {
|
|
|
229
186
|
}
|
|
230
187
|
resArr.push(curRow);
|
|
231
188
|
}
|
|
232
|
-
return markdownTable(resArr, {
|
|
189
|
+
return markdownTable(resArr, {
|
|
190
|
+
align: ['l', ...'r'.repeat(schema.cols.length)],
|
|
191
|
+
stringLength: stringWidth,
|
|
192
|
+
});
|
|
233
193
|
};
|
|
234
194
|
let printResults = () => {
|
|
235
195
|
logUpdate(`
|
|
@@ -239,7 +199,9 @@ async function runBenchFile(file, options = {}) {
|
|
|
239
199
|
\n\n${chalk.blue('Heap')}\n\n${getTable('rts_heap_size')}
|
|
240
200
|
`);
|
|
241
201
|
};
|
|
242
|
-
|
|
202
|
+
if (!process.env.CI) {
|
|
203
|
+
printResults();
|
|
204
|
+
}
|
|
243
205
|
// run all cells
|
|
244
206
|
for (let [rowIndex, row] of schema.rows.entries()) {
|
|
245
207
|
for (let [colIndex, col] of schema.cols.entries()) {
|
|
@@ -247,9 +209,14 @@ async function runBenchFile(file, options = {}) {
|
|
|
247
209
|
// let res = await actor.runCellUpdate(BigInt(rowIndex), BigInt(colIndex));
|
|
248
210
|
let res = await actor.runCellUpdateAwait(BigInt(rowIndex), BigInt(colIndex));
|
|
249
211
|
results.set(`${row}:${col}`, res);
|
|
250
|
-
|
|
212
|
+
if (!process.env.CI) {
|
|
213
|
+
printResults();
|
|
214
|
+
}
|
|
251
215
|
}
|
|
252
216
|
}
|
|
217
|
+
if (process.env.CI) {
|
|
218
|
+
printResults();
|
|
219
|
+
}
|
|
253
220
|
logUpdate.done();
|
|
254
221
|
// save results
|
|
255
222
|
if (options.save) {
|
|
@@ -257,7 +224,8 @@ async function runBenchFile(file, options = {}) {
|
|
|
257
224
|
let json = {
|
|
258
225
|
version: 1,
|
|
259
226
|
moc: options.moc,
|
|
260
|
-
|
|
227
|
+
replica: options.replica,
|
|
228
|
+
replicaVersion: options.replicaVersion,
|
|
261
229
|
gc: options.gc,
|
|
262
230
|
forceGc: options.forceGc,
|
|
263
231
|
results: Array.from(results.entries()),
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ic-mops",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.36.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"mops": "dist/cli.js"
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"author": "Zen Voich <zen.voich@gmail.com>",
|
|
20
20
|
"license": "MIT",
|
|
21
21
|
"engines": {
|
|
22
|
-
"node": ">=
|
|
22
|
+
"node": ">=18.0.0"
|
|
23
23
|
},
|
|
24
24
|
"scripts": {
|
|
25
25
|
"build": "tsc",
|
|
@@ -32,11 +32,12 @@
|
|
|
32
32
|
"esbuild": "esbuild"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@dfinity/agent": "^0.
|
|
36
|
-
"@dfinity/candid": "^0.
|
|
37
|
-
"@dfinity/identity": "^0.
|
|
38
|
-
"@dfinity/identity-secp256k1": "^0.
|
|
39
|
-
"@dfinity/principal": "^0.
|
|
35
|
+
"@dfinity/agent": "^0.19.3",
|
|
36
|
+
"@dfinity/candid": "^0.19.3",
|
|
37
|
+
"@dfinity/identity": "^0.19.3",
|
|
38
|
+
"@dfinity/identity-secp256k1": "^0.19.3",
|
|
39
|
+
"@dfinity/principal": "^0.19.3",
|
|
40
|
+
"@hadronous/pic": "0.2.0",
|
|
40
41
|
"@iarna/toml": "^2.2.5",
|
|
41
42
|
"@noble/hashes": "1.3.2",
|
|
42
43
|
"as-table": "^1.0.55",
|
|
@@ -55,7 +56,7 @@
|
|
|
55
56
|
"glob": "^10.3.3",
|
|
56
57
|
"globby": "^13.2.2",
|
|
57
58
|
"got": "13.0.0",
|
|
58
|
-
"log-update": "
|
|
59
|
+
"log-update": "6.0.0",
|
|
59
60
|
"markdown-table": "3.0.3",
|
|
60
61
|
"mdast-util-from-markdown": "^2.0.0",
|
|
61
62
|
"mdast-util-to-markdown": "^2.1.0",
|
|
@@ -65,6 +66,7 @@
|
|
|
65
66
|
"pem-file": "^1.0.1",
|
|
66
67
|
"prompts": "^2.4.2",
|
|
67
68
|
"stream-to-promise": "^3.0.0",
|
|
69
|
+
"string-width": "7.0.0",
|
|
68
70
|
"tar": "^6.1.15"
|
|
69
71
|
},
|
|
70
72
|
"devDependencies": {
|
|
@@ -78,7 +80,13 @@
|
|
|
78
80
|
"@types/stream-to-promise": "^2.2.1",
|
|
79
81
|
"@types/tar": "^6.1.5",
|
|
80
82
|
"esbuild": "^0.18.16",
|
|
81
|
-
"tsx": "
|
|
83
|
+
"tsx": "4.6.2",
|
|
82
84
|
"typescript": "^5.1.6"
|
|
85
|
+
},
|
|
86
|
+
"overrides": {
|
|
87
|
+
"@dfinity/agent": "^0.19.3",
|
|
88
|
+
"@dfinity/identity": "^0.19.3",
|
|
89
|
+
"@dfinity/principal": "^0.19.3",
|
|
90
|
+
"@dfinity/candid": "^0.19.3"
|
|
83
91
|
}
|
|
84
92
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ic-mops",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.36.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"mops": "dist/cli.js"
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"author": "Zen Voich <zen.voich@gmail.com>",
|
|
20
20
|
"license": "MIT",
|
|
21
21
|
"engines": {
|
|
22
|
-
"node": ">=
|
|
22
|
+
"node": ">=18.0.0"
|
|
23
23
|
},
|
|
24
24
|
"scripts": {
|
|
25
25
|
"build": "tsc",
|
|
@@ -32,11 +32,12 @@
|
|
|
32
32
|
"esbuild": "esbuild"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@dfinity/agent": "^0.
|
|
36
|
-
"@dfinity/candid": "^0.
|
|
37
|
-
"@dfinity/identity": "^0.
|
|
38
|
-
"@dfinity/identity-secp256k1": "^0.
|
|
39
|
-
"@dfinity/principal": "^0.
|
|
35
|
+
"@dfinity/agent": "^0.19.3",
|
|
36
|
+
"@dfinity/candid": "^0.19.3",
|
|
37
|
+
"@dfinity/identity": "^0.19.3",
|
|
38
|
+
"@dfinity/identity-secp256k1": "^0.19.3",
|
|
39
|
+
"@dfinity/principal": "^0.19.3",
|
|
40
|
+
"@hadronous/pic": "0.2.0",
|
|
40
41
|
"@iarna/toml": "^2.2.5",
|
|
41
42
|
"@noble/hashes": "1.3.2",
|
|
42
43
|
"as-table": "^1.0.55",
|
|
@@ -55,7 +56,7 @@
|
|
|
55
56
|
"glob": "^10.3.3",
|
|
56
57
|
"globby": "^13.2.2",
|
|
57
58
|
"got": "13.0.0",
|
|
58
|
-
"log-update": "
|
|
59
|
+
"log-update": "6.0.0",
|
|
59
60
|
"markdown-table": "3.0.3",
|
|
60
61
|
"mdast-util-from-markdown": "^2.0.0",
|
|
61
62
|
"mdast-util-to-markdown": "^2.1.0",
|
|
@@ -65,6 +66,7 @@
|
|
|
65
66
|
"pem-file": "^1.0.1",
|
|
66
67
|
"prompts": "^2.4.2",
|
|
67
68
|
"stream-to-promise": "^3.0.0",
|
|
69
|
+
"string-width": "7.0.0",
|
|
68
70
|
"tar": "^6.1.15"
|
|
69
71
|
},
|
|
70
72
|
"devDependencies": {
|
|
@@ -78,7 +80,13 @@
|
|
|
78
80
|
"@types/stream-to-promise": "^2.2.1",
|
|
79
81
|
"@types/tar": "^6.1.5",
|
|
80
82
|
"esbuild": "^0.18.16",
|
|
81
|
-
"tsx": "
|
|
83
|
+
"tsx": "4.6.2",
|
|
82
84
|
"typescript": "^5.1.6"
|
|
85
|
+
},
|
|
86
|
+
"overrides": {
|
|
87
|
+
"@dfinity/agent": "^0.19.3",
|
|
88
|
+
"@dfinity/identity": "^0.19.3",
|
|
89
|
+
"@dfinity/principal": "^0.19.3",
|
|
90
|
+
"@dfinity/candid": "^0.19.3"
|
|
83
91
|
}
|
|
84
92
|
}
|