@ts-rest/nest
Advanced tools
Comparing version 3.15.0 to 3.16.0
118
index.js
@@ -1,10 +0,9 @@ | ||
import { getRouteResponses, parseJsonQueryObject, checkZodSchema } from '@ts-rest/core'; | ||
import { createParamDecorator, BadRequestException, Injectable, applyDecorators, SetMetadata, UseInterceptors, Put, Patch, Post, Get, Delete } from '@nestjs/common'; | ||
import { SetMetadata, createParamDecorator, BadRequestException, Injectable, UseInterceptors, applyDecorators, Put, Patch, Post, Get, Delete } from '@nestjs/common'; | ||
import { parseJsonQueryObject, checkZodSchema, zodErrorResponse, isAppRouteResponse, validateResponse } from '@ts-rest/core'; | ||
import { map } from 'rxjs'; | ||
import { Reflector } from '@nestjs/core'; | ||
const JsonQuerySymbol = Symbol('JsonQuery'); | ||
const JsonQuery = (jsonQuery = true) => { | ||
return (target) => { | ||
Reflect.defineMetadata(JsonQuerySymbol, jsonQuery, target); | ||
}; | ||
return SetMetadata(JsonQuerySymbol, jsonQuery); | ||
}; | ||
@@ -16,3 +15,3 @@ | ||
routeShapes: {}, | ||
responseShapes: getRouteResponses(router), | ||
responseShapes: {}, | ||
route: router, | ||
@@ -25,24 +24,2 @@ }; | ||
/****************************************************************************** | ||
Copyright (c) Microsoft Corporation. | ||
Permission to use, copy, modify, and/or distribute this software for any | ||
purpose with or without fee is hereby granted. | ||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH | ||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY | ||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, | ||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM | ||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR | ||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | ||
PERFORMANCE OF THIS SOFTWARE. | ||
***************************************************************************** */ | ||
function __decorate(decorators, target, key, desc) { | ||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; | ||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); | ||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; | ||
return c > 3 && r && Object.defineProperty(target, key, r), r; | ||
} | ||
const tsRestAppRouteMetadataKey = Symbol('ts-rest-app-route'); | ||
@@ -54,3 +31,3 @@ const TsRestRequest = createParamDecorator((_, ctx) => { | ||
if (!appRoute) { | ||
throw new Error('Make sure your route is decorated with @Api()'); | ||
throw new Error('Make sure your route is decorated with @TsRest()'); | ||
} | ||
@@ -63,7 +40,7 @@ const isJsonQuery = !!((_a = Reflect.getMetadata(JsonQuerySymbol, ctx.getHandler())) !== null && _a !== void 0 ? _a : Reflect.getMetadata(JsonQuerySymbol, ctx.getClass())); | ||
if (!queryResult.success) { | ||
throw new BadRequestException(queryResult.error); | ||
throw new BadRequestException(zodErrorResponse(queryResult.error)); | ||
} | ||
const bodyResult = checkZodSchema(req.body, appRoute.method === 'GET' ? null : appRoute.body); | ||
if (!bodyResult.success) { | ||
throw new BadRequestException(bodyResult.error); | ||
throw new BadRequestException(zodErrorResponse(bodyResult.error)); | ||
} | ||
@@ -74,3 +51,3 @@ const pathParamsResult = checkZodSchema(req.params, appRoute.pathParams, { | ||
if (!pathParamsResult.success) { | ||
throw new BadRequestException(pathParamsResult.error); | ||
throw new BadRequestException(zodErrorResponse(pathParamsResult.error)); | ||
} | ||
@@ -85,11 +62,49 @@ return { | ||
/****************************************************************************** | ||
Copyright (c) Microsoft Corporation. | ||
Permission to use, copy, modify, and/or distribute this software for any | ||
purpose with or without fee is hereby granted. | ||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH | ||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY | ||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, | ||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM | ||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR | ||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | ||
PERFORMANCE OF THIS SOFTWARE. | ||
***************************************************************************** */ | ||
function __decorate(decorators, target, key, desc) { | ||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; | ||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); | ||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; | ||
return c > 3 && r && Object.defineProperty(target, key, r), r; | ||
} | ||
function __metadata(metadataKey, metadataValue) { | ||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue); | ||
} | ||
let TsRestInterceptor = class TsRestInterceptor { | ||
constructor(reflector) { | ||
this.reflector = reflector; | ||
} | ||
intercept(context, next) { | ||
const res = context.switchToHttp().getResponse(); | ||
const appRoute = this.reflector.get(tsRestAppRouteMetadataKey, context.getHandler()); | ||
if (!appRoute) { | ||
throw new Error('Make sure your route is decorated with @TsRest()'); | ||
} | ||
const isValidationEnabled = Boolean(this.reflector.getAllAndOverride(ValidateResponsesSymbol, [context.getHandler(), context.getClass()])); | ||
return next.handle().pipe(map((value) => { | ||
if (typeof value === 'object' && | ||
typeof value.status === 'number' && | ||
value.body !== undefined) { | ||
res.status(value.status); | ||
return value.body; | ||
if (isAppRouteResponse(value)) { | ||
const response = isValidationEnabled | ||
? validateResponse({ | ||
responseType: appRoute.responses[value.status], | ||
response: value, | ||
}) | ||
: value; | ||
res.status(response.status); | ||
return response.body; | ||
} | ||
@@ -101,4 +116,26 @@ return value; | ||
TsRestInterceptor = __decorate([ | ||
Injectable() | ||
Injectable(), | ||
__metadata("design:paramtypes", [Reflector]) | ||
], TsRestInterceptor); | ||
const ValidateResponsesSymbol = Symbol('ts-rest-validate-responses'); | ||
const TsRest = (appRouteOrOptions, options = {}) => { | ||
const decorators = []; | ||
const isMethodDecorator = 'path' in appRouteOrOptions; | ||
const optionsToUse = isMethodDecorator ? options : appRouteOrOptions; | ||
if (isMethodDecorator) { | ||
decorators.push(...[ | ||
SetMetadata(tsRestAppRouteMetadataKey, appRouteOrOptions), | ||
getMethodDecorator(appRouteOrOptions), | ||
UseInterceptors(TsRestInterceptor), | ||
]); | ||
} | ||
if (optionsToUse.jsonQuery !== undefined) { | ||
decorators.push(JsonQuery(optionsToUse.jsonQuery)); | ||
} | ||
if (optionsToUse.validateResponses !== undefined) { | ||
decorators.push(SetMetadata(ValidateResponsesSymbol, optionsToUse.validateResponses)); | ||
} | ||
return applyDecorators(...decorators); | ||
}; | ||
const getMethodDecorator = (appRoute) => { | ||
@@ -119,6 +156,5 @@ switch (appRoute.method) { | ||
const Api = (appRoute) => { | ||
const methodDecorator = getMethodDecorator(appRoute); | ||
return applyDecorators(SetMetadata(tsRestAppRouteMetadataKey, appRoute), methodDecorator, UseInterceptors(TsRestInterceptor)); | ||
return TsRest(appRoute); | ||
}; | ||
export { Api, ApiDecorator, JsonQuery, JsonQuerySymbol, TsRestInterceptor, TsRestRequest, initNestServer, nestControllerContract, tsRestAppRouteMetadataKey }; | ||
export { Api, ApiDecorator, JsonQuery, JsonQuerySymbol, TsRest, TsRestInterceptor, TsRestRequest, ValidateResponsesSymbol, initNestServer, nestControllerContract, tsRestAppRouteMetadataKey }; |
{ | ||
"name": "@ts-rest/nest", | ||
"version": "3.15.0", | ||
"version": "3.16.0", | ||
"description": "Nest server integration for @ts-rest", | ||
@@ -34,3 +34,4 @@ "license": "MIT", | ||
"zod": "3.x.x", | ||
"@ts-rest/core": "3.15.0" | ||
"@ts-rest/core": "3.16.0", | ||
"@nestjs/core": "9.0.11" | ||
}, | ||
@@ -37,0 +38,0 @@ "devDependencies": { |
export * from './lib/json-query.decorator'; | ||
export * from './lib/ts-rest-nest'; | ||
export * from './lib/ts-rest.decorator'; | ||
export * from './lib/ts-rest.interceptor'; | ||
export * from './lib/ts-rest-request.decorator'; |
@@ -5,2 +5,2 @@ export declare const JsonQuerySymbol: unique symbol; | ||
*/ | ||
export declare const JsonQuery: (jsonQuery?: boolean) => ClassDecorator & MethodDecorator; | ||
export declare const JsonQuery: (jsonQuery?: boolean) => import("@nestjs/common").CustomDecorator<typeof JsonQuerySymbol>; |
@@ -1,4 +0,4 @@ | ||
import { AppRoute, AppRouter, ApiRouteResponse, Without, ApiResponseForRoute } from '@ts-rest/core'; | ||
import { AppRoute, AppRouter, Without, ApiRouteServerResponse } from '@ts-rest/core'; | ||
import { TsRestRequestShape } from './ts-rest-request.decorator'; | ||
type AppRouterMethodShape<T extends AppRoute> = (...args: any[]) => Promise<ApiRouteResponse<T['responses']>>; | ||
type AppRouterMethodShape<T extends AppRoute> = (...args: any[]) => Promise<ApiRouteServerResponse<T['responses']>>; | ||
type AppRouterControllerShape<T extends AppRouter> = Without<{ | ||
@@ -11,6 +11,4 @@ [K in keyof T]: T[K] extends AppRoute ? AppRouterMethodShape<T[K]> : never; | ||
type AppRouterResponseShapes<T extends AppRouter> = Without<{ | ||
[K in keyof T]: T[K] extends AppRoute ? ApiResponseForRoute<T[K]> : never; | ||
[K in keyof T]: T[K] extends AppRoute ? ApiRouteServerResponse<T[K]['responses']> : never; | ||
}, never>; | ||
type NestControllerShapeFromAppRouter<T extends AppRouter> = Without<AppRouterControllerShape<T>, AppRouter>; | ||
type NestAppRouteShape<T extends AppRouter> = AppRouterRequestShapes<T>; | ||
/** | ||
@@ -21,5 +19,5 @@ * @deprecated Use `nestControllerContract`, `NestControllerInterface`, `NestRequestShapes`, and `NestResponseShapes` instead | ||
export declare const initNestServer: <T extends AppRouter>(router: T) => { | ||
controllerShape: NestControllerShapeFromAppRouter<T>; | ||
routeShapes: NestAppRouteShape<T>; | ||
responseShapes: { [K in keyof T]: T[K] extends AppRoute ? ApiResponseForRoute<T[K]> : "not a route"; }; | ||
controllerShape: AppRouterControllerShape<T>; | ||
routeShapes: AppRouterRequestShapes<T>; | ||
responseShapes: AppRouterResponseShapes<T>; | ||
route: T; | ||
@@ -31,3 +29,3 @@ }; | ||
export type NestControllerInterface<T extends AppRouter> = AppRouterControllerShape<T>; | ||
export type NestRequestShapes<T extends AppRouter> = NestAppRouteShape<T>; | ||
export type NestRequestShapes<T extends AppRouter> = AppRouterRequestShapes<T>; | ||
export type NestResponseShapes<T extends AppRouter> = AppRouterResponseShapes<T>; | ||
@@ -34,0 +32,0 @@ /** |
import { CallHandler, ExecutionContext, NestInterceptor } from '@nestjs/common'; | ||
import { Observable } from 'rxjs'; | ||
import { AppRoute } from '@ts-rest/core'; | ||
import { Reflector } from '@nestjs/core'; | ||
export declare class TsRestInterceptor implements NestInterceptor { | ||
private reflector; | ||
constructor(reflector: Reflector); | ||
intercept(context: ExecutionContext, next: CallHandler): Observable<any>; | ||
} | ||
/** | ||
* Method decorator used to register a route's path and method from the passed route and handle ts-rest response objects | ||
* @param appRoute The route to register | ||
*/ | ||
export declare const Api: (appRoute: AppRoute) => MethodDecorator; |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
25052
11
377
5