diff --git a/src/client/interfaces/Enum.ts b/src/client/interfaces/Enum.ts index 147c240a..a67c575e 100644 --- a/src/client/interfaces/Enum.ts +++ b/src/client/interfaces/Enum.ts @@ -1,4 +1,5 @@ export interface Enum { name: string; value: string; + type: string; } diff --git a/src/client/interfaces/Model.d.ts b/src/client/interfaces/Model.d.ts index d82657a5..043052a4 100644 --- a/src/client/interfaces/Model.d.ts +++ b/src/client/interfaces/Model.d.ts @@ -7,8 +7,9 @@ export interface Model { base: string; template: string | null; description: string | null; + validation: string | null; extends: string[]; imports: string[]; enum: Enum[]; - properties: Map; + properties: ModelProperty[]; } diff --git a/src/client/interfaces/ModelProperty.d.ts b/src/client/interfaces/ModelProperty.d.ts index a1abdac0..48555e6a 100644 --- a/src/client/interfaces/ModelProperty.d.ts +++ b/src/client/interfaces/ModelProperty.d.ts @@ -7,4 +7,5 @@ export interface ModelProperty { required: boolean; nullable: boolean; description: string | null; + validation: string | null; } diff --git a/src/openApi/v2/parser/getEnum.ts b/src/openApi/v2/parser/getEnum.ts index bc0d24cf..094a552d 100644 --- a/src/openApi/v2/parser/getEnum.ts +++ b/src/openApi/v2/parser/getEnum.ts @@ -1,4 +1,5 @@ import { Enum } from '../../../client/interfaces/Enum'; +import { PrimaryType } from './constants'; export function getEnum(values?: (string | number)[]): Enum[] { if (Array.isArray(values)) { @@ -11,11 +12,13 @@ export function getEnum(values?: (string | number)[]): Enum[] { return { name: `NUM_${value}`, value: String(value), + type: PrimaryType.NUMBER, }; } return { name: value.replace(/([a-z])([A-Z]+)/g, '$1_$2').toUpperCase(), value: `'${value}'`, + type: PrimaryType.STRING, }; }); } diff --git a/src/openApi/v2/parser/getEnumFromDescription.ts b/src/openApi/v2/parser/getEnumFromDescription.ts index 309b5b60..60696e7e 100644 --- a/src/openApi/v2/parser/getEnumFromDescription.ts +++ b/src/openApi/v2/parser/getEnumFromDescription.ts @@ -1,4 +1,5 @@ import { Enum } from '../../../client/interfaces/Enum'; +import { PrimaryType } from './constants'; export function getEnumFromDescription(description: string): Enum[] { // Check if we can find this special format string: @@ -15,6 +16,7 @@ export function getEnumFromDescription(description: string): Enum[] { symbols.push({ name: name.replace(/([a-z])([A-Z]+)/g, '$1_$2').toUpperCase(), value: String(value), + type: PrimaryType.NUMBER, }); } }); diff --git a/src/openApi/v2/parser/getModel.ts b/src/openApi/v2/parser/getModel.ts index 9f8494f7..c52aa137 100644 --- a/src/openApi/v2/parser/getModel.ts +++ b/src/openApi/v2/parser/getModel.ts @@ -5,12 +5,17 @@ import {getType} from './getType'; import {Model} from '../../../client/interfaces/Model'; import {PrimaryType} from './constants'; import {getEnumType} from './getEnumType'; -import {ModelProperty} from '../../../client/interfaces/ModelProperty'; import {getEnum} from './getEnum'; import {getEnumFromDescription} from './getEnumFromDescription'; +import {getTypeFromProperties} from './getTypeFromProperties'; +import {getValidationForRef} from './getValidationForRef'; +import {getValidationForEnum} from './getValidationForEnum'; +import {getValidationForArrayRef} from './getValidationForArrayRef'; +import {getValidationForType} from './getValidationForType'; +import {getValidationForArray} from './getValidationForArray'; +import {getValidationForProperties} from './getValidationForProperties'; -export function getModel(openApi: OpenApi, definition: OpenApiSchema, name: string = 'unknown'): Model { - +export function getModel(openApi: OpenApi, definition: OpenApiSchema, name: string = ''): Model { // TODO: Properties now contain ALL properties, so we need to filter out enums // before we render the file, plus we need to calculate the final TYPE of a model // by checking all the properties! @@ -19,14 +24,15 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, name: stri const result: Model = { name, - type: 'any', - base: 'any', + type: PrimaryType.OBJECT, + base: PrimaryType.OBJECT, template: null, description: getComment(definition.description), + validation: null, extends: [], imports: [], enum: [], - properties: new Map(), + properties: [], }; if (definition.$ref) { @@ -35,6 +41,7 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, name: stri result.base = definitionRef.base; result.template = definitionRef.template; result.imports.push(...definitionRef.imports); + result.validation = getValidationForRef(definitionRef); return result; } @@ -45,6 +52,7 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, name: stri result.type = getEnumType(enumerators); result.base = PrimaryType.STRING; result.enum.push(...enumerators); + result.validation = getValidationForEnum(name, enumerators); return result; } return result; @@ -57,6 +65,7 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, name: stri result.type = getEnumType(enumerators); result.base = PrimaryType.NUMBER; result.enum.push(...enumerators); + result.validation = getValidationForEnum(name, enumerators); return result; } return result; @@ -66,17 +75,19 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, name: stri // so we can create a typed array, otherwise this will be a "any[]". if (definition.type === 'array' && definition.items) { if (definition.items.$ref) { - const arrayItemsRef = getType(definition.items.$ref); - result.type = `${arrayItemsRef.type}[]`; - result.base = arrayItemsRef.base; - result.template = arrayItemsRef.template; - result.imports.push(...arrayItemsRef.imports); + const arrayItems = getType(definition.items.$ref); + result.type = `${arrayItems.type}[]`; + result.base = arrayItems.base; + result.template = arrayItems.template; + result.imports.push(...arrayItems.imports); + result.validation = getValidationForArrayRef(arrayItems); } else { - const arrayItemsModel = getModel(openApi, definition.items); - result.type = `${arrayItemsModel.type}[]`; - result.base = arrayItemsModel.base; - result.template = arrayItemsModel.template; - result.imports.push(...arrayItemsModel.imports); + const arrayItems = getModel(openApi, definition.items); + result.type = `${arrayItems.type}[]`; + result.base = arrayItems.base; + result.template = arrayItems.template; + result.imports.push(...arrayItems.imports); + result.validation = getValidationForArray(name, arrayItems); } return result; } @@ -96,38 +107,43 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, name: stri const propertyRequired = !!(parent.required && parent.required.includes(propertyName)); const propertyReadOnly = !!property.readOnly; if (property.$ref) { - const propertyRef = getType(property.$ref); + const prop = getType(property.$ref); result.base = PrimaryType.OBJECT; - result.imports.push(...propertyRef.imports); - result.properties.set(propertyName, { + result.imports.push(...prop.imports); + result.properties.push({ name: propertyName, - type: propertyRef.type, - base: propertyRef.base, - template: propertyRef.template, + type: prop.type, + base: prop.base, + template: prop.template, readOnly: propertyReadOnly, required: propertyRequired, nullable: false, description: property.description || null, + validation: getValidationForRef(prop), }); } else { - const propertyModel = getModel(openApi, property); + const prop = getModel(openApi, property); result.base = PrimaryType.OBJECT; - result.imports.push(...propertyModel.imports); - result.properties.set(propertyName, { + result.imports.push(...prop.imports); + result.properties.push({ name: propertyName, - type: propertyModel.type, - base: propertyModel.base, - template: propertyModel.template, + type: prop.type, + base: prop.base, + template: prop.template, readOnly: propertyReadOnly, required: propertyRequired, nullable: false, description: property.description || null, + validation: prop.validation, }); } } } } }); + result.type = getTypeFromProperties(result.properties); + result.base = PrimaryType.OBJECT; + result.validation = getValidationForProperties(name, result.properties, result.extends); } if (definition.type === 'object' && definition.properties) { @@ -137,36 +153,65 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, name: stri const propertyRequired = !!(definition.required && definition.required.includes(propertyName)); const propertyReadOnly = !!property.readOnly; if (property.$ref) { - const propertyRef = getType(property.$ref); + const prop = getType(property.$ref); result.base = PrimaryType.OBJECT; - result.imports.push(...propertyRef.imports); - result.properties.set(propertyName, { + result.imports.push(...prop.imports); + result.properties.push({ name: propertyName, - type: propertyRef.type, - base: propertyRef.base, - template: propertyRef.template, + type: prop.type, + base: prop.base, + template: prop.template, readOnly: propertyReadOnly, required: propertyRequired, nullable: false, description: property.description || null, + validation: getValidationForRef(prop), }); } else { - const propertyModel = getModel(openApi, property); + const prop = getModel(openApi, property); result.base = PrimaryType.OBJECT; - result.imports.push(...propertyModel.imports); - result.properties.set(propertyName, { + result.imports.push(...prop.imports); + result.properties.push({ name: propertyName, - type: propertyModel.type, - base: propertyModel.base, - template: propertyModel.template, + type: prop.type, + base: prop.base, + template: prop.template, readOnly: propertyReadOnly, required: propertyRequired, nullable: false, description: property.description || null, + validation: prop.validation, }); } } } + result.type = getTypeFromProperties(result.properties); + result.base = PrimaryType.OBJECT; + result.validation = getValidationForProperties(name, result.properties, result.extends); + return result; + } + + // If a property has additionalProperties, then it likely to be a dictionary type. + // In that case parse the related property and assume it lives inside a string + // based dictionary: { [key:string]: MyType } + if (definition.type === 'object' && definition.additionalProperties && typeof definition.additionalProperties === 'object') { + if (definition.additionalProperties.$ref) { + const additionalProperties = getType(definition.additionalProperties.$ref); + result.type = `Dictionary<${additionalProperties.type}>`; + result.base = 'Dictionary'; + result.template = additionalProperties.type; + result.imports.push(...additionalProperties.imports); + result.imports.push('Dictionary'); + console.log(name, 'Dictionary', result.type); + } else { + const additionalProperties = getModel(openApi, definition.additionalProperties); + result.type = `Dictionary<${additionalProperties.type}>`; + result.base = 'Dictionary'; + result.template = additionalProperties.type; + result.imports.push(...additionalProperties.imports); + result.imports.push('Dictionary'); + console.log(name, 'Dictionary', result.type); + } return result; } @@ -177,6 +222,7 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, name: stri result.base = definitionType.base; result.template = definitionType.template; result.imports.push(...definitionType.imports); + result.validation = getValidationForType(definitionType); return result; } diff --git a/src/openApi/v2/parser/getModelType.ts b/src/openApi/v2/parser/getModelType.ts deleted file mode 100644 index 7e7f3de6..00000000 --- a/src/openApi/v2/parser/getModelType.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { EOL } from 'os'; -import { ModelProperty } from '../../../client/interfaces/ModelProperty'; - -export function getModelType(properties: ModelProperty[]): string { - return [ - `{`, - ...properties.map(property => { - return ` ${property.readOnly ? 'readonly ' : ''}${property.name}${property.required ? '' : '?'}: ${property.type},`; - }), - `}`, - ].join(EOL); -} diff --git a/src/openApi/v2/parser/getModelValidation.ts b/src/openApi/v2/parser/getModelValidation.ts index 1d652c4f..65b006dd 100644 --- a/src/openApi/v2/parser/getModelValidation.ts +++ b/src/openApi/v2/parser/getModelValidation.ts @@ -4,9 +4,9 @@ import { ModelProperty } from '../../../client/interfaces/ModelProperty'; export function getModelValidation(name: string, properties: ModelProperty[]): string { return [ `yup.object().shape({`, - ...properties.map(property => { - return ` ${property.name}: ${property.validation},`; - }), + // ...properties.map(property => { + // return ` ${property.name}: ${property.validation},`; + // }), `}).noUnknown()`, ].join(EOL); } diff --git a/src/openApi/v2/parser/getModels.ts b/src/openApi/v2/parser/getModels.ts index f6c7eb02..0ba3e7a0 100644 --- a/src/openApi/v2/parser/getModels.ts +++ b/src/openApi/v2/parser/getModels.ts @@ -9,10 +9,8 @@ export function getModels(openApi: OpenApi): Map { if (openApi.definitions.hasOwnProperty(definitionName)) { const definition = openApi.definitions[definitionName]; const definitionType = getType(definitionName); - if (!models.has(definitionType.base)) { - const model = getModel(openApi, definition, definitionType.base); - models.set(definitionType.base, model); - } + const model = getModel(openApi, definition, definitionType.base); + models.set(definitionType.base, model); } } return models; diff --git a/src/openApi/v2/parser/getOperation.ts b/src/openApi/v2/parser/getOperation.ts index ec41b6d7..21752df5 100644 --- a/src/openApi/v2/parser/getOperation.ts +++ b/src/openApi/v2/parser/getOperation.ts @@ -10,6 +10,7 @@ import { getOperationResponses } from './getOperationResponses'; import { getOperationResponse } from './getOperationResponse'; import { getOperationErrors } from './getOperationErrors'; import { Operation } from '../../../client/interfaces/Operation'; +import { PrimaryType } from './constants'; export function getOperation(openApi: OpenApi, url: string, method: string, op: OpenApiOperation): Operation { const serviceName = (op.tags && op.tags[0]) || 'Service'; @@ -35,7 +36,7 @@ export function getOperation(openApi: OpenApi, url: string, method: string, op: parametersBody: null, imports: [], errors: [], - result: 'void', + result: PrimaryType.VOID, }; // Parse the operation parameters (path, query, body, etc). diff --git a/src/openApi/v2/parser/getType.spec.ts b/src/openApi/v2/parser/getType.spec.ts index 993f2219..81776728 100644 --- a/src/openApi/v2/parser/getType.spec.ts +++ b/src/openApi/v2/parser/getType.spec.ts @@ -6,7 +6,7 @@ describe('getType', () => { expect(type.type).toEqual('number'); expect(type.base).toEqual('number'); expect(type.template).toEqual(null); - expect(Array.from(type.imports.values())).toEqual([]); + expect(type.imports).toEqual([]); }); it('should convert string', () => { @@ -14,7 +14,7 @@ describe('getType', () => { expect(type.type).toEqual('string'); expect(type.base).toEqual('string'); expect(type.template).toEqual(null); - expect(Array.from(type.imports.values())).toEqual([]); + expect(type.imports).toEqual([]); }); it('should convert string array', () => { @@ -22,7 +22,7 @@ describe('getType', () => { expect(type.type).toEqual('string[]'); expect(type.base).toEqual('string'); expect(type.template).toEqual(null); - expect(Array.from(type.imports.values())).toEqual([]); + expect(type.imports).toEqual([]); }); it('should convert template with primary', () => { @@ -30,7 +30,7 @@ describe('getType', () => { expect(type.type).toEqual('Link'); expect(type.base).toEqual('Link'); expect(type.template).toEqual('string'); - expect(Array.from(type.imports.values())).toEqual(['Link']); + expect(type.imports).toEqual(['Link']); }); it('should convert template with model', () => { @@ -38,7 +38,7 @@ describe('getType', () => { expect(type.type).toEqual('Link'); expect(type.base).toEqual('Link'); expect(type.template).toEqual('Model'); - expect(Array.from(type.imports.values())).toEqual(['Link', 'Model']); + expect(type.imports).toEqual(['Link', 'Model']); }); it('should have double imports', () => { @@ -46,7 +46,7 @@ describe('getType', () => { expect(type.type).toEqual('Link'); expect(type.base).toEqual('Link'); expect(type.template).toEqual('Link'); - expect(Array.from(type.imports.values())).toEqual(['Link', 'Link']); + expect(type.imports).toEqual(['Link', 'Link']); }); it('should convert generic', () => { @@ -54,6 +54,6 @@ describe('getType', () => { expect(type.type).toEqual('T'); expect(type.base).toEqual('T'); expect(type.template).toEqual(null); - expect(Array.from(type.imports.values())).toEqual([]); + expect(type.imports).toEqual([]); }); }); diff --git a/src/openApi/v2/parser/getTypeFromProperties.ts b/src/openApi/v2/parser/getTypeFromProperties.ts new file mode 100644 index 00000000..ee45e223 --- /dev/null +++ b/src/openApi/v2/parser/getTypeFromProperties.ts @@ -0,0 +1,18 @@ +import { EOL } from 'os'; +import { ModelProperty } from '../../../client/interfaces/ModelProperty'; + +export function getTypeFromProperties(properties: ModelProperty[]): string { + return [ + `{`, + ...properties.map(property => { + let type = ''; + type = `${type}${property.readOnly ? 'readonly ' : ''}`; + type = `${type}${property.name}`; + type = `${type}${property.required ? '' : '?'}`; + type = `${type}: ${property.type}`; + type = `${type}${property.nullable ? ' | null' : ''}`; + return `${type},`; + }), + `}`, + ].join(EOL); +} diff --git a/src/openApi/v2/parser/getValidation.ts b/src/openApi/v2/parser/getValidation.ts deleted file mode 100644 index d2c10bbf..00000000 --- a/src/openApi/v2/parser/getValidation.ts +++ /dev/null @@ -1,11 +0,0 @@ -export function getValidation(validation: string, required: boolean = false, nullable: boolean = false): string { - if (required) { - validation = `${validation}.required()`; - } - - if (nullable) { - validation = `${validation}.nullable()`; - } - - return validation; -} diff --git a/src/openApi/v2/parser/getValidationForArray.ts b/src/openApi/v2/parser/getValidationForArray.ts new file mode 100644 index 00000000..48e8ec44 --- /dev/null +++ b/src/openApi/v2/parser/getValidationForArray.ts @@ -0,0 +1,5 @@ +import { Model } from '../../../client/interfaces/Model'; + +export function getValidationForArray(name: string, model: Model): string { + return `yup.array<${name ? name : 'any'}>().of(${model.validation ? model.validation : 'yup.mixed()'})`; +} diff --git a/src/openApi/v2/parser/getValidationForArrayRef.ts b/src/openApi/v2/parser/getValidationForArrayRef.ts index 16f1bc57..d71a2bb6 100644 --- a/src/openApi/v2/parser/getValidationForArrayRef.ts +++ b/src/openApi/v2/parser/getValidationForArrayRef.ts @@ -1,15 +1,5 @@ import { Type } from '../../../client/interfaces/Type'; -export function getValidationForArrayRef(ref: Type, required: boolean = false, nullable: boolean = false): string { - let validation = `yup.array<${ref.type}>().of(${ref.base}.schema)`; - - if (required) { - validation = `${validation}.required()`; - } - - if (nullable) { - validation = `${validation}.nullable()`; - } - - return validation; +export function getValidationForArrayRef(ref: Type): string { + return `yup.array<${ref.type}>().of(${ref.base}.schema)`; } diff --git a/src/openApi/v2/parser/getValidationForArrayType.ts b/src/openApi/v2/parser/getValidationForArrayType.ts deleted file mode 100644 index 98b6b99d..00000000 --- a/src/openApi/v2/parser/getValidationForArrayType.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { PrimaryType } from './constants'; -import { Type } from '../../../client/interfaces/Type'; - -export function getValidationForArrayType(type: Type, required: boolean = false, nullable: boolean = false): string { - let validation = `yup.array().of(yup.mixed())`; - - switch (type.type) { - case PrimaryType.BOOLEAN: - validation = `yup.array().of(yup.boolean())`; - break; - case PrimaryType.NUMBER: - validation = `yup.array().of(yup.number())`; - break; - case PrimaryType.STRING: - validation = `yup.array().of(yup.string())`; - break; - } - - if (required) { - validation = `${validation}.required()`; - } - - if (nullable) { - validation = `${validation}.nullable()`; - } - - return validation; -} diff --git a/src/openApi/v2/parser/getValidationForEnum.ts b/src/openApi/v2/parser/getValidationForEnum.ts new file mode 100644 index 00000000..485f43ea --- /dev/null +++ b/src/openApi/v2/parser/getValidationForEnum.ts @@ -0,0 +1,16 @@ +import { Enum } from '../../../client/interfaces/Enum'; +import { EOL } from 'os'; + +export function getValidationForEnum(name: string, enumerators: Enum[]): string { + return [ + `yup.mixed${name ? `<${name}>` : ''}().oneOf([`, + ...enumerators.map(enumerator => { + if (name) { + return `${name}.${enumerator.name},`; + } else { + return `${enumerator.value},`; + } + }), + `])`, + ].join(EOL); +} diff --git a/src/openApi/v2/parser/getValidationForProperties.ts b/src/openApi/v2/parser/getValidationForProperties.ts new file mode 100644 index 00000000..fbd99630 --- /dev/null +++ b/src/openApi/v2/parser/getValidationForProperties.ts @@ -0,0 +1,18 @@ +import { EOL } from 'os'; +import { ModelProperty } from '../../../client/interfaces/ModelProperty'; + +export function getValidationForProperties(name: string, properties: ModelProperty[], extendClasses: string[]): string { + return [ + ...extendClasses.map(extendClass => `${extendClass}.schema.concat(`), + `yup.object${name ? `<${name}>` : ''}().shape({`, + ...properties.map(property => { + let validation = ''; + validation = `${validation}${property.name}: yup.lazy(() => ${property.validation}.default(undefined))`; + validation = `${validation}${property.required ? '.required()' : ''}`; + validation = `${validation}${property.nullable ? '.nullable()' : ''}`; + return `${validation},`; + }), + `}).noUnknown()`, + ...extendClasses.map(() => `)`), + ].join(EOL); +} diff --git a/src/openApi/v2/parser/getValidationForRef.ts b/src/openApi/v2/parser/getValidationForRef.ts index d09700c5..74083c7f 100644 --- a/src/openApi/v2/parser/getValidationForRef.ts +++ b/src/openApi/v2/parser/getValidationForRef.ts @@ -1,15 +1,5 @@ import { Type } from '../../../client/interfaces/Type'; -export function getValidationForRef(ref: Type, required = false, nullable = false): string { - let validation = `${ref.base}.schema`; - - if (required) { - validation = `${validation}.required()`; - } - - if (nullable) { - validation = `${validation}.nullable()`; - } - - return validation; +export function getValidationForRef(ref: Type): string { + return `${ref.base}.schema`; } diff --git a/src/openApi/v2/parser/getValidationForType.ts b/src/openApi/v2/parser/getValidationForType.ts index 00a6ed09..401121c0 100644 --- a/src/openApi/v2/parser/getValidationForType.ts +++ b/src/openApi/v2/parser/getValidationForType.ts @@ -1,9 +1,8 @@ import { PrimaryType } from './constants'; import { Type } from '../../../client/interfaces/Type'; -export function getValidationForType(type: Type, required: boolean = false, nullable: boolean = false): string { +export function getValidationForType(type: Type): string { let validation = `yup.mixed<${type.type}>()`; - switch (type.type) { case PrimaryType.BOOLEAN: validation = `yup.boolean()`; @@ -15,14 +14,5 @@ export function getValidationForType(type: Type, required: boolean = false, null validation = `yup.string()`; break; } - - if (required) { - validation = `${validation}.required()`; - } - - if (nullable) { - validation = `${validation}.nullable()`; - } - return validation; } diff --git a/src/utils/exportModel.ts b/src/utils/exportModel.ts index fda05ec7..42c16530 100644 --- a/src/utils/exportModel.ts +++ b/src/utils/exportModel.ts @@ -7,7 +7,7 @@ export function exportModel(model: Model): any { imports: getSortedImports(model.imports).filter(name => { return model.name !== name; }), - properties: Array.from(model.properties.values()) + properties: model.properties .filter((property, index, arr) => { return arr.findIndex(item => item.name === property.name) === index; }) diff --git a/src/utils/getSortedModels.spec.ts b/src/utils/getSortedModels.spec.ts index a2737897..87498a75 100644 --- a/src/utils/getSortedModels.spec.ts +++ b/src/utils/getSortedModels.spec.ts @@ -1,6 +1,5 @@ import { getSortedModels } from './getSortedModels'; import { Model } from '../client/interfaces/Model'; -import { ModelProperty } from '../client/interfaces/ModelProperty'; describe('getSortedModels', () => { it('should return sorted list', () => { @@ -11,10 +10,11 @@ describe('getSortedModels', () => { base: 'John', template: null, description: null, + validation: null, extends: [], imports: [], enum: [], - properties: new Map(), + properties: [], }); models.set('Jane', { name: 'Jane', @@ -22,10 +22,11 @@ describe('getSortedModels', () => { base: 'Jane', template: null, description: null, + validation: null, extends: [], imports: [], enum: [], - properties: new Map(), + properties: [], }); models.set('Doe', { name: 'Doe', @@ -33,10 +34,11 @@ describe('getSortedModels', () => { base: 'Doe', template: null, description: null, + validation: null, extends: [], imports: [], enum: [], - properties: new Map(), + properties: [], }); expect(getSortedModels(new Map())).toEqual([]); diff --git a/src/utils/writeClient.spec.ts b/src/utils/writeClient.spec.ts index adec8222..9f0a4cc5 100644 --- a/src/utils/writeClient.spec.ts +++ b/src/utils/writeClient.spec.ts @@ -6,6 +6,8 @@ import { Client } from '../client/interfaces/Client'; import { Templates } from './readHandlebarsTemplates'; import { Language } from '../index'; import * as glob from 'glob'; +import { Model } from '../client/interfaces/Model'; +import { Service } from '../client/interfaces/Service'; jest.mock('rimraf'); jest.mock('mkdirp'); @@ -22,8 +24,8 @@ describe('writeClient', () => { const client: Client = { server: 'http://localhost:8080', version: 'v1', - models: [], - services: [], + models: new Map(), + services: new Map(), }; const templates: Templates = { diff --git a/src/utils/writeClientIndex.spec.ts b/src/utils/writeClientIndex.spec.ts index e7e226a0..67ac40ab 100644 --- a/src/utils/writeClientIndex.spec.ts +++ b/src/utils/writeClientIndex.spec.ts @@ -2,6 +2,8 @@ import { writeClientIndex } from './writeClientIndex'; import * as fs from 'fs'; import { Client } from '../client/interfaces/Client'; import { Language } from '../index'; +import { Model } from '../client/interfaces/Model'; +import { Service } from '../client/interfaces/Service'; jest.mock('fs'); @@ -12,8 +14,8 @@ describe('writeClientIndex', () => { const client: Client = { server: 'http://localhost:8080', version: 'v1', - models: [], - services: [], + models: new Map(), + services: new Map(), }; const template = () => 'dummy'; writeClientIndex(client, Language.TYPESCRIPT, template, '/'); diff --git a/src/utils/writeClientModels.spec.ts b/src/utils/writeClientModels.spec.ts index c8e76fb5..87c94c24 100644 --- a/src/utils/writeClientModels.spec.ts +++ b/src/utils/writeClientModels.spec.ts @@ -9,24 +9,19 @@ const fsWriteFileSync = fs.writeFileSync as jest.MockedFunction { it('should write to filesystem', () => { - const models: Model[] = [ - { - isInterface: false, - isType: false, - isEnum: false, - name: 'Item', - type: 'Item', - base: 'Item', - template: null, - validation: null, - description: null, - extends: [], - imports: [], - symbols: [], - properties: [], - enums: [], - }, - ]; + const models = new Map(); + models.set('Item', { + name: 'Item', + type: 'Item', + base: 'Item', + template: null, + description: null, + validation: null, + extends: [], + imports: [], + enum: [], + properties: [], + }); const template = () => 'dummy'; writeClientModels(models, Language.TYPESCRIPT, template, '/'); expect(fsWriteFileSync).toBeCalledWith('/Item.ts', 'dummy'); diff --git a/src/utils/writeClientServices.spec.ts b/src/utils/writeClientServices.spec.ts index f697ef9f..9caa754b 100644 --- a/src/utils/writeClientServices.spec.ts +++ b/src/utils/writeClientServices.spec.ts @@ -9,13 +9,12 @@ const fsWriteFileSync = fs.writeFileSync as jest.MockedFunction { it('should write to filesystem', () => { - const services: Service[] = [ - { - name: 'Item', - operations: [], - imports: [], - }, - ]; + const services = new Map(); + services.set('Item', { + name: 'Item', + operations: [], + imports: [], + }); const template = () => 'dummy'; writeClientServices(services, Language.TYPESCRIPT, template, '/'); expect(fsWriteFileSync).toBeCalledWith('/Item.ts', 'dummy'); diff --git a/test/mock/v2/spec.json b/test/mock/v2/spec.json index c0ce2117..6799af7f 100644 --- a/test/mock/v2/spec.json +++ b/test/mock/v2/spec.json @@ -112,6 +112,21 @@ } } }, + "DictionaryWithProperties": { + "description": "This is a complex dictionary", + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "foo": { + "type": "string" + }, + "bar": { + "type": "string" + } + } + } + }, "ModelWithInteger": { "description": "This is a model with one number property", "type": "object",