create-fleetbo-project 1.0.30 → 1.0.32
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/install-react-template.js +59 -184
- package/package.json +1 -1
|
@@ -10,7 +10,6 @@ const unzipper = require('unzipper');
|
|
|
10
10
|
const repoOwner = 'FleetFleetbo';
|
|
11
11
|
const repoName = 'dev.fleetbo.io';
|
|
12
12
|
const branchName = 'master';
|
|
13
|
-
|
|
14
13
|
const repoUrl = `https://github.com/${repoOwner}/${repoName}/archive/refs/heads/${branchName}.zip`;
|
|
15
14
|
const bootstrapUrl = 'https://us-central1-myapp-259bf.cloudfunctions.net/bootstrapProject';
|
|
16
15
|
|
|
@@ -25,6 +24,7 @@ if (!projectNameArg) {
|
|
|
25
24
|
process.exit(1);
|
|
26
25
|
}
|
|
27
26
|
|
|
27
|
+
const projectName = projectNameArg;
|
|
28
28
|
const bootstrapToken = tokenArg ? tokenArg.split('=')[1] : null;
|
|
29
29
|
|
|
30
30
|
if (!bootstrapToken) {
|
|
@@ -33,198 +33,86 @@ if (!bootstrapToken) {
|
|
|
33
33
|
process.exit(1);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
const projectName = projectNameArg;
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Fonction pour copier récursivement un dossier
|
|
40
|
-
*/
|
|
41
|
-
function copyRecursiveSync(src, dest) {
|
|
42
|
-
const exists = fs.existsSync(src);
|
|
43
|
-
const stats = exists && fs.statSync(src);
|
|
44
|
-
const isDirectory = exists && stats.isDirectory();
|
|
45
|
-
|
|
46
|
-
if (isDirectory) {
|
|
47
|
-
if (!fs.existsSync(dest)) {
|
|
48
|
-
fs.mkdirSync(dest, { recursive: true });
|
|
49
|
-
}
|
|
50
|
-
fs.readdirSync(src).forEach(childItemName => {
|
|
51
|
-
copyRecursiveSync(
|
|
52
|
-
path.join(src, childItemName),
|
|
53
|
-
path.join(dest, childItemName)
|
|
54
|
-
);
|
|
55
|
-
});
|
|
56
|
-
} else {
|
|
57
|
-
fs.copyFileSync(src, dest);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
36
|
/**
|
|
62
37
|
* Fonction pour appeler la Cloud Function et récupérer les clés.
|
|
63
38
|
*/
|
|
64
39
|
function fetchProjectKeys(token) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
req.on('error', (e) => reject(e));
|
|
87
|
-
req.write(postData);
|
|
88
|
-
req.end();
|
|
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
|
+
});
|
|
89
61
|
});
|
|
62
|
+
|
|
63
|
+
req.on('error', (e) => reject(e));
|
|
64
|
+
req.write(postData);
|
|
65
|
+
req.end();
|
|
66
|
+
});
|
|
90
67
|
}
|
|
91
68
|
|
|
92
|
-
|
|
93
|
-
* Fonction Principale Asynchrone
|
|
94
|
-
*/
|
|
69
|
+
// --- Fonction Principale Asynchrone ---
|
|
95
70
|
async function setupProject() {
|
|
96
71
|
console.log(`\nCréation de votre projet Fleetbo "${projectName}"...`);
|
|
97
|
-
|
|
98
|
-
const tempDir = path.join(process.cwd(), `fleetbo-temp-${Date.now()}`);
|
|
99
|
-
|
|
72
|
+
|
|
100
73
|
try {
|
|
101
|
-
//
|
|
102
|
-
console.log(
|
|
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
|
+
});
|
|
79
|
+
|
|
80
|
+
// 2. Décompresser l'archive
|
|
81
|
+
console.log(' [2/4] 📦 Extraction du template...');
|
|
103
82
|
await new Promise((resolve, reject) => {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
redirectResponse.pipe(unzipper.Extract({ path: tempDir }))
|
|
108
|
-
.on('close', () => {
|
|
109
|
-
// Attendre un peu pour s'assurer que tous les fichiers sont écrits
|
|
110
|
-
setTimeout(resolve, 500);
|
|
111
|
-
})
|
|
112
|
-
.on('error', (err) => reject(new Error(`Erreur de décompression: ${err.message}`)));
|
|
113
|
-
}).on('error', (err) => reject(new Error(`Erreur réseau après redirection: ${err.message}`)));
|
|
114
|
-
}
|
|
115
|
-
response.pipe(unzipper.Extract({ path: tempDir }))
|
|
116
|
-
.on('close', () => {
|
|
117
|
-
// Attendre un peu pour s'assurer que tous les fichiers sont écrits
|
|
118
|
-
setTimeout(resolve, 500);
|
|
119
|
-
})
|
|
120
|
-
.on('error', (err) => reject(new Error(`Erreur de décompression: ${err.message}`)));
|
|
121
|
-
}).on('error', (err) => reject(new Error(`Erreur réseau: ${err.message}`)));
|
|
83
|
+
response.pipe(unzipper.Extract({ path: '.' }))
|
|
84
|
+
.on('finish', resolve)
|
|
85
|
+
.on('error', reject);
|
|
122
86
|
});
|
|
123
|
-
|
|
124
|
-
console.log(' [2/5] ✅ Template téléchargé. Vérification...');
|
|
125
|
-
|
|
126
|
-
// Vérifier que l'extraction est complète
|
|
127
|
-
if (!fs.existsSync(tempDir) || fs.readdirSync(tempDir).length === 0) {
|
|
128
|
-
throw new Error('Le téléchargement ou l\'extraction a échoué');
|
|
129
|
-
}
|
|
130
87
|
|
|
131
|
-
//
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
const unzippedBaseFolder = tempContents[0];
|
|
137
|
-
let sourceDir = path.join(tempDir, unzippedBaseFolder);
|
|
138
|
-
|
|
139
|
-
if (!fs.existsSync(path.join(sourceDir, 'package.json'))) {
|
|
140
|
-
const nestedProjectDir = fs.readdirSync(sourceDir).find(file => {
|
|
141
|
-
const fullPath = path.join(sourceDir, file);
|
|
142
|
-
return fs.statSync(fullPath).isDirectory() && fs.existsSync(path.join(fullPath, 'package.json'));
|
|
143
|
-
});
|
|
144
|
-
if (!nestedProjectDir) throw new Error('Impossible de trouver package.json dans le template.');
|
|
145
|
-
sourceDir = path.join(sourceDir, nestedProjectDir);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
console.log(` ✅ Racine du projet trouvée: ${sourceDir}`);
|
|
149
|
-
|
|
150
|
-
// Lister tous les fichiers du source avant copie
|
|
151
|
-
function countFilesRecursive(dir) {
|
|
152
|
-
let count = 0;
|
|
153
|
-
const items = fs.readdirSync(dir);
|
|
154
|
-
items.forEach(item => {
|
|
155
|
-
const fullPath = path.join(dir, item);
|
|
156
|
-
const stat = fs.statSync(fullPath);
|
|
157
|
-
if (stat.isDirectory()) {
|
|
158
|
-
count += countFilesRecursive(fullPath);
|
|
159
|
-
} else {
|
|
160
|
-
count++;
|
|
161
|
-
}
|
|
162
|
-
});
|
|
163
|
-
return count;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
const totalSourceFiles = countFilesRecursive(sourceDir);
|
|
167
|
-
console.log(` → ${totalSourceFiles} fichiers au total dans le template`);
|
|
168
|
-
|
|
169
|
-
// Étape 3 : Copier RÉCURSIVEMENT tous les fichiers et dossiers
|
|
170
|
-
console.log(` [3/5] 📂 Copie de tous les fichiers du template...`);
|
|
171
|
-
|
|
172
|
-
// Vérifier que le répertoire source existe et contient des fichiers
|
|
173
|
-
if (!fs.existsSync(sourceDir)) {
|
|
174
|
-
throw new Error(`Le répertoire source n'existe pas: ${sourceDir}`);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
const sourceFiles = fs.readdirSync(sourceDir);
|
|
178
|
-
console.log(` → ${sourceFiles.length} éléments à la racine: ${sourceFiles.join(', ')}`);
|
|
179
|
-
|
|
180
|
-
// Copier récursivement tout le contenu
|
|
181
|
-
copyRecursiveSync(sourceDir, projectDir);
|
|
182
|
-
|
|
183
|
-
// Vérifier que la copie a réussi
|
|
184
|
-
const totalCopiedFiles = countFilesRecursive(projectDir);
|
|
185
|
-
console.log(` ✅ ${totalCopiedFiles} fichiers copiés dans le nouveau projet`);
|
|
186
|
-
|
|
187
|
-
if (totalCopiedFiles !== totalSourceFiles) {
|
|
188
|
-
console.warn(` ⚠️ ATTENTION: ${totalSourceFiles - totalCopiedFiles} fichiers manquants!`);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
if (!fs.existsSync(path.join(projectDir, 'package.json'))) {
|
|
192
|
-
throw new Error('Erreur: package.json n\'a pas été copié correctement');
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// Vérifier spécifiquement le dossier src
|
|
196
|
-
const srcDir = path.join(projectDir, 'src');
|
|
197
|
-
if (fs.existsSync(srcDir)) {
|
|
198
|
-
const srcFiles = fs.readdirSync(srcDir);
|
|
199
|
-
console.log(` → Dossier src contient: ${srcFiles.length} éléments`);
|
|
200
|
-
} else {
|
|
201
|
-
console.warn(' ⚠️ ATTENTION: Le dossier src n\'existe pas!');
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// Étape 4 : Récupération des clés
|
|
205
|
-
console.log(' [4/5] 🔑 Récupération des clés de projet...');
|
|
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...');
|
|
206
93
|
const keys = await fetchProjectKeys(bootstrapToken);
|
|
207
94
|
|
|
208
95
|
if (!keys.enterpriseId || !keys.fleetboDBKey) {
|
|
209
|
-
|
|
96
|
+
throw new Error("Les clés reçues du serveur sont invalides.");
|
|
210
97
|
}
|
|
211
98
|
|
|
212
|
-
//
|
|
99
|
+
// 4. Configurer le fichier .env
|
|
213
100
|
const envContent = `REACT_APP_FLEETBO_DB_KEY=${keys.fleetboDBKey}\nREACT_APP_ENTERPRISE_ID=${keys.enterpriseId}\n`;
|
|
214
|
-
fs.writeFileSync(path.join(
|
|
101
|
+
fs.writeFileSync(path.join(projectName, '.env'), envContent, 'utf8');
|
|
215
102
|
console.log(' ✅ Fichier .env configuré avec succès.');
|
|
216
103
|
|
|
217
|
-
//
|
|
218
|
-
|
|
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...');
|
|
108
|
+
execSync('npm install', { stdio: 'inherit' });
|
|
109
|
+
|
|
110
|
+
// 6. Mettre à jour le package.json avec le nom du projet
|
|
111
|
+
const packageJsonPath = path.join(process.cwd(), 'package.json');
|
|
219
112
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
220
113
|
packageJson.name = projectName;
|
|
221
114
|
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2), 'utf8');
|
|
222
115
|
|
|
223
|
-
// Étape 5 : Installation des dépendances
|
|
224
|
-
console.log(' [5/5] 📦 Installation des dépendances...');
|
|
225
|
-
process.chdir(projectDir);
|
|
226
|
-
execSync('npm install', { stdio: 'inherit' });
|
|
227
|
-
|
|
228
116
|
console.log('\n🚀 Votre projet Fleetbo est prêt !');
|
|
229
117
|
console.log(`\nPour commencer, exécutez les commandes suivantes :`);
|
|
230
118
|
console.log(` cd ${projectName}`);
|
|
@@ -232,25 +120,12 @@ async function setupProject() {
|
|
|
232
120
|
|
|
233
121
|
} catch (error) {
|
|
234
122
|
console.error('\n❌ Une erreur est survenue lors de la création du projet :', error.message);
|
|
235
|
-
console.error(' Détails:', error);
|
|
236
123
|
|
|
237
|
-
//
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
console.log(' 🧹 Nettoyage du projet incomplet...');
|
|
241
|
-
fs.rmSync(projectDir, { recursive: true, force: true });
|
|
124
|
+
// Nettoyer en cas d'erreur
|
|
125
|
+
if (fs.existsSync(projectName)) {
|
|
126
|
+
fs.rmSync(projectName, { recursive: true, force: true });
|
|
242
127
|
}
|
|
243
128
|
process.exit(1);
|
|
244
|
-
} finally {
|
|
245
|
-
// Attendre avant de nettoyer pour être sûr que tout est copié
|
|
246
|
-
if (fs.existsSync(tempDir)) {
|
|
247
|
-
console.log(' 🧹 Nettoyage du dossier temporaire...');
|
|
248
|
-
setTimeout(() => {
|
|
249
|
-
if (fs.existsSync(tempDir)) {
|
|
250
|
-
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
251
|
-
}
|
|
252
|
-
}, 1000);
|
|
253
|
-
}
|
|
254
129
|
}
|
|
255
130
|
}
|
|
256
131
|
|