diff --git a/package.json b/package.json index 7b8947a..89b5863 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,8 @@ }, "dependencies": { "@tanstack/react-query": "^5.29.2", + "@tanstack/react-query-persist-client": "^5.29.2", + "idb-keyval": "^6.2.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.22.3" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f3d5686..0577193 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,12 @@ importers: '@tanstack/react-query': specifier: ^5.29.2 version: 5.29.2(react@18.2.0) + '@tanstack/react-query-persist-client': + specifier: ^5.29.2 + version: 5.29.2(@tanstack/react-query@5.29.2(react@18.2.0))(react@18.2.0) + idb-keyval: + specifier: ^6.2.1 + version: 6.2.1 react: specifier: ^18.2.0 version: 18.2.0 @@ -449,6 +455,15 @@ packages: '@tanstack/query-core@5.29.0': resolution: {integrity: sha512-WgPTRs58hm9CMzEr5jpISe8HXa3qKQ8CxewdYZeVnA54JrPY9B1CZiwsCoLpLkf0dGRZq+LcX5OiJb0bEsOFww==} + '@tanstack/query-persist-client-core@5.29.0': + resolution: {integrity: sha512-aQpXqHQIg/GFtsQKUx/g3cMS/P9CFTWITXPlhrICW14E16gmQ+GMwnoXHAnu/kBV4MucfwUFKhVl4rzryltORQ==} + + '@tanstack/react-query-persist-client@5.29.2': + resolution: {integrity: sha512-I8KnQ1CzEfJAU/+8AQHCCCld2iWmmvxmQUTaoqPQyeLZDWvlUSJ/NpEpfMWtf4qyh5m0KJm8VmhcqdOnJSwaEQ==} + peerDependencies: + '@tanstack/react-query': ^5.29.2 + react: ^18.0.0 + '@tanstack/react-query@5.29.2': resolution: {integrity: sha512-nyuWILR4u7H5moLGSiifLh8kIqQDLNOHGuSz0rcp+J75fNc8aQLyr5+I2JCHU3n+nJrTTW1ssgAD8HiKD7IFBQ==} peerDependencies: @@ -841,6 +856,9 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + idb-keyval@6.2.1: + resolution: {integrity: sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==} + ignore@5.3.1: resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} engines: {node: '>= 4'} @@ -1612,6 +1630,16 @@ snapshots: '@tanstack/query-core@5.29.0': {} + '@tanstack/query-persist-client-core@5.29.0': + dependencies: + '@tanstack/query-core': 5.29.0 + + '@tanstack/react-query-persist-client@5.29.2(@tanstack/react-query@5.29.2(react@18.2.0))(react@18.2.0)': + dependencies: + '@tanstack/query-persist-client-core': 5.29.0 + '@tanstack/react-query': 5.29.2(react@18.2.0) + react: 18.2.0 + '@tanstack/react-query@5.29.2(react@18.2.0)': dependencies: '@tanstack/query-core': 5.29.0 @@ -2073,6 +2101,8 @@ snapshots: dependencies: function-bind: 1.1.2 + idb-keyval@6.2.1: {} + ignore@5.3.1: {} import-fresh@3.3.0: diff --git a/src/app.tsx b/src/app.tsx index ebb6787..58e632c 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -1,5 +1,7 @@ import { Router } from "./router"; -import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { QueryClient } from "@tanstack/react-query"; +import { createIDBPersister } from "./services/infrastructure/persisters/create-idb-persister"; +import { PersistQueryClientProvider } from "@tanstack/react-query-persist-client"; const queryClient = new QueryClient({ defaultOptions: { @@ -7,14 +9,19 @@ const queryClient = new QueryClient({ refetchOnWindowFocus: false, refetchOnMount: false, retry: false, + gcTime: 1000 * 60 * 60 * 24, // 24 hours }, }, }); +const persister = createIDBPersister(); export function App() { return ( - + - + ); } diff --git a/src/services/infrastructure/persisters/create-idb-persister.ts b/src/services/infrastructure/persisters/create-idb-persister.ts new file mode 100644 index 0000000..ded4730 --- /dev/null +++ b/src/services/infrastructure/persisters/create-idb-persister.ts @@ -0,0 +1,22 @@ +import { get, set, del } from "idb-keyval"; +import { + PersistedClient, + Persister, +} from "@tanstack/react-query-persist-client"; +/** + * Creates an Indexed DB persister + * @see https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API + */ +export function createIDBPersister(idbValidKey: IDBValidKey = "reactQuery") { + return { + persistClient: async (client: PersistedClient) => { + await set(idbValidKey, client); + }, + restoreClient: async () => { + return await get(idbValidKey); + }, + removeClient: async () => { + await del(idbValidKey); + }, + } as Persister; +} diff --git a/todo.md b/todo.md index d1115c6..a0b5f38 100644 --- a/todo.md +++ b/todo.md @@ -14,22 +14,22 @@ ## Views -- [ ] Home +- [x] Home - [x] Shows a list of 100 most popular podcasts from iTunes - - [ ] Caches the list for 24 hours + - [x] Caches the list for 24 hours - [x] Has filtering by name and author - [x] Filters are applied in real time - [x] Clicking on a podcast navigates to the podcast page -- [ ] Podcast +- [x] Podcast - [x] Shows the podcast details in an aside (name, author, image, description) - [x] Shows the podcast episodes and number of episodes - - [ ] Caches the podcast info for 24 hours + - [x] Caches the podcast info for 24 hours - [x] Clicking on an episode navigates to the episode page -- [ ] Episode +- [x] Episode - [x] Shows the podcast details (name, author, image, description) - [x] Image and title are clickable and navigate to the podcast page