forked from imbytecat/fullstack-starter
refactor(arch): 移除 experimental_defaults,提炼 useInvalidateTodos,闭环若干悬挂配置
- orpc.ts: 改为纯 createTanstackQueryUtils,不再依赖 experimental_ API - 抽出 src/client/queries/todo.ts 的 useInvalidateTodos,避免 query key 散落页面 - shutdown: setTimeout 内 db.$client.end() 失败也走 process.exit - 删除 db/index.ts 未被使用的 DB 类型导出 - 删除 env.ts 未被消费的 VITE_APP_TITLE,根 title 改为 package.json name - 清理 routes/index.tsx 的 JSX 区段注释、compose.yaml 注释掉的端口块、robots.txt URL 注释
This commit is contained in:
@@ -23,8 +23,6 @@ services:
|
|||||||
|
|
||||||
db:
|
db:
|
||||||
image: postgres:18-alpine
|
image: postgres:18-alpine
|
||||||
# ports:
|
|
||||||
# - "5432:5432"
|
|
||||||
volumes:
|
volumes:
|
||||||
- postgres_data:/var/lib/postgresql
|
- postgres_data:/var/lib/postgresql
|
||||||
environment:
|
environment:
|
||||||
|
|||||||
@@ -1,3 +1,2 @@
|
|||||||
# https://www.robotstxt.org/robotstxt.html
|
|
||||||
User-agent: *
|
User-agent: *
|
||||||
Disallow:
|
Disallow:
|
||||||
|
|||||||
+1
-27
@@ -24,30 +24,4 @@ const getORPCClient = createIsomorphicFn()
|
|||||||
|
|
||||||
const client: RouterClient = getORPCClient()
|
const client: RouterClient = getORPCClient()
|
||||||
|
|
||||||
export const orpc = createTanstackQueryUtils(client, {
|
export const orpc = createTanstackQueryUtils(client)
|
||||||
experimental_defaults: {
|
|
||||||
todo: {
|
|
||||||
create: {
|
|
||||||
mutationOptions: {
|
|
||||||
onSuccess: (_, __, ___, ctx) => {
|
|
||||||
ctx.client.invalidateQueries({ queryKey: orpc.todo.list.key() })
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
update: {
|
|
||||||
mutationOptions: {
|
|
||||||
onSuccess: (_, __, ___, ctx) => {
|
|
||||||
ctx.client.invalidateQueries({ queryKey: orpc.todo.list.key() })
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
remove: {
|
|
||||||
mutationOptions: {
|
|
||||||
onSuccess: (_, __, ___, ctx) => {
|
|
||||||
ctx.client.invalidateQueries({ queryKey: orpc.todo.list.key() })
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { useQueryClient } from '@tanstack/react-query'
|
||||||
|
import { orpc } from '@/client/orpc'
|
||||||
|
|
||||||
|
export const useInvalidateTodos = () => {
|
||||||
|
const queryClient = useQueryClient()
|
||||||
|
return () => queryClient.invalidateQueries({ queryKey: orpc.todo.list.key() })
|
||||||
|
}
|
||||||
+1
-3
@@ -6,9 +6,7 @@ export const env = createEnv({
|
|||||||
DATABASE_URL: z.url(),
|
DATABASE_URL: z.url(),
|
||||||
},
|
},
|
||||||
clientPrefix: 'VITE_',
|
clientPrefix: 'VITE_',
|
||||||
client: {
|
client: {},
|
||||||
VITE_APP_TITLE: z.string().min(1).optional(),
|
|
||||||
},
|
|
||||||
runtimeEnv: process.env,
|
runtimeEnv: process.env,
|
||||||
emptyStringAsUndefined: true,
|
emptyStringAsUndefined: true,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { ReactQueryDevtoolsPanel } from '@tanstack/react-query-devtools'
|
|||||||
import { createRootRouteWithContext, HeadContent, Scripts } from '@tanstack/react-router'
|
import { createRootRouteWithContext, HeadContent, Scripts } from '@tanstack/react-router'
|
||||||
import { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools'
|
import { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools'
|
||||||
import type { ReactNode } from 'react'
|
import type { ReactNode } from 'react'
|
||||||
|
import { name } from '@/../package.json'
|
||||||
import { ErrorComponent } from '@/components/Error'
|
import { ErrorComponent } from '@/components/Error'
|
||||||
import { NotFoundComponent } from '@/components/NotFound'
|
import { NotFoundComponent } from '@/components/NotFound'
|
||||||
import appCss from '@/styles.css?url'
|
import appCss from '@/styles.css?url'
|
||||||
@@ -23,7 +24,7 @@ export const Route = createRootRouteWithContext<RouterContext>()({
|
|||||||
content: 'width=device-width, initial-scale=1',
|
content: 'width=device-width, initial-scale=1',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Furtherverse',
|
title: name,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
links: [
|
links: [
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useMutation, useSuspenseQuery } from '@tanstack/react-query'
|
import { useMutation, useSuspenseQuery } from '@tanstack/react-query'
|
||||||
import { createFileRoute } from '@tanstack/react-router'
|
import { createFileRoute } from '@tanstack/react-router'
|
||||||
import { orpc } from '@/client/orpc'
|
import { orpc } from '@/client/orpc'
|
||||||
|
import { useInvalidateTodos } from '@/client/queries/todo'
|
||||||
import { TodoForm } from '@/components/TodoForm'
|
import { TodoForm } from '@/components/TodoForm'
|
||||||
import { TodoItem } from '@/components/TodoItem'
|
import { TodoItem } from '@/components/TodoItem'
|
||||||
|
|
||||||
@@ -13,9 +14,11 @@ export const Route = createFileRoute('/')({
|
|||||||
|
|
||||||
function Todos() {
|
function Todos() {
|
||||||
const listQuery = useSuspenseQuery(orpc.todo.list.queryOptions())
|
const listQuery = useSuspenseQuery(orpc.todo.list.queryOptions())
|
||||||
const createMutation = useMutation(orpc.todo.create.mutationOptions())
|
const invalidateTodos = useInvalidateTodos()
|
||||||
const updateMutation = useMutation(orpc.todo.update.mutationOptions())
|
|
||||||
const deleteMutation = useMutation(orpc.todo.remove.mutationOptions())
|
const createMutation = useMutation(orpc.todo.create.mutationOptions({ onSuccess: invalidateTodos }))
|
||||||
|
const updateMutation = useMutation(orpc.todo.update.mutationOptions({ onSuccess: invalidateTodos }))
|
||||||
|
const deleteMutation = useMutation(orpc.todo.remove.mutationOptions({ onSuccess: invalidateTodos }))
|
||||||
|
|
||||||
const todos = listQuery.data
|
const todos = listQuery.data
|
||||||
const completedCount = todos.filter((todo) => todo.completed).length
|
const completedCount = todos.filter((todo) => todo.completed).length
|
||||||
@@ -25,7 +28,6 @@ function Todos() {
|
|||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-slate-50 py-12 px-4 sm:px-6 font-sans">
|
<div className="min-h-screen bg-slate-50 py-12 px-4 sm:px-6 font-sans">
|
||||||
<div className="max-w-2xl mx-auto space-y-8">
|
<div className="max-w-2xl mx-auto space-y-8">
|
||||||
{/* Header */}
|
|
||||||
<div className="flex items-end justify-between">
|
<div className="flex items-end justify-between">
|
||||||
<div>
|
<div>
|
||||||
<h1 className="text-3xl font-bold text-slate-900 tracking-tight">我的待办</h1>
|
<h1 className="text-3xl font-bold text-slate-900 tracking-tight">我的待办</h1>
|
||||||
@@ -42,7 +44,6 @@ function Todos() {
|
|||||||
|
|
||||||
<TodoForm onSubmit={(title) => createMutation.mutate({ title })} isPending={createMutation.isPending} />
|
<TodoForm onSubmit={(title) => createMutation.mutate({ title })} isPending={createMutation.isPending} />
|
||||||
|
|
||||||
{/* Progress Bar */}
|
|
||||||
{totalCount > 0 && (
|
{totalCount > 0 && (
|
||||||
<div className="h-1.5 w-full bg-slate-200 rounded-full overflow-hidden">
|
<div className="h-1.5 w-full bg-slate-200 rounded-full overflow-hidden">
|
||||||
<div
|
<div
|
||||||
@@ -52,7 +53,6 @@ function Todos() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Todo List */}
|
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
{todos.length === 0 ? (
|
{todos.length === 0 ? (
|
||||||
<div className="py-20 text-center">
|
<div className="py-20 text-center">
|
||||||
|
|||||||
@@ -6,5 +6,3 @@ export const db = drizzle({
|
|||||||
connection: env.DATABASE_URL,
|
connection: env.DATABASE_URL,
|
||||||
schema,
|
schema,
|
||||||
})
|
})
|
||||||
|
|
||||||
export type DB = typeof db
|
|
||||||
|
|||||||
@@ -5,15 +5,14 @@ export default () => {
|
|||||||
|
|
||||||
let exiting = false
|
let exiting = false
|
||||||
|
|
||||||
const shutdown = async () => {
|
const shutdown = () => {
|
||||||
if (exiting) {
|
if (exiting) {
|
||||||
process.exit(0)
|
process.exit(0)
|
||||||
}
|
}
|
||||||
exiting = true
|
exiting = true
|
||||||
|
|
||||||
setTimeout(async () => {
|
setTimeout(() => {
|
||||||
await db.$client.end()
|
db.$client.end().finally(() => process.exit(0))
|
||||||
process.exit(0)
|
|
||||||
}, 500)
|
}, 500)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user