@rpgjs/vite 5.0.0-alpha.9 → 5.0.0-beta.10

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 (46) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/LICENSE +19 -0
  3. package/dist/compatibility-v4/flag-transform.d.ts +6 -0
  4. package/dist/compatibility-v4/index.d.ts +22 -0
  5. package/dist/compatibility-v4/load-config-file.d.ts +2 -0
  6. package/dist/compatibility-v4/require-transform.d.ts +2 -0
  7. package/dist/compatibility-v4/utils.d.ts +55 -0
  8. package/dist/index.d.ts +1 -0
  9. package/dist/index.js +10232 -7505
  10. package/dist/index.js.map +1 -1
  11. package/dist/mmorpg-build-plugin.d.ts +8 -0
  12. package/dist/rpgjs-plugin.d.ts +9 -3
  13. package/dist/server-plugin.d.ts +2 -149
  14. package/package.json +22 -13
  15. package/src/compatibility-v4/flag-transform.ts +61 -0
  16. package/src/compatibility-v4/index.ts +713 -0
  17. package/src/compatibility-v4/load-config-file.ts +38 -0
  18. package/src/compatibility-v4/require-transform.ts +67 -0
  19. package/src/compatibility-v4/utils.ts +170 -0
  20. package/src/index.ts +2 -1
  21. package/src/mmorpg-build-plugin.ts +123 -0
  22. package/src/module-config.ts +13 -0
  23. package/src/rpgjs-plugin.ts +36 -4
  24. package/src/server-plugin.ts +15 -436
  25. package/tests/compatibility-v4.spec.ts +105 -0
  26. package/tests/fixtures/v4-game/rpg.toml +11 -0
  27. package/tests/fixtures/v4-game/src/modules/main/characters/assets/hero.svg +2 -0
  28. package/tests/fixtures/v4-game/src/modules/main/characters/hero.ts +2 -0
  29. package/tests/fixtures/v4-game/src/modules/main/client.ts +4 -0
  30. package/tests/fixtures/v4-game/src/modules/main/database/potion.ts +6 -0
  31. package/tests/fixtures/v4-game/src/modules/main/events/npc.ts +4 -0
  32. package/tests/fixtures/v4-game/src/modules/main/gui/menu.vue +2 -0
  33. package/tests/fixtures/v4-game/src/modules/main/maps/map.tmx +2 -0
  34. package/tests/fixtures/v4-game/src/modules/main/maps/map.ts +7 -0
  35. package/tests/fixtures/v4-game/src/modules/main/player.ts +4 -0
  36. package/tests/fixtures/v4-game/src/modules/main/scene-map.ts +4 -0
  37. package/tests/fixtures/v4-game/src/modules/main/server.ts +4 -0
  38. package/tests/fixtures/v4-game/src/modules/main/sounds/theme.ogg +2 -0
  39. package/tests/fixtures/v4-game/src/modules/main/sounds/theme.ts +5 -0
  40. package/tests/fixtures/v4-game/src/modules/main/sprite.ts +4 -0
  41. package/tests/fixtures/v4-game/src/modules/main/worlds/maps/world-map.tmx +6 -0
  42. package/tests/fixtures/v4-game/src/modules/main/worlds/world.world +13 -0
  43. package/tests/latency-simulation.spec.ts +209 -0
  44. package/tests/remove-imports-plugin.spec.ts +56 -0
  45. package/tsconfig.json +2 -2
  46. package/vite.config.ts +7 -1
@@ -0,0 +1,4 @@
1
+ export default {
2
+ onInit() {}
3
+ }
4
+
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <map version="1.9" tiledversion="1.9.2" orientation="orthogonal" renderorder="right-down" width="1" height="1" tilewidth="32" tileheight="32" infinite="0" nextlayerid="2" nextobjectid="1">
3
+ <layer id="1" name="Ground" width="1" height="1">
4
+ <data encoding="csv">0</data>
5
+ </layer>
6
+ </map>
@@ -0,0 +1,13 @@
1
+ {
2
+ "maps": [
3
+ {
4
+ "fileName": "maps/world-map.tmx",
5
+ "height": 640,
6
+ "width": 800,
7
+ "x": 64,
8
+ "y": -160
9
+ }
10
+ ],
11
+ "onlyShowAdjacentMaps": false,
12
+ "type": "world"
13
+ }
@@ -0,0 +1,209 @@
1
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
+
3
+ // Mock the PartyConnection class for testing
4
+ class MockPartyConnection {
5
+ public static latencyEnabled: boolean = false;
6
+ public static latencyMinMs: number = 50;
7
+ public static latencyMaxMs: number = 200;
8
+ public static latencyFilter: string = '';
9
+
10
+ public id: string;
11
+ private ws: any;
12
+
13
+ constructor(ws: any, id?: string) {
14
+ this.ws = ws;
15
+ this.id = id || 'test-connection';
16
+ }
17
+
18
+ async send(data: any): Promise<void> {
19
+ if (this.ws.readyState === 1) {
20
+ const message = typeof data === "string" ? data : JSON.stringify(data);
21
+
22
+ // Check if latency simulation is enabled
23
+ if (MockPartyConnection.latencyEnabled && MockPartyConnection.latencyMaxMs > 0) {
24
+ // Apply filter if specified
25
+ if (MockPartyConnection.latencyFilter && !message.includes(MockPartyConnection.latencyFilter)) {
26
+ this.ws.send(message);
27
+ return;
28
+ }
29
+
30
+ // Calculate random latency between min and max
31
+ const latencyMs = Math.random() * (MockPartyConnection.latencyMaxMs - MockPartyConnection.latencyMinMs) + MockPartyConnection.latencyMinMs;
32
+
33
+ // Delay the message
34
+ await new Promise(resolve => setTimeout(resolve, latencyMs));
35
+ }
36
+
37
+ this.ws.send(message);
38
+ }
39
+ }
40
+
41
+ static configureLatency(enabled: boolean, minMs: number, maxMs: number, filter?: string): void {
42
+ MockPartyConnection.latencyEnabled = enabled;
43
+ MockPartyConnection.latencyMinMs = Math.max(0, minMs);
44
+ MockPartyConnection.latencyMaxMs = Math.max(MockPartyConnection.latencyMinMs, maxMs);
45
+ MockPartyConnection.latencyFilter = filter || '';
46
+ }
47
+
48
+ static getLatencyStatus(): { enabled: boolean; minMs: number; maxMs: number; filter: string } {
49
+ return {
50
+ enabled: MockPartyConnection.latencyEnabled,
51
+ minMs: MockPartyConnection.latencyMinMs,
52
+ maxMs: MockPartyConnection.latencyMaxMs,
53
+ filter: MockPartyConnection.latencyFilter
54
+ };
55
+ }
56
+ }
57
+
58
+ describe('Latency Simulation', () => {
59
+ let mockWs: any;
60
+
61
+ beforeEach(() => {
62
+ // Reset latency settings before each test
63
+ MockPartyConnection.configureLatency(false, 0, 0);
64
+
65
+ // Create mock WebSocket
66
+ mockWs = {
67
+ readyState: 1, // WebSocket.OPEN
68
+ send: vi.fn(),
69
+ close: vi.fn()
70
+ };
71
+ });
72
+
73
+ afterEach(() => {
74
+ vi.clearAllMocks();
75
+ });
76
+
77
+ describe('Configuration', () => {
78
+ it('should configure latency settings correctly', () => {
79
+ MockPartyConnection.configureLatency(true, 100, 300, 'sync');
80
+
81
+ const status = MockPartyConnection.getLatencyStatus();
82
+ expect(status.enabled).toBe(true);
83
+ expect(status.minMs).toBe(100);
84
+ expect(status.maxMs).toBe(300);
85
+ expect(status.filter).toBe('sync');
86
+ });
87
+
88
+ it('should clamp minMs to 0', () => {
89
+ MockPartyConnection.configureLatency(true, -50, 200);
90
+
91
+ const status = MockPartyConnection.getLatencyStatus();
92
+ expect(status.minMs).toBe(0);
93
+ });
94
+
95
+ it('should ensure maxMs is at least minMs', () => {
96
+ MockPartyConnection.configureLatency(true, 200, 100);
97
+
98
+ const status = MockPartyConnection.getLatencyStatus();
99
+ expect(status.maxMs).toBe(200); // Should be set to minMs value
100
+ });
101
+
102
+ it('should disable latency when enabled is false', () => {
103
+ MockPartyConnection.configureLatency(false, 100, 300);
104
+
105
+ const status = MockPartyConnection.getLatencyStatus();
106
+ expect(status.enabled).toBe(false);
107
+ });
108
+ });
109
+
110
+ describe('Message Sending', () => {
111
+ it('should send message immediately when latency is disabled', async () => {
112
+ const connection = new MockPartyConnection(mockWs);
113
+ const startTime = Date.now();
114
+
115
+ await connection.send('test message');
116
+
117
+ const endTime = Date.now();
118
+ expect(mockWs.send).toHaveBeenCalledWith('test message');
119
+ expect(endTime - startTime).toBeLessThan(10); // Should be almost immediate
120
+ });
121
+
122
+ it('should delay message when latency is enabled', async () => {
123
+ MockPartyConnection.configureLatency(true, 50, 100);
124
+ const connection = new MockPartyConnection(mockWs);
125
+ const startTime = Date.now();
126
+
127
+ await connection.send('test message');
128
+
129
+ const endTime = Date.now();
130
+ expect(mockWs.send).toHaveBeenCalledWith('test message');
131
+ expect(endTime - startTime).toBeGreaterThanOrEqual(50);
132
+ expect(endTime - startTime).toBeLessThanOrEqual(150); // Allow some buffer
133
+ });
134
+
135
+ it('should apply filter correctly', async () => {
136
+ MockPartyConnection.configureLatency(true, 50, 100, 'sync');
137
+ const connection = new MockPartyConnection(mockWs);
138
+
139
+ // Message with filter should be delayed
140
+ const startTime1 = Date.now();
141
+ await connection.send('sync message');
142
+ const endTime1 = Date.now();
143
+ expect(endTime1 - startTime1).toBeGreaterThanOrEqual(50);
144
+
145
+ // Message without filter should be sent immediately
146
+ const startTime2 = Date.now();
147
+ await connection.send('normal message');
148
+ const endTime2 = Date.now();
149
+ expect(endTime2 - startTime2).toBeLessThan(10);
150
+ });
151
+
152
+ it('should not send when WebSocket is not open', async () => {
153
+ mockWs.readyState = 3; // WebSocket.CLOSED
154
+ const connection = new MockPartyConnection(mockWs);
155
+
156
+ await connection.send('test message');
157
+
158
+ expect(mockWs.send).not.toHaveBeenCalled();
159
+ });
160
+
161
+ it('should handle JSON data correctly', async () => {
162
+ const connection = new MockPartyConnection(mockWs);
163
+ const testData = { type: 'test', value: 123 };
164
+
165
+ await connection.send(testData);
166
+
167
+ expect(mockWs.send).toHaveBeenCalledWith(JSON.stringify(testData));
168
+ });
169
+ });
170
+
171
+ describe('Edge Cases', () => {
172
+ it('should handle zero latency range', async () => {
173
+ MockPartyConnection.configureLatency(true, 0, 0);
174
+ const connection = new MockPartyConnection(mockWs);
175
+ const startTime = Date.now();
176
+
177
+ await connection.send('test message');
178
+
179
+ const endTime = Date.now();
180
+ expect(mockWs.send).toHaveBeenCalledWith('test message');
181
+ expect(endTime - startTime).toBeLessThan(10); // Should be immediate
182
+ });
183
+
184
+ it('should handle very high latency', async () => {
185
+ MockPartyConnection.configureLatency(true, 1000, 2000);
186
+ const connection = new MockPartyConnection(mockWs);
187
+ const startTime = Date.now();
188
+
189
+ await connection.send('test message');
190
+
191
+ const endTime = Date.now();
192
+ expect(mockWs.send).toHaveBeenCalledWith('test message');
193
+ expect(endTime - startTime).toBeGreaterThanOrEqual(1000);
194
+ expect(endTime - startTime).toBeLessThanOrEqual(2100); // Allow buffer
195
+ });
196
+
197
+ it('should handle empty filter string', async () => {
198
+ MockPartyConnection.configureLatency(true, 50, 100, '');
199
+ const connection = new MockPartyConnection(mockWs);
200
+ const startTime = Date.now();
201
+
202
+ await connection.send('test message');
203
+
204
+ const endTime = Date.now();
205
+ expect(mockWs.send).toHaveBeenCalledWith('test message');
206
+ expect(endTime - startTime).toBeGreaterThanOrEqual(50); // Should still be delayed
207
+ });
208
+ });
209
+ });
@@ -0,0 +1,56 @@
1
+ import { afterEach, describe, expect, test, vi } from "vitest";
2
+ import { removeImportsPlugin } from "../src/remove-imports-plugin";
3
+
4
+ const transform = async (code: string, id = "/tmp/source.ts") => {
5
+ const plugin = removeImportsPlugin({
6
+ patterns: ["vue", /^@server\//],
7
+ });
8
+ return plugin.transform?.call({} as any, code, id) as any;
9
+ };
10
+
11
+ describe("removeImportsPlugin", () => {
12
+ afterEach(() => {
13
+ vi.restoreAllMocks();
14
+ });
15
+
16
+ test("replaces default, named and namespace imports with null declarations", async () => {
17
+ const result = await transform(`
18
+ import Vue, { ref as vueRef, computed } from "vue";
19
+ import * as serverApi from "@server/api";
20
+ import { keep } from "client";
21
+
22
+ export const state = [Vue, vueRef, computed, serverApi, keep];
23
+ `);
24
+
25
+ expect(result.code).toContain("const Vue = null;");
26
+ expect(result.code).toContain("const vueRef = null;");
27
+ expect(result.code).toContain("const computed = null;");
28
+ expect(result.code).toContain("const serverApi = null;");
29
+ expect(result.code).toContain('import { keep } from "client";');
30
+ expect(result.map).toBeDefined();
31
+ });
32
+
33
+ test("replaces side-effect imports with a stable comment", async () => {
34
+ const result = await transform(`
35
+ import "vue";
36
+ export const ready = true;
37
+ `);
38
+
39
+ expect(result.code).toContain("// removed import: vue");
40
+ expect(result.code).toContain("export const ready = true;");
41
+ });
42
+
43
+ test("ignores unmatched files and parse failures", async () => {
44
+ expect(await transform('import "vue";', "/tmp/style.css")).toBeNull();
45
+ expect(await transform('import { broken from "vue";')).toBeNull();
46
+ });
47
+
48
+ test("warns once when parsing fails", async () => {
49
+ const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
50
+
51
+ await transform('import { broken from "vue";');
52
+
53
+ expect(warn).toHaveBeenCalledOnce();
54
+ expect(String(warn.mock.calls[0][0])).toContain("Failed to parse");
55
+ });
56
+ });
package/tsconfig.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "compilerOptions": {
3
3
  "target": "ES2020",
4
4
  "module": "ESNext",
5
- "moduleResolution": "node",
5
+ "moduleResolution": "bundler",
6
6
  "declaration": true,
7
7
  "outDir": "dist",
8
8
  "rootDir": "src",
@@ -14,4 +14,4 @@
14
14
  },
15
15
  "include": ["src/**/*"],
16
16
  "exclude": ["node_modules", "dist"]
17
- }
17
+ }
package/vite.config.ts CHANGED
@@ -36,9 +36,15 @@ export default defineConfig({
36
36
  'vite',
37
37
  'vite-plugin-dts',
38
38
  '@canvasengine/compiler',
39
+ '@iarna/toml',
40
+ 'image-size',
41
+ '@babel/parser',
42
+ '@babel/traverse',
43
+ '@babel/generator',
44
+ '@babel/types',
39
45
  'chokidar',
40
46
  'ws'
41
47
  ]
42
48
  }
43
49
  },
44
- })
50
+ })