From b4e31547ae3251f6e7d2854a8bd6a576cabff034 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 19 Jul 2025 22:37:34 +0000 Subject: [PATCH 1/3] Initial plan From 35d858595f20f2f8b84c6e55701fbfacbaee4a44 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 19 Jul 2025 22:44:40 +0000 Subject: [PATCH 2/3] Initial progress: Plan for TanStack Router example Co-authored-by: KevinVandy <28243511+KevinVandy@users.noreply.github.com> --- package-lock.json | 154 ++++++++++++++++++++++++++++++++ pnpm-lock.yaml | 219 ++++++++++++++++++++++++++++++---------------- 2 files changed, 299 insertions(+), 74 deletions(-) create mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..9176bfd --- /dev/null +++ b/package-lock.json @@ -0,0 +1,154 @@ +{ + "name": "@react-data-fetching/react-data-fetching", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@react-data-fetching/react-data-fetching", + "dependencies": { + "@faker-js/faker": "^9.9.0" + }, + "devDependencies": { + "prettier": "^3.6.2", + "turbo": "2.5.5" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@faker-js/faker": { + "version": "9.9.0", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-9.9.0.tgz", + "integrity": "sha512-OEl393iCOoo/z8bMezRlJu+GlRGlsKbUAN7jKB6LhnKoqKve5DXRpalbItIIcwnCjs1k/FOPjFzcA6Qn+H+YbA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/fakerjs" + } + ], + "license": "MIT", + "engines": { + "node": ">=18.0.0", + "npm": ">=9.0.0" + } + }, + "node_modules/prettier": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/turbo": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/turbo/-/turbo-2.5.5.tgz", + "integrity": "sha512-eZ7wI6KjtT1eBqCnh2JPXWNUAxtoxxfi6VdBdZFvil0ychCOTxbm7YLRBi1JSt7U3c+u3CLxpoPxLdvr/Npr3A==", + "dev": true, + "license": "MIT", + "bin": { + "turbo": "bin/turbo" + }, + "optionalDependencies": { + "turbo-darwin-64": "2.5.5", + "turbo-darwin-arm64": "2.5.5", + "turbo-linux-64": "2.5.5", + "turbo-linux-arm64": "2.5.5", + "turbo-windows-64": "2.5.5", + "turbo-windows-arm64": "2.5.5" + } + }, + "node_modules/turbo-darwin-64": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-2.5.5.tgz", + "integrity": "sha512-RYnTz49u4F5tDD2SUwwtlynABNBAfbyT2uU/brJcyh5k6lDLyNfYKdKmqd3K2ls4AaiALWrFKVSBsiVwhdFNzQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/turbo-darwin-arm64": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-2.5.5.tgz", + "integrity": "sha512-Tk+ZeSNdBobZiMw9aFypQt0DlLsWSFWu1ymqsAdJLuPoAH05qCfYtRxE1pJuYHcJB5pqI+/HOxtJoQ40726Btw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/turbo-linux-64": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-2.5.5.tgz", + "integrity": "sha512-2/XvMGykD7VgsvWesZZYIIVXMlgBcQy+ZAryjugoTcvJv8TZzSU/B1nShcA7IAjZ0q7OsZ45uP2cOb8EgKT30w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/turbo-linux-arm64": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-2.5.5.tgz", + "integrity": "sha512-DW+8CjCjybu0d7TFm9dovTTVg1VRnlkZ1rceO4zqsaLrit3DgHnN4to4uwyuf9s2V/BwS3IYcRy+HG9BL596Iw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/turbo-windows-64": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-2.5.5.tgz", + "integrity": "sha512-q5p1BOy8ChtSZfULuF1BhFMYIx6bevXu4fJ+TE/hyNfyHJIfjl90Z6jWdqAlyaFLmn99X/uw+7d6T/Y/dr5JwQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/turbo-windows-arm64": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/turbo-windows-arm64/-/turbo-windows-arm64-2.5.5.tgz", + "integrity": "sha512-AXbF1KmpHUq3PKQwddMGoKMYhHsy5t1YBQO8HZ04HLMR0rWv9adYlQ8kaeQJTko1Ay1anOBFTqaxfVOOsu7+1Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + } + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b970144..4674705 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -223,7 +223,7 @@ importers: specifier: ^7.0.5 version: 7.0.5(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(sugarss@5.0.0)(terser@5.31.2)(yaml@2.4.5) - apps/1-spa/1-4-vite-reactquery-refactor: + apps/1-spa/1-4-vite-reactquery-hooks: dependencies: '@mantine/core': specifier: 8.1.3 @@ -242,7 +242,7 @@ importers: version: 5.83.0(@tanstack/react-query@5.83.0(react@19.1.0))(react@19.1.0) mantine-react-table: specifier: ^2.0.0-beta.6 - version: 2.0.0-beta.6(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/dates@7.11.2(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(dayjs@1.11.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(@tabler/icons-react@3.34.0(react@19.1.0))(clsx@2.1.1)(dayjs@1.11.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 2.0.0-beta.8(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/dates@7.11.2(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(dayjs@1.11.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(@tabler/icons-react@3.34.0(react@19.1.0))(clsx@2.1.1)(dayjs@1.11.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) react: specifier: ^19.1.0 version: 19.1.0 @@ -296,7 +296,80 @@ importers: specifier: ^7.0.5 version: 7.0.5(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(sugarss@5.0.0)(terser@5.31.2)(yaml@2.4.5) - apps/1-spa/1-5-astro-react-spa: + apps/1-spa/1-5-vite-reactquery-query-options: + dependencies: + '@mantine/core': + specifier: 8.1.3 + version: 8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@mantine/hooks': + specifier: 8.1.3 + version: 8.1.3(react@19.1.0) + '@tabler/icons-react': + specifier: 3.34.0 + version: 3.34.0(react@19.1.0) + '@tanstack/react-query': + specifier: ^5.83.0 + version: 5.83.0(react@19.1.0) + '@tanstack/react-query-devtools': + specifier: ^5.83.0 + version: 5.83.0(@tanstack/react-query@5.83.0(react@19.1.0))(react@19.1.0) + mantine-react-table: + specifier: ^2.0.0-beta.6 + version: 2.0.0-beta.8(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/dates@7.11.2(@mantine/core@8.1.3(@mantine/hooks@8.1.3(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(dayjs@1.11.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.1.3(react@19.1.0))(@tabler/icons-react@3.34.0(react@19.1.0))(clsx@2.1.1)(dayjs@1.11.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + react: + specifier: ^19.1.0 + version: 19.1.0 + react-dom: + specifier: ^19.1.0 + version: 19.1.0(react@19.1.0) + react-error-boundary: + specifier: ^6.0.0 + version: 6.0.0(react@19.1.0) + react-router-dom: + specifier: ^7.7.0 + version: 7.7.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + devDependencies: + '@types/react': + specifier: ^19.1.8 + version: 19.1.8 + '@types/react-dom': + specifier: ^19.1.6 + version: 19.1.6(@types/react@19.1.8) + '@typescript-eslint/eslint-plugin': + specifier: ^8.37.0 + version: 8.37.0(@typescript-eslint/parser@8.37.0(eslint@9.31.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.31.0(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/parser': + specifier: ^8.37.0 + version: 8.37.0(eslint@9.31.0(jiti@2.4.2))(typescript@5.8.3) + '@vitejs/plugin-react': + specifier: ^4.7.0 + version: 4.7.0(vite@7.0.5(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(sugarss@5.0.0(postcss@8.5.6))(terser@5.31.2)(yaml@2.4.5)) + eslint: + specifier: ^9.31.0 + version: 9.31.0(jiti@2.4.2) + eslint-plugin-react-hooks: + specifier: ^5.2.0 + version: 5.2.0(eslint@9.31.0(jiti@2.4.2)) + eslint-plugin-react-refresh: + specifier: ^0.4.20 + version: 0.4.20(eslint@9.31.0(jiti@2.4.2)) + postcss: + specifier: ^8.5.6 + version: 8.5.6 + postcss-preset-mantine: + specifier: 1.18.0 + version: 1.18.0(postcss@8.5.6) + postcss-simple-vars: + specifier: ^7.0.1 + version: 7.0.1(postcss@8.5.6) + typescript: + specifier: ^5.8.3 + version: 5.8.3 + vite: + specifier: ^7.0.5 + version: 7.0.5(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(sugarss@5.0.0)(terser@5.31.2)(yaml@2.4.5) + + apps/1-spa/1-7-astro-react-spa: dependencies: '@astrojs/react': specifier: ^4.3.0 @@ -312,7 +385,7 @@ importers: version: 3.34.0(react@19.1.0) '@tailwindcss/vite': specifier: ^4.1.11 - version: 4.1.11(vite@6.3.5(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(sugarss@5.0.0(postcss@8.5.6))(terser@5.31.2)(yaml@2.4.5)) + version: 4.1.11(vite@7.0.5(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(sugarss@5.0.0)(terser@5.31.2)(yaml@2.4.5)) '@tanstack/react-query': specifier: ^5.83.0 version: 5.83.0(react@19.1.0) @@ -410,10 +483,10 @@ importers: dependencies: '@astrojs/vercel': specifier: ^8.2.2 - version: 8.2.2(@remix-run/react@2.16.8(react@19.1.0)(typescript@5.8.3))(@sveltejs/kit@2.25.1(svelte@5.36.8)(vite@7.0.5(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(sugarss@5.0.0)(terser@5.31.2)(yaml@2.4.5)))(astro@5.12.0(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.40.2)(sugarss@5.0.0)(terser@5.31.2)(typescript@5.8.3)(yaml@2.4.5))(next@15.4.2(react@19.1.0))(react@19.1.0)(rollup@4.40.2)(svelte@5.36.8) + version: 8.2.2(@remix-run/react@2.16.8(react@19.1.0)(typescript@5.8.3))(@sveltejs/kit@2.25.1(svelte@5.36.8)(vite@6.3.5(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(sugarss@5.0.0)(terser@5.31.2)(yaml@2.4.5)))(astro@5.12.0(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.40.2)(sugarss@5.0.0)(terser@5.31.2)(typescript@5.8.3)(yaml@2.4.5))(next@15.4.2(react@19.1.0))(react@19.1.0)(rollup@4.40.2)(svelte@5.36.8) '@tailwindcss/vite': specifier: ^4.1.11 - version: 4.1.11(vite@7.0.5(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(sugarss@5.0.0(postcss@8.5.6))(terser@5.31.2)(yaml@2.4.5)) + version: 4.1.11(vite@6.3.5(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(sugarss@5.0.0)(terser@5.31.2)(yaml@2.4.5)) astro: specifier: ^5.12.0 version: 5.12.0(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.40.2)(sugarss@5.0.0)(terser@5.31.2)(typescript@5.8.3)(yaml@2.4.5) @@ -437,7 +510,7 @@ importers: version: 3.34.0(react@19.1.0) '@tailwindcss/vite': specifier: ^4.1.11 - version: 4.1.11(vite@7.0.5(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(sugarss@5.0.0(postcss@8.5.6))(terser@5.31.2)(yaml@2.4.5)) + version: 4.1.11(vite@6.3.5(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(sugarss@5.0.0)(terser@5.31.2)(yaml@2.4.5)) astro: specifier: ^5.12.0 version: 5.12.0(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.40.2)(sugarss@5.0.0)(terser@5.31.2)(typescript@5.8.3)(yaml@2.4.5) @@ -650,7 +723,7 @@ importers: dependencies: '@tailwindcss/vite': specifier: ^4.1.11 - version: 4.1.11(vite@7.0.5(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(sugarss@5.0.0(postcss@8.5.6))(terser@5.31.2)(yaml@2.4.5)) + version: 4.1.11(vite@7.0.5(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(sugarss@5.0.0)(terser@5.31.2)(yaml@2.4.5)) astro: specifier: ^5.12.0 version: 5.12.0(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.40.2)(sugarss@5.0.0)(terser@5.31.2)(typescript@5.8.3)(yaml@2.4.5) @@ -827,7 +900,7 @@ importers: version: 8.2.2(@remix-run/react@2.16.8(react@19.1.0)(typescript@5.8.3))(@sveltejs/kit@2.25.1(svelte@5.36.8)(vite@7.0.5(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(sugarss@5.0.0)(terser@5.31.2)(yaml@2.4.5)))(astro@5.12.0(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.40.2)(sugarss@5.0.0)(terser@5.31.2)(typescript@5.8.3)(yaml@2.4.5))(next@15.4.2(react@19.1.0))(react@19.1.0)(rollup@4.40.2)(svelte@5.36.8) '@tailwindcss/vite': specifier: ^4.1.11 - version: 4.1.11(vite@7.0.5(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(sugarss@5.0.0(postcss@8.5.6))(terser@5.31.2)(yaml@2.4.5)) + version: 4.1.11(vite@7.0.5(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(sugarss@5.0.0)(terser@5.31.2)(yaml@2.4.5)) astro: specifier: ^5.12.0 version: 5.12.0(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.40.2)(sugarss@5.0.0)(terser@5.31.2)(typescript@5.8.3)(yaml@2.4.5) @@ -1566,15 +1639,9 @@ packages: resolution: {integrity: sha512-OEl393iCOoo/z8bMezRlJu+GlRGlsKbUAN7jKB6LhnKoqKve5DXRpalbItIIcwnCjs1k/FOPjFzcA6Qn+H+YbA==} engines: {node: '>=18.0.0', npm: '>=9.0.0'} - '@floating-ui/core@1.6.0': - resolution: {integrity: sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==} - '@floating-ui/core@1.7.2': resolution: {integrity: sha512-wNB5ooIKHQc+Kui96jE/n69rHFWAVoxn5CAzL1Xdd8FG03cgY3MLO+GF9U3W737fYDSgPWA6MReKhBQBop6Pcw==} - '@floating-ui/dom@1.6.13': - resolution: {integrity: sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==} - '@floating-ui/dom@1.7.2': resolution: {integrity: sha512-7cfaOQuCS27HD7DX+6ib2OrnW+b4ZBwDNnCcT0uTyidcmyWb03FnQqJybDBoCnpdxwBSfA94UAYlRCt7mV+TbA==} @@ -1593,9 +1660,6 @@ packages: '@floating-ui/utils@0.2.10': resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==} - '@floating-ui/utils@0.2.9': - resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==} - '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} @@ -4596,11 +4660,6 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - nanoid@3.3.8: - resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} @@ -6494,7 +6553,7 @@ snapshots: '@astrojs/telemetry@3.3.0': dependencies: ci-info: 4.2.0 - debug: 4.4.0 + debug: 4.4.1 dlv: 1.1.3 dset: 3.1.4 is-docker: 3.0.0 @@ -6503,6 +6562,28 @@ snapshots: transitivePeerDependencies: - supports-color + '@astrojs/vercel@8.2.2(@remix-run/react@2.16.8(react@19.1.0)(typescript@5.8.3))(@sveltejs/kit@2.25.1(svelte@5.36.8)(vite@6.3.5(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(sugarss@5.0.0)(terser@5.31.2)(yaml@2.4.5)))(astro@5.12.0(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.40.2)(sugarss@5.0.0)(terser@5.31.2)(typescript@5.8.3)(yaml@2.4.5))(next@15.4.2(react@19.1.0))(react@19.1.0)(rollup@4.40.2)(svelte@5.36.8)': + dependencies: + '@astrojs/internal-helpers': 0.6.1 + '@vercel/analytics': 1.5.0(@remix-run/react@2.16.8(react@19.1.0)(typescript@5.8.3))(@sveltejs/kit@2.25.1(svelte@5.36.8)(vite@6.3.5(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(sugarss@5.0.0)(terser@5.31.2)(yaml@2.4.5)))(next@15.4.2(react@19.1.0))(react@19.1.0)(svelte@5.36.8) + '@vercel/edge': 1.2.1 + '@vercel/nft': 0.29.2(rollup@4.40.2) + '@vercel/routing-utils': 5.0.4 + astro: 5.12.0(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.40.2)(sugarss@5.0.0)(terser@5.31.2)(typescript@5.8.3)(yaml@2.4.5) + esbuild: 0.25.4 + tinyglobby: 0.2.13 + transitivePeerDependencies: + - '@remix-run/react' + - '@sveltejs/kit' + - encoding + - next + - react + - rollup + - supports-color + - svelte + - vue + - vue-router + '@astrojs/vercel@8.2.2(@remix-run/react@2.16.8(react@19.1.0)(typescript@5.8.3))(@sveltejs/kit@2.25.1(svelte@5.36.8)(vite@7.0.5(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(sugarss@5.0.0)(terser@5.31.2)(yaml@2.4.5)))(astro@5.12.0(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.40.2)(sugarss@5.0.0)(terser@5.31.2)(typescript@5.8.3)(yaml@2.4.5))(next@15.4.2(react@19.1.0))(react@19.1.0)(rollup@4.40.2)(svelte@5.36.8)': dependencies: '@astrojs/internal-helpers': 0.6.1 @@ -6546,7 +6627,7 @@ snapshots: '@babel/traverse': 7.27.1 '@babel/types': 7.27.1 convert-source-map: 2.0.0 - debug: 4.4.0 + debug: 4.4.1 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -6566,7 +6647,7 @@ snapshots: '@babel/traverse': 7.28.0 '@babel/types': 7.28.1 convert-source-map: 2.0.0 - debug: 4.4.0 + debug: 4.4.1 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -6790,7 +6871,7 @@ snapshots: '@babel/parser': 7.27.2 '@babel/template': 7.27.2 '@babel/types': 7.27.1 - debug: 4.4.0 + debug: 4.4.1 globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -6803,7 +6884,7 @@ snapshots: '@babel/parser': 7.28.0 '@babel/template': 7.27.2 '@babel/types': 7.28.1 - debug: 4.4.0 + debug: 4.4.1 transitivePeerDependencies: - supports-color @@ -7059,7 +7140,7 @@ snapshots: '@eslint/config-array@0.21.0': dependencies: '@eslint/object-schema': 2.1.6 - debug: 4.4.0 + debug: 4.4.1 minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -7073,7 +7154,7 @@ snapshots: '@eslint/eslintrc@3.3.1': dependencies: ajv: 6.12.6 - debug: 4.4.0 + debug: 4.4.1 espree: 10.4.0 globals: 14.0.0 ignore: 5.3.1 @@ -7095,19 +7176,10 @@ snapshots: '@faker-js/faker@9.9.0': {} - '@floating-ui/core@1.6.0': - dependencies: - '@floating-ui/utils': 0.2.9 - '@floating-ui/core@1.7.2': dependencies: '@floating-ui/utils': 0.2.10 - '@floating-ui/dom@1.6.13': - dependencies: - '@floating-ui/core': 1.6.0 - '@floating-ui/utils': 0.2.9 - '@floating-ui/dom@1.7.2': dependencies: '@floating-ui/core': 1.7.2 @@ -7115,20 +7187,20 @@ snapshots: '@floating-ui/react-dom@2.1.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@floating-ui/dom': 1.6.13 + '@floating-ui/dom': 1.7.2 react: 19.0.0 react-dom: 19.0.0(react@19.0.0) '@floating-ui/react-dom@2.1.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: - '@floating-ui/dom': 1.6.13 + '@floating-ui/dom': 1.7.2 react: 19.1.0 react-dom: 19.1.0(react@19.1.0) '@floating-ui/react@0.26.28(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: '@floating-ui/react-dom': 2.1.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@floating-ui/utils': 0.2.9 + '@floating-ui/utils': 0.2.10 react: 19.0.0 react-dom: 19.0.0(react@19.0.0) tabbable: 6.2.0 @@ -7136,15 +7208,13 @@ snapshots: '@floating-ui/react@0.26.28(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@floating-ui/react-dom': 2.1.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@floating-ui/utils': 0.2.9 + '@floating-ui/utils': 0.2.10 react: 19.1.0 react-dom: 19.1.0(react@19.1.0) tabbable: 6.2.0 '@floating-ui/utils@0.2.10': {} - '@floating-ui/utils@0.2.9': {} - '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.6': @@ -7428,7 +7498,7 @@ snapshots: https-proxy-agent: 7.0.6 node-fetch: 2.7.0 nopt: 8.1.0 - semver: 7.7.1 + semver: 7.7.2 tar: 7.4.3 transitivePeerDependencies: - encoding @@ -7503,7 +7573,7 @@ snapshots: '@npmcli/fs@3.1.1': dependencies: - semver: 7.7.1 + semver: 7.7.2 '@npmcli/git@4.1.0': dependencies: @@ -7513,7 +7583,7 @@ snapshots: proc-log: 3.0.0 promise-inflight: 1.0.1 promise-retry: 2.0.1 - semver: 7.7.1 + semver: 7.7.2 which: 3.0.1 transitivePeerDependencies: - bluebird @@ -7526,7 +7596,7 @@ snapshots: json-parse-even-better-errors: 3.0.2 normalize-package-data: 5.0.0 proc-log: 3.0.0 - semver: 7.7.1 + semver: 7.7.2 transitivePeerDependencies: - bluebird @@ -7973,14 +8043,14 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.1.11 '@tailwindcss/oxide-win32-x64-msvc': 4.1.11 - '@tailwindcss/vite@4.1.11(vite@6.3.5(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(sugarss@5.0.0(postcss@8.5.6))(terser@5.31.2)(yaml@2.4.5))': + '@tailwindcss/vite@4.1.11(vite@6.3.5(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(sugarss@5.0.0)(terser@5.31.2)(yaml@2.4.5))': dependencies: '@tailwindcss/node': 4.1.11 '@tailwindcss/oxide': 4.1.11 tailwindcss: 4.1.11 vite: 6.3.5(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(sugarss@5.0.0)(terser@5.31.2)(yaml@2.4.5) - '@tailwindcss/vite@4.1.11(vite@7.0.5(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(sugarss@5.0.0(postcss@8.5.6))(terser@5.31.2)(yaml@2.4.5))': + '@tailwindcss/vite@4.1.11(vite@7.0.5(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(sugarss@5.0.0)(terser@5.31.2)(yaml@2.4.5))': dependencies: '@tailwindcss/node': 4.1.11 '@tailwindcss/oxide': 4.1.11 @@ -8199,7 +8269,7 @@ snapshots: '@typescript-eslint/types': 8.37.0 '@typescript-eslint/typescript-estree': 8.37.0(typescript@5.8.3) '@typescript-eslint/visitor-keys': 8.37.0 - debug: 4.4.0 + debug: 4.4.1 eslint: 9.31.0(jiti@2.4.2) typescript: 5.8.3 transitivePeerDependencies: @@ -8209,7 +8279,7 @@ snapshots: dependencies: '@typescript-eslint/tsconfig-utils': 8.37.0(typescript@5.8.3) '@typescript-eslint/types': 8.37.0 - debug: 4.4.0 + debug: 4.4.1 typescript: 5.8.3 transitivePeerDependencies: - supports-color @@ -8228,7 +8298,7 @@ snapshots: '@typescript-eslint/types': 8.37.0 '@typescript-eslint/typescript-estree': 8.37.0(typescript@5.8.3) '@typescript-eslint/utils': 8.37.0(eslint@9.31.0(jiti@2.4.2))(typescript@5.8.3) - debug: 4.4.0 + debug: 4.4.1 eslint: 9.31.0(jiti@2.4.2) ts-api-utils: 2.1.0(typescript@5.8.3) typescript: 5.8.3 @@ -8243,11 +8313,11 @@ snapshots: '@typescript-eslint/tsconfig-utils': 8.37.0(typescript@5.8.3) '@typescript-eslint/types': 8.37.0 '@typescript-eslint/visitor-keys': 8.37.0 - debug: 4.4.0 + debug: 4.4.1 fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.4 - semver: 7.7.1 + semver: 7.7.2 ts-api-utils: 2.1.0(typescript@5.8.3) typescript: 5.8.3 transitivePeerDependencies: @@ -8322,6 +8392,14 @@ snapshots: '@vanilla-extract/private@1.0.5': {} + '@vercel/analytics@1.5.0(@remix-run/react@2.16.8(react@19.1.0)(typescript@5.8.3))(@sveltejs/kit@2.25.1(svelte@5.36.8)(vite@6.3.5(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(sugarss@5.0.0)(terser@5.31.2)(yaml@2.4.5)))(next@15.4.2(react@19.1.0))(react@19.1.0)(svelte@5.36.8)': + optionalDependencies: + '@remix-run/react': 2.16.8(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.8.3) + '@sveltejs/kit': 2.25.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.36.8)(vite@6.3.5(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(sugarss@5.0.0(postcss@8.5.6))(terser@5.31.2)(yaml@2.4.5)))(svelte@5.36.8)(vite@6.3.5(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(sugarss@5.0.0(postcss@8.5.6))(terser@5.31.2)(yaml@2.4.5)) + next: 15.4.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + react: 19.1.0 + svelte: 5.36.8 + '@vercel/analytics@1.5.0(@remix-run/react@2.16.8(react@19.1.0)(typescript@5.8.3))(@sveltejs/kit@2.25.1(svelte@5.36.8)(vite@7.0.5(@types/node@24.0.15)(jiti@2.4.2)(lightningcss@1.30.1)(sugarss@5.0.0)(terser@5.31.2)(yaml@2.4.5)))(next@15.4.2(react@19.1.0))(react@19.1.0)(svelte@5.36.8)': optionalDependencies: '@remix-run/react': 2.16.8(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.8.3) @@ -8404,10 +8482,6 @@ snapshots: dependencies: acorn: 8.14.1 - acorn-jsx@5.3.2(acorn@8.14.1): - dependencies: - acorn: 8.14.1 - acorn-jsx@5.3.2(acorn@8.15.0): dependencies: acorn: 8.15.0 @@ -9193,7 +9267,7 @@ snapshots: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.6 - debug: 4.4.0 + debug: 4.4.1 escape-string-regexp: 4.0.0 eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 @@ -9303,7 +9377,7 @@ snapshots: express-urlrewrite@1.4.0: dependencies: - debug: 4.4.0 + debug: 4.4.1 path-to-regexp: 1.8.0 transitivePeerDependencies: - supports-color @@ -10577,8 +10651,8 @@ snapshots: micromark-extension-mdxjs@1.0.1: dependencies: - acorn: 8.14.1 - acorn-jsx: 5.3.2(acorn@8.14.1) + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) micromark-extension-mdx-expression: 1.0.8 micromark-extension-mdx-jsx: 1.0.5 micromark-extension-mdx-md: 1.0.1 @@ -10940,8 +11014,6 @@ snapshots: nanoid@3.3.7: {} - nanoid@3.3.8: {} - natural-compare@1.4.0: {} negotiator@0.6.3: {} @@ -11018,7 +11090,7 @@ snapshots: dependencies: hosted-git-info: 6.1.1 is-core-module: 2.13.1 - semver: 7.7.1 + semver: 7.7.2 validate-npm-package-license: 3.0.4 normalize-path@3.0.0: {} @@ -11027,7 +11099,7 @@ snapshots: npm-install-checks@6.3.0: dependencies: - semver: 7.7.1 + semver: 7.7.2 npm-normalize-package-bin@3.0.1: {} @@ -11035,7 +11107,7 @@ snapshots: dependencies: hosted-git-info: 6.1.1 proc-log: 3.0.0 - semver: 7.7.1 + semver: 7.7.2 validate-npm-package-name: 5.0.1 npm-pick-manifest@8.0.2: @@ -11043,7 +11115,7 @@ snapshots: npm-install-checks: 6.3.0 npm-normalize-package-bin: 3.0.1 npm-package-arg: 10.1.0 - semver: 7.7.1 + semver: 7.7.2 npm-run-path@4.0.1: dependencies: @@ -11340,7 +11412,7 @@ snapshots: postcss@8.4.31: dependencies: - nanoid: 3.3.8 + nanoid: 3.3.11 picocolors: 1.1.1 source-map-js: 1.2.1 @@ -11816,8 +11888,7 @@ snapshots: semver@7.7.1: {} - semver@7.7.2: - optional: true + semver@7.7.2: {} send@0.18.0: dependencies: @@ -11890,7 +11961,7 @@ snapshots: dependencies: color: 4.2.3 detect-libc: 2.0.4 - semver: 7.7.1 + semver: 7.7.2 optionalDependencies: '@img/sharp-darwin-arm64': 0.33.5 '@img/sharp-darwin-x64': 0.33.5 From c1eacc955a075a7be84e950a7408ed855b1eaad1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 19 Jul 2025 23:06:47 +0000 Subject: [PATCH 3/3] Implement TanStack Router example app (1-6-vite-tanstack-router) Co-authored-by: KevinVandy <28243511+KevinVandy@users.noreply.github.com> --- apps/1-6-vite-tanstack-router/.gitignore | 24 ++ apps/1-6-vite-tanstack-router/index.html | 13 + apps/1-6-vite-tanstack-router/package.json | 41 +++ .../postcss.config.cjs | 14 + apps/1-6-vite-tanstack-router/public/vite.svg | 1 + apps/1-6-vite-tanstack-router/src/App.tsx | 7 + .../src/AppLayout.tsx | 110 ++++++ .../src/AppProviders.tsx | 111 ++++++ .../1-6-vite-tanstack-router/src/api-types.ts | 38 ++ apps/1-6-vite-tanstack-router/src/main.tsx | 9 + .../src/pages/HomePage.tsx | 76 ++++ .../src/pages/PostPage.tsx | 276 ++++++++++++++ .../src/pages/UserPage.tsx | 123 +++++++ .../src/pages/UsersPage.tsx | 84 +++++ .../src/queries/comments.ts | 15 + .../src/queries/posts.ts | 34 ++ .../src/queries/users.ts | 23 ++ apps/1-6-vite-tanstack-router/src/theme.ts | 5 + .../src/vite-env.d.ts | 1 + apps/1-6-vite-tanstack-router/tsconfig.json | 25 ++ .../tsconfig.node.json | 11 + apps/1-6-vite-tanstack-router/vite.config.ts | 7 + pnpm-lock.yaml | 344 ++++++++++++++++-- 23 files changed, 1354 insertions(+), 38 deletions(-) create mode 100644 apps/1-6-vite-tanstack-router/.gitignore create mode 100644 apps/1-6-vite-tanstack-router/index.html create mode 100644 apps/1-6-vite-tanstack-router/package.json create mode 100644 apps/1-6-vite-tanstack-router/postcss.config.cjs create mode 100644 apps/1-6-vite-tanstack-router/public/vite.svg create mode 100644 apps/1-6-vite-tanstack-router/src/App.tsx create mode 100644 apps/1-6-vite-tanstack-router/src/AppLayout.tsx create mode 100644 apps/1-6-vite-tanstack-router/src/AppProviders.tsx create mode 100644 apps/1-6-vite-tanstack-router/src/api-types.ts create mode 100644 apps/1-6-vite-tanstack-router/src/main.tsx create mode 100644 apps/1-6-vite-tanstack-router/src/pages/HomePage.tsx create mode 100644 apps/1-6-vite-tanstack-router/src/pages/PostPage.tsx create mode 100644 apps/1-6-vite-tanstack-router/src/pages/UserPage.tsx create mode 100644 apps/1-6-vite-tanstack-router/src/pages/UsersPage.tsx create mode 100644 apps/1-6-vite-tanstack-router/src/queries/comments.ts create mode 100644 apps/1-6-vite-tanstack-router/src/queries/posts.ts create mode 100644 apps/1-6-vite-tanstack-router/src/queries/users.ts create mode 100644 apps/1-6-vite-tanstack-router/src/theme.ts create mode 100644 apps/1-6-vite-tanstack-router/src/vite-env.d.ts create mode 100644 apps/1-6-vite-tanstack-router/tsconfig.json create mode 100644 apps/1-6-vite-tanstack-router/tsconfig.node.json create mode 100644 apps/1-6-vite-tanstack-router/vite.config.ts diff --git a/apps/1-6-vite-tanstack-router/.gitignore b/apps/1-6-vite-tanstack-router/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/apps/1-6-vite-tanstack-router/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/apps/1-6-vite-tanstack-router/index.html b/apps/1-6-vite-tanstack-router/index.html new file mode 100644 index 0000000..96791df --- /dev/null +++ b/apps/1-6-vite-tanstack-router/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite + React Query Hooks Refactor + + +
+ + + diff --git a/apps/1-6-vite-tanstack-router/package.json b/apps/1-6-vite-tanstack-router/package.json new file mode 100644 index 0000000..9340cd7 --- /dev/null +++ b/apps/1-6-vite-tanstack-router/package.json @@ -0,0 +1,41 @@ +{ + "name": "1-6-vite-tanstack-router", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite --port 3316", + "build": "tsc && vite build", + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "preview": "vite preview --port 3316" + }, + "dependencies": { + "@mantine/core": "8.1.3", + "@mantine/hooks": "8.1.3", + "@tabler/icons-react": "3.34.0", + "@tanstack/react-query": "^5.83.0", + "@tanstack/react-query-devtools": "^5.83.0", + "@tanstack/react-router": "^1.106.2", + "@tanstack/router-devtools": "^1.106.2", + "mantine-react-table": "^2.0.0-beta.6", + "react": "^19.1.0", + "react-dom": "^19.1.0", + "react-error-boundary": "^6.0.0" + }, + "devDependencies": { + "@types/node": "^22.0.0", + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@typescript-eslint/eslint-plugin": "^8.37.0", + "@typescript-eslint/parser": "^8.37.0", + "@vitejs/plugin-react": "^4.7.0", + "eslint": "^9.31.0", + "eslint-plugin-react-hooks": "^5.2.0", + "eslint-plugin-react-refresh": "^0.4.20", + "postcss": "^8.5.6", + "postcss-preset-mantine": "1.18.0", + "postcss-simple-vars": "^7.0.1", + "typescript": "^5.8.3", + "vite": "^7.0.5" + } +} diff --git a/apps/1-6-vite-tanstack-router/postcss.config.cjs b/apps/1-6-vite-tanstack-router/postcss.config.cjs new file mode 100644 index 0000000..be8ba93 --- /dev/null +++ b/apps/1-6-vite-tanstack-router/postcss.config.cjs @@ -0,0 +1,14 @@ +module.exports = { + plugins: { + "postcss-preset-mantine": {}, + "postcss-simple-vars": { + variables: { + "mantine-breakpoint-xs": "36em", + "mantine-breakpoint-sm": "48em", + "mantine-breakpoint-md": "62em", + "mantine-breakpoint-lg": "75em", + "mantine-breakpoint-xl": "88em", + }, + }, + }, +}; \ No newline at end of file diff --git a/apps/1-6-vite-tanstack-router/public/vite.svg b/apps/1-6-vite-tanstack-router/public/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/apps/1-6-vite-tanstack-router/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/1-6-vite-tanstack-router/src/App.tsx b/apps/1-6-vite-tanstack-router/src/App.tsx new file mode 100644 index 0000000..3a728fa --- /dev/null +++ b/apps/1-6-vite-tanstack-router/src/App.tsx @@ -0,0 +1,7 @@ +import { AppProviders } from "./AppProviders"; +import "@mantine/core/styles.css"; +import "mantine-react-table/styles.css"; + +export const App = () => { + return ; +}; diff --git a/apps/1-6-vite-tanstack-router/src/AppLayout.tsx b/apps/1-6-vite-tanstack-router/src/AppLayout.tsx new file mode 100644 index 0000000..76801d8 --- /dev/null +++ b/apps/1-6-vite-tanstack-router/src/AppLayout.tsx @@ -0,0 +1,110 @@ +import { + Anchor, + AppShell, + Breadcrumbs, + Burger, + Group, + Stack, +} from "@mantine/core"; +import { useDisclosure } from "@mantine/hooks"; +import { IconHome, IconUsersGroup } from "@tabler/icons-react"; +import { useMemo } from "react"; +import { Link, useRouter } from "@tanstack/react-router"; +import { useQueryClient } from "@tanstack/react-query"; +import { usersQueryOptions } from "./queries/users"; +import { postsQueryOptions } from "./queries/posts"; + +interface AppLayoutProps { + children: React.ReactNode; +} + +export function AppLayout({ children }: AppLayoutProps) { + const router = useRouter(); + const pathname = router.state.location.pathname; + const queryClient = useQueryClient(); + + const links = [ + { + icon: , + color: "blue", + label: "Home Feed", + href: "/", + prefetch: () => queryClient.prefetchQuery(postsQueryOptions), + }, + { + icon: , + color: "teal", + label: "Users", + href: "/users", + prefetch: () => queryClient.prefetchQuery(usersQueryOptions), + }, + ]; + + const breadCrumbLinks = useMemo(() => { + const routes = pathname.split("/"); + routes.shift(); + const links: string[] = []; + for (let i = 0; i < routes.length + 1; i++) { + if (routes[i] && routes[i] !== "/") + if (routes[i] === "posts") { + links.push(`/`); + } else links.push(`/${routes.slice(0, i + 1).join("/")}`); + } + return links; + }, [pathname]); + + if (breadCrumbLinks.length === 1) { + breadCrumbLinks.unshift("/"); + } + + const [opened, { toggle }] = useDisclosure(); + + return ( + + + + + Vite with React Query Hooks Refactor + + + + {links.map((link) => ( + + {link.label} + + ))} + + + + + {breadCrumbLinks.map((link, index) => ( + + {link === "/" ? "Home Feed" : link.split("/").pop()} + + ))} + + {children} + + + + ); +} diff --git a/apps/1-6-vite-tanstack-router/src/AppProviders.tsx b/apps/1-6-vite-tanstack-router/src/AppProviders.tsx new file mode 100644 index 0000000..ef11e06 --- /dev/null +++ b/apps/1-6-vite-tanstack-router/src/AppProviders.tsx @@ -0,0 +1,111 @@ +import { lazy, Suspense } from "react"; +import { MantineProvider } from "@mantine/core"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { + createRouter, + RouterProvider, + createRootRoute, + createRoute, + Outlet +} from "@tanstack/react-router"; +import { theme } from "./theme"; +import { AppLayout } from "./AppLayout"; +import { HomePage } from "./pages/HomePage"; +import { UsersPage } from "./pages/UsersPage"; +import { UserPage } from "./pages/UserPage"; +import { PostPage } from "./pages/PostPage"; + +const ReactQueryDevtoolsProduction = lazy(() => + import("@tanstack/react-query-devtools/production").then((d) => ({ + default: d.ReactQueryDevtools, + })), +); + +const TanStackRouterDevtools = + typeof window !== "undefined" + ? lazy(() => + // Lazy load in development + import("@tanstack/router-devtools").then((res) => ({ + default: res.TanStackRouterDevtools, + })), + ) + : () => null; // Render nothing on server side + +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + staleTime: 1000 * 10, // 10 seconds + }, + }, +}); + +// Create routes +const rootRoute = createRootRoute({ + component: () => ( + + + + ), +}); + +const indexRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '/', + component: HomePage, +}); + +const usersRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '/users', + component: UsersPage, +}); + +const userRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '/users/$id', + component: UserPage, +}); + +const postRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '/posts/$id', + component: PostPage, +}); + +// Create the route tree +const routeTree = rootRoute.addChildren([ + indexRoute, + usersRoute, + userRoute, + postRoute, +]); + +// Create a new router instance +const router = createRouter({ routeTree }); + +// Register the router instance for type safety +declare module "@tanstack/react-router" { + interface Register { + router: typeof router; + } +} + +interface Props { + // children prop is not needed since router handles all rendering +} + +export const AppProviders = ({}: Props) => { + return ( + + + + + + + + + + + + ); +}; diff --git a/apps/1-6-vite-tanstack-router/src/api-types.ts b/apps/1-6-vite-tanstack-router/src/api-types.ts new file mode 100644 index 0000000..49e5816 --- /dev/null +++ b/apps/1-6-vite-tanstack-router/src/api-types.ts @@ -0,0 +1,38 @@ +export interface IUser { + id: number; + name: string; + username: string; + email: string; + address: { + street: string; + suite: string; + city: string; + zipcode: string; + geo: { + lat: string; + lng: string; + }; + }; + phone: string; + website: string; + company: { + name: string; + catchPhrase: string; + bs: string; + }; +} + +export interface IPost { + userId: number; + id: number; + title: string; + body: string; +} + +export interface IComment { + postId: number; + id: number; + name: string; + email: string; + body: string; +} diff --git a/apps/1-6-vite-tanstack-router/src/main.tsx b/apps/1-6-vite-tanstack-router/src/main.tsx new file mode 100644 index 0000000..65c0deb --- /dev/null +++ b/apps/1-6-vite-tanstack-router/src/main.tsx @@ -0,0 +1,9 @@ +import React from "react"; +import ReactDOM from "react-dom/client"; +import { App } from "./App.tsx"; + +ReactDOM.createRoot(document.getElementById("root")!).render( + + + , +); diff --git a/apps/1-6-vite-tanstack-router/src/pages/HomePage.tsx b/apps/1-6-vite-tanstack-router/src/pages/HomePage.tsx new file mode 100644 index 0000000..7e16048 --- /dev/null +++ b/apps/1-6-vite-tanstack-router/src/pages/HomePage.tsx @@ -0,0 +1,76 @@ +import { Suspense } from "react"; +import { Alert, Card, Flex, Skeleton, Stack, Text, Title } from "@mantine/core"; +import { Link } from "@tanstack/react-router"; +import { IconAlertCircle } from "@tabler/icons-react"; +import { useSuspenseQuery } from "@tanstack/react-query"; +import { postsQueryOptions } from "../queries/posts"; +import { QueryErrorResetBoundary } from "@tanstack/react-query"; +import { ErrorBoundary } from "react-error-boundary"; + +export function HomePage() { + return ( + + Your Home Feed + + + {({ reset }) => ( + } + onReset={reset} + > + }> + + + + )} + + + + ); +} + +function HomePageSkeleton() { + return [...Array(5)].map((_, index) => ( + + + + + )); +} + +function HomePageError() { + return ( + } title="Bummer!" color="red"> + There was an error fetching posts + + ); +} + +function HomePagePosts() { + const { data: posts } = useSuspenseQuery(postsQueryOptions); + + return posts.map((post) => ( + + + {post.title} + {post.body} + + Go to post + + + + )); +} diff --git a/apps/1-6-vite-tanstack-router/src/pages/PostPage.tsx b/apps/1-6-vite-tanstack-router/src/pages/PostPage.tsx new file mode 100644 index 0000000..fa7233d --- /dev/null +++ b/apps/1-6-vite-tanstack-router/src/pages/PostPage.tsx @@ -0,0 +1,276 @@ +import { useCallback, useState } from "react"; +import { Link, useParams } from "@tanstack/react-router"; +import { + ActionIcon, + Alert, + Box, + Button, + Card, + Collapse, + Flex, + Loader, + Skeleton, + Stack, + Text, + Textarea, + Title, + Tooltip, +} from "@mantine/core"; +import { IconAlertCircle, IconRefresh, IconTrash } from "@tabler/icons-react"; +import { useMutation, useQueryClient, useQuery } from "@tanstack/react-query"; +import { IComment } from "../api-types"; +import { postQueryOptions } from "../queries/posts"; +import { postCommentsQueryOptions } from "../queries/comments"; +import { userQueryOptions } from "../queries/users"; + +export const PostPage = () => { + const queryClient = useQueryClient(); + const { id: postId } = useParams({ from: "/posts/$id" }); + + //load post + const { + data: post, + isLoading: isLoadingPost, + isError: isErrorLoadingPosts, + } = useQuery(postQueryOptions(postId)); + + //load user - depends on user id from post + const { + data: user, + isLoading: isLoadingUser, + isError: isErrorLoadingUser, + } = useQuery({ + ...userQueryOptions(post?.userId!), + enabled: !!post?.userId, + }); + + //load comments + const { + data: comments, + isLoading: isLoadingComments, + isFetching: isFetchingComments, + isError: isErrorLoadingComments, + refetch: refetchComments, + } = useQuery(postCommentsQueryOptions(postId)); + + //delete comment, refresh comments after delete + const { + mutate: deleteComment, + isPending: isDeletingComment, + context: deletingCommentContext, + } = useMutation({ + mutationFn: async (commentId: number) => { + const response = await fetch( + `http://localhost:3300/comments/${commentId}`, + { + method: "DELETE", + }, + ); + return response.json() as Promise; + }, + //record which comment is being deleted so we can give it lower opacity + onMutate: async (commentId) => ({ commentId }), + onError: (err, commentId) => { + console.error( + `Error deleting comment ${commentId}. Rolling UI back`, + err, + ); + alert("Error deleting comment"); + }, + onSettled: () => { + queryClient.invalidateQueries({ + queryKey: postCommentsQueryOptions(postId).queryKey, + }); //refresh comments + }, + }); + + // Post new comment - with optimistic updates! + const [commentText, setCommentText] = useState(""); + + const { mutate: postComment, isPending: isPostingComment } = useMutation({ + mutationFn: async (comment: Omit) => { + const response = await fetch(`http://localhost:3300/comments`, { + method: "POST", + body: JSON.stringify(comment), + headers: { + "Content-type": "application/json; charset=UTF-8", + }, + }); + return response.json() as Promise; + }, + //optimistic client-side update + onMutate: async (newComment) => { + await queryClient.cancelQueries({ + queryKey: postCommentsQueryOptions(postId).queryKey, + }); + + // Snapshot the previous value + const previousComments = queryClient.getQueryData([ + "comments", + newComment.postId.toString(), + ]); + + // Optimistically update to the new value + queryClient.setQueryData( + postCommentsQueryOptions(postId).queryKey, + (oldComments: any) => [...oldComments, newComment], + ); + + // Return a context object with the snapshot value + return { previousComments }; + }, + // If the mutation fails, + // use the context returned from onMutate to roll back + onError: (err, _newComment, context) => { + queryClient.setQueryData( + postCommentsQueryOptions(postId).queryKey, + context?.previousComments as IComment[], + ); + console.error("Error posting comment. Rolling UI back", err); + }, + onSuccess: () => { + setCommentText(""); //clear comment text + }, + // Always refetch after error or success: + onSettled: () => { + queryClient.invalidateQueries({ + queryKey: postCommentsQueryOptions(postId).queryKey, + }); + }, + }); + + const handleSubmitComment = useCallback(async () => { + const newComment: Omit = { + body: commentText, + email: "user@mailinator.com", + name: "User", + postId: Number(postId), + }; + postComment(newComment); + }, [commentText, postId, postComment]); + + return ( + + + {isErrorLoadingPosts || isErrorLoadingUser ? ( + } + title="Bummer!" + color="red" + > + There was an error loading this post + + ) : !post || isLoadingPost || isLoadingUser ? ( + <> + + + + ) : ( + <> + Post: {post?.id} + {post?.title} + + By:{" "} + <Link + to="/users/$id" + params={{ id: user?.id?.toString() || "" }} + style={{ textDecoration: "none" }} + > + {user?.name} + </Link> + + + {post.body}. {post.body}. {post.body}. {post.body}. {post.body}. + + + )} + + + + Comments on this Post + + + refetchComments()}> + + + + + + + + + + + {isErrorLoadingComments ? ( + } + title="Bummer!" + color="red" + > + There was an error loading comments for this post + + ) : isLoadingComments ? ( + [...Array(5)].map((_, index) => ( + + + + + + )) + ) : ( + comments?.map((comment) => ( + + {comment.email === "user@mailinator.com" && ( + deleteComment(comment.id)} + > + + + )} + + {comment.name} + {comment.email} + {comment.body} + + )) + )} +