create-fleetbo-project 1.2.35 → 1.2.37
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 +25 -5
- package/package.json +1 -1
- package/recov.js +130 -48
|
@@ -152,13 +152,33 @@ function killNetworkService() {
|
|
|
152
152
|
} catch (e) {}
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
+
// Variable de verrouillage globale
|
|
156
|
+
let isExiting = false;
|
|
157
|
+
|
|
155
158
|
async function cleanupAndExit(code = 0) {
|
|
156
|
-
|
|
159
|
+
// Si on est déjà en train de sortir, on ignore les autres signaux
|
|
160
|
+
if (isExiting) return;
|
|
161
|
+
isExiting = true;
|
|
162
|
+
|
|
163
|
+
console.log('\n[Fleetbo] 🛑 Stopping development environment...');
|
|
164
|
+
|
|
165
|
+
try {
|
|
166
|
+
// Nettoyage de l'Uplink dans Firestore
|
|
167
|
+
await axios.post(UPDATE_NETWORK_URL, {
|
|
168
|
+
keyApp: keyApp,
|
|
169
|
+
networkUrl: '',
|
|
170
|
+
tester: testerEmail
|
|
171
|
+
});
|
|
172
|
+
console.log('[Fleetbo] 🧊 Uplink cleaned successfully.');
|
|
173
|
+
} catch (e) {
|
|
174
|
+
// On ne bloque pas si le réseau échoue à la fermeture
|
|
175
|
+
}
|
|
176
|
+
|
|
157
177
|
killNetworkService();
|
|
158
178
|
killProcessOnPort(PORT);
|
|
159
179
|
process.exit(code);
|
|
160
180
|
}
|
|
161
|
-
|
|
181
|
+
// Les écouteurs restent les mêmes, mais la fonction gère maintenant le verrou
|
|
162
182
|
process.on('SIGINT', () => cleanupAndExit(0));
|
|
163
183
|
process.on('SIGTERM', () => cleanupAndExit(0));
|
|
164
184
|
|
|
@@ -171,9 +191,9 @@ async function syncFirebase(keyApp, networkUrl, testerEmail) {
|
|
|
171
191
|
});
|
|
172
192
|
console.log('\\n[Fleetbo] ---------------------------------------------------\\n');
|
|
173
193
|
console.log(\`[Fleetbo] ✅ Uplink Status: Online for \${testerEmail}\`);
|
|
174
|
-
console.log(\`[Fleetbo] 🚀
|
|
175
|
-
console.log(\'[Fleetbo] 👉 Your studio is ready. You can now open the link above.\
|
|
176
|
-
console.log('[Fleetbo] ---------------------------------------------------\\n');
|
|
194
|
+
console.log(\`[Fleetbo] 🚀 Fleetbo Studio: https://fleetbo.io/studio/view/\${keyApp}\`);
|
|
195
|
+
console.log(\'[Fleetbo] 👉 Your studio is ready. You can now open the link above.\');
|
|
196
|
+
console.log('\\n[Fleetbo] ---------------------------------------------------\\n');
|
|
177
197
|
} catch (err) {
|
|
178
198
|
console.error(\`[Fleetbo] ⚠️ Sync Error: \${err.message}\`);
|
|
179
199
|
}
|
package/package.json
CHANGED
package/recov.js
CHANGED
|
@@ -5,14 +5,12 @@ const fs = require('fs');
|
|
|
5
5
|
const path = require('path');
|
|
6
6
|
const https = require('https');
|
|
7
7
|
|
|
8
|
-
// --- Configuration ---
|
|
9
8
|
const repoOwner = 'FleetFleetbo';
|
|
10
9
|
const repoName = 'dev.fleetbo.io';
|
|
11
10
|
const branchName = 'master';
|
|
12
11
|
const archiveUrl = `https://github.com/${repoOwner}/${repoName}/archive/refs/heads/${branchName}.tar.gz`;
|
|
13
12
|
const bootstrapUrl = 'https://us-central1-myapp-259bf.cloudfunctions.net/bootstrapProject';
|
|
14
13
|
|
|
15
|
-
// --- LE CONTENU DU CLI (Version avec Email Dynamique) ---
|
|
16
14
|
const CLI_SCRIPT_CONTENT = `#!/usr/bin/env node
|
|
17
15
|
|
|
18
16
|
const { spawn, execSync } = require('child_process');
|
|
@@ -21,31 +19,121 @@ const path = require('path');
|
|
|
21
19
|
const axios = require('axios');
|
|
22
20
|
const dotenv = require('dotenv');
|
|
23
21
|
const os = require('os');
|
|
22
|
+
const archiver = require('archiver');
|
|
23
|
+
|
|
24
|
+
const CLOUD_ENGINE_URL = "https://us-central1-myapp-259bf.cloudfunctions.net/uploadLogicBundle";
|
|
25
|
+
const UPDATE_NETWORK_URL = 'https://us-central1-myapp-259bf.cloudfunctions.net/updateDeveloperNetwork';
|
|
26
|
+
const PORT = 3000;
|
|
27
|
+
|
|
28
|
+
const args = process.argv.slice(2);
|
|
29
|
+
const command = args[0];
|
|
30
|
+
|
|
31
|
+
const envPath = path.join(process.cwd(), '.env');
|
|
32
|
+
if (!fs.existsSync(envPath)) {
|
|
33
|
+
console.error('❌ Error: Configuration file (.env) not found.');
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
dotenv.config({ path: envPath });
|
|
37
|
+
|
|
38
|
+
const projectId = process.env.REACT_APP_ENTERPRISE_ID;
|
|
39
|
+
const keyApp = process.env.REACT_KEY_APP;
|
|
40
|
+
const testerEmail = process.env.REACT_APP_TESTER_EMAIL;
|
|
41
|
+
|
|
42
|
+
if (!projectId) {
|
|
43
|
+
console.error('\\n❌ Error: Project ID is missing.');
|
|
44
|
+
console.error('👉 Please check your .env file.');
|
|
45
|
+
console.error(' It must contain: REACT_APP_ENTERPRISE_ID=your_project_id\\n');
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (command === 'deploy') {
|
|
50
|
+
(async () => {
|
|
51
|
+
console.log('\\n\\x1b[36m%s\\x1b[0m', '⚡ FLEETBO CLOUD ENGINE v1.0');
|
|
52
|
+
console.log('\\x1b[32m%s\\x1b[0m', 'Target Runtime:', keyApp);
|
|
53
|
+
console.log('------------------------------------------------');
|
|
54
|
+
|
|
55
|
+
console.log('🔨 \\x1b[33mCompiling local assets...\\x1b[0m');
|
|
56
|
+
try {
|
|
57
|
+
execSync('npm run build', { stdio: 'inherit' });
|
|
58
|
+
} catch (e) {
|
|
59
|
+
console.error('\\n❌ Build failed. Fix errors and try again.');
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
let buildDir = 'dist';
|
|
64
|
+
if (!fs.existsSync(path.join(process.cwd(), 'dist')) && fs.existsSync(path.join(process.cwd(), 'build'))) {
|
|
65
|
+
buildDir = 'build';
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (!fs.existsSync(path.join(process.cwd(), buildDir))) {
|
|
69
|
+
console.error(\`\\n❌ Error: Build folder '\${buildDir}' not found.\`);
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
console.log('\\n📦 \\x1b[33mProcessing Neural Logic...\\x1b[0m');
|
|
74
|
+
console.log(\` Detected stack: React (\${buildDir})\`);
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
const zipBuffer = await new Promise((resolve, reject) => {
|
|
78
|
+
const chunks = [];
|
|
79
|
+
const archive = archiver('zip', { zlib: { level: 9 } });
|
|
80
|
+
|
|
81
|
+
archive.on('data', (chunk) => chunks.push(chunk));
|
|
82
|
+
archive.on('error', (err) => reject(err));
|
|
83
|
+
archive.on('end', () => resolve(Buffer.concat(chunks)));
|
|
84
|
+
|
|
85
|
+
archive.directory(path.join(process.cwd(), buildDir), false);
|
|
86
|
+
archive.finalize();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
console.log('☁️ \\x1b[33mEstablishing Uplink to Switch-Engine...\\x1b[0m');
|
|
90
|
+
|
|
91
|
+
const response = await axios.post(CLOUD_ENGINE_URL, zipBuffer, {
|
|
92
|
+
headers: {
|
|
93
|
+
'Content-Type': 'application/zip',
|
|
94
|
+
'x-project-id': projectId,
|
|
95
|
+
'Content-Length': zipBuffer.length
|
|
96
|
+
},
|
|
97
|
+
maxContentLength: Infinity,
|
|
98
|
+
maxBodyLength: Infinity
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
console.log('------------------------------------------------');
|
|
102
|
+
console.log('✅ \\x1b[1m\\x1b[32mDEPLOYMENT SUCCESSFUL\\x1b[0m');
|
|
103
|
+
console.log(\` Build ID: \${response.data.buildId}\`);
|
|
104
|
+
console.log(\` Payload: \${(zipBuffer.length / 1024 / 1024).toFixed(2)} MB\`);
|
|
105
|
+
console.log('\\n📱 \\x1b[36mNative Runtime has been hot-swapped.\\x1b[0m');
|
|
106
|
+
console.log(' Your app is live.\\n');
|
|
107
|
+
|
|
108
|
+
} catch (error) {
|
|
109
|
+
console.error('\\n❌ \\x1b[31mCRITICAL FAILURE\\x1b[0m');
|
|
110
|
+
if (error.response) {
|
|
111
|
+
console.error(\` Server responded with \${error.response.status}: "\${error.response.statusText}".\`);
|
|
112
|
+
console.error(\` Details: \${JSON.stringify(error.response.data)}\`);
|
|
113
|
+
} else {
|
|
114
|
+
console.error(\` \${error.message}\`);
|
|
115
|
+
}
|
|
116
|
+
process.exit(1);
|
|
117
|
+
}
|
|
118
|
+
})();
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const GENERATOR_COMMANDS = ['page', 'g', 'generate', 'android', 'ios'];
|
|
24
123
|
|
|
25
|
-
const args = process.argv.slice(2);
|
|
26
|
-
const command = args[0];
|
|
27
|
-
const GENERATOR_COMMANDS = ['page', 'g', 'generate'];
|
|
28
124
|
if (GENERATOR_COMMANDS.includes(command)) {
|
|
29
125
|
try {
|
|
30
126
|
require('./page.js');
|
|
31
127
|
} catch (error) {
|
|
32
128
|
console.error('\\x1b[31m%s\\x1b[0m', ' CRITICAL ERROR in Fleetbo Generator:');
|
|
33
|
-
|
|
34
|
-
console.error(". The generator script (scripts/page.js) is missing.");
|
|
35
|
-
console.error(" Please update your Fleetbo SDK.");
|
|
36
|
-
} else {
|
|
37
|
-
console.error(error.message);
|
|
38
|
-
}
|
|
129
|
+
console.error(error.message);
|
|
39
130
|
process.exit(1);
|
|
40
131
|
}
|
|
41
132
|
return;
|
|
42
133
|
}
|
|
43
134
|
|
|
44
|
-
const UPDATE_NETWORK_URL = 'https://us-central1-myapp-259bf.cloudfunctions.net/updateDeveloperNetwork';
|
|
45
|
-
const PORT = 3000;
|
|
46
|
-
|
|
47
|
-
|
|
48
135
|
const NULL_DEV = process.platform === 'win32' ? '>nul 2>&1' : '2>/dev/null';
|
|
136
|
+
|
|
49
137
|
function killProcessOnPort(port) {
|
|
50
138
|
try {
|
|
51
139
|
if (process.platform !== 'win32') {
|
|
@@ -60,7 +148,7 @@ function killProcessOnPort(port) {
|
|
|
60
148
|
function killNetworkService() {
|
|
61
149
|
try {
|
|
62
150
|
const cmd = process.platform === 'win32' ? 'taskkill /IM cloudflared.exe /F' : 'pkill cloudflared';
|
|
63
|
-
execSync(cmd + ' ' + NULL_DEV);
|
|
151
|
+
execSync(cmd + ' ' + NULL_DEV);
|
|
64
152
|
} catch (e) {}
|
|
65
153
|
}
|
|
66
154
|
|
|
@@ -81,9 +169,10 @@ async function syncFirebase(keyApp, networkUrl, testerEmail) {
|
|
|
81
169
|
networkUrl,
|
|
82
170
|
tester: testerEmail
|
|
83
171
|
});
|
|
84
|
-
console.log('\\n[Fleetbo]
|
|
172
|
+
console.log('\\n[Fleetbo] ---------------------------------------------------\\n');
|
|
85
173
|
console.log(\`[Fleetbo] ✅ Uplink Status: Online for \${testerEmail}\`);
|
|
86
174
|
console.log(\`[Fleetbo] 🚀 Simulator: https://fleetbo.io/studio/view/\${keyApp}\`);
|
|
175
|
+
console.log(\'[Fleetbo] 👉 Your studio is ready. You can now open the link above.\n');
|
|
87
176
|
console.log('[Fleetbo] ---------------------------------------------------\\n');
|
|
88
177
|
} catch (err) {
|
|
89
178
|
console.error(\`[Fleetbo] ⚠️ Sync Error: \${err.message}\`);
|
|
@@ -93,25 +182,14 @@ async function syncFirebase(keyApp, networkUrl, testerEmail) {
|
|
|
93
182
|
async function runDevEnvironment() {
|
|
94
183
|
console.log(\`[Fleetbo] 🛡️ Initializing Developer Environment on \${os.platform()}...\`);
|
|
95
184
|
|
|
96
|
-
// 1. NETTOYAGE PRÉVENTIF
|
|
97
185
|
killNetworkService();
|
|
98
186
|
killProcessOnPort(PORT);
|
|
99
187
|
|
|
100
|
-
const envPath = path.join(process.cwd(), '.env');
|
|
101
|
-
if (!fs.existsSync(envPath)) {
|
|
102
|
-
console.error('Error: Configuration file not found.');
|
|
103
|
-
process.exit(1);
|
|
104
|
-
}
|
|
105
|
-
dotenv.config({ path: envPath });
|
|
106
|
-
const keyApp = process.env.REACT_KEY_APP;
|
|
107
|
-
const testerEmail = process.env.REACT_APP_TESTER_EMAIL;
|
|
108
|
-
|
|
109
188
|
if (!testerEmail) {
|
|
110
189
|
console.error('Error: REACT_APP_TESTER_EMAIL missing in .env');
|
|
111
190
|
process.exit(1);
|
|
112
191
|
}
|
|
113
192
|
|
|
114
|
-
// 2. DÉMARRAGE DU SERVEUR LOCAL
|
|
115
193
|
console.log(\`[Fleetbo] 📦 Starting Local Server...\`);
|
|
116
194
|
const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
117
195
|
|
|
@@ -132,15 +210,15 @@ async function runDevEnvironment() {
|
|
|
132
210
|
if (!connectionStarted && (output.includes('Local:') || output.includes('Compiled successfully'))) {
|
|
133
211
|
connectionStarted = true;
|
|
134
212
|
console.log(\`\\n[Fleetbo] 🔗 Local Server Ready. Establishing Secure Uplink...\`);
|
|
213
|
+
console.log(\`\\n[Fleetbo] 🛑 STOP! DO NOT open the Studio yet.\`);
|
|
214
|
+
console.log(\`\\n[Fleetbo] ⏳ Establishing Secure Uplink... Please wait...\`);
|
|
215
|
+
|
|
135
216
|
|
|
136
|
-
// 3. DÉMARRAGE DE LA LIAISON (UPLINK)
|
|
137
217
|
const npxCmd = process.platform === 'win32' ? 'npx.cmd' : 'npx';
|
|
218
|
+
|
|
138
219
|
const uplink = spawn(npxCmd, ['cloudflared', 'tunnel', '--url', \`http://localhost:\${PORT}\`], { shell: true });
|
|
139
|
-
|
|
140
|
-
// Capture de l'URL (Silencieux)
|
|
141
220
|
uplink.stderr.on('data', (chunk) => {
|
|
142
221
|
const log = chunk.toString();
|
|
143
|
-
|
|
144
222
|
const match = log.match(/https:\\/\\/[a-zA-Z0-9-]+\\.trycloudflare\\.com/);
|
|
145
223
|
|
|
146
224
|
if (match) {
|
|
@@ -162,7 +240,6 @@ async function runDevEnvironment() {
|
|
|
162
240
|
runDevEnvironment();
|
|
163
241
|
`;
|
|
164
242
|
|
|
165
|
-
// --- Analyse des Arguments ---
|
|
166
243
|
const args = process.argv.slice(2);
|
|
167
244
|
const projectNameArg = args.find(arg => !arg.startsWith('--'));
|
|
168
245
|
const tokenArg = args.find(arg => arg.startsWith('--token='));
|
|
@@ -179,7 +256,6 @@ if (!projectNameArg || !bootstrapTokenArg || !userEmailArg) {
|
|
|
179
256
|
const projectName = projectNameArg;
|
|
180
257
|
const projectDir = path.join(process.cwd(), projectName);
|
|
181
258
|
|
|
182
|
-
// --- Fonctions Utilitaires ---
|
|
183
259
|
function fetchProjectKeys(token) {
|
|
184
260
|
return new Promise((resolve, reject) => {
|
|
185
261
|
const postData = JSON.stringify({ token });
|
|
@@ -226,7 +302,6 @@ function downloadEngine(url, dest) {
|
|
|
226
302
|
});
|
|
227
303
|
}
|
|
228
304
|
|
|
229
|
-
// --- Fonction Principale ---
|
|
230
305
|
async function setupProject() {
|
|
231
306
|
console.log(`\n⚡ Initializing Fleetbo Framework for "${projectName}"...`);
|
|
232
307
|
|
|
@@ -252,39 +327,46 @@ async function setupProject() {
|
|
|
252
327
|
|
|
253
328
|
console.log(' [4/6] ⚙️ Configuring environment & CLI...');
|
|
254
329
|
|
|
255
|
-
const envContent =
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
330
|
+
const envContent =
|
|
331
|
+
`REACT_APP_FLEETBO_DB_KEY=${keys.fleetboDBKey}
|
|
332
|
+
REACT_APP_ENTERPRISE_ID=${keys.enterpriseId}
|
|
333
|
+
REACT_KEY_APP=${projectName}
|
|
334
|
+
REACT_APP_TESTER_EMAIL=${userEmailArg}
|
|
335
|
+
DANGEROUSLY_DISABLE_HOST_CHECK=true
|
|
336
|
+
WDS_SOCKET_PORT=0
|
|
337
|
+
`;
|
|
262
338
|
|
|
263
339
|
fs.writeFileSync(path.join(projectDir, '.env'), envContent, 'utf8');
|
|
264
|
-
// On s'assure que le dossier scripts existe (normalement oui via le tar.gz, mais sécurité d'abord)
|
|
265
340
|
const scriptsDir = path.join(projectDir, 'scripts');
|
|
266
341
|
if (!fs.existsSync(scriptsDir)) {
|
|
267
342
|
fs.mkdirSync(scriptsDir, { recursive: true });
|
|
268
343
|
}
|
|
269
344
|
fs.writeFileSync(path.join(scriptsDir, 'cli.js'), CLI_SCRIPT_CONTENT, 'utf8');
|
|
270
|
-
// On rend le script exécutable (Optionnel mais propre sur Mac/Linux)
|
|
271
345
|
try { fs.chmodSync(path.join(scriptsDir, 'cli.js'), '755'); } catch (e) {}
|
|
272
346
|
|
|
273
347
|
console.log(' [5/6] 📚 Installing dependencies...');
|
|
274
348
|
execSync('npm install', { stdio: 'inherit' });
|
|
275
349
|
|
|
276
|
-
|
|
277
|
-
execSync('npm install cloudflared dotenv axios --save-dev', { stdio: 'ignore' });
|
|
350
|
+
execSync('npm install cloudflared dotenv axios archiver --save-dev', { stdio: 'ignore' });
|
|
278
351
|
|
|
279
352
|
console.log(' [6/6] ✨ Finalizing setup...');
|
|
280
353
|
const packageJsonPath = path.join(projectDir, 'package.json');
|
|
281
354
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
355
|
+
|
|
282
356
|
packageJson.name = projectName;
|
|
283
|
-
|
|
357
|
+
|
|
358
|
+
packageJson.scripts = {
|
|
359
|
+
...packageJson.scripts,
|
|
360
|
+
"fleetbo": "node scripts/cli.js",
|
|
361
|
+
"dev": "node scripts/cli.js"
|
|
362
|
+
};
|
|
363
|
+
|
|
284
364
|
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2), 'utf8');
|
|
285
365
|
|
|
286
366
|
console.log('\n [Fleetbo] ✅ Project successfully created!');
|
|
287
|
-
console.log(`\n👉 Run: cd ${projectName}
|
|
367
|
+
console.log(`\n👉 Run: cd ${projectName}`);
|
|
368
|
+
console.log(`👉 Start Dev: npm run fleetbo`);
|
|
369
|
+
console.log(`👉 Deploy App: npm run fleetbo deploy`);
|
|
288
370
|
|
|
289
371
|
} catch (error) {
|
|
290
372
|
console.error('\n❌ Setup failed:', error.message);
|