mirror of
https://github.com/documenso/documenso.git
synced 2025-11-13 00:03:33 +10:00
feat: add trpc openapi (#1535)
This commit is contained in:
@ -1,43 +1,73 @@
|
||||
import { TRPCError, initTRPC } from '@trpc/server';
|
||||
import SuperJSON from 'superjson';
|
||||
import type { OpenApiMeta } from 'trpc-openapi';
|
||||
|
||||
import { AppError, genericErrorCodeToTrpcErrorCodeMap } from '@documenso/lib/errors/app-error';
|
||||
import { isAdmin } from '@documenso/lib/next-auth/guards/is-admin';
|
||||
import { getApiTokenByToken } from '@documenso/lib/server-only/public-api/get-api-token-by-token';
|
||||
|
||||
import type { TrpcContext } from './context';
|
||||
|
||||
const t = initTRPC.context<TrpcContext>().create({
|
||||
transformer: SuperJSON,
|
||||
errorFormatter(opts) {
|
||||
const { shape, error } = opts;
|
||||
const t = initTRPC
|
||||
.meta<OpenApiMeta>()
|
||||
.context<TrpcContext>()
|
||||
.create({
|
||||
transformer: SuperJSON,
|
||||
errorFormatter(opts) {
|
||||
const { shape, error } = opts;
|
||||
|
||||
const originalError = error.cause;
|
||||
const originalError = error.cause;
|
||||
|
||||
let data: Record<string, unknown> = shape.data;
|
||||
let data: Record<string, unknown> = shape.data;
|
||||
|
||||
if (originalError instanceof AppError) {
|
||||
data = {
|
||||
...data,
|
||||
appError: AppError.toJSON(originalError),
|
||||
code: originalError.code,
|
||||
httpStatus:
|
||||
originalError.statusCode ??
|
||||
genericErrorCodeToTrpcErrorCodeMap[originalError.code]?.status ??
|
||||
500,
|
||||
// Default unknown errors to 400, since if you're throwing an AppError it is expected
|
||||
// that you already know what you're doing.
|
||||
if (originalError instanceof AppError) {
|
||||
data = {
|
||||
...data,
|
||||
appError: AppError.toJSON(originalError),
|
||||
code: originalError.code,
|
||||
httpStatus:
|
||||
originalError.statusCode ??
|
||||
genericErrorCodeToTrpcErrorCodeMap[originalError.code]?.status ??
|
||||
400,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...shape,
|
||||
data,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...shape,
|
||||
data,
|
||||
};
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Middlewares
|
||||
*/
|
||||
export const authenticatedMiddleware = t.middleware(async ({ ctx, next }) => {
|
||||
const authorizationHeader = ctx.req.headers.authorization;
|
||||
|
||||
// Taken from `authenticatedMiddleware` in `@documenso/api/v1/middleware/authenticated.ts`.
|
||||
if (authorizationHeader) {
|
||||
// Support for both "Authorization: Bearer api_xxx" and "Authorization: api_xxx"
|
||||
const [token] = (authorizationHeader || '').split('Bearer ').filter((s) => s.length > 0);
|
||||
|
||||
if (!token) {
|
||||
throw new Error('Token was not provided for authenticated middleware');
|
||||
}
|
||||
|
||||
const apiToken = await getApiTokenByToken({ token });
|
||||
|
||||
return await next({
|
||||
ctx: {
|
||||
...ctx,
|
||||
user: apiToken.user,
|
||||
session: null,
|
||||
source: 'api',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (!ctx.session) {
|
||||
throw new TRPCError({
|
||||
code: 'UNAUTHORIZED',
|
||||
@ -50,6 +80,7 @@ export const authenticatedMiddleware = t.middleware(async ({ ctx, next }) => {
|
||||
...ctx,
|
||||
user: ctx.user,
|
||||
session: ctx.session,
|
||||
source: 'app',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user