Repository: nestjs/swagger
Pull request #728 (2020-05-08 11:12:47)

fix(): process isarray for string based property type
## PR Checklist
Please check if your PR fulfills the following requirements:

- [ x ] The commit message follows our guidelines: https://github.com/nestjs/nest/blob/master/CONTRIBUTING.md
- [ x ] Tests for the changes have been added (for bug fixes / features)
- [ ] Docs have been added / updated (for bug fixes / features)


## PR Type
What kind of change does this PR introduce?

<!-- Please check the one that applies to this PR using "x". -->
```
[ x ] Bugfix
[ ] Feature
[ ] Code style update (formatting, local variables)
[ ] Refactoring (no functional changes, no api changes)
[ ] Build related changes
[ ] CI related changes
[ ] Other... Please describe:
```

## What is the current behavior?
Using the following options: 
```
@ApiProperty({ type: 'integer', isArray: true })
someProp: number[];
```
Produces the following swagger parameter definition, ignoring the isArray flag:
```
"someProp": {
  "type": "integer",
},
```

Issue Number: N/A


## What is the new behavior?
Now, when the type option is a string, the isArray property will still be processed, fixing the above issue:
```
@ApiProperty({ type: 'integer', isArray: true })
someProp: number[];
```
Produces the following swagger parameter definition:
```
"someProp": {
  "type": "array",
  "items": {
    "type": "integer"
  }
},
```

## Does this PR introduce a breaking change?
```
[ ] Yes
[ x ] No
```

<!-- If this PR contains a breaking change, please describe the impact and migration path for existing applications below. -->


## Other information


Patch:
diff --git a/lib/services/schema-object-factory.ts b/lib/services/schema-object-factory.ts
index fb159211..a52d772b 100644
--- a/lib/services/schema-object-factory.ts
+++ b/lib/services/schema-object-factory.ts
@@ -43,7 +43,7 @@ export class SchemaObjectFactory {
     schemas: SchemaObject[],
     schemaRefsStack: string[] = []
   ): Array<ParamWithTypeMetadata | BaseParameterObject> {
-    return parameters.map(param => {
+    return parameters.map((param) => {
       if (!isBodyParameter(param)) {
         return this.createQueryOrParamSchema(param, schemas, schemaRefsStack);
       }
@@ -117,7 +117,7 @@ export class SchemaObjectFactory {
     const extraModels = exploreGlobalApiExtraModelsMetadata(
       type as Type<unknown>
     );
-    extraModels.forEach(item =>
+    extraModels.forEach((item) =>
       this.exploreModelSchema(item, schemas, schemaRefsStack)
     );
 
@@ -125,7 +125,7 @@ export class SchemaObjectFactory {
     const modelProperties = this.modelPropertiesAccessor.getModelProperties(
       prototype
     );
-    const propertiesWithType = modelProperties.map(key => {
+    const propertiesWithType = modelProperties.map((key) => {
       const property = this.mergePropertyWithMetadata(
         key,
         prototype,
@@ -134,20 +134,20 @@ export class SchemaObjectFactory {
       );
 
       const schemaCombinators = ['oneOf', 'anyOf', 'allOf'];
-      if (schemaCombinators.some(key => key in property)) {
+      if (schemaCombinators.some((key) => key in property)) {
         delete (property as SchemaObjectMetadata).type;
       }
       return property;
     });
     const typeDefinition: SchemaObject = {
       type: 'object',
-      properties: mapValues(keyBy(propertiesWithType, 'name'), property =>
+      properties: mapValues(keyBy(propertiesWithType, 'name'), (property) =>
         omit(property, ['name', 'isArray', 'required', 'enumName'])
       ) as Record<string, SchemaObject | ReferenceObject>
     };
     const typeDefinitionRequiredFields = (propertiesWithType as SchemaObjectMetadata[])
-      .filter(property => property.required != false)
-      .map(property => property.name);
+      .filter((property) => property.required != false)
+      .map((property) => property.name);
 
     if (typeDefinitionRequiredFields.length > 0) {
       typeDefinition['required'] = typeDefinitionRequiredFields;
@@ -194,6 +194,13 @@ export class SchemaObjectFactory {
           schemaRefsStack
         );
       }
+      if (metadata.isArray) {
+        return this.transformToArraySchemaProperty(
+          metadata,
+          key,
+          metadata.type
+        );
+      }
 
       return {
         ...metadata,
@@ -399,7 +406,7 @@ export class SchemaObjectFactory {
   ) {
     const objLiteralKeys = Object.keys(literalObj);
     const properties = {};
-    objLiteralKeys.forEach(key => {
+    objLiteralKeys.forEach((key) => {
       const propertyCompilerMetadata = literalObj[key];
       if (isEnumArray<Record<string, any>>(propertyCompilerMetadata)) {
         propertyCompilerMetadata.type = 'array';
@@ -440,7 +447,8 @@ export class SchemaObjectFactory {
 
   private isPrimitiveType(type: Type<unknown> | string): boolean {
     return (
-      isFunction(type) && [String, Boolean, Number].some(item => item === type)
+      isFunction(type) &&
+      [String, Boolean, Number].some((item) => item === type)
     );
   }
 


Test patch:
diff --git a/test/services/fixtures/create-user.dto.ts b/test/services/fixtures/create-user.dto.ts
index 9cef41a7..52a5777c 100644
--- a/test/services/fixtures/create-user.dto.ts
+++ b/test/services/fixtures/create-user.dto.ts
@@ -51,6 +51,12 @@ export class CreateUserDto {
   })
   urls: string[];
 
+  @ApiProperty({
+    type: 'integer',
+    isArray: true
+  })
+  luckyNumbers: number[];
+
   @ApiProperty({
     type: 'array',
     items: {
diff --git a/test/services/schema-object-factory.spec.ts b/test/services/schema-object-factory.spec.ts
index 4e91dbc3..7b1d6551 100644
--- a/test/services/schema-object-factory.spec.ts
+++ b/test/services/schema-object-factory.spec.ts
@@ -145,6 +145,12 @@ describe('SchemaObjectFactory', () => {
             },
             type: 'array'
           },
+          luckyNumbers: {
+            type: 'array',
+            items: {
+              type: 'integer'
+            }
+          },
           options: {
             items: {
               properties: {
@@ -170,6 +176,7 @@ describe('SchemaObjectFactory', () => {
           'profile',
           'tags',
           'urls',
+          'luckyNumbers',
           'options',
           'allOf',
           'houses',