From d13f28f400fd1d19fcc2bc06a172feb040de3e01 Mon Sep 17 00:00:00 2001 From: Teddy Chambard Date: Wed, 4 Jul 2018 10:46:34 +0200 Subject: [PATCH 1/3] Add StreamFile(s)Param decorators --- src/decorators.ts | 23 +++++++++++++++++++++++ src/metadata/parameterGenerator.ts | 4 ++++ 2 files changed, 27 insertions(+) diff --git a/src/decorators.ts b/src/decorators.ts index af6e42c..640e93f 100644 --- a/src/decorators.ts +++ b/src/decorators.ts @@ -110,3 +110,26 @@ export function IsFloat(target: any, propertyKey: string, parameterIndex?: numbe export function IsDouble(target: any, propertyKey: string, parameterIndex?: number) { return; } + +/** + * Creates a mapping between a file on a multipart request and a method + * argument. + * Unlike @FileParam provided by typescript-rest, this decorator allows to pipe the request. + */ +export function StreamFileParam(name: string) { + return function (...args: any[]) { + return; + }; +} + +/** + * Creates a mapping between multiple files on a multipart request and a method + * argument. + * Unlike @FileParam provided by typescript-rest, this decorator allows to pipe the request. + */ +export function StreamFilesParam(name: string) { + return function (...args: any[]) { + return; + }; +} + diff --git a/src/metadata/parameterGenerator.ts b/src/metadata/parameterGenerator.ts index 5c1699f..051efa2 100644 --- a/src/metadata/parameterGenerator.ts +++ b/src/metadata/parameterGenerator.ts @@ -31,6 +31,10 @@ export class ParameterGenerator { return this.getFileParameter(this.parameter); case 'FilesParam': return this.getFilesParameter(this.parameter); + case 'StreamFileParam': + return this.getFileParameter(this.parameter); + case 'StreamFilesParam': + return this.getFilesParameter(this.parameter); case 'Context': case 'ContextRequest': case 'ContextResponse': From 9bc704a3393c475f4e799f3d63268d9e2d1affac Mon Sep 17 00:00:00 2001 From: Teddy Chambard Date: Wed, 4 Jul 2018 11:10:20 +0200 Subject: [PATCH 2/3] Fix missing conditions --- src/metadata/parameterGenerator.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/metadata/parameterGenerator.ts b/src/metadata/parameterGenerator.ts index 051efa2..6e952d8 100644 --- a/src/metadata/parameterGenerator.ts +++ b/src/metadata/parameterGenerator.ts @@ -93,7 +93,7 @@ export class ParameterGenerator { return { description: this.getParameterDescription(parameter), in: 'formData', - name: getDecoratorTextValue(this.parameter, ident => ident.text === 'FileParam') || parameterName, + name: getDecoratorTextValue(this.parameter, ident => ident.text === 'FileParam' || ident.text === 'StreamFileParam') || parameterName, parameterName, required: !parameter.questionToken, type: { typeName: 'file' } @@ -110,7 +110,7 @@ export class ParameterGenerator { return { description: this.getParameterDescription(parameter), in: 'formData', - name: getDecoratorTextValue(this.parameter, ident => ident.text === 'FilesParam') || parameterName, + name: getDecoratorTextValue(this.parameter, ident => ident.text === 'FilesParam' || ident.text === 'StreamFilesParam') || parameterName, parameterName, required: !parameter.questionToken, type: { typeName: 'file' } @@ -259,7 +259,7 @@ export class ParameterGenerator { return ['HeaderParam', 'QueryParam', 'Param', 'FileParam', 'PathParam', 'FilesParam', 'FormParam', 'CookieParam', 'Context', 'ContextRequest', 'ContextResponse', 'ContextNext', - 'ContextLanguage', 'ContextAccept'].some(d => d === decoratorName); + 'ContextLanguage', 'ContextAccept', 'StreamFileParam', 'StreamFilesParam'].some(d => d === decoratorName); } private supportPathDataType(parameterType: Type) { From 990aa14d10d42d4c5c05d05374f6bba46d435010 Mon Sep 17 00:00:00 2001 From: Teddy Chambard Date: Fri, 19 Oct 2018 15:08:08 +0200 Subject: [PATCH 3/3] Add unit tests --- test/data/apis.ts | 12 ++++++++++++ test/unit/definitions.spec.ts | 10 ++++++++++ 2 files changed, 22 insertions(+) diff --git a/test/data/apis.ts b/test/data/apis.ts index 096d047..4ba4c0b 100644 --- a/test/data/apis.ts +++ b/test/data/apis.ts @@ -339,6 +339,18 @@ export class ParameterizedEndpoint { test(@PathParam('objectId') objectId: string): PrimitiveClassModel { return new PrimitiveClassModel(); } + + @Path('/file') + @POST + file(@FileParam('file') file: Express.Multer.File): PrimitiveClassModel { + return new PrimitiveClassModel(); + } + + @Path('/stream') + @POST + stream(@swagger.StreamFileParam('stream') file: Express.Multer.File): PrimitiveClassModel { + return new PrimitiveClassModel(); + } } export abstract class Entity { diff --git a/test/unit/definitions.spec.ts b/test/unit/definitions.spec.ts index 75977e8..0ce5577 100644 --- a/test/unit/definitions.spec.ts +++ b/test/unit/definitions.spec.ts @@ -298,6 +298,16 @@ describe('Definition generation', () => { const expression = jsonata('paths."/parameterized/{objectId}/test".get.parameters[0].in'); expect(expression.evaluate(spec)).to.eq('path'); }); + + it('should generate formData param for params declared on method', () => { + const expression = jsonata('paths."/parameterized/{objectId}/file".post.parameters[0].in'); + expect(expression.evaluate(spec)).to.eq('formData'); + }); + + it('should generate path param for params declared on class', () => { + const expression = jsonata('paths."/parameterized/{objectId}/stream".post.parameters[0].in'); + expect(expression.evaluate(spec)).to.eq('formData'); + }); }); describe('AbstractEntityEndpoint', () => {