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.
Files changed (2) hide show
  1. package/cli.js +61 -43
  2. 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
- const appJsPath = fs.existsSync(path.join(process.cwd(), 'src', 'App.jsx'))
124
- ? path.join(process.cwd(), 'src', 'App.jsx')
125
- : path.join(process.cwd(), 'src', 'App.jsx');
126
- if (!fs.existsSync(appJsPath)) {
127
- console.error(` \x1b[31m[Safety Stop]\x1b[0m App.jsx missing.`);
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(appJsPath, 'utf8');
133
+ let content = fs.readFileSync(targetFile, 'utf8');
132
134
  const importAnchor = '// FLEETBO_MORE_IMPORTS';
133
- const routeAnchor = '{/* FLEETBO_DYNAMIC ROUTES */}';
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 App.jsx. Manual injection required.`);
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
- const importLine = `import ${moduleName} from './app/${cleanSubPath}${moduleName}';`;
142
- const routeLine = `<Route path="/${cleanSubPath}${moduleName.toLowerCase()}" element={<${moduleName} />} />`;
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(/[.*+?^${}()|[\]\\]/g, '\\$&')}`));
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, fini les espaces en dur !)
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(/[.*+?^${}()|[\]\\]/g, '\\$&')}`));
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(appJsPath, content);
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 appJsPath = fs.existsSync(path.join(process.cwd(), 'src', 'App.jsx'))
235
- ? path.join(process.cwd(), 'src', 'App.jsx')
236
- : path.join(process.cwd(), 'src', 'App.jsx');
237
- if (!fs.existsSync(appJsPath)) return false;
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(appJsPath, 'utf8');
240
-
241
- const importLine = `import ${moduleName} from './app/mocks/${moduleName}';`;
242
- const routeLine = `<Route path="/mocks/${moduleName.toLowerCase()}" element={<${moduleName} />} />`;
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(appJsPath, content);
256
- console.log(` \x1b[32m[Unrouted]\x1b[0m ${moduleName} removed from App.jsx.`);
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 💡 Tip:\x1b[0m Upgrade to Senior Pilot for more builds.`);
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 💡 Tip:\x1b[0m Run "npm run fleetbo alex" to create native modules first.`);
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 💡 Tip:\x1b[0m Your free sprint is over. Upgrade to Senior Pilot on fleetbo.io.`);
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('\x1b[32mFleetbo OS ❯\x1b[0m \x1b[1mGO GO GO ! OS IS READY\x1b[0m');
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] 🛡️ Initializing Universal Dev Environment...`);
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
- // 🛡️ FILTRE ANTI-PLOMBERIE FLEETBO
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
- // 🚀 MAGIE 1 : DÉTECTION DU PORT RÉEL (Vite/Vue ou React)
1117
- // Cherche un pattern comme http://localhost:5173 ou http://127.0.0.1:3000
1118
- //LA SOLUTION : On déclenche UNIQUEMENT quand on a trouvé le port !
1119
- // 🌐 CAPTURE AGNOSTIQUE DU PORT (S'adapte dynamiquement à Vite)
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] 🔄 Uplink reconnection ${attempt}/${MAX_UPLINK_RETRIES - 1}...\x1b[0m`);
1162
+ console.log(`\x1b[33m[Fleetbo] Uplink reconnection ${attempt}/${MAX_UPLINK_RETRIES - 1}...\x1b[0m`);
1145
1163
  }
1146
1164
 
1147
- // LE TUNNEL CLOUDFLARE UTILISE LE PORT DÉTECTÉ DYNAMIQUEMENT !
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
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fleetbo-cockpit-cli",
3
- "version": "1.0.181",
3
+ "version": "1.0.184",
4
4
  "description": "Fleetbo CLI - Build native mobile apps with React",
5
5
  "author": "Fleetbo",
6
6
  "license": "MIT",