|
- 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, fetchTag, fetchTags } from '@/lib/tags'
- import { fetchWikiPage,
- fetchWikiPageByTitle,
- fetchWikiPages } from '@/lib/wiki'
-
- import type { Category, FetchPostsOrder, FetchTagsOrder } from '@/types'
-
- 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 }) })
-
- if (wikiPage)
- {
- const effectiveId = String (wikiPage.id ?? '')
- await qc.prefetchQuery ({
- queryKey: wikiKeys.show (effectiveId, { }),
- queryFn: () => fetchWikiPage (effectiveId, { } ) })
-
- if (wikiPage.body)
- {
- await qc.prefetchQuery ({
- queryKey: wikiKeys.index ({ }),
- queryFn: () => fetchWikiPages ({ }) })
- }
- }
-
- const effectiveTitle = wikiPage?.title ?? title
-
- await qc.prefetchQuery ({
- queryKey: tagsKeys.show (effectiveTitle),
- queryFn: () => fetchTagByName (effectiveTitle) })
-
- if (version)
- return
-
- const p = {
- tags: effectiveTitle,
- match: 'all',
- page: 1,
- limit: 8,
- url: '',
- title: '',
- originalCreatedFrom: '',
- originalCreatedTo: '',
- createdFrom: '',
- createdTo: '',
- updatedFrom: '',
- updatedTo: '',
- order: 'original_created_at:desc' } 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 qURL = url.searchParams.get ('url') ?? ''
- const title = url.searchParams.get ('title') ?? ''
- const originalCreatedFrom = url.searchParams.get ('original_created_from') ?? ''
- const originalCreatedTo = url.searchParams.get ('original_created_to') ?? ''
- const createdFrom = url.searchParams.get ('created_from') ?? ''
- const createdTo = url.searchParams.get ('created_to') ?? ''
- const updatedFrom = url.searchParams.get ('updated_from') ?? ''
- const updatedTo = url.searchParams.get ('updated_to') ?? ''
- const m: 'all' | 'any' = url.searchParams.get ('match') === 'any' ? 'any' : 'all'
- const page = Number (url.searchParams.get ('page') || 1)
- const limit = Number (url.searchParams.get ('limit') || 20)
- const order = (url.searchParams.get ('order') ?? 'original_created_at:desc') as FetchPostsOrder
-
- const keys = {
- tags, match: m, page, limit, url: qURL, title,
- originalCreatedFrom, originalCreatedTo, createdFrom, createdTo,
- updatedFrom, updatedTo, order }
-
- await qc.prefetchQuery ({
- queryKey: postsKeys.index (keys),
- queryFn: () => fetchPosts (keys) })
- }
-
-
- 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 tag = url.searchParams.get ('tag')
- const page = Number (url.searchParams.get ('page') || 1)
- const limit = Number (url.searchParams.get ('limit') || 20)
-
- if (tag)
- {
- await qc.prefetchQuery ({
- queryKey: tagsKeys.show (tag),
- queryFn: () => fetchTag (tag) })
- }
-
- await qc.prefetchQuery ({
- queryKey: postsKeys.changes ({ ...(id && { id }),
- ...(tag && { tag }),
- page, limit }),
- queryFn: () => fetchPostChanges ({ ...(id && { id }),
- ...(tag && { tag }),
- page, limit }) })
- }
-
-
- const prefetchTagsIndex: Prefetcher = async (qc, url) => {
- const postRaw = url.searchParams.get ('post')
- const post = postRaw ? Number (postRaw) : null
- const name = url.searchParams.get ('name') ?? ''
- const category = (url.searchParams.get ('category') || null) as Category | null
- const postCountGTE = Number (url.searchParams.get ('post_count_gte') || 1)
- const postCountLTERaw = url.searchParams.get ('post_count_lte')
- const postCountLTE = postCountLTERaw ? Number (postCountLTERaw) : null
- const createdFrom = url.searchParams.get ('created_from') ?? ''
- const createdTo = url.searchParams.get ('created_to') ?? ''
- const updatedFrom = url.searchParams.get ('updated_from') ?? ''
- const updatedTo = url.searchParams.get ('updated_to') ?? ''
- const page = Number (url.searchParams.get ('page') || 1)
- const limit = Number (url.searchParams.get ('limit') || 20)
- const order = (url.searchParams.get ('order') ?? 'post_count:desc') as FetchTagsOrder
-
- const keys = {
- post, name, category, postCountGTE, postCountLTE, createdFrom, createdTo,
- updatedFrom, updatedTo, page, limit, order }
-
- await qc.prefetchQuery ({
- queryKey: tagsKeys.index (keys),
- queryFn: () => fetchTags (keys) })
- }
-
-
- export const routePrefetchers: { test: (u: URL) => boolean; run: Prefetcher }[] = [
- { test: u => ['/', '/posts', '/posts/search'].includes (u.pathname),
- run: prefetchPostsIndex },
- { test: u => (!(['/posts/new', '/posts/changes', '/posts/search'].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 },
- { test: u => u.pathname === '/tags', run: prefetchTagsIndex }]
-
-
- export const prefetchForURL = async (qc: QueryClient, urlLike: string): Promise<void> => {
- const u = new URL (urlLike, location.origin)
- const r = routePrefetchers.find (x => x.test (u))
- if (!(r))
- return
-
- await r.run (qc, u)
- }
|