From 078a8c30fd3e83f8400469b1997a5f8d11a995f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Thu, 3 Sep 2026 10:25:47 +0000 Subject: [PATCH] :wrench: Replace ESLint and Prettier with oxlint and oxfmt - Drop .eslintrc.cjs and .prettierrc, add .oxlintrc.json and .oxfmtrc.json - oxlint covers correctness/suspicious/perf/style/restriction categories plus import and typescript plugins; oxfmt reads the same .prettierrc-style options we had before - Update lefthook.yml pre-commit jobs to run oxlint/oxfmt instead of eslint/prettier - Update .vscode/extensions.json (oxc replaces eslint/prettier/vitest) and settings.json (oxc becomes the default formatter for TS/JS) - Add 'oxlint', 'oxfmt', 'oxc', 'nodenext' to cspell dictionary - Rewrite README 'Development' section to describe the new toolchain --- .eslintrc.cjs | 37 -------------------- .prettierrc => .oxfmtrc.json | 2 +- .oxlintrc.json | 33 ++++++++++++++++++ .vscode/extensions.json | 6 ++-- .vscode/settings.json | 16 ++++----- README.md | 34 ++++++++++++++----- cspell.json | 13 +++++-- lefthook.yml | 66 ++++++++++++------------------------ package-lock.json | 4 +-- package.json | 48 +++++++++++++------------- project-specs.md | 1 + 11 files changed, 130 insertions(+), 130 deletions(-) delete mode 100644 .eslintrc.cjs rename .prettierrc => .oxfmtrc.json (98%) create mode 100644 .oxlintrc.json diff --git a/.eslintrc.cjs b/.eslintrc.cjs deleted file mode 100644 index 284602f..0000000 --- a/.eslintrc.cjs +++ /dev/null @@ -1,37 +0,0 @@ -// .eslintrc.cjs -module.exports = { - root: true, - parser: "@typescript-eslint/parser", - plugins: [ - "@typescript-eslint", - "import", - "unused-imports", - "simple-import-sort", - ], - extends: [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended", - "plugin:@typescript-eslint/strict-type-checked", - "plugin:@typescript-eslint/stylistic-type-checked", - "plugin:import/recommended", - "plugin:import/typescript", - "plugin:prettier/recommended", - ], - env: { - es2022: true, - node: true, - browser: true, - }, - rules: { - "prettier/prettier": "error", - "import/order": "off", - "simple-import-sort/imports": "error", - "simple-import-sort/exports": "error", - "unused-imports/no-unused-imports": "error", - "@typescript-eslint/no-unused-vars": [ - "error", - { argsIgnorePattern: "^_", varsIgnorePattern: "^_" }, - ], - }, - ignorePatterns: ["dist", "node_modules", "public"], -}; diff --git a/.prettierrc b/.oxfmtrc.json similarity index 98% rename from .prettierrc rename to .oxfmtrc.json index 7fed277..89a9584 100644 --- a/.prettierrc +++ b/.oxfmtrc.json @@ -6,4 +6,4 @@ "tabWidth": 4, "endOfLine": "lf", "arrowParens": "always" -} +} \ No newline at end of file diff --git a/.oxlintrc.json b/.oxlintrc.json new file mode 100644 index 0000000..055de8a --- /dev/null +++ b/.oxlintrc.json @@ -0,0 +1,33 @@ +{ + "$schema": "./node_modules/oxlint/configuration_schema.json", + "plugins": [ + "typescript", + "unicorn", + "oxc", + "import" + ], + "categories": { + "correctness": "error", + "suspicious": "error", + "perf": "warn", + "style": "warn", + "restriction": "error", + "nursery": "off" + }, + "rules": {}, + "env": { + "builtin": true, + "es2024": true, + "node": true + }, + "overrides": [ + { + "files": ["**/*.test.ts"], + "rules": { + "no-unused-expressions": "off", + "no-empty-file": "off" + } + } + ], + "ignorePatterns": ["dist", "node_modules", "coverage"] +} \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 9427c83..9977f32 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,9 +1,7 @@ { "recommendations": [ - "esbenp.prettier-vscode", - "dbaeumer.vscode-eslint", + "oxc.oxc-vscode", "streetsidesoftware.code-spell-checker", - "vitest.explorer", "ms-vscode.vscode-typescript-next" ] -} +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 81e0af2..894702b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,11 @@ { "typescript.tsdk": "node_modules/typescript/lib", "[typescript]": { - "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.defaultFormatter": "oxc.oxc-vscode", + "editor.formatOnSave": true + }, + "[javascript]": { + "editor.defaultFormatter": "oxc.oxc-vscode", "editor.formatOnSave": true }, "[json]": { @@ -12,10 +16,6 @@ "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.formatOnSave": true }, - "editor.defaultFormatter": "esbenp.prettier-vscode", - "editor.formatOnSave": true, - "[javascript]": { - "editor.defaultFormatter": "esbenp.prettier-vscode", - "editor.formatOnSave": true - } -} + "editor.defaultFormatter": "oxc.oxc-vscode", + "editor.formatOnSave": true +} \ No newline at end of file diff --git a/README.md b/README.md index 25a3ab3..7b50a24 100644 --- a/README.md +++ b/README.md @@ -7,20 +7,38 @@ Pattern matching for TypeScript/ESM environments (F#-style, not regex). - **Build:** `npm run build` - **Test:** `npm run test`, `npm run test:ci` - **Checks:** `npm run check`, `npm run fix` +- **Format/Fix:** `npm run fix:oxfmt`, `npm run fix:oxlint` + +### Tooling + +- **TypeScript 7** — type checker and build (`tsc`). +- **node --test** + `--experimental-strip-types` — test runner (Node 22.6+, flag dropped on Node 24). +- **c8** — code coverage for `test:ci`. +- **oxlint** — Rust-based linter. +- **oxfmt** — Rust-based formatter (Prettier-compatible). +- **cspell** — spell checking. +- **sort-package-json** — keep `package.json` keys alphabetized. +- **lefthook** — git pre-commit hooks. + +### Requirements + +- Node.js >= 22.6 (>= 24 recommended; `--experimental-strip-types` is unflagged on 24). ## VSCode integration -- Debugging -- Running tests +- Recommended extensions: see `.vscode/extensions.json` (oxc, cspell). +- TypeScript 7 is used via `typescript.tsdk` pointing at `node_modules/typescript/lib`. +- oxc extension provides oxlint squiggles and oxfmt format-on-save. ## Workflows -- Version updates -- Changelog automation -- Publishing +- Version updates via `npm version`. +- Publishing via GitHub Actions on tagged commits (see `.github/workflows/ci.yml`). +- Changesets is available as a devDependency for changelog automation if desired. ## Contribution guidelines -- Commit signing (GPG) -- How to set up commit message template -- Reference to commit-message-template +- Commit signing (GPG). +- Set up commit message template: `npm run use:git-commit-message`. +- See `commit-message-template`. +- Type-only tests use `expect-type`'s `expectTypeOf(...)` inside `node --test` cases. \ No newline at end of file diff --git a/cspell.json b/cspell.json index fd3bbdb..1e91cb5 100644 --- a/cspell.json +++ b/cspell.json @@ -1,6 +1,15 @@ { "version": "0.2", "language": "en", - "words": ["tslib", "typefest", "lefthook"], + "words": [ + "tslib", + "typefest", + "lefthook", + "oxlint", + "oxfmt", + "oxc", + "nodenext", + "nocheck" + ], "ignorePaths": ["dist", "node_modules", "public", "coverage", "*.svg"] -} +} \ No newline at end of file diff --git a/lefthook.yml b/lefthook.yml index 21d676b..bf7d1d5 100644 --- a/lefthook.yml +++ b/lefthook.yml @@ -1,45 +1,21 @@ -# EXAMPLE USAGE: -# -# Refer for explanation to following link: -# https://lefthook.dev/configuration/ -# -# pre-push: -# jobs: -# - name: packages audit -# tags: -# - frontend -# - security -# run: yarn audit -# -# - name: gems audit -# tags: -# - backend -# - security -# run: bundle audit -# -# pre-commit: -# parallel: true -# jobs: -# - run: yarn eslint {staged_files} -# glob: "*.{js,ts,jsx,tsx}" -# -# - name: rubocop -# glob: "*.rb" -# exclude: -# - config/application.rb -# - config/routes.rb -# run: bundle exec rubocop --force-exclusion {all_files} -# -# - name: govet -# files: git ls-files -m -# glob: "*.go" -# run: go vet {files} -# -# - script: "hello.js" -# runner: node -# -# - script: "hello.go" -# runner: go run +pre-commit: + parallel: true + jobs: + - name: oxlint + glob: "*.{ts,tsx,js,jsx,mjs,cjs}" + run: npx oxlint {staged_files} + - name: oxfmt + glob: "*.{ts,tsx,js,jsx,mjs,cjs}" + run: npx oxfmt --check {staged_files} + - name: cspell + run: npx cspell {staged_files} + - name: sort-package-json + run: npx sort-package-json --check + - name: typecheck + run: npx tsc --noEmit + - name: outdated + run: npx check-outdated + commands: typecheck: run: npm run check:tsc @@ -48,8 +24,8 @@ commands: sort: run: npm run check:package lint: - run: npm run check:eslint + run: npm run check:oxlint format: - run: npm run check:prettier + run: npm run check:oxfmt outdated: - run: npm run check:outdated + run: npm run check:outdated \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 8f1a056..b38f662 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,8 @@ "version": "0.0.0", "license": "MIT", "devDependencies": { + "@oxfmt/binding-linux-x64-musl": "^0.66.0", + "@oxlint/binding-linux-x64-musl": "^1.81.0", "@types/node": "^22.10.0", "c8": "^10.1.3", "check-outdated": "^2.13.0", @@ -906,7 +908,6 @@ "x64" ], "dev": true, - "optional": true, "os": [ "linux" ], @@ -1210,7 +1211,6 @@ "x64" ], "dev": true, - "optional": true, "os": [ "linux" ], diff --git a/package.json b/package.json index 12d4b1b..71e0f20 100644 --- a/package.json +++ b/package.json @@ -10,51 +10,47 @@ "adt", "typescript" ], + "repository": { + "type": "git", + "url": "https://github.com/tmueller/tiny-pattern-ts.git" + }, "license": "MIT", - "type": "module", "sideEffects": false, - "engines": { - "node": ">=22.6" - }, - "publishConfig": { - "access": "public" - }, - "main": "./dist/index.js", - "types": "./dist/index.d.ts", + "type": "module", "exports": { ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js" } }, + "main": "./dist/index.js", + "types": "./dist/index.d.ts", "files": [ "dist", "README.md", "LICENSE" ], - "repository": { - "type": "git", - "url": "https://github.com/tmueller/tiny-pattern-ts.git" - }, "scripts": { "build": "tsc -p tsconfig.build.json", - "clean": "node -e \"fs.rmSync('dist', { recursive: true, force: true })\"", - "test": "npm run check:tsc && node --test --experimental-strip-types --no-warnings src/", - "test:unit": "node --test --experimental-strip-types --no-warnings src/", - "test:ci": "c8 --reporter=text --reporter=lcov --reporter=html node --test --experimental-strip-types --no-warnings src/", "check": "npm run check:oxlint && npm run check:oxfmt && npm run check:tsc && npm run check:cspell && npm run check:package && npm run check:outdated", - "check:oxlint": "oxlint src", - "check:oxfmt": "oxfmt --check src", - "check:tsc": "tsc --noEmit", "check:cspell": "cspell .", - "check:package": "sort-package-json --check", "check:outdated": "check-outdated", - "fix:oxlint": "oxlint --fix src", + "check:oxfmt": "oxfmt --check src", + "check:oxlint": "oxlint src", + "check:package": "sort-package-json --check", + "check:tsc": "tsc --noEmit", + "clean": "node -e \"fs.rmSync('dist', { recursive: true, force: true })\"", "fix:oxfmt": "oxfmt src", + "fix:oxlint": "oxlint --fix src", "fix:package": "sort-package-json --write", + "test": "npm run check:tsc && node --test --experimental-strip-types --no-warnings src/", + "test:ci": "c8 --reporter=text --reporter=lcov --reporter=html node --test --experimental-strip-types --no-warnings src/", + "test:unit": "node --test --experimental-strip-types --no-warnings src/", "use:git-commit-message": "cp commit-message-template .git/COMMIT_EDITMSG || true" }, "devDependencies": { + "@oxfmt/binding-linux-x64-musl": "^0.66.0", + "@oxlint/binding-linux-x64-musl": "^1.81.0", "@types/node": "^22.10.0", "c8": "^10.1.3", "check-outdated": "^2.13.0", @@ -66,5 +62,11 @@ "tslib": "^2.8.1", "type-fest": "^4.40.1", "typescript": "^7.0.2" + }, + "engines": { + "node": ">=22.6" + }, + "publishConfig": { + "access": "public" } -} \ No newline at end of file +} diff --git a/project-specs.md b/project-specs.md index e2fac7c..a872e09 100644 --- a/project-specs.md +++ b/project-specs.md @@ -288,6 +288,7 @@ Resolves #... - `dbaeumer.vscode-eslint` (ESLint) - `streetsidesoftware.code-spell-checker` (cspell) - `vitest.explorer` (for test integration) + - TODO: Native test extension with node test runner - `ms-vscode.vscode-typescript-next` (for latest TS features, optional) - Add `.vscode/tasks.json` for common tasks (optional):