From 2962181ed4fb3ab829d53cd70b3ffd17ac0a916b Mon Sep 17 00:00:00 2001 From: jannyHou Date: Mon, 25 May 2020 15:58:48 -0400 Subject: [PATCH] fix: array decorator --- docs/site/Model.md | 21 +++++++++ .../integration/build-schema.integration.ts | 44 +++++++++++++++---- .../src/__tests__/unit/build-schema.unit.ts | 6 --- .../src/build-schema.ts | 10 +++-- 4 files changed, 63 insertions(+), 18 deletions(-) diff --git a/docs/site/Model.md b/docs/site/Model.md index b15e55a762e9..683b37413985 100644 --- a/docs/site/Model.md +++ b/docs/site/Model.md @@ -851,6 +851,27 @@ class TestModel { } ``` +To define a nested array property, you must provide the `jsonSchema` field to +describe the sub-array property. For example: + +```ts +@model() +class TestModel { + // alternatively use @property.array('array') + @property.array(Array, { + jsonSchema: { + type: 'array', + items: {type: 'string'}, + }, + }) + nestedArr: Array>; +} +``` + +If the `jsonSchema` field is missing, you will get an error saying + +> You must provide the "jsonSchema" field when define a nested array property' + ### Validation Rules You can also specify the validation rules in the field `jsonSchema`. For diff --git a/packages/repository-json-schema/src/__tests__/integration/build-schema.integration.ts b/packages/repository-json-schema/src/__tests__/integration/build-schema.integration.ts index 85b0769e1679..de54e31e2abe 100644 --- a/packages/repository-json-schema/src/__tests__/integration/build-schema.integration.ts +++ b/packages/repository-json-schema/src/__tests__/integration/build-schema.integration.ts @@ -251,6 +251,34 @@ describe('build-schema', () => { expectValidJsonSchema(jsonSchema); }); + it('properly converts nested array property when json schema provided', () => { + @model() + class TestModel { + // alternatively use @property.array('array') + @property.array(Array, { + jsonSchema: { + type: 'array', + items: {type: 'string'}, + }, + }) + nestedArr: Array>; + } + + const jsonSchema = modelToJsonSchema(TestModel); + expect(jsonSchema.properties).to.deepEqual({ + nestedArr: { + type: 'array', + items: { + type: 'array', + items: { + type: 'string', + }, + }, + }, + }); + expectValidJsonSchema(jsonSchema); + }); + it('properly converts properties with enum in json schema', () => { enum QueryLanguage { JSON = 'json', @@ -308,22 +336,20 @@ describe('build-schema', () => { }); }); - it('properly converts properties with recursive arrays', () => { + it('throws for nested array property when json schema is missing', () => { @model() class RecursiveArray { @property.array(Array) recArr: string[][]; } - const jsonSchema = modelToJsonSchema(RecursiveArray); - expect(jsonSchema.properties).to.eql({ - recArr: { - type: 'array', - items: { - type: 'array', - }, + expect.throws( + () => { + modelToJsonSchema(RecursiveArray); }, - }); + Error, + 'You must provide the "jsonSchema" field when define a nested array property', + ); }); it('supports explicit primitive type decoration via strings', () => { diff --git a/packages/repository-json-schema/src/__tests__/unit/build-schema.unit.ts b/packages/repository-json-schema/src/__tests__/unit/build-schema.unit.ts index 2d4490a3dc75..958363dfb8a2 100644 --- a/packages/repository-json-schema/src/__tests__/unit/build-schema.unit.ts +++ b/packages/repository-json-schema/src/__tests__/unit/build-schema.unit.ts @@ -71,12 +71,6 @@ describe('build-schema', () => { }); describe('metaToJsonSchema', () => { - it('errors out if "itemType" is an array', () => { - expect(() => metaToJsonProperty({type: Array, itemType: []})).to.throw( - /itemType as an array is not supported/, - ); - }); - it('converts Boolean', () => { expect(metaToJsonProperty({type: Boolean})).to.eql({ type: 'boolean', diff --git a/packages/repository-json-schema/src/build-schema.ts b/packages/repository-json-schema/src/build-schema.ts index 257f14fc4749..a45cd2c6a4a2 100644 --- a/packages/repository-json-schema/src/build-schema.ts +++ b/packages/repository-json-schema/src/build-schema.ts @@ -10,6 +10,7 @@ import { ModelMetadataHelper, Null, PropertyDefinition, + PropertyType, RelationMetadata, resolveType, } from '@loopback/repository'; @@ -242,7 +243,7 @@ export function stringTypeToWrapper(type: string | Function): Function { * Determines whether a given string or constructor is array type or not * @param type - Type as string or wrapper */ -export function isArrayType(type: string | Function) { +export function isArrayType(type: string | Function | PropertyType) { return type === Array || type === 'array'; } @@ -256,8 +257,11 @@ export function metaToJsonProperty(meta: PropertyDefinition): JsonSchema { let propertyType = meta.type as string | Function; if (isArrayType(propertyType) && meta.itemType) { - if (Array.isArray(meta.itemType)) { - throw new Error('itemType as an array is not supported'); + if (isArrayType(meta.itemType) && !meta.jsonSchema) { + throw new Error( + 'You must provide the "jsonSchema" field when define ' + + 'a nested array property', + ); } result = {type: 'array', items: propDef}; propertyType = meta.itemType as string | Function;