@playcademy/vite-plugin 0.1.9 → 0.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -158087,7 +158087,10 @@ class CloudflareProvider {
158087
158087
  namespace: this.config.dispatchNamespace
158088
158088
  });
158089
158089
  if (deleteBindings) {
158090
- await this.deleteD1DatabaseIfExists(deploymentId);
158090
+ await Promise.all([
158091
+ this.deleteD1DatabaseIfExists(deploymentId),
158092
+ this.deleteKVNamespaceIfExists(deploymentId)
158093
+ ]);
158091
158094
  }
158092
158095
  } catch (error2) {
158093
158096
  log2.error("[CloudflareProvider] Deletion from dispatch namespace failed", {
@@ -158138,7 +158141,12 @@ class CloudflareProvider {
158138
158141
  }
158139
158142
  }
158140
158143
  for (const kvName of resourceBindings.kv) {
158141
- log2.warn("[CloudflareProvider] KV namespace binding not yet implemented", { kvName });
158144
+ const namespaceId = await this.ensureKVNamespace(kvName);
158145
+ bindings.push({
158146
+ type: "kv_namespace",
158147
+ name: "KV",
158148
+ namespace_id: namespaceId
158149
+ });
158142
158150
  }
158143
158151
  for (const r2Name of resourceBindings.r2) {
158144
158152
  log2.warn("[CloudflareProvider] R2 bucket binding not yet implemented", { r2Name });
@@ -158250,6 +158258,73 @@ class CloudflareProvider {
158250
158258
  throw new Error(`Failed to execute schema: ${error2 instanceof Error ? error2.message : String(error2)}`);
158251
158259
  }
158252
158260
  }
158261
+ async ensureKVNamespace(namespaceName) {
158262
+ log2.debug("[CloudflareProvider] Ensuring KV namespace exists", { namespaceName });
158263
+ try {
158264
+ const namespaces = await this.client.kv.namespaces.list({
158265
+ account_id: this.config.accountId
158266
+ });
158267
+ for await (const ns of namespaces) {
158268
+ if (ns.title === namespaceName && ns.id) {
158269
+ log2.info("[CloudflareProvider] KV namespace already exists", {
158270
+ namespaceName,
158271
+ namespaceId: ns.id
158272
+ });
158273
+ return ns.id;
158274
+ }
158275
+ }
158276
+ log2.debug("[CloudflareProvider] Creating new KV namespace", { namespaceName });
158277
+ const createResult = await this.client.kv.namespaces.create({
158278
+ account_id: this.config.accountId,
158279
+ title: namespaceName
158280
+ });
158281
+ if (!createResult.id) {
158282
+ throw new Error("KV namespace creation succeeded but no ID returned");
158283
+ }
158284
+ log2.info("[CloudflareProvider] KV namespace created successfully", {
158285
+ namespaceName,
158286
+ namespaceId: createResult.id
158287
+ });
158288
+ return createResult.id;
158289
+ } catch (error2) {
158290
+ log2.error("[CloudflareProvider] Failed to ensure KV namespace", {
158291
+ namespaceName,
158292
+ error: error2
158293
+ });
158294
+ throw new Error(`Failed to ensure KV namespace: ${error2 instanceof Error ? error2.message : String(error2)}`);
158295
+ }
158296
+ }
158297
+ async deleteKVNamespaceIfExists(namespaceName) {
158298
+ try {
158299
+ const namespaces = await this.client.kv.namespaces.list({
158300
+ account_id: this.config.accountId
158301
+ });
158302
+ for await (const ns of namespaces) {
158303
+ if (ns.title === namespaceName && ns.id) {
158304
+ log2.debug("[CloudflareProvider] Deleting KV namespace", {
158305
+ namespaceName,
158306
+ namespaceId: ns.id
158307
+ });
158308
+ await this.client.kv.namespaces.delete(ns.id, {
158309
+ account_id: this.config.accountId
158310
+ });
158311
+ log2.info("[CloudflareProvider] KV namespace deleted successfully", {
158312
+ namespaceName,
158313
+ namespaceId: ns.id
158314
+ });
158315
+ return;
158316
+ }
158317
+ }
158318
+ log2.debug("[CloudflareProvider] KV namespace not found, nothing to delete", {
158319
+ namespaceName
158320
+ });
158321
+ } catch (error2) {
158322
+ log2.warn("[CloudflareProvider] Failed to delete KV namespace", {
158323
+ namespaceName,
158324
+ error: error2
158325
+ });
158326
+ }
158327
+ }
158253
158328
  }
158254
158329
  var RESERVED_SUBDOMAINS = new Set([
158255
158330
  "www",
@@ -169556,32 +169631,37 @@ var version3 = package_default.version;
169556
169631
 
169557
169632
  // src/lib/cli-server.ts
169558
169633
  var import_picocolors = __toESM(require_picocolors(), 1);
169559
- import { startPlaycademyDevServer, startPlaycademyHotReload } from "playcademy/utils";
169634
+ import {
169635
+ loadPlaycademyConfig as loadConfig2,
169636
+ startPlaycademyDevServer,
169637
+ startPlaycademyHotReload
169638
+ } from "playcademy/utils";
169639
+ async function tryLoadConfig(viteConfig) {
169640
+ try {
169641
+ return await loadConfig2();
169642
+ } catch (error2) {
169643
+ if (error2 instanceof Error && !error2.message.includes("Could not find")) {
169644
+ viteConfig.logger.warn(`Could not load playcademy.config.js: ${error2.message}`);
169645
+ }
169646
+ return null;
169647
+ }
169648
+ }
169560
169649
  function needsCliDevServer(config2) {
169561
- if (config2.integrations)
169562
- return true;
169563
- return false;
169650
+ return !!config2.integrations;
169564
169651
  }
169565
- async function startCliDevServer(options) {
169566
- const { port, config: config2, viteConfig, platformUrl } = options;
169567
- let server = await startPlaycademyDevServer({
169568
- port,
169569
- config: config2,
169570
- quiet: true,
169571
- platformUrl
169572
- });
169573
- const watcher = startPlaycademyHotReload(async () => {
169574
- await server.dispose();
169575
- server = await startPlaycademyDevServer({
169576
- port,
169577
- config: config2,
169578
- quiet: true,
169579
- platformUrl
169580
- });
169581
- }, {
169652
+ function formatChangedPath(changedPath) {
169653
+ if (!changedPath)
169654
+ return;
169655
+ if (changedPath.includes("/api/")) {
169656
+ return changedPath.substring(changedPath.indexOf("/api/"));
169657
+ }
169658
+ return changedPath;
169659
+ }
169660
+ function createHotReloadCallbacks(viteConfig) {
169661
+ return {
169582
169662
  onSuccess: (changedPath) => {
169583
- if (changedPath) {
169584
- const relativePath = changedPath.includes("/api/") ? changedPath.substring(changedPath.indexOf("/api/")) : changedPath;
169663
+ const relativePath = formatChangedPath(changedPath);
169664
+ if (relativePath) {
169585
169665
  viteConfig.logger.info(`${import_picocolors.dim("(backend)")} ${import_picocolors.green("hmr update")} ${import_picocolors.dim(relativePath)}`, { timestamp: true });
169586
169666
  } else {
169587
169667
  viteConfig.logger.info("backend reloaded", { timestamp: true });
@@ -169590,12 +169670,44 @@ async function startCliDevServer(options) {
169590
169670
  onError: (error2) => {
169591
169671
  viteConfig.logger.error(`backend reload failed: ${error2 instanceof Error ? error2.message : String(error2)}`);
169592
169672
  }
169593
- });
169594
- return {
169595
- server,
169596
- stopHotReload: () => watcher.close()
169597
169673
  };
169598
169674
  }
169675
+ async function startServer2(options) {
169676
+ const { port, config: config2, platformUrl } = options;
169677
+ return startPlaycademyDevServer({
169678
+ port,
169679
+ config: config2,
169680
+ quiet: true,
169681
+ platformUrl
169682
+ });
169683
+ }
169684
+ function setupHotReload(serverRef, options, viteConfig) {
169685
+ const watcher = startPlaycademyHotReload(async () => {
169686
+ await serverRef.current.dispose();
169687
+ serverRef.current = await startServer2(options);
169688
+ }, createHotReloadCallbacks(viteConfig));
169689
+ return () => watcher.close();
169690
+ }
169691
+ async function setupCliDevServer(options) {
169692
+ const { port, viteConfig, platformUrl } = options;
169693
+ const config2 = await tryLoadConfig(viteConfig);
169694
+ if (!config2)
169695
+ return null;
169696
+ if (!needsCliDevServer(config2))
169697
+ return null;
169698
+ try {
169699
+ const serverOptions = { port, config: config2, platformUrl };
169700
+ const serverRef = { current: await startServer2(serverOptions) };
169701
+ const stopHotReload = setupHotReload(serverRef, serverOptions, viteConfig);
169702
+ return {
169703
+ server: serverRef.current,
169704
+ stopHotReload
169705
+ };
169706
+ } catch (error2) {
169707
+ viteConfig.logger.error(`Failed to start game backend: ${error2 instanceof Error ? error2.message : String(error2)}`);
169708
+ return null;
169709
+ }
169710
+ }
169599
169711
 
169600
169712
  // src/lib/logging.ts
169601
169713
  var import_picocolors2 = __toESM(require_picocolors(), 1);
@@ -169621,7 +169733,6 @@ import path3 from "node:path";
169621
169733
  // src/utils.ts
169622
169734
  import fs4 from "node:fs";
169623
169735
  import path2 from "node:path";
169624
- import { loadPlaycademyConfig as loadConfig2 } from "playcademy/utils";
169625
169736
  function extractProjectInfo(viteConfig) {
169626
169737
  const projectRoot = viteConfig.root;
169627
169738
  const directoryName = path2.basename(projectRoot);
@@ -169672,20 +169783,6 @@ async function findAvailablePort(startPort = 4321) {
169672
169783
  });
169673
169784
  });
169674
169785
  }
169675
- async function loadPlaycademyConfig(viteConfig) {
169676
- const projectRoot = viteConfig.root;
169677
- const configPath = path2.join(projectRoot, "playcademy.config.js");
169678
- try {
169679
- if (fs4.existsSync(configPath)) {
169680
- return await loadConfig2(configPath);
169681
- }
169682
- } catch (error2) {
169683
- viteConfig.logger.error(`Failed to load playcademy.config.js: ${error2 instanceof Error ? error2.message : String(error2)}`);
169684
- viteConfig.logger.error(`configPath: ${configPath}`);
169685
- throw error2;
169686
- }
169687
- return null;
169688
- }
169689
169786
 
169690
169787
  // src/lib/manifest.ts
169691
169788
  var LOG_LINE_TOTAL_WIDTH = 60;
@@ -170341,7 +170438,6 @@ function devServerMiddleware(server, sandbox, gameUrl, showBadge) {
170341
170438
  function playcademy(options = {}) {
170342
170439
  let viteConfig;
170343
170440
  let currentBuildOutputs = {};
170344
- let playcademyConfig = null;
170345
170441
  const exportOptions = options.export ?? {};
170346
170442
  const sandboxOptions = options.sandbox ?? {};
170347
170443
  const devOptions = options.dev ?? {};
@@ -170364,7 +170460,6 @@ function playcademy(options = {}) {
170364
170460
  async configResolved(resolvedConfig) {
170365
170461
  viteConfig = resolvedConfig;
170366
170462
  currentBuildOutputs = {};
170367
- playcademyConfig = await loadPlaycademyConfig(resolvedConfig);
170368
170463
  },
170369
170464
  async configureServer(server) {
170370
170465
  const sandbox = await startSandbox(viteConfig, _options.startSandbox, {
@@ -170372,21 +170467,13 @@ function playcademy(options = {}) {
170372
170467
  customUrl: _options.sandboxUrl,
170373
170468
  quiet: true
170374
170469
  });
170375
- let cliServerManager = null;
170376
- if (playcademyConfig && needsCliDevServer(playcademyConfig)) {
170377
- try {
170378
- cliServerManager = await startCliDevServer({
170379
- port: DEFAULT_PORTS2.BACKEND,
170380
- config: playcademyConfig,
170381
- viteConfig,
170382
- platformUrl: sandbox.baseUrl
170383
- });
170384
- } catch (error2) {
170385
- viteConfig.logger.error(`Failed to start game backend: ${error2}`);
170386
- }
170387
- }
170470
+ const backend = await setupCliDevServer({
170471
+ port: DEFAULT_PORTS2.BACKEND,
170472
+ viteConfig,
170473
+ platformUrl: sandbox.baseUrl
170474
+ });
170388
170475
  if (sandbox.project) {
170389
- const gameUrl = cliServerManager ? `http://localhost:${DEFAULT_PORTS2.BACKEND}` : undefined;
170476
+ const gameUrl = backend ? `http://localhost:${DEFAULT_PORTS2.BACKEND}` : undefined;
170390
170477
  devServerMiddleware(server, sandbox, gameUrl, _options.showBadge);
170391
170478
  }
170392
170479
  server.httpServer?.once("listening", () => {
@@ -170394,16 +170481,14 @@ function playcademy(options = {}) {
170394
170481
  const projectInfo = extractProjectInfo(viteConfig);
170395
170482
  printBanner(viteConfig, {
170396
170483
  sandbox: DEFAULT_PORTS2.SANDBOX,
170397
- backend: cliServerManager ? DEFAULT_PORTS2.BACKEND : undefined
170484
+ backend: backend ? DEFAULT_PORTS2.BACKEND : undefined
170398
170485
  }, projectInfo, version3);
170399
170486
  }, 100);
170400
170487
  });
170401
170488
  server.httpServer?.on("close", () => {
170402
170489
  sandbox.cleanup();
170403
- if (cliServerManager) {
170404
- cliServerManager.server.dispose();
170405
- cliServerManager.stopHotReload();
170406
- }
170490
+ backend?.server.dispose();
170491
+ backend?.stopHotReload();
170407
170492
  });
170408
170493
  },
170409
170494
  async writeBundle() {
@@ -1,27 +1,9 @@
1
- import { startPlaycademyDevServer } from 'playcademy/utils';
2
- import type { PlaycademyConfig } from 'playcademy/types';
3
- import type { ResolvedConfig } from 'vite';
1
+ import type { CliDevServerOptions, CliServerManager } from '../types';
4
2
  /**
5
- * Determines if the CLI dev server is needed based on configuration.
6
- * Checks for integrations or custom routes that require the game backend.
3
+ * Sets up the CLI dev server with hot reload enabled.
4
+ * Loads config, checks if backend is needed, and starts server if appropriate.
5
+ * Returns null if no config or no integrations (backend not needed).
7
6
  *
8
- * @param config - Playcademy configuration
9
- * @returns True if CLI dev server is needed
10
- */
11
- export declare function needsCliDevServer(config: PlaycademyConfig): boolean;
12
- interface CliServerManager {
13
- server: Awaited<ReturnType<typeof startPlaycademyDevServer>>;
14
- stopHotReload: () => void;
15
- }
16
- export interface CliDevServerOptions {
17
- port: number;
18
- config: PlaycademyConfig;
19
- viteConfig: ResolvedConfig;
20
- platformUrl?: string;
21
- }
22
- /**
23
- * Starts the CLI dev server with hot reload enabled.
24
7
  * Used by the Vite plugin to manage the game backend server.
25
8
  */
26
- export declare function startCliDevServer(options: CliDevServerOptions): Promise<CliServerManager>;
27
- export {};
9
+ export declare function setupCliDevServer(options: CliDevServerOptions): Promise<CliServerManager | null>;
package/dist/types.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Type definitions for the Playcademy Vite Plugin
3
3
  */
4
+ import type { ResolvedConfig } from 'vite';
4
5
  import type { ManifestV1 } from '@playcademy/data/types';
5
6
  /**
6
7
  * Project information extracted from package.json and directory structure
@@ -74,3 +75,20 @@ export interface SandboxManager {
74
75
  project: ProjectInfo | null;
75
76
  cleanup: () => void;
76
77
  }
78
+ /**
79
+ * CLI server manager interface for controlling backend server lifecycle
80
+ */
81
+ export interface CliServerManager {
82
+ server: {
83
+ dispose: () => Promise<void>;
84
+ };
85
+ stopHotReload: () => void;
86
+ }
87
+ /**
88
+ * Options for setting up the CLI dev server
89
+ */
90
+ export interface CliDevServerOptions {
91
+ port: number;
92
+ viteConfig: ResolvedConfig;
93
+ platformUrl?: string;
94
+ }
package/dist/utils.d.ts CHANGED
@@ -2,15 +2,7 @@
2
2
  * Utility functions for the Playcademy Vite plugin
3
3
  */
4
4
  import type { ResolvedConfig } from 'vite';
5
- import type { PlaycademyConfig } from '@playcademy/sdk/server';
6
5
  import type { ProjectInfo } from './types';
7
6
  export declare function extractProjectInfo(viteConfig: ResolvedConfig): ProjectInfo;
8
7
  export declare function formatNumberWithCommas(numStr: string): string;
9
8
  export declare function findAvailablePort(startPort?: number): Promise<number>;
10
- /**
11
- * Loads the Playcademy configuration from the project root.
12
- *
13
- * @param viteConfig - Vite resolved configuration
14
- * @returns Playcademy configuration or null if not found
15
- */
16
- export declare function loadPlaycademyConfig(viteConfig: ResolvedConfig): Promise<PlaycademyConfig | null>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@playcademy/vite-plugin",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {