create-fleetbo-project 1.0.32 → 1.0.34

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.
@@ -6,11 +6,23 @@ const path = require('path');
6
6
  const https = require('https');
7
7
  const unzipper = require('unzipper');
8
8
 
9
+ // --- Vérification de la version de Node.js ---
10
+ const [major, minor] = process.versions.node.split('.').map(parseFloat);
11
+ if (major < 16 || (major === 16 && minor < 7)) {
12
+ console.error(`\n❌ Erreur : Ce script requiert Node.js v16.7.0 ou une version supérieure pour fonctionner correctement.`);
13
+ console.error(` Votre version actuelle est ${process.versions.node}.`);
14
+ console.log(` Veuillez mettre à jour votre installation de Node.js.`);
15
+ process.exit(1);
16
+ }
17
+
9
18
  // --- Configuration ---
10
- const repoOwner = 'FleetFleetbo';
11
- const repoName = 'dev.fleetbo.io';
12
- const branchName = 'master';
19
+ const repoOwner = 'FleetFleetbo'; // Assurez-vous que c'est le bon nom d'utilisateur GitHub
20
+ const repoName = 'dev.fleetbo.io'; // Assurez-vous que c'est le bon nom de dépôt
21
+ const branchName = 'master'; // Le nom de la branche est maintenant configurable
22
+
13
23
  const repoUrl = `https://github.com/${repoOwner}/${repoName}/archive/refs/heads/${branchName}.zip`;
24
+
25
+ // URL de votre Cloud Function.
14
26
  const bootstrapUrl = 'https://us-central1-myapp-259bf.cloudfunctions.net/bootstrapProject';
15
27
 
16
28
  // --- Analyse des Arguments ---
@@ -24,7 +36,6 @@ if (!projectNameArg) {
24
36
  process.exit(1);
25
37
  }
26
38
 
27
- const projectName = projectNameArg;
28
39
  const bootstrapToken = tokenArg ? tokenArg.split('=')[1] : null;
29
40
 
30
41
  if (!bootstrapToken) {
@@ -33,82 +44,101 @@ if (!bootstrapToken) {
33
44
  process.exit(1);
34
45
  }
35
46
 
47
+ const projectName = projectNameArg;
48
+
36
49
  /**
37
50
  * Fonction pour appeler la Cloud Function et récupérer les clés.
38
51
  */
39
52
  function fetchProjectKeys(token) {
40
- return new Promise((resolve, reject) => {
41
- const postData = JSON.stringify({ token });
42
- const options = {
43
- method: 'POST',
44
- headers: {
45
- 'Content-Type': 'application/json',
46
- 'Content-Length': Buffer.byteLength(postData)
47
- }
48
- };
49
-
50
- const req = https.request(bootstrapUrl, options, (res) => {
51
- let data = '';
52
- res.on('data', (chunk) => { data += chunk; });
53
- res.on('end', () => {
54
- if (res.statusCode >= 200 && res.statusCode < 300) {
55
- resolve(JSON.parse(data));
56
- } else {
57
- const errorMsg = JSON.parse(data).error || `Erreur serveur (code: ${res.statusCode})`;
58
- reject(new Error(errorMsg));
59
- }
60
- });
53
+ return new Promise((resolve, reject) => {
54
+ const postData = JSON.stringify({ token });
55
+ const options = { method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(postData) } };
56
+ const req = https.request(bootstrapUrl, options, (res) => {
57
+ let data = '';
58
+ res.on('data', (chunk) => { data += chunk; });
59
+ res.on('end', () => {
60
+ if (res.statusCode >= 200 && res.statusCode < 300) {
61
+ try {
62
+ resolve(JSON.parse(data));
63
+ } catch (e) {
64
+ reject(new Error('Réponse invalide du serveur de clés.'));
65
+ }
66
+ } else {
67
+ const errorMsg = JSON.parse(data).error || `Erreur serveur (code: ${res.statusCode})`;
68
+ reject(new Error(errorMsg));
69
+ }
70
+ });
71
+ });
72
+ req.on('error', (e) => reject(e));
73
+ req.write(postData);
74
+ req.end();
61
75
  });
62
-
63
- req.on('error', (e) => reject(e));
64
- req.write(postData);
65
- req.end();
66
- });
67
76
  }
68
77
 
69
- // --- Fonction Principale Asynchrone ---
78
+ /**
79
+ * Fonction Principale Asynchrone (Version pro avec téléchargement direct et gestion de fichiers robuste)
80
+ */
70
81
  async function setupProject() {
71
82
  console.log(`\nCréation de votre projet Fleetbo "${projectName}"...`);
72
-
73
- try {
74
- // 1. Télécharger le template depuis GitHub
75
- console.log(' [1/4] 📥 Téléchargement du template...');
76
- const response = await new Promise((resolve, reject) => {
77
- https.get(repoUrl, res => resolve(res)).on('error', err => reject(err));
78
- });
83
+ const projectDir = path.join(process.cwd(), projectName);
84
+ const tempDir = path.join(process.cwd(), `fleetbo-temp-${Date.now()}`);
79
85
 
80
- // 2. Décompresser l'archive
81
- console.log(' [2/4] 📦 Extraction du template...');
86
+ try {
87
+ // Étape 1 : Téléchargement et décompression
88
+ console.log(` [1/5] 📥 Téléchargement du template...`);
82
89
  await new Promise((resolve, reject) => {
83
- response.pipe(unzipper.Extract({ path: '.' }))
84
- .on('finish', resolve)
85
- .on('error', reject);
90
+ https.get(repoUrl, (response) => {
91
+ if (response.statusCode === 301 || response.statusCode === 302) {
92
+ return https.get(response.headers.location, (redirectResponse) => {
93
+ redirectResponse.pipe(unzipper.Extract({ path: tempDir }))
94
+ .on('finish', resolve)
95
+ .on('error', (err) => reject(new Error(`Erreur de décompression: ${err.message}`)));
96
+ }).on('error', (err) => reject(new Error(`Erreur réseau après redirection: ${err.message}`)));
97
+ }
98
+ if (response.statusCode !== 200) {
99
+ return reject(new Error(`Échec du téléchargement. Statut: ${response.statusCode}`));
100
+ }
101
+ response.pipe(unzipper.Extract({ path: tempDir }))
102
+ .on('finish', resolve)
103
+ .on('error', (err) => reject(new Error(`Erreur de décompression: ${err.message}`)));
104
+ }).on('error', (err) => reject(new Error(`Erreur réseau: ${err.message}`)));
86
105
  });
106
+ console.log(' [2/5] ✅ Template téléchargé. Organisation des fichiers...');
87
107
 
88
- // Le dossier décompressé aura un nom comme "dev.fleetbo.io-master", on le renomme
89
- fs.renameSync(`${repoName}-${branchName}`, projectName);
90
-
91
- // 3. Récupérer les clés du projet
92
- console.log(' [3/4] 🔑 Récupération des clés de projet...');
93
- const keys = await fetchProjectKeys(bootstrapToken);
108
+ // Étape 2 bis : Localiser la racine du projet dans le dossier décompressé
109
+ const unzippedBaseFolder = fs.readdirSync(tempDir)[0];
110
+ let sourceDir = path.join(tempDir, unzippedBaseFolder);
94
111
 
112
+ if (!fs.existsSync(path.join(sourceDir, 'package.json'))) {
113
+ const nestedProjectDir = fs.readdirSync(sourceDir).find(file => {
114
+ const fullPath = path.join(sourceDir, file);
115
+ return fs.statSync(fullPath).isDirectory() && fs.existsSync(path.join(fullPath, 'package.json'));
116
+ });
117
+ if (!nestedProjectDir) throw new Error('Impossible de trouver le fichier package.json dans le template téléchargé.');
118
+ sourceDir = path.join(sourceDir, nestedProjectDir);
119
+ }
120
+
121
+ // Étape 2 ter : Copier les fichiers vers la destination finale
122
+ fs.mkdirSync(projectDir, { recursive: true });
123
+ for (const file of fs.readdirSync(sourceDir)) {
124
+ fs.cpSync(path.join(sourceDir, file), path.join(projectDir, file), { recursive: true });
125
+ }
126
+
127
+ process.chdir(projectDir);
128
+ console.log(' [3/5] 🔑 Récupération des clés de projet...');
129
+ const keys = await fetchProjectKeys(bootstrapToken);
95
130
  if (!keys.enterpriseId || !keys.fleetboDBKey) {
96
- throw new Error("Les clés reçues du serveur sont invalides.");
131
+ throw new Error("Les clés reçues du serveur sont invalides.");
97
132
  }
98
133
 
99
- // 4. Configurer le fichier .env
134
+ console.log(' [4/5] ✅ Fichier .env configuré avec succès.');
100
135
  const envContent = `REACT_APP_FLEETBO_DB_KEY=${keys.fleetboDBKey}\nREACT_APP_ENTERPRISE_ID=${keys.enterpriseId}\n`;
101
- fs.writeFileSync(path.join(projectName, '.env'), envContent, 'utf8');
102
- console.log(' ✅ Fichier .env configuré avec succès.');
136
+ fs.writeFileSync(path.join(projectDir, '.env'), envContent, 'utf8');
103
137
 
104
- // 5. Se déplacer dans le nouveau dossier et installer les dépendances
105
- process.chdir(projectName);
106
-
107
- console.log(' [4/4] 📦 Installation des dépendances...');
138
+ console.log(' [5/5] 📦 Installation des dépendances...');
108
139
  execSync('npm install', { stdio: 'inherit' });
109
140
 
110
- // 6. Mettre à jour le package.json avec le nom du projet
111
- const packageJsonPath = path.join(process.cwd(), 'package.json');
141
+ const packageJsonPath = path.join(projectDir, 'package.json');
112
142
  const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
113
143
  packageJson.name = projectName;
114
144
  fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2), 'utf8');
@@ -120,13 +150,15 @@ async function setupProject() {
120
150
 
121
151
  } catch (error) {
122
152
  console.error('\n❌ Une erreur est survenue lors de la création du projet :', error.message);
123
-
124
- // Nettoyer en cas d'erreur
125
- if (fs.existsSync(projectName)) {
126
- fs.rmSync(projectName, { recursive: true, force: true });
153
+ if (fs.existsSync(projectDir)) {
154
+ fs.rmSync(projectDir, { recursive: true, force: true });
155
+ }
156
+ } finally {
157
+ if (fs.existsSync(tempDir)) {
158
+ fs.rmSync(tempDir, { recursive: true, force: true });
127
159
  }
128
- process.exit(1);
129
160
  }
130
161
  }
131
162
 
132
- setupProject();
163
+ setupProject();
164
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-fleetbo-project",
3
- "version": "1.0.32",
3
+ "version": "1.0.34",
4
4
  "description": "Creates a new Fleetbo project.",
5
5
  "main": "install-react-template.js",
6
6
  "bin": {