@littlepartytime/dev-kit 1.0.0 → 1.2.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.
Files changed (58) hide show
  1. package/dist/cli.d.ts.map +1 -1
  2. package/dist/cli.js +4 -3
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/dev.d.ts +12 -0
  5. package/dist/commands/dev.d.ts.map +1 -0
  6. package/dist/commands/dev.js +76 -0
  7. package/dist/commands/dev.js.map +1 -0
  8. package/dist/index.d.ts +2 -0
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +3 -1
  11. package/dist/index.js.map +1 -1
  12. package/dist/server/engine-loader.d.ts +11 -0
  13. package/dist/server/engine-loader.d.ts.map +1 -0
  14. package/dist/server/engine-loader.js +45 -0
  15. package/dist/server/engine-loader.js.map +1 -0
  16. package/dist/server/game-room.d.ts +25 -0
  17. package/dist/server/game-room.d.ts.map +1 -0
  18. package/dist/server/game-room.js +78 -0
  19. package/dist/server/game-room.js.map +1 -0
  20. package/dist/server/socket-server.d.ts +16 -0
  21. package/dist/server/socket-server.d.ts.map +1 -0
  22. package/dist/server/socket-server.js +167 -0
  23. package/dist/server/socket-server.js.map +1 -0
  24. package/dist/testing/game-preview.d.ts +53 -0
  25. package/dist/testing/game-preview.d.ts.map +1 -0
  26. package/dist/testing/game-preview.js +158 -0
  27. package/dist/testing/game-preview.js.map +1 -0
  28. package/dist/testing/index.d.ts +3 -0
  29. package/dist/testing/index.d.ts.map +1 -0
  30. package/dist/testing/index.js +6 -0
  31. package/dist/testing/index.js.map +1 -0
  32. package/dist/webapp/App.d.ts +3 -0
  33. package/dist/webapp/App.d.ts.map +1 -0
  34. package/dist/webapp/App.js +70 -0
  35. package/dist/webapp/App.js.map +1 -0
  36. package/dist/webapp/App.tsx +40 -0
  37. package/dist/webapp/index.html +16 -0
  38. package/dist/webapp/main.d.ts +2 -0
  39. package/dist/webapp/main.d.ts.map +1 -0
  40. package/dist/webapp/main.js +12 -0
  41. package/dist/webapp/main.js.map +1 -0
  42. package/dist/webapp/main.tsx +9 -0
  43. package/dist/webapp/pages/Debug.d.ts +3 -0
  44. package/dist/webapp/pages/Debug.d.ts.map +1 -0
  45. package/dist/webapp/pages/Debug.js +69 -0
  46. package/dist/webapp/pages/Debug.js.map +1 -0
  47. package/dist/webapp/pages/Debug.tsx +40 -0
  48. package/dist/webapp/pages/Play.d.ts +3 -0
  49. package/dist/webapp/pages/Play.d.ts.map +1 -0
  50. package/dist/webapp/pages/Play.js +129 -0
  51. package/dist/webapp/pages/Play.js.map +1 -0
  52. package/dist/webapp/pages/Play.tsx +137 -0
  53. package/dist/webapp/pages/Preview.d.ts +3 -0
  54. package/dist/webapp/pages/Preview.d.ts.map +1 -0
  55. package/dist/webapp/pages/Preview.js +118 -0
  56. package/dist/webapp/pages/Preview.js.map +1 -0
  57. package/dist/webapp/pages/Preview.tsx +265 -0
  58. package/package.json +31 -3
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,QAAA,MAAM,OAAO,QAAkB,CAAC;AAEhC,iBAAe,IAAI,kBAmBlB"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,QAAA,MAAM,OAAO,QAAkB,CAAC;AAEhC,iBAAe,IAAI,kBAoBlB"}
package/dist/cli.js CHANGED
@@ -42,15 +42,16 @@ async function main() {
42
42
  break;
43
43
  }
44
44
  case 'dev': {
45
- console.log('lpt-dev-kit dev server is not yet implemented (Phase 2)');
46
- process.exit(1);
45
+ const { devCommand } = await Promise.resolve().then(() => __importStar(require('./commands/dev')));
46
+ await devCommand(process.cwd());
47
+ break;
47
48
  }
48
49
  default:
49
50
  console.log('Usage: lpt-dev-kit <command>');
50
51
  console.log('');
51
52
  console.log('Commands:');
53
+ console.log(' dev Start development server');
52
54
  console.log(' pack Build and package game as .zip');
53
- console.log(' dev Start development server (coming soon)');
54
55
  process.exit(command ? 1 : 0);
55
56
  }
56
57
  }
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAEhC,KAAK,UAAU,IAAI;IACjB,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,MAAM,EAAE,WAAW,EAAE,GAAG,wDAAa,iBAAiB,GAAC,CAAC;YACxD,MAAM,WAAW,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;YACjC,MAAM;QACR,CAAC;QACD,KAAK,KAAK,CAAC,CAAC,CAAC;YACX,OAAO,CAAC,GAAG,CAAC,yDAAyD,CAAC,CAAC;YACvE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD;YACE,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;YAC5C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAChB,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;YACxD,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC;YAChE,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC3B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAEhC,KAAK,UAAU,IAAI;IACjB,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,MAAM,EAAE,WAAW,EAAE,GAAG,wDAAa,iBAAiB,GAAC,CAAC;YACxD,MAAM,WAAW,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;YACjC,MAAM;QACR,CAAC;QACD,KAAK,KAAK,CAAC,CAAC,CAAC;YACX,MAAM,EAAE,UAAU,EAAE,GAAG,wDAAa,gBAAgB,GAAC,CAAC;YACtD,MAAM,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;YAChC,MAAM;QACR,CAAC;QACD;YACE,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;YAC5C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAChB,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;YAClD,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;YACxD,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC3B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,12 @@
1
+ export interface DevOptions {
2
+ port?: number;
3
+ socketPort?: number;
4
+ silent?: boolean;
5
+ }
6
+ export interface DevServerHandle {
7
+ stop(): Promise<void>;
8
+ port: number;
9
+ socketPort: number;
10
+ }
11
+ export declare function devCommand(projectDir: string, options?: DevOptions): Promise<DevServerHandle>;
12
+ //# sourceMappingURL=dev.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,UAAe,GAAG,OAAO,CAAC,eAAe,CAAC,CAwEvG"}
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.devCommand = devCommand;
7
+ // packages/dev-kit/src/commands/dev.ts
8
+ const path_1 = __importDefault(require("path"));
9
+ const vite_1 = require("vite");
10
+ const socket_server_1 = require("../server/socket-server");
11
+ const chokidar_1 = __importDefault(require("chokidar"));
12
+ async function devCommand(projectDir, options = {}) {
13
+ const port = options.port || 4000;
14
+ const socketPort = options.socketPort || 4001;
15
+ if (!options.silent) {
16
+ console.log('');
17
+ console.log(' Little Party Time Dev Kit');
18
+ console.log(' =========================');
19
+ console.log('');
20
+ }
21
+ // Start Socket.IO server
22
+ const { server, io, reloadEngine } = (0, socket_server_1.createSocketServer)({
23
+ port: socketPort,
24
+ projectDir,
25
+ });
26
+ // Watch for engine changes
27
+ const enginePath = path_1.default.join(projectDir, 'dist', 'engine.cjs');
28
+ const watcher = chokidar_1.default.watch(enginePath, { ignoreInitial: true });
29
+ watcher.on('change', () => {
30
+ if (!options.silent) {
31
+ console.log('[Dev] Engine changed, reloading...');
32
+ }
33
+ reloadEngine();
34
+ });
35
+ // Start Vite dev server
36
+ const webappDir = path_1.default.join(__dirname, '..', 'webapp');
37
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
38
+ const react = require('@vitejs/plugin-react').default;
39
+ const vite = await (0, vite_1.createServer)({
40
+ root: webappDir,
41
+ plugins: [react()],
42
+ server: {
43
+ port,
44
+ fs: {
45
+ allow: [webappDir, projectDir],
46
+ },
47
+ },
48
+ resolve: {
49
+ alias: {
50
+ '/src': path_1.default.join(projectDir, 'src'),
51
+ },
52
+ },
53
+ });
54
+ await vite.listen();
55
+ if (!options.silent) {
56
+ console.log(` Preview: http://localhost:${port}/preview`);
57
+ console.log(` Multiplayer: http://localhost:${port}/play`);
58
+ console.log(` Debug Panel: http://localhost:${port}/debug`);
59
+ console.log(` Socket.IO: ws://localhost:${socketPort}`);
60
+ console.log('');
61
+ console.log(' Press Ctrl+C to stop');
62
+ console.log('');
63
+ }
64
+ return {
65
+ port,
66
+ socketPort,
67
+ async stop() {
68
+ await watcher.close();
69
+ await vite.close();
70
+ io.disconnectSockets(true);
71
+ io.close();
72
+ await new Promise((resolve) => server.close(() => resolve()));
73
+ },
74
+ };
75
+ }
76
+ //# sourceMappingURL=dev.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
1
  export { validateBundle } from './utils/validate-bundle';
2
2
  export type { ValidationResult } from './utils/validate-bundle';
3
+ export { devCommand } from './commands/dev';
4
+ export type { DevOptions, DevServerHandle } from './commands/dev';
3
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,YAAY,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,YAAY,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.validateBundle = void 0;
3
+ exports.devCommand = exports.validateBundle = void 0;
4
4
  var validate_bundle_1 = require("./utils/validate-bundle");
5
5
  Object.defineProperty(exports, "validateBundle", { enumerable: true, get: function () { return validate_bundle_1.validateBundle; } });
6
+ var dev_1 = require("./commands/dev");
7
+ Object.defineProperty(exports, "devCommand", { enumerable: true, get: function () { return dev_1.devCommand; } });
6
8
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,2DAAyD;AAAhD,iHAAA,cAAc,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,2DAAyD;AAAhD,iHAAA,cAAc,OAAA;AAEvB,sCAA4C;AAAnC,iGAAA,UAAU,OAAA"}
@@ -0,0 +1,11 @@
1
+ export interface GameEngine {
2
+ init(players: any[], options?: Record<string, unknown>): any;
3
+ handleAction(state: any, playerId: string, action: any): any;
4
+ isGameOver(state: any): boolean;
5
+ getResult(state: any): any;
6
+ getPlayerView(state: any, playerId: string): any;
7
+ }
8
+ export declare function loadEngine(projectDir: string): GameEngine;
9
+ export declare function getEngine(): GameEngine | null;
10
+ export declare function clearEngineCache(): void;
11
+ //# sourceMappingURL=engine-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine-loader.d.ts","sourceRoot":"","sources":["../../src/server/engine-loader.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,GAAG,CAAC;IAC7D,YAAY,CAAC,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,GAAG,CAAC;IAC7D,UAAU,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC;IAChC,SAAS,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG,CAAC;IAC3B,aAAa,CAAC,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,GAAG,GAAG,CAAC;CAClD;AAKD,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,CAyBzD;AAED,wBAAgB,SAAS,IAAI,UAAU,GAAG,IAAI,CAE7C;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAMvC"}
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.loadEngine = loadEngine;
7
+ exports.getEngine = getEngine;
8
+ exports.clearEngineCache = clearEngineCache;
9
+ // packages/dev-kit/src/server/engine-loader.ts
10
+ const path_1 = __importDefault(require("path"));
11
+ const fs_1 = __importDefault(require("fs"));
12
+ let cachedEngine = null;
13
+ let cachedEnginePath = null;
14
+ function loadEngine(projectDir) {
15
+ const enginePath = path_1.default.join(projectDir, 'dist', 'engine.cjs');
16
+ if (!fs_1.default.existsSync(enginePath)) {
17
+ throw new Error(`Engine not found at ${enginePath}. Run 'npm run build' first.`);
18
+ }
19
+ // Clear require cache for hot reload
20
+ if (cachedEnginePath && require.cache[require.resolve(cachedEnginePath)]) {
21
+ delete require.cache[require.resolve(cachedEnginePath)];
22
+ }
23
+ const module = require(enginePath);
24
+ cachedEngine = module.engine || module.default?.engine || module;
25
+ cachedEnginePath = enginePath;
26
+ // Validate engine has required methods
27
+ const required = ['init', 'handleAction', 'isGameOver', 'getResult', 'getPlayerView'];
28
+ for (const method of required) {
29
+ if (typeof cachedEngine[method] !== 'function') {
30
+ throw new Error(`Engine missing required method: ${method}`);
31
+ }
32
+ }
33
+ return cachedEngine;
34
+ }
35
+ function getEngine() {
36
+ return cachedEngine;
37
+ }
38
+ function clearEngineCache() {
39
+ if (cachedEnginePath && require.cache[require.resolve(cachedEnginePath)]) {
40
+ delete require.cache[require.resolve(cachedEnginePath)];
41
+ }
42
+ cachedEngine = null;
43
+ cachedEnginePath = null;
44
+ }
45
+ //# sourceMappingURL=engine-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine-loader.js","sourceRoot":"","sources":["../../src/server/engine-loader.ts"],"names":[],"mappings":";;;;;AAeA,gCAyBC;AAED,8BAEC;AAED,4CAMC;AApDD,+CAA+C;AAC/C,gDAAwB;AACxB,4CAAoB;AAUpB,IAAI,YAAY,GAAsB,IAAI,CAAC;AAC3C,IAAI,gBAAgB,GAAkB,IAAI,CAAC;AAE3C,SAAgB,UAAU,CAAC,UAAkB;IAC3C,MAAM,UAAU,GAAG,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;IAE/D,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,uBAAuB,UAAU,8BAA8B,CAAC,CAAC;IACnF,CAAC;IAED,qCAAqC;IACrC,IAAI,gBAAgB,IAAI,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC;QACzE,OAAO,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACnC,YAAY,GAAG,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,MAAM,IAAI,MAAM,CAAC;IACjE,gBAAgB,GAAG,UAAU,CAAC;IAE9B,uCAAuC;IACvC,MAAM,QAAQ,GAAG,CAAC,MAAM,EAAE,cAAc,EAAE,YAAY,EAAE,WAAW,EAAE,eAAe,CAAC,CAAC;IACtF,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;QAC9B,IAAI,OAAQ,YAAoB,CAAC,MAAM,CAAC,KAAK,UAAU,EAAE,CAAC;YACxD,MAAM,IAAI,KAAK,CAAC,mCAAmC,MAAM,EAAE,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC;IAED,OAAO,YAA0B,CAAC;AACpC,CAAC;AAED,SAAgB,SAAS;IACvB,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,SAAgB,gBAAgB;IAC9B,IAAI,gBAAgB,IAAI,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC;QACzE,OAAO,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAC1D,CAAC;IACD,YAAY,GAAG,IAAI,CAAC;IACpB,gBAAgB,GAAG,IAAI,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,25 @@
1
+ import type { GameEngine } from './engine-loader';
2
+ export interface Player {
3
+ id: string;
4
+ nickname: string;
5
+ avatarUrl: string | null;
6
+ isHost: boolean;
7
+ socketId: string;
8
+ ready: boolean;
9
+ }
10
+ export interface GameRoom {
11
+ players: Player[];
12
+ state: any | null;
13
+ phase: 'lobby' | 'ready' | 'playing' | 'ended';
14
+ gameId: string;
15
+ }
16
+ export declare function createRoom(gameId: string): GameRoom;
17
+ export declare function addPlayer(room: GameRoom, socketId: string, nickname: string): Player;
18
+ export declare function removePlayer(room: GameRoom, socketId: string): Player | null;
19
+ export declare function getPlayerBySocketId(room: GameRoom, socketId: string): Player | undefined;
20
+ export declare function setPlayerReady(room: GameRoom, socketId: string, ready: boolean): void;
21
+ export declare function allPlayersReady(room: GameRoom): boolean;
22
+ export declare function startGame(room: GameRoom, engine: GameEngine): void;
23
+ export declare function handleAction(room: GameRoom, engine: GameEngine, playerId: string, action: any): void;
24
+ export declare function resetRoom(room: GameRoom): void;
25
+ //# sourceMappingURL=game-room.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"game-room.d.ts","sourceRoot":"","sources":["../../src/server/game-room.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE,GAAG,GAAG,IAAI,CAAC;IAClB,KAAK,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;IAC/C,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAOnD;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAYpF;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAY5E;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAExF;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAGrF;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAEvD;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAUlE;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,IAAI,CAQpG;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAI9C"}
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createRoom = createRoom;
4
+ exports.addPlayer = addPlayer;
5
+ exports.removePlayer = removePlayer;
6
+ exports.getPlayerBySocketId = getPlayerBySocketId;
7
+ exports.setPlayerReady = setPlayerReady;
8
+ exports.allPlayersReady = allPlayersReady;
9
+ exports.startGame = startGame;
10
+ exports.handleAction = handleAction;
11
+ exports.resetRoom = resetRoom;
12
+ function createRoom(gameId) {
13
+ return {
14
+ players: [],
15
+ state: null,
16
+ phase: 'lobby',
17
+ gameId,
18
+ };
19
+ }
20
+ function addPlayer(room, socketId, nickname) {
21
+ const isHost = room.players.length === 0;
22
+ const player = {
23
+ id: `player-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
24
+ nickname,
25
+ avatarUrl: null,
26
+ isHost,
27
+ socketId,
28
+ ready: false,
29
+ };
30
+ room.players.push(player);
31
+ return player;
32
+ }
33
+ function removePlayer(room, socketId) {
34
+ const index = room.players.findIndex(p => p.socketId === socketId);
35
+ if (index === -1)
36
+ return null;
37
+ const [removed] = room.players.splice(index, 1);
38
+ // Promote new host if needed
39
+ if (removed.isHost && room.players.length > 0) {
40
+ room.players[0].isHost = true;
41
+ }
42
+ return removed;
43
+ }
44
+ function getPlayerBySocketId(room, socketId) {
45
+ return room.players.find(p => p.socketId === socketId);
46
+ }
47
+ function setPlayerReady(room, socketId, ready) {
48
+ const player = getPlayerBySocketId(room, socketId);
49
+ if (player)
50
+ player.ready = ready;
51
+ }
52
+ function allPlayersReady(room) {
53
+ return room.players.length >= 2 && room.players.every(p => p.ready);
54
+ }
55
+ function startGame(room, engine) {
56
+ const players = room.players.map(p => ({
57
+ id: p.id,
58
+ nickname: p.nickname,
59
+ avatarUrl: p.avatarUrl,
60
+ isHost: p.isHost,
61
+ }));
62
+ room.state = engine.init(players);
63
+ room.phase = 'playing';
64
+ }
65
+ function handleAction(room, engine, playerId, action) {
66
+ if (room.phase !== 'playing' || !room.state)
67
+ return;
68
+ room.state = engine.handleAction(room.state, playerId, action);
69
+ if (engine.isGameOver(room.state)) {
70
+ room.phase = 'ended';
71
+ }
72
+ }
73
+ function resetRoom(room) {
74
+ room.state = null;
75
+ room.phase = 'lobby';
76
+ room.players.forEach(p => p.ready = false);
77
+ }
78
+ //# sourceMappingURL=game-room.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"game-room.js","sourceRoot":"","sources":["../../src/server/game-room.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { Server } from 'socket.io';
2
+ import http from 'http';
3
+ import * as GameRoom from './game-room';
4
+ export interface SocketServerOptions {
5
+ port: number;
6
+ projectDir: string;
7
+ onStateChange?: (room: GameRoom.GameRoom) => void;
8
+ onLog?: (message: string) => void;
9
+ }
10
+ export declare function createSocketServer(options: SocketServerOptions): {
11
+ server: http.Server;
12
+ io: Server;
13
+ getRoom: () => GameRoom.GameRoom;
14
+ reloadEngine: () => void;
15
+ };
16
+ //# sourceMappingURL=socket-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"socket-server.d.ts","sourceRoot":"","sources":["../../src/server/socket-server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACnC,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,KAAK,QAAQ,MAAM,aAAa,CAAC;AAExC,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,QAAQ,KAAK,IAAI,CAAC;IAClD,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,mBAAmB,GAAG;IAChE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,QAAQ,CAAC,QAAQ,CAAC;IACjC,YAAY,EAAE,MAAM,IAAI,CAAC;CAC1B,CAyIA"}
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.createSocketServer = createSocketServer;
40
+ // packages/dev-kit/src/server/socket-server.ts
41
+ const socket_io_1 = require("socket.io");
42
+ const http_1 = __importDefault(require("http"));
43
+ const engine_loader_1 = require("./engine-loader");
44
+ const GameRoom = __importStar(require("./game-room"));
45
+ function createSocketServer(options) {
46
+ const { port, projectDir, onStateChange, onLog } = options;
47
+ const log = (msg) => {
48
+ onLog?.(msg);
49
+ console.log(`[Socket] ${msg}`);
50
+ };
51
+ // Load engine
52
+ let engine = (0, engine_loader_1.loadEngine)(projectDir);
53
+ log(`Engine loaded from ${projectDir}`);
54
+ // Create room
55
+ const room = GameRoom.createRoom('dev-game');
56
+ const server = http_1.default.createServer();
57
+ const io = new socket_io_1.Server(server, {
58
+ cors: { origin: '*' },
59
+ });
60
+ io.on('connection', (socket) => {
61
+ const nickname = socket.handshake.query.nickname || `Player ${room.players.length + 1}`;
62
+ const player = GameRoom.addPlayer(room, socket.id, nickname);
63
+ log(`${player.nickname} joined (${player.id})`);
64
+ // Notify all
65
+ io.emit('room:update', {
66
+ players: room.players.map(p => ({ id: p.id, nickname: p.nickname, isHost: p.isHost, ready: p.ready })),
67
+ phase: room.phase,
68
+ });
69
+ onStateChange?.(room);
70
+ // Ready toggle
71
+ socket.on('player:ready', (ready) => {
72
+ GameRoom.setPlayerReady(room, socket.id, ready);
73
+ io.emit('room:update', {
74
+ players: room.players.map(p => ({ id: p.id, nickname: p.nickname, isHost: p.isHost, ready: p.ready })),
75
+ phase: room.phase,
76
+ });
77
+ onStateChange?.(room);
78
+ log(`${player.nickname} is ${ready ? 'ready' : 'not ready'}`);
79
+ });
80
+ // Start game (host only)
81
+ socket.on('game:start', () => {
82
+ if (!player.isHost)
83
+ return;
84
+ if (!GameRoom.allPlayersReady(room))
85
+ return;
86
+ GameRoom.startGame(room, engine);
87
+ log(`Game started!`);
88
+ // Send initial state to each player
89
+ room.players.forEach(p => {
90
+ const playerSocket = io.sockets.sockets.get(p.socketId);
91
+ if (playerSocket) {
92
+ const view = engine.getPlayerView(room.state, p.id);
93
+ playerSocket.emit('game:state', view);
94
+ }
95
+ });
96
+ io.emit('room:update', {
97
+ players: room.players.map(p => ({ id: p.id, nickname: p.nickname, isHost: p.isHost, ready: p.ready })),
98
+ phase: room.phase,
99
+ });
100
+ onStateChange?.(room);
101
+ });
102
+ // Game action
103
+ socket.on('game:action', (action) => {
104
+ if (room.phase !== 'playing')
105
+ return;
106
+ log(`${player.nickname} action: ${JSON.stringify(action)}`);
107
+ GameRoom.handleAction(room, engine, player.id, action);
108
+ // Broadcast updated state
109
+ room.players.forEach(p => {
110
+ const playerSocket = io.sockets.sockets.get(p.socketId);
111
+ if (playerSocket) {
112
+ const view = engine.getPlayerView(room.state, p.id);
113
+ playerSocket.emit('game:state', view);
114
+ }
115
+ });
116
+ // Check game over (use type assertion since handleAction may have changed phase)
117
+ if (room.phase === 'ended') {
118
+ const result = engine.getResult(room.state);
119
+ io.emit('game:result', result);
120
+ log(`Game ended! Result: ${JSON.stringify(result)}`);
121
+ }
122
+ io.emit('room:update', {
123
+ players: room.players.map(p => ({ id: p.id, nickname: p.nickname, isHost: p.isHost, ready: p.ready })),
124
+ phase: room.phase,
125
+ });
126
+ onStateChange?.(room);
127
+ });
128
+ // Play again
129
+ socket.on('game:playAgain', () => {
130
+ if (!player.isHost)
131
+ return;
132
+ GameRoom.resetRoom(room);
133
+ io.emit('room:update', {
134
+ players: room.players.map(p => ({ id: p.id, nickname: p.nickname, isHost: p.isHost, ready: p.ready })),
135
+ phase: room.phase,
136
+ });
137
+ onStateChange?.(room);
138
+ log(`Room reset by host`);
139
+ });
140
+ // Disconnect
141
+ socket.on('disconnect', () => {
142
+ const removed = GameRoom.removePlayer(room, socket.id);
143
+ if (removed) {
144
+ log(`${removed.nickname} left`);
145
+ io.emit('room:update', {
146
+ players: room.players.map(p => ({ id: p.id, nickname: p.nickname, isHost: p.isHost, ready: p.ready })),
147
+ phase: room.phase,
148
+ });
149
+ onStateChange?.(room);
150
+ }
151
+ });
152
+ });
153
+ server.listen(port, () => {
154
+ log(`Socket.IO server listening on port ${port}`);
155
+ });
156
+ return {
157
+ server,
158
+ io,
159
+ getRoom: () => room,
160
+ reloadEngine: () => {
161
+ (0, engine_loader_1.clearEngineCache)();
162
+ engine = (0, engine_loader_1.loadEngine)(projectDir);
163
+ log(`Engine reloaded`);
164
+ },
165
+ };
166
+ }
167
+ //# sourceMappingURL=socket-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"socket-server.js","sourceRoot":"","sources":["../../src/server/socket-server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ export interface GamePreviewOptions {
2
+ /** Absolute path to the game project directory */
3
+ projectDir: string;
4
+ /** Number of players to simulate */
5
+ playerCount: number;
6
+ /** Vite dev server port (default: 4100) */
7
+ port?: number;
8
+ /** Socket.IO server port (default: 4101) */
9
+ socketPort?: number;
10
+ /** Run browser in headless mode (default: true) */
11
+ headless?: boolean;
12
+ /** Browser type to use (default: 'chromium') */
13
+ browserType?: 'chromium' | 'firefox' | 'webkit';
14
+ }
15
+ export declare class GamePreview {
16
+ private options;
17
+ private serverHandle;
18
+ private browser;
19
+ private context;
20
+ private playerPages;
21
+ constructor(options: GamePreviewOptions);
22
+ /**
23
+ * Start the dev server and launch browser pages for each player.
24
+ * Each player automatically joins the game lobby.
25
+ */
26
+ start(): Promise<void>;
27
+ /**
28
+ * Get the Playwright Page object for a specific player by index.
29
+ * Player 0 is the host.
30
+ */
31
+ getPlayerPage(playerIndex: number): any;
32
+ /**
33
+ * Get all Playwright Page objects.
34
+ */
35
+ getPlayerPages(): any[];
36
+ /**
37
+ * Get the number of players.
38
+ */
39
+ get playerCount(): number;
40
+ /**
41
+ * Click "Ready" for all players.
42
+ */
43
+ readyAll(): Promise<void>;
44
+ /**
45
+ * Have the host start the game. Requires all players to be ready.
46
+ */
47
+ startGame(): Promise<void>;
48
+ /**
49
+ * Stop the browser and dev server, cleaning up all resources.
50
+ */
51
+ stop(): Promise<void>;
52
+ }
53
+ //# sourceMappingURL=game-preview.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"game-preview.d.ts","sourceRoot":"","sources":["../../src/testing/game-preview.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,kBAAkB;IACjC,kDAAkD;IAClD,UAAU,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,2CAA2C;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gDAAgD;IAChD,WAAW,CAAC,EAAE,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC;CACjD;AAID,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,YAAY,CAAgC;IACpD,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,WAAW,CAAyC;gBAEhD,OAAO,EAAE,kBAAkB;IAUvC;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAiD5B;;;OAGG;IACH,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,GAAG;IASvC;;OAEG;IACH,cAAc,IAAI,GAAG,EAAE;IAIvB;;OAEG;IACH,IAAI,WAAW,IAAI,MAAM,CAExB;IAED;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAS/B;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAYhC;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAe5B"}