playcademy 0.22.0 → 0.22.1-beta.1

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
@@ -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",
1068
+ version: "0.0.14-beta.1",
1069
1069
  type: "module",
1070
1070
  exports: {
1071
1071
  "./server": {
@@ -3045,7 +3045,7 @@ import { existsSync as existsSync11, mkdirSync as mkdirSync5, readFileSync as re
3045
3045
  import { join as join13 } from "node:path";
3046
3046
 
3047
3047
  // src/version.ts
3048
- var cliVersion = false ? "0.0.0-dev" : "0.22.0";
3048
+ var cliVersion = false ? "0.0.0-dev" : "0.22.1-beta.1";
3049
3049
 
3050
3050
  // src/lib/init/database.ts
3051
3051
  var drizzleConfigTemplate = loadTemplateString("database/drizzle-config.ts");
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",
23
+ version: "0.0.14-beta.1",
24
24
  type: "module",
25
25
  exports: {
26
26
  "./server": {
package/dist/db.d.ts CHANGED
@@ -134,6 +134,14 @@ declare function getBucket(mf: Miniflare): Promise<unknown | null>;
134
134
  */
135
135
  declare function executeSeedFile(seedFilePath: string, mf: Miniflare, envSecrets?: Record<string, string>): Promise<void>;
136
136
 
137
+ /**
138
+ * Game Types
139
+ *
140
+ * Literal types and API DTOs. Database row types are in @playcademy/data/types.
141
+ *
142
+ * @module types/game
143
+ */
144
+
137
145
  /** Log entry captured from seed worker console output */
138
146
  interface SeedLogEntry {
139
147
  /** Log level (log, warn, error, info) */
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",
39
+ version: "0.0.14-beta.1",
40
40
  type: "module",
41
41
  exports: {
42
42
  "./server": {
package/dist/index.d.ts CHANGED
@@ -3,6 +3,14 @@ import { SchemaInfo } from '@playcademy/cloudflare';
3
3
  import { PlaycademyClient } from '@playcademy/sdk/internal';
4
4
  import * as drizzle_orm_pg_core from 'drizzle-orm/pg-core';
5
5
 
6
+ /**
7
+ * User Types
8
+ *
9
+ * Enums, DTOs and API response types. Database row types are in @playcademy/data/types.
10
+ *
11
+ * @module types/user
12
+ */
13
+
6
14
  /**
7
15
  * OpenID Connect UserInfo claims (NOT a database row).
8
16
  */
@@ -1317,6 +1325,7 @@ interface DeploymentDiffOptions {
1317
1325
  backend?: BackendDiff;
1318
1326
  integrations?: IntegrationsDiff;
1319
1327
  secrets?: SecretsDiff;
1328
+ driftLabels?: Set<string>;
1320
1329
  }
1321
1330
 
1322
1331
  /**
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",
329
+ version: "0.0.14-beta.1",
330
330
  type: "module",
331
331
  exports: {
332
332
  "./server": {
@@ -635,6 +635,12 @@ var PLAYCADEMY_BASE_URLS = {
635
635
  };
636
636
  var LOG_COLLECTOR_URL = "https://logs.playcademy.gg";
637
637
 
638
+ // ../constants/src/game.ts
639
+ var GAME_MEMBER_ROLES = {
640
+ OWNER: "owner",
641
+ COLLABORATOR: "collaborator"
642
+ };
643
+
638
644
  // ../constants/src/overworld.ts
639
645
  var ITEM_SLUGS = {
640
646
  /** Primary platform currency */
@@ -3465,6 +3471,243 @@ async function updateConfigFile(configPath, updates, options = {}) {
3465
3471
  await formatConfigWithPrettier(configPath);
3466
3472
  }
3467
3473
  }
3474
+ async function updateConfigScalars(configPath, updates, options = {}) {
3475
+ const entries = Object.entries(updates);
3476
+ const provided = entries.filter(([, value]) => value !== void 0);
3477
+ if (provided.length === 0) {
3478
+ return { written: [], skipped: [] };
3479
+ }
3480
+ const configContent = readFileSync2(configPath, "utf8");
3481
+ const isJson = configPath.endsWith(".json");
3482
+ let result;
3483
+ if (isJson) {
3484
+ result = updateJsonScalars(configContent, configPath, provided);
3485
+ } else {
3486
+ result = updateJsScalars(configContent, configPath, provided);
3487
+ }
3488
+ if (result.written.length > 0 && options.format !== false) {
3489
+ await formatConfigWithPrettier(configPath);
3490
+ }
3491
+ return result;
3492
+ }
3493
+ function updateJsonScalars(content, configPath, updates) {
3494
+ const parsed = JSON.parse(content);
3495
+ const written = [];
3496
+ for (const [field, value] of updates) {
3497
+ if (value === null) {
3498
+ if (field in parsed) {
3499
+ delete parsed[field];
3500
+ written.push(field);
3501
+ }
3502
+ } else {
3503
+ parsed[field] = value;
3504
+ written.push(field);
3505
+ }
3506
+ }
3507
+ if (written.length > 0) {
3508
+ writeFileSync2(configPath, JSON.stringify(parsed, null, 4), "utf8");
3509
+ }
3510
+ return { written, skipped: [] };
3511
+ }
3512
+ function buildScalarPropertyRegex(field) {
3513
+ return new RegExp(
3514
+ `(^|[\\s,{])(${field})(\\s*:\\s*)(['"\`])((?:(?!\\4)[^\\\\\\n\\r])*)\\4`,
3515
+ "gm"
3516
+ );
3517
+ }
3518
+ function fieldKeyPresent(content, field) {
3519
+ const objectRange = findExportDefaultObjectRange(content);
3520
+ if (!objectRange) {
3521
+ return false;
3522
+ }
3523
+ const presenceRegex = new RegExp(`(^|[\\s,{])${field}\\s*:`, "gm");
3524
+ const objectContent = content.slice(objectRange.openBrace + 1, objectRange.closeBrace);
3525
+ for (const match of objectContent.matchAll(presenceRegex)) {
3526
+ const prefix = match[1] ?? "";
3527
+ const keyStart = objectRange.openBrace + 1 + match.index + prefix.length;
3528
+ if (isTopLevelObjectProperty(content, objectRange.openBrace, keyStart)) {
3529
+ return true;
3530
+ }
3531
+ }
3532
+ return false;
3533
+ }
3534
+ function stringifyJsStringLiteral(value) {
3535
+ return JSON.stringify(value);
3536
+ }
3537
+ function updateJsScalars(content, configPath, updates) {
3538
+ const written = [];
3539
+ const skipped = [];
3540
+ let working = content;
3541
+ for (const [field, value] of updates) {
3542
+ const outcome = tryRewriteJsScalar(working, field, value);
3543
+ if (outcome.kind === "written") {
3544
+ working = outcome.content;
3545
+ written.push(field);
3546
+ } else {
3547
+ skipped.push(outcome.skipped);
3548
+ }
3549
+ }
3550
+ if (written.length > 0) {
3551
+ writeFileSync2(configPath, working, "utf8");
3552
+ }
3553
+ return { written, skipped };
3554
+ }
3555
+ function tryRewriteJsScalar(content, field, value) {
3556
+ if (value === null) {
3557
+ return {
3558
+ kind: "skipped",
3559
+ skipped: {
3560
+ field,
3561
+ intendedValue: null,
3562
+ reason: fieldKeyPresent(content, field) ? "removal-unsupported" : "missing"
3563
+ }
3564
+ };
3565
+ }
3566
+ const match = findTopLevelLiteralScalar(content, field);
3567
+ if (match) {
3568
+ const replacement = `${match.prefix}${match.key}${match.separator}${stringifyJsStringLiteral(value)}`;
3569
+ const nextContent = `${content.slice(0, match.start)}${replacement}${content.slice(match.end)}`;
3570
+ return { kind: "written", content: nextContent };
3571
+ }
3572
+ return {
3573
+ kind: "skipped",
3574
+ skipped: {
3575
+ field,
3576
+ intendedValue: value,
3577
+ reason: fieldKeyPresent(content, field) ? "non-literal" : "missing"
3578
+ }
3579
+ };
3580
+ }
3581
+ function findExportDefaultObjectRange(content) {
3582
+ const exportDefaultIndex = content.indexOf("export default");
3583
+ if (exportDefaultIndex === -1) {
3584
+ return null;
3585
+ }
3586
+ const openBrace = content.indexOf("{", exportDefaultIndex);
3587
+ if (openBrace === -1) {
3588
+ return null;
3589
+ }
3590
+ const closeBrace = findMatchingBrace(content, openBrace);
3591
+ return closeBrace === null ? null : { openBrace, closeBrace };
3592
+ }
3593
+ function findTopLevelLiteralScalar(content, field) {
3594
+ const objectRange = findExportDefaultObjectRange(content);
3595
+ if (!objectRange) {
3596
+ return null;
3597
+ }
3598
+ const literalRegex = buildScalarPropertyRegex(field);
3599
+ const objectContent = content.slice(objectRange.openBrace + 1, objectRange.closeBrace);
3600
+ for (const match of objectContent.matchAll(literalRegex)) {
3601
+ const [matchedText, prefix = "", key = "", separator = "", quote = "", literal = ""] = match;
3602
+ const start = objectRange.openBrace + 1 + match.index;
3603
+ const keyStart = start + prefix.length;
3604
+ const isInterpolatedTemplate = quote === "`" && literal.includes("${");
3605
+ if (!isInterpolatedTemplate && isTopLevelObjectProperty(content, objectRange.openBrace, keyStart)) {
3606
+ return {
3607
+ start,
3608
+ end: start + matchedText.length,
3609
+ prefix,
3610
+ key,
3611
+ separator
3612
+ };
3613
+ }
3614
+ }
3615
+ return null;
3616
+ }
3617
+ function findMatchingBrace(content, openBrace) {
3618
+ let depth = 0;
3619
+ let quote = null;
3620
+ let inLineComment = false;
3621
+ let inBlockComment = false;
3622
+ for (let index2 = openBrace; index2 < content.length; index2 += 1) {
3623
+ const char = content[index2];
3624
+ const next = content[index2 + 1];
3625
+ if (inLineComment) {
3626
+ if (char === "\n") {
3627
+ inLineComment = false;
3628
+ }
3629
+ } else if (inBlockComment) {
3630
+ if (char === "*" && next === "/") {
3631
+ inBlockComment = false;
3632
+ index2 += 1;
3633
+ }
3634
+ } else if (quote) {
3635
+ if (char === quote && !isEscapedCharacter(content, index2)) {
3636
+ quote = null;
3637
+ }
3638
+ } else if (char === "/" && next === "/") {
3639
+ inLineComment = true;
3640
+ index2 += 1;
3641
+ } else if (char === "/" && next === "*") {
3642
+ inBlockComment = true;
3643
+ index2 += 1;
3644
+ } else if (char === "'" || char === '"' || char === "`") {
3645
+ quote = char;
3646
+ } else if (char === "{") {
3647
+ depth += 1;
3648
+ } else if (char === "}") {
3649
+ depth -= 1;
3650
+ if (depth === 0) {
3651
+ return index2;
3652
+ }
3653
+ }
3654
+ }
3655
+ return null;
3656
+ }
3657
+ function isTopLevelObjectProperty(content, openBrace, keyStart) {
3658
+ let objectDepth = 0;
3659
+ let bracketDepth = 0;
3660
+ let parenDepth = 0;
3661
+ let quote = null;
3662
+ let inLineComment = false;
3663
+ let inBlockComment = false;
3664
+ for (let index2 = openBrace + 1; index2 < keyStart; index2 += 1) {
3665
+ const char = content[index2];
3666
+ const next = content[index2 + 1];
3667
+ if (inLineComment) {
3668
+ if (char === "\n") {
3669
+ inLineComment = false;
3670
+ }
3671
+ } else if (inBlockComment) {
3672
+ if (char === "*" && next === "/") {
3673
+ inBlockComment = false;
3674
+ index2 += 1;
3675
+ }
3676
+ } else if (quote) {
3677
+ if (char === quote && !isEscapedCharacter(content, index2)) {
3678
+ quote = null;
3679
+ }
3680
+ } else if (char === "/" && next === "/") {
3681
+ inLineComment = true;
3682
+ index2 += 1;
3683
+ } else if (char === "/" && next === "*") {
3684
+ inBlockComment = true;
3685
+ index2 += 1;
3686
+ } else if (char === "'" || char === '"' || char === "`") {
3687
+ quote = char;
3688
+ } else if (char === "{") {
3689
+ objectDepth += 1;
3690
+ } else if (char === "}") {
3691
+ objectDepth -= 1;
3692
+ } else if (char === "[") {
3693
+ bracketDepth += 1;
3694
+ } else if (char === "]") {
3695
+ bracketDepth -= 1;
3696
+ } else if (char === "(") {
3697
+ parenDepth += 1;
3698
+ } else if (char === ")") {
3699
+ parenDepth -= 1;
3700
+ }
3701
+ }
3702
+ return !inLineComment && !inBlockComment && !quote && objectDepth === 0 && bracketDepth === 0 && parenDepth === 0;
3703
+ }
3704
+ function isEscapedCharacter(content, index2) {
3705
+ let backslashCount = 0;
3706
+ for (let cursor2 = index2 - 1; cursor2 >= 0 && content[cursor2] === "\\"; cursor2 -= 1) {
3707
+ backslashCount += 1;
3708
+ }
3709
+ return backslashCount % 2 === 1;
3710
+ }
3468
3711
  function deepMerge(target, source) {
3469
3712
  const result = { ...target };
3470
3713
  for (const key of Object.keys(source)) {
@@ -3659,6 +3902,19 @@ ${indent(level)}integrations: {`];
3659
3902
  return lines.join("\n");
3660
3903
  }
3661
3904
 
3905
+ // src/lib/deploy/metadata-payload.ts
3906
+ function buildDeployGameMetadataPayload(config) {
3907
+ return {
3908
+ displayName: config.displayName,
3909
+ platform: config.platform || "web",
3910
+ gameType: "hosted",
3911
+ metadata: {
3912
+ ...config.description !== void 0 && { description: config.description },
3913
+ ...config.emoji !== void 0 && { emoji: config.emoji }
3914
+ }
3915
+ };
3916
+ }
3917
+
3662
3918
  // src/lib/core/game.ts
3663
3919
  function getSlugFromConfig(config) {
3664
3920
  return generateSlug(config.name);
@@ -3678,15 +3934,15 @@ async function ensureGameExists(client, config) {
3678
3934
  logger.newLine();
3679
3935
  game = await runStep(
3680
3936
  `Creating app metadata for "${slug}"`,
3681
- () => client.dev.games.upsert(slug, {
3682
- displayName: config.name,
3683
- platform: config.platform ?? "web",
3684
- gameType: "hosted",
3685
- metadata: {
3686
- ...config.description && { description: config.description },
3687
- ...config.emoji && { emoji: config.emoji }
3688
- }
3689
- }),
3937
+ () => client.dev.games.upsert(
3938
+ slug,
3939
+ buildDeployGameMetadataPayload({
3940
+ displayName: config.name,
3941
+ description: config.description,
3942
+ emoji: config.emoji,
3943
+ platform: config.platform
3944
+ })
3945
+ ),
3690
3946
  "App metadata created"
3691
3947
  );
3692
3948
  }
@@ -4057,7 +4313,7 @@ import { existsSync as existsSync9, mkdirSync as mkdirSync2, readFileSync as rea
4057
4313
  import { join as join13 } from "node:path";
4058
4314
 
4059
4315
  // src/version.ts
4060
- var cliVersion = false ? "0.0.0-dev" : "0.22.0";
4316
+ var cliVersion = false ? "0.0.0-dev" : "0.22.1-beta.1";
4061
4317
 
4062
4318
  // src/lib/init/database.ts
4063
4319
  var drizzleConfigTemplate = loadTemplateString("database/drizzle-config.ts");
@@ -10030,6 +10286,75 @@ async function loadDeployConfig(configPath) {
10030
10286
  throw new Error(`Unsupported config file type: ${ext}`);
10031
10287
  }
10032
10288
 
10289
+ // src/lib/deploy/dashboard-drift.ts
10290
+ var DASHBOARD_DRIFT_LABELS = {
10291
+ displayName: "Display name",
10292
+ platform: "Platform",
10293
+ metadataPrefix: "metadata."
10294
+ };
10295
+ function metadataValuesEqual(a, b) {
10296
+ if (Object.is(a, b)) {
10297
+ return true;
10298
+ }
10299
+ if (typeof a === "object" && a !== null && typeof b === "object" && b !== null) {
10300
+ return JSON.stringify(sortJsonKeys(a)) === JSON.stringify(sortJsonKeys(b));
10301
+ }
10302
+ return false;
10303
+ }
10304
+ function sortJsonKeys(value) {
10305
+ if (value === null || typeof value !== "object") {
10306
+ return value;
10307
+ }
10308
+ if (Array.isArray(value)) {
10309
+ return value.map(sortJsonKeys);
10310
+ }
10311
+ const sorted = {};
10312
+ for (const key of Object.keys(value).toSorted()) {
10313
+ sorted[key] = sortJsonKeys(value[key]);
10314
+ }
10315
+ return sorted;
10316
+ }
10317
+ function getDashboardMetadataDriftRows(remoteGame, localPayload) {
10318
+ const rows = [];
10319
+ if (remoteGame.displayName !== localPayload.displayName) {
10320
+ rows.push({
10321
+ label: DASHBOARD_DRIFT_LABELS.displayName,
10322
+ dashboard: remoteGame.displayName,
10323
+ afterDeploy: localPayload.displayName
10324
+ });
10325
+ }
10326
+ if (remoteGame.platform !== localPayload.platform) {
10327
+ rows.push({
10328
+ label: DASHBOARD_DRIFT_LABELS.platform,
10329
+ dashboard: remoteGame.platform,
10330
+ afterDeploy: localPayload.platform
10331
+ });
10332
+ }
10333
+ const remoteMeta = { ...remoteGame.metadata };
10334
+ const localMeta = { ...localPayload.metadata };
10335
+ const keys = /* @__PURE__ */ new Set([...Object.keys(remoteMeta), ...Object.keys(localMeta)]);
10336
+ for (const key of [...keys].toSorted()) {
10337
+ const rv = remoteMeta[key];
10338
+ const lv = localMeta[key];
10339
+ if (!metadataValuesEqual(rv, lv)) {
10340
+ rows.push({
10341
+ label: `${DASHBOARD_DRIFT_LABELS.metadataPrefix}${key}`,
10342
+ dashboard: rv,
10343
+ afterDeploy: lv
10344
+ });
10345
+ }
10346
+ }
10347
+ return rows;
10348
+ }
10349
+ function skipsDeployGameDueToSecretsOnly(context2, plan) {
10350
+ const changes = plan.changes;
10351
+ if (!changes) {
10352
+ return false;
10353
+ }
10354
+ const isSecretsOnly = !plan.shouldUpdateGame && !plan.shouldUploadBuild && !plan.shouldDeployBackend && changes.secrets !== void 0 && hasChanges(changes.secrets);
10355
+ return Boolean(isSecretsOnly && context2.existingGame && context2.localSecrets);
10356
+ }
10357
+
10033
10358
  // src/lib/deploy/diff.ts
10034
10359
  import { dim as dim6, green as green6, red as red4, yellow as yellow5 } from "colorette";
10035
10360
  function calculateConfigDiff(existingGame, newConfig) {
@@ -10261,7 +10586,7 @@ function displayIntegrationAndSecretsChanges(integrations, secrets, secretsChang
10261
10586
  }
10262
10587
  }
10263
10588
  function displayDeploymentDiff(options) {
10264
- const { diff, noChanges, build: build3, backend, integrations, secrets } = options;
10589
+ const { diff, noChanges, build: build3, backend, integrations, secrets, driftLabels } = options;
10265
10590
  if (noChanges) {
10266
10591
  logger.remark("No changes detected");
10267
10592
  logger.newLine();
@@ -10280,21 +10605,29 @@ function displayDeploymentDiff(options) {
10280
10605
  logger.highlight("Changes detected:");
10281
10606
  logger.newLine();
10282
10607
  if (hasConfigChanges) {
10608
+ let driftHint2 = function(label) {
10609
+ return driftLabels?.has(label) ? ` ${red4("[differs from platform]")}` : "";
10610
+ };
10611
+ var driftHint = driftHint2;
10283
10612
  logger.bold("Config", 1);
10284
10613
  if (diff.displayName) {
10285
- logger.data("Name", `${red4(diff.displayName.old)} \u2192 ${green6(diff.displayName.new)}`, 2);
10614
+ logger.data(
10615
+ "Name",
10616
+ `${red4(diff.displayName.old)} \u2192 ${green6(diff.displayName.new)}${driftHint2(DASHBOARD_DRIFT_LABELS.displayName)}`,
10617
+ 2
10618
+ );
10286
10619
  }
10287
10620
  if (diff.emoji) {
10288
10621
  logger.data(
10289
10622
  "Emoji",
10290
- `${red4(diff.emoji.old || "(none)")} \u2192 ${green6(diff.emoji.new || "(none)")}`,
10623
+ `${red4(diff.emoji.old || "(none)")} \u2192 ${green6(diff.emoji.new || "(none)")}${driftHint2(`${DASHBOARD_DRIFT_LABELS.metadataPrefix}emoji`)}`,
10291
10624
  2
10292
10625
  );
10293
10626
  }
10294
10627
  if (diff.description) {
10295
10628
  logger.data(
10296
10629
  "Description",
10297
- `${red4(diff.description.old || "(none)")} \u2192 ${green6(diff.description.new || "(none)")}`,
10630
+ `${red4(diff.description.old || "(none)")} \u2192 ${green6(diff.description.new || "(none)")}${driftHint2(`${DASHBOARD_DRIFT_LABELS.metadataPrefix}description`)}`,
10298
10631
  2
10299
10632
  );
10300
10633
  }
@@ -10325,6 +10658,7 @@ function displayDeploymentDiff(options) {
10325
10658
  }
10326
10659
 
10327
10660
  // src/lib/deploy/interaction.ts
10661
+ import { join as join38 } from "path";
10328
10662
  import { confirm as confirm6, input as input3, select as select5 } from "@inquirer/prompts";
10329
10663
 
10330
10664
  // src/lib/deploy/schema.ts
@@ -10809,6 +11143,8 @@ async function confirmDeploymentPlan(plan, context2) {
10809
11143
  const previousResources = context2.previousResources || [];
10810
11144
  const addedResources = currentResources.filter((r) => !previousResources.includes(r));
10811
11145
  const removedResources = previousResources.filter((r) => !currentResources.includes(r));
11146
+ const drift = await detectDashboardDrift(context2, plan);
11147
+ const driftLabels = drift ? new Set(drift.rows.map((r) => r.label)) : void 0;
10812
11148
  displayDeploymentDiff({
10813
11149
  diff: plan.changes.config ? calculateConfigDiff(context2.existingGame, config) : {},
10814
11150
  noChanges: false,
@@ -10837,12 +11173,23 @@ async function confirmDeploymentPlan(plan, context2) {
10837
11173
  currentKeys: currentIntegrationKeys,
10838
11174
  metadata: plan.changes.integrationsMetadata
10839
11175
  },
10840
- secrets: plan.changes.secrets
11176
+ secrets: plan.changes.secrets,
11177
+ driftLabels
10841
11178
  });
10842
11179
  if (isNonInteractive()) {
10843
11180
  logger.remark("Updating project (CI auto-confirm)", 1);
11181
+ if (drift) {
11182
+ logger.remark("Dashboard edits will be overwritten by local config", 1);
11183
+ }
10844
11184
  return true;
10845
11185
  }
11186
+ if (drift) {
11187
+ return await promptDashboardDriftResolution({
11188
+ context: context2,
11189
+ rows: drift.rows,
11190
+ remoteGame: drift.remoteGame
11191
+ });
11192
+ }
10846
11193
  const shouldDeploy = await confirm6({
10847
11194
  message: `Update ${config.displayName}?`,
10848
11195
  default: true
@@ -10851,6 +11198,227 @@ async function confirmDeploymentPlan(plan, context2) {
10851
11198
  }
10852
11199
  return false;
10853
11200
  }
11201
+ async function detectDashboardDrift(context2, plan) {
11202
+ if (!context2.config.slug || skipsDeployGameDueToSecretsOnly(context2, plan)) {
11203
+ return null;
11204
+ }
11205
+ try {
11206
+ const remoteGame = await context2.client.games.fetch(context2.config.slug, {
11207
+ force: true
11208
+ });
11209
+ const localPayload = buildDeployGameMetadataPayload(context2.config);
11210
+ const rows = getDashboardMetadataDriftRows(remoteGame, localPayload);
11211
+ if (rows.length === 0) {
11212
+ return null;
11213
+ }
11214
+ return { rows, remoteGame };
11215
+ } catch {
11216
+ return null;
11217
+ }
11218
+ }
11219
+ async function promptDashboardDriftResolution(args) {
11220
+ const { context: context2, rows, remoteGame } = args;
11221
+ logger.admonition("warning", "Config drift detected", [
11222
+ "Your local config is out of sync with the platform"
11223
+ ]);
11224
+ logger.newLine();
11225
+ const canWriteConfig = Boolean(context2.configFileName);
11226
+ const choices = [
11227
+ {
11228
+ name: "Keep local values",
11229
+ value: "config-wins"
11230
+ }
11231
+ ];
11232
+ if (canWriteConfig) {
11233
+ choices.push({
11234
+ name: "Keep platform values",
11235
+ value: "platform-wins"
11236
+ });
11237
+ }
11238
+ choices.push({ name: "Cancel", value: "cancel" });
11239
+ const decision = await select5({
11240
+ message: "How do you want to proceed?",
11241
+ choices,
11242
+ default: "config-wins"
11243
+ });
11244
+ if (decision === "cancel") {
11245
+ return false;
11246
+ }
11247
+ if (decision === "config-wins") {
11248
+ return true;
11249
+ }
11250
+ return await applyPlatformValuesToLocalConfig({ context: context2, rows, remoteGame });
11251
+ }
11252
+ var AUTO_RESOLVABLE_METADATA_KEYS = /* @__PURE__ */ new Set(["description", "emoji"]);
11253
+ async function applyPlatformValuesToLocalConfig(args) {
11254
+ const { context: context2, rows, remoteGame } = args;
11255
+ if (!context2.configFileName) {
11256
+ logger.admonition("warning", "Cannot rewrite config", [
11257
+ "No `playcademy.config.{js,json}` file was found for this project; falling back to deploying with your local values."
11258
+ ]);
11259
+ return true;
11260
+ }
11261
+ let writeDisplayName = rows.some((r) => r.label === DASHBOARD_DRIFT_LABELS.displayName);
11262
+ if (writeDisplayName) {
11263
+ const acknowledgedSlugChange = await confirmDisplayNameSlugChange(context2, remoteGame);
11264
+ if (!acknowledgedSlugChange) {
11265
+ writeDisplayName = false;
11266
+ }
11267
+ }
11268
+ const { updates, unresolvableLabels } = buildScalarUpdatesFromDrift({
11269
+ rows,
11270
+ remoteGame,
11271
+ writeDisplayName
11272
+ });
11273
+ applyUpdatesToContext(context2, updates, writeDisplayName);
11274
+ const configPath = join38(context2.projectPath, context2.configFileName);
11275
+ const result = await updateConfigScalars(configPath, updates);
11276
+ reportConfigUpdate(result, unresolvableLabels, context2.configFileName);
11277
+ return true;
11278
+ }
11279
+ function buildScalarUpdatesFromDrift(args) {
11280
+ const { rows, remoteGame, writeDisplayName } = args;
11281
+ const updates = {};
11282
+ const unresolvableLabels = [];
11283
+ for (const row of rows) {
11284
+ const decision = classifyDriftRow(row, remoteGame, writeDisplayName);
11285
+ if (decision.kind === "write") {
11286
+ applyDecisionToUpdates(updates, decision);
11287
+ } else if (decision.kind === "unresolvable") {
11288
+ unresolvableLabels.push(row.label);
11289
+ }
11290
+ }
11291
+ return { updates, unresolvableLabels };
11292
+ }
11293
+ function classifyDriftRow(row, remoteGame, writeDisplayName) {
11294
+ if (row.label === DASHBOARD_DRIFT_LABELS.displayName) {
11295
+ if (!writeDisplayName) {
11296
+ return { kind: "skip" };
11297
+ }
11298
+ if (typeof remoteGame.displayName !== "string") {
11299
+ return { kind: "unresolvable" };
11300
+ }
11301
+ return { kind: "write", field: "name", value: remoteGame.displayName };
11302
+ }
11303
+ if (row.label === DASHBOARD_DRIFT_LABELS.platform) {
11304
+ if (typeof remoteGame.platform !== "string") {
11305
+ return { kind: "unresolvable" };
11306
+ }
11307
+ return { kind: "write", field: "platform", value: remoteGame.platform };
11308
+ }
11309
+ if (!row.label.startsWith(DASHBOARD_DRIFT_LABELS.metadataPrefix)) {
11310
+ return { kind: "skip" };
11311
+ }
11312
+ const key = row.label.slice(DASHBOARD_DRIFT_LABELS.metadataPrefix.length);
11313
+ if (!AUTO_RESOLVABLE_METADATA_KEYS.has(key)) {
11314
+ return { kind: "unresolvable" };
11315
+ }
11316
+ const remoteValue = remoteGame.metadata?.[key];
11317
+ if (typeof remoteValue !== "string" && remoteValue !== void 0) {
11318
+ return { kind: "unresolvable" };
11319
+ }
11320
+ const value = remoteValue ?? null;
11321
+ if (key === "description") {
11322
+ return { kind: "write", field: "description", value };
11323
+ }
11324
+ if (key === "emoji") {
11325
+ return { kind: "write", field: "emoji", value };
11326
+ }
11327
+ return { kind: "unresolvable" };
11328
+ }
11329
+ function applyDecisionToUpdates(updates, decision) {
11330
+ if (decision.field === "name" && decision.value !== null) {
11331
+ updates.name = decision.value;
11332
+ } else if (decision.field === "platform" && decision.value !== null) {
11333
+ updates.platform = decision.value;
11334
+ } else if (decision.field === "description") {
11335
+ updates.description = decision.value;
11336
+ } else if (decision.field === "emoji") {
11337
+ updates.emoji = decision.value;
11338
+ }
11339
+ }
11340
+ async function confirmDisplayNameSlugChange(context2, remoteGame) {
11341
+ const currentSlug = context2.config.slug ?? "(unknown)";
11342
+ const dashboardName = remoteGame.displayName ?? "(unset)";
11343
+ logger.newLine();
11344
+ logger.admonition("warning", "Updating `name` changes your deployment slug", [
11345
+ `If we rewrite \`name\` in your config to "${dashboardName}", your next deploy will derive a different slug from it.`,
11346
+ "",
11347
+ `This deploy will still target the current slug "${currentSlug}", but the next \`playcademy deploy\` will create a new game at the new slug unless you keep them aligned.`,
11348
+ "",
11349
+ "Choose No to leave `name` alone and only sync the other drifted fields."
11350
+ ]);
11351
+ logger.newLine();
11352
+ return await confirm6({
11353
+ message: `Rewrite \`name\` to "${dashboardName}" and accept the slug change on the next deploy?`,
11354
+ default: false
11355
+ });
11356
+ }
11357
+ function applyUpdatesToContext(context2, updates, writeDisplayName) {
11358
+ if (writeDisplayName && typeof updates.name === "string") {
11359
+ context2.config.displayName = updates.name;
11360
+ if (context2.fullConfig) {
11361
+ context2.fullConfig.name = updates.name;
11362
+ }
11363
+ }
11364
+ if ("description" in updates) {
11365
+ context2.config.description = updates.description ?? void 0;
11366
+ if (context2.fullConfig) {
11367
+ context2.fullConfig.description = updates.description ?? void 0;
11368
+ }
11369
+ }
11370
+ if ("emoji" in updates) {
11371
+ context2.config.emoji = updates.emoji ?? void 0;
11372
+ if (context2.fullConfig) {
11373
+ context2.fullConfig.emoji = updates.emoji ?? void 0;
11374
+ }
11375
+ }
11376
+ if (typeof updates.platform === "string") {
11377
+ const narrowed = narrowToPlaycademyPlatform(updates.platform);
11378
+ if (narrowed) {
11379
+ context2.config.platform = narrowed;
11380
+ if (context2.fullConfig) {
11381
+ context2.fullConfig.platform = narrowed;
11382
+ }
11383
+ }
11384
+ }
11385
+ }
11386
+ var PLAYCADEMY_PLATFORM_VALUES = ["web", "unity", "godot"];
11387
+ function narrowToPlaycademyPlatform(value) {
11388
+ return PLAYCADEMY_PLATFORM_VALUES.includes(value) ? value : null;
11389
+ }
11390
+ function reportConfigUpdate(result, unresolvableLabels, configFileName) {
11391
+ logger.newLine();
11392
+ if (result.written.length > 0) {
11393
+ const fieldList = result.written.join(", ");
11394
+ logger.success(`Updated ${fieldList} in ${configFileName} to match the dashboard`);
11395
+ } else {
11396
+ logger.remark(`No fields were rewritten in ${configFileName}`, 1);
11397
+ }
11398
+ const manualLines = [];
11399
+ for (const skipped of result.skipped) {
11400
+ const target = skipped.intendedValue === null ? "(remove this field)" : `"${skipped.intendedValue}"`;
11401
+ if (skipped.reason === "non-literal") {
11402
+ manualLines.push(`\`${skipped.field}\` in ${configFileName} \u2192 set to ${target}`);
11403
+ } else if (skipped.reason === "removal-unsupported") {
11404
+ manualLines.push(`\`${skipped.field}\` in ${configFileName} \u2192 remove this field`);
11405
+ } else {
11406
+ manualLines.push(`\`${skipped.field}\` missing from ${configFileName} \u2192 add ${target}`);
11407
+ }
11408
+ }
11409
+ for (const label of unresolvableLabels) {
11410
+ manualLines.push(`${label}: not editable from the General tab; reconcile manually`);
11411
+ }
11412
+ if (manualLines.length > 0) {
11413
+ logger.newLine();
11414
+ logger.admonition("note", "Some fields need a manual update", [
11415
+ "These could not be rewritten automatically (dynamic expression, missing key, unsupported JS field removal, or not a user-editable field):",
11416
+ "",
11417
+ ...manualLines
11418
+ ]);
11419
+ }
11420
+ logger.newLine();
11421
+ }
10854
11422
 
10855
11423
  // src/lib/deploy/output.ts
10856
11424
  import { underline as underline2 } from "colorette";
@@ -11050,7 +11618,7 @@ function logDeploymentPlanDebug(plan, context2) {
11050
11618
 
11051
11619
  // src/lib/deploy/preparation.ts
11052
11620
  import { stat } from "node:fs/promises";
11053
- import { join as join38 } from "node:path";
11621
+ import { join as join39 } from "node:path";
11054
11622
 
11055
11623
  // ../data/src/domains/game/helpers.ts
11056
11624
  function isHostedGame(game) {
@@ -11223,14 +11791,17 @@ var games = pgTable2("games", {
11223
11791
  createdAt: timestamp2("created_at", { withTimezone: true }).defaultNow(),
11224
11792
  updatedAt: timestamp2("updated_at", { withTimezone: true }).defaultNow()
11225
11793
  });
11226
- var gameMemberRoleEnum = pgEnum2("game_member_role", ["owner", "collaborator"]);
11794
+ var gameMemberRoleEnum = pgEnum2("game_member_role", [
11795
+ GAME_MEMBER_ROLES.OWNER,
11796
+ GAME_MEMBER_ROLES.COLLABORATOR
11797
+ ]);
11227
11798
  var gameMembers = pgTable2(
11228
11799
  "game_members",
11229
11800
  {
11230
11801
  id: uuid("id").primaryKey().defaultRandom(),
11231
11802
  gameId: uuid("game_id").notNull().references(() => games.id, { onDelete: "cascade" }),
11232
11803
  userId: text2("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
11233
- role: gameMemberRoleEnum("role").notNull().default("collaborator"),
11804
+ role: gameMemberRoleEnum("role").notNull().default(GAME_MEMBER_ROLES.COLLABORATOR),
11234
11805
  createdAt: timestamp2("created_at", { withTimezone: true }).notNull().defaultNow()
11235
11806
  },
11236
11807
  (table) => [uniqueIndex2("game_members_game_user_idx").on(table.gameId, table.userId)]
@@ -11681,8 +12252,8 @@ async function bundleAndHash(context2) {
11681
12252
  });
11682
12253
  const bundleHash = hashContent(bundle.code);
11683
12254
  const [serverSize, dbSize] = await Promise.all([
11684
- getDirectorySize(join38(context2.projectPath, SERVER_ROOT_DIRECTORY)),
11685
- getDirectorySize(join38(context2.projectPath, DEFAULT_DATABASE_DIRECTORY))
12255
+ getDirectorySize(join39(context2.projectPath, SERVER_ROOT_DIRECTORY)),
12256
+ getDirectorySize(join39(context2.projectPath, DEFAULT_DATABASE_DIRECTORY))
11686
12257
  ]);
11687
12258
  context2.currentBackendBundle = bundle;
11688
12259
  context2.currentBackendBundleHash = bundleHash;
@@ -11859,18 +12430,7 @@ function hasOptionalFieldsMissing(missing) {
11859
12430
  // src/lib/deploy/steps.ts
11860
12431
  import { existsSync as existsSync28 } from "fs";
11861
12432
  import { readFile as readFile6 } from "fs/promises";
11862
- import { basename as basename3, join as join39, resolve as resolve13 } from "path";
11863
- function prepareGameMetadata(config) {
11864
- return {
11865
- displayName: config.displayName,
11866
- platform: config.platform || "web",
11867
- gameType: "hosted",
11868
- metadata: {
11869
- ...config.description && { description: config.description },
11870
- ...config.emoji && { emoji: config.emoji }
11871
- }
11872
- };
11873
- }
12433
+ import { basename as basename3, join as join40, resolve as resolve13 } from "path";
11874
12434
  async function prepareBuildFile(buildPath) {
11875
12435
  const resolvedPath = resolve13(buildPath);
11876
12436
  if (resolvedPath.endsWith(".zip") && existsSync28(resolvedPath)) {
@@ -11984,7 +12544,7 @@ async function handleIntegrationConfigChanges(game, context2) {
11984
12544
  }
11985
12545
  async function deployGame(context2, shouldUploadBuild, shouldDeployBackend) {
11986
12546
  const { client, config, fullConfig } = context2;
11987
- const metadata = prepareGameMetadata(config);
12547
+ const metadata = buildDeployGameMetadataPayload(config);
11988
12548
  if (!shouldUploadBuild && !shouldDeployBackend) {
11989
12549
  const game2 = await runStep(
11990
12550
  "Updating app metadata",
@@ -12054,8 +12614,8 @@ async function deployGame(context2, shouldUploadBuild, shouldDeployBackend) {
12054
12614
  compatibilityFlags: [...BACKEND_COMPATIBILITY_FLAGS]
12055
12615
  };
12056
12616
  const [serverSize, dbSize] = await Promise.all([
12057
- getDirectorySize(join39(context2.projectPath, SERVER_ROOT_DIRECTORY)),
12058
- getDirectorySize(join39(context2.projectPath, DEFAULT_DATABASE_DIRECTORY))
12617
+ getDirectorySize(join40(context2.projectPath, SERVER_ROOT_DIRECTORY)),
12618
+ getDirectorySize(join40(context2.projectPath, DEFAULT_DATABASE_DIRECTORY))
12059
12619
  ]);
12060
12620
  const isMigrateMode = Boolean(deploymentPrep.schemaInfo?.migrationTag);
12061
12621
  backendMetadata = {
@@ -12118,7 +12678,7 @@ async function deployGame(context2, shouldUploadBuild, shouldDeployBackend) {
12118
12678
 
12119
12679
  // src/lib/db/path.ts
12120
12680
  import { copyFileSync, existsSync as existsSync29, mkdirSync as mkdirSync9, readdirSync as readdirSync4, unlinkSync } from "fs";
12121
- import { join as join40 } from "path";
12681
+ import { join as join41 } from "path";
12122
12682
  var DB_DIRECTORY = CLI_DIRECTORIES.DATABASE;
12123
12683
  var INITIAL_DB_NAME = CLI_FILES.INITIAL_DATABASE;
12124
12684
  function ensureDirectoryExists(dir) {
@@ -12127,7 +12687,7 @@ function ensureDirectoryExists(dir) {
12127
12687
  }
12128
12688
  }
12129
12689
  function findMiniflareDatabase(dbDir) {
12130
- const miniflareDir = join40(dbDir, MINIFLARE_D1_DIRECTORY);
12690
+ const miniflareDir = join41(dbDir, MINIFLARE_D1_DIRECTORY);
12131
12691
  if (!existsSync29(miniflareDir)) {
12132
12692
  return null;
12133
12693
  }
@@ -12135,7 +12695,7 @@ function findMiniflareDatabase(dbDir) {
12135
12695
  if (sqliteFiles.length === 0) {
12136
12696
  return null;
12137
12697
  }
12138
- return join40(miniflareDir, sqliteFiles[0]);
12698
+ return join41(miniflareDir, sqliteFiles[0]);
12139
12699
  }
12140
12700
  function migrateInitialDbToTarget(initialPath, targetPath) {
12141
12701
  if (!existsSync29(initialPath)) {
@@ -12145,7 +12705,7 @@ function migrateInitialDbToTarget(initialPath, targetPath) {
12145
12705
  unlinkSync(initialPath);
12146
12706
  }
12147
12707
  function getDevDbPath() {
12148
- const initialDbPath = join40(DB_DIRECTORY, INITIAL_DB_NAME);
12708
+ const initialDbPath = join41(DB_DIRECTORY, INITIAL_DB_NAME);
12149
12709
  ensureDirectoryExists(DB_DIRECTORY);
12150
12710
  const miniflareDbPath = findMiniflareDatabase(DB_DIRECTORY);
12151
12711
  if (miniflareDbPath) {
@@ -12286,10 +12846,10 @@ async function bundleSeedWorker(seedFilePath, projectPath) {
12286
12846
  // src/lib/db/reset.ts
12287
12847
  import { execSync as execSync7 } from "child_process";
12288
12848
  import { rmSync as rmSync3 } from "fs";
12289
- import { join as join41 } from "path";
12849
+ import { join as join42 } from "path";
12290
12850
  async function resetDatabase(workspace, mf, options = { debug: false }) {
12291
12851
  const { debug } = options;
12292
- const dbDir = join41(workspace, CLI_DIRECTORIES.DATABASE);
12852
+ const dbDir = join42(workspace, CLI_DIRECTORIES.DATABASE);
12293
12853
  await runStep(
12294
12854
  "Resetting database...",
12295
12855
  async () => {
@@ -12737,7 +13297,7 @@ import { dim as dim9 } from "colorette";
12737
13297
 
12738
13298
  // src/lib/bucket/collect.ts
12739
13299
  import { readdirSync as readdirSync5, statSync as statSync4 } from "fs";
12740
- import { join as join42, relative as relative6, sep as sep3 } from "path";
13300
+ import { join as join43, relative as relative6, sep as sep3 } from "path";
12741
13301
  function shouldSkipFile(filePath, baseDir, gitignorePatterns) {
12742
13302
  const relativePath = relative6(baseDir, filePath);
12743
13303
  const pathParts = relativePath.split(sep3);
@@ -12754,7 +13314,7 @@ function collectFiles(directory, baseDir, gitignorePatterns) {
12754
13314
  try {
12755
13315
  const entries = readdirSync5(directory, { withFileTypes: true });
12756
13316
  for (const entry of entries) {
12757
- const fullPath = join42(directory, entry.name);
13317
+ const fullPath = join43(directory, entry.name);
12758
13318
  if (!shouldSkipFile(fullPath, baseDir, gitignorePatterns)) {
12759
13319
  if (entry.isDirectory()) {
12760
13320
  files.push(...collectFiles(fullPath, baseDir, gitignorePatterns));
@@ -13727,7 +14287,7 @@ ${error.suggestion}` : error.message;
13727
14287
 
13728
14288
  // src/lib/upgrade/channel.ts
13729
14289
  import { mkdir as mkdir6, readFile as readFile7, writeFile as writeFile5 } from "node:fs/promises";
13730
- import { join as join43 } from "node:path";
14290
+ import { join as join44 } from "node:path";
13731
14291
  var RELEASE_CHANNELS = ["stable", "beta"];
13732
14292
  var CDN_BASE_URLS = {
13733
14293
  stable: "https://cdn.playcademy.net/cli",
@@ -13741,7 +14301,7 @@ function getLatestVersionUrl(channel) {
13741
14301
  }
13742
14302
  var CHANNEL_FILE = "channel";
13743
14303
  function getChannelFilePath() {
13744
- return join43(CLI_USER_DIRECTORIES.CONFIG, CHANNEL_FILE);
14304
+ return join44(CLI_USER_DIRECTORIES.CONFIG, CHANNEL_FILE);
13745
14305
  }
13746
14306
  function channelFromVersion(version3) {
13747
14307
  return version3.includes("-beta") ? "beta" : "stable";
@@ -14040,6 +14600,7 @@ async function fetchLatestVersion(channel) {
14040
14600
  }
14041
14601
  export {
14042
14602
  ConfigError,
14603
+ DASHBOARD_DRIFT_LABELS,
14043
14604
  INSTALL_SCRIPT_URL,
14044
14605
  METRICS_RESOLVER_EXTENSIONS,
14045
14606
  METRICS_RESOLVER_PATH,
@@ -14054,6 +14615,7 @@ export {
14054
14615
  applySecretsChanges,
14055
14616
  assertVersionExists,
14056
14617
  buildCustomRouteImportStatements,
14618
+ buildDeployGameMetadataPayload,
14057
14619
  buildLogStreamUrl,
14058
14620
  buildMetricsResolverCode,
14059
14621
  buildMetricsResolverImportStatement,
@@ -14145,6 +14707,7 @@ export {
14145
14707
  getContentType,
14146
14708
  getCurrentProfile,
14147
14709
  getCustomRoutesDirectory,
14710
+ getDashboardMetadataDriftRows,
14148
14711
  getDatabaseDirectory,
14149
14712
  getDeployedGame,
14150
14713
  getDirectorySize,
@@ -14288,6 +14851,7 @@ export {
14288
14851
  setCliContext,
14289
14852
  setupGlobalErrorHandlers,
14290
14853
  shouldSkipFile,
14854
+ skipsDeployGameDueToSecretsOnly,
14291
14855
  startCallbackServer,
14292
14856
  startDevServer,
14293
14857
  startHotReload,
@@ -14295,6 +14859,7 @@ export {
14295
14859
  transpileTypeScript,
14296
14860
  updateBuildMetadata,
14297
14861
  updateConfigFile,
14862
+ updateConfigScalars,
14298
14863
  updateEnvExample,
14299
14864
  updateExistingCourses,
14300
14865
  updateViteConfig,
@@ -162,6 +162,13 @@ var init_env_vars = __esm({
162
162
  }
163
163
  });
164
164
 
165
+ // ../constants/src/game.ts
166
+ var init_game = __esm({
167
+ "../constants/src/game.ts"() {
168
+ "use strict";
169
+ }
170
+ });
171
+
165
172
  // ../constants/src/overworld.ts
166
173
  var ITEM_SLUGS, CURRENCIES, BADGES;
167
174
  var init_overworld = __esm({
@@ -239,6 +246,7 @@ var init_src = __esm({
239
246
  init_character();
240
247
  init_domains();
241
248
  init_env_vars();
249
+ init_game();
242
250
  init_overworld();
243
251
  init_system();
244
252
  init_timeback();
@@ -353,9 +361,9 @@ var init_routes = __esm({
353
361
  // ../edge-play/src/entry/metadata.ts
354
362
  function getRuntimeMetadata() {
355
363
  return {
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"
364
+ cliVersion: true ? "0.22.1-beta.1" : "0.0.0-dev",
365
+ sdkVersion: true ? "0.9.1-beta.1" : "0.0.0-dev",
366
+ buildId: true ? "47e1158a40df" : "dev-source"
359
367
  };
360
368
  }
361
369
  var init_metadata = __esm({
@@ -1,7 +1,7 @@
1
1
  {
2
- "cliVersion": "0.22.0",
3
- "sdkVersion": "0.9.0",
4
- "runtimeBuildId": "1afaa748bb29",
5
- "inputFingerprint": "1afaa748bb29d1cff8b2e3f72ef7edac7a62ec98fa06e02d42adc2efa1334aca",
2
+ "cliVersion": "0.22.1-beta.1",
3
+ "sdkVersion": "0.9.1-beta.1",
4
+ "runtimeBuildId": "47e1158a40df",
5
+ "inputFingerprint": "47e1158a40dffb72acd8372da8f037fbf6a9e9f1b8e98ec9d14bade2ffbbaad4",
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",
484
+ version: "0.0.14-beta.1",
485
485
  type: "module",
486
486
  exports: {
487
487
  "./server": {
@@ -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.22.0";
2594
+ var cliVersion = false ? "0.0.0-dev" : "0.22.1-beta.1";
2595
2595
 
2596
2596
  // src/lib/build/binary-resource.ts
2597
2597
  function writeFileTree(baseDir, files) {
package/dist/version.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var cliVersion = false ? "0.0.0-dev" : "0.22.0";
2
+ var cliVersion = false ? "0.0.0-dev" : "0.22.1-beta.1";
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.22.0",
3
+ "version": "0.22.1-beta.1",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {