@configjs/cli 1.1.3 → 1.1.4
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 +25 -5
- package/dist/{check-7PYMMMZK.js → check-XDGAGYOE.js} +2 -2
- package/dist/{chunk-OJGTPK6N.js → chunk-4VHPGJVU.js} +1674 -11
- package/dist/{chunk-ZSDLWQSS.js → chunk-BVXGN3AC.js} +35 -2
- package/dist/{install-7LTMBLVZ.js → chunk-OAAGGK2H.js} +79 -247
- package/dist/{chunk-VJ254HJY.js → chunk-WKYUK64P.js} +110 -16
- package/dist/cli.js +17 -6
- package/dist/install-APYIRHSN.js +258 -0
- package/dist/install-nextjs-C3LEKJLY.js +353 -0
- package/dist/{installed-Y76PWTXI.js → installed-IKSARZIK.js} +1 -1
- package/dist/{list-NW6ENYK6.js → list-IJK225B3.js} +1 -1
- package/dist/{remove-7HJKNAEX.js → remove-IIT34Y3T.js} +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -5,7 +5,7 @@ import "./chunk-QGM4M3NI.js";
|
|
|
5
5
|
import { Command } from "commander";
|
|
6
6
|
|
|
7
7
|
// package.json
|
|
8
|
-
var version = "1.1.
|
|
8
|
+
var version = "1.1.4";
|
|
9
9
|
|
|
10
10
|
// src/cli.ts
|
|
11
11
|
var program = new Command();
|
|
@@ -13,7 +13,7 @@ program.name("confjs").description("Configure your frontend stack, instantly").v
|
|
|
13
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(
|
|
14
14
|
async (options) => {
|
|
15
15
|
try {
|
|
16
|
-
const { installReact } = await import("./install-
|
|
16
|
+
const { installReact } = await import("./install-APYIRHSN.js");
|
|
17
17
|
await installReact(options);
|
|
18
18
|
} catch (error) {
|
|
19
19
|
console.error("Error:", error);
|
|
@@ -21,9 +21,20 @@ program.command("react").description("Configure a React project").option("-y, --
|
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
);
|
|
24
|
+
program.command("nextjs").description("Configure a Next.js 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(
|
|
25
|
+
async (options) => {
|
|
26
|
+
try {
|
|
27
|
+
const { installNextjs } = await import("./install-nextjs-C3LEKJLY.js");
|
|
28
|
+
await installNextjs(options);
|
|
29
|
+
} catch (error) {
|
|
30
|
+
console.error("Error:", error);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
);
|
|
24
35
|
program.command("list").description("List available libraries").option("-c, --category <category>", "Filter by category").action(async (options) => {
|
|
25
36
|
try {
|
|
26
|
-
const { listLibraries } = await import("./list-
|
|
37
|
+
const { listLibraries } = await import("./list-IJK225B3.js");
|
|
27
38
|
listLibraries(options);
|
|
28
39
|
} catch (error) {
|
|
29
40
|
console.error("Error:", error);
|
|
@@ -32,7 +43,7 @@ program.command("list").description("List available libraries").option("-c, --ca
|
|
|
32
43
|
});
|
|
33
44
|
program.command("check").description("Check compatibility without installing").option("-c, --config <file>", "Configuration file to check").action(async (options) => {
|
|
34
45
|
try {
|
|
35
|
-
const { checkCompatibility } = await import("./check-
|
|
46
|
+
const { checkCompatibility } = await import("./check-XDGAGYOE.js");
|
|
36
47
|
await checkCompatibility(options);
|
|
37
48
|
} catch (error) {
|
|
38
49
|
console.error("Error:", error);
|
|
@@ -41,7 +52,7 @@ program.command("check").description("Check compatibility without installing").o
|
|
|
41
52
|
});
|
|
42
53
|
program.command("installed").description("List installed plugins").action(async () => {
|
|
43
54
|
try {
|
|
44
|
-
const { installedCommand } = await import("./installed-
|
|
55
|
+
const { installedCommand } = await import("./installed-IKSARZIK.js");
|
|
45
56
|
await installedCommand();
|
|
46
57
|
} catch (error) {
|
|
47
58
|
console.error("Error:", error);
|
|
@@ -50,7 +61,7 @@ program.command("installed").description("List installed plugins").action(async
|
|
|
50
61
|
});
|
|
51
62
|
program.command("remove <plugin>").description("Remove an installed plugin").action(async (plugin) => {
|
|
52
63
|
try {
|
|
53
|
-
const { removeCommand } = await import("./remove-
|
|
64
|
+
const { removeCommand } = await import("./remove-IIT34Y3T.js");
|
|
54
65
|
await removeCommand(plugin);
|
|
55
66
|
} catch (error) {
|
|
56
67
|
console.error("Error:", error);
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Installer,
|
|
3
|
+
SpinnerManager,
|
|
4
|
+
displayInstallationReport,
|
|
5
|
+
getTranslations,
|
|
6
|
+
promptConfirmation,
|
|
7
|
+
promptLanguage,
|
|
8
|
+
promptPluginSelection
|
|
9
|
+
} from "./chunk-OAAGGK2H.js";
|
|
10
|
+
import {
|
|
11
|
+
CompatibilityValidator,
|
|
12
|
+
compatibilityRules
|
|
13
|
+
} from "./chunk-WKYUK64P.js";
|
|
14
|
+
import {
|
|
15
|
+
BackupManager,
|
|
16
|
+
ConfigWriter,
|
|
17
|
+
pluginRegistry
|
|
18
|
+
} from "./chunk-4VHPGJVU.js";
|
|
19
|
+
import {
|
|
20
|
+
DetectionError,
|
|
21
|
+
detectContext
|
|
22
|
+
} from "./chunk-BVXGN3AC.js";
|
|
23
|
+
import {
|
|
24
|
+
checkPathExists,
|
|
25
|
+
logger
|
|
26
|
+
} from "./chunk-QRFLHLFE.js";
|
|
27
|
+
import "./chunk-QGM4M3NI.js";
|
|
28
|
+
|
|
29
|
+
// src/cli/prompts/vite-setup.ts
|
|
30
|
+
import inquirer from "inquirer";
|
|
31
|
+
async function promptViteSetup(language) {
|
|
32
|
+
const t = getTranslations(language);
|
|
33
|
+
const answers = await inquirer.prompt([
|
|
34
|
+
{
|
|
35
|
+
type: "confirm",
|
|
36
|
+
name: "shouldCreate",
|
|
37
|
+
message: t.vite.proposeSetup,
|
|
38
|
+
default: true
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
type: "input",
|
|
42
|
+
name: "projectName",
|
|
43
|
+
message: t.vite.projectName,
|
|
44
|
+
default: t.vite.projectNamePlaceholder,
|
|
45
|
+
when: (answers2) => answers2.shouldCreate === true,
|
|
46
|
+
validate: (input) => {
|
|
47
|
+
if (!input || input.trim().length === 0) {
|
|
48
|
+
return t.vite.validation.empty;
|
|
49
|
+
}
|
|
50
|
+
if (!/^[a-z0-9-_]+$/i.test(input)) {
|
|
51
|
+
return t.vite.validation.invalid;
|
|
52
|
+
}
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
type: "list",
|
|
58
|
+
name: "template",
|
|
59
|
+
message: t.vite.template,
|
|
60
|
+
choices: t.vite.templateOptions,
|
|
61
|
+
when: (answers2) => answers2.shouldCreate === true
|
|
62
|
+
}
|
|
63
|
+
]);
|
|
64
|
+
if (!answers.shouldCreate) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
projectName: answers.projectName.trim(),
|
|
69
|
+
template: answers.template
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// src/cli/utils/vite-installer.ts
|
|
74
|
+
import { resolve } from "path";
|
|
75
|
+
import { execa } from "execa";
|
|
76
|
+
async function createViteProject(options, currentDir, language) {
|
|
77
|
+
const t = getTranslations(language);
|
|
78
|
+
const { projectName, template } = options;
|
|
79
|
+
const projectPath = resolve(currentDir, projectName);
|
|
80
|
+
if (await checkPathExists(projectPath)) {
|
|
81
|
+
throw new Error(t.vite.folderExists(projectName));
|
|
82
|
+
}
|
|
83
|
+
logger.info(t.vite.creating);
|
|
84
|
+
try {
|
|
85
|
+
const result = await execa(
|
|
86
|
+
"npm",
|
|
87
|
+
["create", "vite@latest", projectName, "--", "--template", template],
|
|
88
|
+
{
|
|
89
|
+
cwd: currentDir,
|
|
90
|
+
stdio: "inherit",
|
|
91
|
+
env: {
|
|
92
|
+
...process.env,
|
|
93
|
+
// Désactiver les prompts interactifs de Vite
|
|
94
|
+
npm_config_yes: "true"
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
);
|
|
98
|
+
if (result.exitCode !== 0) {
|
|
99
|
+
throw new Error(`${t.vite.error}: exit code ${result.exitCode}`);
|
|
100
|
+
}
|
|
101
|
+
logger.success(t.vite.success);
|
|
102
|
+
logger.info(t.vite.changingDirectory);
|
|
103
|
+
return projectPath;
|
|
104
|
+
} catch (error) {
|
|
105
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
106
|
+
logger.error(`${t.vite.error}: ${errorMessage}`);
|
|
107
|
+
throw error;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// src/cli/commands/install.ts
|
|
112
|
+
import pc from "picocolors";
|
|
113
|
+
async function installReact(options) {
|
|
114
|
+
try {
|
|
115
|
+
const language = await promptLanguage();
|
|
116
|
+
const t = getTranslations(language);
|
|
117
|
+
console.log();
|
|
118
|
+
console.log(pc.bold(pc.cyan(`\u{1F50D} ${t.detection.detecting}`)));
|
|
119
|
+
let projectRoot = process.cwd();
|
|
120
|
+
let ctx;
|
|
121
|
+
try {
|
|
122
|
+
ctx = await detectContext(projectRoot);
|
|
123
|
+
} catch (error) {
|
|
124
|
+
if (error instanceof DetectionError) {
|
|
125
|
+
console.log();
|
|
126
|
+
console.log(pc.yellow(t.vite.noReactDetected));
|
|
127
|
+
console.log();
|
|
128
|
+
const viteOptions = await promptViteSetup(language);
|
|
129
|
+
if (!viteOptions) {
|
|
130
|
+
console.log();
|
|
131
|
+
console.log(pc.gray(t.common.cancel));
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const newProjectPath = await createViteProject(
|
|
135
|
+
viteOptions,
|
|
136
|
+
projectRoot,
|
|
137
|
+
language
|
|
138
|
+
);
|
|
139
|
+
process.chdir(newProjectPath);
|
|
140
|
+
projectRoot = newProjectPath;
|
|
141
|
+
console.log();
|
|
142
|
+
ctx = await detectContext(projectRoot);
|
|
143
|
+
} else {
|
|
144
|
+
throw error;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
console.log(
|
|
148
|
+
pc.green(` \u2713 ${t.detection.framework}: `) + pc.bold(`${ctx.framework} ${pc.gray(ctx.frameworkVersion)}`)
|
|
149
|
+
);
|
|
150
|
+
console.log(
|
|
151
|
+
pc.green(` \u2713 ${t.detection.typescript}: `) + pc.bold(ctx.typescript ? "Oui" : "Non")
|
|
152
|
+
);
|
|
153
|
+
if (ctx.bundler) {
|
|
154
|
+
console.log(
|
|
155
|
+
pc.green(` \u2713 ${t.detection.bundler}: `) + pc.bold(`${ctx.bundler} ${pc.gray(ctx.bundlerVersion || "")}`)
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
console.log(
|
|
159
|
+
pc.green(` \u2713 ${t.detection.packageManager}: `) + pc.bold(ctx.packageManager)
|
|
160
|
+
);
|
|
161
|
+
console.log();
|
|
162
|
+
let selectedPlugins = [];
|
|
163
|
+
if (options.yes) {
|
|
164
|
+
logger.info("Using default recommendations (--yes mode)");
|
|
165
|
+
} else {
|
|
166
|
+
selectedPlugins = await promptPluginSelection(
|
|
167
|
+
ctx,
|
|
168
|
+
pluginRegistry,
|
|
169
|
+
language
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
if (selectedPlugins.length === 0) {
|
|
173
|
+
console.log();
|
|
174
|
+
console.log(pc.yellow(`\u26A0\uFE0F ${t.common.selected(0)}`));
|
|
175
|
+
console.log(pc.gray("Exiting..."));
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
console.log();
|
|
179
|
+
console.log(
|
|
180
|
+
pc.bold(pc.green(`\u2713 ${t.common.selected(selectedPlugins.length)}`))
|
|
181
|
+
);
|
|
182
|
+
console.log();
|
|
183
|
+
if (!options.yes && !options.silent) {
|
|
184
|
+
const confirmed = await promptConfirmation(selectedPlugins, language);
|
|
185
|
+
if (!confirmed) {
|
|
186
|
+
console.log(t.common.cancel);
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
if (options.dryRun) {
|
|
191
|
+
console.log();
|
|
192
|
+
console.log(pc.bold(pc.yellow("\u2501".repeat(60))));
|
|
193
|
+
console.log(pc.bold(pc.yellow("\u{1F50D} MODE DRY-RUN (simulation uniquement)")));
|
|
194
|
+
console.log(pc.bold(pc.yellow("\u2501".repeat(60))));
|
|
195
|
+
console.log();
|
|
196
|
+
console.log(pc.bold(pc.cyan("\u{1F4E6} Packages \xE0 installer :")));
|
|
197
|
+
for (const plugin of selectedPlugins) {
|
|
198
|
+
console.log(
|
|
199
|
+
pc.blue(` \u2022 ${plugin.displayName}`) + pc.gray(
|
|
200
|
+
` (${plugin.name}${plugin.version ? `@${plugin.version}` : ""})`
|
|
201
|
+
)
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
console.log();
|
|
205
|
+
console.log(pc.bold(pc.cyan("\u{1F4DD} Fichiers qui seraient cr\xE9\xE9s/modifi\xE9s :")));
|
|
206
|
+
for (const plugin of selectedPlugins) {
|
|
207
|
+
console.log(pc.gray(` \u2022 ${plugin.displayName} configuration`));
|
|
208
|
+
}
|
|
209
|
+
console.log();
|
|
210
|
+
console.log(
|
|
211
|
+
pc.yellow("\u26A0\uFE0F Aucune modification n'a \xE9t\xE9 effectu\xE9e (dry-run)")
|
|
212
|
+
);
|
|
213
|
+
console.log(
|
|
214
|
+
pc.cyan("\u{1F4A1} Ex\xE9cutez sans --dry-run pour appliquer les changements")
|
|
215
|
+
);
|
|
216
|
+
console.log();
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
const backupManager = new BackupManager();
|
|
220
|
+
const configWriter = new ConfigWriter(backupManager);
|
|
221
|
+
const validator = new CompatibilityValidator(compatibilityRules);
|
|
222
|
+
const installer = new Installer(ctx, validator, configWriter, backupManager);
|
|
223
|
+
if (options.install === false) {
|
|
224
|
+
console.log();
|
|
225
|
+
console.log(pc.yellow("\u2699\uFE0F Mode configuration uniquement (--no-install)"));
|
|
226
|
+
console.log(pc.gray("Les packages ne seront PAS install\xE9s"));
|
|
227
|
+
console.log();
|
|
228
|
+
}
|
|
229
|
+
const spinner = new SpinnerManager();
|
|
230
|
+
spinner.start(t.installation.installing);
|
|
231
|
+
try {
|
|
232
|
+
const result = await installer.install(selectedPlugins, {
|
|
233
|
+
skipPackageInstall: options.install === false
|
|
234
|
+
});
|
|
235
|
+
spinner.succeed(t.installation.success);
|
|
236
|
+
if (result.success) {
|
|
237
|
+
displayInstallationReport(result, selectedPlugins, language);
|
|
238
|
+
} else {
|
|
239
|
+
console.error(`
|
|
240
|
+
${t.installation.error}`);
|
|
241
|
+
process.exit(1);
|
|
242
|
+
}
|
|
243
|
+
} catch (error) {
|
|
244
|
+
spinner.fail(t.installation.error);
|
|
245
|
+
throw error;
|
|
246
|
+
}
|
|
247
|
+
} catch (error) {
|
|
248
|
+
logger.error("Installation failed:", error);
|
|
249
|
+
if (error instanceof Error) {
|
|
250
|
+
console.error(`
|
|
251
|
+
\u274C ${error.message}`);
|
|
252
|
+
}
|
|
253
|
+
process.exit(1);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
export {
|
|
257
|
+
installReact
|
|
258
|
+
};
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Installer,
|
|
3
|
+
SpinnerManager,
|
|
4
|
+
displayInstallationReport,
|
|
5
|
+
getTranslations,
|
|
6
|
+
promptConfirmation,
|
|
7
|
+
promptLanguage,
|
|
8
|
+
promptPluginSelection
|
|
9
|
+
} from "./chunk-OAAGGK2H.js";
|
|
10
|
+
import {
|
|
11
|
+
CompatibilityValidator,
|
|
12
|
+
compatibilityRules
|
|
13
|
+
} from "./chunk-WKYUK64P.js";
|
|
14
|
+
import {
|
|
15
|
+
BackupManager,
|
|
16
|
+
ConfigWriter,
|
|
17
|
+
pluginRegistry
|
|
18
|
+
} from "./chunk-4VHPGJVU.js";
|
|
19
|
+
import {
|
|
20
|
+
DetectionError,
|
|
21
|
+
detectContext
|
|
22
|
+
} from "./chunk-BVXGN3AC.js";
|
|
23
|
+
import {
|
|
24
|
+
checkPathExists,
|
|
25
|
+
logger
|
|
26
|
+
} from "./chunk-QRFLHLFE.js";
|
|
27
|
+
import "./chunk-QGM4M3NI.js";
|
|
28
|
+
|
|
29
|
+
// src/cli/prompts/nextjs-setup.ts
|
|
30
|
+
import inquirer from "inquirer";
|
|
31
|
+
async function promptNextjsSetup(language) {
|
|
32
|
+
const t = getTranslations(language);
|
|
33
|
+
const answers = await inquirer.prompt([
|
|
34
|
+
{
|
|
35
|
+
type: "confirm",
|
|
36
|
+
name: "shouldCreate",
|
|
37
|
+
message: t.nextjs.proposeSetup,
|
|
38
|
+
default: true
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
type: "input",
|
|
42
|
+
name: "projectName",
|
|
43
|
+
message: t.nextjs.projectName,
|
|
44
|
+
default: t.nextjs.projectNamePlaceholder,
|
|
45
|
+
when: (answers2) => answers2.shouldCreate === true,
|
|
46
|
+
validate: (input) => {
|
|
47
|
+
if (!input || input.trim().length === 0) {
|
|
48
|
+
return t.nextjs.validation.empty;
|
|
49
|
+
}
|
|
50
|
+
if (!/^[a-z0-9-_]+$/i.test(input)) {
|
|
51
|
+
return t.nextjs.validation.invalid;
|
|
52
|
+
}
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
type: "confirm",
|
|
58
|
+
name: "typescript",
|
|
59
|
+
message: t.nextjs.typescript,
|
|
60
|
+
default: true,
|
|
61
|
+
when: (answers2) => answers2.shouldCreate === true
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
type: "confirm",
|
|
65
|
+
name: "eslint",
|
|
66
|
+
message: t.nextjs.eslint,
|
|
67
|
+
default: true,
|
|
68
|
+
when: (answers2) => answers2.shouldCreate === true
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
type: "confirm",
|
|
72
|
+
name: "tailwind",
|
|
73
|
+
message: t.nextjs.tailwind,
|
|
74
|
+
default: true,
|
|
75
|
+
when: (answers2) => answers2.shouldCreate === true
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
type: "confirm",
|
|
79
|
+
name: "srcDir",
|
|
80
|
+
message: t.nextjs.srcDir,
|
|
81
|
+
default: false,
|
|
82
|
+
when: (answers2) => answers2.shouldCreate === true
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
type: "confirm",
|
|
86
|
+
name: "appRouter",
|
|
87
|
+
message: t.nextjs.appRouter,
|
|
88
|
+
default: true,
|
|
89
|
+
when: (answers2) => answers2.shouldCreate === true
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
type: "input",
|
|
93
|
+
name: "importAlias",
|
|
94
|
+
message: t.nextjs.importAlias,
|
|
95
|
+
default: "@/*",
|
|
96
|
+
when: (answers2) => answers2.shouldCreate === true,
|
|
97
|
+
validate: (input) => {
|
|
98
|
+
if (!input || input.trim().length === 0) {
|
|
99
|
+
return "L'alias d'import ne peut pas \xEAtre vide";
|
|
100
|
+
}
|
|
101
|
+
if (!/^[@~]\/\*$/.test(input.trim())) {
|
|
102
|
+
return "L'alias doit \xEAtre au format @/* ou ~/*";
|
|
103
|
+
}
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
]);
|
|
108
|
+
if (!answers.shouldCreate) {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
projectName: answers.projectName.trim(),
|
|
113
|
+
typescript: answers.typescript,
|
|
114
|
+
eslint: answers.eslint,
|
|
115
|
+
tailwind: answers.tailwind,
|
|
116
|
+
srcDir: answers.srcDir,
|
|
117
|
+
appRouter: answers.appRouter,
|
|
118
|
+
importAlias: answers.importAlias.trim()
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// src/cli/utils/nextjs-installer.ts
|
|
123
|
+
import { resolve } from "path";
|
|
124
|
+
import { execa } from "execa";
|
|
125
|
+
async function createNextjsProject(options, currentDir, language) {
|
|
126
|
+
const t = getTranslations(language);
|
|
127
|
+
const {
|
|
128
|
+
projectName,
|
|
129
|
+
typescript,
|
|
130
|
+
eslint,
|
|
131
|
+
tailwind,
|
|
132
|
+
srcDir,
|
|
133
|
+
appRouter,
|
|
134
|
+
importAlias
|
|
135
|
+
} = options;
|
|
136
|
+
const projectPath = resolve(currentDir, projectName);
|
|
137
|
+
if (await checkPathExists(projectPath)) {
|
|
138
|
+
throw new Error(t.nextjs.folderExists(projectName));
|
|
139
|
+
}
|
|
140
|
+
logger.info(t.nextjs.creating);
|
|
141
|
+
try {
|
|
142
|
+
const args = ["create", "next-app@latest", projectName];
|
|
143
|
+
if (typescript) {
|
|
144
|
+
args.push("--typescript");
|
|
145
|
+
} else {
|
|
146
|
+
args.push("--javascript");
|
|
147
|
+
}
|
|
148
|
+
if (eslint) {
|
|
149
|
+
args.push("--eslint");
|
|
150
|
+
} else {
|
|
151
|
+
args.push("--no-eslint");
|
|
152
|
+
}
|
|
153
|
+
if (tailwind) {
|
|
154
|
+
args.push("--tailwind");
|
|
155
|
+
} else {
|
|
156
|
+
args.push("--no-tailwind");
|
|
157
|
+
}
|
|
158
|
+
if (srcDir) {
|
|
159
|
+
args.push("--src-dir");
|
|
160
|
+
} else {
|
|
161
|
+
args.push("--no-src-dir");
|
|
162
|
+
}
|
|
163
|
+
if (appRouter) {
|
|
164
|
+
args.push("--app");
|
|
165
|
+
} else {
|
|
166
|
+
args.push("--pages");
|
|
167
|
+
}
|
|
168
|
+
args.push("--import-alias", importAlias);
|
|
169
|
+
const result = await execa("npm", args, {
|
|
170
|
+
cwd: currentDir,
|
|
171
|
+
stdio: "inherit",
|
|
172
|
+
env: {
|
|
173
|
+
...process.env,
|
|
174
|
+
// Désactiver les prompts interactifs de create-next-app
|
|
175
|
+
npm_config_yes: "true"
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
if (result.exitCode !== 0) {
|
|
179
|
+
throw new Error(`${t.nextjs.error}: exit code ${result.exitCode}`);
|
|
180
|
+
}
|
|
181
|
+
logger.success(t.nextjs.success);
|
|
182
|
+
logger.info(t.nextjs.changingDirectory);
|
|
183
|
+
return projectPath;
|
|
184
|
+
} catch (error) {
|
|
185
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
186
|
+
logger.error(`${t.nextjs.error}: ${errorMessage}`);
|
|
187
|
+
throw error;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// src/cli/commands/install-nextjs.ts
|
|
192
|
+
import pc from "picocolors";
|
|
193
|
+
async function installNextjs(options) {
|
|
194
|
+
try {
|
|
195
|
+
const language = await promptLanguage();
|
|
196
|
+
const t = getTranslations(language);
|
|
197
|
+
console.log();
|
|
198
|
+
console.log(pc.bold(pc.cyan(`\u{1F50D} ${t.detection.detecting}`)));
|
|
199
|
+
let projectRoot = process.cwd();
|
|
200
|
+
let ctx;
|
|
201
|
+
try {
|
|
202
|
+
ctx = await detectContext(projectRoot);
|
|
203
|
+
} catch (error) {
|
|
204
|
+
if (error instanceof DetectionError) {
|
|
205
|
+
console.log();
|
|
206
|
+
console.log(pc.yellow(t.nextjs.noNextjsDetected));
|
|
207
|
+
console.log();
|
|
208
|
+
const nextjsOptions = await promptNextjsSetup(language);
|
|
209
|
+
if (!nextjsOptions) {
|
|
210
|
+
console.log();
|
|
211
|
+
console.log(pc.gray(t.common.cancel));
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
const newProjectPath = await createNextjsProject(
|
|
215
|
+
nextjsOptions,
|
|
216
|
+
projectRoot,
|
|
217
|
+
language
|
|
218
|
+
);
|
|
219
|
+
process.chdir(newProjectPath);
|
|
220
|
+
projectRoot = newProjectPath;
|
|
221
|
+
console.log();
|
|
222
|
+
ctx = await detectContext(projectRoot);
|
|
223
|
+
} else {
|
|
224
|
+
throw error;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
if (ctx.framework !== "nextjs") {
|
|
228
|
+
console.log();
|
|
229
|
+
console.log(
|
|
230
|
+
pc.yellow(
|
|
231
|
+
`\u26A0\uFE0F Framework d\xE9tect\xE9: ${ctx.framework}. Cette commande est destin\xE9e aux projets Next.js.`
|
|
232
|
+
)
|
|
233
|
+
);
|
|
234
|
+
console.log(
|
|
235
|
+
pc.gray(
|
|
236
|
+
'Utilisez "npx @configjs/cli react" pour les projets React standard.'
|
|
237
|
+
)
|
|
238
|
+
);
|
|
239
|
+
console.log();
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
console.log(
|
|
243
|
+
pc.green(` \u2713 ${t.detection.framework}: `) + pc.bold(`${ctx.framework} ${pc.gray(ctx.frameworkVersion)}`)
|
|
244
|
+
);
|
|
245
|
+
console.log(
|
|
246
|
+
pc.green(` \u2713 ${t.detection.typescript}: `) + pc.bold(ctx.typescript ? "Oui" : "Non")
|
|
247
|
+
);
|
|
248
|
+
if (ctx.bundler) {
|
|
249
|
+
console.log(
|
|
250
|
+
pc.green(` \u2713 ${t.detection.bundler}: `) + pc.bold(`${ctx.bundler} ${pc.gray(ctx.bundlerVersion || "")}`)
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
console.log(
|
|
254
|
+
pc.green(` \u2713 ${t.detection.packageManager}: `) + pc.bold(ctx.packageManager)
|
|
255
|
+
);
|
|
256
|
+
console.log();
|
|
257
|
+
let selectedPlugins = [];
|
|
258
|
+
if (options.yes) {
|
|
259
|
+
logger.info("Using default recommendations (--yes mode)");
|
|
260
|
+
} else {
|
|
261
|
+
selectedPlugins = await promptPluginSelection(
|
|
262
|
+
ctx,
|
|
263
|
+
pluginRegistry,
|
|
264
|
+
language
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
if (selectedPlugins.length === 0) {
|
|
268
|
+
console.log();
|
|
269
|
+
console.log(pc.yellow(`\u26A0\uFE0F ${t.common.selected(0)}`));
|
|
270
|
+
console.log(pc.gray("Exiting..."));
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
console.log();
|
|
274
|
+
console.log(
|
|
275
|
+
pc.bold(pc.green(`\u2713 ${t.common.selected(selectedPlugins.length)}`))
|
|
276
|
+
);
|
|
277
|
+
console.log();
|
|
278
|
+
if (!options.yes && !options.silent) {
|
|
279
|
+
const confirmed = await promptConfirmation(selectedPlugins, language);
|
|
280
|
+
if (!confirmed) {
|
|
281
|
+
console.log(t.common.cancel);
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
if (options.dryRun) {
|
|
286
|
+
console.log();
|
|
287
|
+
console.log(pc.bold(pc.yellow("\u2501".repeat(60))));
|
|
288
|
+
console.log(pc.bold(pc.yellow("\u{1F50D} MODE DRY-RUN (simulation uniquement)")));
|
|
289
|
+
console.log(pc.bold(pc.yellow("\u2501".repeat(60))));
|
|
290
|
+
console.log();
|
|
291
|
+
console.log(pc.bold(pc.cyan("\u{1F4E6} Packages \xE0 installer :")));
|
|
292
|
+
for (const plugin of selectedPlugins) {
|
|
293
|
+
console.log(
|
|
294
|
+
pc.blue(` \u2022 ${plugin.displayName}`) + pc.gray(
|
|
295
|
+
` (${plugin.name}${plugin.version ? `@${plugin.version}` : ""})`
|
|
296
|
+
)
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
console.log();
|
|
300
|
+
console.log(pc.bold(pc.cyan("\u{1F4DD} Fichiers qui seraient cr\xE9\xE9s/modifi\xE9s :")));
|
|
301
|
+
for (const plugin of selectedPlugins) {
|
|
302
|
+
console.log(pc.gray(` \u2022 ${plugin.displayName} configuration`));
|
|
303
|
+
}
|
|
304
|
+
console.log();
|
|
305
|
+
console.log(
|
|
306
|
+
pc.yellow("\u26A0\uFE0F Aucune modification n'a \xE9t\xE9 effectu\xE9e (dry-run)")
|
|
307
|
+
);
|
|
308
|
+
console.log(
|
|
309
|
+
pc.cyan("\u{1F4A1} Ex\xE9cutez sans --dry-run pour appliquer les changements")
|
|
310
|
+
);
|
|
311
|
+
console.log();
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
const backupManager = new BackupManager();
|
|
315
|
+
const configWriter = new ConfigWriter(backupManager);
|
|
316
|
+
const validator = new CompatibilityValidator(compatibilityRules);
|
|
317
|
+
const installer = new Installer(ctx, validator, configWriter, backupManager);
|
|
318
|
+
if (options.install === false) {
|
|
319
|
+
console.log();
|
|
320
|
+
console.log(pc.yellow("\u2699\uFE0F Mode configuration uniquement (--no-install)"));
|
|
321
|
+
console.log(pc.gray("Les packages ne seront PAS install\xE9s"));
|
|
322
|
+
console.log();
|
|
323
|
+
}
|
|
324
|
+
const spinner = new SpinnerManager();
|
|
325
|
+
spinner.start(t.installation.installing);
|
|
326
|
+
try {
|
|
327
|
+
const result = await installer.install(selectedPlugins, {
|
|
328
|
+
skipPackageInstall: options.install === false
|
|
329
|
+
});
|
|
330
|
+
spinner.succeed(t.installation.success);
|
|
331
|
+
if (result.success) {
|
|
332
|
+
displayInstallationReport(result, selectedPlugins, language);
|
|
333
|
+
} else {
|
|
334
|
+
console.error(`
|
|
335
|
+
${t.installation.error}`);
|
|
336
|
+
process.exit(1);
|
|
337
|
+
}
|
|
338
|
+
} catch (error) {
|
|
339
|
+
spinner.fail(t.installation.error);
|
|
340
|
+
throw error;
|
|
341
|
+
}
|
|
342
|
+
} catch (error) {
|
|
343
|
+
logger.error("Installation failed:", error);
|
|
344
|
+
if (error instanceof Error) {
|
|
345
|
+
console.error(`
|
|
346
|
+
\u274C ${error.message}`);
|
|
347
|
+
}
|
|
348
|
+
process.exit(1);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
export {
|
|
352
|
+
installNextjs
|
|
353
|
+
};
|