@shadow-library/fastify 1.4.0 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -952,6 +952,394 @@ class CreateProductDto {
952
952
  }
953
953
  ```
954
954
 
955
+ ## Data Transformation
956
+
957
+ The `@Transform` decorator enables automatic data transformation at two key points in the request-response lifecycle:
958
+
959
+ 1. **After Validation (Request)**: Transforms incoming data (body, query, params) after AJV validation but before it reaches your route handler. This allows validation to run against the original data type while your handler receives the transformed type.
960
+
961
+ 2. **Before Serialization (Response)**: Transforms outgoing response data before it's serialized and sent to the client. This allows you to work with one data type internally while presenting a different format to API consumers.
962
+
963
+ ### How It Works
964
+
965
+ The `@Transform` decorator works in conjunction with `@Field` from `@shadow-library/class-schema`. The `@Field` decorator defines the **source/validation type** (the type used for JSON Schema validation), while `@Transform` converts the data to the **target type** (the type your code actually works with or returns to the client).
966
+
967
+ ```mermaid
968
+ flowchart LR
969
+ subgraph responseFlow["Response Flow"]
970
+ Response["Response (JSON)"]
971
+ Serialization["Serialization (JSON)"]
972
+ ResTransform["Transform (Pre Serialization)"]
973
+ ResHandler["Route Handler (Returns Data)"]
974
+ end
975
+
976
+ subgraph requestFlow["Request Flow"]
977
+ ReqHandler["Route Handler (Receives Transformed Data)"]
978
+ ReqTransform["Transform (Post Validation)"]
979
+ Validation["Validation (AJV)"]
980
+ rawReq["Raw Request (JSON)"]
981
+ end
982
+
983
+ rawReq --> Validation
984
+ Validation --> ReqTransform
985
+ ReqTransform --> ReqHandler
986
+ ResHandler --> ResTransform
987
+ ResTransform --> Serialization
988
+ Serialization --> Response
989
+ ```
990
+
991
+ ### Basic Usage
992
+
993
+ The `@Transform` decorator accepts either a transformer name (string) or an options object:
994
+
995
+ ```typescript
996
+ // Single transformer - applies to both input and output
997
+ @Transform('string:trim')
998
+
999
+ // Options object - specify different transformers for input and output
1000
+ @Transform({ input: 'int:parse', output: 'int:stringify' })
1001
+
1002
+ // Options object - specify only input or output
1003
+ @Transform({ input: 'string:trim' }) // Only transforms input
1004
+ @Transform({ output: 'email:normalize' }) // Only transforms output
1005
+ ```
1006
+
1007
+ #### Example
1008
+
1009
+ ```typescript
1010
+ import { Schema, Field } from '@shadow-library/class-schema';
1011
+ import { Transform } from '@shadow-library/fastify';
1012
+
1013
+ @Schema()
1014
+ class CreateUserDto {
1015
+ @Field(() => String)
1016
+ @Transform('string:trim')
1017
+ name: string;
1018
+
1019
+ @Field(() => String, { format: 'email' })
1020
+ @Transform('email:normalize')
1021
+ email: string;
1022
+ }
1023
+
1024
+ @HttpController('/users')
1025
+ export class UserController {
1026
+ @Post()
1027
+ async createUser(@Body() userData: CreateUserDto) {
1028
+ // userData.name is automatically trimmed
1029
+ // userData.email is normalized (trimmed and lowercased)
1030
+ return this.userService.create(userData);
1031
+ }
1032
+ }
1033
+ ```
1034
+
1035
+ ### Built-in Transformers
1036
+
1037
+ The following transformers are available out of the box:
1038
+
1039
+ | Transformer | Input Type | Output Type | Description |
1040
+ | ----------------- | ---------- | ----------- | ------------------------------------------------------------------------------------ |
1041
+ | `email:normalize` | `string` | `string` | Trims whitespace and converts to lowercase |
1042
+ | `string:trim` | `string` | `string` | Removes leading and trailing whitespace |
1043
+ | `int:parse` | `string` | `number` | Parses string to integer (base 10) |
1044
+ | `float:parse` | `string` | `number` | Parses string to floating-point number |
1045
+ | `bigint:parse` | `string` | `bigint` | Parses string to BigInt |
1046
+ | `strip:null` | `any` | `any` | Returns undefined when the field is null which will remove the field from the object |
1047
+
1048
+ ### Request Transformation Examples
1049
+
1050
+ #### Normalizing User Input
1051
+
1052
+ ```typescript
1053
+ @Schema()
1054
+ class SignUpDto {
1055
+ @Field(() => String)
1056
+ @Transform('string:trim')
1057
+ username: string;
1058
+
1059
+ @Field(() => String, { format: 'email' })
1060
+ @Transform('email:normalize')
1061
+ email: string;
1062
+
1063
+ @Field(() => String)
1064
+ password: string;
1065
+ }
1066
+ ```
1067
+
1068
+ #### Parsing Query Parameters
1069
+
1070
+ Query parameters are always received as strings from the HTTP layer. Use `@Transform` to convert them to the appropriate type while keeping `@Field` for validation:
1071
+
1072
+ ```typescript
1073
+ @Schema()
1074
+ class PaginationQuery {
1075
+ // @Field defines the validation type (string from query params)
1076
+ // @Transform converts the validated string to a number for your handler
1077
+ @Field(() => String, { pattern: '^[0-9]+$' })
1078
+ @Transform('int:parse')
1079
+ page: number;
1080
+
1081
+ @Field(() => String, { pattern: '^[0-9]+$' })
1082
+ @Transform('int:parse')
1083
+ limit: number;
1084
+ }
1085
+
1086
+ @HttpController('/products')
1087
+ export class ProductController {
1088
+ @Get()
1089
+ async getProducts(@Query() query: PaginationQuery) {
1090
+ // query.page and query.limit are numbers here, not strings
1091
+ // Validation ensured they were numeric strings before transformation
1092
+ return this.productService.findAll(query.page, query.limit);
1093
+ }
1094
+ }
1095
+ ```
1096
+
1097
+ #### Working with Large Numbers
1098
+
1099
+ JavaScript numbers lose precision beyond `Number.MAX_SAFE_INTEGER`. Use BigInt for large numbers while transmitting as strings:
1100
+
1101
+ ```typescript
1102
+ @Schema()
1103
+ class TransactionDto {
1104
+ // Validated as a string (safe for JSON transmission)
1105
+ // Transformed to BigInt for precise arithmetic in your handler
1106
+ @Field(() => String, { pattern: '^-?[0-9]+$' })
1107
+ @Transform('bigint:parse')
1108
+ amount: bigint;
1109
+
1110
+ @Field(() => String)
1111
+ recipientId: string;
1112
+ }
1113
+
1114
+ @HttpController('/transactions')
1115
+ export class TransactionController {
1116
+ @Post()
1117
+ async createTransaction(@Body() dto: TransactionDto) {
1118
+ // dto.amount is a BigInt - safe for precise calculations
1119
+ const fee = dto.amount / 100n; // BigInt arithmetic
1120
+ return this.transactionService.process(dto);
1121
+ }
1122
+ }
1123
+ ```
1124
+
1125
+ ### Response Transformation Examples
1126
+
1127
+ Transformers also work on response schemas, allowing you to convert internal data types to API-friendly formats.
1128
+
1129
+ #### Currency Formatting
1130
+
1131
+ Store and compute with integers (cents) to avoid floating-point errors, but display as decimal strings for the API:
1132
+
1133
+ ```typescript
1134
+ // Define a custom transformer for cents to decimal conversion
1135
+ declare module '@shadow-library/fastify' {
1136
+ export interface CustomTransformers {
1137
+ 'currency:format': (value: number) => string;
1138
+ }
1139
+ }
1140
+
1141
+ // Register the transformer in your module config
1142
+ FastifyModule.forRoot({
1143
+ controllers: [ProductController],
1144
+ transformers: {
1145
+ 'currency:format': (cents: number) => (cents / 100).toFixed(2),
1146
+ },
1147
+ });
1148
+
1149
+ // Use in your response DTO
1150
+ @Schema()
1151
+ class ProductResponse {
1152
+ @Field(() => Number)
1153
+ id: number;
1154
+
1155
+ @Field(() => String)
1156
+ name: string;
1157
+
1158
+ // Internally stored as integer (cents), transformed to "19.99" format for API response
1159
+ @Field(() => String)
1160
+ @Transform('currency:format')
1161
+ price: number; // TypeScript type is what is used internally
1162
+ }
1163
+
1164
+ @HttpController('/products')
1165
+ export class ProductController {
1166
+ @Get('/:id')
1167
+ @RespondFor(200, ProductResponse)
1168
+ async getProduct(@Params() params: { id: string }): Promise<ProductResponse> {
1169
+ const product = await this.productService.findById(params.id);
1170
+ // product.price = 1999 (integer cents from database)
1171
+ return product;
1172
+ // Response: { id: 1, name: "Widget", price: "19.99" }
1173
+ }
1174
+ }
1175
+ ```
1176
+
1177
+ #### Date Formatting
1178
+
1179
+ ```typescript
1180
+ declare module '@shadow-library/fastify' {
1181
+ export interface CustomTransformers {
1182
+ 'date:iso': (value: Date) => string;
1183
+ }
1184
+ }
1185
+
1186
+ FastifyModule.forRoot({
1187
+ controllers: [EventController],
1188
+ transformers: {
1189
+ 'date:iso': (date: Date) => date.toISOString(),
1190
+ },
1191
+ });
1192
+
1193
+ @Schema()
1194
+ class EventResponse {
1195
+ @Field(() => String)
1196
+ name: string;
1197
+
1198
+ // Date object internally, ISO string in API response
1199
+ @Field(() => String)
1200
+ @Transform('date:iso')
1201
+ startDate: Date;
1202
+ }
1203
+ ```
1204
+
1205
+ ### Different Input and Output Transformers
1206
+
1207
+ Sometimes you need different transformations for incoming requests vs outgoing responses. The `@Transform` decorator supports separate `input` and `output` options:
1208
+
1209
+ ```typescript
1210
+ declare module '@shadow-library/fastify' {
1211
+ export interface CustomTransformers {
1212
+ 'cents:parse': (value: string) => number;
1213
+ 'cents:format': (value: number) => string;
1214
+ }
1215
+ }
1216
+
1217
+ FastifyModule.forRoot({
1218
+ controllers: [TransactionController],
1219
+ transformers: {
1220
+ 'cents:parse': (value: string) => Math.round(parseFloat(value) * 100),
1221
+ 'cents:format': (cents: number) => (cents / 100).toFixed(2),
1222
+ },
1223
+ });
1224
+
1225
+ @Schema()
1226
+ class TransactionDto {
1227
+ @Field(() => String)
1228
+ @Transform({ input: 'cents:parse', output: 'cents:format' })
1229
+ amount: number;
1230
+ }
1231
+
1232
+ @HttpController('/transactions')
1233
+ export class TransactionController {
1234
+ @Post()
1235
+ @RespondFor(201, TransactionDto)
1236
+ async createTransaction(@Body() dto: TransactionDto): Promise<TransactionDto> {
1237
+ // Request: { "amount": "19.99" }
1238
+ // dto.amount = 1999 (parsed to cents)
1239
+
1240
+ // Your business logic works with cents (integers)
1241
+ const saved = await this.transactionService.save(dto);
1242
+
1243
+ return saved;
1244
+ // Response: { "amount": "19.99" } (formatted back to decimal string)
1245
+ }
1246
+ }
1247
+ ```
1248
+
1249
+ #### Input-Only or Output-Only Transformations
1250
+
1251
+ You can also specify only input or output transformation:
1252
+
1253
+ ```typescript
1254
+ @Schema()
1255
+ class SearchQuery {
1256
+ // Only transform input - sanitize search terms
1257
+ @Field(() => String)
1258
+ @Transform({ input: 'string:trim' })
1259
+ query: string;
1260
+ }
1261
+
1262
+ @Schema()
1263
+ class UserResponse {
1264
+ @Field(() => String)
1265
+ name: string;
1266
+
1267
+ // Only transform output - mask email for privacy
1268
+ @Field(() => String)
1269
+ @Transform({ output: 'email:mask' })
1270
+ email: string;
1271
+ }
1272
+ ```
1273
+
1274
+ ### Extending with Custom Transformers
1275
+
1276
+ #### Step 1: Declare the Transformer Types
1277
+
1278
+ Extend the `CustomTransformers` interface for type-safe transformer names:
1279
+
1280
+ ```typescript
1281
+ declare module '@shadow-library/fastify' {
1282
+ export interface CustomTransformers {
1283
+ 'phone:normalize': (value: string) => string;
1284
+ 'currency:format': (value: number) => string;
1285
+ 'date:parse': (value: string) => Date;
1286
+ 'boolean:parse': (value: string) => boolean;
1287
+ }
1288
+ }
1289
+ ```
1290
+
1291
+ #### Step 2: Register Transformers in Module Config
1292
+
1293
+ ```typescript
1294
+ @Module({
1295
+ imports: [
1296
+ FastifyModule.forRoot({
1297
+ controllers: [UserController, ProductController],
1298
+ transformers: {
1299
+ 'phone:normalize': (phone: string) => phone.replace(/[^0-9+]/g, ''),
1300
+ 'currency:format': (cents: number) => (cents / 100).toFixed(2),
1301
+ 'date:parse': (dateStr: string) => new Date(dateStr),
1302
+ 'boolean:parse': (value: string) => value === 'true' || value === '1',
1303
+ },
1304
+ }),
1305
+ ],
1306
+ })
1307
+ export class AppModule {}
1308
+ ```
1309
+
1310
+ #### Step 3: Use in Your Schemas
1311
+
1312
+ ```typescript
1313
+ @Schema()
1314
+ class UserDto {
1315
+ @Field(() => String)
1316
+ @Transform('phone:normalize')
1317
+ phone: string;
1318
+
1319
+ @Field(() => String)
1320
+ @Transform('boolean:parse')
1321
+ isActive: boolean;
1322
+ }
1323
+ ```
1324
+
1325
+ ### Best Practices
1326
+
1327
+ 1. **Validate First, Transform After**: The `@Field` decorator defines what's valid input. `@Transform` converts valid input to your preferred type.
1328
+
1329
+ 2. **Use Strings for Query/Params Validation**: Query parameters and URL params are always strings. Validate them as strings, then transform:
1330
+
1331
+ ```typescript
1332
+ @Field(() => String, { pattern: '^[0-9]+$' }) // Validate as numeric string
1333
+ @Transform('int:parse') // Convert to number
1334
+ id: number;
1335
+ ```
1336
+
1337
+ 3. **Avoid Floating-Point for Currency**: Store monetary values as integers (cents) and use transformers for display formatting.
1338
+
1339
+ 4. **Keep Transformers Pure**: Transformers should be pure functions without side effects.
1340
+
1341
+ 5. **Handle Edge Cases**: Ensure your custom transformers handle edge cases like empty strings, null values, etc.
1342
+
955
1343
  ## Response Serialization
956
1344
 
957
1345
  Define response schemas for automatic serialization and documentation:
@@ -1,5 +1,4 @@
1
- import { JSONSchema } from '@shadow-library/class-schema';
2
- import { Class } from 'type-fest';
1
+ import { JSONSchema, SchemaClass } from '@shadow-library/class-schema';
3
2
  /**
4
3
  * Defining types
5
4
  */
@@ -10,7 +9,7 @@ export declare enum RouteInputType {
10
9
  REQUEST = "request",
11
10
  RESPONSE = "response"
12
11
  }
13
- export type RouteInputSchemas = Partial<Record<'body' | 'params' | 'query', JSONSchema | Class<unknown>>>;
12
+ export type RouteInputSchemas = Partial<Record<'body' | 'params' | 'query', JSONSchema | SchemaClass>>;
14
13
  /**
15
14
  * Declaring the constants
16
15
  */
@@ -13,6 +13,9 @@ export interface DynamicRender<T extends JsonObject> {
13
13
  template: string;
14
14
  data: T;
15
15
  }
16
+ /**
17
+ * Declaring the constants
18
+ */
16
19
  export declare const HttpStatus: (status: number) => MethodDecorator;
17
20
  export declare const Header: (name: string, value: string | (() => string)) => MethodDecorator;
18
21
  export declare const Redirect: (redirect: string, status?: number) => MethodDecorator;
@@ -6,11 +6,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.Render = exports.Redirect = exports.Header = exports.HttpStatus = void 0;
7
7
  exports.RespondFor = RespondFor;
8
8
  const app_1 = require("@shadow-library/app");
9
- const class_schema_1 = require("@shadow-library/class-schema");
10
9
  /**
11
10
  * Declaring the constants
12
11
  */
13
- const isClass = (schema) => schema.toString().startsWith('class ');
14
12
  const HttpStatus = (status) => (0, app_1.Route)({ status });
15
13
  exports.HttpStatus = HttpStatus;
16
14
  const Header = (name, value) => (0, app_1.Route)({ headers: { [name]: value } });
@@ -20,7 +18,5 @@ exports.Redirect = Redirect;
20
18
  const Render = (render) => (0, app_1.Route)({ render: render ?? true });
21
19
  exports.Render = Render;
22
20
  function RespondFor(statusCode, schema) {
23
- if (isClass(schema))
24
- schema = class_schema_1.ClassSchema.generate(schema);
25
21
  return (0, app_1.Route)({ schemas: { response: { [statusCode]: schema } } });
26
22
  }
@@ -4,4 +4,5 @@ export * from './http-output.decorator.js';
4
4
  export * from './http-route.decorator.js';
5
5
  export * from './middleware.decorator.js';
6
6
  export * from './sensitive.decorator.js';
7
+ export * from './transform.decorator.js';
7
8
  export * from './version.decorator.js';
@@ -20,4 +20,5 @@ __exportStar(require("./http-output.decorator.js"), exports);
20
20
  __exportStar(require("./http-route.decorator.js"), exports);
21
21
  __exportStar(require("./middleware.decorator.js"), exports);
22
22
  __exportStar(require("./sensitive.decorator.js"), exports);
23
+ __exportStar(require("./transform.decorator.js"), exports);
23
24
  __exportStar(require("./version.decorator.js"), exports);
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Importing npm packages
3
+ */
4
+ import { TransformerContext } from '@shadow-library/class-schema';
5
+ /**
6
+ * Importing user defined packages
7
+ */
8
+ /**
9
+ * Defining types
10
+ */
11
+ export interface TransformOptions {
12
+ input?: TransformTypes;
13
+ output?: TransformTypes;
14
+ }
15
+ export interface CustomTransformers {
16
+ }
17
+ export interface InbuiltTransformers {
18
+ 'email:normalize': (value: string) => string;
19
+ 'string:trim': (value: string) => string;
20
+ 'int:parse': (value: string) => number;
21
+ 'float:parse': (value: string) => number;
22
+ 'bigint:parse': (value: string) => bigint;
23
+ 'strip:null': (value: any) => any;
24
+ }
25
+ export type TransformTypes = keyof CustomTransformers | keyof InbuiltTransformers;
26
+ export type TransformerFn = (value: any, ctx: TransformerContext) => any;
27
+ /**
28
+ * Declaring the constants
29
+ */
30
+ export declare function Transform(type: TransformTypes | TransformOptions): PropertyDecorator;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ /**
3
+ * Importing npm packages
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Transform = Transform;
7
+ const class_schema_1 = require("@shadow-library/class-schema");
8
+ /**
9
+ * Declaring the constants
10
+ */
11
+ function Transform(type) {
12
+ const options = typeof type === 'string' ? { input: type, output: type } : type;
13
+ return (target, propertyKey) => {
14
+ const decorator = (0, class_schema_1.FieldMetadata)({ 'x-fastify': { transform: options } });
15
+ decorator(target, propertyKey);
16
+ };
17
+ }
@@ -2,7 +2,7 @@
2
2
  * Importing npm packages
3
3
  */
4
4
  import { RouteMetadata } from '@shadow-library/app';
5
- import { JSONSchema } from '@shadow-library/class-schema';
5
+ import { JSONSchema, SchemaClass } from '@shadow-library/class-schema';
6
6
  import { FastifyInstance, RouteShorthandOptions } from 'fastify';
7
7
  /**
8
8
  * Importing user defined packages
@@ -18,7 +18,7 @@ declare module '@shadow-library/app' {
18
18
  path?: string;
19
19
  version?: number;
20
20
  schemas?: RouteInputSchemas & {
21
- response?: Record<number | string, JSONSchema>;
21
+ response?: Record<number | string, JSONSchema | SchemaClass>;
22
22
  };
23
23
  rawBody?: boolean;
24
24
  silentValidation?: boolean;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Importing npm packages
3
+ */
4
+ /**
5
+ * Importing user defined packages
6
+ */
7
+ import { InbuiltTransformers } from '../decorators/index.js';
8
+ /**
9
+ * Defining types
10
+ */
11
+ /**
12
+ * Declaring the constants
13
+ */
14
+ export declare const INBUILT_TRANSFORMERS: InbuiltTransformers;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ /**
3
+ * Importing npm packages
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.INBUILT_TRANSFORMERS = void 0;
7
+ /**
8
+ * Defining types
9
+ */
10
+ /**
11
+ * Declaring the constants
12
+ */
13
+ exports.INBUILT_TRANSFORMERS = {
14
+ 'email:normalize': value => value.trim().toLowerCase(),
15
+ 'string:trim': value => value.trim(),
16
+ 'int:parse': value => parseInt(value, 10),
17
+ 'float:parse': value => parseFloat(value),
18
+ 'bigint:parse': value => BigInt(value),
19
+ 'strip:null': value => (value === null ? undefined : value),
20
+ };
@@ -8,6 +8,7 @@ import { Promisable } from 'type-fest';
8
8
  /**
9
9
  * Importing user defined packages
10
10
  */
11
+ import { CustomTransformers } from '../decorators/index.js';
11
12
  import { ErrorHandler } from '../interfaces/index.js';
12
13
  import { ContextService } from '../services/index.js';
13
14
  /**
@@ -59,6 +60,10 @@ export interface FastifyConfig extends FastifyServerOptions {
59
60
  * The global route prefix for all routes in the Fastify instance
60
61
  */
61
62
  routePrefix?: string;
63
+ /**
64
+ * Object defining custom transformers for request and response data transformation
65
+ */
66
+ transformers?: Record<keyof CustomTransformers, (value: any) => any>;
62
67
  }
63
68
  export interface FastifyModuleOptions extends Partial<FastifyConfig> {
64
69
  /**
@@ -1,4 +1,5 @@
1
1
  import { ControllerRouteMetadata, Router } from '@shadow-library/app';
2
+ import { Transformer } from '@shadow-library/class-schema';
2
3
  import { type FastifyInstance } from 'fastify';
3
4
  import { Chain as MockRequestChain, InjectOptions as MockRequestOptions, Response as MockResponse } from 'light-my-request';
4
5
  import { JsonObject, JsonValue } from 'type-fest';
@@ -49,12 +50,15 @@ export interface ChildRouteRequest {
49
50
  params: Record<string, string>;
50
51
  query: Record<string, string>;
51
52
  }
53
+ interface Transformers {
54
+ body?: Transformer;
55
+ query?: Transformer;
56
+ params?: Transformer;
57
+ response?: Record<string, Transformer>;
58
+ }
52
59
  interface RouteArtifacts {
53
- transforms: {
54
- maskBody?(body: object): object;
55
- maskQuery?(query: object): object;
56
- maskParams?(params: object): object;
57
- };
60
+ masks: Partial<Record<'body' | 'query' | 'params', Transformer>>;
61
+ transformers: Transformers;
58
62
  }
59
63
  export declare class FastifyRouter extends Router {
60
64
  private readonly config;
@@ -64,17 +68,25 @@ export declare class FastifyRouter extends Router {
64
68
  private readonly logger;
65
69
  private readonly cachedDynamicMiddlewares;
66
70
  private readonly childRouter;
71
+ private readonly transformers;
67
72
  private readonly sensitiveTransformer;
73
+ private readonly inputDataTransformer;
74
+ private readonly outputDataTransformer;
68
75
  constructor(config: FastifyConfig, instance: FastifyInstance, context: ContextService);
69
76
  getInstance(): FastifyInstance;
77
+ private isTransformable;
70
78
  private joinPaths;
79
+ private addRouteHandler;
71
80
  private registerRawBody;
72
81
  private maskField;
82
+ private generateDataTransformer;
73
83
  private getRequestLogger;
74
84
  private parseControllers;
75
85
  private getStatusCode;
76
86
  private generateRouteHandler;
77
87
  private getMiddlewareHandler;
88
+ private transformResponseHandler;
89
+ private transformRequestHandler;
78
90
  register(controllers: ControllerRouteMetadata[]): Promise<void>;
79
91
  start(): Promise<void>;
80
92
  stop(): Promise<void>;