refactor: 更好的orpc结构

This commit is contained in:
2026-01-22 16:37:10 +08:00
parent 660ee0a545
commit 2b3e91167e
20 changed files with 53 additions and 28 deletions

View File

@@ -1 +0,0 @@
export * from './db'

View File

@@ -1,7 +0,0 @@
import { implement } from '@orpc/server'
import { contract } from './contract'
// biome-ignore lint/complexity/noBannedTypes: 暂无 context
type Context = {}
export const os = implement(contract).$context<Context>()

View File

@@ -3,8 +3,8 @@ import { RPCLink } from '@orpc/client/fetch'
import { createRouterClient } from '@orpc/server'
import { createIsomorphicFn } from '@tanstack/react-start'
import { getRequestHeaders } from '@tanstack/react-start/server'
import { router } from '@/api/routers'
import type { RouterClient } from '@/api/types'
import { router } from '@/server/api/routers'
import type { RouterClient } from '@/server/api/types'
const getORPCClient = createIsomorphicFn()
.server(() =>
@@ -21,4 +21,4 @@ const getORPCClient = createIsomorphicFn()
return createORPCClient<RouterClient>(link)
})
export const client: RouterClient = getORPCClient()
export const orpc: RouterClient = getORPCClient()

View File

@@ -1,7 +1,7 @@
import { createTanstackQueryUtils } from '@orpc/tanstack-query'
import { client } from './client'
import { orpc as orpcClient } from './orpc.client'
export const orpc = createTanstackQueryUtils(client, {
export const orpc = createTanstackQueryUtils(orpcClient, {
experimental_defaults: {
todo: {
create: {

View File

@@ -2,7 +2,7 @@ import { ORPCError, onError, ValidationError } from '@orpc/server'
import { RPCHandler } from '@orpc/server/fetch'
import { createFileRoute } from '@tanstack/react-router'
import { z } from 'zod'
import { router } from '@/api/routers'
import { router } from '@/server/api/routers'
const handler = new RPCHandler(router, {
interceptors: [
@@ -49,7 +49,9 @@ export const Route = createFileRoute('/api/rpc/$')({
ANY: async ({ request }) => {
const { response } = await handler.handle(request, {
prefix: '/api/rpc',
context: {},
context: {
headers: request.headers,
},
})
return response ?? new Response('Not Found', { status: 404 })

View File

@@ -4,7 +4,7 @@ import { isTauri } from '@tauri-apps/api/core'
import { getCurrentWindow } from '@tauri-apps/api/window'
import type { ChangeEventHandler, FormEventHandler } from 'react'
import { useEffect, useState } from 'react'
import { orpc } from '@/lib/orpc/query-client'
import { orpc } from '@/client/query-client'
export const Route = createFileRoute('/')({
component: Todos,

View File

@@ -0,0 +1,25 @@
import type { Database } from '@/server/db'
/**
* 基础 Context - 所有请求都包含的上下文
*/
export interface BaseContext {
headers: Headers
}
/**
* 数据库 Context - 通过 db middleware 扩展
*/
export interface DBContext extends BaseContext {
db: Database
}
/**
* 认证 Context - 通过 auth middleware 扩展(未来使用)
*
* @example
* export interface AuthContext extends DBContext {
* userId: string
* user: User
* }
*/

View File

@@ -1,4 +1,4 @@
import * as todo from './todo'
import * as todo from './todo.contract'
export const contract = {
todo,

View File

@@ -5,7 +5,7 @@ import {
createUpdateSchema,
} from 'drizzle-zod'
import { z } from 'zod'
import { todoTable } from '@/db/schema'
import { todoTable } from '@/server/db/schema'
const selectSchema = createSelectSchema(todoTable)

View File

@@ -1,5 +1,5 @@
import { os } from '@orpc/server'
import { getDb } from '@/db'
import { getDb } from '@/server/db'
export const db = os.middleware(async ({ context, next }) => {
return next({

View File

@@ -0,0 +1 @@
export * from './db.middleware'

View File

@@ -1,5 +1,5 @@
import { os } from '../server'
import * as todo from './todo'
import * as todo from './todo.router'
export const router = os.router({
todo,

View File

@@ -1,8 +1,8 @@
import { ORPCError } from '@orpc/server'
import { eq } from 'drizzle-orm'
import { db } from '@/api/middlewares'
import { os } from '@/api/server'
import { todoTable } from '@/db/schema'
import { todoTable } from '@/server/db/schema'
import { db } from '../middlewares'
import { os } from '../server'
export const list = os.todo.list.use(db).handler(async ({ context }) => {
const todos = await context.db.query.todoTable.findMany({

View File

@@ -0,0 +1,5 @@
import { implement } from '@orpc/server'
import type { BaseContext } from './context'
import { contract } from './contracts'
export const os = implement(contract).$context<BaseContext>()

View File

@@ -3,7 +3,7 @@ import type {
InferContractRouterInputs,
InferContractRouterOutputs,
} from '@orpc/contract'
import type { Contract } from './contract'
import type { Contract } from './contracts'
export type RouterClient = ContractRouterClient<Contract>
export type RouterInputs = InferContractRouterInputs<Contract>

View File

@@ -1,6 +1,6 @@
import { drizzle } from 'drizzle-orm/postgres-js'
import * as schema from '@/db/schema'
import { env } from '@/env'
import * as schema from '@/server/db/schema'
export const createDb = () =>
drizzle({
@@ -11,12 +11,12 @@ export const createDb = () =>
schema,
})
export type Db = ReturnType<typeof createDb>
export type Database = ReturnType<typeof createDb>
export const getDb = (() => {
let db: Db | null = null
let db: Database | null = null
return (singleton = true): Db => {
return (singleton = true): Database => {
if (!singleton) {
return createDb()
}