Skip to content

Commit 3b79789

Browse files
committed
refactor(eslint): add eslint config
1 parent d32b0a1 commit 3b79789

File tree

14 files changed

+326
-31
lines changed

14 files changed

+326
-31
lines changed

bun.lock

Lines changed: 219 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

eslint.config.mjs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import tsPlugin from "@typescript-eslint/eslint-plugin";
2+
import tsParser from "@typescript-eslint/parser";
3+
import prettierPlugin from "eslint-plugin-prettier";
4+
5+
/**
6+
* ESLint flat config for the project.
7+
* - TypeScript parser + plugin for typed linting
8+
* - Prettier plugin to keep formatting enforced by ESLint
9+
* - Basic overrides for test files and generated or output folders
10+
*/
11+
export default [
12+
// ignore common build/artifact folders
13+
{
14+
ignores: ["dist/**", "build/**", "node_modules/**"],
15+
},
16+
17+
// General JS/TS settings
18+
{
19+
files: ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.cjs", "**/*.mjs"],
20+
languageOptions: {
21+
parser: tsParser,
22+
parserOptions: {
23+
project: ["./tsconfig.json"],
24+
tsconfigRootDir: new URL(".", import.meta.url).pathname,
25+
ecmaVersion: "latest",
26+
sourceType: "module",
27+
},
28+
globals: {
29+
// Bun testing / runtime globals (Bun provides `Bun` as global runtime)
30+
Bun: "readonly",
31+
},
32+
},
33+
// Plugins are loaded by name in the flat config as objects
34+
plugins: {
35+
"@typescript-eslint": tsPlugin,
36+
prettier: prettierPlugin,
37+
},
38+
rules: {
39+
// Prettier enforces formatting — run prettier as part of linting
40+
"prettier/prettier": "error",
41+
42+
// Replace core ESLint `no-unused-vars` with TypeScript-aware rule
43+
"no-unused-vars": "off",
44+
"@typescript-eslint/no-unused-vars": ["warn", { argsIgnorePattern: "^_" }],
45+
46+
// Type-only import enforcement for consistency
47+
"@typescript-eslint/consistent-type-imports": "error",
48+
49+
// Allow some pragmatic leniency for lib code (disable if you want stricter checks)
50+
"@typescript-eslint/explicit-module-boundary-types": "off",
51+
"@typescript-eslint/no-explicit-any": "off",
52+
},
53+
},
54+
55+
// Test files — bun.test uses describe/it/expect (similar to Jest), mark them as known
56+
{
57+
files: ["**/*.test.ts", "**/*.spec.ts"],
58+
languageOptions: {
59+
globals: {
60+
describe: "readonly",
61+
it: "readonly",
62+
test: "readonly",
63+
expect: "readonly",
64+
beforeAll: "readonly",
65+
afterAll: "readonly",
66+
},
67+
},
68+
rules: {
69+
// Tests often include non-null assertions and other patterns that are okay
70+
"@typescript-eslint/no-non-null-assertion": "off",
71+
"@typescript-eslint/no-explicit-any": "off",
72+
},
73+
},
74+
];

examples/advanced-scheduling/demo.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const HealthId = component<Health>();
1717
class InputSystem implements System<[deltaTime: number]> {
1818
readonly dependencies: readonly System<[deltaTime: number]>[] = [];
1919

20-
update(deltaTime: number): void {
20+
update(_deltaTime: number): void {
2121
console.log(`[InputSystem] Processing input at ${Date.now()}`);
2222
// 这里可以处理键盘/鼠标输入等
2323
}
@@ -54,7 +54,7 @@ class DamageSystem implements System<[deltaTime: number]> {
5454
this.query = world.createQuery([PositionId, HealthId]);
5555
}
5656

57-
update(deltaTime: number): void {
57+
update(_deltaTime: number): void {
5858
console.log(`[DamageSystem] Applying damage based on position`);
5959

6060
this.query.forEach([PositionId, HealthId], (entity, position, health) => {
@@ -76,7 +76,7 @@ class RenderSystem implements System<[deltaTime: number]> {
7676
this.query = world.createQuery([PositionId]);
7777
}
7878

79-
update(deltaTime: number): void {
79+
update(_deltaTime: number): void {
8080
console.log(`[RenderSystem] Rendering entities`);
8181

8282
this.query.forEach([PositionId], (entity, position) => {

package.json

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
"type": "module",
55
"devDependencies": {
66
"@types/bun": "1.3.2",
7+
"@typescript-eslint/eslint-plugin": "^8.48.1",
8+
"@typescript-eslint/parser": "^8.48.1",
9+
"eslint": "^9.39.1",
10+
"eslint-plugin-prettier": "^5.5.4",
711
"husky": "^9.1.7",
812
"lint-staged": "^16.2.6",
913
"prettier": "^3.6.2",
@@ -14,14 +18,18 @@
1418
"test": "bun test",
1519
"demo": "bun run examples/simple/demo.ts",
1620
"release": "bun run scripts/release.ts",
17-
"prepare": "husky"
21+
"prepare": "husky",
22+
"lint": "eslint --ext .ts,.tsx,.js --quiet",
23+
"lint:fix": "eslint --ext .ts,.tsx,.js --fix",
24+
"format": "prettier --write ."
1825
},
1926
"peerDependencies": {
2027
"typescript": "^5.9.3"
2128
},
2229
"lint-staged": {
2330
"*.{ts,tsx}": [
24-
"prettier --write"
31+
"prettier --write",
32+
"eslint --fix"
2533
],
2634
"*.{json,md}": [
2735
"prettier --write"

scripts/build.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export async function build() {
1515

1616
// 使用 Bun.build 构建所有入口点
1717
console.log("🔨 Building workflow library...");
18-
const result = await tsdownBuild({
18+
await tsdownBuild({
1919
entry: entrypoints,
2020
outDir: "dist",
2121
dts: true,

src/archetype.test.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ describe("Archetype", () => {
115115
archetype.addEntity(entity2, new Map([[positionComponent, { x: 2, y: 2 }]]));
116116

117117
const iteratedEntities: EntityId[] = [];
118-
archetype.forEach((entityId, components) => {
118+
archetype.forEach((entityId, _components) => {
119119
iteratedEntities.push(entityId);
120120
});
121121

@@ -138,7 +138,6 @@ describe("Archetype", () => {
138138

139139
it("should handle wildcard relations in forEachWithComponents", () => {
140140
// Create a relation component type: position relation from entity to entity
141-
const positionRelation = relation(positionComponent, createEntityId(1026)); // Dummy target for type
142141
const wildcardPositionRelation = relation(positionComponent, "*");
143142

144143
const entity1 = createEntityId(1024);

src/entity.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,9 +288,9 @@ describe("EntityIdManager", () => {
288288

289289
it("should reuse IDs from freelist before allocating new ones", () => {
290290
const manager = new EntityIdManager();
291-
const id1 = manager.allocate(); // 1024
291+
manager.allocate(); // 1024
292292
const id2 = manager.allocate(); // 1025
293-
const id3 = manager.allocate(); // 1026
293+
manager.allocate(); // 1026
294294

295295
manager.deallocate(id2);
296296
expect(manager.allocate()).toBe(id2); // Should reuse 1025

src/entity.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,8 @@ export function getIdType(
211211
case "wildcard":
212212
return "wildcard-relation";
213213
}
214-
} catch (error) {
214+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
215+
} catch (_error) {
215216
return "invalid"; // fallback for invalid relation IDs
216217
}
217218
}
@@ -274,7 +275,8 @@ export function getDetailedIdType(id: EntityId<any>):
274275
componentId: decoded.componentId,
275276
targetId: decoded.targetId as any,
276277
};
277-
} catch (error) {
278+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
279+
} catch (_error) {
278280
// Invalid relation ID
279281
return { type: "invalid" };
280282
}
@@ -317,7 +319,8 @@ export function inspectEntityId(id: EntityId<any>): string {
317319
? `Component ID (${decoded.targetId})`
318320
: "Wildcard (*)";
319321
return `Relation ID: ${componentStr} -> ${targetStr}`;
320-
} catch (error) {
322+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
323+
} catch (_error) {
321324
return `Invalid Relation ID (${id})`;
322325
}
323326
}

src/query-filter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Archetype } from "./archetype";
1+
import type { Archetype } from "./archetype";
22
import type { EntityId } from "./entity";
33
import { getComponentIdFromRelationId, getDetailedIdType, isRelationId } from "./entity";
44

src/query.perf.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ function performanceTest() {
6161
let totalTime = 0;
6262
for (let i = 0; i < iterations; i++) {
6363
const start = performance.now();
64-
const entities = positionVelocityQuery.getEntitiesWithComponents([positionComponent, velocityComponent]);
64+
positionVelocityQuery.getEntitiesWithComponents([positionComponent, velocityComponent]);
6565
const end = performance.now();
6666
totalTime += end - start;
6767
}
@@ -71,7 +71,7 @@ function performanceTest() {
7171
totalTime = 0;
7272
for (let i = 0; i < iterations; i++) {
7373
const start = performance.now();
74-
positionVelocityQuery.forEach([positionComponent, velocityComponent], (entity, position, velocity) => {
74+
positionVelocityQuery.forEach([positionComponent, velocityComponent], (_entity, _position, _velocity) => {
7575
// 空操作,只是为了测量遍历性能
7676
});
7777
const end = performance.now();

0 commit comments

Comments
 (0)