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.
- package/install-react-template.js +90 -65
- package/package.json +1 -1
|
@@ -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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
81
|
-
|
|
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
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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
|
-
//
|
|
89
|
-
fs.
|
|
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
|
-
|
|
123
|
+
throw new Error("Les clés reçues du serveur sont invalides.");
|
|
97
124
|
}
|
|
98
125
|
|
|
99
|
-
|
|
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(
|
|
102
|
-
console.log(' ✅ Fichier .env configuré avec succès.');
|
|
128
|
+
fs.writeFileSync(path.join(projectDir, '.env'), envContent, 'utf8');
|
|
103
129
|
|
|
104
|
-
|
|
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
|
-
//
|
|
111
|
-
const packageJsonPath = path.join(
|
|
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
|
-
|
|
125
|
-
|
|
126
|
-
|
|
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();
|