@dxos/cli 2.4.15-alpha.0 → 2.5.1-alpha.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/README.md +60 -69
- package/bin/dx.js +1 -1
- package/dist/known-extensions.yml +129 -0
- package/dist/src/extensions.d.ts +6 -0
- package/dist/src/extensions.d.ts.map +1 -0
- package/dist/src/extensions.js +45 -0
- package/dist/src/extensions.js.map +1 -0
- package/dist/src/main.d.ts +2 -0
- package/dist/src/main.d.ts.map +1 -0
- package/dist/src/main.js +78 -0
- package/dist/src/main.js.map +1 -0
- package/dist/src/modules/cert.d.ts +4 -0
- package/dist/src/modules/cert.d.ts.map +1 -0
- package/dist/src/modules/cert.js +33 -0
- package/dist/src/modules/cert.js.map +1 -0
- package/dist/src/modules/extension.d.ts +4 -0
- package/dist/src/modules/extension.d.ts.map +1 -0
- package/dist/src/modules/extension.js +145 -0
- package/dist/src/modules/extension.js.map +1 -0
- package/dist/src/modules/installation.d.ts +5 -0
- package/dist/src/modules/installation.d.ts.map +1 -0
- package/dist/src/modules/installation.js +91 -0
- package/dist/src/modules/installation.js.map +1 -0
- package/dist/src/modules/pluggable.d.ts +14 -0
- package/dist/src/modules/pluggable.d.ts.map +1 -0
- package/dist/src/modules/pluggable.js +48 -0
- package/dist/src/modules/pluggable.js.map +1 -0
- package/dist/src/modules/profile.d.ts +2 -0
- package/dist/src/modules/profile.d.ts.map +1 -0
- package/dist/src/modules/profile.js +75 -0
- package/dist/src/modules/profile.js.map +1 -0
- package/dist/src/modules/services.d.ts +5 -0
- package/dist/src/modules/services.d.ts.map +1 -0
- package/dist/src/modules/services.js +260 -0
- package/dist/src/modules/services.js.map +1 -0
- package/dist/src/pluggable.d.ts +65 -0
- package/dist/src/pluggable.d.ts.map +1 -0
- package/dist/src/pluggable.js +226 -0
- package/dist/src/pluggable.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +22 -38
- package/dist/es/extensions.js +0 -100
- package/dist/es/main.js +0 -98
- package/dist/es/modules/cert.js +0 -43
- package/dist/es/modules/extension.js +0 -191
- package/dist/es/modules/installation.js +0 -144
- package/dist/es/modules/pluggable.js +0 -68
- package/dist/es/modules/profile.js +0 -100
- package/dist/es/modules/services.js +0 -408
- package/dist/es/pluggable.js +0 -312
|
@@ -1,408 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
-
|
|
5
|
-
Object.defineProperty(exports, "__esModule", {
|
|
6
|
-
value: true
|
|
7
|
-
});
|
|
8
|
-
exports.ServicesModule = void 0;
|
|
9
|
-
|
|
10
|
-
var _assert = _interopRequireDefault(require("assert"));
|
|
11
|
-
|
|
12
|
-
var _path = _interopRequireDefault(require("path"));
|
|
13
|
-
|
|
14
|
-
var _os = _interopRequireDefault(require("os"));
|
|
15
|
-
|
|
16
|
-
var _cliCore = require("@dxos/cli-core");
|
|
17
|
-
|
|
18
|
-
var _pluggable = require("../pluggable");
|
|
19
|
-
|
|
20
|
-
//
|
|
21
|
-
// Copyright 2020 DXOS.org
|
|
22
|
-
//
|
|
23
|
-
const DEFAULT_LOG_LINES = 100;
|
|
24
|
-
const DEFAULT_CONFIG_PATH = '/root/.wire/profile/local.yml';
|
|
25
|
-
|
|
26
|
-
const DEFAULT_STORAGE_PATH = _path.default.join('/root', _cliCore.STORAGE_ROOT);
|
|
27
|
-
|
|
28
|
-
const SERVICE_DAEMON = 'daemon';
|
|
29
|
-
const SERVICE_CONTAINER = 'container';
|
|
30
|
-
|
|
31
|
-
const getServiceInfo = (moduleName, serviceName) => {
|
|
32
|
-
(0, _assert.default)(moduleName, 'Invalid extension.');
|
|
33
|
-
const pluggable = new _pluggable.Pluggable({
|
|
34
|
-
moduleName
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
if (!pluggable.installed) {
|
|
38
|
-
throw new Error(`Extension '${moduleName}' is not installed.`);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const compose = pluggable.getDockerCompose();
|
|
42
|
-
(0, _assert.default)(compose, `Extension '${moduleName}' does not provide containers.`); // TODO(egorgripasov): Docker compose?
|
|
43
|
-
|
|
44
|
-
const service = compose.services[serviceName];
|
|
45
|
-
(0, _assert.default)(service, `Service ${serviceName} not found in compose file.`);
|
|
46
|
-
return service;
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
const getAuth = (config, imageInfo) => ({
|
|
50
|
-
username: config.get('services.machine.githubUsername'),
|
|
51
|
-
password: config.get('services.machine.githubAccessToken'),
|
|
52
|
-
serveraddress: `https://${imageInfo.image.split('/')[0]}`
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
const getServiceType = async serviceName => {
|
|
56
|
-
const {
|
|
57
|
-
services = []
|
|
58
|
-
} = await (0, _cliCore.listServices)();
|
|
59
|
-
return services.map(({
|
|
60
|
-
name
|
|
61
|
-
}) => name).includes(serviceName) ? SERVICE_DAEMON : SERVICE_CONTAINER;
|
|
62
|
-
};
|
|
63
|
-
/**
|
|
64
|
-
* Services CLI module.
|
|
65
|
-
* @returns {object}
|
|
66
|
-
*/
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const ServicesModule = ({
|
|
70
|
-
config,
|
|
71
|
-
profilePath
|
|
72
|
-
}) => ({
|
|
73
|
-
command: ['service'],
|
|
74
|
-
describe: 'DXOS service management.',
|
|
75
|
-
handler: (0, _cliCore.asyncHandler)(async argv => {
|
|
76
|
-
const {
|
|
77
|
-
json
|
|
78
|
-
} = argv;
|
|
79
|
-
const {
|
|
80
|
-
services
|
|
81
|
-
} = await (0, _cliCore.listServices)();
|
|
82
|
-
const containers = await _cliCore.DockerContainer.list();
|
|
83
|
-
const containerService = await Promise.all(containers.map(async container => ({
|
|
84
|
-
name: container.name,
|
|
85
|
-
exec: container.image,
|
|
86
|
-
status: container.state === _cliCore.RUNNING_STATE ? 'online' : container.state,
|
|
87
|
-
ports: container.ports.filter(port => port.PublicPort).map(port => port.PublicPort).filter((value, index, arr) => arr.indexOf(value) === index).join(','),
|
|
88
|
-
...(await container.stats()),
|
|
89
|
-
type: SERVICE_CONTAINER
|
|
90
|
-
})));
|
|
91
|
-
const result = services.map(service => ({ ...service,
|
|
92
|
-
type: SERVICE_DAEMON
|
|
93
|
-
})).concat(containerService).sort((a, b) => {
|
|
94
|
-
return a.name.localeCompare(b.name);
|
|
95
|
-
});
|
|
96
|
-
(0, _cliCore.print)(result, {
|
|
97
|
-
json
|
|
98
|
-
});
|
|
99
|
-
}),
|
|
100
|
-
builder: yargs => yargs.command({
|
|
101
|
-
command: ['install'],
|
|
102
|
-
describe: 'Install service from container.',
|
|
103
|
-
builder: yargs => yargs.option('from', {
|
|
104
|
-
describe: 'Extension name',
|
|
105
|
-
required: true
|
|
106
|
-
}).option('service', {
|
|
107
|
-
describe: 'Service to install',
|
|
108
|
-
required: true
|
|
109
|
-
}).option('force', {
|
|
110
|
-
type: 'boolean',
|
|
111
|
-
default: false,
|
|
112
|
-
description: 'Force install'
|
|
113
|
-
}).option('auth', {
|
|
114
|
-
type: 'boolean',
|
|
115
|
-
default: false,
|
|
116
|
-
description: 'Authentication required'
|
|
117
|
-
}).option('dev', {
|
|
118
|
-
type: 'boolean',
|
|
119
|
-
default: false,
|
|
120
|
-
description: 'Dev build'
|
|
121
|
-
}),
|
|
122
|
-
handler: (0, _cliCore.asyncHandler)(async argv => {
|
|
123
|
-
const {
|
|
124
|
-
from: moduleName,
|
|
125
|
-
service: serviceName,
|
|
126
|
-
auth: authRequired,
|
|
127
|
-
force,
|
|
128
|
-
dev
|
|
129
|
-
} = argv;
|
|
130
|
-
const service = getServiceInfo(moduleName, serviceName);
|
|
131
|
-
const auth = authRequired ? getAuth(config, service) : undefined;
|
|
132
|
-
const dockerImage = new _cliCore.DockerImage({
|
|
133
|
-
service,
|
|
134
|
-
auth,
|
|
135
|
-
dev
|
|
136
|
-
});
|
|
137
|
-
await dockerImage.pull(force);
|
|
138
|
-
})
|
|
139
|
-
}).command({
|
|
140
|
-
command: ['upgrade'],
|
|
141
|
-
describe: 'Upgrade service container.',
|
|
142
|
-
builder: yargs => yargs.option('from', {
|
|
143
|
-
describe: 'Extension name',
|
|
144
|
-
required: true
|
|
145
|
-
}).option('service', {
|
|
146
|
-
describe: 'Service to upgrade',
|
|
147
|
-
required: true
|
|
148
|
-
}).option('auth', {
|
|
149
|
-
type: 'boolean',
|
|
150
|
-
default: false,
|
|
151
|
-
description: 'Authentication required'
|
|
152
|
-
}).option('dev', {
|
|
153
|
-
type: 'boolean',
|
|
154
|
-
default: false,
|
|
155
|
-
description: 'Dev build'
|
|
156
|
-
}),
|
|
157
|
-
handler: (0, _cliCore.asyncHandler)(async argv => {
|
|
158
|
-
const {
|
|
159
|
-
from: moduleName,
|
|
160
|
-
service: serviceName,
|
|
161
|
-
auth: authRequired,
|
|
162
|
-
dev
|
|
163
|
-
} = argv;
|
|
164
|
-
const service = getServiceInfo(moduleName, serviceName);
|
|
165
|
-
const auth = authRequired ? getAuth(config, service) : undefined;
|
|
166
|
-
const {
|
|
167
|
-
image: imageName
|
|
168
|
-
} = service;
|
|
169
|
-
const container = await _cliCore.DockerContainer.find({
|
|
170
|
-
imageName
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
if (container && container.started) {
|
|
174
|
-
throw new Error(`Unable to upgrade '${service.container_name}' while it's running.`);
|
|
175
|
-
} // TODO(egorgripasov): Already up-to-date message.
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
const dockerImage = new _cliCore.DockerImage({
|
|
179
|
-
service,
|
|
180
|
-
auth,
|
|
181
|
-
dev
|
|
182
|
-
});
|
|
183
|
-
await dockerImage.pull(true);
|
|
184
|
-
await _cliCore.DockerImage.cleanNotLatest(imageName);
|
|
185
|
-
})
|
|
186
|
-
}).command({
|
|
187
|
-
command: ['start'],
|
|
188
|
-
describe: 'Start service container.',
|
|
189
|
-
builder: yargs => yargs.option('from', {
|
|
190
|
-
describe: 'Extension name',
|
|
191
|
-
required: true
|
|
192
|
-
}).option('service', {
|
|
193
|
-
describe: 'Service to install',
|
|
194
|
-
required: true
|
|
195
|
-
}).option('name', {
|
|
196
|
-
type: 'string',
|
|
197
|
-
description: 'Container name'
|
|
198
|
-
}).option('profile-path', {
|
|
199
|
-
type: 'string',
|
|
200
|
-
description: 'Profile to pass to container.',
|
|
201
|
-
default: profilePath
|
|
202
|
-
}).option('forward-env', {
|
|
203
|
-
type: 'string',
|
|
204
|
-
description: 'ENV to forward. Could be "full", "system", "config"'
|
|
205
|
-
}).option('host-net', {
|
|
206
|
-
type: 'boolean',
|
|
207
|
-
description: 'Use host network',
|
|
208
|
-
default: false
|
|
209
|
-
}).option('storage-path', {
|
|
210
|
-
type: 'string',
|
|
211
|
-
description: 'Path to ECHO and HALO storage.',
|
|
212
|
-
default: _path.default.join(_os.default.homedir(), _cliCore.STORAGE_ROOT)
|
|
213
|
-
}).option('binds', {
|
|
214
|
-
type: 'array',
|
|
215
|
-
description: 'Additional volume binds.'
|
|
216
|
-
}).option('dev', {
|
|
217
|
-
type: 'boolean',
|
|
218
|
-
default: false,
|
|
219
|
-
description: 'Dev build'
|
|
220
|
-
}).option('replace-args', {
|
|
221
|
-
type: 'boolean',
|
|
222
|
-
description: 'Replace default arguments with provided.',
|
|
223
|
-
default: false
|
|
224
|
-
}),
|
|
225
|
-
handler: (0, _cliCore.asyncHandler)(async argv => {
|
|
226
|
-
const {
|
|
227
|
-
from: moduleName,
|
|
228
|
-
service: serviceName,
|
|
229
|
-
forward,
|
|
230
|
-
forwardEnv,
|
|
231
|
-
hostNet,
|
|
232
|
-
profilePath: profile,
|
|
233
|
-
storagePath,
|
|
234
|
-
binds: additionalBinds = [],
|
|
235
|
-
dev,
|
|
236
|
-
replaceArgs
|
|
237
|
-
} = argv;
|
|
238
|
-
const service = getServiceInfo(moduleName, serviceName);
|
|
239
|
-
const dockerImage = new _cliCore.DockerImage({
|
|
240
|
-
service,
|
|
241
|
-
dev
|
|
242
|
-
});
|
|
243
|
-
const forwardArgs = forward ? JSON.parse(forward).args : [];
|
|
244
|
-
const command = replaceArgs ? forwardArgs : service.command.split(' ').concat(forwardArgs);
|
|
245
|
-
const {
|
|
246
|
-
name = service.container_name
|
|
247
|
-
} = argv;
|
|
248
|
-
(0, _assert.default)(name, 'Service name is required.'); // TODO(egorgripasov): Share volumes between services.
|
|
249
|
-
|
|
250
|
-
const volumes = (service.volumes || []).map(volume => volume.split(':')).filter(vol => vol.length === 2);
|
|
251
|
-
let env;
|
|
252
|
-
|
|
253
|
-
switch (forwardEnv) {
|
|
254
|
-
case 'full':
|
|
255
|
-
env = Object.entries(process.env).map(([key, value]) => `${key}=${value}`);
|
|
256
|
-
break;
|
|
257
|
-
|
|
258
|
-
case 'system':
|
|
259
|
-
env = Object.entries(process.env).filter(([key]) => _cliCore.ENVS.includes(key)).map(([key, value]) => `${key}=${value}`);
|
|
260
|
-
break;
|
|
261
|
-
|
|
262
|
-
case 'config':
|
|
263
|
-
env = Object.entries((0, _cliCore.mapConfigToEnv)(config)).map(([key, value]) => `${key}=${value}`);
|
|
264
|
-
break;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
const binds = [`${profile}:${DEFAULT_CONFIG_PATH}`, `${storagePath}:${DEFAULT_STORAGE_PATH}:rw`, ...additionalBinds];
|
|
268
|
-
const container = await dockerImage.getOrCreateContainer(name, command, env, binds, hostNet, volumes);
|
|
269
|
-
await container.start();
|
|
270
|
-
})
|
|
271
|
-
}) // Get logs.
|
|
272
|
-
.command({
|
|
273
|
-
command: ['logs [name]'],
|
|
274
|
-
describe: 'Fetch logs.',
|
|
275
|
-
builder: yargs => yargs.option('name').option('lines', {
|
|
276
|
-
type: 'number',
|
|
277
|
-
default: DEFAULT_LOG_LINES
|
|
278
|
-
}).option('follow', {
|
|
279
|
-
alias: 'f',
|
|
280
|
-
type: 'boolean'
|
|
281
|
-
}).option('log-file').option('running-only', {
|
|
282
|
-
default: false
|
|
283
|
-
}),
|
|
284
|
-
handler: (0, _cliCore.asyncHandler)(async argv => {
|
|
285
|
-
const {
|
|
286
|
-
name,
|
|
287
|
-
lines,
|
|
288
|
-
runningOnly,
|
|
289
|
-
logFile,
|
|
290
|
-
follow
|
|
291
|
-
} = argv;
|
|
292
|
-
(0, _assert.default)(name, 'Invalid Service Name.');
|
|
293
|
-
const serviceType = await getServiceType(name);
|
|
294
|
-
|
|
295
|
-
if (serviceType === SERVICE_DAEMON) {
|
|
296
|
-
await (0, _cliCore.getLogs)(name, {
|
|
297
|
-
lines,
|
|
298
|
-
runningOnly,
|
|
299
|
-
logFile,
|
|
300
|
-
follow
|
|
301
|
-
});
|
|
302
|
-
} else {
|
|
303
|
-
const container = await _cliCore.DockerContainer.find({
|
|
304
|
-
name
|
|
305
|
-
});
|
|
306
|
-
|
|
307
|
-
if (!container) {
|
|
308
|
-
throw new Error(`Unable to find "${name}" service.`);
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
await container.logs(lines, follow);
|
|
312
|
-
}
|
|
313
|
-
})
|
|
314
|
-
}) // Restart.
|
|
315
|
-
.command({
|
|
316
|
-
command: ['restart [name]'],
|
|
317
|
-
describe: 'Restart serice.',
|
|
318
|
-
builder: yargs => yargs.option('name'),
|
|
319
|
-
handler: (0, _cliCore.asyncHandler)(async argv => {
|
|
320
|
-
const {
|
|
321
|
-
name
|
|
322
|
-
} = argv;
|
|
323
|
-
(0, _assert.default)(name, 'Invalid Service Name.');
|
|
324
|
-
const serviceType = await getServiceType(name);
|
|
325
|
-
|
|
326
|
-
if (serviceType === SERVICE_DAEMON) {
|
|
327
|
-
await (0, _cliCore.restartService)(name);
|
|
328
|
-
} else {
|
|
329
|
-
const container = await _cliCore.DockerContainer.find({
|
|
330
|
-
name
|
|
331
|
-
});
|
|
332
|
-
|
|
333
|
-
if (!container) {
|
|
334
|
-
throw new Error(`Unable to find "${name}" service.`);
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
await container.restart();
|
|
338
|
-
}
|
|
339
|
-
})
|
|
340
|
-
}) // Stop.
|
|
341
|
-
.command({
|
|
342
|
-
command: ['stop [name]'],
|
|
343
|
-
describe: 'Stop service.',
|
|
344
|
-
builder: yargs => yargs.option('name'),
|
|
345
|
-
handler: (0, _cliCore.asyncHandler)(async argv => {
|
|
346
|
-
const {
|
|
347
|
-
name
|
|
348
|
-
} = argv;
|
|
349
|
-
(0, _assert.default)(name, 'Invalid Service Name.');
|
|
350
|
-
const serviceType = await getServiceType(name);
|
|
351
|
-
|
|
352
|
-
if (serviceType === SERVICE_DAEMON) {
|
|
353
|
-
await (0, _cliCore.stopService)(name);
|
|
354
|
-
} else {
|
|
355
|
-
const container = await _cliCore.DockerContainer.find({
|
|
356
|
-
name
|
|
357
|
-
});
|
|
358
|
-
|
|
359
|
-
if (!container) {
|
|
360
|
-
throw new Error(`Unable to find "${name}" service.`);
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
await container.stop();
|
|
364
|
-
}
|
|
365
|
-
})
|
|
366
|
-
}).command({
|
|
367
|
-
command: ['reset'],
|
|
368
|
-
describe: 'Reset storage for specific service.',
|
|
369
|
-
builder: yargs => yargs.option('name', {
|
|
370
|
-
describe: 'Service name'
|
|
371
|
-
}).option('volume', {
|
|
372
|
-
describe: 'Volume name'
|
|
373
|
-
}),
|
|
374
|
-
handler: (0, _cliCore.asyncHandler)(async argv => {
|
|
375
|
-
const {
|
|
376
|
-
name,
|
|
377
|
-
volume,
|
|
378
|
-
json
|
|
379
|
-
} = argv;
|
|
380
|
-
const container = await _cliCore.DockerContainer.find({
|
|
381
|
-
name
|
|
382
|
-
});
|
|
383
|
-
|
|
384
|
-
if (!container) {
|
|
385
|
-
throw new Error(`Unable to find "${name}" service.`);
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
let volumesToDelete = await Promise.all(Object.keys(container.volumes).filter(vol => !volume || vol === volume).map(async vol => _cliCore.DockerVolume.get(vol, name))); // Kill service container before removing volume.
|
|
389
|
-
|
|
390
|
-
volumesToDelete = volumesToDelete.filter(volume => !!volume);
|
|
391
|
-
|
|
392
|
-
if (volumesToDelete.length) {
|
|
393
|
-
await container.destroy();
|
|
394
|
-
await Promise.all(volumesToDelete.map(async volume => {
|
|
395
|
-
if (volume) {
|
|
396
|
-
await volume.remove();
|
|
397
|
-
}
|
|
398
|
-
}));
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
(0, _cliCore.print)(volumesToDelete.map(vol => vol.name), {
|
|
402
|
-
json
|
|
403
|
-
});
|
|
404
|
-
})
|
|
405
|
-
})
|
|
406
|
-
});
|
|
407
|
-
|
|
408
|
-
exports.ServicesModule = ServicesModule;
|
package/dist/es/pluggable.js
DELETED
|
@@ -1,312 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
-
|
|
5
|
-
Object.defineProperty(exports, "__esModule", {
|
|
6
|
-
value: true
|
|
7
|
-
});
|
|
8
|
-
exports.Pluggable = void 0;
|
|
9
|
-
|
|
10
|
-
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
11
|
-
|
|
12
|
-
var _child_process = require("child_process");
|
|
13
|
-
|
|
14
|
-
var _findRoot = _interopRequireDefault(require("find-root"));
|
|
15
|
-
|
|
16
|
-
var _fs = _interopRequireDefault(require("fs"));
|
|
17
|
-
|
|
18
|
-
var _lodash = _interopRequireDefault(require("lodash.isarray"));
|
|
19
|
-
|
|
20
|
-
var _ora = _interopRequireDefault(require("ora"));
|
|
21
|
-
|
|
22
|
-
var _path = _interopRequireDefault(require("path"));
|
|
23
|
-
|
|
24
|
-
var _readPkgUp = _interopRequireDefault(require("read-pkg-up"));
|
|
25
|
-
|
|
26
|
-
var _cliCore = require("@dxos/cli-core");
|
|
27
|
-
|
|
28
|
-
var _extensions = require("./extensions");
|
|
29
|
-
|
|
30
|
-
//
|
|
31
|
-
// Copyright 2020 DXOS.org
|
|
32
|
-
//
|
|
33
|
-
|
|
34
|
-
/* eslint import/no-dynamic-require: 0 */
|
|
35
|
-
|
|
36
|
-
/* eslint global-require: 0 */
|
|
37
|
-
const pkg = _readPkgUp.default.sync({
|
|
38
|
-
cwd: _path.default.join(__dirname, '../')
|
|
39
|
-
});
|
|
40
|
-
/**
|
|
41
|
-
* @param {String} command
|
|
42
|
-
* @param {Array} args
|
|
43
|
-
* @param {Object} options
|
|
44
|
-
*/
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const runCommand = async (command, args, options) => {
|
|
48
|
-
return new Promise((resolve, reject) => {
|
|
49
|
-
const {
|
|
50
|
-
spinner: spinnerText
|
|
51
|
-
} = options;
|
|
52
|
-
const spinner = (0, _ora.default)(spinnerText);
|
|
53
|
-
spinner.start();
|
|
54
|
-
(0, _child_process.exec)(`${(0, _cliCore.prepareExec)(command)} ${args.join(' ')}`, err => {
|
|
55
|
-
if (err) {
|
|
56
|
-
spinner.fail();
|
|
57
|
-
reject(err);
|
|
58
|
-
} else {
|
|
59
|
-
spinner.succeed();
|
|
60
|
-
spinner.clear();
|
|
61
|
-
resolve();
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
};
|
|
66
|
-
/**
|
|
67
|
-
* Finds root dir of a workspace.
|
|
68
|
-
* @param {String} from
|
|
69
|
-
*/
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const getWorkspaceRoot = from => {
|
|
73
|
-
try {
|
|
74
|
-
return (0, _findRoot.default)(from, dir => {
|
|
75
|
-
const pkgPath = _path.default.join(dir, 'package.json');
|
|
76
|
-
|
|
77
|
-
if (_fs.default.existsSync(pkgPath)) {
|
|
78
|
-
const {
|
|
79
|
-
workspaces
|
|
80
|
-
} = require(pkgPath);
|
|
81
|
-
|
|
82
|
-
return workspaces && ((0, _lodash.default)(workspaces) || workspaces.packages);
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
|
-
} catch (err) {
|
|
86
|
-
return '';
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
/**
|
|
90
|
-
* Pluggable CLI module.
|
|
91
|
-
*/
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
class Pluggable {
|
|
95
|
-
/**
|
|
96
|
-
* Pluggable factory.
|
|
97
|
-
* @param {Object} options
|
|
98
|
-
*/
|
|
99
|
-
static create(options) {
|
|
100
|
-
return new Pluggable(options);
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* @constructor
|
|
104
|
-
* @param {String} moduleName
|
|
105
|
-
* @param {String} version
|
|
106
|
-
*/
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
constructor({
|
|
110
|
-
moduleName,
|
|
111
|
-
version
|
|
112
|
-
}) {
|
|
113
|
-
(0, _defineProperty2.default)(this, "_modulePath", void 0);
|
|
114
|
-
this._moduleName = moduleName;
|
|
115
|
-
this._version = version;
|
|
116
|
-
this._workspaceRoot = getWorkspaceRoot(__dirname);
|
|
117
|
-
this._isInWorkspace = this._workspaceRoot && _fs.default.existsSync(_path.default.resolve(this._workspaceRoot, 'node_modules', this._moduleName));
|
|
118
|
-
this._installed = this.isInstalled();
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
get moduleName() {
|
|
122
|
-
return this._moduleName;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
get version() {
|
|
126
|
-
return this._version;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
get workspaceRoot() {
|
|
130
|
-
return this._workspaceRoot;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
get installed() {
|
|
134
|
-
return this._installed;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
get isInWorkspace() {
|
|
138
|
-
return this._isInWorkspace;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
get modulePath() {
|
|
142
|
-
if (!this._modulePath) {
|
|
143
|
-
const {
|
|
144
|
-
moduleName
|
|
145
|
-
} = this;
|
|
146
|
-
|
|
147
|
-
const pkgPath = require.resolve(`${moduleName}/package.json`);
|
|
148
|
-
|
|
149
|
-
const pkg = require(pkgPath);
|
|
150
|
-
|
|
151
|
-
this._modulePath = _path.default.resolve(_path.default.dirname(pkgPath), pkg.main);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
return this._modulePath;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
get module() {
|
|
158
|
-
var _module$default;
|
|
159
|
-
|
|
160
|
-
const module = require(this.modulePath);
|
|
161
|
-
|
|
162
|
-
const moduleCli = (_module$default = module.default) !== null && _module$default !== void 0 ? _module$default : module; // Difference between `module.exports` and `export default`.
|
|
163
|
-
|
|
164
|
-
return moduleCli;
|
|
165
|
-
}
|
|
166
|
-
/**
|
|
167
|
-
* Checks if workspace is defined.
|
|
168
|
-
*/
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
isWorkspace() {
|
|
172
|
-
return !!this.workspaceRoot;
|
|
173
|
-
}
|
|
174
|
-
/**
|
|
175
|
-
* Checks if extension is installed.
|
|
176
|
-
*/
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
isInstalled() {
|
|
180
|
-
const {
|
|
181
|
-
moduleName
|
|
182
|
-
} = this;
|
|
183
|
-
if (this._isInWorkspace) return true;
|
|
184
|
-
|
|
185
|
-
try {
|
|
186
|
-
const pkgPath = require.resolve(`${moduleName}/package.json`);
|
|
187
|
-
|
|
188
|
-
const pkg = require(pkgPath); // Check if module is installed and version matches cli version.
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
return !!pkg; // TODO(egorgripasov): Extension compatibility. Semver?
|
|
192
|
-
// && pkg.version === this.version;
|
|
193
|
-
} catch (err) {
|
|
194
|
-
return false;
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
/**
|
|
198
|
-
* Install CLI extension.
|
|
199
|
-
*/
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
async installModule(npmClient, options = {}) {
|
|
203
|
-
const moduleName = this._moduleName;
|
|
204
|
-
const version = this._version;
|
|
205
|
-
|
|
206
|
-
if (this.isWorkspace()) {
|
|
207
|
-
console.error(`The module ${moduleName}@${version} has to be added to devDependencies.`);
|
|
208
|
-
return;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
const isYarn = npmClient ? npmClient === 'yarn' : await (0, _cliCore.isGlobalYarn)(pkg.package.name);
|
|
212
|
-
const command = isYarn ? 'yarn' : 'npm';
|
|
213
|
-
const args = isYarn ? ['global', 'add'] : ['install', '-g'];
|
|
214
|
-
args.push(`${moduleName}${version ? `@${version}` : ''}`);
|
|
215
|
-
return runCommand(command, args, options);
|
|
216
|
-
}
|
|
217
|
-
/**
|
|
218
|
-
* Uninstall CLI extension.
|
|
219
|
-
*/
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
async uninstallModule(npmClient, options = {}) {
|
|
223
|
-
const moduleName = this._moduleName;
|
|
224
|
-
|
|
225
|
-
if (this.isWorkspace()) {
|
|
226
|
-
console.error(`The module ${moduleName} has to be removed from devDependencies.`);
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
const isYarn = npmClient ? npmClient === 'yarn' : await (0, _cliCore.isGlobalYarn)(pkg.package.name);
|
|
231
|
-
const command = isYarn ? 'yarn' : 'npm';
|
|
232
|
-
const args = isYarn ? ['global', 'remove'] : ['uninstall', '-g'];
|
|
233
|
-
args.push(`${moduleName}`);
|
|
234
|
-
return runCommand(command, args, options);
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* Init extension in a scope of main CLI.
|
|
238
|
-
* @param {Object} state
|
|
239
|
-
*/
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
async init(state) {
|
|
243
|
-
return this.module.init(state);
|
|
244
|
-
}
|
|
245
|
-
/**
|
|
246
|
-
* Destroy extension in a scope of main CLI.
|
|
247
|
-
* @param {Object} state
|
|
248
|
-
*/
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
async destroy(state) {
|
|
252
|
-
return this.module.destroy(state);
|
|
253
|
-
}
|
|
254
|
-
/**
|
|
255
|
-
* Runs command of an CLI extension.
|
|
256
|
-
* @param {Object} state
|
|
257
|
-
* @param {Object} argv
|
|
258
|
-
*/
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
async run(state, argv) {
|
|
262
|
-
const {
|
|
263
|
-
installed,
|
|
264
|
-
moduleName,
|
|
265
|
-
version
|
|
266
|
-
} = this;
|
|
267
|
-
|
|
268
|
-
if (!installed) {
|
|
269
|
-
const spinner = `Installing ${moduleName}${version ? `@${version}` : ''}`;
|
|
270
|
-
|
|
271
|
-
try {
|
|
272
|
-
await this.installModule(null, {
|
|
273
|
-
spinner
|
|
274
|
-
});
|
|
275
|
-
await (0, _extensions.addInstalled)(moduleName, this.getInfo());
|
|
276
|
-
const {
|
|
277
|
-
init,
|
|
278
|
-
destroy
|
|
279
|
-
} = this.module;
|
|
280
|
-
|
|
281
|
-
if (init || destroy) {
|
|
282
|
-
console.log(`${moduleName} was successfully installed. Please run your command again.`);
|
|
283
|
-
return;
|
|
284
|
-
}
|
|
285
|
-
} catch (err) {
|
|
286
|
-
console.error(err);
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
return this.module.runAsExtension(state, argv);
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
getInfo() {
|
|
295
|
-
this._cleanCache();
|
|
296
|
-
|
|
297
|
-
return this.module.info;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
getDockerCompose() {
|
|
301
|
-
this._cleanCache();
|
|
302
|
-
|
|
303
|
-
return this.module.dockerCompose;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
_cleanCache() {
|
|
307
|
-
delete require.cache[require.resolve(this.modulePath)];
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
exports.Pluggable = Pluggable;
|