@crouton-kit/crouter 0.2.6 → 0.3.1
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/dist/builtin-skills/skills/crouter-development/marketplaces/SKILL.md +9 -9
- package/dist/builtin-skills/skills/crouter-development/plugins/SKILL.md +19 -19
- package/dist/cli.js +42 -37
- package/dist/commands/__tests__/human.test.d.ts +1 -0
- package/dist/commands/__tests__/human.test.js +214 -0
- package/dist/commands/__tests__/skill.test.d.ts +1 -0
- package/dist/commands/__tests__/skill.test.js +287 -0
- package/dist/commands/debug.d.ts +3 -0
- package/dist/commands/debug.js +179 -0
- package/dist/commands/flow.d.ts +2 -0
- package/dist/commands/flow.js +24 -0
- package/dist/commands/human.d.ts +2 -0
- package/dist/commands/human.js +480 -0
- package/dist/commands/job.d.ts +2 -0
- package/dist/commands/job.js +669 -0
- package/dist/commands/pkg.d.ts +2 -0
- package/dist/commands/pkg.js +1021 -0
- package/dist/commands/plan.d.ts +4 -2
- package/dist/commands/plan.js +306 -22
- package/dist/commands/skill.d.ts +2 -2
- package/dist/commands/skill.js +607 -456
- package/dist/commands/spec.d.ts +3 -2
- package/dist/commands/spec.js +283 -10
- package/dist/commands/sys.d.ts +2 -0
- package/dist/commands/sys.js +712 -0
- package/dist/core/__tests__/argv-parser.test.d.ts +1 -0
- package/dist/core/__tests__/argv-parser.test.js +199 -0
- package/dist/core/__tests__/flow-leaves.test.d.ts +1 -0
- package/dist/core/__tests__/flow-leaves.test.js +248 -0
- package/dist/core/__tests__/job.test.d.ts +1 -0
- package/dist/core/__tests__/job.test.js +346 -0
- package/dist/core/__tests__/pkg.test.d.ts +1 -0
- package/dist/core/__tests__/pkg.test.js +218 -0
- package/dist/core/__tests__/sys.test.d.ts +1 -0
- package/dist/core/__tests__/sys.test.js +208 -0
- package/dist/core/artifact.d.ts +29 -18
- package/dist/core/artifact.js +78 -221
- package/dist/core/auto-update.js +11 -3
- package/dist/core/command.d.ts +36 -0
- package/dist/core/command.js +287 -0
- package/dist/core/errors.d.ts +3 -0
- package/dist/core/errors.js +5 -0
- package/dist/core/fs-utils.d.ts +1 -0
- package/dist/core/fs-utils.js +4 -0
- package/dist/core/help.d.ts +98 -0
- package/dist/core/help.js +163 -0
- package/dist/core/io.d.ts +29 -0
- package/dist/core/io.js +83 -0
- package/dist/core/jobs.d.ts +87 -0
- package/dist/core/jobs.js +353 -0
- package/dist/core/pagination.d.ts +33 -0
- package/dist/core/pagination.js +89 -0
- package/dist/core/self-update.d.ts +21 -0
- package/dist/{commands/update.js → core/self-update.js} +28 -63
- package/dist/core/spawn.d.ts +47 -65
- package/dist/core/spawn.js +78 -228
- package/dist/prompts/agent.d.ts +10 -5
- package/dist/prompts/agent.js +51 -74
- package/dist/prompts/debug.d.ts +8 -0
- package/dist/prompts/debug.js +37 -0
- package/dist/prompts/review.js +4 -11
- package/dist/prompts/skill.d.ts +0 -1
- package/dist/prompts/skill.js +95 -149
- package/package.json +4 -2
- package/dist/commands/agent.d.ts +0 -2
- package/dist/commands/agent.js +0 -265
- package/dist/commands/config.d.ts +0 -2
- package/dist/commands/config.js +0 -146
- package/dist/commands/doctor.d.ts +0 -2
- package/dist/commands/doctor.js +0 -268
- package/dist/commands/marketplace.d.ts +0 -2
- package/dist/commands/marketplace.js +0 -365
- package/dist/commands/plugin.d.ts +0 -2
- package/dist/commands/plugin.js +0 -367
- package/dist/commands/update.d.ts +0 -4
- package/dist/prompts/plan.d.ts +0 -1
- package/dist/prompts/plan.js +0 -175
- package/dist/prompts/spec.d.ts +0 -1
- package/dist/prompts/spec.js +0 -153
|
@@ -1,365 +0,0 @@
|
|
|
1
|
-
import { join, isAbsolute } from 'node:path';
|
|
2
|
-
import { renameSync } from 'node:fs';
|
|
3
|
-
import { notFound, usage } from '../core/errors.js';
|
|
4
|
-
import { out, err, hint, info, jsonOut, handleError } from '../core/output.js';
|
|
5
|
-
import { requireScopeRoot, resolveScopeArg, projectScopeRoot, } from '../core/scope.js';
|
|
6
|
-
import { readConfig, updateConfig, updateState, ensureScopeInitialized } from '../core/config.js';
|
|
7
|
-
import { listAllMarketplaces, findMarketplaceByName, listInstalledPlugins, } from '../core/resolver.js';
|
|
8
|
-
import { pathExists, ensureDir, removePath, linkOrCopy, isSymlink, nowIso } from '../core/fs-utils.js';
|
|
9
|
-
import { clone, pull, deriveNameFromUrl } from '../core/git.js';
|
|
10
|
-
import { readMarketplaceManifest, readPluginManifest } from '../core/manifest.js';
|
|
11
|
-
export function registerMarketplaceCommands(program) {
|
|
12
|
-
const marketplace = program
|
|
13
|
-
.command('marketplace')
|
|
14
|
-
.description('manage marketplaces');
|
|
15
|
-
// list
|
|
16
|
-
marketplace
|
|
17
|
-
.command('list')
|
|
18
|
-
.description('list installed marketplaces across all scopes')
|
|
19
|
-
.option('--json', 'emit JSON')
|
|
20
|
-
.action(async (opts) => {
|
|
21
|
-
try {
|
|
22
|
-
const all = listAllMarketplaces();
|
|
23
|
-
if (opts.json) {
|
|
24
|
-
jsonOut({
|
|
25
|
-
marketplaces: all.map((m) => ({
|
|
26
|
-
name: m.name,
|
|
27
|
-
scope: m.scope,
|
|
28
|
-
url: m.url,
|
|
29
|
-
ref: m.ref,
|
|
30
|
-
version: m.manifest.version,
|
|
31
|
-
plugins_count: m.manifest.plugins.length,
|
|
32
|
-
root: m.root,
|
|
33
|
-
})),
|
|
34
|
-
});
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
for (const m of all) {
|
|
38
|
-
const version = m.manifest.version !== undefined ? m.manifest.version : 'unknown';
|
|
39
|
-
out(`${m.scope}:${m.name}@${version} ${m.url} (${m.manifest.plugins.length} plugins)`);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
catch (e) {
|
|
43
|
-
handleError(e, { json: opts.json });
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
// add
|
|
47
|
-
marketplace
|
|
48
|
-
.command('add <git-url>')
|
|
49
|
-
.description('clone and register a marketplace')
|
|
50
|
-
.option('--scope <scope>', 'user|project (default: user)')
|
|
51
|
-
.option('--ref <branch>', 'branch/tag to clone')
|
|
52
|
-
.action(async (gitUrl, opts) => {
|
|
53
|
-
try {
|
|
54
|
-
const scope = opts.scope !== undefined
|
|
55
|
-
? resolveScopeArg(opts.scope)
|
|
56
|
-
: 'user';
|
|
57
|
-
if (scope === 'all') {
|
|
58
|
-
throw usage('--scope must be user or project, not all');
|
|
59
|
-
}
|
|
60
|
-
hint(`default scope is user (private); pass --scope project to share with collaborators`);
|
|
61
|
-
const root = requireScopeRoot(scope);
|
|
62
|
-
ensureScopeInitialized(scope, root);
|
|
63
|
-
const tempName = deriveNameFromUrl(gitUrl);
|
|
64
|
-
const mktsDir = join(root, 'marketplaces');
|
|
65
|
-
ensureDir(mktsDir);
|
|
66
|
-
const tempDest = join(mktsDir, tempName);
|
|
67
|
-
if (pathExists(tempDest)) {
|
|
68
|
-
removePath(tempDest);
|
|
69
|
-
}
|
|
70
|
-
info(`cloning ${gitUrl}...`);
|
|
71
|
-
clone(gitUrl, tempDest, { depth: 1, ref: opts.ref });
|
|
72
|
-
const manifest = readMarketplaceManifest(tempDest);
|
|
73
|
-
if (!manifest) {
|
|
74
|
-
removePath(tempDest);
|
|
75
|
-
throw notFound(`marketplace manifest not found at ${tempDest}/.crouter-marketplace/marketplace.json — not a valid marketplace`);
|
|
76
|
-
}
|
|
77
|
-
const finalName = manifest.name;
|
|
78
|
-
const finalDest = join(mktsDir, finalName);
|
|
79
|
-
if (finalName !== tempName) {
|
|
80
|
-
if (pathExists(finalDest)) {
|
|
81
|
-
removePath(finalDest);
|
|
82
|
-
}
|
|
83
|
-
renameSync(tempDest, finalDest);
|
|
84
|
-
}
|
|
85
|
-
updateConfig(scope, (cfg) => {
|
|
86
|
-
const ref = opts.ref !== undefined ? opts.ref : 'main';
|
|
87
|
-
cfg.marketplaces[finalName] = {
|
|
88
|
-
url: gitUrl,
|
|
89
|
-
ref,
|
|
90
|
-
installed_at: nowIso(),
|
|
91
|
-
};
|
|
92
|
-
});
|
|
93
|
-
out(finalDest);
|
|
94
|
-
info(`marketplace "${finalName}" added to ${scope} scope`);
|
|
95
|
-
}
|
|
96
|
-
catch (e) {
|
|
97
|
-
handleError(e);
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
// remove
|
|
101
|
-
marketplace
|
|
102
|
-
.command('remove <name>')
|
|
103
|
-
.description('remove a marketplace and its sourced plugins')
|
|
104
|
-
.option('--scope <scope>', 'user|project')
|
|
105
|
-
.action(async (name, opts) => {
|
|
106
|
-
try {
|
|
107
|
-
const scopeArg = opts.scope !== undefined ? resolveScopeArg(opts.scope) : undefined;
|
|
108
|
-
let targetScope;
|
|
109
|
-
let mktRoot;
|
|
110
|
-
if (scopeArg !== undefined && scopeArg !== 'all') {
|
|
111
|
-
const s = scopeArg;
|
|
112
|
-
const found = findMarketplaceByName(name, s);
|
|
113
|
-
if (!found) {
|
|
114
|
-
throw notFound(`marketplace not found: ${name} (scope: ${s})`);
|
|
115
|
-
}
|
|
116
|
-
targetScope = s;
|
|
117
|
-
mktRoot = found.root;
|
|
118
|
-
}
|
|
119
|
-
else {
|
|
120
|
-
const found = findMarketplaceByName(name);
|
|
121
|
-
if (!found) {
|
|
122
|
-
throw notFound(`marketplace not found: ${name}`);
|
|
123
|
-
}
|
|
124
|
-
targetScope = found.scope;
|
|
125
|
-
mktRoot = found.root;
|
|
126
|
-
}
|
|
127
|
-
const scope = targetScope;
|
|
128
|
-
const root = requireScopeRoot(scope);
|
|
129
|
-
const plgDir = join(root, 'plugins');
|
|
130
|
-
const cfg = readConfig(scope);
|
|
131
|
-
const pluginsToRemove = [];
|
|
132
|
-
for (const [pluginName, entry] of Object.entries(cfg.plugins)) {
|
|
133
|
-
if (entry.source_marketplace === name) {
|
|
134
|
-
pluginsToRemove.push(pluginName);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
for (const pluginName of pluginsToRemove) {
|
|
138
|
-
const pluginPath = join(plgDir, pluginName);
|
|
139
|
-
removePath(pluginPath);
|
|
140
|
-
info(`removed plugin "${pluginName}" (sourced from ${name})`);
|
|
141
|
-
}
|
|
142
|
-
removePath(mktRoot);
|
|
143
|
-
updateConfig(scope, (c) => {
|
|
144
|
-
delete c.marketplaces[name];
|
|
145
|
-
for (const pluginName of pluginsToRemove) {
|
|
146
|
-
delete c.plugins[pluginName];
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
info(`marketplace "${name}" removed from ${scope} scope`);
|
|
150
|
-
}
|
|
151
|
-
catch (e) {
|
|
152
|
-
handleError(e);
|
|
153
|
-
}
|
|
154
|
-
});
|
|
155
|
-
// browse
|
|
156
|
-
marketplace
|
|
157
|
-
.command('browse <name>')
|
|
158
|
-
.description('list available plugins in a marketplace, marking installed ones')
|
|
159
|
-
.option('--json', 'emit JSON')
|
|
160
|
-
.action(async (name, opts) => {
|
|
161
|
-
try {
|
|
162
|
-
const mkt = findMarketplaceByName(name);
|
|
163
|
-
if (!mkt) {
|
|
164
|
-
throw notFound(`marketplace not found: ${name}`);
|
|
165
|
-
}
|
|
166
|
-
const allPlugins = listInstalledPlugins('user').concat(projectScopeRoot() ? listInstalledPlugins('project') : []);
|
|
167
|
-
const installedMap = new Map();
|
|
168
|
-
for (const p of allPlugins) {
|
|
169
|
-
if (!installedMap.has(p.name)) {
|
|
170
|
-
installedMap.set(p.name, p.scope);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
if (opts.json) {
|
|
174
|
-
jsonOut({
|
|
175
|
-
marketplace: mkt.name,
|
|
176
|
-
plugins: mkt.manifest.plugins.map((entry) => {
|
|
177
|
-
const installedScope = installedMap.get(entry.name);
|
|
178
|
-
const installed = installedScope !== undefined;
|
|
179
|
-
const result = {
|
|
180
|
-
name: entry.name,
|
|
181
|
-
version: entry.version,
|
|
182
|
-
description: entry.description,
|
|
183
|
-
keywords: entry.keywords,
|
|
184
|
-
installed,
|
|
185
|
-
};
|
|
186
|
-
if (installed) {
|
|
187
|
-
result.installed_scope = installedScope;
|
|
188
|
-
}
|
|
189
|
-
return result;
|
|
190
|
-
}),
|
|
191
|
-
});
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
for (const entry of mkt.manifest.plugins) {
|
|
195
|
-
const installedScope = installedMap.get(entry.name);
|
|
196
|
-
const installed = installedScope !== undefined;
|
|
197
|
-
const mark = installed ? '[x]' : '[ ]';
|
|
198
|
-
const version = entry.version !== undefined ? `@${entry.version}` : '';
|
|
199
|
-
const desc = entry.description !== undefined ? ` ${entry.description}` : '';
|
|
200
|
-
out(`${mark} ${entry.name}${version}${desc}`);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
catch (e) {
|
|
204
|
-
handleError(e, { json: opts.json });
|
|
205
|
-
}
|
|
206
|
-
});
|
|
207
|
-
// update
|
|
208
|
-
marketplace
|
|
209
|
-
.command('update [name]')
|
|
210
|
-
.description('git pull marketplace(s) and update their sourced plugins')
|
|
211
|
-
.action(async (name, _opts) => {
|
|
212
|
-
try {
|
|
213
|
-
const toUpdate = name !== undefined
|
|
214
|
-
? (() => {
|
|
215
|
-
const found = findMarketplaceByName(name);
|
|
216
|
-
if (!found) {
|
|
217
|
-
throw notFound(`marketplace not found: ${name}`);
|
|
218
|
-
}
|
|
219
|
-
return [found];
|
|
220
|
-
})()
|
|
221
|
-
: listAllMarketplaces();
|
|
222
|
-
for (const mkt of toUpdate) {
|
|
223
|
-
info(`updating marketplace "${mkt.name}" (${mkt.scope})...`);
|
|
224
|
-
const pullResult = pull(mkt.root);
|
|
225
|
-
if (pullResult.status !== 0) {
|
|
226
|
-
err(`crtr: git pull failed for ${mkt.name}: ${pullResult.stderr.trim()}`);
|
|
227
|
-
continue;
|
|
228
|
-
}
|
|
229
|
-
const freshManifest = readMarketplaceManifest(mkt.root);
|
|
230
|
-
const newVersion = freshManifest !== null && freshManifest.version !== undefined
|
|
231
|
-
? freshManifest.version
|
|
232
|
-
: undefined;
|
|
233
|
-
updateState(mkt.scope, (s) => {
|
|
234
|
-
if (!s.marketplaces[mkt.name]) {
|
|
235
|
-
s.marketplaces[mkt.name] = {};
|
|
236
|
-
}
|
|
237
|
-
s.marketplaces[mkt.name].last_updated = nowIso();
|
|
238
|
-
});
|
|
239
|
-
// newVersion is available but ConfigMarketplaceEntry has no version field; state tracks last_updated
|
|
240
|
-
const cfg = readConfig(mkt.scope);
|
|
241
|
-
for (const [pluginName, entry] of Object.entries(cfg.plugins)) {
|
|
242
|
-
if (entry.source_marketplace !== mkt.name)
|
|
243
|
-
continue;
|
|
244
|
-
const pluginPath = join(requireScopeRoot(mkt.scope), 'plugins', pluginName);
|
|
245
|
-
if (isSymlink(pluginPath)) {
|
|
246
|
-
// symlink points into marketplace; content is already updated by the pull above
|
|
247
|
-
info(`plugin "${pluginName}" updated via symlink (marketplace pull)`);
|
|
248
|
-
}
|
|
249
|
-
else if (pathExists(pluginPath)) {
|
|
250
|
-
// URL-sourced plugin — pull it too
|
|
251
|
-
const pluginPullResult = pull(pluginPath);
|
|
252
|
-
if (pluginPullResult.status !== 0) {
|
|
253
|
-
err(`crtr: git pull failed for plugin "${pluginName}": ${pluginPullResult.stderr.trim()}`);
|
|
254
|
-
continue;
|
|
255
|
-
}
|
|
256
|
-
info(`plugin "${pluginName}" updated`);
|
|
257
|
-
}
|
|
258
|
-
if (freshManifest !== null) {
|
|
259
|
-
const pluginEntry = freshManifest.plugins.find((p) => p.name === pluginName);
|
|
260
|
-
if (pluginEntry !== undefined && pluginEntry.version !== undefined) {
|
|
261
|
-
updateConfig(mkt.scope, (c) => {
|
|
262
|
-
if (c.plugins[pluginName]) {
|
|
263
|
-
c.plugins[pluginName].version = pluginEntry.version;
|
|
264
|
-
}
|
|
265
|
-
});
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
updateState(mkt.scope, (s) => {
|
|
269
|
-
if (!s.plugins[pluginName]) {
|
|
270
|
-
s.plugins[pluginName] = {};
|
|
271
|
-
}
|
|
272
|
-
s.plugins[pluginName].last_updated = nowIso();
|
|
273
|
-
});
|
|
274
|
-
}
|
|
275
|
-
info(`marketplace "${mkt.name}" up to date`);
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
catch (e) {
|
|
279
|
-
handleError(e);
|
|
280
|
-
}
|
|
281
|
-
});
|
|
282
|
-
// install
|
|
283
|
-
marketplace
|
|
284
|
-
.command('install <marketplace-plugin>')
|
|
285
|
-
.description('install a plugin from a marketplace using <marketplace>:<plugin> syntax')
|
|
286
|
-
.option('--scope <scope>', 'user|project')
|
|
287
|
-
.action(async (marketplacePlugin, opts) => {
|
|
288
|
-
try {
|
|
289
|
-
const colonIdx = marketplacePlugin.indexOf(':');
|
|
290
|
-
if (colonIdx === -1) {
|
|
291
|
-
throw usage(`argument must be in the form <marketplace>:<plugin> (e.g. crouton-kit:authoring)`);
|
|
292
|
-
}
|
|
293
|
-
const mktName = marketplacePlugin.slice(0, colonIdx);
|
|
294
|
-
const pluginName = marketplacePlugin.slice(colonIdx + 1);
|
|
295
|
-
if (!mktName || !pluginName) {
|
|
296
|
-
throw usage(`argument must be in the form <marketplace>:<plugin> (e.g. crouton-kit:authoring)`);
|
|
297
|
-
}
|
|
298
|
-
const scopeArg = opts.scope !== undefined ? resolveScopeArg(opts.scope) : undefined;
|
|
299
|
-
let mkt;
|
|
300
|
-
if (scopeArg !== undefined && scopeArg !== 'all') {
|
|
301
|
-
mkt = findMarketplaceByName(mktName, scopeArg);
|
|
302
|
-
}
|
|
303
|
-
else {
|
|
304
|
-
mkt = findMarketplaceByName(mktName);
|
|
305
|
-
}
|
|
306
|
-
if (!mkt) {
|
|
307
|
-
throw notFound(`marketplace not found: ${mktName}`);
|
|
308
|
-
}
|
|
309
|
-
const entry = mkt.manifest.plugins.find((p) => p.name === pluginName);
|
|
310
|
-
if (!entry) {
|
|
311
|
-
throw notFound(`plugin "${pluginName}" not found in marketplace "${mktName}"`);
|
|
312
|
-
}
|
|
313
|
-
let destScope;
|
|
314
|
-
if (opts.scope !== undefined && scopeArg !== 'all') {
|
|
315
|
-
destScope = scopeArg;
|
|
316
|
-
}
|
|
317
|
-
else {
|
|
318
|
-
destScope = mkt.scope;
|
|
319
|
-
}
|
|
320
|
-
const destRoot = requireScopeRoot(destScope);
|
|
321
|
-
ensureScopeInitialized(destScope, destRoot);
|
|
322
|
-
const destPluginDir = join(destRoot, 'plugins', pluginName);
|
|
323
|
-
const source = entry.source;
|
|
324
|
-
const isRelativePath = source.startsWith('./') || source.startsWith('../') ||
|
|
325
|
-
(!source.includes('://') && !isAbsolute(source));
|
|
326
|
-
if (isRelativePath) {
|
|
327
|
-
const sourcePath = join(mkt.root, source);
|
|
328
|
-
if (!pathExists(sourcePath)) {
|
|
329
|
-
throw notFound(`plugin source path does not exist: ${sourcePath}`);
|
|
330
|
-
}
|
|
331
|
-
linkOrCopy(sourcePath, destPluginDir);
|
|
332
|
-
info(`linked plugin "${pluginName}" → ${sourcePath}`);
|
|
333
|
-
}
|
|
334
|
-
else {
|
|
335
|
-
// URL source — clone directly
|
|
336
|
-
if (pathExists(destPluginDir)) {
|
|
337
|
-
removePath(destPluginDir);
|
|
338
|
-
}
|
|
339
|
-
info(`cloning plugin "${pluginName}" from ${source}...`);
|
|
340
|
-
clone(source, destPluginDir, { depth: 1 });
|
|
341
|
-
}
|
|
342
|
-
const pluginManifest = readPluginManifest(destPluginDir);
|
|
343
|
-
if (!pluginManifest) {
|
|
344
|
-
removePath(destPluginDir);
|
|
345
|
-
throw notFound(`plugin manifest not found at ${destPluginDir}/.crouter-plugin/plugin.json`);
|
|
346
|
-
}
|
|
347
|
-
const version = entry.version !== undefined ? entry.version : pluginManifest.version;
|
|
348
|
-
updateConfig(destScope, (cfg) => {
|
|
349
|
-
const pluginCfg = {
|
|
350
|
-
enabled: true,
|
|
351
|
-
source_marketplace: mktName,
|
|
352
|
-
};
|
|
353
|
-
if (version !== undefined) {
|
|
354
|
-
pluginCfg.version = version;
|
|
355
|
-
}
|
|
356
|
-
cfg.plugins[pluginName] = pluginCfg;
|
|
357
|
-
});
|
|
358
|
-
out(destPluginDir);
|
|
359
|
-
info(`plugin "${pluginName}" installed to ${destScope} scope`);
|
|
360
|
-
}
|
|
361
|
-
catch (e) {
|
|
362
|
-
handleError(e);
|
|
363
|
-
}
|
|
364
|
-
});
|
|
365
|
-
}
|