miaoda-game-devkit 0.2.11 → 0.2.12

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.
@@ -2,11 +2,99 @@
2
2
  import { resolve as resolve4 } from "path";
3
3
  import { describe, expect, it } from "vitest";
4
4
 
5
+ // src/react/manual-game-clock.ts
6
+ var ManualGameClock = class {
7
+ time = 0;
8
+ nextId = 1;
9
+ frames = /* @__PURE__ */ new Map();
10
+ timers = /* @__PURE__ */ new Map();
11
+ now() {
12
+ return this.time;
13
+ }
14
+ requestFrame(callback) {
15
+ const id = this.nextId++;
16
+ this.frames.set(id, callback);
17
+ return id;
18
+ }
19
+ cancelFrame(id) {
20
+ this.frames.delete(id);
21
+ }
22
+ setTimeout(callback, delayMs) {
23
+ const id = this.nextId++;
24
+ this.timers.set(id, { callback, dueAt: this.time + delayMs });
25
+ return id;
26
+ }
27
+ clearTimeout(id) {
28
+ this.timers.delete(id);
29
+ }
30
+ advanceBy(deltaMs) {
31
+ if (!Number.isFinite(deltaMs) || deltaMs < 0) {
32
+ throw new RangeError("deltaMs must be a non-negative finite number");
33
+ }
34
+ this.time += deltaMs;
35
+ const dueTimers = [...this.timers.entries()].filter(([, timer]) => timer.dueAt <= this.time).sort((left, right) => left[1].dueAt - right[1].dueAt);
36
+ for (const [id, timer] of dueTimers) {
37
+ if (timer.dueAt <= this.time && this.timers.delete(id)) timer.callback();
38
+ }
39
+ }
40
+ stepFrame(deltaMs = 16) {
41
+ this.advanceBy(deltaMs);
42
+ const callbacks = [...this.frames.values()];
43
+ this.frames.clear();
44
+ for (const callback of callbacks) callback(this.time);
45
+ }
46
+ stepFrames(count, deltaMs = 16) {
47
+ if (!Number.isInteger(count) || count < 0) {
48
+ throw new RangeError("count must be a non-negative integer");
49
+ }
50
+ for (let index = 0; index < count; index += 1) this.stepFrame(deltaMs);
51
+ }
52
+ pendingFrameCount() {
53
+ return this.frames.size;
54
+ }
55
+ pendingTimerCount() {
56
+ return this.timers.size;
57
+ }
58
+ };
59
+
60
+ // src/react-vitest-config.ts
61
+ import { resolve } from "path";
62
+ import { defineConfig } from "vitest/config";
63
+ function defineReactGameVitestConfig(options) {
64
+ return defineConfig({
65
+ resolve: {
66
+ alias: { ...options.aliases, "@": resolve(options.projectRoot, "src") }
67
+ },
68
+ test: {
69
+ include: [
70
+ "src/**/*.{test,spec}.{ts,tsx}",
71
+ "tests/**/*.{test,spec}.{ts,tsx}"
72
+ ],
73
+ environment: "jsdom",
74
+ environmentOptions: {
75
+ jsdom: { url: "http://localhost/", pretendToBeVisual: true }
76
+ },
77
+ setupFiles: [
78
+ "miaoda-game-devkit/react/vitest-setup",
79
+ ...options.additionalSetupFiles ?? []
80
+ ],
81
+ reporters: ["minimal"],
82
+ restoreMocks: true,
83
+ clearMocks: true,
84
+ testTimeout: options.testTimeout,
85
+ hookTimeout: options.hookTimeout
86
+ }
87
+ });
88
+ }
89
+
5
90
  // src/vite.ts
6
91
  import { existsSync } from "fs";
7
92
  import { createRequire } from "module";
8
- import { dirname, join, normalize, resolve, sep } from "path";
93
+ import { dirname, join, normalize, resolve as resolve2, sep } from "path";
9
94
  var PHASER_MODULE_ID = "phaser";
95
+ var REXUI_OPTIMIZE_ENTRIES = [
96
+ "phaser4-rex-plugins/templates/ui/ui-plugin.js"
97
+ ];
10
98
  function isPromiseLike(value) {
11
99
  return typeof value === "object" && value !== null && "then" in value && typeof value.then === "function";
12
100
  }
@@ -27,14 +115,14 @@ function isInsideDirectory(filePath, directory) {
27
115
  return normalizedFile.startsWith(normalizedDirectory);
28
116
  }
29
117
  function phaserRexUIScenePlugin(projectRoot2) {
30
- let scenesRoot = projectRoot2 ? resolve(projectRoot2, "src/scenes") : void 0;
118
+ let scenesRoot = projectRoot2 ? resolve2(projectRoot2, "src/scenes") : void 0;
31
119
  let phaserFacade = projectRoot2 ? resolvePhaserFacade(projectRoot2) : void 0;
32
120
  return {
33
121
  name: "miaoda-phaser-rexui-scene",
34
122
  enforce: "pre",
35
123
  configResolved(config) {
36
124
  const resolvedProjectRoot = projectRoot2 ?? config.root;
37
- scenesRoot ??= resolve(resolvedProjectRoot, "src/scenes");
125
+ scenesRoot ??= resolve2(resolvedProjectRoot, "src/scenes");
38
126
  phaserFacade ??= resolvePhaserFacade(resolvedProjectRoot);
39
127
  },
40
128
  /** 查询参数属于构建工具元数据,去除后才能稳定判断真实源码位置。 */
@@ -48,8 +136,18 @@ function phaserRexUIScenePlugin(projectRoot2) {
48
136
  };
49
137
  }
50
138
  function withGameDefaults(config) {
139
+ const optimizeDeps = config.optimizeDeps ?? {};
51
140
  return {
52
141
  ...config,
142
+ optimizeDeps: {
143
+ ...optimizeDeps,
144
+ include: [
145
+ .../* @__PURE__ */ new Set([
146
+ ...optimizeDeps.include ?? [],
147
+ ...REXUI_OPTIMIZE_ENTRIES
148
+ ])
149
+ ]
150
+ },
53
151
  plugins: [
54
152
  phaserRexUIScenePlugin(),
55
153
  ...config.plugins ?? []
@@ -67,8 +165,8 @@ function defineGameViteConfig(config) {
67
165
  }
68
166
 
69
167
  // src/vitest-config.ts
70
- import { resolve as resolve2 } from "path";
71
- import { defineConfig } from "vitest/config";
168
+ import { resolve as resolve3 } from "path";
169
+ import { defineConfig as defineConfig2 } from "vitest/config";
72
170
 
73
171
  // src/gameplay-audit.ts
74
172
  import { readdirSync, readFileSync, statSync } from "fs";
@@ -682,12 +780,12 @@ function defineGameVitestConfig(options) {
682
780
  - ${auditIssues.join("\n- ")}`
683
781
  );
684
782
  }
685
- return defineConfig({
783
+ return defineConfig2({
686
784
  plugins: [phaserRexUIScenePlugin(options.projectRoot)],
687
785
  resolve: {
688
786
  alias: {
689
787
  ...options.aliases,
690
- "@": resolve2(options.projectRoot, "src")
788
+ "@": resolve3(options.projectRoot, "src")
691
789
  }
692
790
  },
693
791
  // devkit 作为 external ESM 加载时,应用测试也必须 externalize Phaser,
@@ -751,91 +849,6 @@ function defineGameVitestConfig(options) {
751
849
  });
752
850
  }
753
851
 
754
- // src/react-vitest-config.ts
755
- import { resolve as resolve3 } from "path";
756
- import { defineConfig as defineConfig2 } from "vitest/config";
757
- function defineReactGameVitestConfig(options) {
758
- return defineConfig2({
759
- resolve: {
760
- alias: { ...options.aliases, "@": resolve3(options.projectRoot, "src") }
761
- },
762
- test: {
763
- include: [
764
- "src/**/*.{test,spec}.{ts,tsx}",
765
- "tests/**/*.{test,spec}.{ts,tsx}"
766
- ],
767
- environment: "jsdom",
768
- environmentOptions: {
769
- jsdom: { url: "http://localhost/", pretendToBeVisual: true }
770
- },
771
- setupFiles: [
772
- "miaoda-game-devkit/react/vitest-setup",
773
- ...options.additionalSetupFiles ?? []
774
- ],
775
- reporters: ["minimal"],
776
- restoreMocks: true,
777
- clearMocks: true,
778
- testTimeout: options.testTimeout,
779
- hookTimeout: options.hookTimeout
780
- }
781
- });
782
- }
783
-
784
- // src/react/manual-game-clock.ts
785
- var ManualGameClock = class {
786
- time = 0;
787
- nextId = 1;
788
- frames = /* @__PURE__ */ new Map();
789
- timers = /* @__PURE__ */ new Map();
790
- now() {
791
- return this.time;
792
- }
793
- requestFrame(callback) {
794
- const id = this.nextId++;
795
- this.frames.set(id, callback);
796
- return id;
797
- }
798
- cancelFrame(id) {
799
- this.frames.delete(id);
800
- }
801
- setTimeout(callback, delayMs) {
802
- const id = this.nextId++;
803
- this.timers.set(id, { callback, dueAt: this.time + delayMs });
804
- return id;
805
- }
806
- clearTimeout(id) {
807
- this.timers.delete(id);
808
- }
809
- advanceBy(deltaMs) {
810
- if (!Number.isFinite(deltaMs) || deltaMs < 0) {
811
- throw new RangeError("deltaMs must be a non-negative finite number");
812
- }
813
- this.time += deltaMs;
814
- const dueTimers = [...this.timers.entries()].filter(([, timer]) => timer.dueAt <= this.time).sort((left, right) => left[1].dueAt - right[1].dueAt);
815
- for (const [id, timer] of dueTimers) {
816
- if (timer.dueAt <= this.time && this.timers.delete(id)) timer.callback();
817
- }
818
- }
819
- stepFrame(deltaMs = 16) {
820
- this.advanceBy(deltaMs);
821
- const callbacks = [...this.frames.values()];
822
- this.frames.clear();
823
- for (const callback of callbacks) callback(this.time);
824
- }
825
- stepFrames(count, deltaMs = 16) {
826
- if (!Number.isInteger(count) || count < 0) {
827
- throw new RangeError("count must be a non-negative integer");
828
- }
829
- for (let index = 0; index < count; index += 1) this.stepFrame(deltaMs);
830
- }
831
- pendingFrameCount() {
832
- return this.frames.size;
833
- }
834
- pendingTimerCount() {
835
- return this.timers.size;
836
- }
837
- };
838
-
839
852
  // src/lint/vitest-config.test.ts
840
853
  var projectRoot = resolve4(import.meta.dirname, "../..");
841
854
  var gameplayAudit = {
@@ -868,6 +881,21 @@ describe("defineGameVitestConfig", () => {
868
881
  name: "miaoda-phaser-rexui-scene"
869
882
  });
870
883
  });
884
+ it("defineGameViteConfig \u9884\u6784\u5EFA\u52A8\u6001 RexUI \u5165\u53E3\u5E76\u4FDD\u7559\u9879\u76EE\u914D\u7F6E", () => {
885
+ const config = defineGameViteConfig({
886
+ optimizeDeps: {
887
+ include: ["application-dependency"],
888
+ exclude: ["excluded-dependency"]
889
+ }
890
+ });
891
+ expect(config.optimizeDeps).toEqual({
892
+ include: [
893
+ "application-dependency",
894
+ "phaser4-rex-plugins/templates/ui/ui-plugin.js"
895
+ ],
896
+ exclude: ["excluded-dependency"]
897
+ });
898
+ });
871
899
  it("\u63D0\u4F9B Phaser \u8FD0\u884C\u65F6\u6D4B\u8BD5\u9700\u8981\u7684\u56FA\u5B9A\u57FA\u7EBF", () => {
872
900
  const config = defineGameVitestConfig({ projectRoot, gameplayAudit });
873
901
  expect(config.resolve?.alias).toMatchObject({
package/dist/vite.js CHANGED
@@ -28,6 +28,9 @@ var import_node_fs = require("fs");
28
28
  var import_node_module = require("module");
29
29
  var import_node_path = require("path");
30
30
  var PHASER_MODULE_ID = "phaser";
31
+ var REXUI_OPTIMIZE_ENTRIES = [
32
+ "phaser4-rex-plugins/templates/ui/ui-plugin.js"
33
+ ];
31
34
  function isPromiseLike(value) {
32
35
  return typeof value === "object" && value !== null && "then" in value && typeof value.then === "function";
33
36
  }
@@ -69,8 +72,18 @@ function phaserRexUIScenePlugin(projectRoot) {
69
72
  };
70
73
  }
71
74
  function withGameDefaults(config) {
75
+ const optimizeDeps = config.optimizeDeps ?? {};
72
76
  return {
73
77
  ...config,
78
+ optimizeDeps: {
79
+ ...optimizeDeps,
80
+ include: [
81
+ .../* @__PURE__ */ new Set([
82
+ ...optimizeDeps.include ?? [],
83
+ ...REXUI_OPTIMIZE_ENTRIES
84
+ ])
85
+ ]
86
+ },
74
87
  plugins: [
75
88
  phaserRexUIScenePlugin(),
76
89
  ...config.plugins ?? []
package/dist/vite.mjs CHANGED
@@ -3,6 +3,9 @@ import { existsSync } from "fs";
3
3
  import { createRequire } from "module";
4
4
  import { dirname, join, normalize, resolve, sep } from "path";
5
5
  var PHASER_MODULE_ID = "phaser";
6
+ var REXUI_OPTIMIZE_ENTRIES = [
7
+ "phaser4-rex-plugins/templates/ui/ui-plugin.js"
8
+ ];
6
9
  function isPromiseLike(value) {
7
10
  return typeof value === "object" && value !== null && "then" in value && typeof value.then === "function";
8
11
  }
@@ -44,8 +47,18 @@ function phaserRexUIScenePlugin(projectRoot) {
44
47
  };
45
48
  }
46
49
  function withGameDefaults(config) {
50
+ const optimizeDeps = config.optimizeDeps ?? {};
47
51
  return {
48
52
  ...config,
53
+ optimizeDeps: {
54
+ ...optimizeDeps,
55
+ include: [
56
+ .../* @__PURE__ */ new Set([
57
+ ...optimizeDeps.include ?? [],
58
+ ...REXUI_OPTIMIZE_ENTRIES
59
+ ])
60
+ ]
61
+ },
49
62
  plugins: [
50
63
  phaserRexUIScenePlugin(),
51
64
  ...config.plugins ?? []
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "miaoda-game-devkit",
3
- "version": "0.2.11",
3
+ "version": "0.2.12",
4
4
  "description": "Shared lint and deterministic Phaser HEADLESS testing tools for Miaoda games",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.js",