@babylonjsmarket/cli 1.0.2 → 1.0.3
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/dist/index.js +587 -435
- package/dist/index.js.map +1 -1
- package/dist/lib/inject/detect-target.d.ts +13 -8
- package/dist/lib/inject/detect-target.js +3 -3
- package/dist/lib/inject/detect-target.js.map +1 -1
- package/dist/lib/inject/engine.js +20 -19
- package/dist/lib/inject/engine.js.map +1 -1
- package/dist/lib/inject/index.js +20 -19
- package/dist/lib/inject/index.js.map +1 -1
- package/dist/lib/inject/inject-options.js +5 -5
- package/dist/lib/inject/inject-options.js.map +1 -1
- package/package.json +4 -2
package/dist/index.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { Command as
|
|
5
|
-
import
|
|
4
|
+
import { Command as Command8 } from "commander";
|
|
5
|
+
import chalk6 from "chalk";
|
|
6
6
|
|
|
7
|
-
// src/commands/
|
|
7
|
+
// src/commands/login-simple.ts
|
|
8
8
|
import { Command } from "commander";
|
|
9
|
+
import chalk from "chalk";
|
|
10
|
+
import open from "open";
|
|
11
|
+
import ora from "ora";
|
|
12
|
+
import fetch2 from "node-fetch";
|
|
9
13
|
|
|
10
14
|
// src/utils/auth.ts
|
|
11
15
|
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
|
|
@@ -171,78 +175,224 @@ var AuthManager = class {
|
|
|
171
175
|
}
|
|
172
176
|
};
|
|
173
177
|
|
|
178
|
+
// src/commands/login-simple.ts
|
|
179
|
+
import { createServer } from "https";
|
|
180
|
+
import { createServer as createHttpServer } from "http";
|
|
181
|
+
import { URL } from "url";
|
|
182
|
+
import { execSync } from "child_process";
|
|
183
|
+
import fs from "fs";
|
|
184
|
+
import path from "path";
|
|
185
|
+
import os from "os";
|
|
186
|
+
var loginCommand = new Command("login").description("Authenticate with BabylonJS Market").option("--no-browser", "Don't open browser automatically").action(async (options) => {
|
|
187
|
+
const authManager = new AuthManager();
|
|
188
|
+
if (authManager.isAuthenticated()) {
|
|
189
|
+
const user = authManager.getUser();
|
|
190
|
+
console.log(chalk.yellow("You are already logged in as:"), chalk.cyan(user?.email || "Unknown"));
|
|
191
|
+
console.log(chalk.gray('Run "bjs-cli logout" to log out first.'));
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
console.log(chalk.blue("Starting authentication flow..."));
|
|
195
|
+
try {
|
|
196
|
+
const port = 8765;
|
|
197
|
+
let token = null;
|
|
198
|
+
const certDir = path.join(os.homedir(), ".bjs", "certs");
|
|
199
|
+
const keyPath = path.join(certDir, "localhost-key.pem");
|
|
200
|
+
const certPath = path.join(certDir, "localhost-cert.pem");
|
|
201
|
+
if (!fs.existsSync(certDir)) {
|
|
202
|
+
fs.mkdirSync(certDir, { recursive: true });
|
|
203
|
+
}
|
|
204
|
+
if (!fs.existsSync(keyPath) || !fs.existsSync(certPath)) {
|
|
205
|
+
console.log(chalk.gray("Generating self-signed certificate for HTTPS..."));
|
|
206
|
+
try {
|
|
207
|
+
execSync(
|
|
208
|
+
`openssl req -x509 -newkey rsa:2048 -nodes -sha256 -days 365 -keyout "${keyPath}" -out "${certPath}" -subj "/C=US/ST=State/L=City/O=BJS-CLI/CN=localhost"`,
|
|
209
|
+
{ stdio: "pipe" }
|
|
210
|
+
);
|
|
211
|
+
} catch (error) {
|
|
212
|
+
console.log(chalk.yellow("Could not generate HTTPS certificate, falling back to HTTP"));
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
let server;
|
|
216
|
+
let protocol = "https";
|
|
217
|
+
if (fs.existsSync(keyPath) && fs.existsSync(certPath)) {
|
|
218
|
+
const serverOptions = {
|
|
219
|
+
key: fs.readFileSync(keyPath),
|
|
220
|
+
cert: fs.readFileSync(certPath)
|
|
221
|
+
};
|
|
222
|
+
server = createServer(serverOptions, (req, res) => {
|
|
223
|
+
handleRequest(req, res);
|
|
224
|
+
});
|
|
225
|
+
} else {
|
|
226
|
+
protocol = "http";
|
|
227
|
+
server = createHttpServer((req, res) => {
|
|
228
|
+
handleRequest(req, res);
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
const handleRequest = (req, res) => {
|
|
232
|
+
const url = new URL(req.url, `${protocol}://localhost:${port}`);
|
|
233
|
+
token = url.searchParams.get("token");
|
|
234
|
+
if (token) {
|
|
235
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
236
|
+
res.end(`
|
|
237
|
+
<!DOCTYPE html>
|
|
238
|
+
<html>
|
|
239
|
+
<head>
|
|
240
|
+
<title>Authentication Successful</title>
|
|
241
|
+
<style>
|
|
242
|
+
body { font-family: system-ui; padding: 40px; text-align: center; }
|
|
243
|
+
.success { color: green; }
|
|
244
|
+
.token { background: #f0f0f0; padding: 10px; margin: 20px; font-family: monospace; word-break: break-all; }
|
|
245
|
+
</style>
|
|
246
|
+
</head>
|
|
247
|
+
<body>
|
|
248
|
+
<h1 class="success">\u2713 Authentication Successful!</h1>
|
|
249
|
+
<p>You can close this window and return to your terminal.</p>
|
|
250
|
+
<div class="token">Token received: ${token.substring(0, 8)}...</div>
|
|
251
|
+
<script>setTimeout(() => window.close(), 3000);</script>
|
|
252
|
+
</body>
|
|
253
|
+
</html>
|
|
254
|
+
`);
|
|
255
|
+
server.close();
|
|
256
|
+
} else {
|
|
257
|
+
res.writeHead(400, { "Content-Type": "text/plain" });
|
|
258
|
+
res.end("Missing token parameter");
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
await new Promise((resolve) => {
|
|
262
|
+
server.listen(port, () => {
|
|
263
|
+
console.log(chalk.gray(`Local callback server started on port ${port} (${protocol.toUpperCase()})`));
|
|
264
|
+
resolve();
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
const callbackUrl = `${protocol}://localhost:${port}`;
|
|
268
|
+
const authUrl = `${API_URL}/auth/cli?callback=${encodeURIComponent(callbackUrl)}`;
|
|
269
|
+
console.log("\n" + chalk.green("To authenticate, visit:"));
|
|
270
|
+
console.log(chalk.cyan.bold(authUrl));
|
|
271
|
+
if (options.browser !== false) {
|
|
272
|
+
console.log("\n" + chalk.gray("Opening browser..."));
|
|
273
|
+
await open(authUrl);
|
|
274
|
+
}
|
|
275
|
+
console.log("\n" + chalk.blue("Waiting for authentication..."));
|
|
276
|
+
const spinner = ora("Waiting for browser authentication...").start();
|
|
277
|
+
const timeout = setTimeout(() => {
|
|
278
|
+
server.close();
|
|
279
|
+
spinner.fail(chalk.red("Authentication timed out"));
|
|
280
|
+
process.exit(1);
|
|
281
|
+
}, 3e5);
|
|
282
|
+
await new Promise((resolve) => {
|
|
283
|
+
server.on("close", () => {
|
|
284
|
+
clearTimeout(timeout);
|
|
285
|
+
resolve();
|
|
286
|
+
});
|
|
287
|
+
});
|
|
288
|
+
if (!token) {
|
|
289
|
+
spinner.fail(chalk.red("No token received"));
|
|
290
|
+
process.exit(1);
|
|
291
|
+
}
|
|
292
|
+
spinner.text = "Exchanging token...";
|
|
293
|
+
const exchangeResponse = await fetch2(`${API_URL}/api/auth/cli/exchange`, {
|
|
294
|
+
method: "POST",
|
|
295
|
+
headers: { "Content-Type": "application/json" },
|
|
296
|
+
body: JSON.stringify({ token })
|
|
297
|
+
});
|
|
298
|
+
if (!exchangeResponse.ok) {
|
|
299
|
+
const error = await exchangeResponse.text();
|
|
300
|
+
spinner.fail(chalk.red("Failed to exchange token"));
|
|
301
|
+
console.error(chalk.red("Error:"), error);
|
|
302
|
+
process.exit(1);
|
|
303
|
+
}
|
|
304
|
+
const tokenData = await exchangeResponse.json();
|
|
305
|
+
authManager.saveTokens(
|
|
306
|
+
tokenData.access_token,
|
|
307
|
+
tokenData.refresh_token,
|
|
308
|
+
tokenData.expires_in
|
|
309
|
+
);
|
|
310
|
+
authManager.saveUser(tokenData.user);
|
|
311
|
+
spinner.succeed(chalk.green("Authentication successful!"));
|
|
312
|
+
console.log(chalk.blue("\nLogged in as:"), chalk.cyan(tokenData.user.email));
|
|
313
|
+
console.log(chalk.gray(`
|
|
314
|
+
Authentication data saved to ~/.bjs/config.json`));
|
|
315
|
+
} catch (error) {
|
|
316
|
+
console.error(chalk.red("Login failed:"), error.message);
|
|
317
|
+
process.exit(1);
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
// src/commands/logout.ts
|
|
322
|
+
import { Command as Command2 } from "commander";
|
|
323
|
+
|
|
174
324
|
// src/utils/theme-colors.ts
|
|
175
|
-
import
|
|
325
|
+
import chalk2 from "chalk";
|
|
176
326
|
var themes = {
|
|
177
327
|
classic: {
|
|
178
|
-
primary: (text) =>
|
|
179
|
-
secondary: (text) =>
|
|
180
|
-
accent: (text) =>
|
|
181
|
-
success: (text) =>
|
|
182
|
-
error: (text) =>
|
|
183
|
-
warning: (text) =>
|
|
184
|
-
info: (text) =>
|
|
185
|
-
dim: (text) =>
|
|
328
|
+
primary: (text) => chalk2.cyan(text),
|
|
329
|
+
secondary: (text) => chalk2.yellow(text),
|
|
330
|
+
accent: (text) => chalk2.magenta(text),
|
|
331
|
+
success: (text) => chalk2.green(text),
|
|
332
|
+
error: (text) => chalk2.red(text),
|
|
333
|
+
warning: (text) => chalk2.yellow(text),
|
|
334
|
+
info: (text) => chalk2.blue(text),
|
|
335
|
+
dim: (text) => chalk2.gray(text)
|
|
186
336
|
},
|
|
187
337
|
desert: {
|
|
188
|
-
primary: (text) =>
|
|
189
|
-
secondary: (text) =>
|
|
190
|
-
accent: (text) =>
|
|
191
|
-
success: (text) =>
|
|
192
|
-
error: (text) =>
|
|
193
|
-
warning: (text) =>
|
|
194
|
-
info: (text) =>
|
|
195
|
-
dim: (text) =>
|
|
338
|
+
primary: (text) => chalk2.yellow(text),
|
|
339
|
+
secondary: (text) => chalk2.red(text),
|
|
340
|
+
accent: (text) => chalk2.green(text),
|
|
341
|
+
success: (text) => chalk2.green(text),
|
|
342
|
+
error: (text) => chalk2.red(text),
|
|
343
|
+
warning: (text) => chalk2.yellow(text),
|
|
344
|
+
info: (text) => chalk2.cyan(text),
|
|
345
|
+
dim: (text) => chalk2.gray(text)
|
|
196
346
|
},
|
|
197
347
|
matrix: {
|
|
198
|
-
primary: (text) =>
|
|
199
|
-
secondary: (text) =>
|
|
200
|
-
accent: (text) =>
|
|
201
|
-
success: (text) =>
|
|
202
|
-
error: (text) =>
|
|
203
|
-
warning: (text) =>
|
|
204
|
-
info: (text) =>
|
|
205
|
-
dim: (text) =>
|
|
348
|
+
primary: (text) => chalk2.green(text),
|
|
349
|
+
secondary: (text) => chalk2.greenBright(text),
|
|
350
|
+
accent: (text) => chalk2.cyan(text),
|
|
351
|
+
success: (text) => chalk2.greenBright(text),
|
|
352
|
+
error: (text) => chalk2.red(text),
|
|
353
|
+
warning: (text) => chalk2.yellow(text),
|
|
354
|
+
info: (text) => chalk2.green(text),
|
|
355
|
+
dim: (text) => chalk2.gray(text)
|
|
206
356
|
},
|
|
207
357
|
commando: {
|
|
208
|
-
primary: (text) =>
|
|
358
|
+
primary: (text) => chalk2.rgb(107, 142, 35)(text),
|
|
209
359
|
// Olive green
|
|
210
|
-
secondary: (text) =>
|
|
360
|
+
secondary: (text) => chalk2.rgb(139, 90, 43)(text),
|
|
211
361
|
// Brown
|
|
212
|
-
accent: (text) =>
|
|
362
|
+
accent: (text) => chalk2.rgb(47, 79, 47)(text),
|
|
213
363
|
// Dark green
|
|
214
|
-
success: (text) =>
|
|
215
|
-
error: (text) =>
|
|
364
|
+
success: (text) => chalk2.green(text),
|
|
365
|
+
error: (text) => chalk2.rgb(139, 0, 0)(text),
|
|
216
366
|
// Dark red
|
|
217
|
-
warning: (text) =>
|
|
367
|
+
warning: (text) => chalk2.rgb(189, 183, 107)(text),
|
|
218
368
|
// Khaki
|
|
219
|
-
info: (text) =>
|
|
369
|
+
info: (text) => chalk2.rgb(85, 107, 47)(text),
|
|
220
370
|
// Dark olive green
|
|
221
|
-
dim: (text) =>
|
|
371
|
+
dim: (text) => chalk2.gray(text)
|
|
222
372
|
},
|
|
223
373
|
sandiego: {
|
|
224
|
-
primary: (text) =>
|
|
225
|
-
secondary: (text) =>
|
|
226
|
-
accent: (text) =>
|
|
227
|
-
success: (text) =>
|
|
228
|
-
error: (text) =>
|
|
229
|
-
warning: (text) =>
|
|
230
|
-
info: (text) =>
|
|
231
|
-
dim: (text) =>
|
|
374
|
+
primary: (text) => chalk2.red(text),
|
|
375
|
+
secondary: (text) => chalk2.yellow(text),
|
|
376
|
+
accent: (text) => chalk2.white(text),
|
|
377
|
+
success: (text) => chalk2.green(text),
|
|
378
|
+
error: (text) => chalk2.redBright(text),
|
|
379
|
+
warning: (text) => chalk2.yellowBright(text),
|
|
380
|
+
info: (text) => chalk2.blue(text),
|
|
381
|
+
dim: (text) => chalk2.gray(text)
|
|
232
382
|
},
|
|
233
383
|
ed209: {
|
|
234
|
-
primary: (text) =>
|
|
384
|
+
primary: (text) => chalk2.rgb(192, 192, 192)(text),
|
|
235
385
|
// Silver
|
|
236
|
-
secondary: (text) =>
|
|
386
|
+
secondary: (text) => chalk2.rgb(135, 206, 235)(text),
|
|
237
387
|
// Sky blue
|
|
238
|
-
accent: (text) =>
|
|
388
|
+
accent: (text) => chalk2.rgb(105, 105, 105)(text),
|
|
239
389
|
// Dim gray
|
|
240
|
-
success: (text) =>
|
|
241
|
-
error: (text) =>
|
|
242
|
-
warning: (text) =>
|
|
390
|
+
success: (text) => chalk2.greenBright(text),
|
|
391
|
+
error: (text) => chalk2.redBright(text),
|
|
392
|
+
warning: (text) => chalk2.rgb(255, 140, 0)(text),
|
|
243
393
|
// Dark orange
|
|
244
|
-
info: (text) =>
|
|
245
|
-
dim: (text) =>
|
|
394
|
+
info: (text) => chalk2.cyanBright(text),
|
|
395
|
+
dim: (text) => chalk2.gray(text)
|
|
246
396
|
}
|
|
247
397
|
};
|
|
248
398
|
function getThemeColors(themeName) {
|
|
@@ -258,16 +408,16 @@ function applyTheme(themeName) {
|
|
|
258
408
|
return {
|
|
259
409
|
...theme,
|
|
260
410
|
// Add some convenience methods
|
|
261
|
-
header: (text) => theme.primary(
|
|
262
|
-
subheader: (text) => theme.secondary(
|
|
263
|
-
highlight: (text) => theme.accent(
|
|
411
|
+
header: (text) => theme.primary(chalk2.bold(text)),
|
|
412
|
+
subheader: (text) => theme.secondary(chalk2.bold(text)),
|
|
413
|
+
highlight: (text) => theme.accent(chalk2.bold(text)),
|
|
264
414
|
code: (text) => theme.dim(`\`${text}\``),
|
|
265
|
-
link: (text) => theme.info(
|
|
415
|
+
link: (text) => theme.info(chalk2.underline(text))
|
|
266
416
|
};
|
|
267
417
|
}
|
|
268
418
|
|
|
269
419
|
// src/commands/logout.ts
|
|
270
|
-
var logoutCommand = new
|
|
420
|
+
var logoutCommand = new Command2("logout").description("Log out from BabylonJS Market").action(async () => {
|
|
271
421
|
const authManager = new AuthManager();
|
|
272
422
|
const theme = applyTheme();
|
|
273
423
|
if (!authManager.isAuthenticated()) {
|
|
@@ -283,8 +433,8 @@ var logoutCommand = new Command("logout").description("Log out from BabylonJS Ma
|
|
|
283
433
|
});
|
|
284
434
|
|
|
285
435
|
// src/commands/whoami.ts
|
|
286
|
-
import { Command as
|
|
287
|
-
var whoamiCommand = new
|
|
436
|
+
import { Command as Command3 } from "commander";
|
|
437
|
+
var whoamiCommand = new Command3("whoami").description("Display current authenticated user").action(async () => {
|
|
288
438
|
const authManager = new AuthManager();
|
|
289
439
|
const theme = applyTheme();
|
|
290
440
|
if (!authManager.isAuthenticated()) {
|
|
@@ -308,13 +458,13 @@ var whoamiCommand = new Command2("whoami").description("Display current authenti
|
|
|
308
458
|
});
|
|
309
459
|
|
|
310
460
|
// src/commands/download.ts
|
|
311
|
-
import { Command as
|
|
312
|
-
import
|
|
461
|
+
import { Command as Command4 } from "commander";
|
|
462
|
+
import ora2 from "ora";
|
|
313
463
|
import { createWriteStream, existsSync as existsSync2, mkdirSync as mkdirSync2 } from "fs";
|
|
314
464
|
import { pipeline } from "stream/promises";
|
|
315
|
-
import
|
|
316
|
-
import
|
|
317
|
-
var downloadCommand = new
|
|
465
|
+
import fetch3 from "node-fetch";
|
|
466
|
+
import path2 from "path";
|
|
467
|
+
var downloadCommand = new Command4("download").description("Download assets from BabylonJS Market").argument("<asset-key>", "Asset key to download").option("-o, --output <path>", "Output directory (default: current directory)").action(async (assetKey, options) => {
|
|
318
468
|
const authManager = new AuthManager();
|
|
319
469
|
const theme = applyTheme();
|
|
320
470
|
if (!authManager.isAuthenticated()) {
|
|
@@ -322,7 +472,7 @@ var downloadCommand = new Command3("download").description("Download assets from
|
|
|
322
472
|
console.log(theme.dim('Run "bjs login" to authenticate.'));
|
|
323
473
|
process.exit(1);
|
|
324
474
|
}
|
|
325
|
-
const spinner =
|
|
475
|
+
const spinner = ora2("Requesting download token...").start();
|
|
326
476
|
try {
|
|
327
477
|
const tokenResponse = await authManager.makeAuthenticatedRequest(
|
|
328
478
|
`${API_URL}/api/assets/download?key=${encodeURIComponent(assetKey)}`
|
|
@@ -353,7 +503,7 @@ var downloadCommand = new Command3("download").description("Download assets from
|
|
|
353
503
|
} else {
|
|
354
504
|
fullDownloadUrl = `${API_URL}/${downloadUrl}`;
|
|
355
505
|
}
|
|
356
|
-
const fileResponse = await
|
|
506
|
+
const fileResponse = await fetch3(fullDownloadUrl);
|
|
357
507
|
if (!fileResponse.ok) {
|
|
358
508
|
throw new Error(`Failed to download file: ${fileResponse.status}`);
|
|
359
509
|
}
|
|
@@ -361,7 +511,7 @@ var downloadCommand = new Command3("download").description("Download assets from
|
|
|
361
511
|
if (!existsSync2(outputDir)) {
|
|
362
512
|
mkdirSync2(outputDir, { recursive: true });
|
|
363
513
|
}
|
|
364
|
-
const outputPath =
|
|
514
|
+
const outputPath = path2.join(outputDir, fileName);
|
|
365
515
|
const contentLength = fileResponse.headers.get("content-length");
|
|
366
516
|
const total = contentLength ? parseInt(contentLength, 10) : 0;
|
|
367
517
|
let loaded = 0;
|
|
@@ -384,7 +534,7 @@ var downloadCommand = new Command3("download").description("Download assets from
|
|
|
384
534
|
});
|
|
385
535
|
|
|
386
536
|
// src/commands/bbs.ts
|
|
387
|
-
import { Command as
|
|
537
|
+
import { Command as Command5 } from "commander";
|
|
388
538
|
import terminalKit3 from "terminal-kit";
|
|
389
539
|
|
|
390
540
|
// src/utils/buffered-bbs.ts
|
|
@@ -956,14 +1106,14 @@ var BufferedBBS = class extends EventEmitter {
|
|
|
956
1106
|
|
|
957
1107
|
// src/utils/course-detail-viewer.ts
|
|
958
1108
|
import terminalKit2 from "terminal-kit";
|
|
959
|
-
import
|
|
1109
|
+
import chalk5 from "chalk";
|
|
960
1110
|
|
|
961
1111
|
// src/utils/markdown-terminal.ts
|
|
962
|
-
import
|
|
1112
|
+
import chalk4 from "chalk";
|
|
963
1113
|
import stripAnsi from "strip-ansi";
|
|
964
1114
|
|
|
965
1115
|
// src/utils/code-highlighter.ts
|
|
966
|
-
import
|
|
1116
|
+
import chalk3 from "chalk";
|
|
967
1117
|
import { highlight, supportsLanguage } from "cli-highlight";
|
|
968
1118
|
var CodeHighlighter = class {
|
|
969
1119
|
static SUPPORTED_LANGUAGES = [
|
|
@@ -1063,9 +1213,9 @@ var CodeHighlighter = class {
|
|
|
1063
1213
|
return code.split("\n").map((line) => {
|
|
1064
1214
|
const lang = language.toLowerCase();
|
|
1065
1215
|
if (lang === "javascript" || lang === "typescript" || lang === "js" || lang === "ts") {
|
|
1066
|
-
return line.replace(/\b(const|let|var|function|class|interface|type|return|if|else|for|while|import|export|from|extends|implements|new|this|super|async|await|try|catch|throw|switch|case|break|continue|default)\b/g,
|
|
1216
|
+
return line.replace(/\b(const|let|var|function|class|interface|type|return|if|else|for|while|import|export|from|extends|implements|new|this|super|async|await|try|catch|throw|switch|case|break|continue|default)\b/g, chalk3.blue("$1")).replace(/(["'])(?:(?=(\\?))\2.)*?\1/g, chalk3.green("$&")).replace(/\b(\d+)\b/g, chalk3.cyan("$1")).replace(/(\/\/.*$)/g, chalk3.gray("$1")).replace(/(\w+)(?=\()/g, chalk3.yellow("$1")).replace(/\.(\w+)/g, "." + chalk3.cyan("$1"));
|
|
1067
1217
|
}
|
|
1068
|
-
return
|
|
1218
|
+
return chalk3.white(line);
|
|
1069
1219
|
});
|
|
1070
1220
|
}
|
|
1071
1221
|
/**
|
|
@@ -1075,16 +1225,16 @@ var CodeHighlighter = class {
|
|
|
1075
1225
|
const lines = [];
|
|
1076
1226
|
const maxWidth = width - 4;
|
|
1077
1227
|
const frameColors = {
|
|
1078
|
-
classic:
|
|
1079
|
-
desert:
|
|
1080
|
-
matrix:
|
|
1081
|
-
commando:
|
|
1228
|
+
classic: chalk3.cyan,
|
|
1229
|
+
desert: chalk3.yellow,
|
|
1230
|
+
matrix: chalk3.green,
|
|
1231
|
+
commando: chalk3.rgb(107, 142, 35),
|
|
1082
1232
|
// Olive green
|
|
1083
|
-
sandiego:
|
|
1084
|
-
ed209:
|
|
1233
|
+
sandiego: chalk3.red,
|
|
1234
|
+
ed209: chalk3.rgb(192, 192, 192)
|
|
1085
1235
|
// Silver
|
|
1086
1236
|
};
|
|
1087
|
-
const frameColor = frameColors[theme] ||
|
|
1237
|
+
const frameColor = frameColors[theme] || chalk3.cyan;
|
|
1088
1238
|
const languageAliases = {
|
|
1089
1239
|
"ts": "typescript",
|
|
1090
1240
|
"js": "javascript",
|
|
@@ -1111,11 +1261,11 @@ var CodeHighlighter = class {
|
|
|
1111
1261
|
const highlightedLines = this.highlightCode(code, displayLang);
|
|
1112
1262
|
highlightedLines.forEach((line, index) => {
|
|
1113
1263
|
const lineNum = String(lineNumStart + index).padStart(3, " ");
|
|
1114
|
-
const lineNumFormatted =
|
|
1264
|
+
const lineNumFormatted = chalk3.dim.gray(`${lineNum} \u2502`);
|
|
1115
1265
|
let codeLine = line;
|
|
1116
1266
|
const maxLineLength = maxWidth - 8;
|
|
1117
1267
|
if (codeLine.length > 200) {
|
|
1118
|
-
codeLine = codeLine.substring(0, 197) +
|
|
1268
|
+
codeLine = codeLine.substring(0, 197) + chalk3.dim("...");
|
|
1119
1269
|
}
|
|
1120
1270
|
lines.push(`${frameColor("\u2502")} ${lineNumFormatted} ${codeLine}`);
|
|
1121
1271
|
});
|
|
@@ -1143,14 +1293,14 @@ var CodeHighlighter = class {
|
|
|
1143
1293
|
*/
|
|
1144
1294
|
static formatInlineCode(code, theme = "classic") {
|
|
1145
1295
|
const themeColors = {
|
|
1146
|
-
classic:
|
|
1147
|
-
desert:
|
|
1148
|
-
matrix:
|
|
1149
|
-
commando:
|
|
1150
|
-
sandiego:
|
|
1151
|
-
ed209:
|
|
1296
|
+
classic: chalk3.bgGray.white,
|
|
1297
|
+
desert: chalk3.bgYellow.black,
|
|
1298
|
+
matrix: chalk3.bgGreen.black,
|
|
1299
|
+
commando: chalk3.bgRgb(107, 142, 35).white,
|
|
1300
|
+
sandiego: chalk3.bgRed.white,
|
|
1301
|
+
ed209: chalk3.bgRgb(105, 105, 105).white
|
|
1152
1302
|
};
|
|
1153
|
-
const colorFn = themeColors[theme] ||
|
|
1303
|
+
const colorFn = themeColors[theme] || chalk3.bgGray.white;
|
|
1154
1304
|
return ` ${colorFn(code)} `;
|
|
1155
1305
|
}
|
|
1156
1306
|
/**
|
|
@@ -1180,7 +1330,7 @@ var CodeHighlighter = class {
|
|
|
1180
1330
|
|
|
1181
1331
|
// src/utils/markdown-terminal.ts
|
|
1182
1332
|
import asciify from "asciify-image";
|
|
1183
|
-
import
|
|
1333
|
+
import fetch4 from "node-fetch";
|
|
1184
1334
|
var MarkdownTerminalRenderer = class {
|
|
1185
1335
|
theme;
|
|
1186
1336
|
width;
|
|
@@ -1358,27 +1508,27 @@ var MarkdownTerminalRenderer = class {
|
|
|
1358
1508
|
return `\0LINK${index}\0`;
|
|
1359
1509
|
});
|
|
1360
1510
|
result = result.replace(/\*\*\*(.+?)\*\*\*/g, (_, content) => {
|
|
1361
|
-
return
|
|
1511
|
+
return chalk4.bold(chalk4.italic(content));
|
|
1362
1512
|
});
|
|
1363
1513
|
result = result.replace(/___(.+?)___/g, (_, content) => {
|
|
1364
|
-
return
|
|
1514
|
+
return chalk4.bold(chalk4.italic(content));
|
|
1365
1515
|
});
|
|
1366
1516
|
result = result.replace(/\*\*(.+?)\*\*/g, (_, content) => {
|
|
1367
|
-
const withItalic = content.replace(/\*(.+?)\*/g, (_2, text2) =>
|
|
1368
|
-
return
|
|
1517
|
+
const withItalic = content.replace(/\*(.+?)\*/g, (_2, text2) => chalk4.italic(text2));
|
|
1518
|
+
return chalk4.bold(withItalic);
|
|
1369
1519
|
});
|
|
1370
1520
|
result = result.replace(/__(.+?)__/g, (_, content) => {
|
|
1371
|
-
const withItalic = content.replace(/_(.+?)_/g, (_2, text2) =>
|
|
1372
|
-
return
|
|
1521
|
+
const withItalic = content.replace(/_(.+?)_/g, (_2, text2) => chalk4.italic(text2));
|
|
1522
|
+
return chalk4.bold(withItalic);
|
|
1373
1523
|
});
|
|
1374
1524
|
result = result.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g, (_, content) => {
|
|
1375
|
-
return
|
|
1525
|
+
return chalk4.italic(content);
|
|
1376
1526
|
});
|
|
1377
1527
|
result = result.replace(/(?<!_)_(?!_)(.+?)(?<!_)_(?!_)/g, (_, content) => {
|
|
1378
|
-
return
|
|
1528
|
+
return chalk4.italic(content);
|
|
1379
1529
|
});
|
|
1380
1530
|
result = result.replace(/~~(.+?)~~/g, (_, content) => {
|
|
1381
|
-
return
|
|
1531
|
+
return chalk4.strikethrough(content);
|
|
1382
1532
|
});
|
|
1383
1533
|
result = result.replace(/\x00CODE(\d+)\x00/g, (_, index) => {
|
|
1384
1534
|
return codeBlocks[parseInt(index)];
|
|
@@ -1386,9 +1536,9 @@ var MarkdownTerminalRenderer = class {
|
|
|
1386
1536
|
result = result.replace(/\x00LINK(\d+)\x00/g, (_, index) => {
|
|
1387
1537
|
const link = links[parseInt(index)];
|
|
1388
1538
|
let formattedText = link.text;
|
|
1389
|
-
formattedText = formattedText.replace(/\*\*(.+?)\*\*/g, (_2, text2) =>
|
|
1390
|
-
formattedText = formattedText.replace(/\*(.+?)\*/g, (_2, text2) =>
|
|
1391
|
-
return
|
|
1539
|
+
formattedText = formattedText.replace(/\*\*(.+?)\*\*/g, (_2, text2) => chalk4.bold(text2));
|
|
1540
|
+
formattedText = formattedText.replace(/\*(.+?)\*/g, (_2, text2) => chalk4.italic(text2));
|
|
1541
|
+
return chalk4.underline(chalk4.blue(formattedText)) + chalk4.gray(` (${link.url})`);
|
|
1392
1542
|
});
|
|
1393
1543
|
return result;
|
|
1394
1544
|
}
|
|
@@ -1402,9 +1552,9 @@ var MarkdownTerminalRenderer = class {
|
|
|
1402
1552
|
const imageIndex = this.trackedImages.length;
|
|
1403
1553
|
const lines = [];
|
|
1404
1554
|
lines.push("");
|
|
1405
|
-
lines.push(
|
|
1555
|
+
lines.push(chalk4.gray("\u250C" + border + "\u2510"));
|
|
1406
1556
|
try {
|
|
1407
|
-
const response = await
|
|
1557
|
+
const response = await fetch4(url);
|
|
1408
1558
|
if (response.ok) {
|
|
1409
1559
|
const buffer = await response.buffer();
|
|
1410
1560
|
const asciiArt = await asciify(buffer, {
|
|
@@ -1418,31 +1568,31 @@ var MarkdownTerminalRenderer = class {
|
|
|
1418
1568
|
for (const line of asciiLines) {
|
|
1419
1569
|
if (line) {
|
|
1420
1570
|
const padding2 = Math.max(0, width - line.length);
|
|
1421
|
-
lines.push(
|
|
1571
|
+
lines.push(chalk4.gray("\u2502 ") + chalk4.cyan(line) + " ".repeat(padding2) + chalk4.gray("\u2502"));
|
|
1422
1572
|
}
|
|
1423
1573
|
}
|
|
1424
1574
|
} else {
|
|
1425
|
-
lines.push(
|
|
1575
|
+
lines.push(chalk4.gray("\u2502") + chalk4.yellow(" \u{1F5BC} Image could not be loaded ") + " ".repeat(Math.max(0, width - 32)) + chalk4.gray("\u2502"));
|
|
1426
1576
|
}
|
|
1427
1577
|
} catch (error) {
|
|
1428
|
-
lines.push(
|
|
1578
|
+
lines.push(chalk4.gray("\u2502") + chalk4.yellow(" \u{1F5BC} Image (local/offline) ") + " ".repeat(Math.max(0, width - 28)) + chalk4.gray("\u2502"));
|
|
1429
1579
|
}
|
|
1430
1580
|
if (lines.length === 2) {
|
|
1431
|
-
lines.push(
|
|
1581
|
+
lines.push(chalk4.gray("\u2502") + chalk4.dim(" [Image] ") + " ".repeat(Math.max(0, width - 10)) + chalk4.gray("\u2502"));
|
|
1432
1582
|
}
|
|
1433
|
-
lines.push(
|
|
1583
|
+
lines.push(chalk4.gray("\u251C" + border + "\u2524"));
|
|
1434
1584
|
if (alt && alt.trim()) {
|
|
1435
1585
|
const altLines = this.wrapText(alt, width - 2);
|
|
1436
1586
|
for (const line of altLines) {
|
|
1437
1587
|
const padding2 = Math.max(0, width - stripAnsi(line).length);
|
|
1438
|
-
lines.push(
|
|
1588
|
+
lines.push(chalk4.gray("\u2502 ") + chalk4.white(line) + " ".repeat(padding2) + chalk4.gray("\u2502"));
|
|
1439
1589
|
}
|
|
1440
|
-
lines.push(
|
|
1590
|
+
lines.push(chalk4.gray("\u251C" + border + "\u2524"));
|
|
1441
1591
|
}
|
|
1442
1592
|
const instruction = `Press [I] to open image ${imageIndex} in browser`;
|
|
1443
1593
|
const padding = Math.max(0, width - instruction.length);
|
|
1444
|
-
lines.push(
|
|
1445
|
-
lines.push(
|
|
1594
|
+
lines.push(chalk4.gray("\u2502 ") + chalk4.yellow(instruction) + " ".repeat(padding) + chalk4.gray("\u2502"));
|
|
1595
|
+
lines.push(chalk4.gray("\u2514" + border + "\u2518"));
|
|
1446
1596
|
lines.push("");
|
|
1447
1597
|
return lines.join("\n");
|
|
1448
1598
|
}
|
|
@@ -1571,8 +1721,8 @@ var MarkdownTerminalRenderer = class {
|
|
|
1571
1721
|
|
|
1572
1722
|
// src/utils/course-detail-viewer.ts
|
|
1573
1723
|
import { EventEmitter as EventEmitter2 } from "events";
|
|
1574
|
-
import { execSync } from "child_process";
|
|
1575
|
-
import
|
|
1724
|
+
import { execSync as execSync2 } from "child_process";
|
|
1725
|
+
import open2 from "open";
|
|
1576
1726
|
|
|
1577
1727
|
// src/utils/course-detail/layout.ts
|
|
1578
1728
|
function computeTocWidth(terminalWidth) {
|
|
@@ -2219,8 +2369,8 @@ var CourseDetailViewer = class extends EventEmitter2 {
|
|
|
2219
2369
|
}
|
|
2220
2370
|
const imageStartLine = result.length;
|
|
2221
2371
|
result.push("");
|
|
2222
|
-
result.push(
|
|
2223
|
-
result.push(
|
|
2372
|
+
result.push(chalk5.cyan("[IMAGE] ") + chalk5.white(alt || "Image"));
|
|
2373
|
+
result.push(chalk5.yellow("Press [I] to view in browser"));
|
|
2224
2374
|
const imageEndLine = result.length;
|
|
2225
2375
|
this.trackedImages.push({ url, alt, lineNumber: imageStartLine, endLine: imageEndLine });
|
|
2226
2376
|
result.push("");
|
|
@@ -2731,7 +2881,7 @@ var CourseDetailViewer = class extends EventEmitter2 {
|
|
|
2731
2881
|
image.lineNumber <= viewportStart && image.endLine && image.endLine >= viewportEnd
|
|
2732
2882
|
);
|
|
2733
2883
|
if (imageVisible) {
|
|
2734
|
-
|
|
2884
|
+
open2(image.url);
|
|
2735
2885
|
return true;
|
|
2736
2886
|
}
|
|
2737
2887
|
}
|
|
@@ -2757,13 +2907,13 @@ var CourseDetailViewer = class extends EventEmitter2 {
|
|
|
2757
2907
|
command = "clip";
|
|
2758
2908
|
} else {
|
|
2759
2909
|
try {
|
|
2760
|
-
|
|
2910
|
+
execSync2("which xclip", { stdio: "ignore" });
|
|
2761
2911
|
command = "xclip -selection clipboard";
|
|
2762
2912
|
} catch {
|
|
2763
2913
|
command = "xsel --clipboard --input";
|
|
2764
2914
|
}
|
|
2765
2915
|
}
|
|
2766
|
-
|
|
2916
|
+
execSync2(command, { input: block.code });
|
|
2767
2917
|
const nowMs = Date.now();
|
|
2768
2918
|
this.vs = {
|
|
2769
2919
|
...this.vs,
|
|
@@ -2879,14 +3029,14 @@ var CourseDetailViewer = class extends EventEmitter2 {
|
|
|
2879
3029
|
};
|
|
2880
3030
|
|
|
2881
3031
|
// src/commands/bbs.ts
|
|
2882
|
-
import
|
|
2883
|
-
import
|
|
3032
|
+
import fs5 from "fs";
|
|
3033
|
+
import path5 from "path";
|
|
2884
3034
|
import { homedir as homedir2 } from "os";
|
|
2885
3035
|
import process2 from "process";
|
|
2886
3036
|
|
|
2887
3037
|
// src/utils/asset-downloader.ts
|
|
2888
|
-
import
|
|
2889
|
-
import
|
|
3038
|
+
import fetch5 from "node-fetch";
|
|
3039
|
+
import fs2 from "fs";
|
|
2890
3040
|
import { pipeline as pipeline2 } from "stream/promises";
|
|
2891
3041
|
var AssetDownloader = class {
|
|
2892
3042
|
authManager;
|
|
@@ -2928,7 +3078,7 @@ var AssetDownloader = class {
|
|
|
2928
3078
|
} else {
|
|
2929
3079
|
downloadUrl = `${this.baseUrl}/${downloadUrl}`;
|
|
2930
3080
|
}
|
|
2931
|
-
const fileResponse = await
|
|
3081
|
+
const fileResponse = await fetch5(downloadUrl);
|
|
2932
3082
|
if (!fileResponse.ok) {
|
|
2933
3083
|
if (fileResponse.status === 401) {
|
|
2934
3084
|
throw new Error("Download token expired. Please try again.");
|
|
@@ -2939,7 +3089,7 @@ var AssetDownloader = class {
|
|
|
2939
3089
|
const contentLength = fileResponse.headers.get("content-length");
|
|
2940
3090
|
const total = parseInt(contentLength || "0", 10);
|
|
2941
3091
|
let loaded = 0;
|
|
2942
|
-
const writer =
|
|
3092
|
+
const writer = fs2.createWriteStream(outputPath);
|
|
2943
3093
|
fileResponse.body.on("data", (chunk) => {
|
|
2944
3094
|
loaded += chunk.length;
|
|
2945
3095
|
writer.write(chunk);
|
|
@@ -2953,7 +3103,7 @@ var AssetDownloader = class {
|
|
|
2953
3103
|
});
|
|
2954
3104
|
await pipeline2(fileResponse.body, writer);
|
|
2955
3105
|
} else {
|
|
2956
|
-
const fileStream =
|
|
3106
|
+
const fileStream = fs2.createWriteStream(outputPath);
|
|
2957
3107
|
await pipeline2(fileResponse.body, fileStream);
|
|
2958
3108
|
}
|
|
2959
3109
|
return true;
|
|
@@ -2981,15 +3131,15 @@ var AssetDownloader = class {
|
|
|
2981
3131
|
};
|
|
2982
3132
|
|
|
2983
3133
|
// src/utils/project-scanner.ts
|
|
2984
|
-
import
|
|
2985
|
-
import
|
|
3134
|
+
import fs3 from "fs";
|
|
3135
|
+
import path3 from "path";
|
|
2986
3136
|
async function scanForProjects(baseDir, maxDepth = 2) {
|
|
2987
3137
|
const projects = [];
|
|
2988
3138
|
let projectId = 1;
|
|
2989
3139
|
async function scanDirectory(dir, depth) {
|
|
2990
3140
|
if (depth > maxDepth) return;
|
|
2991
3141
|
try {
|
|
2992
|
-
const entries = await
|
|
3142
|
+
const entries = await fs3.promises.readdir(dir, { withFileTypes: true });
|
|
2993
3143
|
for (const entry of entries) {
|
|
2994
3144
|
if (entry.name === "node_modules" || entry.name === ".git" || entry.name === "dist" || entry.name === ".next") {
|
|
2995
3145
|
continue;
|
|
@@ -2997,7 +3147,7 @@ async function scanForProjects(baseDir, maxDepth = 2) {
|
|
|
2997
3147
|
if (entry.isSymbolicLink()) {
|
|
2998
3148
|
continue;
|
|
2999
3149
|
}
|
|
3000
|
-
const fullPath =
|
|
3150
|
+
const fullPath = path3.join(dir, entry.name);
|
|
3001
3151
|
if (entry.isDirectory()) {
|
|
3002
3152
|
const isProject = await isProjectDirectory(fullPath);
|
|
3003
3153
|
if (isProject) {
|
|
@@ -3016,10 +3166,10 @@ async function scanForProjects(baseDir, maxDepth = 2) {
|
|
|
3016
3166
|
}
|
|
3017
3167
|
async function isProjectDirectory(dir) {
|
|
3018
3168
|
try {
|
|
3019
|
-
const entries = await
|
|
3169
|
+
const entries = await fs3.promises.readdir(dir);
|
|
3020
3170
|
if (entries.includes("package.json")) {
|
|
3021
|
-
const packageJsonPath =
|
|
3022
|
-
const packageJson = JSON.parse(await
|
|
3171
|
+
const packageJsonPath = path3.join(dir, "package.json");
|
|
3172
|
+
const packageJson = JSON.parse(await fs3.promises.readFile(packageJsonPath, "utf-8"));
|
|
3023
3173
|
const allDeps = {
|
|
3024
3174
|
...packageJson.dependencies || {},
|
|
3025
3175
|
...packageJson.devDependencies || {}
|
|
@@ -3042,10 +3192,10 @@ async function isProjectDirectory(dir) {
|
|
|
3042
3192
|
async function detectGenre(dir) {
|
|
3043
3193
|
const configFiles = ["arcade.json", ".arcade", ".arcade.json"];
|
|
3044
3194
|
for (const configFile of configFiles) {
|
|
3045
|
-
const configPath =
|
|
3046
|
-
if (
|
|
3195
|
+
const configPath = path3.join(dir, configFile);
|
|
3196
|
+
if (fs3.existsSync(configPath)) {
|
|
3047
3197
|
try {
|
|
3048
|
-
const config = JSON.parse(await
|
|
3198
|
+
const config = JSON.parse(await fs3.promises.readFile(configPath, "utf-8"));
|
|
3049
3199
|
if (config.genre || config.template) {
|
|
3050
3200
|
return config.genre || config.template;
|
|
3051
3201
|
}
|
|
@@ -3053,20 +3203,20 @@ async function detectGenre(dir) {
|
|
|
3053
3203
|
}
|
|
3054
3204
|
}
|
|
3055
3205
|
}
|
|
3056
|
-
const packageJsonPath =
|
|
3057
|
-
if (
|
|
3206
|
+
const packageJsonPath = path3.join(dir, "package.json");
|
|
3207
|
+
if (fs3.existsSync(packageJsonPath)) {
|
|
3058
3208
|
try {
|
|
3059
|
-
const pkg = JSON.parse(await
|
|
3209
|
+
const pkg = JSON.parse(await fs3.promises.readFile(packageJsonPath, "utf-8"));
|
|
3060
3210
|
if (pkg.arcade?.genre) return pkg.arcade.genre;
|
|
3061
3211
|
if (pkg.arcade?.template) return pkg.arcade.template;
|
|
3062
3212
|
if (pkg.gameType) return pkg.gameType;
|
|
3063
3213
|
} catch {
|
|
3064
3214
|
}
|
|
3065
3215
|
}
|
|
3066
|
-
const componentsDir =
|
|
3067
|
-
if (
|
|
3216
|
+
const componentsDir = path3.join(dir, "src", "Components");
|
|
3217
|
+
if (fs3.existsSync(componentsDir)) {
|
|
3068
3218
|
try {
|
|
3069
|
-
const components = await
|
|
3219
|
+
const components = await fs3.promises.readdir(componentsDir);
|
|
3070
3220
|
const componentNames = components.map((c) => c.toLowerCase());
|
|
3071
3221
|
if (componentNames.some((c) => c.includes("fps") || c.includes("firstperson"))) {
|
|
3072
3222
|
return "FPS";
|
|
@@ -3086,10 +3236,10 @@ async function detectGenre(dir) {
|
|
|
3086
3236
|
} catch {
|
|
3087
3237
|
}
|
|
3088
3238
|
}
|
|
3089
|
-
const dataDir =
|
|
3090
|
-
if (
|
|
3239
|
+
const dataDir = path3.join(dir, "data");
|
|
3240
|
+
if (fs3.existsSync(dataDir)) {
|
|
3091
3241
|
try {
|
|
3092
|
-
const dataDirs = await
|
|
3242
|
+
const dataDirs = await fs3.promises.readdir(dataDir);
|
|
3093
3243
|
for (const d of dataDirs) {
|
|
3094
3244
|
const lowerName = d.toLowerCase();
|
|
3095
3245
|
if (lowerName === "thirdperson") return "ThirdPerson";
|
|
@@ -3104,12 +3254,12 @@ async function detectGenre(dir) {
|
|
|
3104
3254
|
}
|
|
3105
3255
|
async function scanComponents(dir) {
|
|
3106
3256
|
const components = [];
|
|
3107
|
-
const componentsDir =
|
|
3108
|
-
if (!
|
|
3257
|
+
const componentsDir = path3.join(dir, "src", "Components");
|
|
3258
|
+
if (!fs3.existsSync(componentsDir)) {
|
|
3109
3259
|
return components;
|
|
3110
3260
|
}
|
|
3111
3261
|
try {
|
|
3112
|
-
const files = await
|
|
3262
|
+
const files = await fs3.promises.readdir(componentsDir);
|
|
3113
3263
|
for (const file of files) {
|
|
3114
3264
|
if (file.endsWith(".ts") || file.endsWith(".js")) {
|
|
3115
3265
|
const componentName = file.replace(/\.(ts|js)$/, "");
|
|
@@ -3123,14 +3273,14 @@ async function scanComponents(dir) {
|
|
|
3123
3273
|
return components.sort();
|
|
3124
3274
|
}
|
|
3125
3275
|
async function analyzeProject(dir, id) {
|
|
3126
|
-
const name =
|
|
3276
|
+
const name = path3.basename(dir);
|
|
3127
3277
|
let hasPackageJson = false;
|
|
3128
3278
|
let engine = "Unknown";
|
|
3129
3279
|
try {
|
|
3130
|
-
const packageJsonPath =
|
|
3131
|
-
if (
|
|
3280
|
+
const packageJsonPath = path3.join(dir, "package.json");
|
|
3281
|
+
if (fs3.existsSync(packageJsonPath)) {
|
|
3132
3282
|
hasPackageJson = true;
|
|
3133
|
-
const packageJson = JSON.parse(await
|
|
3283
|
+
const packageJson = JSON.parse(await fs3.promises.readFile(packageJsonPath, "utf-8"));
|
|
3134
3284
|
const allDeps = {
|
|
3135
3285
|
...packageJson.dependencies || {},
|
|
3136
3286
|
...packageJson.devDependencies || {}
|
|
@@ -3158,15 +3308,15 @@ async function analyzeProject(dir, id) {
|
|
|
3158
3308
|
}
|
|
3159
3309
|
|
|
3160
3310
|
// src/utils/component-catalog.ts
|
|
3161
|
-
import
|
|
3162
|
-
import
|
|
3311
|
+
import fs4 from "fs";
|
|
3312
|
+
import path4 from "path";
|
|
3163
3313
|
function getLibraryPath() {
|
|
3164
3314
|
const auth = new AuthManager();
|
|
3165
3315
|
return auth.getLibraryPath();
|
|
3166
3316
|
}
|
|
3167
3317
|
function isLibraryInitialized() {
|
|
3168
3318
|
const libraryPath = getLibraryPath();
|
|
3169
|
-
return
|
|
3319
|
+
return fs4.existsSync(path4.join(libraryPath, "Components"));
|
|
3170
3320
|
}
|
|
3171
3321
|
async function initializeLibrary(libraryPath) {
|
|
3172
3322
|
const targetPath = libraryPath || getLibraryPath();
|
|
@@ -3180,13 +3330,13 @@ async function initializeLibrary(libraryPath) {
|
|
|
3180
3330
|
];
|
|
3181
3331
|
try {
|
|
3182
3332
|
for (const dir of dirs) {
|
|
3183
|
-
const fullPath =
|
|
3184
|
-
if (!
|
|
3185
|
-
|
|
3333
|
+
const fullPath = path4.join(targetPath, dir);
|
|
3334
|
+
if (!fs4.existsSync(fullPath)) {
|
|
3335
|
+
fs4.mkdirSync(fullPath, { recursive: true });
|
|
3186
3336
|
}
|
|
3187
3337
|
}
|
|
3188
|
-
const readmePath =
|
|
3189
|
-
if (!
|
|
3338
|
+
const readmePath = path4.join(targetPath, "README.md");
|
|
3339
|
+
if (!fs4.existsSync(readmePath)) {
|
|
3190
3340
|
const readme = `# BJS Library
|
|
3191
3341
|
|
|
3192
3342
|
Your personal library of BabylonJS components, systems, and game mode presets.
|
|
@@ -3213,7 +3363,7 @@ Your personal library of BabylonJS components, systems, and game mode presets.
|
|
|
3213
3363
|
|
|
3214
3364
|
Content from babylonjsmarket.com will be downloaded here automatically.
|
|
3215
3365
|
`;
|
|
3216
|
-
|
|
3366
|
+
fs4.writeFileSync(readmePath, readme);
|
|
3217
3367
|
}
|
|
3218
3368
|
return { success: true, message: `Library initialized at ${targetPath}` };
|
|
3219
3369
|
} catch (error) {
|
|
@@ -3222,12 +3372,12 @@ Content from babylonjsmarket.com will be downloaded here automatically.
|
|
|
3222
3372
|
}
|
|
3223
3373
|
function getGameModeSchema(modeName) {
|
|
3224
3374
|
const libraryPath = getLibraryPath();
|
|
3225
|
-
const schemaPath =
|
|
3226
|
-
if (!
|
|
3375
|
+
const schemaPath = path4.join(libraryPath, "GameModes", modeName, "gamemode.json");
|
|
3376
|
+
if (!fs4.existsSync(schemaPath)) {
|
|
3227
3377
|
return null;
|
|
3228
3378
|
}
|
|
3229
3379
|
try {
|
|
3230
|
-
const content =
|
|
3380
|
+
const content = fs4.readFileSync(schemaPath, "utf-8");
|
|
3231
3381
|
return JSON.parse(content);
|
|
3232
3382
|
} catch {
|
|
3233
3383
|
return null;
|
|
@@ -3294,45 +3444,45 @@ var COMPONENT_CATALOG = [
|
|
|
3294
3444
|
];
|
|
3295
3445
|
async function installComponent(componentName, targetProjectPath) {
|
|
3296
3446
|
const libraryPath = getLibraryPath();
|
|
3297
|
-
const componentDir =
|
|
3298
|
-
const componentFile =
|
|
3447
|
+
const componentDir = path4.join(libraryPath, "Components", componentName);
|
|
3448
|
+
const componentFile = path4.join(componentDir, `${componentName}.ts`);
|
|
3299
3449
|
const files = [];
|
|
3300
|
-
if (!
|
|
3301
|
-
const legacyPath =
|
|
3302
|
-
if (
|
|
3303
|
-
const targetComponentDir2 =
|
|
3304
|
-
if (!
|
|
3305
|
-
|
|
3306
|
-
}
|
|
3307
|
-
const targetComponentPath2 =
|
|
3308
|
-
if (
|
|
3450
|
+
if (!fs4.existsSync(componentFile)) {
|
|
3451
|
+
const legacyPath = path4.join(libraryPath, "Components", `${componentName}.ts`);
|
|
3452
|
+
if (fs4.existsSync(legacyPath)) {
|
|
3453
|
+
const targetComponentDir2 = path4.join(targetProjectPath, "src", "Components");
|
|
3454
|
+
if (!fs4.existsSync(targetComponentDir2)) {
|
|
3455
|
+
fs4.mkdirSync(targetComponentDir2, { recursive: true });
|
|
3456
|
+
}
|
|
3457
|
+
const targetComponentPath2 = path4.join(targetComponentDir2, `${componentName}.ts`);
|
|
3458
|
+
if (fs4.existsSync(targetComponentPath2)) {
|
|
3309
3459
|
return { success: false, message: `${componentName}.ts already exists`, files };
|
|
3310
3460
|
}
|
|
3311
|
-
|
|
3461
|
+
fs4.copyFileSync(legacyPath, targetComponentPath2);
|
|
3312
3462
|
files.push(`src/Components/${componentName}.ts`);
|
|
3313
3463
|
return { success: true, message: `Installed ${componentName} (${files.length} files)`, files };
|
|
3314
3464
|
}
|
|
3315
3465
|
return { success: false, message: `Component ${componentName} not found in Library`, files };
|
|
3316
3466
|
}
|
|
3317
|
-
const targetComponentDir =
|
|
3318
|
-
if (!
|
|
3319
|
-
|
|
3467
|
+
const targetComponentDir = path4.join(targetProjectPath, "src", "Components");
|
|
3468
|
+
if (!fs4.existsSync(targetComponentDir)) {
|
|
3469
|
+
fs4.mkdirSync(targetComponentDir, { recursive: true });
|
|
3320
3470
|
}
|
|
3321
|
-
const targetComponentPath =
|
|
3322
|
-
if (
|
|
3471
|
+
const targetComponentPath = path4.join(targetComponentDir, `${componentName}.ts`);
|
|
3472
|
+
if (fs4.existsSync(targetComponentPath)) {
|
|
3323
3473
|
return { success: false, message: `${componentName}.ts already exists`, files };
|
|
3324
3474
|
}
|
|
3325
|
-
|
|
3475
|
+
fs4.copyFileSync(componentFile, targetComponentPath);
|
|
3326
3476
|
files.push(`src/Components/${componentName}.ts`);
|
|
3327
|
-
const testPath =
|
|
3328
|
-
if (
|
|
3329
|
-
const targetTestDir =
|
|
3330
|
-
if (!
|
|
3331
|
-
|
|
3332
|
-
}
|
|
3333
|
-
const targetTestPath =
|
|
3334
|
-
if (!
|
|
3335
|
-
|
|
3477
|
+
const testPath = path4.join(componentDir, `${componentName}.test.ts`);
|
|
3478
|
+
if (fs4.existsSync(testPath)) {
|
|
3479
|
+
const targetTestDir = path4.join(targetProjectPath, "tests", "Components");
|
|
3480
|
+
if (!fs4.existsSync(targetTestDir)) {
|
|
3481
|
+
fs4.mkdirSync(targetTestDir, { recursive: true });
|
|
3482
|
+
}
|
|
3483
|
+
const targetTestPath = path4.join(targetTestDir, `${componentName}.test.ts`);
|
|
3484
|
+
if (!fs4.existsSync(targetTestPath)) {
|
|
3485
|
+
fs4.copyFileSync(testPath, targetTestPath);
|
|
3336
3486
|
files.push(`tests/Components/${componentName}.test.ts`);
|
|
3337
3487
|
}
|
|
3338
3488
|
}
|
|
@@ -3344,26 +3494,26 @@ async function installComponent(componentName, targetProjectPath) {
|
|
|
3344
3494
|
}
|
|
3345
3495
|
function getAvailableComponents(targetProjectPath) {
|
|
3346
3496
|
const libraryPath = getLibraryPath();
|
|
3347
|
-
const libraryComponentsDir =
|
|
3348
|
-
const targetComponentDir =
|
|
3497
|
+
const libraryComponentsDir = path4.join(libraryPath, "Components");
|
|
3498
|
+
const targetComponentDir = path4.join(targetProjectPath, "src", "Components");
|
|
3349
3499
|
const installedComponents = /* @__PURE__ */ new Set();
|
|
3350
3500
|
const availableComponents = [];
|
|
3351
|
-
if (
|
|
3352
|
-
const files =
|
|
3501
|
+
if (fs4.existsSync(targetComponentDir)) {
|
|
3502
|
+
const files = fs4.readdirSync(targetComponentDir);
|
|
3353
3503
|
for (const file of files) {
|
|
3354
3504
|
if (file.endsWith(".ts")) {
|
|
3355
3505
|
installedComponents.add(file.replace(".ts", ""));
|
|
3356
3506
|
}
|
|
3357
3507
|
}
|
|
3358
3508
|
}
|
|
3359
|
-
if (
|
|
3360
|
-
const entries =
|
|
3509
|
+
if (fs4.existsSync(libraryComponentsDir)) {
|
|
3510
|
+
const entries = fs4.readdirSync(libraryComponentsDir, { withFileTypes: true });
|
|
3361
3511
|
for (const entry of entries) {
|
|
3362
3512
|
let name;
|
|
3363
3513
|
if (entry.isDirectory()) {
|
|
3364
3514
|
name = entry.name;
|
|
3365
|
-
const mainFile =
|
|
3366
|
-
if (!
|
|
3515
|
+
const mainFile = path4.join(libraryComponentsDir, name, `${name}.ts`);
|
|
3516
|
+
if (!fs4.existsSync(mainFile)) {
|
|
3367
3517
|
continue;
|
|
3368
3518
|
}
|
|
3369
3519
|
} else if (entry.isFile() && entry.name.endsWith(".ts")) {
|
|
@@ -3386,13 +3536,13 @@ function getAvailableComponents(targetProjectPath) {
|
|
|
3386
3536
|
}
|
|
3387
3537
|
function getGameModeCatalog() {
|
|
3388
3538
|
const libraryPath = getLibraryPath();
|
|
3389
|
-
const gameModesDir =
|
|
3539
|
+
const gameModesDir = path4.join(libraryPath, "GameModes");
|
|
3390
3540
|
const modes = [];
|
|
3391
|
-
if (!
|
|
3541
|
+
if (!fs4.existsSync(gameModesDir)) {
|
|
3392
3542
|
return modes;
|
|
3393
3543
|
}
|
|
3394
3544
|
try {
|
|
3395
|
-
const dirs =
|
|
3545
|
+
const dirs = fs4.readdirSync(gameModesDir, { withFileTypes: true });
|
|
3396
3546
|
for (const dir of dirs) {
|
|
3397
3547
|
if (!dir.isDirectory()) continue;
|
|
3398
3548
|
const schema = getGameModeSchema(dir.name);
|
|
@@ -3405,13 +3555,13 @@ function getGameModeCatalog() {
|
|
|
3405
3555
|
hasShared: schema.includeShared || false
|
|
3406
3556
|
});
|
|
3407
3557
|
} else {
|
|
3408
|
-
const modePath =
|
|
3558
|
+
const modePath = path4.join(gameModesDir, dir.name);
|
|
3409
3559
|
modes.push({
|
|
3410
3560
|
name: dir.name,
|
|
3411
3561
|
description: `${dir.name} game mode`,
|
|
3412
|
-
hasScenes:
|
|
3413
|
-
hasScreens:
|
|
3414
|
-
hasShared:
|
|
3562
|
+
hasScenes: fs4.existsSync(path4.join(modePath, "Scenes")),
|
|
3563
|
+
hasScreens: fs4.existsSync(path4.join(modePath, "Screens")),
|
|
3564
|
+
hasShared: fs4.existsSync(path4.join(modePath, "Data"))
|
|
3415
3565
|
});
|
|
3416
3566
|
}
|
|
3417
3567
|
}
|
|
@@ -3420,12 +3570,12 @@ function getGameModeCatalog() {
|
|
|
3420
3570
|
return modes;
|
|
3421
3571
|
}
|
|
3422
3572
|
function getAvailableGameModes(targetProjectPath) {
|
|
3423
|
-
const targetDataDir =
|
|
3573
|
+
const targetDataDir = path4.join(targetProjectPath, "data");
|
|
3424
3574
|
const installedModes = /* @__PURE__ */ new Set();
|
|
3425
|
-
if (
|
|
3426
|
-
const dirs =
|
|
3575
|
+
if (fs4.existsSync(targetDataDir)) {
|
|
3576
|
+
const dirs = fs4.readdirSync(targetDataDir);
|
|
3427
3577
|
for (const dir of dirs) {
|
|
3428
|
-
const stat =
|
|
3578
|
+
const stat = fs4.statSync(path4.join(targetDataDir, dir));
|
|
3429
3579
|
if (stat.isDirectory()) {
|
|
3430
3580
|
installedModes.add(dir);
|
|
3431
3581
|
}
|
|
@@ -3434,12 +3584,12 @@ function getAvailableGameModes(targetProjectPath) {
|
|
|
3434
3584
|
return getGameModeCatalog().filter((m) => !installedModes.has(m.name));
|
|
3435
3585
|
}
|
|
3436
3586
|
function getInstalledGameModes(targetProjectPath) {
|
|
3437
|
-
const targetDataDir =
|
|
3587
|
+
const targetDataDir = path4.join(targetProjectPath, "data");
|
|
3438
3588
|
const modes = [];
|
|
3439
|
-
if (
|
|
3440
|
-
const dirs =
|
|
3589
|
+
if (fs4.existsSync(targetDataDir)) {
|
|
3590
|
+
const dirs = fs4.readdirSync(targetDataDir);
|
|
3441
3591
|
for (const dir of dirs) {
|
|
3442
|
-
const stat =
|
|
3592
|
+
const stat = fs4.statSync(path4.join(targetDataDir, dir));
|
|
3443
3593
|
if (stat.isDirectory() && dir !== "Shared") {
|
|
3444
3594
|
modes.push(dir);
|
|
3445
3595
|
}
|
|
@@ -3448,29 +3598,29 @@ function getInstalledGameModes(targetProjectPath) {
|
|
|
3448
3598
|
return modes;
|
|
3449
3599
|
}
|
|
3450
3600
|
function copyDir(src, dest, files, baseRelPath) {
|
|
3451
|
-
|
|
3452
|
-
const entries =
|
|
3601
|
+
fs4.mkdirSync(dest, { recursive: true });
|
|
3602
|
+
const entries = fs4.readdirSync(src, { withFileTypes: true });
|
|
3453
3603
|
for (const entry of entries) {
|
|
3454
|
-
const srcPath =
|
|
3455
|
-
const destPath =
|
|
3456
|
-
const relPath =
|
|
3604
|
+
const srcPath = path4.join(src, entry.name);
|
|
3605
|
+
const destPath = path4.join(dest, entry.name);
|
|
3606
|
+
const relPath = path4.join(baseRelPath, entry.name);
|
|
3457
3607
|
if (entry.isDirectory()) {
|
|
3458
3608
|
copyDir(srcPath, destPath, files, relPath);
|
|
3459
3609
|
} else if (entry.name !== "gamemode.json") {
|
|
3460
|
-
|
|
3610
|
+
fs4.copyFileSync(srcPath, destPath);
|
|
3461
3611
|
files.push(relPath);
|
|
3462
3612
|
}
|
|
3463
3613
|
}
|
|
3464
3614
|
}
|
|
3465
3615
|
async function installGameMode(modeName, targetProjectPath) {
|
|
3466
3616
|
const libraryPath = getLibraryPath();
|
|
3467
|
-
const gameModeDir =
|
|
3617
|
+
const gameModeDir = path4.join(libraryPath, "GameModes", modeName);
|
|
3468
3618
|
const files = [];
|
|
3469
|
-
if (!
|
|
3619
|
+
if (!fs4.existsSync(gameModeDir)) {
|
|
3470
3620
|
return { success: false, message: `Game mode ${modeName} not found in Library`, files };
|
|
3471
3621
|
}
|
|
3472
|
-
const targetDataDir =
|
|
3473
|
-
if (
|
|
3622
|
+
const targetDataDir = path4.join(targetProjectPath, "data", modeName);
|
|
3623
|
+
if (fs4.existsSync(targetDataDir)) {
|
|
3474
3624
|
return { success: false, message: `${modeName} already exists`, files };
|
|
3475
3625
|
}
|
|
3476
3626
|
const schema = getGameModeSchema(modeName);
|
|
@@ -3484,34 +3634,34 @@ async function installGameMode(modeName, targetProjectPath) {
|
|
|
3484
3634
|
}
|
|
3485
3635
|
if (schema.systems) {
|
|
3486
3636
|
for (const sysName of schema.systems) {
|
|
3487
|
-
const sysPath =
|
|
3488
|
-
if (
|
|
3489
|
-
const targetSysDir =
|
|
3490
|
-
if (!
|
|
3491
|
-
|
|
3637
|
+
const sysPath = path4.join(libraryPath, "Systems", `${sysName}.ts`);
|
|
3638
|
+
if (fs4.existsSync(sysPath)) {
|
|
3639
|
+
const targetSysDir = path4.join(targetProjectPath, "src", "Systems");
|
|
3640
|
+
if (!fs4.existsSync(targetSysDir)) {
|
|
3641
|
+
fs4.mkdirSync(targetSysDir, { recursive: true });
|
|
3492
3642
|
}
|
|
3493
|
-
const targetSysPath =
|
|
3494
|
-
if (!
|
|
3495
|
-
|
|
3643
|
+
const targetSysPath = path4.join(targetSysDir, `${sysName}.ts`);
|
|
3644
|
+
if (!fs4.existsSync(targetSysPath)) {
|
|
3645
|
+
fs4.copyFileSync(sysPath, targetSysPath);
|
|
3496
3646
|
files.push(`src/Systems/${sysName}.ts`);
|
|
3497
3647
|
}
|
|
3498
3648
|
}
|
|
3499
3649
|
}
|
|
3500
3650
|
}
|
|
3501
|
-
|
|
3502
|
-
const modeDataDir =
|
|
3503
|
-
if (
|
|
3504
|
-
const targetSharedDir =
|
|
3651
|
+
fs4.mkdirSync(targetDataDir, { recursive: true });
|
|
3652
|
+
const modeDataDir = path4.join(gameModeDir, "Data");
|
|
3653
|
+
if (fs4.existsSync(modeDataDir)) {
|
|
3654
|
+
const targetSharedDir = path4.join(targetDataDir, "Shared");
|
|
3505
3655
|
copyDir(modeDataDir, targetSharedDir, files, `data/${modeName}/Shared`);
|
|
3506
3656
|
}
|
|
3507
|
-
const modeScenesDir =
|
|
3508
|
-
if (
|
|
3509
|
-
const targetScenesDir =
|
|
3657
|
+
const modeScenesDir = path4.join(gameModeDir, "Scenes");
|
|
3658
|
+
if (fs4.existsSync(modeScenesDir)) {
|
|
3659
|
+
const targetScenesDir = path4.join(targetDataDir, "Scenes");
|
|
3510
3660
|
copyDir(modeScenesDir, targetScenesDir, files, `data/${modeName}/Scenes`);
|
|
3511
3661
|
}
|
|
3512
|
-
const modeScreensDir =
|
|
3513
|
-
if (
|
|
3514
|
-
const targetScreensDir =
|
|
3662
|
+
const modeScreensDir = path4.join(gameModeDir, "Screens");
|
|
3663
|
+
if (fs4.existsSync(modeScreensDir)) {
|
|
3664
|
+
const targetScreensDir = path4.join(targetDataDir, "Screens");
|
|
3515
3665
|
copyDir(modeScreensDir, targetScreensDir, files, `data/${modeName}/Screens`);
|
|
3516
3666
|
}
|
|
3517
3667
|
} else {
|
|
@@ -3528,18 +3678,18 @@ async function installGameMode(modeName, targetProjectPath) {
|
|
|
3528
3678
|
}
|
|
3529
3679
|
function getProjectScenes(targetProjectPath) {
|
|
3530
3680
|
const scenes = [];
|
|
3531
|
-
const dataDir =
|
|
3532
|
-
if (!
|
|
3533
|
-
const modes =
|
|
3681
|
+
const dataDir = path4.join(targetProjectPath, "data");
|
|
3682
|
+
if (!fs4.existsSync(dataDir)) return scenes;
|
|
3683
|
+
const modes = fs4.readdirSync(dataDir);
|
|
3534
3684
|
for (const mode of modes) {
|
|
3535
|
-
const scenesDir =
|
|
3536
|
-
if (
|
|
3537
|
-
const sceneFiles =
|
|
3685
|
+
const scenesDir = path4.join(dataDir, mode, "Scenes");
|
|
3686
|
+
if (fs4.existsSync(scenesDir)) {
|
|
3687
|
+
const sceneFiles = fs4.readdirSync(scenesDir);
|
|
3538
3688
|
for (const file of sceneFiles) {
|
|
3539
3689
|
if (file.endsWith(".ts")) {
|
|
3540
3690
|
scenes.push({
|
|
3541
3691
|
name: file.replace(".ts", ""),
|
|
3542
|
-
path:
|
|
3692
|
+
path: path4.join(scenesDir, file),
|
|
3543
3693
|
gameMode: mode
|
|
3544
3694
|
});
|
|
3545
3695
|
}
|
|
@@ -3549,12 +3699,12 @@ function getProjectScenes(targetProjectPath) {
|
|
|
3549
3699
|
return scenes;
|
|
3550
3700
|
}
|
|
3551
3701
|
async function createScene(targetProjectPath, gameMode, sceneName) {
|
|
3552
|
-
const scenesDir =
|
|
3553
|
-
if (!
|
|
3554
|
-
|
|
3702
|
+
const scenesDir = path4.join(targetProjectPath, "data", gameMode, "Scenes");
|
|
3703
|
+
if (!fs4.existsSync(scenesDir)) {
|
|
3704
|
+
fs4.mkdirSync(scenesDir, { recursive: true });
|
|
3555
3705
|
}
|
|
3556
|
-
const scenePath =
|
|
3557
|
-
if (
|
|
3706
|
+
const scenePath = path4.join(scenesDir, `${sceneName}.ts`);
|
|
3707
|
+
if (fs4.existsSync(scenePath)) {
|
|
3558
3708
|
return { success: false, message: `Scene ${sceneName} already exists`, path: "" };
|
|
3559
3709
|
}
|
|
3560
3710
|
const template = `import Basics from "../../Shared/Basics";
|
|
@@ -3584,7 +3734,7 @@ export default {
|
|
|
3584
3734
|
};
|
|
3585
3735
|
`;
|
|
3586
3736
|
try {
|
|
3587
|
-
|
|
3737
|
+
fs4.writeFileSync(scenePath, template);
|
|
3588
3738
|
return {
|
|
3589
3739
|
success: true,
|
|
3590
3740
|
message: `Created scene ${sceneName}`,
|
|
@@ -3605,46 +3755,46 @@ async function migrateFromArcadeRef() {
|
|
|
3605
3755
|
}
|
|
3606
3756
|
}
|
|
3607
3757
|
try {
|
|
3608
|
-
const srcComponents =
|
|
3609
|
-
if (
|
|
3610
|
-
const targetComponents =
|
|
3611
|
-
const componentFiles2 =
|
|
3758
|
+
const srcComponents = path4.join(ARCADE_REF_PATH, "src", "Components");
|
|
3759
|
+
if (fs4.existsSync(srcComponents)) {
|
|
3760
|
+
const targetComponents = path4.join(libraryPath, "Components");
|
|
3761
|
+
const componentFiles2 = fs4.readdirSync(srcComponents);
|
|
3612
3762
|
for (const file of componentFiles2) {
|
|
3613
3763
|
if (file.endsWith(".ts")) {
|
|
3614
|
-
const srcPath =
|
|
3615
|
-
const destPath =
|
|
3616
|
-
if (!
|
|
3617
|
-
|
|
3764
|
+
const srcPath = path4.join(srcComponents, file);
|
|
3765
|
+
const destPath = path4.join(targetComponents, file);
|
|
3766
|
+
if (!fs4.existsSync(destPath)) {
|
|
3767
|
+
fs4.copyFileSync(srcPath, destPath);
|
|
3618
3768
|
files.push(`Components/${file}`);
|
|
3619
3769
|
}
|
|
3620
3770
|
}
|
|
3621
3771
|
}
|
|
3622
3772
|
}
|
|
3623
|
-
const srcTests =
|
|
3624
|
-
if (
|
|
3625
|
-
const targetTests =
|
|
3626
|
-
const testFiles =
|
|
3773
|
+
const srcTests = path4.join(ARCADE_REF_PATH, "tests", "Components");
|
|
3774
|
+
if (fs4.existsSync(srcTests)) {
|
|
3775
|
+
const targetTests = path4.join(libraryPath, "Tests");
|
|
3776
|
+
const testFiles = fs4.readdirSync(srcTests);
|
|
3627
3777
|
for (const file of testFiles) {
|
|
3628
3778
|
if (file.endsWith(".test.ts")) {
|
|
3629
|
-
const srcPath =
|
|
3630
|
-
const destPath =
|
|
3631
|
-
if (!
|
|
3632
|
-
|
|
3779
|
+
const srcPath = path4.join(srcTests, file);
|
|
3780
|
+
const destPath = path4.join(targetTests, file);
|
|
3781
|
+
if (!fs4.existsSync(destPath)) {
|
|
3782
|
+
fs4.copyFileSync(srcPath, destPath);
|
|
3633
3783
|
files.push(`Tests/${file}`);
|
|
3634
3784
|
}
|
|
3635
3785
|
}
|
|
3636
3786
|
}
|
|
3637
3787
|
}
|
|
3638
|
-
const srcData =
|
|
3639
|
-
if (
|
|
3640
|
-
const targetData =
|
|
3641
|
-
const dataFiles =
|
|
3788
|
+
const srcData = path4.join(ARCADE_REF_PATH, "data", "Shared");
|
|
3789
|
+
if (fs4.existsSync(srcData)) {
|
|
3790
|
+
const targetData = path4.join(libraryPath, "Data");
|
|
3791
|
+
const dataFiles = fs4.readdirSync(srcData);
|
|
3642
3792
|
for (const file of dataFiles) {
|
|
3643
3793
|
if (file.endsWith(".ts")) {
|
|
3644
|
-
const srcPath =
|
|
3645
|
-
const destPath =
|
|
3646
|
-
if (!
|
|
3647
|
-
|
|
3794
|
+
const srcPath = path4.join(srcData, file);
|
|
3795
|
+
const destPath = path4.join(targetData, file);
|
|
3796
|
+
if (!fs4.existsSync(destPath)) {
|
|
3797
|
+
fs4.copyFileSync(srcPath, destPath);
|
|
3648
3798
|
files.push(`Data/${file}`);
|
|
3649
3799
|
}
|
|
3650
3800
|
}
|
|
@@ -3652,24 +3802,24 @@ async function migrateFromArcadeRef() {
|
|
|
3652
3802
|
}
|
|
3653
3803
|
const gameModes = ["ThirdPerson", "Arcade"];
|
|
3654
3804
|
for (const mode of gameModes) {
|
|
3655
|
-
const srcMode =
|
|
3656
|
-
if (
|
|
3657
|
-
const targetMode =
|
|
3658
|
-
if (!
|
|
3659
|
-
|
|
3805
|
+
const srcMode = path4.join(ARCADE_REF_PATH, "data", mode);
|
|
3806
|
+
if (fs4.existsSync(srcMode)) {
|
|
3807
|
+
const targetMode = path4.join(libraryPath, "GameModes", mode);
|
|
3808
|
+
if (!fs4.existsSync(targetMode)) {
|
|
3809
|
+
fs4.mkdirSync(targetMode, { recursive: true });
|
|
3660
3810
|
const subdirs = ["Scenes", "Screens", "Shared"];
|
|
3661
3811
|
for (const subdir of subdirs) {
|
|
3662
|
-
const srcSubdir =
|
|
3663
|
-
if (
|
|
3664
|
-
const targetSubdir = subdir === "Shared" ?
|
|
3665
|
-
|
|
3666
|
-
const subFiles =
|
|
3812
|
+
const srcSubdir = path4.join(srcMode, subdir);
|
|
3813
|
+
if (fs4.existsSync(srcSubdir)) {
|
|
3814
|
+
const targetSubdir = subdir === "Shared" ? path4.join(targetMode, "Data") : path4.join(targetMode, subdir);
|
|
3815
|
+
fs4.mkdirSync(targetSubdir, { recursive: true });
|
|
3816
|
+
const subFiles = fs4.readdirSync(srcSubdir);
|
|
3667
3817
|
for (const file of subFiles) {
|
|
3668
|
-
const srcPath =
|
|
3669
|
-
const destPath =
|
|
3670
|
-
const stat =
|
|
3818
|
+
const srcPath = path4.join(srcSubdir, file);
|
|
3819
|
+
const destPath = path4.join(targetSubdir, file);
|
|
3820
|
+
const stat = fs4.statSync(srcPath);
|
|
3671
3821
|
if (stat.isFile()) {
|
|
3672
|
-
|
|
3822
|
+
fs4.copyFileSync(srcPath, destPath);
|
|
3673
3823
|
files.push(`GameModes/${mode}/${subdir === "Shared" ? "Data" : subdir}/${file}`);
|
|
3674
3824
|
}
|
|
3675
3825
|
}
|
|
@@ -3681,11 +3831,11 @@ async function migrateFromArcadeRef() {
|
|
|
3681
3831
|
components: mode === "ThirdPerson" ? ["Movement", "FollowCamera", "PlayerInput", "Animation", "Physics", "KeyboardTiming"] : ["Movement", "SimpleCamera", "PlayerInput", "SimplePhysics"],
|
|
3682
3832
|
data: ["Light", "Basics"],
|
|
3683
3833
|
includeShared: true,
|
|
3684
|
-
scenes:
|
|
3685
|
-
screens:
|
|
3834
|
+
scenes: fs4.existsSync(path4.join(srcMode, "Scenes")) ? fs4.readdirSync(path4.join(srcMode, "Scenes")).filter((f) => f.endsWith(".ts")) : [],
|
|
3835
|
+
screens: fs4.existsSync(path4.join(srcMode, "Screens")) ? fs4.readdirSync(path4.join(srcMode, "Screens")).filter((f) => f.endsWith(".ts")) : []
|
|
3686
3836
|
};
|
|
3687
|
-
|
|
3688
|
-
|
|
3837
|
+
fs4.writeFileSync(
|
|
3838
|
+
path4.join(targetMode, "gamemode.json"),
|
|
3689
3839
|
JSON.stringify(schema, null, 2)
|
|
3690
3840
|
);
|
|
3691
3841
|
files.push(`GameModes/${mode}/gamemode.json`);
|
|
@@ -3835,12 +3985,12 @@ async function syncLibrary(onProgress) {
|
|
|
3835
3985
|
componentSuccess = false;
|
|
3836
3986
|
continue;
|
|
3837
3987
|
}
|
|
3838
|
-
const fullPath =
|
|
3839
|
-
const dir =
|
|
3840
|
-
if (!
|
|
3841
|
-
|
|
3988
|
+
const fullPath = path4.join(libraryPath, filePath);
|
|
3989
|
+
const dir = path4.dirname(fullPath);
|
|
3990
|
+
if (!fs4.existsSync(dir)) {
|
|
3991
|
+
fs4.mkdirSync(dir, { recursive: true });
|
|
3842
3992
|
}
|
|
3843
|
-
|
|
3993
|
+
fs4.writeFileSync(fullPath, result.content);
|
|
3844
3994
|
}
|
|
3845
3995
|
if (componentSuccess) {
|
|
3846
3996
|
auth.updateLibraryFile(component.path, component.version);
|
|
@@ -3864,8 +4014,8 @@ async function syncLibrary(onProgress) {
|
|
|
3864
4014
|
}
|
|
3865
4015
|
|
|
3866
4016
|
// src/commands/bbs.ts
|
|
3867
|
-
import
|
|
3868
|
-
import
|
|
4017
|
+
import open3 from "open";
|
|
4018
|
+
import fetch6 from "node-fetch";
|
|
3869
4019
|
|
|
3870
4020
|
// src/commands/bbs/state.ts
|
|
3871
4021
|
var THEMES = [
|
|
@@ -5105,7 +5255,7 @@ function fatalError(error, context) {
|
|
|
5105
5255
|
}
|
|
5106
5256
|
process2.exit(1);
|
|
5107
5257
|
}
|
|
5108
|
-
var bbsCommand = new
|
|
5258
|
+
var bbsCommand = new Command5("bbs").description("BabylonJS Market BBS - Browse courses and assets in retro style").option("-t, --theme <theme>", "Color theme (classic, desert, matrix, commando, sandiego, ed209)", "classic").option("--no-animations", "Disable animations").option("--no-mouse", "Disable mouse support").option("--no-browser", "Don't open browser automatically during authentication").option("--saveTo <path>", "Directory to save downloaded files (default: current directory)").action(async (options) => {
|
|
5109
5259
|
process2.on("uncaughtException", (error) => {
|
|
5110
5260
|
fatalError(error, "Uncaught Exception");
|
|
5111
5261
|
});
|
|
@@ -5113,7 +5263,7 @@ var bbsCommand = new Command4("bbs").description("BabylonJS Market BBS - Browse
|
|
|
5113
5263
|
fatalError(reason instanceof Error ? reason : new Error(String(reason)), "Unhandled Promise Rejection");
|
|
5114
5264
|
});
|
|
5115
5265
|
const authManager = new AuthManager();
|
|
5116
|
-
const downloadDirectory = options.saveTo ?
|
|
5266
|
+
const downloadDirectory = options.saveTo ? path5.resolve(options.saveTo) : process2.cwd();
|
|
5117
5267
|
const savedPrefs = authManager.getPreferences();
|
|
5118
5268
|
if (savedPrefs && savedPrefs.theme && THEMES.includes(savedPrefs.theme)) {
|
|
5119
5269
|
options.theme = savedPrefs.theme;
|
|
@@ -5162,7 +5312,7 @@ var bbsCommand = new Command4("bbs").description("BabylonJS Market BBS - Browse
|
|
|
5162
5312
|
bbs.showPollingStatus("checking", "Requesting authentication code...");
|
|
5163
5313
|
backBuffer.draw({ dst: screenBuffer });
|
|
5164
5314
|
screenBuffer.draw({ delta: true });
|
|
5165
|
-
const deviceCodeResponse = await
|
|
5315
|
+
const deviceCodeResponse = await fetch6(AUTH_DEVICE_CODE_URL, {
|
|
5166
5316
|
method: "POST",
|
|
5167
5317
|
headers: { "Content-Type": "application/json" },
|
|
5168
5318
|
body: JSON.stringify({ client_id: CLIENT_ID })
|
|
@@ -5179,7 +5329,7 @@ var bbsCommand = new Command4("bbs").description("BabylonJS Market BBS - Browse
|
|
|
5179
5329
|
screenBuffer.draw({ delta: true });
|
|
5180
5330
|
if (options.browser !== false) {
|
|
5181
5331
|
const urlToOpen = deviceData.verification_uri_complete || deviceData.verification_uri;
|
|
5182
|
-
await
|
|
5332
|
+
await open3(urlToOpen);
|
|
5183
5333
|
}
|
|
5184
5334
|
const startTime = Date.now();
|
|
5185
5335
|
const pollInterval = (deviceData.interval || 5) * 1e3;
|
|
@@ -5189,7 +5339,7 @@ var bbsCommand = new Command4("bbs").description("BabylonJS Market BBS - Browse
|
|
|
5189
5339
|
bbs.showPollingStatus("checking", "Checking authentication status...");
|
|
5190
5340
|
backBuffer.draw({ dst: screenBuffer });
|
|
5191
5341
|
screenBuffer.draw({ delta: true });
|
|
5192
|
-
const tokenResponse = await
|
|
5342
|
+
const tokenResponse = await fetch6(AUTH_DEVICE_TOKEN_URL, {
|
|
5193
5343
|
method: "POST",
|
|
5194
5344
|
headers: { "Content-Type": "application/json" },
|
|
5195
5345
|
body: JSON.stringify({
|
|
@@ -5260,7 +5410,7 @@ var bbsCommand = new Command4("bbs").description("BabylonJS Market BBS - Browse
|
|
|
5260
5410
|
}
|
|
5261
5411
|
const user = authManager.getUser();
|
|
5262
5412
|
try {
|
|
5263
|
-
|
|
5413
|
+
fs5.appendFileSync("/tmp/bbs-debug.log", `${(/* @__PURE__ */ new Date()).toISOString()} BBS starting - animations: ${options.animations}
|
|
5264
5414
|
`);
|
|
5265
5415
|
if (options.animations) {
|
|
5266
5416
|
await bbs.showLoadingAnimation("Dialing BabylonJS Market BBS...", 1500);
|
|
@@ -5271,12 +5421,12 @@ var bbsCommand = new Command4("bbs").description("BabylonJS Market BBS - Browse
|
|
|
5271
5421
|
backBuffer.draw({ dst: screenBuffer });
|
|
5272
5422
|
screenBuffer.draw({ delta: true });
|
|
5273
5423
|
}
|
|
5274
|
-
|
|
5424
|
+
fs5.appendFileSync("/tmp/bbs-debug.log", `${(/* @__PURE__ */ new Date()).toISOString()} Fetching courses from ${API_URL}
|
|
5275
5425
|
`);
|
|
5276
5426
|
let allCoursesResponse;
|
|
5277
5427
|
try {
|
|
5278
5428
|
allCoursesResponse = await authManager.makeAuthenticatedRequest(`${API_URL}/api/auth/courses/all`);
|
|
5279
|
-
|
|
5429
|
+
fs5.appendFileSync("/tmp/bbs-debug.log", `${(/* @__PURE__ */ new Date()).toISOString()} Courses fetched OK
|
|
5280
5430
|
`);
|
|
5281
5431
|
} catch (fetchError) {
|
|
5282
5432
|
throw new Error(`Network error: ${fetchError.message}`);
|
|
@@ -5299,7 +5449,7 @@ var bbsCommand = new Command4("bbs").description("BabylonJS Market BBS - Browse
|
|
|
5299
5449
|
}
|
|
5300
5450
|
let scannedProjects = [];
|
|
5301
5451
|
const configuredProjectsDir = authManager.getProjectsDirectory();
|
|
5302
|
-
if (configuredProjectsDir &&
|
|
5452
|
+
if (configuredProjectsDir && fs5.existsSync(configuredProjectsDir)) {
|
|
5303
5453
|
try {
|
|
5304
5454
|
const scanPromise = scanForProjects(configuredProjectsDir, 2);
|
|
5305
5455
|
const timeoutPromise = new Promise(
|
|
@@ -5341,7 +5491,7 @@ var bbsCommand = new Command4("bbs").description("BabylonJS Market BBS - Browse
|
|
|
5341
5491
|
term[color](msg);
|
|
5342
5492
|
};
|
|
5343
5493
|
const debugLog = (msg) => {
|
|
5344
|
-
|
|
5494
|
+
fs5.appendFileSync("/tmp/bbs-debug.log", `${(/* @__PURE__ */ new Date()).toISOString()} ${msg}
|
|
5345
5495
|
`);
|
|
5346
5496
|
};
|
|
5347
5497
|
const buildRenderContext = () => {
|
|
@@ -5470,10 +5620,10 @@ var bbsCommand = new Command4("bbs").description("BabylonJS Market BBS - Browse
|
|
|
5470
5620
|
assetKey = toy.assetKey || toy.name.toLowerCase().replace(/\s+/g, "-");
|
|
5471
5621
|
fileName = assetKey + ".glb";
|
|
5472
5622
|
}
|
|
5473
|
-
const outputPath =
|
|
5623
|
+
const outputPath = path5.join(downloadDirectory, fileName);
|
|
5474
5624
|
try {
|
|
5475
|
-
if (!
|
|
5476
|
-
|
|
5625
|
+
if (!fs5.existsSync(downloadDirectory)) {
|
|
5626
|
+
fs5.mkdirSync(downloadDirectory, { recursive: true });
|
|
5477
5627
|
}
|
|
5478
5628
|
showStatus(`Downloading ${name}...`, "yellow");
|
|
5479
5629
|
const success = await assetDownloader.downloadAsset(
|
|
@@ -5501,19 +5651,19 @@ var bbsCommand = new Command4("bbs").description("BabylonJS Market BBS - Browse
|
|
|
5501
5651
|
if (!input || input.trim() === "") {
|
|
5502
5652
|
return homedir2() + "/";
|
|
5503
5653
|
}
|
|
5504
|
-
const dir =
|
|
5505
|
-
const base =
|
|
5506
|
-
if (dir &&
|
|
5507
|
-
const entries =
|
|
5654
|
+
const dir = path5.dirname(input);
|
|
5655
|
+
const base = path5.basename(input);
|
|
5656
|
+
if (dir && fs5.existsSync(dir)) {
|
|
5657
|
+
const entries = fs5.readdirSync(dir);
|
|
5508
5658
|
const matches = entries.filter((e) => e.toLowerCase().startsWith(base.toLowerCase())).filter((e) => {
|
|
5509
5659
|
try {
|
|
5510
|
-
return
|
|
5660
|
+
return fs5.statSync(path5.join(dir, e)).isDirectory();
|
|
5511
5661
|
} catch {
|
|
5512
5662
|
return false;
|
|
5513
5663
|
}
|
|
5514
5664
|
});
|
|
5515
5665
|
if (matches.length === 1) {
|
|
5516
|
-
return
|
|
5666
|
+
return path5.join(dir, matches[0]) + "/";
|
|
5517
5667
|
} else if (matches.length > 1) {
|
|
5518
5668
|
const commonPrefix = matches.reduce((prefix, match) => {
|
|
5519
5669
|
let i = 0;
|
|
@@ -5523,7 +5673,7 @@ var bbsCommand = new Command4("bbs").description("BabylonJS Market BBS - Browse
|
|
|
5523
5673
|
return match.slice(0, i);
|
|
5524
5674
|
});
|
|
5525
5675
|
if (commonPrefix.length > base.length) {
|
|
5526
|
-
return
|
|
5676
|
+
return path5.join(dir, commonPrefix);
|
|
5527
5677
|
}
|
|
5528
5678
|
}
|
|
5529
5679
|
} else if (input.startsWith("~")) {
|
|
@@ -5537,8 +5687,8 @@ var bbsCommand = new Command4("bbs").description("BabylonJS Market BBS - Browse
|
|
|
5537
5687
|
switch (effect.type) {
|
|
5538
5688
|
case "CommitProjectsDir": {
|
|
5539
5689
|
if (state.projectsDirInput.trim()) {
|
|
5540
|
-
const resolvedPath =
|
|
5541
|
-
if (
|
|
5690
|
+
const resolvedPath = path5.resolve(state.projectsDirInput.trim());
|
|
5691
|
+
if (fs5.existsSync(resolvedPath)) {
|
|
5542
5692
|
authManager.setProjectsDirectory(resolvedPath);
|
|
5543
5693
|
dispatch({ type: "SetProjectsDirResult", success: "\u2713 Saved! Scanning..." });
|
|
5544
5694
|
await render();
|
|
@@ -5565,9 +5715,9 @@ var bbsCommand = new Command4("bbs").description("BabylonJS Market BBS - Browse
|
|
|
5565
5715
|
break;
|
|
5566
5716
|
case "CommitLibraryPath": {
|
|
5567
5717
|
if (state.libraryPathInput.trim()) {
|
|
5568
|
-
const resolvedPath =
|
|
5718
|
+
const resolvedPath = path5.resolve(state.libraryPathInput.trim());
|
|
5569
5719
|
authManager.setLibraryPath(resolvedPath);
|
|
5570
|
-
if (!
|
|
5720
|
+
if (!fs5.existsSync(path5.join(resolvedPath, "Components"))) {
|
|
5571
5721
|
const result = await initializeLibrary(resolvedPath);
|
|
5572
5722
|
state = { ...state, libraryPathSuccess: result.success ? "\u2713 Library initialized!" : result.message };
|
|
5573
5723
|
} else {
|
|
@@ -5801,7 +5951,7 @@ var bbsCommand = new Command4("bbs").description("BabylonJS Market BBS - Browse
|
|
|
5801
5951
|
} else {
|
|
5802
5952
|
showStatus(`Opening browser to purchase: ${course.title}...`, "yellow");
|
|
5803
5953
|
const category = course.category || "foundations";
|
|
5804
|
-
await
|
|
5954
|
+
await open3(`https://dev.babylonjsmarket.com/products/${category}/${course.slug}/`);
|
|
5805
5955
|
showStatus(`Opened browser for course purchase`, "green");
|
|
5806
5956
|
setTimeout(() => {
|
|
5807
5957
|
term.moveTo(1, statusY);
|
|
@@ -5834,7 +5984,7 @@ var bbsCommand = new Command4("bbs").description("BabylonJS Market BBS - Browse
|
|
|
5834
5984
|
const project = state.projects[state.projectsSelectedIndex];
|
|
5835
5985
|
if (project) {
|
|
5836
5986
|
const editor = process2.env.EDITOR || "code";
|
|
5837
|
-
const editorName =
|
|
5987
|
+
const editorName = path5.basename(editor);
|
|
5838
5988
|
showStatus(`Opening ${project.name} in ${editorName}...`, "yellow");
|
|
5839
5989
|
const { spawn } = await import("child_process");
|
|
5840
5990
|
const editorProcess = spawn(editor, [project.path], { detached: true, stdio: "ignore" });
|
|
@@ -6069,7 +6219,7 @@ var bbsCommand = new Command4("bbs").description("BabylonJS Market BBS - Browse
|
|
|
6069
6219
|
});
|
|
6070
6220
|
|
|
6071
6221
|
// src/commands/inject.ts
|
|
6072
|
-
import { Command as
|
|
6222
|
+
import { Command as Command6 } from "commander";
|
|
6073
6223
|
import { mkdtempSync, existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
|
|
6074
6224
|
import { join as join4 } from "path";
|
|
6075
6225
|
import { tmpdir } from "os";
|
|
@@ -6090,8 +6240,8 @@ function getVersion() {
|
|
|
6090
6240
|
}
|
|
6091
6241
|
|
|
6092
6242
|
// src/lib/inject/engine.ts
|
|
6093
|
-
import
|
|
6094
|
-
import
|
|
6243
|
+
import fs7 from "fs";
|
|
6244
|
+
import path7 from "path";
|
|
6095
6245
|
import mri from "mri";
|
|
6096
6246
|
import colors2 from "picocolors";
|
|
6097
6247
|
|
|
@@ -6105,15 +6255,15 @@ BabylonJS Market for curator review (reverse of ${cyan("arcade eject")}).
|
|
|
6105
6255
|
|
|
6106
6256
|
With no ${bold("--target")}, the tool auto-detects per seed:
|
|
6107
6257
|
* any file extending ${cyan("PanelDebuggerSystem")} / ${cyan("StateStepperSystem")} or
|
|
6108
|
-
importing from ${cyan("@babylonjsmarket/viz
|
|
6109
|
-
* otherwise \u2192 ${cyan("arcade
|
|
6258
|
+
importing from ${cyan("@babylonjsmarket/viz")} \u2192 ${cyan("viz")},
|
|
6259
|
+
* otherwise \u2192 ${cyan("arcade")}.
|
|
6110
6260
|
|
|
6111
6261
|
Multi-seed inputs must all detect to the same target.
|
|
6112
6262
|
|
|
6113
6263
|
Options:
|
|
6114
|
-
--target <arcade
|
|
6264
|
+
--target <arcade|viz> skip auto-detection (legacy: arcade-pro, viz-pro)
|
|
6115
6265
|
--source <path> override <cwd>/src/components/<Name>/
|
|
6116
|
-
--layer <core|solid|ecs> viz
|
|
6266
|
+
--layer <core|solid|ecs> viz only; skip per-file layer detection
|
|
6117
6267
|
--force allow overwriting an existing target
|
|
6118
6268
|
--dry-run print the plan, write nothing, do not submit
|
|
6119
6269
|
-h, --help print this help message
|
|
@@ -6121,17 +6271,17 @@ Options:
|
|
|
6121
6271
|
Examples:
|
|
6122
6272
|
bjs inject Foo # auto-detect target
|
|
6123
6273
|
bjs inject Foo Bar --dry-run # multi-name, preview
|
|
6124
|
-
bjs inject MyPanelDebugger --target viz
|
|
6274
|
+
bjs inject MyPanelDebugger --target viz
|
|
6125
6275
|
bjs inject Foo --source ./packages/demo/src/components/Foo
|
|
6126
6276
|
`;
|
|
6127
6277
|
|
|
6128
6278
|
// src/lib/inject/detect-target.ts
|
|
6129
6279
|
function detectTarget(seedFiles) {
|
|
6130
6280
|
for (const { source } of seedFiles) {
|
|
6131
|
-
if (/from\s+['"]@babylonjsmarket\/viz
|
|
6132
|
-
if (/extends\s+(PanelDebuggerSystem|StateStepperSystem)\b/.test(source)) return "viz
|
|
6281
|
+
if (/from\s+['"]@babylonjsmarket\/viz(?:-pro)?['"]/.test(source)) return "viz";
|
|
6282
|
+
if (/extends\s+(PanelDebuggerSystem|StateStepperSystem)\b/.test(source)) return "viz";
|
|
6133
6283
|
}
|
|
6134
|
-
return "arcade
|
|
6284
|
+
return "arcade";
|
|
6135
6285
|
}
|
|
6136
6286
|
function detectLayer(filePath, source, subjectLayer) {
|
|
6137
6287
|
const base = filePath.split(/[\\/]/).pop() ?? filePath;
|
|
@@ -6148,28 +6298,28 @@ function detectLayer(filePath, source, subjectLayer) {
|
|
|
6148
6298
|
}
|
|
6149
6299
|
|
|
6150
6300
|
// src/lib/inject/monorepo-root.ts
|
|
6151
|
-
import
|
|
6152
|
-
import
|
|
6301
|
+
import fs6 from "fs";
|
|
6302
|
+
import path6 from "path";
|
|
6153
6303
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
6154
6304
|
function findMonorepoRoot() {
|
|
6155
|
-
const here =
|
|
6305
|
+
const here = path6.dirname(fileURLToPath2(import.meta.url));
|
|
6156
6306
|
let dir = here;
|
|
6157
6307
|
while (true) {
|
|
6158
|
-
const pkgPath =
|
|
6159
|
-
if (
|
|
6308
|
+
const pkgPath = path6.join(dir, "package.json");
|
|
6309
|
+
if (fs6.existsSync(pkgPath)) {
|
|
6160
6310
|
try {
|
|
6161
|
-
const pkg = JSON.parse(
|
|
6311
|
+
const pkg = JSON.parse(fs6.readFileSync(pkgPath, "utf8"));
|
|
6162
6312
|
if (pkg.name === "babylonjs-market-monorepo") {
|
|
6163
6313
|
return {
|
|
6164
6314
|
root: dir,
|
|
6165
|
-
arcadeProRoot:
|
|
6166
|
-
vizProRoot:
|
|
6315
|
+
arcadeProRoot: path6.join(dir, "packages", "arcade-pro"),
|
|
6316
|
+
vizProRoot: path6.join(dir, "packages", "viz-pro")
|
|
6167
6317
|
};
|
|
6168
6318
|
}
|
|
6169
6319
|
} catch {
|
|
6170
6320
|
}
|
|
6171
6321
|
}
|
|
6172
|
-
const parent =
|
|
6322
|
+
const parent = path6.dirname(dir);
|
|
6173
6323
|
if (parent === dir) {
|
|
6174
6324
|
throw new Error(
|
|
6175
6325
|
`Could not locate umbrella repo (no ancestor package.json with name "babylonjs-market-monorepo" above ${here}).`
|
|
@@ -6184,46 +6334,46 @@ var { cyan: cyan2, green, yellow, dim, bold: bold2 } = colors2;
|
|
|
6184
6334
|
function componentFiles(dir) {
|
|
6185
6335
|
const out = [];
|
|
6186
6336
|
const walk = (d) => {
|
|
6187
|
-
for (const e of
|
|
6188
|
-
const p =
|
|
6337
|
+
for (const e of fs7.readdirSync(d, { withFileTypes: true })) {
|
|
6338
|
+
const p = path7.join(d, e.name);
|
|
6189
6339
|
if (e.isDirectory()) walk(p);
|
|
6190
6340
|
else if (/\.(ts|tsx)$/.test(e.name)) out.push(p);
|
|
6191
6341
|
}
|
|
6192
6342
|
};
|
|
6193
|
-
if (
|
|
6343
|
+
if (fs7.existsSync(dir)) walk(dir);
|
|
6194
6344
|
return out;
|
|
6195
6345
|
}
|
|
6196
6346
|
function allComponentFiles(dir) {
|
|
6197
6347
|
const out = [];
|
|
6198
6348
|
const walk = (d) => {
|
|
6199
|
-
for (const e of
|
|
6200
|
-
const p =
|
|
6349
|
+
for (const e of fs7.readdirSync(d, { withFileTypes: true })) {
|
|
6350
|
+
const p = path7.join(d, e.name);
|
|
6201
6351
|
if (e.isDirectory()) walk(p);
|
|
6202
6352
|
else out.push(p);
|
|
6203
6353
|
}
|
|
6204
6354
|
};
|
|
6205
|
-
if (
|
|
6355
|
+
if (fs7.existsSync(dir)) walk(dir);
|
|
6206
6356
|
return out;
|
|
6207
6357
|
}
|
|
6208
6358
|
function projectComponentNames(projectDir) {
|
|
6209
|
-
const dir =
|
|
6210
|
-
if (!
|
|
6211
|
-
return
|
|
6359
|
+
const dir = path7.join(projectDir, "src", "components");
|
|
6360
|
+
if (!fs7.existsSync(dir)) return [];
|
|
6361
|
+
return fs7.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isDirectory() && e.name !== "_shared").map((e) => e.name);
|
|
6212
6362
|
}
|
|
6213
6363
|
function directDeps(name, componentsDir, allNames) {
|
|
6214
6364
|
const deps = /* @__PURE__ */ new Set();
|
|
6215
|
-
const metaPath =
|
|
6216
|
-
if (
|
|
6365
|
+
const metaPath = path7.join(componentsDir, name, "meta.json");
|
|
6366
|
+
if (fs7.existsSync(metaPath)) {
|
|
6217
6367
|
try {
|
|
6218
|
-
const meta = JSON.parse(
|
|
6368
|
+
const meta = JSON.parse(fs7.readFileSync(metaPath, "utf8"));
|
|
6219
6369
|
for (const d of meta.dependencies ?? []) if (allNames.has(d)) deps.add(d);
|
|
6220
6370
|
} catch {
|
|
6221
6371
|
}
|
|
6222
6372
|
}
|
|
6223
6373
|
const relRe = /['"]\.\.\/([A-Z][A-Za-z0-9_]*)\//g;
|
|
6224
6374
|
const aliasRe = /['"]~\/components\/([A-Z][A-Za-z0-9_]*)\//g;
|
|
6225
|
-
for (const file of componentFiles(
|
|
6226
|
-
const src =
|
|
6375
|
+
for (const file of componentFiles(path7.join(componentsDir, name))) {
|
|
6376
|
+
const src = fs7.readFileSync(file, "utf8");
|
|
6227
6377
|
let m;
|
|
6228
6378
|
while (m = relRe.exec(src)) if (allNames.has(m[1])) deps.add(m[1]);
|
|
6229
6379
|
while (m = aliasRe.exec(src)) if (allNames.has(m[1])) deps.add(m[1]);
|
|
@@ -6258,7 +6408,7 @@ function rewriteArcadeImports(src, injected) {
|
|
|
6258
6408
|
}
|
|
6259
6409
|
function rewriteVizImports(src, injected, layerOf, fromLayer) {
|
|
6260
6410
|
return src.replace(
|
|
6261
|
-
/(['"])@babylonjsmarket\/(?:viz-pro|arcade|arcade-pro)\/([A-Z][A-Za-z0-9_]*)\1/g,
|
|
6411
|
+
/(['"])@babylonjsmarket\/(?:viz-pro|viz|arcade|arcade-pro)\/([A-Z][A-Za-z0-9_]*)\1/g,
|
|
6262
6412
|
(whole, quote, sibling) => {
|
|
6263
6413
|
if (!injected.has(sibling)) return whole;
|
|
6264
6414
|
const dest = layerOf(sibling);
|
|
@@ -6272,7 +6422,7 @@ function planArcadeProRegistry(existingRegistry, names, registryRelPath = "src/r
|
|
|
6272
6422
|
const warnings = [];
|
|
6273
6423
|
if (existingRegistry === void 0) {
|
|
6274
6424
|
warnings.push(
|
|
6275
|
-
`! packages/arcade
|
|
6425
|
+
`! packages/arcade/${registryRelPath} not found \u2014 add resolvers manually for: ${names.join(", ")}`
|
|
6276
6426
|
);
|
|
6277
6427
|
return { lines: [], added: [], warnings, markerFound: false };
|
|
6278
6428
|
}
|
|
@@ -6293,15 +6443,15 @@ function planArcadeProRegistry(existingRegistry, names, registryRelPath = "src/r
|
|
|
6293
6443
|
return { lines, added, warnings, markerFound: true };
|
|
6294
6444
|
}
|
|
6295
6445
|
function patchArcadeProRegistry(arcadeProRoot, names, dryRun) {
|
|
6296
|
-
const registryPath =
|
|
6297
|
-
const existing =
|
|
6446
|
+
const registryPath = path7.join(arcadeProRoot, "src", "registry.ts");
|
|
6447
|
+
const existing = fs7.existsSync(registryPath) ? fs7.readFileSync(registryPath, "utf8") : void 0;
|
|
6298
6448
|
const plan = planArcadeProRegistry(existing, names);
|
|
6299
6449
|
if (plan.warnings.length) return plan.warnings;
|
|
6300
6450
|
if (plan.added.length && !dryRun) {
|
|
6301
6451
|
const marker = /ARCADE_PRO_COMPONENT_REGISTRY:\s*Record<string,\s*LazyComponentResolver>\s*=\s*\{/;
|
|
6302
6452
|
const next = existing.replace(marker, (m) => `${m}
|
|
6303
6453
|
${plan.lines.join("\n")}`);
|
|
6304
|
-
|
|
6454
|
+
fs7.writeFileSync(registryPath, next);
|
|
6305
6455
|
}
|
|
6306
6456
|
return plan.added.map((n) => ` patched registry: ${n}`);
|
|
6307
6457
|
}
|
|
@@ -6319,21 +6469,21 @@ function planVizProBarrel(existingBarrel, layer, fileName) {
|
|
|
6319
6469
|
return { line: `export * from './${fileName}';`, warnings: [] };
|
|
6320
6470
|
}
|
|
6321
6471
|
function patchVizProBarrel(vizProRoot, layer, fileName, dryRun) {
|
|
6322
|
-
const barrelPath =
|
|
6323
|
-
const existing =
|
|
6472
|
+
const barrelPath = path7.join(vizProRoot, "src", layer, "index.ts");
|
|
6473
|
+
const existing = fs7.existsSync(barrelPath) ? fs7.readFileSync(barrelPath, "utf8") : void 0;
|
|
6324
6474
|
const plan = planVizProBarrel(existing, layer, fileName);
|
|
6325
6475
|
if (plan.warnings.length) return plan.warnings;
|
|
6326
6476
|
if (plan.line === null) return [];
|
|
6327
6477
|
if (!dryRun) {
|
|
6328
6478
|
const next = existing.endsWith("\n") ? existing + plan.line + "\n" : existing + "\n" + plan.line + "\n";
|
|
6329
|
-
|
|
6479
|
+
fs7.writeFileSync(barrelPath, next);
|
|
6330
6480
|
}
|
|
6331
6481
|
return [` patched ${layer}/index.ts: ${fileName}`];
|
|
6332
6482
|
}
|
|
6333
6483
|
function stripProjectRegistry(projectDir, names, dryRun) {
|
|
6334
|
-
const registryPath =
|
|
6335
|
-
if (!
|
|
6336
|
-
let text =
|
|
6484
|
+
const registryPath = path7.join(projectDir, "src", "registry.ts");
|
|
6485
|
+
if (!fs7.existsSync(registryPath)) return [];
|
|
6486
|
+
let text = fs7.readFileSync(registryPath, "utf8");
|
|
6337
6487
|
const removed = [];
|
|
6338
6488
|
for (const name of names) {
|
|
6339
6489
|
const re = new RegExp(
|
|
@@ -6345,7 +6495,7 @@ function stripProjectRegistry(projectDir, names, dryRun) {
|
|
|
6345
6495
|
removed.push(name);
|
|
6346
6496
|
}
|
|
6347
6497
|
}
|
|
6348
|
-
if (removed.length && !dryRun)
|
|
6498
|
+
if (removed.length && !dryRun) fs7.writeFileSync(registryPath, text);
|
|
6349
6499
|
return removed;
|
|
6350
6500
|
}
|
|
6351
6501
|
async function inject(args, opts = {}) {
|
|
@@ -6362,7 +6512,8 @@ async function inject(args, opts = {}) {
|
|
|
6362
6512
|
const move = Boolean(argv.move);
|
|
6363
6513
|
const confirm2 = Boolean(argv.confirm);
|
|
6364
6514
|
const force = Boolean(argv.force);
|
|
6365
|
-
const
|
|
6515
|
+
const rawTarget = argv.target;
|
|
6516
|
+
const explicitTarget = rawTarget === "arcade-pro" ? "arcade" : rawTarget === "viz-pro" ? "viz" : rawTarget;
|
|
6366
6517
|
const sourceOverride = argv.source;
|
|
6367
6518
|
const layerOverride = argv.layer;
|
|
6368
6519
|
const names = argv._.map(String);
|
|
@@ -6388,8 +6539,8 @@ async function inject(args, opts = {}) {
|
|
|
6388
6539
|
process.exit(1);
|
|
6389
6540
|
return;
|
|
6390
6541
|
}
|
|
6391
|
-
if (explicitTarget && explicitTarget !== "arcade
|
|
6392
|
-
console.error(yellow(`Unknown --target ${
|
|
6542
|
+
if (explicitTarget && explicitTarget !== "arcade" && explicitTarget !== "viz") {
|
|
6543
|
+
console.error(yellow(`Unknown --target ${rawTarget}. Use arcade or viz.`));
|
|
6393
6544
|
process.exit(1);
|
|
6394
6545
|
return;
|
|
6395
6546
|
}
|
|
@@ -6416,12 +6567,12 @@ async function inject(args, opts = {}) {
|
|
|
6416
6567
|
return;
|
|
6417
6568
|
}
|
|
6418
6569
|
}
|
|
6419
|
-
const componentsDir =
|
|
6570
|
+
const componentsDir = path7.join(projectDir, "src", "components");
|
|
6420
6571
|
const allProjectNames = projectComponentNames(projectDir);
|
|
6421
6572
|
const seeds = [];
|
|
6422
6573
|
for (const name of names) {
|
|
6423
|
-
const sourceDir = sourceOverride ?
|
|
6424
|
-
if (!
|
|
6574
|
+
const sourceDir = sourceOverride ? path7.resolve(cwd, sourceOverride) : path7.join(componentsDir, name);
|
|
6575
|
+
if (!fs7.existsSync(sourceDir)) {
|
|
6425
6576
|
console.error(
|
|
6426
6577
|
yellow(
|
|
6427
6578
|
`Could not find source for "${name}". Looked at ${sourceDir}. Use --source <path> to point at the seed explicitly.`
|
|
@@ -6436,9 +6587,9 @@ async function inject(args, opts = {}) {
|
|
|
6436
6587
|
const closure = sourceOverride ? seedNames : resolveClosure(seedNames, componentsDir, allProjectNames);
|
|
6437
6588
|
const closureFiles = [];
|
|
6438
6589
|
for (const name of closure) {
|
|
6439
|
-
const dir = sourceOverride && seedNames.has(name) ? seeds.find((s) => s.name === name).sourceDir :
|
|
6590
|
+
const dir = sourceOverride && seedNames.has(name) ? seeds.find((s) => s.name === name).sourceDir : path7.join(componentsDir, name);
|
|
6440
6591
|
for (const f of componentFiles(dir)) {
|
|
6441
|
-
closureFiles.push({ path: f, source:
|
|
6592
|
+
closureFiles.push({ path: f, source: fs7.readFileSync(f, "utf8") });
|
|
6442
6593
|
}
|
|
6443
6594
|
}
|
|
6444
6595
|
const target = explicitTarget ?? detectTarget(closureFiles);
|
|
@@ -6447,7 +6598,7 @@ async function inject(args, opts = {}) {
|
|
|
6447
6598
|
const dir = seed.sourceDir;
|
|
6448
6599
|
const files = componentFiles(dir).map((f) => ({
|
|
6449
6600
|
path: f,
|
|
6450
|
-
source:
|
|
6601
|
+
source: fs7.readFileSync(f, "utf8")
|
|
6451
6602
|
}));
|
|
6452
6603
|
const perSeed = detectTarget(files);
|
|
6453
6604
|
if (perSeed !== target) {
|
|
@@ -6464,15 +6615,15 @@ async function inject(args, opts = {}) {
|
|
|
6464
6615
|
let chosenRoot;
|
|
6465
6616
|
if (mode === "apply") {
|
|
6466
6617
|
try {
|
|
6467
|
-
if (target === "arcade
|
|
6468
|
-
if (!
|
|
6618
|
+
if (target === "arcade") {
|
|
6619
|
+
if (!fs7.existsSync(packageRoot)) {
|
|
6469
6620
|
throw new Error(
|
|
6470
|
-
`packages/arcade
|
|
6621
|
+
`packages/arcade is not checked out at ${packageRoot}. Run \`git submodule update --init packages/arcade\` and retry.`
|
|
6471
6622
|
);
|
|
6472
6623
|
}
|
|
6473
6624
|
chosenRoot = packageRoot;
|
|
6474
6625
|
} else {
|
|
6475
|
-
if (!
|
|
6626
|
+
if (!fs7.existsSync(vizProRoot)) {
|
|
6476
6627
|
throw new Error(
|
|
6477
6628
|
`packages/viz-pro is not checked out at ${vizProRoot}. Run \`git submodule update --init packages/viz-pro\` and retry.`
|
|
6478
6629
|
);
|
|
@@ -6491,7 +6642,7 @@ async function inject(args, opts = {}) {
|
|
|
6491
6642
|
console.log(` target: ${cyan2(target)}`);
|
|
6492
6643
|
console.log(` components: ${cyan2([...closure].sort().join(", "))}`);
|
|
6493
6644
|
if (mode === "collect") {
|
|
6494
|
-
const result = target === "arcade
|
|
6645
|
+
const result = target === "arcade" ? collectArcadePro({ seeds, closure, componentsDir, sourceOverride }) : collectVizPro({ seeds, closure, componentsDir, sourceOverride, layerOverride });
|
|
6495
6646
|
for (const f of result.files) console.log(green(` + packages/${target}/${f.path}`));
|
|
6496
6647
|
for (const w of result.warnings) console.log(yellow(w));
|
|
6497
6648
|
console.log(
|
|
@@ -6499,7 +6650,7 @@ async function inject(args, opts = {}) {
|
|
|
6499
6650
|
);
|
|
6500
6651
|
return { ...result, target };
|
|
6501
6652
|
}
|
|
6502
|
-
if (target === "arcade
|
|
6653
|
+
if (target === "arcade") {
|
|
6503
6654
|
await injectArcadePro({
|
|
6504
6655
|
seeds,
|
|
6505
6656
|
closure,
|
|
@@ -6530,9 +6681,9 @@ async function inject(args, opts = {}) {
|
|
|
6530
6681
|
);
|
|
6531
6682
|
}
|
|
6532
6683
|
for (const seed of seeds) {
|
|
6533
|
-
if (
|
|
6534
|
-
if (!dryRun)
|
|
6535
|
-
console.log(dim(` - ${
|
|
6684
|
+
if (fs7.existsSync(seed.sourceDir)) {
|
|
6685
|
+
if (!dryRun) fs7.rmSync(seed.sourceDir, { recursive: true, force: true });
|
|
6686
|
+
console.log(dim(` - ${path7.relative(projectDir, seed.sourceDir)}/ (project copy removed)`));
|
|
6536
6687
|
}
|
|
6537
6688
|
}
|
|
6538
6689
|
const removed = stripProjectRegistry(
|
|
@@ -6552,31 +6703,31 @@ Done. Components landed in packages/${target}/.
|
|
|
6552
6703
|
}
|
|
6553
6704
|
async function injectArcadePro(args) {
|
|
6554
6705
|
const { seeds, closure, componentsDir, sourceOverride, arcadeProRoot, dryRun, force } = args;
|
|
6555
|
-
const destComponents =
|
|
6556
|
-
if (!dryRun)
|
|
6706
|
+
const destComponents = path7.join(arcadeProRoot, "src", "Components");
|
|
6707
|
+
if (!dryRun) fs7.mkdirSync(destComponents, { recursive: true });
|
|
6557
6708
|
const sourceOf = (name) => {
|
|
6558
6709
|
const seed = seeds.find((s) => s.name === name);
|
|
6559
|
-
return seed && sourceOverride ? seed.sourceDir :
|
|
6710
|
+
return seed && sourceOverride ? seed.sourceDir : path7.join(componentsDir, name);
|
|
6560
6711
|
};
|
|
6561
6712
|
for (const name of [...closure].sort()) {
|
|
6562
6713
|
const src = sourceOf(name);
|
|
6563
|
-
const dest =
|
|
6564
|
-
if (
|
|
6714
|
+
const dest = path7.join(destComponents, name);
|
|
6715
|
+
if (fs7.existsSync(dest) && !force) {
|
|
6565
6716
|
console.log(
|
|
6566
|
-
yellow(` ! packages/arcade
|
|
6717
|
+
yellow(` ! packages/arcade/src/Components/${name}/ already exists \u2014 pass --force to overwrite.`)
|
|
6567
6718
|
);
|
|
6568
6719
|
continue;
|
|
6569
6720
|
}
|
|
6570
6721
|
if (!dryRun) {
|
|
6571
|
-
if (
|
|
6572
|
-
|
|
6722
|
+
if (fs7.existsSync(dest)) fs7.rmSync(dest, { recursive: true, force: true });
|
|
6723
|
+
fs7.cpSync(src, dest, { recursive: true });
|
|
6573
6724
|
}
|
|
6574
|
-
console.log(green(` + packages/arcade
|
|
6725
|
+
console.log(green(` + packages/arcade/src/Components/${name}/`));
|
|
6575
6726
|
}
|
|
6576
6727
|
if (!dryRun) {
|
|
6577
6728
|
for (const name of closure) {
|
|
6578
|
-
const dest =
|
|
6579
|
-
if (!
|
|
6729
|
+
const dest = path7.join(destComponents, name);
|
|
6730
|
+
if (!fs7.existsSync(dest)) continue;
|
|
6580
6731
|
rewriteTree(dest, (text) => rewriteArcadeImports(text, closure));
|
|
6581
6732
|
}
|
|
6582
6733
|
}
|
|
@@ -6592,21 +6743,21 @@ function collectArcadePro(args) {
|
|
|
6592
6743
|
const { seeds, closure, componentsDir, sourceOverride } = args;
|
|
6593
6744
|
const sourceOf = (name) => {
|
|
6594
6745
|
const seed = seeds.find((s) => s.name === name);
|
|
6595
|
-
return seed && sourceOverride ? seed.sourceDir :
|
|
6746
|
+
return seed && sourceOverride ? seed.sourceDir : path7.join(componentsDir, name);
|
|
6596
6747
|
};
|
|
6597
6748
|
const files = [];
|
|
6598
6749
|
const warnings = [];
|
|
6599
6750
|
for (const name of [...closure].sort()) {
|
|
6600
6751
|
const src = sourceOf(name);
|
|
6601
|
-
if (!
|
|
6752
|
+
if (!fs7.existsSync(src)) {
|
|
6602
6753
|
warnings.push(` ! source for ${name} missing at ${src}`);
|
|
6603
6754
|
continue;
|
|
6604
6755
|
}
|
|
6605
6756
|
for (const abs of allComponentFiles(src)) {
|
|
6606
|
-
const rel =
|
|
6607
|
-
const baseRel =
|
|
6757
|
+
const rel = path7.relative(src, abs);
|
|
6758
|
+
const baseRel = path7.posix.join("src", "Components", name, rel.split(path7.sep).join("/"));
|
|
6608
6759
|
const isText = /\.(ts|tsx)$/i.test(abs);
|
|
6609
|
-
const raw =
|
|
6760
|
+
const raw = fs7.readFileSync(abs, "utf8");
|
|
6610
6761
|
const contents = isText ? rewriteArcadeImports(raw, closure) : raw;
|
|
6611
6762
|
files.push({ path: baseRel, contents });
|
|
6612
6763
|
}
|
|
@@ -6625,15 +6776,15 @@ function classifyVizFiles(args) {
|
|
|
6625
6776
|
const { seeds, closure, componentsDir, sourceOverride, layerOverride } = args;
|
|
6626
6777
|
const sourceOf = (name) => {
|
|
6627
6778
|
const seed = seeds.find((s) => s.name === name);
|
|
6628
|
-
return seed && sourceOverride ? seed.sourceDir :
|
|
6779
|
+
return seed && sourceOverride ? seed.sourceDir : path7.join(componentsDir, name);
|
|
6629
6780
|
};
|
|
6630
6781
|
const files = [];
|
|
6631
6782
|
for (const name of closure) {
|
|
6632
6783
|
const dir = sourceOf(name);
|
|
6633
6784
|
for (const abs of componentFiles(dir)) {
|
|
6634
|
-
const base =
|
|
6785
|
+
const base = path7.basename(abs);
|
|
6635
6786
|
if (/\.test\.tsx?$/.test(base)) continue;
|
|
6636
|
-
const source =
|
|
6787
|
+
const source = fs7.readFileSync(abs, "utf8");
|
|
6637
6788
|
const layer = layerOverride ?? detectLayer(abs, source);
|
|
6638
6789
|
files.push({ src: abs, base, owner: name, source, layer, destBase: base });
|
|
6639
6790
|
}
|
|
@@ -6641,9 +6792,9 @@ function classifyVizFiles(args) {
|
|
|
6641
6792
|
for (const name of closure) {
|
|
6642
6793
|
const dir = sourceOf(name);
|
|
6643
6794
|
for (const abs of componentFiles(dir)) {
|
|
6644
|
-
const base =
|
|
6795
|
+
const base = path7.basename(abs);
|
|
6645
6796
|
if (!/\.test\.tsx?$/.test(base)) continue;
|
|
6646
|
-
const source =
|
|
6797
|
+
const source = fs7.readFileSync(abs, "utf8");
|
|
6647
6798
|
const subjectBase = base.replace(/\.test(\.tsx?)$/, "$1");
|
|
6648
6799
|
const subjectAlt = base.replace(/\.test\.tsx?$/, ".tsx");
|
|
6649
6800
|
const subject = files.find((f) => f.owner === name && (f.base === subjectBase || f.base === subjectAlt));
|
|
@@ -6663,8 +6814,8 @@ async function injectVizPro(args) {
|
|
|
6663
6814
|
const { files, primaryLayer } = classifyVizFiles(args);
|
|
6664
6815
|
const layerOf = (name) => primaryLayer.get(name);
|
|
6665
6816
|
for (const f of files) {
|
|
6666
|
-
const dest =
|
|
6667
|
-
if (
|
|
6817
|
+
const dest = path7.join(vizProRoot, "src", f.layer, f.destBase);
|
|
6818
|
+
if (fs7.existsSync(dest) && !force) {
|
|
6668
6819
|
console.log(
|
|
6669
6820
|
yellow(
|
|
6670
6821
|
` ! packages/viz-pro/src/${f.layer}/${f.destBase} already exists \u2014 pass --force to overwrite.`
|
|
@@ -6673,13 +6824,13 @@ async function injectVizPro(args) {
|
|
|
6673
6824
|
}
|
|
6674
6825
|
}
|
|
6675
6826
|
for (const f of files) {
|
|
6676
|
-
const destDir =
|
|
6677
|
-
const dest =
|
|
6678
|
-
if (
|
|
6827
|
+
const destDir = path7.join(vizProRoot, "src", f.layer);
|
|
6828
|
+
const dest = path7.join(destDir, f.destBase);
|
|
6829
|
+
if (fs7.existsSync(dest) && !force) continue;
|
|
6679
6830
|
if (!dryRun) {
|
|
6680
|
-
|
|
6831
|
+
fs7.mkdirSync(destDir, { recursive: true });
|
|
6681
6832
|
const rewritten = rewriteVizImports(f.source, closure, layerOf, f.layer);
|
|
6682
|
-
|
|
6833
|
+
fs7.writeFileSync(dest, rewritten);
|
|
6683
6834
|
}
|
|
6684
6835
|
console.log(green(` + packages/viz-pro/src/${f.layer}/${f.destBase}`));
|
|
6685
6836
|
}
|
|
@@ -6707,7 +6858,7 @@ function collectVizPro(args) {
|
|
|
6707
6858
|
const files = [];
|
|
6708
6859
|
const warnings = [];
|
|
6709
6860
|
for (const f of classified) {
|
|
6710
|
-
const rel =
|
|
6861
|
+
const rel = path7.posix.join("src", f.layer, f.destBase);
|
|
6711
6862
|
const contents = rewriteVizImports(f.source, closure, layerOf, f.layer);
|
|
6712
6863
|
files.push({ path: rel, contents });
|
|
6713
6864
|
}
|
|
@@ -6728,19 +6879,19 @@ function collectVizPro(args) {
|
|
|
6728
6879
|
return { files, patches, warnings };
|
|
6729
6880
|
}
|
|
6730
6881
|
function rewriteTree(dir, rewrite) {
|
|
6731
|
-
for (const e of
|
|
6732
|
-
const p =
|
|
6882
|
+
for (const e of fs7.readdirSync(dir, { withFileTypes: true })) {
|
|
6883
|
+
const p = path7.join(dir, e.name);
|
|
6733
6884
|
if (e.isDirectory()) rewriteTree(p, rewrite);
|
|
6734
6885
|
else if (/\.(ts|tsx)$/.test(e.name)) {
|
|
6735
|
-
const before =
|
|
6886
|
+
const before = fs7.readFileSync(p, "utf8");
|
|
6736
6887
|
const after = rewrite(before);
|
|
6737
|
-
if (after !== before)
|
|
6888
|
+
if (after !== before) fs7.writeFileSync(p, after);
|
|
6738
6889
|
}
|
|
6739
6890
|
}
|
|
6740
6891
|
}
|
|
6741
6892
|
|
|
6742
6893
|
// src/commands/inject.ts
|
|
6743
|
-
var injectCommand = new
|
|
6894
|
+
var injectCommand = new Command6("inject").description("Submit a component or system to BabylonJS Market for curator review").argument("[names...]", "Component / system name(s) to submit").option("--target <target>", "arcade | viz (skip auto-detection; legacy arcade-pro/viz-pro accepted)").option("--source <path>", "override <cwd>/src/components/<Name>/").option("--layer <layer>", "viz only; skip per-file layer detection (core|solid|ecs)").option("--force", "allow overwriting an existing target").option("--dry-run", "print the plan, write nothing, do not submit").allowUnknownOption(false).action(async (names, options) => {
|
|
6744
6895
|
const auth = new AuthManager();
|
|
6745
6896
|
const theme = applyTheme();
|
|
6746
6897
|
if (!auth.isAuthenticated()) {
|
|
@@ -6848,10 +6999,10 @@ function readSeedMeta(projectDir, seedName) {
|
|
|
6848
6999
|
}
|
|
6849
7000
|
|
|
6850
7001
|
// src/commands/submissions.ts
|
|
6851
|
-
import { Command as
|
|
7002
|
+
import { Command as Command7 } from "commander";
|
|
6852
7003
|
import { createInterface } from "readline";
|
|
6853
|
-
async function apiCall(auth, method,
|
|
6854
|
-
return auth.makeAuthenticatedRequest(`${API_URL}${
|
|
7004
|
+
async function apiCall(auth, method, path8) {
|
|
7005
|
+
return auth.makeAuthenticatedRequest(`${API_URL}${path8}`, { method });
|
|
6855
7006
|
}
|
|
6856
7007
|
function formatDate(s) {
|
|
6857
7008
|
if (!s) return "";
|
|
@@ -7079,7 +7230,7 @@ async function withdrawSubmissionAction(idArg, opts) {
|
|
|
7079
7230
|
}
|
|
7080
7231
|
console.log(theme.success("Withdrawn."));
|
|
7081
7232
|
}
|
|
7082
|
-
var submissionsCommand = new
|
|
7233
|
+
var submissionsCommand = new Command7("submissions").description("List or inspect your marketplace submissions").action(async () => {
|
|
7083
7234
|
await listSubmissionsAction({});
|
|
7084
7235
|
});
|
|
7085
7236
|
submissionsCommand.command("list").description("List your submissions").option("--status <status>", "filter: pending|reviewing|merged|rejected|withdrawn").option("--limit <n>", "max results (default 20, capped at 100 server-side)", (v) => parseInt(v, 10)).option("--json", "machine-readable output").action(async (opts) => {
|
|
@@ -7093,8 +7244,9 @@ submissionsCommand.command("withdraw <id>").description("Withdraw a pending subm
|
|
|
7093
7244
|
});
|
|
7094
7245
|
|
|
7095
7246
|
// src/index.ts
|
|
7096
|
-
var program = new
|
|
7247
|
+
var program = new Command8();
|
|
7097
7248
|
program.name("bjs").description("BabylonJS Market CLI - BBS-style interface for courses and assets").version(getVersion());
|
|
7249
|
+
program.addCommand(loginCommand);
|
|
7098
7250
|
program.addCommand(logoutCommand);
|
|
7099
7251
|
program.addCommand(whoamiCommand);
|
|
7100
7252
|
program.addCommand(downloadCommand);
|
|
@@ -7108,7 +7260,7 @@ try {
|
|
|
7108
7260
|
if (error.code === "commander.executeSubCommandAsync") {
|
|
7109
7261
|
process.exit(error.exitCode);
|
|
7110
7262
|
}
|
|
7111
|
-
console.error(
|
|
7263
|
+
console.error(chalk6.red("Error:"), error.message);
|
|
7112
7264
|
process.exit(1);
|
|
7113
7265
|
}
|
|
7114
7266
|
//# sourceMappingURL=index.js.map
|