ic-mops 1.0.0 → 1.1.0-pre.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +3 -0
- package/bundle/cli.tgz +0 -0
- package/cli.ts +50 -52
- package/commands/install/install-all.ts +28 -6
- package/commands/install/install-dep.ts +5 -4
- package/commands/install/install-deps.ts +3 -2
- package/commands/install/install-local-dep.ts +11 -5
- package/commands/install/install-mops-dep.ts +8 -5
- package/dist/cli.js +44 -48
- package/dist/commands/install/install-all.d.ts +2 -1
- package/dist/commands/install/install-all.js +24 -6
- package/dist/commands/install/install-dep.d.ts +2 -1
- package/dist/commands/install/install-dep.js +4 -4
- package/dist/commands/install/install-deps.d.ts +2 -1
- package/dist/commands/install/install-deps.js +2 -2
- package/dist/commands/install/install-local-dep.d.ts +2 -1
- package/dist/commands/install/install-local-dep.js +9 -4
- package/dist/commands/install/install-mops-dep.d.ts +2 -1
- package/dist/commands/install/install-mops-dep.js +7 -5
- package/dist/integrity.d.ts +20 -0
- package/dist/integrity.js +41 -10
- package/dist/mops.d.ts +2 -1
- package/dist/mops.js +13 -10
- package/dist/package.json +1 -1
- package/dist/resolve-packages.js +7 -0
- package/dist/vessel.d.ts +2 -1
- package/dist/vessel.js +4 -1
- package/integrity.ts +55 -13
- package/mops.ts +15 -11
- package/package.json +1 -1
- package/resolve-packages.ts +9 -0
- package/test +4 -0
- package/vessel.ts +5 -1
package/CHANGELOG.md
CHANGED
package/bundle/cli.tgz
CHANGED
|
Binary file
|
package/cli.ts
CHANGED
|
@@ -25,7 +25,6 @@ import {toolchain} from './commands/toolchain/index.js';
|
|
|
25
25
|
import {Tool} from './types.js';
|
|
26
26
|
import * as self from './commands/self.js';
|
|
27
27
|
import {resolvePackages} from './resolve-packages.js';
|
|
28
|
-
// import {docs} from './commands/docs.js';
|
|
29
28
|
|
|
30
29
|
declare global {
|
|
31
30
|
// eslint-disable-next-line no-var
|
|
@@ -90,6 +89,7 @@ program
|
|
|
90
89
|
.command('install')
|
|
91
90
|
.alias('i')
|
|
92
91
|
.description('Install all dependencies specified in mops.toml')
|
|
92
|
+
.option('--no-toolchain', 'Do not install toolchain')
|
|
93
93
|
.option('--verbose')
|
|
94
94
|
.addOption(new Option('--lock <action>', 'Lockfile action').choices(['check', 'update', 'ignore']))
|
|
95
95
|
.action(async (options) => {
|
|
@@ -102,10 +102,15 @@ program
|
|
|
102
102
|
return;
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
if (options.toolchain) {
|
|
106
|
+
await toolchain.ensureToolchainInited({strict: false});
|
|
107
|
+
}
|
|
106
108
|
|
|
107
109
|
let ok = await installAll(options);
|
|
108
|
-
|
|
110
|
+
|
|
111
|
+
if (options.toolchain) {
|
|
112
|
+
await toolchain.installAll(options);
|
|
113
|
+
}
|
|
109
114
|
|
|
110
115
|
// check conflicts
|
|
111
116
|
await resolvePackages({conflicts: 'warning'});
|
|
@@ -152,16 +157,6 @@ program
|
|
|
152
157
|
console.log(getNetwork());
|
|
153
158
|
});
|
|
154
159
|
|
|
155
|
-
// user import
|
|
156
|
-
program
|
|
157
|
-
.command('mops user import <data>')
|
|
158
|
-
.description('Import .pem file data to use as identity')
|
|
159
|
-
.addOption(new Option('--no-encrypt', 'Do not ask for a password to encrypt identity'))
|
|
160
|
-
.action(async (data, options) => {
|
|
161
|
-
await importPem(data, options);
|
|
162
|
-
await getPrincipal();
|
|
163
|
-
});
|
|
164
|
-
|
|
165
160
|
// sources
|
|
166
161
|
program
|
|
167
162
|
.command('sources')
|
|
@@ -173,21 +168,13 @@ program
|
|
|
173
168
|
process.exit(1);
|
|
174
169
|
}
|
|
175
170
|
if (options.install) {
|
|
176
|
-
await installAll({silent: true, lock: 'ignore', threads: 6});
|
|
171
|
+
await installAll({silent: true, lock: 'ignore', threads: 6, installFromLockFile: true});
|
|
177
172
|
}
|
|
178
173
|
await toolchain.ensureToolchainInited({strict: false});
|
|
179
174
|
let sourcesArr = await sources(options);
|
|
180
175
|
console.log(sourcesArr.join('\n'));
|
|
181
176
|
});
|
|
182
177
|
|
|
183
|
-
// get-principal
|
|
184
|
-
program
|
|
185
|
-
.command('get-principal')
|
|
186
|
-
.description('Print your principal')
|
|
187
|
-
.action(async () => {
|
|
188
|
-
await getPrincipal();
|
|
189
|
-
});
|
|
190
|
-
|
|
191
178
|
// search
|
|
192
179
|
program
|
|
193
180
|
.command('search <text>')
|
|
@@ -225,7 +212,7 @@ program
|
|
|
225
212
|
.option('-w, --watch', 'Enable watch mode')
|
|
226
213
|
.action(async (filter, options) => {
|
|
227
214
|
checkConfigFile(true);
|
|
228
|
-
await installAll({silent: true, lock: 'ignore'});
|
|
215
|
+
await installAll({silent: true, lock: 'ignore', installFromLockFile: true});
|
|
229
216
|
await test(filter, options);
|
|
230
217
|
});
|
|
231
218
|
|
|
@@ -241,7 +228,7 @@ program
|
|
|
241
228
|
.addOption(new Option('--verbose', 'Show more information'))
|
|
242
229
|
.action(async (filter, options) => {
|
|
243
230
|
checkConfigFile(true);
|
|
244
|
-
await installAll({silent: true, lock: 'ignore'});
|
|
231
|
+
await installAll({silent: true, lock: 'ignore', installFromLockFile: true});
|
|
245
232
|
await bench(filter, options);
|
|
246
233
|
});
|
|
247
234
|
|
|
@@ -256,37 +243,48 @@ program
|
|
|
256
243
|
await template();
|
|
257
244
|
});
|
|
258
245
|
|
|
259
|
-
//
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
//
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
// user
|
|
271
|
-
|
|
272
|
-
.command('
|
|
273
|
-
.
|
|
246
|
+
// mops user *
|
|
247
|
+
const userCommand = new Command('user').description('User management');
|
|
248
|
+
|
|
249
|
+
// user get-principal
|
|
250
|
+
userCommand
|
|
251
|
+
.command('get-principal')
|
|
252
|
+
.description('Print your principal')
|
|
253
|
+
.action(async () => {
|
|
254
|
+
await getPrincipal();
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
// user import
|
|
258
|
+
userCommand
|
|
259
|
+
.command('import <data>')
|
|
260
|
+
.description('Import .pem file data to use as identity')
|
|
261
|
+
.addOption(new Option('--no-encrypt', 'Do not ask for a password to encrypt identity'))
|
|
262
|
+
.action(async (data, options) => {
|
|
263
|
+
await importPem(data, options);
|
|
264
|
+
await getPrincipal();
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
// user set <prop> <value>
|
|
268
|
+
userCommand
|
|
269
|
+
.command('set')
|
|
274
270
|
.addArgument(new Argument('<prop>').choices(['name', 'site', 'email', 'github', 'twitter']))
|
|
275
|
-
.addArgument(new Argument('
|
|
276
|
-
.description('
|
|
277
|
-
.action(async (
|
|
278
|
-
|
|
279
|
-
await getUserProp(prop);
|
|
280
|
-
}
|
|
281
|
-
else if (sub == 'set') {
|
|
282
|
-
if (!value) {
|
|
283
|
-
console.log('error: missing required argument "value"');
|
|
284
|
-
return;
|
|
285
|
-
}
|
|
286
|
-
await setUserProp(prop, value);
|
|
287
|
-
}
|
|
271
|
+
.addArgument(new Argument('<value>'))
|
|
272
|
+
.description('Set user property')
|
|
273
|
+
.action(async (prop, value) => {
|
|
274
|
+
await setUserProp(prop, value);
|
|
288
275
|
});
|
|
289
276
|
|
|
277
|
+
// user get <prop>
|
|
278
|
+
userCommand
|
|
279
|
+
.command('get')
|
|
280
|
+
.addArgument(new Argument('<prop>').choices(['name', 'site', 'email', 'github', 'twitter']))
|
|
281
|
+
.description('Get user property')
|
|
282
|
+
.action(async (prop) => {
|
|
283
|
+
await getUserProp(prop);
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
program.addCommand(userCommand);
|
|
287
|
+
|
|
290
288
|
// bump
|
|
291
289
|
program
|
|
292
290
|
.command('bump [major|minor|patch]')
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import process from 'node:process';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import {createLogUpdate} from 'log-update';
|
|
4
|
-
import {checkConfigFile, readConfig} from '../../mops.js';
|
|
5
|
-
import {checkIntegrity} from '../../integrity.js';
|
|
4
|
+
import {checkConfigFile, parseDepValue, readConfig} from '../../mops.js';
|
|
5
|
+
import {checkIntegrity, checkLockFileLight, readLockFile} from '../../integrity.js';
|
|
6
6
|
import {installDeps} from './install-deps.js';
|
|
7
7
|
import {checkRequirements} from '../../check-requirements.js';
|
|
8
8
|
import {syncLocalCache} from './sync-local-cache.js';
|
|
@@ -13,9 +13,10 @@ type InstallAllOptions = {
|
|
|
13
13
|
silent ?: boolean;
|
|
14
14
|
lock ?: 'check' | 'update' | 'ignore';
|
|
15
15
|
threads ?: number;
|
|
16
|
+
installFromLockFile ?: boolean;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
|
-
export async function installAll({verbose = false, silent = false, threads, lock} : InstallAllOptions = {}) : Promise<boolean> {
|
|
19
|
+
export async function installAll({verbose = false, silent = false, threads, lock, installFromLockFile} : InstallAllOptions = {}) : Promise<boolean> {
|
|
19
20
|
if (!checkConfigFile()) {
|
|
20
21
|
return false;
|
|
21
22
|
}
|
|
@@ -24,12 +25,33 @@ export async function installAll({verbose = false, silent = false, threads, lock
|
|
|
24
25
|
let deps = Object.values(config.dependencies || {});
|
|
25
26
|
let devDeps = Object.values(config['dev-dependencies'] || {});
|
|
26
27
|
let allDeps = [...deps, ...devDeps];
|
|
28
|
+
let installedFromLockFile = false;
|
|
27
29
|
|
|
28
|
-
|
|
29
|
-
if (
|
|
30
|
-
|
|
30
|
+
// install from lock file to avoid installing intermediate dependencies
|
|
31
|
+
if ((lock !== 'ignore' || installFromLockFile) && checkLockFileLight()) {
|
|
32
|
+
let lockFileJson = readLockFile();
|
|
33
|
+
|
|
34
|
+
if (lockFileJson && lockFileJson.version === 3) {
|
|
35
|
+
verbose && console.log('Installing from lock file...');
|
|
36
|
+
installedFromLockFile = true;
|
|
37
|
+
let deps = Object.entries(lockFileJson.deps).map(([name, version]) => {
|
|
38
|
+
return parseDepValue(name, version);
|
|
39
|
+
});
|
|
40
|
+
let ok = await installDeps(deps, {silent, verbose, threads, ignoreTransitive: true});
|
|
41
|
+
if (!ok) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
31
45
|
}
|
|
32
46
|
|
|
47
|
+
if (!installedFromLockFile) {
|
|
48
|
+
let ok = await installDeps(allDeps, {silent, verbose, threads});
|
|
49
|
+
if (!ok) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
33
55
|
let logUpdate = createLogUpdate(process.stdout, {showCursor: true});
|
|
34
56
|
|
|
35
57
|
if (!silent && lock !== 'ignore') {
|
|
@@ -9,13 +9,14 @@ type InstallDepOptions = {
|
|
|
9
9
|
verbose ?: boolean;
|
|
10
10
|
silent ?: boolean;
|
|
11
11
|
threads ?: number;
|
|
12
|
+
ignoreTransitive ?: boolean;
|
|
12
13
|
};
|
|
13
14
|
|
|
14
15
|
// install dependency
|
|
15
16
|
// returns false if failed
|
|
16
|
-
export async function installDep(dep : Dependency, {verbose, silent, threads} : InstallDepOptions = {}, parentPkgPath ?: string) : Promise<boolean> {
|
|
17
|
+
export async function installDep(dep : Dependency, {verbose, silent, threads, ignoreTransitive} : InstallDepOptions = {}, parentPkgPath ?: string) : Promise<boolean> {
|
|
17
18
|
if (dep.repo) {
|
|
18
|
-
await installFromGithub(dep.name, dep.repo, {silent, verbose});
|
|
19
|
+
await installFromGithub(dep.name, dep.repo, {silent, verbose, ignoreTransitive});
|
|
19
20
|
return true;
|
|
20
21
|
}
|
|
21
22
|
else if (dep.path) {
|
|
@@ -24,10 +25,10 @@ export async function installDep(dep : Dependency, {verbose, silent, threads} :
|
|
|
24
25
|
if (parentPkgPath) {
|
|
25
26
|
depPath = path.resolve(parentPkgPath, dep.path);
|
|
26
27
|
}
|
|
27
|
-
return installLocalDep(dep.name, depPath, {silent, verbose});
|
|
28
|
+
return installLocalDep(dep.name, depPath, {silent, verbose, ignoreTransitive});
|
|
28
29
|
}
|
|
29
30
|
else if (dep.version) {
|
|
30
|
-
return installMopsDep(dep.name, dep.version, {silent, verbose, threads});
|
|
31
|
+
return installMopsDep(dep.name, dep.version, {silent, verbose, threads, ignoreTransitive});
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
return true;
|
|
@@ -5,16 +5,17 @@ type InstallDepsOptions = {
|
|
|
5
5
|
verbose ?: boolean;
|
|
6
6
|
silent ?: boolean;
|
|
7
7
|
threads ?: number;
|
|
8
|
+
ignoreTransitive ?: boolean;
|
|
8
9
|
};
|
|
9
10
|
|
|
10
11
|
// install all dependencies
|
|
11
12
|
// returns actual installed dependencies
|
|
12
13
|
// returns false if failed
|
|
13
|
-
export async function installDeps(deps : Dependency[], {verbose, silent, threads} : InstallDepsOptions = {}, parentPkgPath ?: string) : Promise<boolean> {
|
|
14
|
+
export async function installDeps(deps : Dependency[], {verbose, silent, threads, ignoreTransitive} : InstallDepsOptions = {}, parentPkgPath ?: string) : Promise<boolean> {
|
|
14
15
|
let ok = true;
|
|
15
16
|
|
|
16
17
|
for (const dep of deps) {
|
|
17
|
-
let res = await installDep(dep, {verbose, silent, threads}, parentPkgPath);
|
|
18
|
+
let res = await installDep(dep, {verbose, silent, threads, ignoreTransitive}, parentPkgPath);
|
|
18
19
|
if (!res) {
|
|
19
20
|
ok = false;
|
|
20
21
|
}
|
|
@@ -7,11 +7,12 @@ import {installDeps} from './install-deps.js';
|
|
|
7
7
|
type InstallLocalDepOptions = {
|
|
8
8
|
verbose ?: boolean;
|
|
9
9
|
silent ?: boolean;
|
|
10
|
+
ignoreTransitive ?: boolean;
|
|
10
11
|
};
|
|
11
12
|
|
|
12
13
|
// skip install and just find non-local dependencies to install
|
|
13
14
|
// pkgPath should be relative to the current root dir or absolute
|
|
14
|
-
export async function installLocalDep(pkg : string, pkgPath = '', {verbose, silent} : InstallLocalDepOptions = {}) : Promise<boolean> {
|
|
15
|
+
export async function installLocalDep(pkg : string, pkgPath = '', {verbose, silent, ignoreTransitive} : InstallLocalDepOptions = {}) : Promise<boolean> {
|
|
15
16
|
if (!silent) {
|
|
16
17
|
let logUpdate = createLogUpdate(process.stdout, {showCursor: true});
|
|
17
18
|
logUpdate(`Local dependency ${pkg} = "${pkgPath}"`);
|
|
@@ -25,7 +26,12 @@ export async function installLocalDep(pkg : string, pkgPath = '', {verbose, sile
|
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
// install dependencies
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
29
|
+
if (!ignoreTransitive) {
|
|
30
|
+
let dir = path.resolve(getRootDir(), pkgPath);
|
|
31
|
+
let config = readConfig(path.join(dir, 'mops.toml'));
|
|
32
|
+
return installDeps(Object.values(config.dependencies || {}), {silent, verbose}, pkgPath);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -19,9 +19,10 @@ type InstallMopsDepOptions = {
|
|
|
19
19
|
silent ?: boolean;
|
|
20
20
|
dep ?: boolean;
|
|
21
21
|
threads ?: number;
|
|
22
|
+
ignoreTransitive ?: boolean;
|
|
22
23
|
};
|
|
23
24
|
|
|
24
|
-
export async function installMopsDep(pkg : string, version = '', {verbose, silent, dep, threads} : InstallMopsDepOptions = {}) : Promise<boolean> {
|
|
25
|
+
export async function installMopsDep(pkg : string, version = '', {verbose, silent, dep, threads, ignoreTransitive} : InstallMopsDepOptions = {}) : Promise<boolean> {
|
|
25
26
|
threads = threads || 12;
|
|
26
27
|
let depName = getDepName(pkg);
|
|
27
28
|
|
|
@@ -113,11 +114,13 @@ export async function installMopsDep(pkg : string, version = '', {verbose, silen
|
|
|
113
114
|
}
|
|
114
115
|
|
|
115
116
|
// install dependencies
|
|
116
|
-
|
|
117
|
-
|
|
117
|
+
if (!ignoreTransitive) {
|
|
118
|
+
let config = readConfig(path.join(cacheDir, 'mops.toml'));
|
|
119
|
+
let res = await installDeps(Object.values(config.dependencies || {}), {silent, verbose});
|
|
118
120
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
+
if (!res) {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
121
124
|
}
|
|
122
125
|
|
|
123
126
|
return true;
|
package/dist/cli.js
CHANGED
|
@@ -72,6 +72,7 @@ program
|
|
|
72
72
|
.command('install')
|
|
73
73
|
.alias('i')
|
|
74
74
|
.description('Install all dependencies specified in mops.toml')
|
|
75
|
+
.option('--no-toolchain', 'Do not install toolchain')
|
|
75
76
|
.option('--verbose')
|
|
76
77
|
.addOption(new Option('--lock <action>', 'Lockfile action').choices(['check', 'update', 'ignore']))
|
|
77
78
|
.action(async (options) => {
|
|
@@ -82,9 +83,13 @@ program
|
|
|
82
83
|
if (!compatible) {
|
|
83
84
|
return;
|
|
84
85
|
}
|
|
85
|
-
|
|
86
|
+
if (options.toolchain) {
|
|
87
|
+
await toolchain.ensureToolchainInited({ strict: false });
|
|
88
|
+
}
|
|
86
89
|
let ok = await installAll(options);
|
|
87
|
-
|
|
90
|
+
if (options.toolchain) {
|
|
91
|
+
await toolchain.installAll(options);
|
|
92
|
+
}
|
|
88
93
|
// check conflicts
|
|
89
94
|
await resolvePackages({ conflicts: 'warning' });
|
|
90
95
|
if (!ok) {
|
|
@@ -125,15 +130,6 @@ program
|
|
|
125
130
|
.action(async () => {
|
|
126
131
|
console.log(getNetwork());
|
|
127
132
|
});
|
|
128
|
-
// user import
|
|
129
|
-
program
|
|
130
|
-
.command('mops user import <data>')
|
|
131
|
-
.description('Import .pem file data to use as identity')
|
|
132
|
-
.addOption(new Option('--no-encrypt', 'Do not ask for a password to encrypt identity'))
|
|
133
|
-
.action(async (data, options) => {
|
|
134
|
-
await importPem(data, options);
|
|
135
|
-
await getPrincipal();
|
|
136
|
-
});
|
|
137
133
|
// sources
|
|
138
134
|
program
|
|
139
135
|
.command('sources')
|
|
@@ -145,19 +141,12 @@ program
|
|
|
145
141
|
process.exit(1);
|
|
146
142
|
}
|
|
147
143
|
if (options.install) {
|
|
148
|
-
await installAll({ silent: true, lock: 'ignore', threads: 6 });
|
|
144
|
+
await installAll({ silent: true, lock: 'ignore', threads: 6, installFromLockFile: true });
|
|
149
145
|
}
|
|
150
146
|
await toolchain.ensureToolchainInited({ strict: false });
|
|
151
147
|
let sourcesArr = await sources(options);
|
|
152
148
|
console.log(sourcesArr.join('\n'));
|
|
153
149
|
});
|
|
154
|
-
// get-principal
|
|
155
|
-
program
|
|
156
|
-
.command('get-principal')
|
|
157
|
-
.description('Print your principal')
|
|
158
|
-
.action(async () => {
|
|
159
|
-
await getPrincipal();
|
|
160
|
-
});
|
|
161
150
|
// search
|
|
162
151
|
program
|
|
163
152
|
.command('search <text>')
|
|
@@ -193,7 +182,7 @@ program
|
|
|
193
182
|
.option('-w, --watch', 'Enable watch mode')
|
|
194
183
|
.action(async (filter, options) => {
|
|
195
184
|
checkConfigFile(true);
|
|
196
|
-
await installAll({ silent: true, lock: 'ignore' });
|
|
185
|
+
await installAll({ silent: true, lock: 'ignore', installFromLockFile: true });
|
|
197
186
|
await test(filter, options);
|
|
198
187
|
});
|
|
199
188
|
// bench
|
|
@@ -208,7 +197,7 @@ program
|
|
|
208
197
|
.addOption(new Option('--verbose', 'Show more information'))
|
|
209
198
|
.action(async (filter, options) => {
|
|
210
199
|
checkConfigFile(true);
|
|
211
|
-
await installAll({ silent: true, lock: 'ignore' });
|
|
200
|
+
await installAll({ silent: true, lock: 'ignore', installFromLockFile: true });
|
|
212
201
|
await bench(filter, options);
|
|
213
202
|
});
|
|
214
203
|
// template
|
|
@@ -221,35 +210,42 @@ program
|
|
|
221
210
|
}
|
|
222
211
|
await template();
|
|
223
212
|
});
|
|
224
|
-
//
|
|
225
|
-
|
|
226
|
-
//
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
//
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
.
|
|
237
|
-
.
|
|
213
|
+
// mops user *
|
|
214
|
+
const userCommand = new Command('user').description('User management');
|
|
215
|
+
// user get-principal
|
|
216
|
+
userCommand
|
|
217
|
+
.command('get-principal')
|
|
218
|
+
.description('Print your principal')
|
|
219
|
+
.action(async () => {
|
|
220
|
+
await getPrincipal();
|
|
221
|
+
});
|
|
222
|
+
// user import
|
|
223
|
+
userCommand
|
|
224
|
+
.command('import <data>')
|
|
225
|
+
.description('Import .pem file data to use as identity')
|
|
226
|
+
.addOption(new Option('--no-encrypt', 'Do not ask for a password to encrypt identity'))
|
|
227
|
+
.action(async (data, options) => {
|
|
228
|
+
await importPem(data, options);
|
|
229
|
+
await getPrincipal();
|
|
230
|
+
});
|
|
231
|
+
// user set <prop> <value>
|
|
232
|
+
userCommand
|
|
233
|
+
.command('set')
|
|
238
234
|
.addArgument(new Argument('<prop>').choices(['name', 'site', 'email', 'github', 'twitter']))
|
|
239
|
-
.addArgument(new Argument('
|
|
240
|
-
.description('
|
|
241
|
-
.action(async (
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
}
|
|
235
|
+
.addArgument(new Argument('<value>'))
|
|
236
|
+
.description('Set user property')
|
|
237
|
+
.action(async (prop, value) => {
|
|
238
|
+
await setUserProp(prop, value);
|
|
239
|
+
});
|
|
240
|
+
// user get <prop>
|
|
241
|
+
userCommand
|
|
242
|
+
.command('get')
|
|
243
|
+
.addArgument(new Argument('<prop>').choices(['name', 'site', 'email', 'github', 'twitter']))
|
|
244
|
+
.description('Get user property')
|
|
245
|
+
.action(async (prop) => {
|
|
246
|
+
await getUserProp(prop);
|
|
252
247
|
});
|
|
248
|
+
program.addCommand(userCommand);
|
|
253
249
|
// bump
|
|
254
250
|
program
|
|
255
251
|
.command('bump [major|minor|patch]')
|
|
@@ -3,6 +3,7 @@ type InstallAllOptions = {
|
|
|
3
3
|
silent?: boolean;
|
|
4
4
|
lock?: 'check' | 'update' | 'ignore';
|
|
5
5
|
threads?: number;
|
|
6
|
+
installFromLockFile?: boolean;
|
|
6
7
|
};
|
|
7
|
-
export declare function installAll({ verbose, silent, threads, lock }?: InstallAllOptions): Promise<boolean>;
|
|
8
|
+
export declare function installAll({ verbose, silent, threads, lock, installFromLockFile }?: InstallAllOptions): Promise<boolean>;
|
|
8
9
|
export {};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import process from 'node:process';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import { createLogUpdate } from 'log-update';
|
|
4
|
-
import { checkConfigFile, readConfig } from '../../mops.js';
|
|
5
|
-
import { checkIntegrity } from '../../integrity.js';
|
|
4
|
+
import { checkConfigFile, parseDepValue, readConfig } from '../../mops.js';
|
|
5
|
+
import { checkIntegrity, checkLockFileLight, readLockFile } from '../../integrity.js';
|
|
6
6
|
import { installDeps } from './install-deps.js';
|
|
7
7
|
import { checkRequirements } from '../../check-requirements.js';
|
|
8
8
|
import { syncLocalCache } from './sync-local-cache.js';
|
|
9
9
|
import { notifyInstalls } from '../../notify-installs.js';
|
|
10
|
-
export async function installAll({ verbose = false, silent = false, threads, lock } = {}) {
|
|
10
|
+
export async function installAll({ verbose = false, silent = false, threads, lock, installFromLockFile } = {}) {
|
|
11
11
|
if (!checkConfigFile()) {
|
|
12
12
|
return false;
|
|
13
13
|
}
|
|
@@ -15,9 +15,27 @@ export async function installAll({ verbose = false, silent = false, threads, loc
|
|
|
15
15
|
let deps = Object.values(config.dependencies || {});
|
|
16
16
|
let devDeps = Object.values(config['dev-dependencies'] || {});
|
|
17
17
|
let allDeps = [...deps, ...devDeps];
|
|
18
|
-
let
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
let installedFromLockFile = false;
|
|
19
|
+
// install from lock file to avoid installing intermediate dependencies
|
|
20
|
+
if ((lock !== 'ignore' || installFromLockFile) && checkLockFileLight()) {
|
|
21
|
+
let lockFileJson = readLockFile();
|
|
22
|
+
if (lockFileJson && lockFileJson.version === 3) {
|
|
23
|
+
verbose && console.log('Installing from lock file...');
|
|
24
|
+
installedFromLockFile = true;
|
|
25
|
+
let deps = Object.entries(lockFileJson.deps).map(([name, version]) => {
|
|
26
|
+
return parseDepValue(name, version);
|
|
27
|
+
});
|
|
28
|
+
let ok = await installDeps(deps, { silent, verbose, threads, ignoreTransitive: true });
|
|
29
|
+
if (!ok) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (!installedFromLockFile) {
|
|
35
|
+
let ok = await installDeps(allDeps, { silent, verbose, threads });
|
|
36
|
+
if (!ok) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
21
39
|
}
|
|
22
40
|
let logUpdate = createLogUpdate(process.stdout, { showCursor: true });
|
|
23
41
|
if (!silent && lock !== 'ignore') {
|
|
@@ -3,6 +3,7 @@ type InstallDepOptions = {
|
|
|
3
3
|
verbose?: boolean;
|
|
4
4
|
silent?: boolean;
|
|
5
5
|
threads?: number;
|
|
6
|
+
ignoreTransitive?: boolean;
|
|
6
7
|
};
|
|
7
|
-
export declare function installDep(dep: Dependency, { verbose, silent, threads }?: InstallDepOptions, parentPkgPath?: string): Promise<boolean>;
|
|
8
|
+
export declare function installDep(dep: Dependency, { verbose, silent, threads, ignoreTransitive }?: InstallDepOptions, parentPkgPath?: string): Promise<boolean>;
|
|
8
9
|
export {};
|
|
@@ -5,9 +5,9 @@ import { installLocalDep } from './install-local-dep.js';
|
|
|
5
5
|
import { getRootDir } from '../../mops.js';
|
|
6
6
|
// install dependency
|
|
7
7
|
// returns false if failed
|
|
8
|
-
export async function installDep(dep, { verbose, silent, threads } = {}, parentPkgPath) {
|
|
8
|
+
export async function installDep(dep, { verbose, silent, threads, ignoreTransitive } = {}, parentPkgPath) {
|
|
9
9
|
if (dep.repo) {
|
|
10
|
-
await installFromGithub(dep.name, dep.repo, { silent, verbose });
|
|
10
|
+
await installFromGithub(dep.name, dep.repo, { silent, verbose, ignoreTransitive });
|
|
11
11
|
return true;
|
|
12
12
|
}
|
|
13
13
|
else if (dep.path) {
|
|
@@ -16,10 +16,10 @@ export async function installDep(dep, { verbose, silent, threads } = {}, parentP
|
|
|
16
16
|
if (parentPkgPath) {
|
|
17
17
|
depPath = path.resolve(parentPkgPath, dep.path);
|
|
18
18
|
}
|
|
19
|
-
return installLocalDep(dep.name, depPath, { silent, verbose });
|
|
19
|
+
return installLocalDep(dep.name, depPath, { silent, verbose, ignoreTransitive });
|
|
20
20
|
}
|
|
21
21
|
else if (dep.version) {
|
|
22
|
-
return installMopsDep(dep.name, dep.version, { silent, verbose, threads });
|
|
22
|
+
return installMopsDep(dep.name, dep.version, { silent, verbose, threads, ignoreTransitive });
|
|
23
23
|
}
|
|
24
24
|
return true;
|
|
25
25
|
}
|
|
@@ -3,6 +3,7 @@ type InstallDepsOptions = {
|
|
|
3
3
|
verbose?: boolean;
|
|
4
4
|
silent?: boolean;
|
|
5
5
|
threads?: number;
|
|
6
|
+
ignoreTransitive?: boolean;
|
|
6
7
|
};
|
|
7
|
-
export declare function installDeps(deps: Dependency[], { verbose, silent, threads }?: InstallDepsOptions, parentPkgPath?: string): Promise<boolean>;
|
|
8
|
+
export declare function installDeps(deps: Dependency[], { verbose, silent, threads, ignoreTransitive }?: InstallDepsOptions, parentPkgPath?: string): Promise<boolean>;
|
|
8
9
|
export {};
|
|
@@ -2,10 +2,10 @@ import { installDep } from './install-dep.js';
|
|
|
2
2
|
// install all dependencies
|
|
3
3
|
// returns actual installed dependencies
|
|
4
4
|
// returns false if failed
|
|
5
|
-
export async function installDeps(deps, { verbose, silent, threads } = {}, parentPkgPath) {
|
|
5
|
+
export async function installDeps(deps, { verbose, silent, threads, ignoreTransitive } = {}, parentPkgPath) {
|
|
6
6
|
let ok = true;
|
|
7
7
|
for (const dep of deps) {
|
|
8
|
-
let res = await installDep(dep, { verbose, silent, threads }, parentPkgPath);
|
|
8
|
+
let res = await installDep(dep, { verbose, silent, threads, ignoreTransitive }, parentPkgPath);
|
|
9
9
|
if (!res) {
|
|
10
10
|
ok = false;
|
|
11
11
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
type InstallLocalDepOptions = {
|
|
2
2
|
verbose?: boolean;
|
|
3
3
|
silent?: boolean;
|
|
4
|
+
ignoreTransitive?: boolean;
|
|
4
5
|
};
|
|
5
|
-
export declare function installLocalDep(pkg: string, pkgPath?: string, { verbose, silent }?: InstallLocalDepOptions): Promise<boolean>;
|
|
6
|
+
export declare function installLocalDep(pkg: string, pkgPath?: string, { verbose, silent, ignoreTransitive }?: InstallLocalDepOptions): Promise<boolean>;
|
|
6
7
|
export {};
|
|
@@ -5,7 +5,7 @@ import { getRootDir, readConfig } from '../../mops.js';
|
|
|
5
5
|
import { installDeps } from './install-deps.js';
|
|
6
6
|
// skip install and just find non-local dependencies to install
|
|
7
7
|
// pkgPath should be relative to the current root dir or absolute
|
|
8
|
-
export async function installLocalDep(pkg, pkgPath = '', { verbose, silent } = {}) {
|
|
8
|
+
export async function installLocalDep(pkg, pkgPath = '', { verbose, silent, ignoreTransitive } = {}) {
|
|
9
9
|
if (!silent) {
|
|
10
10
|
let logUpdate = createLogUpdate(process.stdout, { showCursor: true });
|
|
11
11
|
logUpdate(`Local dependency ${pkg} = "${pkgPath}"`);
|
|
@@ -17,7 +17,12 @@ export async function installLocalDep(pkg, pkgPath = '', { verbose, silent } = {
|
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
// install dependencies
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
if (!ignoreTransitive) {
|
|
21
|
+
let dir = path.resolve(getRootDir(), pkgPath);
|
|
22
|
+
let config = readConfig(path.join(dir, 'mops.toml'));
|
|
23
|
+
return installDeps(Object.values(config.dependencies || {}), { silent, verbose }, pkgPath);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
23
28
|
}
|
|
@@ -3,6 +3,7 @@ type InstallMopsDepOptions = {
|
|
|
3
3
|
silent?: boolean;
|
|
4
4
|
dep?: boolean;
|
|
5
5
|
threads?: number;
|
|
6
|
+
ignoreTransitive?: boolean;
|
|
6
7
|
};
|
|
7
|
-
export declare function installMopsDep(pkg: string, version?: string, { verbose, silent, dep, threads }?: InstallMopsDepOptions): Promise<boolean>;
|
|
8
|
+
export declare function installMopsDep(pkg: string, version?: string, { verbose, silent, dep, threads, ignoreTransitive }?: InstallMopsDepOptions): Promise<boolean>;
|
|
8
9
|
export {};
|
|
@@ -13,7 +13,7 @@ import { getDepCacheDir, getMopsDepCacheName, isDepCached } from '../../cache.js
|
|
|
13
13
|
import { downloadFile, getPackageFilesInfo } from '../../api/downloadPackageFiles.js';
|
|
14
14
|
import { installDeps } from './install-deps.js';
|
|
15
15
|
import { getDepName } from '../../helpers/get-dep-name.js';
|
|
16
|
-
export async function installMopsDep(pkg, version = '', { verbose, silent, dep, threads } = {}) {
|
|
16
|
+
export async function installMopsDep(pkg, version = '', { verbose, silent, dep, threads, ignoreTransitive } = {}) {
|
|
17
17
|
threads = threads || 12;
|
|
18
18
|
let depName = getDepName(pkg);
|
|
19
19
|
if (!checkConfigFile()) {
|
|
@@ -90,10 +90,12 @@ export async function installMopsDep(pkg, version = '', { verbose, silent, dep,
|
|
|
90
90
|
logUpdate.clear();
|
|
91
91
|
}
|
|
92
92
|
// install dependencies
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
93
|
+
if (!ignoreTransitive) {
|
|
94
|
+
let config = readConfig(path.join(cacheDir, 'mops.toml'));
|
|
95
|
+
let res = await installDeps(Object.values(config.dependencies || {}), { silent, verbose });
|
|
96
|
+
if (!res) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
97
99
|
}
|
|
98
100
|
return true;
|
|
99
101
|
}
|
package/dist/integrity.d.ts
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
|
+
type LockFileV1 = {
|
|
2
|
+
version: 1;
|
|
3
|
+
mopsTomlHash: string;
|
|
4
|
+
hashes: Record<string, Record<string, string>>;
|
|
5
|
+
};
|
|
6
|
+
type LockFileV2 = {
|
|
7
|
+
version: 2;
|
|
8
|
+
mopsTomlDepsHash: string;
|
|
9
|
+
hashes: Record<string, Record<string, string>>;
|
|
10
|
+
};
|
|
11
|
+
type LockFileV3 = {
|
|
12
|
+
version: 3;
|
|
13
|
+
mopsTomlDepsHash: string;
|
|
14
|
+
hashes: Record<string, Record<string, string>>;
|
|
15
|
+
deps: Record<string, string>;
|
|
16
|
+
};
|
|
17
|
+
type LockFile = LockFileV1 | LockFileV2 | LockFileV3;
|
|
1
18
|
export declare function checkIntegrity(lock?: 'check' | 'update' | 'ignore'): Promise<void>;
|
|
2
19
|
export declare function getLocalFileHash(fileId: string): string;
|
|
3
20
|
export declare function checkRemote(): Promise<void>;
|
|
21
|
+
export declare function readLockFile(): LockFile | null;
|
|
22
|
+
export declare function checkLockFileLight(): boolean;
|
|
4
23
|
export declare function updateLockFile(): Promise<void>;
|
|
5
24
|
export declare function checkLockFile(force?: boolean): Promise<void>;
|
|
25
|
+
export {};
|
package/dist/integrity.js
CHANGED
|
@@ -78,21 +78,36 @@ export async function checkRemote() {
|
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
|
-
export
|
|
81
|
+
export function readLockFile() {
|
|
82
82
|
let rootDir = getRootDir();
|
|
83
83
|
let lockFile = path.join(rootDir, 'mops.lock');
|
|
84
|
-
// if lock file exists and mops.toml hasn't changed, don't update it
|
|
85
84
|
if (fs.existsSync(lockFile)) {
|
|
86
|
-
|
|
85
|
+
return JSON.parse(fs.readFileSync(lockFile).toString());
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
// check if lock file exists and integrity of mopsTomlDepsHash
|
|
90
|
+
export function checkLockFileLight() {
|
|
91
|
+
let existingLockFileJson = readLockFile();
|
|
92
|
+
if (existingLockFileJson) {
|
|
87
93
|
let mopsTomlDepsHash = getMopsTomlDepsHash();
|
|
88
|
-
if (mopsTomlDepsHash ===
|
|
89
|
-
return;
|
|
94
|
+
if (existingLockFileJson.version === 3 && mopsTomlDepsHash === existingLockFileJson.mopsTomlDepsHash) {
|
|
95
|
+
return true;
|
|
90
96
|
}
|
|
91
97
|
}
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
export async function updateLockFile() {
|
|
101
|
+
// if lock file exists and mops.toml hasn't changed, don't update it
|
|
102
|
+
if (checkLockFileLight()) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
let resolvedDeps = await resolvePackages();
|
|
92
106
|
let fileHashes = await getFileHashesFromRegistry();
|
|
93
107
|
let lockFileJson = {
|
|
94
|
-
version:
|
|
108
|
+
version: 3,
|
|
95
109
|
mopsTomlDepsHash: getMopsTomlDepsHash(),
|
|
110
|
+
deps: resolvedDeps,
|
|
96
111
|
hashes: fileHashes.reduce((acc, [packageId, fileHashes]) => {
|
|
97
112
|
acc[packageId] = fileHashes.reduce((acc, [fileId, hash]) => {
|
|
98
113
|
acc[fileId] = bytesToHex(new Uint8Array(hash));
|
|
@@ -101,6 +116,8 @@ export async function updateLockFile() {
|
|
|
101
116
|
return acc;
|
|
102
117
|
}, {}),
|
|
103
118
|
};
|
|
119
|
+
let rootDir = getRootDir();
|
|
120
|
+
let lockFile = path.join(rootDir, 'mops.lock');
|
|
104
121
|
fs.writeFileSync(lockFile, JSON.stringify(lockFileJson, null, 2));
|
|
105
122
|
}
|
|
106
123
|
// compare hashes of local files with hashes from the lock file
|
|
@@ -118,9 +135,9 @@ export async function checkLockFile(force = false) {
|
|
|
118
135
|
let lockFileJsonGeneric = JSON.parse(fs.readFileSync(lockFile).toString());
|
|
119
136
|
let packageIds = await getResolvedMopsPackageIds();
|
|
120
137
|
// check lock file version
|
|
121
|
-
if (lockFileJsonGeneric.version !== 1 && lockFileJsonGeneric.version !== 2) {
|
|
138
|
+
if (lockFileJsonGeneric.version !== 1 && lockFileJsonGeneric.version !== 2 && lockFileJsonGeneric.version !== 3) {
|
|
122
139
|
console.error('Integrity check failed');
|
|
123
|
-
console.error(`Invalid lock file version: ${lockFileJsonGeneric.version}. Supported versions: 1`);
|
|
140
|
+
console.error(`Invalid lock file version: ${lockFileJsonGeneric.version}. Supported versions: 1, 2, 3`);
|
|
124
141
|
process.exit(1);
|
|
125
142
|
}
|
|
126
143
|
let lockFileJson = lockFileJsonGeneric;
|
|
@@ -134,8 +151,8 @@ export async function checkLockFile(force = false) {
|
|
|
134
151
|
process.exit(1);
|
|
135
152
|
}
|
|
136
153
|
}
|
|
137
|
-
// V2: check mops.toml deps hash
|
|
138
|
-
if (lockFileJson.version === 2) {
|
|
154
|
+
// V2, V3: check mops.toml deps hash
|
|
155
|
+
if (lockFileJson.version === 2 || lockFileJson.version === 3) {
|
|
139
156
|
if (lockFileJson.mopsTomlDepsHash !== getMopsTomlDepsHash()) {
|
|
140
157
|
console.error('Integrity check failed');
|
|
141
158
|
console.error('Mismatched mops.toml dependencies hash');
|
|
@@ -144,6 +161,20 @@ export async function checkLockFile(force = false) {
|
|
|
144
161
|
process.exit(1);
|
|
145
162
|
}
|
|
146
163
|
}
|
|
164
|
+
// V3: check locked deps (including GitHub and local packages)
|
|
165
|
+
if (lockFileJson.version === 3) {
|
|
166
|
+
let lockedDeps = { ...lockFileJson.deps };
|
|
167
|
+
let resolvedDeps = await resolvePackages();
|
|
168
|
+
for (let name of Object.keys(resolvedDeps)) {
|
|
169
|
+
if (lockedDeps[name] !== resolvedDeps[name]) {
|
|
170
|
+
console.error('Integrity check failed');
|
|
171
|
+
console.error(`Mismatched package ${name}`);
|
|
172
|
+
console.error(`Locked: ${lockedDeps[name]}`);
|
|
173
|
+
console.error(`Actual: ${resolvedDeps[name]}`);
|
|
174
|
+
process.exit(1);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
147
178
|
// check number of packages
|
|
148
179
|
if (Object.keys(lockFileJson.hashes).length !== packageIds.length) {
|
|
149
180
|
console.error('Integrity check failed');
|
package/dist/mops.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Identity } from '@dfinity/agent';
|
|
2
|
-
import { Config } from './types.js';
|
|
2
|
+
import { Config, Dependency } from './types.js';
|
|
3
3
|
import { mainActor, storageActor } from './api/actors.js';
|
|
4
4
|
import { getNetwork } from './api/network.js';
|
|
5
5
|
import { getHighestVersion } from './api/getHighestVersion.js';
|
|
@@ -21,6 +21,7 @@ export declare function parseGithubURL(href: string): {
|
|
|
21
21
|
};
|
|
22
22
|
export declare function getGithubCommit(repo: string, ref: string): Promise<any>;
|
|
23
23
|
export declare function getDependencyType(version: string): "local" | "mops" | "github";
|
|
24
|
+
export declare function parseDepValue(name: string, value: string): Dependency;
|
|
24
25
|
export declare function readConfig(configFile?: string): Config;
|
|
25
26
|
export declare function writeConfig(config: Config, configFile?: string): void;
|
|
26
27
|
export declare function formatDir(name: string, version: string): string;
|
package/dist/mops.js
CHANGED
|
@@ -135,6 +135,18 @@ export function getDependencyType(version) {
|
|
|
135
135
|
return 'mops';
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
|
+
export function parseDepValue(name, value) {
|
|
139
|
+
let depType = getDependencyType(value);
|
|
140
|
+
if (depType === 'github') {
|
|
141
|
+
return { name, repo: value, version: '' };
|
|
142
|
+
}
|
|
143
|
+
else if (depType === 'local') {
|
|
144
|
+
return { name, repo: '', path: value, version: '' };
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
return { name, repo: '', version: value };
|
|
148
|
+
}
|
|
149
|
+
}
|
|
138
150
|
export function readConfig(configFile = getClosestConfigFile()) {
|
|
139
151
|
let text = fs.readFileSync(configFile).toString();
|
|
140
152
|
let toml = TOML.parse(text);
|
|
@@ -143,16 +155,7 @@ export function readConfig(configFile = getClosestConfigFile()) {
|
|
|
143
155
|
if (!data || typeof data !== 'string') {
|
|
144
156
|
throw Error(`Invalid dependency value ${name} = "${data}"`);
|
|
145
157
|
}
|
|
146
|
-
|
|
147
|
-
if (depType === 'github') {
|
|
148
|
-
deps[name] = { name, repo: data, version: '' };
|
|
149
|
-
}
|
|
150
|
-
else if (depType === 'local') {
|
|
151
|
-
deps[name] = { name, repo: '', path: data, version: '' };
|
|
152
|
-
}
|
|
153
|
-
else {
|
|
154
|
-
deps[name] = { name, repo: '', version: data };
|
|
155
|
-
}
|
|
158
|
+
deps[name] = parseDepValue(name, data);
|
|
156
159
|
});
|
|
157
160
|
};
|
|
158
161
|
processDeps(toml.dependencies || {});
|
package/dist/package.json
CHANGED
package/dist/resolve-packages.js
CHANGED
|
@@ -5,10 +5,17 @@ import { checkConfigFile, getRootDir, parseGithubURL, readConfig } from './mops.
|
|
|
5
5
|
import { readVesselConfig } from './vessel.js';
|
|
6
6
|
import { getDepCacheDir, getDepCacheName } from './cache.js';
|
|
7
7
|
import { getPackageId } from './helpers/get-package-id.js';
|
|
8
|
+
import { checkLockFileLight, readLockFile } from './integrity.js';
|
|
8
9
|
export async function resolvePackages({ conflicts = 'ignore' } = {}) {
|
|
9
10
|
if (!checkConfigFile()) {
|
|
10
11
|
return {};
|
|
11
12
|
}
|
|
13
|
+
if (checkLockFileLight()) {
|
|
14
|
+
let lockFileJson = readLockFile();
|
|
15
|
+
if (lockFileJson && lockFileJson.version === 3) {
|
|
16
|
+
return lockFileJson.deps;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
12
19
|
let rootDir = getRootDir();
|
|
13
20
|
let packages = {};
|
|
14
21
|
let versions = {};
|
package/dist/vessel.d.ts
CHANGED
|
@@ -13,8 +13,9 @@ export declare const readVesselConfig: (dir: string, { cache, silent }?: {
|
|
|
13
13
|
silent?: boolean | undefined;
|
|
14
14
|
}) => Promise<VesselConfig | null>;
|
|
15
15
|
export declare const downloadFromGithub: (repo: string, dest: string, onProgress: any) => Promise<unknown>;
|
|
16
|
-
export declare const installFromGithub: (name: string, repo: string, { verbose, dep, silent }?: {
|
|
16
|
+
export declare const installFromGithub: (name: string, repo: string, { verbose, dep, silent, ignoreTransitive }?: {
|
|
17
17
|
verbose?: boolean | undefined;
|
|
18
18
|
dep?: boolean | undefined;
|
|
19
19
|
silent?: boolean | undefined;
|
|
20
|
+
ignoreTransitive?: boolean | undefined;
|
|
20
21
|
}) => Promise<void>;
|
package/dist/vessel.js
CHANGED
|
@@ -116,7 +116,7 @@ export const downloadFromGithub = async (repo, dest, onProgress) => {
|
|
|
116
116
|
});
|
|
117
117
|
return promise;
|
|
118
118
|
};
|
|
119
|
-
export const installFromGithub = async (name, repo, { verbose = false, dep = false, silent = false } = {}) => {
|
|
119
|
+
export const installFromGithub = async (name, repo, { verbose = false, dep = false, silent = false, ignoreTransitive = false } = {}) => {
|
|
120
120
|
let cacheName = getGithubDepCacheName(name, repo);
|
|
121
121
|
let cacheDir = getDepCacheDir(cacheName);
|
|
122
122
|
let logUpdate = createLogUpdate(process.stdout, { showCursor: true });
|
|
@@ -143,6 +143,9 @@ export const installFromGithub = async (name, repo, { verbose = false, dep = fal
|
|
|
143
143
|
else {
|
|
144
144
|
logUpdate.clear();
|
|
145
145
|
}
|
|
146
|
+
if (ignoreTransitive) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
146
149
|
const config = await readVesselConfig(cacheDir, { silent });
|
|
147
150
|
if (config) {
|
|
148
151
|
for (const { name, repo } of config.dependencies) {
|
package/integrity.ts
CHANGED
|
@@ -24,7 +24,14 @@ type LockFileV2 = {
|
|
|
24
24
|
hashes : Record<string, Record<string, string>>;
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
-
type
|
|
27
|
+
type LockFileV3 = {
|
|
28
|
+
version : 3;
|
|
29
|
+
mopsTomlDepsHash : string;
|
|
30
|
+
hashes : Record<string, Record<string, string>>;
|
|
31
|
+
deps : Record<string, string>;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
type LockFile = LockFileV1 | LockFileV2 | LockFileV3;
|
|
28
35
|
|
|
29
36
|
export async function checkIntegrity(lock ?: 'check' | 'update' | 'ignore') {
|
|
30
37
|
let force = !!lock;
|
|
@@ -109,24 +116,41 @@ export async function checkRemote() {
|
|
|
109
116
|
}
|
|
110
117
|
}
|
|
111
118
|
|
|
112
|
-
export
|
|
119
|
+
export function readLockFile() : LockFile | null {
|
|
113
120
|
let rootDir = getRootDir();
|
|
114
121
|
let lockFile = path.join(rootDir, 'mops.lock');
|
|
115
|
-
|
|
116
|
-
// if lock file exists and mops.toml hasn't changed, don't update it
|
|
117
122
|
if (fs.existsSync(lockFile)) {
|
|
118
|
-
|
|
123
|
+
return JSON.parse(fs.readFileSync(lockFile).toString()) as LockFile;
|
|
124
|
+
}
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// check if lock file exists and integrity of mopsTomlDepsHash
|
|
129
|
+
export function checkLockFileLight() : boolean {
|
|
130
|
+
let existingLockFileJson = readLockFile();
|
|
131
|
+
if (existingLockFileJson) {
|
|
119
132
|
let mopsTomlDepsHash = getMopsTomlDepsHash();
|
|
120
|
-
if (mopsTomlDepsHash ===
|
|
121
|
-
return;
|
|
133
|
+
if (existingLockFileJson.version === 3 && mopsTomlDepsHash === existingLockFileJson.mopsTomlDepsHash) {
|
|
134
|
+
return true;
|
|
122
135
|
}
|
|
123
136
|
}
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export async function updateLockFile() {
|
|
141
|
+
// if lock file exists and mops.toml hasn't changed, don't update it
|
|
142
|
+
if (checkLockFileLight()) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
let resolvedDeps = await resolvePackages();
|
|
124
147
|
|
|
125
148
|
let fileHashes = await getFileHashesFromRegistry();
|
|
126
149
|
|
|
127
|
-
let lockFileJson :
|
|
128
|
-
version:
|
|
150
|
+
let lockFileJson : LockFileV3 = {
|
|
151
|
+
version: 3,
|
|
129
152
|
mopsTomlDepsHash: getMopsTomlDepsHash(),
|
|
153
|
+
deps: resolvedDeps,
|
|
130
154
|
hashes: fileHashes.reduce((acc, [packageId, fileHashes]) => {
|
|
131
155
|
acc[packageId] = fileHashes.reduce((acc, [fileId, hash]) => {
|
|
132
156
|
acc[fileId] = bytesToHex(new Uint8Array(hash));
|
|
@@ -136,6 +160,8 @@ export async function updateLockFile() {
|
|
|
136
160
|
}, {} as Record<string, Record<string, string>>),
|
|
137
161
|
};
|
|
138
162
|
|
|
163
|
+
let rootDir = getRootDir();
|
|
164
|
+
let lockFile = path.join(rootDir, 'mops.lock');
|
|
139
165
|
fs.writeFileSync(lockFile, JSON.stringify(lockFileJson, null, 2));
|
|
140
166
|
}
|
|
141
167
|
|
|
@@ -157,9 +183,9 @@ export async function checkLockFile(force = false) {
|
|
|
157
183
|
let packageIds = await getResolvedMopsPackageIds();
|
|
158
184
|
|
|
159
185
|
// check lock file version
|
|
160
|
-
if (lockFileJsonGeneric.version !== 1 && lockFileJsonGeneric.version !== 2) {
|
|
186
|
+
if (lockFileJsonGeneric.version !== 1 && lockFileJsonGeneric.version !== 2 && lockFileJsonGeneric.version !== 3) {
|
|
161
187
|
console.error('Integrity check failed');
|
|
162
|
-
console.error(`Invalid lock file version: ${lockFileJsonGeneric.version}. Supported versions: 1`);
|
|
188
|
+
console.error(`Invalid lock file version: ${lockFileJsonGeneric.version}. Supported versions: 1, 2, 3`);
|
|
163
189
|
process.exit(1);
|
|
164
190
|
}
|
|
165
191
|
|
|
@@ -176,8 +202,8 @@ export async function checkLockFile(force = false) {
|
|
|
176
202
|
}
|
|
177
203
|
}
|
|
178
204
|
|
|
179
|
-
// V2: check mops.toml deps hash
|
|
180
|
-
if (lockFileJson.version === 2) {
|
|
205
|
+
// V2, V3: check mops.toml deps hash
|
|
206
|
+
if (lockFileJson.version === 2 || lockFileJson.version === 3) {
|
|
181
207
|
if (lockFileJson.mopsTomlDepsHash !== getMopsTomlDepsHash()) {
|
|
182
208
|
console.error('Integrity check failed');
|
|
183
209
|
console.error('Mismatched mops.toml dependencies hash');
|
|
@@ -187,6 +213,22 @@ export async function checkLockFile(force = false) {
|
|
|
187
213
|
}
|
|
188
214
|
}
|
|
189
215
|
|
|
216
|
+
// V3: check locked deps (including GitHub and local packages)
|
|
217
|
+
if (lockFileJson.version === 3) {
|
|
218
|
+
let lockedDeps = {...lockFileJson.deps};
|
|
219
|
+
let resolvedDeps = await resolvePackages();
|
|
220
|
+
|
|
221
|
+
for (let name of Object.keys(resolvedDeps)) {
|
|
222
|
+
if (lockedDeps[name] !== resolvedDeps[name]) {
|
|
223
|
+
console.error('Integrity check failed');
|
|
224
|
+
console.error(`Mismatched package ${name}`);
|
|
225
|
+
console.error(`Locked: ${lockedDeps[name]}`);
|
|
226
|
+
console.error(`Actual: ${resolvedDeps[name]}`);
|
|
227
|
+
process.exit(1);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
190
232
|
// check number of packages
|
|
191
233
|
if (Object.keys(lockFileJson.hashes).length !== packageIds.length) {
|
|
192
234
|
console.error('Integrity check failed');
|
package/mops.ts
CHANGED
|
@@ -8,7 +8,7 @@ import prompts from 'prompts';
|
|
|
8
8
|
import fetch from 'node-fetch';
|
|
9
9
|
|
|
10
10
|
import {decodeFile} from './pem.js';
|
|
11
|
-
import {Config} from './types.js';
|
|
11
|
+
import {Config, Dependency} from './types.js';
|
|
12
12
|
import {mainActor, storageActor} from './api/actors.js';
|
|
13
13
|
import {getNetwork} from './api/network.js';
|
|
14
14
|
import {getHighestVersion} from './api/getHighestVersion.js';
|
|
@@ -156,6 +156,19 @@ export function getDependencyType(version : string) {
|
|
|
156
156
|
}
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
+
export function parseDepValue(name : string, value : string) : Dependency {
|
|
160
|
+
let depType = getDependencyType(value);
|
|
161
|
+
if (depType === 'github') {
|
|
162
|
+
return {name, repo: value, version: ''};
|
|
163
|
+
}
|
|
164
|
+
else if (depType === 'local') {
|
|
165
|
+
return {name, repo: '', path: value, version: ''};
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
return {name, repo: '', version: value};
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
159
172
|
export function readConfig(configFile = getClosestConfigFile()) : Config {
|
|
160
173
|
let text = fs.readFileSync(configFile).toString();
|
|
161
174
|
let toml = TOML.parse(text);
|
|
@@ -165,16 +178,7 @@ export function readConfig(configFile = getClosestConfigFile()) : Config {
|
|
|
165
178
|
if (!data || typeof data !== 'string') {
|
|
166
179
|
throw Error(`Invalid dependency value ${name} = "${data}"`);
|
|
167
180
|
}
|
|
168
|
-
|
|
169
|
-
if (depType === 'github') {
|
|
170
|
-
deps[name] = {name, repo: data, version: ''};
|
|
171
|
-
}
|
|
172
|
-
else if (depType === 'local') {
|
|
173
|
-
deps[name] = {name, repo: '', path: data, version: ''};
|
|
174
|
-
}
|
|
175
|
-
else {
|
|
176
|
-
deps[name] = {name, repo: '', version: data};
|
|
177
|
-
}
|
|
181
|
+
deps[name] = parseDepValue(name, data);
|
|
178
182
|
});
|
|
179
183
|
};
|
|
180
184
|
|
package/package.json
CHANGED
package/resolve-packages.ts
CHANGED
|
@@ -6,12 +6,21 @@ import {VesselConfig, readVesselConfig} from './vessel.js';
|
|
|
6
6
|
import {Config, Dependency} from './types.js';
|
|
7
7
|
import {getDepCacheDir, getDepCacheName} from './cache.js';
|
|
8
8
|
import {getPackageId} from './helpers/get-package-id.js';
|
|
9
|
+
import {checkLockFileLight, readLockFile} from './integrity.js';
|
|
9
10
|
|
|
10
11
|
export async function resolvePackages({conflicts = 'ignore' as 'warning' | 'error' | 'ignore'} = {}) : Promise<Record<string, string>> {
|
|
11
12
|
if (!checkConfigFile()) {
|
|
12
13
|
return {};
|
|
13
14
|
}
|
|
14
15
|
|
|
16
|
+
if (checkLockFileLight()) {
|
|
17
|
+
let lockFileJson = readLockFile();
|
|
18
|
+
|
|
19
|
+
if (lockFileJson && lockFileJson.version === 3) {
|
|
20
|
+
return lockFileJson.deps;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
15
24
|
let rootDir = getRootDir();
|
|
16
25
|
let packages : Record<string, Dependency & {isRoot : boolean;}> = {};
|
|
17
26
|
let versions : Record<string, Array<{
|
package/test
ADDED
package/vessel.ts
CHANGED
|
@@ -149,7 +149,7 @@ export const downloadFromGithub = async (repo : string, dest : string, onProgres
|
|
|
149
149
|
return promise;
|
|
150
150
|
};
|
|
151
151
|
|
|
152
|
-
export const installFromGithub = async (name : string, repo : string, {verbose = false, dep = false, silent = false} = {}) => {
|
|
152
|
+
export const installFromGithub = async (name : string, repo : string, {verbose = false, dep = false, silent = false, ignoreTransitive = false} = {}) => {
|
|
153
153
|
let cacheName = getGithubDepCacheName(name, repo);
|
|
154
154
|
let cacheDir = getDepCacheDir(cacheName);
|
|
155
155
|
|
|
@@ -183,6 +183,10 @@ export const installFromGithub = async (name : string, repo : string, {verbose =
|
|
|
183
183
|
logUpdate.clear();
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
+
if (ignoreTransitive) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
|
|
186
190
|
const config = await readVesselConfig(cacheDir, {silent});
|
|
187
191
|
|
|
188
192
|
if (config) {
|