create-fleetbo-project 1.0.18 → 1.0.20

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,143 +1,132 @@
1
1
  #!/usr/bin/env node
2
- // Fichier : install-react-template.js (Version corrigée avec téléchargement complet)
2
+
3
3
  const { execSync } = require('child_process');
4
4
  const fs = require('fs');
5
5
  const path = require('path');
6
6
  const https = require('https');
7
7
  const unzipper = require('unzipper');
8
- const axios = require('axios');
9
- const ora = require('ora');
10
- const chalk = require('chalk');
11
8
 
12
9
  // --- Configuration ---
13
- const projectName = process.argv[2];
14
- const tokenArgIndex = process.argv.indexOf('--token');
15
- const bootstrapToken = tokenArgIndex !== -1 ? process.argv[tokenArgIndex + 1] : null;
16
- const repoUrl = 'https://github.com/FleetFleetbo/dev.fleetbo.io/archive/refs/heads/main.zip';
10
+ const repoOwner = 'FleetFleetbo';
11
+ const repoName = 'dev.fleetbo.io';
12
+ const repoUrl = `https://github.com/${repoOwner}/${repoName}/archive/refs/heads/main.zip`;
13
+
14
+ // URL de votre Cloud Function. Remplacez par la vôtre !
17
15
  const bootstrapUrl = 'https://us-central1-myapp-259bf.cloudfunctions.net/bootstrapProject';
18
16
 
19
- // --- Validation ---
20
- if (!projectName || !bootstrapToken) {
21
- console.error(chalk.red('Erreur : Nom du projet ou token manquant.'));
22
- console.log('Usage: npx create-fleetbo-project <nom-du-projet> --token <votre-token>');
17
+ // --- Analyse des Arguments ---
18
+ const args = process.argv.slice(2);
19
+ const projectNameArg = args.find(arg => !arg.startsWith('--'));
20
+ const tokenArg = args.find(arg => arg.startsWith('--token='));
21
+
22
+ if (!projectNameArg) {
23
+ console.error('\n❌ Erreur : Veuillez spécifier un nom pour votre projet.');
24
+ console.log(' Usage: npx create-fleetbo-project <nom-du-projet> --token=<votre-token>');
23
25
  process.exit(1);
24
26
  }
25
27
 
26
- // --- Fonction pour télécharger le fichier ---
27
- function downloadFile(url, dest) {
28
- return new Promise((resolve, reject) => {
29
- const file = fs.createWriteStream(dest);
30
- https.get(url, (response) => {
31
- // Gérer les redirections
32
- if (response.statusCode === 302 || response.statusCode === 301) {
33
- file.close();
34
- fs.unlinkSync(dest);
35
- return downloadFile(response.headers.location, dest).then(resolve).catch(reject);
36
- }
37
-
38
- if (response.statusCode !== 200) {
39
- file.close();
40
- fs.unlinkSync(dest);
41
- return reject(new Error(`Échec du téléchargement: ${response.statusCode}`));
42
- }
43
-
44
- response.pipe(file);
45
-
46
- file.on('finish', () => {
47
- file.close(() => resolve());
48
- });
49
- }).on('error', (err) => {
50
- fs.unlinkSync(dest);
51
- reject(err);
52
- });
28
+ const bootstrapToken = tokenArg ? tokenArg.split('=')[1] : null;
53
29
 
54
- file.on('error', (err) => {
55
- fs.unlinkSync(dest);
56
- reject(err);
57
- });
58
- });
30
+ if (!bootstrapToken) {
31
+ console.error('\n❌ Erreur : Le token d\'amorçage est manquant.');
32
+ console.log(' Usage: npx create-fleetbo-project <nom-du-projet> --token=<votre-token>');
33
+ process.exit(1);
59
34
  }
60
35
 
61
- // --- Fonction pour décompresser ---
62
- function extractZip(zipPath, extractTo) {
63
- return new Promise((resolve, reject) => {
64
- fs.createReadStream(zipPath)
65
- .pipe(unzipper.Extract({ path: extractTo }))
66
- .on('close', () => {
67
- // Attendre un peu pour s'assurer que tous les fichiers sont écrits
68
- setTimeout(resolve, 500);
69
- })
70
- .on('error', reject);
71
- });
36
+ const projectName = projectNameArg;
37
+
38
+ /**
39
+ * Fonction pour appeler la Cloud Function et récupérer les clés.
40
+ */
41
+ function fetchProjectKeys(token) {
42
+ return new Promise((resolve, reject) => {
43
+ const postData = JSON.stringify({ token });
44
+
45
+ const options = {
46
+ method: 'POST',
47
+ headers: {
48
+ 'Content-Type': 'application/json',
49
+ 'Content-Length': Buffer.byteLength(postData),
50
+ },
51
+ };
52
+
53
+ const req = https.request(bootstrapUrl, options, (res) => {
54
+ let data = '';
55
+ res.on('data', (chunk) => { data += chunk; });
56
+ res.on('end', () => {
57
+ if (res.statusCode >= 200 && res.statusCode < 300) {
58
+ resolve(JSON.parse(data));
59
+ } else {
60
+ const errorMsg = JSON.parse(data).error || `Erreur serveur (code: ${res.statusCode})`;
61
+ reject(new Error(errorMsg));
62
+ }
63
+ });
64
+ });
65
+
66
+ req.on('error', (e) => reject(e));
67
+ req.write(postData);
68
+ req.end();
69
+ });
72
70
  }
73
71
 
74
- // --- Fonction Principale ---
72
+
73
+ /**
74
+ * Fonction Principale Asynchrone
75
+ */
75
76
  async function setupProject() {
76
- console.log(chalk.blue(`Création de votre projet Fleetbo "${projectName}"...`));
77
- const spinner = ora();
78
- const tempZip = path.join(process.cwd(), 'temp-fleetbo.zip');
77
+ console.log(`\nCréation de votre projet Fleetbo "${projectName}"...`);
79
78
 
80
79
  try {
81
- spinner.start('Récupération de la configuration sécurisée...');
82
- const response = await axios.post(bootstrapUrl, { token: bootstrapToken });
83
- const projectSecrets = response.data;
84
- spinner.succeed(chalk.green('Configuration récupérée !'));
85
-
86
- spinner.start('Téléchargement du template...');
87
- await downloadFile(repoUrl, tempZip);
88
- spinner.succeed(chalk.green('Template téléchargé.'));
89
-
90
- spinner.start('Décompression des fichiers...');
91
- await extractZip(tempZip, '.');
92
-
93
- // Supprimer le fichier ZIP temporaire
94
- fs.unlinkSync(tempZip);
95
-
96
- const extractedDir = 'dev.fleetbo.io-main';
97
-
98
- // Vérifier que le dossier existe
99
- if (!fs.existsSync(extractedDir)) {
100
- throw new Error(`Le dossier ${extractedDir} n'a pas été créé après la décompression`);
101
- }
80
+ // 1. Télécharger le template depuis GitHub
81
+ console.log(' [1/5] 📥 Téléchargement du template...');
82
+ const response = await new Promise((resolve, reject) => {
83
+ https.get(repoUrl, res => resolve(res)).on('error', err => reject(err));
84
+ });
102
85
 
103
- // Vérifier que le dossier cible n'existe pas déjà
104
- if (fs.existsSync(projectName)) {
105
- throw new Error(`Le dossier ${projectName} existe déjà`);
106
- }
86
+ // 2. Décompresser l'archive
87
+ await new Promise((resolve, reject) => {
88
+ response.pipe(unzipper.Extract({ path: '.' }))
89
+ .on('finish', resolve)
90
+ .on('error', reject);
91
+ });
92
+ fs.renameSync(`${repoName}-main`, projectName);
93
+ process.chdir(projectName);
94
+ console.log(' [2/5] ✅ Template téléchargé et décompressé.');
107
95
 
108
- fs.renameSync(extractedDir, projectName);
109
- spinner.succeed(chalk.green('Fichiers décompressés.'));
96
+ // 3. Récupérer les clés de projet sécurisées
97
+ console.log(' [3/5] 🔑 Récupération des clés de projet...');
98
+ const keys = await fetchProjectKeys(bootstrapToken);
99
+ if (!keys.enterpriseId || !keys.fleetboDBKey) {
100
+ throw new Error("Les clés reçues du serveur sont invalides.");
101
+ }
110
102
 
111
- process.chdir(projectName);
103
+ // 4. Créer le fichier .env avec les clés
104
+ const envContent = `REACT_APP_FLEETBO_DB_KEY=${keys.fleetboDBKey}\nREACT_APP_ENTERPRISE_ID=${keys.enterpriseId}\n`;
105
+ fs.writeFileSync(path.join(process.cwd(), '.env'), envContent, 'utf8');
106
+ console.log(' [4/5] ✅ Fichier .env configuré avec succès.');
112
107
 
113
- spinner.start('Configuration du projet...');
114
- const envContent = `REACT_APP_FLEETBO_DB_KEY="${projectSecrets.fleetboDB}"\nREACT_APP_ENTERPRISE_ID=${projectSecrets.appId}\n`;
115
- fs.writeFileSync('.env', envContent, 'utf8');
108
+ // 5. Installer les dépendances
109
+ console.log(' [5/5] 📦 Installation des dépendances (cela peut prendre quelques minutes)...');
110
+ execSync('npm install', { stdio: 'inherit' });
116
111
 
112
+ // Mise à jour du package.json (optionnel mais propre)
117
113
  const packageJsonPath = path.join(process.cwd(), 'package.json');
118
114
  const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
119
115
  packageJson.name = projectName;
120
116
  fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2), 'utf8');
121
- spinner.succeed(chalk.green('Projet configuré.'));
122
117
 
123
- spinner.start('Installation des dépendances (cela peut prendre quelques minutes)...');
124
- execSync('npm install', { stdio: 'inherit' });
125
- spinner.succeed(chalk.green('Dépendances installées.'));
126
-
127
- console.log(chalk.green.bold('\n🚀 Votre projet Fleetbo est prêt !'));
128
- console.log(`\nPour commencer :`);
129
- console.log(chalk.cyan(` cd ${projectName}`));
130
- console.log(chalk.cyan(` npm start`));
118
+ console.log('\n🚀 Votre projet Fleetbo est prêt !');
119
+ console.log(`\nPour commencer, exécutez les commandes suivantes :`);
120
+ console.log(` cd ${projectName}`);
121
+ console.log(` npm start`);
131
122
 
132
123
  } catch (error) {
133
- if (spinner.isSpinning) spinner.fail();
134
-
135
- // Nettoyer le fichier temporaire en cas d'erreur
136
- if (fs.existsSync(tempZip)) {
137
- fs.unlinkSync(tempZip);
124
+ console.error('\n❌ Une erreur est survenue lors de la création du projet :', error.message);
125
+ // Nettoyage en cas d'erreur
126
+ if (fs.existsSync(projectName)) {
127
+ console.log(' Nettoyage du répertoire du projet...');
128
+ fs.rmSync(projectName, { recursive: true, force: true });
138
129
  }
139
-
140
- console.error(chalk.red('\n❌ Une erreur est survenue :'), error.response ? error.response.data : error.message);
141
130
  process.exit(1);
142
131
  }
143
132
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-fleetbo-project",
3
- "version": "1.0.18",
3
+ "version": "1.0.20",
4
4
  "description": "Creates a new Fleetbo project.",
5
5
  "main": "install-react-template.js",
6
6
  "bin": {