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.
@@ -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 BLINDÉE ---
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
- // 1. NETTOYAGE VIOLENT (Anti-Zombie)
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 React...');
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
- // 2. NETTOYAGE AU DÉMARRAGE
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(1000);
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()}\` // <--- CRUCIAL
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
- path: uri.pathname,
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
- path: uri.pathname + uri.search,
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('finish', () => {
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');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-fleetbo-project",
3
- "version": "1.2.14",
3
+ "version": "1.2.17",
4
4
  "description": "Creates a new Fleetbo project.",
5
5
  "main": "install-react-template.js",
6
6
  "bin": {