@playcademy/vite-plugin 1.1.3-beta.2 → 1.1.3-beta.4

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.
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Append custom shortcuts to Vite's CLI hotkeys.
3
+ *
4
+ * Vite has no additive API for shortcuts — the only seam is wrapping
5
+ * `bindCLIShortcuts` before Vite calls it. Both plugin variants (game and
6
+ * dashboard) hang their hotkeys off this one wrapper so the fragile
7
+ * Vite-internals handling lives in a single place.
8
+ */
9
+ import type { ViteDevServer } from 'vite';
10
+ type CustomShortcuts = NonNullable<NonNullable<Parameters<ViteDevServer['bindCLIShortcuts']>[0]>['customShortcuts']>;
11
+ export declare function appendCliShortcuts(server: ViteDevServer, shortcuts: CustomShortcuts): void;
12
+ export {};
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Dashboard app auto-start for game dev
3
+ *
4
+ * When the project declares a dashboard, the game's dev server starts the
5
+ * dashboard app's own dev script alongside the sandbox and backend — one
6
+ * command brings up the whole loop: game UI, game worker, dashboard UI,
7
+ * dashboard worker, all sharing the same local data. The child is the
8
+ * dashboard's regular Vite process (with the plugin's dashboard mode), so
9
+ * running it standalone or auto-started behaves identically.
10
+ */
11
+ import { spawn } from 'node:child_process';
12
+ import type { PluginLogger } from './logging';
13
+ /**
14
+ * Set in the spawned environment so a misconfigured project (for example
15
+ * `dashboard.directory` pointing back at the game app) cannot recursively
16
+ * auto-start dashboards from inside a dashboard child.
17
+ */
18
+ export declare const DASHBOARD_CHILD_ENV = "PLAYCADEMY_DASHBOARD_CHILD";
19
+ /**
20
+ * Dev-only endpoint the dashboard child's Vite server exposes so the game
21
+ * terminal can toggle the dashboard role: the auto-started child forwards
22
+ * its output but has no keyboard of its own, so `a` in the game terminal
23
+ * POSTs here instead.
24
+ */
25
+ export declare const DASHBOARD_ROLE_TOGGLE_PATH = "/__playcademy/dashboard/toggle-role";
26
+ export interface DashboardAppManager {
27
+ /** Signals the child group immediately; resolves once it has exited. */
28
+ stop(): Promise<void>;
29
+ /** Port the dashboard app's Vite server was told to bind */
30
+ port: number;
31
+ }
32
+ export interface SetupDashboardAppOptions {
33
+ enabled: boolean;
34
+ configPath?: string;
35
+ /** Port the dashboard app's Vite must bind (canonical default when unset) */
36
+ port?: number;
37
+ /** Injectable for tests */
38
+ spawnImpl?: typeof spawn;
39
+ logger?: PluginLogger;
40
+ }
41
+ /**
42
+ * Reduce a raw child output line to what the parent should relay: ANSI
43
+ * stripped (the noise patterns must see plain text — color codes sit
44
+ * between every token), the child's own timestamp prefix removed, and
45
+ * startup noise dropped entirely. Returns null for lines to swallow.
46
+ */
47
+ export declare function sanitizeChildOutputLine(rawLine: string): string | null;
48
+ /**
49
+ * Start the dashboard app's dev script when the project has a dashboard.
50
+ * Returns null when disabled, running inside a dashboard child, no config
51
+ * exists, or no dashboard is configured — game dev proceeds without one.
52
+ * A dashboard that IS configured but fails to load warns instead of
53
+ * silently doing nothing.
54
+ */
55
+ export declare function setupDashboardApp(options: SetupDashboardAppOptions): Promise<DashboardAppManager | null>;
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Backend server management
3
+ */
4
+ export { setupGameBackendDevServer } from './server';
@@ -0,0 +1,9 @@
1
+ import type { GameBackendDevServerOptions, GameBackendServerManager } from '../../types';
2
+ /**
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 the project has no backend features.
6
+ *
7
+ * Used by the Vite plugin to manage the game backend server.
8
+ */
9
+ export declare function setupGameBackendDevServer(options: GameBackendDevServerOptions): Promise<GameBackendServerManager | null>;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Hot reload callbacks — log a rebuild outcome under the given domain
3
+ * (`backend` for the game worker, `dashboard` for the dashboard worker).
4
+ */
5
+ import type { ResolvedConfig } from 'vite';
6
+ /**
7
+ * Creates hot reload callbacks for logging rebuild results.
8
+ */
9
+ export declare function createHotReloadCallbacks(viteConfig: ResolvedConfig, domain: string): {
10
+ onSuccess: (changedPath?: string) => void;
11
+ onError: (error: unknown) => void;
12
+ };
@@ -3,4 +3,5 @@
3
3
  */
4
4
  export type { PluginLogger } from './adapter';
5
5
  export { createLoggerAdapter } from './adapter';
6
- export { createBackendBannerOptions, createTimebackBannerOptions, log, printBanner } from './utils';
6
+ export * from './hot-reload';
7
+ export { createGameBannerOptions, createTimebackBannerOptions, printBanner } from './utils';
@@ -1,18 +1,13 @@
1
- import type { ResolvedConfig } from 'vite';
2
- import type { BannerOptions } from '../../types';
3
1
  /**
4
2
  * Centralized logging utilities for the Vite plugin.
5
3
  * Provides clear, prefixed, and color-coded output for multiple servers.
6
4
  */
7
- export declare const log: {
8
- sandbox: (msg: string) => void;
9
- backend: (msg: string) => void;
10
- playcademy: (msg: string) => void;
11
- };
5
+ import type { ResolvedConfig } from 'vite';
6
+ import type { BannerOptions } from '../../types';
12
7
  /**
13
- * Create backend banner options from server info
8
+ * Create game backend banner options from server info
14
9
  */
15
- export declare function createBackendBannerOptions(backendPort: number | undefined, vitePort: number | undefined): BannerOptions['backend'];
10
+ export declare function createGameBannerOptions(gameBackendPort: number | undefined, vitePort: number | undefined): BannerOptions['gameBackend'];
16
11
  /**
17
12
  * Create timeback banner options from sandbox state
18
13
  */
@@ -0,0 +1,15 @@
1
+ /**
2
+ * 'a' hotkey - cycle the auto-started dashboard app's role (admin/viewer)
3
+ *
4
+ * The dashboard child forwards its output into the game terminal but its
5
+ * own hotkeys need a keyboard, so the game terminal reaches its role
6
+ * toggle through the dev-only endpoint the child exposes. The child logs
7
+ * the role change itself; that line is forwarded here, so success needs
8
+ * no extra output.
9
+ */
10
+ import type { HotkeyOptions } from '../../types';
11
+ export declare function toggleDashboardRoleHotkey(options: HotkeyOptions): {
12
+ key: string;
13
+ description: string;
14
+ action: () => undefined;
15
+ };
@@ -7,14 +7,16 @@
7
7
  * these references at module scope to properly clean them up on restart.
8
8
  */
9
9
  import type { ViteDevServer } from 'vite';
10
- import type { CliServerManager, PlatformRoleOverride, SandboxManager, TimebackRoleOverride } from '../types';
10
+ import type { DashboardAppManager } from '../lib/dashboard-app';
11
+ import type { GameBackendServerManager, PlatformRoleOverride, SandboxManager, TimebackRoleOverride } from '../types';
11
12
  import type { PlaycademyMode } from '../types/options';
12
13
  /**
13
14
  * Module-level server references
14
15
  */
15
16
  export declare const serverState: {
16
17
  sandbox: SandboxManager | null;
17
- backend: CliServerManager | null;
18
+ gameBackend: GameBackendServerManager | null;
19
+ dashboardApp: DashboardAppManager | null;
18
20
  viteServer: ViteDevServer | null;
19
21
  currentMode: PlaycademyMode;
20
22
  timebackRoleOverride: TimebackRoleOverride | null;
@@ -28,14 +30,6 @@ export declare function getSandboxRef(): SandboxManager | null;
28
30
  * Set sandbox server reference
29
31
  */
30
32
  export declare function setSandboxRef(sandbox: SandboxManager | null): void;
31
- /**
32
- * Get backend server reference
33
- */
34
- export declare function getBackendRef(): CliServerManager | null;
35
- /**
36
- * Set backend server reference
37
- */
38
- export declare function setBackendRef(backend: CliServerManager | null): void;
39
33
  /**
40
34
  * Check if any servers are currently running
41
35
  */
@@ -2,5 +2,5 @@
2
2
  * Type exports for the Playcademy Vite Plugin
3
3
  */
4
4
  export type { PlaycademyExportOptions, PlaycademySandboxOptions, PlaycademyDisplayOptions, PlaycademyPluginOptions, PlaycademyTimebackOptions, PlaycademyMode, } from './options';
5
- export type { BannerOptions, CliDevServerOptions, CliServerManager, HotkeyOptions, PlatformModeOptions, PlatformRoleOverride, PlaycademyOutputData, PluginContext, ProjectInfo, ResolvedPluginOptions, SandboxManager, StandaloneModeOptions, TimebackCourseConfig, TimebackPluginContext, TimebackRoleOverride, } from './internal';
5
+ export type { BannerOptions, GameBackendDevServerOptions, GameBackendServerManager, HotkeyOptions, PlatformModeOptions, PlatformRoleOverride, PlaycademyOutputData, PluginContext, ProjectInfo, ResolvedPluginOptions, SandboxManager, StandaloneModeOptions, TimebackCourseConfig, TimebackPluginContext, TimebackRoleOverride, } from './internal';
6
6
  export { TIMEBACK_ROLES, PLATFORM_ROLES } from './internal';
@@ -19,9 +19,13 @@ export type PlatformRoleOverride = (typeof PLATFORM_ROLES)[number];
19
19
  export interface ResolvedPluginOptions {
20
20
  configPath?: string;
21
21
  mode: PlaycademyMode;
22
+ gameBackendPort: number;
23
+ sandboxPort: number;
24
+ dashboardAppPort: number;
22
25
  autoZip: boolean;
23
26
  sandboxUrl: string;
24
27
  startSandbox: boolean;
28
+ startDashboard: boolean;
25
29
  verbose: boolean;
26
30
  logLevel: 'debug' | 'info' | 'warn' | 'error';
27
31
  recreateDb: boolean;
@@ -37,8 +41,6 @@ export interface ResolvedPluginOptions {
37
41
  export interface PluginContext {
38
42
  options: ResolvedPluginOptions;
39
43
  viteConfig: ResolvedConfig | null;
40
- backendPort: number | null;
41
- sandboxPort: number | null;
42
44
  buildOutputs: PlaycademyOutputData;
43
45
  }
44
46
  /**
@@ -99,7 +101,7 @@ export interface SandboxManager {
99
101
  /**
100
102
  * CLI server manager interface for controlling backend server lifecycle
101
103
  */
102
- export interface CliServerManager {
104
+ export interface GameBackendServerManager {
103
105
  server: {
104
106
  dispose: () => Promise<void>;
105
107
  };
@@ -110,7 +112,7 @@ export interface CliServerManager {
110
112
  /**
111
113
  * Options for setting up the CLI dev server
112
114
  */
113
- export interface CliDevServerOptions {
115
+ export interface GameBackendDevServerOptions {
114
116
  port: number;
115
117
  viteConfig: ResolvedConfig;
116
118
  platformUrl?: string;
@@ -122,7 +124,9 @@ export interface CliDevServerOptions {
122
124
  */
123
125
  export interface PlatformModeOptions {
124
126
  startSandbox: boolean;
127
+ startDashboard: boolean;
125
128
  sandboxPort: number;
129
+ dashboardAppPort: number;
126
130
  verbose: boolean;
127
131
  logLevel: 'debug' | 'info' | 'warn' | 'error';
128
132
  sandboxUrl: string;
@@ -131,7 +135,7 @@ export interface PlatformModeOptions {
131
135
  memoryOnly: boolean;
132
136
  databasePath?: string;
133
137
  hideBadge: boolean;
134
- backendPort: number;
138
+ gameBackendPort: number;
135
139
  configPath?: string;
136
140
  timeback?: PlaycademyTimebackOptions | false;
137
141
  }
@@ -139,7 +143,7 @@ export interface PlatformModeOptions {
139
143
  * Options for standalone mode (backend only)
140
144
  */
141
145
  export interface StandaloneModeOptions {
142
- backendPort: number;
146
+ gameBackendPort: number;
143
147
  configPath?: string;
144
148
  }
145
149
  /**
@@ -165,11 +169,15 @@ export interface BannerOptions {
165
169
  enabled: false;
166
170
  };
167
171
  /** Backend server info */
168
- backend?: {
172
+ gameBackend?: {
169
173
  port: number;
170
174
  /** Vite port for proxied URL display */
171
175
  vitePort?: number;
172
176
  };
177
+ /** Dashboard app info (when auto-started alongside the game) */
178
+ dashboard?: {
179
+ port: number;
180
+ };
173
181
  /** Timeback info (shell-backed modes only) */
174
182
  timeback?: {
175
183
  courseCount: number;
@@ -12,6 +12,31 @@
12
12
  * @default 'platform'
13
13
  */
14
14
  export type PlaycademyMode = 'platform' | 'demo' | 'standalone';
15
+ /**
16
+ * Configuration for developing a game's dashboard app.
17
+ *
18
+ * In dashboard mode the plugin runs the real composed dashboard worker —
19
+ * the platform's auth layer plus your api/ routes — under Miniflare, with
20
+ * the same local data the game's dev server uses, and proxies `/api/*` to
21
+ * it with an always-signed-in developer session.
22
+ */
23
+ export interface PlaycademyDashboardOptions {
24
+ /**
25
+ * The role of the local developer identity.
26
+ *
27
+ * Set `'viewer'` to exercise read-only UI states and route role policy.
28
+ * Toggle at runtime with the `d` hotkey in the Vite terminal.
29
+ *
30
+ * @default 'admin'
31
+ */
32
+ role?: 'admin' | 'viewer';
33
+ /**
34
+ * Port for the local dashboard worker.
35
+ *
36
+ * @default 8789
37
+ */
38
+ workerPort?: number;
39
+ }
15
40
  /**
16
41
  * Configuration options for exporting/building Playcademy games
17
42
  *
@@ -334,6 +359,65 @@ export interface PlaycademyPluginOptions {
334
359
  * ```
335
360
  */
336
361
  mode?: PlaycademyMode;
362
+ /**
363
+ * Develop a dashboard app instead of a game.
364
+ *
365
+ * Runs the real composed dashboard worker (platform auth layer + your
366
+ * api/ routes) locally and proxies `/api/*` to it with a signed-in
367
+ * session; disables the game machinery (sandbox, shell, backend
368
+ * bundling, manifest/zip). `playcademy dashboard init` sets this up.
369
+ *
370
+ * @example
371
+ * ```ts
372
+ * {
373
+ * dashboard: true
374
+ * }
375
+ * ```
376
+ * @example
377
+ * ```ts
378
+ * {
379
+ * dashboard: { role: 'viewer' } // exercise read-only UI states
380
+ * }
381
+ * ```
382
+ */
383
+ dashboard?: boolean | PlaycademyDashboardOptions;
384
+ /**
385
+ * Port for the local game backend worker.
386
+ *
387
+ * Override when the default collides with another dev server on the
388
+ * same machine — every internal consumer (the /api proxy, hot reload,
389
+ * the dev shell) follows this port.
390
+ *
391
+ * @default 8788
392
+ */
393
+ gameBackendPort?: number;
394
+ /**
395
+ * Port for the local sandbox platform.
396
+ *
397
+ * @default 4321
398
+ */
399
+ sandboxPort?: number;
400
+ /**
401
+ * Port for the auto-started dashboard app's Vite server.
402
+ *
403
+ * The game's dev server assigns this port when it spawns the dashboard
404
+ * app (with `--strictPort`), so the dashboard's own vite config cannot
405
+ * move it.
406
+ *
407
+ * @default 8790
408
+ */
409
+ dashboardAppPort?: number;
410
+ /**
411
+ * Auto-start the project's dashboard app alongside game dev.
412
+ *
413
+ * When the project's playcademy.config declares a dashboard, the game's
414
+ * dev server starts the dashboard's own dev script next to the sandbox
415
+ * and backend. Set `false` to run the dashboard separately (or not at
416
+ * all) with `playcademy dashboard dev`.
417
+ *
418
+ * @default true
419
+ */
420
+ startDashboard?: boolean;
337
421
  /**
338
422
  * Export/build configuration options.
339
423
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@playcademy/vite-plugin",
3
- "version": "1.1.3-beta.2",
3
+ "version": "1.1.3-beta.4",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -19,14 +19,14 @@
19
19
  "dependencies": {
20
20
  "archiver": "^7.0.1",
21
21
  "picocolors": "^1.1.1",
22
- "playcademy": "0.27.1-beta.2"
22
+ "playcademy": "0.27.1-beta.4"
23
23
  },
24
24
  "devDependencies": {
25
25
  "@electric-sql/pglite": "^0.3.16",
26
26
  "@inquirer/prompts": "^7.8.6",
27
27
  "@playcademy/constants": "0.0.1",
28
- "@playcademy/sandbox": "0.6.1-beta.3",
29
- "@playcademy/sdk": "0.15.1-beta.1",
28
+ "@playcademy/sandbox": "0.6.1-beta.5",
29
+ "@playcademy/sdk": "0.15.1-beta.3",
30
30
  "@playcademy/types": "0.0.1",
31
31
  "@playcademy/utils": "0.0.1",
32
32
  "@types/archiver": "^6.0.3",
@@ -35,6 +35,6 @@
35
35
  "peerDependencies": {
36
36
  "@playcademy/sdk": ">=0.12.0",
37
37
  "typescript": "^5 || ^6",
38
- "vite": "^5 || ^6 || ^7"
38
+ "vite": "^5 || ^6 || ^7 || ^8"
39
39
  }
40
40
  }
@@ -1,11 +0,0 @@
1
- /**
2
- * Hot reload callbacks for backend server
3
- */
4
- import type { ResolvedConfig } from 'vite';
5
- /**
6
- * Creates hot reload callbacks for logging backend updates.
7
- */
8
- export declare function createHotReloadCallbacks(viteConfig: ResolvedConfig): {
9
- onSuccess: (changedPath?: string) => void;
10
- onError: (error: unknown) => void;
11
- };
@@ -1,5 +0,0 @@
1
- /**
2
- * Backend server management
3
- */
4
- export { setupCliDevServer } from './server';
5
- export { createHotReloadCallbacks } from './hot-reload';
@@ -1,9 +0,0 @@
1
- import type { CliDevServerOptions, CliServerManager } from '../../types';
2
- /**
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).
6
- *
7
- * Used by the Vite plugin to manage the game backend server.
8
- */
9
- export declare function setupCliDevServer(options: CliDevServerOptions): Promise<CliServerManager | null>;