fleetbo-cockpit-cli 1.0.181 → 1.0.184
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/cli.js +61 -43
- package/package.json +1 -1
package/cli.js
CHANGED
|
@@ -120,49 +120,62 @@ const checkGitSecurity = () => {
|
|
|
120
120
|
};
|
|
121
121
|
|
|
122
122
|
const injectRouteIntoAppJs = (moduleName, subPath = '') => {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
123
|
+
// 🔍 DÉTERMINATION DU FICHIER CIBLE SELON LE FRAMEWORK
|
|
124
|
+
const targetFile = JS_FRAMEWORK === 'vue'
|
|
125
|
+
? path.join(process.cwd(), 'src', 'router.js') // Cible Vue
|
|
126
|
+
: path.join(process.cwd(), 'src', 'App.jsx'); // Cible React
|
|
127
|
+
|
|
128
|
+
if (!fs.existsSync(targetFile)) {
|
|
129
|
+
console.error(` \x1b[31m[Safety Stop]\x1b[0m ${path.basename(targetFile)} missing.`);
|
|
128
130
|
return false;
|
|
129
131
|
}
|
|
130
132
|
|
|
131
|
-
let content = fs.readFileSync(
|
|
133
|
+
let content = fs.readFileSync(targetFile, 'utf8');
|
|
132
134
|
const importAnchor = '// FLEETBO_MORE_IMPORTS';
|
|
133
|
-
const routeAnchor =
|
|
135
|
+
const routeAnchor = JS_FRAMEWORK === 'vue'
|
|
136
|
+
? '/* FLEETBO_DYNAMIC ROUTES */'
|
|
137
|
+
: '{/* FLEETBO_DYNAMIC ROUTES */}';
|
|
134
138
|
|
|
135
139
|
if (!content.includes(importAnchor) || !content.includes(routeAnchor)) {
|
|
136
|
-
console.log(` \x1b[33m[Skipped]\x1b[0m Anchors missing in
|
|
140
|
+
console.log(` \x1b[33m[Skipped]\x1b[0m Anchors missing in ${path.basename(targetFile)}. Manual injection required.`);
|
|
137
141
|
return false;
|
|
138
142
|
}
|
|
139
143
|
|
|
140
144
|
const cleanSubPath = subPath ? `${subPath}/` : '';
|
|
141
|
-
|
|
142
|
-
|
|
145
|
+
let importLine, routeLine;
|
|
146
|
+
|
|
147
|
+
if (JS_FRAMEWORK === 'vue') {
|
|
148
|
+
// 🟢 SYNTAXE VUE
|
|
149
|
+
importLine = `import ${moduleName} from './app/${cleanSubPath}${moduleName}.vue';`;
|
|
150
|
+
routeLine = `{ path: '/${cleanSubPath}${moduleName.toLowerCase()}', component: ${moduleName} },`;
|
|
151
|
+
} else {
|
|
152
|
+
// 🔵 SYNTAXE REACT
|
|
153
|
+
importLine = `import ${moduleName} from './app/${cleanSubPath}${moduleName}';`;
|
|
154
|
+
routeLine = `<Route path="/${cleanSubPath}${moduleName.toLowerCase()}" element={<${moduleName} />} />`;
|
|
155
|
+
}
|
|
143
156
|
|
|
144
157
|
let modified = false;
|
|
145
158
|
|
|
146
159
|
// 1. Injection de l'import (Capture l'indentation d'origine)
|
|
147
160
|
if (!content.includes(importLine)) {
|
|
148
|
-
const importMatch = content.match(new RegExp(`(\\n[ \\t]*)${importAnchor.replace(/[.*+?^${}()|[
|
|
161
|
+
const importMatch = content.match(new RegExp(`(\\n[ \\t]*)${importAnchor.replace(/[.*+?^${}()|[\\]\\]/g, '\\$&')}`));
|
|
149
162
|
const importIndent = importMatch ? importMatch[1] : '\n';
|
|
150
163
|
content = content.replace(importAnchor, `${importLine}${importIndent}${importAnchor}`);
|
|
151
164
|
modified = true;
|
|
152
165
|
}
|
|
153
|
-
|
|
154
|
-
// 2. Injection de la route (Capture l'indentation d'origine
|
|
166
|
+
|
|
167
|
+
// 2. Injection de la route (Capture l'indentation d'origine)
|
|
155
168
|
if (!content.includes(routeLine)) {
|
|
156
|
-
const routeMatch = content.match(new RegExp(`(\\n[ \\t]*)${routeAnchor.replace(/[.*+?^${}()|[
|
|
169
|
+
const routeMatch = content.match(new RegExp(`(\\n[ \\t]*)${routeAnchor.replace(/[.*+?^${}()|[\\]\\]/g, '\\$&')}`));
|
|
157
170
|
const routeIndent = routeMatch ? routeMatch[1] : '\n';
|
|
158
171
|
content = content.replace(routeAnchor, `${routeLine}${routeIndent}${routeAnchor}`);
|
|
159
172
|
modified = true;
|
|
160
173
|
}
|
|
161
|
-
|
|
174
|
+
|
|
162
175
|
if (modified) {
|
|
163
|
-
fs.writeFileSync(
|
|
176
|
+
fs.writeFileSync(targetFile, content);
|
|
164
177
|
}
|
|
165
|
-
|
|
178
|
+
|
|
166
179
|
return modified;
|
|
167
180
|
};
|
|
168
181
|
|
|
@@ -231,34 +244,39 @@ const getModuleCache = async ({ projectId, moduleName }) => {
|
|
|
231
244
|
};
|
|
232
245
|
|
|
233
246
|
const removeRouteFromAppJs = (moduleName) => {
|
|
234
|
-
const
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
if (!fs.existsSync(
|
|
247
|
+
const targetFile = JS_FRAMEWORK === 'vue'
|
|
248
|
+
? path.join(process.cwd(), 'src', 'router.js')
|
|
249
|
+
: path.join(process.cwd(), 'src', 'App.jsx');
|
|
250
|
+
if (!fs.existsSync(targetFile)) return false;
|
|
238
251
|
|
|
239
|
-
let content = fs.readFileSync(
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
252
|
+
let content = fs.readFileSync(targetFile, 'utf8');
|
|
253
|
+
|
|
254
|
+
let importLine, routeLine;
|
|
255
|
+
if (JS_FRAMEWORK === 'vue') {
|
|
256
|
+
importLine = `import ${moduleName} from './app/mocks/${moduleName}.vue';`;
|
|
257
|
+
routeLine = `{ path: '/mocks/${moduleName.toLowerCase()}', component: ${moduleName} },`;
|
|
258
|
+
} else {
|
|
259
|
+
importLine = `import ${moduleName} from './app/mocks/${moduleName}';`;
|
|
260
|
+
routeLine = `<Route path="/mocks/${moduleName.toLowerCase()}" element={<${moduleName} />} />`;
|
|
261
|
+
}
|
|
243
262
|
|
|
244
263
|
const originalContent = content;
|
|
245
|
-
|
|
246
|
-
// On supprime l'import ET le saut de ligne qui le suit
|
|
264
|
+
|
|
247
265
|
const importRegex = new RegExp(`${importLine.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\n?`, 'g');
|
|
248
266
|
content = content.replace(importRegex, '');
|
|
249
267
|
|
|
250
|
-
// On supprime la route ET tous les espaces/sauts de ligne qui la PRÉCÈDENT
|
|
251
268
|
const routeRegex = new RegExp(`\\n?\\s*${routeLine.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}`, 'g');
|
|
252
269
|
content = content.replace(routeRegex, '');
|
|
253
270
|
|
|
254
271
|
if (content !== originalContent) {
|
|
255
|
-
fs.writeFileSync(
|
|
256
|
-
console.log(` \x1b[32m[Unrouted]\x1b[0m ${moduleName} removed from
|
|
272
|
+
fs.writeFileSync(targetFile, content);
|
|
273
|
+
console.log(` \x1b[32m[Unrouted]\x1b[0m ${moduleName} removed from ${path.basename(targetFile)}.`);
|
|
257
274
|
return true;
|
|
258
275
|
}
|
|
259
276
|
return false;
|
|
260
277
|
};
|
|
261
278
|
|
|
279
|
+
|
|
262
280
|
// ============================================
|
|
263
281
|
// COMMAND: alex
|
|
264
282
|
// ============================================
|
|
@@ -968,11 +986,11 @@ else if (command === 'android' || command === 'ios') {
|
|
|
968
986
|
console.error(`\x1b[31m Error:\x1b[0m ${error.message}`);
|
|
969
987
|
|
|
970
988
|
if (error.message.includes('Limit') || error.message.includes('Quota')) {
|
|
971
|
-
console.log(`\n\x1b[33m
|
|
989
|
+
console.log(`\n\x1b[33m Tip:\x1b[0m Upgrade to Senior Pilot for more builds.`);
|
|
972
990
|
} else if (error.message.includes('No native module')) {
|
|
973
|
-
console.log(`\n\x1b[33m
|
|
991
|
+
console.log(`\n\x1b[33m Tip:\x1b[0m Run "npm run fleetbo alex" to create native modules first.`);
|
|
974
992
|
} else if (error.message.includes('Trial Period Ended')) {
|
|
975
|
-
console.log(`\n\x1b[33m
|
|
993
|
+
console.log(`\n\x1b[33m Tip:\x1b[0m Your free sprint is over. Upgrade to Senior Pilot on fleetbo.io.`);
|
|
976
994
|
}
|
|
977
995
|
console.log('');
|
|
978
996
|
process.exit(1);
|
|
@@ -1056,8 +1074,8 @@ else {
|
|
|
1056
1074
|
await axios.post(UPDATE_NETWORK_URL, { keyApp, networkUrl, tester: testerEmail });
|
|
1057
1075
|
console.log('\n\x1b[32mEngine started successfully\x1b[0m');
|
|
1058
1076
|
console.log(`\n\x1b[32mFleetbo OS ❯\x1b[0m -------------------------------------------------------------`);
|
|
1059
|
-
console.log(
|
|
1060
|
-
console.log('\x1b[32mFleetbo OS ❯\x1b[0m You can now start coding and previewing.
|
|
1077
|
+
console.log(`\x1b[32mFleetbo OS ❯\x1b[0m \x1b[1mGO ! ${projectName} running in OS\x1b[0m`);
|
|
1078
|
+
console.log('\x1b[32mFleetbo OS ❯\x1b[0m You can now start coding and previewing.');
|
|
1061
1079
|
console.log(`\x1b[32mFleetbo OS ❯\x1b[0m -------------------------------------------------------------`);
|
|
1062
1080
|
console.log(`\n\x1b[34mPilot Instruction ❯\x1b[0m Return to the Workspace. The Engine is ready for your orders.\n`);
|
|
1063
1081
|
} catch (err) {
|
|
@@ -1066,7 +1084,7 @@ else {
|
|
|
1066
1084
|
}
|
|
1067
1085
|
|
|
1068
1086
|
async function runDevEnvironment() {
|
|
1069
|
-
console.log(`[Fleetbo]
|
|
1087
|
+
console.log(`[Fleetbo] Initializing Universal Dev Environment...`);
|
|
1070
1088
|
|
|
1071
1089
|
killNetworkService();
|
|
1072
1090
|
killProcessOnPort(PORT); // On tue le 3000 par précaution, au cas où
|
|
@@ -1096,7 +1114,7 @@ else {
|
|
|
1096
1114
|
devServer.stdout.on('data', (data) => {
|
|
1097
1115
|
const output = data.toString();
|
|
1098
1116
|
|
|
1099
|
-
//
|
|
1117
|
+
// FILTRE ANTI-PLOMBERIE FLEETBO
|
|
1100
1118
|
const lines = output.split('\n');
|
|
1101
1119
|
const forbiddenTerms = [
|
|
1102
1120
|
'Attempting to bind to HOST', 'If this was unintentional', 'Learn more here:',
|
|
@@ -1113,10 +1131,10 @@ else {
|
|
|
1113
1131
|
process.stdout.write(filteredOutput + '\n');
|
|
1114
1132
|
}
|
|
1115
1133
|
|
|
1116
|
-
//
|
|
1117
|
-
//
|
|
1118
|
-
//
|
|
1119
|
-
//
|
|
1134
|
+
// MAGIE 1 : DÉTECTION DU PORT RÉEL (Vite/Vue ou React)
|
|
1135
|
+
// Cherche un pattern comme http://localhost:5173 ou http://127.0.0.1:3000
|
|
1136
|
+
// LA SOLUTION : On déclenche UNIQUEMENT quand on a trouvé le port !
|
|
1137
|
+
// CAPTURE AGNOSTIQUE DU PORT (S'adapte dynamiquement à Vite)
|
|
1120
1138
|
const portMatch = output.match(/http:\/\/(?:localhost|127\.0\.0\.1):(\d+)/);
|
|
1121
1139
|
|
|
1122
1140
|
if (portMatch) {
|
|
@@ -1141,10 +1159,10 @@ else {
|
|
|
1141
1159
|
const npxCmd = process.platform === 'win32' ? 'npx.cmd' : 'npx';
|
|
1142
1160
|
|
|
1143
1161
|
if (attempt > 0) {
|
|
1144
|
-
console.log(`\x1b[33m[Fleetbo]
|
|
1162
|
+
console.log(`\x1b[33m[Fleetbo] Uplink reconnection ${attempt}/${MAX_UPLINK_RETRIES - 1}...\x1b[0m`);
|
|
1145
1163
|
}
|
|
1146
1164
|
|
|
1147
|
-
//
|
|
1165
|
+
// LE TUNNEL CLOUDFLARE UTILISE LE PORT DÉTECTÉ DYNAMIQUEMENT !
|
|
1148
1166
|
const uplinkCommand = `${npxCmd} -y cloudflared tunnel --url http://127.0.0.1:${detectedPort} --http-host-header 127.0.0.1:${detectedPort}`;
|
|
1149
1167
|
uplinkProcess = spawn(uplinkCommand, { shell: true });
|
|
1150
1168
|
|