diff --git a/src/client/interfaces/Model.d.ts b/src/client/interfaces/Model.d.ts index c288e9e5..34846d8e 100644 --- a/src/client/interfaces/Model.d.ts +++ b/src/client/interfaces/Model.d.ts @@ -3,7 +3,7 @@ import type { Schema } from './Schema'; export interface Model extends Schema { name: string; - export: 'reference' | 'generic' | 'enum' | 'array' | 'dictionary' | 'interface'; + export: 'reference' | 'generic' | 'enum' | 'array' | 'dictionary' | 'interface' | 'one-of' | 'any-of' | 'all-of'; type: string; base: string; template: string | null; diff --git a/src/openApi/v3/parser/getModel.ts b/src/openApi/v3/parser/getModel.ts index f9a39e05..5c3a22aa 100644 --- a/src/openApi/v3/parser/getModel.ts +++ b/src/openApi/v3/parser/getModel.ts @@ -103,7 +103,7 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, isDefiniti } } - if (definition.type === 'object' && typeof definition.additionalProperties === 'object') { + if (definition.type === 'object' && definition.additionalProperties && typeof definition.additionalProperties === 'object') { if (definition.additionalProperties.$ref) { const additionalProperties = getType(definition.additionalProperties.$ref); model.export = 'dictionary'; @@ -125,70 +125,42 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, isDefiniti return model; } } + // TODO: + // Add correct support for oneOf + // https://swagger.io/docs/specification/data-models/oneof-anyof-allof-not/ - if (definition.anyOf?.length && !definition.properties) { - const compositionTypes = definition.anyOf.filter(type => type.$ref).map(type => getType(type.$ref)); - const composition = compositionTypes - .map(type => type.type) - .sort() - .join(' | '); - model.export = 'generic'; - model.imports.push(...compositionTypes.map(type => type.base)); - model.type = composition; - model.base = composition; + if (definition.oneOf?.length || definition.anyOf?.length || definition.allOf?.length) { + let types: OpenApiSchema[] = []; + if (definition.oneOf?.length) { + model.export = 'one-of'; + types = definition.oneOf; + } else if (definition.anyOf?.length) { + model.export = 'any-of'; + types = definition.anyOf; + } else if (definition.allOf?.length) { + model.export = 'all-of'; + types = definition.allOf; + } + const compositionTypes = types.map(model => getModel(openApi, model)); + model.properties = compositionTypes; + model.imports.push(...compositionTypes.reduce((acc: string[], type) => acc.concat(type.imports), [])); + model.enums.push(...compositionTypes.reduce((acc: Model[], type) => acc.concat(type.enums), [])); return model; } - if (definition.oneOf?.length && !definition.properties) { - const compositionTypes = definition.oneOf.filter(type => type.$ref).map(type => getType(type.$ref)); - const composition = compositionTypes - .map(type => type.type) - .sort() - .join(' | '); - model.export = 'generic'; - model.imports.push(...compositionTypes.map(type => type.base)); - model.type = composition; - model.base = composition; - return model; - } - - if (definition.type === 'object' || definition.allOf) { + if (definition.type === 'object') { model.export = 'interface'; model.type = 'any'; model.base = 'any'; model.default = getModelDefault(definition, model); - - if (definition.allOf?.length) { - definition.allOf.forEach(parent => { - if (parent.$ref) { - const parentRef = getType(parent.$ref); - model.extends.push(parentRef.base); - model.imports.push(parentRef.base); - } - if (parent.type === 'object' && parent.properties) { - const properties = getModelProperties(openApi, parent, getModel); - properties.forEach(property => { - model.properties.push(property); - model.imports.push(...property.imports); - if (property.export === 'enum') { - model.enums.push(property); - } - }); - } - }); - } - - if (definition.properties) { - const properties = getModelProperties(openApi, definition, getModel); - properties.forEach(property => { - model.properties.push(property); - model.imports.push(...property.imports); - if (property.export === 'enum') { - model.enums.push(property); - } - }); - } - + const properties = getModelProperties(openApi, definition, getModel); + properties.forEach(property => { + model.properties.push(property); + model.imports.push(...property.imports); + if (property.export === 'enum') { + model.enums.push(property); + } + }); return model; } diff --git a/src/templates/partials/schema.hbs b/src/templates/partials/schema.hbs index 68194de6..14b9156b 100644 --- a/src/templates/partials/schema.hbs +++ b/src/templates/partials/schema.hbs @@ -6,6 +6,12 @@ {{>schemaArray}} {{else equals export 'dictionary'}} {{>schemaDictionary}} +{{else equals export 'any-of'}} +{{>schemaComposition}} +{{else equals export 'all-of'}} +{{>schemaComposition}} +{{else equals export 'one-of'}} +{{>schemaComposition}} {{else}} {{>schemaGeneric}} {{/equals}} diff --git a/src/templates/partials/schemaComposition.hbs b/src/templates/partials/schemaComposition.hbs new file mode 100644 index 00000000..32c5a647 --- /dev/null +++ b/src/templates/partials/schemaComposition.hbs @@ -0,0 +1,13 @@ +{ + type: '{{export}}', + contains: [{{#each properties}}{{>schema}}{{#unless @last}}, {{/unless}}{{/each}}], +{{#if isReadOnly}} + isReadOnly: {{{isReadOnly}}}, +{{/if}} +{{#if isRequired}} + isRequired: {{{isRequired}}}, +{{/if}} +{{#if isNullable}} + isNullable: {{{isNullable}}}, +{{/if}} +} diff --git a/src/templates/partials/type.hbs b/src/templates/partials/type.hbs index fb17c467..b6b4834b 100644 --- a/src/templates/partials/type.hbs +++ b/src/templates/partials/type.hbs @@ -8,6 +8,12 @@ {{>typeArray}} {{else equals export 'dictionary'}} {{>typeDictionary}} +{{else equals export 'one-of'}} +{{>typeUnion}} +{{else equals export 'any-of'}} +{{>typeUnion}} +{{else equals export 'all-of'}} +{{>typeIntersection}} {{else}} {{>typeGeneric}} {{/equals}} diff --git a/src/templates/partials/typeIntersection.hbs b/src/templates/partials/typeIntersection.hbs new file mode 100644 index 00000000..d966489f --- /dev/null +++ b/src/templates/partials/typeIntersection.hbs @@ -0,0 +1 @@ +({{#each properties}}{{>type}}{{#unless @last}} & {{/unless}}{{/each}}){{>isNullable}} diff --git a/src/templates/partials/typeUnion.hbs b/src/templates/partials/typeUnion.hbs new file mode 100644 index 00000000..b2561f52 --- /dev/null +++ b/src/templates/partials/typeUnion.hbs @@ -0,0 +1 @@ +({{#each properties}}{{>type}}{{#unless @last}} | {{/unless}}{{/each}}){{>isNullable}} diff --git a/src/utils/registerHandlebarTemplates.ts b/src/utils/registerHandlebarTemplates.ts index 7bd3a0e0..a4f46849 100644 --- a/src/utils/registerHandlebarTemplates.ts +++ b/src/utils/registerHandlebarTemplates.ts @@ -51,6 +51,7 @@ import partialParameters from '../templates/partials/parameters.hbs'; import partialResult from '../templates/partials/result.hbs'; import partialSchema from '../templates/partials/schema.hbs'; import partialSchemaArray from '../templates/partials/schemaArray.hbs'; +import partialSchemaComposition from '../templates/partials/schemaComposition.hbs'; import partialSchemaDictionary from '../templates/partials/schemaDictionary.hbs'; import partialSchemaEnum from '../templates/partials/schemaEnum.hbs'; import partialSchemaGeneric from '../templates/partials/schemaGeneric.hbs'; @@ -61,7 +62,9 @@ import partialTypeDictionary from '../templates/partials/typeDictionary.hbs'; import partialTypeEnum from '../templates/partials/typeEnum.hbs'; import partialTypeGeneric from '../templates/partials/typeGeneric.hbs'; import partialTypeInterface from '../templates/partials/typeInterface.hbs'; +import partialTypeIntersection from '../templates/partials/typeIntersection.hbs'; import partialTypeReference from '../templates/partials/typeReference.hbs'; +import partialTypeUnion from '../templates/partials/typeUnion.hbs'; import { registerHandlebarHelpers } from './registerHandlebarHelpers'; export interface Templates { @@ -121,6 +124,7 @@ export function registerHandlebarTemplates(): Templates { Handlebars.registerPartial('schemaEnum', Handlebars.template(partialSchemaEnum)); Handlebars.registerPartial('schemaGeneric', Handlebars.template(partialSchemaGeneric)); Handlebars.registerPartial('schemaInterface', Handlebars.template(partialSchemaInterface)); + Handlebars.registerPartial('schemaComposition', Handlebars.template(partialSchemaComposition)); Handlebars.registerPartial('type', Handlebars.template(partialType)); Handlebars.registerPartial('typeArray', Handlebars.template(partialTypeArray)); Handlebars.registerPartial('typeDictionary', Handlebars.template(partialTypeDictionary)); @@ -128,6 +132,8 @@ export function registerHandlebarTemplates(): Templates { Handlebars.registerPartial('typeGeneric', Handlebars.template(partialTypeGeneric)); Handlebars.registerPartial('typeInterface', Handlebars.template(partialTypeInterface)); Handlebars.registerPartial('typeReference', Handlebars.template(partialTypeReference)); + Handlebars.registerPartial('typeUnion', Handlebars.template(partialTypeUnion)); + Handlebars.registerPartial('typeIntersection', Handlebars.template(partialTypeIntersection)); Handlebars.registerPartial('base', Handlebars.template(partialBase)); // Generic functions used in 'request' file @see src/templates/core/request.hbs for more info diff --git a/test/__snapshots__/index.spec.js.snap b/test/__snapshots__/index.spec.js.snap index 8e8eb9e2..90507fb4 100644 --- a/test/__snapshots__/index.spec.js.snap +++ b/test/__snapshots__/index.spec.js.snap @@ -2644,7 +2644,13 @@ export type { ArrayWithNumbers } from './models/ArrayWithNumbers'; export type { ArrayWithProperties } from './models/ArrayWithProperties'; export type { ArrayWithReferences } from './models/ArrayWithReferences'; export type { ArrayWithStrings } from './models/ArrayWithStrings'; -export type { Date } from './models/Date'; +export type { CompositionWithAllOfAndNullable } from './models/CompositionWithAllOfAndNullable'; +export type { CompositionWithAnyOf } from './models/CompositionWithAnyOf'; +export type { CompositionWithAnyOfAndNullable } from './models/CompositionWithAnyOfAndNullable'; +export type { CompositionWithAnyOfAnonymous } from './models/CompositionWithAnyOfAnonymous'; +export type { CompositionWithOneOf } from './models/CompositionWithOneOf'; +export type { CompositionWithOneOfAndNullable } from './models/CompositionWithOneOfAndNullable'; +export type { CompositionWithOneOfAnonymous } from './models/CompositionWithOneOfAnonymous'; export type { DictionaryWithArray } from './models/DictionaryWithArray'; export type { DictionaryWithDictionary } from './models/DictionaryWithDictionary'; export type { DictionaryWithProperties } from './models/DictionaryWithProperties'; @@ -2657,7 +2663,6 @@ export { EnumWithStrings } from './models/EnumWithStrings'; export type { ModelLink } from './models/ModelLink'; export type { ModelThatExtends } from './models/ModelThatExtends'; export type { ModelThatExtendsExtends } from './models/ModelThatExtendsExtends'; -export type { ModelWithAnyOf } from './models/ModelWithAnyOf'; export type { ModelWithArray } from './models/ModelWithArray'; export type { ModelWithBoolean } from './models/ModelWithBoolean'; export type { ModelWithCircularReference } from './models/ModelWithCircularReference'; @@ -2670,7 +2675,6 @@ export type { ModelWithInteger } from './models/ModelWithInteger'; export type { ModelWithLink } from './models/ModelWithLink'; export type { ModelWithNestedEnums } from './models/ModelWithNestedEnums'; export type { ModelWithNestedProperties } from './models/ModelWithNestedProperties'; -export type { ModelWithOneOf } from './models/ModelWithOneOf'; export type { ModelWithOrderedProperties } from './models/ModelWithOrderedProperties'; export type { ModelWithPattern } from './models/ModelWithPattern'; export type { ModelWithProperties } from './models/ModelWithProperties'; @@ -2690,7 +2694,13 @@ export { $ArrayWithNumbers } from './schemas/$ArrayWithNumbers'; export { $ArrayWithProperties } from './schemas/$ArrayWithProperties'; export { $ArrayWithReferences } from './schemas/$ArrayWithReferences'; export { $ArrayWithStrings } from './schemas/$ArrayWithStrings'; -export { $Date } from './schemas/$Date'; +export { $CompositionWithAllOfAndNullable } from './schemas/$CompositionWithAllOfAndNullable'; +export { $CompositionWithAnyOf } from './schemas/$CompositionWithAnyOf'; +export { $CompositionWithAnyOfAndNullable } from './schemas/$CompositionWithAnyOfAndNullable'; +export { $CompositionWithAnyOfAnonymous } from './schemas/$CompositionWithAnyOfAnonymous'; +export { $CompositionWithOneOf } from './schemas/$CompositionWithOneOf'; +export { $CompositionWithOneOfAndNullable } from './schemas/$CompositionWithOneOfAndNullable'; +export { $CompositionWithOneOfAnonymous } from './schemas/$CompositionWithOneOfAnonymous'; export { $DictionaryWithArray } from './schemas/$DictionaryWithArray'; export { $DictionaryWithDictionary } from './schemas/$DictionaryWithDictionary'; export { $DictionaryWithProperties } from './schemas/$DictionaryWithProperties'; @@ -2703,7 +2713,6 @@ export { $EnumWithStrings } from './schemas/$EnumWithStrings'; export { $ModelLink } from './schemas/$ModelLink'; export { $ModelThatExtends } from './schemas/$ModelThatExtends'; export { $ModelThatExtendsExtends } from './schemas/$ModelThatExtendsExtends'; -export { $ModelWithAnyOf } from './schemas/$ModelWithAnyOf'; export { $ModelWithArray } from './schemas/$ModelWithArray'; export { $ModelWithBoolean } from './schemas/$ModelWithBoolean'; export { $ModelWithCircularReference } from './schemas/$ModelWithCircularReference'; @@ -2716,7 +2725,6 @@ export { $ModelWithInteger } from './schemas/$ModelWithInteger'; export { $ModelWithLink } from './schemas/$ModelWithLink'; export { $ModelWithNestedEnums } from './schemas/$ModelWithNestedEnums'; export { $ModelWithNestedProperties } from './schemas/$ModelWithNestedProperties'; -export { $ModelWithOneOf } from './schemas/$ModelWithOneOf'; export { $ModelWithOrderedProperties } from './schemas/$ModelWithOrderedProperties'; export { $ModelWithPattern } from './schemas/$ModelWithPattern'; export { $ModelWithProperties } from './schemas/$ModelWithProperties'; @@ -2817,15 +2825,134 @@ exports[`v3 should generate: ./test/generated/v3/models/ArrayWithStrings.ts 1`] export type ArrayWithStrings = Array;" `; -exports[`v3 should generate: ./test/generated/v3/models/Date.ts 1`] = ` +exports[`v3 should generate: ./test/generated/v3/models/CompositionWithAllOfAndNullable.ts 1`] = ` +"/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +import type { ModelWithArray } from './ModelWithArray'; +import type { ModelWithDictionary } from './ModelWithDictionary'; +import type { ModelWithEnum } from './ModelWithEnum'; + +/** + * This is a model with one property with a 'all of' relationship + */ +export interface CompositionWithAllOfAndNullable { + propA?: ({ + boolean?: boolean, + } & ModelWithEnum & ModelWithArray & ModelWithDictionary) | null; +} +" +`; + +exports[`v3 should generate: ./test/generated/v3/models/CompositionWithAnyOf.ts 1`] = ` +"/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +import type { ModelWithArray } from './ModelWithArray'; +import type { ModelWithDictionary } from './ModelWithDictionary'; +import type { ModelWithEnum } from './ModelWithEnum'; +import type { ModelWithString } from './ModelWithString'; + +/** + * This is a model with one property with a 'any of' relationship + */ +export interface CompositionWithAnyOf { + propA?: (ModelWithString | ModelWithEnum | ModelWithArray | ModelWithDictionary); +} +" +`; + +exports[`v3 should generate: ./test/generated/v3/models/CompositionWithAnyOfAndNullable.ts 1`] = ` +"/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +import type { ModelWithArray } from './ModelWithArray'; +import type { ModelWithDictionary } from './ModelWithDictionary'; +import type { ModelWithEnum } from './ModelWithEnum'; + +/** + * This is a model with one property with a 'any of' relationship + */ +export interface CompositionWithAnyOfAndNullable { + propA?: ({ + boolean?: boolean, + } | ModelWithEnum | ModelWithArray | ModelWithDictionary) | null; +} +" +`; + +exports[`v3 should generate: ./test/generated/v3/models/CompositionWithAnyOfAnonymous.ts 1`] = ` "/* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ /** - * This is a type-only model that defines Date as a string + * This is a model with one property with a 'any of' relationship where the options are not $ref */ -export type Date = string;" +export interface CompositionWithAnyOfAnonymous { + propA?: ({ + propA?: any, + } | string | number); +} +" +`; + +exports[`v3 should generate: ./test/generated/v3/models/CompositionWithOneOf.ts 1`] = ` +"/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +import type { ModelWithArray } from './ModelWithArray'; +import type { ModelWithDictionary } from './ModelWithDictionary'; +import type { ModelWithEnum } from './ModelWithEnum'; +import type { ModelWithString } from './ModelWithString'; + +/** + * This is a model with one property with a 'one of' relationship + */ +export interface CompositionWithOneOf { + propA?: (ModelWithString | ModelWithEnum | ModelWithArray | ModelWithDictionary); +} +" +`; + +exports[`v3 should generate: ./test/generated/v3/models/CompositionWithOneOfAndNullable.ts 1`] = ` +"/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +import type { ModelWithArray } from './ModelWithArray'; +import type { ModelWithDictionary } from './ModelWithDictionary'; +import type { ModelWithEnum } from './ModelWithEnum'; + +/** + * This is a model with one property with a 'one of' relationship + */ +export interface CompositionWithOneOfAndNullable { + propA?: ({ + boolean?: boolean, + } | ModelWithEnum | ModelWithArray | ModelWithDictionary) | null; +} +" +`; + +exports[`v3 should generate: ./test/generated/v3/models/CompositionWithOneOfAnonymous.ts 1`] = ` +"/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +/** + * This is a model with one property with a 'one of' relationship where the options are not $ref + */ +export interface CompositionWithOneOfAnonymous { + propA?: ({ + propA?: any, + } | string | number); +} +" `; exports[`v3 should generate: ./test/generated/v3/models/DictionaryWithArray.ts 1`] = ` @@ -2983,11 +3110,10 @@ import type { ModelWithString } from './ModelWithString'; /** * This is a model that extends another model */ -export interface ModelThatExtends extends ModelWithString { - propExtendsA?: string; - propExtendsB?: ModelWithString; -} -" +export type ModelThatExtends = (ModelWithString & { + propExtendsA?: string, + propExtendsB?: ModelWithString, +});" `; exports[`v3 should generate: ./test/generated/v3/models/ModelThatExtendsExtends.ts 1`] = ` @@ -3001,30 +3127,10 @@ import type { ModelWithString } from './ModelWithString'; /** * This is a model that extends another model */ -export interface ModelThatExtendsExtends extends ModelWithString, ModelThatExtends { - propExtendsC?: string; - propExtendsD?: ModelWithString; -} -" -`; - -exports[`v3 should generate: ./test/generated/v3/models/ModelWithAnyOf.ts 1`] = ` -"/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ - -import type { ModelWithArray } from './ModelWithArray'; -import type { ModelWithDictionary } from './ModelWithDictionary'; -import type { ModelWithEnum } from './ModelWithEnum'; -import type { ModelWithString } from './ModelWithString'; - -/** - * This is a model with one property with a 'any of' relationship - */ -export interface ModelWithAnyOf { - propA?: ModelWithArray | ModelWithDictionary | ModelWithEnum | ModelWithString; -} -" +export type ModelThatExtendsExtends = (ModelWithString & ModelThatExtends & { + propExtendsC?: string, + propExtendsD?: ModelWithString, +});" `; exports[`v3 should generate: ./test/generated/v3/models/ModelWithArray.ts 1`] = ` @@ -3271,25 +3377,6 @@ export interface ModelWithNestedProperties { " `; -exports[`v3 should generate: ./test/generated/v3/models/ModelWithOneOf.ts 1`] = ` -"/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ - -import type { ModelWithArray } from './ModelWithArray'; -import type { ModelWithDictionary } from './ModelWithDictionary'; -import type { ModelWithEnum } from './ModelWithEnum'; -import type { ModelWithString } from './ModelWithString'; - -/** - * This is a model with one property with a 'one of' relationship - */ -export interface ModelWithOneOf { - propA?: ModelWithArray | ModelWithDictionary | ModelWithEnum | ModelWithString; -} -" -`; - exports[`v3 should generate: ./test/generated/v3/models/ModelWithOrderedProperties.ts 1`] = ` "/* istanbul ignore file */ /* tslint:disable */ @@ -3552,13 +3639,185 @@ export const $ArrayWithStrings = { };" `; -exports[`v3 should generate: ./test/generated/v3/schemas/$Date.ts 1`] = ` +exports[`v3 should generate: ./test/generated/v3/schemas/$CompositionWithAllOfAndNullable.ts 1`] = ` "/* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ -export const $Date = { - type: 'string', +export const $CompositionWithAllOfAndNullable = { + properties: { + propA: { + type: 'all-of', + contains: [{ + properties: { + boolean: { + type: 'boolean', + }, + }, + }, { + type: 'ModelWithEnum', + }, { + type: 'ModelWithArray', + }, { + type: 'ModelWithDictionary', + }], + isNullable: true, + }, + }, +};" +`; + +exports[`v3 should generate: ./test/generated/v3/schemas/$CompositionWithAnyOf.ts 1`] = ` +"/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +export const $CompositionWithAnyOf = { + properties: { + propA: { + type: 'any-of', + contains: [{ + type: 'ModelWithString', + }, { + type: 'ModelWithEnum', + }, { + type: 'ModelWithArray', + }, { + type: 'ModelWithDictionary', + }], + }, + }, +};" +`; + +exports[`v3 should generate: ./test/generated/v3/schemas/$CompositionWithAnyOfAndNullable.ts 1`] = ` +"/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +export const $CompositionWithAnyOfAndNullable = { + properties: { + propA: { + type: 'any-of', + contains: [{ + properties: { + boolean: { + type: 'boolean', + }, + }, + }, { + type: 'ModelWithEnum', + }, { + type: 'ModelWithArray', + }, { + type: 'ModelWithDictionary', + }], + isNullable: true, + }, + }, +};" +`; + +exports[`v3 should generate: ./test/generated/v3/schemas/$CompositionWithAnyOfAnonymous.ts 1`] = ` +"/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +export const $CompositionWithAnyOfAnonymous = { + properties: { + propA: { + type: 'any-of', + contains: [{ + properties: { + propA: { + properties: { + }, + }, + }, + }, { + type: 'string', + }, { + type: 'number', + }], + }, + }, +};" +`; + +exports[`v3 should generate: ./test/generated/v3/schemas/$CompositionWithOneOf.ts 1`] = ` +"/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +export const $CompositionWithOneOf = { + properties: { + propA: { + type: 'one-of', + contains: [{ + type: 'ModelWithString', + }, { + type: 'ModelWithEnum', + }, { + type: 'ModelWithArray', + }, { + type: 'ModelWithDictionary', + }], + }, + }, +};" +`; + +exports[`v3 should generate: ./test/generated/v3/schemas/$CompositionWithOneOfAndNullable.ts 1`] = ` +"/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +export const $CompositionWithOneOfAndNullable = { + properties: { + propA: { + type: 'one-of', + contains: [{ + properties: { + boolean: { + type: 'boolean', + }, + }, + }, { + type: 'ModelWithEnum', + }, { + type: 'ModelWithArray', + }, { + type: 'ModelWithDictionary', + }], + isNullable: true, + }, + }, +};" +`; + +exports[`v3 should generate: ./test/generated/v3/schemas/$CompositionWithOneOfAnonymous.ts 1`] = ` +"/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +export const $CompositionWithOneOfAnonymous = { + properties: { + propA: { + type: 'one-of', + contains: [{ + properties: { + propA: { + properties: { + }, + }, + }, + }, { + type: 'string', + }, { + type: 'number', + }], + }, + }, };" `; @@ -3699,18 +3958,20 @@ exports[`v3 should generate: ./test/generated/v3/schemas/$ModelThatExtends.ts 1` /* tslint:disable */ /* eslint-disable */ -import { $ModelWithString } from './$ModelWithString'; - export const $ModelThatExtends = { - properties: { - ...$ModelWithString.properties, - propExtendsA: { - type: 'string', + type: 'all-of', + contains: [{ + type: 'ModelWithString', + }, { + properties: { + propExtendsA: { + type: 'string', + }, + propExtendsB: { + type: 'ModelWithString', + }, }, - propExtendsB: { - type: 'ModelWithString', - }, - }, + }], };" `; @@ -3719,34 +3980,22 @@ exports[`v3 should generate: ./test/generated/v3/schemas/$ModelThatExtendsExtend /* tslint:disable */ /* eslint-disable */ -import { $ModelWithString } from './$ModelWithString'; -import { $ModelThatExtends } from './$ModelThatExtends'; - export const $ModelThatExtendsExtends = { - properties: { - ...$ModelWithString.properties, - ...$ModelThatExtends.properties, - propExtendsC: { - type: 'string', + type: 'all-of', + contains: [{ + type: 'ModelWithString', + }, { + type: 'ModelThatExtends', + }, { + properties: { + propExtendsC: { + type: 'string', + }, + propExtendsD: { + type: 'ModelWithString', + }, }, - propExtendsD: { - type: 'ModelWithString', - }, - }, -};" -`; - -exports[`v3 should generate: ./test/generated/v3/schemas/$ModelWithAnyOf.ts 1`] = ` -"/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ - -export const $ModelWithAnyOf = { - properties: { - propA: { - type: 'ModelWithArray | ModelWithDictionary | ModelWithEnum | ModelWithString', - }, - }, + }], };" `; @@ -3983,20 +4232,6 @@ export const $ModelWithNestedProperties = { };" `; -exports[`v3 should generate: ./test/generated/v3/schemas/$ModelWithOneOf.ts 1`] = ` -"/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ - -export const $ModelWithOneOf = { - properties: { - propA: { - type: 'ModelWithArray | ModelWithDictionary | ModelWithEnum | ModelWithString', - }, - }, -};" -`; - exports[`v3 should generate: ./test/generated/v3/schemas/$ModelWithOrderedProperties.ts 1`] = ` "/* istanbul ignore file */ /* tslint:disable */ @@ -4261,7 +4496,7 @@ export class ComplexService { readonly type: 'Monkey' | 'Horse' | 'Bird', listOfModels?: Array | null, listOfStrings?: Array | null, - parameters: ModelWithArray | ModelWithDictionary | ModelWithEnum | ModelWithString, + parameters: (ModelWithString | ModelWithEnum | ModelWithArray | ModelWithDictionary), readonly user?: { readonly id?: number, readonly name?: string | null, diff --git a/test/spec/v3.json b/test/spec/v3.json index 8e752d0c..726df9c1 100644 --- a/test/spec/v3.json +++ b/test/spec/v3.json @@ -869,7 +869,7 @@ "in": "formData", "required": true, "schema": { - "type": "file" + "type": "File" } }, { @@ -1185,7 +1185,7 @@ }, "SimpleFile": { "description": "This is a simple file", - "type": "file" + "type": "File" }, "SimpleReference": { "description": "This is a simple reference", @@ -1338,10 +1338,6 @@ } } }, - "Date": { - "description": "This is a type-only model that defines Date as a string", - "type": "string" - }, "ModelWithInteger": { "description": "This is a model with one number property", "type": "object", @@ -1469,7 +1465,7 @@ "propWithFile": { "type": "array", "items": { - "type": "file" + "type": "File" } }, "propWithNumber": { @@ -1519,7 +1515,7 @@ } } }, - "ModelWithOneOf": { + "CompositionWithOneOf": { "description": "This is a model with one property with a 'one of' relationship", "type": "object", "properties": { @@ -1542,7 +1538,33 @@ } } }, - "ModelWithAnyOf": { + "CompositionWithOneOfAnonymous": { + "description": "This is a model with one property with a 'one of' relationship where the options are not $ref", + "type": "object", + "properties": { + "propA": { + "type": "object", + "oneOf": [ + { + "description": "Anonymous object type", + "type": "object", + "properties": { + "propA": "string" + } + }, + { + "description": "Anonymous string type", + "type": "string" + }, + { + "description": "Anonymous integer type", + "type": "integer" + } + ] + } + } + }, + "CompositionWithAnyOf": { "description": "This is a model with one property with a 'any of' relationship", "type": "object", "properties": { @@ -1565,6 +1587,119 @@ } } }, + "CompositionWithAnyOfAnonymous": { + "description": "This is a model with one property with a 'any of' relationship where the options are not $ref", + "type": "object", + "properties": { + "propA": { + "type": "object", + "anyOf": [ + { + "description": "Anonymous object type", + "type": "object", + "properties": { + "propA": "string" + } + }, + { + "description": "Anonymous string type", + "type": "string" + }, + { + "description": "Anonymous integer type", + "type": "integer" + } + ] + } + } + }, + "CompositionWithOneOfAndNullable": { + "description": "This is a model with one property with a 'one of' relationship", + "type": "object", + "properties": { + "propA": { + "nullable": true, + "type": "object", + "oneOf": [ + { + "type": "object", + "properties": { + "boolean": { + "type": "boolean" + } + } + }, + { + "$ref": "#/components/schemas/ModelWithEnum" + }, + { + "$ref": "#/components/schemas/ModelWithArray" + }, + { + "$ref": "#/components/schemas/ModelWithDictionary" + } + ] + } + } + }, + "CompositionWithAllOfAndNullable": { + "description": "This is a model with one property with a 'all of' relationship", + "type": "object", + "properties": { + "propA": { + "nullable": true, + "type": "object", + "allOf": [ + { + "type": "object", + "properties": { + "boolean": { + "type": "boolean" + } + } + }, + { + "$ref": "#/components/schemas/ModelWithEnum" + }, + { + "$ref": "#/components/schemas/ModelWithArray" + }, + { + "$ref": "#/components/schemas/ModelWithDictionary" + } + ] + } + } + }, + "CompositionWithAnyOfAndNullable": { + "description": "This is a model with one property with a 'any of' relationship", + "type": "object", + "properties": { + "propA": { + "nullable": true, + "type": "object", + "anyOf": [ + { + "type": "object", + "properties": { + "boolean": { + "type": "boolean" + } + } + }, + { + "$ref": "#/components/schemas/ModelWithEnum" + }, + { + "$ref": "#/components/schemas/ModelWithArray" + }, + { + "$ref": "#/components/schemas/ModelWithDictionary" + } + ] + } + } + }, "ModelWithProperties": { "description": "This is a model with one nested property", "type": "object",