@nmshd/typescript-rest 3.0.5

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.
Files changed (62) hide show
  1. package/.ci/runChecks.sh +7 -0
  2. package/.eslintrc.js +226 -0
  3. package/.github/dependabot.yml +27 -0
  4. package/.github/workflows/publish.yml +33 -0
  5. package/.github/workflows/test.yml +31 -0
  6. package/.prettierrc +27 -0
  7. package/.vscode/settings.json +31 -0
  8. package/LICENSE +22 -0
  9. package/README.md +128 -0
  10. package/dist/decorators/methods.d.ts +165 -0
  11. package/dist/decorators/methods.js +263 -0
  12. package/dist/decorators/methods.js.map +1 -0
  13. package/dist/decorators/parameters.d.ts +295 -0
  14. package/dist/decorators/parameters.js +423 -0
  15. package/dist/decorators/parameters.js.map +1 -0
  16. package/dist/decorators/services.d.ts +199 -0
  17. package/dist/decorators/services.js +367 -0
  18. package/dist/decorators/services.js.map +1 -0
  19. package/dist/server/config.d.ts +4 -0
  20. package/dist/server/config.js +43 -0
  21. package/dist/server/config.js.map +1 -0
  22. package/dist/server/model/errors.d.ts +111 -0
  23. package/dist/server/model/errors.js +178 -0
  24. package/dist/server/model/errors.js.map +1 -0
  25. package/dist/server/model/metadata.d.ts +91 -0
  26. package/dist/server/model/metadata.js +80 -0
  27. package/dist/server/model/metadata.js.map +1 -0
  28. package/dist/server/model/return-types.d.ts +86 -0
  29. package/dist/server/model/return-types.js +110 -0
  30. package/dist/server/model/return-types.js.map +1 -0
  31. package/dist/server/model/server-types.d.ts +118 -0
  32. package/dist/server/model/server-types.js +47 -0
  33. package/dist/server/model/server-types.js.map +1 -0
  34. package/dist/server/parameter-processor.d.ts +13 -0
  35. package/dist/server/parameter-processor.js +84 -0
  36. package/dist/server/parameter-processor.js.map +1 -0
  37. package/dist/server/server-container.d.ts +55 -0
  38. package/dist/server/server-container.js +432 -0
  39. package/dist/server/server-container.js.map +1 -0
  40. package/dist/server/server.d.ts +136 -0
  41. package/dist/server/server.js +278 -0
  42. package/dist/server/server.js.map +1 -0
  43. package/dist/server/service-invoker.d.ts +28 -0
  44. package/dist/server/service-invoker.js +270 -0
  45. package/dist/server/service-invoker.js.map +1 -0
  46. package/dist/typescript-rest.d.ts +9 -0
  47. package/dist/typescript-rest.js +31 -0
  48. package/dist/typescript-rest.js.map +1 -0
  49. package/package.json +113 -0
  50. package/src/decorators/methods.ts +279 -0
  51. package/src/decorators/parameters.ts +442 -0
  52. package/src/decorators/services.ts +390 -0
  53. package/src/server/config.ts +40 -0
  54. package/src/server/model/errors.ts +178 -0
  55. package/src/server/model/metadata.ts +118 -0
  56. package/src/server/model/return-types.ts +109 -0
  57. package/src/server/model/server-types.ts +130 -0
  58. package/src/server/parameter-processor.ts +105 -0
  59. package/src/server/server-container.ts +504 -0
  60. package/src/server/server.ts +340 -0
  61. package/src/server/service-invoker.ts +266 -0
  62. package/src/typescript-rest.ts +16 -0
@@ -0,0 +1,504 @@
1
+ /* eslint-disable prefer-spread */
2
+ 'use strict';
3
+
4
+ import * as bodyParser from 'body-parser';
5
+ import * as cookieParser from 'cookie-parser';
6
+ import * as debug from 'debug';
7
+ import * as express from 'express';
8
+ import { NextFunction, Request, Response } from 'express';
9
+ import * as _ from 'lodash';
10
+ import * as multer from 'multer';
11
+ import * as Errors from './model/errors';
12
+ import { ServiceClass, ServiceMethod } from './model/metadata';
13
+ import {
14
+ FileLimits,
15
+ HttpMethod,
16
+ ParameterConverter,
17
+ ParserType,
18
+ ServiceAuthenticator,
19
+ ServiceContext,
20
+ ServiceFactory
21
+ } from './model/server-types';
22
+ import { ServiceInvoker } from './service-invoker';
23
+
24
+ export class DefaultServiceFactory implements ServiceFactory {
25
+ public create(serviceClass: any) {
26
+ return new serviceClass();
27
+ }
28
+ public getTargetClass(serviceClass: Function) {
29
+ return serviceClass as FunctionConstructor;
30
+ }
31
+ }
32
+
33
+ export class ServerContainer {
34
+ public static get(): ServerContainer {
35
+ return ServerContainer.instance;
36
+ }
37
+
38
+ private static instance: ServerContainer = new ServerContainer();
39
+
40
+ public cookiesSecret: string;
41
+ public cookiesDecoder: (val: string) => string;
42
+ public fileDest: string;
43
+ public fileFilter: (
44
+ req: Express.Request,
45
+ file: Express.Multer.File,
46
+ callback: (error: Error, acceptFile: boolean) => void
47
+ ) => void;
48
+ public fileLimits: FileLimits;
49
+ public ignoreNextMiddlewares: boolean = false;
50
+ public authenticator: Map<string, ServiceAuthenticator> = new Map<string, ServiceAuthenticator>();
51
+ public serviceFactory: ServiceFactory = new DefaultServiceFactory();
52
+ public paramConverters: Map<Function, ParameterConverter> = new Map<Function, ParameterConverter>();
53
+ public router: express.Router;
54
+
55
+ private debugger = {
56
+ build: debug('typescript-rest:server-container:build'),
57
+ runtime: debug('typescript-rest:server-container:runtime')
58
+ };
59
+ private upload: multer.Multer;
60
+ private serverClasses: Map<Function, ServiceClass> = new Map<Function, ServiceClass>();
61
+ private paths: Map<string, Set<HttpMethod>> = new Map<string, Set<HttpMethod>>();
62
+ private pathsResolved: boolean = false;
63
+
64
+ private constructor() {
65
+ // noop, make the constructor private
66
+ }
67
+
68
+ public registerServiceClass(target: Function): ServiceClass {
69
+ this.pathsResolved = false;
70
+ target = this.serviceFactory.getTargetClass(target);
71
+ if (!this.serverClasses.has(target)) {
72
+ this.debugger.build('Registering a new service class, %o', target);
73
+ this.serverClasses.set(target, new ServiceClass(target));
74
+ this.inheritParentClass(target);
75
+ }
76
+ const serviceClass: ServiceClass = this.serverClasses.get(target);
77
+ return serviceClass;
78
+ }
79
+
80
+ public registerServiceMethod(target: Function, methodName: string): ServiceMethod {
81
+ if (methodName) {
82
+ this.pathsResolved = false;
83
+ const classData: ServiceClass = this.registerServiceClass(target);
84
+ if (!classData.methods.has(methodName)) {
85
+ this.debugger.build('Registering the rest method <%s> for the service class, %o', methodName, target);
86
+ classData.methods.set(methodName, new ServiceMethod());
87
+ }
88
+ const serviceMethod: ServiceMethod = classData.methods.get(methodName);
89
+ return serviceMethod;
90
+ }
91
+ return null;
92
+ }
93
+
94
+ public getPaths(): Set<string> {
95
+ this.resolveAllPaths();
96
+ const result = new Set<string>();
97
+ this.paths.forEach((value, key) => {
98
+ result.add(key);
99
+ });
100
+ return result;
101
+ }
102
+
103
+ public getHttpMethods(path: string): Set<HttpMethod> {
104
+ this.resolveAllPaths();
105
+ const methods: Set<HttpMethod> = this.paths.get(path);
106
+ return methods || new Set<HttpMethod>();
107
+ }
108
+
109
+ public buildServices(types?: Array<Function>) {
110
+ if (types) {
111
+ types = types.map((type) => this.serviceFactory.getTargetClass(type));
112
+ }
113
+ this.debugger.build('Creating service endpoints for types: %o', types);
114
+ if (this.authenticator) {
115
+ this.authenticator.forEach((auth, name) => {
116
+ this.debugger.build('Initializing authenticator: %s', name);
117
+ auth.initialize(this.router);
118
+ });
119
+ }
120
+ this.serverClasses.forEach((classData) => {
121
+ if (!classData.isAbstract) {
122
+ classData.methods.forEach((method) => {
123
+ if (this.validateTargetType(classData.targetClass, types)) {
124
+ this.buildService(classData, method);
125
+ }
126
+ });
127
+ }
128
+ });
129
+ this.pathsResolved = true;
130
+ this.handleNotAllowedMethods();
131
+ }
132
+
133
+ private inheritParentClass(target: Function) {
134
+ const classData: ServiceClass = this.serverClasses.get(target);
135
+ const parent = Object.getPrototypeOf(classData.targetClass.prototype).constructor;
136
+ const parentClassData: ServiceClass = this.getServiceClass(parent);
137
+ if (parentClassData) {
138
+ if (parentClassData.methods) {
139
+ parentClassData.methods.forEach((value, key) => {
140
+ classData.methods.set(key, _.cloneDeep(value));
141
+ });
142
+ }
143
+
144
+ if (parentClassData.properties) {
145
+ parentClassData.properties.forEach((value, key) => {
146
+ classData.properties.set(key, _.cloneDeep(value));
147
+ });
148
+ }
149
+
150
+ if (parentClassData.languages) {
151
+ classData.languages = _.union(classData.languages, parentClassData.languages);
152
+ }
153
+
154
+ if (parentClassData.accepts) {
155
+ classData.accepts = _.union(classData.accepts, parentClassData.accepts);
156
+ }
157
+ }
158
+ this.debugger.build('Service class registered with the given metadata: %o', classData);
159
+ }
160
+
161
+ private buildService(serviceClass: ServiceClass, serviceMethod: ServiceMethod) {
162
+ this.debugger.build('Creating service endpoint for method: %o', serviceMethod);
163
+ if (!serviceMethod.resolvedPath) {
164
+ this.resolveProperties(serviceClass, serviceMethod);
165
+ }
166
+
167
+ let args: Array<any> = [serviceMethod.resolvedPath];
168
+ args = args.concat(this.buildSecurityMiddlewares(serviceClass, serviceMethod));
169
+ args = args.concat(this.buildParserMiddlewares(serviceClass, serviceMethod));
170
+ args.push(this.buildServiceMiddleware(serviceMethod, serviceClass));
171
+ switch (serviceMethod.httpMethod) {
172
+ case HttpMethod.GET:
173
+ this.router.get.apply(this.router, args);
174
+ break;
175
+ case HttpMethod.POST:
176
+ this.router.post.apply(this.router, args);
177
+ break;
178
+ case HttpMethod.PUT:
179
+ this.router.put.apply(this.router, args);
180
+ break;
181
+ case HttpMethod.DELETE:
182
+ this.router.delete.apply(this.router, args);
183
+ break;
184
+ case HttpMethod.HEAD:
185
+ this.router.head.apply(this.router, args);
186
+ break;
187
+ case HttpMethod.OPTIONS:
188
+ this.router.options.apply(this.router, args);
189
+ break;
190
+ case HttpMethod.PATCH:
191
+ this.router.patch.apply(this.router, args);
192
+ break;
193
+
194
+ default:
195
+ throw Error(`Invalid http method for service [${serviceMethod.resolvedPath}]`);
196
+ }
197
+ }
198
+
199
+ private resolveAllPaths() {
200
+ if (!this.pathsResolved) {
201
+ this.debugger.build('Building the server list of paths');
202
+ this.paths.clear();
203
+ this.serverClasses.forEach((classData) => {
204
+ classData.methods.forEach((method) => {
205
+ if (!method.resolvedPath) {
206
+ this.resolveProperties(classData, method);
207
+ }
208
+ });
209
+ });
210
+ this.pathsResolved = true;
211
+ }
212
+ }
213
+
214
+ private getServiceClass(target: Function): ServiceClass {
215
+ target = this.serviceFactory.getTargetClass(target);
216
+ return this.serverClasses.get(target) || null;
217
+ }
218
+
219
+ private resolveProperties(serviceClass: ServiceClass, serviceMethod: ServiceMethod): void {
220
+ this.resolveLanguages(serviceClass, serviceMethod);
221
+ this.resolveAccepts(serviceClass, serviceMethod);
222
+ this.resolvePath(serviceClass, serviceMethod);
223
+ }
224
+
225
+ private resolveLanguages(serviceClass: ServiceClass, serviceMethod: ServiceMethod): void {
226
+ this.debugger.build('Resolving the list of acceptable languages for method %s', serviceMethod.name);
227
+
228
+ const resolvedLanguages = _.union(serviceClass.languages, serviceMethod.languages);
229
+ if (resolvedLanguages.length > 0) {
230
+ serviceMethod.resolvedLanguages = resolvedLanguages;
231
+ }
232
+ }
233
+
234
+ private resolveAccepts(serviceClass: ServiceClass, serviceMethod: ServiceMethod): void {
235
+ this.debugger.build('Resolving the list of acceptable types for method %s', serviceMethod.name);
236
+ const resolvedAccepts = _.union(serviceClass.accepts, serviceMethod.accepts);
237
+ if (resolvedAccepts.length > 0) {
238
+ serviceMethod.resolvedAccepts = resolvedAccepts;
239
+ }
240
+ }
241
+
242
+ private resolvePath(serviceClass: ServiceClass, serviceMethod: ServiceMethod): void {
243
+ this.debugger.build('Resolving the path for method %s', serviceMethod.name);
244
+
245
+ const classPath: string = serviceClass.path ? serviceClass.path.trim() : '';
246
+ let resolvedPath = _.startsWith(classPath, '/') ? classPath : '/' + classPath;
247
+ if (_.endsWith(resolvedPath, '/')) {
248
+ resolvedPath = resolvedPath.slice(0, resolvedPath.length - 1);
249
+ }
250
+
251
+ if (serviceMethod.path) {
252
+ const methodPath: string = serviceMethod.path.trim();
253
+ resolvedPath = resolvedPath + (_.startsWith(methodPath, '/') ? methodPath : '/' + methodPath);
254
+ }
255
+
256
+ let declaredHttpMethods: Set<HttpMethod> = this.paths.get(resolvedPath);
257
+ if (!declaredHttpMethods) {
258
+ declaredHttpMethods = new Set<HttpMethod>();
259
+ this.paths.set(resolvedPath, declaredHttpMethods);
260
+ }
261
+ if (declaredHttpMethods.has(serviceMethod.httpMethod)) {
262
+ throw Error(`Duplicated declaration for path [${resolvedPath}], method [${serviceMethod.httpMethod}].`);
263
+ }
264
+ declaredHttpMethods.add(serviceMethod.httpMethod);
265
+ serviceMethod.resolvedPath = resolvedPath;
266
+ }
267
+
268
+ private validateTargetType(targetClass: Function, types: Array<Function>): boolean {
269
+ if (types && types.length > 0) {
270
+ return types.indexOf(targetClass) > -1;
271
+ }
272
+ return true;
273
+ }
274
+
275
+ private handleNotAllowedMethods() {
276
+ this.debugger.build('Creating middleware to handle not allowed methods');
277
+ const paths: Set<string> = this.getPaths();
278
+ paths.forEach((path) => {
279
+ const supported: Set<HttpMethod> = this.getHttpMethods(path);
280
+ const allowedMethods: Array<string> = new Array<string>();
281
+ supported.forEach((method: HttpMethod) => {
282
+ allowedMethods.push(HttpMethod[method]);
283
+ });
284
+ const allowed: string = allowedMethods.join(', ');
285
+ this.debugger.build('Registering middleware to validate allowed HTTP methods for path %s.', path);
286
+ this.debugger.build('Allowed HTTP methods [%s].', allowed);
287
+ this.router.all(path, (req: express.Request, res: express.Response, next: express.NextFunction) => {
288
+ if (res.headersSent || allowedMethods.indexOf(req.method) > -1) {
289
+ next();
290
+ } else {
291
+ res.set('Allow', allowed);
292
+ throw new Errors.MethodNotAllowedError();
293
+ }
294
+ });
295
+ });
296
+ }
297
+
298
+ private getUploader(): multer.Multer {
299
+ if (!this.upload) {
300
+ const options: multer.Options = {};
301
+ if (this.fileDest) {
302
+ options.dest = this.fileDest;
303
+ }
304
+ if (this.fileFilter) {
305
+ options.fileFilter = this.fileFilter;
306
+ }
307
+ if (this.fileLimits) {
308
+ options.limits = this.fileLimits;
309
+ }
310
+ if (options.dest) {
311
+ this.debugger.build('Creating a file Uploader with options: %o.', options);
312
+ this.upload = multer(options);
313
+ } else {
314
+ this.debugger.build('Creating a file Uploader with the default options.');
315
+ this.upload = multer();
316
+ }
317
+ }
318
+ return this.upload;
319
+ }
320
+
321
+ private buildServiceMiddleware(serviceMethod: ServiceMethod, serviceClass: ServiceClass) {
322
+ const serviceInvoker = new ServiceInvoker(serviceClass, serviceMethod);
323
+ this.debugger.build('Creating the service middleware for method <%s>.', serviceMethod.name);
324
+ return async (req: express.Request, res: express.Response, next: express.NextFunction) => {
325
+ const context: ServiceContext = new ServiceContext();
326
+ context.request = req;
327
+ context.response = res;
328
+ context.next = next;
329
+ await serviceInvoker.callService(context);
330
+ };
331
+ }
332
+
333
+ private buildSecurityMiddlewares(serviceClass: ServiceClass, serviceMethod: ServiceMethod) {
334
+ const result: Array<express.RequestHandler> = new Array<express.RequestHandler>();
335
+ const authenticatorMap: Record<string, Array<string>> | undefined =
336
+ serviceMethod.authenticator || serviceClass.authenticator;
337
+ if (this.authenticator && authenticatorMap) {
338
+ const authenticatorNames: Array<string> = Object.keys(authenticatorMap);
339
+ for (const authenticatorName of authenticatorNames) {
340
+ let roles: Array<string> = authenticatorMap[authenticatorName];
341
+ this.debugger.build(
342
+ 'Registering an authenticator middleware <%s> for method <%s>.',
343
+ authenticatorName,
344
+ serviceMethod.name
345
+ );
346
+ const authenticator = this.getAuthenticator(authenticatorName);
347
+ result.push(authenticator.getMiddleware());
348
+ roles = roles.filter((role) => role !== '*');
349
+ if (roles.length) {
350
+ this.debugger.build(
351
+ 'Registering a role validator middleware <%s> for method <%s>.',
352
+ authenticatorName,
353
+ serviceMethod.name
354
+ );
355
+ this.debugger.build('Roles: <%j>.', roles);
356
+ result.push(this.buildAuthMiddleware(authenticator, roles));
357
+ }
358
+ }
359
+ }
360
+
361
+ return result;
362
+ }
363
+
364
+ private getAuthenticator(authenticatorName: string) {
365
+ if (!this.authenticator.has(authenticatorName)) {
366
+ throw new Error(`Invalid authenticator name ${authenticatorName}`);
367
+ }
368
+ return this.authenticator.get(authenticatorName);
369
+ }
370
+
371
+ private buildAuthMiddleware(authenticator: ServiceAuthenticator, roles: Array<string>): express.RequestHandler {
372
+ return (req: Request, res: Response, next: NextFunction) => {
373
+ const requestRoles = authenticator.getRoles(req, res);
374
+ if (this.debugger.runtime.enabled) {
375
+ this.debugger.runtime('Validating authentication roles: <%j>.', requestRoles);
376
+ }
377
+ if (requestRoles.some((role: string) => roles.indexOf(role) >= 0)) {
378
+ next();
379
+ } else {
380
+ throw new Errors.ForbiddenError();
381
+ }
382
+ };
383
+ }
384
+
385
+ private buildParserMiddlewares(
386
+ serviceClass: ServiceClass,
387
+ serviceMethod: ServiceMethod
388
+ ): Array<express.RequestHandler> {
389
+ const result: Array<express.RequestHandler> = new Array<express.RequestHandler>();
390
+ const bodyParserOptions = serviceMethod.bodyParserOptions || serviceClass.bodyParserOptions;
391
+
392
+ if (serviceMethod.mustParseCookies) {
393
+ this.debugger.build('Registering cookie parser middleware for method <%s>.', serviceMethod.name);
394
+ result.push(this.buildCookieParserMiddleware());
395
+ }
396
+ if (serviceMethod.mustParseBody) {
397
+ const bodyParserType = serviceMethod.bodyParserType || serviceClass.bodyParserType || ParserType.json;
398
+ this.debugger.build(
399
+ 'Registering body %s parser middleware for method <%s>' + ' with options: %j.',
400
+ ParserType[bodyParserType],
401
+ serviceMethod.name,
402
+ bodyParserOptions
403
+ );
404
+ result.push(this.buildBodyParserMiddleware(serviceMethod, bodyParserOptions, bodyParserType));
405
+ }
406
+ if (serviceMethod.mustParseForms || serviceMethod.acceptMultiTypedParam) {
407
+ this.debugger.build(
408
+ 'Registering body form parser middleware for method <%s>' + ' with options: %j.',
409
+ serviceMethod.name,
410
+ bodyParserOptions
411
+ );
412
+ result.push(this.buildFormParserMiddleware(bodyParserOptions));
413
+ }
414
+ if (serviceMethod.files.length > 0) {
415
+ this.debugger.build('Registering file parser middleware for method <%s>.', serviceMethod.name);
416
+ result.push(this.buildFilesParserMiddleware(serviceMethod));
417
+ }
418
+
419
+ return result;
420
+ }
421
+
422
+ private buildBodyParserMiddleware(
423
+ serviceMethod: ServiceMethod,
424
+ bodyParserOptions: any,
425
+ bodyParserType: ParserType
426
+ ) {
427
+ switch (bodyParserType) {
428
+ case ParserType.text:
429
+ return this.buildTextBodyParserMiddleware(bodyParserOptions);
430
+ case ParserType.raw:
431
+ return this.buildRawBodyParserMiddleware(bodyParserOptions);
432
+ default:
433
+ return this.buildJsonBodyParserMiddleware(bodyParserOptions);
434
+ }
435
+ }
436
+
437
+ private buildFilesParserMiddleware(serviceMethod: ServiceMethod) {
438
+ const options: Array<multer.Field> = new Array<multer.Field>();
439
+ serviceMethod.files.forEach((fileData) => {
440
+ if (fileData.singleFile) {
441
+ options.push({ name: fileData.name, maxCount: 1 });
442
+ } else {
443
+ options.push({ name: fileData.name });
444
+ }
445
+ });
446
+ this.debugger.build('Creating file parser with options %j.', options);
447
+ return this.getUploader().fields(options);
448
+ }
449
+
450
+ private buildFormParserMiddleware(bodyParserOptions: any) {
451
+ if (!bodyParserOptions) {
452
+ bodyParserOptions = { extended: true };
453
+ }
454
+ this.debugger.build('Creating form body parser with options %j.', bodyParserOptions);
455
+ const middleware = bodyParser.urlencoded(bodyParserOptions);
456
+ return middleware;
457
+ }
458
+
459
+ private buildJsonBodyParserMiddleware(bodyParserOptions: any) {
460
+ let middleware: express.RequestHandler;
461
+ this.debugger.build('Creating json body parser with options %j.', bodyParserOptions || {});
462
+ if (bodyParserOptions) {
463
+ middleware = bodyParser.json(bodyParserOptions);
464
+ } else {
465
+ middleware = bodyParser.json();
466
+ }
467
+ return middleware;
468
+ }
469
+
470
+ private buildTextBodyParserMiddleware(bodyParserOptions: any) {
471
+ let middleware: express.RequestHandler;
472
+ this.debugger.build('Creating text body parser with options %j.', bodyParserOptions || {});
473
+ if (bodyParserOptions) {
474
+ middleware = bodyParser.text(bodyParserOptions);
475
+ } else {
476
+ middleware = bodyParser.text();
477
+ }
478
+ return middleware;
479
+ }
480
+
481
+ private buildRawBodyParserMiddleware(bodyParserOptions: any) {
482
+ let middleware: express.RequestHandler;
483
+ this.debugger.build('Creating raw body parser with options %j.', bodyParserOptions || {});
484
+ if (bodyParserOptions) {
485
+ middleware = bodyParser.raw(bodyParserOptions);
486
+ } else {
487
+ middleware = bodyParser.raw();
488
+ }
489
+ return middleware;
490
+ }
491
+
492
+ private buildCookieParserMiddleware() {
493
+ const args = [];
494
+ if (this.cookiesSecret) {
495
+ args.push(this.cookiesSecret);
496
+ }
497
+ if (this.cookiesDecoder) {
498
+ args.push({ decode: this.cookiesDecoder });
499
+ }
500
+ this.debugger.build('Creating cookie parser with options %j.', args);
501
+ const middleware = cookieParser.apply(this, args);
502
+ return middleware;
503
+ }
504
+ }