From d3706a3985dc00510e864f1f504148131211d869 Mon Sep 17 00:00:00 2001 From: Ferdi Koomen Date: Thu, 15 Oct 2020 17:50:54 +0200 Subject: [PATCH] Allow x-nullable on root props, exposing pattern as regexp --- .../v2/interfaces/OpenApiParameter.d.ts | 3 +- src/openApi/v2/parser/extendEnum.ts | 7 +- src/openApi/v2/parser/getModel.ts | 2 +- .../v2/parser/getOperationParameter.ts | 2 +- src/openApi/v3/parser/extendEnum.ts | 7 +- src/openApi/v3/parser/getModel.ts | 14 ++ src/templates/partials/base.hbs | 2 +- src/templates/partials/schemaArray.hbs | 4 +- src/templates/partials/schemaDictionary.hbs | 4 +- src/templates/partials/schemaGeneric.hbs | 4 +- test/__snapshots__/index.spec.js.snap | 207 ++++++++++++++---- test/spec/v2.json | 6 + test/spec/v3.json | 7 + 13 files changed, 209 insertions(+), 60 deletions(-) diff --git a/src/openApi/v2/interfaces/OpenApiParameter.d.ts b/src/openApi/v2/interfaces/OpenApiParameter.d.ts index 3f4f3532..9906ad19 100644 --- a/src/openApi/v2/interfaces/OpenApiParameter.d.ts +++ b/src/openApi/v2/interfaces/OpenApiParameter.d.ts @@ -1,4 +1,5 @@ import type { WithEnumExtension } from './Extensions/WithEnumExtension'; +import { WithNullableExtension } from './Extensions/WithNullableExtension'; import type { OpenApiItems } from './OpenApiItems'; import type { OpenApiReference } from './OpenApiReference'; import type { OpenApiSchema } from './OpenApiSchema'; @@ -6,7 +7,7 @@ import type { OpenApiSchema } from './OpenApiSchema'; /** * https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#parameterObject */ -export interface OpenApiParameter extends OpenApiReference, WithEnumExtension { +export interface OpenApiParameter extends OpenApiReference, WithEnumExtension, WithNullableExtension { name: string; in: 'path' | 'query' | 'header' | 'formData' | 'body'; description?: string; diff --git a/src/openApi/v2/parser/extendEnum.ts b/src/openApi/v2/parser/extendEnum.ts index 4d62a025..efd89463 100644 --- a/src/openApi/v2/parser/extendEnum.ts +++ b/src/openApi/v2/parser/extendEnum.ts @@ -1,9 +1,6 @@ import type { Enum } from '../../../client/interfaces/Enum'; import type { WithEnumExtension } from '../interfaces/Extensions/WithEnumExtension'; -const KEY_ENUM_NAMES = 'x-enum-varnames'; -const KEY_ENUM_DESCRIPTIONS = 'x-enum-descriptions'; - /** * Extend the enum with the x-enum properties. This adds the capability * to use names and descriptions inside the generated enums. @@ -11,8 +8,8 @@ const KEY_ENUM_DESCRIPTIONS = 'x-enum-descriptions'; * @param definition */ export function extendEnum(enumerators: Enum[], definition: WithEnumExtension): Enum[] { - const names = definition[KEY_ENUM_NAMES]; - const descriptions = definition[KEY_ENUM_DESCRIPTIONS]; + const names = definition['x-enum-varnames']; + const descriptions = definition['x-enum-descriptions']; return enumerators.map((enumerator, index) => ({ name: (names && names[index]) || enumerator.name, diff --git a/src/openApi/v2/parser/getModel.ts b/src/openApi/v2/parser/getModel.ts index 779baae3..c95bbe0e 100644 --- a/src/openApi/v2/parser/getModel.ts +++ b/src/openApi/v2/parser/getModel.ts @@ -20,7 +20,7 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, isDefiniti description: getComment(definition.description), isDefinition: isDefinition, isReadOnly: definition.readOnly === true, - isNullable: false, + isNullable: definition['x-nullable'] === true, isRequired: false, format: definition.format, maximum: definition.maximum, diff --git a/src/openApi/v2/parser/getOperationParameter.ts b/src/openApi/v2/parser/getOperationParameter.ts index 4fba8197..c929b3b1 100644 --- a/src/openApi/v2/parser/getOperationParameter.ts +++ b/src/openApi/v2/parser/getOperationParameter.ts @@ -25,7 +25,7 @@ export function getOperationParameter(openApi: OpenApi, parameter: OpenApiParame isDefinition: false, isReadOnly: false, isRequired: parameter.required === true, - isNullable: false, + isNullable: parameter['x-nullable'] === true, format: parameter.format, maximum: parameter.maximum, exclusiveMaximum: parameter.exclusiveMaximum, diff --git a/src/openApi/v3/parser/extendEnum.ts b/src/openApi/v3/parser/extendEnum.ts index 4d62a025..efd89463 100644 --- a/src/openApi/v3/parser/extendEnum.ts +++ b/src/openApi/v3/parser/extendEnum.ts @@ -1,9 +1,6 @@ import type { Enum } from '../../../client/interfaces/Enum'; import type { WithEnumExtension } from '../interfaces/Extensions/WithEnumExtension'; -const KEY_ENUM_NAMES = 'x-enum-varnames'; -const KEY_ENUM_DESCRIPTIONS = 'x-enum-descriptions'; - /** * Extend the enum with the x-enum properties. This adds the capability * to use names and descriptions inside the generated enums. @@ -11,8 +8,8 @@ const KEY_ENUM_DESCRIPTIONS = 'x-enum-descriptions'; * @param definition */ export function extendEnum(enumerators: Enum[], definition: WithEnumExtension): Enum[] { - const names = definition[KEY_ENUM_NAMES]; - const descriptions = definition[KEY_ENUM_DESCRIPTIONS]; + const names = definition['x-enum-varnames']; + const descriptions = definition['x-enum-descriptions']; return enumerators.map((enumerator, index) => ({ name: (names && names[index]) || enumerator.name, diff --git a/src/openApi/v3/parser/getModel.ts b/src/openApi/v3/parser/getModel.ts index 655459d3..d7ef1678 100644 --- a/src/openApi/v3/parser/getModel.ts +++ b/src/openApi/v3/parser/getModel.ts @@ -23,6 +23,20 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, isDefiniti isReadOnly: definition.readOnly === true, isNullable: definition.nullable === true, isRequired: false, + format: definition.format, + maximum: definition.maximum, + exclusiveMaximum: definition.exclusiveMaximum, + minimum: definition.minimum, + exclusiveMinimum: definition.exclusiveMinimum, + multipleOf: definition.multipleOf, + maxLength: definition.maxLength, + minLength: definition.minLength, + pattern: definition.pattern, + maxItems: definition.maxItems, + minItems: definition.minItems, + uniqueItems: definition.uniqueItems, + maxProperties: definition.maxProperties, + minProperties: definition.minProperties, imports: [], extends: [], enum: [], diff --git a/src/templates/partials/base.hbs b/src/templates/partials/base.hbs index 148d6bb3..46772416 100644 --- a/src/templates/partials/base.hbs +++ b/src/templates/partials/base.hbs @@ -3,5 +3,5 @@ {{~#equals @root.httpClient 'xhr'}}Blob{{/equals~}} {{~#equals @root.httpClient 'node'}}Buffer | ArrayBuffer | ArrayBufferView{{/equals~}} {{~else~}} -{{base}} +{{{base}}} {{~/equals~}} diff --git a/src/templates/partials/schemaArray.hbs b/src/templates/partials/schemaArray.hbs index 8d537a7f..efc1f298 100644 --- a/src/templates/partials/schemaArray.hbs +++ b/src/templates/partials/schemaArray.hbs @@ -1,5 +1,7 @@ { - type: 'Array', + array: { + type: '{{>base}}', + }, {{#if isReadOnly}} isReadOnly: {{{isReadOnly}}}, {{/if}} diff --git a/src/templates/partials/schemaDictionary.hbs b/src/templates/partials/schemaDictionary.hbs index c965c92c..7334bd04 100644 --- a/src/templates/partials/schemaDictionary.hbs +++ b/src/templates/partials/schemaDictionary.hbs @@ -1,5 +1,7 @@ { - type: 'Dictionary', + dictionary: { + type: '{{>base}}', + }, {{#if isReadOnly}} isReadOnly: {{{isReadOnly}}}, {{/if}} diff --git a/src/templates/partials/schemaGeneric.hbs b/src/templates/partials/schemaGeneric.hbs index 7b0d96c9..a2306847 100644 --- a/src/templates/partials/schemaGeneric.hbs +++ b/src/templates/partials/schemaGeneric.hbs @@ -1,6 +1,6 @@ { {{#if type}} - type: '{{{base}}}', + type: '{{>base}}', {{/if}} {{#if isReadOnly}} isReadOnly: {{{isReadOnly}}}, @@ -36,7 +36,7 @@ minLength: {{{minLength}}}, {{/if}} {{#if pattern}} - pattern: '{{{pattern}}}', + pattern: /{{{pattern}}}/, {{/if}} {{#if maxItems}} maxItems: {{{maxItems}}}, diff --git a/test/__snapshots__/index.spec.js.snap b/test/__snapshots__/index.spec.js.snap index 6fcd3434..a859693a 100644 --- a/test/__snapshots__/index.spec.js.snap +++ b/test/__snapshots__/index.spec.js.snap @@ -312,6 +312,7 @@ export type { SimpleFile } from './models/SimpleFile'; export type { SimpleInteger } from './models/SimpleInteger'; export type { SimpleReference } from './models/SimpleReference'; export type { SimpleString } from './models/SimpleString'; +export type { SimpleStringWithPattern } from './models/SimpleStringWithPattern'; export { $ArrayWithArray } from './schemas/$ArrayWithArray'; export { $ArrayWithBooleans } from './schemas/$ArrayWithBooleans'; @@ -355,6 +356,7 @@ export { $SimpleFile } from './schemas/$SimpleFile'; export { $SimpleInteger } from './schemas/$SimpleInteger'; export { $SimpleReference } from './schemas/$SimpleReference'; export { $SimpleString } from './schemas/$SimpleString'; +export { $SimpleStringWithPattern } from './schemas/$SimpleStringWithPattern'; export { ComplexService } from './services/ComplexService'; export { DefaultsService } from './services/DefaultsService'; @@ -1003,12 +1005,24 @@ exports[`v2 should generate: ./test/generated/v2/models/SimpleString.ts 1`] = ` export type SimpleString = string;" `; +exports[`v2 should generate: ./test/generated/v2/models/SimpleStringWithPattern.ts 1`] = ` +"/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +/** + * This is a simple string + */ +export type SimpleStringWithPattern = string;" +`; + exports[`v2 should generate: ./test/generated/v2/schemas/$ArrayWithArray.ts 1`] = ` "/* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ export const $ArrayWithArray = { - type: 'Array', + array: { + type: 'ModelWithString', + }, };" `; @@ -1017,7 +1031,9 @@ exports[`v2 should generate: ./test/generated/v2/schemas/$ArrayWithBooleans.ts 1 /* tslint:disable */ /* eslint-disable */ export const $ArrayWithBooleans = { - type: 'Array', + array: { + type: 'boolean', + }, };" `; @@ -1026,7 +1042,9 @@ exports[`v2 should generate: ./test/generated/v2/schemas/$ArrayWithNumbers.ts 1` /* tslint:disable */ /* eslint-disable */ export const $ArrayWithNumbers = { - type: 'Array', + array: { + type: 'number', + }, };" `; @@ -1035,7 +1053,9 @@ exports[`v2 should generate: ./test/generated/v2/schemas/$ArrayWithProperties.ts /* tslint:disable */ /* eslint-disable */ export const $ArrayWithProperties = { - type: 'Array', + array: { + type: 'any', + }, };" `; @@ -1044,7 +1064,9 @@ exports[`v2 should generate: ./test/generated/v2/schemas/$ArrayWithReferences.ts /* tslint:disable */ /* eslint-disable */ export const $ArrayWithReferences = { - type: 'Array', + array: { + type: 'ModelWithString', + }, };" `; @@ -1053,7 +1075,9 @@ exports[`v2 should generate: ./test/generated/v2/schemas/$ArrayWithStrings.ts 1` /* tslint:disable */ /* eslint-disable */ export const $ArrayWithStrings = { - type: 'Array', + array: { + type: 'string', + }, };" `; @@ -1062,7 +1086,9 @@ exports[`v2 should generate: ./test/generated/v2/schemas/$DictionaryWithArray.ts /* tslint:disable */ /* eslint-disable */ export const $DictionaryWithArray = { - type: 'Dictionary', + dictionary: { + type: 'ModelWithString', + }, };" `; @@ -1071,7 +1097,9 @@ exports[`v2 should generate: ./test/generated/v2/schemas/$DictionaryWithDictiona /* tslint:disable */ /* eslint-disable */ export const $DictionaryWithDictionary = { - type: 'Dictionary', + dictionary: { + type: 'string', + }, };" `; @@ -1080,7 +1108,9 @@ exports[`v2 should generate: ./test/generated/v2/schemas/$DictionaryWithProperti /* tslint:disable */ /* eslint-disable */ export const $DictionaryWithProperties = { - type: 'Dictionary', + dictionary: { + type: 'any', + }, };" `; @@ -1089,7 +1119,9 @@ exports[`v2 should generate: ./test/generated/v2/schemas/$DictionaryWithReferenc /* tslint:disable */ /* eslint-disable */ export const $DictionaryWithReference = { - type: 'Dictionary', + dictionary: { + type: 'ModelWithString', + }, };" `; @@ -1098,7 +1130,9 @@ exports[`v2 should generate: ./test/generated/v2/schemas/$DictionaryWithString.t /* tslint:disable */ /* eslint-disable */ export const $DictionaryWithString = { - type: 'Dictionary', + dictionary: { + type: 'string', + }, };" `; @@ -1198,13 +1232,19 @@ exports[`v2 should generate: ./test/generated/v2/schemas/$ModelWithArray.ts 1`] export const $ModelWithArray = { properties: { prop: { - type: 'Array', + array: { + type: 'ModelWithString', + }, }, propWithFile: { - type: 'Array', + array: { + type: 'Blob', + }, }, propWithNumber: { - type: 'Array', + array: { + type: 'number', + }, }, }, };" @@ -1243,7 +1283,9 @@ exports[`v2 should generate: ./test/generated/v2/schemas/$ModelWithDictionary.ts export const $ModelWithDictionary = { properties: { prop: { - type: 'Dictionary', + dictionary: { + type: 'string', + }, }, }, };" @@ -1343,16 +1385,24 @@ exports[`v2 should generate: ./test/generated/v2/schemas/$ModelWithNestedEnums.t export const $ModelWithNestedEnums = { properties: { dictionaryWithEnum: { - type: 'Dictionary', + dictionary: { + type: 'string', + }, }, dictionaryWithEnumFromDescription: { - type: 'Dictionary', + dictionary: { + type: 'number', + }, }, arrayWithEnum: { - type: 'Array', + array: { + type: 'string', + }, }, arrayWithDescription: { - type: 'Array', + array: { + type: 'number', + }, }, }, };" @@ -1433,7 +1483,7 @@ export const $ModelWithPattern = { type: 'string', isRequired: true, maxLength: 64, - pattern: '^[a-zA-Z0-9_]*$', + pattern: /^[a-zA-Z0-9_]*$/, }, name: { type: 'string', @@ -1541,7 +1591,7 @@ exports[`v2 should generate: ./test/generated/v2/schemas/$SimpleFile.ts 1`] = ` /* tslint:disable */ /* eslint-disable */ export const $SimpleFile = { - type: 'File', + type: 'Blob', };" `; @@ -1572,6 +1622,17 @@ export const $SimpleString = { };" `; +exports[`v2 should generate: ./test/generated/v2/schemas/$SimpleStringWithPattern.ts 1`] = ` +"/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export const $SimpleStringWithPattern = { + type: 'string', + maxLength: 64, + pattern: /^[a-zA-Z0-9_]*$/, +};" +`; + exports[`v2 should generate: ./test/generated/v2/services/ComplexService.ts 1`] = ` "/* istanbul ignore file */ /* tslint:disable */ @@ -2411,6 +2472,7 @@ export type { SimpleFile } from './models/SimpleFile'; export type { SimpleInteger } from './models/SimpleInteger'; export type { SimpleReference } from './models/SimpleReference'; export type { SimpleString } from './models/SimpleString'; +export type { SimpleStringWithPattern } from './models/SimpleStringWithPattern'; export { $ArrayWithArray } from './schemas/$ArrayWithArray'; export { $ArrayWithBooleans } from './schemas/$ArrayWithBooleans'; @@ -2455,6 +2517,7 @@ export { $SimpleFile } from './schemas/$SimpleFile'; export { $SimpleInteger } from './schemas/$SimpleInteger'; export { $SimpleReference } from './schemas/$SimpleReference'; export { $SimpleString } from './schemas/$SimpleString'; +export { $SimpleStringWithPattern } from './schemas/$SimpleStringWithPattern'; export { ComplexService } from './services/ComplexService'; export { DefaultsService } from './services/DefaultsService'; @@ -3123,12 +3186,24 @@ exports[`v3 should generate: ./test/generated/v3/models/SimpleString.ts 1`] = ` export type SimpleString = string;" `; +exports[`v3 should generate: ./test/generated/v3/models/SimpleStringWithPattern.ts 1`] = ` +"/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +/** + * This is a simple string + */ +export type SimpleStringWithPattern = string | null;" +`; + exports[`v3 should generate: ./test/generated/v3/schemas/$ArrayWithArray.ts 1`] = ` "/* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ export const $ArrayWithArray = { - type: 'Array', + array: { + type: 'ModelWithString', + }, };" `; @@ -3137,7 +3212,9 @@ exports[`v3 should generate: ./test/generated/v3/schemas/$ArrayWithBooleans.ts 1 /* tslint:disable */ /* eslint-disable */ export const $ArrayWithBooleans = { - type: 'Array', + array: { + type: 'boolean', + }, };" `; @@ -3146,7 +3223,9 @@ exports[`v3 should generate: ./test/generated/v3/schemas/$ArrayWithNumbers.ts 1` /* tslint:disable */ /* eslint-disable */ export const $ArrayWithNumbers = { - type: 'Array', + array: { + type: 'number', + }, };" `; @@ -3155,7 +3234,9 @@ exports[`v3 should generate: ./test/generated/v3/schemas/$ArrayWithProperties.ts /* tslint:disable */ /* eslint-disable */ export const $ArrayWithProperties = { - type: 'Array', + array: { + type: 'any', + }, };" `; @@ -3164,7 +3245,9 @@ exports[`v3 should generate: ./test/generated/v3/schemas/$ArrayWithReferences.ts /* tslint:disable */ /* eslint-disable */ export const $ArrayWithReferences = { - type: 'Array', + array: { + type: 'ModelWithString', + }, };" `; @@ -3173,7 +3256,9 @@ exports[`v3 should generate: ./test/generated/v3/schemas/$ArrayWithStrings.ts 1` /* tslint:disable */ /* eslint-disable */ export const $ArrayWithStrings = { - type: 'Array', + array: { + type: 'string', + }, };" `; @@ -3182,7 +3267,9 @@ exports[`v3 should generate: ./test/generated/v3/schemas/$DictionaryWithArray.ts /* tslint:disable */ /* eslint-disable */ export const $DictionaryWithArray = { - type: 'Dictionary', + dictionary: { + type: 'ModelWithString', + }, };" `; @@ -3191,7 +3278,9 @@ exports[`v3 should generate: ./test/generated/v3/schemas/$DictionaryWithDictiona /* tslint:disable */ /* eslint-disable */ export const $DictionaryWithDictionary = { - type: 'Dictionary', + dictionary: { + type: 'string', + }, };" `; @@ -3200,7 +3289,9 @@ exports[`v3 should generate: ./test/generated/v3/schemas/$DictionaryWithProperti /* tslint:disable */ /* eslint-disable */ export const $DictionaryWithProperties = { - type: 'Dictionary', + dictionary: { + type: 'any', + }, };" `; @@ -3209,7 +3300,9 @@ exports[`v3 should generate: ./test/generated/v3/schemas/$DictionaryWithReferenc /* tslint:disable */ /* eslint-disable */ export const $DictionaryWithReference = { - type: 'Dictionary', + dictionary: { + type: 'ModelWithString', + }, };" `; @@ -3218,7 +3311,9 @@ exports[`v3 should generate: ./test/generated/v3/schemas/$DictionaryWithString.t /* tslint:disable */ /* eslint-disable */ export const $DictionaryWithString = { - type: 'Dictionary', + dictionary: { + type: 'string', + }, };" `; @@ -3331,13 +3426,19 @@ exports[`v3 should generate: ./test/generated/v3/schemas/$ModelWithArray.ts 1`] export const $ModelWithArray = { properties: { prop: { - type: 'Array', + array: { + type: 'ModelWithString', + }, }, propWithFile: { - type: 'Array', + array: { + type: 'Blob', + }, }, propWithNumber: { - type: 'Array', + array: { + type: 'number', + }, }, }, };" @@ -3376,7 +3477,9 @@ exports[`v3 should generate: ./test/generated/v3/schemas/$ModelWithDictionary.ts export const $ModelWithDictionary = { properties: { prop: { - type: 'Dictionary', + dictionary: { + type: 'string', + }, }, }, };" @@ -3476,16 +3579,24 @@ exports[`v3 should generate: ./test/generated/v3/schemas/$ModelWithNestedEnums.t export const $ModelWithNestedEnums = { properties: { dictionaryWithEnum: { - type: 'Dictionary', + dictionary: { + type: 'string', + }, }, dictionaryWithEnumFromDescription: { - type: 'Dictionary', + dictionary: { + type: 'number', + }, }, arrayWithEnum: { - type: 'Array', + array: { + type: 'string', + }, }, arrayWithDescription: { - type: 'Array', + array: { + type: 'number', + }, }, }, };" @@ -3563,7 +3674,7 @@ export const $ModelWithPattern = { type: 'string', isRequired: true, maxLength: 64, - pattern: '^[a-zA-Z0-9_]*$', + pattern: /^[a-zA-Z0-9_]*$/, }, name: { type: 'string', @@ -3676,7 +3787,7 @@ exports[`v3 should generate: ./test/generated/v3/schemas/$SimpleFile.ts 1`] = ` /* tslint:disable */ /* eslint-disable */ export const $SimpleFile = { - type: 'File', + type: 'Blob', };" `; @@ -3707,6 +3818,18 @@ export const $SimpleString = { };" `; +exports[`v3 should generate: ./test/generated/v3/schemas/$SimpleStringWithPattern.ts 1`] = ` +"/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export const $SimpleStringWithPattern = { + type: 'string', + isNullable: true, + maxLength: 64, + pattern: /^[a-zA-Z0-9_]*$/, +};" +`; + exports[`v3 should generate: ./test/generated/v3/services/ComplexService.ts 1`] = ` "/* istanbul ignore file */ /* tslint:disable */ diff --git a/test/spec/v2.json b/test/spec/v2.json index da86c684..6159a8a8 100644 --- a/test/spec/v2.json +++ b/test/spec/v2.json @@ -711,6 +711,12 @@ "description": "This is a simple reference", "$ref": "#/definitions/ModelWithString" }, + "SimpleStringWithPattern": { + "description": "This is a simple string", + "type": "string", + "maxLength": 64, + "pattern": "^[a-zA-Z0-9_]*$" + }, "EnumWithStrings": { "description": "This is a simple enum with strings", "enum": [ diff --git a/test/spec/v3.json b/test/spec/v3.json index 6ae5f82c..f0843826 100644 --- a/test/spec/v3.json +++ b/test/spec/v3.json @@ -1191,6 +1191,13 @@ "description": "This is a simple reference", "$ref": "#/components/schemas/ModelWithString" }, + "SimpleStringWithPattern": { + "description": "This is a simple string", + "type": "string", + "nullable": true, + "maxLength": 64, + "pattern": "^[a-zA-Z0-9_]*$" + }, "EnumWithStrings": { "description": "This is a simple enum with strings", "enum": [