ic-mops 0.34.3 → 0.35.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.
Files changed (50) hide show
  1. package/cli.ts +9 -44
  2. package/commands/add.ts +7 -5
  3. package/commands/bench.ts +1 -1
  4. package/commands/install-all.ts +4 -4
  5. package/commands/remove.ts +4 -4
  6. package/commands/sync.ts +5 -5
  7. package/commands/update.ts +3 -3
  8. package/declarations/main/main.did +67 -78
  9. package/declarations/main/main.did.d.ts +72 -83
  10. package/declarations/main/main.did.js +12 -23
  11. package/dist/bin/mops.d.ts +2 -0
  12. package/dist/bin/mops.js +2 -0
  13. package/dist/cli.js +9 -43
  14. package/dist/commands/add.d.ts +2 -2
  15. package/dist/commands/add.js +6 -3
  16. package/dist/commands/bench.js +1 -1
  17. package/dist/commands/install-all.d.ts +2 -2
  18. package/dist/commands/install-all.js +3 -3
  19. package/dist/commands/remove.d.ts +2 -2
  20. package/dist/commands/remove.js +3 -2
  21. package/dist/commands/sync.d.ts +2 -2
  22. package/dist/commands/sync.js +4 -4
  23. package/dist/commands/toolchain/moc.d.ts +4 -0
  24. package/dist/commands/toolchain/moc.js +36 -0
  25. package/dist/commands/toolchain/mocv.d.ts +1 -0
  26. package/dist/commands/toolchain/mocv.js +272 -0
  27. package/dist/commands/toolchain/toolchain-utils.d.ts +3 -0
  28. package/dist/commands/toolchain/toolchain-utils.js +56 -0
  29. package/dist/commands/toolchain/wasmtime.d.ts +4 -0
  30. package/dist/commands/toolchain/wasmtime.js +23 -0
  31. package/dist/commands/update.d.ts +2 -2
  32. package/dist/commands/update.js +2 -2
  33. package/dist/declarations/main/main.did +67 -78
  34. package/dist/declarations/main/main.did.d.ts +72 -83
  35. package/dist/declarations/main/main.did.js +12 -23
  36. package/dist/integrity.d.ts +2 -2
  37. package/dist/integrity.js +6 -3
  38. package/dist/moc-wrapper.d.ts +2 -0
  39. package/dist/moc-wrapper.js +8 -0
  40. package/dist/out/cli.d.ts +2 -0
  41. package/dist/out/cli.js +115242 -0
  42. package/dist/package.json +1 -1
  43. package/dist/templates/cli.d.ts +2 -0
  44. package/dist/templates/cli.js +3660 -0
  45. package/integrity.ts +8 -4
  46. package/package.json +1 -1
  47. package/dist/helpers/download-package-files.d.ts +0 -12
  48. package/dist/helpers/download-package-files.js +0 -62
  49. package/dist/helpers/resolve-version.d.ts +0 -1
  50. package/dist/helpers/resolve-version.js +0 -11
@@ -1,19 +1,4 @@
1
1
  export const idlFactory = ({ IDL }) => {
2
- const TestsChanges = IDL.Record({
3
- 'addedNames' : IDL.Vec(IDL.Text),
4
- 'removedNames' : IDL.Vec(IDL.Text),
5
- });
6
- const DepChange = IDL.Record({
7
- 'oldVersion' : IDL.Text,
8
- 'name' : IDL.Text,
9
- 'newVersion' : IDL.Text,
10
- });
11
- const PackageChanges__1 = IDL.Record({
12
- 'tests' : TestsChanges,
13
- 'deps' : IDL.Vec(DepChange),
14
- 'notes' : IDL.Text,
15
- 'devDeps' : IDL.Vec(DepChange),
16
- });
17
2
  const PublishingId = IDL.Text;
18
3
  const Err = IDL.Text;
19
4
  const Result = IDL.Variant({ 'ok' : IDL.Null, 'err' : Err });
@@ -133,6 +118,15 @@ export const idlFactory = ({ IDL }) => {
133
118
  'sourceFiles' : IDL.Nat,
134
119
  'sourceSize' : IDL.Nat,
135
120
  });
121
+ const TestsChanges = IDL.Record({
122
+ 'addedNames' : IDL.Vec(IDL.Text),
123
+ 'removedNames' : IDL.Vec(IDL.Text),
124
+ });
125
+ const DepChange = IDL.Record({
126
+ 'oldVersion' : IDL.Text,
127
+ 'name' : IDL.Text,
128
+ 'newVersion' : IDL.Text,
129
+ });
136
130
  const PackageChanges = IDL.Record({
137
131
  'tests' : TestsChanges,
138
132
  'deps' : IDL.Vec(DepChange),
@@ -250,20 +244,15 @@ export const idlFactory = ({ IDL }) => {
250
244
  'license' : IDL.Text,
251
245
  'readme' : IDL.Text,
252
246
  });
253
- const PublishingErr = IDL.Text;
254
- const Result_2 = IDL.Variant({ 'ok' : PublishingId, 'err' : PublishingErr });
247
+ const Result_2 = IDL.Variant({ 'ok' : PublishingId, 'err' : Err });
255
248
  const TestStats = IDL.Record({
256
249
  'passedNames' : IDL.Vec(IDL.Text),
257
250
  'passed' : IDL.Nat,
258
251
  });
259
- return IDL.Service({
252
+ const Main = IDL.Service({
260
253
  'backup' : IDL.Func([], [], []),
261
- 'claimAirdrop' : IDL.Func([IDL.Principal], [IDL.Text], []),
262
254
  'computeHashesForExistingFiles' : IDL.Func([], [], []),
263
- 'diff' : IDL.Func([IDL.Text, IDL.Text], [PackageChanges__1], ['query']),
264
255
  'finishPublish' : IDL.Func([PublishingId], [Result], []),
265
- 'getAirdropAmount' : IDL.Func([], [IDL.Nat], ['query']),
266
- 'getAirdropAmountAll' : IDL.Func([], [IDL.Nat], ['query']),
267
256
  'getApiVersion' : IDL.Func([], [Text], ['query']),
268
257
  'getBackupCanisterId' : IDL.Func([], [IDL.Principal], ['query']),
269
258
  'getDefaultPackages' : IDL.Func(
@@ -356,7 +345,6 @@ export const idlFactory = ({ IDL }) => {
356
345
  [],
357
346
  ),
358
347
  'startPublish' : IDL.Func([PackageConfigV2], [Result_2], []),
359
- 'takeAirdropSnapshot' : IDL.Func([], [], ['oneway']),
360
348
  'transferOwnership' : IDL.Func(
361
349
  [PackageName, IDL.Principal],
362
350
  [Result_1],
@@ -370,5 +358,6 @@ export const idlFactory = ({ IDL }) => {
370
358
  'uploadNotes' : IDL.Func([PublishingId, IDL.Text], [Result], []),
371
359
  'uploadTestStats' : IDL.Func([PublishingId, TestStats], [Result], []),
372
360
  });
361
+ return Main;
373
362
  };
374
363
  export const init = ({ IDL }) => { return []; };
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import '../cli.js';
package/dist/cli.js CHANGED
@@ -2,14 +2,12 @@
2
2
  import fs from 'node:fs';
3
3
  import { program, Argument, Option } from 'commander';
4
4
  import chalk from 'chalk';
5
- import { Principal } from '@dfinity/principal';
6
5
  import { init } from './commands/init.js';
7
6
  import { publish } from './commands/publish.js';
8
7
  import { importPem } from './commands/import-identity.js';
9
8
  import { sources } from './commands/sources.js';
10
- import { checkApiCompatibility, setNetwork, apiVersion, checkConfigFile, getNetworkFile, getIdentity } from './mops.js';
9
+ import { checkApiCompatibility, setNetwork, apiVersion, checkConfigFile, getNetworkFile } from './mops.js';
11
10
  import { getNetwork } from './api/network.js';
12
- import { mainActor } from './api/actors.js';
13
11
  import { whoami } from './commands/whoami.js';
14
12
  import { installAll } from './commands/install-all.js';
15
13
  import { search } from './commands/search.js';
@@ -48,7 +46,7 @@ program
48
46
  .description('Install the package and save it to mops.toml')
49
47
  .option('--dev')
50
48
  .option('--verbose')
51
- .addOption(new Option('--lockfile <lockfile>', 'Lockfile action').choices(['save', 'ignore']))
49
+ .addOption(new Option('--lock <action>', 'Lockfile action').choices(['update', 'ignore']))
52
50
  .action(async (pkg, options) => {
53
51
  if (!checkConfigFile()) {
54
52
  process.exit(1);
@@ -63,7 +61,7 @@ program
63
61
  .option('--dev', 'Remove from dev-dependencies instead of dependencies')
64
62
  .option('--verbose', 'Show more information')
65
63
  .option('--dry-run', 'Do not actually remove anything')
66
- .addOption(new Option('--lockfile <lockfile>', 'Lockfile action').choices(['save', 'ignore']))
64
+ .addOption(new Option('--lock <action>', 'Lockfile action').choices(['update', 'ignore']))
67
65
  .action(async (pkg, options) => {
68
66
  if (!checkConfigFile()) {
69
67
  process.exit(1);
@@ -76,7 +74,7 @@ program
76
74
  .alias('i')
77
75
  .description('Install all dependencies specified in mops.toml')
78
76
  .option('--verbose')
79
- .addOption(new Option('--lockfile <lockfile>', 'Lockfile action').choices(['save', 'check', 'ignore']))
77
+ .addOption(new Option('--lock <action>', 'Lockfile action').choices(['check', 'update', 'ignore']))
80
78
  .action(async (pkg, options) => {
81
79
  if (!checkConfigFile()) {
82
80
  process.exit(1);
@@ -144,7 +142,7 @@ program
144
142
  if (!checkConfigFile()) {
145
143
  process.exit(1);
146
144
  }
147
- await installAll({ silent: true, lockfile: 'ignore' });
145
+ await installAll({ silent: true, lock: 'ignore' });
148
146
  let sourcesArr = await sources(options);
149
147
  console.log(sourcesArr.join('\n'));
150
148
  });
@@ -185,7 +183,7 @@ program
185
183
  .addOption(new Option('--mode <mode>', 'Test mode').choices(['interpreter', 'wasi']).default('interpreter'))
186
184
  .option('-w, --watch', 'Enable watch mode')
187
185
  .action(async (filter, options) => {
188
- await installAll({ silent: true, lockfile: 'ignore' });
186
+ await installAll({ silent: true, lock: 'ignore' });
189
187
  await test(filter, options);
190
188
  });
191
189
  // bench
@@ -198,7 +196,7 @@ program
198
196
  // .addOption(new Option('--force-gc', 'Force GC'))
199
197
  .addOption(new Option('--verbose', 'Show more information'))
200
198
  .action(async (filter, options) => {
201
- await installAll({ silent: true, lockfile: 'ignore' });
199
+ await installAll({ silent: true, lock: 'ignore' });
202
200
  await bench(filter, options);
203
201
  });
204
202
  // template
@@ -254,38 +252,6 @@ program
254
252
  await setUserProp(prop, value);
255
253
  }
256
254
  });
257
- // temp: airdrop
258
- program
259
- .command('airdrop <check|claim> [canister]')
260
- .action(async (sub, canister) => {
261
- let identity = await getIdentity();
262
- let main = await mainActor(identity);
263
- if (sub === 'check') {
264
- let amount = await main.getAirdropAmount();
265
- if (amount === 0n) {
266
- console.log('No airdrop available');
267
- return;
268
- }
269
- console.log(`You can claim ${Number(amount) / 1000000000000} TCycles`);
270
- }
271
- else if (sub === 'claim') {
272
- let principal;
273
- try {
274
- principal = Principal.fromText(canister);
275
- }
276
- catch (err) {
277
- console.log('Invalid canister id');
278
- console.log(err);
279
- return;
280
- }
281
- console.log('Sending cycles to the canister ' + canister);
282
- let res = await main.claimAirdrop(principal);
283
- console.log(res);
284
- }
285
- else {
286
- console.log('Unknown sub command. Available sub commands: check, claim');
287
- }
288
- });
289
255
  // bump
290
256
  program
291
257
  .command('bump [major|minor|patch]')
@@ -297,7 +263,7 @@ program
297
263
  program
298
264
  .command('sync')
299
265
  .description('Add missing packages and remove unused packages')
300
- .addOption(new Option('--lockfile <lockfile>', 'Lockfile action').choices(['save', 'ignore']))
266
+ .addOption(new Option('--lock <action>', 'Lockfile action').choices(['update', 'ignore']))
301
267
  .action(async (options) => {
302
268
  await sync(options);
303
269
  });
@@ -312,7 +278,7 @@ program
312
278
  program
313
279
  .command('update [pkg]')
314
280
  .description('Update dependencies specified in mops.toml')
315
- .addOption(new Option('--lockfile <lockfile>', 'Lockfile action').choices(['save', 'ignore']))
281
+ .addOption(new Option('--lock <action>', 'Lockfile action').choices(['update', 'ignore']))
316
282
  .action(async (pkg, options) => {
317
283
  await update(pkg, options);
318
284
  });
@@ -1,7 +1,7 @@
1
1
  type AddOptions = {
2
2
  verbose?: boolean;
3
3
  dev?: boolean;
4
- lockfile?: 'save' | 'ignore';
4
+ lock?: 'update' | 'ignore';
5
5
  };
6
- export declare function add(name: string, { verbose, dev, lockfile }?: AddOptions, asName?: string): Promise<void>;
6
+ export declare function add(name: string, { verbose, dev, lock }?: AddOptions, asName?: string): Promise<void>;
7
7
  export {};
@@ -6,8 +6,9 @@ import { getHighestVersion } from '../api/getHighestVersion.js';
6
6
  import { installFromGithub } from '../vessel.js';
7
7
  import { install } from './install.js';
8
8
  import { notifyInstalls } from '../notify-installs.js';
9
+ import { checkIntegrity } from '../integrity.js';
9
10
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
10
- export async function add(name, { verbose = false, dev = false, lockfile } = {}, asName) {
11
+ export async function add(name, { verbose = false, dev = false, lock } = {}, asName) {
11
12
  if (!checkConfigFile()) {
12
13
  return;
13
14
  }
@@ -90,10 +91,12 @@ export async function add(name, { verbose = false, dev = false, lockfile } = {},
90
91
  throw Error(`Invalid config file: [${depsProp}] not found`);
91
92
  }
92
93
  writeConfig(config);
93
- // logUpdate('Checking integrity...');
94
+ if (lock !== 'ignore') {
95
+ logUpdate('Checking integrity...');
96
+ }
94
97
  await Promise.all([
95
98
  notifyInstalls(Object.keys(installedPackages)),
96
- // checkIntegrity(lockfile),
99
+ checkIntegrity(lock),
97
100
  ]);
98
101
  logUpdate.clear();
99
102
  console.log(chalk.green('Package installed ') + `${pkgDetails.name} = "${pkgDetails.repo || pkgDetails.path || pkgDetails.version}"`);
@@ -134,7 +134,7 @@ function startDfx(verbose = false) {
134
134
  stopDfx(verbose);
135
135
  let dir = path.join(getRootDir(), '.mops/.bench');
136
136
  fs.writeFileSync(path.join(dir, 'dfx.json'), JSON.stringify(dfxJson(''), null, 2));
137
- execSync('dfx start --background --clean' + (verbose ? '' : ' -qqqq'), { cwd: dir, stdio: ['inherit', verbose ? 'inherit' : 'ignore', 'inherit'] });
137
+ execSync('dfx start --background --clean --artificial-delay 0' + (verbose ? '' : ' -qqqq'), { cwd: dir, stdio: ['inherit', verbose ? 'inherit' : 'ignore', 'inherit'] });
138
138
  }
139
139
  function stopDfx(verbose = false) {
140
140
  let dir = path.join(getRootDir(), '.mops/.bench');
@@ -1,7 +1,7 @@
1
1
  type InstallAllOptions = {
2
2
  verbose?: boolean;
3
3
  silent?: boolean;
4
- lockfile?: 'save' | 'check' | 'ignore';
4
+ lock?: 'check' | 'update' | 'ignore';
5
5
  };
6
- export declare function installAll({ verbose, silent, lockfile }?: InstallAllOptions): Promise<void>;
6
+ export declare function installAll({ verbose, silent, lock }?: InstallAllOptions): Promise<void>;
7
7
  export {};
@@ -5,7 +5,7 @@ import { install } from './install.js';
5
5
  import { installFromGithub } from '../vessel.js';
6
6
  import { notifyInstalls } from '../notify-installs.js';
7
7
  import { checkIntegrity } from '../integrity.js';
8
- export async function installAll({ verbose = false, silent = false, lockfile } = {}) {
8
+ export async function installAll({ verbose = false, silent = false, lock } = {}) {
9
9
  if (!checkConfigFile()) {
10
10
  return;
11
11
  }
@@ -26,12 +26,12 @@ export async function installAll({ verbose = false, silent = false, lockfile } =
26
26
  installedPackages = { ...installedPackages, ...res };
27
27
  }
28
28
  }
29
- if (!silent && lockfile !== 'ignore') {
29
+ if (!silent && lock !== 'ignore') {
30
30
  logUpdate('Checking integrity...');
31
31
  }
32
32
  await Promise.all([
33
33
  notifyInstalls(Object.keys(installedPackages)),
34
- checkIntegrity(lockfile),
34
+ checkIntegrity(lock),
35
35
  ]);
36
36
  if (!silent) {
37
37
  logUpdate.clear();
@@ -2,7 +2,7 @@ type RemoveOptions = {
2
2
  verbose?: boolean;
3
3
  dev?: boolean;
4
4
  dryRun?: boolean;
5
- lockfile?: 'save' | 'ignore';
5
+ lock?: 'update' | 'ignore';
6
6
  };
7
- export declare function remove(name: string, { dev, verbose, dryRun, lockfile }?: RemoveOptions): Promise<void>;
7
+ export declare function remove(name: string, { dev, verbose, dryRun, lock }?: RemoveOptions): Promise<void>;
8
8
  export {};
@@ -2,8 +2,9 @@ import fs from 'node:fs';
2
2
  import { deleteSync } from 'del';
3
3
  import chalk from 'chalk';
4
4
  import { formatDir, formatGithubDir, checkConfigFile, readConfig, writeConfig } from '../mops.js';
5
+ import { checkIntegrity } from '../integrity.js';
5
6
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
6
- export async function remove(name, { dev = false, verbose = false, dryRun = false, lockfile } = {}) {
7
+ export async function remove(name, { dev = false, verbose = false, dryRun = false, lock } = {}) {
7
8
  if (!checkConfigFile()) {
8
9
  return;
9
10
  }
@@ -80,6 +81,6 @@ export async function remove(name, { dev = false, verbose = false, dryRun = fals
80
81
  delete config['dev-dependencies'][name];
81
82
  }
82
83
  dryRun || writeConfig(config);
83
- // await checkIntegrity(lockfile);
84
+ await checkIntegrity(lock);
84
85
  console.log(chalk.green('Package removed ') + `${name} = "${version}"`);
85
86
  }
@@ -1,5 +1,5 @@
1
1
  type SyncOptions = {
2
- lockfile?: 'save' | 'ignore';
2
+ lock?: 'update' | 'ignore';
3
3
  };
4
- export declare function sync({ lockfile }?: SyncOptions): Promise<void>;
4
+ export declare function sync({ lock }?: SyncOptions): Promise<void>;
5
5
  export {};
@@ -6,7 +6,7 @@ import { checkConfigFile, getRootDir, readConfig } from '../mops.js';
6
6
  import { add } from './add.js';
7
7
  import { remove } from './remove.js';
8
8
  import { checkIntegrity } from '../integrity.js';
9
- export async function sync({ lockfile } = {}) {
9
+ export async function sync({ lock } = {}) {
10
10
  if (!checkConfigFile()) {
11
11
  return;
12
12
  }
@@ -19,14 +19,14 @@ export async function sync({ lockfile } = {}) {
19
19
  let devDeps = new Set(Object.keys(config['dev-dependencies'] || {}));
20
20
  // add missing packages
21
21
  for (let pkg of missing) {
22
- await add(pkg, { lockfile: 'ignore' });
22
+ await add(pkg, { lock: 'ignore' });
23
23
  }
24
24
  // remove unused packages
25
25
  for (let pkg of unused) {
26
26
  let dev = devDeps.has(pkg) && !deps.has(pkg);
27
- await remove(pkg, { dev, lockfile: 'ignore' });
27
+ await remove(pkg, { dev, lock: 'ignore' });
28
28
  }
29
- await checkIntegrity(lockfile);
29
+ await checkIntegrity(lock);
30
30
  }
31
31
  let ignore = [
32
32
  '**/node_modules/**',
@@ -0,0 +1,4 @@
1
+ export declare let isCached: (version: string) => boolean;
2
+ export declare let download: (version: string, { silent }?: {
3
+ silent?: boolean | undefined;
4
+ }) => Promise<void>;
@@ -0,0 +1,36 @@
1
+ import path from 'node:path';
2
+ import fs from 'fs-extra';
3
+ import { globalCacheDir } from '../../mops.js';
4
+ import { downloadGithubRelease } from './toolchain-utils.js';
5
+ let cacheDir = path.join(globalCacheDir, 'moc');
6
+ export let isCached = (version) => {
7
+ let dir = path.join(cacheDir, version);
8
+ return fs.existsSync(dir) && fs.existsSync(path.join(dir, 'moc'));
9
+ };
10
+ export let download = async (version, { silent = false } = {}) => {
11
+ if (process.platform == 'win32') {
12
+ console.log('Windows is not supported. Please use WSL');
13
+ process.exit(1);
14
+ }
15
+ if (!version) {
16
+ console.log('version is not defined');
17
+ process.exit(1);
18
+ }
19
+ if (isCached(version)) {
20
+ return;
21
+ }
22
+ let url;
23
+ if (parseInt(version.replaceAll('.', '')) >= parseInt('0.9.5'.replaceAll('.', ''))) {
24
+ let platfrom = process.platform == 'darwin' ? 'Darwin' : 'Linux';
25
+ let arch = process.arch.startsWith('arm') ? 'arm64' : 'x86_64';
26
+ // currently only x64 binaries are available
27
+ arch = 'x86_64';
28
+ url = `https://github.com/dfinity/motoko/releases/download/${version}/motoko-${platfrom}-${arch}-${version}.tar.gz`;
29
+ }
30
+ else {
31
+ let platfrom = process.platform == 'darwin' ? 'macos' : 'linux64';
32
+ url = `https://github.com/dfinity/motoko/releases/download/${version}/motoko-${platfrom}-${version}.tar.gz`;
33
+ }
34
+ silent || console.log(`Downloading ${url}`);
35
+ await downloadGithubRelease(url, path.join(cacheDir, version));
36
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,272 @@
1
+ // @ts-nocheck
2
+ import fs from 'fs-extra';
3
+ import os from 'os';
4
+ import path from 'path';
5
+ import tar from 'tar';
6
+ import { program } from 'commander';
7
+ import prompts from 'prompts';
8
+ import { Octokit } from 'octokit';
9
+ import chalk from 'chalk';
10
+ import fetch from 'node-fetch';
11
+ if (process.platform == 'win32') {
12
+ console.log('Windows is not supported. Please use WSL');
13
+ process.exit(1);
14
+ }
15
+ let zshrc = path.join(os.homedir(), '.zshrc');
16
+ let bashrc = path.join(os.homedir(), '.bashrc');
17
+ let cacheDir = path.join(os.homedir(), '.cache/mocv');
18
+ let curVersionFile = path.join(cacheDir, 'versions/current/version.txt');
19
+ let tmpDir = path.join(cacheDir, '.tmp');
20
+ let file = path.join(tmpDir, 'moc.tar.gz');
21
+ let download = async (version, { silent = false } = {}) => {
22
+ if (!version) {
23
+ console.log('version is not defined');
24
+ process.exit(1);
25
+ }
26
+ if (isCached(version)) {
27
+ return;
28
+ }
29
+ let url;
30
+ if (parseInt(version.replaceAll('.', '')) >= parseInt('0.9.5'.replaceAll('.', ''))) {
31
+ let platfrom = process.platform == 'darwin' ? 'Darwin' : 'Linux';
32
+ let arch = process.arch.startsWith('arm') ? 'arm64' : 'x86_64';
33
+ // currently only x64 binaries are available
34
+ arch = 'x86_64';
35
+ url = `https://github.com/dfinity/motoko/releases/download/${version}/motoko-${platfrom}-${arch}-${version}.tar.gz`;
36
+ }
37
+ else {
38
+ let platfrom = process.platform == 'darwin' ? 'macos' : 'linux64';
39
+ url = `https://github.com/dfinity/motoko/releases/download/${version}/motoko-${platfrom}-${version}.tar.gz`;
40
+ }
41
+ silent || console.log(`Downloading ${url}`);
42
+ let res = await fetch(url);
43
+ if (res.status !== 200) {
44
+ console.log(`ERR ${res.status} ${url}`);
45
+ console.log(`moc version '${version}' not found`);
46
+ process.exit(1);
47
+ }
48
+ let arrayBuffer = await res.arrayBuffer();
49
+ let buffer = Buffer.from(arrayBuffer);
50
+ fs.mkdirSync(tmpDir, { recursive: true });
51
+ fs.writeFileSync(file, buffer);
52
+ let verDir = path.join(cacheDir, 'versions', version);
53
+ fs.mkdirSync(verDir, { recursive: true });
54
+ await tar.extract({
55
+ file,
56
+ cwd: verDir,
57
+ });
58
+ fs.rmSync(file);
59
+ };
60
+ let isCached = (version) => {
61
+ let dir = path.join(cacheDir, 'versions', version);
62
+ return fs.existsSync(path.join(dir, 'moc'))
63
+ && fs.existsSync(path.join(dir, 'mo-doc'))
64
+ && fs.existsSync(path.join(dir, 'mo-ide'));
65
+ };
66
+ let setCurrent = (version) => {
67
+ fs.copySync(path.join(cacheDir, 'versions', version), path.join(cacheDir, 'versions/current'), { recursive: true });
68
+ fs.writeFileSync(curVersionFile, version);
69
+ };
70
+ let getCurrent = () => {
71
+ if (fs.existsSync(curVersionFile)) {
72
+ return fs.readFileSync(curVersionFile).toString();
73
+ }
74
+ };
75
+ let getLatest = async () => {
76
+ let releases = await getReleases();
77
+ return releases[0].tag_name;
78
+ };
79
+ let getReleases = async () => {
80
+ let octokit = new Octokit;
81
+ let res = await octokit.request('GET /repos/dfinity/motoko/releases', {
82
+ per_page: 10,
83
+ headers: {
84
+ 'X-GitHub-Api-Version': '2022-11-28'
85
+ }
86
+ });
87
+ if (res.status !== 200) {
88
+ console.log('Releases fetch error');
89
+ process.exit(1);
90
+ }
91
+ return res.data;
92
+ };
93
+ let use = async (version) => {
94
+ if (version === 'latest') {
95
+ version = await getLatest();
96
+ }
97
+ await download(version);
98
+ setCurrent(version);
99
+ console.log(`Selected moc ${version}`);
100
+ // update github env
101
+ if (process.env.GITHUB_ENV) {
102
+ fs.appendFileSync(process.env.GITHUB_ENV, `DFX_MOC_PATH=${path.join(cacheDir, 'versions', version)}/moc\n`);
103
+ }
104
+ };
105
+ program.name('mocv')
106
+ .action(async (_, config) => {
107
+ if (config.args.length) {
108
+ console.log(`unknown command '${config.args.join(' ')}'`);
109
+ process.exit(1);
110
+ }
111
+ let releases = await getReleases();
112
+ let versions = releases.map((item) => item.tag_name);
113
+ let current = getCurrent();
114
+ let currentIndex = versions.indexOf(current);
115
+ let res = await prompts({
116
+ type: 'select',
117
+ name: 'version',
118
+ message: 'Select moc version',
119
+ choices: releases.map((release, i) => {
120
+ let date = new Date(release.published_at).toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' });
121
+ return {
122
+ title: release.tag_name + chalk.gray(` ${date}${currentIndex === i ? chalk.italic(' (current)') : ''}`),
123
+ value: release.tag_name,
124
+ };
125
+ }),
126
+ initial: currentIndex == -1 ? 0 : currentIndex,
127
+ });
128
+ if (!res.version) {
129
+ return;
130
+ }
131
+ await use(res.version);
132
+ });
133
+ let updateShellConfig = async ({ reset = false, yes = false } = {}) => {
134
+ let setDfxMocPath = reset || yes;
135
+ let updatePath = reset || yes;
136
+ if (!setDfxMocPath) {
137
+ let res = await prompts({
138
+ type: 'select',
139
+ name: 'setDfxMocPath',
140
+ message: 'Do you want to set DFX_MOC_PATH, so `dfx` will use the current `moc` version?',
141
+ choices: [
142
+ {
143
+ title: 'Yes',
144
+ value: true,
145
+ },
146
+ {
147
+ title: 'No',
148
+ value: false,
149
+ },
150
+ ],
151
+ });
152
+ setDfxMocPath = res.setDfxMocPath;
153
+ }
154
+ if (!updatePath) {
155
+ let res = await prompts({
156
+ type: 'select',
157
+ name: 'updatePath',
158
+ message: 'Do you want to update PATH, so you can call `moc`, `mo-doc` and `mo-ide` from the terminal?',
159
+ choices: [
160
+ {
161
+ title: 'Yes',
162
+ value: true,
163
+ },
164
+ {
165
+ title: 'No',
166
+ value: false,
167
+ },
168
+ ],
169
+ });
170
+ updatePath = res.updatePath;
171
+ }
172
+ if (!setDfxMocPath && !updatePath) {
173
+ console.log('Nothing to do');
174
+ return;
175
+ }
176
+ let configFiles = [];
177
+ if (reset || yes) {
178
+ configFiles = [bashrc, zshrc];
179
+ }
180
+ else {
181
+ let { configFile } = await prompts({
182
+ type: 'select',
183
+ name: 'configFile',
184
+ message: 'Select your shell config file',
185
+ choices: [
186
+ {
187
+ title: bashrc,
188
+ value: bashrc,
189
+ },
190
+ {
191
+ title: zshrc,
192
+ value: zshrc,
193
+ },
194
+ ],
195
+ });
196
+ configFiles = [configFile];
197
+ }
198
+ for (let configFile of configFiles) {
199
+ if (!fs.existsSync(configFile)) {
200
+ console.log(`${configFile} not found`);
201
+ process.exit(1);
202
+ }
203
+ let data = fs.readFileSync(configFile).toString();
204
+ let setDfxLine = '\nexport DFX_MOC_PATH="$HOME/.cache/mocv/versions/current/moc"';
205
+ let updatePathLine = '\nPATH="$HOME/.cache/mocv/versions/current:$PATH"';
206
+ let newLines = [];
207
+ setDfxMocPath && newLines.push(setDfxLine);
208
+ updatePath && newLines.push(updatePathLine);
209
+ let oldLines = [
210
+ `\nexport DFX_MOC_PATH=${path.join(cacheDir, 'versions/current')}/moc\n`,
211
+ setDfxLine,
212
+ updatePathLine,
213
+ ];
214
+ for (let oldLine of oldLines) {
215
+ data = data.replace(oldLine, '');
216
+ }
217
+ if (data.endsWith('\n\n')) {
218
+ data = data.trimEnd() + '\n';
219
+ }
220
+ if (!reset) {
221
+ if (!data.endsWith('\n')) {
222
+ data += '\n';
223
+ }
224
+ for (let newLine of newLines) {
225
+ data += newLine;
226
+ }
227
+ data += '\n';
228
+ }
229
+ fs.writeFileSync(configFile, data);
230
+ }
231
+ ;
232
+ console.log('Success!');
233
+ // console.log(`Run "source ${configFile}" to apply changes`);
234
+ console.log('Restart terminal to apply changes');
235
+ };
236
+ program.command('init')
237
+ .description('mocv one time initialization')
238
+ .option('-y, --yes', 'Skip prompts')
239
+ .action(async (options) => {
240
+ updateShellConfig(options);
241
+ });
242
+ program.command('reset')
243
+ .description('Reset changes made by `mocv init`')
244
+ .action(async () => {
245
+ updateShellConfig({ reset: true });
246
+ });
247
+ program.command('use <version>')
248
+ .description('Set current moc version.\nExample 1: "mocv use 0.8.4"\nExample 2: "mocv use latest"')
249
+ .action(async (version) => {
250
+ await use(version);
251
+ });
252
+ program.command('current')
253
+ .description('Print current moc version')
254
+ .action(async () => {
255
+ console.log(getCurrent());
256
+ });
257
+ program.command('bin [version]')
258
+ .description('Print bin directory')
259
+ .action(async (version = getCurrent()) => {
260
+ if (version === 'latest') {
261
+ version = await getLatest();
262
+ }
263
+ if (!version) {
264
+ console.log('No version selected. Please pass a version arg or run `mocv` or `mocv use <version>`');
265
+ process.exit(1);
266
+ }
267
+ if (!isCached(version)) {
268
+ await download(version, { silent: true });
269
+ }
270
+ console.log(path.join(cacheDir, 'versions', version));
271
+ });
272
+ program.parse();