playcademy 0.21.1-beta.2 → 0.22.0

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/cli.js CHANGED
@@ -674,7 +674,7 @@ function setupGlobalErrorHandlers() {
674
674
  // src/lib/init/run.ts
675
675
  import { execSync as execSync5 } from "child_process";
676
676
  import { writeFileSync as writeFileSync10 } from "fs";
677
- import { resolve as resolve8 } from "path";
677
+ import { resolve as resolve9 } from "path";
678
678
  import { confirm as confirm5 } from "@inquirer/prompts";
679
679
 
680
680
  // ../utils/src/ansi.ts
@@ -1065,7 +1065,7 @@ var SAMPLE_BUCKET_FILENAME = "bucket.ts";
1065
1065
  // ../better-auth/package.json
1066
1066
  var package_default = {
1067
1067
  name: "@playcademy/better-auth",
1068
- version: "0.0.13-beta.2",
1068
+ version: "0.0.13",
1069
1069
  type: "module",
1070
1070
  exports: {
1071
1071
  "./server": {
@@ -2425,17 +2425,17 @@ import { cyan as cyan3, magenta as magenta2, yellow as yellow3 } from "colorette
2425
2425
  // src/lib/init/engine/registry.ts
2426
2426
  import { blue as blue2, cyan as cyan2, green as green2, magenta, red as red2, yellow as yellow2 } from "colorette";
2427
2427
 
2428
- // src/lib/init/engine/hooks.ts
2429
- import { existsSync as existsSync6, mkdirSync, writeFileSync as writeFileSync2 } from "fs";
2430
- import { rename, rm } from "fs/promises";
2431
- import { dirname as dirname4, join as join9 } from "path";
2428
+ // src/lib/godot/addon.ts
2429
+ import { existsSync as existsSync6, mkdirSync, mkdtempSync, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "fs";
2430
+ import { rm } from "fs/promises";
2431
+ import { dirname as dirname4, join as join9, resolve as resolve5, sep } from "path";
2432
2432
  import JSZip from "jszip";
2433
- async function godotAfterFetch({ destDir }) {
2434
- const addonsDir = join9(destDir, "addons");
2433
+ async function downloadAndExtractAddon(projectDir, options) {
2434
+ const addonsDir = join9(projectDir, "addons");
2435
2435
  const targetDir = join9(addonsDir, "playcademy");
2436
2436
  let zipData;
2437
2437
  await runStep(
2438
- "Downloading Playcademy Addon for Godot",
2438
+ "Downloading Playcademy addon",
2439
2439
  async () => {
2440
2440
  const response = await fetch(GODOT_ADDON_URL);
2441
2441
  if (!response.ok) {
@@ -2445,45 +2445,66 @@ async function godotAfterFetch({ destDir }) {
2445
2445
  }
2446
2446
  zipData = await response.arrayBuffer();
2447
2447
  },
2448
- "Playcademy Addon downloaded",
2449
- { silent: true }
2448
+ "Playcademy addon downloaded",
2449
+ { silent: options?.silent }
2450
2450
  );
2451
2451
  await runStep(
2452
- "Extracting Playcademy Addon",
2452
+ "Extracting addon",
2453
2453
  async () => {
2454
2454
  const zip = await JSZip.loadAsync(zipData);
2455
2455
  if (!existsSync6(addonsDir)) {
2456
2456
  mkdirSync(addonsDir, { recursive: true });
2457
2457
  }
2458
- const extractPromises = [];
2459
- zip.forEach((relativePath, file) => {
2460
- if (file.dir) {
2461
- return;
2458
+ const tempDir = mkdtempSync(join9(addonsDir, ".playcademy-sync-"));
2459
+ const tempBase = resolve5(tempDir) + sep;
2460
+ const backupDir = join9(addonsDir, `.playcademy-backup-${Date.now()}`);
2461
+ try {
2462
+ const extractPromises = [];
2463
+ zip.forEach((relativePath, file) => {
2464
+ if (file.dir) {
2465
+ return;
2466
+ }
2467
+ const extractPath = resolve5(tempDir, relativePath);
2468
+ if (!extractPath.startsWith(tempBase)) {
2469
+ return;
2470
+ }
2471
+ extractPromises.push(
2472
+ file.async("nodebuffer").then((content) => {
2473
+ const dir = dirname4(extractPath);
2474
+ if (!existsSync6(dir)) {
2475
+ mkdirSync(dir, { recursive: true });
2476
+ }
2477
+ writeFileSync2(extractPath, content);
2478
+ })
2479
+ );
2480
+ });
2481
+ await Promise.all(extractPromises);
2482
+ const extractedRoot = join9(tempDir, "playcademy", "addons", "playcademy");
2483
+ if (!existsSync6(extractedRoot)) {
2484
+ throw new Error(
2485
+ "Unexpected addon zip layout \u2014 expected playcademy/addons/playcademy"
2486
+ );
2462
2487
  }
2463
- const extractPath = join9(destDir, relativePath);
2464
- extractPromises.push(
2465
- file.async("nodebuffer").then((content) => {
2466
- const dir = dirname4(extractPath);
2467
- if (!existsSync6(dir)) {
2468
- mkdirSync(dir, { recursive: true });
2469
- }
2470
- writeFileSync2(extractPath, content);
2471
- })
2472
- );
2473
- });
2474
- await Promise.all(extractPromises);
2475
- const extractedRoot = join9(destDir, "playcademy", "addons", "playcademy");
2476
- if (existsSync6(extractedRoot)) {
2477
2488
  if (existsSync6(targetDir)) {
2478
- await rm(targetDir, { recursive: true, force: true });
2489
+ renameSync2(targetDir, backupDir);
2490
+ }
2491
+ try {
2492
+ renameSync2(extractedRoot, targetDir);
2493
+ } catch (swapError) {
2494
+ if (existsSync6(backupDir)) {
2495
+ renameSync2(backupDir, targetDir);
2496
+ }
2497
+ throw swapError;
2498
+ }
2499
+ if (existsSync6(backupDir)) {
2500
+ await rm(backupDir, { recursive: true, force: true });
2479
2501
  }
2480
- await rename(extractedRoot, targetDir);
2481
- const extractedParent = join9(destDir, "playcademy");
2482
- await rm(extractedParent, { recursive: true, force: true });
2502
+ } finally {
2503
+ await rm(tempDir, { recursive: true, force: true });
2483
2504
  }
2484
2505
  },
2485
- "Playcademy Addon extracted",
2486
- { silent: true }
2506
+ "Playcademy addon extracted",
2507
+ { silent: options?.silent }
2487
2508
  );
2488
2509
  }
2489
2510
 
@@ -2558,7 +2579,7 @@ var godotFrameworks = [
2558
2579
  color: magenta,
2559
2580
  description: "Godot 4 with Playcademy addon",
2560
2581
  source: { location: `${TEMPLATE_REPOS.SUPERBUILDERS}/godot-template` },
2561
- afterFetch: godotAfterFetch
2582
+ afterFetch: ({ destDir }) => downloadAndExtractAddon(destDir, { silent: true })
2562
2583
  }
2563
2584
  ]
2564
2585
  }
@@ -2794,7 +2815,7 @@ function ensureRootGitignore(workspace = getWorkspace()) {
2794
2815
 
2795
2816
  // src/lib/init/project.ts
2796
2817
  import { existsSync as existsSync9, mkdirSync as mkdirSync3 } from "fs";
2797
- import { resolve as resolve5 } from "path";
2818
+ import { resolve as resolve6 } from "path";
2798
2819
  import { confirm as confirm2, input, select as select3 } from "@inquirer/prompts";
2799
2820
  async function promptForProjectDirectory(projectDir) {
2800
2821
  let dir = projectDir;
@@ -2821,7 +2842,7 @@ async function promptForProjectDirectory(projectDir) {
2821
2842
  cancelled: false
2822
2843
  };
2823
2844
  }
2824
- const targetDir = resolve5(process.cwd(), dir);
2845
+ const targetDir = resolve6(process.cwd(), dir);
2825
2846
  if (existsSync9(targetDir)) {
2826
2847
  logger.newLine();
2827
2848
  logger.admonition("warning", "Directory Exists", [`Directory "${dir}" already exists.`]);
@@ -2868,7 +2889,7 @@ import { bold as bold4, cyan as cyan4 } from "colorette";
2868
2889
 
2869
2890
  // src/lib/init/scaffold.ts
2870
2891
  import { existsSync as existsSync12, mkdirSync as mkdirSync6, readFileSync as readFileSync7, writeFileSync as writeFileSync7 } from "fs";
2871
- import { join as join14, resolve as resolve6 } from "path";
2892
+ import { join as join14, resolve as resolve7 } from "path";
2872
2893
 
2873
2894
  // src/lib/init/auth.ts
2874
2895
  import { existsSync as existsSync10, mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "fs";
@@ -3024,7 +3045,7 @@ import { existsSync as existsSync11, mkdirSync as mkdirSync5, readFileSync as re
3024
3045
  import { join as join13 } from "node:path";
3025
3046
 
3026
3047
  // src/version.ts
3027
- var cliVersion = false ? "0.0.0-dev" : "0.21.1-beta.2";
3048
+ var cliVersion = false ? "0.0.0-dev" : "0.22.0";
3028
3049
 
3029
3050
  // src/lib/init/database.ts
3030
3051
  var drizzleConfigTemplate = loadTemplateString("database/drizzle-config.ts");
@@ -3124,7 +3145,7 @@ var sampleKvRouteTemplate = loadTemplateString("api/sample-kv.ts");
3124
3145
  var sampleBucketRouteTemplate = loadTemplateString("api/sample-bucket.ts");
3125
3146
  var playcademyGitignoreTemplate = loadTemplateString("playcademy-gitignore");
3126
3147
  async function scaffoldApiDirectory(apiDirectory, sampleRoutes) {
3127
- const apiPath = resolve6(getWorkspace(), apiDirectory);
3148
+ const apiPath = resolve7(getWorkspace(), apiDirectory);
3128
3149
  const samplePath = join14(apiPath, "sample");
3129
3150
  if (!existsSync12(apiPath)) {
3130
3151
  mkdirSync6(apiPath, { recursive: true });
@@ -3137,7 +3158,7 @@ async function scaffoldApiDirectory(apiDirectory, sampleRoutes) {
3137
3158
  }
3138
3159
  }
3139
3160
  function validateApiDirectoryDoesNotExist(value) {
3140
- const dirPath = resolve6(getWorkspace(), value.trim());
3161
+ const dirPath = resolve7(getWorkspace(), value.trim());
3141
3162
  if (existsSync12(dirPath)) {
3142
3163
  return `Directory "${value.trim()}" already exists. Please choose a different name or remove the existing directory.`;
3143
3164
  }
@@ -3193,7 +3214,7 @@ async function scaffoldIntegrations(appName, options) {
3193
3214
  return depsAdded;
3194
3215
  }
3195
3216
  function addPlaycademySdk() {
3196
- const pkgPath = resolve6(getWorkspace(), "package.json");
3217
+ const pkgPath = resolve7(getWorkspace(), "package.json");
3197
3218
  const pkg = JSON.parse(readFileSync7(pkgPath, "utf8"));
3198
3219
  const hasSdk = pkg.dependencies?.["@playcademy/sdk"] || pkg.devDependencies?.["@playcademy/sdk"];
3199
3220
  if (hasSdk) {
@@ -3421,7 +3442,7 @@ async function selectConfigFormat(hasPackageJson2) {
3421
3442
  // src/lib/init/types.ts
3422
3443
  import { execSync as execSync4 } from "node:child_process";
3423
3444
  import { existsSync as existsSync15, readFileSync as readFileSync9, writeFileSync as writeFileSync9 } from "node:fs";
3424
- import { dirname as dirname5, join as join17, resolve as resolve7 } from "node:path";
3445
+ import { dirname as dirname5, join as join17, resolve as resolve8 } from "node:path";
3425
3446
  import { fileURLToPath as fileURLToPath2 } from "node:url";
3426
3447
 
3427
3448
  // src/lib/bundle/backend.ts
@@ -3592,7 +3613,7 @@ function getDepVersions() {
3592
3613
  return { honoVersion: "^4.9.9", workersTypesVersion: "^4.20251011.0" };
3593
3614
  }
3594
3615
  try {
3595
- const pkgPath = resolve7(
3616
+ const pkgPath = resolve8(
3596
3617
  dirname5(fileURLToPath2(import.meta.url)),
3597
3618
  "..",
3598
3619
  "..",
@@ -3888,7 +3909,7 @@ async function runInit(options = {}) {
3888
3909
  timebackCourses: timebackConfig ?? void 0
3889
3910
  };
3890
3911
  const configContent = configFormat === "js" ? generateJsConfig(configOptions) : generateJsonConfig(configOptions);
3891
- const configPath = resolve8(getWorkspace(), configFileName);
3912
+ const configPath = resolve9(getWorkspace(), configFileName);
3892
3913
  writeFileSync10(configPath, configContent, "utf8");
3893
3914
  await formatConfigWithPrettier(configPath);
3894
3915
  if (database || auth || kv || bucket) {
package/dist/constants.js CHANGED
@@ -20,7 +20,7 @@ var SAMPLE_BUCKET_FILENAME = "bucket.ts";
20
20
  // ../better-auth/package.json
21
21
  var package_default = {
22
22
  name: "@playcademy/better-auth",
23
- version: "0.0.13-beta.2",
23
+ version: "0.0.13",
24
24
  type: "module",
25
25
  exports: {
26
26
  "./server": {
package/dist/db.js CHANGED
@@ -36,7 +36,7 @@ var DEFAULT_API_ROUTES_DIRECTORY = join2(SERVER_ROOT_DIRECTORY, "api");
36
36
  // ../better-auth/package.json
37
37
  var package_default = {
38
38
  name: "@playcademy/better-auth",
39
- version: "0.0.13-beta.2",
39
+ version: "0.0.13",
40
40
  type: "module",
41
41
  exports: {
42
42
  "./server": {
package/dist/index.js CHANGED
@@ -326,7 +326,7 @@ var SAMPLE_BUCKET_FILENAME = "bucket.ts";
326
326
  // ../better-auth/package.json
327
327
  var package_default = {
328
328
  name: "@playcademy/better-auth",
329
- version: "0.0.13-beta.2",
329
+ version: "0.0.13",
330
330
  type: "module",
331
331
  exports: {
332
332
  "./server": {
@@ -4057,7 +4057,7 @@ import { existsSync as existsSync9, mkdirSync as mkdirSync2, readFileSync as rea
4057
4057
  import { join as join13 } from "node:path";
4058
4058
 
4059
4059
  // src/version.ts
4060
- var cliVersion = false ? "0.0.0-dev" : "0.21.1-beta.2";
4060
+ var cliVersion = false ? "0.0.0-dev" : "0.22.0";
4061
4061
 
4062
4062
  // src/lib/init/database.ts
4063
4063
  var drizzleConfigTemplate = loadTemplateString("database/drizzle-config.ts");
@@ -5529,17 +5529,17 @@ import { cyan as cyan4, magenta as magenta2, yellow as yellow4 } from "colorette
5529
5529
  // src/lib/init/engine/registry.ts
5530
5530
  import { blue as blue2, cyan as cyan3, green as green3, magenta, red as red3, yellow as yellow3 } from "colorette";
5531
5531
 
5532
- // src/lib/init/engine/hooks.ts
5533
- import { existsSync as existsSync17, mkdirSync as mkdirSync4, writeFileSync as writeFileSync10 } from "fs";
5534
- import { rename, rm } from "fs/promises";
5535
- import { dirname as dirname5, join as join22 } from "path";
5532
+ // src/lib/godot/addon.ts
5533
+ import { existsSync as existsSync17, mkdirSync as mkdirSync4, mkdtempSync as mkdtempSync2, renameSync as renameSync2, writeFileSync as writeFileSync10 } from "fs";
5534
+ import { rm } from "fs/promises";
5535
+ import { dirname as dirname5, join as join22, resolve as resolve8, sep as sep2 } from "path";
5536
5536
  import JSZip from "jszip";
5537
- async function godotAfterFetch({ destDir }) {
5538
- const addonsDir = join22(destDir, "addons");
5537
+ async function downloadAndExtractAddon(projectDir, options) {
5538
+ const addonsDir = join22(projectDir, "addons");
5539
5539
  const targetDir = join22(addonsDir, "playcademy");
5540
5540
  let zipData;
5541
5541
  await runStep(
5542
- "Downloading Playcademy Addon for Godot",
5542
+ "Downloading Playcademy addon",
5543
5543
  async () => {
5544
5544
  const response = await fetch(GODOT_ADDON_URL);
5545
5545
  if (!response.ok) {
@@ -5549,45 +5549,66 @@ async function godotAfterFetch({ destDir }) {
5549
5549
  }
5550
5550
  zipData = await response.arrayBuffer();
5551
5551
  },
5552
- "Playcademy Addon downloaded",
5553
- { silent: true }
5552
+ "Playcademy addon downloaded",
5553
+ { silent: options?.silent }
5554
5554
  );
5555
5555
  await runStep(
5556
- "Extracting Playcademy Addon",
5556
+ "Extracting addon",
5557
5557
  async () => {
5558
5558
  const zip = await JSZip.loadAsync(zipData);
5559
5559
  if (!existsSync17(addonsDir)) {
5560
5560
  mkdirSync4(addonsDir, { recursive: true });
5561
5561
  }
5562
- const extractPromises = [];
5563
- zip.forEach((relativePath, file) => {
5564
- if (file.dir) {
5565
- return;
5562
+ const tempDir = mkdtempSync2(join22(addonsDir, ".playcademy-sync-"));
5563
+ const tempBase = resolve8(tempDir) + sep2;
5564
+ const backupDir = join22(addonsDir, `.playcademy-backup-${Date.now()}`);
5565
+ try {
5566
+ const extractPromises = [];
5567
+ zip.forEach((relativePath, file) => {
5568
+ if (file.dir) {
5569
+ return;
5570
+ }
5571
+ const extractPath = resolve8(tempDir, relativePath);
5572
+ if (!extractPath.startsWith(tempBase)) {
5573
+ return;
5574
+ }
5575
+ extractPromises.push(
5576
+ file.async("nodebuffer").then((content) => {
5577
+ const dir = dirname5(extractPath);
5578
+ if (!existsSync17(dir)) {
5579
+ mkdirSync4(dir, { recursive: true });
5580
+ }
5581
+ writeFileSync10(extractPath, content);
5582
+ })
5583
+ );
5584
+ });
5585
+ await Promise.all(extractPromises);
5586
+ const extractedRoot = join22(tempDir, "playcademy", "addons", "playcademy");
5587
+ if (!existsSync17(extractedRoot)) {
5588
+ throw new Error(
5589
+ "Unexpected addon zip layout \u2014 expected playcademy/addons/playcademy"
5590
+ );
5566
5591
  }
5567
- const extractPath = join22(destDir, relativePath);
5568
- extractPromises.push(
5569
- file.async("nodebuffer").then((content) => {
5570
- const dir = dirname5(extractPath);
5571
- if (!existsSync17(dir)) {
5572
- mkdirSync4(dir, { recursive: true });
5573
- }
5574
- writeFileSync10(extractPath, content);
5575
- })
5576
- );
5577
- });
5578
- await Promise.all(extractPromises);
5579
- const extractedRoot = join22(destDir, "playcademy", "addons", "playcademy");
5580
- if (existsSync17(extractedRoot)) {
5581
5592
  if (existsSync17(targetDir)) {
5582
- await rm(targetDir, { recursive: true, force: true });
5593
+ renameSync2(targetDir, backupDir);
5594
+ }
5595
+ try {
5596
+ renameSync2(extractedRoot, targetDir);
5597
+ } catch (swapError) {
5598
+ if (existsSync17(backupDir)) {
5599
+ renameSync2(backupDir, targetDir);
5600
+ }
5601
+ throw swapError;
5602
+ }
5603
+ if (existsSync17(backupDir)) {
5604
+ await rm(backupDir, { recursive: true, force: true });
5583
5605
  }
5584
- await rename(extractedRoot, targetDir);
5585
- const extractedParent = join22(destDir, "playcademy");
5586
- await rm(extractedParent, { recursive: true, force: true });
5606
+ } finally {
5607
+ await rm(tempDir, { recursive: true, force: true });
5587
5608
  }
5588
5609
  },
5589
- "Playcademy Addon extracted",
5590
- { silent: true }
5610
+ "Playcademy addon extracted",
5611
+ { silent: options?.silent }
5591
5612
  );
5592
5613
  }
5593
5614
 
@@ -5662,7 +5683,7 @@ var godotFrameworks = [
5662
5683
  color: magenta,
5663
5684
  description: "Godot 4 with Playcademy addon",
5664
5685
  source: { location: `${TEMPLATE_REPOS.SUPERBUILDERS}/godot-template` },
5665
- afterFetch: godotAfterFetch
5686
+ afterFetch: ({ destDir }) => downloadAndExtractAddon(destDir, { silent: true })
5666
5687
  }
5667
5688
  ]
5668
5689
  }
@@ -5993,7 +6014,7 @@ async function applyEngineSelection(selection, destDir, options = {}) {
5993
6014
 
5994
6015
  // src/lib/init/project.ts
5995
6016
  import { existsSync as existsSync19, mkdirSync as mkdirSync6 } from "fs";
5996
- import { resolve as resolve8 } from "path";
6017
+ import { resolve as resolve9 } from "path";
5997
6018
  import { confirm as confirm4, input as input2, select as select4 } from "@inquirer/prompts";
5998
6019
  async function promptForProjectDirectory(projectDir) {
5999
6020
  let dir = projectDir;
@@ -6020,7 +6041,7 @@ async function promptForProjectDirectory(projectDir) {
6020
6041
  cancelled: false
6021
6042
  };
6022
6043
  }
6023
- const targetDir = resolve8(process.cwd(), dir);
6044
+ const targetDir = resolve9(process.cwd(), dir);
6024
6045
  if (existsSync19(targetDir)) {
6025
6046
  logger.newLine();
6026
6047
  logger.admonition("warning", "Directory Exists", [`Directory "${dir}" already exists.`]);
@@ -6064,7 +6085,7 @@ function createProjectDirectory(info) {
6064
6085
  // src/lib/init/run.ts
6065
6086
  import { execSync as execSync6 } from "child_process";
6066
6087
  import { writeFileSync as writeFileSync11 } from "fs";
6067
- import { resolve as resolve9 } from "path";
6088
+ import { resolve as resolve10 } from "path";
6068
6089
  import { confirm as confirm5 } from "@inquirer/prompts";
6069
6090
  init_file_loader();
6070
6091
  var motd = `
@@ -6225,7 +6246,7 @@ async function runInit(options = {}) {
6225
6246
  timebackCourses: timebackConfig ?? void 0
6226
6247
  };
6227
6248
  const configContent = configFormat === "js" ? generateJsConfig(configOptions) : generateJsonConfig(configOptions);
6228
- const configPath = resolve9(getWorkspace(), configFileName);
6249
+ const configPath = resolve10(getWorkspace(), configFileName);
6229
6250
  writeFileSync11(configPath, configContent, "utf8");
6230
6251
  await formatConfigWithPrettier(configPath);
6231
6252
  if (database || auth || kv || bucket) {
@@ -6542,14 +6563,14 @@ function readServerInfo(type, projectRoot) {
6542
6563
  return servers[0] || null;
6543
6564
  }
6544
6565
  async function isPortInUse(port) {
6545
- return new Promise((resolve13) => {
6566
+ return new Promise((resolve14) => {
6546
6567
  const server = createServer();
6547
6568
  server.once("error", () => {
6548
- resolve13(true);
6569
+ resolve14(true);
6549
6570
  });
6550
6571
  server.once("listening", () => {
6551
6572
  server.close();
6552
- resolve13(false);
6573
+ resolve14(false);
6553
6574
  });
6554
6575
  server.listen(port);
6555
6576
  });
@@ -6563,7 +6584,7 @@ async function waitForPort(port, timeoutMs = 5e3) {
6563
6584
  Stop the other server or specify a different port with --port <number>.`
6564
6585
  );
6565
6586
  }
6566
- await new Promise((resolve13) => setTimeout(resolve13, 100));
6587
+ await new Promise((resolve14) => setTimeout(resolve14, 100));
6567
6588
  }
6568
6589
  }
6569
6590
 
@@ -6856,7 +6877,7 @@ function getMonorepoRoot() {
6856
6877
  var isCompiledBinary = typeof IS_COMPILED_BINARY !== "undefined" && IS_COMPILED_BINARY;
6857
6878
 
6858
6879
  // src/lib/build/raw-loader.ts
6859
- import { resolve as resolve10 } from "node:path";
6880
+ import { resolve as resolve11 } from "node:path";
6860
6881
  var RAW_IMPORT_SUFFIX = "?raw";
6861
6882
  var RAW_IMPORT_FILTER = /\?raw$/;
6862
6883
  var RAW_NAMESPACE = "playcademy-raw";
@@ -6871,7 +6892,7 @@ function resolveRawImportPath(path4, resolveDir) {
6871
6892
  if (!sourcePath.startsWith(".") && !sourcePath.startsWith("/")) {
6872
6893
  return void 0;
6873
6894
  }
6874
- return resolve10(resolveDir, sourcePath);
6895
+ return resolve11(resolveDir, sourcePath);
6875
6896
  }
6876
6897
 
6877
6898
  // src/lib/build/text-loader-patterns.ts
@@ -10608,12 +10629,12 @@ async function getSchemaStatementCount(previousSchemaSnapshot, lastAppliedMigrat
10608
10629
 
10609
10630
  // src/lib/deploy/validate.ts
10610
10631
  import { existsSync as existsSync27 } from "fs";
10611
- import { resolve as resolve11 } from "path";
10632
+ import { resolve as resolve12 } from "path";
10612
10633
  function validateBuildPath(path4) {
10613
10634
  if (!path4.trim()) {
10614
10635
  return "Build path is required";
10615
10636
  }
10616
- const resolvedPath = resolve11(path4.trim());
10637
+ const resolvedPath = resolve12(path4.trim());
10617
10638
  if (!existsSync27(resolvedPath)) {
10618
10639
  return `Build path not found: ${path4.trim()}`;
10619
10640
  }
@@ -11838,7 +11859,7 @@ function hasOptionalFieldsMissing(missing) {
11838
11859
  // src/lib/deploy/steps.ts
11839
11860
  import { existsSync as existsSync28 } from "fs";
11840
11861
  import { readFile as readFile6 } from "fs/promises";
11841
- import { basename as basename3, join as join39, resolve as resolve12 } from "path";
11862
+ import { basename as basename3, join as join39, resolve as resolve13 } from "path";
11842
11863
  function prepareGameMetadata(config) {
11843
11864
  return {
11844
11865
  displayName: config.displayName,
@@ -11851,7 +11872,7 @@ function prepareGameMetadata(config) {
11851
11872
  };
11852
11873
  }
11853
11874
  async function prepareBuildFile(buildPath) {
11854
- const resolvedPath = resolve12(buildPath);
11875
+ const resolvedPath = resolve13(buildPath);
11855
11876
  if (resolvedPath.endsWith(".zip") && existsSync28(resolvedPath)) {
11856
11877
  const buffer = await readFile6(resolvedPath);
11857
11878
  const uint8Array = new Uint8Array(buffer);
@@ -12649,7 +12670,7 @@ function getErrorHtml(error) {
12649
12670
 
12650
12671
  // src/lib/auth/http-server/server.ts
12651
12672
  async function startCallbackServer(timeoutMs) {
12652
- return new Promise((resolve13) => {
12673
+ return new Promise((resolve14) => {
12653
12674
  let server = null;
12654
12675
  let timeoutId = null;
12655
12676
  function cleanup(callback) {
@@ -12667,7 +12688,7 @@ async function startCallbackServer(timeoutMs) {
12667
12688
  }
12668
12689
  timeoutId = setTimeout(() => {
12669
12690
  cleanup(() => {
12670
- resolve13({
12691
+ resolve14({
12671
12692
  success: false,
12672
12693
  error: "Authentication timed out. Please try again."
12673
12694
  });
@@ -12681,7 +12702,7 @@ async function startCallbackServer(timeoutMs) {
12681
12702
  const userId = url.searchParams.get("userId");
12682
12703
  if (!sessionToken || !email || !userId) {
12683
12704
  cleanup(() => {
12684
- resolve13({
12705
+ resolve14({
12685
12706
  success: false,
12686
12707
  error: "Invalid callback data received"
12687
12708
  });
@@ -12693,7 +12714,7 @@ async function startCallbackServer(timeoutMs) {
12693
12714
  res.writeHead(200, { "Content-Type": "text/html" });
12694
12715
  res.end(SUCCESS_HTML);
12695
12716
  cleanup(() => {
12696
- resolve13({
12717
+ resolve14({
12697
12718
  success: true,
12698
12719
  data: { sessionToken, email, userId }
12699
12720
  });
@@ -12716,10 +12737,10 @@ import { dim as dim9 } from "colorette";
12716
12737
 
12717
12738
  // src/lib/bucket/collect.ts
12718
12739
  import { readdirSync as readdirSync5, statSync as statSync4 } from "fs";
12719
- import { join as join42, relative as relative6, sep as sep2 } from "path";
12740
+ import { join as join42, relative as relative6, sep as sep3 } from "path";
12720
12741
  function shouldSkipFile(filePath, baseDir, gitignorePatterns) {
12721
12742
  const relativePath = relative6(baseDir, filePath);
12722
- const pathParts = relativePath.split(sep2);
12743
+ const pathParts = relativePath.split(sep3);
12723
12744
  const alwaysSkip = BUCKET_ALWAYS_SKIP;
12724
12745
  for (const part of pathParts) {
12725
12746
  if (alwaysSkip.includes(part)) {
@@ -13807,7 +13828,7 @@ function formatExit(name, code, signal) {
13807
13828
  return `${name} exited`;
13808
13829
  }
13809
13830
  function upgradeStandalone(targetVersion, channel) {
13810
- return new Promise((resolve13, reject) => {
13831
+ return new Promise((resolve14, reject) => {
13811
13832
  const curl = spawn("curl", ["-fsSL", INSTALL_SCRIPT_URL], {
13812
13833
  stdio: ["ignore", "pipe", "pipe"]
13813
13834
  });
@@ -13841,7 +13862,7 @@ function upgradeStandalone(targetVersion, channel) {
13841
13862
  if (error) {
13842
13863
  reject(error);
13843
13864
  } else {
13844
- resolve13({ stdout: stdout2, stderr });
13865
+ resolve14({ stdout: stdout2, stderr });
13845
13866
  }
13846
13867
  }
13847
13868
  function tryFinalize() {
@@ -353,9 +353,9 @@ var init_routes = __esm({
353
353
  // ../edge-play/src/entry/metadata.ts
354
354
  function getRuntimeMetadata() {
355
355
  return {
356
- cliVersion: true ? "0.21.1-beta.2" : "0.0.0-dev",
357
- sdkVersion: true ? "0.8.1-beta.2" : "0.0.0-dev",
358
- buildId: true ? "2e237b524a89" : "dev-source"
356
+ cliVersion: true ? "0.22.0" : "0.0.0-dev",
357
+ sdkVersion: true ? "0.9.0" : "0.0.0-dev",
358
+ buildId: true ? "1afaa748bb29" : "dev-source"
359
359
  };
360
360
  }
361
361
  var init_metadata = __esm({
@@ -1,7 +1,7 @@
1
1
  {
2
- "cliVersion": "0.21.1-beta.2",
3
- "sdkVersion": "0.8.1-beta.2",
4
- "runtimeBuildId": "2e237b524a89",
5
- "inputFingerprint": "2e237b524a898fec8226e02ad2237041fc19c6c9551db3cd59565072961c6bb5",
2
+ "cliVersion": "0.22.0",
3
+ "sdkVersion": "0.9.0",
4
+ "runtimeBuildId": "1afaa748bb29",
5
+ "inputFingerprint": "1afaa748bb29d1cff8b2e3f72ef7edac7a62ec98fa06e02d42adc2efa1334aca",
6
6
  "entry": "index.js"
7
7
  }
package/dist/utils.js CHANGED
@@ -481,7 +481,7 @@ var DEFAULT_API_ROUTES_DIRECTORY = join2(SERVER_ROOT_DIRECTORY, "api");
481
481
  // ../better-auth/package.json
482
482
  var package_default = {
483
483
  name: "@playcademy/better-auth",
484
- version: "0.0.13-beta.2",
484
+ version: "0.0.13",
485
485
  type: "module",
486
486
  exports: {
487
487
  "./server": {
@@ -2031,14 +2031,14 @@ function readServerInfo(type, projectRoot) {
2031
2031
  return servers[0] || null;
2032
2032
  }
2033
2033
  async function isPortInUse(port) {
2034
- return new Promise((resolve7) => {
2034
+ return new Promise((resolve8) => {
2035
2035
  const server = createServer();
2036
2036
  server.once("error", () => {
2037
- resolve7(true);
2037
+ resolve8(true);
2038
2038
  });
2039
2039
  server.once("listening", () => {
2040
2040
  server.close();
2041
- resolve7(false);
2041
+ resolve8(false);
2042
2042
  });
2043
2043
  server.listen(port);
2044
2044
  });
@@ -2052,7 +2052,7 @@ async function waitForPort(port, timeoutMs = 5e3) {
2052
2052
  Stop the other server or specify a different port with --port <number>.`
2053
2053
  );
2054
2054
  }
2055
- await new Promise((resolve7) => setTimeout(resolve7, 100));
2055
+ await new Promise((resolve8) => setTimeout(resolve8, 100));
2056
2056
  }
2057
2057
  }
2058
2058
 
@@ -2591,7 +2591,7 @@ import { existsSync as existsSync9, mkdirSync as mkdirSync2, writeFileSync as wr
2591
2591
  import { dirname as dirname4, join as join14 } from "node:path";
2592
2592
 
2593
2593
  // src/version.ts
2594
- var cliVersion = false ? "0.0.0-dev" : "0.21.1-beta.2";
2594
+ var cliVersion = false ? "0.0.0-dev" : "0.22.0";
2595
2595
 
2596
2596
  // src/lib/build/binary-resource.ts
2597
2597
  function writeFileTree(baseDir, files) {
@@ -5799,17 +5799,17 @@ import { cyan as cyan4, magenta as magenta2, yellow as yellow4 } from "colorette
5799
5799
  // src/lib/init/engine/registry.ts
5800
5800
  import { blue as blue2, cyan as cyan3, green as green3, magenta, red as red3, yellow as yellow3 } from "colorette";
5801
5801
 
5802
- // src/lib/init/engine/hooks.ts
5803
- import { existsSync as existsSync15, mkdirSync as mkdirSync4, writeFileSync as writeFileSync7 } from "fs";
5804
- import { rename, rm as rm2 } from "fs/promises";
5805
- import { dirname as dirname8, join as join23 } from "path";
5802
+ // src/lib/godot/addon.ts
5803
+ import { existsSync as existsSync15, mkdirSync as mkdirSync4, mkdtempSync as mkdtempSync2, renameSync, writeFileSync as writeFileSync7 } from "fs";
5804
+ import { rm as rm2 } from "fs/promises";
5805
+ import { dirname as dirname8, join as join23, resolve as resolve7, sep } from "path";
5806
5806
  import JSZip from "jszip";
5807
- async function godotAfterFetch({ destDir }) {
5808
- const addonsDir = join23(destDir, "addons");
5807
+ async function downloadAndExtractAddon(projectDir, options) {
5808
+ const addonsDir = join23(projectDir, "addons");
5809
5809
  const targetDir = join23(addonsDir, "playcademy");
5810
5810
  let zipData;
5811
5811
  await runStep(
5812
- "Downloading Playcademy Addon for Godot",
5812
+ "Downloading Playcademy addon",
5813
5813
  async () => {
5814
5814
  const response = await fetch(GODOT_ADDON_URL);
5815
5815
  if (!response.ok) {
@@ -5819,45 +5819,66 @@ async function godotAfterFetch({ destDir }) {
5819
5819
  }
5820
5820
  zipData = await response.arrayBuffer();
5821
5821
  },
5822
- "Playcademy Addon downloaded",
5823
- { silent: true }
5822
+ "Playcademy addon downloaded",
5823
+ { silent: options?.silent }
5824
5824
  );
5825
5825
  await runStep(
5826
- "Extracting Playcademy Addon",
5826
+ "Extracting addon",
5827
5827
  async () => {
5828
5828
  const zip = await JSZip.loadAsync(zipData);
5829
5829
  if (!existsSync15(addonsDir)) {
5830
5830
  mkdirSync4(addonsDir, { recursive: true });
5831
5831
  }
5832
- const extractPromises = [];
5833
- zip.forEach((relativePath, file) => {
5834
- if (file.dir) {
5835
- return;
5832
+ const tempDir = mkdtempSync2(join23(addonsDir, ".playcademy-sync-"));
5833
+ const tempBase = resolve7(tempDir) + sep;
5834
+ const backupDir = join23(addonsDir, `.playcademy-backup-${Date.now()}`);
5835
+ try {
5836
+ const extractPromises = [];
5837
+ zip.forEach((relativePath, file) => {
5838
+ if (file.dir) {
5839
+ return;
5840
+ }
5841
+ const extractPath = resolve7(tempDir, relativePath);
5842
+ if (!extractPath.startsWith(tempBase)) {
5843
+ return;
5844
+ }
5845
+ extractPromises.push(
5846
+ file.async("nodebuffer").then((content) => {
5847
+ const dir = dirname8(extractPath);
5848
+ if (!existsSync15(dir)) {
5849
+ mkdirSync4(dir, { recursive: true });
5850
+ }
5851
+ writeFileSync7(extractPath, content);
5852
+ })
5853
+ );
5854
+ });
5855
+ await Promise.all(extractPromises);
5856
+ const extractedRoot = join23(tempDir, "playcademy", "addons", "playcademy");
5857
+ if (!existsSync15(extractedRoot)) {
5858
+ throw new Error(
5859
+ "Unexpected addon zip layout \u2014 expected playcademy/addons/playcademy"
5860
+ );
5836
5861
  }
5837
- const extractPath = join23(destDir, relativePath);
5838
- extractPromises.push(
5839
- file.async("nodebuffer").then((content) => {
5840
- const dir = dirname8(extractPath);
5841
- if (!existsSync15(dir)) {
5842
- mkdirSync4(dir, { recursive: true });
5843
- }
5844
- writeFileSync7(extractPath, content);
5845
- })
5846
- );
5847
- });
5848
- await Promise.all(extractPromises);
5849
- const extractedRoot = join23(destDir, "playcademy", "addons", "playcademy");
5850
- if (existsSync15(extractedRoot)) {
5851
5862
  if (existsSync15(targetDir)) {
5852
- await rm2(targetDir, { recursive: true, force: true });
5863
+ renameSync(targetDir, backupDir);
5864
+ }
5865
+ try {
5866
+ renameSync(extractedRoot, targetDir);
5867
+ } catch (swapError) {
5868
+ if (existsSync15(backupDir)) {
5869
+ renameSync(backupDir, targetDir);
5870
+ }
5871
+ throw swapError;
5872
+ }
5873
+ if (existsSync15(backupDir)) {
5874
+ await rm2(backupDir, { recursive: true, force: true });
5853
5875
  }
5854
- await rename(extractedRoot, targetDir);
5855
- const extractedParent = join23(destDir, "playcademy");
5856
- await rm2(extractedParent, { recursive: true, force: true });
5876
+ } finally {
5877
+ await rm2(tempDir, { recursive: true, force: true });
5857
5878
  }
5858
5879
  },
5859
- "Playcademy Addon extracted",
5860
- { silent: true }
5880
+ "Playcademy addon extracted",
5881
+ { silent: options?.silent }
5861
5882
  );
5862
5883
  }
5863
5884
 
@@ -5932,7 +5953,7 @@ var godotFrameworks = [
5932
5953
  color: magenta,
5933
5954
  description: "Godot 4 with Playcademy addon",
5934
5955
  source: { location: `${TEMPLATE_REPOS.SUPERBUILDERS}/godot-template` },
5935
- afterFetch: godotAfterFetch
5956
+ afterFetch: ({ destDir }) => downloadAndExtractAddon(destDir, { silent: true })
5936
5957
  }
5937
5958
  ]
5938
5959
  }
package/dist/version.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var cliVersion = false ? "0.0.0-dev" : "0.21.1-beta.2";
2
+ var cliVersion = false ? "0.0.0-dev" : "0.22.0";
3
3
  export {
4
4
  cliVersion
5
5
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "playcademy",
3
- "version": "0.21.1-beta.2",
3
+ "version": "0.22.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -50,7 +50,7 @@
50
50
  },
51
51
  "dependencies": {
52
52
  "@inquirer/prompts": "^7.8.6",
53
- "@playcademy/sdk": "0.8.0",
53
+ "@playcademy/sdk": "0.9.0",
54
54
  "chokidar": "^4.0.3",
55
55
  "colorette": "^2.0.20",
56
56
  "commander": "^14.0.1",