create-fleetbo-project 1.2.10 → 1.2.12

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.
@@ -4,41 +4,117 @@ const { execSync } = require('child_process');
4
4
  const fs = require('fs');
5
5
  const path = require('path');
6
6
  const https = require('https');
7
- // const os = require('os'); // Pas strictement nécessaire ici
8
7
 
9
8
  // --- Configuration ---
10
9
  const repoOwner = 'FleetFleetbo';
11
10
  const repoName = 'dev.fleetbo.io';
12
11
  const branchName = 'master';
13
-
14
- // URL de téléchargement direct de l'archive
15
12
  const archiveUrl = `https://github.com/${repoOwner}/${repoName}/archive/refs/heads/${branchName}.tar.gz`;
16
13
  const bootstrapUrl = 'https://us-central1-myapp-259bf.cloudfunctions.net/bootstrapProject';
17
14
 
15
+ // --- LE CONTENU DU GARDIEN (Injecté dynamiquement) ---
16
+ const CLI_SCRIPT_CONTENT = `#!/usr/bin/env node
17
+
18
+ const { spawn } = require('child_process');
19
+ const fs = require('fs');
20
+ const path = require('path');
21
+ const axios = require('axios');
22
+ const dotenv = require('dotenv');
23
+ const ngrok = require('ngrok');
24
+ const os = require('os');
25
+
26
+ const UPDATE_NETWORK_URL = 'https://us-central1-myapp-259bf.cloudfunctions.net/updateDeveloperNetwork';
27
+ const PORT = 3000;
28
+
29
+ async function cleanupAndExit(code = 0) {
30
+ console.log('\\n[Fleetbo] 🛑 Shutting down services...');
31
+ try { await ngrok.kill(); } catch (e) {}
32
+ process.exit(code);
33
+ }
34
+
35
+ process.on('SIGINT', () => cleanupAndExit(0));
36
+ process.on('SIGTERM', () => cleanupAndExit(0));
37
+
38
+ async function syncFirebase(keyApp, networkUrl) {
39
+ try {
40
+ await axios.post(UPDATE_NETWORK_URL, { keyApp, networkUrl });
41
+ console.log('\\n[Fleetbo] ---------------------------------------------------');
42
+ console.log(\`[Fleetbo] ✅ Tunnel Active: \${networkUrl}\`);
43
+ console.log(\`[Fleetbo] 🚀 Simulator: https://fleetbo.io/studio/view/\${keyApp}\`);
44
+ console.log('[Fleetbo] ---------------------------------------------------\\n');
45
+ } catch (err) {
46
+ console.error(\`[Fleetbo] ⚠️ Sync Error: \${err.message}\`);
47
+ }
48
+ }
49
+
50
+ async function runGuardian() {
51
+ console.log(\`[Fleetbo] 🛡️ Starting Fleetbo Guardian on \${os.platform()}...\`);
52
+
53
+ const envPath = path.join(process.cwd(), '.env');
54
+ if (!fs.existsSync(envPath)) {
55
+ console.error('Error: .env file not found.');
56
+ process.exit(1);
57
+ }
58
+ dotenv.config({ path: envPath });
59
+
60
+ const keyApp = process.env.REACT_KEY_APP;
61
+
62
+ console.log(\`[Fleetbo] 📦 Booting React Server...\`);
63
+ const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm';
64
+
65
+ const devServer = spawn(npmCmd, ['start'], {
66
+ stdio: ['ignore', 'pipe', 'pipe'],
67
+ env: { ...process.env, BROWSER: 'none' }
68
+ });
69
+
70
+ devServer.stdout.pipe(process.stdout);
71
+ devServer.stderr.pipe(process.stderr);
72
+
73
+ let tunnelStarted = false;
74
+
75
+ devServer.stdout.on('data', async (data) => {
76
+ const output = data.toString();
77
+ if (!tunnelStarted && (output.includes('Local:') || output.includes('Compiled successfully'))) {
78
+ tunnelStarted = true;
79
+ console.log(\`\\n[Fleetbo] 🔗 React is ready. Opening secure tunnel...\`);
80
+
81
+ try {
82
+ const url = await ngrok.connect({ addr: PORT });
83
+ await syncFirebase(keyApp, url);
84
+ } catch (err) {
85
+ console.error('\\n[Fleetbo] ❌ NGROK CONNECTION FAILED');
86
+ if (err.message.includes('ERR_NGROK_4018') || err.message.includes('limited') || err.message.includes('authtoken')) {
87
+ console.error('-------------------------------------------------------');
88
+ console.error('⚠️ MISSING OR INVALID AUTH TOKEN');
89
+ console.error(' Run this command once:');
90
+ console.error(' npx ngrok config add-authtoken <YOUR_TOKEN>');
91
+ console.error('-------------------------------------------------------');
92
+ }
93
+ cleanupAndExit(1);
94
+ }
95
+ }
96
+ });
97
+ }
98
+
99
+ runGuardian();
100
+ `;
101
+
18
102
  // --- Analyse des Arguments ---
19
103
  const args = process.argv.slice(2);
20
104
  const projectNameArg = args.find(arg => !arg.startsWith('--'));
21
105
  const tokenArg = args.find(arg => arg.startsWith('--token='));
106
+ const bootstrapTokenArg = tokenArg ? tokenArg.split('=')[1] : null;
22
107
 
23
- if (!projectNameArg) {
24
- console.error('\n ❌ Error : Please specify a name for your project.');
25
- console.log(' Usage: npx create-fleetbo-project <project-name> --token=<your-token>');
26
- process.exit(1);
27
- }
28
-
29
- const bootstrapToken = tokenArg ? tokenArg.split('=')[1] : null;
30
-
31
- if (!bootstrapToken) {
32
- console.error('\n ❌ Error : The bootstrap token is missing.');
33
- console.log(' Usage: npx create-fleetbo-project <project-name> --token=<your-token>');
34
- process.exit(1);
108
+ if (!projectNameArg || !bootstrapTokenArg) {
109
+ console.error('\n ❌ Usage: npx create-fleetbo-project <project-name> --token=<your-token>');
110
+ process.exit(1);
35
111
  }
36
112
 
37
113
  const projectName = projectNameArg;
38
114
  const projectDir = path.join(process.cwd(), projectName);
39
115
 
40
- // --- Fonctions Utilitaires ---
41
116
 
117
+ // --- Fonctions Utilitaires ---
42
118
  function fetchProjectKeys(token) {
43
119
  return new Promise((resolve, reject) => {
44
120
  const postData = JSON.stringify({ token });
@@ -48,16 +124,8 @@ function fetchProjectKeys(token) {
48
124
  res.on('data', (chunk) => { data += chunk; });
49
125
  res.on('end', () => {
50
126
  if (res.statusCode >= 200 && res.statusCode < 300) {
51
- try {
52
- resolve(JSON.parse(data));
53
- } catch (e) {
54
- reject(new Error('Invalid response from the key server.'));
55
- }
56
- } else {
57
- let errorMsg = `Server error (code: ${res.statusCode})`;
58
- try { errorMsg = JSON.parse(data).error || errorMsg; } catch(e){}
59
- reject(new Error(errorMsg));
60
- }
127
+ try { resolve(JSON.parse(data)); } catch (e) { reject(new Error('Invalid response')); }
128
+ } else { reject(new Error(`Server error ${res.statusCode}`)); }
61
129
  });
62
130
  });
63
131
  req.on('error', (e) => reject(e));
@@ -66,123 +134,76 @@ function fetchProjectKeys(token) {
66
134
  });
67
135
  }
68
136
 
69
- // --- CORRECTION ICI : Gestion des redirections (301/302) ---
70
137
  function downloadEngine(url, dest) {
71
138
  return new Promise((resolve, reject) => {
72
139
  const request = https.get(url, (response) => {
73
- // 1. Gérer la redirection (GitHub renvoie souvent 302 Found)
74
140
  if (response.statusCode === 301 || response.statusCode === 302) {
75
- const newUrl = response.headers.location;
76
- if (!newUrl) {
77
- reject(new Error("Redirect status found but no location header."));
78
- return;
79
- }
80
- // Appel récursif avec la nouvelle URL
81
- downloadEngine(newUrl, dest)
82
- .then(resolve)
83
- .catch(reject);
84
- return;
85
- }
86
-
87
- // 2. Vérifier le succès (200 OK)
88
- if (response.statusCode !== 200) {
89
- reject(new Error(`Failed to download engine (Status: ${response.statusCode})`));
141
+ downloadEngine(response.headers.location, dest).then(resolve).catch(reject);
90
142
  return;
91
143
  }
92
-
93
- // 3. Écriture du fichier
144
+ if (response.statusCode !== 200) { reject(new Error(`Status: ${response.statusCode}`)); return; }
94
145
  const file = fs.createWriteStream(dest);
95
146
  response.pipe(file);
96
-
97
- file.on('finish', () => {
98
- file.close(resolve);
99
- });
100
-
101
- file.on('error', (err) => {
102
- fs.unlink(dest, () => {}); // Supprimer fichier incomplet
103
- reject(err);
104
- });
105
- });
106
-
107
- request.on('error', (err) => {
108
- fs.unlink(dest, () => {});
109
- reject(err);
147
+ file.on('finish', () => file.close(resolve));
148
+ file.on('error', (err) => { fs.unlink(dest, () => {}); reject(err); });
110
149
  });
150
+ request.on('error', (err) => reject(err));
111
151
  });
112
152
  }
113
153
 
114
154
  // --- Fonction Principale ---
115
-
116
155
  async function setupProject() {
117
156
  console.log(`\n⚡ Initializing Fleetbo Framework for "${projectName}"...`);
118
157
 
119
158
  try {
120
- if (fs.existsSync(projectDir)) {
121
- throw new Error(`Directory "${projectName}" already exists.`);
122
- }
159
+ if (fs.existsSync(projectDir)) throw new Error(`Directory "${projectName}" already exists.`);
123
160
  fs.mkdirSync(projectDir);
124
161
 
125
- // Étape 1 : Téléchargement
162
+ // 1. Download
126
163
  console.log(' [1/6] 📥 Downloading Fleetbo Core Engine...');
127
164
  const archivePath = path.join(projectDir, 'engine.tar.gz');
128
-
129
- // Cette fonction gère maintenant la redirection GitHub
130
165
  await downloadEngine(archiveUrl, archivePath);
131
166
 
132
- // Étape 2 : Extraction
167
+ // 2. Extract
133
168
  console.log(' [2/6] 📦 Scaffolding project structure...');
134
169
  try {
135
- // On ignore les erreurs de tar si c'est juste des warnings, mais on catch les erreurs fatales
136
170
  execSync(`tar -xf "${archivePath}" -C "${projectDir}" --strip-components=1`, { stdio: 'ignore' });
137
171
  fs.unlinkSync(archivePath);
138
- } catch (e) {
139
- // Fallback pour Windows si 'tar' n'est pas dans le path (rare sur Win10/11 mais possible)
140
- throw new Error("Failed to extract engine. Make sure 'tar' command is available.");
141
- }
172
+ } catch (e) { throw new Error("Failed to extract engine. Ensure 'tar' is available."); }
142
173
 
143
174
  process.chdir(projectDir);
144
175
 
145
- // Étape 3 : Authentification
176
+ // 3. Auth
146
177
  console.log(' [3/6] 🔑 Authenticating with Fleetbo Cloud...');
147
- const keys = await fetchProjectKeys(bootstrapToken);
148
- if (!keys.enterpriseId || !keys.fleetboDBKey) {
149
- throw new Error("Received keys from the server are invalid.");
150
- }
178
+ const keys = await fetchProjectKeys(bootstrapTokenArg);
179
+ if (!keys.enterpriseId) throw new Error("Invalid keys.");
151
180
 
152
- // Étape 4 : Environnement
153
- console.log(' [4/6] ⚙️ Configuring environment...');
181
+ // 4. Environment & CLI Generation
182
+ console.log(' [4/6] ⚙️ Configuring environment & CLI...');
154
183
  const envContent = `REACT_APP_FLEETBO_DB_KEY=${keys.fleetboDBKey}\nREACT_APP_ENTERPRISE_ID=${keys.enterpriseId}\nREACT_KEY_APP=${projectName}\nDANGEROUSLY_DISABLE_HOST_CHECK=true\n`;
155
184
  fs.writeFileSync(path.join(projectDir, '.env'), envContent, 'utf8');
185
+ fs.writeFileSync(path.join(projectDir, 'cli.js'), CLI_SCRIPT_CONTENT, 'utf8');
156
186
 
157
- // Étape 5 : Dépendances
187
+ // 5. Deps
158
188
  console.log(' [5/6] 📚 Installing dependencies...');
159
- // On installe les deps du projet + ngrok en dev
160
189
  execSync('npm install', { stdio: 'inherit' });
161
- execSync('npm install ngrok dotenv --save-dev', { stdio: 'ignore' });
190
+ // AJOUT DE AXIOS ICI
191
+ execSync('npm install ngrok dotenv axios --save-dev', { stdio: 'ignore' });
162
192
 
163
- // Étape 6 : Finalisation
193
+ // 6. Finalize
164
194
  console.log(' [6/6] ✨ Finalizing setup...');
165
195
  const packageJsonPath = path.join(projectDir, 'package.json');
166
196
  const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
167
197
  packageJson.name = projectName;
168
-
169
- packageJson.scripts = {
170
- ...packageJson.scripts,
171
- "fleetbo": "node cli.js",
172
- "dev": "node cli.js"
173
- };
198
+ packageJson.scripts = { ...packageJson.scripts, "fleetbo": "node cli.js", "dev": "node cli.js" };
174
199
  fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2), 'utf8');
175
200
 
176
201
  console.log('\n✅ Project successfully created!');
177
- console.log(`\n👉 Get started with:`);
178
- console.log(` cd ${projectName}`);
179
- console.log(` npm run fleetbo`);
202
+ console.log(`\n👉 Run: cd ${projectName} && npm run fleetbo`);
180
203
 
181
204
  } catch (error) {
182
205
  console.error('\n❌ Setup failed:', error.message);
183
- if (fs.existsSync(projectDir)) {
184
- try { fs.rmSync(projectDir, { recursive: true, force: true }); } catch(e){}
185
- }
206
+ if (fs.existsSync(projectDir)) try { fs.rmSync(projectDir, { recursive: true, force: true }); } catch(e){}
186
207
  process.exit(1);
187
208
  }
188
209
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-fleetbo-project",
3
- "version": "1.2.10",
3
+ "version": "1.2.12",
4
4
  "description": "Creates a new Fleetbo project.",
5
5
  "main": "install-react-template.js",
6
6
  "bin": {