@configjs/cli 1.1.4 → 1.1.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.
@@ -1,329 +1,131 @@
1
1
  import {
2
- getPluginsByCategory
3
- } from "./chunk-4VHPGJVU.js";
2
+ CompatibilityValidator,
3
+ allCompatibilityRules
4
+ } from "./chunk-D37FHAGO.js";
5
+ import {
6
+ BackupManager,
7
+ ConfigWriter,
8
+ getPluginsByCategory,
9
+ pluginRegistry
10
+ } from "./chunk-V75HW2AM.js";
4
11
  import {
5
12
  PluginTracker
6
- } from "./chunk-BVXGN3AC.js";
13
+ } from "./chunk-TVZWTKJU.js";
14
+ import {
15
+ installPackages
16
+ } from "./chunk-MQV3WNMH.js";
7
17
  import {
8
- installPackages,
9
18
  logger
10
- } from "./chunk-QRFLHLFE.js";
19
+ } from "./chunk-HM2JWJOO.js";
20
+ import {
21
+ getTranslations
22
+ } from "./chunk-3V72QFFY.js";
11
23
 
12
- // src/cli/i18n/fr.ts
13
- var fr = {
14
- language: {
15
- select: "Choisissez votre langue",
16
- options: [
17
- { value: "fr", name: "Fran\xE7ais" },
18
- { value: "en", name: "English" },
19
- { value: "es", name: "Espa\xF1ol" }
20
- ]
21
- },
22
- common: {
23
- continue: "Continuer",
24
- cancel: "Annuler",
25
- back: "Retour",
26
- none: "Aucun",
27
- selected: (count) => count === 0 ? "Aucune biblioth\xE8que s\xE9lectionn\xE9e" : count === 1 ? "1 biblioth\xE8que s\xE9lectionn\xE9e" : `${count} biblioth\xE8ques s\xE9lectionn\xE9es`
28
- },
29
- plugins: {
30
- selectCategory: (category) => `S\xE9lectionnez vos biblioth\xE8ques : ${category}`,
31
- selectMultiple: "S\xE9lection multiple",
32
- pressSpace: "Appuyez sur <espace> pour s\xE9lectionner",
33
- pressEnter: "Appuyez sur <entr\xE9e> pour valider",
34
- description: "Description"
35
- },
36
- detection: {
37
- detecting: "\u{1F50D} D\xE9tection du contexte...",
38
- framework: "Framework",
39
- typescript: "TypeScript",
40
- bundler: "Bundler",
41
- packageManager: "Gestionnaire de paquets"
42
- },
43
- confirmation: {
44
- summary: "\u{1F4CB} R\xE9sum\xE9 de l'installation",
45
- packagesToInstall: "\u{1F4E6} Packages \xE0 installer",
46
- filesToCreate: "\u{1F4DD} Fichiers qui seront cr\xE9\xE9s",
47
- filesToModify: "\u{1F4DD} Fichiers qui seront modifi\xE9s",
48
- continueQuestion: "Continuer avec l'installation ?"
49
- },
50
- installation: {
51
- installing: "Installation en cours...",
52
- configuring: "Configuration en cours...",
53
- success: "\u2728 Installation termin\xE9e !",
54
- error: "\u274C Erreur lors de l'installation",
55
- rollback: "\u21BA Rollback en cours..."
56
- },
57
- report: {
58
- title: "\u2728 Installation termin\xE9e !",
59
- packagesInstalled: "\u{1F4E6} Packages install\xE9s",
60
- filesCreated: "\u{1F4DD} Fichiers cr\xE9\xE9s",
61
- filesModified: "\u{1F4DD} Fichiers modifi\xE9s",
62
- nextSteps: "\u{1F680} Prochaines \xE9tapes"
63
- },
64
- errors: {
65
- detectionFailed: "\xC9chec de la d\xE9tection du contexte",
66
- installationFailed: "\xC9chec de l'installation",
67
- validationFailed: "\xC9chec de la validation",
68
- incompatiblePlugins: (plugins) => `Plugins incompatibles d\xE9tect\xE9s : ${plugins.join(", ")}`
69
- },
70
- vite: {
71
- noReactDetected: "\u26A0\uFE0F Aucun projet React d\xE9tect\xE9 dans le r\xE9pertoire actuel.",
72
- proposeSetup: "Souhaitez-vous cr\xE9er un nouveau projet React avec Vite ?",
73
- projectName: "Nom du projet",
74
- projectNamePlaceholder: "mon-projet-react",
75
- template: "Template",
76
- templateOptions: [
77
- { value: "react", name: "React (JavaScript)" },
78
- { value: "react-ts", name: "React (TypeScript)" }
79
- ],
80
- creating: "Cr\xE9ation du projet React avec Vite...",
81
- success: "\u2705 Projet cr\xE9\xE9 avec succ\xE8s !",
82
- error: "\u274C Erreur lors de la cr\xE9ation du projet",
83
- changingDirectory: "Changement vers le r\xE9pertoire du projet...",
84
- validation: {
85
- empty: "Le nom du projet ne peut pas \xEAtre vide",
86
- invalid: "Le nom du projet ne peut contenir que des lettres, chiffres, tirets et underscores"
24
+ // src/core/framework-registry.ts
25
+ var frameworkRegistry = {
26
+ react: {
27
+ id: "react",
28
+ displayName: "React",
29
+ detectPackages: ["react", "react-dom"],
30
+ defaultBundler: "vite",
31
+ createCommand: "npm create vite@latest",
32
+ templates: {
33
+ js: "react",
34
+ ts: "react-ts"
87
35
  },
88
- folderExists: (name) => `Le dossier "${name}" existe d\xE9j\xE0. Veuillez choisir un autre nom.`
89
- },
90
- nextjs: {
91
- noNextjsDetected: "\u26A0\uFE0F Aucun projet Next.js d\xE9tect\xE9 dans le r\xE9pertoire actuel.",
92
- proposeSetup: "Souhaitez-vous cr\xE9er un nouveau projet Next.js ?",
93
- projectName: "Nom du projet",
94
- projectNamePlaceholder: "mon-projet-nextjs",
95
- typescript: "Utiliser TypeScript ?",
96
- eslint: "Utiliser ESLint ?",
97
- tailwind: "Utiliser TailwindCSS ?",
98
- srcDir: "Utiliser le dossier src/ ?",
99
- appRouter: "Utiliser App Router (recommand\xE9) ?",
100
- importAlias: "Alias d'import (ex: @/*)",
101
- creating: "Cr\xE9ation du projet Next.js...",
102
- success: "\u2705 Projet cr\xE9\xE9 avec succ\xE8s !",
103
- error: "\u274C Erreur lors de la cr\xE9ation du projet",
104
- changingDirectory: "Changement vers le r\xE9pertoire du projet...",
105
- validation: {
106
- empty: "Le nom du projet ne peut pas \xEAtre vide",
107
- invalid: "Le nom du projet ne peut contenir que des lettres, chiffres, tirets et underscores"
36
+ getSetupPrompt: async (language) => {
37
+ const { promptViteSetup } = await import("./vite-setup-3U22LJFG.js");
38
+ return await promptViteSetup(language);
108
39
  },
109
- folderExists: (name) => `Le dossier "${name}" existe d\xE9j\xE0. Veuillez choisir un autre nom.`
110
- }
111
- };
112
-
113
- // src/cli/i18n/en.ts
114
- var en = {
115
- language: {
116
- select: "Choose your language",
117
- options: [
118
- { value: "fr", name: "Fran\xE7ais" },
119
- { value: "en", name: "English" },
120
- { value: "es", name: "Espa\xF1ol" }
121
- ]
122
- },
123
- common: {
124
- continue: "Continue",
125
- cancel: "Cancel",
126
- back: "Back",
127
- none: "None",
128
- selected: (count) => count === 0 ? "No library selected" : count === 1 ? "1 library selected" : `${count} libraries selected`
129
- },
130
- plugins: {
131
- selectCategory: (category) => `Select your libraries: ${category}`,
132
- selectMultiple: "Multiple selection",
133
- pressSpace: "Press <space> to select",
134
- pressEnter: "Press <enter> to confirm",
135
- description: "Description"
136
- },
137
- detection: {
138
- detecting: "\u{1F50D} Detecting context...",
139
- framework: "Framework",
140
- typescript: "TypeScript",
141
- bundler: "Bundler",
142
- packageManager: "Package manager"
143
- },
144
- confirmation: {
145
- summary: "\u{1F4CB} Installation Summary",
146
- packagesToInstall: "\u{1F4E6} Packages to install",
147
- filesToCreate: "\u{1F4DD} Files that will be created",
148
- filesToModify: "\u{1F4DD} Files that will be modified",
149
- continueQuestion: "Continue with installation?"
150
- },
151
- installation: {
152
- installing: "Installing...",
153
- configuring: "Configuring...",
154
- success: "\u2728 Installation completed!",
155
- error: "\u274C Installation error",
156
- rollback: "\u21BA Rolling back..."
157
- },
158
- report: {
159
- title: "\u2728 Installation completed!",
160
- packagesInstalled: "\u{1F4E6} Installed packages",
161
- filesCreated: "\u{1F4DD} Created files",
162
- filesModified: "\u{1F4DD} Modified files",
163
- nextSteps: "\u{1F680} Next steps"
164
- },
165
- errors: {
166
- detectionFailed: "Context detection failed",
167
- installationFailed: "Installation failed",
168
- validationFailed: "Validation failed",
169
- incompatiblePlugins: (plugins) => `Incompatible plugins detected: ${plugins.join(", ")}`
170
- },
171
- vite: {
172
- noReactDetected: "\u26A0\uFE0F No React project detected in the current directory.",
173
- proposeSetup: "Would you like to create a new React project with Vite?",
174
- projectName: "Project name",
175
- projectNamePlaceholder: "my-react-project",
176
- template: "Template",
177
- templateOptions: [
178
- { value: "react", name: "React (JavaScript)" },
179
- { value: "react-ts", name: "React (TypeScript)" }
180
- ],
181
- creating: "Creating React project with Vite...",
182
- success: "\u2705 Project created successfully!",
183
- error: "\u274C Error creating project",
184
- changingDirectory: "Changing to project directory...",
185
- validation: {
186
- empty: "Project name cannot be empty",
187
- invalid: "Project name can only contain letters, numbers, dashes and underscores"
40
+ createProject: async (options, currentDir, language) => {
41
+ const { createViteProject } = await import("./vite-installer-XIJFJ4CN.js");
42
+ return await createViteProject(
43
+ options,
44
+ currentDir,
45
+ language
46
+ );
188
47
  },
189
- folderExists: (name) => `Folder "${name}" already exists. Please choose another name.`
48
+ i18nKeys: {
49
+ noFrameworkDetected: "vite.noReactDetected",
50
+ creating: "vite.creating",
51
+ folderExists: (name) => `vite.folderExists(${name})`
52
+ }
190
53
  },
191
54
  nextjs: {
192
- noNextjsDetected: "\u26A0\uFE0F No Next.js project detected in the current directory.",
193
- proposeSetup: "Would you like to create a new Next.js project?",
194
- projectName: "Project name",
195
- projectNamePlaceholder: "my-nextjs-project",
196
- typescript: "Use TypeScript?",
197
- eslint: "Use ESLint?",
198
- tailwind: "Use TailwindCSS?",
199
- srcDir: "Use src/ directory?",
200
- appRouter: "Use App Router (recommended)?",
201
- importAlias: "Import alias (e.g. @/*)",
202
- creating: "Creating Next.js project...",
203
- success: "\u2705 Project created successfully!",
204
- error: "\u274C Error creating project",
205
- changingDirectory: "Changing to project directory...",
206
- validation: {
207
- empty: "Project name cannot be empty",
208
- invalid: "Project name can only contain letters, numbers, dashes and underscores"
55
+ id: "nextjs",
56
+ displayName: "Next.js",
57
+ detectPackages: ["next"],
58
+ defaultBundler: "nextjs",
59
+ createCommand: "npm create next-app@latest",
60
+ getSetupPrompt: async (language) => {
61
+ const { promptNextjsSetup } = await import("./nextjs-setup-7LWMEC5I.js");
62
+ return await promptNextjsSetup(language);
209
63
  },
210
- folderExists: (name) => `Folder "${name}" already exists. Please choose another name.`
211
- }
212
- };
213
-
214
- // src/cli/i18n/es.ts
215
- var es = {
216
- language: {
217
- select: "Elige tu idioma",
218
- options: [
219
- { value: "fr", name: "Fran\xE7ais" },
220
- { value: "en", name: "English" },
221
- { value: "es", name: "Espa\xF1ol" }
222
- ]
223
- },
224
- common: {
225
- continue: "Continuar",
226
- cancel: "Cancelar",
227
- back: "Volver",
228
- none: "Ninguno",
229
- selected: (count) => count === 0 ? "Ninguna biblioteca seleccionada" : count === 1 ? "1 biblioteca seleccionada" : `${count} bibliotecas seleccionadas`
230
- },
231
- plugins: {
232
- selectCategory: (category) => `Selecciona tus bibliotecas: ${category}`,
233
- selectMultiple: "Selecci\xF3n m\xFAltiple",
234
- pressSpace: "Presiona <espacio> para seleccionar",
235
- pressEnter: "Presiona <entrar> para confirmar",
236
- description: "Descripci\xF3n"
237
- },
238
- detection: {
239
- detecting: "\u{1F50D} Detectando contexto...",
240
- framework: "Framework",
241
- typescript: "TypeScript",
242
- bundler: "Bundler",
243
- packageManager: "Gestor de paquetes"
244
- },
245
- confirmation: {
246
- summary: "\u{1F4CB} Resumen de la instalaci\xF3n",
247
- packagesToInstall: "\u{1F4E6} Paquetes a instalar",
248
- filesToCreate: "\u{1F4DD} Archivos que se crear\xE1n",
249
- filesToModify: "\u{1F4DD} Archivos que se modificar\xE1n",
250
- continueQuestion: "\xBFContinuar con la instalaci\xF3n?"
251
- },
252
- installation: {
253
- installing: "Instalando...",
254
- configuring: "Configurando...",
255
- success: "\u2728 \xA1Instalaci\xF3n completada!",
256
- error: "\u274C Error en la instalaci\xF3n",
257
- rollback: "\u21BA Revirtiendo..."
258
- },
259
- report: {
260
- title: "\u2728 \xA1Instalaci\xF3n completada!",
261
- packagesInstalled: "\u{1F4E6} Paquetes instalados",
262
- filesCreated: "\u{1F4DD} Archivos creados",
263
- filesModified: "\u{1F4DD} Archivos modificados",
264
- nextSteps: "\u{1F680} Pr\xF3ximos pasos"
265
- },
266
- errors: {
267
- detectionFailed: "Fallo en la detecci\xF3n del contexto",
268
- installationFailed: "Fallo en la instalaci\xF3n",
269
- validationFailed: "Fallo en la validaci\xF3n",
270
- incompatiblePlugins: (plugins) => `Plugins incompatibles detectados: ${plugins.join(", ")}`
64
+ createProject: async (options, currentDir, language) => {
65
+ const { createNextjsProject } = await import("./nextjs-installer-RWBGWW23.js");
66
+ return await createNextjsProject(
67
+ options,
68
+ currentDir,
69
+ language
70
+ );
71
+ },
72
+ i18nKeys: {
73
+ noFrameworkDetected: "nextjs.noNextjsDetected",
74
+ creating: "nextjs.creating",
75
+ folderExists: (name) => `nextjs.folderExists(${name})`
76
+ }
271
77
  },
272
- vite: {
273
- noReactDetected: "\u26A0\uFE0F No se detect\xF3 ning\xFAn proyecto React en el directorio actual.",
274
- proposeSetup: "\xBFDesea crear un nuevo proyecto React con Vite?",
275
- projectName: "Nombre del proyecto",
276
- projectNamePlaceholder: "mi-proyecto-react",
277
- template: "Plantilla",
278
- templateOptions: [
279
- { value: "react", name: "React (JavaScript)" },
280
- { value: "react-ts", name: "React (TypeScript)" }
281
- ],
282
- creating: "Creando proyecto React con Vite...",
283
- success: "\u2705 \xA1Proyecto creado con \xE9xito!",
284
- error: "\u274C Error al crear el proyecto",
285
- changingDirectory: "Cambiando al directorio del proyecto...",
286
- validation: {
287
- empty: "El nombre del proyecto no puede estar vac\xEDo",
288
- invalid: "El nombre del proyecto solo puede contener letras, n\xFAmeros, guiones y guiones bajos"
78
+ vue: {
79
+ id: "vue",
80
+ displayName: "Vue.js",
81
+ detectPackages: ["vue"],
82
+ defaultBundler: "vite",
83
+ createCommand: "npm create vite@latest",
84
+ templates: {
85
+ js: "vue",
86
+ ts: "vue-ts"
87
+ },
88
+ getSetupPrompt: async (language) => {
89
+ const { promptVueSetup } = await import("./vue-setup-X65P3CZX.js");
90
+ return await promptVueSetup(language);
91
+ },
92
+ createProject: async (options, currentDir, language) => {
93
+ const { createVueProject } = await import("./vue-installer-SFROF4N3.js");
94
+ return await createVueProject(
95
+ options,
96
+ currentDir,
97
+ language
98
+ );
289
99
  },
290
- folderExists: (name) => `La carpeta "${name}" ya existe. Por favor, elija otro nombre.`
100
+ i18nKeys: {
101
+ noFrameworkDetected: "vue.noVueDetected",
102
+ creating: "vue.creating",
103
+ folderExists: (name) => `vue.folderExists(${name})`
104
+ }
291
105
  },
292
- nextjs: {
293
- noNextjsDetected: "\u26A0\uFE0F No se detect\xF3 ning\xFAn proyecto Next.js en el directorio actual.",
294
- proposeSetup: "\xBFDesea crear un nuevo proyecto Next.js?",
295
- projectName: "Nombre del proyecto",
296
- projectNamePlaceholder: "mi-proyecto-nextjs",
297
- typescript: "\xBFUsar TypeScript?",
298
- eslint: "\xBFUsar ESLint?",
299
- tailwind: "\xBFUsar TailwindCSS?",
300
- srcDir: "\xBFUsar directorio src/?",
301
- appRouter: "\xBFUsar App Router (recomendado)?",
302
- importAlias: "Alias de importaci\xF3n (ej: @/*)",
303
- creating: "Creando proyecto Next.js...",
304
- success: "\u2705 \xA1Proyecto creado con \xE9xito!",
305
- error: "\u274C Error al crear el proyecto",
306
- changingDirectory: "Cambiando al directorio del proyecto...",
307
- validation: {
308
- empty: "El nombre del proyecto no puede estar vac\xEDo",
309
- invalid: "El nombre del proyecto solo puede contener letras, n\xFAmeros, guiones y guiones bajos"
106
+ svelte: {
107
+ id: "svelte",
108
+ displayName: "Svelte",
109
+ detectPackages: ["svelte", "@sveltejs/kit"],
110
+ defaultBundler: "vite",
111
+ createCommand: "npm create svelte@latest",
112
+ getSetupPrompt: async (_language) => {
113
+ return await Promise.resolve(null);
114
+ },
115
+ createProject: async (_options, _currentDir, _language) => {
116
+ return await Promise.reject(
117
+ new Error("Svelte project creation not yet implemented")
118
+ );
310
119
  },
311
- folderExists: (name) => `La carpeta "${name}" ya existe. Por favor, elija otro nombre.`
120
+ i18nKeys: {
121
+ noFrameworkDetected: "svelte.noSvelteDetected",
122
+ creating: "svelte.creating",
123
+ folderExists: (name) => `svelte.folderExists(${name})`
124
+ }
312
125
  }
313
126
  };
314
-
315
- // src/cli/i18n/index.ts
316
- function getTranslations(lang) {
317
- switch (lang) {
318
- case "fr":
319
- return fr;
320
- case "en":
321
- return en;
322
- case "es":
323
- return es;
324
- default:
325
- return en;
326
- }
127
+ function getFrameworkMetadata(framework) {
128
+ return frameworkRegistry[framework];
327
129
  }
328
130
 
329
131
  // src/cli/prompts/language.ts
@@ -382,6 +184,15 @@ async function promptPluginSelection(ctx, availablePlugins, lang) {
382
184
  if (ctx.framework === "nextjs" && plugin.name === "react-router-dom") {
383
185
  continue;
384
186
  }
187
+ if (ctx.framework === "vue" && plugin.name === "react-router-dom") {
188
+ continue;
189
+ }
190
+ if (ctx.framework === "vue" && (plugin.name === "zustand" || plugin.name === "@reduxjs/toolkit" || plugin.name === "jotai")) {
191
+ continue;
192
+ }
193
+ if (ctx.framework === "vue" && plugin.name === "shadcn-ui") {
194
+ continue;
195
+ }
385
196
  if (plugin.requiresTypeScript === true && !ctx.typescript) {
386
197
  continue;
387
198
  }
@@ -469,13 +280,14 @@ var Installer = class {
469
280
  * @param validator - Validateur de compatibilité
470
281
  * @param writer - Writer de configuration
471
282
  * @param backupManager - Gestionnaire de backups
283
+ * @param fs - Système de fichiers optionnel (par défaut: filesystem réel via memfs.useAsNodeFs)
472
284
  */
473
- constructor(ctx, validator, writer, backupManager) {
285
+ constructor(ctx, validator, writer, backupManager, _fs) {
474
286
  this.ctx = ctx;
475
287
  this.validator = validator;
476
288
  this.writer = writer;
477
289
  this.backupManager = backupManager;
478
- this.tracker = new PluginTracker(ctx.projectRoot);
290
+ this.tracker = new PluginTracker(ctx.projectRoot, ctx.fsAdapter);
479
291
  }
480
292
  tracker;
481
293
  /**
@@ -995,12 +807,244 @@ function displayNextSteps(lang) {
995
807
  console.log();
996
808
  }
997
809
 
810
+ // src/cli/commands/base-framework-command.ts
811
+ import pc2 from "picocolors";
812
+ var BaseFrameworkCommand = class {
813
+ /**
814
+ * Affiche les informations spécifiques du contexte détecté
815
+ *
816
+ * Permet d'afficher des informations spécifiques au framework
817
+ * (ex: Vue version, Next.js router type, etc.)
818
+ *
819
+ * @param _ctx - Contexte du projet
820
+ * @param _t - Traductions
821
+ */
822
+ displayFrameworkSpecificInfo(_ctx, _t) {
823
+ }
824
+ /**
825
+ * Vérifie que le framework détecté correspond au framework attendu
826
+ *
827
+ * @param ctx - Contexte du projet
828
+ * @returns true si le framework correspond
829
+ */
830
+ validateFramework(ctx) {
831
+ return ctx.framework === this.getFramework();
832
+ }
833
+ /**
834
+ * Affiche un message d'avertissement si le framework ne correspond pas
835
+ *
836
+ * @param ctx - Contexte du projet
837
+ * @param _t - Traductions
838
+ */
839
+ displayFrameworkMismatchWarning(ctx, _t) {
840
+ const framework = this.getFramework();
841
+ const metadata = getFrameworkMetadata(framework);
842
+ console.log();
843
+ console.log(
844
+ pc2.yellow(
845
+ `\u26A0\uFE0F Framework d\xE9tect\xE9: ${ctx.framework}. Cette commande est destin\xE9e aux projets ${metadata?.displayName || framework}.`
846
+ )
847
+ );
848
+ console.log(
849
+ pc2.gray(
850
+ `Utilisez "npx @configjs/cli ${ctx.framework}" pour les projets ${ctx.framework}.`
851
+ )
852
+ );
853
+ console.log();
854
+ }
855
+ /**
856
+ * Affiche le contexte détecté
857
+ *
858
+ * @param ctx - Contexte du projet
859
+ * @param t - Traductions
860
+ */
861
+ displayDetectedContext(ctx, t) {
862
+ console.log(
863
+ pc2.green(` \u2713 ${t.detection.framework}: `) + pc2.bold(`${ctx.framework} ${pc2.gray(ctx.frameworkVersion)}`)
864
+ );
865
+ console.log(
866
+ pc2.green(` \u2713 ${t.detection.typescript}: `) + pc2.bold(ctx.typescript ? "Oui" : "Non")
867
+ );
868
+ if (ctx.bundler) {
869
+ console.log(
870
+ pc2.green(` \u2713 ${t.detection.bundler}: `) + pc2.bold(`${ctx.bundler} ${pc2.gray(ctx.bundlerVersion || "")}`)
871
+ );
872
+ }
873
+ console.log(
874
+ pc2.green(` \u2713 ${t.detection.packageManager}: `) + pc2.bold(ctx.packageManager)
875
+ );
876
+ this.displayFrameworkSpecificInfo(ctx, t);
877
+ console.log();
878
+ }
879
+ /**
880
+ * Sélectionne les plugins à installer
881
+ *
882
+ * @param ctx - Contexte du projet
883
+ * @param language - Langue sélectionnée
884
+ * @param options - Options CLI
885
+ * @returns Liste des plugins sélectionnés
886
+ */
887
+ async selectPlugins(ctx, language, options) {
888
+ if (options.yes) {
889
+ logger.info("Using default recommendations (--yes mode)");
890
+ return [];
891
+ }
892
+ return promptPluginSelection(ctx, pluginRegistry, language);
893
+ }
894
+ /**
895
+ * Demande confirmation avant installation
896
+ *
897
+ * @param selectedPlugins - Plugins sélectionnés
898
+ * @param language - Langue sélectionnée
899
+ * @param options - Options CLI
900
+ * @returns true si l'utilisateur confirme
901
+ */
902
+ async confirmInstallation(selectedPlugins, language, options) {
903
+ if (options.yes || options.silent) {
904
+ return true;
905
+ }
906
+ return promptConfirmation(selectedPlugins, language);
907
+ }
908
+ /**
909
+ * Gère le mode dry-run
910
+ *
911
+ * @param selectedPlugins - Plugins sélectionnés
912
+ * @param options - Options CLI
913
+ */
914
+ handleDryRun(selectedPlugins, options) {
915
+ if (!options.dryRun) {
916
+ return false;
917
+ }
918
+ console.log();
919
+ console.log(pc2.bold(pc2.yellow("\u2501".repeat(60))));
920
+ console.log(pc2.bold(pc2.yellow("\u{1F50D} MODE DRY-RUN (simulation uniquement)")));
921
+ console.log(pc2.bold(pc2.yellow("\u2501".repeat(60))));
922
+ console.log();
923
+ console.log(pc2.bold(pc2.cyan("\u{1F4E6} Packages \xE0 installer :")));
924
+ for (const plugin of selectedPlugins) {
925
+ console.log(
926
+ pc2.blue(` \u2022 ${plugin.displayName}`) + pc2.gray(
927
+ ` (${plugin.name}${plugin.version ? `@${plugin.version}` : ""})`
928
+ )
929
+ );
930
+ }
931
+ console.log();
932
+ console.log(pc2.bold(pc2.cyan("\u{1F4DD} Fichiers qui seraient cr\xE9\xE9s/modifi\xE9s :")));
933
+ for (const plugin of selectedPlugins) {
934
+ console.log(pc2.gray(` \u2022 ${plugin.displayName} configuration`));
935
+ }
936
+ console.log();
937
+ console.log(
938
+ pc2.yellow("\u26A0\uFE0F Aucune modification n'a \xE9t\xE9 effectu\xE9e (dry-run)")
939
+ );
940
+ console.log(
941
+ pc2.cyan("\u{1F4A1} Ex\xE9cutez sans --dry-run pour appliquer les changements")
942
+ );
943
+ console.log();
944
+ return true;
945
+ }
946
+ /**
947
+ * Effectue l'installation des plugins
948
+ *
949
+ * @param ctx - Contexte du projet
950
+ * @param selectedPlugins - Plugins sélectionnés
951
+ * @param language - Langue sélectionnée
952
+ * @param options - Options CLI
953
+ */
954
+ async performInstallation(ctx, selectedPlugins, language, options) {
955
+ const t = getTranslations(language);
956
+ const backupManager = new BackupManager();
957
+ const configWriter = new ConfigWriter(backupManager);
958
+ const validator = new CompatibilityValidator(allCompatibilityRules);
959
+ const installer = new Installer(ctx, validator, configWriter, backupManager);
960
+ if (options.install === false) {
961
+ console.log();
962
+ console.log(pc2.yellow("\u2699\uFE0F Mode configuration uniquement (--no-install)"));
963
+ console.log(pc2.gray("Les packages ne seront PAS install\xE9s"));
964
+ console.log();
965
+ }
966
+ const spinner = new SpinnerManager();
967
+ spinner.start(t.installation.installing);
968
+ try {
969
+ const result = await installer.install(selectedPlugins, {
970
+ skipPackageInstall: options.install === false
971
+ });
972
+ spinner.succeed(t.installation.success);
973
+ if (result.success) {
974
+ displayInstallationReport(result, selectedPlugins, language);
975
+ } else {
976
+ console.error(`
977
+ ${t.installation.error}`);
978
+ process.exit(1);
979
+ }
980
+ } catch (error) {
981
+ spinner.fail(t.installation.error);
982
+ throw error;
983
+ }
984
+ }
985
+ /**
986
+ * Méthode principale d'exécution de la commande
987
+ *
988
+ * Cette méthode orchestre toute la logique commune :
989
+ * 1. Sélection de la langue
990
+ * 2. Détection/création du contexte
991
+ * 3. Validation du framework
992
+ * 4. Affichage du contexte
993
+ * 5. Sélection des plugins
994
+ * 6. Confirmation
995
+ * 7. Installation
996
+ *
997
+ * @param options - Options CLI
998
+ */
999
+ async execute(options) {
1000
+ try {
1001
+ const language = await promptLanguage();
1002
+ const t = getTranslations(language);
1003
+ console.log();
1004
+ console.log(pc2.bold(pc2.cyan(`\u{1F50D} ${t.detection.detecting}`)));
1005
+ const projectRoot = process.cwd();
1006
+ const ctx = await this.getOrCreateContext(projectRoot, language);
1007
+ if (!this.validateFramework(ctx)) {
1008
+ this.displayFrameworkMismatchWarning(ctx, t);
1009
+ return;
1010
+ }
1011
+ this.displayDetectedContext(ctx, t);
1012
+ const selectedPlugins = await this.selectPlugins(ctx, language, options);
1013
+ if (selectedPlugins.length === 0) {
1014
+ console.log();
1015
+ console.log(pc2.yellow(`\u26A0\uFE0F ${t.common.selected(0)}`));
1016
+ console.log(pc2.gray("Exiting..."));
1017
+ return;
1018
+ }
1019
+ console.log();
1020
+ console.log(
1021
+ pc2.bold(pc2.green(`\u2713 ${t.common.selected(selectedPlugins.length)}`))
1022
+ );
1023
+ console.log();
1024
+ const confirmed = await this.confirmInstallation(
1025
+ selectedPlugins,
1026
+ language,
1027
+ options
1028
+ );
1029
+ if (!confirmed) {
1030
+ console.log();
1031
+ console.log(pc2.gray(t.common.cancel));
1032
+ return;
1033
+ }
1034
+ if (this.handleDryRun(selectedPlugins, options)) {
1035
+ return;
1036
+ }
1037
+ await this.performInstallation(ctx, selectedPlugins, language, options);
1038
+ } catch (error) {
1039
+ const errorMessage = error instanceof Error ? error.message : String(error);
1040
+ logger.error(`Fatal error: ${errorMessage}`);
1041
+ console.error("Fatal error:", errorMessage);
1042
+ process.exit(1);
1043
+ }
1044
+ }
1045
+ };
1046
+
998
1047
  export {
999
- getTranslations,
1000
- promptLanguage,
1001
- promptPluginSelection,
1002
- promptConfirmation,
1003
- Installer,
1004
- SpinnerManager,
1005
- displayInstallationReport
1048
+ getFrameworkMetadata,
1049
+ BaseFrameworkCommand
1006
1050
  };