Open
Description
Docs: https://trpc.io/
Server.ts:
export class Server {
@Inject()
protected app: PlatformApplication
.....
@Inject()
protected trpcService: tRPCservice
.....
}
/router/userRouter.ts:
import { z } from 'zod'
import { publicProcedure, t } from '../createRouterHelper'
import { LocalProtocol } from '../../protocols'
import { Inject, Injectable } from '@tsed/di'
@Injectable()
export class UserRouter {
@Inject()
private localAuthProtocol: LocalProtocol
init() {
return t.router({
login: publicProcedure
.input(
z.object({
login: z.string(),
password: z.string().or(z.number())
})
)
.mutation(async (req) => {
return await this.localAuthProtocol.$onVerify(req.ctx.req, req.input)
}),
})
}
}
createRouterHelper.ts:
import * as trpc from '@trpc/server'
import { TRPCError } from '@trpc/server'
import superjson from 'superjson'
import { Context } from './context'
export const t = trpc.initTRPC.context<Context>().create({
transformer: superjson
})
export const trpcRouter = t.router
export const publicProcedure = t.procedure
export const middleware = t.middleware
export const mergeRouters = t.mergeRouters
export const isAuthMiddleware = middleware(async ({ ctx, next }) => {
if (!ctx.user?.id) {
throw new TRPCError({ code: 'UNAUTHORIZED' })
}
return next({
ctx
})
})
export const authProcedure = publicProcedure.use(isAuthMiddleware)
router.ts:
import { UserRouter } from "./routes/userRouter";
import { trpcRouter } from "./createRouterHelper";
import { Inject, Injectable } from "@tsed/di";
@Injectable()
export class TRPCRouter {
@Inject()
private userRouter: UserRouter;
createRouter() {
return trpcRouter({
user: this.userRouter.init(),
});
}
}
export type AppRouter = ReturnType<TRPCRouter["createRouter"]>;
context.ts:
import { User } from "@prisma/client"
import { Inject, Injectable, ProviderScope, Scope } from "@tsed/di"
import { $prisma } from "../PrismaInstance"
import * as jwt from 'jsonwebtoken'
import * as trpcExpress from '@trpc/server/adapters/express'
import { JwtProtocol } from "../protocols"
import { inferAsyncReturnType } from "@trpc/server"
@Injectable()
@Scope(ProviderScope.SINGLETON)
export class TRPCContext {
@Inject()
private jwtProtocol: JwtProtocol
//DEMO verify jwt
private verifyJwt(req: trpcExpress.CreateExpressContextOptions['req']) {
let token = String(req.headers.authorization).split(' ')[1]
return (token && jwt.verify(token, 'thisismysupersecretprivatekey1')) || undefined
}
async createContext({ req, res }: trpcExpress.CreateExpressContextOptions) {
let user: User | undefined | null = undefined
try { user = await this.jwtProtocol.$onVerify(req, this.verifyJwt(req))} catch (error) {}
return { req, res, user, prisma: $prisma }
}
}
export type Context = inferAsyncReturnType<TRPCContext['createContext']>
tRPCservice.ts:
import { Injectable, Inject } from '@tsed/di'
import { PlatformApplication, Req, Res } from '@tsed/common'
import * as trpcExpress from '@trpc/server/adapters/express'
import { TRPCRouter } from './router'
import { TRPCContext } from './context'
@Injectable()
export class tRPCservice {
@Inject()
protected app: PlatformApplication<Express.Application>
@Inject()
trpcRouter: TRPCRouter
@Inject()
trpcContext: TRPCContext
async $onInit() {
const trpcApiEndpoint = '/trpc'
const routes = this.trpcRouter.createRouter()
const createContext = this.trpcContext.createContext.bind(this.trpcContext)
this.app
.use((req: Req, res: Res, next: () => void) => {
res.setHeader('Access-Control-Allow-Origin', '*')
res.setHeader('Access-Control-Request-Method', '*')
res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET')
res.setHeader('Access-Control-Allow-Headers', '*')
// res.header("Access-Control-Allow-Credentials", "true")
if (req.method === 'OPTIONS') {
return res.status(200).end()
}
next()
})
.use(
trpcApiEndpoint,
trpcExpress.createExpressMiddleware({
router: routes,
createContext: createContext
})
)
}
}