fix: replace linter with biome

This commit is contained in:
David Nguyen 2026-03-24 14:55:13 +11:00
parent 53b6078fa9
commit b815f12f73
21 changed files with 315 additions and 3998 deletions

View file

@ -1,8 +0,0 @@
# Config files
*.config.js
*.config.cjs
# Statically hosted javascript files
apps/*/public/*.js
apps/*/public/*.cjs
scripts/

View file

@ -1,16 +0,0 @@
/** @type {import('eslint').Linter.Config} */
module.exports = {
root: true,
extends: ['@documenso/eslint-config'],
rules: {
'@next/next/no-img-element': 'off',
'no-unreachable': 'error',
'react-hooks/exhaustive-deps': 'off',
},
settings: {
next: {
rootDir: ['apps/*/'],
},
},
ignorePatterns: ['lingui.config.ts', 'packages/lib/translations/**/*.js'],
};

View file

@ -1,20 +0,0 @@
node_modules
.next
public
**/**/node_modules
**/**/.next
**/**/public
packages/lib/translations/**/*.js
*.lock
*.log
*.test.ts
.gitignore
.npmignore
.prettierignore
.DS_Store
.eslintignore
# Docs MDX - Prettier strips indentation from code blocks inside components
apps/docs/content/**/*.mdx

View file

@ -1,11 +1,11 @@
{
"typescript.tsdk": "node_modules/typescript/lib",
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll": "explicit"
"source.fixAll.biome": "explicit",
"source.organizeImports.biome": "explicit"
},
"eslint.validate": ["typescript", "typescriptreact", "javascript", "javascriptreact"],
"javascript.preferences.importModuleSpecifier": "non-relative",
"javascript.preferences.useAliasesForRenames": false,
"typescript.enablePromptUseWorkspaceTsdk": true,
@ -16,7 +16,7 @@
"editor.defaultFormatter": "Prisma.prisma"
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
"editor.defaultFormatter": "biomejs.biome"
},
"prisma.pinToPrisma6": true
}

View file

@ -8,7 +8,7 @@
- `npm run test:e2e` - Run E2E tests with Playwright
- `npm run test:dev -w @documenso/app-tests` - Run single E2E test in dev mode
- `npm run test-ui:dev -w @documenso/app-tests` - Run E2E tests with UI
- `npm run format` - Format code with Prettier
- `npm run format` - Format code with Biome
- `npm run dev` - Start development server for Remix app
**Important:** Do not run `npm run build` to verify changes unless explicitly asked. Builds take a long time (~2 minutes). Use `npx tsc --noEmit` for type checking specific packages if needed.

View file

@ -65,8 +65,6 @@ Documenso is an open-source document signing platform built as a **monorepo** us
| Package | Description |
| ---------------------------- | ------------------------- |
| `@documenso/app-tests` | E2E tests (Playwright) |
| `@documenso/eslint-config` | Shared ESLint config |
| `@documenso/prettier-config` | Shared Prettier config |
| `@documenso/tailwind-config` | Shared Tailwind config |
| `@documenso/tsconfig` | Shared TypeScript configs |

132
biome.json Normal file
View file

@ -0,0 +1,132 @@
{
"$schema": "https://biomejs.dev/schemas/2.4.8/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 120,
"lineEnding": "lf"
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"nursery": {
"noMisusedPromises": "error",
"noDuplicateEnumValues": "error",
"noUndeclaredEnvVars": "warn",
"noFloatingPromises": "warn",
"useSortedClasses": {
"level": "warn",
"fix": "safe"
}
},
"correctness": {
"useExhaustiveDependencies": "off",
"noUnusedImports": {
"level": "warn",
"fix": "safe"
},
"noUnusedVariables": "warn"
},
"a11y": {
"noSvgWithoutTitle": "off",
"useButtonType": "warn",
"noLabelWithoutControl": "off",
"useKeyWithClickEvents": "warn",
"useSemanticElements": "warn",
"useFocusableInteractive": "warn",
"useAriaPropsForRole": "warn",
"useValidAriaRole": "warn",
"noStaticElementInteractions": "warn",
"noRedundantAlt": "warn",
"noRedundantRoles": "warn"
},
"security": {
"noDangerouslySetInnerHtml": "warn"
},
"suspicious": {
"useAwait": "warn",
"noExplicitAny": "warn",
"noImplicitAnyLet": "warn",
"noAssignInExpressions": "warn",
"noArrayIndexKey": "off",
"useIterableCallbackReturn": "warn"
},
"style": {
"noNonNullAssertion": "warn",
"useBlockStatements": {
"level": "error",
"fix": "safe"
},
"useNodejsImportProtocol": "warn"
},
"complexity": {
"noStaticOnlyClass": "off",
"useLiteralKeys": "warn",
"noUselessFragments": {
"level": "warn",
"fix": "safe"
}
}
}
},
"javascript": {
"formatter": {
"jsxQuoteStyle": "double",
"quoteProperties": "asNeeded",
"trailingCommas": "all",
"semicolons": "always",
"arrowParentheses": "always",
"bracketSameLine": false,
"quoteStyle": "single",
"attributePosition": "auto",
"bracketSpacing": true
}
},
"css": {
"parser": {
"tailwindDirectives": true
}
},
"html": {
"formatter": {
"indentScriptAndStyle": false,
"selfCloseVoidElements": "always"
}
},
"overrides": [
{
"includes": ["*.ts", "*.tsx", "*.mts", "*.cts"],
"linter": {
"rules": {
"complexity": {
"noArguments": "error"
},
"style": {
"useConst": "error"
},
"suspicious": {
"noVar": "error"
},
"nursery": {
"useSpread": "error"
}
}
}
}
],
"assist": {
"enabled": true,
"actions": {
"source": {
"organizeImports": "on"
}
}
}
}

View file

@ -1,15 +1,10 @@
const path = require('path');
const eslint = (filenames) =>
`eslint --fix ${filenames.map((f) => `"${path.relative(process.cwd(), f)}"`).join(' ')}`;
const prettier = (filenames) =>
`prettier --write ${filenames.map((f) => `"${path.relative(process.cwd(), f)}"`).join(' ')}`;
const biome = (filenames) =>
`biome check --write --no-errors-on-unmatched ${filenames.map((f) => `"${path.relative(process.cwd(), f)}"`).join(' ')}`;
/** @type {import('lint-staged').Config} */
module.exports = {
'**/*.{ts,tsx,cts,mts}': [eslint, prettier],
'**/*.{js,jsx,cjs,mjs}': [prettier],
'**/*.{yml,mdx}': [prettier],
'**/*.{ts,tsx,cts,mts,js,jsx,cjs,mjs,json,css}': [biome],
'**/*/package.json': 'npm run precommit',
};

3924
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -14,9 +14,9 @@
"dev:docs": "turbo run dev --filter=@documenso/docs",
"dev:openpage-api": "turbo run dev --filter=@documenso/openpage-api",
"start": "turbo run start --filter=@documenso/remix --filter=@documenso/docs --filter=@documenso/openpage-api",
"lint": "turbo run lint",
"lint:fix": "turbo run lint:fix",
"format": "prettier --write \"**/*.{js,jsx,cjs,mjs,ts,tsx,cts,mts,mdx}\"",
"lint": "biome check .",
"lint:fix": "biome check --write .",
"format": "biome check --write .",
"prepare": "husky && husky install || true",
"commitlint": "commitlint --edit",
"clean": "turbo run clean && rimraf node_modules",
@ -47,6 +47,7 @@
"node": ">=22.0.0"
},
"devDependencies": {
"@biomejs/biome": "2.4.8",
"@commitlint/cli": "^20.1.0",
"@commitlint/config-conventional": "^20.0.0",
"@datadog/pprof": "^5.13.5",
@ -60,7 +61,6 @@
"@ts-rest/serverless": "^3.52.1",
"dotenv": "^17.2.3",
"dotenv-cli": "^11.0.0",
"eslint": "^8.57.0",
"husky": "^9.1.7",
"inngest-cli": "^1.16.1",
"lint-staged": "^16.2.7",
@ -70,7 +70,6 @@
"pino": "^9.14.0",
"pino-pretty": "^13.1.2",
"playwright": "1.56.1",
"prettier": "^3.6.2",
"prisma": "^6.19.0",
"prisma-extension-kysely": "^3.0.0",
"prisma-json-types-generator": "^3.6.2",

View file

@ -5,8 +5,6 @@
"types": "./index.ts",
"license": "MIT",
"scripts": {
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"clean": "rimraf node_modules"
},
"files": [
@ -26,4 +24,4 @@
"ts-pattern": "^5.9.0",
"zod": "^3.25.76"
}
}
}

View file

@ -5,8 +5,6 @@
"types": "./index.ts",
"license": "MIT",
"scripts": {
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"clean": "rimraf node_modules"
},
"dependencies": {

View file

@ -1,82 +0,0 @@
module.exports = {
extends: ['next', 'turbo', 'eslint:recommended', 'plugin:@typescript-eslint/recommended'],
plugins: ['unused-imports'],
env: {
es2022: true,
node: true,
browser: true,
},
parser: '@typescript-eslint/parser',
parserOptions: {
tsconfigRootDir: __dirname,
project: ['../../tsconfig.eslint.json'],
ecmaVersion: 2022,
ecmaFeatures: {
jsx: true,
},
sourceType: 'module',
},
rules: {
'@next/next/no-html-link-for-pages': 'off',
'react/no-unescaped-entities': 'off',
'@typescript-eslint/no-unused-vars': 'off',
'unused-imports/no-unused-imports': 'warn',
'unused-imports/no-unused-vars': [
'warn',
{
vars: 'all',
varsIgnorePattern: '^_',
args: 'after-used',
argsIgnorePattern: '^_',
destructuredArrayIgnorePattern: '^_',
},
],
'no-multi-spaces': [
'error',
{
ignoreEOLComments: false,
exceptions: {
BinaryExpression: false,
VariableDeclarator: false,
ImportDeclaration: false,
Property: false,
},
},
],
// Safety with promises so we aren't running with scissors
'no-promise-executor-return': 'error',
'prefer-promise-reject-errors': 'error',
'require-atomic-updates': 'error',
'@typescript-eslint/no-floating-promises': 'error',
'@typescript-eslint/no-misused-promises': [
'error',
{ checksVoidReturn: { attributes: false } },
],
'@typescript-eslint/promise-function-async': 'error',
'@typescript-eslint/require-await': 'error',
// We never want to use `as` but are required to on occasion to handle
// shortcomings in third-party and generated types.
//
// To handle this we want this rule to catch usages and highlight them as
// warnings so we can write appropriate interfaces and guards later.
'@typescript-eslint/consistent-type-assertions': ['warn', { assertionStyle: 'never' }],
'@typescript-eslint/consistent-type-imports': [
'warn',
{
prefer: 'type-imports',
fixStyle: 'separate-type-imports',
disallowTypeAnnotations: false,
},
],
},
};

View file

@ -1,20 +0,0 @@
{
"name": "@documenso/eslint-config",
"version": "0.0.0",
"main": "./index.cjs",
"license": "MIT",
"scripts": {
"clean": "rimraf node_modules"
},
"dependencies": {
"@typescript-eslint/eslint-plugin": "^7.18.0",
"@typescript-eslint/parser": "^7.18.0",
"eslint": "^8.57.0",
"eslint-config-next": "^15",
"eslint-config-turbo": "^1.13.4",
"eslint-plugin-package-json": "^0.85.0",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-unused-imports": "^4.3.0",
"typescript": "5.6.2"
}
}

View file

@ -1,9 +0,0 @@
{
"extends": "@documenso/tsconfig/base.json",
"compilerOptions": {
"allowJs": true,
"noEmit": true,
},
"include": ["**/*.cjs", "**/*.js"],
"exclude": ["dist", "build", "node_modules"]
}

View file

@ -12,8 +12,6 @@
"scripts": {
"test": "vitest run",
"test:watch": "vitest",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"clean": "rimraf node_modules"
},
"dependencies": {

View file

@ -1,42 +0,0 @@
/** @type {import('prettier').Config} */
module.exports = {
arrowParens: 'always',
printWidth: 100,
semi: true,
singleQuote: true,
tabWidth: 2,
trailingComma: 'all',
importOrder: [
'^server-only|client-only$',
'^react$',
'^next(/.*)?$',
'<THIRD_PARTY_MODULES>',
'^@documenso/(.*)$',
'^~/(.*)$',
'^[./]',
],
importOrderSeparation: true,
importOrderSortSpecifiers: true,
// !: Waiting for these to make it upstream
// importOrderMergeDuplicateImports: true,
// importOrderCombineTypeAndValueImports: true,
plugins: [
'@trivago/prettier-plugin-sort-imports',
// !: Disabled until Prettier 3.x is supported.
// 'prettier-plugin-sql',
'prettier-plugin-tailwindcss',
],
overrides: [
{
files: ['*.sql'],
options: {
language: 'postgresql',
keywordCase: 'upper',
expressionWidth: 60,
},
},
],
};

View file

@ -1,15 +0,0 @@
{
"name": "@documenso/prettier-config",
"version": "0.0.0",
"main": "./index.cjs",
"license": "MIT",
"scripts": {
"clean": "rimraf node_modules"
},
"dependencies": {
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
"prettier": "^3.6.2",
"prettier-plugin-tailwindcss": "^0.7.1"
},
"devDependencies": {}
}

View file

@ -5,8 +5,6 @@
"types": "./index.ts",
"license": "MIT",
"scripts": {
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"clean": "rimraf node_modules"
},
"dependencies": {

View file

@ -12,8 +12,6 @@
"index.tsx"
],
"scripts": {
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"clean": "rimraf node_modules"
},
"devDependencies": {

View file

@ -1 +0,0 @@
module.exports = require('@documenso/prettier-config');