From d5e2973dce617f451e4eb07491b3a6874ea6ca47 Mon Sep 17 00:00:00 2001 From: xuatz Date: Sun, 22 Jun 2025 20:29:30 +0900 Subject: chore: migrate away from eslint to oxlint (#1642) * chore: migrate away from eslint to oxlint * revert turbo task name lint * it seems like we can remove the seemingly default globals --- apps/browser-extension/.oxlintrc.json | 34 +++++++++++++++++++ apps/browser-extension/package.json | 15 ++------- apps/cli/.oxlintrc.json | 22 ++++++++++++ apps/cli/package.json | 11 ++---- apps/cli/src/commands/bookmarks.ts | 2 +- apps/landing/.oxlintrc.json | 34 +++++++++++++++++++ apps/landing/package.json | 12 ++----- apps/mcp/.oxlintrc.json | 22 ++++++++++++ apps/mcp/package.json | 11 ++---- apps/mobile/.oxlintrc.json | 39 ++++++++++++++++++++++ apps/mobile/app/dashboard/bookmarks/new.tsx | 2 +- apps/mobile/components/bookmarks/BookmarkCard.tsx | 2 +- apps/mobile/package.json | 20 ++--------- apps/web/.oxlintrc.json | 35 +++++++++++++++++++ apps/web/app/dashboard/cleanups/page.tsx | 1 + apps/web/app/dashboard/highlights/page.tsx | 1 + apps/web/app/dashboard/lists/page.tsx | 1 + apps/web/app/dashboard/tags/page.tsx | 1 + .../components/dashboard/bookmarks/EditorCard.tsx | 2 +- .../components/dashboard/lists/EditListModal.tsx | 6 +++- .../components/dashboard/preview/HighlightsBox.tsx | 7 ++-- apps/web/components/settings/ApiKeySettings.tsx | 1 + apps/web/components/settings/ImportExport.tsx | 2 +- apps/web/components/settings/UserDetails.tsx | 1 + .../components/shared/sidebar/MobileSidebar.tsx | 1 + apps/web/components/shared/sidebar/Sidebar.tsx | 1 + apps/web/components/ui/copy-button.tsx | 2 +- apps/web/lib/importBookmarkParser.ts | 2 +- apps/web/lib/userLocalSettings/types.ts | 2 +- apps/web/package.json | 15 ++------- apps/web/server/api/client.ts | 2 +- apps/workers/.oxlintrc.json | 22 ++++++++++++ apps/workers/package.json | 11 ++---- apps/workers/workers/crawlerWorker.ts | 2 +- apps/workers/workers/feedWorker.ts | 2 +- apps/workers/workers/videoWorker.ts | 2 +- 36 files changed, 252 insertions(+), 96 deletions(-) create mode 100644 apps/browser-extension/.oxlintrc.json create mode 100644 apps/cli/.oxlintrc.json create mode 100644 apps/landing/.oxlintrc.json create mode 100644 apps/mcp/.oxlintrc.json create mode 100644 apps/mobile/.oxlintrc.json create mode 100644 apps/web/.oxlintrc.json create mode 100644 apps/workers/.oxlintrc.json (limited to 'apps') diff --git a/apps/browser-extension/.oxlintrc.json b/apps/browser-extension/.oxlintrc.json new file mode 100644 index 00000000..91dc201f --- /dev/null +++ b/apps/browser-extension/.oxlintrc.json @@ -0,0 +1,34 @@ +{ + "$schema": "../../node_modules/oxlint/configuration_schema.json", + "extends": [ + "../../tooling/oxlint/oxlint-base.json", + "../../tooling/oxlint/oxlint-react.json" + ], + "categories": { + "correctness": "warn" + }, + "env": { + "builtin": true, + "commonjs": true, + "browser": true, + "es2022": true, + "node": true + }, + "globals": { + "React": "writeable" + }, + "settings": { + "react": { + "version": "detect" + } + }, + "ignorePatterns": [ + "**/*.config.js", + "**/*.config.cjs", + "**/.eslintrc.cjs", + ".next", + "dist", + "build", + "pnpm-lock.yaml" + ] +} diff --git a/apps/browser-extension/package.json b/apps/browser-extension/package.json index cf1eac1c..f70799f4 100644 --- a/apps/browser-extension/package.json +++ b/apps/browser-extension/package.json @@ -8,8 +8,8 @@ "build": "tsc && vite build", "format": "prettier .", "format:fix": "prettier . --write", - "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", - "lint:fix": "eslint . --ext ts,tsx --fix", + "lint": "oxlint .", + "lint:fix": "oxlint . --fix", "preview": "vite preview", "typecheck": "tsc --noEmit" }, @@ -41,7 +41,6 @@ }, "devDependencies": { "@crxjs/vite-plugin": "2.0.0-beta.28", - "@karakeep/eslint-config": "workspace:^0.2.0", "@karakeep/prettier-config": "workspace:^0.1.0", "@karakeep/tailwind-config": "workspace:^0.1.0", "@karakeep/tsconfig": "workspace:^0.1.0", @@ -50,20 +49,10 @@ "@types/react-dom": "^18.3.1", "@vitejs/plugin-react-swc": "^3.5.0", "autoprefixer": "^10.4.17", - "eslint": "^8.57.0", - "eslint-plugin-react-hooks": "^4.6.0", - "eslint-plugin-react-refresh": "^0.4.5", "postcss": "^8.4.35", "tailwindcss": "^3.4.1", "typescript": "^5.7.3", "vite": "^5.1.0" }, - "eslintConfig": { - "root": true, - "extends": [ - "@karakeep/eslint-config/base", - "@karakeep/eslint-config/react" - ] - }, "prettier": "@karakeep/prettier-config" } diff --git a/apps/cli/.oxlintrc.json b/apps/cli/.oxlintrc.json new file mode 100644 index 00000000..44a3dcef --- /dev/null +++ b/apps/cli/.oxlintrc.json @@ -0,0 +1,22 @@ +{ + "$schema": "../../node_modules/oxlint/configuration_schema.json", + "extends": [ + "../../tooling/oxlint/oxlint-base.json" + ], + "categories": { + "correctness": "warn" + }, + "env": { + "builtin": true, + "commonjs": true + }, + "ignorePatterns": [ + "**/*.config.js", + "**/*.config.cjs", + "**/.eslintrc.cjs", + "**/.next", + "**/dist", + "**/build", + "**/pnpm-lock.yaml" + ] +} diff --git a/apps/cli/package.json b/apps/cli/package.json index b0454b2e..0aa8230e 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -15,7 +15,6 @@ }, "devDependencies": { "@commander-js/extra-typings": "^12.0.1", - "@karakeep/eslint-config": "workspace:^0.2.0", "@karakeep/prettier-config": "workspace:^0.1.0", "@karakeep/shared": "workspace:^0.1.0", "@karakeep/trpc": "workspace:^0.1.0", @@ -33,8 +32,8 @@ "scripts": { "build": "vite build", "run": "tsx src/index.ts", - "lint": "eslint .", - "lint:fix": "eslint . --fix", + "lint": "oxlint .", + "lint:fix": "oxlint . --fix", "format": "prettier . --ignore-path ../../.prettierignore", "format:fix": "prettier . --write --ignore-path ../../.prettierignore", "typecheck": "tsc --noEmit" @@ -44,11 +43,5 @@ "url": "git+https://github.com/karakeep-app/karakeep.git", "directory": "apps/cli" }, - "eslintConfig": { - "root": true, - "extends": [ - "@karakeep/eslint-config/base" - ] - }, "prettier": "@karakeep/prettier-config" } diff --git a/apps/cli/src/commands/bookmarks.ts b/apps/cli/src/commands/bookmarks.ts index 130ad376..308b57b0 100644 --- a/apps/cli/src/commands/bookmarks.ts +++ b/apps/cli/src/commands/bookmarks.ts @@ -261,7 +261,7 @@ bookmarkCmd results = [...results, ...resp.bookmarks]; } printObject(results.map(normalizeBookmark), { maxArrayLength: null }); - } catch (e) { + } catch { printStatusMessage(false, "Failed to query bookmarks"); } }); diff --git a/apps/landing/.oxlintrc.json b/apps/landing/.oxlintrc.json new file mode 100644 index 00000000..91dc201f --- /dev/null +++ b/apps/landing/.oxlintrc.json @@ -0,0 +1,34 @@ +{ + "$schema": "../../node_modules/oxlint/configuration_schema.json", + "extends": [ + "../../tooling/oxlint/oxlint-base.json", + "../../tooling/oxlint/oxlint-react.json" + ], + "categories": { + "correctness": "warn" + }, + "env": { + "builtin": true, + "commonjs": true, + "browser": true, + "es2022": true, + "node": true + }, + "globals": { + "React": "writeable" + }, + "settings": { + "react": { + "version": "detect" + } + }, + "ignorePatterns": [ + "**/*.config.js", + "**/*.config.cjs", + "**/.eslintrc.cjs", + ".next", + "dist", + "build", + "pnpm-lock.yaml" + ] +} diff --git a/apps/landing/package.json b/apps/landing/package.json index d35ef885..ed396b85 100644 --- a/apps/landing/package.json +++ b/apps/landing/package.json @@ -8,8 +8,8 @@ "dev": "vite", "build": "tsc -b && vite build", "preview": "vite preview", - "lint": "eslint .", - "lint:fix": "eslint . --fix", + "lint": "oxlint .", + "lint:fix": "oxlint . --fix", "format": "prettier . --ignore-path ../../.prettierignore", "format:fix": "prettier . --ignore-path ../../.prettierignore --write", "typecheck": "tsc --noEmit" @@ -28,7 +28,6 @@ "tailwindcss-animate": "^1.0.7" }, "devDependencies": { - "@karakeep/eslint-config": "workspace:^0.2.0", "@karakeep/prettier-config": "workspace:^0.1.0", "@karakeep/tailwind-config": "workspace:^0.1.0", "@karakeep/tsconfig": "workspace:^0.1.0", @@ -42,12 +41,5 @@ "vite": "^5.1.0", "vite-plugin-svgr": "^4.3.0" }, - "eslintConfig": { - "root": true, - "extends": [ - "@karakeep/eslint-config/base", - "@karakeep/eslint-config/react" - ] - }, "prettier": "@karakeep/prettier-config" } diff --git a/apps/mcp/.oxlintrc.json b/apps/mcp/.oxlintrc.json new file mode 100644 index 00000000..44a3dcef --- /dev/null +++ b/apps/mcp/.oxlintrc.json @@ -0,0 +1,22 @@ +{ + "$schema": "../../node_modules/oxlint/configuration_schema.json", + "extends": [ + "../../tooling/oxlint/oxlint-base.json" + ], + "categories": { + "correctness": "warn" + }, + "env": { + "builtin": true, + "commonjs": true + }, + "ignorePatterns": [ + "**/*.config.js", + "**/*.config.cjs", + "**/.eslintrc.cjs", + "**/.next", + "**/dist", + "**/build", + "**/pnpm-lock.yaml" + ] +} diff --git a/apps/mcp/package.json b/apps/mcp/package.json index 0e00aec0..bfa9d833 100644 --- a/apps/mcp/package.json +++ b/apps/mcp/package.json @@ -14,7 +14,6 @@ "karakeep-mcp": "dist/index.js" }, "devDependencies": { - "@karakeep/eslint-config": "workspace:^0.2.0", "@karakeep/prettier-config": "workspace:^0.1.0", "@karakeep/tsconfig": "workspace:^0.1.0", "@tsconfig/node22": "^22.0.0", @@ -26,8 +25,8 @@ "scripts": { "build": "vite build && shx chmod +x dist/index.js", "run": "tsx src/index.ts", - "lint": "eslint .", - "lint:fix": "eslint . --fix", + "lint": "oxlint .", + "lint:fix": "oxlint . --fix", "format": "prettier . --ignore-path ../../.prettierignore", "format:fix": "prettier . --write --ignore-path ../../.prettierignore", "typecheck": "tsc --noEmit" @@ -37,12 +36,6 @@ "url": "git+https://github.com/karakeep-app/karakeep.git", "directory": "apps/mcp" }, - "eslintConfig": { - "root": true, - "extends": [ - "@karakeep/eslint-config/base" - ] - }, "prettier": "@karakeep/prettier-config", "dependencies": { "@karakeep/sdk": "workspace:*", diff --git a/apps/mobile/.oxlintrc.json b/apps/mobile/.oxlintrc.json new file mode 100644 index 00000000..dc4ad1e1 --- /dev/null +++ b/apps/mobile/.oxlintrc.json @@ -0,0 +1,39 @@ +{ + "$schema": "../../node_modules/oxlint/configuration_schema.json", + "extends": [ + "../../tooling/oxlint/oxlint-base.json", + "../../tooling/oxlint/oxlint-react.json" + ], + "categories": { + "correctness": "warn" + }, + "env": { + "builtin": true, + "commonjs": true, + "browser": true, + "es2022": true, + "node": true + }, + "globals": { + "React": "writeable" + }, + "settings": { + "react": { + "version": "detect" + } + }, + "ignorePatterns": [ + "**/*.config.js", + "**/*.config.cjs", + "**/.eslintrc.cjs", + "tailwind.config.ts", + ".next", + "dist", + "build", + "pnpm-lock.yaml", + "expo-plugins/**", + "ios/**", + "android/**", + "plugins/**" + ] +} diff --git a/apps/mobile/app/dashboard/bookmarks/new.tsx b/apps/mobile/app/dashboard/bookmarks/new.tsx index e821555a..d24c1597 100644 --- a/apps/mobile/app/dashboard/bookmarks/new.tsx +++ b/apps/mobile/app/dashboard/bookmarks/new.tsx @@ -48,7 +48,7 @@ const NoteEditorPage = () => { throw new Error(`Unsupported URL protocol: ${url.protocol}`); } createBookmark({ type: BookmarkTypes.LINK, url: data }); - } catch (e: unknown) { + } catch { createBookmark({ type: BookmarkTypes.TEXT, text: data }); } }; diff --git a/apps/mobile/components/bookmarks/BookmarkCard.tsx b/apps/mobile/components/bookmarks/BookmarkCard.tsx index 5b118f43..52d39c5c 100644 --- a/apps/mobile/components/bookmarks/BookmarkCard.tsx +++ b/apps/mobile/components/bookmarks/BookmarkCard.tsx @@ -224,7 +224,7 @@ function LinkCard({ } else { imageComp = ( diff --git a/apps/mobile/package.json b/apps/mobile/package.json index 426df353..f60b77a3 100644 --- a/apps/mobile/package.json +++ b/apps/mobile/package.json @@ -10,8 +10,8 @@ "web": "expo start --web", "format": "prettier .", "format:fix": "prettier . --write", - "lint": "eslint .", - "lint:fix": "eslint . --fix", + "lint": "oxlint .", + "lint:fix": "oxlint . --fix", "typecheck": "tsc --noEmit" }, "dependencies": { @@ -61,31 +61,15 @@ }, "devDependencies": { "@babel/core": "~7.26.0", - "@karakeep/eslint-config": "workspace:^0.2.0", "@karakeep/prettier-config": "workspace:^0.1.0", "@karakeep/tailwind-config": "workspace:^0.1.0", "@karakeep/tsconfig": "workspace:^0.1.0", "@types/react": "^18.3.12", "ajv": "latest", - "eslint": "^8.57.0", - "eslint-config-universe": "^12.0.0", "prettier": "^3.4.2", "tailwindcss": "^3.4.1", "typescript": "^5.7.3" }, "private": true, - "eslintConfig": { - "root": true, - "extends": [ - "@karakeep/eslint-config/base", - "@karakeep/eslint-config/react" - ], - "ignorePatterns": [ - "expo-plugins/**", - "ios/**", - "android/**", - "plugins/**" - ] - }, "prettier": "@karakeep/prettier-config" } diff --git a/apps/web/.oxlintrc.json b/apps/web/.oxlintrc.json new file mode 100644 index 00000000..3a2cb742 --- /dev/null +++ b/apps/web/.oxlintrc.json @@ -0,0 +1,35 @@ +{ + "$schema": "../../node_modules/oxlint/configuration_schema.json", + "extends": [ + "../../tooling/oxlint/oxlint-base.json", + "../../tooling/oxlint/oxlint-nextjs.json", + "../../tooling/oxlint/oxlint-react.json" + ], + "categories": { + "correctness": "warn" + }, + "env": { + "builtin": true, + "commonjs": true, + "browser": true, + "es2022": true, + "node": true + }, + "globals": { + "React": "writeable" + }, + "settings": { + "react": { + "version": "detect" + } + }, + "ignorePatterns": [ + "**/*.config.js", + "**/*.config.cjs", + "**/.eslintrc.cjs", + ".next", + "dist", + "build", + "pnpm-lock.yaml" + ] +} diff --git a/apps/web/app/dashboard/cleanups/page.tsx b/apps/web/app/dashboard/cleanups/page.tsx index 1974d2a7..8da6e75b 100644 --- a/apps/web/app/dashboard/cleanups/page.tsx +++ b/apps/web/app/dashboard/cleanups/page.tsx @@ -4,6 +4,7 @@ import { useTranslation } from "@/lib/i18n/server"; import { Paintbrush, Tags } from "lucide-react"; export default async function Cleanups() { + // oxlint-disable-next-line rules-of-hooks const { t } = await useTranslation(); return ( diff --git a/apps/web/app/dashboard/highlights/page.tsx b/apps/web/app/dashboard/highlights/page.tsx index 646b1c41..1410d1fd 100644 --- a/apps/web/app/dashboard/highlights/page.tsx +++ b/apps/web/app/dashboard/highlights/page.tsx @@ -5,6 +5,7 @@ import { api } from "@/server/api/client"; import { Highlighter } from "lucide-react"; export default async function HighlightsPage() { + // oxlint-disable-next-line rules-of-hooks const { t } = await useTranslation(); const highlights = await api.highlights.getAll({}); return ( diff --git a/apps/web/app/dashboard/lists/page.tsx b/apps/web/app/dashboard/lists/page.tsx index 36eb8b7a..1c28073d 100644 --- a/apps/web/app/dashboard/lists/page.tsx +++ b/apps/web/app/dashboard/lists/page.tsx @@ -4,6 +4,7 @@ import { useTranslation } from "@/lib/i18n/server"; import { api } from "@/server/api/client"; export default async function ListsPage() { + // oxlint-disable-next-line rules-of-hooks const { t } = await useTranslation(); const lists = await api.lists.list(); diff --git a/apps/web/app/dashboard/tags/page.tsx b/apps/web/app/dashboard/tags/page.tsx index 1639e4c5..9108d6ba 100644 --- a/apps/web/app/dashboard/tags/page.tsx +++ b/apps/web/app/dashboard/tags/page.tsx @@ -4,6 +4,7 @@ import { useTranslation } from "@/lib/i18n/server"; import { api } from "@/server/api/client"; export default async function TagsPage() { + // oxlint-disable-next-line rules-of-hooks const { t } = await useTranslation(); const allTags = (await api.tags.list()).tags; diff --git a/apps/web/components/dashboard/bookmarks/EditorCard.tsx b/apps/web/components/dashboard/bookmarks/EditorCard.tsx index 75745bad..a5966845 100644 --- a/apps/web/components/dashboard/bookmarks/EditorCard.tsx +++ b/apps/web/components/dashboard/bookmarks/EditorCard.tsx @@ -132,7 +132,7 @@ export default function EditorCard({ className }: { className?: string }) { if (!text.length) return; try { tryToImportUrls(text); - } catch (e) { + } catch { // Not a URL mutate({ type: BookmarkTypes.TEXT, text }); } diff --git a/apps/web/components/dashboard/lists/EditListModal.tsx b/apps/web/components/dashboard/lists/EditListModal.tsx index 7a750c33..3b35e7d4 100644 --- a/apps/web/components/dashboard/lists/EditListModal.tsx +++ b/apps/web/components/dashboard/lists/EditListModal.tsx @@ -192,7 +192,11 @@ export function EditListModal({ (value: z.infer) => { value.parentId = value.parentId === "" ? null : value.parentId; value.query = value.type === "smart" ? value.query : undefined; - isEdit ? editList({ ...value, listId: list.id }) : createList(value); + if (isEdit) { + editList({ ...value, listId: list.id }); + } else { + createList(value); + } }, ); diff --git a/apps/web/components/dashboard/preview/HighlightsBox.tsx b/apps/web/components/dashboard/preview/HighlightsBox.tsx index af065a9d..4da22d04 100644 --- a/apps/web/components/dashboard/preview/HighlightsBox.tsx +++ b/apps/web/components/dashboard/preview/HighlightsBox.tsx @@ -1,3 +1,4 @@ +import { Fragment } from "react"; import { Collapsible, CollapsibleContent, @@ -28,10 +29,10 @@ export default function HighlightsBox({ bookmarkId }: { bookmarkId: string }) { {highlights.highlights.map((highlight) => ( - <> - + + - + ))} diff --git a/apps/web/components/settings/ApiKeySettings.tsx b/apps/web/components/settings/ApiKeySettings.tsx index 8f07e5a4..2b9d19d1 100644 --- a/apps/web/components/settings/ApiKeySettings.tsx +++ b/apps/web/components/settings/ApiKeySettings.tsx @@ -13,6 +13,7 @@ import AddApiKey from "./AddApiKey"; import DeleteApiKey from "./DeleteApiKey"; export default async function ApiKeys() { + // oxlint-disable-next-line rules-of-hooks const { t } = await useTranslation(); const keys = await api.apiKeys.list(); return ( diff --git a/apps/web/components/settings/ImportExport.tsx b/apps/web/components/settings/ImportExport.tsx index 35c2b88f..3dde577b 100644 --- a/apps/web/components/settings/ImportExport.tsx +++ b/apps/web/components/settings/ImportExport.tsx @@ -282,7 +282,7 @@ export function ImportExportRow() { }; }); return { status: "fulfilled" as const, value: created }; - } catch (e) { + } catch { setImportProgress((prev) => { const newDone = (prev?.done ?? 0) + 1; return { diff --git a/apps/web/components/settings/UserDetails.tsx b/apps/web/components/settings/UserDetails.tsx index b86129c8..5b99c0ea 100644 --- a/apps/web/components/settings/UserDetails.tsx +++ b/apps/web/components/settings/UserDetails.tsx @@ -7,6 +7,7 @@ import { Card, CardContent, CardHeader, CardTitle } from "../ui/card"; import { Label } from "../ui/label"; export default async function UserDetails() { + // oxlint-disable-next-line rules-of-hooks const { t } = await useTranslation(); const whoami = await api.users.whoami(); diff --git a/apps/web/components/shared/sidebar/MobileSidebar.tsx b/apps/web/components/shared/sidebar/MobileSidebar.tsx index 15285a9e..c512a981 100644 --- a/apps/web/components/shared/sidebar/MobileSidebar.tsx +++ b/apps/web/components/shared/sidebar/MobileSidebar.tsx @@ -9,6 +9,7 @@ export default async function MobileSidebar({ }: { items: (t: TFunction) => TSidebarItem[]; }) { + // oxlint-disable-next-line rules-of-hooks const { t } = await useTranslation(); return (