create-fleetbo-project 1.0.19 → 1.0.21

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,154 @@
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
+ */
76
+ /**
77
+ * Fonction Principale Asynchrone (Version corrigée)
78
+ */
75
79
  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');
80
+ console.log(`\nCréation de votre projet Fleetbo "${projectName}"...`);
79
81
 
80
82
  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
- }
102
-
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
- }
83
+ // Étape 1 & 2 : Télécharger et décompresser de manière sécurisée
84
+ console.log(' [1/5] 📥 Téléchargement du template...');
85
+ await new Promise((resolve, reject) => {
86
+ https.get(repoUrl, (response) => {
87
+ // Gérer les redirections (très courant avec GitHub)
88
+ if (response.statusCode === 301 || response.statusCode === 302) {
89
+ console.log(' -> Redirection détectée, suivi du lien...');
90
+ https.get(response.headers.location, (redirectResponse) => {
91
+ if (redirectResponse.statusCode !== 200) {
92
+ return reject(new Error(`Échec du téléchargement après redirection. Code de statut: ${redirectResponse.statusCode}`));
93
+ }
94
+ redirectResponse.pipe(unzipper.Extract({ path: '.' }))
95
+ .on('finish', resolve)
96
+ .on('error', (err) => reject(new Error(`Erreur lors de la décompression: ${err.message}`)));
97
+ }).on('error', (err) => reject(new Error(`Erreur réseau après redirection: ${err.message}`)));
98
+ return;
99
+ }
100
+
101
+ // Gérer les erreurs directes (ex: 404 Dépôt non trouvé)
102
+ if (response.statusCode !== 200) {
103
+ return reject(new Error(`Échec du téléchargement du template. Code de statut: ${response.statusCode}`));
104
+ }
105
+
106
+ // Si le code est 200 OK, on décompresse
107
+ response.pipe(unzipper.Extract({ path: '.' }))
108
+ .on('finish', resolve)
109
+ .on('error', (err) => reject(new Error(`Erreur lors de la décompression: ${err.message}`)));
110
+
111
+ }).on('error', (err) => reject(new Error(`Erreur réseau lors du téléchargement: ${err.message}`)));
112
+ });
107
113
 
108
- fs.renameSync(extractedDir, projectName);
109
- spinner.succeed(chalk.green('Fichiers décompressés.'));
114
+ console.log(' [2/5] ✅ Template téléchargé et décompressé.');
110
115
 
116
+ // Le reste du script continue ici
111
117
  process.chdir(projectName);
118
+ console.log(' [3/5] 🔑 Récupération des clés de projet...');
119
+ const keys = await fetchProjectKeys(bootstrapToken);
120
+ if (!keys.enterpriseId || !keys.fleetboDBKey) {
121
+ throw new Error("Les clés reçues du serveur sont invalides.");
122
+ }
112
123
 
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');
124
+ // 4. Créer le fichier .env avec les clés
125
+ const envContent = `REACT_APP_FLEETBO_DB_KEY=${keys.fleetboDBKey}\nREACT_APP_ENTERPRISE_ID=${keys.enterpriseId}\n`;
126
+ fs.writeFileSync(path.join(process.cwd(), '.env'), envContent, 'utf8');
127
+ console.log(' [4/5] ✅ Fichier .env configuré avec succès.');
116
128
 
129
+ // 5. Installer les dépendances
130
+ console.log(' [5/5] 📦 Installation des dépendances (cela peut prendre quelques minutes)...');
131
+ execSync('npm install', { stdio: 'inherit' });
132
+
133
+ // Mise à jour du package.json
117
134
  const packageJsonPath = path.join(process.cwd(), 'package.json');
118
135
  const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
119
136
  packageJson.name = projectName;
120
137
  fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2), 'utf8');
121
- spinner.succeed(chalk.green('Projet configuré.'));
122
-
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
138
 
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`));
139
+ console.log('\n🚀 Votre projet Fleetbo est prêt !');
140
+ console.log(`\nPour commencer, exécutez les commandes suivantes :`);
141
+ console.log(` cd ${projectName}`);
142
+ console.log(` npm start`);
131
143
 
132
144
  } 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);
145
+ console.error('\n❌ Une erreur est survenue lors de la création du projet :', error.message);
146
+ // Nettoyage en cas d'erreur
147
+ const dirToDelete = path.join(process.cwd(), projectName);
148
+ if (fs.existsSync(dirToDelete)) {
149
+ console.log(' Nettoyage du répertoire du projet...');
150
+ fs.rmSync(dirToDelete, { recursive: true, force: true });
138
151
  }
139
-
140
- console.error(chalk.red('\n❌ Une erreur est survenue :'), error.response ? error.response.data : error.message);
141
152
  process.exit(1);
142
153
  }
143
154
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-fleetbo-project",
3
- "version": "1.0.19",
3
+ "version": "1.0.21",
4
4
  "description": "Creates a new Fleetbo project.",
5
5
  "main": "install-react-template.js",
6
6
  "bin": {