@configjs/cli 1.0.3 → 1.0.5
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/{check-I62WT7NB.js → check-4Y5YGVVD.js} +6 -3
- package/dist/chunk-5S5KGCVY.js +276 -0
- package/dist/chunk-AMLNK7QR.js +417 -0
- package/dist/{chunk-T4WVSBI6.js → chunk-G5QBS6TL.js} +1 -1
- package/dist/chunk-QGM4M3NI.js +37 -0
- package/dist/{chunk-7ZLAP62L.js → chunk-UB6NBZEM.js} +265 -454
- package/dist/cli.js +23 -4
- package/dist/{install-ML3FB63K.js → install-M6JANAU5.js} +57 -239
- package/dist/installed-BXP7ZWOU.js +41 -0
- package/dist/{list-CBEUUZUI.js → list-HKDWBO2I.js} +3 -1
- package/dist/remove-ZZD67W4M.js +1736 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import "./chunk-QGM4M3NI.js";
|
|
2
3
|
|
|
3
4
|
// src/cli.ts
|
|
4
5
|
import { Command } from "commander";
|
|
5
6
|
|
|
6
7
|
// package.json
|
|
7
|
-
var version = "1.0.
|
|
8
|
+
var version = "1.0.5";
|
|
8
9
|
|
|
9
10
|
// src/cli.ts
|
|
10
11
|
var program = new Command();
|
|
@@ -12,7 +13,7 @@ program.name("confjs").description("Configure your frontend stack, instantly").v
|
|
|
12
13
|
program.command("react").description("Configure a React project").option("-y, --yes", "Accept all defaults").option("-d, --dry-run", "Simulate without writing to disk").option("-s, --silent", "Non-interactive mode").option("--debug", "Enable debug logs").option("-c, --config <file>", "Use configuration file").option("-f, --force", "Force installation (overwrite configs)").option("--no-install", "Generate configs only, skip package installation").action(
|
|
13
14
|
async (options) => {
|
|
14
15
|
try {
|
|
15
|
-
const { installReact } = await import("./install-
|
|
16
|
+
const { installReact } = await import("./install-M6JANAU5.js");
|
|
16
17
|
await installReact(options);
|
|
17
18
|
} catch (error) {
|
|
18
19
|
console.error("Error:", error);
|
|
@@ -22,7 +23,7 @@ program.command("react").description("Configure a React project").option("-y, --
|
|
|
22
23
|
);
|
|
23
24
|
program.command("list").description("List available libraries").option("-c, --category <category>", "Filter by category").action(async (options) => {
|
|
24
25
|
try {
|
|
25
|
-
const { listLibraries } = await import("./list-
|
|
26
|
+
const { listLibraries } = await import("./list-HKDWBO2I.js");
|
|
26
27
|
listLibraries(options);
|
|
27
28
|
} catch (error) {
|
|
28
29
|
console.error("Error:", error);
|
|
@@ -31,11 +32,29 @@ program.command("list").description("List available libraries").option("-c, --ca
|
|
|
31
32
|
});
|
|
32
33
|
program.command("check").description("Check compatibility without installing").option("-c, --config <file>", "Configuration file to check").action(async (options) => {
|
|
33
34
|
try {
|
|
34
|
-
const { checkCompatibility } = await import("./check-
|
|
35
|
+
const { checkCompatibility } = await import("./check-4Y5YGVVD.js");
|
|
35
36
|
await checkCompatibility(options);
|
|
36
37
|
} catch (error) {
|
|
37
38
|
console.error("Error:", error);
|
|
38
39
|
process.exit(1);
|
|
39
40
|
}
|
|
40
41
|
});
|
|
42
|
+
program.command("installed").description("List installed plugins").action(async () => {
|
|
43
|
+
try {
|
|
44
|
+
const { installedCommand } = await import("./installed-BXP7ZWOU.js");
|
|
45
|
+
await installedCommand();
|
|
46
|
+
} catch (error) {
|
|
47
|
+
console.error("Error:", error);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
program.command("remove <plugin>").description("Remove an installed plugin").action(async (plugin) => {
|
|
52
|
+
try {
|
|
53
|
+
const { removeCommand } = await import("./remove-ZZD67W4M.js");
|
|
54
|
+
await removeCommand(plugin);
|
|
55
|
+
} catch (error) {
|
|
56
|
+
console.error("Error:", error);
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
41
60
|
program.parse(process.argv);
|
|
@@ -1,246 +1,22 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CompatibilityValidator,
|
|
3
3
|
compatibilityRules
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-G5QBS6TL.js";
|
|
5
5
|
import {
|
|
6
6
|
BackupManager,
|
|
7
7
|
ConfigWriter,
|
|
8
|
-
checkPathExists,
|
|
9
|
-
detectPackageManager,
|
|
10
8
|
getPluginsByCategory,
|
|
9
|
+
pluginRegistry
|
|
10
|
+
} from "./chunk-UB6NBZEM.js";
|
|
11
|
+
import {
|
|
12
|
+
PluginTracker,
|
|
13
|
+
detectContext
|
|
14
|
+
} from "./chunk-AMLNK7QR.js";
|
|
15
|
+
import {
|
|
11
16
|
installPackages,
|
|
12
|
-
logger
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
readTsConfig
|
|
16
|
-
} from "./chunk-7ZLAP62L.js";
|
|
17
|
-
|
|
18
|
-
// src/core/detector.ts
|
|
19
|
-
import { resolve, join } from "path";
|
|
20
|
-
import { platform, version } from "process";
|
|
21
|
-
var detectionCache = /* @__PURE__ */ new Map();
|
|
22
|
-
var DetectionError = class extends Error {
|
|
23
|
-
constructor(message, context) {
|
|
24
|
-
super(message);
|
|
25
|
-
this.context = context;
|
|
26
|
-
this.name = "DetectionError";
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
function detectFramework(pkg) {
|
|
30
|
-
const deps = {
|
|
31
|
-
...pkg["dependencies"] || {},
|
|
32
|
-
...pkg["devDependencies"] || {}
|
|
33
|
-
};
|
|
34
|
-
if (deps["react"]) {
|
|
35
|
-
return {
|
|
36
|
-
framework: "react",
|
|
37
|
-
version: deps["react"].replace(/[\^~]/, "")
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
if (deps["vue"]) {
|
|
41
|
-
return {
|
|
42
|
-
framework: "vue",
|
|
43
|
-
version: deps["vue"].replace(/[\^~]/, "")
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
if (deps["svelte"]) {
|
|
47
|
-
return {
|
|
48
|
-
framework: "svelte",
|
|
49
|
-
version: deps["svelte"].replace(/[\^~]/, "")
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
throw new DetectionError(
|
|
53
|
-
"No supported framework detected. Supported frameworks: React, Vue, Svelte",
|
|
54
|
-
{ dependencies: Object.keys(deps) }
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
async function detectBundler(projectRoot, pkg) {
|
|
58
|
-
const deps = {
|
|
59
|
-
...pkg["dependencies"] || {},
|
|
60
|
-
...pkg["devDependencies"] || {}
|
|
61
|
-
};
|
|
62
|
-
if (deps["vite"]) {
|
|
63
|
-
const viteConfigExists = await checkPathExists(join(projectRoot, "vite.config.js")) || await checkPathExists(join(projectRoot, "vite.config.ts")) || await checkPathExists(join(projectRoot, "vite.config.mjs")) || await checkPathExists(join(projectRoot, "vite.config.cjs"));
|
|
64
|
-
if (viteConfigExists) {
|
|
65
|
-
return {
|
|
66
|
-
bundler: "vite",
|
|
67
|
-
version: deps["vite"].replace(/[\^~]/, "")
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
if (deps["react-scripts"]) {
|
|
72
|
-
return {
|
|
73
|
-
bundler: "cra",
|
|
74
|
-
version: deps["react-scripts"].replace(/[\^~]/, "")
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
if (deps["webpack"]) {
|
|
78
|
-
const webpackConfigExists = await checkPathExists(join(projectRoot, "webpack.config.js")) || await checkPathExists(join(projectRoot, "webpack.config.ts"));
|
|
79
|
-
if (webpackConfigExists) {
|
|
80
|
-
return {
|
|
81
|
-
bundler: "webpack",
|
|
82
|
-
version: deps["webpack"].replace(/[\^~]/, "")
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
if (deps["@rspack/core"]) {
|
|
87
|
-
return {
|
|
88
|
-
bundler: "rspack",
|
|
89
|
-
version: deps["@rspack/core"].replace(/[\^~]/, "")
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
return {
|
|
93
|
-
bundler: null,
|
|
94
|
-
version: null
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
async function detectTypeScript(projectRoot) {
|
|
98
|
-
const tsConfig = await readTsConfig(projectRoot);
|
|
99
|
-
if (tsConfig) {
|
|
100
|
-
const possiblePaths = [
|
|
101
|
-
join(projectRoot, "tsconfig.json"),
|
|
102
|
-
join(projectRoot, "tsconfig.app.json"),
|
|
103
|
-
join(projectRoot, "tsconfig.node.json")
|
|
104
|
-
];
|
|
105
|
-
for (const path of possiblePaths) {
|
|
106
|
-
if (await checkPathExists(path)) {
|
|
107
|
-
return {
|
|
108
|
-
typescript: true,
|
|
109
|
-
tsconfigPath: path
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
return {
|
|
114
|
-
typescript: true,
|
|
115
|
-
tsconfigPath: join(projectRoot, "tsconfig.json")
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
return {
|
|
119
|
-
typescript: false
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
async function detectSrcDir(projectRoot) {
|
|
123
|
-
const possibleDirs = ["src", "app", "source", "lib"];
|
|
124
|
-
for (const dir of possibleDirs) {
|
|
125
|
-
const dirPath = join(projectRoot, dir);
|
|
126
|
-
if (await checkPathExists(dirPath)) {
|
|
127
|
-
return dir;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
return "src";
|
|
131
|
-
}
|
|
132
|
-
async function detectPublicDir(projectRoot) {
|
|
133
|
-
const possibleDirs = ["public", "static", "assets"];
|
|
134
|
-
for (const dir of possibleDirs) {
|
|
135
|
-
const dirPath = join(projectRoot, dir);
|
|
136
|
-
if (await checkPathExists(dirPath)) {
|
|
137
|
-
return dir;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
return "public";
|
|
141
|
-
}
|
|
142
|
-
async function detectGit(projectRoot) {
|
|
143
|
-
const gitDir = join(projectRoot, ".git");
|
|
144
|
-
const hasGit = await checkPathExists(gitDir);
|
|
145
|
-
if (!hasGit) {
|
|
146
|
-
return { hasGit: false };
|
|
147
|
-
}
|
|
148
|
-
const hooksPath = join(gitDir, "hooks");
|
|
149
|
-
const hasHooks = await checkPathExists(hooksPath);
|
|
150
|
-
return {
|
|
151
|
-
hasGit: true,
|
|
152
|
-
gitHooksPath: hasHooks ? hooksPath : void 0
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
async function detectLockfile(projectRoot, packageManager) {
|
|
156
|
-
const lockfiles = {
|
|
157
|
-
npm: "package-lock.json",
|
|
158
|
-
yarn: "yarn.lock",
|
|
159
|
-
pnpm: "pnpm-lock.yaml",
|
|
160
|
-
bun: "bun.lockb"
|
|
161
|
-
};
|
|
162
|
-
const lockfile = lockfiles[packageManager];
|
|
163
|
-
const lockfilePath = join(projectRoot, lockfile);
|
|
164
|
-
if (await checkPathExists(lockfilePath)) {
|
|
165
|
-
return lockfile;
|
|
166
|
-
}
|
|
167
|
-
return lockfile;
|
|
168
|
-
}
|
|
169
|
-
async function detectContext(projectRoot) {
|
|
170
|
-
const fullPath = resolve(projectRoot);
|
|
171
|
-
if (detectionCache.has(fullPath)) {
|
|
172
|
-
logger.debug(`Using cached context for ${fullPath}`);
|
|
173
|
-
const cached = detectionCache.get(fullPath);
|
|
174
|
-
if (cached) {
|
|
175
|
-
return cached;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
logger.debug(`Detecting context for project: ${fullPath}`);
|
|
179
|
-
let pkg;
|
|
180
|
-
try {
|
|
181
|
-
pkg = await readPackageJson(fullPath);
|
|
182
|
-
} catch (error) {
|
|
183
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
184
|
-
throw new DetectionError(
|
|
185
|
-
`Invalid project: package.json not found or invalid. ${errorMessage}`,
|
|
186
|
-
{ projectRoot: fullPath }
|
|
187
|
-
);
|
|
188
|
-
}
|
|
189
|
-
const [
|
|
190
|
-
frameworkInfo,
|
|
191
|
-
typescriptInfo,
|
|
192
|
-
bundlerInfo,
|
|
193
|
-
packageManager,
|
|
194
|
-
srcDir,
|
|
195
|
-
publicDir,
|
|
196
|
-
gitInfo
|
|
197
|
-
] = await Promise.all([
|
|
198
|
-
Promise.resolve(detectFramework(pkg)),
|
|
199
|
-
detectTypeScript(fullPath),
|
|
200
|
-
detectBundler(fullPath, pkg),
|
|
201
|
-
detectPackageManager(fullPath),
|
|
202
|
-
detectSrcDir(fullPath),
|
|
203
|
-
detectPublicDir(fullPath),
|
|
204
|
-
detectGit(fullPath)
|
|
205
|
-
]);
|
|
206
|
-
const lockfile = await detectLockfile(fullPath, packageManager);
|
|
207
|
-
const dependencies = pkg["dependencies"] || {};
|
|
208
|
-
const devDependencies = pkg["devDependencies"] || {};
|
|
209
|
-
const context = {
|
|
210
|
-
// Framework
|
|
211
|
-
framework: frameworkInfo.framework,
|
|
212
|
-
frameworkVersion: frameworkInfo.version,
|
|
213
|
-
// Bundler
|
|
214
|
-
bundler: bundlerInfo.bundler,
|
|
215
|
-
bundlerVersion: bundlerInfo.version,
|
|
216
|
-
// Language
|
|
217
|
-
typescript: typescriptInfo.typescript,
|
|
218
|
-
tsconfigPath: typescriptInfo.tsconfigPath,
|
|
219
|
-
// Package Manager
|
|
220
|
-
packageManager,
|
|
221
|
-
lockfile,
|
|
222
|
-
// Structure
|
|
223
|
-
projectRoot: fullPath,
|
|
224
|
-
srcDir,
|
|
225
|
-
publicDir,
|
|
226
|
-
// Environment
|
|
227
|
-
os: platform,
|
|
228
|
-
nodeVersion: version,
|
|
229
|
-
// Dependencies
|
|
230
|
-
dependencies,
|
|
231
|
-
devDependencies,
|
|
232
|
-
// Git
|
|
233
|
-
hasGit: gitInfo.hasGit,
|
|
234
|
-
gitHooksPath: gitInfo.gitHooksPath
|
|
235
|
-
};
|
|
236
|
-
detectionCache.set(fullPath, context);
|
|
237
|
-
logger.debug(`Context detected successfully for ${fullPath}`, {
|
|
238
|
-
framework: context.framework,
|
|
239
|
-
bundler: context.bundler,
|
|
240
|
-
typescript: context.typescript
|
|
241
|
-
});
|
|
242
|
-
return context;
|
|
243
|
-
}
|
|
17
|
+
logger
|
|
18
|
+
} from "./chunk-5S5KGCVY.js";
|
|
19
|
+
import "./chunk-QGM4M3NI.js";
|
|
244
20
|
|
|
245
21
|
// src/cli/prompts/language.ts
|
|
246
22
|
import inquirer from "inquirer";
|
|
@@ -584,7 +360,9 @@ var Installer = class {
|
|
|
584
360
|
this.validator = validator;
|
|
585
361
|
this.writer = writer;
|
|
586
362
|
this.backupManager = backupManager;
|
|
363
|
+
this.tracker = new PluginTracker(ctx.projectRoot);
|
|
587
364
|
}
|
|
365
|
+
tracker;
|
|
588
366
|
/**
|
|
589
367
|
* Installe un ensemble de plugins
|
|
590
368
|
*
|
|
@@ -603,8 +381,35 @@ var Installer = class {
|
|
|
603
381
|
const startTime = Date.now();
|
|
604
382
|
logger.info(`Starting installation of ${plugins.length} plugin(s)`);
|
|
605
383
|
try {
|
|
384
|
+
await this.tracker.load();
|
|
385
|
+
const notInstalled = plugins.filter((p) => {
|
|
386
|
+
const isInstalled = this.tracker.isInstalled(p.name);
|
|
387
|
+
if (isInstalled) {
|
|
388
|
+
logger.info(`${p.displayName} is already installed, skipping...`);
|
|
389
|
+
}
|
|
390
|
+
return !isInstalled;
|
|
391
|
+
});
|
|
392
|
+
if (notInstalled.length === 0) {
|
|
393
|
+
logger.info("All plugins are already installed");
|
|
394
|
+
return {
|
|
395
|
+
success: true,
|
|
396
|
+
duration: Date.now() - startTime,
|
|
397
|
+
installed: [],
|
|
398
|
+
warnings: [],
|
|
399
|
+
filesCreated: []
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
for (const plugin of notInstalled) {
|
|
403
|
+
const conflicts = this.tracker.checkCategoryConflicts(plugin.category);
|
|
404
|
+
if (conflicts.length > 0) {
|
|
405
|
+
const conflictNames = conflicts.map((c) => c.displayName).join(", ");
|
|
406
|
+
throw new Error(
|
|
407
|
+
`Cannot install ${plugin.displayName}: conflicts with already installed plugin(s) in category ${plugin.category}: ${conflictNames}. Please remove conflicting plugins first.`
|
|
408
|
+
);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
606
411
|
logger.debug("Validating plugins compatibility...");
|
|
607
|
-
const validationResult = this.validator.validate(
|
|
412
|
+
const validationResult = this.validator.validate(notInstalled);
|
|
608
413
|
if (!validationResult.valid) {
|
|
609
414
|
const errorMessages = validationResult.errors.map((e) => e.message).join("; ");
|
|
610
415
|
throw new Error(
|
|
@@ -618,7 +423,7 @@ var Installer = class {
|
|
|
618
423
|
);
|
|
619
424
|
}
|
|
620
425
|
logger.debug("Resolving dependencies...");
|
|
621
|
-
const resolved = this.resolveDependencies(
|
|
426
|
+
const resolved = this.resolveDependencies(notInstalled);
|
|
622
427
|
const allPlugins = resolved.plugins;
|
|
623
428
|
if (resolved.autoInstalled.length > 0) {
|
|
624
429
|
logger.info(
|
|
@@ -663,6 +468,19 @@ var Installer = class {
|
|
|
663
468
|
}
|
|
664
469
|
logger.debug("Running post-install hooks...");
|
|
665
470
|
await this.runPostInstallHooks(allPlugins);
|
|
471
|
+
logger.debug("Tracking installed plugins...");
|
|
472
|
+
for (const plugin of allPlugins) {
|
|
473
|
+
await this.tracker.addPlugin({
|
|
474
|
+
name: plugin.name,
|
|
475
|
+
displayName: plugin.displayName,
|
|
476
|
+
category: plugin.category,
|
|
477
|
+
version: plugin.version,
|
|
478
|
+
packages: {
|
|
479
|
+
dependencies: [],
|
|
480
|
+
devDependencies: []
|
|
481
|
+
}
|
|
482
|
+
});
|
|
483
|
+
}
|
|
666
484
|
const duration = Date.now() - startTime;
|
|
667
485
|
const installed = allPlugins.map((p) => p.name);
|
|
668
486
|
logger.info(
|
|
@@ -981,8 +799,8 @@ ${t.report.title}`);
|
|
|
981
799
|
console.log(`${t.report.packagesInstalled}:`);
|
|
982
800
|
for (const pluginName of report.installed) {
|
|
983
801
|
const plugin = plugins.find((p) => p.name === pluginName);
|
|
984
|
-
const
|
|
985
|
-
console.log(` \u2713 ${plugin?.displayName || pluginName}${
|
|
802
|
+
const version = plugin?.version ? ` (${plugin.version})` : "";
|
|
803
|
+
console.log(` \u2713 ${plugin?.displayName || pluginName}${version}`);
|
|
986
804
|
}
|
|
987
805
|
console.log("");
|
|
988
806
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PluginTracker,
|
|
3
|
+
detectContext
|
|
4
|
+
} from "./chunk-AMLNK7QR.js";
|
|
5
|
+
import {
|
|
6
|
+
logger
|
|
7
|
+
} from "./chunk-5S5KGCVY.js";
|
|
8
|
+
import "./chunk-QGM4M3NI.js";
|
|
9
|
+
|
|
10
|
+
// src/cli/commands/installed.ts
|
|
11
|
+
async function installedCommand() {
|
|
12
|
+
try {
|
|
13
|
+
const ctx = await detectContext(process.cwd());
|
|
14
|
+
const tracker = new PluginTracker(ctx.projectRoot);
|
|
15
|
+
await tracker.load();
|
|
16
|
+
const installedPlugins = tracker.getInstalledPlugins();
|
|
17
|
+
if (installedPlugins.length === 0) {
|
|
18
|
+
console.log("\n\u{1F4E6} No plugins installed yet.\n");
|
|
19
|
+
console.log("Run `configjs install` to add plugins to your project.\n");
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
console.log(`
|
|
23
|
+
\u{1F4E6} Installed plugins (${installedPlugins.length}):
|
|
24
|
+
`);
|
|
25
|
+
for (const plugin of installedPlugins) {
|
|
26
|
+
const date = new Date(plugin.installedAt).toLocaleDateString();
|
|
27
|
+
console.log(` \u2713 ${plugin.displayName}`);
|
|
28
|
+
console.log(` Category: ${plugin.category.toUpperCase()}`);
|
|
29
|
+
console.log(` Version: ${plugin.version || "N/A"}`);
|
|
30
|
+
console.log(` Installed: ${date}`);
|
|
31
|
+
console.log();
|
|
32
|
+
}
|
|
33
|
+
} catch (error) {
|
|
34
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
35
|
+
logger.error(`Failed to list installed plugins: ${errorMessage}`);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export {
|
|
40
|
+
installedCommand
|
|
41
|
+
};
|