playcademy 0.14.26 → 0.14.28

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/db.js CHANGED
@@ -2049,6 +2049,7 @@ import {
2049
2049
  green,
2050
2050
  greenBright,
2051
2051
  red,
2052
+ underline,
2052
2053
  yellow,
2053
2054
  yellowBright
2054
2055
  } from "colorette";
@@ -2750,6 +2751,7 @@ function formatError(error, indent = 0) {
2750
2751
  function customTransform(text) {
2751
2752
  let result = text;
2752
2753
  result = result.replace(/`([^`]+)`/g, (_, code) => greenBright(code));
2754
+ result = result.replace(/<<([^>]+)>>/g, (_, url) => underline(url));
2753
2755
  result = result.replace(/<([^>]+)>/g, (_, path) => blueBright(path));
2754
2756
  return result;
2755
2757
  }
package/dist/index.js CHANGED
@@ -47,8 +47,8 @@ function getPackageVersionFromData(pkg, fallback = "0.0.0") {
47
47
  }
48
48
  function getPackageNameVersionFromData(pkg) {
49
49
  const name = getPackageNameFromData(pkg);
50
- const version2 = getPackageVersionFromData(pkg);
51
- return `${name}@${version2}`;
50
+ const version3 = getPackageVersionFromData(pkg);
51
+ return `${name}@${version3}`;
52
52
  }
53
53
  function hasDependencyInData(pkg, packageName) {
54
54
  if (!pkg) return false;
@@ -324,123 +324,6 @@ var init_file_loader = __esm({
324
324
  }
325
325
  });
326
326
 
327
- // ../constants/src/auth.ts
328
- var init_auth = __esm({
329
- "../constants/src/auth.ts"() {
330
- "use strict";
331
- }
332
- });
333
-
334
- // ../constants/src/domains.ts
335
- var PLAYCADEMY_BASE_URLS, GAME_WORKER_DOMAINS;
336
- var init_domains = __esm({
337
- "../constants/src/domains.ts"() {
338
- "use strict";
339
- PLAYCADEMY_BASE_URLS = {
340
- production: "https://hub.playcademy.net",
341
- staging: "https://hub.dev.playcademy.net"
342
- };
343
- GAME_WORKER_DOMAINS = {
344
- production: "playcademy.gg",
345
- staging: "staging.playcademy.gg"
346
- };
347
- }
348
- });
349
-
350
- // ../constants/src/env-vars.ts
351
- var init_env_vars = __esm({
352
- "../constants/src/env-vars.ts"() {
353
- "use strict";
354
- }
355
- });
356
-
357
- // ../constants/src/overworld.ts
358
- var ITEM_SLUGS, CURRENCIES, BADGES, CORE_GAME_UUIDS;
359
- var init_overworld = __esm({
360
- "../constants/src/overworld.ts"() {
361
- "use strict";
362
- ITEM_SLUGS = {
363
- /** Primary platform currency */
364
- PLAYCADEMY_CREDITS: "PLAYCADEMY_CREDITS",
365
- /** Experience points currency */
366
- PLAYCADEMY_XP: "PLAYCADEMY_XP",
367
- /** Core platform badges */
368
- FOUNDING_MEMBER_BADGE: "FOUNDING_MEMBER_BADGE",
369
- EARLY_ADOPTER_BADGE: "EARLY_ADOPTER_BADGE",
370
- FIRST_GAME_BADGE: "FIRST_GAME_BADGE",
371
- /** Example items */
372
- COMMON_SWORD: "COMMON_SWORD",
373
- SMALL_HEALTH_POTION: "SMALL_HEALTH_POTION",
374
- SMALL_BACKPACK: "SMALL_BACKPACK",
375
- /** Placeable items */
376
- LAVA_LAMP: "LAVA_LAMP",
377
- BOOMBOX: "BOOMBOX",
378
- CABIN_BED: "CABIN_BED"
379
- };
380
- CURRENCIES = {
381
- /** Primary platform currency slug */
382
- PRIMARY: ITEM_SLUGS.PLAYCADEMY_CREDITS,
383
- /** Experience points slug */
384
- XP: ITEM_SLUGS.PLAYCADEMY_XP
385
- };
386
- BADGES = {
387
- FOUNDING_MEMBER: ITEM_SLUGS.FOUNDING_MEMBER_BADGE,
388
- EARLY_ADOPTER: ITEM_SLUGS.EARLY_ADOPTER_BADGE,
389
- FIRST_GAME: ITEM_SLUGS.FIRST_GAME_BADGE
390
- };
391
- CORE_GAME_UUIDS = {
392
- /** Internal playground game for development and testing */
393
- PLAYGROUND: "00000000-0000-0000-0000-000000000001"
394
- };
395
- }
396
- });
397
-
398
- // ../constants/src/system.ts
399
- var init_system = __esm({
400
- "../constants/src/system.ts"() {
401
- "use strict";
402
- }
403
- });
404
-
405
- // ../constants/src/timeback.ts
406
- var TIMEBACK_ROUTES;
407
- var init_timeback = __esm({
408
- "../constants/src/timeback.ts"() {
409
- "use strict";
410
- TIMEBACK_ROUTES = {
411
- END_ACTIVITY: "/integrations/timeback/end-activity"
412
- };
413
- }
414
- });
415
-
416
- // ../constants/src/workers.ts
417
- var WORKER_NAMING;
418
- var init_workers = __esm({
419
- "../constants/src/workers.ts"() {
420
- "use strict";
421
- WORKER_NAMING = {
422
- /** Prefix for staging worker names (e.g., "staging-bamboo") */
423
- STAGING_PREFIX: "staging-",
424
- /** Suffix for staging worker hostnames (e.g., "bamboo-staging.playcademy.gg") */
425
- STAGING_SUFFIX: "-staging"
426
- };
427
- }
428
- });
429
-
430
- // ../constants/src/index.ts
431
- var init_src = __esm({
432
- "../constants/src/index.ts"() {
433
- "use strict";
434
- init_auth();
435
- init_domains();
436
- init_env_vars();
437
- init_overworld();
438
- init_system();
439
- init_timeback();
440
- init_workers();
441
- }
442
- });
443
-
444
327
  // ../../node_modules/cli-width/index.js
445
328
  var require_cli_width = __commonJS({
446
329
  "../../node_modules/cli-width/index.js"(exports, module) {
@@ -1821,25 +1704,6 @@ var require_wrap_ansi = __commonJS({
1821
1704
  }
1822
1705
  });
1823
1706
 
1824
- // ../edge-play/src/constants.ts
1825
- var ROUTES;
1826
- var init_constants3 = __esm({
1827
- "../edge-play/src/constants.ts"() {
1828
- "use strict";
1829
- init_src();
1830
- ROUTES = {
1831
- /** Route index (lists available routes) */
1832
- INDEX: "/api",
1833
- /** Health check endpoint */
1834
- HEALTH: "/api/health",
1835
- /** TimeBack integration routes */
1836
- TIMEBACK: {
1837
- END_ACTIVITY: `/api${TIMEBACK_ROUTES.END_ACTIVITY}`
1838
- }
1839
- };
1840
- }
1841
- });
1842
-
1843
1707
  // src/index.ts
1844
1708
  init_file_loader();
1845
1709
  import { dirname as dirname5 } from "node:path";
@@ -2475,8 +2339,58 @@ var CONFIG_FILE_NAMES = [
2475
2339
  "playcademy.config.mjs"
2476
2340
  ];
2477
2341
 
2478
- // src/constants/urls.ts
2479
- init_src();
2342
+ // ../constants/src/domains.ts
2343
+ var PLAYCADEMY_BASE_URLS = {
2344
+ production: "https://hub.playcademy.net",
2345
+ staging: "https://hub.dev.playcademy.net"
2346
+ };
2347
+ var GAME_WORKER_DOMAINS = {
2348
+ production: "playcademy.gg",
2349
+ staging: "staging.playcademy.gg"
2350
+ };
2351
+
2352
+ // ../constants/src/overworld.ts
2353
+ var ITEM_SLUGS = {
2354
+ /** Primary platform currency */
2355
+ PLAYCADEMY_CREDITS: "PLAYCADEMY_CREDITS",
2356
+ /** Experience points currency */
2357
+ PLAYCADEMY_XP: "PLAYCADEMY_XP",
2358
+ /** Core platform badges */
2359
+ FOUNDING_MEMBER_BADGE: "FOUNDING_MEMBER_BADGE",
2360
+ EARLY_ADOPTER_BADGE: "EARLY_ADOPTER_BADGE",
2361
+ FIRST_GAME_BADGE: "FIRST_GAME_BADGE",
2362
+ /** Example items */
2363
+ COMMON_SWORD: "COMMON_SWORD",
2364
+ SMALL_HEALTH_POTION: "SMALL_HEALTH_POTION",
2365
+ SMALL_BACKPACK: "SMALL_BACKPACK",
2366
+ /** Placeable items */
2367
+ LAVA_LAMP: "LAVA_LAMP",
2368
+ BOOMBOX: "BOOMBOX",
2369
+ CABIN_BED: "CABIN_BED"
2370
+ };
2371
+ var CURRENCIES = {
2372
+ /** Primary platform currency slug */
2373
+ PRIMARY: ITEM_SLUGS.PLAYCADEMY_CREDITS,
2374
+ /** Experience points slug */
2375
+ XP: ITEM_SLUGS.PLAYCADEMY_XP
2376
+ };
2377
+ var BADGES = {
2378
+ FOUNDING_MEMBER: ITEM_SLUGS.FOUNDING_MEMBER_BADGE,
2379
+ EARLY_ADOPTER: ITEM_SLUGS.EARLY_ADOPTER_BADGE,
2380
+ FIRST_GAME: ITEM_SLUGS.FIRST_GAME_BADGE
2381
+ };
2382
+ var CORE_GAME_UUIDS = {
2383
+ /** Internal playground game for development and testing */
2384
+ PLAYGROUND: "00000000-0000-0000-0000-000000000001"
2385
+ };
2386
+
2387
+ // ../constants/src/workers.ts
2388
+ var WORKER_NAMING = {
2389
+ /** Prefix for staging worker names (e.g., "staging-bamboo") */
2390
+ STAGING_PREFIX: "staging-",
2391
+ /** Suffix for staging worker hostnames (e.g., "bamboo-staging.playcademy.gg") */
2392
+ STAGING_SUFFIX: "-staging"
2393
+ };
2480
2394
 
2481
2395
  // src/lib/core/client.ts
2482
2396
  import { PlaycademyClient } from "@playcademy/sdk/internal";
@@ -2522,6 +2436,7 @@ import {
2522
2436
  green,
2523
2437
  greenBright,
2524
2438
  red,
2439
+ underline,
2525
2440
  yellow,
2526
2441
  yellowBright
2527
2442
  } from "colorette";
@@ -3254,6 +3169,7 @@ function setupGlobalErrorHandlers() {
3254
3169
  function customTransform(text5) {
3255
3170
  let result = text5;
3256
3171
  result = result.replace(/`([^`]+)`/g, (_, code) => greenBright(code));
3172
+ result = result.replace(/<<([^>]+)>>/g, (_, url) => underline(url));
3257
3173
  result = result.replace(/<([^>]+)>/g, (_, path4) => blueBright(path4));
3258
3174
  return result;
3259
3175
  }
@@ -3937,7 +3853,9 @@ async function requireConfigFile() {
3937
3853
  logger.error("No <playcademy.config.{js,json}> file found");
3938
3854
  logger.newLine();
3939
3855
  logger.admonition("note", "Getting Started", [
3940
- "Run `playcademy init` to create a config file first"
3856
+ "Run `playcademy init` to create a config file first",
3857
+ "",
3858
+ "Learn more: <<https://docs.playcademy.net/platform/quickstart>>"
3941
3859
  ]);
3942
3860
  logger.newLine();
3943
3861
  process.exit(1);
@@ -4154,21 +4072,21 @@ function processConfigVariables(config) {
4154
4072
 
4155
4073
  // ../timeback/dist/constants.js
4156
4074
  var __esm2 = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
4157
- var init_auth2 = () => {
4075
+ var init_auth = () => {
4158
4076
  };
4159
4077
  var PLAYCADEMY_BASE_URLS2;
4160
- var init_domains2 = __esm2(() => {
4078
+ var init_domains = __esm2(() => {
4161
4079
  PLAYCADEMY_BASE_URLS2 = {
4162
4080
  production: "https://hub.playcademy.net",
4163
4081
  staging: "https://hub.dev.playcademy.net"
4164
4082
  };
4165
4083
  });
4166
- var init_env_vars2 = () => {
4084
+ var init_env_vars = () => {
4167
4085
  };
4168
4086
  var ITEM_SLUGS2;
4169
4087
  var CURRENCIES2;
4170
4088
  var BADGES2;
4171
- var init_overworld2 = __esm2(() => {
4089
+ var init_overworld = __esm2(() => {
4172
4090
  ITEM_SLUGS2 = {
4173
4091
  PLAYCADEMY_CREDITS: "PLAYCADEMY_CREDITS",
4174
4092
  PLAYCADEMY_XP: "PLAYCADEMY_XP",
@@ -4199,7 +4117,7 @@ var TIMEBACK_COURSE_DEFAULTS;
4199
4117
  var TIMEBACK_RESOURCE_DEFAULTS;
4200
4118
  var TIMEBACK_COMPONENT_DEFAULTS;
4201
4119
  var TIMEBACK_COMPONENT_RESOURCE_DEFAULTS;
4202
- var init_timeback2 = __esm2(() => {
4120
+ var init_timeback = __esm2(() => {
4203
4121
  TIMEBACK_COURSE_DEFAULTS = {
4204
4122
  gradingScheme: "STANDARD",
4205
4123
  level: {
@@ -4237,15 +4155,15 @@ var init_timeback2 = __esm2(() => {
4237
4155
  lessonType: "quiz"
4238
4156
  };
4239
4157
  });
4240
- var init_workers2 = () => {
4158
+ var init_workers = () => {
4241
4159
  };
4242
- var init_src2 = __esm2(() => {
4243
- init_auth2();
4244
- init_domains2();
4245
- init_env_vars2();
4246
- init_overworld2();
4247
- init_timeback2();
4248
- init_workers2();
4160
+ var init_src = __esm2(() => {
4161
+ init_auth();
4162
+ init_domains();
4163
+ init_env_vars();
4164
+ init_overworld();
4165
+ init_timeback();
4166
+ init_workers();
4249
4167
  });
4250
4168
  var TIMEBACK_API_URLS;
4251
4169
  var TIMEBACK_AUTH_URLS;
@@ -4274,7 +4192,7 @@ var RESOURCE_DEFAULTS;
4274
4192
  var HTTP_STATUS;
4275
4193
  var ERROR_NAMES;
4276
4194
  var init_constants = __esm2(() => {
4277
- init_src2();
4195
+ init_src();
4278
4196
  TIMEBACK_API_URLS = {
4279
4197
  production: "https://api.alpha-1edtech.ai",
4280
4198
  staging: "https://api.staging.alpha-1edtech.com"
@@ -4452,21 +4370,21 @@ init_constants();
4452
4370
 
4453
4371
  // ../timeback/dist/types.js
4454
4372
  var __esm3 = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
4455
- var init_auth3 = () => {
4373
+ var init_auth2 = () => {
4456
4374
  };
4457
4375
  var PLAYCADEMY_BASE_URLS3;
4458
- var init_domains3 = __esm3(() => {
4376
+ var init_domains2 = __esm3(() => {
4459
4377
  PLAYCADEMY_BASE_URLS3 = {
4460
4378
  production: "https://hub.playcademy.net",
4461
4379
  staging: "https://hub.dev.playcademy.net"
4462
4380
  };
4463
4381
  });
4464
- var init_env_vars3 = () => {
4382
+ var init_env_vars2 = () => {
4465
4383
  };
4466
4384
  var ITEM_SLUGS3;
4467
4385
  var CURRENCIES3;
4468
4386
  var BADGES3;
4469
- var init_overworld3 = __esm3(() => {
4387
+ var init_overworld2 = __esm3(() => {
4470
4388
  ITEM_SLUGS3 = {
4471
4389
  PLAYCADEMY_CREDITS: "PLAYCADEMY_CREDITS",
4472
4390
  PLAYCADEMY_XP: "PLAYCADEMY_XP",
@@ -4497,7 +4415,7 @@ var TIMEBACK_COURSE_DEFAULTS2;
4497
4415
  var TIMEBACK_RESOURCE_DEFAULTS2;
4498
4416
  var TIMEBACK_COMPONENT_DEFAULTS2;
4499
4417
  var TIMEBACK_COMPONENT_RESOURCE_DEFAULTS2;
4500
- var init_timeback3 = __esm3(() => {
4418
+ var init_timeback2 = __esm3(() => {
4501
4419
  TIMEBACK_COURSE_DEFAULTS2 = {
4502
4420
  gradingScheme: "STANDARD",
4503
4421
  level: {
@@ -4535,15 +4453,15 @@ var init_timeback3 = __esm3(() => {
4535
4453
  lessonType: "quiz"
4536
4454
  };
4537
4455
  });
4538
- var init_workers3 = () => {
4456
+ var init_workers2 = () => {
4539
4457
  };
4540
- var init_src3 = __esm3(() => {
4541
- init_auth3();
4542
- init_domains3();
4543
- init_env_vars3();
4544
- init_overworld3();
4545
- init_timeback3();
4546
- init_workers3();
4458
+ var init_src2 = __esm3(() => {
4459
+ init_auth2();
4460
+ init_domains2();
4461
+ init_env_vars2();
4462
+ init_overworld2();
4463
+ init_timeback2();
4464
+ init_workers2();
4547
4465
  });
4548
4466
  var TIMEBACK_API_URLS2;
4549
4467
  var TIMEBACK_AUTH_URLS2;
@@ -4572,7 +4490,7 @@ var RESOURCE_DEFAULTS2;
4572
4490
  var HTTP_STATUS2;
4573
4491
  var ERROR_NAMES2;
4574
4492
  var init_constants2 = __esm3(() => {
4575
- init_src3();
4493
+ init_src2();
4576
4494
  TIMEBACK_API_URLS2 = {
4577
4495
  production: "https://api.alpha-1edtech.ai",
4578
4496
  staging: "https://api.staging.alpha-1edtech.com"
@@ -5602,10 +5520,10 @@ function hasAuthSetup() {
5602
5520
  import { existsSync as existsSync8, mkdirSync as mkdirSync2, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
5603
5521
  import { join as join12 } from "path";
5604
5522
 
5605
- // package.json
5523
+ // package.json with { type: 'json' }
5606
5524
  var package_default2 = {
5607
5525
  name: "playcademy",
5608
- version: "0.14.25",
5526
+ version: "0.14.27",
5609
5527
  type: "module",
5610
5528
  exports: {
5611
5529
  ".": {
@@ -6070,7 +5988,9 @@ function displayConfigSuccess(timebackConfig) {
6070
5988
  logger.admonition("tip", "Next Steps", [
6071
5989
  "1. Review and customize your config file",
6072
5990
  "2. Build your project",
6073
- "3. Run `playcademy deploy` to deploy"
5991
+ "3. Run `playcademy deploy` to deploy",
5992
+ "",
5993
+ "Learn more: <<https://docs.playcademy.net/platform/quickstart>>"
6074
5994
  ]);
6075
5995
  logger.newLine();
6076
5996
  if (timebackConfig) {
@@ -6081,7 +6001,7 @@ function displayConfigSuccess(timebackConfig) {
6081
6001
  " \u2192 Run `playcademy timeback setup`",
6082
6002
  " \u2192 Then verify with `playcademy timeback verify`",
6083
6003
  "",
6084
- "This will create the necessary TimeBack resources."
6004
+ "Learn more: <<https://docs.playcademy.net/timeback>>"
6085
6005
  ]);
6086
6006
  logger.newLine();
6087
6007
  }
@@ -6114,6 +6034,8 @@ function displaySuccessMessage(context2) {
6114
6034
  }
6115
6035
  const deployStep = nextSteps.length + 1;
6116
6036
  nextSteps.push(`${deployStep}. Deploy: \`playcademy deploy\``);
6037
+ nextSteps.push("");
6038
+ nextSteps.push("Learn more: <<https://docs.playcademy.net/platform/quickstart>>");
6117
6039
  logger.admonition("tip", "Next Steps", nextSteps);
6118
6040
  logger.newLine();
6119
6041
  }
@@ -6781,95 +6703,28 @@ function needsBackend(config) {
6781
6703
  }
6782
6704
 
6783
6705
  // src/lib/dev/display.ts
6784
- import { dim as dim4 } from "colorette";
6785
-
6786
- // ../edge-play/src/index.ts
6787
- init_constants3();
6788
-
6789
- // ../edge-play/src/register-routes.ts
6790
- init_constants3();
6791
-
6792
- // src/lib/dev/route-sorting.ts
6793
- function getSegmentType(segment) {
6794
- if (segment.startsWith(":") && segment.includes("{.*}")) {
6795
- return 2 /* CatchAll */;
6796
- }
6797
- if (segment.startsWith(":")) {
6798
- return 1 /* Dynamic */;
6799
- }
6800
- return 0 /* Static */;
6801
- }
6802
- function compareSegments(a, b) {
6803
- const typeA = getSegmentType(a);
6804
- const typeB = getSegmentType(b);
6805
- if (typeA !== typeB) {
6806
- if (typeA === 1 /* Dynamic */ && typeB === 0 /* Static */) {
6807
- return -1;
6808
- }
6809
- if (typeA === 0 /* Static */ && typeB === 1 /* Dynamic */) {
6810
- return 1;
6811
- }
6812
- if (typeA === 2 /* CatchAll */ && typeB === 0 /* Static */) {
6813
- return -1;
6814
- }
6815
- if (typeA === 0 /* Static */ && typeB === 2 /* CatchAll */) {
6816
- return 1;
6817
- }
6818
- return typeA - typeB;
6706
+ import { bold as bold5, cyan as cyan3, dim as dim4, green as green2 } from "colorette";
6707
+ function printDevBanner(options) {
6708
+ const { version: version3, port, startupTimeMs, quiet } = options;
6709
+ logger.newLine();
6710
+ logger.raw(
6711
+ ` ${green2(bold5("PLAYCADEMY BACKEND"))} ${green2(`v${version3}`)} ${dim4("ready in")} ${bold5(startupTimeMs.toString())} ms`
6712
+ );
6713
+ logger.newLine();
6714
+ logger.raw(
6715
+ ` ${green2("\u279C")} ${bold5("Local:")} ${cyan3(`http://localhost:${bold5(port.toString())}/api`)}`
6716
+ );
6717
+ logger.newLine();
6718
+ if (!quiet) {
6719
+ logger.raw(` ${dim4("Press")} ${bold5("Ctrl+C")} ${dim4("to stop the server")}`);
6720
+ logger.newLine();
6819
6721
  }
6820
- return a.localeCompare(b);
6821
- }
6822
- function sortRoutes(routes) {
6823
- return [...routes].sort((a, b) => {
6824
- const segmentsA = a.path.split("/").filter(Boolean);
6825
- const segmentsB = b.path.split("/").filter(Boolean);
6826
- const maxLength = Math.max(segmentsA.length, segmentsB.length);
6827
- for (let i = 0; i < maxLength; i++) {
6828
- const segA = segmentsA[i];
6829
- const segB = segmentsB[i];
6830
- if (segA === void 0) return -1;
6831
- if (segB === void 0) return 1;
6832
- const comparison = compareSegments(segA, segB);
6833
- if (comparison !== 0) {
6834
- return comparison;
6835
- }
6836
- }
6837
- return 0;
6838
- });
6839
- }
6840
-
6841
- // src/lib/dev/display.ts
6842
- function displayRegisteredRoutes(integrations, customRoutes = []) {
6843
- const healthRoutes = [
6844
- { path: ROUTES.HEALTH, method: "GET" }
6845
- ];
6846
- const timebackRoutes = [];
6847
- if (integrations?.timeback) {
6848
- const hasSandboxCreds = !!process.env.TIMEBACK_API_CLIENT_ID;
6849
- const method = hasSandboxCreds ? "POST" : "POST (not configured)";
6850
- timebackRoutes.push({ path: ROUTES.TIMEBACK.END_ACTIVITY, method });
6851
- }
6852
- const customRoutesList = customRoutes.map((route) => {
6853
- const methods = route.methods?.join(", ") || "*";
6854
- const isCatchAll = /{\.\*}/.test(route.path);
6855
- return {
6856
- path: route.path,
6857
- method: isCatchAll ? `${methods} (catch-all)` : methods
6858
- };
6859
- });
6860
- const allRoutes = [...healthRoutes, ...timebackRoutes, ...customRoutesList];
6861
- const sortedRoutes = sortRoutes(allRoutes);
6862
- const maxPathLength = Math.max(...sortedRoutes.map((r) => r.path.length));
6863
- sortedRoutes.forEach((route) => {
6864
- const paddedPath = route.path.padEnd(maxPathLength + 2, " ");
6865
- logger.customRaw(`<${paddedPath}> ${dim4(route.method)}`, 1);
6866
- });
6867
6722
  }
6868
6723
 
6869
6724
  // src/lib/dev/reload.ts
6870
6725
  import { join as join20, relative } from "path";
6871
6726
  import chokidar from "chokidar";
6872
- import { bold as bold5, cyan as cyan3, dim as dim5, green as green2 } from "colorette";
6727
+ import { bold as bold6, cyan as cyan4, dim as dim5, green as green3 } from "colorette";
6873
6728
  function formatTime() {
6874
6729
  const now = /* @__PURE__ */ new Date();
6875
6730
  let hours = now.getHours();
@@ -6900,8 +6755,8 @@ function startHotReload(onReload, options = {}) {
6900
6755
  if (changedPath) {
6901
6756
  const relativePath = relative(workspace, changedPath);
6902
6757
  const timestamp5 = dim5(formatTime());
6903
- const brand = bold5(cyan3("[playcademy]"));
6904
- const event = eventType === "changed" ? green2("reload") : green2(eventType || "reload");
6758
+ const brand = bold6(cyan4("[playcademy]"));
6759
+ const event = eventType === "changed" ? green3("reload") : green3(eventType || "reload");
6905
6760
  console.log(`${timestamp5} ${brand} ${event} ${dim5(relativePath)}`);
6906
6761
  } else {
6907
6762
  logger.success("Reloaded");
@@ -7028,7 +6883,6 @@ async function registerCustomRoutes(app, routes) {
7028
6883
  }
7029
6884
 
7030
6885
  // src/lib/dev/server.ts
7031
- init_src();
7032
6886
  import { mkdir as mkdir4 } from "fs/promises";
7033
6887
  import { join as join24 } from "path";
7034
6888
  import { Log, LogLevel, Miniflare } from "miniflare";
@@ -7632,7 +7486,7 @@ var FilteredLog = class extends Log {
7632
7486
  };
7633
7487
  async function startDevServer(options) {
7634
7488
  const { port, config: _config, platformUrl, logger: logger2 = true, customLogger } = options;
7635
- await waitForPort(port);
7489
+ await waitForPort(port, 1e3);
7636
7490
  const config = _config ?? await loadConfig();
7637
7491
  await ensurePlaycademyTypes();
7638
7492
  const hasSandboxTimebackCreds = !!process.env.TIMEBACK_API_CLIENT_ID;
@@ -7788,7 +7642,7 @@ async function loadDeployConfig(configPath) {
7788
7642
  }
7789
7643
 
7790
7644
  // src/lib/deploy/diff.ts
7791
- import { dim as dim6, green as green3, red as red2 } from "colorette";
7645
+ import { dim as dim6, green as green4, red as red2 } from "colorette";
7792
7646
  function calculateConfigDiff(existingGame, newConfig) {
7793
7647
  const diff = {};
7794
7648
  if (newConfig.displayName && existingGame.displayName !== newConfig.displayName) {
@@ -7865,19 +7719,19 @@ function displayDeploymentDiff(options) {
7865
7719
  if (hasConfigChanges) {
7866
7720
  logger.bold("Config", 1);
7867
7721
  if (diff.displayName) {
7868
- const value = `${red2(diff.displayName.old)} \u2192 ${green3(diff.displayName.new)}`;
7722
+ const value = `${red2(diff.displayName.old)} \u2192 ${green4(diff.displayName.new)}`;
7869
7723
  logger.data("Name", value, 2);
7870
7724
  }
7871
7725
  if (diff.emoji) {
7872
7726
  const oldEmoji = diff.emoji.old || "(none)";
7873
7727
  const newEmoji = diff.emoji.new || "(none)";
7874
- const value = `${red2(oldEmoji)} \u2192 ${green3(newEmoji)}`;
7728
+ const value = `${red2(oldEmoji)} \u2192 ${green4(newEmoji)}`;
7875
7729
  logger.data("Emoji", value, 2);
7876
7730
  }
7877
7731
  if (diff.description) {
7878
7732
  const oldDesc = diff.description.old || "(none)";
7879
7733
  const newDesc = diff.description.new || "(none)";
7880
- const value = `${red2(oldDesc)} \u2192 ${green3(newDesc)}`;
7734
+ const value = `${red2(oldDesc)} \u2192 ${green4(newDesc)}`;
7881
7735
  logger.data("Description", value, 2);
7882
7736
  }
7883
7737
  logger.newLine();
@@ -7889,9 +7743,9 @@ function displayDeploymentDiff(options) {
7889
7743
  if (previousSize !== void 0 && currentSize !== void 0) {
7890
7744
  logger.sizeChange("Build", previousSize, currentSize, formatSize, formatDelta, 2);
7891
7745
  } else if (currentSize !== void 0) {
7892
- logger.data("Build", green3(formatSize(currentSize)), 2);
7746
+ logger.data("Build", green4(formatSize(currentSize)), 2);
7893
7747
  } else {
7894
- logger.data("Build", green3("Updated"), 2);
7748
+ logger.data("Build", green4("Updated"), 2);
7895
7749
  }
7896
7750
  logger.newLine();
7897
7751
  }
@@ -7908,7 +7762,7 @@ function displayDeploymentDiff(options) {
7908
7762
  if (hasRouteChanges) {
7909
7763
  const parts = [];
7910
7764
  if (backend?.addedRoutes && backend.addedRoutes.length > 0) {
7911
- parts.push(...backend.addedRoutes.map((r) => green3(`+${r}`)));
7765
+ parts.push(...backend.addedRoutes.map((r) => green4(`+${r}`)));
7912
7766
  }
7913
7767
  if (backend?.removedRoutes && backend.removedRoutes.length > 0) {
7914
7768
  parts.push(...backend.removedRoutes.map((r) => red2(`-${r}`)));
@@ -7935,7 +7789,7 @@ function displayDeploymentDiff(options) {
7935
7789
  if (schemaStatementCount && schemaStatementCount > 0) {
7936
7790
  const parts = [];
7937
7791
  parts.push(
7938
- green3(
7792
+ green4(
7939
7793
  `+${schemaStatementCount} SQL ${pluralize(schemaStatementCount, "statement")}`
7940
7794
  )
7941
7795
  );
@@ -7964,7 +7818,7 @@ function displayDeploymentDiff(options) {
7964
7818
  if (r === "bucket") return "Bucket";
7965
7819
  return r;
7966
7820
  });
7967
- parts.push(...formatted.map((r) => green3(`+${r}`)));
7821
+ parts.push(...formatted.map((r) => green4(`+${r}`)));
7968
7822
  }
7969
7823
  if (backend?.removedResources && backend.removedResources.length > 0) {
7970
7824
  const formatted = backend.removedResources.map((r) => {
@@ -7985,9 +7839,9 @@ function displayDeploymentDiff(options) {
7985
7839
  } else if (previousSize !== void 0 && currentSize !== void 0) {
7986
7840
  logger.sizeChange("Bundle", previousSize, currentSize, formatSize, formatDelta, 2);
7987
7841
  } else if (currentSize !== void 0) {
7988
- logger.data("Bundle", green3(formatSize(currentSize)), 2);
7842
+ logger.data("Bundle", green4(formatSize(currentSize)), 2);
7989
7843
  } else {
7990
- logger.data("Bundle", green3("Updated"), 2);
7844
+ logger.data("Bundle", green4("Updated"), 2);
7991
7845
  }
7992
7846
  }
7993
7847
  logger.newLine();
@@ -7997,7 +7851,7 @@ function displayDeploymentDiff(options) {
7997
7851
  for (const integration of metadata) {
7998
7852
  logger.bold(integration.name, 1);
7999
7853
  for (const change of integration.changes) {
8000
- const value = `${red2(change.current)} \u2192 ${green3(change.next)}`;
7854
+ const value = `${red2(change.current)} \u2192 ${green4(change.next)}`;
8001
7855
  logger.data(change.label, value, 2);
8002
7856
  }
8003
7857
  logger.newLine();
@@ -8010,7 +7864,7 @@ function displayDeploymentDiff(options) {
8010
7864
  if (comparison.hasChanges) {
8011
7865
  logger.bold("Integrations", 1);
8012
7866
  if (comparison.added.length > 0) {
8013
- const addedList = comparison.added.map((k) => green3(k)).join(", ");
7867
+ const addedList = comparison.added.map((k) => green4(k)).join(", ");
8014
7868
  logger.data("Added", addedList, 2);
8015
7869
  }
8016
7870
  if (comparison.removed.length > 0) {
@@ -8029,7 +7883,7 @@ function displayDeploymentDiff(options) {
8029
7883
  if (hasSecretsChanges) {
8030
7884
  logger.bold("Secrets", 1);
8031
7885
  if (added.length > 0) {
8032
- const addedList = added.map((k) => green3(k)).join(", ");
7886
+ const addedList = added.map((k) => green4(k)).join(", ");
8033
7887
  logger.data("Added", addedList, 2);
8034
7888
  }
8035
7889
  if (removed.length > 0) {
@@ -8493,8 +8347,7 @@ async function confirmDeploymentPlan(plan, context2) {
8493
8347
  }
8494
8348
 
8495
8349
  // src/lib/deploy/output.ts
8496
- init_src();
8497
- import { underline } from "colorette";
8350
+ import { underline as underline2 } from "colorette";
8498
8351
  function displayCurrentConfiguration(context2) {
8499
8352
  const { config } = context2;
8500
8353
  logger.newLine();
@@ -8542,12 +8395,12 @@ function reportDeploymentSuccess(result, context2) {
8542
8395
  logger.success(`${game.displayName} ${action} successfully!`);
8543
8396
  logger.newLine();
8544
8397
  const baseUrl = getWebBaseUrl(client.getBaseUrl());
8545
- logger.data("Project URL", underline(`${baseUrl}/play/${game.slug}`), 1);
8398
+ logger.data("Project URL", underline2(`${baseUrl}/play/${game.slug}`), 1);
8546
8399
  if (backendMetadata || context2.previousBackendBundleHash) {
8547
8400
  const env = getEnvironment();
8548
8401
  const subdomain = env === "staging" ? `${game.slug}-staging` : game.slug;
8549
8402
  const backendUrl = `https://${subdomain}.${GAME_WORKER_DOMAINS.production}/api`;
8550
- logger.data("Backend API", underline(`${backendUrl}`), 1);
8403
+ logger.data("Backend API", underline2(`${backendUrl}`), 1);
8551
8404
  }
8552
8405
  logger.newLine();
8553
8406
  }
@@ -9466,7 +9319,6 @@ async function bundleStubWorker() {
9466
9319
  }
9467
9320
 
9468
9321
  // src/lib/deploy/utils.ts
9469
- init_src();
9470
9322
  function getDeploymentId(gameSlug) {
9471
9323
  const environment = getEnvironment();
9472
9324
  return environment === "production" ? gameSlug : `${WORKER_NAMING.STAGING_PREFIX}${gameSlug}`;
@@ -10197,7 +10049,7 @@ async function uploadFilesLocal(files, prefix, uploadFn) {
10197
10049
  }
10198
10050
 
10199
10051
  // src/lib/timeback/display.ts
10200
- import { bold as bold6, greenBright as greenBright2, redBright as redBright2 } from "colorette";
10052
+ import { bold as bold7, greenBright as greenBright2, redBright as redBright2 } from "colorette";
10201
10053
  function displayIntegrationDetails(integration) {
10202
10054
  logger.highlight("Verified Course");
10203
10055
  logger.newLine();
@@ -10234,9 +10086,9 @@ function displayIntegrationList(integrations, statusByCourseId, options) {
10234
10086
  if (showStatusColumn) {
10235
10087
  if (options?.staticLabel) {
10236
10088
  const coloredLabel = options.staticLabelColor ? options.staticLabelColor(options.staticLabel) : greenBright2(options.staticLabel);
10237
- statusText = bold6(coloredLabel);
10089
+ statusText = bold7(coloredLabel);
10238
10090
  } else if (statusByCourseId && integration.courseId in statusByCourseId) {
10239
- statusText = statusByCourseId[integration.courseId] ? bold6(greenBright2(successLabel)) : bold6(redBright2(failureLabel));
10091
+ statusText = statusByCourseId[integration.courseId] ? bold7(greenBright2(successLabel)) : bold7(redBright2(failureLabel));
10240
10092
  }
10241
10093
  }
10242
10094
  const row = {
@@ -10270,7 +10122,7 @@ function displayCleanupWarning(integrations, gameName, logger2) {
10270
10122
  }
10271
10123
 
10272
10124
  // src/lib/timeback/setup.ts
10273
- import { bold as bold7 } from "colorette";
10125
+ import { bold as bold8 } from "colorette";
10274
10126
  function displaySetupDryRun(derivedRequest, env, logger2) {
10275
10127
  logger2.highlight("TimeBack Setup [DRY RUN]");
10276
10128
  logger2.newLine();
@@ -10300,7 +10152,7 @@ function displaySetupDryRun(derivedRequest, env, logger2) {
10300
10152
  logger2.admonition("tip", "Ready for setup", [
10301
10153
  "Your Timeback configuration has been validated!",
10302
10154
  "",
10303
- `Run without \`--dry-run\` to create ${bold7(`${derivedRequest.courses.length} course(s)`)} in ${bold7(env || "staging")}`
10155
+ `Run without \`--dry-run\` to create ${bold8(`${derivedRequest.courses.length} course(s)`)} in ${bold8(env || "staging")}`
10304
10156
  ]);
10305
10157
  logger2.newLine();
10306
10158
  }
@@ -10817,7 +10669,7 @@ initCommand.addCommand(configCommand);
10817
10669
  // src/commands/login.ts
10818
10670
  import { userInfo } from "os";
10819
10671
  import { input as input3, password, select as select4 } from "@inquirer/prompts";
10820
- import { bold as bold8, dim as dim8, whiteBright } from "colorette";
10672
+ import { bold as bold9, dim as dim8, whiteBright } from "colorette";
10821
10673
  import { Command as Command3 } from "commander";
10822
10674
  import open from "open";
10823
10675
  var loginCommand = new Command3("login").description("Authenticate with Playcademy").option("-e, --email <email>", "Email address (for email/password auth)").option("-p, --password <password>", "Password (for email/password auth)").option("--sso", "Use Timeback SSO authentication").option("--env <environment>", "Environment to login to (staging or production)").action(async (options) => {
@@ -10831,12 +10683,12 @@ var loginCommand = new Command3("login").description("Authenticate with Playcade
10831
10683
  const otherEnv = environment === "staging" ? "production" : "staging";
10832
10684
  const otherProfile = await getProfile(otherEnv, profileName);
10833
10685
  logger.admonition("note", "Hello again", [
10834
- bold8("You're already logged in"),
10686
+ bold9("You're already logged in"),
10835
10687
  "",
10836
- dim8("Email: ") + bold8(email2),
10837
- dim8("Environment: ") + bold8(environment),
10838
- dim8("Profile: ") + bold8(profileName),
10839
- ...otherProfile ? [dim8("Other Profile: ") + bold8(otherEnv)] : []
10688
+ dim8("Email: ") + bold9(email2),
10689
+ dim8("Environment: ") + bold9(environment),
10690
+ dim8("Profile: ") + bold9(profileName),
10691
+ ...otherProfile ? [dim8("Other Profile: ") + bold9(otherEnv)] : []
10840
10692
  ]);
10841
10693
  logger.newLine();
10842
10694
  return;
@@ -10912,7 +10764,9 @@ var loginCommand = new Command3("login").description("Authenticate with Playcade
10912
10764
  `Email: ${authProfile.email}`,
10913
10765
  `Environment: ${environment}`,
10914
10766
  ...profileName !== "default" ? [`Profile: ${profileName}`] : [],
10915
- ...profileName !== "default" ? [`Use \`--profile ${profileName}\` with commands to use this profile`] : []
10767
+ ...profileName !== "default" ? [`Use \`--profile ${profileName}\` with commands to use this profile`] : [],
10768
+ "",
10769
+ "Learn more: <<https://docs.playcademy.net/platform/cli/authentication>>"
10916
10770
  ]);
10917
10771
  logger.newLine();
10918
10772
  } catch (error) {
@@ -10966,7 +10820,7 @@ async function handleSsoLogin(environment, profileName) {
10966
10820
  logger.admonition("warning", "Your API Key", [
10967
10821
  "Save this key securely - it will not be shown again!",
10968
10822
  "",
10969
- whiteBright(bold8(apiKeyResult.apiKey))
10823
+ whiteBright(bold9(apiKeyResult.apiKey))
10970
10824
  ]);
10971
10825
  logger.newLine();
10972
10826
  await runStep(
@@ -11074,7 +10928,7 @@ var meCommand = new Command5("me").description("Display current user information
11074
10928
 
11075
10929
  // src/commands/update.ts
11076
10930
  import { execSync as execSync8 } from "child_process";
11077
- import { bold as bold9 } from "colorette";
10931
+ import { bold as bold10 } from "colorette";
11078
10932
  import { Command as Command6 } from "commander";
11079
10933
  var updateCommands = {
11080
10934
  bun: "bun install -g playcademy@latest",
@@ -11088,7 +10942,7 @@ var updateCommand = new Command6("update").description("Update the Playcademy CL
11088
10942
  const runnerName = getPackageRunnerName(runnerPath);
11089
10943
  logger.newLine();
11090
10944
  logger.admonition("info", "Package Runner Detected", [
11091
- `You are running the CLI via package runner (${bold9(runnerName)}).`,
10945
+ `You are running the CLI via package runner (${bold10(runnerName)}).`,
11092
10946
  "",
11093
10947
  "Package runners use the latest version of the CLI by default, but may cache older versions.",
11094
10948
  `To ensure you run the package's latest version: \`${runnerName} playcademy@latest\``
@@ -11422,8 +11276,10 @@ var getStatusCommand = new Command12("status").description("Check your developer
11422
11276
  }
11423
11277
  });
11424
11278
 
11279
+ // package.json
11280
+ var version2 = "0.14.27";
11281
+
11425
11282
  // src/commands/dev/server.ts
11426
- import { underline as underline2 } from "colorette";
11427
11283
  function setupCleanupHandlers(workspace, getServer) {
11428
11284
  let isShuttingDown = false;
11429
11285
  const cleanup = () => {
@@ -11462,6 +11318,7 @@ async function setupServerHotReload(serverRef, port, workspace, config, loggerEn
11462
11318
  }
11463
11319
  async function runDevServer(options) {
11464
11320
  const serverRef = { current: null };
11321
+ const startTime = Date.now();
11465
11322
  try {
11466
11323
  const config = await loadConfigAndSetWorkspace();
11467
11324
  const workspace = getWorkspace();
@@ -11472,7 +11329,9 @@ async function runDevServer(options) {
11472
11329
  logger.warn("No backend integrations or custom routes configured");
11473
11330
  logger.newLine();
11474
11331
  logger.admonition("tip", "How to Add Backend", [
11475
- `Add integrations to <playcademy.config.js> or run \`playcademy api init\``
11332
+ "Add integrations to <playcademy.config.js> or run `playcademy api init`",
11333
+ "",
11334
+ "Learn more: <<https://docs.playcademy.net/platform/integrations>>"
11476
11335
  ]);
11477
11336
  logger.newLine();
11478
11337
  logger.remark("Nothing to do");
@@ -11486,25 +11345,25 @@ async function runDevServer(options) {
11486
11345
  logger: options.logger !== false
11487
11346
  });
11488
11347
  serverRef.current = server;
11489
- logger.newLine();
11490
- logger.success(`Project API started: ${underline2(`<http://localhost:${port}/api>`)}`);
11491
- logger.newLine();
11492
11348
  const customRoutesDir = getCustomRoutesDirectory(workspace, config);
11493
- const customRoutes = await discoverRoutes(customRoutesDir);
11494
- displayRegisteredRoutes(config.integrations, customRoutes);
11495
- logger.newLine();
11349
+ await discoverRoutes(customRoutesDir);
11350
+ const quiet = options.quiet || process.env.PLAYCADEMY_EMBEDDED === "1";
11351
+ printDevBanner({
11352
+ version: version2,
11353
+ port,
11354
+ startupTimeMs: Date.now() - startTime,
11355
+ quiet
11356
+ });
11496
11357
  if (options.reload !== false) {
11497
11358
  await setupServerHotReload(serverRef, port, workspace, config, options.logger !== false);
11498
11359
  }
11499
- logger.remark(`Press ${underline2("ctrl+c")} to stop`);
11500
- logger.newLine();
11501
11360
  } catch (error) {
11502
11361
  logAndExit(error, { prefix: "Failed to start dev server" });
11503
11362
  }
11504
11363
  }
11505
11364
 
11506
11365
  // src/commands/dev/index.ts
11507
- var devCommand = new Command13("dev").description("Start local backend development server").option("-p, --port <port>", "Backend server port", String(DEFAULT_PORTS.BACKEND)).option("--no-reload", "Disable hot reload").option("--no-logger", "Disable HTTP request logging").action(runDevServer);
11366
+ var devCommand = new Command13("dev").description("Start local backend development server").option("-p, --port <port>", "Backend server port", String(DEFAULT_PORTS.BACKEND)).option("--no-reload", "Disable hot reload").option("--no-logger", "Disable HTTP request logging").option("-q, --quiet", "Quiet mode").action(runDevServer);
11508
11367
  devCommand.addCommand(applyCommand);
11509
11368
  devCommand.addCommand(getStatusCommand);
11510
11369
 
@@ -11586,7 +11445,9 @@ async function runApiInit() {
11586
11445
  logger.admonition("tip", "Next Steps", [
11587
11446
  `1. Review sample routes in <${apiDir}/sample/>`,
11588
11447
  "2. Run `playcademy dev` to test locally",
11589
- "3. Run `playcademy deploy` to deploy your project"
11448
+ "3. Run `playcademy deploy` to deploy your project",
11449
+ "",
11450
+ "Learn more: <<https://docs.playcademy.net/platform/integrations/custom-routes>>"
11590
11451
  ]);
11591
11452
  logger.newLine();
11592
11453
  } catch (error) {
@@ -11606,7 +11467,7 @@ import { Command as Command17 } from "commander";
11606
11467
  init_file_loader();
11607
11468
  import { writeFileSync as writeFileSync13 } from "fs";
11608
11469
  import { join as join33 } from "path";
11609
- import { bold as bold10 } from "colorette";
11470
+ import { bold as bold11 } from "colorette";
11610
11471
  import { Command as Command15 } from "commander";
11611
11472
  var addAuthCommand = new Command15("add").description("Add an authentication provider to your project").argument("<provider>", "Provider to add: email | github | google").addHelpText(
11612
11473
  "after",
@@ -11674,16 +11535,16 @@ Examples:
11674
11535
  PLACEHOLDER_GAME_URL
11675
11536
  ).replace("{provider}", provider);
11676
11537
  logger.admonition("tip", "Next Steps", [
11677
- bold10(`1. Add callback URL to your ${providerDisplayName} OAuth app:`),
11538
+ bold11(`1. Add callback URL to your ${providerDisplayName} OAuth app:`),
11678
11539
  "",
11679
11540
  ` <${callbackUrl}>`,
11680
11541
  "",
11681
- bold10("2. Add credentials to <.env> (for local development):"),
11542
+ bold11("2. Add credentials to <.env> (for local development):"),
11682
11543
  "",
11683
11544
  ` \`${provider.toUpperCase()}_CLIENT_ID=[your-id]\``,
11684
11545
  ` \`${provider.toUpperCase()}_CLIENT_SECRET=[your-secret]\``,
11685
11546
  "",
11686
- bold10("3. Set production secrets (for deployment):"),
11547
+ bold11("3. Set production secrets (for deployment):"),
11687
11548
  "",
11688
11549
  ` \`playcademy secret set ${provider.toUpperCase()}_CLIENT_ID=[your-id]\``,
11689
11550
  ` \`playcademy secret set ${provider.toUpperCase()}_CLIENT_SECRET=[your-secret]\``
@@ -11777,7 +11638,9 @@ var initAuthCommand = new Command16("init").description("Add authentication to y
11777
11638
  "1. Install dependencies: `bun install`",
11778
11639
  "2. Review auth config: <server/lib/auth.ts>",
11779
11640
  "3. Push schema: `bun db:push`",
11780
- "4. Start dev server: `playcademy dev`"
11641
+ "4. Start dev server: `playcademy dev`",
11642
+ "",
11643
+ "Learn more: <<https://docs.playcademy.net/platform/integrations/authentication>>"
11781
11644
  ]);
11782
11645
  logger.newLine();
11783
11646
  if (additionalStrategies.length > 0) {
@@ -11910,7 +11773,9 @@ async function runDbInit() {
11910
11773
  "1. Install dependencies: `bun install`",
11911
11774
  "2. Review schema in <./server/db/schema/example.ts>",
11912
11775
  "3. Push schema: `bun db:push`",
11913
- "4. Start dev server: `playcademy dev`"
11776
+ "4. Start dev server: `playcademy dev`",
11777
+ "",
11778
+ "Learn more: <<https://docs.playcademy.net/platform/integrations/database>>"
11914
11779
  ]);
11915
11780
  logger.newLine();
11916
11781
  } catch (error) {
@@ -11923,7 +11788,7 @@ async function runDbInit() {
11923
11788
  import { existsSync as existsSync23 } from "fs";
11924
11789
  import { join as join34 } from "path";
11925
11790
  import { confirm as confirm8, input as input7 } from "@inquirer/prompts";
11926
- import { bold as bold11, redBright as redBright4, underline as underline3 } from "colorette";
11791
+ import { bold as bold12, redBright as redBright4, underline as underline3 } from "colorette";
11927
11792
  import { Miniflare as Miniflare2 } from "miniflare";
11928
11793
  async function runDbResetRemote(options) {
11929
11794
  const environment = ensureEnvironment(options.env);
@@ -11941,9 +11806,9 @@ async function runDbResetRemote(options) {
11941
11806
  const game = await client.games.fetch(deployedGame.gameId);
11942
11807
  logger.newLine();
11943
11808
  logger.admonition("warning", "DESTRUCTIVE OPERATION", [
11944
- `Are you sure you want to ${redBright4(underline3(bold11("DELETE ALL DATA")))} in your ${environment} database?`,
11809
+ `Are you sure you want to ${redBright4(underline3(bold12("DELETE ALL DATA")))} in your ${environment} database?`,
11945
11810
  `All tables will be dropped and recreated from schema.`,
11946
- `This action is irreversible and ${underline3(bold11("cannot be undone"))}.`
11811
+ `This action is irreversible and ${underline3(bold12("cannot be undone"))}.`
11947
11812
  ]);
11948
11813
  logger.newLine();
11949
11814
  const confirmed = await confirm8({
@@ -12064,7 +11929,7 @@ async function runDbReset(options = {}) {
12064
11929
  import { existsSync as existsSync24 } from "fs";
12065
11930
  import { join as join35 } from "path";
12066
11931
  import { confirm as confirm9, input as input8 } from "@inquirer/prompts";
12067
- import { bold as bold12, redBright as redBright5, underline as underline4 } from "colorette";
11932
+ import { bold as bold13, redBright as redBright5, underline as underline4 } from "colorette";
12068
11933
  import { Miniflare as Miniflare3 } from "miniflare";
12069
11934
  async function runDbResetRemote2(gameSlug, environment) {
12070
11935
  const client = await requireAuthenticatedClient();
@@ -12108,8 +11973,8 @@ async function runDbSeedRemote(seedFile, options) {
12108
11973
  logger.newLine();
12109
11974
  if (willReset) {
12110
11975
  logger.admonition("warning", "Remote Database Seeding", [
12111
- `Are you sure you want to ${redBright5(underline4(bold12("DELETE ALL DATA")))} in your ${environment} database?`,
12112
- `This action is irreversible and ${underline4(bold12("cannot be undone"))}.`,
11976
+ `Are you sure you want to ${redBright5(underline4(bold13("DELETE ALL DATA")))} in your ${environment} database?`,
11977
+ `This action is irreversible and ${underline4(bold13("cannot be undone"))}.`,
12113
11978
  `Run this command with \`--no-reset\` if you want to seed without resetting.`
12114
11979
  ]);
12115
11980
  } else {
@@ -12309,7 +12174,9 @@ async function runKVClear(options = {}) {
12309
12174
  logger.error("KV storage is not configured");
12310
12175
  logger.newLine();
12311
12176
  logger.admonition("tip", "Getting Started", [
12312
- "Run `playcademy kv init` to enable KV storage"
12177
+ "Run `playcademy kv init` to enable KV storage",
12178
+ "",
12179
+ "Learn more: <<https://docs.playcademy.net/platform/integrations/kv>>"
12313
12180
  ]);
12314
12181
  logger.newLine();
12315
12182
  }
@@ -12421,7 +12288,9 @@ async function runKVDelete(key, options = {}) {
12421
12288
  logger.error("KV storage is not configured");
12422
12289
  logger.newLine();
12423
12290
  logger.admonition("tip", "Getting Started", [
12424
- "Run `playcademy kv init` to enable KV storage"
12291
+ "Run `playcademy kv init` to enable KV storage",
12292
+ "",
12293
+ "Learn more: <<https://docs.playcademy.net/platform/integrations/kv>>"
12425
12294
  ]);
12426
12295
  logger.newLine();
12427
12296
  }
@@ -12498,7 +12367,9 @@ async function runKVGet(key, options = {}) {
12498
12367
  logger.error("KV storage is not configured");
12499
12368
  logger.newLine();
12500
12369
  logger.admonition("tip", "Getting Started", [
12501
- "Run `playcademy kv init` to enable KV storage"
12370
+ "Run `playcademy kv init` to enable KV storage",
12371
+ "",
12372
+ "Learn more: <<https://docs.playcademy.net/platform/integrations/kv>>"
12502
12373
  ]);
12503
12374
  logger.newLine();
12504
12375
  }
@@ -12620,7 +12491,9 @@ async function runKVInit() {
12620
12491
  logger.admonition("tip", "Next Steps", [
12621
12492
  "1. Use `c.env.KV` in your API routes",
12622
12493
  "2. Run `playcademy dev` to test locally",
12623
- "3. Run `playcademy deploy`"
12494
+ "3. Run `playcademy deploy`",
12495
+ "",
12496
+ "Learn more: <<https://docs.playcademy.net/platform/integrations/kv>>"
12624
12497
  ]);
12625
12498
  logger.newLine();
12626
12499
  } catch (error) {
@@ -12668,7 +12541,9 @@ async function runKVInspect(key, options = {}) {
12668
12541
  logger.error("KV storage is not configured");
12669
12542
  logger.newLine();
12670
12543
  logger.admonition("tip", "Getting Started", [
12671
- "Run `playcademy kv init` to enable KV storage"
12544
+ "Run `playcademy kv init` to enable KV storage",
12545
+ "",
12546
+ "Learn more: <<https://docs.playcademy.net/platform/integrations/kv>>"
12672
12547
  ]);
12673
12548
  logger.newLine();
12674
12549
  }
@@ -12786,7 +12661,9 @@ async function runKVList(options = {}) {
12786
12661
  logger.error("KV storage is not configured");
12787
12662
  logger.newLine();
12788
12663
  logger.admonition("tip", "Getting Started", [
12789
- "Run `playcademy kv init` to enable KV storage"
12664
+ "Run `playcademy kv init` to enable KV storage",
12665
+ "",
12666
+ "Learn more: <<https://docs.playcademy.net/platform/integrations/kv>>"
12790
12667
  ]);
12791
12668
  logger.newLine();
12792
12669
  }
@@ -12880,7 +12757,9 @@ async function runKVSeed(seedFile, options = {}) {
12880
12757
  logger.error("KV storage is not configured");
12881
12758
  logger.newLine();
12882
12759
  logger.admonition("tip", "Getting Started", [
12883
- "Run `playcademy kv init` to enable KV storage"
12760
+ "Run `playcademy kv init` to enable KV storage",
12761
+ "",
12762
+ "Learn more: <<https://docs.playcademy.net/platform/integrations/kv>>"
12884
12763
  ]);
12885
12764
  logger.newLine();
12886
12765
  }
@@ -13023,7 +12902,9 @@ async function runKVSet(key, value, options = {}) {
13023
12902
  logger.error("KV storage is not configured");
13024
12903
  logger.newLine();
13025
12904
  logger.admonition("tip", "Getting Started", [
13026
- "Run `playcademy kv init` to enable KV storage"
12905
+ "Run `playcademy kv init` to enable KV storage",
12906
+ "",
12907
+ "Learn more: <<https://docs.playcademy.net/platform/integrations/kv>>"
13027
12908
  ]);
13028
12909
  logger.newLine();
13029
12910
  }
@@ -13117,7 +12998,9 @@ async function runKVStats(options = {}) {
13117
12998
  logger.error("KV storage is not configured");
13118
12999
  logger.newLine();
13119
13000
  logger.admonition("tip", "Getting Started", [
13120
- "Run `playcademy kv init` to enable KV storage"
13001
+ "Run `playcademy kv init` to enable KV storage",
13002
+ "",
13003
+ "Learn more: <<https://docs.playcademy.net/platform/integrations/kv>>"
13121
13004
  ]);
13122
13005
  logger.newLine();
13123
13006
  }
@@ -13735,7 +13618,9 @@ async function runBucketInit() {
13735
13618
  logger.admonition("tip", "Next Steps", [
13736
13619
  "1. Use `c.env.BUCKET` in your API routes to upload/download files",
13737
13620
  "2. Run `playcademy dev` to test locally",
13738
- "3. Run `playcademy deploy`"
13621
+ "3. Run `playcademy deploy`",
13622
+ "",
13623
+ "Learn more: <<https://docs.playcademy.net/platform/integrations/bucket>>"
13739
13624
  ]);
13740
13625
  logger.newLine();
13741
13626
  } catch (error) {
@@ -13809,7 +13694,9 @@ async function runBucketListLocal(options) {
13809
13694
  logger.error("Bucket storage is not configured");
13810
13695
  logger.newLine();
13811
13696
  logger.admonition("tip", "Getting Started", [
13812
- "Run `playcademy bucket init` to enable bucket storage"
13697
+ "Run `playcademy bucket init` to enable bucket storage",
13698
+ "",
13699
+ "Learn more: <<https://docs.playcademy.net/platform/integrations/bucket>>"
13813
13700
  ]);
13814
13701
  logger.newLine();
13815
13702
  }
@@ -13966,7 +13853,9 @@ async function runBucketPutLocal(key, filePath, options) {
13966
13853
  logger.error("Bucket storage is not configured");
13967
13854
  logger.newLine();
13968
13855
  logger.admonition("tip", "Getting Started", [
13969
- "Run `playcademy bucket init` to enable bucket storage"
13856
+ "Run `playcademy bucket init` to enable bucket storage",
13857
+ "",
13858
+ "Learn more: <<https://docs.playcademy.net/platform/integrations/bucket>>"
13970
13859
  ]);
13971
13860
  logger.newLine();
13972
13861
  }
@@ -14115,7 +14004,9 @@ async function runDomainAdd(hostname, options) {
14115
14004
  `2. Run \`playcademy domain verify ${normalizedHostname}\` to check validation status`,
14116
14005
  "",
14117
14006
  "Note: SSL certificate validation may take a few minutes to initialize.",
14118
- `Run verify command to see all required DNS records once SSL provisioning begins.`
14007
+ "Run verify command to see all required DNS records once SSL provisioning begins.",
14008
+ "",
14009
+ "Learn more: <<https://docs.playcademy.net/platform/cli/deployment#custom-domains>>"
14119
14010
  ]);
14120
14011
  logger.newLine();
14121
14012
  } catch (error) {
@@ -14504,7 +14395,7 @@ async function listProfilesAction() {
14504
14395
  var listCommand3 = new Command27("list").alias("ls").description("List all stored authentication profiles").action(listProfilesAction);
14505
14396
 
14506
14397
  // src/commands/profiles/remove.ts
14507
- import { bold as bold13 } from "colorette";
14398
+ import { bold as bold14 } from "colorette";
14508
14399
  import { Command as Command28 } from "commander";
14509
14400
  var removeCommand = new Command28("remove").alias("rm").description('Remove an authentication profile (defaults to "default")').argument("[name]", "Profile name to remove", "default").option("--env <environment>", "Environment to remove profile from (staging or production)").action(async (name, options) => {
14510
14401
  const { env } = options;
@@ -14520,7 +14411,7 @@ var removeCommand = new Command28("remove").alias("rm").description('Remove an a
14520
14411
  }
14521
14412
  await removeProfile(environment, name);
14522
14413
  logger.admonition("note", "Removed!", [
14523
- `Profile ${bold13(name)} removed from ${environment}`,
14414
+ `Profile ${bold14(name)} removed from ${environment}`,
14524
14415
  environment === "production" ? `To re-authenticate run \`playcademy login --env ${environment}\`` : "To re-authenticate run `playcademy login`"
14525
14416
  ]);
14526
14417
  logger.newLine();
@@ -14665,6 +14556,7 @@ var cleanupCommand = new Command31("cleanup").description("Remove TimeBack integ
14665
14556
  logger.newLine();
14666
14557
  } catch (error) {
14667
14558
  logger.error(`Cleanup failed: ${getErrorMessage(error)}`);
14559
+ logger.newLine();
14668
14560
  process.exit(1);
14669
14561
  }
14670
14562
  });
@@ -14707,13 +14599,15 @@ var initCommand2 = new Command32("init").description("Add TimeBack integration t
14707
14599
  logger.success("TimeBack integration added!");
14708
14600
  logger.newLine();
14709
14601
  logger.admonition("tip", "Next Steps", [
14710
- `1. Set up TimeBack resources: \`playcademy timeback setup\``,
14711
- `2. Deploy your project: \`playcademy deploy\``
14602
+ "1. Set up TimeBack resources: `playcademy timeback setup`",
14603
+ "2. Deploy your project: `playcademy deploy`",
14604
+ "",
14605
+ "Learn more: <<https://docs.playcademy.net/timeback>>"
14712
14606
  ]);
14713
14607
  logger.newLine();
14714
14608
  } catch (error) {
14715
14609
  logger.newLine();
14716
- throw error;
14610
+ formatErrorAndExit(error);
14717
14611
  }
14718
14612
  });
14719
14613
 
@@ -14792,7 +14686,9 @@ var setupCommand = new Command33("setup").description("Set up TimeBack integrati
14792
14686
  }
14793
14687
  logger.admonition("tip", "Next Steps", [
14794
14688
  "1. Run `playcademy timeback verify` to verify the setup",
14795
- "2. Deploy your project with `playcademy deploy`"
14689
+ "2. Deploy your project with `playcademy deploy`",
14690
+ "",
14691
+ "Learn more: <<https://docs.playcademy.net/timeback>>"
14796
14692
  ]);
14797
14693
  logger.newLine();
14798
14694
  } catch (error) {
@@ -14897,7 +14793,7 @@ var verifyCommand = new Command35("verify").description("Verify TimeBack integra
14897
14793
  "",
14898
14794
  ` \`playcademy timeback setup --env ${environment}\``,
14899
14795
  "",
14900
- "This will create the necessary TimeBack resources."
14796
+ "Learn more: <<https://docs.playcademy.net/timeback>>"
14901
14797
  ]);
14902
14798
  } else {
14903
14799
  logger.error(`Verification failed: ${getErrorMessage(error)}`);
@@ -14998,11 +14894,11 @@ var debugCommand = new Command38("debug").description("Debug and inspect project
14998
14894
  // src/commands/vite/index.ts
14999
14895
  import { Command as Command39 } from "commander";
15000
14896
 
15001
- // src/commands/vite/init.ts
14897
+ // src/commands/vite/config.ts
15002
14898
  import path3 from "node:path";
15003
14899
  import { confirm as confirm17 } from "@inquirer/prompts";
15004
- import { dim as dim9, underline as underline7 } from "colorette";
15005
- async function runViteInit() {
14900
+ import { dim as dim9 } from "colorette";
14901
+ async function runViteConfig() {
15006
14902
  try {
15007
14903
  logger.newLine();
15008
14904
  await requireConfigFile();
@@ -15047,7 +14943,7 @@ async function runViteInit() {
15047
14943
  `2. Run \`${devCommand2}\` to start development`,
15048
14944
  `3. Run \`${buildCommand}\` to build your project`,
15049
14945
  "",
15050
- `Learn more: ${underline7("<https://docs.playcademy.gg/vite-plugin>")}`
14946
+ "Learn more: <<https://docs.playcademy.net/platform/vite-plugin>>"
15051
14947
  ]);
15052
14948
  logger.newLine();
15053
14949
  } catch (error) {
@@ -15061,7 +14957,7 @@ async function runViteInit() {
15061
14957
 
15062
14958
  // src/commands/vite/index.ts
15063
14959
  var viteCommand = new Command39("vite").description("Vite plugin management");
15064
- viteCommand.command("init").description("Add Vite plugin to your project").action(runViteInit);
14960
+ viteCommand.command("config").description("Add Vite plugin to your project").action(runViteConfig);
15065
14961
 
15066
14962
  // src/index.ts
15067
14963
  setupGlobalErrorHandlers();
@@ -15130,7 +15026,6 @@ export {
15130
15026
  displayIntegrationDetails,
15131
15027
  displayIntegrationList,
15132
15028
  displayMissingCourseRequirementsAndExit,
15133
- displayRegisteredRoutes,
15134
15029
  displayResourcesStatus,
15135
15030
  displaySetupDryRun,
15136
15031
  displaySuccessMessage,
@@ -15229,6 +15124,7 @@ export {
15229
15124
  outputUploadResults,
15230
15125
  prepareDeploymentContext,
15231
15126
  printDebugInfo,
15127
+ printDevBanner,
15232
15128
  processConfigVariables,
15233
15129
  promptForAuthStrategies,
15234
15130
  promptForCustomRoutes,
@@ -1,5 +1,5 @@
1
1
  // TimeBack integration configuration
2
- // See https://docs.playcademy.com/timeback for more details
2
+ // See https://docs.playcademy.net/timeback for more details
3
3
  timeback: {
4
4
  course: {
5
5
  subjects: {{SUBJECTS}},{{DEFAULT_SUBJECT}}
package/dist/utils.js CHANGED
@@ -2031,6 +2031,7 @@ import {
2031
2031
  green,
2032
2032
  greenBright,
2033
2033
  red,
2034
+ underline,
2034
2035
  yellow,
2035
2036
  yellowBright
2036
2037
  } from "colorette";
@@ -2732,6 +2733,7 @@ function formatError(error, indent = 0) {
2732
2733
  function customTransform(text) {
2733
2734
  let result = text;
2734
2735
  result = result.replace(/`([^`]+)`/g, (_, code) => greenBright(code));
2736
+ result = result.replace(/<<([^>]+)>>/g, (_, url) => underline(url));
2735
2737
  result = result.replace(/<([^>]+)>/g, (_, path2) => blueBright(path2));
2736
2738
  return result;
2737
2739
  }
@@ -3989,10 +3991,10 @@ var protectedRouteTemplate = loadTemplateString("api/sample-protected.ts");
3989
3991
  import { existsSync as existsSync7, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
3990
3992
  import { join as join12 } from "path";
3991
3993
 
3992
- // package.json
3994
+ // package.json with { type: 'json' }
3993
3995
  var package_default2 = {
3994
3996
  name: "playcademy",
3995
- version: "0.14.25",
3997
+ version: "0.14.27",
3996
3998
  type: "module",
3997
3999
  exports: {
3998
4000
  ".": {
@@ -4376,7 +4378,7 @@ var FilteredLog = class extends Log {
4376
4378
  };
4377
4379
  async function startDevServer(options) {
4378
4380
  const { port, config: _config, platformUrl, logger: logger2 = true, customLogger } = options;
4379
- await waitForPort(port);
4381
+ await waitForPort(port, 1e3);
4380
4382
  const config = _config ?? await loadConfig();
4381
4383
  await ensurePlaycademyTypes();
4382
4384
  const hasSandboxTimebackCreds = !!process.env.TIMEBACK_API_CLIENT_ID;
package/dist/version.js CHANGED
@@ -1,7 +1,7 @@
1
- // package.json
1
+ // package.json with { type: 'json' }
2
2
  var package_default = {
3
3
  name: "playcademy",
4
- version: "0.14.25",
4
+ version: "0.14.27",
5
5
  type: "module",
6
6
  exports: {
7
7
  ".": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "playcademy",
3
- "version": "0.14.26",
3
+ "version": "0.14.28",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {