miaoda-game-devkit 0.2.12 → 0.2.13
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.
- package/README.md +18 -8
- package/bin/miaoda-phaser-game-lint.js +3 -0
- package/bin/miaoda-react-game-lint.js +3 -0
- package/dist/cli/phaser-lint.js +163 -0
- package/dist/cli/react-lint.js +163 -0
- package/dist/lint/setup.mjs +23 -41
- package/dist/react/vitest-config.js +34 -1
- package/dist/react/vitest-config.mjs +35 -2
- package/dist/react/vitest-setup.js +72 -1
- package/dist/react/vitest-setup.mjs +72 -1
- package/dist/vitest-config.js +16 -1
- package/dist/vitest-config.mjs +16 -1
- package/package.json +7 -4
- package/bin/miaoda-game-lint.js +0 -3
- package/dist/cli/lint.js +0 -127
- package/dist/lint/contracts.config.mjs +0 -38
- package/dist/lint/game-telemetry.contract.mjs +0 -1402
- package/dist/lint/gameplay-audit.contract.mjs +0 -909
- package/dist/lint/gameplay-contract.contract.mjs +0 -1408
- package/dist/lint/phaser-headless.contract.mjs +0 -1856
- package/dist/lint/phaser-text-assertions.contract.mjs +0 -32
- package/dist/lint/resource-import-plugin.contract.mjs +0 -97
- package/dist/lint/vitest-config.contract.mjs +0 -1028
|
@@ -4,6 +4,73 @@
|
|
|
4
4
|
var import_vitest = require("@testing-library/jest-dom/vitest");
|
|
5
5
|
var import_react = require("@testing-library/react");
|
|
6
6
|
var import_vitest2 = require("vitest");
|
|
7
|
+
|
|
8
|
+
// src/testing/jsdom-canvas.ts
|
|
9
|
+
var contexts = /* @__PURE__ */ new WeakMap();
|
|
10
|
+
function createCanvasContext(canvas) {
|
|
11
|
+
const imageData = (width = 1, height = 1) => ({
|
|
12
|
+
data: new Uint8ClampedArray(width * height * 4),
|
|
13
|
+
width,
|
|
14
|
+
height,
|
|
15
|
+
colorSpace: "srgb"
|
|
16
|
+
});
|
|
17
|
+
const state = {
|
|
18
|
+
canvas,
|
|
19
|
+
font: "16px sans-serif"
|
|
20
|
+
};
|
|
21
|
+
const context = new Proxy(state, {
|
|
22
|
+
get(target, property) {
|
|
23
|
+
if (property in target) return target[property];
|
|
24
|
+
if (property === "createImageData" || property === "getImageData") {
|
|
25
|
+
return (...args) => imageData(args.at(-2), args.at(-1));
|
|
26
|
+
}
|
|
27
|
+
if (property === "measureText") {
|
|
28
|
+
return (value) => {
|
|
29
|
+
const font = String(target.font ?? "16px sans-serif");
|
|
30
|
+
const size = Number.parseFloat(font.match(/([\d.]+)px/)?.[1] ?? "16");
|
|
31
|
+
const width = [...String(value)].reduce((total, character) => {
|
|
32
|
+
if (/\s/.test(character)) return total + size * 0.33;
|
|
33
|
+
if (/[^\u0000-\u00ff]/.test(character)) return total + size;
|
|
34
|
+
if (/[MW@#%&]/.test(character)) return total + size * 0.9;
|
|
35
|
+
if (/[ilI1.,'`]/.test(character)) return total + size * 0.32;
|
|
36
|
+
if (/[A-Z0-9]/.test(character)) return total + size * 0.64;
|
|
37
|
+
return total + size * 0.56;
|
|
38
|
+
}, 0);
|
|
39
|
+
return {
|
|
40
|
+
width,
|
|
41
|
+
actualBoundingBoxAscent: size * 0.8,
|
|
42
|
+
actualBoundingBoxDescent: size * 0.2
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
if (property === "createLinearGradient" || property === "createRadialGradient") {
|
|
47
|
+
return () => ({ addColorStop() {
|
|
48
|
+
} });
|
|
49
|
+
}
|
|
50
|
+
return () => void 0;
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
return context;
|
|
54
|
+
}
|
|
55
|
+
function installJSDOMCanvasContext() {
|
|
56
|
+
HTMLCanvasElement.prototype.getContext = function getContext(contextId) {
|
|
57
|
+
if (contextId !== "2d") return null;
|
|
58
|
+
const existing = contexts.get(this);
|
|
59
|
+
if (existing) return existing;
|
|
60
|
+
const context = createCanvasContext(this);
|
|
61
|
+
contexts.set(this, context);
|
|
62
|
+
return context;
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// src/testing/jsdom-storage.ts
|
|
67
|
+
function clearJSDOMStorage() {
|
|
68
|
+
window.localStorage.clear();
|
|
69
|
+
window.sessionStorage.clear();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// src/react-vitest-setup.ts
|
|
73
|
+
installJSDOMCanvasContext();
|
|
7
74
|
var failures = [];
|
|
8
75
|
var consoleError;
|
|
9
76
|
var onError = (event) => failures.push(event.error ?? event.message);
|
|
@@ -22,6 +89,7 @@ var onRejection = (event) => failures.push(event.reason);
|
|
|
22
89
|
} catch (error) {
|
|
23
90
|
failures.push(error);
|
|
24
91
|
} finally {
|
|
92
|
+
clearJSDOMStorage();
|
|
25
93
|
window.removeEventListener("error", onError);
|
|
26
94
|
window.removeEventListener("unhandledrejection", onRejection);
|
|
27
95
|
consoleError?.mockRestore();
|
|
@@ -30,6 +98,9 @@ var onRejection = (event) => failures.push(event.reason);
|
|
|
30
98
|
if (failures.length > 0) {
|
|
31
99
|
const captured = failures;
|
|
32
100
|
failures = [];
|
|
33
|
-
throw new AggregateError(
|
|
101
|
+
throw new AggregateError(
|
|
102
|
+
captured,
|
|
103
|
+
"Unexpected React/JSDOM runtime failures"
|
|
104
|
+
);
|
|
34
105
|
}
|
|
35
106
|
});
|
|
@@ -2,6 +2,73 @@
|
|
|
2
2
|
import "@testing-library/jest-dom/vitest";
|
|
3
3
|
import { cleanup } from "@testing-library/react";
|
|
4
4
|
import { afterEach, beforeEach, vi } from "vitest";
|
|
5
|
+
|
|
6
|
+
// src/testing/jsdom-canvas.ts
|
|
7
|
+
var contexts = /* @__PURE__ */ new WeakMap();
|
|
8
|
+
function createCanvasContext(canvas) {
|
|
9
|
+
const imageData = (width = 1, height = 1) => ({
|
|
10
|
+
data: new Uint8ClampedArray(width * height * 4),
|
|
11
|
+
width,
|
|
12
|
+
height,
|
|
13
|
+
colorSpace: "srgb"
|
|
14
|
+
});
|
|
15
|
+
const state = {
|
|
16
|
+
canvas,
|
|
17
|
+
font: "16px sans-serif"
|
|
18
|
+
};
|
|
19
|
+
const context = new Proxy(state, {
|
|
20
|
+
get(target, property) {
|
|
21
|
+
if (property in target) return target[property];
|
|
22
|
+
if (property === "createImageData" || property === "getImageData") {
|
|
23
|
+
return (...args) => imageData(args.at(-2), args.at(-1));
|
|
24
|
+
}
|
|
25
|
+
if (property === "measureText") {
|
|
26
|
+
return (value) => {
|
|
27
|
+
const font = String(target.font ?? "16px sans-serif");
|
|
28
|
+
const size = Number.parseFloat(font.match(/([\d.]+)px/)?.[1] ?? "16");
|
|
29
|
+
const width = [...String(value)].reduce((total, character) => {
|
|
30
|
+
if (/\s/.test(character)) return total + size * 0.33;
|
|
31
|
+
if (/[^\u0000-\u00ff]/.test(character)) return total + size;
|
|
32
|
+
if (/[MW@#%&]/.test(character)) return total + size * 0.9;
|
|
33
|
+
if (/[ilI1.,'`]/.test(character)) return total + size * 0.32;
|
|
34
|
+
if (/[A-Z0-9]/.test(character)) return total + size * 0.64;
|
|
35
|
+
return total + size * 0.56;
|
|
36
|
+
}, 0);
|
|
37
|
+
return {
|
|
38
|
+
width,
|
|
39
|
+
actualBoundingBoxAscent: size * 0.8,
|
|
40
|
+
actualBoundingBoxDescent: size * 0.2
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
if (property === "createLinearGradient" || property === "createRadialGradient") {
|
|
45
|
+
return () => ({ addColorStop() {
|
|
46
|
+
} });
|
|
47
|
+
}
|
|
48
|
+
return () => void 0;
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
return context;
|
|
52
|
+
}
|
|
53
|
+
function installJSDOMCanvasContext() {
|
|
54
|
+
HTMLCanvasElement.prototype.getContext = function getContext(contextId) {
|
|
55
|
+
if (contextId !== "2d") return null;
|
|
56
|
+
const existing = contexts.get(this);
|
|
57
|
+
if (existing) return existing;
|
|
58
|
+
const context = createCanvasContext(this);
|
|
59
|
+
contexts.set(this, context);
|
|
60
|
+
return context;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// src/testing/jsdom-storage.ts
|
|
65
|
+
function clearJSDOMStorage() {
|
|
66
|
+
window.localStorage.clear();
|
|
67
|
+
window.sessionStorage.clear();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// src/react-vitest-setup.ts
|
|
71
|
+
installJSDOMCanvasContext();
|
|
5
72
|
var failures = [];
|
|
6
73
|
var consoleError;
|
|
7
74
|
var onError = (event) => failures.push(event.error ?? event.message);
|
|
@@ -20,6 +87,7 @@ afterEach(() => {
|
|
|
20
87
|
} catch (error) {
|
|
21
88
|
failures.push(error);
|
|
22
89
|
} finally {
|
|
90
|
+
clearJSDOMStorage();
|
|
23
91
|
window.removeEventListener("error", onError);
|
|
24
92
|
window.removeEventListener("unhandledrejection", onRejection);
|
|
25
93
|
consoleError?.mockRestore();
|
|
@@ -28,6 +96,9 @@ afterEach(() => {
|
|
|
28
96
|
if (failures.length > 0) {
|
|
29
97
|
const captured = failures;
|
|
30
98
|
failures = [];
|
|
31
|
-
throw new AggregateError(
|
|
99
|
+
throw new AggregateError(
|
|
100
|
+
captured,
|
|
101
|
+
"Unexpected React/JSDOM runtime failures"
|
|
102
|
+
);
|
|
32
103
|
}
|
|
33
104
|
});
|
package/dist/vitest-config.js
CHANGED
|
@@ -627,6 +627,12 @@ GAMEPLAY_AUDIT: ALL CONTRACTS PASSED (${tests.filter((test) => test.metadata).le
|
|
|
627
627
|
}
|
|
628
628
|
};
|
|
629
629
|
|
|
630
|
+
// src/testing/vitest-node-args.ts
|
|
631
|
+
function getJSDOMWorkerExecArgv() {
|
|
632
|
+
const nodeMajor = Number.parseInt(process.versions.node, 10);
|
|
633
|
+
return nodeMajor >= 25 ? ["--no-experimental-webstorage"] : [];
|
|
634
|
+
}
|
|
635
|
+
|
|
630
636
|
// src/vite.ts
|
|
631
637
|
var import_node_fs2 = require("fs");
|
|
632
638
|
var import_node_module = require("module");
|
|
@@ -674,7 +680,10 @@ function phaserRexUIScenePlugin(projectRoot) {
|
|
|
674
680
|
var PHASER_FACADE_DEPENDENCY = /miaoda-game-devkit[\\/]dist[\\/]phaser-facade\.mjs$/;
|
|
675
681
|
var REXUI_DEPENDENCY = /phaser4-rex-plugins/;
|
|
676
682
|
function defineGameVitestConfig(options) {
|
|
677
|
-
const auditIssues = validateGameplayAuditOptions(
|
|
683
|
+
const auditIssues = validateGameplayAuditOptions(
|
|
684
|
+
options.gameplayAudit,
|
|
685
|
+
options.projectRoot
|
|
686
|
+
);
|
|
678
687
|
if (auditIssues.length > 0) {
|
|
679
688
|
throw new Error(
|
|
680
689
|
`\u65E0\u6548\u7684 gameplayAudit \u914D\u7F6E\uFF1A
|
|
@@ -696,6 +705,7 @@ function defineGameVitestConfig(options) {
|
|
|
696
705
|
},
|
|
697
706
|
test: {
|
|
698
707
|
include: ["tests/**/*.test.ts"],
|
|
708
|
+
execArgv: getJSDOMWorkerExecArgv(),
|
|
699
709
|
testTimeout: options.testTimeout,
|
|
700
710
|
hookTimeout: options.hookTimeout,
|
|
701
711
|
server: {
|
|
@@ -721,6 +731,11 @@ function defineGameVitestConfig(options) {
|
|
|
721
731
|
"miaoda-game-devkit/vitest-setup",
|
|
722
732
|
...options.additionalSetupFiles ?? []
|
|
723
733
|
],
|
|
734
|
+
sequence: {
|
|
735
|
+
// Vitest 默认并行执行多个 setup file;这里保证项目 setup
|
|
736
|
+
// 始终在 devkit 完成环境边界后运行。
|
|
737
|
+
setupFiles: "list"
|
|
738
|
+
},
|
|
724
739
|
reporters: [
|
|
725
740
|
// Vitest's minimal reporter is optimized for AI output: passing tests
|
|
726
741
|
// stay quiet while failed tests retain their useful error message.
|
package/dist/vitest-config.mjs
CHANGED
|
@@ -603,6 +603,12 @@ GAMEPLAY_AUDIT: ALL CONTRACTS PASSED (${tests.filter((test) => test.metadata).le
|
|
|
603
603
|
}
|
|
604
604
|
};
|
|
605
605
|
|
|
606
|
+
// src/testing/vitest-node-args.ts
|
|
607
|
+
function getJSDOMWorkerExecArgv() {
|
|
608
|
+
const nodeMajor = Number.parseInt(process.versions.node, 10);
|
|
609
|
+
return nodeMajor >= 25 ? ["--no-experimental-webstorage"] : [];
|
|
610
|
+
}
|
|
611
|
+
|
|
606
612
|
// src/vite.ts
|
|
607
613
|
import { existsSync } from "fs";
|
|
608
614
|
import { createRequire } from "module";
|
|
@@ -650,7 +656,10 @@ function phaserRexUIScenePlugin(projectRoot) {
|
|
|
650
656
|
var PHASER_FACADE_DEPENDENCY = /miaoda-game-devkit[\\/]dist[\\/]phaser-facade\.mjs$/;
|
|
651
657
|
var REXUI_DEPENDENCY = /phaser4-rex-plugins/;
|
|
652
658
|
function defineGameVitestConfig(options) {
|
|
653
|
-
const auditIssues = validateGameplayAuditOptions(
|
|
659
|
+
const auditIssues = validateGameplayAuditOptions(
|
|
660
|
+
options.gameplayAudit,
|
|
661
|
+
options.projectRoot
|
|
662
|
+
);
|
|
654
663
|
if (auditIssues.length > 0) {
|
|
655
664
|
throw new Error(
|
|
656
665
|
`\u65E0\u6548\u7684 gameplayAudit \u914D\u7F6E\uFF1A
|
|
@@ -672,6 +681,7 @@ function defineGameVitestConfig(options) {
|
|
|
672
681
|
},
|
|
673
682
|
test: {
|
|
674
683
|
include: ["tests/**/*.test.ts"],
|
|
684
|
+
execArgv: getJSDOMWorkerExecArgv(),
|
|
675
685
|
testTimeout: options.testTimeout,
|
|
676
686
|
hookTimeout: options.hookTimeout,
|
|
677
687
|
server: {
|
|
@@ -697,6 +707,11 @@ function defineGameVitestConfig(options) {
|
|
|
697
707
|
"miaoda-game-devkit/vitest-setup",
|
|
698
708
|
...options.additionalSetupFiles ?? []
|
|
699
709
|
],
|
|
710
|
+
sequence: {
|
|
711
|
+
// Vitest 默认并行执行多个 setup file;这里保证项目 setup
|
|
712
|
+
// 始终在 devkit 完成环境边界后运行。
|
|
713
|
+
setupFiles: "list"
|
|
714
|
+
},
|
|
700
715
|
reporters: [
|
|
701
716
|
// Vitest's minimal reporter is optimized for AI output: passing tests
|
|
702
717
|
// stay quiet while failed tests retain their useful error message.
|
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "miaoda-game-devkit",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "Shared
|
|
3
|
+
"version": "0.2.13",
|
|
4
|
+
"description": "Shared React and Phaser game lint plus deterministic testing tools for Miaoda games",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"module": "./dist/index.mjs",
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
9
9
|
"bin": {
|
|
10
|
-
"miaoda-game-lint": "bin/miaoda-game-lint.js"
|
|
10
|
+
"miaoda-phaser-game-lint": "bin/miaoda-phaser-game-lint.js",
|
|
11
|
+
"miaoda-react-game-lint": "bin/miaoda-react-game-lint.js"
|
|
11
12
|
},
|
|
12
13
|
"exports": {
|
|
13
14
|
".": {
|
|
@@ -82,6 +83,8 @@
|
|
|
82
83
|
"oxlint-config.json",
|
|
83
84
|
"tsconfig-base.json",
|
|
84
85
|
"!dist/**/*.map",
|
|
86
|
+
"!dist/lint/*.contract.mjs",
|
|
87
|
+
"!dist/lint/contracts.config.mjs",
|
|
85
88
|
"!dist/lint/**/*.test.*"
|
|
86
89
|
],
|
|
87
90
|
"nx": {
|
|
@@ -105,7 +108,7 @@
|
|
|
105
108
|
"build"
|
|
106
109
|
],
|
|
107
110
|
"options": {
|
|
108
|
-
"command": "
|
|
111
|
+
"command": "vitest run --config dist/lint/contracts.config.mjs",
|
|
109
112
|
"cwd": "packages/game-devkit"
|
|
110
113
|
}
|
|
111
114
|
}
|
package/bin/miaoda-game-lint.js
DELETED
package/dist/cli/lint.js
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
|
|
4
|
-
// src/cli/lint.ts
|
|
5
|
-
var import_node_child_process = require("child_process");
|
|
6
|
-
var import_node_fs = require("fs");
|
|
7
|
-
var import_node_module = require("module");
|
|
8
|
-
var import_node_os = require("os");
|
|
9
|
-
var import_node_path = require("path");
|
|
10
|
-
var devkitRoot = (0, import_node_path.resolve)(__dirname, "../..");
|
|
11
|
-
var projectRoot = process.cwd();
|
|
12
|
-
var requireFromDevkit = (0, import_node_module.createRequire)((0, import_node_path.join)(devkitRoot, "package.json"));
|
|
13
|
-
var contractsOnly = process.argv.slice(2).includes("--contracts-only");
|
|
14
|
-
var projectBiomeConfig = (0, import_node_path.join)(projectRoot, "biome.json");
|
|
15
|
-
var biomeConfig = (0, import_node_fs.existsSync)(projectBiomeConfig) ? projectBiomeConfig : (0, import_node_path.join)(devkitRoot, "biome-config.json");
|
|
16
|
-
function resolveBin(packageName, binName) {
|
|
17
|
-
const packageJsonPath = requireFromDevkit.resolve(`${packageName}/package.json`);
|
|
18
|
-
const packageJson = JSON.parse((0, import_node_fs.readFileSync)(packageJsonPath, "utf8"));
|
|
19
|
-
const relativeBin = typeof packageJson.bin === "string" ? packageJson.bin : packageJson.bin?.[binName];
|
|
20
|
-
if (!relativeBin) {
|
|
21
|
-
throw new Error(`${packageName} does not expose the ${binName} executable`);
|
|
22
|
-
}
|
|
23
|
-
return (0, import_node_path.resolve)((0, import_node_path.dirname)(packageJsonPath), relativeBin);
|
|
24
|
-
}
|
|
25
|
-
function run(name, packageName, binName, args) {
|
|
26
|
-
return new Promise((resolveResult) => {
|
|
27
|
-
const child = (0, import_node_child_process.spawn)(process.execPath, [resolveBin(packageName, binName), ...args], {
|
|
28
|
-
cwd: projectRoot,
|
|
29
|
-
env: process.env,
|
|
30
|
-
stdio: "inherit"
|
|
31
|
-
});
|
|
32
|
-
child.once("error", (error) => {
|
|
33
|
-
console.error(`[${name}] ${error.message}`);
|
|
34
|
-
resolveResult({ name, ok: false });
|
|
35
|
-
});
|
|
36
|
-
child.once("close", (code, signal) => {
|
|
37
|
-
if (signal) {
|
|
38
|
-
console.error(`[${name}] terminated by ${signal}`);
|
|
39
|
-
}
|
|
40
|
-
resolveResult({ name, ok: code === 0 && signal === null });
|
|
41
|
-
});
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
async function runContracts() {
|
|
45
|
-
return run(
|
|
46
|
-
"vitest",
|
|
47
|
-
"vitest",
|
|
48
|
-
"vitest",
|
|
49
|
-
["run", "--config", (0, import_node_path.join)(devkitRoot, "dist/lint/contracts.config.mjs")]
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
function checkGameViteConfig() {
|
|
53
|
-
const viteConfigPath = (0, import_node_path.join)(projectRoot, "vite.config.ts");
|
|
54
|
-
if (!(0, import_node_fs.existsSync)(viteConfigPath)) {
|
|
55
|
-
console.error(
|
|
56
|
-
"[vite-config] \u7F3A\u5C11\u6A21\u677F\u5FC5\u9700\u7684 vite.config.ts\u3002\u8BF7\u6062\u590D\u6A21\u677F\u539F\u6587\u4EF6\u540E\u91CD\u65B0\u8FD0\u884C pnpm lint\u3002"
|
|
57
|
-
);
|
|
58
|
-
return { name: "vite-config", ok: false };
|
|
59
|
-
}
|
|
60
|
-
const source = (0, import_node_fs.readFileSync)(viteConfigPath, "utf8");
|
|
61
|
-
const hasDevkitImport = /from\s+["']miaoda-game-devkit\/vite["']/.test(source);
|
|
62
|
-
const hasConfigCall = /defineGameViteConfig\s*\(/.test(source);
|
|
63
|
-
if (!hasDevkitImport || !hasConfigCall) {
|
|
64
|
-
console.error(
|
|
65
|
-
"[vite-config] vite.config.ts \u672A\u4F7F\u7528\u6A21\u677F\u89C4\u5B9A\u7684\u914D\u7F6E\u5165\u53E3\u3002\n\u8BF7\u4ECE miaoda-game-devkit/vite \u5BFC\u5165 defineGameViteConfig\uFF0C\u5E76\u7528 defineGameViteConfig({ ... }) \u5305\u4F4F\u5F53\u524D\u7684\u914D\u7F6E\u5BF9\u8C61\u3002\n\u53EA\u66FF\u6362\u914D\u7F6E\u51FD\u6570\uFF0C\u4FDD\u7559\u73B0\u6709 plugins\u3001resolve \u7B49\u5BF9\u8C61\u5185\u5BB9\u4E0D\u53D8\u3002"
|
|
66
|
-
);
|
|
67
|
-
return { name: "vite-config", ok: false };
|
|
68
|
-
}
|
|
69
|
-
return { name: "vite-config", ok: true };
|
|
70
|
-
}
|
|
71
|
-
function projectUsesPhaser4() {
|
|
72
|
-
const manifestPath = (0, import_node_path.join)(projectRoot, "package.json");
|
|
73
|
-
if (!(0, import_node_fs.existsSync)(manifestPath)) return false;
|
|
74
|
-
try {
|
|
75
|
-
const manifest = JSON.parse((0, import_node_fs.readFileSync)(manifestPath, "utf8"));
|
|
76
|
-
const version = manifest.dependencies?.phaser ?? manifest.devDependencies?.phaser;
|
|
77
|
-
return typeof version === "string" && /(?:^|[^0-9])4(?:\.|$)/.test(version);
|
|
78
|
-
} catch {
|
|
79
|
-
return false;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
async function runAllChecks() {
|
|
83
|
-
if (contractsOnly) {
|
|
84
|
-
return [await runContracts()];
|
|
85
|
-
}
|
|
86
|
-
const viteConfig = projectUsesPhaser4() ? [checkGameViteConfig()] : [];
|
|
87
|
-
const [tsgo, biome] = await Promise.all([
|
|
88
|
-
run("tsgo", "@typescript/native-preview", "tsgo", ["-p", "tsconfig.json"]),
|
|
89
|
-
run("biome", "@biomejs/biome", "biome", [
|
|
90
|
-
"lint",
|
|
91
|
-
"--config-path",
|
|
92
|
-
biomeConfig,
|
|
93
|
-
"src"
|
|
94
|
-
])
|
|
95
|
-
]);
|
|
96
|
-
const tailwindOutput = (0, import_node_path.join)((0, import_node_os.tmpdir)(), `miaoda-game-devkit-${process.pid}.css`);
|
|
97
|
-
const tailwind = await run("tailwind", "tailwindcss", "tailwindcss", [
|
|
98
|
-
"-i",
|
|
99
|
-
(0, import_node_path.join)(projectRoot, "src/index.css"),
|
|
100
|
-
"-o",
|
|
101
|
-
tailwindOutput
|
|
102
|
-
]);
|
|
103
|
-
(0, import_node_fs.rmSync)(tailwindOutput, { force: true });
|
|
104
|
-
const oxlint = await run("oxlint", "oxlint", "oxlint", [
|
|
105
|
-
"-c",
|
|
106
|
-
(0, import_node_path.join)(devkitRoot, "oxlint-config.json"),
|
|
107
|
-
"src"
|
|
108
|
-
]);
|
|
109
|
-
const contracts = await runContracts();
|
|
110
|
-
return [...viteConfig, tsgo, biome, tailwind, oxlint, contracts];
|
|
111
|
-
}
|
|
112
|
-
async function main() {
|
|
113
|
-
const results = await runAllChecks();
|
|
114
|
-
const failed = results.filter((result) => !result.ok);
|
|
115
|
-
console.log("");
|
|
116
|
-
if (failed.length === 0) {
|
|
117
|
-
console.log("RESULT: ALL CHECKS PASSED - Finished with 0 errors. Found no issues.");
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
console.error(`RESULT: FAILED - Found errors in: ${failed.map(({ name }) => name).join(", ")}`);
|
|
121
|
-
console.error("Fix all lint errors, then re-run 'pnpm lint'.");
|
|
122
|
-
process.exitCode = 1;
|
|
123
|
-
}
|
|
124
|
-
main().catch((error) => {
|
|
125
|
-
console.error(error);
|
|
126
|
-
process.exitCode = 1;
|
|
127
|
-
});
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
// src/lint/vitest.config.ts
|
|
2
|
-
import { dirname, resolve } from "path";
|
|
3
|
-
import { fileURLToPath } from "url";
|
|
4
|
-
import { defineConfig } from "vitest/config";
|
|
5
|
-
var phaserPackageRoot = dirname(
|
|
6
|
-
fileURLToPath(import.meta.resolve("phaser/package.json"))
|
|
7
|
-
);
|
|
8
|
-
var vitest_config_default = defineConfig({
|
|
9
|
-
resolve: {
|
|
10
|
-
alias: {
|
|
11
|
-
phaser: resolve(phaserPackageRoot, "dist/phaser.js")
|
|
12
|
-
}
|
|
13
|
-
},
|
|
14
|
-
test: {
|
|
15
|
-
server: {
|
|
16
|
-
deps: {
|
|
17
|
-
// 合约文件运行在 Vitest 的 Node worker 中,不能被 Vite
|
|
18
|
-
// 按浏览器模块转换。
|
|
19
|
-
external: [/miaoda-game-devkit/]
|
|
20
|
-
}
|
|
21
|
-
},
|
|
22
|
-
environment: "jsdom",
|
|
23
|
-
environmentOptions: {
|
|
24
|
-
jsdom: {
|
|
25
|
-
url: "http://localhost/"
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
include: [resolve(import.meta.dirname, "*.contract.mjs")],
|
|
29
|
-
// 发布后的契约位于使用方的 node_modules 目录中。
|
|
30
|
-
exclude: [],
|
|
31
|
-
setupFiles: [resolve(import.meta.dirname, "setup.mjs")],
|
|
32
|
-
restoreMocks: true,
|
|
33
|
-
clearMocks: true
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
export {
|
|
37
|
-
vitest_config_default as default
|
|
38
|
-
};
|