ic-mops 0.36.1 → 0.37.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 (106) hide show
  1. package/bin/moc-wrapper.sh +3 -0
  2. package/bin/mops.ts +3 -0
  3. package/cache.ts +2 -2
  4. package/cli.ts +61 -4
  5. package/commands/add.ts +3 -1
  6. package/commands/bench-replica.ts +5 -3
  7. package/commands/docs.ts +9 -6
  8. package/commands/install-all.ts +7 -2
  9. package/commands/install.ts +5 -1
  10. package/commands/publish.ts +2 -0
  11. package/commands/test/test.ts +42 -19
  12. package/commands/toolchain/index.ts +325 -0
  13. package/commands/toolchain/moc.ts +58 -0
  14. package/commands/toolchain/pocket-ic.ts +74 -0
  15. package/commands/toolchain/toolchain-utils.ts +83 -0
  16. package/commands/toolchain/wasmtime.ts +45 -0
  17. package/dist/bin/mops.d.ts +1 -1
  18. package/dist/cache.js +2 -2
  19. package/dist/cli.d.ts +0 -1
  20. package/dist/cli.js +52 -3
  21. package/dist/commands/add.js +2 -1
  22. package/dist/commands/bench-replica.d.ts +1 -1
  23. package/dist/commands/bench-replica.js +5 -3
  24. package/dist/commands/docs.js +9 -6
  25. package/dist/commands/install-all.js +5 -2
  26. package/dist/commands/install.js +5 -1
  27. package/dist/commands/publish.js +1 -0
  28. package/dist/commands/test/test.js +41 -19
  29. package/dist/commands/toolchain/index.d.ts +26 -0
  30. package/dist/commands/toolchain/index.js +274 -0
  31. package/dist/commands/toolchain/moc.d.ts +5 -1
  32. package/dist/commands/toolchain/moc.js +18 -6
  33. package/dist/commands/toolchain/mocv.js +0 -1
  34. package/dist/commands/toolchain/pocket-ic.d.ts +12 -0
  35. package/dist/commands/toolchain/pocket-ic.js +62 -0
  36. package/dist/commands/toolchain/toolchain-utils.d.ts +2 -2
  37. package/dist/commands/toolchain/toolchain-utils.js +22 -6
  38. package/dist/commands/toolchain/wasmtime.d.ts +5 -1
  39. package/dist/commands/toolchain/wasmtime.js +16 -4
  40. package/dist/integrity.js +40 -15
  41. package/dist/mops.js +2 -2
  42. package/dist/package.json +9 -4
  43. package/dist/pic-js/examples/clock/tests/clock/index.d.ts +1 -0
  44. package/dist/pic-js/examples/clock/tests/clock/index.js +5 -0
  45. package/dist/pic-js/examples/clock/tests/jest.config.d.ts +3 -0
  46. package/dist/pic-js/examples/clock/tests/jest.config.js +8 -0
  47. package/dist/pic-js/examples/clock/tests/src/clock.spec.d.ts +1 -0
  48. package/dist/pic-js/examples/clock/tests/src/clock.spec.js +48 -0
  49. package/dist/pic-js/examples/counter/tests/counter/index.d.ts +1 -0
  50. package/dist/pic-js/examples/counter/tests/counter/index.js +5 -0
  51. package/dist/pic-js/examples/counter/tests/jest.config.d.ts +3 -0
  52. package/dist/pic-js/examples/counter/tests/jest.config.js +8 -0
  53. package/dist/pic-js/examples/counter/tests/src/counter.spec.d.ts +1 -0
  54. package/dist/pic-js/examples/counter/tests/src/counter.spec.js +80 -0
  55. package/dist/pic-js/examples/todo/tests/jest.config.d.ts +3 -0
  56. package/dist/pic-js/examples/todo/tests/jest.config.js +8 -0
  57. package/dist/pic-js/examples/todo/tests/src/todo.spec.d.ts +1 -0
  58. package/dist/pic-js/examples/todo/tests/src/todo.spec.js +211 -0
  59. package/dist/pic-js/examples/todo/tests/todo/index.d.ts +1 -0
  60. package/dist/pic-js/examples/todo/tests/todo/index.js +5 -0
  61. package/dist/pic-js/packages/pic/src/error.d.ts +12 -0
  62. package/dist/pic-js/packages/pic/src/error.js +36 -0
  63. package/dist/pic-js/packages/pic/src/http-client.d.ts +15 -0
  64. package/dist/pic-js/packages/pic/src/http-client.js +37 -0
  65. package/dist/pic-js/packages/pic/src/identity.d.ts +66 -0
  66. package/dist/pic-js/packages/pic/src/identity.js +86 -0
  67. package/dist/pic-js/packages/pic/src/index.d.ts +4 -0
  68. package/dist/pic-js/packages/pic/src/index.js +8 -0
  69. package/dist/pic-js/packages/pic/src/management-canister.d.ts +30 -0
  70. package/dist/pic-js/packages/pic/src/management-canister.js +43 -0
  71. package/dist/pic-js/packages/pic/src/pocket-ic-actor.d.ts +83 -0
  72. package/dist/pic-js/packages/pic/src/pocket-ic-actor.js +58 -0
  73. package/dist/pic-js/packages/pic/src/pocket-ic-client-types.d.ts +61 -0
  74. package/dist/pic-js/packages/pic/src/pocket-ic-client-types.js +2 -0
  75. package/dist/pic-js/packages/pic/src/pocket-ic-client.d.ts +24 -0
  76. package/dist/pic-js/packages/pic/src/pocket-ic-client.js +123 -0
  77. package/dist/pic-js/packages/pic/src/pocket-ic-server.d.ts +10 -0
  78. package/dist/pic-js/packages/pic/src/pocket-ic-server.js +55 -0
  79. package/dist/pic-js/packages/pic/src/pocket-ic-types.d.ts +40 -0
  80. package/dist/pic-js/packages/pic/src/pocket-ic-types.js +2 -0
  81. package/dist/pic-js/packages/pic/src/pocket-ic.d.ts +447 -0
  82. package/dist/pic-js/packages/pic/src/pocket-ic.js +551 -0
  83. package/dist/pic-js/packages/pic/src/util/candid.d.ts +1 -0
  84. package/dist/pic-js/packages/pic/src/util/candid.js +7 -0
  85. package/dist/pic-js/packages/pic/src/util/encoding.d.ts +5 -0
  86. package/dist/pic-js/packages/pic/src/util/encoding.js +19 -0
  87. package/dist/pic-js/packages/pic/src/util/fs.d.ts +4 -0
  88. package/dist/pic-js/packages/pic/src/util/fs.js +29 -0
  89. package/dist/pic-js/packages/pic/src/util/index.d.ts +5 -0
  90. package/dist/pic-js/packages/pic/src/util/index.js +21 -0
  91. package/dist/pic-js/packages/pic/src/util/os.d.ts +4 -0
  92. package/dist/pic-js/packages/pic/src/util/os.js +19 -0
  93. package/dist/pic-js/packages/pic/src/util/poll.d.ts +5 -0
  94. package/dist/pic-js/packages/pic/src/util/poll.js +28 -0
  95. package/dist/templates/mops-test.yml +4 -4
  96. package/dist/types.d.ts +7 -0
  97. package/dist/vessel.js +5 -1
  98. package/global.d.ts +2 -1
  99. package/integrity.ts +57 -17
  100. package/mops.ts +3 -3
  101. package/package.json +9 -4
  102. package/templates/mops-test.yml +4 -4
  103. package/types.ts +10 -1
  104. package/vessel.ts +6 -1
  105. package/bun.lockb +0 -0
  106. package/cli-local.ts +0 -3
@@ -1,22 +1,32 @@
1
1
  import path from 'node:path';
2
2
  import fs from 'fs-extra';
3
3
  import { globalCacheDir } from '../../mops.js';
4
- import { downloadGithubRelease } from './toolchain-utils.js';
4
+ import * as toolchainUtils from './toolchain-utils.js';
5
5
  let cacheDir = path.join(globalCacheDir, 'moc');
6
+ export let repo = 'dfinity/motoko';
7
+ export let getLatestReleaseTag = async () => {
8
+ return toolchainUtils.getLatestReleaseTag(repo);
9
+ };
10
+ export let getReleases = async () => {
11
+ return toolchainUtils.getReleases(repo);
12
+ };
6
13
  export let isCached = (version) => {
7
14
  let dir = path.join(cacheDir, version);
8
15
  return fs.existsSync(dir) && fs.existsSync(path.join(dir, 'moc'));
9
16
  };
10
- export let download = async (version, { silent = false } = {}) => {
17
+ export let download = async (version, { silent = false, verbose = false } = {}) => {
11
18
  if (process.platform == 'win32') {
12
- console.log('Windows is not supported. Please use WSL');
19
+ console.error('Windows is not supported. Please use WSL');
13
20
  process.exit(1);
14
21
  }
15
22
  if (!version) {
16
- console.log('version is not defined');
23
+ console.error('version is not defined');
17
24
  process.exit(1);
18
25
  }
19
26
  if (isCached(version)) {
27
+ if (verbose) {
28
+ console.log(`moc ${version} is already installed`);
29
+ }
20
30
  return;
21
31
  }
22
32
  let url;
@@ -31,6 +41,8 @@ export let download = async (version, { silent = false } = {}) => {
31
41
  let platfrom = process.platform == 'darwin' ? 'macos' : 'linux64';
32
42
  url = `https://github.com/dfinity/motoko/releases/download/${version}/motoko-${platfrom}-${version}.tar.gz`;
33
43
  }
34
- silent || console.log(`Downloading ${url}`);
35
- await downloadGithubRelease(url, path.join(cacheDir, version));
44
+ if (verbose && !silent) {
45
+ console.log(`Downloading ${url}`);
46
+ }
47
+ await toolchainUtils.downloadAndExtract(url, path.join(cacheDir, version));
36
48
  };
@@ -228,7 +228,6 @@ let updateShellConfig = async ({ reset = false, yes = false } = {}) => {
228
228
  }
229
229
  fs.writeFileSync(configFile, data);
230
230
  }
231
- ;
232
231
  console.log('Success!');
233
232
  // console.log(`Run "source ${configFile}" to apply changes`);
234
233
  console.log('Restart terminal to apply changes');
@@ -0,0 +1,12 @@
1
+ export declare let repo: string;
2
+ export declare let getLatestReleaseTag: () => Promise<string>;
3
+ export declare let getReleases: () => Promise<{
4
+ tag_name: string;
5
+ published_at: Date;
6
+ draft: boolean;
7
+ }[]>;
8
+ export declare let isCached: (version: string) => boolean;
9
+ export declare let download: (version: string, { silent, verbose }?: {
10
+ silent?: boolean | undefined;
11
+ verbose?: boolean | undefined;
12
+ }) => Promise<void>;
@@ -0,0 +1,62 @@
1
+ import path from 'node:path';
2
+ import fs from 'node:fs';
3
+ import { globalCacheDir } from '../../mops.js';
4
+ import * as toolchainUtils from './toolchain-utils.js';
5
+ let cacheDir = path.join(globalCacheDir, 'pocket-ic');
6
+ export let repo = 'dfinity/pocketic';
7
+ export let getLatestReleaseTag = async () => {
8
+ return '1.0.0';
9
+ // return toolchainUtils.getLatestReleaseTag(repo);
10
+ };
11
+ export let getReleases = async () => {
12
+ // return toolchainUtils.getReleases(repo);
13
+ return [
14
+ // {
15
+ // tag_name: '2.0.1',
16
+ // published_at: new Date('2023-11-23'),
17
+ // draft: false,
18
+ // },
19
+ // {
20
+ // tag_name: '2.0.0',
21
+ // published_at: new Date('2023-11-21'),
22
+ // draft: false,
23
+ // },
24
+ {
25
+ tag_name: '1.0.0',
26
+ published_at: new Date('2023-10-12'),
27
+ draft: false,
28
+ },
29
+ ];
30
+ };
31
+ export let isCached = (version) => {
32
+ let dir = path.join(cacheDir, version);
33
+ return fs.existsSync(dir) && fs.existsSync(path.join(dir, 'pocket-ic'));
34
+ };
35
+ export let download = async (version, { silent = false, verbose = false } = {}) => {
36
+ if (!version) {
37
+ console.error('version is not defined');
38
+ process.exit(1);
39
+ }
40
+ if (version !== '1.0.0') {
41
+ console.error('Currently only pocket-ic 1.0.0 is supported');
42
+ process.exit(1);
43
+ }
44
+ if (isCached(version)) {
45
+ if (verbose) {
46
+ console.log(`pocket-ic ${version} is already installed`);
47
+ }
48
+ return;
49
+ }
50
+ let platfrom = process.platform == 'darwin' ? 'darwin' : 'linux';
51
+ let arch = 'x86_64';
52
+ let hashes = {
53
+ // '2.0.1': '69e1408347723dbaa7a6cd2faa9b65c42abbe861',
54
+ // '2.0.0': '29ec86dc9f9ca4691d4d4386c8b2aa41e14d9d16',
55
+ '1.0.0': '307d5847c1d2fe1f5e19181c7d0fcec23f4658b3',
56
+ };
57
+ let url = `https://download.dfinity.systems/ic/${hashes[version]}/openssl-static-binaries/${arch}-${platfrom}/pocket-ic.gz`;
58
+ if (verbose && !silent) {
59
+ console.log(`Downloading ${url}`);
60
+ }
61
+ await toolchainUtils.downloadAndExtract(url, path.join(cacheDir, version));
62
+ };
@@ -1,3 +1,3 @@
1
- export declare let downloadGithubRelease: (url: string, dest: string) => Promise<void>;
2
- export declare let getLatestReleaseTag: (repo: string) => Promise<string | undefined>;
1
+ export declare let downloadAndExtract: (url: string, dest: string) => Promise<void>;
2
+ export declare let getLatestReleaseTag: (repo: string) => Promise<string>;
3
3
  export declare let getReleases: (repo: string) => Promise<any>;
@@ -1,4 +1,6 @@
1
1
  import path from 'node:path';
2
+ import { unzipSync } from 'node:zlib';
3
+ import { chmodSync } from 'node:fs';
2
4
  import fs from 'fs-extra';
3
5
  import decompress from 'decompress';
4
6
  import decompressTarxz from 'decomp-tarxz';
@@ -6,7 +8,7 @@ import { deleteSync } from 'del';
6
8
  import { Octokit } from 'octokit';
7
9
  import tar from 'tar';
8
10
  import { getRootDir } from '../../mops.js';
9
- export let downloadGithubRelease = async (url, dest) => {
11
+ export let downloadAndExtract = async (url, dest) => {
10
12
  let res = await fetch(url);
11
13
  if (res.status !== 200) {
12
14
  console.error(`ERROR ${res.status} ${url}`);
@@ -20,25 +22,34 @@ export let downloadGithubRelease = async (url, dest) => {
20
22
  fs.writeFileSync(archive, buffer);
21
23
  fs.mkdirSync(dest, { recursive: true });
22
24
  if (archive.endsWith('.xz')) {
23
- await decompress(archive, dest, {
24
- strip: 1,
25
+ await decompress(archive, tmpDir, {
25
26
  plugins: [decompressTarxz()],
26
27
  }).catch(() => {
27
28
  deleteSync([tmpDir]);
28
29
  });
30
+ fs.cpSync(path.join(tmpDir, path.parse(archive).name.replace('.tar', '')), dest, { recursive: true });
29
31
  }
30
- else {
32
+ else if (archive.endsWith('tar.gz')) {
31
33
  await tar.extract({
32
34
  file: archive,
33
35
  cwd: dest,
34
36
  });
35
37
  }
38
+ else if (archive.endsWith('.gz')) {
39
+ let destFile = path.join(dest, path.parse(archive).name);
40
+ fs.writeFileSync(destFile, unzipSync(buffer));
41
+ chmodSync(destFile, 0o700);
42
+ }
36
43
  deleteSync([tmpDir], { force: true });
37
44
  };
38
45
  export let getLatestReleaseTag = async (repo) => {
39
46
  let releases = await getReleases(repo);
40
47
  let release = releases.find((release) => !release.prerelease && !release.draft);
41
- return release?.tag_name;
48
+ if (!release?.tag_name) {
49
+ console.error(`Failed to fetch latest release tag for ${repo}`);
50
+ process.exit(1);
51
+ }
52
+ return release.tag_name.replace(/^v/, '');
42
53
  };
43
54
  export let getReleases = async (repo) => {
44
55
  let octokit = new Octokit;
@@ -52,5 +63,10 @@ export let getReleases = async (repo) => {
52
63
  console.log('Releases fetch error');
53
64
  process.exit(1);
54
65
  }
55
- return res.data;
66
+ return res.data.map((release) => {
67
+ return {
68
+ ...release,
69
+ tag_name: release.tag_name.replace(/^v/, ''),
70
+ };
71
+ });
56
72
  };
@@ -1,4 +1,8 @@
1
+ export declare let repo: string;
2
+ export declare let getLatestReleaseTag: () => Promise<string>;
3
+ export declare let getReleases: () => Promise<any>;
1
4
  export declare let isCached: (version: string) => boolean;
2
- export declare let download: (version: string, { silent }?: {
5
+ export declare let download: (version: string, { silent, verbose }?: {
3
6
  silent?: boolean | undefined;
7
+ verbose?: boolean | undefined;
4
8
  }) => Promise<void>;
@@ -1,23 +1,35 @@
1
1
  import path from 'node:path';
2
2
  import fs from 'fs-extra';
3
3
  import { globalCacheDir } from '../../mops.js';
4
- import { downloadGithubRelease } from './toolchain-utils.js';
4
+ import * as toolchainUtils from './toolchain-utils.js';
5
5
  let cacheDir = path.join(globalCacheDir, 'wasmtime');
6
+ export let repo = 'bytecodealliance/wasmtime';
7
+ export let getLatestReleaseTag = async () => {
8
+ return toolchainUtils.getLatestReleaseTag(repo);
9
+ };
10
+ export let getReleases = async () => {
11
+ return toolchainUtils.getReleases(repo);
12
+ };
6
13
  export let isCached = (version) => {
7
14
  let dir = path.join(cacheDir, version);
8
15
  return fs.existsSync(dir) && fs.existsSync(path.join(dir, 'wasmtime'));
9
16
  };
10
- export let download = async (version, { silent = false } = {}) => {
17
+ export let download = async (version, { silent = false, verbose = false } = {}) => {
11
18
  if (!version) {
12
19
  console.error('version is not defined');
13
20
  process.exit(1);
14
21
  }
15
22
  if (isCached(version)) {
23
+ if (verbose) {
24
+ console.log(`wasmtime ${version} is already installed`);
25
+ }
16
26
  return;
17
27
  }
18
28
  let platfrom = process.platform == 'darwin' ? 'macos' : 'linux';
19
29
  let arch = process.arch.startsWith('arm') ? 'aarch64' : 'x86_64';
20
30
  let url = `https://github.com/bytecodealliance/wasmtime/releases/download/v${version}/wasmtime-v${version}-${arch}-${platfrom}.tar.xz`;
21
- silent || console.log(`Downloading ${url}`);
22
- await downloadGithubRelease(url, path.join(cacheDir, version));
31
+ if (verbose && !silent) {
32
+ console.log(`Downloading ${url}`);
33
+ }
34
+ await toolchainUtils.downloadAndExtract(url, path.join(cacheDir, version));
23
35
  };
package/dist/integrity.js CHANGED
@@ -2,7 +2,7 @@ import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { sha256 } from '@noble/hashes/sha256';
4
4
  import { bytesToHex } from '@noble/hashes/utils';
5
- import { getDependencyType, getRootDir } from './mops.js';
5
+ import { getDependencyType, getRootDir, readConfig } from './mops.js';
6
6
  import { mainActor } from './api/actors.js';
7
7
  import { resolvePackages } from './resolve-packages.js';
8
8
  export async function checkIntegrity(lock) {
@@ -48,6 +48,18 @@ export function getLocalFileHash(fileId) {
48
48
  function getMopsTomlHash() {
49
49
  return bytesToHex(sha256(fs.readFileSync(getRootDir() + '/mops.toml')));
50
50
  }
51
+ function getMopsTomlDepsHash() {
52
+ let config = readConfig();
53
+ let deps = config.dependencies || {};
54
+ let devDeps = config['dev-dependencies'] || {};
55
+ let allDeps = { ...deps, ...devDeps };
56
+ // sort allDeps by key
57
+ let sortedDeps = Object.keys(allDeps).sort().reduce((acc, key) => {
58
+ acc[key] = allDeps[key]?.version || allDeps[key]?.repo || allDeps[key]?.path || '';
59
+ return acc;
60
+ }, {});
61
+ return bytesToHex(sha256(JSON.stringify(sortedDeps)));
62
+ }
51
63
  // compare hashes of local files with hashes from the registry
52
64
  export async function checkRemote() {
53
65
  let fileHashesFromRegistry = await getFileHashesFromRegistry();
@@ -70,15 +82,15 @@ export async function updateLockFile() {
70
82
  // if lock file exists and mops.toml hasn't changed, don't update it
71
83
  if (fs.existsSync(lockFile)) {
72
84
  let lockFileJson = JSON.parse(fs.readFileSync(lockFile).toString());
73
- let mopsTomlHash = getMopsTomlHash();
74
- if (mopsTomlHash === lockFileJson.mopsTomlHash) {
85
+ let mopsTomlDepsHash = getMopsTomlDepsHash();
86
+ if (mopsTomlDepsHash === lockFileJson.mopsTomlDepsHash) {
75
87
  return;
76
88
  }
77
89
  }
78
90
  let fileHashes = await getFileHashesFromRegistry();
79
91
  let lockFileJson = {
80
- version: 1,
81
- mopsTomlHash: getMopsTomlHash(),
92
+ version: 2,
93
+ mopsTomlDepsHash: getMopsTomlDepsHash(),
82
94
  hashes: fileHashes.reduce((acc, [packageId, fileHashes]) => {
83
95
  acc[packageId] = fileHashes.reduce((acc, [fileId, hash]) => {
84
96
  acc[fileId] = bytesToHex(new Uint8Array(hash));
@@ -101,21 +113,34 @@ export async function checkLockFile(force = false) {
101
113
  }
102
114
  return;
103
115
  }
104
- let lockFileJson = JSON.parse(fs.readFileSync(lockFile).toString());
116
+ let lockFileJsonGeneric = JSON.parse(fs.readFileSync(lockFile).toString());
105
117
  let packageIds = await getResolvedMopsPackageIds();
106
118
  // check lock file version
107
- if (lockFileJson.version !== 1) {
119
+ if (lockFileJsonGeneric.version !== 1 && lockFileJsonGeneric.version !== 2) {
108
120
  console.error('Integrity check failed');
109
- console.error(`Invalid lock file version: ${lockFileJson.version}. Supported versions: 1`);
121
+ console.error(`Invalid lock file version: ${lockFileJsonGeneric.version}. Supported versions: 1`);
110
122
  process.exit(1);
111
123
  }
112
- // check mops.toml hash
113
- if (lockFileJson.mopsTomlHash !== getMopsTomlHash()) {
114
- console.error('Integrity check failed');
115
- console.error('Mismatched mops.toml hash');
116
- console.error(`Locked hash: ${lockFileJson.mopsTomlHash}`);
117
- console.error(`Actual hash: ${getMopsTomlHash()}`);
118
- process.exit(1);
124
+ let lockFileJson = lockFileJsonGeneric;
125
+ // V1: check mops.toml hash
126
+ if (lockFileJson.version === 1) {
127
+ if (lockFileJson.mopsTomlHash !== getMopsTomlHash()) {
128
+ console.error('Integrity check failed');
129
+ console.error('Mismatched mops.toml hash');
130
+ console.error(`Locked hash: ${lockFileJson.mopsTomlHash}`);
131
+ console.error(`Actual hash: ${getMopsTomlHash()}`);
132
+ process.exit(1);
133
+ }
134
+ }
135
+ // V2: check mops.toml deps hash
136
+ if (lockFileJson.version === 2) {
137
+ if (lockFileJson.mopsTomlDepsHash !== getMopsTomlDepsHash()) {
138
+ console.error('Integrity check failed');
139
+ console.error('Mismatched mops.toml dependencies hash');
140
+ console.error(`Locked hash: ${lockFileJson.mopsTomlDepsHash}`);
141
+ console.error(`Actual hash: ${getMopsTomlDepsHash()}`);
142
+ process.exit(1);
143
+ }
119
144
  }
120
145
  // check number of packages
121
146
  if (Object.keys(lockFileJson.hashes).length !== packageIds.length) {
package/dist/mops.js CHANGED
@@ -93,7 +93,7 @@ export let getIdentity = async () => {
93
93
  };
94
94
  export function getClosestConfigFile(dir = process.cwd()) {
95
95
  if (!path.basename(dir)) {
96
- throw '';
96
+ return '';
97
97
  }
98
98
  let configFile = path.join(dir, 'mops.toml');
99
99
  if (fs.existsSync(configFile)) {
@@ -182,7 +182,7 @@ export function readConfig(configFile = getClosestConfigFile()) {
182
182
  return toml;
183
183
  }
184
184
  export function writeConfig(config, configFile = getClosestConfigFile()) {
185
- let resConfig = { ...config };
185
+ let resConfig = JSON.parse(JSON.stringify(config));
186
186
  let deps = resConfig.dependencies || {};
187
187
  Object.entries(config.dependencies || {}).forEach(([name, { repo, path, version }]) => {
188
188
  deps[name] = repo || path || version;
package/dist/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "ic-mops",
3
- "version": "0.36.1",
3
+ "version": "0.37.0",
4
4
  "type": "module",
5
5
  "bin": {
6
- "mops": "dist/cli.js"
6
+ "mops": "dist/bin/mops.js",
7
+ "moc-wrapper": "bin/moc-wrapper.sh"
7
8
  },
8
9
  "files": [
9
10
  "*",
@@ -37,7 +38,6 @@
37
38
  "@dfinity/identity": "^0.19.3",
38
39
  "@dfinity/identity-secp256k1": "^0.19.3",
39
40
  "@dfinity/principal": "^0.19.3",
40
- "@hadronous/pic": "0.2.0",
41
41
  "@iarna/toml": "^2.2.5",
42
42
  "@noble/hashes": "1.3.2",
43
43
  "as-table": "^1.0.55",
@@ -45,13 +45,15 @@
45
45
  "camelcase": "^7.0.1",
46
46
  "chalk": "^5.3.0",
47
47
  "chokidar": "^3.5.3",
48
- "commander": "^11.0.0",
48
+ "commander": "11.1.0",
49
49
  "debounce": "^1.2.1",
50
+ "decomp-tarxz": "0.1.1",
50
51
  "decompress": "^4.2.1",
51
52
  "del": "^7.0.0",
52
53
  "dhall-to-json-cli": "^1.7.6",
53
54
  "eslint": "^8.45.0",
54
55
  "execa": "7.1.1",
56
+ "fs-extra": "11.2.0",
55
57
  "get-folder-size": "^4.0.0",
56
58
  "glob": "^10.3.3",
57
59
  "globby": "^13.2.2",
@@ -63,7 +65,9 @@
63
65
  "minimatch": "^9.0.3",
64
66
  "ncp": "^2.0.0",
65
67
  "node-fetch": "^3.3.2",
68
+ "octokit": "3.1.2",
66
69
  "pem-file": "^1.0.1",
70
+ "pic-ic": "0.3.2",
67
71
  "prompts": "^2.4.2",
68
72
  "stream-to-promise": "^3.0.0",
69
73
  "string-width": "7.0.0",
@@ -73,6 +77,7 @@
73
77
  "@tsconfig/strictest": "^2.0.1",
74
78
  "@types/debounce": "^1.2.1",
75
79
  "@types/decompress": "^4.2.4",
80
+ "@types/fs-extra": "11.0.4",
76
81
  "@types/glob": "^8.1.0",
77
82
  "@types/ncp": "^2.0.5",
78
83
  "@types/node": "^20.4.4",
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.idlFactory = void 0;
4
+ var clock_did_1 = require("../../declarations/clock.did");
5
+ Object.defineProperty(exports, "idlFactory", { enumerable: true, get: function () { return clock_did_1.idlFactory; } });
@@ -0,0 +1,3 @@
1
+ import type { Config } from 'jest';
2
+ declare const config: Config;
3
+ export default config;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const config = {
4
+ watch: false,
5
+ preset: 'ts-jest/presets/js-with-ts',
6
+ testEnvironment: 'node',
7
+ };
8
+ exports.default = config;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const node_path_1 = require("node:path");
4
+ const principal_1 = require("@dfinity/principal");
5
+ const pic_1 = require("@hadronous/pic");
6
+ const clock_1 = require("../clock");
7
+ const WASM_PATH = (0, node_path_1.resolve)(__dirname, '..', '..', '..', '..', '.dfx', 'local', 'canisters', 'clock', 'clock.wasm');
8
+ describe('Clock', () => {
9
+ let actor;
10
+ let pic;
11
+ let canisterId;
12
+ beforeEach(async () => {
13
+ pic = await pic_1.PocketIc.create();
14
+ const fixture = await pic.setupCanister(clock_1.idlFactory, WASM_PATH);
15
+ actor = fixture.actor;
16
+ canisterId = fixture.canisterId;
17
+ });
18
+ afterEach(async () => {
19
+ await pic.tearDown();
20
+ });
21
+ it('should create the correct canister', async () => {
22
+ const canisterExists = await pic.checkCanisterExists(canisterId);
23
+ expect(canisterExists).toBe(true);
24
+ });
25
+ it('should not create any other canister', async () => {
26
+ const otherCanisterId = principal_1.Principal.fromUint8Array(new Uint8Array([0]));
27
+ const canisterExists = await pic.checkCanisterExists(otherCanisterId);
28
+ expect(canisterExists).toBe(false);
29
+ });
30
+ it('should set and get canister cycles', async () => {
31
+ const cycles = await pic.getCyclesBalance(canisterId);
32
+ const cyclesToAdd = 1000000;
33
+ const updatedCyclesBalance = await pic.addCycles(canisterId, cyclesToAdd);
34
+ const fetchUpdatedCyclesBalance = await pic.getCyclesBalance(canisterId);
35
+ expect(updatedCyclesBalance).toEqual(cycles + cyclesToAdd);
36
+ expect(fetchUpdatedCyclesBalance).toEqual(updatedCyclesBalance);
37
+ });
38
+ it.each([1, 10, 1000, 100000])('should return the correct time after %d second(s)', async (timeToAdvanceS) => {
39
+ await pic.resetTime();
40
+ await pic.tick();
41
+ const timeToAdvanceMs = timeToAdvanceS * 1000;
42
+ const initialTime = await actor.get();
43
+ await pic.advanceTime(timeToAdvanceMs);
44
+ await pic.tick();
45
+ const finalTime = await actor.get();
46
+ expect(finalTime).toEqual(initialTime + BigInt(timeToAdvanceMs));
47
+ });
48
+ });
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.idlFactory = void 0;
4
+ var counter_did_1 = require("../../declarations/counter.did");
5
+ Object.defineProperty(exports, "idlFactory", { enumerable: true, get: function () { return counter_did_1.idlFactory; } });
@@ -0,0 +1,3 @@
1
+ import type { Config } from 'jest';
2
+ declare const config: Config;
3
+ export default config;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const config = {
4
+ watch: false,
5
+ preset: 'ts-jest/presets/js-with-ts',
6
+ testEnvironment: 'node',
7
+ };
8
+ exports.default = config;
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const node_path_1 = require("node:path");
4
+ const pic_1 = require("@hadronous/pic");
5
+ const counter_1 = require("../counter");
6
+ const WASM_PATH = (0, node_path_1.resolve)(__dirname, '..', '..', '..', '..', '.dfx', 'local', 'canisters', 'counter', 'counter.wasm');
7
+ describe('Counter', () => {
8
+ let pic;
9
+ let actor;
10
+ let canisterId;
11
+ beforeEach(async () => {
12
+ pic = await pic_1.PocketIc.create();
13
+ const fixture = await pic.setupCanister(counter_1.idlFactory, WASM_PATH);
14
+ actor = fixture.actor;
15
+ canisterId = fixture.canisterId;
16
+ });
17
+ afterEach(async () => {
18
+ await pic.tearDown();
19
+ });
20
+ it('should start at 0', async () => {
21
+ const result = await actor.get();
22
+ expect(result).toEqual(0n);
23
+ });
24
+ it.each([42n, 306n, 7n])('should set the counter to %d', async (input) => {
25
+ await actor.set(input);
26
+ const result = await actor.get();
27
+ expect(result).toEqual(input);
28
+ });
29
+ it('should increment from 0', async () => {
30
+ const initialCount = await actor.get();
31
+ await actor.inc();
32
+ const countAfterFirstInc = await actor.get();
33
+ await actor.inc();
34
+ const finalCount = await actor.get();
35
+ expect(initialCount).toEqual(0n);
36
+ expect(countAfterFirstInc).toEqual(1n);
37
+ expect(finalCount).toEqual(2n);
38
+ });
39
+ it.each([42n, 306n, 7n])('should increment from %d', async (input) => {
40
+ await actor.set(input);
41
+ const initialCount = await actor.get();
42
+ await actor.inc();
43
+ const countAfterFirstInc = await actor.get();
44
+ await actor.inc();
45
+ const finalCount = await actor.get();
46
+ expect(initialCount).toEqual(input);
47
+ expect(countAfterFirstInc).toEqual(input + 1n);
48
+ expect(finalCount).toEqual(input + 2n);
49
+ });
50
+ it.each([42n, 306n, 7n])('should decrement from %d', async (input) => {
51
+ await actor.set(input);
52
+ const initialCount = await actor.get();
53
+ await actor.dec();
54
+ const countAfterFirstDec = await actor.get();
55
+ await actor.dec();
56
+ const finalCount = await actor.get();
57
+ expect(initialCount).toEqual(input);
58
+ expect(countAfterFirstDec).toEqual(input - 1n);
59
+ expect(finalCount).toEqual(input - 2n);
60
+ });
61
+ it('should fail to decrement from 0', async () => {
62
+ const initialCount = await actor.get();
63
+ expect(initialCount).toEqual(0n);
64
+ await expect(actor.dec()).rejects.toThrow('Natural subtraction underflow');
65
+ });
66
+ it('should upgrade the canister', async () => {
67
+ await actor.inc();
68
+ const preUpgradeCount = await actor.get();
69
+ await pic.upgradeCanister(canisterId, WASM_PATH);
70
+ const postUpgradeCount = await actor.get();
71
+ expect(preUpgradeCount).toEqual(postUpgradeCount);
72
+ });
73
+ it('should reinstall the canister', async () => {
74
+ await actor.inc();
75
+ const preReinstallCount = await actor.get();
76
+ await pic.reinstallCode(canisterId, WASM_PATH);
77
+ const postReinstallCount = await actor.get();
78
+ expect(postReinstallCount).not.toEqual(preReinstallCount);
79
+ });
80
+ });
@@ -0,0 +1,3 @@
1
+ import type { Config } from 'jest';
2
+ declare const config: Config;
3
+ export default config;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const config = {
4
+ watch: false,
5
+ preset: 'ts-jest/presets/js-with-ts',
6
+ testEnvironment: 'node',
7
+ };
8
+ exports.default = config;
@@ -0,0 +1 @@
1
+ export {};