create-fleetbo-project 1.2.97 → 1.2.98
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 +98 -46
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
// 🥷 SILENCIEUX ABSOLU : S'exécute instantanément pour tuer la plomberie de NPX
|
|
3
4
|
process.stdout.write("\x1b[1A\x1b[2K".repeat(4));
|
|
4
5
|
console.clear();
|
|
5
6
|
|
|
@@ -15,54 +16,61 @@ const projectNameArg = args.find(arg => !arg.startsWith('--'));
|
|
|
15
16
|
const tokenArg = args.find(arg => arg.startsWith('--token='));
|
|
16
17
|
const emailArg = args.find(arg => arg.startsWith('--email='));
|
|
17
18
|
const frameworkArg = args.find(arg => arg.startsWith('--framework='));
|
|
18
|
-
|
|
19
19
|
const bootstrapTokenArg = tokenArg ? tokenArg.split('=')[1] : null;
|
|
20
20
|
const userEmailArg = emailArg ? emailArg.split('=')[1] : null;
|
|
21
|
-
const
|
|
21
|
+
const jsFramework = frameworkArg ? frameworkArg.split('=')[1] : 'react';
|
|
22
22
|
|
|
23
23
|
if (!projectNameArg || !bootstrapTokenArg || !userEmailArg) {
|
|
24
|
-
console.error('\n Usage: npx create-fleetbo-project <
|
|
24
|
+
console.error('\n Usage: npx create-fleetbo-project <n> --token=<token> --email=<email> [--framework=vue]');
|
|
25
25
|
process.exit(1);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
console.log(`\n 🔍 Resolving latest Vue template from npm registry...`);
|
|
28
|
+
// 🌐 RÉSOLUTION UNIFIÉE DEPUIS NPM
|
|
29
|
+
// React : my-fleetbo-react | Vue : my-fleetbo-vue
|
|
30
|
+
// NPM = CDN industriel, SemVer, zéro rate limit GitHub
|
|
31
|
+
const getArchiveUrl = () => {
|
|
32
|
+
const templatePackage = jsFramework === 'vue' ? 'my-fleetbo-vue' : 'my-fleetbo-react';
|
|
33
|
+
console.log(` 🔍 Resolving latest ${jsFramework.toUpperCase()} template from npm registry...`);
|
|
35
34
|
try {
|
|
36
|
-
|
|
35
|
+
const tarball = execSync(`npm view ${templatePackage} dist.tarball`, { stdio: ['pipe', 'pipe', 'ignore'] }).toString().trim();
|
|
36
|
+
if (!tarball) throw new Error('Empty response');
|
|
37
|
+
return Promise.resolve(tarball);
|
|
37
38
|
} catch (e) {
|
|
38
|
-
|
|
39
|
-
process.exit(1);
|
|
39
|
+
return Promise.reject(new Error(`Could not locate "${templatePackage}" on npm. Is it published?`));
|
|
40
40
|
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
archiveUrl = `https://github.com/${repoOwner}/${repoName}/archive/refs/heads/${branchName}.tar.gz`;
|
|
46
|
-
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const projectName = projectNameArg;
|
|
44
|
+
const projectDir = path.join(process.cwd(), projectName);
|
|
47
45
|
|
|
48
46
|
function fetchProjectKeys(token) {
|
|
49
47
|
return new Promise((resolve, reject) => {
|
|
50
48
|
const postData = JSON.stringify({ token });
|
|
51
49
|
const uri = new URL(bootstrapUrl);
|
|
52
50
|
const options = {
|
|
53
|
-
hostname: uri.hostname,
|
|
54
|
-
|
|
51
|
+
hostname: uri.hostname,
|
|
52
|
+
path: uri.pathname,
|
|
53
|
+
method: 'POST',
|
|
54
|
+
headers: {
|
|
55
|
+
'Content-Type': 'application/json',
|
|
56
|
+
'Content-Length': Buffer.byteLength(postData)
|
|
57
|
+
}
|
|
55
58
|
};
|
|
56
59
|
const req = https.request(options, (res) => {
|
|
57
60
|
let data = '';
|
|
58
61
|
res.on('data', (chunk) => { data += chunk; });
|
|
59
62
|
res.on('end', () => {
|
|
60
63
|
if (res.statusCode >= 200 && res.statusCode < 300) {
|
|
61
|
-
try { resolve(JSON.parse(data)); }
|
|
62
|
-
|
|
64
|
+
try { resolve(JSON.parse(data)); }
|
|
65
|
+
catch (e) { reject(new Error('Invalid response')); }
|
|
66
|
+
} else {
|
|
67
|
+
reject(new Error(`Server error ${res.statusCode}`));
|
|
68
|
+
}
|
|
63
69
|
});
|
|
64
70
|
});
|
|
65
|
-
req.on('error', (e) => reject(e));
|
|
71
|
+
req.on('error', (e) => reject(e));
|
|
72
|
+
req.write(postData);
|
|
73
|
+
req.end();
|
|
66
74
|
});
|
|
67
75
|
}
|
|
68
76
|
|
|
@@ -70,33 +78,51 @@ function downloadEngine(url, dest) {
|
|
|
70
78
|
return new Promise((resolve, reject) => {
|
|
71
79
|
const uri = new URL(url);
|
|
72
80
|
const options = {
|
|
73
|
-
hostname: uri.hostname,
|
|
74
|
-
|
|
81
|
+
hostname: uri.hostname,
|
|
82
|
+
path: uri.pathname + uri.search,
|
|
83
|
+
method: 'GET',
|
|
84
|
+
headers: {
|
|
85
|
+
'User-Agent': 'Fleetbo-CLI-Installer',
|
|
86
|
+
'Accept': '*/*'
|
|
87
|
+
}
|
|
75
88
|
};
|
|
76
89
|
const request = https.get(options, (response) => {
|
|
77
90
|
if (response.statusCode === 301 || response.statusCode === 302) {
|
|
78
|
-
if (!response.headers.location) {
|
|
91
|
+
if (!response.headers.location) {
|
|
92
|
+
reject(new Error("Redirect error"));
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
79
95
|
downloadEngine(response.headers.location, dest).then(resolve).catch(reject);
|
|
80
96
|
return;
|
|
81
97
|
}
|
|
82
|
-
if (response.statusCode !== 200) {
|
|
98
|
+
if (response.statusCode !== 200) {
|
|
99
|
+
reject(new Error(`Status: ${response.statusCode}`));
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
83
102
|
const file = fs.createWriteStream(dest);
|
|
84
103
|
response.pipe(file);
|
|
85
104
|
file.on('finish', () => file.close(resolve));
|
|
86
|
-
file.on('error', (err) => {
|
|
105
|
+
file.on('error', (err) => {
|
|
106
|
+
fs.unlink(dest, () => {});
|
|
107
|
+
reject(err);
|
|
108
|
+
});
|
|
87
109
|
});
|
|
88
110
|
request.on('error', (err) => reject(err));
|
|
89
111
|
});
|
|
90
112
|
}
|
|
91
113
|
|
|
92
114
|
async function setupProject() {
|
|
93
|
-
console.log(`\n ⚡ Initializing Fleetbo Framework
|
|
115
|
+
console.log(`\n ⚡ Initializing Fleetbo Framework for "${projectName}"...`);
|
|
94
116
|
|
|
95
117
|
try {
|
|
96
|
-
if (fs.existsSync(projectDir)) {
|
|
118
|
+
if (fs.existsSync(projectDir)) {
|
|
119
|
+
throw new Error(`Directory "${projectName}" already exists.`);
|
|
120
|
+
}
|
|
97
121
|
fs.mkdirSync(projectDir);
|
|
98
122
|
|
|
99
|
-
|
|
123
|
+
const frameworkLabel = jsFramework === 'vue' ? 'Vue' : 'React';
|
|
124
|
+
console.log(` [1/8] Downloading Fleetbo ${frameworkLabel} Engine...`);
|
|
125
|
+
const archiveUrl = await getArchiveUrl();
|
|
100
126
|
const archivePath = path.join(projectDir, 'engine.tar.gz');
|
|
101
127
|
await downloadEngine(archiveUrl, archivePath);
|
|
102
128
|
|
|
@@ -104,17 +130,19 @@ async function setupProject() {
|
|
|
104
130
|
try {
|
|
105
131
|
execSync(`tar -xf "${archivePath}" -C "${projectDir}" --strip-components=1`, { stdio: 'ignore' });
|
|
106
132
|
fs.unlinkSync(archivePath);
|
|
107
|
-
} catch (e) {
|
|
133
|
+
} catch (e) {
|
|
134
|
+
throw new Error("Extract failed.");
|
|
135
|
+
}
|
|
108
136
|
|
|
109
137
|
process.chdir(projectDir);
|
|
110
138
|
|
|
111
|
-
console.log(' [3/8] Standardizing Architecture...');
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
139
|
+
console.log(' [3/8] Standardizing Architecture (Vite)...');
|
|
140
|
+
// Pour Vite, on s'assure juste que l'arborescence de base est correcte.
|
|
141
|
+
// On retire les vieux renommages CRA (App.js) pour éviter de casser App.jsx
|
|
142
|
+
const oldPath = path.join(projectDir, 'src/pages');
|
|
143
|
+
const newPath = path.join(projectDir, 'src/app');
|
|
144
|
+
if (fs.existsSync(oldPath) && !fs.existsSync(newPath)) {
|
|
145
|
+
try { fs.renameSync(oldPath, newPath); } catch (err) {}
|
|
118
146
|
}
|
|
119
147
|
|
|
120
148
|
console.log(' [4/8] Authenticating with Fleetbo Cloud...');
|
|
@@ -132,7 +160,17 @@ WDS_SOCKET_PORT=0`;
|
|
|
132
160
|
fs.writeFileSync(path.join(projectDir, '.env'), envContent, 'utf8');
|
|
133
161
|
|
|
134
162
|
console.log(' [6/8] Securing environment (adding .gitignore)...');
|
|
135
|
-
const gitignoreContent = `# Fleetbo Security
|
|
163
|
+
const gitignoreContent = `# Fleetbo Security
|
|
164
|
+
.env
|
|
165
|
+
.env.local
|
|
166
|
+
node_modules/
|
|
167
|
+
dist/
|
|
168
|
+
build/
|
|
169
|
+
.DS_Store
|
|
170
|
+
npm-debug.log*
|
|
171
|
+
yarn-debug.log*
|
|
172
|
+
yarn-error.log*
|
|
173
|
+
`;
|
|
136
174
|
fs.writeFileSync(path.join(projectDir, '.gitignore'), gitignoreContent, 'utf8');
|
|
137
175
|
|
|
138
176
|
const npmrcContent = `loglevel=silent\nupdate-notifier=false\n`;
|
|
@@ -140,6 +178,7 @@ WDS_SOCKET_PORT=0`;
|
|
|
140
178
|
|
|
141
179
|
console.log(' [7/8] Installing dependencies...');
|
|
142
180
|
execSync('npm install --no-audit --no-fund --silent', { stdio: 'inherit' });
|
|
181
|
+
|
|
143
182
|
execSync('npm install cloudflared --save-dev --no-audit --no-fund --silent', { stdio: 'ignore' });
|
|
144
183
|
|
|
145
184
|
console.log(' [8/8] Finalizing setup...');
|
|
@@ -147,6 +186,7 @@ WDS_SOCKET_PORT=0`;
|
|
|
147
186
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
148
187
|
packageJson.name = projectName;
|
|
149
188
|
|
|
189
|
+
// Configuration pour utiliser le package NPM centralisé
|
|
150
190
|
packageJson.scripts = {
|
|
151
191
|
...packageJson.scripts,
|
|
152
192
|
"fleetbo": "npx -y fleetbo-cockpit-cli@latest",
|
|
@@ -158,23 +198,35 @@ WDS_SOCKET_PORT=0`;
|
|
|
158
198
|
|
|
159
199
|
const scriptsDir = path.join(projectDir, 'scripts');
|
|
160
200
|
if (fs.existsSync(scriptsDir)) {
|
|
161
|
-
try {
|
|
201
|
+
try {
|
|
202
|
+
fs.rmSync(scriptsDir, { recursive: true, force: true });
|
|
203
|
+
} catch (e) {
|
|
204
|
+
// Ignore si ça échoue
|
|
205
|
+
}
|
|
162
206
|
}
|
|
163
207
|
|
|
208
|
+
// ==========================================
|
|
209
|
+
// 🎯 L'ANNONCE DE SUCCÈS ET LE MINI-TUTO
|
|
210
|
+
// ==========================================
|
|
164
211
|
console.log('\n \x1b[1;32m✓ [Fleetbo] Project successfully created!\x1b[0m');
|
|
165
212
|
console.log(`\n Installation path: \x1b[36m${projectDir}\x1b[0m\n`);
|
|
213
|
+
|
|
166
214
|
console.log(' \x1b[1;33m🚀 NEXT STEPS (Mini-Tutorial):\x1b[0m');
|
|
167
215
|
console.log(' --------------------------------------------------');
|
|
168
|
-
console.log(` 1️
|
|
169
|
-
console.log(' 2️
|
|
170
|
-
console.log(' 3️
|
|
216
|
+
console.log(` 1️ Navigate to your project : \x1b[36mcd ${projectName}\x1b[0m`);
|
|
217
|
+
console.log(' 2️ Launch the Fleetbo Engine : \x1b[36mnpm run fleetbo\x1b[0m');
|
|
218
|
+
console.log(' 3️ Summon Alex (AI Architect): \x1b[36mnpm run fleetbo alex\x1b[0m');
|
|
171
219
|
console.log(' --------------------------------------------------');
|
|
172
220
|
console.log('\n \x1b[2mHappy coding! Build something amazing without limits.\x1b[0m\n');
|
|
221
|
+
|
|
222
|
+
console.log('');
|
|
173
223
|
|
|
174
224
|
} catch (error) {
|
|
175
225
|
console.error('\n Setup failed:', error.message);
|
|
176
226
|
if (fs.existsSync(projectDir)) {
|
|
177
|
-
try {
|
|
227
|
+
try {
|
|
228
|
+
fs.rmSync(projectDir, { recursive: true, force: true });
|
|
229
|
+
} catch(e) {}
|
|
178
230
|
}
|
|
179
231
|
process.exit(1);
|
|
180
232
|
}
|