ic-mops 0.1.3 → 0.1.6
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.js +13 -5
- package/commands/import-identity.js +7 -2
- package/commands/install-all.js +1 -1
- package/commands/install.js +32 -15
- package/commands/publish.js +21 -10
- package/commands/sources.js +3 -3
- package/commands/uninstall.js +3 -3
- package/commands/whoami.js +3 -2
- package/declarations/main/main.did +46 -30
- package/declarations/main/main.did.d.ts +47 -26
- package/declarations/main/main.did.js +52 -29
- package/declarations/storage/index.js +38 -0
- package/declarations/storage/storage.did +46 -0
- package/declarations/storage/storage.did.d.ts +37 -0
- package/declarations/storage/storage.did.js +38 -0
- package/mops.js +45 -3
- package/package.json +1 -1
package/cli.js
CHANGED
|
@@ -11,7 +11,7 @@ import {install} from './commands/install.js';
|
|
|
11
11
|
import {publish} from './commands/publish.js';
|
|
12
12
|
import {importPem} from './commands/import-identity.js';
|
|
13
13
|
import {sources} from './commands/sources.js';
|
|
14
|
-
import {
|
|
14
|
+
import {checkApiCompatibility, getHighestVersion, getNetwork, setNetwork} from './mops.js';
|
|
15
15
|
import {whoami} from './commands/whoami.js';
|
|
16
16
|
import {installAll} from './commands/install-all.js';
|
|
17
17
|
import logUpdate from 'log-update';
|
|
@@ -55,17 +55,22 @@ program
|
|
|
55
55
|
config.dependencies = {};
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
let compatible = await checkApiCompatibility();
|
|
59
|
+
if (!compatible) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
58
63
|
if (!pkg) {
|
|
59
64
|
installAll(options);
|
|
60
65
|
}
|
|
61
66
|
else {
|
|
62
|
-
let version = await
|
|
63
|
-
await install(pkg, version, options.verbose);
|
|
67
|
+
let version = await getHighestVersion(pkg);
|
|
68
|
+
await install(pkg, version, {verbose: options.verbose});
|
|
64
69
|
|
|
65
70
|
config.dependencies[pkg] = version;
|
|
66
71
|
wirteConfig(config);
|
|
67
72
|
logUpdate.clear();
|
|
68
|
-
console.log(chalk.green('Package installed ') + `${pkg} =
|
|
73
|
+
console.log(chalk.green('Package installed ') + `${pkg} = "${version}"`);
|
|
69
74
|
}
|
|
70
75
|
});
|
|
71
76
|
|
|
@@ -74,7 +79,10 @@ program
|
|
|
74
79
|
.command('publish')
|
|
75
80
|
.description('Publish package to the mops registry')
|
|
76
81
|
.action(async () => {
|
|
77
|
-
await
|
|
82
|
+
let compatible = await checkApiCompatibility();
|
|
83
|
+
if (compatible) {
|
|
84
|
+
await publish();
|
|
85
|
+
}
|
|
78
86
|
});
|
|
79
87
|
|
|
80
88
|
// set-network
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import {globalCacheDir} from '../mops.js';
|
|
3
5
|
|
|
4
6
|
export async function importPem(data) {
|
|
5
7
|
try {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
+
if (!fs.existsSync(globalCacheDir)) {
|
|
9
|
+
fs.mkdirSync(globalCacheDir);
|
|
10
|
+
}
|
|
11
|
+
let identityPem = path.resolve(globalCacheDir, 'identity.pem');
|
|
12
|
+
fs.writeFileSync(identityPem, data);
|
|
8
13
|
console.log(chalk.green('Success'));
|
|
9
14
|
}
|
|
10
15
|
catch (err) {
|
package/commands/install-all.js
CHANGED
package/commands/install.js
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
2
|
import fs from 'fs';
|
|
3
3
|
import logUpdate from 'log-update';
|
|
4
|
-
import {checkConfigFile,
|
|
4
|
+
import {checkConfigFile, getHighestVersion, mainActor, progressBar, readConfig, storageActor} from '../mops.js';
|
|
5
5
|
import {parallel} from '../parallel.js';
|
|
6
|
+
import chalk from 'chalk';
|
|
6
7
|
|
|
7
|
-
export async function install(pkg, version = '', verbose
|
|
8
|
+
export async function install(pkg, version = '', {verbose, silent, dep} = {}) {
|
|
8
9
|
if (!checkConfigFile()) {
|
|
9
10
|
return;
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
if (!version) {
|
|
13
|
-
version = await
|
|
14
|
+
version = await getHighestVersion(pkg);
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
let dir = path.join(process.cwd(), '.mops', `${pkg}@${version}`);
|
|
@@ -18,44 +19,60 @@ export async function install(pkg, version = '', verbose = false, dep = false) {
|
|
|
18
19
|
|
|
19
20
|
// cache
|
|
20
21
|
if (fs.existsSync(dir)) {
|
|
21
|
-
logUpdate(`${dep ? 'Dependency' : 'Installing'} ${pkg}@${version} (cache)`);
|
|
22
|
+
silent || logUpdate(`${dep ? 'Dependency' : 'Installing'} ${pkg}@${version} (cache)`);
|
|
22
23
|
}
|
|
23
24
|
// no cache
|
|
24
25
|
else {
|
|
25
26
|
fs.mkdirSync(dir, {recursive: true});
|
|
26
27
|
|
|
28
|
+
if (!dep) {
|
|
29
|
+
actor.notifyInstall(pkg, version);
|
|
30
|
+
}
|
|
31
|
+
let packageDetails = await actor.getPackageDetails(pkg, version);
|
|
27
32
|
let filesIds = await actor.getFileIds(pkg, version);
|
|
33
|
+
let storage = await storageActor(packageDetails.publication.storage);
|
|
28
34
|
|
|
29
35
|
// progress
|
|
30
36
|
let total = filesIds.length + 1;
|
|
31
37
|
let step = 0;
|
|
32
38
|
let progress = () => {
|
|
33
39
|
step++;
|
|
34
|
-
logUpdate(`${dep ? 'Dependency' : 'Installing'} ${pkg}@${version} ${progressBar(step, total)}`);
|
|
40
|
+
silent || logUpdate(`${dep ? 'Dependency' : 'Installing'} ${pkg}@${version} ${progressBar(step, total)}`);
|
|
35
41
|
};
|
|
36
42
|
|
|
37
43
|
// download files
|
|
38
44
|
progress();
|
|
39
45
|
await parallel(8, filesIds, async (fileId) => {
|
|
40
|
-
let
|
|
41
|
-
|
|
42
|
-
|
|
46
|
+
let fileMetaRes = await storage.getFileMeta(fileId);
|
|
47
|
+
if (fileMetaRes.err) {
|
|
48
|
+
console.log(chalk.red('ERR: ') + fileMetaRes.err);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
let fileMeta = fileMetaRes.ok;
|
|
52
|
+
|
|
53
|
+
let chunks = Array(Number(fileMeta.chunkCount));
|
|
54
|
+
for (let i = 0; i < fileMeta.chunkCount; i++) {
|
|
55
|
+
let chunkRes = await storage.downloadChunk(fileId, i);
|
|
56
|
+
if (chunkRes.err) {
|
|
57
|
+
console.log(chalk.red('ERR: ') + chunkRes.err);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
chunks[i] = chunkRes.ok;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
fs.mkdirSync(path.join(dir, path.dirname(fileMeta.path)), {recursive: true});
|
|
64
|
+
fs.writeFileSync(path.join(dir, fileMeta.path), Buffer.from(chunks.flat()));
|
|
43
65
|
progress();
|
|
44
66
|
});
|
|
45
|
-
|
|
46
|
-
// TODO: slow (update call)
|
|
47
|
-
// if (!dep) {
|
|
48
|
-
// await actor.notifyInstall(pkg, version);
|
|
49
|
-
// }
|
|
50
67
|
}
|
|
51
68
|
|
|
52
69
|
if (verbose) {
|
|
53
|
-
logUpdate.done();
|
|
70
|
+
silent || logUpdate.done();
|
|
54
71
|
}
|
|
55
72
|
|
|
56
73
|
// install dependencies
|
|
57
74
|
let config = readConfig(path.join(dir, 'mops.toml'));
|
|
58
75
|
for (let [name, version] of Object.entries(config.dependencies || {})) {
|
|
59
|
-
await install(name, version, verbose, true);
|
|
76
|
+
await install(name, version, {verbose, silent, dep: true});
|
|
60
77
|
}
|
|
61
78
|
}
|
package/commands/publish.js
CHANGED
|
@@ -17,7 +17,7 @@ export async function publish() {
|
|
|
17
17
|
|
|
18
18
|
// validate
|
|
19
19
|
for (let key of Object.keys(config)) {
|
|
20
|
-
if (!['package', 'dependencies', '
|
|
20
|
+
if (!['package', 'dependencies', 'scripts'].includes(key)) {
|
|
21
21
|
console.log(chalk.red('Error: ') + `Unknown config section [${key}]`);
|
|
22
22
|
return;
|
|
23
23
|
}
|
|
@@ -59,7 +59,6 @@ export async function publish() {
|
|
|
59
59
|
'homepage',
|
|
60
60
|
'readme',
|
|
61
61
|
'license',
|
|
62
|
-
'isPrivate',
|
|
63
62
|
'files',
|
|
64
63
|
'dfx',
|
|
65
64
|
'moc',
|
|
@@ -101,11 +100,6 @@ export async function publish() {
|
|
|
101
100
|
return;
|
|
102
101
|
}
|
|
103
102
|
|
|
104
|
-
if (config.package.permissions && Object.keys(config.package.permissions).length > 50) {
|
|
105
|
-
console.log(chalk.red('Error: ') + 'max permissions is 50');
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
103
|
if (config.package.keywords) {
|
|
110
104
|
for (let keyword of config.package.keywords) {
|
|
111
105
|
if (keyword.length > 20) {
|
|
@@ -135,7 +129,6 @@ export async function publish() {
|
|
|
135
129
|
documentation: config.package.documentation || '',
|
|
136
130
|
readme: 'README.md',
|
|
137
131
|
license: config.package.license || '',
|
|
138
|
-
isPrivate: false,
|
|
139
132
|
owner: getIdentity()?.getPrincipal() || Principal.anonymous(),
|
|
140
133
|
dfx: config.package.dfx || '',
|
|
141
134
|
moc: config.package.moc || '',
|
|
@@ -143,7 +136,6 @@ export async function publish() {
|
|
|
143
136
|
dependencies: (Object.entries(config.dependencies || {})).map(([name, version]) => {
|
|
144
137
|
return {name, version};
|
|
145
138
|
}),
|
|
146
|
-
permissions: [],
|
|
147
139
|
scripts: [],
|
|
148
140
|
};
|
|
149
141
|
|
|
@@ -196,8 +188,27 @@ export async function publish() {
|
|
|
196
188
|
// upload files
|
|
197
189
|
await parallel(8, files, async (file) => {
|
|
198
190
|
progress();
|
|
191
|
+
|
|
192
|
+
let chunkSize = 1024 * 1024 + 512 * 1024; // 1.5mb
|
|
199
193
|
let content = fs.readFileSync(file);
|
|
200
|
-
|
|
194
|
+
let chunkCount = Math.ceil(content.length / chunkSize);
|
|
195
|
+
let firstChunk = Array.from(content.slice(0, chunkSize));
|
|
196
|
+
|
|
197
|
+
let res = await actor.startFileUpload(puiblishingId, file, chunkCount, firstChunk);
|
|
198
|
+
if (res.err) {
|
|
199
|
+
console.log(chalk.red('Error: ') + res.err);
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
let fileId = res.ok;
|
|
203
|
+
|
|
204
|
+
for (let i = 1, start = i * chunkSize; start < content.length; i++) {
|
|
205
|
+
let chunk = Array.from(content.slice(start, start + chunkSize));
|
|
206
|
+
let res = await actor.uploadFileChunk(puiblishingId, fileId, i, chunk);
|
|
207
|
+
if (res.err) {
|
|
208
|
+
console.log(chalk.red('Error: ') + res.err);
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
201
212
|
});
|
|
202
213
|
|
|
203
214
|
// finish
|
package/commands/sources.js
CHANGED
|
@@ -2,7 +2,7 @@ import path from 'path';
|
|
|
2
2
|
import fs from 'fs';
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
import {install} from './install.js';
|
|
5
|
-
import {
|
|
5
|
+
import {getHighestVersion, readConfig} from '../mops.js';
|
|
6
6
|
|
|
7
7
|
function rootDir(cwd = process.cwd()) {
|
|
8
8
|
let configFile = path.join(cwd, 'mops.toml');
|
|
@@ -73,8 +73,8 @@ export async function sources({verbose} = {}) {
|
|
|
73
73
|
packages['base-unofficial'] = downloadedPackages['base-unofficial'];
|
|
74
74
|
}
|
|
75
75
|
else {
|
|
76
|
-
let version = await
|
|
77
|
-
await install('base-unofficial', version,
|
|
76
|
+
let version = await getHighestVersion('base-unofficial');
|
|
77
|
+
await install('base-unofficial', version, {silent: true, dep: true});
|
|
78
78
|
packages['base-unofficial'] = version;
|
|
79
79
|
}
|
|
80
80
|
}
|
package/commands/uninstall.js
CHANGED
|
@@ -13,20 +13,20 @@ export async function uninstall(pkg, version) {
|
|
|
13
13
|
let pkgDir = path.join(process.cwd(), '.mops', `${pkg}@${version}`);
|
|
14
14
|
|
|
15
15
|
if (!fs.existsSync(pkgDir)) {
|
|
16
|
-
console.log(`No cache to remove ${pkg} =
|
|
16
|
+
console.log(`No cache to remove ${pkg} = "${version}"`);
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
// don't remove if there are dependents
|
|
21
21
|
// let dependents = getDependents(pkg, version);
|
|
22
22
|
// if (dependents.length) {
|
|
23
|
-
// console.log(`Cache left ${pkg} =
|
|
23
|
+
// console.log(`Cache left ${pkg} = "${version}" (dependents: ${dependents})`)
|
|
24
24
|
// return;
|
|
25
25
|
// }
|
|
26
26
|
|
|
27
27
|
del.sync([`${pkgDir}/**`]);
|
|
28
28
|
|
|
29
|
-
console.log(chalk.green('Package removed ') + `${pkg} =
|
|
29
|
+
console.log(chalk.green('Package removed ') + `${pkg} = "${version}"`);
|
|
30
30
|
|
|
31
31
|
// remove dependencies
|
|
32
32
|
// let text = fs.readFileSync(path.join(pkgDir, 'mops.toml')).toString();
|
package/commands/whoami.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import fs from 'fs';
|
|
3
|
-
import
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import {getIdentity, globalCacheDir} from '../mops.js';
|
|
4
5
|
|
|
5
6
|
export function whoami() {
|
|
6
|
-
let identityPem =
|
|
7
|
+
let identityPem = path.resolve(globalCacheDir, 'identity.pem');
|
|
7
8
|
if (fs.existsSync(identityPem)) {
|
|
8
9
|
let identity = getIdentity();
|
|
9
10
|
console.log(identity.getPrincipal().toText());
|
|
@@ -1,11 +1,23 @@
|
|
|
1
1
|
type Version = text;
|
|
2
2
|
type Time = int;
|
|
3
3
|
type Text = text;
|
|
4
|
+
type StorageStats =
|
|
5
|
+
record {
|
|
6
|
+
cyclesBalance: nat;
|
|
7
|
+
fileCount: nat;
|
|
8
|
+
memorySize: nat;
|
|
9
|
+
};
|
|
10
|
+
type StorageId = principal;
|
|
4
11
|
type Script =
|
|
5
12
|
record {
|
|
6
13
|
name: text;
|
|
7
14
|
value: text;
|
|
8
15
|
};
|
|
16
|
+
type Result_2 =
|
|
17
|
+
variant {
|
|
18
|
+
err: Err;
|
|
19
|
+
ok: FileId;
|
|
20
|
+
};
|
|
9
21
|
type Result_1 =
|
|
10
22
|
variant {
|
|
11
23
|
err: PublishingErr;
|
|
@@ -18,23 +30,39 @@ type Result =
|
|
|
18
30
|
};
|
|
19
31
|
type PublishingId = text;
|
|
20
32
|
type PublishingErr = text;
|
|
21
|
-
type
|
|
33
|
+
type PackagePublication =
|
|
22
34
|
record {
|
|
23
|
-
|
|
35
|
+
storage: principal;
|
|
36
|
+
time: Time;
|
|
24
37
|
user: principal;
|
|
25
38
|
};
|
|
26
|
-
type
|
|
39
|
+
type PackageName__1 = text;
|
|
40
|
+
type PackageName = text;
|
|
41
|
+
type PackageDetails =
|
|
27
42
|
record {
|
|
28
|
-
|
|
43
|
+
config: PackageConfig__1;
|
|
29
44
|
downloadsInLast30Days: nat;
|
|
30
45
|
downloadsTotal: nat;
|
|
46
|
+
owner: principal;
|
|
47
|
+
publication: PackagePublication;
|
|
48
|
+
};
|
|
49
|
+
type PackageConfig__1 =
|
|
50
|
+
record {
|
|
51
|
+
dependencies: vec Dependency;
|
|
52
|
+
description: text;
|
|
53
|
+
dfx: text;
|
|
54
|
+
documentation: text;
|
|
55
|
+
donation: text;
|
|
56
|
+
homepage: text;
|
|
31
57
|
keywords: vec text;
|
|
58
|
+
license: text;
|
|
59
|
+
moc: text;
|
|
32
60
|
name: PackageName;
|
|
33
|
-
|
|
61
|
+
readme: text;
|
|
62
|
+
repository: text;
|
|
63
|
+
scripts: vec Script;
|
|
34
64
|
version: text;
|
|
35
65
|
};
|
|
36
|
-
type PackageName__1 = text;
|
|
37
|
-
type PackageName = text;
|
|
38
66
|
type PackageConfig =
|
|
39
67
|
record {
|
|
40
68
|
dependencies: vec Dependency;
|
|
@@ -43,48 +71,36 @@ type PackageConfig =
|
|
|
43
71
|
documentation: text;
|
|
44
72
|
donation: text;
|
|
45
73
|
homepage: text;
|
|
46
|
-
isPrivate: bool;
|
|
47
74
|
keywords: vec text;
|
|
48
75
|
license: text;
|
|
49
76
|
moc: text;
|
|
50
77
|
name: PackageName;
|
|
51
|
-
owner: principal;
|
|
52
|
-
permissions: vec Permission;
|
|
53
78
|
readme: text;
|
|
54
79
|
repository: text;
|
|
55
80
|
scripts: vec Script;
|
|
56
81
|
version: text;
|
|
57
82
|
};
|
|
58
83
|
type FileId = text;
|
|
59
|
-
type File =
|
|
60
|
-
record {
|
|
61
|
-
content: blob;
|
|
62
|
-
id: FileId;
|
|
63
|
-
path: Text;
|
|
64
|
-
};
|
|
65
84
|
type Err = text;
|
|
66
85
|
type Dependency =
|
|
67
86
|
record {
|
|
68
87
|
name: PackageName;
|
|
69
88
|
version: text;
|
|
70
89
|
};
|
|
71
|
-
type Access =
|
|
72
|
-
variant {
|
|
73
|
-
readOnly;
|
|
74
|
-
readWrite;
|
|
75
|
-
};
|
|
76
90
|
service : {
|
|
77
91
|
finishPublish: (PublishingId) -> (Result);
|
|
78
|
-
|
|
79
|
-
getFile: (FileId) -> (File) query;
|
|
92
|
+
getApiVersion: () -> (Text) query;
|
|
80
93
|
getFileIds: (PackageName__1, Version) -> (vec FileId) query;
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
94
|
+
getHighestVersion: (PackageName__1) -> (Version) query;
|
|
95
|
+
getPackageDetails: (PackageName__1, Version) -> (PackageDetails) query;
|
|
96
|
+
getRecentlyUpdatedPackages: () -> (vec PackageDetails) query;
|
|
97
|
+
getStoragesStats: () -> (vec record {
|
|
98
|
+
StorageId;
|
|
99
|
+
StorageStats;
|
|
100
|
+
}) query;
|
|
85
101
|
notifyInstall: (PackageName__1, Version) -> () oneway;
|
|
86
|
-
search: (Text) -> (vec
|
|
102
|
+
search: (Text) -> (vec PackageDetails) query;
|
|
103
|
+
startFileUpload: (PublishingId, Text, nat, blob) -> (Result_2);
|
|
87
104
|
startPublish: (PackageConfig) -> (Result_1);
|
|
88
|
-
|
|
89
|
-
whoami: () -> (Text) query;
|
|
105
|
+
uploadFileChunk: (PublishingId, FileId, nat, blob) -> (Result);
|
|
90
106
|
}
|
|
@@ -1,22 +1,13 @@
|
|
|
1
1
|
import type { Principal } from '@dfinity/principal';
|
|
2
2
|
import type { ActorMethod } from '@dfinity/agent';
|
|
3
3
|
|
|
4
|
-
export type Access = { 'readOnly' : null } |
|
|
5
|
-
{ 'readWrite' : null };
|
|
6
4
|
export interface Dependency { 'name' : PackageName, 'version' : string }
|
|
7
5
|
export type Err = string;
|
|
8
|
-
export interface File {
|
|
9
|
-
'id' : FileId,
|
|
10
|
-
'content' : Array<number>,
|
|
11
|
-
'path' : Text,
|
|
12
|
-
}
|
|
13
6
|
export type FileId = string;
|
|
14
7
|
export interface PackageConfig {
|
|
15
8
|
'dfx' : string,
|
|
16
9
|
'moc' : string,
|
|
17
|
-
'permissions' : Array<Permission>,
|
|
18
10
|
'scripts' : Array<Script>,
|
|
19
|
-
'owner' : Principal,
|
|
20
11
|
'documentation' : string,
|
|
21
12
|
'name' : PackageName,
|
|
22
13
|
'homepage' : string,
|
|
@@ -24,46 +15,76 @@ export interface PackageConfig {
|
|
|
24
15
|
'version' : string,
|
|
25
16
|
'keywords' : Array<string>,
|
|
26
17
|
'donation' : string,
|
|
27
|
-
'isPrivate' : boolean,
|
|
28
18
|
'repository' : string,
|
|
29
19
|
'dependencies' : Array<Dependency>,
|
|
30
20
|
'license' : string,
|
|
31
21
|
'readme' : string,
|
|
32
22
|
}
|
|
33
|
-
export
|
|
34
|
-
|
|
35
|
-
|
|
23
|
+
export interface PackageConfig__1 {
|
|
24
|
+
'dfx' : string,
|
|
25
|
+
'moc' : string,
|
|
26
|
+
'scripts' : Array<Script>,
|
|
27
|
+
'documentation' : string,
|
|
36
28
|
'name' : PackageName,
|
|
37
|
-
'
|
|
38
|
-
'downloadsInLast30Days' : bigint,
|
|
29
|
+
'homepage' : string,
|
|
39
30
|
'description' : string,
|
|
40
31
|
'version' : string,
|
|
41
32
|
'keywords' : Array<string>,
|
|
42
|
-
'
|
|
33
|
+
'donation' : string,
|
|
34
|
+
'repository' : string,
|
|
35
|
+
'dependencies' : Array<Dependency>,
|
|
36
|
+
'license' : string,
|
|
37
|
+
'readme' : string,
|
|
38
|
+
}
|
|
39
|
+
export interface PackageDetails {
|
|
40
|
+
'owner' : Principal,
|
|
41
|
+
'downloadsTotal' : bigint,
|
|
42
|
+
'downloadsInLast30Days' : bigint,
|
|
43
|
+
'config' : PackageConfig__1,
|
|
44
|
+
'publication' : PackagePublication,
|
|
45
|
+
}
|
|
46
|
+
export type PackageName = string;
|
|
47
|
+
export type PackageName__1 = string;
|
|
48
|
+
export interface PackagePublication {
|
|
49
|
+
'storage' : Principal,
|
|
50
|
+
'time' : Time,
|
|
51
|
+
'user' : Principal,
|
|
43
52
|
}
|
|
44
|
-
export interface Permission { 'access' : Access, 'user' : Principal }
|
|
45
53
|
export type PublishingErr = string;
|
|
46
54
|
export type PublishingId = string;
|
|
47
55
|
export type Result = { 'ok' : null } |
|
|
48
56
|
{ 'err' : Err };
|
|
49
57
|
export type Result_1 = { 'ok' : PublishingId } |
|
|
50
58
|
{ 'err' : PublishingErr };
|
|
59
|
+
export type Result_2 = { 'ok' : FileId } |
|
|
60
|
+
{ 'err' : Err };
|
|
51
61
|
export interface Script { 'value' : string, 'name' : string }
|
|
62
|
+
export type StorageId = Principal;
|
|
63
|
+
export interface StorageStats {
|
|
64
|
+
'fileCount' : bigint,
|
|
65
|
+
'cyclesBalance' : bigint,
|
|
66
|
+
'memorySize' : bigint,
|
|
67
|
+
}
|
|
52
68
|
export type Text = string;
|
|
53
69
|
export type Time = bigint;
|
|
54
70
|
export type Version = string;
|
|
55
71
|
export interface _SERVICE {
|
|
56
72
|
'finishPublish' : ActorMethod<[PublishingId], Result>,
|
|
57
|
-
'
|
|
58
|
-
'getFile' : ActorMethod<[FileId], File>,
|
|
73
|
+
'getApiVersion' : ActorMethod<[], Text>,
|
|
59
74
|
'getFileIds' : ActorMethod<[PackageName__1, Version], Array<FileId>>,
|
|
60
|
-
'
|
|
61
|
-
'
|
|
62
|
-
'
|
|
63
|
-
'
|
|
75
|
+
'getHighestVersion' : ActorMethod<[PackageName__1], Version>,
|
|
76
|
+
'getPackageDetails' : ActorMethod<[PackageName__1, Version], PackageDetails>,
|
|
77
|
+
'getRecentlyUpdatedPackages' : ActorMethod<[], Array<PackageDetails>>,
|
|
78
|
+
'getStoragesStats' : ActorMethod<[], Array<[StorageId, StorageStats]>>,
|
|
64
79
|
'notifyInstall' : ActorMethod<[PackageName__1, Version], undefined>,
|
|
65
|
-
'search' : ActorMethod<[Text], Array<
|
|
80
|
+
'search' : ActorMethod<[Text], Array<PackageDetails>>,
|
|
81
|
+
'startFileUpload' : ActorMethod<
|
|
82
|
+
[PublishingId, Text, bigint, Array<number>],
|
|
83
|
+
Result_2,
|
|
84
|
+
>,
|
|
66
85
|
'startPublish' : ActorMethod<[PackageConfig], Result_1>,
|
|
67
|
-
'
|
|
68
|
-
|
|
86
|
+
'uploadFileChunk' : ActorMethod<
|
|
87
|
+
[PublishingId, FileId, bigint, Array<number>],
|
|
88
|
+
Result,
|
|
89
|
+
>,
|
|
69
90
|
}
|
|
@@ -2,19 +2,17 @@ export const idlFactory = ({ IDL }) => {
|
|
|
2
2
|
const PublishingId = IDL.Text;
|
|
3
3
|
const Err = IDL.Text;
|
|
4
4
|
const Result = IDL.Variant({ 'ok' : IDL.Null, 'err' : Err });
|
|
5
|
+
const Text = IDL.Text;
|
|
5
6
|
const PackageName__1 = IDL.Text;
|
|
6
7
|
const Version = IDL.Text;
|
|
7
|
-
const
|
|
8
|
-
const Permission = IDL.Record({ 'access' : Access, 'user' : IDL.Principal });
|
|
8
|
+
const FileId = IDL.Text;
|
|
9
9
|
const Script = IDL.Record({ 'value' : IDL.Text, 'name' : IDL.Text });
|
|
10
10
|
const PackageName = IDL.Text;
|
|
11
11
|
const Dependency = IDL.Record({ 'name' : PackageName, 'version' : IDL.Text });
|
|
12
|
-
const
|
|
12
|
+
const PackageConfig__1 = IDL.Record({
|
|
13
13
|
'dfx' : IDL.Text,
|
|
14
14
|
'moc' : IDL.Text,
|
|
15
|
-
'permissions' : IDL.Vec(Permission),
|
|
16
15
|
'scripts' : IDL.Vec(Script),
|
|
17
|
-
'owner' : IDL.Principal,
|
|
18
16
|
'documentation' : IDL.Text,
|
|
19
17
|
'name' : PackageName,
|
|
20
18
|
'homepage' : IDL.Text,
|
|
@@ -22,61 +20,86 @@ export const idlFactory = ({ IDL }) => {
|
|
|
22
20
|
'version' : IDL.Text,
|
|
23
21
|
'keywords' : IDL.Vec(IDL.Text),
|
|
24
22
|
'donation' : IDL.Text,
|
|
25
|
-
'isPrivate' : IDL.Bool,
|
|
26
23
|
'repository' : IDL.Text,
|
|
27
24
|
'dependencies' : IDL.Vec(Dependency),
|
|
28
25
|
'license' : IDL.Text,
|
|
29
26
|
'readme' : IDL.Text,
|
|
30
27
|
});
|
|
31
|
-
const FileId = IDL.Text;
|
|
32
|
-
const Text = IDL.Text;
|
|
33
|
-
const File = IDL.Record({
|
|
34
|
-
'id' : FileId,
|
|
35
|
-
'content' : IDL.Vec(IDL.Nat8),
|
|
36
|
-
'path' : Text,
|
|
37
|
-
});
|
|
38
28
|
const Time = IDL.Int;
|
|
39
|
-
const
|
|
40
|
-
'
|
|
29
|
+
const PackagePublication = IDL.Record({
|
|
30
|
+
'storage' : IDL.Principal,
|
|
31
|
+
'time' : Time,
|
|
32
|
+
'user' : IDL.Principal,
|
|
33
|
+
});
|
|
34
|
+
const PackageDetails = IDL.Record({
|
|
35
|
+
'owner' : IDL.Principal,
|
|
41
36
|
'downloadsTotal' : IDL.Nat,
|
|
42
37
|
'downloadsInLast30Days' : IDL.Nat,
|
|
38
|
+
'config' : PackageConfig__1,
|
|
39
|
+
'publication' : PackagePublication,
|
|
40
|
+
});
|
|
41
|
+
const StorageId = IDL.Principal;
|
|
42
|
+
const StorageStats = IDL.Record({
|
|
43
|
+
'fileCount' : IDL.Nat,
|
|
44
|
+
'cyclesBalance' : IDL.Nat,
|
|
45
|
+
'memorySize' : IDL.Nat,
|
|
46
|
+
});
|
|
47
|
+
const Result_2 = IDL.Variant({ 'ok' : FileId, 'err' : Err });
|
|
48
|
+
const PackageConfig = IDL.Record({
|
|
49
|
+
'dfx' : IDL.Text,
|
|
50
|
+
'moc' : IDL.Text,
|
|
51
|
+
'scripts' : IDL.Vec(Script),
|
|
52
|
+
'documentation' : IDL.Text,
|
|
53
|
+
'name' : PackageName,
|
|
54
|
+
'homepage' : IDL.Text,
|
|
43
55
|
'description' : IDL.Text,
|
|
44
56
|
'version' : IDL.Text,
|
|
45
57
|
'keywords' : IDL.Vec(IDL.Text),
|
|
46
|
-
'
|
|
58
|
+
'donation' : IDL.Text,
|
|
59
|
+
'repository' : IDL.Text,
|
|
60
|
+
'dependencies' : IDL.Vec(Dependency),
|
|
61
|
+
'license' : IDL.Text,
|
|
62
|
+
'readme' : IDL.Text,
|
|
47
63
|
});
|
|
48
64
|
const PublishingErr = IDL.Text;
|
|
49
65
|
const Result_1 = IDL.Variant({ 'ok' : PublishingId, 'err' : PublishingErr });
|
|
50
66
|
return IDL.Service({
|
|
51
67
|
'finishPublish' : IDL.Func([PublishingId], [Result], []),
|
|
52
|
-
'
|
|
68
|
+
'getApiVersion' : IDL.Func([], [Text], ['query']),
|
|
69
|
+
'getFileIds' : IDL.Func(
|
|
53
70
|
[PackageName__1, Version],
|
|
54
|
-
[
|
|
71
|
+
[IDL.Vec(FileId)],
|
|
55
72
|
['query'],
|
|
56
73
|
),
|
|
57
|
-
'
|
|
58
|
-
'
|
|
74
|
+
'getHighestVersion' : IDL.Func([PackageName__1], [Version], ['query']),
|
|
75
|
+
'getPackageDetails' : IDL.Func(
|
|
59
76
|
[PackageName__1, Version],
|
|
60
|
-
[
|
|
77
|
+
[PackageDetails],
|
|
61
78
|
['query'],
|
|
62
79
|
),
|
|
63
|
-
'getLastConfig' : IDL.Func([PackageName__1], [PackageConfig], ['query']),
|
|
64
|
-
'getLastVersion' : IDL.Func([PackageName__1], [Version], ['query']),
|
|
65
|
-
'getReadmeFile' : IDL.Func([PackageName__1, Version], [File], ['query']),
|
|
66
80
|
'getRecentlyUpdatedPackages' : IDL.Func(
|
|
67
81
|
[],
|
|
68
|
-
[IDL.Vec(
|
|
82
|
+
[IDL.Vec(PackageDetails)],
|
|
83
|
+
['query'],
|
|
84
|
+
),
|
|
85
|
+
'getStoragesStats' : IDL.Func(
|
|
86
|
+
[],
|
|
87
|
+
[IDL.Vec(IDL.Tuple(StorageId, StorageStats))],
|
|
69
88
|
['query'],
|
|
70
89
|
),
|
|
71
90
|
'notifyInstall' : IDL.Func([PackageName__1, Version], [], ['oneway']),
|
|
72
|
-
'search' : IDL.Func([Text], [IDL.Vec(
|
|
91
|
+
'search' : IDL.Func([Text], [IDL.Vec(PackageDetails)], ['query']),
|
|
92
|
+
'startFileUpload' : IDL.Func(
|
|
93
|
+
[PublishingId, Text, IDL.Nat, IDL.Vec(IDL.Nat8)],
|
|
94
|
+
[Result_2],
|
|
95
|
+
[],
|
|
96
|
+
),
|
|
73
97
|
'startPublish' : IDL.Func([PackageConfig], [Result_1], []),
|
|
74
|
-
'
|
|
75
|
-
[PublishingId,
|
|
98
|
+
'uploadFileChunk' : IDL.Func(
|
|
99
|
+
[PublishingId, FileId, IDL.Nat, IDL.Vec(IDL.Nat8)],
|
|
76
100
|
[Result],
|
|
77
101
|
[],
|
|
78
102
|
),
|
|
79
|
-
'whoami' : IDL.Func([], [Text], ['query']),
|
|
80
103
|
});
|
|
81
104
|
};
|
|
82
105
|
export const init = ({ IDL }) => { return []; };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Actor, HttpAgent } from "@dfinity/agent";
|
|
2
|
+
|
|
3
|
+
// Imports and re-exports candid interface
|
|
4
|
+
import { idlFactory } from './storage.did.js';
|
|
5
|
+
export { idlFactory } from './storage.did.js';
|
|
6
|
+
// CANISTER_ID is replaced by webpack based on node environment
|
|
7
|
+
export const canisterId = process.env.STORAGE_CANISTER_ID;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
*
|
|
11
|
+
* @param {string | import("@dfinity/principal").Principal} canisterId Canister ID of Agent
|
|
12
|
+
* @param {{agentOptions?: import("@dfinity/agent").HttpAgentOptions; actorOptions?: import("@dfinity/agent").ActorConfig}} [options]
|
|
13
|
+
* @return {import("@dfinity/agent").ActorSubclass<import("./storage.did.js")._SERVICE>}
|
|
14
|
+
*/
|
|
15
|
+
export const createActor = (canisterId, options) => {
|
|
16
|
+
const agent = new HttpAgent({ ...options?.agentOptions });
|
|
17
|
+
|
|
18
|
+
// Fetch root key for certificate validation during development
|
|
19
|
+
if(process.env.NODE_ENV !== "production") {
|
|
20
|
+
agent.fetchRootKey().catch(err=>{
|
|
21
|
+
console.warn("Unable to fetch root key. Check to ensure that your local replica is running");
|
|
22
|
+
console.error(err);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Creates an actor with using the candid interface and the HttpAgent
|
|
27
|
+
return Actor.createActor(idlFactory, {
|
|
28
|
+
agent,
|
|
29
|
+
canisterId,
|
|
30
|
+
...options?.actorOptions,
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* A ready-to-use agent for the storage canister
|
|
36
|
+
* @type {import("@dfinity/agent").ActorSubclass<import("./storage.did.js")._SERVICE>}
|
|
37
|
+
*/
|
|
38
|
+
export const storage = createActor(canisterId);
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
type StorageStats =
|
|
2
|
+
record {
|
|
3
|
+
cyclesBalance: nat;
|
|
4
|
+
fileCount: nat;
|
|
5
|
+
memorySize: nat;
|
|
6
|
+
};
|
|
7
|
+
type Storage =
|
|
8
|
+
service {
|
|
9
|
+
acceptCycles: () -> ();
|
|
10
|
+
deleteFile: (FileId) -> ();
|
|
11
|
+
downloadChunk: (FileId, nat) -> (Result_2) query;
|
|
12
|
+
finishUpload: (FileId) -> ();
|
|
13
|
+
getFileIdsRange: (nat, nat) -> (vec FileId) query;
|
|
14
|
+
getFileMeta: (FileId) -> (Result_1) query;
|
|
15
|
+
getStats: () -> (StorageStats) query;
|
|
16
|
+
startUpload: (FileMeta) -> (Result);
|
|
17
|
+
updateFileOwners: (FileId, vec principal) -> ();
|
|
18
|
+
uploadChunk: (FileId, nat, Chunk) -> ();
|
|
19
|
+
};
|
|
20
|
+
type Result_2 =
|
|
21
|
+
variant {
|
|
22
|
+
err: Err;
|
|
23
|
+
ok: Chunk;
|
|
24
|
+
};
|
|
25
|
+
type Result_1 =
|
|
26
|
+
variant {
|
|
27
|
+
err: Err;
|
|
28
|
+
ok: FileMeta;
|
|
29
|
+
};
|
|
30
|
+
type Result =
|
|
31
|
+
variant {
|
|
32
|
+
err: Err;
|
|
33
|
+
ok;
|
|
34
|
+
};
|
|
35
|
+
type FileMeta =
|
|
36
|
+
record {
|
|
37
|
+
chunkCount: nat;
|
|
38
|
+
id: FileId__1;
|
|
39
|
+
owners: vec principal;
|
|
40
|
+
path: text;
|
|
41
|
+
};
|
|
42
|
+
type FileId__1 = text;
|
|
43
|
+
type FileId = text;
|
|
44
|
+
type Err = text;
|
|
45
|
+
type Chunk = blob;
|
|
46
|
+
service : () -> Storage
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Principal } from '@dfinity/principal';
|
|
2
|
+
import type { ActorMethod } from '@dfinity/agent';
|
|
3
|
+
|
|
4
|
+
export type Chunk = Array<number>;
|
|
5
|
+
export type Err = string;
|
|
6
|
+
export type FileId = string;
|
|
7
|
+
export type FileId__1 = string;
|
|
8
|
+
export interface FileMeta {
|
|
9
|
+
'id' : FileId__1,
|
|
10
|
+
'owners' : Array<Principal>,
|
|
11
|
+
'path' : string,
|
|
12
|
+
'chunkCount' : bigint,
|
|
13
|
+
}
|
|
14
|
+
export type Result = { 'ok' : null } |
|
|
15
|
+
{ 'err' : Err };
|
|
16
|
+
export type Result_1 = { 'ok' : FileMeta } |
|
|
17
|
+
{ 'err' : Err };
|
|
18
|
+
export type Result_2 = { 'ok' : Chunk } |
|
|
19
|
+
{ 'err' : Err };
|
|
20
|
+
export interface Storage {
|
|
21
|
+
'acceptCycles' : ActorMethod<[], undefined>,
|
|
22
|
+
'deleteFile' : ActorMethod<[FileId], undefined>,
|
|
23
|
+
'downloadChunk' : ActorMethod<[FileId, bigint], Result_2>,
|
|
24
|
+
'finishUpload' : ActorMethod<[FileId], undefined>,
|
|
25
|
+
'getFileIdsRange' : ActorMethod<[bigint, bigint], Array<FileId>>,
|
|
26
|
+
'getFileMeta' : ActorMethod<[FileId], Result_1>,
|
|
27
|
+
'getStats' : ActorMethod<[], StorageStats>,
|
|
28
|
+
'startUpload' : ActorMethod<[FileMeta], Result>,
|
|
29
|
+
'updateFileOwners' : ActorMethod<[FileId, Array<Principal>], undefined>,
|
|
30
|
+
'uploadChunk' : ActorMethod<[FileId, bigint, Chunk], undefined>,
|
|
31
|
+
}
|
|
32
|
+
export interface StorageStats {
|
|
33
|
+
'fileCount' : bigint,
|
|
34
|
+
'cyclesBalance' : bigint,
|
|
35
|
+
'memorySize' : bigint,
|
|
36
|
+
}
|
|
37
|
+
export interface _SERVICE extends Storage {}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export const idlFactory = ({ IDL }) => {
|
|
2
|
+
const FileId = IDL.Text;
|
|
3
|
+
const Chunk = IDL.Vec(IDL.Nat8);
|
|
4
|
+
const Err = IDL.Text;
|
|
5
|
+
const Result_2 = IDL.Variant({ 'ok' : Chunk, 'err' : Err });
|
|
6
|
+
const FileId__1 = IDL.Text;
|
|
7
|
+
const FileMeta = IDL.Record({
|
|
8
|
+
'id' : FileId__1,
|
|
9
|
+
'owners' : IDL.Vec(IDL.Principal),
|
|
10
|
+
'path' : IDL.Text,
|
|
11
|
+
'chunkCount' : IDL.Nat,
|
|
12
|
+
});
|
|
13
|
+
const Result_1 = IDL.Variant({ 'ok' : FileMeta, 'err' : Err });
|
|
14
|
+
const StorageStats = IDL.Record({
|
|
15
|
+
'fileCount' : IDL.Nat,
|
|
16
|
+
'cyclesBalance' : IDL.Nat,
|
|
17
|
+
'memorySize' : IDL.Nat,
|
|
18
|
+
});
|
|
19
|
+
const Result = IDL.Variant({ 'ok' : IDL.Null, 'err' : Err });
|
|
20
|
+
const Storage = IDL.Service({
|
|
21
|
+
'acceptCycles' : IDL.Func([], [], []),
|
|
22
|
+
'deleteFile' : IDL.Func([FileId], [], []),
|
|
23
|
+
'downloadChunk' : IDL.Func([FileId, IDL.Nat], [Result_2], ['query']),
|
|
24
|
+
'finishUpload' : IDL.Func([FileId], [], []),
|
|
25
|
+
'getFileIdsRange' : IDL.Func(
|
|
26
|
+
[IDL.Nat, IDL.Nat],
|
|
27
|
+
[IDL.Vec(FileId)],
|
|
28
|
+
['query'],
|
|
29
|
+
),
|
|
30
|
+
'getFileMeta' : IDL.Func([FileId], [Result_1], ['query']),
|
|
31
|
+
'getStats' : IDL.Func([], [StorageStats], ['query']),
|
|
32
|
+
'startUpload' : IDL.Func([FileMeta], [Result], []),
|
|
33
|
+
'updateFileOwners' : IDL.Func([FileId, IDL.Vec(IDL.Principal)], [], []),
|
|
34
|
+
'uploadChunk' : IDL.Func([FileId, IDL.Nat, Chunk], [], []),
|
|
35
|
+
});
|
|
36
|
+
return Storage;
|
|
37
|
+
};
|
|
38
|
+
export const init = ({ IDL }) => { return []; };
|
package/mops.js
CHANGED
|
@@ -6,13 +6,19 @@ import path from 'path';
|
|
|
6
6
|
import fs from 'fs';
|
|
7
7
|
|
|
8
8
|
import {idlFactory} from './declarations/main/main.did.js';
|
|
9
|
+
import {idlFactory as storageIdlFactory} from './declarations/storage/storage.did.js';
|
|
9
10
|
import {decodeFile} from './pem.js';
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
global.fetch = fetch;
|
|
13
14
|
|
|
15
|
+
// (!) make changes in pair with backend
|
|
16
|
+
let apiVersion = '0.1';
|
|
17
|
+
|
|
14
18
|
let networkFile = new URL('./network.txt', import.meta.url);
|
|
15
19
|
|
|
20
|
+
export let globalCacheDir = path.resolve(process.env.HOME || process.env.APPDATA, 'mops');
|
|
21
|
+
|
|
16
22
|
export function setNetwork(network) {
|
|
17
23
|
fs.writeFileSync(networkFile, network);
|
|
18
24
|
}
|
|
@@ -41,7 +47,7 @@ export function getNetwork() {
|
|
|
41
47
|
}
|
|
42
48
|
|
|
43
49
|
export let getIdentity = () => {
|
|
44
|
-
let identityPem =
|
|
50
|
+
let identityPem = path.resolve(globalCacheDir, 'identity.pem');
|
|
45
51
|
if (fs.existsSync(identityPem)) {
|
|
46
52
|
return decodeFile(identityPem);
|
|
47
53
|
}
|
|
@@ -65,6 +71,23 @@ export let mainActor = async () => {
|
|
|
65
71
|
});
|
|
66
72
|
};
|
|
67
73
|
|
|
74
|
+
export let storageActor = async (storageId) => {
|
|
75
|
+
let network = getNetwork().network;
|
|
76
|
+
let host = getNetwork().host;
|
|
77
|
+
|
|
78
|
+
let identity = getIdentity();
|
|
79
|
+
let agent = new HttpAgent({host, identity});
|
|
80
|
+
|
|
81
|
+
if (network === 'local') {
|
|
82
|
+
await agent.fetchRootKey();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return Actor.createActor(storageIdlFactory, {
|
|
86
|
+
agent,
|
|
87
|
+
canisterId: storageId,
|
|
88
|
+
});
|
|
89
|
+
};
|
|
90
|
+
|
|
68
91
|
export function checkConfigFile() {
|
|
69
92
|
let configFile = path.join(process.cwd(), 'mops.toml');
|
|
70
93
|
if (!fs.existsSync(configFile)) {
|
|
@@ -79,12 +102,31 @@ export function progressBar(step, total) {
|
|
|
79
102
|
return `[${':'.repeat(done)}${' '.repeat(10 - done)}]`;
|
|
80
103
|
}
|
|
81
104
|
|
|
82
|
-
export async function
|
|
105
|
+
export async function getHighestVersion(pkgName) {
|
|
83
106
|
let actor = await mainActor();
|
|
84
|
-
return actor.
|
|
107
|
+
return actor.getHighestVersion(pkgName);
|
|
85
108
|
}
|
|
86
109
|
|
|
87
110
|
export function readConfig(configFile = path.join(process.cwd(), 'mops.toml')) {
|
|
88
111
|
let text = fs.readFileSync(configFile).toString();
|
|
89
112
|
return TOML.parse(text);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// warn on minor mismatch
|
|
116
|
+
// err on major mismatch
|
|
117
|
+
export async function checkApiCompatibility() {
|
|
118
|
+
let actor = await mainActor();
|
|
119
|
+
let backendApiVer = await actor.getApiVersion();
|
|
120
|
+
if (backendApiVer.split('.')[0] !== apiVersion.split('.')[0]) {
|
|
121
|
+
console.log(chalk.red('ERR: ') + `CLI incompatible with backend. CLI v${apiVersion}, Backend v${backendApiVer}`);
|
|
122
|
+
console.log('Run ' + chalk.greenBright('npm i -g ic-mops') + ' to upgrade cli.');
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
else if (backendApiVer.split('.')[1] !== apiVersion.split('.')[1]) {
|
|
126
|
+
console.log('-'.repeat(50));
|
|
127
|
+
console.log(chalk.yellow('WARN: ') + `CLI probably incompatible with backend. CLI v${apiVersion}, Backend v${backendApiVer}`);
|
|
128
|
+
console.log('Recommended to run ' + chalk.greenBright('npm i -g ic-mops') + ' to upgrade cli.');
|
|
129
|
+
console.log('-'.repeat(50));
|
|
130
|
+
}
|
|
131
|
+
return true;
|
|
90
132
|
}
|