create-fleetbo-project 1.2.14 → 1.2.17
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 +44 -70
- package/package.json +1 -1
|
@@ -12,10 +12,10 @@ const branchName = 'master';
|
|
|
12
12
|
const archiveUrl = `https://github.com/${repoOwner}/${repoName}/archive/refs/heads/${branchName}.tar.gz`;
|
|
13
13
|
const bootstrapUrl = 'https://us-central1-myapp-259bf.cloudfunctions.net/bootstrapProject';
|
|
14
14
|
|
|
15
|
-
// --- LE CONTENU DU GARDIEN (CLI.JS) - VERSION
|
|
15
|
+
// --- LE CONTENU DU GARDIEN (CLI.JS) - VERSION BYPASS WARNING ---
|
|
16
16
|
const CLI_SCRIPT_CONTENT = `#!/usr/bin/env node
|
|
17
17
|
|
|
18
|
-
const { spawn, exec } = require('child_process');
|
|
18
|
+
const { spawn, exec, execSync } = require('child_process');
|
|
19
19
|
const fs = require('fs');
|
|
20
20
|
const path = require('path');
|
|
21
21
|
const axios = require('axios');
|
|
@@ -24,11 +24,25 @@ const ngrok = require('ngrok');
|
|
|
24
24
|
const os = require('os');
|
|
25
25
|
|
|
26
26
|
const UPDATE_NETWORK_URL = 'https://us-central1-myapp-259bf.cloudfunctions.net/updateDeveloperNetwork';
|
|
27
|
-
const PORT = 3000;
|
|
27
|
+
const PORT = 3000;
|
|
28
|
+
const NGROK_PORT = 4040;
|
|
28
29
|
|
|
29
30
|
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
30
31
|
|
|
31
|
-
//
|
|
32
|
+
// Tueur de processus générique par port
|
|
33
|
+
function killProcessOnPort(port) {
|
|
34
|
+
try {
|
|
35
|
+
if (process.platform !== 'win32') {
|
|
36
|
+
const pid = execSync(\`lsof -ti:\${port} 2>/dev/null\`).toString().trim();
|
|
37
|
+
if (pid) {
|
|
38
|
+
const pids = pid.split('\\n').join(' ');
|
|
39
|
+
console.log(\`[Fleetbo] 🔫 Freeing port \${port} (PIDs: \${pids})...\`);
|
|
40
|
+
execSync(\`kill -9 \${pids}\`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
} catch (e) {}
|
|
44
|
+
}
|
|
45
|
+
|
|
32
46
|
async function forceKillNgrok() {
|
|
33
47
|
return new Promise((resolve) => {
|
|
34
48
|
const cmd = process.platform === 'win32' ? 'taskkill /IM ngrok.exe /F' : 'pkill ngrok';
|
|
@@ -37,8 +51,9 @@ async function forceKillNgrok() {
|
|
|
37
51
|
}
|
|
38
52
|
|
|
39
53
|
async function cleanupAndExit(code = 0) {
|
|
40
|
-
console.log('\\n[Fleetbo] 🛑 Stopping
|
|
54
|
+
console.log('\\n[Fleetbo] 🛑 Stopping services...');
|
|
41
55
|
try { await ngrok.kill(); } catch(e){}
|
|
56
|
+
killProcessOnPort(PORT);
|
|
42
57
|
process.exit(code);
|
|
43
58
|
}
|
|
44
59
|
|
|
@@ -47,10 +62,13 @@ process.on('SIGTERM', () => cleanupAndExit(0));
|
|
|
47
62
|
|
|
48
63
|
async function syncFirebase(keyApp, networkUrl) {
|
|
49
64
|
try {
|
|
65
|
+
// Si on utilise l'auth basique, l'URL inclut user:pass@... pour faciliter l'accès si besoin
|
|
66
|
+
// Mais pour le simulateur, mieux vaut envoyer l'URL standard et laisser le navigateur demander.
|
|
50
67
|
await axios.post(UPDATE_NETWORK_URL, { keyApp, networkUrl });
|
|
51
68
|
console.log('\\n[Fleetbo] ---------------------------------------------------');
|
|
52
69
|
console.log(\`[Fleetbo] ✅ Tunnel Active: \${networkUrl}\`);
|
|
53
70
|
console.log(\`[Fleetbo] 🚀 Simulator: https://fleetbo.io/studio/view/\${keyApp}\`);
|
|
71
|
+
console.log(\`[Fleetbo] 🔑 Credentials: User="fleetbo", Pass="admin"\`); // RAPPEL POUR LE DEV
|
|
54
72
|
console.log('[Fleetbo] ---------------------------------------------------\\n');
|
|
55
73
|
} catch (err) {
|
|
56
74
|
console.error(\`[Fleetbo] ⚠️ Sync Error: \${err.message}\`);
|
|
@@ -60,9 +78,10 @@ async function syncFirebase(keyApp, networkUrl) {
|
|
|
60
78
|
async function runGuardian() {
|
|
61
79
|
console.log(\`[Fleetbo] 🛡️ Starting Fleetbo Guardian on \${os.platform()}...\`);
|
|
62
80
|
|
|
63
|
-
|
|
64
|
-
console.log(\`[Fleetbo] 🧹 Cleaning up...\`);
|
|
81
|
+
console.log(\`[Fleetbo] 🧹 Preparing environment...\`);
|
|
65
82
|
await forceKillNgrok();
|
|
83
|
+
killProcessOnPort(NGROK_PORT);
|
|
84
|
+
killProcessOnPort(PORT);
|
|
66
85
|
await sleep(1000);
|
|
67
86
|
|
|
68
87
|
const envPath = path.join(process.cwd(), '.env');
|
|
@@ -75,20 +94,19 @@ async function runGuardian() {
|
|
|
75
94
|
const keyApp = process.env.REACT_KEY_APP;
|
|
76
95
|
const authToken = process.env.NGROK_AUTHTOKEN;
|
|
77
96
|
|
|
78
|
-
// 3. AUTHENTIFICATION (Si token présent dans .env, sinon Global)
|
|
79
97
|
if (authToken) {
|
|
80
98
|
try {
|
|
81
99
|
await ngrok.authtoken(authToken);
|
|
82
|
-
await sleep(
|
|
100
|
+
await sleep(500);
|
|
83
101
|
} catch (e) {}
|
|
84
102
|
}
|
|
85
103
|
|
|
86
|
-
console.log(\`[Fleetbo] 📦 Booting React Server...\`);
|
|
104
|
+
console.log(\`[Fleetbo] 📦 Booting React Server on port \${PORT}...\`);
|
|
87
105
|
const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
88
106
|
|
|
89
107
|
const devServer = spawn(npmCmd, ['start'], {
|
|
90
108
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
91
|
-
env: { ...process.env, BROWSER: 'none' }
|
|
109
|
+
env: { ...process.env, BROWSER: 'none', PORT: PORT.toString() }
|
|
92
110
|
});
|
|
93
111
|
|
|
94
112
|
devServer.stdout.pipe(process.stdout);
|
|
@@ -104,19 +122,19 @@ async function runGuardian() {
|
|
|
104
122
|
console.log(\`\\n[Fleetbo] 🔗 React is ready. Initiating Tunnel...\`);
|
|
105
123
|
|
|
106
124
|
try {
|
|
107
|
-
// 4. CONNEXION AVEC NOM UNIQUE (Évite les collisions)
|
|
108
125
|
const url = await ngrok.connect({
|
|
109
126
|
addr: PORT,
|
|
110
|
-
name: \`fleetbo_\${Date.now()}
|
|
127
|
+
name: \`fleetbo_\${Date.now()}\`,
|
|
128
|
+
auth: "fleetbo:admin" // <--- C'EST ICI QUE C'EST DÉFINI
|
|
111
129
|
});
|
|
112
130
|
await syncFirebase(keyApp, url);
|
|
113
131
|
} catch (firstErr) {
|
|
114
|
-
// 5. RETRY LOGIC
|
|
115
132
|
try {
|
|
116
133
|
await sleep(2000);
|
|
117
134
|
const urlRetry = await ngrok.connect({
|
|
118
135
|
addr: PORT,
|
|
119
|
-
name: \`fleetbo_retry_\${Date.now()}
|
|
136
|
+
name: \`fleetbo_retry_\${Date.now()}\`,
|
|
137
|
+
auth: "fleetbo:admin" // Retry avec Auth aussi
|
|
120
138
|
});
|
|
121
139
|
await syncFirebase(keyApp, urlRetry);
|
|
122
140
|
} catch (finalErr) {
|
|
@@ -137,12 +155,8 @@ runGuardian();
|
|
|
137
155
|
// --- Analyse des Arguments ---
|
|
138
156
|
const args = process.argv.slice(2);
|
|
139
157
|
const projectNameArg = args.find(arg => !arg.startsWith('--'));
|
|
140
|
-
|
|
141
|
-
// Argument Token Fleetbo
|
|
142
158
|
const tokenArg = args.find(arg => arg.startsWith('--token='));
|
|
143
159
|
const bootstrapTokenArg = tokenArg ? tokenArg.split('=')[1] : null;
|
|
144
|
-
|
|
145
|
-
// --- NOUVEAU : Argument Token Ngrok (Optionnel) ---
|
|
146
160
|
const ngrokArg = args.find(arg => arg.startsWith('--ngrok='));
|
|
147
161
|
const ngrokTokenArg = ngrokArg ? ngrokArg.split('=')[1] : null;
|
|
148
162
|
|
|
@@ -154,20 +168,14 @@ if (!projectNameArg || !bootstrapTokenArg) {
|
|
|
154
168
|
const projectName = projectNameArg;
|
|
155
169
|
const projectDir = path.join(process.cwd(), projectName);
|
|
156
170
|
|
|
157
|
-
|
|
158
171
|
// --- Fonctions Utilitaires ---
|
|
159
172
|
function fetchProjectKeys(token) {
|
|
160
173
|
return new Promise((resolve, reject) => {
|
|
161
174
|
const postData = JSON.stringify({ token });
|
|
162
175
|
const uri = new URL(bootstrapUrl);
|
|
163
176
|
const options = {
|
|
164
|
-
hostname: uri.hostname,
|
|
165
|
-
|
|
166
|
-
method: 'POST',
|
|
167
|
-
headers: {
|
|
168
|
-
'Content-Type': 'application/json',
|
|
169
|
-
'Content-Length': Buffer.byteLength(postData)
|
|
170
|
-
}
|
|
177
|
+
hostname: uri.hostname, path: uri.pathname, method: 'POST',
|
|
178
|
+
headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(postData) }
|
|
171
179
|
};
|
|
172
180
|
const req = https.request(options, (res) => {
|
|
173
181
|
let data = '';
|
|
@@ -188,15 +196,9 @@ function downloadEngine(url, dest) {
|
|
|
188
196
|
return new Promise((resolve, reject) => {
|
|
189
197
|
const uri = new URL(url);
|
|
190
198
|
const options = {
|
|
191
|
-
hostname: uri.hostname,
|
|
192
|
-
|
|
193
|
-
method: 'GET',
|
|
194
|
-
headers: {
|
|
195
|
-
'User-Agent': 'Fleetbo-CLI-Installer',
|
|
196
|
-
'Accept': '*/*'
|
|
197
|
-
}
|
|
199
|
+
hostname: uri.hostname, path: uri.pathname + uri.search, method: 'GET',
|
|
200
|
+
headers: { 'User-Agent': 'Fleetbo-CLI-Installer', 'Accept': '*/*' }
|
|
198
201
|
};
|
|
199
|
-
|
|
200
202
|
const request = https.get(options, (response) => {
|
|
201
203
|
if (response.statusCode === 301 || response.statusCode === 302) {
|
|
202
204
|
if (!response.headers.location) {
|
|
@@ -206,29 +208,13 @@ function downloadEngine(url, dest) {
|
|
|
206
208
|
downloadEngine(response.headers.location, dest).then(resolve).catch(reject);
|
|
207
209
|
return;
|
|
208
210
|
}
|
|
209
|
-
|
|
210
|
-
if (response.statusCode !== 200) {
|
|
211
|
-
reject(new Error(`Failed to download (Status: ${response.statusCode})`));
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
|
|
211
|
+
if (response.statusCode !== 200) { reject(new Error(`Status: ${response.statusCode}`)); return; }
|
|
215
212
|
const file = fs.createWriteStream(dest);
|
|
216
213
|
response.pipe(file);
|
|
217
|
-
|
|
218
|
-
file.on('
|
|
219
|
-
file.close(resolve);
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
file.on('error', (err) => {
|
|
223
|
-
fs.unlink(dest, () => {});
|
|
224
|
-
reject(err);
|
|
225
|
-
});
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
request.on('error', (err) => {
|
|
229
|
-
fs.unlink(dest, () => {});
|
|
230
|
-
reject(err);
|
|
214
|
+
file.on('finish', () => file.close(resolve));
|
|
215
|
+
file.on('error', (err) => { fs.unlink(dest, () => {}); reject(err); });
|
|
231
216
|
});
|
|
217
|
+
request.on('error', (err) => reject(err));
|
|
232
218
|
});
|
|
233
219
|
}
|
|
234
220
|
|
|
@@ -240,12 +226,10 @@ async function setupProject() {
|
|
|
240
226
|
if (fs.existsSync(projectDir)) throw new Error(`Directory "${projectName}" already exists.`);
|
|
241
227
|
fs.mkdirSync(projectDir);
|
|
242
228
|
|
|
243
|
-
// 1. Download
|
|
244
229
|
console.log(' [1/6] 📥 Downloading Fleetbo Core Engine...');
|
|
245
230
|
const archivePath = path.join(projectDir, 'engine.tar.gz');
|
|
246
231
|
await downloadEngine(archiveUrl, archivePath);
|
|
247
232
|
|
|
248
|
-
// 2. Extract
|
|
249
233
|
console.log(' [2/6] 📦 Scaffolding project structure...');
|
|
250
234
|
try {
|
|
251
235
|
execSync(`tar -xf "${archivePath}" -C "${projectDir}" --strip-components=1`, { stdio: 'ignore' });
|
|
@@ -254,37 +238,25 @@ async function setupProject() {
|
|
|
254
238
|
|
|
255
239
|
process.chdir(projectDir);
|
|
256
240
|
|
|
257
|
-
// 3. Auth
|
|
258
241
|
console.log(' [3/6] 🔑 Authenticating with Fleetbo Cloud...');
|
|
259
242
|
const keys = await fetchProjectKeys(bootstrapTokenArg);
|
|
260
243
|
if (!keys.enterpriseId) throw new Error("Invalid keys.");
|
|
261
244
|
|
|
262
|
-
// 4. Environment & CLI Generation
|
|
263
245
|
console.log(' [4/6] ⚙️ Configuring environment & CLI...');
|
|
264
|
-
|
|
265
|
-
// --- CRÉATION DU .ENV ---
|
|
266
|
-
let envContent = `REACT_APP_FLEETBO_DB_KEY=${keys.fleetboDBKey}\n`;
|
|
267
|
-
envContent += `REACT_APP_ENTERPRISE_ID=${keys.enterpriseId}\n`;
|
|
268
|
-
envContent += `REACT_KEY_APP=${projectName}\n`;
|
|
269
|
-
envContent += `DANGEROUSLY_DISABLE_HOST_CHECK=true\n`;
|
|
270
|
-
|
|
271
|
-
// Ajout conditionnel du token Ngrok
|
|
246
|
+
let envContent = `REACT_APP_FLEETBO_DB_KEY=${keys.fleetboDBKey}\nREACT_APP_ENTERPRISE_ID=${keys.enterpriseId}\nREACT_KEY_APP=${projectName}\nDANGEROUSLY_DISABLE_HOST_CHECK=true\n`;
|
|
272
247
|
if (ngrokTokenArg) {
|
|
273
248
|
console.log(' ✅ Ngrok token injected into .env');
|
|
274
249
|
envContent += `NGROK_AUTHTOKEN=${ngrokTokenArg}\n`;
|
|
275
250
|
} else {
|
|
276
251
|
console.log(' ℹ️ No Ngrok token provided. Assuming global config.');
|
|
277
252
|
}
|
|
278
|
-
|
|
279
253
|
fs.writeFileSync(path.join(projectDir, '.env'), envContent, 'utf8');
|
|
280
254
|
fs.writeFileSync(path.join(projectDir, 'cli.js'), CLI_SCRIPT_CONTENT, 'utf8');
|
|
281
255
|
|
|
282
|
-
// 5. Deps
|
|
283
256
|
console.log(' [5/6] 📚 Installing dependencies...');
|
|
284
257
|
execSync('npm install', { stdio: 'inherit' });
|
|
285
258
|
execSync('npm install ngrok dotenv axios --save-dev', { stdio: 'ignore' });
|
|
286
259
|
|
|
287
|
-
// 6. Finalize
|
|
288
260
|
console.log(' [6/6] ✨ Finalizing setup...');
|
|
289
261
|
const packageJsonPath = path.join(projectDir, 'package.json');
|
|
290
262
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
@@ -306,6 +278,8 @@ setupProject();
|
|
|
306
278
|
|
|
307
279
|
|
|
308
280
|
|
|
281
|
+
|
|
282
|
+
|
|
309
283
|
{/*
|
|
310
284
|
|
|
311
285
|
const { execSync } = require('child_process');
|