create-fleetbo-project 1.2.9 → 1.2.11

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,44 +4,119 @@ 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');
8
7
 
9
8
  // --- Configuration ---
10
- // On cible l'archive (zip/tar) plutôt que le repo git
11
9
  const repoOwner = 'FleetFleetbo';
12
10
  const repoName = 'dev.fleetbo.io';
13
11
  const branchName = 'master';
14
-
15
- // URL de téléchargement direct de l'archive (plus rapide, pas de .git)
16
12
  const archiveUrl = `https://github.com/${repoOwner}/${repoName}/archive/refs/heads/${branchName}.tar.gz`;
17
13
  const bootstrapUrl = 'https://us-central1-myapp-259bf.cloudfunctions.net/bootstrapProject';
18
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
+
19
102
  // --- Analyse des Arguments ---
20
103
  const args = process.argv.slice(2);
21
104
  const projectNameArg = args.find(arg => !arg.startsWith('--'));
22
105
  const tokenArg = args.find(arg => arg.startsWith('--token='));
23
106
 
24
- if (!projectNameArg) {
25
- console.error('\n ❌ Error : Please specify a name for your project.');
26
- console.log(' Usage: npx create-fleetbo-project <project-name> --token=<your-token>');
27
- process.exit(1);
28
- }
29
-
30
- const bootstrapToken = tokenArg ? tokenArg.split('=')[1] : null;
31
-
32
- if (!bootstrapToken) {
33
- console.error('\n ❌ Error : The bootstrap token is missing.');
34
- console.log(' Usage: npx create-fleetbo-project <project-name> --token=<your-token>');
35
- process.exit(1);
107
+ if (!projectNameArg || !bootstrapToken(tokenArg)) {
108
+ console.error('\n ❌ Usage: npx create-fleetbo-project <project-name> --token=<your-token>');
109
+ process.exit(1);
36
110
  }
37
111
 
112
+ function bootstrapToken(arg) { return arg ? arg.split('=')[1] : null; }
38
113
  const projectName = projectNameArg;
39
114
  const projectDir = path.join(process.cwd(), projectName);
115
+ const bToken = bootstrapToken(tokenArg);
40
116
 
41
- // --- Fonctions Utilitaires ---
42
117
 
118
+ // --- Fonctions Utilitaires ---
43
119
  function fetchProjectKeys(token) {
44
- // ... (Code inchangé pour la récupération des clés) ...
45
120
  return new Promise((resolve, reject) => {
46
121
  const postData = JSON.stringify({ token });
47
122
  const options = { method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(postData) } };
@@ -50,15 +125,8 @@ function fetchProjectKeys(token) {
50
125
  res.on('data', (chunk) => { data += chunk; });
51
126
  res.on('end', () => {
52
127
  if (res.statusCode >= 200 && res.statusCode < 300) {
53
- try {
54
- resolve(JSON.parse(data));
55
- } catch (e) {
56
- reject(new Error('Invalid response from the key server.'));
57
- }
58
- } else {
59
- const errorMsg = JSON.parse(data).error || `Server error (code: ${res.statusCode})`;
60
- reject(new Error(errorMsg));
61
- }
128
+ try { resolve(JSON.parse(data)); } catch (e) { reject(new Error('Invalid response')); }
129
+ } else { reject(new Error(`Server error ${res.statusCode}`)); }
62
130
  });
63
131
  });
64
132
  req.on('error', (e) => reject(e));
@@ -67,105 +135,78 @@ function fetchProjectKeys(token) {
67
135
  });
68
136
  }
69
137
 
70
- // Fonction pour télécharger l'archive
71
138
  function downloadEngine(url, dest) {
72
139
  return new Promise((resolve, reject) => {
73
- const file = fs.createWriteStream(dest);
74
- https.get(url, (response) => {
75
- if (response.statusCode !== 200) {
76
- reject(new Error(`Failed to download engine (Status: ${response.statusCode})`));
140
+ const request = https.get(url, (response) => {
141
+ if (response.statusCode === 301 || response.statusCode === 302) {
142
+ downloadEngine(response.headers.location, dest).then(resolve).catch(reject);
77
143
  return;
78
144
  }
145
+ if (response.statusCode !== 200) { reject(new Error(`Status: ${response.statusCode}`)); return; }
146
+ const file = fs.createWriteStream(dest);
79
147
  response.pipe(file);
80
- file.on('finish', () => {
81
- file.close(resolve);
82
- });
83
- }).on('error', (err) => {
84
- fs.unlink(dest, () => {}); // Supprimer le fichier partiel
85
- reject(err);
148
+ file.on('finish', () => file.close(resolve));
149
+ file.on('error', (err) => { fs.unlink(dest, () => {}); reject(err); });
86
150
  });
151
+ request.on('error', (err) => reject(err));
87
152
  });
88
153
  }
89
154
 
90
155
  // --- Fonction Principale ---
91
-
92
156
  async function setupProject() {
93
157
  console.log(`\n⚡ Initializing Fleetbo Framework for "${projectName}"...`);
94
158
 
95
159
  try {
96
- // Création du dossier
97
- if (fs.existsSync(projectDir)) {
98
- throw new Error(`Directory "${projectName}" already exists.`);
99
- }
160
+ if (fs.existsSync(projectDir)) throw new Error(`Directory "${projectName}" already exists.`);
100
161
  fs.mkdirSync(projectDir);
101
162
 
102
- // Étape 1 : Téléchargement du Moteur (Sans Git)
163
+ // 1. Download
103
164
  console.log(' [1/6] 📥 Downloading Fleetbo Core Engine...');
104
165
  const archivePath = path.join(projectDir, 'engine.tar.gz');
105
166
  await downloadEngine(archiveUrl, archivePath);
106
167
 
107
- // Étape 2 : Extraction (Scaffolding)
168
+ // 2. Extract
108
169
  console.log(' [2/6] 📦 Scaffolding project structure...');
109
- // On utilise 'tar' qui est présent sur Win10+, Mac et Linux.
110
- // --strip-components=1 permet de retirer le dossier racine "dev.fleetbo.io-master" de l'archive
111
170
  try {
112
- execSync(`tar -xf "${archivePath}" -C "${projectDir}" --strip-components=1`);
113
- fs.unlinkSync(archivePath); // Nettoyage de l'archive
114
- } catch (e) {
115
- throw new Error("Failed to extract the engine. Ensure 'tar' is available on your system.");
116
- }
171
+ execSync(`tar -xf "${archivePath}" -C "${projectDir}" --strip-components=1`, { stdio: 'ignore' });
172
+ fs.unlinkSync(archivePath);
173
+ } catch (e) { throw new Error("Failed to extract engine. Ensure 'tar' is available."); }
117
174
 
118
- // On se déplace dans le dossier (Plus besoin de supprimer .git car il n'y en a pas !)
119
175
  process.chdir(projectDir);
120
176
 
121
- // Étape 3 : Récupération des clés (Authentication)
177
+ // 3. Auth
122
178
  console.log(' [3/6] 🔑 Authenticating with Fleetbo Cloud...');
123
- const keys = await fetchProjectKeys(bootstrapToken);
124
- if (!keys.enterpriseId || !keys.fleetboDBKey) {
125
- throw new Error("Received keys from the server are invalid.");
126
- }
179
+ const keys = await fetchProjectKeys(bToken);
180
+ if (!keys.enterpriseId) throw new Error("Invalid keys.");
127
181
 
128
- // Étape 4 : Configuration de l'environnement
129
- console.log(' [4/6] ⚙️ Configuring environment...');
130
- // Configuration .env optimisée pour le simulateur (DANGEROUSLY_DISABLE_HOST_CHECK)
182
+ // 4. Environment & CLI Generation
183
+ console.log(' [4/6] ⚙️ Configuring environment & CLI...');
131
184
  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`;
132
185
  fs.writeFileSync(path.join(projectDir, '.env'), envContent, 'utf8');
133
186
 
134
- // Étape 5 : Installation des dépendances
135
- console.log(' [5/6] 📚 Installing dependencies (this may take a moment)...');
136
- // Installation silencieuse pour faire plus "pro" (pipe stdio si erreur)
187
+ // --- ICI ON CRÉE LE FICHIER CLI.JS ---
188
+ fs.writeFileSync(path.join(projectDir, 'cli.js'), CLI_SCRIPT_CONTENT, 'utf8');
189
+ // -------------------------------------
190
+
191
+ // 5. Deps
192
+ console.log(' [5/6] 📚 Installing dependencies...');
137
193
  execSync('npm install', { stdio: 'inherit' });
138
-
139
- // Installation des outils de dev (Ngrok est vital pour le flow)
140
- console.log(' Installing development tools...');
141
194
  execSync('npm install ngrok dotenv --save-dev', { stdio: 'ignore' });
142
195
 
143
- // Étape 6 : Finalisation
196
+ // 6. Finalize
144
197
  console.log(' [6/6] ✨ Finalizing setup...');
145
-
146
198
  const packageJsonPath = path.join(projectDir, 'package.json');
147
199
  const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
148
200
  packageJson.name = projectName;
149
-
150
- // On ajoute la commande 'fleetbo'
151
- packageJson.scripts = {
152
- ...packageJson.scripts,
153
- "fleetbo": "node cli.js",
154
- "dev": "node cli.js"
155
- };
201
+ packageJson.scripts = { ...packageJson.scripts, "fleetbo": "node cli.js", "dev": "node cli.js" };
156
202
  fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2), 'utf8');
157
203
 
158
204
  console.log('\n✅ Project successfully created!');
159
- console.log(`\n👉 Get started with:`);
160
- console.log(` cd ${projectName}`);
161
- console.log(` npm run fleetbo`);
205
+ console.log(`\n👉 Run: cd ${projectName} && npm run fleetbo`);
162
206
 
163
207
  } catch (error) {
164
208
  console.error('\n❌ Setup failed:', error.message);
165
- // Nettoyage en cas d'erreur
166
- if (fs.existsSync(projectDir)) {
167
- try { fs.rmSync(projectDir, { recursive: true, force: true }); } catch(e){}
168
- }
209
+ if (fs.existsSync(projectDir)) try { fs.rmSync(projectDir, { recursive: true, force: true }); } catch(e){}
169
210
  process.exit(1);
170
211
  }
171
212
  }
@@ -174,9 +215,6 @@ setupProject();
174
215
 
175
216
 
176
217
 
177
-
178
-
179
-
180
218
  {/*
181
219
 
182
220
  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.9",
3
+ "version": "1.2.11",
4
4
  "description": "Creates a new Fleetbo project.",
5
5
  "main": "install-react-template.js",
6
6
  "bin": {