|
- import { QueryClient } from '@tanstack/react-query'
- import { match } from 'path-to-regexp'
-
- import { fetchPost, fetchPosts, fetchPostChanges } from '@/lib/posts'
- import { postsKeys, tagsKeys, wikiKeys } from '@/lib/queryKeys'
- import { fetchTagByName } from '@/lib/tags'
- import { fetchWikiPageByTitle, fetchWikiPages } from '@/lib/wiki'
-
- type Prefetcher = (qc: QueryClient, url: URL) => Promise<void>
-
- const mPost = match<{ id: string }> ('/posts/:id')
- const mWiki = match<{ title: string }> ('/wiki/:title')
-
-
- const prefetchWikiPagesIndex: Prefetcher = async (qc, url) => {
- const title = url.searchParams.get ('title') ?? ''
-
- await qc.prefetchQuery ({
- queryKey: wikiKeys.index ({ title }),
- queryFn: () => fetchWikiPages ({ title }) })
- }
-
-
- const prefetchWikiPageShow: Prefetcher = async (qc, url) => {
- const m = mWiki (url.pathname)
- if (!(m))
- return
-
- const title = decodeURIComponent (m.params.title)
- const version = url.searchParams.get ('version') || undefined
-
- const wikiPage = await qc.fetchQuery ({
- queryKey: wikiKeys.show (title, { version }),
- queryFn: () => fetchWikiPageByTitle (title, { version }) })
-
- const effectiveTitle = wikiPage.title
-
- await qc.prefetchQuery ({
- queryKey: tagsKeys.show (effectiveTitle),
- queryFn: () => fetchTagByName (effectiveTitle) })
-
- if (version)
- return
-
- const p = { tags: effectiveTitle, match: 'all', page: 1, limit: 8 } as const
- await qc.prefetchQuery ({
- queryKey: postsKeys.index (p),
- queryFn: () => fetchPosts (p) })
- }
-
-
- const prefetchPostsIndex: Prefetcher = async (qc, url) => {
- const tags = url.searchParams.get ('tags') ?? ''
- const m = url.searchParams.get ('match') === 'any' ? 'any' : 'all'
- const page = Number (url.searchParams.get ('page') || 1)
- const limit = Number (url.searchParams.get ('limit') || 20)
-
- await qc.prefetchQuery ({
- queryKey: postsKeys.index ({ tags, match: m, page, limit }),
- queryFn: () => fetchPosts ({ tags, match: m, page, limit }) })
- }
-
-
- const prefetchPostShow: Prefetcher = async (qc, url) => {
- const m = mPost (url.pathname)
- if (!(m))
- return
-
- const { id } = m.params
-
- await qc.prefetchQuery ({
- queryKey: postsKeys.show (id),
- queryFn: () => fetchPost (id) })
- }
-
-
- const prefetchPostChanges: Prefetcher = async (qc, url) => {
- const id = url.searchParams.get ('id')
- const page = Number (url.searchParams.get ('page') || 1)
- const limit = Number (url.searchParams.get ('limit') || 20)
-
- await qc.prefetchQuery ({
- queryKey: postsKeys.changes ({ ...(id && { id }), page, limit }),
- queryFn: () => fetchPostChanges ({ ...(id && { id }), page, limit }) })
- }
-
-
- export const routePrefetchers: { test: (u: URL) => boolean; run: Prefetcher }[] = [
- { test: u => u.pathname === '/' || u.pathname === '/posts', run: prefetchPostsIndex },
- { test: u => (!(['/posts/new', '/posts/changes'].includes (u.pathname))
- && Boolean (mPost (u.pathname))),
- run: prefetchPostShow },
- { test: u => u.pathname === '/posts/changes', run: prefetchPostChanges },
- { test: u => u.pathname === '/wiki', run: prefetchWikiPagesIndex },
- { test: u => (!(['/wiki/new', '/wiki/changes'].includes (u.pathname))
- && Boolean (mWiki (u.pathname))),
- run: prefetchWikiPageShow },
- ]
-
-
- export const prefetchForURL = async (qc: QueryClient, urlLike: string): Promise<void> => {
- const u = new URL (urlLike, location.origin)
- const jobs = routePrefetchers.filter (r => r.test (u)).map (r => r.run (qc, u))
- if (jobs.length === 0)
- return
-
- await Promise.all (jobs)
- }
|