From abe6a8bfca21e0a5795cd41cb0d4a9ae6eb4c86a Mon Sep 17 00:00:00 2001 From: Leonardo Montini Date: Wed, 13 Aug 2025 14:15:16 +0200 Subject: [PATCH 1/2] chore: setup router eslint plugin --- .eslintrc | 2 +- package.json | 5 +- pnpm-lock.yaml | 153 ++++++++++++++++++++++++++++++++++++------ src/routes/__root.tsx | 24 +++---- 4 files changed, 149 insertions(+), 35 deletions(-) diff --git a/.eslintrc b/.eslintrc index af7fa28f..402a51d8 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,5 +1,5 @@ { - "extends": ["react-app"], + "extends": ["react-app", "plugin:@tanstack/eslint-plugin-router/recommended"], "parser": "@typescript-eslint/parser", "plugins": ["react-hooks"] } diff --git a/package.json b/package.json index bda81f9e..2df45386 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,8 @@ "dev:backend": "convex dev --tail-logs", "build": "vite build", "start": "vite start", - "lint": "prettier --check '**/*' --ignore-unknown && eslint --ext .ts,.tsx ./src", - "format": "prettier --write '**/*' --ignore-unknown", + "lint": "prettier --check 'src/**/*' --ignore-unknown && eslint --ext .ts,.tsx ./src", + "format": "prettier --write 'src/**/*' --ignore-unknown", "linkAll": "node scripts/link.js" }, "dependencies": { @@ -83,6 +83,7 @@ "@content-collections/core": "^0.8.2", "@content-collections/vite": "^0.2.4", "@shikijs/transformers": "^1.10.3", + "@tanstack/eslint-plugin-router": "^1.131.2", "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", "@types/remove-markdown": "^0.3.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c5073471..81c712e6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -201,6 +201,9 @@ importers: '@shikijs/transformers': specifier: ^1.10.3 version: 1.10.3 + '@tanstack/eslint-plugin-router': + specifier: ^1.131.2 + version: 1.131.2(eslint@8.57.0)(typescript@5.6.3) '@types/react': specifier: ^18.3.12 version: 18.3.12 @@ -2003,6 +2006,12 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + '@eslint-community/eslint-utils@4.7.0': + resolution: {integrity: sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + '@eslint-community/regexpp@4.10.0': resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} @@ -3421,6 +3430,11 @@ packages: peerDependencies: vite: '>=6.0.0' + '@tanstack/eslint-plugin-router@1.131.2': + resolution: {integrity: sha512-f0x2+MqVnfo+0z+HhAnJYoFbRRGcuc9W4p662Qsgi/z6KCFj1/HCQdorcZ3C8yjYAOsLd8zJivY1YnPbcJE+Yg==} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + '@tanstack/history@1.131.2': resolution: {integrity: sha512-cs1WKawpXIe+vSTeiZUuSBy8JFjEuDgdMKZFRLKwQysKo8y2q6Q1HvS74Yw+m5IhOW1nTZooa6rlgdfXcgFAaw==} engines: {node: '>=12'} @@ -3841,6 +3855,12 @@ packages: peerDependencies: typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/project-service@8.39.1': + resolution: {integrity: sha512-8fZxek3ONTwBu9ptw5nCKqZOSkXshZB7uAxuFF0J/wTMkKydjXCzqqga7MlFMpHi9DoG4BadhmTkITBcg8Aybw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/scope-manager@5.62.0': resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3849,12 +3869,22 @@ packages: resolution: {integrity: sha512-Qh976RbQM/fYtjx9hs4XkayYujB/aPwglw2choHmf3zBjB4qOywWSdt9+KLRdHubGcoSwBnXUH2sR3hkyaERRg==} engines: {node: ^16.0.0 || >=18.0.0} + '@typescript-eslint/scope-manager@8.39.1': + resolution: {integrity: sha512-RkBKGBrjgskFGWuyUGz/EtD8AF/GW49S21J8dvMzpJitOF1slLEbbHnNEtAHtnDAnx8qDEdRrULRnWVx27wGBw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/tsconfig-utils@8.39.0': resolution: {integrity: sha512-Fd3/QjmFV2sKmvv3Mrj8r6N8CryYiCS8Wdb/6/rgOXAWGcFuc+VkQuG28uk/4kVNVZBQuuDHEDUpo/pQ32zsIQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/tsconfig-utils@8.39.1': + resolution: {integrity: sha512-ePUPGVtTMR8XMU2Hee8kD0Pu4NDE1CN9Q1sxGSGd/mbOtGZDM7pnhXNJnzW63zk/q+Z54zVzj44HtwXln5CvHA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/type-utils@5.62.0': resolution: {integrity: sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3877,6 +3907,10 @@ packages: resolution: {integrity: sha512-ArDdaOllnCj3yn/lzKn9s0pBQYmmyme/v1HbGIGB0GB/knFI3fWMHloC+oYTJW46tVbYnGKTMDK4ah1sC2v0Kg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/types@8.39.1': + resolution: {integrity: sha512-7sPDKQQp+S11laqTrhHqeAbsCfMkwJMrV7oTDvtDds4mEofJYir414bYKUEb8YPUm9QL3U+8f6L6YExSoAGdQw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/typescript-estree@5.62.0': resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3901,12 +3935,25 @@ packages: peerDependencies: typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/typescript-estree@8.39.1': + resolution: {integrity: sha512-EKkpcPuIux48dddVDXyQBlKdeTPMmALqBUbEk38McWv0qVEZwOpVJBi7ugK5qVNgeuYjGNQxrrnoM/5+TI/BPw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/utils@5.62.0': resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + '@typescript-eslint/utils@8.39.1': + resolution: {integrity: sha512-VF5tZ2XnUSTuiqZFXCZfZs1cgkdd3O/sSYmdo2EpSyDlC86UM/8YytTmKnehOW3TGAlivqTDT6bS87B/GQ/jyg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/visitor-keys@5.62.0': resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3919,6 +3966,10 @@ packages: resolution: {integrity: sha512-ldgiJ+VAhQCfIjeOgu8Kj5nSxds0ktPOSO9p4+0VDH2R2pLvQraaM5Oen2d7NxzMCm+Sn/vJT+mv2H5u6b/3fA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/visitor-keys@8.39.1': + resolution: {integrity: sha512-W8FQi6kEh2e8zVhQ0eeRnxdvIoOkAp/CPAahcNio6nO9dsIwb9b34z90KOlheoyuVf6LSOEdjlkxSkapNEc+4A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@ungap/structured-clone@1.2.0': resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} @@ -4309,9 +4360,6 @@ packages: brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - brace-expansion@2.0.2: resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} @@ -8587,7 +8635,7 @@ snapshots: '@babel/core': 7.26.9 '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-plugin-utils': 7.27.1 - debug: 4.4.0 + debug: 4.4.1 lodash.debounce: 4.0.8 resolve: 1.22.10 transitivePeerDependencies: @@ -8598,7 +8646,7 @@ snapshots: '@babel/core': 7.26.9 '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-plugin-utils': 7.27.1 - debug: 4.4.0 + debug: 4.4.1 lodash.debounce: 4.0.8 resolve: 1.22.10 transitivePeerDependencies: @@ -9502,7 +9550,7 @@ snapshots: '@babel/parser': 7.26.9 '@babel/template': 7.27.2 '@babel/types': 7.28.0 - debug: 4.4.0 + debug: 4.4.1 globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -9515,7 +9563,7 @@ snapshots: '@babel/parser': 7.28.0 '@babel/template': 7.27.2 '@babel/types': 7.28.0 - debug: 4.4.0 + debug: 4.4.1 transitivePeerDependencies: - supports-color @@ -10048,6 +10096,11 @@ snapshots: eslint: 8.57.0 eslint-visitor-keys: 3.4.3 + '@eslint-community/eslint-utils@4.7.0(eslint@8.57.0)': + dependencies: + eslint: 8.57.0 + eslint-visitor-keys: 3.4.3 + '@eslint-community/regexpp@4.10.0': {} '@eslint/eslintrc@2.1.4': @@ -11511,6 +11564,14 @@ snapshots: transitivePeerDependencies: - supports-color + '@tanstack/eslint-plugin-router@1.131.2(eslint@8.57.0)(typescript@5.6.3)': + dependencies: + '@typescript-eslint/utils': 8.39.1(eslint@8.57.0)(typescript@5.6.3) + eslint: 8.57.0 + transitivePeerDependencies: + - supports-color + - typescript + '@tanstack/history@1.131.2': {} '@tanstack/pacer@0.7.0': {} @@ -12143,6 +12204,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/project-service@8.39.1(typescript@5.6.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.39.1(typescript@5.6.3) + '@typescript-eslint/types': 8.39.1 + debug: 4.4.1 + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/scope-manager@5.62.0': dependencies: '@typescript-eslint/types': 5.62.0 @@ -12153,15 +12223,24 @@ snapshots: '@typescript-eslint/types': 7.2.0 '@typescript-eslint/visitor-keys': 7.2.0 + '@typescript-eslint/scope-manager@8.39.1': + dependencies: + '@typescript-eslint/types': 8.39.1 + '@typescript-eslint/visitor-keys': 8.39.1 + '@typescript-eslint/tsconfig-utils@8.39.0(typescript@5.9.2)': dependencies: typescript: 5.9.2 + '@typescript-eslint/tsconfig-utils@8.39.1(typescript@5.6.3)': + dependencies: + typescript: 5.6.3 + '@typescript-eslint/type-utils@5.62.0(eslint@8.57.0)(typescript@5.6.3)': dependencies: '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.6.3) '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.6.3) - debug: 4.4.0 + debug: 4.4.1 eslint: 8.57.0 tsutils: 3.21.0(typescript@5.6.3) optionalDependencies: @@ -12175,14 +12254,16 @@ snapshots: '@typescript-eslint/types@8.39.0': {} + '@typescript-eslint/types@8.39.1': {} + '@typescript-eslint/typescript-estree@5.62.0(typescript@5.6.3)': dependencies: '@typescript-eslint/types': 5.62.0 '@typescript-eslint/visitor-keys': 5.62.0 - debug: 4.4.0 + debug: 4.4.1 globby: 11.1.0 is-glob: 4.0.3 - semver: 7.6.3 + semver: 7.7.2 tsutils: 3.21.0(typescript@5.6.3) optionalDependencies: typescript: 5.6.3 @@ -12220,6 +12301,22 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/typescript-estree@8.39.1(typescript@5.6.3)': + dependencies: + '@typescript-eslint/project-service': 8.39.1(typescript@5.6.3) + '@typescript-eslint/tsconfig-utils': 8.39.1(typescript@5.6.3) + '@typescript-eslint/types': 8.39.1 + '@typescript-eslint/visitor-keys': 8.39.1 + debug: 4.4.1 + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.2 + ts-api-utils: 2.1.0(typescript@5.6.3) + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/utils@5.62.0(eslint@8.57.0)(typescript@5.6.3)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) @@ -12235,6 +12332,17 @@ snapshots: - supports-color - typescript + '@typescript-eslint/utils@8.39.1(eslint@8.57.0)(typescript@5.6.3)': + dependencies: + '@eslint-community/eslint-utils': 4.7.0(eslint@8.57.0) + '@typescript-eslint/scope-manager': 8.39.1 + '@typescript-eslint/types': 8.39.1 + '@typescript-eslint/typescript-estree': 8.39.1(typescript@5.6.3) + eslint: 8.57.0 + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/visitor-keys@5.62.0': dependencies: '@typescript-eslint/types': 5.62.0 @@ -12250,6 +12358,11 @@ snapshots: '@typescript-eslint/types': 8.39.0 eslint-visitor-keys: 4.2.1 + '@typescript-eslint/visitor-keys@8.39.1': + dependencies: + '@typescript-eslint/types': 8.39.1 + eslint-visitor-keys: 4.2.1 + '@ungap/structured-clone@1.2.0': {} '@vercel/analytics@1.2.2(react@19.0.0)': @@ -12448,7 +12561,7 @@ snapshots: agent-base@6.0.2: dependencies: - debug: 4.4.0 + debug: 4.4.1 transitivePeerDependencies: - supports-color @@ -12773,10 +12886,6 @@ snapshots: balanced-match: 1.0.2 concat-map: 0.0.1 - brace-expansion@2.0.1: - dependencies: - balanced-match: 1.0.2 - brace-expansion@2.0.2: dependencies: balanced-match: 1.0.2 @@ -14497,7 +14606,7 @@ snapshots: https-proxy-agent@5.0.1: dependencies: agent-base: 6.0.2 - debug: 4.4.0 + debug: 4.4.1 transitivePeerDependencies: - supports-color @@ -15133,7 +15242,7 @@ snapshots: micromark@2.11.4: dependencies: - debug: 4.4.0 + debug: 4.4.1 parse-entities: 2.0.0 transitivePeerDependencies: - supports-color @@ -15173,15 +15282,15 @@ snapshots: minimatch@8.0.4: dependencies: - brace-expansion: 2.0.1 + brace-expansion: 2.0.2 minimatch@9.0.3: dependencies: - brace-expansion: 2.0.1 + brace-expansion: 2.0.2 minimatch@9.0.5: dependencies: - brace-expansion: 2.0.1 + brace-expansion: 2.0.2 minimist@1.2.8: {} @@ -16616,6 +16725,10 @@ snapshots: dependencies: typescript: 5.6.3 + ts-api-utils@2.1.0(typescript@5.6.3): + dependencies: + typescript: 5.6.3 + ts-api-utils@2.1.0(typescript@5.9.2): dependencies: typescript: 5.9.2 diff --git a/src/routes/__root.tsx b/src/routes/__root.tsx index 8790f65c..9a5e5392 100644 --- a/src/routes/__root.tsx +++ b/src/routes/__root.tsx @@ -27,6 +27,18 @@ import { ThemeProvider } from '~/components/ThemeProvider' export const Route = createRootRouteWithContext<{ queryClient: QueryClient }>()({ + beforeLoad: async (ctx) => { + if ( + ctx.location.href.match(/\/docs\/(react|vue|angular|svelte|solid)\//gm) + ) { + throw redirect({ + href: ctx.location.href.replace( + /\/docs\/(react|vue|angular|svelte|solid)\//gm, + '/docs/framework/$1/' + ), + }) + } + }, head: () => ({ meta: [ { @@ -112,18 +124,6 @@ export const Route = createRootRouteWithContext<{ }, ], }), - beforeLoad: async (ctx) => { - if ( - ctx.location.href.match(/\/docs\/(react|vue|angular|svelte|solid)\//gm) - ) { - throw redirect({ - href: ctx.location.href.replace( - /\/docs\/(react|vue|angular|svelte|solid)\//gm, - '/docs/framework/$1/' - ), - }) - } - }, staleTime: Infinity, errorComponent: (props) => { return ( From e5b1795daebd57edef427f5e3a14f6ab9b2374e6 Mon Sep 17 00:00:00 2001 From: Leonardo Montini Date: Sat, 23 Aug 2025 11:38:36 +0200 Subject: [PATCH 2/2] chore: prettier & lint --- src/routes/__root.tsx | 36 +++++++++---------- src/routes/_libraries/form.$version.index.tsx | 2 +- .../_libraries/pacer.$version.index.tsx | 2 +- src/styles/app.css | 2 +- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/routes/__root.tsx b/src/routes/__root.tsx index 21bb1ae4..849aa486 100644 --- a/src/routes/__root.tsx +++ b/src/routes/__root.tsx @@ -38,6 +38,24 @@ export const Route = createRootRouteWithContext<{ convexQueryClient: ConvexQueryClient ensureUser: () => Promise }>()({ + beforeLoad: async (ctx) => { + if ( + ctx.location.href.match(/\/docs\/(react|vue|angular|svelte|solid)\//gm) + ) { + throw redirect({ + href: ctx.location.href.replace( + /\/docs\/(react|vue|angular|svelte|solid)\//gm, + '/docs/framework/$1/' + ), + }) + } + + // // During SSR only (the only time serverHttpClient exists), + // // set the auth token for Convex to make HTTP queries with. + // if (token) { + // ctx.context.convexQueryClient.serverHttpClient?.setAuth(token) + // } + }, head: () => ({ meta: [ { @@ -123,24 +141,6 @@ export const Route = createRootRouteWithContext<{ }, ], }), - beforeLoad: async (ctx) => { - if ( - ctx.location.href.match(/\/docs\/(react|vue|angular|svelte|solid)\//gm) - ) { - throw redirect({ - href: ctx.location.href.replace( - /\/docs\/(react|vue|angular|svelte|solid)\//gm, - '/docs/framework/$1/' - ), - }) - } - - // // During SSR only (the only time serverHttpClient exists), - // // set the auth token for Convex to make HTTP queries with. - // if (token) { - // ctx.context.convexQueryClient.serverHttpClient?.setAuth(token) - // } - }, staleTime: Infinity, errorComponent: (props) => { return ( diff --git a/src/routes/_libraries/form.$version.index.tsx b/src/routes/_libraries/form.$version.index.tsx index cc21f381..1da879df 100644 --- a/src/routes/_libraries/form.$version.index.tsx +++ b/src/routes/_libraries/form.$version.index.tsx @@ -53,7 +53,7 @@ export default function FormVersionIndex() { className: 'bg-yellow-400 text-black', }} /> - +
diff --git a/src/routes/_libraries/pacer.$version.index.tsx b/src/routes/_libraries/pacer.$version.index.tsx index 90a9f175..aa322e32 100644 --- a/src/routes/_libraries/pacer.$version.index.tsx +++ b/src/routes/_libraries/pacer.$version.index.tsx @@ -49,7 +49,7 @@ export default function PacerVersionIndex() {
- + diff --git a/src/styles/app.css b/src/styles/app.css index f10d1b11..fa7d305e 100644 --- a/src/styles/app.css +++ b/src/styles/app.css @@ -735,4 +735,4 @@ mark { font-style: italic; font-weight: 900; src: url('/fonts/inter-v19-latin-900italic.woff2') format('woff2'); -} \ No newline at end of file +}