playcademy 0.13.19 → 0.13.21
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/constants.d.ts +28 -1
- package/dist/constants.js +18 -0
- package/dist/db.js +9 -2
- package/dist/edge-play/src/entry/middleware.ts +74 -0
- package/dist/edge-play/src/entry/setup.ts +52 -0
- package/dist/edge-play/src/entry/types.ts +30 -0
- package/dist/edge-play/src/entry.ts +20 -71
- package/dist/edge-play/src/routes/health.ts +56 -27
- package/dist/edge-play/src/routes/index.ts +43 -15
- package/dist/edge-play/src/types.ts +8 -1
- package/dist/index.d.ts +51 -1
- package/dist/index.js +792 -241
- package/dist/templates/gitignore.template +3 -0
- package/dist/templates/playcademy-env.d.ts.template +1 -2
- package/dist/utils.d.ts +13 -13
- package/dist/utils.js +1074 -395
- package/package.json +2 -2
package/dist/utils.js
CHANGED
|
@@ -87,7 +87,8 @@ async function loadFile(filename, options = {}) {
|
|
|
87
87
|
required = false,
|
|
88
88
|
searchUp = false,
|
|
89
89
|
maxLevels = 3,
|
|
90
|
-
parseJson = false
|
|
90
|
+
parseJson = false,
|
|
91
|
+
stripComments = false
|
|
91
92
|
} = options;
|
|
92
93
|
let fileResult;
|
|
93
94
|
if (searchUp) {
|
|
@@ -116,8 +117,11 @@ async function loadFile(filename, options = {}) {
|
|
|
116
117
|
return null;
|
|
117
118
|
}
|
|
118
119
|
try {
|
|
119
|
-
|
|
120
|
+
let content = await readFile(fileResult.path, "utf-8");
|
|
120
121
|
if (parseJson) {
|
|
122
|
+
if (stripComments) {
|
|
123
|
+
content = stripJsonComments(content);
|
|
124
|
+
}
|
|
121
125
|
return JSON.parse(content);
|
|
122
126
|
}
|
|
123
127
|
return content;
|
|
@@ -182,6 +186,11 @@ function getCurrentDirectoryName(fallback = "unknown-directory") {
|
|
|
182
186
|
function getFileExtension(path2) {
|
|
183
187
|
return path2.split(".").pop()?.toLowerCase();
|
|
184
188
|
}
|
|
189
|
+
function stripJsonComments(jsonc) {
|
|
190
|
+
let result = jsonc.replace(/\/\*[\s\S]*?\*\//g, "");
|
|
191
|
+
result = result.replace(/\/\/.*/g, "");
|
|
192
|
+
return result;
|
|
193
|
+
}
|
|
185
194
|
async function loadModule(filename, options = {}) {
|
|
186
195
|
const { cwd = process.cwd(), required = false, searchUp = false, maxLevels = 3 } = options;
|
|
187
196
|
let fileResult;
|
|
@@ -285,104 +294,230 @@ var init_file_loader = __esm({
|
|
|
285
294
|
}
|
|
286
295
|
});
|
|
287
296
|
|
|
288
|
-
// src/lib/config/loader.ts
|
|
289
|
-
init_file_loader();
|
|
290
|
-
import { dirname as dirname2, resolve as resolve2 } from "path";
|
|
291
|
-
|
|
292
297
|
// src/constants/api.ts
|
|
293
|
-
var DEFAULT_API_ROUTES_DIRECTORY
|
|
298
|
+
var DEFAULT_API_ROUTES_DIRECTORY;
|
|
299
|
+
var init_api = __esm({
|
|
300
|
+
"src/constants/api.ts"() {
|
|
301
|
+
"use strict";
|
|
302
|
+
DEFAULT_API_ROUTES_DIRECTORY = "server/api";
|
|
303
|
+
}
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
// src/constants/config.ts
|
|
307
|
+
var ENV_FILES, TSCONFIG_FILES;
|
|
308
|
+
var init_config = __esm({
|
|
309
|
+
"src/constants/config.ts"() {
|
|
310
|
+
"use strict";
|
|
311
|
+
ENV_FILES = [
|
|
312
|
+
".env",
|
|
313
|
+
// Loaded first
|
|
314
|
+
".env.development",
|
|
315
|
+
// Overrides .env
|
|
316
|
+
".env.local"
|
|
317
|
+
// Overrides all (highest priority)
|
|
318
|
+
];
|
|
319
|
+
TSCONFIG_FILES = [
|
|
320
|
+
"tsconfig.app.json",
|
|
321
|
+
// Modern tooling (try first)
|
|
322
|
+
"tsconfig.json"
|
|
323
|
+
// Standard (fallback)
|
|
324
|
+
];
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
// src/constants/database.ts
|
|
329
|
+
var init_database = __esm({
|
|
330
|
+
"src/constants/database.ts"() {
|
|
331
|
+
"use strict";
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
// src/constants/http-server.ts
|
|
336
|
+
var init_http_server = __esm({
|
|
337
|
+
"src/constants/http-server.ts"() {
|
|
338
|
+
"use strict";
|
|
339
|
+
}
|
|
340
|
+
});
|
|
294
341
|
|
|
295
342
|
// src/constants/paths.ts
|
|
296
343
|
import { join } from "path";
|
|
297
|
-
var WORKSPACE_NAME
|
|
298
|
-
var
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
344
|
+
var WORKSPACE_NAME, CLI_DIRECTORIES;
|
|
345
|
+
var init_paths = __esm({
|
|
346
|
+
"src/constants/paths.ts"() {
|
|
347
|
+
"use strict";
|
|
348
|
+
WORKSPACE_NAME = ".playcademy";
|
|
349
|
+
CLI_DIRECTORIES = {
|
|
350
|
+
/** Root directory for CLI artifacts in workspace */
|
|
351
|
+
WORKSPACE: WORKSPACE_NAME,
|
|
352
|
+
/** Database directory within workspace */
|
|
353
|
+
DATABASE: join(WORKSPACE_NAME, "db"),
|
|
354
|
+
/** KV storage directory within workspace */
|
|
355
|
+
KV: join(WORKSPACE_NAME, "kv"),
|
|
356
|
+
/** Bucket storage directory within workspace */
|
|
357
|
+
BUCKET: join(WORKSPACE_NAME, "bucket")
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
});
|
|
308
361
|
|
|
309
362
|
// src/constants/ports.ts
|
|
310
|
-
var DEFAULT_PORTS
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
363
|
+
var DEFAULT_PORTS;
|
|
364
|
+
var init_ports = __esm({
|
|
365
|
+
"src/constants/ports.ts"() {
|
|
366
|
+
"use strict";
|
|
367
|
+
DEFAULT_PORTS = {
|
|
368
|
+
/** Sandbox server (mock platform API) */
|
|
369
|
+
SANDBOX: 4321,
|
|
370
|
+
/** Backend dev server (game backend with HMR) */
|
|
371
|
+
BACKEND: 8788
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
});
|
|
316
375
|
|
|
317
376
|
// src/constants/timeback.ts
|
|
318
|
-
var CONFIG_FILE_NAMES
|
|
319
|
-
|
|
320
|
-
"
|
|
321
|
-
|
|
322
|
-
|
|
377
|
+
var CONFIG_FILE_NAMES;
|
|
378
|
+
var init_timeback = __esm({
|
|
379
|
+
"src/constants/timeback.ts"() {
|
|
380
|
+
"use strict";
|
|
381
|
+
CONFIG_FILE_NAMES = [
|
|
382
|
+
"playcademy.config.js",
|
|
383
|
+
"playcademy.config.json",
|
|
384
|
+
"playcademy.config.mjs"
|
|
385
|
+
];
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
// ../constants/src/auth.ts
|
|
390
|
+
var init_auth = __esm({
|
|
391
|
+
"../constants/src/auth.ts"() {
|
|
392
|
+
"use strict";
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
// ../constants/src/domains.ts
|
|
397
|
+
var init_domains = __esm({
|
|
398
|
+
"../constants/src/domains.ts"() {
|
|
399
|
+
"use strict";
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
// ../constants/src/env-vars.ts
|
|
404
|
+
var init_env_vars = __esm({
|
|
405
|
+
"../constants/src/env-vars.ts"() {
|
|
406
|
+
"use strict";
|
|
407
|
+
}
|
|
408
|
+
});
|
|
323
409
|
|
|
324
410
|
// ../constants/src/overworld.ts
|
|
325
|
-
var ITEM_SLUGS
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
};
|
|
411
|
+
var ITEM_SLUGS, CURRENCIES, BADGES, CORE_GAME_UUIDS;
|
|
412
|
+
var init_overworld = __esm({
|
|
413
|
+
"../constants/src/overworld.ts"() {
|
|
414
|
+
"use strict";
|
|
415
|
+
ITEM_SLUGS = {
|
|
416
|
+
/** Primary platform currency */
|
|
417
|
+
PLAYCADEMY_CREDITS: "PLAYCADEMY_CREDITS",
|
|
418
|
+
/** Experience points currency */
|
|
419
|
+
PLAYCADEMY_XP: "PLAYCADEMY_XP",
|
|
420
|
+
/** Core platform badges */
|
|
421
|
+
FOUNDING_MEMBER_BADGE: "FOUNDING_MEMBER_BADGE",
|
|
422
|
+
EARLY_ADOPTER_BADGE: "EARLY_ADOPTER_BADGE",
|
|
423
|
+
FIRST_GAME_BADGE: "FIRST_GAME_BADGE",
|
|
424
|
+
/** Example items */
|
|
425
|
+
COMMON_SWORD: "COMMON_SWORD",
|
|
426
|
+
SMALL_HEALTH_POTION: "SMALL_HEALTH_POTION",
|
|
427
|
+
SMALL_BACKPACK: "SMALL_BACKPACK",
|
|
428
|
+
/** Placeable items */
|
|
429
|
+
LAVA_LAMP: "LAVA_LAMP",
|
|
430
|
+
BOOMBOX: "BOOMBOX",
|
|
431
|
+
CABIN_BED: "CABIN_BED"
|
|
432
|
+
};
|
|
433
|
+
CURRENCIES = {
|
|
434
|
+
/** Primary platform currency slug */
|
|
435
|
+
PRIMARY: ITEM_SLUGS.PLAYCADEMY_CREDITS,
|
|
436
|
+
/** Experience points slug */
|
|
437
|
+
XP: ITEM_SLUGS.PLAYCADEMY_XP
|
|
438
|
+
};
|
|
439
|
+
BADGES = {
|
|
440
|
+
FOUNDING_MEMBER: ITEM_SLUGS.FOUNDING_MEMBER_BADGE,
|
|
441
|
+
EARLY_ADOPTER: ITEM_SLUGS.EARLY_ADOPTER_BADGE,
|
|
442
|
+
FIRST_GAME: ITEM_SLUGS.FIRST_GAME_BADGE
|
|
443
|
+
};
|
|
444
|
+
CORE_GAME_UUIDS = {
|
|
445
|
+
/** Internal playground game for development and testing */
|
|
446
|
+
PLAYGROUND: "00000000-0000-0000-0000-000000000001"
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
// ../constants/src/system.ts
|
|
452
|
+
var init_system = __esm({
|
|
453
|
+
"../constants/src/system.ts"() {
|
|
454
|
+
"use strict";
|
|
455
|
+
}
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
// ../constants/src/timeback.ts
|
|
459
|
+
var init_timeback2 = __esm({
|
|
460
|
+
"../constants/src/timeback.ts"() {
|
|
461
|
+
"use strict";
|
|
462
|
+
}
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
// ../constants/src/workers.ts
|
|
466
|
+
var init_workers = __esm({
|
|
467
|
+
"../constants/src/workers.ts"() {
|
|
468
|
+
"use strict";
|
|
469
|
+
}
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
// ../constants/src/index.ts
|
|
473
|
+
var init_src = __esm({
|
|
474
|
+
"../constants/src/index.ts"() {
|
|
475
|
+
"use strict";
|
|
476
|
+
init_auth();
|
|
477
|
+
init_domains();
|
|
478
|
+
init_env_vars();
|
|
479
|
+
init_overworld();
|
|
480
|
+
init_system();
|
|
481
|
+
init_timeback2();
|
|
482
|
+
init_workers();
|
|
483
|
+
}
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
// src/constants/urls.ts
|
|
487
|
+
var init_urls = __esm({
|
|
488
|
+
"src/constants/urls.ts"() {
|
|
489
|
+
"use strict";
|
|
490
|
+
init_src();
|
|
491
|
+
}
|
|
492
|
+
});
|
|
358
493
|
|
|
359
494
|
// src/constants/index.ts
|
|
360
|
-
var CLOUDFLARE_COMPATIBILITY_DATE
|
|
495
|
+
var CLOUDFLARE_COMPATIBILITY_DATE;
|
|
496
|
+
var init_constants = __esm({
|
|
497
|
+
"src/constants/index.ts"() {
|
|
498
|
+
"use strict";
|
|
499
|
+
init_api();
|
|
500
|
+
init_config();
|
|
501
|
+
init_database();
|
|
502
|
+
init_http_server();
|
|
503
|
+
init_paths();
|
|
504
|
+
init_ports();
|
|
505
|
+
init_timeback();
|
|
506
|
+
init_urls();
|
|
507
|
+
CLOUDFLARE_COMPATIBILITY_DATE = "2024-01-01";
|
|
508
|
+
}
|
|
509
|
+
});
|
|
361
510
|
|
|
362
|
-
// src/
|
|
363
|
-
var
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
this.suggestion = suggestion;
|
|
368
|
-
this.name = "ConfigError";
|
|
369
|
-
}
|
|
370
|
-
/**
|
|
371
|
-
* Format a user-friendly error message with the field and suggestion
|
|
372
|
-
*/
|
|
373
|
-
toString() {
|
|
374
|
-
let msg = `Configuration Error: ${this.message}`;
|
|
375
|
-
if (this.field) {
|
|
376
|
-
msg += `
|
|
377
|
-
Field: ${this.field}`;
|
|
378
|
-
}
|
|
379
|
-
if (this.suggestion) {
|
|
380
|
-
msg += `
|
|
381
|
-
Suggestion: ${this.suggestion}`;
|
|
382
|
-
}
|
|
383
|
-
return msg;
|
|
511
|
+
// src/constants.ts
|
|
512
|
+
var init_constants2 = __esm({
|
|
513
|
+
"src/constants.ts"() {
|
|
514
|
+
"use strict";
|
|
515
|
+
init_constants();
|
|
384
516
|
}
|
|
385
|
-
};
|
|
517
|
+
});
|
|
518
|
+
|
|
519
|
+
// src/lib/config/loader.ts
|
|
520
|
+
import { dirname as dirname2, resolve as resolve2 } from "path";
|
|
386
521
|
async function findConfigPath(configPath) {
|
|
387
522
|
const { findFile: findFile2 } = await Promise.resolve().then(() => (init_file_loader(), file_loader_exports));
|
|
388
523
|
if (configPath) {
|
|
@@ -565,89 +700,37 @@ function processConfigVariables(config) {
|
|
|
565
700
|
};
|
|
566
701
|
return processValue(processed);
|
|
567
702
|
}
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
]);
|
|
598
|
-
if (localhostAvailable && ipv4AllAvailable && ipv6AllAvailable) {
|
|
599
|
-
return startPort;
|
|
600
|
-
}
|
|
601
|
-
return findAvailablePort(startPort + 1);
|
|
602
|
-
}
|
|
603
|
-
function getRegistryPath() {
|
|
604
|
-
const home = homedir();
|
|
605
|
-
const dir = join2(home, ".playcademy");
|
|
606
|
-
if (!existsSync2(dir)) {
|
|
607
|
-
mkdirSync(dir, { recursive: true });
|
|
608
|
-
}
|
|
609
|
-
return join2(dir, ".proc");
|
|
610
|
-
}
|
|
611
|
-
function readRegistry() {
|
|
612
|
-
const registryPath = getRegistryPath();
|
|
613
|
-
if (!existsSync2(registryPath)) {
|
|
614
|
-
return {};
|
|
615
|
-
}
|
|
616
|
-
try {
|
|
617
|
-
const content = readFileSync(registryPath, "utf-8");
|
|
618
|
-
return JSON.parse(content);
|
|
619
|
-
} catch {
|
|
620
|
-
return {};
|
|
621
|
-
}
|
|
622
|
-
}
|
|
623
|
-
function writeRegistry(registry) {
|
|
624
|
-
const registryPath = getRegistryPath();
|
|
625
|
-
writeFileSync(registryPath, JSON.stringify(registry, null, 2), "utf-8");
|
|
626
|
-
}
|
|
627
|
-
function getServerKey(type, port) {
|
|
628
|
-
return `${type}-${port}`;
|
|
629
|
-
}
|
|
630
|
-
function writeServerInfo(type, info) {
|
|
631
|
-
const registry = readRegistry();
|
|
632
|
-
const key = getServerKey(type, info.port);
|
|
633
|
-
registry[key] = info;
|
|
634
|
-
writeRegistry(registry);
|
|
635
|
-
}
|
|
636
|
-
function readServerInfo(type, projectRoot) {
|
|
637
|
-
const registry = readRegistry();
|
|
638
|
-
const servers = Object.entries(registry).filter(([key]) => key.startsWith(`${type}-`)).map(([, info]) => info);
|
|
639
|
-
if (servers.length === 0) {
|
|
640
|
-
return null;
|
|
641
|
-
}
|
|
642
|
-
if (projectRoot) {
|
|
643
|
-
const match = servers.find((s) => s.projectRoot === projectRoot);
|
|
644
|
-
return match || null;
|
|
703
|
+
var ConfigError;
|
|
704
|
+
var init_loader = __esm({
|
|
705
|
+
"src/lib/config/loader.ts"() {
|
|
706
|
+
"use strict";
|
|
707
|
+
init_file_loader();
|
|
708
|
+
init_constants2();
|
|
709
|
+
ConfigError = class extends Error {
|
|
710
|
+
constructor(message, field, suggestion) {
|
|
711
|
+
super(message);
|
|
712
|
+
this.field = field;
|
|
713
|
+
this.suggestion = suggestion;
|
|
714
|
+
this.name = "ConfigError";
|
|
715
|
+
}
|
|
716
|
+
/**
|
|
717
|
+
* Format a user-friendly error message with the field and suggestion
|
|
718
|
+
*/
|
|
719
|
+
toString() {
|
|
720
|
+
let msg = `Configuration Error: ${this.message}`;
|
|
721
|
+
if (this.field) {
|
|
722
|
+
msg += `
|
|
723
|
+
Field: ${this.field}`;
|
|
724
|
+
}
|
|
725
|
+
if (this.suggestion) {
|
|
726
|
+
msg += `
|
|
727
|
+
Suggestion: ${this.suggestion}`;
|
|
728
|
+
}
|
|
729
|
+
return msg;
|
|
730
|
+
}
|
|
731
|
+
};
|
|
645
732
|
}
|
|
646
|
-
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
// src/lib/core/client.ts
|
|
650
|
-
import { PlaycademyClient } from "@playcademy/sdk";
|
|
733
|
+
});
|
|
651
734
|
|
|
652
735
|
// ../utils/src/package-manager.ts
|
|
653
736
|
import { execSync } from "child_process";
|
|
@@ -701,16 +784,29 @@ function getInstallCommand(pm) {
|
|
|
701
784
|
return "npm install";
|
|
702
785
|
}
|
|
703
786
|
}
|
|
787
|
+
var init_package_manager = __esm({
|
|
788
|
+
"../utils/src/package-manager.ts"() {
|
|
789
|
+
"use strict";
|
|
790
|
+
}
|
|
791
|
+
});
|
|
704
792
|
|
|
705
793
|
// src/lib/core/context.ts
|
|
706
|
-
var context = {};
|
|
707
794
|
function getWorkspace() {
|
|
708
795
|
return context.workspace || process.cwd();
|
|
709
796
|
}
|
|
797
|
+
var context;
|
|
798
|
+
var init_context = __esm({
|
|
799
|
+
"src/lib/core/context.ts"() {
|
|
800
|
+
"use strict";
|
|
801
|
+
init_package_manager();
|
|
802
|
+
context = {};
|
|
803
|
+
}
|
|
804
|
+
});
|
|
710
805
|
|
|
711
806
|
// src/lib/core/logger.ts
|
|
712
807
|
import {
|
|
713
808
|
blue,
|
|
809
|
+
blueBright,
|
|
714
810
|
bold,
|
|
715
811
|
cyan,
|
|
716
812
|
dim,
|
|
@@ -723,8 +819,10 @@ import {
|
|
|
723
819
|
} from "colorette";
|
|
724
820
|
import { colorize } from "json-colorizer";
|
|
725
821
|
function customTransform(text) {
|
|
726
|
-
|
|
727
|
-
|
|
822
|
+
let result = text;
|
|
823
|
+
result = result.replace(/`([^`]+)`/g, (_, code) => greenBright(code));
|
|
824
|
+
result = result.replace(/<([^>]+)>/g, (_, path2) => blueBright(path2));
|
|
825
|
+
return result;
|
|
728
826
|
}
|
|
729
827
|
function formatTable(data, title) {
|
|
730
828
|
if (data.length === 0) return;
|
|
@@ -757,159 +855,199 @@ function formatTable(data, title) {
|
|
|
757
855
|
});
|
|
758
856
|
console.log(bottomBorder);
|
|
759
857
|
}
|
|
760
|
-
var logger
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
858
|
+
var logger;
|
|
859
|
+
var init_logger = __esm({
|
|
860
|
+
"src/lib/core/logger.ts"() {
|
|
861
|
+
"use strict";
|
|
862
|
+
logger = {
|
|
863
|
+
table: (data, title) => {
|
|
864
|
+
formatTable(data, title);
|
|
865
|
+
},
|
|
866
|
+
/**
|
|
867
|
+
* Info message - general information
|
|
868
|
+
*/
|
|
869
|
+
info: (message, indent = 0) => {
|
|
870
|
+
const spaces = " ".repeat(indent);
|
|
871
|
+
console.log(`${spaces}${blue("\u2139")} ${bold(customTransform(message))}`);
|
|
872
|
+
},
|
|
873
|
+
/**
|
|
874
|
+
* Admonition - highlighted note/tip/warning box (Docusaurus-style)
|
|
875
|
+
*/
|
|
876
|
+
admonition: (type, title, lines, indent = 0) => {
|
|
877
|
+
const spaces = " ".repeat(indent);
|
|
878
|
+
const configs = {
|
|
879
|
+
note: { color: green },
|
|
880
|
+
tip: { color: cyan },
|
|
881
|
+
info: { color: blue },
|
|
882
|
+
warning: { color: yellow }
|
|
883
|
+
};
|
|
884
|
+
const { color } = configs[type];
|
|
885
|
+
console.log(`${spaces}${color("\u250C\u2500")} ${bold(color(title.toUpperCase()))}`);
|
|
886
|
+
if (lines && lines.length > 0) {
|
|
887
|
+
lines.forEach((line) => {
|
|
888
|
+
console.log(`${spaces}${color("\u2502")} ${customTransform(line)}`);
|
|
889
|
+
});
|
|
890
|
+
}
|
|
891
|
+
console.log(`${spaces}${color("\u2514\u2500")}`);
|
|
892
|
+
},
|
|
893
|
+
/**
|
|
894
|
+
* Dim message - less important information
|
|
895
|
+
*/
|
|
896
|
+
dim: (message, indent = 0) => {
|
|
897
|
+
const spaces = " ".repeat(indent);
|
|
898
|
+
console.log(`${spaces}${dim(customTransform(message))}`);
|
|
899
|
+
},
|
|
900
|
+
/**
|
|
901
|
+
* Success message - operation completed successfully
|
|
902
|
+
*/
|
|
903
|
+
success: (message, indent = 0) => {
|
|
904
|
+
const spaces = " ".repeat(indent);
|
|
905
|
+
console.log(`${spaces}${green("\u2714")} ${bold(customTransform(message))}`);
|
|
906
|
+
},
|
|
907
|
+
remark: (message, indent = 0) => {
|
|
908
|
+
const spaces = " ".repeat(indent);
|
|
909
|
+
console.log(`${spaces}${bold(yellowBright("\u2726"))} ${bold(customTransform(message))}`);
|
|
910
|
+
},
|
|
911
|
+
/**
|
|
912
|
+
* Error message - operation failed
|
|
913
|
+
*/
|
|
914
|
+
error: (message, indent = 0) => {
|
|
915
|
+
const spaces = " ".repeat(indent);
|
|
916
|
+
console.error(`${spaces}${red("\u2716")} ${customTransform(message)}`);
|
|
917
|
+
},
|
|
918
|
+
bold: (message, indent = 0) => {
|
|
919
|
+
const spaces = " ".repeat(indent);
|
|
920
|
+
console.log(`${spaces}${bold(customTransform(message))}`);
|
|
921
|
+
},
|
|
922
|
+
/**
|
|
923
|
+
* Warning message - something to be aware of
|
|
924
|
+
*/
|
|
925
|
+
warn: (message, indent = 0) => {
|
|
926
|
+
const spaces = " ".repeat(indent);
|
|
927
|
+
console.warn(`${spaces}${yellow("\u26A0")} ${bold(customTransform(message))}`);
|
|
928
|
+
},
|
|
929
|
+
/**
|
|
930
|
+
* Debug message - only shown when DEBUG env var is set
|
|
931
|
+
*/
|
|
932
|
+
debug: (message, indent = 0) => {
|
|
933
|
+
const spaces = " ".repeat(indent);
|
|
934
|
+
if (process.env.DEBUG) {
|
|
935
|
+
console.log(gray("[DEBUG]"), `${spaces}${message}`);
|
|
936
|
+
}
|
|
937
|
+
},
|
|
938
|
+
/**
|
|
939
|
+
* Step message - shows progress through a process
|
|
940
|
+
*/
|
|
941
|
+
step: (step, total, message, indent = 0) => {
|
|
942
|
+
const spaces = " ".repeat(indent);
|
|
943
|
+
console.log(spaces + cyan(`[${step}/${total}]`), customTransform(message));
|
|
944
|
+
},
|
|
945
|
+
/**
|
|
946
|
+
* Highlighted message - draws attention
|
|
947
|
+
*/
|
|
948
|
+
highlight: (message, indent = 0) => {
|
|
949
|
+
const spaces = " ".repeat(indent);
|
|
950
|
+
console.log(bold(`${spaces}${cyan(customTransform(message))}`));
|
|
951
|
+
},
|
|
952
|
+
/**
|
|
953
|
+
* Aside message - for side information
|
|
954
|
+
*/
|
|
955
|
+
aside: (message, indent = 0) => {
|
|
956
|
+
const spaces = " ".repeat(indent);
|
|
957
|
+
console.log(`${spaces}${bold(customTransform(message))}`);
|
|
958
|
+
},
|
|
959
|
+
/**
|
|
960
|
+
* Data display - for structured data output
|
|
961
|
+
*/
|
|
962
|
+
data: (label, value, indent = 0) => {
|
|
963
|
+
const spaces = " ".repeat(indent);
|
|
964
|
+
if (value !== void 0) {
|
|
965
|
+
console.log(`${spaces}${dim(label + ":")} ${bold(value)}`);
|
|
966
|
+
} else {
|
|
967
|
+
console.log(`${spaces}${dim(label)}`);
|
|
968
|
+
}
|
|
969
|
+
},
|
|
970
|
+
/**
|
|
971
|
+
* JSON output - pretty-printed JSON
|
|
972
|
+
*/
|
|
973
|
+
json: (data, indent = 0) => {
|
|
974
|
+
const spaces = " ".repeat(indent);
|
|
975
|
+
const jsonString = colorize(JSON.stringify(data, null, 2));
|
|
976
|
+
jsonString.split("\n").forEach((line) => {
|
|
977
|
+
console.log(`${spaces}${line}`);
|
|
978
|
+
});
|
|
979
|
+
},
|
|
980
|
+
/**
|
|
981
|
+
* New line
|
|
982
|
+
*/
|
|
983
|
+
newLine: () => {
|
|
984
|
+
console.log();
|
|
985
|
+
},
|
|
986
|
+
/**
|
|
987
|
+
* Raw output - no formatting, useful for ASCII art or pre-formatted text
|
|
988
|
+
*/
|
|
989
|
+
raw: (text, indent = 0) => {
|
|
990
|
+
const spaces = " ".repeat(indent);
|
|
991
|
+
console.log(`${spaces}${text}`);
|
|
992
|
+
},
|
|
993
|
+
customRaw: (text, indent = 0) => {
|
|
994
|
+
const spaces = " ".repeat(indent);
|
|
995
|
+
console.log(`${spaces}${customTransform(text)}`);
|
|
996
|
+
},
|
|
997
|
+
/**
|
|
998
|
+
* Display a configuration error with helpful suggestions
|
|
999
|
+
*/
|
|
1000
|
+
configError: (error, indent = 0) => {
|
|
1001
|
+
const spaces = " ".repeat(indent);
|
|
1002
|
+
const isConfigError = error && typeof error === "object" && "name" in error && error.name === "ConfigError";
|
|
1003
|
+
if (isConfigError && "message" in error && "field" in error && "suggestion" in error) {
|
|
1004
|
+
const configErr = error;
|
|
1005
|
+
console.error(`${spaces}${red("\u2716")} ${bold(configErr.message)}`);
|
|
1006
|
+
if (configErr.field) {
|
|
1007
|
+
console.error(`${spaces} ${dim("Field:")} ${configErr.field}`);
|
|
1008
|
+
}
|
|
1009
|
+
if (configErr.suggestion) {
|
|
1010
|
+
console.error(`${spaces} ${dim("Fix:")} ${configErr.suggestion}`);
|
|
1011
|
+
}
|
|
1012
|
+
} else if (error instanceof Error) {
|
|
1013
|
+
console.error(`${spaces}${red("\u2716")} ${bold(error.message)}`);
|
|
1014
|
+
} else {
|
|
1015
|
+
console.error(`${spaces}${red("\u2716")} ${bold(String(error))}`);
|
|
1016
|
+
}
|
|
905
1017
|
}
|
|
906
|
-
}
|
|
907
|
-
console.error(`${spaces}${red("\u2716")} ${bold(error.message)}`);
|
|
908
|
-
} else {
|
|
909
|
-
console.error(`${spaces}${red("\u2716")} ${bold(String(error))}`);
|
|
910
|
-
}
|
|
1018
|
+
};
|
|
911
1019
|
}
|
|
912
|
-
};
|
|
1020
|
+
});
|
|
1021
|
+
|
|
1022
|
+
// src/lib/core/config.ts
|
|
1023
|
+
var init_config2 = __esm({
|
|
1024
|
+
"src/lib/core/config.ts"() {
|
|
1025
|
+
"use strict";
|
|
1026
|
+
init_constants2();
|
|
1027
|
+
init_context();
|
|
1028
|
+
init_logger();
|
|
1029
|
+
}
|
|
1030
|
+
});
|
|
1031
|
+
|
|
1032
|
+
// src/lib/auth/storage.ts
|
|
1033
|
+
var init_storage = __esm({
|
|
1034
|
+
"src/lib/auth/storage.ts"() {
|
|
1035
|
+
"use strict";
|
|
1036
|
+
init_constants2();
|
|
1037
|
+
init_config2();
|
|
1038
|
+
}
|
|
1039
|
+
});
|
|
1040
|
+
|
|
1041
|
+
// src/lib/core/client.ts
|
|
1042
|
+
import { PlaycademyClient } from "@playcademy/sdk";
|
|
1043
|
+
var init_client = __esm({
|
|
1044
|
+
"src/lib/core/client.ts"() {
|
|
1045
|
+
"use strict";
|
|
1046
|
+
init_storage();
|
|
1047
|
+
init_logger();
|
|
1048
|
+
init_config2();
|
|
1049
|
+
}
|
|
1050
|
+
});
|
|
913
1051
|
|
|
914
1052
|
// src/lib/core/errors.ts
|
|
915
1053
|
function getErrorMessage(error) {
|
|
@@ -920,34 +1058,141 @@ function getErrorMessage(error) {
|
|
|
920
1058
|
}
|
|
921
1059
|
return "Unknown error";
|
|
922
1060
|
}
|
|
1061
|
+
var init_errors = __esm({
|
|
1062
|
+
"src/lib/core/errors.ts"() {
|
|
1063
|
+
"use strict";
|
|
1064
|
+
}
|
|
1065
|
+
});
|
|
1066
|
+
|
|
1067
|
+
// ../utils/src/uuid.ts
|
|
1068
|
+
var init_uuid = __esm({
|
|
1069
|
+
"../utils/src/uuid.ts"() {
|
|
1070
|
+
"use strict";
|
|
1071
|
+
}
|
|
1072
|
+
});
|
|
1073
|
+
|
|
1074
|
+
// ../utils/src/mime.ts
|
|
1075
|
+
var init_mime = __esm({
|
|
1076
|
+
"../utils/src/mime.ts"() {
|
|
1077
|
+
"use strict";
|
|
1078
|
+
}
|
|
1079
|
+
});
|
|
923
1080
|
|
|
924
1081
|
// ../utils/src/ansi.ts
|
|
925
|
-
var isInteractive
|
|
1082
|
+
var isInteractive;
|
|
1083
|
+
var init_ansi = __esm({
|
|
1084
|
+
"../utils/src/ansi.ts"() {
|
|
1085
|
+
"use strict";
|
|
1086
|
+
isInteractive = typeof process !== "undefined" && process.stdout?.isTTY && !process.env.CI && process.env.TERM !== "dumb";
|
|
1087
|
+
}
|
|
1088
|
+
});
|
|
926
1089
|
|
|
927
1090
|
// ../utils/src/spinner.ts
|
|
928
|
-
var SPINNER_FRAMES
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
1091
|
+
var SPINNER_FRAMES, CHECK_MARK, CROSS_MARK;
|
|
1092
|
+
var init_spinner = __esm({
|
|
1093
|
+
"../utils/src/spinner.ts"() {
|
|
1094
|
+
"use strict";
|
|
1095
|
+
init_ansi();
|
|
1096
|
+
SPINNER_FRAMES = [
|
|
1097
|
+
10251,
|
|
1098
|
+
10265,
|
|
1099
|
+
10297,
|
|
1100
|
+
10296,
|
|
1101
|
+
10300,
|
|
1102
|
+
10292,
|
|
1103
|
+
10278,
|
|
1104
|
+
10279,
|
|
1105
|
+
10247,
|
|
1106
|
+
10255
|
|
1107
|
+
].map((code) => String.fromCodePoint(code));
|
|
1108
|
+
CHECK_MARK = String.fromCodePoint(10004);
|
|
1109
|
+
CROSS_MARK = String.fromCodePoint(10006);
|
|
1110
|
+
}
|
|
1111
|
+
});
|
|
1112
|
+
|
|
1113
|
+
// ../utils/src/log.ts
|
|
1114
|
+
var init_log = __esm({
|
|
1115
|
+
"../utils/src/log.ts"() {
|
|
1116
|
+
"use strict";
|
|
1117
|
+
init_ansi();
|
|
1118
|
+
init_spinner();
|
|
1119
|
+
}
|
|
1120
|
+
});
|
|
1121
|
+
|
|
1122
|
+
// ../utils/src/name.ts
|
|
1123
|
+
var init_name = __esm({
|
|
1124
|
+
"../utils/src/name.ts"() {
|
|
1125
|
+
"use strict";
|
|
1126
|
+
}
|
|
1127
|
+
});
|
|
1128
|
+
|
|
1129
|
+
// ../utils/src/string.ts
|
|
1130
|
+
function pluralize(count, singular, plural) {
|
|
1131
|
+
return count === 1 ? singular : plural || `${singular}s`;
|
|
1132
|
+
}
|
|
1133
|
+
var init_string = __esm({
|
|
1134
|
+
"../utils/src/string.ts"() {
|
|
1135
|
+
"use strict";
|
|
1136
|
+
}
|
|
1137
|
+
});
|
|
1138
|
+
|
|
1139
|
+
// ../utils/src/lifecycle.ts
|
|
1140
|
+
var init_lifecycle = __esm({
|
|
1141
|
+
"../utils/src/lifecycle.ts"() {
|
|
1142
|
+
"use strict";
|
|
1143
|
+
}
|
|
1144
|
+
});
|
|
1145
|
+
|
|
1146
|
+
// ../utils/src/timezone.ts
|
|
1147
|
+
var init_timezone = __esm({
|
|
1148
|
+
"../utils/src/timezone.ts"() {
|
|
1149
|
+
"use strict";
|
|
1150
|
+
}
|
|
1151
|
+
});
|
|
1152
|
+
|
|
1153
|
+
// ../utils/src/slug.ts
|
|
1154
|
+
var init_slug = __esm({
|
|
1155
|
+
"../utils/src/slug.ts"() {
|
|
1156
|
+
"use strict";
|
|
1157
|
+
}
|
|
1158
|
+
});
|
|
942
1159
|
|
|
943
1160
|
// ../utils/src/pure/index.ts
|
|
944
|
-
|
|
1161
|
+
var init_pure = __esm({
|
|
1162
|
+
"../utils/src/pure/index.ts"() {
|
|
1163
|
+
"use strict";
|
|
1164
|
+
init_uuid();
|
|
1165
|
+
init_mime();
|
|
1166
|
+
init_log();
|
|
1167
|
+
init_name();
|
|
1168
|
+
init_string();
|
|
1169
|
+
init_lifecycle();
|
|
1170
|
+
init_timezone();
|
|
1171
|
+
init_package_json();
|
|
1172
|
+
init_slug();
|
|
1173
|
+
}
|
|
1174
|
+
});
|
|
1175
|
+
|
|
1176
|
+
// ../utils/src/index.ts
|
|
1177
|
+
var init_src2 = __esm({
|
|
1178
|
+
"../utils/src/index.ts"() {
|
|
1179
|
+
"use strict";
|
|
1180
|
+
init_pure();
|
|
1181
|
+
}
|
|
1182
|
+
});
|
|
1183
|
+
|
|
1184
|
+
// src/lib/config/timeback-derive.ts
|
|
1185
|
+
var init_timeback_derive = __esm({
|
|
1186
|
+
"src/lib/config/timeback-derive.ts"() {
|
|
1187
|
+
"use strict";
|
|
1188
|
+
init_game();
|
|
1189
|
+
}
|
|
1190
|
+
});
|
|
945
1191
|
|
|
946
1192
|
// src/lib/templates/loader.ts
|
|
947
1193
|
import { existsSync as existsSync4, readFileSync as readFileSync2 } from "fs";
|
|
948
1194
|
import { dirname as dirname3, resolve as resolve3 } from "path";
|
|
949
1195
|
import { fileURLToPath } from "url";
|
|
950
|
-
var currentDir = dirname3(fileURLToPath(import.meta.url));
|
|
951
1196
|
function loadTemplateString(filename) {
|
|
952
1197
|
const filenamesToTry = filename.endsWith(".template") ? [filename] : [filename, `${filename}.template`];
|
|
953
1198
|
const candidatePaths = filenamesToTry.flatMap((name) => [
|
|
@@ -963,6 +1208,49 @@ function loadTemplateString(filename) {
|
|
|
963
1208
|
}
|
|
964
1209
|
throw new Error(`Template not found: ${filename}. Searched: ${candidatePaths.join(", ")}`);
|
|
965
1210
|
}
|
|
1211
|
+
var currentDir;
|
|
1212
|
+
var init_loader2 = __esm({
|
|
1213
|
+
"src/lib/templates/loader.ts"() {
|
|
1214
|
+
"use strict";
|
|
1215
|
+
currentDir = dirname3(fileURLToPath(import.meta.url));
|
|
1216
|
+
}
|
|
1217
|
+
});
|
|
1218
|
+
|
|
1219
|
+
// src/lib/config/generator.ts
|
|
1220
|
+
var init_generator = __esm({
|
|
1221
|
+
"src/lib/config/generator.ts"() {
|
|
1222
|
+
"use strict";
|
|
1223
|
+
init_loader2();
|
|
1224
|
+
}
|
|
1225
|
+
});
|
|
1226
|
+
|
|
1227
|
+
// src/lib/config/writer.ts
|
|
1228
|
+
var init_writer = __esm({
|
|
1229
|
+
"src/lib/config/writer.ts"() {
|
|
1230
|
+
"use strict";
|
|
1231
|
+
}
|
|
1232
|
+
});
|
|
1233
|
+
|
|
1234
|
+
// src/lib/config/index.ts
|
|
1235
|
+
var init_config3 = __esm({
|
|
1236
|
+
"src/lib/config/index.ts"() {
|
|
1237
|
+
"use strict";
|
|
1238
|
+
init_loader();
|
|
1239
|
+
init_timeback_derive();
|
|
1240
|
+
init_generator();
|
|
1241
|
+
init_writer();
|
|
1242
|
+
}
|
|
1243
|
+
});
|
|
1244
|
+
|
|
1245
|
+
// src/lib/core/game.ts
|
|
1246
|
+
var init_game = __esm({
|
|
1247
|
+
"src/lib/core/game.ts"() {
|
|
1248
|
+
"use strict";
|
|
1249
|
+
init_src2();
|
|
1250
|
+
init_slug();
|
|
1251
|
+
init_config3();
|
|
1252
|
+
}
|
|
1253
|
+
});
|
|
966
1254
|
|
|
967
1255
|
// src/lib/core/import.ts
|
|
968
1256
|
import { mkdtempSync, rmSync } from "fs";
|
|
@@ -998,13 +1286,135 @@ async function importTypescriptDefault(filePath, bundleOptions) {
|
|
|
998
1286
|
}
|
|
999
1287
|
return module;
|
|
1000
1288
|
}
|
|
1289
|
+
var init_import = __esm({
|
|
1290
|
+
"src/lib/core/import.ts"() {
|
|
1291
|
+
"use strict";
|
|
1292
|
+
}
|
|
1293
|
+
});
|
|
1294
|
+
|
|
1295
|
+
// src/lib/core/index.ts
|
|
1296
|
+
var init_core = __esm({
|
|
1297
|
+
"src/lib/core/index.ts"() {
|
|
1298
|
+
"use strict";
|
|
1299
|
+
init_client();
|
|
1300
|
+
init_config2();
|
|
1301
|
+
init_context();
|
|
1302
|
+
init_errors();
|
|
1303
|
+
init_game();
|
|
1304
|
+
init_import();
|
|
1305
|
+
init_logger();
|
|
1306
|
+
}
|
|
1307
|
+
});
|
|
1308
|
+
|
|
1309
|
+
// src/utils.ts
|
|
1310
|
+
init_loader();
|
|
1311
|
+
init_loader();
|
|
1312
|
+
init_loader();
|
|
1313
|
+
|
|
1314
|
+
// src/lib/dev/server.ts
|
|
1315
|
+
init_src();
|
|
1316
|
+
import { mkdir as mkdir2 } from "fs/promises";
|
|
1317
|
+
import { join as join12 } from "path";
|
|
1318
|
+
import { Log, LogLevel, Miniflare } from "miniflare";
|
|
1319
|
+
|
|
1320
|
+
// ../utils/src/port.ts
|
|
1321
|
+
import { existsSync as existsSync2, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
1322
|
+
import { createServer } from "node:net";
|
|
1323
|
+
import { homedir } from "node:os";
|
|
1324
|
+
import { join as join2 } from "node:path";
|
|
1325
|
+
async function isPortAvailableOnHost(port, host) {
|
|
1326
|
+
return new Promise((resolve4) => {
|
|
1327
|
+
const server = createServer();
|
|
1328
|
+
let resolved = false;
|
|
1329
|
+
const cleanup = (result) => {
|
|
1330
|
+
if (resolved) return;
|
|
1331
|
+
resolved = true;
|
|
1332
|
+
try {
|
|
1333
|
+
server.close();
|
|
1334
|
+
} catch {
|
|
1335
|
+
}
|
|
1336
|
+
resolve4(result);
|
|
1337
|
+
};
|
|
1338
|
+
const timeout = setTimeout(() => cleanup(true), 100);
|
|
1339
|
+
server.once("error", (err) => {
|
|
1340
|
+
clearTimeout(timeout);
|
|
1341
|
+
if (err.code === "EAFNOSUPPORT" || err.code === "EADDRNOTAVAIL") {
|
|
1342
|
+
cleanup(true);
|
|
1343
|
+
} else {
|
|
1344
|
+
cleanup(false);
|
|
1345
|
+
}
|
|
1346
|
+
});
|
|
1347
|
+
server.once("listening", () => {
|
|
1348
|
+
clearTimeout(timeout);
|
|
1349
|
+
cleanup(true);
|
|
1350
|
+
});
|
|
1351
|
+
server.listen(port, host).unref();
|
|
1352
|
+
});
|
|
1353
|
+
}
|
|
1354
|
+
async function findAvailablePort(startPort = 4321) {
|
|
1355
|
+
if (await isPortAvailableOnHost(startPort, "0.0.0.0")) {
|
|
1356
|
+
return startPort;
|
|
1357
|
+
} else {
|
|
1358
|
+
return findAvailablePort(startPort + 1);
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
function getRegistryPath() {
|
|
1362
|
+
const home = homedir();
|
|
1363
|
+
const dir = join2(home, ".playcademy");
|
|
1364
|
+
if (!existsSync2(dir)) {
|
|
1365
|
+
mkdirSync(dir, { recursive: true });
|
|
1366
|
+
}
|
|
1367
|
+
return join2(dir, ".proc");
|
|
1368
|
+
}
|
|
1369
|
+
function readRegistry() {
|
|
1370
|
+
const registryPath = getRegistryPath();
|
|
1371
|
+
if (!existsSync2(registryPath)) {
|
|
1372
|
+
return {};
|
|
1373
|
+
}
|
|
1374
|
+
try {
|
|
1375
|
+
const content = readFileSync(registryPath, "utf-8");
|
|
1376
|
+
return JSON.parse(content);
|
|
1377
|
+
} catch {
|
|
1378
|
+
return {};
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
function writeRegistry(registry) {
|
|
1382
|
+
const registryPath = getRegistryPath();
|
|
1383
|
+
writeFileSync(registryPath, JSON.stringify(registry, null, 2), "utf-8");
|
|
1384
|
+
}
|
|
1385
|
+
function getServerKey(type, port) {
|
|
1386
|
+
return `${type}-${port}`;
|
|
1387
|
+
}
|
|
1388
|
+
function writeServerInfo(type, info) {
|
|
1389
|
+
const registry = readRegistry();
|
|
1390
|
+
const key = getServerKey(type, info.port);
|
|
1391
|
+
registry[key] = info;
|
|
1392
|
+
writeRegistry(registry);
|
|
1393
|
+
}
|
|
1394
|
+
function readServerInfo(type, projectRoot) {
|
|
1395
|
+
const registry = readRegistry();
|
|
1396
|
+
const servers = Object.entries(registry).filter(([key]) => key.startsWith(`${type}-`)).map(([, info]) => info);
|
|
1397
|
+
if (servers.length === 0) {
|
|
1398
|
+
return null;
|
|
1399
|
+
}
|
|
1400
|
+
if (projectRoot) {
|
|
1401
|
+
const match = servers.find((s) => s.projectRoot === projectRoot);
|
|
1402
|
+
return match || null;
|
|
1403
|
+
}
|
|
1404
|
+
return servers[0] || null;
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1407
|
+
// src/lib/dev/server.ts
|
|
1408
|
+
init_constants2();
|
|
1409
|
+
init_loader();
|
|
1410
|
+
init_core();
|
|
1001
1411
|
|
|
1002
1412
|
// src/lib/deploy/bundle.ts
|
|
1003
1413
|
import { existsSync as existsSync5 } from "fs";
|
|
1004
1414
|
import { join as join6 } from "path";
|
|
1005
1415
|
|
|
1006
1416
|
// ../edge-play/src/entry.ts
|
|
1007
|
-
var entry_default = "/**\n * Game Backend Entry Point\n *\n * This file is the main entry point for deployed game backends.\n * It creates a Hono app and registers all enabled integration routes.\n *\n * Bundled with esbuild and deployed to Cloudflare Workers (or AWS Lambda).\n * Config is injected at build time via esbuild's `define` option.\n */\n\nimport { Hono } from 'hono'\nimport {
|
|
1417
|
+
var entry_default = "/**\n * Game Backend Entry Point\n *\n * This file is the main entry point for deployed game backends.\n * It creates a Hono app and registers all enabled integration routes.\n *\n * Bundled with esbuild and deployed to Cloudflare Workers (or AWS Lambda).\n * Config is injected at build time via esbuild's `define` option.\n */\n\nimport { Hono } from 'hono'\n\nimport { registerCors, registerEnvSetup, registerSdkInit } from './entry/middleware'\nimport { setupProcessGlobal } from './entry/setup'\nimport { registerBuiltinRoutes } from './register-routes'\n\nimport type { RuntimeConfig } from './entry/types'\nimport type { HonoEnv } from './types'\n\n/**\n * Config injected at build time by esbuild\n *\n * The `declare const` tells TypeScript \"this exists at runtime, trust me.\"\n * During bundling, esbuild's `define` option does literal text replacement:\n *\n * Example bundling:\n * Source: if (PLAYCADEMY_CONFIG.integrations.timeback) { ... }\n * Define: { 'PLAYCADEMY_CONFIG': JSON.stringify({ integrations: { timeback: {...} } }) }\n * Output: if ({\"integrations\":{\"timeback\":{...}}}.integrations.timeback) { ... }\n *\n * This enables tree-shaking: if timeback is not configured, those code paths are removed.\n * The bundled Worker only includes the routes that are actually enabled.\n */\ndeclare const PLAYCADEMY_CONFIG: RuntimeConfig\n\n// Setup process global polyfill for SDK compatibility\nsetupProcessGlobal()\n\n// Create Hono app\nconst app = new Hono<HonoEnv>()\n\n// Register middleware\nregisterCors(app)\nregisterEnvSetup(app, PLAYCADEMY_CONFIG)\nregisterSdkInit(app, PLAYCADEMY_CONFIG)\n\n// Register built-in integration routes based on enabled integrations\n// This function conditionally imports and registers routes like:\n// - GET /api (always included)\n// - GET /api/health (always included)\n// - POST /api/integrations/timeback/end-activity (if timeback enabled)\n//\n// Uses dynamic imports for tree-shaking: if an integration is not enabled,\n// its route code is completely removed from the bundle.\nawait registerBuiltinRoutes(app, PLAYCADEMY_CONFIG.integrations)\n\nexport default app\n";
|
|
1008
1418
|
|
|
1009
1419
|
// ../utils/src/path.ts
|
|
1010
1420
|
import fs from "node:fs";
|
|
@@ -1220,6 +1630,9 @@ function getMonorepoRoot() {
|
|
|
1220
1630
|
return memoizedRoot;
|
|
1221
1631
|
}
|
|
1222
1632
|
|
|
1633
|
+
// src/lib/deploy/bundle.ts
|
|
1634
|
+
init_constants2();
|
|
1635
|
+
|
|
1223
1636
|
// src/lib/build/plugins.ts
|
|
1224
1637
|
function textLoaderPlugin() {
|
|
1225
1638
|
return {
|
|
@@ -1253,8 +1666,12 @@ function textLoaderPlugin() {
|
|
|
1253
1666
|
};
|
|
1254
1667
|
}
|
|
1255
1668
|
|
|
1669
|
+
// src/lib/deploy/bundle.ts
|
|
1670
|
+
init_core();
|
|
1671
|
+
|
|
1256
1672
|
// src/lib/dev/routes.ts
|
|
1257
1673
|
init_file_loader();
|
|
1674
|
+
init_core();
|
|
1258
1675
|
import { mkdir, writeFile } from "fs/promises";
|
|
1259
1676
|
import { tmpdir as tmpdir2 } from "os";
|
|
1260
1677
|
import { join as join5, relative } from "path";
|
|
@@ -1310,6 +1727,7 @@ function filePathToRoutePath(filePath) {
|
|
|
1310
1727
|
routePath = routePath.replace(/\/?index$/, "");
|
|
1311
1728
|
}
|
|
1312
1729
|
let urlPath = "/" + routePath.replace(/\\/g, "/");
|
|
1730
|
+
urlPath = urlPath.replace(/\[\.\.\.([^\]]+)\]/g, ":$1{.*}");
|
|
1313
1731
|
urlPath = urlPath.replace(/\[([^\]]+)\]/g, ":$1");
|
|
1314
1732
|
urlPath = urlPath === "/" ? "/api" : `/api${urlPath}`;
|
|
1315
1733
|
return urlPath;
|
|
@@ -1454,7 +1872,7 @@ async function bundleBackend(config, options = {}) {
|
|
|
1454
1872
|
const { customRouteData, customRoutesDir } = await discoverCustomRoutes(config);
|
|
1455
1873
|
const bundleConfig = {
|
|
1456
1874
|
...config,
|
|
1457
|
-
|
|
1875
|
+
__routeMetadata: customRouteData
|
|
1458
1876
|
};
|
|
1459
1877
|
const entryCode = generateEntryCode(customRouteData, customRoutesDir);
|
|
1460
1878
|
const paths = resolveEmbeddedSourcePaths();
|
|
@@ -1504,8 +1922,19 @@ function generateEntryCode(customRoutes, customRoutesDir) {
|
|
|
1504
1922
|
// src/lib/init/prompts.ts
|
|
1505
1923
|
import { checkbox, confirm, input, select } from "@inquirer/prompts";
|
|
1506
1924
|
import { bold as bold3, cyan as cyan2 } from "colorette";
|
|
1925
|
+
init_constants2();
|
|
1926
|
+
|
|
1927
|
+
// src/lib/init/scaffold.ts
|
|
1928
|
+
init_constants2();
|
|
1929
|
+
init_core();
|
|
1930
|
+
init_loader2();
|
|
1507
1931
|
|
|
1508
1932
|
// src/lib/init/database.ts
|
|
1933
|
+
init_log();
|
|
1934
|
+
init_slug();
|
|
1935
|
+
init_core();
|
|
1936
|
+
init_logger();
|
|
1937
|
+
init_loader2();
|
|
1509
1938
|
import { existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
1510
1939
|
import { join as join7 } from "path";
|
|
1511
1940
|
var drizzleConfigTemplate = loadTemplateString("database/drizzle-config.ts");
|
|
@@ -1530,7 +1959,9 @@ var sampleBucketRouteTemplate = loadTemplateString("api/sample-bucket.ts");
|
|
|
1530
1959
|
var playcademyGitignoreTemplate = loadTemplateString("playcademy-gitignore");
|
|
1531
1960
|
|
|
1532
1961
|
// src/lib/init/display.ts
|
|
1533
|
-
|
|
1962
|
+
init_package_manager();
|
|
1963
|
+
init_context();
|
|
1964
|
+
init_logger();
|
|
1534
1965
|
|
|
1535
1966
|
// src/lib/init/kv.ts
|
|
1536
1967
|
function hasKVSetup(config) {
|
|
@@ -1544,57 +1975,292 @@ function hasBucketSetup(config) {
|
|
|
1544
1975
|
|
|
1545
1976
|
// src/lib/init/types.ts
|
|
1546
1977
|
init_file_loader();
|
|
1978
|
+
init_package_manager();
|
|
1979
|
+
init_string();
|
|
1980
|
+
init_constants2();
|
|
1981
|
+
init_loader();
|
|
1982
|
+
init_core();
|
|
1547
1983
|
import { execSync as execSync2 } from "child_process";
|
|
1548
|
-
import { writeFileSync as
|
|
1549
|
-
import { dirname as dirname4, join as
|
|
1984
|
+
import { writeFileSync as writeFileSync4 } from "fs";
|
|
1985
|
+
import { dirname as dirname4, join as join11 } from "path";
|
|
1550
1986
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1987
|
+
|
|
1988
|
+
// src/lib/deploy/backend.ts
|
|
1989
|
+
init_src2();
|
|
1990
|
+
init_constants2();
|
|
1991
|
+
init_core();
|
|
1992
|
+
import { existsSync as existsSync7 } from "node:fs";
|
|
1993
|
+
import { join as join8 } from "node:path";
|
|
1994
|
+
|
|
1995
|
+
// src/lib/integrations/timeback.ts
|
|
1996
|
+
init_src2();
|
|
1997
|
+
init_core();
|
|
1998
|
+
|
|
1999
|
+
// src/lib/integrations/utils.ts
|
|
2000
|
+
init_string();
|
|
2001
|
+
|
|
2002
|
+
// src/lib/deploy/schema.ts
|
|
2003
|
+
init_core();
|
|
2004
|
+
|
|
2005
|
+
// src/lib/deploy/secrets.ts
|
|
2006
|
+
init_core();
|
|
2007
|
+
init_logger();
|
|
2008
|
+
|
|
2009
|
+
// src/lib/deploy/utils.ts
|
|
2010
|
+
init_src();
|
|
2011
|
+
|
|
2012
|
+
// src/lib/deploy/backend.ts
|
|
2013
|
+
function getCustomRoutesDirectory(projectPath, config) {
|
|
2014
|
+
const customRoutes = config?.integrations?.customRoutes;
|
|
2015
|
+
const customRoutesDir = typeof customRoutes === "object" && customRoutes.directory || DEFAULT_API_ROUTES_DIRECTORY;
|
|
2016
|
+
return join8(projectPath, customRoutesDir);
|
|
2017
|
+
}
|
|
2018
|
+
function hasLocalCustomRoutes(projectPath, config) {
|
|
2019
|
+
const customRoutesDir = getCustomRoutesDirectory(projectPath, config);
|
|
2020
|
+
return existsSync7(customRoutesDir);
|
|
2021
|
+
}
|
|
2022
|
+
|
|
2023
|
+
// src/lib/secrets/env.ts
|
|
2024
|
+
init_file_loader();
|
|
2025
|
+
init_constants2();
|
|
2026
|
+
import { existsSync as existsSync8 } from "fs";
|
|
2027
|
+
import { join as join9 } from "path";
|
|
2028
|
+
function parseEnvFile(contents) {
|
|
2029
|
+
const secrets = {};
|
|
2030
|
+
for (const line of contents.split("\n")) {
|
|
2031
|
+
const trimmed = line.trim();
|
|
2032
|
+
if (!trimmed || trimmed.startsWith("#")) {
|
|
2033
|
+
continue;
|
|
2034
|
+
}
|
|
2035
|
+
const match = trimmed.match(/^([A-Z_][A-Z0-9_]*)=(.*)$/);
|
|
2036
|
+
if (match) {
|
|
2037
|
+
const [, key, value] = match;
|
|
2038
|
+
if (!key || !value) {
|
|
2039
|
+
continue;
|
|
2040
|
+
}
|
|
2041
|
+
const unquoted = value.replace(/^["']|["']$/g, "");
|
|
2042
|
+
secrets[key] = unquoted;
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
2045
|
+
return secrets;
|
|
2046
|
+
}
|
|
2047
|
+
async function readEnvFile(workspace) {
|
|
2048
|
+
let secrets = {};
|
|
2049
|
+
for (const filename of ENV_FILES) {
|
|
2050
|
+
try {
|
|
2051
|
+
const contents = await loadFile(filename, { cwd: workspace, searchUp: false });
|
|
2052
|
+
if (contents) {
|
|
2053
|
+
const fileSecrets = parseEnvFile(contents);
|
|
2054
|
+
secrets = { ...secrets, ...fileSecrets };
|
|
2055
|
+
}
|
|
2056
|
+
} catch {
|
|
2057
|
+
continue;
|
|
2058
|
+
}
|
|
2059
|
+
}
|
|
2060
|
+
return secrets;
|
|
2061
|
+
}
|
|
2062
|
+
function getLoadedEnvFiles(workspace) {
|
|
2063
|
+
return ENV_FILES.filter((filename) => existsSync8(join9(workspace, filename)));
|
|
2064
|
+
}
|
|
2065
|
+
function hasEnvFile(workspace) {
|
|
2066
|
+
return ENV_FILES.some((filename) => existsSync8(join9(workspace, filename)));
|
|
2067
|
+
}
|
|
2068
|
+
|
|
2069
|
+
// src/lib/init/types.ts
|
|
2070
|
+
init_loader2();
|
|
2071
|
+
|
|
2072
|
+
// src/lib/init/tsconfig.ts
|
|
2073
|
+
init_file_loader();
|
|
2074
|
+
init_constants2();
|
|
2075
|
+
import { existsSync as existsSync9, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
2076
|
+
import { join as join10 } from "path";
|
|
2077
|
+
function hasPlaycademyEnv(config) {
|
|
2078
|
+
return config.include?.includes("playcademy-env.d.ts") ?? false;
|
|
2079
|
+
}
|
|
2080
|
+
function addPlaycademyEnv(config) {
|
|
2081
|
+
if (!config.include) {
|
|
2082
|
+
config.include = [];
|
|
2083
|
+
}
|
|
2084
|
+
config.include.push("playcademy-env.d.ts");
|
|
2085
|
+
}
|
|
2086
|
+
function updateExistingIncludeArray(content) {
|
|
2087
|
+
const includeRegex = /"include"\s*:\s*\[([^\]]*)\]/;
|
|
2088
|
+
const match = content.match(includeRegex);
|
|
2089
|
+
if (!match || !match[1]) {
|
|
2090
|
+
return null;
|
|
2091
|
+
}
|
|
2092
|
+
const fullMatch = match[0];
|
|
2093
|
+
const arrayContents = match[1];
|
|
2094
|
+
if (arrayContents.includes("playcademy-env.d.ts")) {
|
|
2095
|
+
return content;
|
|
2096
|
+
}
|
|
2097
|
+
const trimmedContents = arrayContents.trim();
|
|
2098
|
+
const newEntry = '"playcademy-env.d.ts"';
|
|
2099
|
+
let newArrayContents;
|
|
2100
|
+
if (trimmedContents === "") {
|
|
2101
|
+
newArrayContents = newEntry;
|
|
2102
|
+
} else if (arrayContents.includes("\n")) {
|
|
2103
|
+
newArrayContents = `${arrayContents},
|
|
2104
|
+
${newEntry}
|
|
2105
|
+
`;
|
|
2106
|
+
} else {
|
|
2107
|
+
newArrayContents = `${trimmedContents}, ${newEntry}`;
|
|
2108
|
+
}
|
|
2109
|
+
const newIncludeArray = `"include": [${newArrayContents}]`;
|
|
2110
|
+
return content.replace(fullMatch, newIncludeArray);
|
|
2111
|
+
}
|
|
2112
|
+
function addNewIncludeProperty(content) {
|
|
2113
|
+
const closingBraceMatch = content.match(/\n(\s*)\}(\s*)$/);
|
|
2114
|
+
if (!closingBraceMatch || closingBraceMatch.index === void 0) {
|
|
2115
|
+
return null;
|
|
2116
|
+
}
|
|
2117
|
+
const propertyMatch = content.match(/\n(\s+)"/);
|
|
2118
|
+
const propertyIndent = propertyMatch ? propertyMatch[1] : " ";
|
|
2119
|
+
const insertPosition = closingBraceMatch.index;
|
|
2120
|
+
const beforeClosing = content.slice(0, insertPosition).trim();
|
|
2121
|
+
const needsComma = beforeClosing.endsWith("]") || beforeClosing.endsWith("}") || beforeClosing.endsWith('"');
|
|
2122
|
+
const comma = needsComma ? "," : "";
|
|
2123
|
+
const includeEntry = `${comma}
|
|
2124
|
+
${propertyIndent}"include": ["playcademy-env.d.ts"]`;
|
|
2125
|
+
const updatedContent = content.slice(0, insertPosition) + includeEntry + content.slice(insertPosition);
|
|
2126
|
+
return updatedContent;
|
|
2127
|
+
}
|
|
2128
|
+
function addToIncludeArrayPreservingComments(content) {
|
|
2129
|
+
return updateExistingIncludeArray(content) || addNewIncludeProperty(content);
|
|
2130
|
+
}
|
|
2131
|
+
async function ensureTsconfigIncludes(workspace) {
|
|
2132
|
+
for (const filename of TSCONFIG_FILES) {
|
|
2133
|
+
const configPath = join10(workspace, filename);
|
|
2134
|
+
if (!existsSync9(configPath)) {
|
|
2135
|
+
continue;
|
|
2136
|
+
}
|
|
2137
|
+
try {
|
|
2138
|
+
const config = await loadFile(configPath, {
|
|
2139
|
+
parseJson: true,
|
|
2140
|
+
stripComments: true
|
|
2141
|
+
});
|
|
2142
|
+
if (!config) continue;
|
|
2143
|
+
if (config.references && filename !== "tsconfig.json") {
|
|
2144
|
+
continue;
|
|
2145
|
+
}
|
|
2146
|
+
if (hasPlaycademyEnv(config)) {
|
|
2147
|
+
return filename;
|
|
2148
|
+
}
|
|
2149
|
+
try {
|
|
2150
|
+
const rawContent = readFileSync4(configPath, "utf-8");
|
|
2151
|
+
const updatedContent = addToIncludeArrayPreservingComments(rawContent);
|
|
2152
|
+
if (updatedContent && updatedContent !== rawContent) {
|
|
2153
|
+
writeFileSync3(configPath, updatedContent);
|
|
2154
|
+
return filename;
|
|
2155
|
+
}
|
|
2156
|
+
} catch {
|
|
2157
|
+
}
|
|
2158
|
+
addPlaycademyEnv(config);
|
|
2159
|
+
writeFileSync3(configPath, JSON.stringify(config, null, 4) + "\n");
|
|
2160
|
+
return filename;
|
|
2161
|
+
} catch {
|
|
2162
|
+
continue;
|
|
2163
|
+
}
|
|
2164
|
+
}
|
|
2165
|
+
return null;
|
|
2166
|
+
}
|
|
2167
|
+
|
|
2168
|
+
// src/lib/init/types.ts
|
|
1551
2169
|
var playcademyEnvTemplate = loadTemplateString("playcademy-env.d.ts");
|
|
1552
|
-
|
|
2170
|
+
function detectBackendFeatures(workspace, config) {
|
|
2171
|
+
return {
|
|
2172
|
+
hasDB: hasDatabaseSetup(),
|
|
2173
|
+
hasKV: hasKVSetup(config),
|
|
2174
|
+
hasBucket: hasBucketSetup(config),
|
|
2175
|
+
hasRoutes: hasLocalCustomRoutes(workspace, config),
|
|
2176
|
+
hasSecrets: hasEnvFile(workspace)
|
|
2177
|
+
};
|
|
2178
|
+
}
|
|
2179
|
+
function hasAnyBackend(features) {
|
|
2180
|
+
return Object.values(features).some(Boolean);
|
|
2181
|
+
}
|
|
2182
|
+
async function setupPlaycademyDependencies(workspace) {
|
|
2183
|
+
const playcademyDir = join11(workspace, CLI_DIRECTORIES.WORKSPACE);
|
|
2184
|
+
const playcademyPkgPath = join11(playcademyDir, "package.json");
|
|
2185
|
+
const __dirname = dirname4(fileURLToPath2(import.meta.url));
|
|
2186
|
+
const cliPkg = await loadPackageJson({ cwd: __dirname, searchUp: true, required: true });
|
|
2187
|
+
const workersTypesVersion = cliPkg?.devDependencies?.["@cloudflare/workers-types"] || "latest";
|
|
2188
|
+
const honoVersion = cliPkg?.dependencies?.hono || "latest";
|
|
2189
|
+
const playcademyPkg = {
|
|
2190
|
+
private: true,
|
|
2191
|
+
dependencies: { hono: honoVersion },
|
|
2192
|
+
devDependencies: { "@cloudflare/workers-types": workersTypesVersion }
|
|
2193
|
+
};
|
|
2194
|
+
writeFileSync4(playcademyPkgPath, JSON.stringify(playcademyPkg, null, 4) + "\n");
|
|
2195
|
+
const pm = detectPackageManager(workspace);
|
|
2196
|
+
const installCmd = getInstallCommand(pm);
|
|
2197
|
+
execSync2(installCmd, {
|
|
2198
|
+
cwd: playcademyDir,
|
|
2199
|
+
stdio: ["ignore", "ignore", "ignore"]
|
|
2200
|
+
});
|
|
2201
|
+
}
|
|
2202
|
+
function generateBindingsTypeString(features) {
|
|
2203
|
+
const bindings = [];
|
|
2204
|
+
if (features.hasKV) bindings.push(" KV: KVNamespace");
|
|
2205
|
+
if (features.hasDB) bindings.push(" DB: D1Database");
|
|
2206
|
+
if (features.hasBucket) bindings.push(" BUCKET: R2Bucket");
|
|
2207
|
+
return bindings.length > 0 ? "\n" + bindings.join("\n") : "";
|
|
2208
|
+
}
|
|
2209
|
+
async function generateSecretsTypeString(workspace, verbose = false) {
|
|
2210
|
+
try {
|
|
2211
|
+
const envSecrets = await readEnvFile(workspace);
|
|
2212
|
+
const secretKeys = Object.keys(envSecrets);
|
|
2213
|
+
if (secretKeys.length === 0) {
|
|
2214
|
+
if (verbose) logger.success("No secrets in <.env> files");
|
|
2215
|
+
return "\n secrets: Record<string, string>";
|
|
2216
|
+
}
|
|
2217
|
+
if (verbose) {
|
|
2218
|
+
const loadedFiles = getLoadedEnvFiles(workspace);
|
|
2219
|
+
const fileList = loadedFiles.map((f) => `<${f}>`).join(", ");
|
|
2220
|
+
logger.success(
|
|
2221
|
+
`Loaded ${secretKeys.length} ${pluralize(secretKeys.length, "secret")} from ${fileList}`
|
|
2222
|
+
);
|
|
2223
|
+
}
|
|
2224
|
+
const secretTypes = secretKeys.map((key) => ` ${key}: string`).join("\n");
|
|
2225
|
+
return `
|
|
2226
|
+
secrets: {
|
|
2227
|
+
${secretTypes}
|
|
2228
|
+
[key: string]: string
|
|
2229
|
+
}`;
|
|
2230
|
+
} catch {
|
|
2231
|
+
return "\n secrets: Record<string, string>";
|
|
2232
|
+
}
|
|
2233
|
+
}
|
|
2234
|
+
async function ensurePlaycademyTypes(options = {}) {
|
|
2235
|
+
const { verbose = false } = options;
|
|
1553
2236
|
try {
|
|
1554
2237
|
const workspace = getWorkspace();
|
|
1555
2238
|
const config = await loadConfig();
|
|
1556
|
-
const
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
2239
|
+
const features = detectBackendFeatures(workspace, config);
|
|
2240
|
+
if (!hasAnyBackend(features)) {
|
|
2241
|
+
if (verbose) {
|
|
2242
|
+
logger.dim("No backend functionality detected");
|
|
2243
|
+
}
|
|
1560
2244
|
return;
|
|
1561
2245
|
}
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
const cliPkg = await loadPackageJson({ cwd: __dirname, searchUp: true, required: true });
|
|
1566
|
-
const workersTypesVersion = cliPkg?.devDependencies?.["@cloudflare/workers-types"] || "latest";
|
|
1567
|
-
const honoVersion = cliPkg?.dependencies?.hono || "latest";
|
|
1568
|
-
const playcademyPkg = {
|
|
1569
|
-
private: true,
|
|
1570
|
-
dependencies: {
|
|
1571
|
-
hono: honoVersion
|
|
1572
|
-
},
|
|
1573
|
-
devDependencies: {
|
|
1574
|
-
"@cloudflare/workers-types": workersTypesVersion
|
|
1575
|
-
}
|
|
1576
|
-
};
|
|
1577
|
-
writeFileSync3(playcademyPkgPath, JSON.stringify(playcademyPkg, null, 4) + "\n");
|
|
1578
|
-
const pm = detectPackageManager(workspace);
|
|
1579
|
-
const installCmd = getInstallCommand(pm);
|
|
1580
|
-
execSync2(installCmd, {
|
|
1581
|
-
cwd: playcademyDir,
|
|
1582
|
-
stdio: ["ignore", "ignore", "ignore"]
|
|
1583
|
-
});
|
|
1584
|
-
const bindings = [];
|
|
1585
|
-
if (hasKV) {
|
|
1586
|
-
bindings.push(" KV: KVNamespace");
|
|
2246
|
+
await setupPlaycademyDependencies(workspace);
|
|
2247
|
+
if (verbose) {
|
|
2248
|
+
logger.success(`Installed packages in <${CLI_DIRECTORIES.WORKSPACE}>`);
|
|
1587
2249
|
}
|
|
1588
|
-
|
|
1589
|
-
|
|
2250
|
+
const bindingsStr = generateBindingsTypeString(features);
|
|
2251
|
+
const secretsStr = await generateSecretsTypeString(workspace, verbose);
|
|
2252
|
+
let envContent = playcademyEnvTemplate.replace("{{BINDINGS}}", bindingsStr);
|
|
2253
|
+
envContent = envContent.replace("{{SECRETS}}", secretsStr);
|
|
2254
|
+
const envPath = join11(workspace, "playcademy-env.d.ts");
|
|
2255
|
+
writeFileSync4(envPath, envContent);
|
|
2256
|
+
if (verbose) {
|
|
2257
|
+
logger.success(`Generated <playcademy-env.d.ts>`);
|
|
1590
2258
|
}
|
|
1591
|
-
|
|
1592
|
-
|
|
2259
|
+
const tsConfigFilename = await ensureTsconfigIncludes(workspace);
|
|
2260
|
+
if (verbose) {
|
|
2261
|
+
logger.success(`Updated <${tsConfigFilename}>`);
|
|
1593
2262
|
}
|
|
1594
|
-
|
|
1595
|
-
const envContent = playcademyEnvTemplate.replace("{{BINDINGS}}", bindingsStr);
|
|
1596
|
-
const envPath = join8(workspace, "playcademy-env.d.ts");
|
|
1597
|
-
writeFileSync3(envPath, envContent);
|
|
2263
|
+
logger.newLine();
|
|
1598
2264
|
} catch (error) {
|
|
1599
2265
|
logger.warn(
|
|
1600
2266
|
`Failed to generate TypeScript types: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -1603,6 +2269,8 @@ async function ensurePlaycademyTypes() {
|
|
|
1603
2269
|
}
|
|
1604
2270
|
|
|
1605
2271
|
// src/lib/init/gitignore.ts
|
|
2272
|
+
init_core();
|
|
2273
|
+
init_loader2();
|
|
1606
2274
|
var rootGitignoreTemplate = loadTemplateString("gitignore");
|
|
1607
2275
|
|
|
1608
2276
|
// src/lib/dev/server.ts
|
|
@@ -1629,9 +2297,19 @@ async function startDevServer(options) {
|
|
|
1629
2297
|
const kvDir = hasKV ? await ensureKvDirectory() : void 0;
|
|
1630
2298
|
const hasBucket = hasBucketSetup(config);
|
|
1631
2299
|
const bucketDir = hasBucket ? await ensureBucketDirectory() : void 0;
|
|
2300
|
+
const workspace = getWorkspace();
|
|
2301
|
+
const envSecrets = await readEnvFile(workspace);
|
|
1632
2302
|
const log2 = logger2 ? new FilteredLog(LogLevel.INFO) : new Log(LogLevel.NONE);
|
|
1633
|
-
const sandboxInfo = readServerInfo("sandbox",
|
|
2303
|
+
const sandboxInfo = readServerInfo("sandbox", workspace);
|
|
1634
2304
|
const baseUrl = platformUrl ?? sandboxInfo?.url ?? process.env.PLAYCADEMY_BASE_URL ?? `http://localhost:${DEFAULT_PORTS.SANDBOX}`;
|
|
2305
|
+
const bindings = {
|
|
2306
|
+
PLAYCADEMY_API_KEY: process.env.PLAYCADEMY_API_KEY || "dev-api-key",
|
|
2307
|
+
GAME_ID: CORE_GAME_UUIDS.PLAYGROUND,
|
|
2308
|
+
PLAYCADEMY_BASE_URL: baseUrl
|
|
2309
|
+
};
|
|
2310
|
+
for (const [key, value] of Object.entries(envSecrets)) {
|
|
2311
|
+
bindings[`secrets_${key}`] = value;
|
|
2312
|
+
}
|
|
1635
2313
|
const mf = new Miniflare({
|
|
1636
2314
|
port,
|
|
1637
2315
|
log: log2,
|
|
@@ -1642,11 +2320,7 @@ async function startDevServer(options) {
|
|
|
1642
2320
|
contents: bundle.code
|
|
1643
2321
|
}
|
|
1644
2322
|
],
|
|
1645
|
-
bindings
|
|
1646
|
-
PLAYCADEMY_API_KEY: process.env.PLAYCADEMY_API_KEY || "dev-api-key",
|
|
1647
|
-
GAME_ID: CORE_GAME_UUIDS.PLAYGROUND,
|
|
1648
|
-
PLAYCADEMY_BASE_URL: baseUrl
|
|
1649
|
-
},
|
|
2323
|
+
bindings,
|
|
1650
2324
|
d1Databases: hasDatabase ? ["DB"] : [],
|
|
1651
2325
|
d1Persist: dbDir,
|
|
1652
2326
|
kvNamespaces: hasKV ? ["KV"] : [],
|
|
@@ -1662,7 +2336,7 @@ async function startDevServer(options) {
|
|
|
1662
2336
|
return { server: mf, port };
|
|
1663
2337
|
}
|
|
1664
2338
|
async function ensureDatabaseDirectory() {
|
|
1665
|
-
const dbDir =
|
|
2339
|
+
const dbDir = join12(getWorkspace(), CLI_DIRECTORIES.DATABASE);
|
|
1666
2340
|
try {
|
|
1667
2341
|
await mkdir2(dbDir, { recursive: true });
|
|
1668
2342
|
} catch (error) {
|
|
@@ -1671,7 +2345,7 @@ async function ensureDatabaseDirectory() {
|
|
|
1671
2345
|
return dbDir;
|
|
1672
2346
|
}
|
|
1673
2347
|
async function ensureKvDirectory() {
|
|
1674
|
-
const kvDir =
|
|
2348
|
+
const kvDir = join12(getWorkspace(), CLI_DIRECTORIES.KV);
|
|
1675
2349
|
try {
|
|
1676
2350
|
await mkdir2(kvDir, { recursive: true });
|
|
1677
2351
|
} catch (error) {
|
|
@@ -1680,7 +2354,7 @@ async function ensureKvDirectory() {
|
|
|
1680
2354
|
return kvDir;
|
|
1681
2355
|
}
|
|
1682
2356
|
async function ensureBucketDirectory() {
|
|
1683
|
-
const bucketDir =
|
|
2357
|
+
const bucketDir = join12(getWorkspace(), CLI_DIRECTORIES.BUCKET);
|
|
1684
2358
|
try {
|
|
1685
2359
|
await mkdir2(bucketDir, { recursive: true });
|
|
1686
2360
|
} catch (error) {
|
|
@@ -1703,7 +2377,9 @@ async function writeBackendServerInfo(port) {
|
|
|
1703
2377
|
}
|
|
1704
2378
|
|
|
1705
2379
|
// src/lib/dev/reload.ts
|
|
1706
|
-
|
|
2380
|
+
init_constants2();
|
|
2381
|
+
init_core();
|
|
2382
|
+
import { join as join13, relative as relative2 } from "path";
|
|
1707
2383
|
import chokidar from "chokidar";
|
|
1708
2384
|
import { bold as bold4, cyan as cyan3, dim as dim3, green as green2 } from "colorette";
|
|
1709
2385
|
function formatTime() {
|
|
@@ -1720,9 +2396,9 @@ function startHotReload(onReload, options = {}) {
|
|
|
1720
2396
|
const customRoutesConfig = options.config?.integrations?.customRoutes;
|
|
1721
2397
|
const customRoutesDir = typeof customRoutesConfig === "object" && customRoutesConfig.directory || DEFAULT_API_ROUTES_DIRECTORY;
|
|
1722
2398
|
const watchPaths = [
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
2399
|
+
join13(workspace, customRoutesDir),
|
|
2400
|
+
join13(workspace, "playcademy.config.js"),
|
|
2401
|
+
join13(workspace, "playcademy.config.json")
|
|
1726
2402
|
];
|
|
1727
2403
|
const watcher = chokidar.watch(watchPaths, {
|
|
1728
2404
|
persistent: true,
|
|
@@ -1760,6 +2436,9 @@ function startHotReload(onReload, options = {}) {
|
|
|
1760
2436
|
watcher.on("unlink", createReloadHandler("removed"));
|
|
1761
2437
|
return watcher;
|
|
1762
2438
|
}
|
|
2439
|
+
|
|
2440
|
+
// src/utils.ts
|
|
2441
|
+
init_import();
|
|
1763
2442
|
export {
|
|
1764
2443
|
findConfigPath as findPlaycademyConfigPath,
|
|
1765
2444
|
importTypescriptDefault,
|