diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cbea7d46c..f4a086fdf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,11 +31,8 @@ jobs: - run: bun install --frozen-lockfile - - name: Lint - run: bun run lint - - - name: Typecheck - run: bunx tsgo --noEmit + - name: Lint & typecheck + run: bun run check - name: Unit tests run: bun test tests/engine/ diff --git a/AGENTS.md b/AGENTS.md index de5d8ce2e..ea65947b9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -17,7 +17,7 @@ The root app (`src/`) is the Tauri/Vite desktop editor. Its `src/engine/` files ## Commands -- `bun run check` — lint + typecheck (run before committing) +- `bun run check` — type-aware lint + typecheck via oxlint + tsgo (run before committing) - `bun run test:dupes` — jscpd copy-paste detection across all TS sources - `bun run format` — oxfmt with import sorting - `bun test ./tests/engine` — unit tests @@ -64,7 +64,7 @@ The root app (`src/`) is the Tauri/Vite desktop editor. Its `src/engine/` files Run all quality gates (see [Code quality](#code-quality) for the self-review checklist): ```sh -bun run check # oxlint + typecheck +bun run check # oxlint + tsgo type-aware lint & typecheck bun run format # oxfmt bun run test:dupes # jscpd < 3% bun run test:unit # bun:test @@ -143,7 +143,7 @@ When adding features, update `CHANGELOG.md` (Unreleased section) and `README.md` Before submitting a PR, run the full quality gate and do a self-review: ```sh -bun run check # oxlint + typecheck — zero errors required +bun run check # oxlint + tsgo type-aware lint & typecheck — zero errors required bun run format # oxfmt with import sorting bun run test:dupes # jscpd — must stay under 3% duplication bun run test:unit # bun:test diff --git a/bun.lock b/bun.lock index 28324f02e..27f1867ec 100644 --- a/bun.lock +++ b/bun.lock @@ -62,6 +62,7 @@ "jscpd": "^4.0.8", "oxfmt": "^0.35.0", "oxlint": "^1.50.0", + "oxlint-tsgolint": "^0.16.0", "tw-animate-css": "^1.4.0", "typescript": "~5.8.3", "unplugin-icons": "^23.0.1", @@ -715,6 +716,18 @@ "@oxfmt/binding-win32-x64-msvc": ["@oxfmt/binding-win32-x64-msvc@0.35.0", "", { "os": "win32", "cpu": "x64" }, "sha512-WCDJjlS95NboR0ugI2BEwzt1tYvRDorDRM9Lvctls1SLyKYuNRCyrPwp1urUPFBnwgBNn9p2/gnmo7gFMySRoQ=="], + "@oxlint-tsgolint/darwin-arm64": ["@oxlint-tsgolint/darwin-arm64@0.16.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-WQt5lGwRPJBw7q2KNR0mSPDAaMmZmVvDlEEti96xLO7ONhyomQc6fBZxxwZ4qTFedjJnrHX94sFelZ4OKzS7UQ=="], + + "@oxlint-tsgolint/darwin-x64": ["@oxlint-tsgolint/darwin-x64@0.16.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-VJo29XOzdkalvCTiE2v6FU3qZlgHaM8x8hUEVJGPU2i5W+FlocPpmn00+Ld2n7Q0pqIjyD5EyvZ5UmoIEJMfqg=="], + + "@oxlint-tsgolint/linux-arm64": ["@oxlint-tsgolint/linux-arm64@0.16.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-MPfqRt1+XRHv9oHomcBMQ3KpTE+CSkZz14wUxDQoqTNdUlV0HWdzwIE9q65I3D9YyxEnqpM7j4qtDQ3apqVvbQ=="], + + "@oxlint-tsgolint/linux-x64": ["@oxlint-tsgolint/linux-x64@0.16.0", "", { "os": "linux", "cpu": "x64" }, "sha512-XQSwVUsnwLokMhe1TD6IjgvW5WMTPzOGGkdFDtXWQmlN2YeTw94s/NN0KgDrn2agM1WIgAenEkvnm0u7NgwEyw=="], + + "@oxlint-tsgolint/win32-arm64": ["@oxlint-tsgolint/win32-arm64@0.16.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-EWdlspQiiFGsP2AiCYdhg5dTYyAlj6y1nRyNI2dQWq4Q/LITFHiSRVPe+7m7K7lcsZCEz2icN/bCeSkZaORqIg=="], + + "@oxlint-tsgolint/win32-x64": ["@oxlint-tsgolint/win32-x64@0.16.0", "", { "os": "win32", "cpu": "x64" }, "sha512-1ufk8cgktXJuJZHKF63zCHAkaLMwZrEXnZ89H2y6NO85PtOXqu4zbdNl0VBpPP3fCUuUBu9RvNqMFiv0VsbXWA=="], + "@oxlint/binding-android-arm-eabi": ["@oxlint/binding-android-arm-eabi@1.51.0", "", { "os": "android", "cpu": "arm" }, "sha512-jJYIqbx4sX+suIxWstc4P7SzhEwb4ArWA2KVrmEuu9vH2i0qM6QIHz/ehmbGE4/2fZbpuMuBzTl7UkfNoqiSgw=="], "@oxlint/binding-android-arm64": ["@oxlint/binding-android-arm64@1.51.0", "", { "os": "android", "cpu": "arm64" }, "sha512-GtXyBCcH4ti98YdiMNCrpBNGitx87EjEWxevnyhcBK12k/Vu4EzSB45rzSC4fGFUD6sQgeaxItRCEEWeVwPafw=="], @@ -1917,6 +1930,8 @@ "oxlint": ["oxlint@1.51.0", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.51.0", "@oxlint/binding-android-arm64": "1.51.0", "@oxlint/binding-darwin-arm64": "1.51.0", "@oxlint/binding-darwin-x64": "1.51.0", "@oxlint/binding-freebsd-x64": "1.51.0", "@oxlint/binding-linux-arm-gnueabihf": "1.51.0", "@oxlint/binding-linux-arm-musleabihf": "1.51.0", "@oxlint/binding-linux-arm64-gnu": "1.51.0", "@oxlint/binding-linux-arm64-musl": "1.51.0", "@oxlint/binding-linux-ppc64-gnu": "1.51.0", "@oxlint/binding-linux-riscv64-gnu": "1.51.0", "@oxlint/binding-linux-riscv64-musl": "1.51.0", "@oxlint/binding-linux-s390x-gnu": "1.51.0", "@oxlint/binding-linux-x64-gnu": "1.51.0", "@oxlint/binding-linux-x64-musl": "1.51.0", "@oxlint/binding-openharmony-arm64": "1.51.0", "@oxlint/binding-win32-arm64-msvc": "1.51.0", "@oxlint/binding-win32-ia32-msvc": "1.51.0", "@oxlint/binding-win32-x64-msvc": "1.51.0" }, "peerDependencies": { "oxlint-tsgolint": ">=0.15.0" }, "optionalPeers": ["oxlint-tsgolint"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-g6DNPaV9/WI9MoX2XllafxQuxwY1TV++j7hP8fTJByVBuCoVtm3dy9f/2vtH/HU40JztcgWF4G7ua+gkainklQ=="], + "oxlint-tsgolint": ["oxlint-tsgolint@0.16.0", "", { "optionalDependencies": { "@oxlint-tsgolint/darwin-arm64": "0.16.0", "@oxlint-tsgolint/darwin-x64": "0.16.0", "@oxlint-tsgolint/linux-arm64": "0.16.0", "@oxlint-tsgolint/linux-x64": "0.16.0", "@oxlint-tsgolint/win32-arm64": "0.16.0", "@oxlint-tsgolint/win32-x64": "0.16.0" }, "bin": { "tsgolint": "bin/tsgolint.js" } }, "sha512-4RuJK2jP08XwqtUu+5yhCbxEauCm6tv2MFHKEMsjbosK2+vy5us82oI3VLuHwbNyZG7ekZA26U2LLHnGR4frIA=="], + "p-defer": ["p-defer@4.0.1", "", {}, "sha512-Mr5KC5efvAK5VUptYEIopP1bakB85k2IWXaRC0rsh1uwn1L6M0LVml8OIQ4Gudg4oyZakf7FmeRLkMMtZW1i5A=="], "p-event": ["p-event@6.0.1", "", { "dependencies": { "p-timeout": "^6.1.2" } }, "sha512-Q6Bekk5wpzW5qIyUP4gdMEujObYstZl6DMMOSenwBvV0BlE5LkDwkjs5yHbZmdCEq2o4RJx4tE1vwxFVf2FG1w=="], diff --git a/oxlint.json b/oxlint.json index 8fd76272c..48874fe6a 100644 --- a/oxlint.json +++ b/oxlint.json @@ -11,6 +11,7 @@ "typescript/no-explicit-any": "warn", "typescript/no-non-null-assertion": "warn", + "typescript/no-floating-promises": "warn", "import/no-cycle": "error", "import/no-self-import": "error", diff --git a/package.json b/package.json index c46f333a7..3d4188991 100644 --- a/package.json +++ b/package.json @@ -9,13 +9,12 @@ ], "scripts": { "dev": "vite", - "build": "tsgo --noEmit && vite build", + "build": "bun run lint && vite build", "preview": "vite preview", "tauri": "tauri", - "lint": "oxlint -c oxlint.json src/", + "lint": "oxlint -c oxlint.json --type-aware --type-check src/", "format": "oxfmt --write src/", - "typecheck": "tsgo --noEmit", - "check": "bun run lint && bun run typecheck", + "check": "bun run lint", "test": "playwright test --project=openpencil", "test:update": "playwright test --project=openpencil --update-snapshots", "test:figma": "playwright test --project=figma", @@ -87,6 +86,7 @@ "jscpd": "^4.0.8", "oxfmt": "^0.35.0", "oxlint": "^1.50.0", + "oxlint-tsgolint": "^0.16.0", "tw-animate-css": "^1.4.0", "typescript": "~5.8.3", "unplugin-icons": "^23.0.1",