@cerema/cadriciel 1.7.4 → 1.8.0
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/cli/global/create.js +253 -38
- package/cli/global/doctor.js +81 -213
- package/cli/global/init.js +237 -34
- package/cli/global/install.js +21 -100
- package/cli/{_old → global}/login.js +12 -12
- package/cli.js +425 -431
- package/package.json +3 -2
- package/.gitlab-ci.yml +0 -16
- package/bun.lock +0 -578
- package/cli/assets/docker/.env +0 -27
- package/cli/assets/docker/docker-compose.yml +0 -209
- package/cli/assets/docker/init-db/01-create-keycloak-db.sql +0 -1
- package/cli/assets/docker/init-db/02-cadriciel.sql +0 -3604
- /package/cli/{_old → global}/load.js +0 -0
- /package/cli/{_old → global}/logout.js +0 -0
package/cli/global/create.js
CHANGED
|
@@ -11,6 +11,157 @@ module.exports = (args) => {
|
|
|
11
11
|
const CACHE_DIR = path.join(os.homedir(), '.cadriciel', 'starters-cache');
|
|
12
12
|
const PACKAGE_NAME = '@cadriciel/starters';
|
|
13
13
|
|
|
14
|
+
// Helper: Parse CLI arguments
|
|
15
|
+
const parseArgs = (cmdArgs) => {
|
|
16
|
+
const options = {
|
|
17
|
+
name: null,
|
|
18
|
+
template: null,
|
|
19
|
+
features: null,
|
|
20
|
+
allFeatures: false,
|
|
21
|
+
defaults: false,
|
|
22
|
+
list: false,
|
|
23
|
+
listFeatures: null,
|
|
24
|
+
yes: false,
|
|
25
|
+
test: false,
|
|
26
|
+
help: false
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
for (let i = 0; i < cmdArgs.length; i++) {
|
|
30
|
+
const arg = cmdArgs[i];
|
|
31
|
+
const nextArg = cmdArgs[i + 1];
|
|
32
|
+
|
|
33
|
+
switch (arg) {
|
|
34
|
+
case '-n':
|
|
35
|
+
case '--name':
|
|
36
|
+
options.name = nextArg;
|
|
37
|
+
i++;
|
|
38
|
+
break;
|
|
39
|
+
case '-t':
|
|
40
|
+
case '--template':
|
|
41
|
+
options.template = nextArg;
|
|
42
|
+
i++;
|
|
43
|
+
break;
|
|
44
|
+
case '-f':
|
|
45
|
+
case '--features':
|
|
46
|
+
options.features = nextArg ? nextArg.split(',').map(f => f.trim()) : [];
|
|
47
|
+
i++;
|
|
48
|
+
break;
|
|
49
|
+
case '-a':
|
|
50
|
+
case '--all-features':
|
|
51
|
+
options.allFeatures = true;
|
|
52
|
+
break;
|
|
53
|
+
case '-d':
|
|
54
|
+
case '--defaults':
|
|
55
|
+
options.defaults = true;
|
|
56
|
+
break;
|
|
57
|
+
case '-l':
|
|
58
|
+
case '--list':
|
|
59
|
+
options.list = true;
|
|
60
|
+
break;
|
|
61
|
+
case '--list-features':
|
|
62
|
+
options.listFeatures = nextArg;
|
|
63
|
+
i++;
|
|
64
|
+
break;
|
|
65
|
+
case '-y':
|
|
66
|
+
case '--yes':
|
|
67
|
+
options.yes = true;
|
|
68
|
+
break;
|
|
69
|
+
case '--test':
|
|
70
|
+
options.test = true;
|
|
71
|
+
break;
|
|
72
|
+
case '-h':
|
|
73
|
+
case '--help':
|
|
74
|
+
options.help = true;
|
|
75
|
+
break;
|
|
76
|
+
default:
|
|
77
|
+
// Positional argument (project name if not already set)
|
|
78
|
+
if (!arg.startsWith('-') && !options.name && arg !== 'create') {
|
|
79
|
+
options.name = arg;
|
|
80
|
+
}
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return options;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
// Helper: Display help
|
|
89
|
+
const showHelp = () => {
|
|
90
|
+
console.log(chalk.bold.cyan('\nUsage: cad create [options] [project-name]\n'));
|
|
91
|
+
console.log(chalk.bold('Options:'));
|
|
92
|
+
console.log(' -n, --name <name> Project name');
|
|
93
|
+
console.log(' -t, --template <id> Template ID (skip template selection)');
|
|
94
|
+
console.log(' -f, --features <list> Comma-separated list of features to enable');
|
|
95
|
+
console.log(' -a, --all-features Enable all available features');
|
|
96
|
+
console.log(' -d, --defaults Use default feature selection');
|
|
97
|
+
console.log(' -l, --list List available templates');
|
|
98
|
+
console.log(' --list-features <id> List features for a specific template');
|
|
99
|
+
console.log(' -y, --yes Auto-confirm prompts (e.g., overwrite)');
|
|
100
|
+
console.log(' --test Use current directory for starters (dev mode)');
|
|
101
|
+
console.log(' -h, --help Show this help message');
|
|
102
|
+
console.log(chalk.bold('\nExamples:'));
|
|
103
|
+
console.log(chalk.gray(' # Interactive mode (default)'));
|
|
104
|
+
console.log(' cad create');
|
|
105
|
+
console.log(' cad create my-project');
|
|
106
|
+
console.log(chalk.gray('\n # Automated mode'));
|
|
107
|
+
console.log(' cad create -n my-project -t basic -d');
|
|
108
|
+
console.log(' cad create -n my-project -t basic -f auth,api');
|
|
109
|
+
console.log(' cad create -n my-project -t basic -a -y');
|
|
110
|
+
console.log(chalk.gray('\n # List templates and features'));
|
|
111
|
+
console.log(' cad create --list');
|
|
112
|
+
console.log(' cad create --list-features basic');
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
// Helper: List templates
|
|
116
|
+
const listTemplates = (starters) => {
|
|
117
|
+
console.log(chalk.bold.cyan('\nAvailable templates:\n'));
|
|
118
|
+
starters.forEach(s => {
|
|
119
|
+
console.log(` ${chalk.bold.green(s.id)}`);
|
|
120
|
+
console.log(` Name: ${s.name}`);
|
|
121
|
+
console.log(` Description: ${s.description}`);
|
|
122
|
+
console.log('');
|
|
123
|
+
});
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
// Helper: List features for a template
|
|
127
|
+
const listFeatures = (starter) => {
|
|
128
|
+
const optionsConfig = starter.config.options || {};
|
|
129
|
+
const coreFeatures = [];
|
|
130
|
+
const optionalFeatures = [];
|
|
131
|
+
|
|
132
|
+
Object.keys(optionsConfig).forEach(key => {
|
|
133
|
+
const opt = optionsConfig[key];
|
|
134
|
+
if (opt.type === 'core') {
|
|
135
|
+
coreFeatures.push({ id: key, ...opt });
|
|
136
|
+
} else {
|
|
137
|
+
optionalFeatures.push({ id: key, ...opt });
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
console.log(chalk.bold.cyan(`\nFeatures for template: ${starter.name}\n`));
|
|
142
|
+
|
|
143
|
+
if (coreFeatures.length > 0) {
|
|
144
|
+
console.log(chalk.bold('Core (always included):'));
|
|
145
|
+
coreFeatures.forEach(f => {
|
|
146
|
+
console.log(` ${chalk.gray('•')} ${f.id}${f.description ? ` - ${f.description}` : ''}`);
|
|
147
|
+
});
|
|
148
|
+
console.log('');
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (optionalFeatures.length > 0) {
|
|
152
|
+
console.log(chalk.bold('Optional:'));
|
|
153
|
+
optionalFeatures.forEach(f => {
|
|
154
|
+
const defaultTag = f.default ? chalk.green(' [default]') : '';
|
|
155
|
+
console.log(` ${chalk.gray('•')} ${chalk.bold(f.id)}${f.description ? ` - ${f.description}` : ''}${defaultTag}`);
|
|
156
|
+
});
|
|
157
|
+
console.log('');
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (optionalFeatures.length === 0 && coreFeatures.length === 0) {
|
|
161
|
+
console.log(chalk.yellow(' No features defined for this template.'));
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
|
|
14
165
|
// Helper: Fetch/Update the starters package
|
|
15
166
|
const fetchStarters = async () => {
|
|
16
167
|
const spinner = ora('Fetching latest starters...').start();
|
|
@@ -71,19 +222,23 @@ module.exports = (args) => {
|
|
|
71
222
|
};
|
|
72
223
|
|
|
73
224
|
// Helper: Generate Project
|
|
74
|
-
const generateProject = async (starter, options, targetName) => {
|
|
225
|
+
const generateProject = async (starter, options, targetName, autoConfirm = false) => {
|
|
75
226
|
const targetPath = path.resolve(process.cwd(), targetName);
|
|
76
227
|
|
|
77
228
|
if (fs.existsSync(targetPath)) {
|
|
78
|
-
|
|
79
|
-
{
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
229
|
+
if (autoConfirm) {
|
|
230
|
+
console.log(chalk.yellow(`Directory ${targetName} already exists. Overwriting...`));
|
|
231
|
+
} else {
|
|
232
|
+
const { replace } = await inquirer.prompt([
|
|
233
|
+
{
|
|
234
|
+
type: 'confirm',
|
|
235
|
+
name: 'replace',
|
|
236
|
+
message: `Directory ${targetName} already exists. Overwrite?`,
|
|
237
|
+
default: false
|
|
238
|
+
}
|
|
239
|
+
]);
|
|
240
|
+
if (!replace) return;
|
|
241
|
+
}
|
|
87
242
|
}
|
|
88
243
|
|
|
89
244
|
const spinner = ora(`Generating project ${targetName}...`).start();
|
|
@@ -133,7 +288,14 @@ module.exports = (args) => {
|
|
|
133
288
|
// Check if file or directory
|
|
134
289
|
const stat = await fs.promises.stat(srcPath);
|
|
135
290
|
const filterFunc = (src, dest) => {
|
|
136
|
-
|
|
291
|
+
const basename = path.basename(src);
|
|
292
|
+
// Exclude node_modules and runtime state files
|
|
293
|
+
if (basename === 'node_modules') return false;
|
|
294
|
+
// Exclude runtime state files in .store (uuid, workspace, runtime json)
|
|
295
|
+
if (basename === '.uuid' ||
|
|
296
|
+
basename === '.workspace.json' ||
|
|
297
|
+
basename === '.node-runtime.json' ||
|
|
298
|
+
basename === '.rls.json') return false;
|
|
137
299
|
return true;
|
|
138
300
|
}
|
|
139
301
|
|
|
@@ -175,16 +337,23 @@ module.exports = (args) => {
|
|
|
175
337
|
description: 'Create a new project from Cadriciel templates',
|
|
176
338
|
},
|
|
177
339
|
start: async (cmdArgs) => {
|
|
340
|
+
// Parse CLI arguments
|
|
341
|
+
const opts = parseArgs(cmdArgs);
|
|
342
|
+
|
|
343
|
+
// Show help if requested
|
|
344
|
+
if (opts.help) {
|
|
345
|
+
showHelp();
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
|
|
178
349
|
console.log(chalk.bold.cyan('Cadriciel Project Generator'));
|
|
179
350
|
|
|
180
|
-
//
|
|
181
|
-
const
|
|
182
|
-
// Remove --test from args so it doesn't interfere with project name
|
|
183
|
-
const filteredArgs = cmdArgs.filter(arg => arg !== '--test');
|
|
351
|
+
// Determine if running in automated mode
|
|
352
|
+
const isAutomated = opts.template && opts.name && (opts.features || opts.allFeatures || opts.defaults);
|
|
184
353
|
|
|
185
354
|
// 1. Fetch Starters
|
|
186
355
|
let startersPath;
|
|
187
|
-
if (
|
|
356
|
+
if (opts.test) {
|
|
188
357
|
console.log(chalk.yellow('Running in TEST mode: Using current directory for starters.'));
|
|
189
358
|
startersPath = process.cwd();
|
|
190
359
|
} else {
|
|
@@ -199,12 +368,26 @@ module.exports = (args) => {
|
|
|
199
368
|
return;
|
|
200
369
|
}
|
|
201
370
|
|
|
202
|
-
//
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
371
|
+
// Handle --list: show available templates and exit
|
|
372
|
+
if (opts.list) {
|
|
373
|
+
listTemplates(starters);
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// Handle --list-features: show features for a template and exit
|
|
378
|
+
if (opts.listFeatures) {
|
|
379
|
+
const starter = starters.find(s => s.id === opts.listFeatures);
|
|
380
|
+
if (!starter) {
|
|
381
|
+
console.log(chalk.red(`Template '${opts.listFeatures}' not found.`));
|
|
382
|
+
console.log(chalk.gray('Use --list to see available templates.'));
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
listFeatures(starter);
|
|
386
|
+
return;
|
|
206
387
|
}
|
|
207
|
-
|
|
388
|
+
|
|
389
|
+
// 2. Get Project Name
|
|
390
|
+
let targetName = opts.name;
|
|
208
391
|
if (!targetName) {
|
|
209
392
|
const answers = await inquirer.prompt([
|
|
210
393
|
{
|
|
@@ -218,25 +401,38 @@ module.exports = (args) => {
|
|
|
218
401
|
}
|
|
219
402
|
|
|
220
403
|
// 3. Select Starter
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
value: s.id
|
|
229
|
-
}))
|
|
404
|
+
let starter;
|
|
405
|
+
if (opts.template) {
|
|
406
|
+
starter = starters.find(s => s.id === opts.template);
|
|
407
|
+
if (!starter) {
|
|
408
|
+
console.log(chalk.red(`Template '${opts.template}' not found.`));
|
|
409
|
+
console.log(chalk.gray('Use --list to see available templates.'));
|
|
410
|
+
return;
|
|
230
411
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
412
|
+
console.log(chalk.gray(`Using template: ${starter.name}`));
|
|
413
|
+
} else if (opts.defaults || opts.allFeatures || opts.features) {
|
|
414
|
+
// In automated mode without explicit template, use first available
|
|
415
|
+
starter = starters[0];
|
|
416
|
+
console.log(chalk.gray(`Using default template: ${starter.name}`));
|
|
417
|
+
} else {
|
|
418
|
+
const { selectedStarterId } = await inquirer.prompt([
|
|
419
|
+
{
|
|
420
|
+
type: 'list',
|
|
421
|
+
name: 'selectedStarterId',
|
|
422
|
+
message: 'Select a template:',
|
|
423
|
+
choices: starters.map(s => ({
|
|
424
|
+
name: `${chalk.bold(s.name)} - ${s.description}${opts.test ? ` (${s.path})` : ''}`,
|
|
425
|
+
value: s.id
|
|
426
|
+
}))
|
|
427
|
+
}
|
|
428
|
+
]);
|
|
429
|
+
starter = starters.find(s => s.id === selectedStarterId);
|
|
430
|
+
}
|
|
234
431
|
|
|
235
432
|
// 4. Select Features
|
|
236
|
-
// Determine selectable features from config
|
|
237
433
|
const optionsConfig = starter.config.options || {};
|
|
238
434
|
const selectableFeatures = Object.keys(optionsConfig)
|
|
239
|
-
.filter(key => optionsConfig[key].type !== 'core')
|
|
435
|
+
.filter(key => optionsConfig[key].type !== 'core')
|
|
240
436
|
.map(key => ({
|
|
241
437
|
name: optionsConfig[key].description || key,
|
|
242
438
|
value: key,
|
|
@@ -244,7 +440,26 @@ module.exports = (args) => {
|
|
|
244
440
|
}));
|
|
245
441
|
|
|
246
442
|
let selectedFeatures = [];
|
|
247
|
-
|
|
443
|
+
|
|
444
|
+
if (opts.allFeatures) {
|
|
445
|
+
// Enable all features
|
|
446
|
+
selectedFeatures = selectableFeatures.map(f => f.value);
|
|
447
|
+
console.log(chalk.gray(`Enabling all features: ${selectedFeatures.join(', ') || 'none'}`));
|
|
448
|
+
} else if (opts.features) {
|
|
449
|
+
// Use specified features
|
|
450
|
+
const validFeatures = selectableFeatures.map(f => f.value);
|
|
451
|
+
const invalidFeatures = opts.features.filter(f => !validFeatures.includes(f));
|
|
452
|
+
if (invalidFeatures.length > 0) {
|
|
453
|
+
console.log(chalk.yellow(`Warning: Unknown features ignored: ${invalidFeatures.join(', ')}`));
|
|
454
|
+
}
|
|
455
|
+
selectedFeatures = opts.features.filter(f => validFeatures.includes(f));
|
|
456
|
+
console.log(chalk.gray(`Selected features: ${selectedFeatures.join(', ') || 'none'}`));
|
|
457
|
+
} else if (opts.defaults) {
|
|
458
|
+
// Use default features
|
|
459
|
+
selectedFeatures = selectableFeatures.filter(f => f.checked).map(f => f.value);
|
|
460
|
+
console.log(chalk.gray(`Using default features: ${selectedFeatures.join(', ') || 'none'}`));
|
|
461
|
+
} else if (selectableFeatures.length > 0) {
|
|
462
|
+
// Interactive mode
|
|
248
463
|
const featureAnswers = await inquirer.prompt([
|
|
249
464
|
{
|
|
250
465
|
type: 'checkbox',
|
|
@@ -257,9 +472,9 @@ module.exports = (args) => {
|
|
|
257
472
|
}
|
|
258
473
|
|
|
259
474
|
// 5. Generate
|
|
260
|
-
await generateProject(starter, { selectedFeatures }, targetName);
|
|
475
|
+
await generateProject(starter, { selectedFeatures }, targetName, opts.yes);
|
|
261
476
|
|
|
262
|
-
if (
|
|
477
|
+
if (opts.test) process.exit(0);
|
|
263
478
|
},
|
|
264
479
|
};
|
|
265
480
|
};
|
package/cli/global/doctor.js
CHANGED
|
@@ -1,226 +1,94 @@
|
|
|
1
1
|
module.exports = (args) => {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
return checkInstallation(candidate.command, postProcess).catch(() =>
|
|
30
|
-
tryCandidate(index + 1)
|
|
31
|
-
);
|
|
32
|
-
};
|
|
33
|
-
return tryCandidate(0);
|
|
34
|
-
};
|
|
35
|
-
const PACKAGE_MANAGERS = [
|
|
2
|
+
const { exec } = require('child_process');
|
|
3
|
+
const Listr = require('listr');
|
|
4
|
+
const chalk = require('chalk-v2');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
const platform = os.platform();
|
|
7
|
+
const checkInstallation = (command, postProcess = (output) => output) => {
|
|
8
|
+
return new Promise((resolve, reject) => {
|
|
9
|
+
exec(command, (error, stdout) => {
|
|
10
|
+
if (error) {
|
|
11
|
+
reject(new Error('Not installed'));
|
|
12
|
+
} else {
|
|
13
|
+
resolve(postProcess(stdout.trim()));
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
return {
|
|
19
|
+
info: {
|
|
20
|
+
title: 'doctor',
|
|
21
|
+
description: `Affichage des pré-requis du cadriciel.`,
|
|
22
|
+
},
|
|
23
|
+
start: () => {
|
|
24
|
+
console.log(' ');
|
|
25
|
+
|
|
26
|
+
console.log(' 🏥 ' + chalk.bold('Pré-requis globaux'));
|
|
27
|
+
console.log(' ');
|
|
28
|
+
const myTasks = [
|
|
36
29
|
{
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
command: 'bun --version',
|
|
40
|
-
detectors: ['bun.lock', 'bun.lockb'],
|
|
30
|
+
title: 'Homebrew',
|
|
31
|
+
task: () => checkInstallation('brew --version'),
|
|
41
32
|
},
|
|
42
33
|
{
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
command: 'pnpm -v',
|
|
46
|
-
detectors: ['pnpm-lock.yaml', 'pnpm-lock.yml'],
|
|
34
|
+
title: 'Pnpm',
|
|
35
|
+
task: () => checkInstallation('pnpm -v'),
|
|
47
36
|
},
|
|
48
37
|
{
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
command: 'yarn -v',
|
|
52
|
-
detectors: ['yarn.lock'],
|
|
38
|
+
title: 'Git',
|
|
39
|
+
task: () => checkInstallation('git --version'),
|
|
53
40
|
},
|
|
54
41
|
{
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
command: 'npm -v',
|
|
58
|
-
detectors: ['package-lock.json'],
|
|
59
|
-
},
|
|
60
|
-
];
|
|
61
|
-
const findCadricielContext = () => {
|
|
62
|
-
let currentPath = process.cwd();
|
|
63
|
-
const rootPath = path.parse(currentPath).root;
|
|
64
|
-
while (true) {
|
|
65
|
-
const versionPath = path.join(currentPath, '.cadriciel', 'version.json');
|
|
66
|
-
if (fs.existsSync(versionPath)) {
|
|
67
|
-
try {
|
|
68
|
-
const version = JSON.parse(fs.readFileSync(versionPath, 'utf8'));
|
|
69
|
-
return {
|
|
70
|
-
architecture: typeof version.name === 'string' ? version.name : null,
|
|
71
|
-
projectRoot: currentPath,
|
|
72
|
-
};
|
|
73
|
-
} catch (error) {
|
|
74
|
-
return {
|
|
75
|
-
architecture: null,
|
|
76
|
-
projectRoot: currentPath,
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
if (currentPath === rootPath) break;
|
|
81
|
-
currentPath = path.dirname(currentPath);
|
|
82
|
-
}
|
|
83
|
-
return {
|
|
84
|
-
architecture: null,
|
|
85
|
-
projectRoot: null,
|
|
86
|
-
};
|
|
87
|
-
};
|
|
88
|
-
const detectPackageManager = (projectRoot) => {
|
|
89
|
-
const searchRoot = projectRoot || process.cwd();
|
|
90
|
-
const packageJsonPath = path.join(searchRoot, 'package.json');
|
|
91
|
-
if (fs.existsSync(packageJsonPath)) {
|
|
92
|
-
try {
|
|
93
|
-
const pkgJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
94
|
-
if (pkgJson.packageManager && typeof pkgJson.packageManager === 'string') {
|
|
95
|
-
const requested = pkgJson.packageManager.split('@')[0].trim().toLowerCase();
|
|
96
|
-
const pm = PACKAGE_MANAGERS.find((el) => el.id === requested);
|
|
97
|
-
if (pm) return pm;
|
|
98
|
-
}
|
|
99
|
-
} catch (error) { }
|
|
100
|
-
}
|
|
101
|
-
for (const pm of PACKAGE_MANAGERS) {
|
|
102
|
-
if (
|
|
103
|
-
pm.detectors.some((fileName) =>
|
|
104
|
-
fs.existsSync(path.join(searchRoot, fileName))
|
|
105
|
-
)
|
|
106
|
-
) {
|
|
107
|
-
return pm;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
return PACKAGE_MANAGERS.find((el) => el.id === 'npm');
|
|
111
|
-
};
|
|
112
|
-
const createNodeArchitectureTasks = (projectRoot) => {
|
|
113
|
-
const detectedManager = detectPackageManager(projectRoot);
|
|
114
|
-
const tasks = [
|
|
115
|
-
{
|
|
116
|
-
title: 'Node ou Bun',
|
|
117
|
-
task: () =>
|
|
118
|
-
checkOneOfInstallations(
|
|
119
|
-
[
|
|
120
|
-
{ command: 'node -v', label: 'Node' },
|
|
121
|
-
{ command: 'bun --version', label: 'Bun' },
|
|
122
|
-
],
|
|
123
|
-
'Node ou Bun'
|
|
124
|
-
),
|
|
125
|
-
},
|
|
126
|
-
{
|
|
127
|
-
title: 'npm ou Bun',
|
|
128
|
-
task: () =>
|
|
129
|
-
checkOneOfInstallations(
|
|
130
|
-
[
|
|
131
|
-
{ command: 'npm -v', label: 'npm' },
|
|
132
|
-
{ command: 'bun --version', label: 'Bun' },
|
|
133
|
-
],
|
|
134
|
-
'npm ou Bun'
|
|
135
|
-
),
|
|
136
|
-
},
|
|
137
|
-
];
|
|
138
|
-
if (detectedManager) {
|
|
139
|
-
tasks.push({
|
|
140
|
-
title: `Gestionnaire (${detectedManager.displayName})`,
|
|
141
|
-
task: () => checkInstallation(detectedManager.command),
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
tasks.push(
|
|
145
|
-
{
|
|
146
|
-
title: 'Docker',
|
|
147
|
-
task: () => checkInstallation('docker ps'),
|
|
148
|
-
},
|
|
149
|
-
{
|
|
150
|
-
title: 'Docker Compose',
|
|
151
|
-
task: () => checkInstallation('docker-compose --version'),
|
|
152
|
-
}
|
|
153
|
-
);
|
|
154
|
-
return tasks;
|
|
155
|
-
};
|
|
156
|
-
const runArchitectureDoctor = ({ architecture, projectRoot }) => {
|
|
157
|
-
if (!architecture) {
|
|
158
|
-
if (!projectRoot) {
|
|
159
|
-
console.log(' ');
|
|
160
|
-
console.log(
|
|
161
|
-
chalk.yellow(
|
|
162
|
-
" ⚠️ Impossible de détecter l'architecture du cadriciel (.cadriciel/version.json introuvable)."
|
|
163
|
-
)
|
|
164
|
-
);
|
|
165
|
-
}
|
|
166
|
-
return Promise.resolve();
|
|
167
|
-
}
|
|
168
|
-
const normalized = architecture.toLowerCase();
|
|
169
|
-
if (normalized === 'node') {
|
|
170
|
-
console.log(' ');
|
|
171
|
-
console.log(' 🧱 ' + chalk.bold('Pré-requis architecture Node'));
|
|
172
|
-
console.log(' ');
|
|
173
|
-
const nodeTasks = new Listr(createNodeArchitectureTasks(projectRoot), {
|
|
174
|
-
concurrent: true,
|
|
175
|
-
exitOnError: false,
|
|
176
|
-
});
|
|
177
|
-
return nodeTasks.run().catch(() => { });
|
|
178
|
-
}
|
|
179
|
-
console.log(' ');
|
|
180
|
-
console.log(' 🧱 ' + chalk.bold('Pré-requis architecture'));
|
|
181
|
-
console.log(' ');
|
|
182
|
-
console.log(
|
|
183
|
-
chalk.yellow(
|
|
184
|
-
` Architecture '${architecture}' détectée mais non prise en charge par ce docteur.`
|
|
185
|
-
)
|
|
186
|
-
);
|
|
187
|
-
return Promise.resolve();
|
|
188
|
-
};
|
|
189
|
-
return {
|
|
190
|
-
info: {
|
|
191
|
-
title: 'doctor',
|
|
192
|
-
description: `Affichage des pré-requis du cadriciel.`,
|
|
42
|
+
title: 'Java',
|
|
43
|
+
task: () => checkInstallation('java --version'),
|
|
193
44
|
},
|
|
194
|
-
|
|
195
|
-
|
|
45
|
+
];
|
|
46
|
+
if (platform === 'linux ') myTasks.splice(0, 1);
|
|
47
|
+
if (platform === 'win32') myTasks.splice(0, 1);
|
|
196
48
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
title: 'Git',
|
|
202
|
-
task: () => checkInstallation('git --version'),
|
|
203
|
-
},
|
|
204
|
-
{
|
|
205
|
-
title: 'Java',
|
|
206
|
-
task: () => checkInstallation('java --version'),
|
|
207
|
-
},
|
|
208
|
-
];
|
|
209
|
-
if (platform === 'linux') myTasks.splice(0, 1);
|
|
210
|
-
if (platform === 'win32') myTasks.splice(0, 1);
|
|
49
|
+
const tasks = new Listr(myTasks, {
|
|
50
|
+
concurrent: true,
|
|
51
|
+
exitOnError: false,
|
|
52
|
+
});
|
|
211
53
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
54
|
+
const dockerTasks = new Listr(
|
|
55
|
+
[
|
|
56
|
+
{
|
|
57
|
+
title: 'Docker',
|
|
58
|
+
task: () => checkInstallation('docker ps'),
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
title: 'Docker Compose',
|
|
62
|
+
task: () => checkInstallation('docker-compose --version'),
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
{ concurrent: true, exitOnError: false }
|
|
66
|
+
);
|
|
216
67
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
68
|
+
tasks
|
|
69
|
+
.run()
|
|
70
|
+
.then(() => {
|
|
71
|
+
console.log(' ');
|
|
72
|
+
console.log(
|
|
73
|
+
' 📦 ' +
|
|
74
|
+
chalk.bold('Pré-requis Docker') +
|
|
75
|
+
' (si vous utilisez docker)'
|
|
76
|
+
);
|
|
77
|
+
console.log(' ');
|
|
78
|
+
dockerTasks.run().then(()=>{
|
|
79
|
+
}).catch((err) => {});
|
|
80
|
+
})
|
|
81
|
+
.catch((err) => {
|
|
82
|
+
console.log(' ');
|
|
83
|
+
console.log(
|
|
84
|
+
' 📦 ' +
|
|
85
|
+
chalk.bold('Pré-requis Docker') +
|
|
86
|
+
' (si vous utilisez docker)'
|
|
87
|
+
);
|
|
88
|
+
console.log(' ');
|
|
89
|
+
dockerTasks.run().then(()=>{
|
|
90
|
+
}).catch((err) => {});
|
|
91
|
+
});
|
|
92
|
+
},
|
|
93
|
+
};
|
|
226
94
|
};
|