6235b293f0
#321 #321 Co-authored-by: miteruzo <miteruzo@naver.com> Reviewed-on: #330
223 lines
7.4 KiB
TypeScript
223 lines
7.4 KiB
TypeScript
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, fetchTagChanges, 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 mTag = match<{ id: string }> ('/tags/:id')
|
|
|
|
|
|
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) })
|
|
}
|
|
|
|
|
|
const prefetchTagShow: Prefetcher = async (qc, url) => {
|
|
const m = mTag (url.pathname)
|
|
if (!(m))
|
|
return
|
|
|
|
const { id } = m.params
|
|
|
|
await qc.prefetchQuery ({
|
|
queryKey: tagsKeys.show (id),
|
|
queryFn: () => fetchTag (id) })
|
|
}
|
|
|
|
|
|
const prefetchTagChanges: 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: tagsKeys.changes ({ ...(id && { id }), page, limit }),
|
|
queryFn: () => fetchTagChanges ({ ...(id && { id }), page, limit }) })
|
|
}
|
|
|
|
|
|
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 },
|
|
{ test: u => (!(['/tags/nico', '/tags/changes'].includes (u.pathname))
|
|
&& Boolean (mTag (u.pathname))),
|
|
run: prefetchTagShow },
|
|
{ test: u => u.pathname === '/tags/changes', run: prefetchTagChanges }]
|
|
|
|
|
|
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)
|
|
}
|