feat: use ofetch

This commit is contained in:
DIYgod 2024-05-13 22:03:43 +08:00
parent 85b13634f6
commit 2d30d7100b
No known key found for this signature in database
9 changed files with 105 additions and 120 deletions

View File

@ -57,6 +57,7 @@
"hast-util-to-jsx-runtime": "2.3.0",
"lethargy": "1.0.9",
"lucide-react": "0.378.0",
"ofetch": "1.3.4",
"react-hook-form": "7.51.4",
"react-router-dom": "6.23.1",
"rehype-infer-description-meta": "2.0.0",

View File

@ -104,6 +104,9 @@ importers:
lucide-react:
specifier: 0.378.0
version: 0.378.0(react@18.3.1)
ofetch:
specifier: 1.3.4
version: 1.3.4
react-hook-form:
specifier: 7.51.4
version: 7.51.4(react@18.3.1)
@ -2094,6 +2097,9 @@ packages:
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
engines: {node: '>=6'}
destr@2.0.3:
resolution: {integrity: sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ==}
detect-libc@2.0.3:
resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==}
engines: {node: '>=8'}
@ -3344,6 +3350,9 @@ packages:
node-api-version@0.2.0:
resolution: {integrity: sha512-fthTTsi8CxaBXMaBAD7ST2uylwvsnYxh2PfaScwpMhos6KlSFajXQPcM4ogNE1q2s3Lbz9GCGqeIHC+C6OZnKg==}
node-fetch-native@1.6.4:
resolution: {integrity: sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==}
node-gyp@9.4.1:
resolution: {integrity: sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==}
engines: {node: ^12.13 || ^14.13 || >=16}
@ -3421,6 +3430,9 @@ packages:
resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==}
engines: {node: '>= 0.4'}
ofetch@1.3.4:
resolution: {integrity: sha512-KLIET85ik3vhEfS+3fDlc/BAZiAp+43QEC/yCo5zkNoY2YaKvNkOaFr/6wCFgFH1kuYQM5pMNi0Tg8koiIemtw==}
once@1.4.0:
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
@ -6423,6 +6435,8 @@ snapshots:
dequal@2.0.3: {}
destr@2.0.3: {}
detect-libc@2.0.3: {}
detect-node-es@1.1.0: {}
@ -8111,6 +8125,8 @@ snapshots:
dependencies:
semver: 7.6.2
node-fetch-native@1.6.4: {}
node-gyp@9.4.1:
dependencies:
env-paths: 2.2.1
@ -8201,6 +8217,12 @@ snapshots:
define-properties: 1.2.1
es-object-atoms: 1.0.0
ofetch@1.3.4:
dependencies:
destr: 2.0.3
node-fetch-native: 1.6.4
ufo: 1.5.3
once@1.4.0:
dependencies:
wrappy: 1.0.2

View File

@ -18,10 +18,10 @@ import {
ContextMenuSeparator,
} from "@renderer/components/ui/context-menu"
import { useMutation, useQueryClient } from "@tanstack/react-query"
import { getCsrfToken } from "@hono/auth-js/react"
import { useToast } from "@renderer/components/ui/use-toast"
import { ToastAction } from "@renderer/components/ui/toast"
import { SubscriptionResponse } from "@renderer/lib/types"
import { apiFetch } from "@renderer/lib/queries/api-fetch"
export function FeedList({
className,
@ -93,23 +93,13 @@ function FeedCategory({
const queryClient = useQueryClient()
const deleteMutation = useMutation({
mutationFn: async (feed: SubscriptionResponse[number]) => {
return (
await (
await fetch(`${import.meta.env.VITE_API_URL}/subscriptions`, {
method: "DELETE",
headers: {
"Content-Type": "application/json",
},
credentials: "include",
body: JSON.stringify({
feedId: feed.feedId,
csrfToken: await getCsrfToken(),
}),
})
).json()
).data
},
mutationFn: async (feed: SubscriptionResponse[number]) =>
apiFetch("/subscriptions", {
method: "DELETE",
body: {
feedId: feed.feedId,
},
}),
onSuccess: (_, variables) => {
queryClient.invalidateQueries({
queryKey: ["subscriptions", view],
@ -126,19 +116,14 @@ function FeedCategory({
<ToastAction
altText="Undo"
onClick={async () => {
await fetch(`${import.meta.env.VITE_API_URL}/subscriptions`, {
await apiFetch("/subscriptions", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
credentials: "include",
body: JSON.stringify({
body: {
url: variables.feeds.url,
view,
category: variables.category,
// private: variables.private,
csrfToken: await getCsrfToken(),
}),
},
})
queryClient.invalidateQueries({
queryKey: ["subscriptions", view],

View File

@ -12,7 +12,6 @@ import {
} from "@renderer/components/ui/form"
import { Input } from "@renderer/components/ui/input"
import { useMutation, useQueryClient } from "@tanstack/react-query"
import { getCsrfToken } from "@hono/auth-js/react"
import {
DialogContent,
DialogHeader,
@ -31,6 +30,7 @@ import { views } from "@renderer/lib/constants"
import { cn } from "@renderer/lib/utils"
import { Switch } from "@renderer/components/ui/switch"
import { FollowSummary } from "../feed-summary"
import { apiFetch } from "@renderer/lib/queries/api-fetch"
const formSchema = z.object({
view: z.enum(["0", "1", "2", "3", "4", "5"]),
@ -54,26 +54,16 @@ export function FollowDialog({
const queryClient = useQueryClient()
const followMutation = useMutation({
mutationFn: async (values: z.infer<typeof formSchema>) => {
return (
await (
await fetch(`${import.meta.env.VITE_API_URL}/subscriptions`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
credentials: "include",
body: JSON.stringify({
url: feed.url,
view: parseInt(values.view),
category: values.category,
private: values.private,
csrfToken: await getCsrfToken(),
}),
})
).json()
).data
},
mutationFn: async (values: z.infer<typeof formSchema>) =>
apiFetch("/subscriptions", {
method: "POST",
body: {
url: feed.url,
view: parseInt(values.view),
category: values.category,
private: values.private,
},
}),
onSuccess: (_, variables) => {
queryClient.invalidateQueries({
queryKey: ["subscriptions", parseInt(variables.view)],

View File

@ -13,7 +13,6 @@ import {
import { Input } from "@renderer/components/ui/input"
import { useEffect } from "react"
import { useMutation } from "@tanstack/react-query"
import { getCsrfToken } from "@hono/auth-js/react"
import { Image } from "@renderer/components/ui/image"
import { FeedResponse, EntriesResponse } from "@renderer/lib/types"
import {
@ -24,6 +23,7 @@ import {
} from "@renderer/components/ui/card"
import { FollowButton } from "./button"
import { FollowSummary } from "../feed-summary"
import { apiFetch } from "@renderer/lib/queries/api-fetch"
const formSchema = z.object({
keyword: z.string().min(1),
@ -61,28 +61,22 @@ export function FollowForm({ type }: { type: string }) {
})
const mutation = useMutation({
mutationFn: async (keyword: string) => {
return (
await (
await fetch(`${import.meta.env.VITE_API_URL}/discover`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
credentials: "include",
body: JSON.stringify({
csrfToken: await getCsrfToken(),
keyword,
type: type === "rss" ? "rss" : "auto",
}),
})
).json()
).data as {
feed: Partial<FeedResponse>
docs?: string
entries?: Partial<EntriesResponse>
isSubscribed?: boolean
subscriptionCount?: number
}[]
const { data } = await apiFetch<{
data: {
feed: Partial<FeedResponse>
docs?: string
entries?: Partial<EntriesResponse>
isSubscribed?: boolean
subscriptionCount?: number
}[]
}>("/discover", {
method: "POST",
body: {
keyword,
type: type === "rss" ? "rss" : "auto",
},
})
return data
},
})

View File

@ -0,0 +1,19 @@
import { ofetch } from "ofetch"
import { getCsrfToken } from "@hono/auth-js/react"
export const apiFetch = ofetch.create({
baseURL: import.meta.env.VITE_API_URL,
headers: {
"Content-Type": "application/json",
},
credentials: "include",
onRequest: async ({ options }) => {
if (options.method && options.method.toLowerCase() !== "get") {
const csrfToken = await getCsrfToken()
if (!options.body) {
options.body = {}
}
;(options.body as Record<string, any>).csrfToken = csrfToken
}
},
})

View File

@ -1,6 +1,7 @@
import { useInfiniteQuery } from "@tanstack/react-query"
import { levels } from "@renderer/lib/constants"
import { EntriesResponse, ListResponse } from "../types"
import { apiFetch } from "@renderer/lib/queries/api-fetch"
export const useEntries = ({
level,
@ -13,8 +14,6 @@ export const useEntries = ({
queryKey: ["entries", level, id],
enabled: level !== undefined && id !== undefined,
queryFn: async ({ pageParam }) => {
let entries: ListResponse<EntriesResponse> | null = null
const baseUrl = `${import.meta.env.VITE_API_URL}/entries?`
const params: {
category?: string
view?: string
@ -27,26 +26,12 @@ export const useEntries = ({
} else if (level === levels.feed) {
params.feedId = id + ""
}
entries = await (
await fetch(
baseUrl +
new URLSearchParams({
offset: pageParam + "",
...params,
}),
{
credentials: "include",
},
)
).json()
if (!entries) {
entries = {
code: -1,
}
}
return entries
return await apiFetch<ListResponse<EntriesResponse>>("/entries", {
query: {
offset: pageParam + "",
...params,
},
})
},
getNextPageParam: (lastPage, _, lastPageParam) =>
lastPageParam + (lastPage.data?.length || 0),

View File

@ -1,5 +1,6 @@
import { useQuery } from "@tanstack/react-query"
import { SubscriptionResponse } from "../types"
import { apiFetch } from "@renderer/lib/queries/api-fetch"
export type Response = {
list: {
@ -14,17 +15,13 @@ export const useSubscriptions = (view?: number) =>
useQuery({
queryKey: ["subscriptions", view],
queryFn: async () => {
const subscriptions = (
await (
await fetch(
`${import.meta.env.VITE_API_URL}/subscriptions` +
(view !== undefined ? `?view=${view}` : ``),
{
credentials: "include",
},
)
).json()
).data as SubscriptionResponse
const { data: subscriptions } = await apiFetch<{
data: SubscriptionResponse
}>("/subscriptions", {
query: {
view,
},
})
const categories = {
list: {},

View File

@ -1,29 +1,21 @@
import { Button } from "@renderer/components/ui/button"
import { UserButton } from "@renderer/components/user-button"
import { getCsrfToken, authConfigManager } from "@hono/auth-js/react"
import { useEffect } from "react"
import { useNavigate } from "react-router-dom"
import { apiFetch } from "@renderer/lib/queries/api-fetch"
export function Component() {
const navigate = useNavigate()
const getCallbackUrl = async () => {
const response = await (
await fetch(
`${authConfigManager.getConfig().baseUrl}/auth-app/new-session`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
credentials: "include",
body: JSON.stringify({
csrfToken: await getCsrfToken(),
}),
},
)
).json()
return `follow://auth?token=${response.data.sessionToken}`
const { data } = await apiFetch<{
data: {
sessionToken: string
}
}>("/auth-app/new-session", {
method: "POST",
})
return `follow://auth?token=${data.sessionToken}`
}
useEffect(() => {