chore: migrate from ESLint/Prettier to Biome
- Add biome.json with recommended preset + custom rules - Remove eslint.config.mjs (root, apps/react, apps/elysia) - Remove .prettierrc and .prettierignore - Update package.json: remove eslint/prettier deps, add biome scripts - Update Makefile: lint/format targets to biome - Update CI (lint.yml): eslint -> biome ci - Update VSCode config: biomejs.biome extension + default formatter - Apply biome format --write to all files - Update submodule pointers for react and elysia Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
e71f1261f6
commit
76ccc5ffe9
@@ -6,17 +6,16 @@ on:
|
||||
paths:
|
||||
- 'apps/*/src/**/*.ts'
|
||||
- 'apps/*/src/**/*.tsx'
|
||||
- 'apps/*/eslint.config.mjs'
|
||||
- 'eslint.config.mjs'
|
||||
- 'biome.json'
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'apps/*/src/**/*.ts'
|
||||
- 'apps/*/src/**/*.tsx'
|
||||
- 'eslint.config.mjs'
|
||||
- 'biome.json'
|
||||
|
||||
jobs:
|
||||
eslint:
|
||||
biome:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
@@ -26,5 +25,5 @@ jobs:
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
- run: npm install -g eslint @antfu/eslint-config
|
||||
- run: eslint . --no-error-on-unmatched-pattern
|
||||
- run: npm install -g @biomejs/biome
|
||||
- run: biome ci . --no-errors-on-unmatched
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
# Add files here to ignore them from prettier formatting
|
||||
/dist
|
||||
/coverage
|
||||
*.env
|
||||
**/target/
|
||||
**/node_modules/
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"printWidth": 100,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "all",
|
||||
"semi": true,
|
||||
"arrowParens": "always"
|
||||
}
|
||||
Vendored
+1
-2
@@ -1,8 +1,7 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"nrwl.angular-console",
|
||||
"esbenp.prettier-vscode",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"biomejs.biome",
|
||||
"ms-playwright.playwright",
|
||||
"firsttris.vscode-jest-runner"
|
||||
]
|
||||
|
||||
Vendored
+23
-1
@@ -1 +1,23 @@
|
||||
{}
|
||||
{
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "biomejs.biome"
|
||||
},
|
||||
"[javascriptreact]": {
|
||||
"editor.defaultFormatter": "biomejs.biome"
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "biomejs.biome"
|
||||
},
|
||||
"[typescriptreact]": {
|
||||
"editor.defaultFormatter": "biomejs.biome"
|
||||
},
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "biomejs.biome"
|
||||
},
|
||||
"[jsonc]": {
|
||||
"editor.defaultFormatter": "biomejs.biome"
|
||||
},
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.organizeImports.biome": "explicit"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,11 +8,11 @@ help: ## Show this help
|
||||
dev: ## Start development infrastructure (Redis etc.)
|
||||
docker compose -f infra/compose/shared.yml up -d
|
||||
|
||||
lint: ## Run ESLint across the repo
|
||||
eslint . --no-error-on-unmatched-pattern
|
||||
lint: ## Run Biome linter
|
||||
biome lint .
|
||||
|
||||
format: ## Format code with Prettier
|
||||
prettier --write "**/*.{ts,tsx,js,jsx,json,md,yaml,yml}"
|
||||
format: ## Format code with Biome
|
||||
biome format --write .
|
||||
|
||||
clean: ## Clean build artifacts
|
||||
rm -rf apps/*/dist apps/*/.next apps/*/target 2>/dev/null || true
|
||||
|
||||
+1
-1
Submodule apps/elysia updated: d2ef82ca6d...4b7c2cbd65
+1
-1
Submodule apps/react updated: 1eba6080e3...49c471b60b
+58
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"$schema": "https://biomejs.dev/schemas/2.5.3/schema.json",
|
||||
"assist": { "actions": { "source": { "organizeImports": "on" } } },
|
||||
"linter": {
|
||||
"enabled": true,
|
||||
"rules": {
|
||||
"preset": "recommended",
|
||||
"suspicious": {
|
||||
"noConsole": "off",
|
||||
"noExplicitAny": "warn"
|
||||
},
|
||||
"correctness": {
|
||||
"noUnusedVariables": "error"
|
||||
},
|
||||
"style": {
|
||||
"noNonNullAssertion": "off"
|
||||
},
|
||||
"complexity": {
|
||||
"noForEach": "off",
|
||||
"noThisInStatic": "off"
|
||||
}
|
||||
}
|
||||
},
|
||||
"formatter": {
|
||||
"enabled": true,
|
||||
"formatWithErrors": false,
|
||||
"indentStyle": "space",
|
||||
"indentWidth": 2,
|
||||
"lineWidth": 100,
|
||||
"lineEnding": "lf"
|
||||
},
|
||||
"javascript": {
|
||||
"jsxRuntime": "transparent",
|
||||
"formatter": {
|
||||
"quoteStyle": "single",
|
||||
"jsxQuoteStyle": "double",
|
||||
"trailingCommas": "all",
|
||||
"semicolons": "always",
|
||||
"arrowParentheses": "always"
|
||||
}
|
||||
},
|
||||
"files": {
|
||||
"ignoreUnknown": false,
|
||||
"includes": [
|
||||
"**",
|
||||
"!**/.opencode",
|
||||
"!**/dist",
|
||||
"!**/out",
|
||||
"!**/build",
|
||||
"!**/node_modules",
|
||||
"!**/target",
|
||||
"!**/coverage",
|
||||
"!**/*.env",
|
||||
"!**/*.env.*",
|
||||
"!**/apps/react/src/routeTree.gen.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
import antfu from '@antfu/eslint-config';
|
||||
|
||||
export default antfu({
|
||||
formatters: true,
|
||||
typescript: true,
|
||||
rules: {
|
||||
'no-console': 'off',
|
||||
'eslint-comments/no-unlimited-disable': 'off',
|
||||
},
|
||||
});
|
||||
Vendored
+45
-43
@@ -1,75 +1,77 @@
|
||||
import { existsSync, readFileSync } from "node:fs"
|
||||
import { resolve, sep } from "node:path"
|
||||
import { existsSync, readFileSync } from 'node:fs';
|
||||
import { resolve, sep } from 'node:path';
|
||||
|
||||
const distDir = resolve("./dist")
|
||||
const indexPath = resolve(distDir, "index.html")
|
||||
const distDir = resolve('./dist');
|
||||
const indexPath = resolve(distDir, 'index.html');
|
||||
|
||||
const contentTypes = {
|
||||
html: "text/html; charset=utf-8",
|
||||
css: "text/css; charset=utf-8",
|
||||
js: "application/javascript; charset=utf-8",
|
||||
json: "application/json; charset=utf-8",
|
||||
svg: "image/svg+xml",
|
||||
png: "image/png",
|
||||
jpg: "image/jpeg",
|
||||
jpeg: "image/jpeg",
|
||||
gif: "image/gif",
|
||||
webp: "image/webp",
|
||||
ico: "image/x-icon",
|
||||
woff: "font/woff",
|
||||
woff2: "font/woff2",
|
||||
ttf: "font/ttf",
|
||||
}
|
||||
html: 'text/html; charset=utf-8',
|
||||
css: 'text/css; charset=utf-8',
|
||||
js: 'application/javascript; charset=utf-8',
|
||||
json: 'application/json; charset=utf-8',
|
||||
svg: 'image/svg+xml',
|
||||
png: 'image/png',
|
||||
jpg: 'image/jpeg',
|
||||
jpeg: 'image/jpeg',
|
||||
gif: 'image/gif',
|
||||
webp: 'image/webp',
|
||||
ico: 'image/x-icon',
|
||||
woff: 'font/woff',
|
||||
woff2: 'font/woff2',
|
||||
ttf: 'font/ttf',
|
||||
};
|
||||
|
||||
function responseFromFile(filePath, headers) {
|
||||
try {
|
||||
return new Response(readFileSync(filePath), { headers })
|
||||
return new Response(readFileSync(filePath), { headers });
|
||||
} catch (error) {
|
||||
if (error?.code === "ENOENT") {
|
||||
return new Response("Not Found", { status: 404 })
|
||||
if (error?.code === 'ENOENT') {
|
||||
return new Response('Not Found', { status: 404 });
|
||||
}
|
||||
|
||||
console.error("File read error:", error)
|
||||
return new Response("Internal Server Error", { status: 500 })
|
||||
console.error('File read error:', error);
|
||||
return new Response('Internal Server Error', { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
function serveIndex() {
|
||||
return responseFromFile(indexPath, {
|
||||
"Content-Type": contentTypes.html,
|
||||
"Cache-Control": "no-cache",
|
||||
})
|
||||
'Content-Type': contentTypes.html,
|
||||
'Cache-Control': 'no-cache',
|
||||
});
|
||||
}
|
||||
|
||||
function serveFile(filePath, pathname) {
|
||||
const ext = filePath.split(".").pop() || ""
|
||||
const ext = filePath.split('.').pop() || '';
|
||||
return responseFromFile(filePath, {
|
||||
"Content-Type": contentTypes[ext] || "application/octet-stream",
|
||||
"Cache-Control": pathname.startsWith("/assets/") ? "public, max-age=31536000, immutable" : "no-cache",
|
||||
})
|
||||
'Content-Type': contentTypes[ext] || 'application/octet-stream',
|
||||
'Cache-Control': pathname.startsWith('/assets/')
|
||||
? 'public, max-age=31536000, immutable'
|
||||
: 'no-cache',
|
||||
});
|
||||
}
|
||||
|
||||
Bun.serve({
|
||||
port: 80,
|
||||
hostname: "0.0.0.0",
|
||||
hostname: '0.0.0.0',
|
||||
fetch(req) {
|
||||
const url = new URL(req.url)
|
||||
const pathname = url.pathname
|
||||
const filePath = resolve(distDir, pathname.slice(1))
|
||||
const insideDist = filePath === distDir || filePath.startsWith(`${distDir}${sep}`)
|
||||
const url = new URL(req.url);
|
||||
const pathname = url.pathname;
|
||||
const filePath = resolve(distDir, pathname.slice(1));
|
||||
const insideDist = filePath === distDir || filePath.startsWith(`${distDir}${sep}`);
|
||||
|
||||
if (!insideDist) {
|
||||
return new Response("Forbidden", { status: 403 })
|
||||
return new Response('Forbidden', { status: 403 });
|
||||
}
|
||||
|
||||
if (pathname !== "/" && existsSync(filePath)) {
|
||||
return serveFile(filePath, pathname)
|
||||
if (pathname !== '/' && existsSync(filePath)) {
|
||||
return serveFile(filePath, pathname);
|
||||
}
|
||||
|
||||
if (!pathname.includes(".") && existsSync(indexPath)) {
|
||||
return serveIndex()
|
||||
if (!pathname.includes('.') && existsSync(indexPath)) {
|
||||
return serveIndex();
|
||||
}
|
||||
|
||||
return new Response("Not Found", { status: 404 })
|
||||
return new Response('Not Found', { status: 404 });
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
+5
-4
@@ -2,12 +2,13 @@
|
||||
"name": "asepharyana-hub",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"lint": "eslint .",
|
||||
"format": "prettier --write .",
|
||||
"lint": "biome lint .",
|
||||
"format": "biome format --write .",
|
||||
"check": "biome check --write .",
|
||||
"ci": "biome ci .",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"prettier": "^3.4.2",
|
||||
"eslint": "^9.18.0"
|
||||
"@biomejs/biome": "2.5.3"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user