create-fleetbo-project 1.0.32 → 1.0.33

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