@energy8platform/platform-core 0.16.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 (57) hide show
  1. package/README.md +482 -0
  2. package/bin/simulate.ts +139 -0
  3. package/dist/dev-bridge.cjs.js +237 -0
  4. package/dist/dev-bridge.cjs.js.map +1 -0
  5. package/dist/dev-bridge.d.ts +141 -0
  6. package/dist/dev-bridge.esm.js +235 -0
  7. package/dist/dev-bridge.esm.js.map +1 -0
  8. package/dist/index.cjs.js +569 -0
  9. package/dist/index.cjs.js.map +1 -0
  10. package/dist/index.d.ts +439 -0
  11. package/dist/index.esm.js +560 -0
  12. package/dist/index.esm.js.map +1 -0
  13. package/dist/loading.cjs.js +190 -0
  14. package/dist/loading.cjs.js.map +1 -0
  15. package/dist/loading.d.ts +86 -0
  16. package/dist/loading.esm.js +185 -0
  17. package/dist/loading.esm.js.map +1 -0
  18. package/dist/lua.cjs.js +1129 -0
  19. package/dist/lua.cjs.js.map +1 -0
  20. package/dist/lua.d.ts +319 -0
  21. package/dist/lua.esm.js +1119 -0
  22. package/dist/lua.esm.js.map +1 -0
  23. package/dist/simulation.cjs.js +374 -0
  24. package/dist/simulation.cjs.js.map +1 -0
  25. package/dist/simulation.d.ts +190 -0
  26. package/dist/simulation.esm.js +368 -0
  27. package/dist/simulation.esm.js.map +1 -0
  28. package/dist/vite.cjs.js +179 -0
  29. package/dist/vite.cjs.js.map +1 -0
  30. package/dist/vite.d.ts +13 -0
  31. package/dist/vite.esm.js +176 -0
  32. package/dist/vite.esm.js.map +1 -0
  33. package/package.json +100 -0
  34. package/scripts/install-simulate.mjs +101 -0
  35. package/src/EventEmitter.ts +55 -0
  36. package/src/PlatformSession.ts +156 -0
  37. package/src/dev-bridge/DevBridge.ts +305 -0
  38. package/src/dev-bridge/index.ts +2 -0
  39. package/src/index.ts +98 -0
  40. package/src/loading/CSSPreloader.ts +129 -0
  41. package/src/loading/index.ts +3 -0
  42. package/src/loading/logo.ts +95 -0
  43. package/src/lua/ActionRouter.ts +132 -0
  44. package/src/lua/LuaEngine.ts +412 -0
  45. package/src/lua/LuaEngineAPI.ts +314 -0
  46. package/src/lua/PersistentState.ts +80 -0
  47. package/src/lua/SessionManager.ts +227 -0
  48. package/src/lua/SimulationRunner.ts +192 -0
  49. package/src/lua/fengari.d.ts +10 -0
  50. package/src/lua/index.ts +28 -0
  51. package/src/lua/types.ts +149 -0
  52. package/src/simulation/NativeSimulationRunner.ts +367 -0
  53. package/src/simulation/ParallelSimulationRunner.ts +156 -0
  54. package/src/simulation/SimulationWorker.ts +44 -0
  55. package/src/simulation/index.ts +21 -0
  56. package/src/types.ts +85 -0
  57. package/src/vite/index.ts +196 -0
@@ -0,0 +1,196 @@
1
+ import type { Plugin } from 'vite';
2
+
3
+ // ─── DevBridge Plugin ────────────────────────────────────
4
+
5
+ /**
6
+ * Vite plugin that auto-injects the DevBridge mock-host bootstrapper
7
+ * into the HTML during development, so the game can communicate with
8
+ * a mock casino host without manual setup.
9
+ *
10
+ * Pair with `luaPlugin` to also enable `.lua` raw imports and serve a
11
+ * Lua execution endpoint at POST /__lua-play.
12
+ */
13
+ const VIRTUAL_ID = '/@dev-bridge-entry.js';
14
+
15
+ export function devBridgePlugin(configPath: string): Plugin {
16
+ let entrySrc = '';
17
+ let viteRoot = '';
18
+ let resolvedConfigPath = configPath;
19
+
20
+ return {
21
+ name: 'platform-core:dev-bridge',
22
+ apply: 'serve', // dev only
23
+ enforce: 'pre',
24
+
25
+ configResolved(config) {
26
+ viteRoot = config.root;
27
+ // Resolve relative config path against Vite root so the virtual
28
+ // module can import it with an absolute path.
29
+ if (configPath.startsWith('.')) {
30
+ resolvedConfigPath = config.root + '/' + configPath.replace(/^\.\//, '');
31
+ }
32
+ },
33
+
34
+ resolveId(id) {
35
+ if (id === VIRTUAL_ID) return id;
36
+ },
37
+
38
+ load(id) {
39
+ if (id === VIRTUAL_ID) {
40
+ // This goes through Vite's pipeline so bare imports are resolved
41
+ return `
42
+ import { DevBridge } from '@energy8platform/platform-core/dev-bridge';
43
+
44
+ try {
45
+ const mod = await import('${resolvedConfigPath}');
46
+ const config = mod.default ?? mod.config ?? mod;
47
+ new DevBridge(config).start();
48
+ } catch (e) {
49
+ console.warn('[DevBridge] Failed to load config:', e);
50
+ }
51
+
52
+ await import('${entrySrc}');
53
+ `;
54
+ }
55
+ },
56
+
57
+ transformIndexHtml(html) {
58
+ // Find the app's entry module script (skip Vite internal /@... scripts)
59
+ const scriptRegex = /<script\s+type="module"\s+src="((?!\/@)[^"]+)"\s*>\s*<\/script>/;
60
+ const match = html.match(scriptRegex);
61
+
62
+ if (!match) {
63
+ console.warn('[DevBridge] Could not find entry module script in index.html');
64
+ return html;
65
+ }
66
+
67
+ entrySrc = match[1];
68
+ if (entrySrc.startsWith('.')) {
69
+ entrySrc = viteRoot + '/' + entrySrc.replace(/^\.\//, '');
70
+ } else if (entrySrc.startsWith('/')) {
71
+ entrySrc = viteRoot + entrySrc;
72
+ }
73
+ return html.replace(match[0], `<script type="module" src="${VIRTUAL_ID}"></script>`);
74
+ },
75
+ };
76
+ }
77
+
78
+ // ─── Lua Plugin ─────────────────────────────────────────
79
+
80
+ /**
81
+ * Vite plugin that:
82
+ * 1. Enables importing `.lua` files as raw strings with HMR
83
+ * 2. Runs a LuaEngine on the Vite dev server (Node.js) via POST /__lua-play
84
+ *
85
+ * fengari runs server-side only — no browser shims needed.
86
+ */
87
+ export function luaPlugin(configPath: string): Plugin {
88
+ let luaEngine: any = null;
89
+ let viteServer: any = null;
90
+
91
+ async function initEngine() {
92
+ if (!viteServer) return;
93
+
94
+ try {
95
+ // Invalidate cached modules so HMR picks up changes
96
+ const root = viteServer.config.root;
97
+ const fullConfigPath = configPath.startsWith('.')
98
+ ? root + '/' + configPath.replace(/^\.\//, '')
99
+ : configPath;
100
+
101
+ // Invalidate the config module and its dependencies
102
+ const configMod = viteServer.moduleGraph.getModuleById(fullConfigPath);
103
+ if (configMod) viteServer.moduleGraph.invalidateModule(configMod);
104
+
105
+ // ssrLoadModule handles TS transpilation and resolves all imports
106
+ const mod = await viteServer.ssrLoadModule(fullConfigPath);
107
+ const config = mod.default ?? mod.config ?? mod;
108
+
109
+ if (!config.luaScript || !config.gameDefinition) {
110
+ console.log('[LuaPlugin] No luaScript/gameDefinition in config — Lua server disabled');
111
+ luaEngine = null;
112
+ return;
113
+ }
114
+
115
+ // Load LuaEngine via SSR (fengari runs natively in Node.js)
116
+ const luaMod = await viteServer.ssrLoadModule('@energy8platform/platform-core/lua');
117
+ const { LuaEngine } = luaMod;
118
+
119
+ if (luaEngine) luaEngine.destroy();
120
+ luaEngine = new LuaEngine({
121
+ script: config.luaScript,
122
+ gameDefinition: config.gameDefinition,
123
+ seed: config.luaSeed,
124
+ });
125
+ console.log('[LuaPlugin] LuaEngine initialized (server-side)');
126
+ } catch (e: any) {
127
+ console.warn('[LuaPlugin] Failed to initialize LuaEngine:', e.message);
128
+ luaEngine = null;
129
+ }
130
+ }
131
+
132
+ return {
133
+ name: 'platform-core:lua',
134
+ apply: 'serve',
135
+
136
+ async configureServer(server) {
137
+ viteServer = server;
138
+ await initEngine();
139
+
140
+ // POST /__lua-play — execute Lua on the server
141
+ server.middlewares.use('/__lua-play', (req: any, res: any) => {
142
+ if (req.method !== 'POST') {
143
+ res.statusCode = 405;
144
+ res.end('Method Not Allowed');
145
+ return;
146
+ }
147
+
148
+ let body = '';
149
+ req.on('data', (chunk: string) => { body += chunk; });
150
+ req.on('end', () => {
151
+ try {
152
+ if (!luaEngine) {
153
+ res.statusCode = 503;
154
+ res.setHeader('Content-Type', 'application/json');
155
+ res.end(JSON.stringify({ error: 'LuaEngine not initialized' }));
156
+ return;
157
+ }
158
+
159
+ const params = JSON.parse(body);
160
+ const result = luaEngine.execute(params);
161
+
162
+ res.statusCode = 200;
163
+ res.setHeader('Content-Type', 'application/json');
164
+ res.end(JSON.stringify(result));
165
+ } catch (e: any) {
166
+ res.statusCode = 500;
167
+ res.setHeader('Content-Type', 'application/json');
168
+ res.end(JSON.stringify({ error: e.message }));
169
+ }
170
+ });
171
+ });
172
+ },
173
+
174
+ transform(code: string, id: string) {
175
+ if (id.endsWith('.lua')) {
176
+ return {
177
+ code: `export default ${JSON.stringify(code)};`,
178
+ map: null,
179
+ };
180
+ }
181
+ },
182
+
183
+ async handleHotUpdate({ file, server }: { file: string; server: any }) {
184
+ if (file.endsWith('.lua') || file.includes('dev.config')) {
185
+ console.log('[LuaPlugin] Reloading LuaEngine...');
186
+
187
+ // Invalidate all SSR modules so ssrLoadModule picks up fresh code
188
+ server.moduleGraph.invalidateAll();
189
+
190
+ await initEngine();
191
+ server.ws.send({ type: 'full-reload' });
192
+ return [];
193
+ }
194
+ },
195
+ };
196
+ }