@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.
- package/README.fr.md +1 -1
- package/README.md +16 -2
- package/dist/{check-XDGAGYOE.js → check-AJCBQBFD.js} +6 -5
- package/dist/chunk-3V72QFFY.js +383 -0
- package/dist/{chunk-OAAGGK2H.js → chunk-CNAEKUBH.js} +361 -317
- package/dist/chunk-D37FHAGO.js +569 -0
- package/dist/chunk-HM2JWJOO.js +418 -0
- package/dist/chunk-MQV3WNMH.js +114 -0
- package/dist/{chunk-BVXGN3AC.js → chunk-TVZWTKJU.js} +316 -224
- package/dist/{chunk-4VHPGJVU.js → chunk-V75HW2AM.js} +8557 -6661
- package/dist/cli.js +23 -9
- package/dist/{installed-IKSARZIK.js → installed-WA6I2IFD.js} +4 -3
- package/dist/{list-IJK225B3.js → list-Y7I5NUWT.js} +3 -2
- package/dist/nextjs-command-AUVNEBHG.js +59 -0
- package/dist/nextjs-installer-RWBGWW23.js +80 -0
- package/dist/nextjs-setup-7LWMEC5I.js +100 -0
- package/dist/react-command-DTIKCCPO.js +59 -0
- package/dist/{remove-IIT34Y3T.js → remove-JBICRDXX.js} +4 -3
- package/dist/vite-installer-XIJFJ4CN.js +49 -0
- package/dist/vite-setup-3U22LJFG.js +51 -0
- package/dist/vue-command-R4XETTRT.js +73 -0
- package/dist/vue-installer-SFROF4N3.js +74 -0
- package/dist/vue-setup-X65P3CZX.js +91 -0
- package/package.json +5 -2
- package/dist/chunk-QRFLHLFE.js +0 -300
- package/dist/chunk-WKYUK64P.js +0 -308
- package/dist/install-APYIRHSN.js +0 -258
- package/dist/install-nextjs-C3LEKJLY.js +0 -353
|
@@ -0,0 +1,569 @@
|
|
|
1
|
+
import {
|
|
2
|
+
pluginRegistry
|
|
3
|
+
} from "./chunk-V75HW2AM.js";
|
|
4
|
+
import {
|
|
5
|
+
logger
|
|
6
|
+
} from "./chunk-HM2JWJOO.js";
|
|
7
|
+
|
|
8
|
+
// src/core/compatibility-generator.ts
|
|
9
|
+
function generateCompatibilityRules(plugins) {
|
|
10
|
+
logger.debug(
|
|
11
|
+
`Generating compatibility rules from ${plugins.length} plugin(s)`
|
|
12
|
+
);
|
|
13
|
+
const rules = [];
|
|
14
|
+
rules.push(...generateExclusiveRules(plugins));
|
|
15
|
+
rules.push(...generateConflictRules(plugins));
|
|
16
|
+
rules.push(...generateRequiresRules(plugins));
|
|
17
|
+
rules.push(...generateRecommendsRules(plugins));
|
|
18
|
+
logger.debug(`Generated ${rules.length} compatibility rule(s)`);
|
|
19
|
+
return rules;
|
|
20
|
+
}
|
|
21
|
+
function generateExclusiveRules(plugins) {
|
|
22
|
+
const rules = [];
|
|
23
|
+
const pluginsByCategory = /* @__PURE__ */ new Map();
|
|
24
|
+
for (const plugin of plugins) {
|
|
25
|
+
const category = plugin.category;
|
|
26
|
+
if (!pluginsByCategory.has(category)) {
|
|
27
|
+
pluginsByCategory.set(category, []);
|
|
28
|
+
}
|
|
29
|
+
const arr = pluginsByCategory.get(category);
|
|
30
|
+
if (arr) {
|
|
31
|
+
arr.push(plugin);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
for (const [category, categoryPlugins] of pluginsByCategory.entries()) {
|
|
35
|
+
if (categoryPlugins.length < 2) {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
const exclusiveCategories = [
|
|
39
|
+
"state" /* STATE */,
|
|
40
|
+
// Un seul state management
|
|
41
|
+
"routing" /* ROUTING */,
|
|
42
|
+
// Un seul routing
|
|
43
|
+
"css" /* CSS */
|
|
44
|
+
// Un seul framework CSS (peut être flexible selon le cas)
|
|
45
|
+
];
|
|
46
|
+
if (!exclusiveCategories.includes(category)) {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
const pluginNames = categoryPlugins.map((p) => p.name);
|
|
50
|
+
const severity = category === "css" /* CSS */ ? "warning" : "error";
|
|
51
|
+
const allowOverride = category === "css" /* CSS */;
|
|
52
|
+
rules.push({
|
|
53
|
+
type: "EXCLUSIVE",
|
|
54
|
+
plugins: pluginNames,
|
|
55
|
+
reason: getExclusiveReason(category),
|
|
56
|
+
severity,
|
|
57
|
+
allowOverride
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
return rules;
|
|
61
|
+
}
|
|
62
|
+
function getExclusiveReason(category) {
|
|
63
|
+
switch (category) {
|
|
64
|
+
case "state" /* STATE */:
|
|
65
|
+
return "Une seule solution de state management est recommand\xE9e";
|
|
66
|
+
case "routing" /* ROUTING */:
|
|
67
|
+
return "Un seul syst\xE8me de routing est recommand\xE9";
|
|
68
|
+
case "css" /* CSS */:
|
|
69
|
+
return "Approches CSS potentiellement conflictuelles";
|
|
70
|
+
default:
|
|
71
|
+
return "Ces plugins sont mutuellement exclusifs";
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function generateConflictRules(plugins) {
|
|
75
|
+
const rules = [];
|
|
76
|
+
for (const plugin of plugins) {
|
|
77
|
+
if (!plugin.incompatibleWith || plugin.incompatibleWith.length === 0) {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
for (const incompatiblePluginName of plugin.incompatibleWith) {
|
|
81
|
+
const incompatiblePlugin = plugins.find(
|
|
82
|
+
(p) => p.name === incompatiblePluginName
|
|
83
|
+
);
|
|
84
|
+
if (!incompatiblePlugin) {
|
|
85
|
+
logger.warn(
|
|
86
|
+
`Plugin ${plugin.name} declares incompatibleWith ${incompatiblePluginName}, but plugin not found in registry`
|
|
87
|
+
);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
const commonFrameworks = plugin.frameworks.filter(
|
|
91
|
+
(f) => incompatiblePlugin.frameworks.includes(f)
|
|
92
|
+
);
|
|
93
|
+
const isCssConflict = plugin.category === "css" /* CSS */ && incompatiblePlugin.category === "css" /* CSS */;
|
|
94
|
+
const severity = isCssConflict ? "warning" : "error";
|
|
95
|
+
const allowOverride = isCssConflict;
|
|
96
|
+
if (commonFrameworks.length === 0) {
|
|
97
|
+
rules.push({
|
|
98
|
+
type: "CONFLICT",
|
|
99
|
+
plugins: [plugin.name, incompatiblePluginName],
|
|
100
|
+
reason: `${plugin.displayName} est incompatible avec ${incompatiblePlugin.displayName}`,
|
|
101
|
+
severity,
|
|
102
|
+
allowOverride
|
|
103
|
+
});
|
|
104
|
+
} else {
|
|
105
|
+
for (const framework of commonFrameworks) {
|
|
106
|
+
rules.push({
|
|
107
|
+
type: "CONFLICT",
|
|
108
|
+
plugins: [plugin.name, incompatiblePluginName],
|
|
109
|
+
framework,
|
|
110
|
+
reason: `${plugin.displayName} est incompatible avec ${incompatiblePlugin.displayName} pour ${framework}`,
|
|
111
|
+
severity,
|
|
112
|
+
allowOverride
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return rules;
|
|
119
|
+
}
|
|
120
|
+
function generateRequiresRules(plugins) {
|
|
121
|
+
const rules = [];
|
|
122
|
+
for (const plugin of plugins) {
|
|
123
|
+
if (!plugin.requires || plugin.requires.length === 0) {
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
for (const framework of plugin.frameworks) {
|
|
127
|
+
rules.push({
|
|
128
|
+
type: "REQUIRES",
|
|
129
|
+
plugin: plugin.name,
|
|
130
|
+
requires: plugin.requires,
|
|
131
|
+
framework,
|
|
132
|
+
reason: `${plugin.displayName} n\xE9cessite les d\xE9pendances suivantes: ${plugin.requires.join(", ")}`,
|
|
133
|
+
severity: "error",
|
|
134
|
+
allowOverride: false
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return rules;
|
|
139
|
+
}
|
|
140
|
+
function generateRecommendsRules(plugins) {
|
|
141
|
+
const rules = [];
|
|
142
|
+
for (const plugin of plugins) {
|
|
143
|
+
if (!plugin.recommends || plugin.recommends.length === 0) {
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
for (const framework of plugin.frameworks) {
|
|
147
|
+
rules.push({
|
|
148
|
+
type: "RECOMMENDS",
|
|
149
|
+
plugin: plugin.name,
|
|
150
|
+
recommends: plugin.recommends,
|
|
151
|
+
framework,
|
|
152
|
+
reason: `${plugin.displayName} recommande d'installer: ${plugin.recommends.join(", ")}`,
|
|
153
|
+
severity: "info"
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return rules;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// src/core/validator.ts
|
|
161
|
+
var CompatibilityValidator = class {
|
|
162
|
+
/**
|
|
163
|
+
* @param rules - Règles de compatibilité à appliquer
|
|
164
|
+
*/
|
|
165
|
+
constructor(rules) {
|
|
166
|
+
this.rules = rules;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Valide la compatibilité d'un ensemble de plugins
|
|
170
|
+
*
|
|
171
|
+
* @param plugins - Liste des plugins à valider
|
|
172
|
+
* @param ctx - Contexte du projet (optionnel, pour règles spécifiques framework)
|
|
173
|
+
* @returns Résultat de la validation avec erreurs, warnings et suggestions
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* ```typescript
|
|
177
|
+
* const result = validator.validate([plugin1, plugin2, plugin3], ctx)
|
|
178
|
+
* if (!result.valid) {
|
|
179
|
+
* // Gérer les erreurs
|
|
180
|
+
* }
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
validate(plugins, ctx) {
|
|
184
|
+
logger.debug(`Validating ${plugins.length} plugin(s)`);
|
|
185
|
+
const pluginNames = new Set(plugins.map((p) => p.name));
|
|
186
|
+
const applicableRules = ctx ? this.rules.filter(
|
|
187
|
+
(rule) => !rule.framework || rule.framework === ctx.framework
|
|
188
|
+
) : this.rules.filter((rule) => !rule.framework);
|
|
189
|
+
const allConflicts = this.checkConflicts(
|
|
190
|
+
plugins,
|
|
191
|
+
pluginNames,
|
|
192
|
+
applicableRules
|
|
193
|
+
);
|
|
194
|
+
const conflictErrors = [];
|
|
195
|
+
const conflictWarnings = [];
|
|
196
|
+
for (const conflict of allConflicts) {
|
|
197
|
+
const rule = applicableRules.find(
|
|
198
|
+
(r) => r.type === "CONFLICT" && r.plugins?.every((p) => conflict.plugins?.includes(p))
|
|
199
|
+
);
|
|
200
|
+
if (rule?.severity === "error") {
|
|
201
|
+
conflictErrors.push(conflict);
|
|
202
|
+
} else {
|
|
203
|
+
conflictWarnings.push(conflict);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
const frameworkConflicts = ctx ? this.checkFrameworkConflicts(plugins, pluginNames, ctx, applicableRules) : [];
|
|
207
|
+
const frameworkErrors = [];
|
|
208
|
+
const frameworkWarnings = [];
|
|
209
|
+
for (const conflict of frameworkConflicts) {
|
|
210
|
+
const rule = applicableRules.find(
|
|
211
|
+
(r) => r.type === "CONFLICT" && r.framework === ctx?.framework && r.plugins?.some((p) => conflict.plugins?.includes(p))
|
|
212
|
+
);
|
|
213
|
+
if (rule?.severity === "error") {
|
|
214
|
+
frameworkErrors.push(conflict);
|
|
215
|
+
} else {
|
|
216
|
+
frameworkWarnings.push(conflict);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
const exclusivityResults = this.checkExclusivity(
|
|
220
|
+
plugins,
|
|
221
|
+
pluginNames,
|
|
222
|
+
applicableRules
|
|
223
|
+
);
|
|
224
|
+
const exclusivityErrors = [];
|
|
225
|
+
const exclusivityWarnings = [];
|
|
226
|
+
for (const result of exclusivityResults) {
|
|
227
|
+
const rule = applicableRules.find(
|
|
228
|
+
(r) => r.type === "EXCLUSIVE" && result.plugins?.every((p) => r.plugins?.includes(p))
|
|
229
|
+
);
|
|
230
|
+
if (rule?.severity === "warning") {
|
|
231
|
+
exclusivityWarnings.push(result);
|
|
232
|
+
} else {
|
|
233
|
+
exclusivityErrors.push(result);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
const errors = [
|
|
237
|
+
...exclusivityErrors,
|
|
238
|
+
...conflictErrors,
|
|
239
|
+
...this.checkDependencies(plugins, pluginNames, applicableRules, ctx),
|
|
240
|
+
...frameworkErrors
|
|
241
|
+
];
|
|
242
|
+
const warnings = [
|
|
243
|
+
...exclusivityWarnings,
|
|
244
|
+
...conflictWarnings,
|
|
245
|
+
...frameworkWarnings
|
|
246
|
+
];
|
|
247
|
+
const suggestions = this.checkRecommendations(
|
|
248
|
+
plugins,
|
|
249
|
+
pluginNames,
|
|
250
|
+
applicableRules
|
|
251
|
+
);
|
|
252
|
+
const valid = errors.length === 0;
|
|
253
|
+
logger.debug(`Validation result: ${valid ? "valid" : "invalid"}`, {
|
|
254
|
+
errors: errors.length,
|
|
255
|
+
warnings: warnings.length,
|
|
256
|
+
suggestions: suggestions.length
|
|
257
|
+
});
|
|
258
|
+
return {
|
|
259
|
+
valid,
|
|
260
|
+
errors,
|
|
261
|
+
warnings,
|
|
262
|
+
suggestions
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Vérifie les conflits avec le framework
|
|
267
|
+
*
|
|
268
|
+
* @param _plugins - Liste des plugins (non utilisée, conservée pour cohérence)
|
|
269
|
+
* @param pluginNames - Set des noms de plugins pour lookup rapide
|
|
270
|
+
* @param ctx - Contexte du projet
|
|
271
|
+
* @param rules - Règles applicables
|
|
272
|
+
* @returns Liste des erreurs/warnings de conflit framework
|
|
273
|
+
*
|
|
274
|
+
* @internal
|
|
275
|
+
*/
|
|
276
|
+
checkFrameworkConflicts(_plugins, pluginNames, ctx, rules) {
|
|
277
|
+
const conflicts = [];
|
|
278
|
+
for (const rule of rules) {
|
|
279
|
+
if (rule.type !== "CONFLICT" || !rule.framework || rule.framework !== ctx.framework) {
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
if (rule.plugins && rule.plugins.length > 0) {
|
|
283
|
+
const conflictingPlugins = rule.plugins.filter(
|
|
284
|
+
(pluginName) => pluginNames.has(pluginName)
|
|
285
|
+
);
|
|
286
|
+
const isFrameworkIncompatible = rule.plugins.length === 1;
|
|
287
|
+
const shouldReportConflict = isFrameworkIncompatible ? conflictingPlugins.length > 0 : conflictingPlugins.length > 1;
|
|
288
|
+
if (shouldReportConflict) {
|
|
289
|
+
conflicts.push({
|
|
290
|
+
type: "CONFLICT",
|
|
291
|
+
plugins: conflictingPlugins,
|
|
292
|
+
message: rule.reason,
|
|
293
|
+
canOverride: rule.allowOverride ?? true
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
return conflicts;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Vérifie les règles d'exclusivité (EXCLUSIVE)
|
|
302
|
+
*
|
|
303
|
+
* @param _plugins - Liste des plugins (non utilisée, conservée pour cohérence)
|
|
304
|
+
* @param pluginNames - Set des noms de plugins pour lookup rapide
|
|
305
|
+
* @param rules - Règles applicables
|
|
306
|
+
* @returns Liste des erreurs d'exclusivité
|
|
307
|
+
*
|
|
308
|
+
* @internal
|
|
309
|
+
*/
|
|
310
|
+
checkExclusivity(_plugins, pluginNames, rules = this.rules) {
|
|
311
|
+
const errors = [];
|
|
312
|
+
for (const rule of rules) {
|
|
313
|
+
if (rule.type !== "EXCLUSIVE" || !rule.plugins) {
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
const selectedExclusivePlugins = rule.plugins.filter(
|
|
317
|
+
(pluginName) => pluginNames.has(pluginName)
|
|
318
|
+
);
|
|
319
|
+
if (selectedExclusivePlugins.length > 1) {
|
|
320
|
+
errors.push({
|
|
321
|
+
type: "EXCLUSIVE",
|
|
322
|
+
plugins: selectedExclusivePlugins,
|
|
323
|
+
message: rule.reason,
|
|
324
|
+
canOverride: rule.allowOverride ?? false
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
return errors;
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Vérifie les conflits entre plugins (CONFLICT)
|
|
332
|
+
*
|
|
333
|
+
* @param _plugins - Liste des plugins (non utilisée, conservée pour cohérence)
|
|
334
|
+
* @param pluginNames - Set des noms de plugins pour lookup rapide
|
|
335
|
+
* @param rules - Règles applicables
|
|
336
|
+
* @returns Liste des warnings/erreurs de conflit
|
|
337
|
+
*
|
|
338
|
+
* @internal
|
|
339
|
+
*/
|
|
340
|
+
checkConflicts(_plugins, pluginNames, rules = this.rules) {
|
|
341
|
+
const conflicts = [];
|
|
342
|
+
for (const rule of rules) {
|
|
343
|
+
if (rule.framework) {
|
|
344
|
+
continue;
|
|
345
|
+
}
|
|
346
|
+
if (rule.type !== "CONFLICT" || !rule.plugins) {
|
|
347
|
+
continue;
|
|
348
|
+
}
|
|
349
|
+
const conflictingPlugins = rule.plugins.filter(
|
|
350
|
+
(pluginName) => pluginNames.has(pluginName)
|
|
351
|
+
);
|
|
352
|
+
if (conflictingPlugins.length > 1) {
|
|
353
|
+
conflicts.push({
|
|
354
|
+
type: "CONFLICT",
|
|
355
|
+
plugins: conflictingPlugins,
|
|
356
|
+
message: rule.reason,
|
|
357
|
+
canOverride: rule.allowOverride ?? true
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
return conflicts;
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Vérifie les dépendances requises (REQUIRES)
|
|
365
|
+
*
|
|
366
|
+
* @param _plugins - Liste des plugins (non utilisée, conservée pour cohérence)
|
|
367
|
+
* @param pluginNames - Set des noms de plugins pour lookup rapide
|
|
368
|
+
* @param rules - Règles applicables
|
|
369
|
+
* @param ctx - Contexte du projet (optionnel)
|
|
370
|
+
* @returns Liste des erreurs de dépendances manquantes
|
|
371
|
+
*
|
|
372
|
+
* @internal
|
|
373
|
+
*/
|
|
374
|
+
checkDependencies(_plugins, pluginNames, rules = this.rules, ctx) {
|
|
375
|
+
const errors = [];
|
|
376
|
+
for (const rule of rules) {
|
|
377
|
+
if (rule.type !== "REQUIRES" || !rule.plugin || !rule.requires) {
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
if (!pluginNames.has(rule.plugin)) {
|
|
381
|
+
continue;
|
|
382
|
+
}
|
|
383
|
+
const missingDependencies = [];
|
|
384
|
+
for (const dep of rule.requires) {
|
|
385
|
+
const pluginName = dep.split("@")[0];
|
|
386
|
+
if (!pluginName) {
|
|
387
|
+
continue;
|
|
388
|
+
}
|
|
389
|
+
if (dep.includes("@") && ctx) {
|
|
390
|
+
const allDeps = { ...ctx.dependencies, ...ctx.devDependencies };
|
|
391
|
+
if (!allDeps[pluginName]) {
|
|
392
|
+
missingDependencies.push(dep);
|
|
393
|
+
}
|
|
394
|
+
} else {
|
|
395
|
+
if (!pluginNames.has(pluginName)) {
|
|
396
|
+
missingDependencies.push(dep);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
if (missingDependencies.length > 0) {
|
|
401
|
+
errors.push({
|
|
402
|
+
type: "REQUIRES",
|
|
403
|
+
plugin: rule.plugin,
|
|
404
|
+
required: missingDependencies.join(", "),
|
|
405
|
+
message: `${rule.plugin} requires: ${missingDependencies.join(", ")}. ${rule.reason}`,
|
|
406
|
+
canOverride: rule.allowOverride ?? false
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
return errors;
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Vérifie les recommandations (RECOMMENDS)
|
|
414
|
+
*
|
|
415
|
+
* @param _plugins - Liste des plugins (non utilisée, conservée pour cohérence)
|
|
416
|
+
* @param pluginNames - Set des noms de plugins pour lookup rapide
|
|
417
|
+
* @param rules - Règles applicables
|
|
418
|
+
* @returns Liste des suggestions de plugins recommandés
|
|
419
|
+
*
|
|
420
|
+
* @internal
|
|
421
|
+
*/
|
|
422
|
+
checkRecommendations(_plugins, pluginNames, rules = this.rules) {
|
|
423
|
+
const suggestions = [];
|
|
424
|
+
for (const rule of rules) {
|
|
425
|
+
if (rule.type !== "RECOMMENDS" || !rule.plugin || !rule.recommends) {
|
|
426
|
+
continue;
|
|
427
|
+
}
|
|
428
|
+
if (!pluginNames.has(rule.plugin)) {
|
|
429
|
+
continue;
|
|
430
|
+
}
|
|
431
|
+
const missingRecommendations = rule.recommends.filter(
|
|
432
|
+
(rec) => !pluginNames.has(rec)
|
|
433
|
+
);
|
|
434
|
+
if (missingRecommendations.length > 0) {
|
|
435
|
+
suggestions.push(
|
|
436
|
+
`${rule.plugin} recommends: ${missingRecommendations.join(", ")}. ${rule.reason}`
|
|
437
|
+
);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
return suggestions;
|
|
441
|
+
}
|
|
442
|
+
};
|
|
443
|
+
var compatibilityRules = generateCompatibilityRules(pluginRegistry);
|
|
444
|
+
var additionalCompatibilityRules = [
|
|
445
|
+
// ====================================================================
|
|
446
|
+
// Règles spécifiques Next.js
|
|
447
|
+
// ====================================================================
|
|
448
|
+
// React Router incompatible avec Next.js (routing intégré)
|
|
449
|
+
{
|
|
450
|
+
type: "CONFLICT",
|
|
451
|
+
plugins: ["react-router-dom"],
|
|
452
|
+
framework: "nextjs",
|
|
453
|
+
reason: "React Router est incompatible avec Next.js. Next.js a son propre syst\xE8me de routing int\xE9gr\xE9.",
|
|
454
|
+
severity: "error",
|
|
455
|
+
allowOverride: false
|
|
456
|
+
},
|
|
457
|
+
// Framer Motion peut causer des problèmes SSR avec Next.js
|
|
458
|
+
{
|
|
459
|
+
type: "CONFLICT",
|
|
460
|
+
plugins: ["framer-motion"],
|
|
461
|
+
framework: "nextjs",
|
|
462
|
+
reason: "Framer Motion peut causer des probl\xE8mes avec le Server-Side Rendering (SSR) de Next.js. Utilisez des alternatives compatibles SSR ou configurez correctement le dynamic import.",
|
|
463
|
+
severity: "warning",
|
|
464
|
+
allowOverride: true
|
|
465
|
+
},
|
|
466
|
+
// Shadcn/ui nécessite une configuration spéciale pour Next.js
|
|
467
|
+
{
|
|
468
|
+
type: "RECOMMENDS",
|
|
469
|
+
plugin: "shadcn-ui",
|
|
470
|
+
recommends: ["shadcn-ui-nextjs"],
|
|
471
|
+
framework: "nextjs",
|
|
472
|
+
reason: "Pour Next.js, utilisez la variante shadcn-ui-nextjs qui est optimis\xE9e pour React Server Components.",
|
|
473
|
+
severity: "info"
|
|
474
|
+
},
|
|
475
|
+
// ====================================================================
|
|
476
|
+
// Règles spécifiques Vue.js
|
|
477
|
+
// ====================================================================
|
|
478
|
+
// React Router incompatible avec Vue.js (utiliser Vue Router)
|
|
479
|
+
{
|
|
480
|
+
type: "CONFLICT",
|
|
481
|
+
plugins: ["react-router-dom"],
|
|
482
|
+
framework: "vue",
|
|
483
|
+
reason: "React Router est incompatible avec Vue.js. Utilisez Vue Router (vue-router) pour Vue.js.",
|
|
484
|
+
severity: "error",
|
|
485
|
+
allowOverride: false
|
|
486
|
+
},
|
|
487
|
+
// State management React incompatible avec Vue.js
|
|
488
|
+
{
|
|
489
|
+
type: "CONFLICT",
|
|
490
|
+
plugins: ["zustand", "@reduxjs/toolkit", "jotai"],
|
|
491
|
+
framework: "vue",
|
|
492
|
+
reason: "Zustand, Redux Toolkit et Jotai sont sp\xE9cifiques \xE0 React. Pour Vue.js, utilisez Pinia (state management officiel).",
|
|
493
|
+
severity: "error",
|
|
494
|
+
allowOverride: false
|
|
495
|
+
},
|
|
496
|
+
// Shadcn/ui incompatible avec Vue.js (spécifique React)
|
|
497
|
+
{
|
|
498
|
+
type: "CONFLICT",
|
|
499
|
+
plugins: ["shadcn-ui"],
|
|
500
|
+
framework: "vue",
|
|
501
|
+
reason: "Shadcn/ui est sp\xE9cifique \xE0 React. Pour Vue.js, utilisez Vuetify ou Quasar (frameworks UI Vue.js).",
|
|
502
|
+
severity: "error",
|
|
503
|
+
allowOverride: false
|
|
504
|
+
},
|
|
505
|
+
// Pinia nécessite Vue 3
|
|
506
|
+
{
|
|
507
|
+
type: "REQUIRES",
|
|
508
|
+
plugin: "pinia",
|
|
509
|
+
requires: ["vue@^3.0.0"],
|
|
510
|
+
framework: "vue",
|
|
511
|
+
reason: "Pinia n\xE9cessite Vue 3. Vue 2 n'est plus support\xE9.",
|
|
512
|
+
severity: "error",
|
|
513
|
+
allowOverride: false
|
|
514
|
+
},
|
|
515
|
+
// Vue Router version doit correspondre à Vue version
|
|
516
|
+
{
|
|
517
|
+
type: "CONFLICT",
|
|
518
|
+
plugins: ["vue-router"],
|
|
519
|
+
framework: "vue",
|
|
520
|
+
reason: "Assurez-vous que la version de Vue Router correspond \xE0 la version de Vue.js (Vue Router 4 pour Vue 3).",
|
|
521
|
+
severity: "warning",
|
|
522
|
+
allowOverride: true
|
|
523
|
+
}
|
|
524
|
+
];
|
|
525
|
+
function normalizeArray(values) {
|
|
526
|
+
if (!values || values.length === 0) {
|
|
527
|
+
return [];
|
|
528
|
+
}
|
|
529
|
+
return [...values].sort();
|
|
530
|
+
}
|
|
531
|
+
function buildRuleKey(rule) {
|
|
532
|
+
const plugins = normalizeArray(rule.plugins).join("|");
|
|
533
|
+
const requires = normalizeArray(rule.requires).join("|");
|
|
534
|
+
const recommends = normalizeArray(rule.recommends).join("|");
|
|
535
|
+
return [
|
|
536
|
+
rule.type,
|
|
537
|
+
rule.framework ?? "*",
|
|
538
|
+
rule.plugin ?? "",
|
|
539
|
+
plugins,
|
|
540
|
+
requires,
|
|
541
|
+
recommends,
|
|
542
|
+
rule.severity,
|
|
543
|
+
String(rule.allowOverride ?? false),
|
|
544
|
+
String(rule.autoInstall ?? false),
|
|
545
|
+
String(rule.prompt ?? false)
|
|
546
|
+
].join("::");
|
|
547
|
+
}
|
|
548
|
+
function deduplicateCompatibilityRules(rules) {
|
|
549
|
+
const seen = /* @__PURE__ */ new Set();
|
|
550
|
+
const deduplicated = [];
|
|
551
|
+
for (const rule of rules) {
|
|
552
|
+
const key = buildRuleKey(rule);
|
|
553
|
+
if (seen.has(key)) {
|
|
554
|
+
continue;
|
|
555
|
+
}
|
|
556
|
+
seen.add(key);
|
|
557
|
+
deduplicated.push(rule);
|
|
558
|
+
}
|
|
559
|
+
return deduplicated;
|
|
560
|
+
}
|
|
561
|
+
var allCompatibilityRules = deduplicateCompatibilityRules([
|
|
562
|
+
...compatibilityRules,
|
|
563
|
+
...additionalCompatibilityRules
|
|
564
|
+
]);
|
|
565
|
+
|
|
566
|
+
export {
|
|
567
|
+
CompatibilityValidator,
|
|
568
|
+
allCompatibilityRules
|
|
569
|
+
};
|