diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptClientCodegen.java index b3305c904f5b..9a13e71a7423 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptClientCodegen.java @@ -50,6 +50,7 @@ import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; import static org.openapitools.codegen.utils.CamelizeOption.LOWERCASE_FIRST_LETTER; import static org.openapitools.codegen.utils.OnceLogger.once; @@ -174,6 +175,9 @@ public TypeScriptClientCodegen() { // models setModelPackage("models"); supportingFiles.add(new SupportingFile("model" + File.separator + "ObjectSerializer.mustache", "models", "ObjectSerializer.ts")); + supportingFiles.add(new SupportingFile("model" + File.separator + "TypeMatcher.mustache", "models", "TypeMatcher.ts")); + supportingFiles.add(new SupportingFile("model" + File.separator + "ModelTypes.mustache", "models", "ModelTypes.ts")); + modelTemplateFiles.put("model" + File.separator + "model.mustache", ".ts"); // api @@ -360,12 +364,22 @@ private String getNameWithEnumPropertyNaming(String name) { } } + @Override + public CodegenModel fromModel(String name, Schema schema) { + CodegenModel codegenModel = super.fromModel(name, schema); + return new ExtendedCodegenModel(codegenModel); + } + @Override public ModelsMap postProcessModels(ModelsMap objs) { // process enum in models List models = postProcessModelsEnum(objs).getModels(); for (ModelMap mo : models) { - CodegenModel cm = mo.getModel(); + CodegenModel model = mo.getModel(); + // Convert to ExtendedCodegenModel if it's not already one (e.g., in tests) + ExtendedCodegenModel cm = model instanceof ExtendedCodegenModel + ? (ExtendedCodegenModel) model + : new ExtendedCodegenModel(model); cm.imports = new TreeSet<>(cm.imports); // name enum with model name, e.g. StatusEnum => Pet.StatusEnum for (CodegenProperty var : cm.vars) { @@ -381,15 +395,37 @@ public ModelsMap postProcessModels(ModelsMap objs) { } } } + + List oneOfsList = Optional.ofNullable(cm.getComposedSchemas()) + .map(CodegenComposedSchemas::getOneOf) + .orElse(Collections.emptyList()); + + // create a set of any non-primitive, non-array types used in the oneOf schemas which will + // need to be imported. + cm.oneOfModels = oneOfsList.stream() + .filter(cp -> !cp.getIsPrimitiveType() && !cp.getIsArray()) + .map(CodegenProperty::getBaseType) + .filter(Objects::nonNull) + .collect(Collectors.toCollection(TreeSet::new)); + + // create a set of any complex, inner types used by arrays in the oneOf schema (e.g. if + // the oneOf uses Array, Foo needs to be imported). + cm.oneOfArrays = oneOfsList.stream() + .filter(CodegenProperty::getIsArray) + .map(CodegenProperty::getComplexType) + .filter(Objects::nonNull) + .collect(Collectors.toCollection(TreeSet::new)); + + // create a set of primitive types used in the oneOf schemas for the deserialization process. + cm.oneOfPrimitives = oneOfsList.stream() + .filter(CodegenProperty::getIsPrimitiveType) + .collect(Collectors.toCollection(HashSet::new)); + if (!cm.oneOf.isEmpty()) { // For oneOfs only import $refs within the oneOf - TreeSet oneOfRefs = new TreeSet<>(); - for (String im : cm.imports) { - if (cm.oneOf.contains(im)) { - oneOfRefs.add(im); - } - } - cm.imports = oneOfRefs; + cm.imports = cm.imports.stream() + .filter(im -> cm.oneOfModels.contains(im) || cm.oneOfArrays.contains(im)) + .collect(Collectors.toCollection(TreeSet::new)); } } for (ModelMap mo : models) { @@ -1117,4 +1153,111 @@ protected void addImport(Set importsToBeAddedTo, String type) { protected String[] splitComposedTypes(String type) { return type.replace(" ", "").split("[|&<>]"); } + + public class ExtendedCodegenModel extends CodegenModel { + // oneOfModels contains a list of non-primitive, non-array types referenced in oneOf schemas that need to be + // imported. + // oneOfArrays contains a list of complex inner types used in arrays within oneOf schemas (e.g. if + // oneOf uses Array, Foo needs to be imported). + // oneOfPrimitives contains a list of primitive types used in oneOf schemas for the deserialization process. + @Getter @Setter + public Set oneOfModels = new TreeSet<>(); + @Getter @Setter + public Set oneOfArrays = new TreeSet<>(); + @Getter @Setter + public Set oneOfPrimitives = new HashSet<>(); + + public ExtendedCodegenModel(CodegenModel cm) { + super(); + + this.parent = cm.parent; + this.parentSchema = cm.parentSchema; + this.interfaces = cm.interfaces; + this.allParents = cm.allParents; + this.parentModel = cm.parentModel; + this.interfaceModels = cm.interfaceModels; + this.children = cm.children; + this.anyOf = cm.anyOf; + this.oneOf = cm.oneOf; + this.allOf = cm.allOf; + this.permits = cm.permits; + this.name = cm.name; + this.schemaName = cm.schemaName; + this.classname = cm.classname; + this.title = cm.title; + this.description = cm.description; + this.classVarName = cm.classVarName; + this.modelJson = cm.modelJson; + this.dataType = cm.dataType; + this.xmlPrefix = cm.xmlPrefix; + this.xmlNamespace = cm.xmlNamespace; + this.xmlName = cm.xmlName; + this.classFilename = cm.classFilename; + this.unescapedDescription = cm.unescapedDescription; + this.defaultValue = cm.defaultValue; + this.arrayModelType = cm.arrayModelType; + this.isAlias = cm.isAlias; + this.isString = cm.isString; + this.isInteger = cm.isInteger; + this.isLong = cm.isLong; + this.isNumber = cm.isNumber; + this.isNumeric = cm.isNumeric; + this.isFloat = cm.isFloat; + this.isDouble = cm.isDouble; + this.isDate = cm.isDate; + this.isDateTime = cm.isDateTime; + this.vars = cm.vars; + this.allVars = cm.allVars; + this.requiredVars = cm.requiredVars; + this.optionalVars = cm.optionalVars; + this.hasReadOnly = cm.hasReadOnly; + this.readOnlyVars = cm.readOnlyVars; + this.readWriteVars = cm.readWriteVars; + this.parentVars = cm.parentVars; + this.parentRequiredVars = cm.parentRequiredVars; + this.nonNullableVars = cm.nonNullableVars; + this.allowableValues = cm.allowableValues; + this.mandatory = cm.mandatory; + this.allMandatory = cm.allMandatory; + this.imports = cm.imports; + this.hasVars = cm.hasVars; + this.emptyVars = cm.emptyVars; + this.hasMoreModels = cm.hasMoreModels; + this.hasEnums = cm.hasEnums; + this.isEnum = cm.isEnum; + this.hasValidation = cm.hasValidation; + this.isNullable = cm.isNullable; + this.hasRequired = cm.hasRequired; + this.hasOptional = cm.hasOptional; + this.isArray = cm.isArray; + this.hasChildren = cm.hasChildren; + this.isMap = cm.isMap; + this.isDeprecated = cm.isDeprecated; + this.hasOnlyReadOnly = cm.hasOnlyReadOnly; + this.externalDocumentation = cm.externalDocumentation; + + this.vendorExtensions = cm.vendorExtensions; + this.additionalPropertiesType = cm.additionalPropertiesType; + this.isAdditionalPropertiesTrue = cm.isAdditionalPropertiesTrue; + this.setMaxProperties(cm.getMaxProperties()); + this.setMinProperties(cm.getMinProperties()); + this.setUniqueItems(cm.getUniqueItems()); + this.setMaxItems(cm.getMaxItems()); + this.setMinItems(cm.getMinItems()); + this.setMaxLength(cm.getMaxLength()); + this.setMinLength(cm.getMinLength()); + this.setExclusiveMinimum(cm.getExclusiveMinimum()); + this.setExclusiveMaximum(cm.getExclusiveMaximum()); + this.setMinimum(cm.getMinimum()); + this.setMaximum(cm.getMaximum()); + this.setPattern(cm.getPattern()); + this.setMultipleOf(cm.getMultipleOf()); + this.setItems(cm.getItems()); + this.setAdditionalProperties(cm.getAdditionalProperties()); + this.setIsModel(cm.getIsModel()); + this.setComposedSchemas(cm.getComposedSchemas()); + this.setDiscriminator(cm.getDiscriminator()); + } + + } } diff --git a/modules/openapi-generator/src/main/resources/typescript/model/ModelTypes.mustache b/modules/openapi-generator/src/main/resources/typescript/model/ModelTypes.mustache new file mode 100644 index 000000000000..24a680aba301 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/typescript/model/ModelTypes.mustache @@ -0,0 +1,11 @@ +/** + * Represents a single attribute/property metadata entry in the attributeTypeMap. + * Used for validation and type matching in oneOf scenarios. + */ +export type AttributeTypeMapEntry = { + name: string; + baseName: string; + type: string; + format: string; + required: boolean; +}; diff --git a/modules/openapi-generator/src/main/resources/typescript/model/ObjectSerializer.mustache b/modules/openapi-generator/src/main/resources/typescript/model/ObjectSerializer.mustache index 714af5bbe22e..f0053b715971 100644 --- a/modules/openapi-generator/src/main/resources/typescript/model/ObjectSerializer.mustache +++ b/modules/openapi-generator/src/main/resources/typescript/model/ObjectSerializer.mustache @@ -127,26 +127,37 @@ export class ObjectSerializer { // Check the discriminator let discriminatorProperty = typeMap[expectedType].discriminator; - if (discriminatorProperty == null) { - return expectedType; // the type does not have a discriminator. use it. - } else { - if (data[discriminatorProperty]) { - var discriminatorType = data[discriminatorProperty]; - let mapping = typeMap[expectedType].mapping; - if (mapping != undefined && mapping[discriminatorType]) { - return mapping[discriminatorType]; // use the type given in the discriminator - } else if(typeMap[discriminatorType]) { - return discriminatorType; - } else { - return expectedType; // discriminator did not map to a type + if (discriminatorProperty == null || !data[discriminatorProperty]) { + if (this.hasFindMatchingTypeMethod(typeMap[expectedType])) { + const foundType = typeMap[expectedType].findMatchingType(data); + if (foundType == undefined) { + throw new Error("Unable to determine a unique type for the provided object: oneOf type resolution failed. The object does not match exactly one schema. Consider adding a discriminator or making schemas mutually exclusive."); } + + return foundType; + } + return expectedType; // the type does not have a discriminator and findMatchingType method. use it. + } else { + let discriminatorType = data[discriminatorProperty]; + let mapping = typeMap[expectedType].mapping; + if (mapping != undefined && mapping[discriminatorType]) { + return mapping[discriminatorType]; // use the type given in the discriminator + } else if(typeMap[discriminatorType]) { + return discriminatorType; } else { - return expectedType; // discriminator was not present (or an empty string) + throw new Error(`Discriminator property '${discriminatorProperty}' has value '${discriminatorType}' which does not map to any known type in '${expectedType}'.`); } } } } + private static hasFindMatchingTypeMethod(klass: any): boolean { + if (typeof klass.findMatchingType === 'function') { + return true; + } + return false; + } + public static serialize(data: any, type: string, format: string): any { if (data == undefined) { return data; diff --git a/modules/openapi-generator/src/main/resources/typescript/model/TypeMatcher.mustache b/modules/openapi-generator/src/main/resources/typescript/model/TypeMatcher.mustache new file mode 100644 index 000000000000..43457fa0b3fa --- /dev/null +++ b/modules/openapi-generator/src/main/resources/typescript/model/TypeMatcher.mustache @@ -0,0 +1,36 @@ +import { AttributeTypeMapEntry } from '../models/ModelTypes{{importFileExtension}}'; + +/** + * Validates if data contains all required attributes from the attributeTypeMap. + * + * @param data - The data object to validate + * @param attributeTypeMap - Array of attribute metadata including required flag + * @returns true if all required attributes are present in data, false otherwise + */ +export function instanceOfType(data: any, attributeTypeMap: Array): boolean { + for (const attribute of attributeTypeMap) { + if (attribute.required && data[attribute.baseName] === undefined) { + return false; + } + } + + return true; +} + +/** + * Attempts to find a matching type from an array of possible types by validating + * the data against each type's attribute requirements. + * + * @param data - The data object to match + * @param types - Array of possible type constructors + * @returns The name of the matching type, or undefined if no match found + */ +export function findMatchingType(data: any, types: Array): string | undefined { + for (const type of types) { + if (instanceOfType(data, type.getAttributeTypeMap())) { + return type.name; + } + } + + return undefined; +} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/typescript/model/model.mustache b/modules/openapi-generator/src/main/resources/typescript/model/model.mustache index 34cf53b15259..fb91a6ea0f91 100644 --- a/modules/openapi-generator/src/main/resources/typescript/model/model.mustache +++ b/modules/openapi-generator/src/main/resources/typescript/model/model.mustache @@ -1,9 +1,14 @@ {{>licenseInfo}} {{#models}} {{#model}} +{{#oneOf}} +{{#-first}}{{>model/modelOneOf}}{{/-first}} +{{/oneOf}} +{{^oneOf}} {{#tsImports}} import { {{classname}} } from '{{filename}}{{importFileExtension}}'; {{/tsImports}} +import { AttributeTypeMapEntry } from '../models/ModelTypes{{importFileExtension}}'; import { HttpFile } from '../http/http{{importFileExtension}}'; {{#description}} @@ -12,10 +17,6 @@ import { HttpFile } from '../http/http{{importFileExtension}}'; */ {{/description}} {{^isEnum}} -{{#oneOf}} -{{#-first}}{{>model/modelOneOf}}{{/-first}} -{{/oneOf}} -{{^oneOf}} export class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{ {{#vars}} {{#description}} @@ -46,13 +47,14 @@ export class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{ {{/hasDiscriminatorWithNonEmptyMapping}} {{^isArray}} - static {{#parent}}override {{/parent}}readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static {{#parent}}override {{/parent}}readonly attributeTypeMap: Array = [ {{#vars}} { "name": "{{name}}", "baseName": "{{baseName}}", "type": "{{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}", - "format": "{{dataFormat}}" + "format": "{{dataFormat}}", + "required": {{required}} }{{^-last}}, {{/-last}} {{/vars}} @@ -97,7 +99,6 @@ export enum {{classname}}{{enumName}} { {{/vars}} {{/hasEnums}} -{{/oneOf}} {{/isEnum}} {{#isEnum}} export enum {{classname}} { @@ -108,5 +109,6 @@ export enum {{classname}} { {{/allowableValues}} } {{/isEnum}} +{{/oneOf}} {{/model}} {{/models}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/typescript/model/modelOneOf.mustache b/modules/openapi-generator/src/main/resources/typescript/model/modelOneOf.mustache index d5e026ac6d45..a0d5ee199f91 100644 --- a/modules/openapi-generator/src/main/resources/typescript/model/modelOneOf.mustache +++ b/modules/openapi-generator/src/main/resources/typescript/model/modelOneOf.mustache @@ -1,11 +1,8 @@ -{{#hasImports}} -import { - {{#imports}} - {{{.}}}{{importFileExtension}}, - {{/imports}} -} from './'; +{{#tsImports}} +import { {{classname}} } from '{{filename}}{{importFileExtension}}'; +{{/tsImports}} +import { findMatchingType } from '../models/TypeMatcher{{importFileExtension}}'; -{{/hasImports}} /** * @type {{classname}} * Type @@ -37,4 +34,16 @@ export class {{classname}}Class { static readonly mapping: {[index: string]: string} | undefined = undefined; {{/hasDiscriminatorWithNonEmptyMapping}} + + private static readonly arrayOfTypes: Array<{{#oneOfModels}}typeof {{{.}}}{{^-last}} | {{/-last}}{{/oneOfModels}}> = [{{#oneOfModels}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOfModels}}]; + + /** + * Determines which oneOf schema matches the provided data. + * + * @param data - The data object to match against oneOf schemas + * @returns The name of the matching type, or undefined if no unique match is found + */ + public static findMatchingType(data: any): string | undefined { + return findMatchingType(data, this.arrayOfTypes); + } } \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/typescript/model/models_all.mustache b/modules/openapi-generator/src/main/resources/typescript/model/models_all.mustache index 5d93be1dad82..46a477ad26c0 100644 --- a/modules/openapi-generator/src/main/resources/typescript/model/models_all.mustache +++ b/modules/openapi-generator/src/main/resources/typescript/model/models_all.mustache @@ -2,4 +2,6 @@ {{#model}} export * from '{{{ importPath }}}{{importFileExtension}}' {{/model}} -{{/models}} \ No newline at end of file +{{/models}} +export * from './TypeMatcher{{importFileExtension}}' +export * from './ModelTypes{{importFileExtension}}' \ No newline at end of file diff --git a/modules/openapi-generator/src/test/resources/3_0/typescript/oneOf.yaml b/modules/openapi-generator/src/test/resources/3_0/typescript/oneOf.yaml new file mode 100644 index 000000000000..9c49046cacf4 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/typescript/oneOf.yaml @@ -0,0 +1,62 @@ +openapi: 3.0.0 +info: + version: 1.0.0 + title: testing oneOf +servers: + - url: http://localhost:3000 +paths: + /test: + get: + operationId: testWithoutDiscriminator + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/PetResponse' + /test-discriminator: + get: + operationId: testDiscriminator + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/PetDiscriminatorResponse' +components: + schemas: + PetDiscriminatorResponse: + discriminator: + propertyName: petType + mapping: + cat: "#/components/schemas/Cat" + dog: "#/components/schemas/Dog" + oneOf: + - $ref: "#/components/schemas/Cat" + - $ref: "#/components/schemas/Dog" + PetResponse: + oneOf: + - $ref: "#/components/schemas/Cat" + - $ref: "#/components/schemas/Dog" + Cat: + type: object + properties: + name: + type: string + petType: + type: string + required: + - name + - petType + Dog: + type: object + properties: + bark: + type: string + petType: + type: string + required: + - bark + - petType \ No newline at end of file diff --git a/samples/client/echo_api/typescript/build/.openapi-generator/FILES b/samples/client/echo_api/typescript/build/.openapi-generator/FILES index 4db34aea13ac..ea1b97a079b7 100644 --- a/samples/client/echo_api/typescript/build/.openapi-generator/FILES +++ b/samples/client/echo_api/typescript/build/.openapi-generator/FILES @@ -26,6 +26,7 @@ models/Bird.ts models/Category.ts models/DataQuery.ts models/DefaultValue.ts +models/ModelTypes.ts models/NumberPropertiesOnly.ts models/ObjectSerializer.ts models/Pet.ts @@ -35,6 +36,7 @@ models/Tag.ts models/TestFormObjectMultipartRequestMarker.ts models/TestQueryStyleDeepObjectExplodeTrueObjectAllOfQueryObjectParameter.ts models/TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter.ts +models/TypeMatcher.ts models/all.ts package.json rxjsStub.ts diff --git a/samples/client/echo_api/typescript/build/models/Bird.ts b/samples/client/echo_api/typescript/build/models/Bird.ts index c08fd50f9ea2..6f6aa850a51e 100644 --- a/samples/client/echo_api/typescript/build/models/Bird.ts +++ b/samples/client/echo_api/typescript/build/models/Bird.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class Bird { @@ -20,18 +21,20 @@ export class Bird { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "size", "baseName": "size", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "color", "baseName": "color", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/client/echo_api/typescript/build/models/Category.ts b/samples/client/echo_api/typescript/build/models/Category.ts index 739eab7c4cc1..538ff3442be0 100644 --- a/samples/client/echo_api/typescript/build/models/Category.ts +++ b/samples/client/echo_api/typescript/build/models/Category.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class Category { @@ -20,18 +21,20 @@ export class Category { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "name", "baseName": "name", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/client/echo_api/typescript/build/models/DataQuery.ts b/samples/client/echo_api/typescript/build/models/DataQuery.ts index 6b52d951fb72..457bbf706847 100644 --- a/samples/client/echo_api/typescript/build/models/DataQuery.ts +++ b/samples/client/echo_api/typescript/build/models/DataQuery.ts @@ -11,6 +11,7 @@ */ import { Query } from '../models/Query'; +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class DataQuery extends Query { @@ -31,24 +32,27 @@ export class DataQuery extends Query { static override readonly mapping: {[index: string]: string} | undefined = undefined; - static override readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static override readonly attributeTypeMap: Array = [ { "name": "suffix", "baseName": "suffix", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "text", "baseName": "text", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "date", "baseName": "date", "type": "Date", - "format": "date-time" + "format": "date-time", + "required": false } ]; static override getAttributeTypeMap() { diff --git a/samples/client/echo_api/typescript/build/models/DefaultValue.ts b/samples/client/echo_api/typescript/build/models/DefaultValue.ts index 05cc0d9ad412..4bf132b26934 100644 --- a/samples/client/echo_api/typescript/build/models/DefaultValue.ts +++ b/samples/client/echo_api/typescript/build/models/DefaultValue.ts @@ -11,6 +11,7 @@ */ import { StringEnumRef } from '../models/StringEnumRef'; +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -30,54 +31,62 @@ export class DefaultValue { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "arrayStringEnumRefDefault", "baseName": "array_string_enum_ref_default", "type": "Array", - "format": "" + "format": "", + "required": false }, { "name": "arrayStringEnumDefault", "baseName": "array_string_enum_default", "type": "Array", - "format": "" + "format": "", + "required": false }, { "name": "arrayStringDefault", "baseName": "array_string_default", "type": "Array", - "format": "" + "format": "", + "required": false }, { "name": "arrayIntegerDefault", "baseName": "array_integer_default", "type": "Array", - "format": "" + "format": "", + "required": false }, { "name": "arrayString", "baseName": "array_string", "type": "Array", - "format": "" + "format": "", + "required": false }, { "name": "arrayStringNullable", "baseName": "array_string_nullable", "type": "Array", - "format": "" + "format": "", + "required": false }, { "name": "arrayStringExtensionNullable", "baseName": "array_string_extension_nullable", "type": "Array", - "format": "" + "format": "", + "required": false }, { "name": "stringNullable", "baseName": "string_nullable", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/client/echo_api/typescript/build/models/ModelTypes.ts b/samples/client/echo_api/typescript/build/models/ModelTypes.ts new file mode 100644 index 000000000000..24a680aba301 --- /dev/null +++ b/samples/client/echo_api/typescript/build/models/ModelTypes.ts @@ -0,0 +1,11 @@ +/** + * Represents a single attribute/property metadata entry in the attributeTypeMap. + * Used for validation and type matching in oneOf scenarios. + */ +export type AttributeTypeMapEntry = { + name: string; + baseName: string; + type: string; + format: string; + required: boolean; +}; diff --git a/samples/client/echo_api/typescript/build/models/NumberPropertiesOnly.ts b/samples/client/echo_api/typescript/build/models/NumberPropertiesOnly.ts index 8787f9c7f6ba..9de7f1080633 100644 --- a/samples/client/echo_api/typescript/build/models/NumberPropertiesOnly.ts +++ b/samples/client/echo_api/typescript/build/models/NumberPropertiesOnly.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class NumberPropertiesOnly { @@ -21,24 +22,27 @@ export class NumberPropertiesOnly { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "number", "baseName": "number", "type": "number", - "format": "" + "format": "", + "required": false }, { "name": "_float", "baseName": "float", "type": "number", - "format": "float" + "format": "float", + "required": false }, { "name": "_double", "baseName": "double", "type": "number", - "format": "double" + "format": "double", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/client/echo_api/typescript/build/models/ObjectSerializer.ts b/samples/client/echo_api/typescript/build/models/ObjectSerializer.ts index a91cfd29d80e..ce6d818e81d4 100644 --- a/samples/client/echo_api/typescript/build/models/ObjectSerializer.ts +++ b/samples/client/echo_api/typescript/build/models/ObjectSerializer.ts @@ -135,26 +135,37 @@ export class ObjectSerializer { // Check the discriminator let discriminatorProperty = typeMap[expectedType].discriminator; - if (discriminatorProperty == null) { - return expectedType; // the type does not have a discriminator. use it. - } else { - if (data[discriminatorProperty]) { - var discriminatorType = data[discriminatorProperty]; - let mapping = typeMap[expectedType].mapping; - if (mapping != undefined && mapping[discriminatorType]) { - return mapping[discriminatorType]; // use the type given in the discriminator - } else if(typeMap[discriminatorType]) { - return discriminatorType; - } else { - return expectedType; // discriminator did not map to a type + if (discriminatorProperty == null || !data[discriminatorProperty]) { + if (this.hasFindMatchingTypeMethod(typeMap[expectedType])) { + const foundType = typeMap[expectedType].findMatchingType(data); + if (foundType == undefined) { + throw new Error("Unable to determine a unique type for the provided object: oneOf type resolution failed. The object does not match exactly one schema. Consider adding a discriminator or making schemas mutually exclusive."); } + + return foundType; + } + return expectedType; // the type does not have a discriminator and findMatchingType method. use it. + } else { + let discriminatorType = data[discriminatorProperty]; + let mapping = typeMap[expectedType].mapping; + if (mapping != undefined && mapping[discriminatorType]) { + return mapping[discriminatorType]; // use the type given in the discriminator + } else if(typeMap[discriminatorType]) { + return discriminatorType; } else { - return expectedType; // discriminator was not present (or an empty string) + throw new Error(`Discriminator property '${discriminatorProperty}' has value '${discriminatorType}' which does not map to any known type in '${expectedType}'.`); } } } } + private static hasFindMatchingTypeMethod(klass: any): boolean { + if (typeof klass.findMatchingType === 'function') { + return true; + } + return false; + } + public static serialize(data: any, type: string, format: string): any { if (data == undefined) { return data; diff --git a/samples/client/echo_api/typescript/build/models/Pet.ts b/samples/client/echo_api/typescript/build/models/Pet.ts index 276d033ed06f..4b0c421e3b01 100644 --- a/samples/client/echo_api/typescript/build/models/Pet.ts +++ b/samples/client/echo_api/typescript/build/models/Pet.ts @@ -12,6 +12,7 @@ import { Category } from '../models/Category'; import { Tag } from '../models/Tag'; +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class Pet { @@ -29,42 +30,48 @@ export class Pet { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "name", "baseName": "name", "type": "string", - "format": "" + "format": "", + "required": true }, { "name": "category", "baseName": "category", "type": "Category", - "format": "" + "format": "", + "required": false }, { "name": "photoUrls", "baseName": "photoUrls", "type": "Array", - "format": "" + "format": "", + "required": true }, { "name": "tags", "baseName": "tags", "type": "Array", - "format": "" + "format": "", + "required": false }, { "name": "status", "baseName": "status", "type": "PetStatusEnum", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/client/echo_api/typescript/build/models/Query.ts b/samples/client/echo_api/typescript/build/models/Query.ts index a69887a4288a..afb6e29e47a1 100644 --- a/samples/client/echo_api/typescript/build/models/Query.ts +++ b/samples/client/echo_api/typescript/build/models/Query.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class Query { @@ -23,18 +24,20 @@ export class Query { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "outcomes", "baseName": "outcomes", "type": "Array", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/client/echo_api/typescript/build/models/StringEnumRef.ts b/samples/client/echo_api/typescript/build/models/StringEnumRef.ts index b208b9c892cb..da0298c084f4 100644 --- a/samples/client/echo_api/typescript/build/models/StringEnumRef.ts +++ b/samples/client/echo_api/typescript/build/models/StringEnumRef.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export enum StringEnumRef { diff --git a/samples/client/echo_api/typescript/build/models/Tag.ts b/samples/client/echo_api/typescript/build/models/Tag.ts index cb9adebd7f8b..b6fdea4330bb 100644 --- a/samples/client/echo_api/typescript/build/models/Tag.ts +++ b/samples/client/echo_api/typescript/build/models/Tag.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class Tag { @@ -20,18 +21,20 @@ export class Tag { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "name", "baseName": "name", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/client/echo_api/typescript/build/models/TestFormObjectMultipartRequestMarker.ts b/samples/client/echo_api/typescript/build/models/TestFormObjectMultipartRequestMarker.ts index 14e19e7ccec1..b495ad8b438f 100644 --- a/samples/client/echo_api/typescript/build/models/TestFormObjectMultipartRequestMarker.ts +++ b/samples/client/echo_api/typescript/build/models/TestFormObjectMultipartRequestMarker.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class TestFormObjectMultipartRequestMarker { @@ -19,12 +20,13 @@ export class TestFormObjectMultipartRequestMarker { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "name", "baseName": "name", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/client/echo_api/typescript/build/models/TestQueryStyleDeepObjectExplodeTrueObjectAllOfQueryObjectParameter.ts b/samples/client/echo_api/typescript/build/models/TestQueryStyleDeepObjectExplodeTrueObjectAllOfQueryObjectParameter.ts index b0201ab7eb84..287458066847 100644 --- a/samples/client/echo_api/typescript/build/models/TestQueryStyleDeepObjectExplodeTrueObjectAllOfQueryObjectParameter.ts +++ b/samples/client/echo_api/typescript/build/models/TestQueryStyleDeepObjectExplodeTrueObjectAllOfQueryObjectParameter.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class TestQueryStyleDeepObjectExplodeTrueObjectAllOfQueryObjectParameter { @@ -22,30 +23,34 @@ export class TestQueryStyleDeepObjectExplodeTrueObjectAllOfQueryObjectParameter static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "size", "baseName": "size", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "color", "baseName": "color", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "name", "baseName": "name", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/client/echo_api/typescript/build/models/TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter.ts b/samples/client/echo_api/typescript/build/models/TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter.ts index 0474367333cd..e31d7defc6db 100644 --- a/samples/client/echo_api/typescript/build/models/TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter.ts +++ b/samples/client/echo_api/typescript/build/models/TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter { @@ -19,12 +20,13 @@ export class TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "values", "baseName": "values", "type": "Array", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/client/echo_api/typescript/build/models/TypeMatcher.ts b/samples/client/echo_api/typescript/build/models/TypeMatcher.ts new file mode 100644 index 000000000000..2f1c20864a70 --- /dev/null +++ b/samples/client/echo_api/typescript/build/models/TypeMatcher.ts @@ -0,0 +1,36 @@ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; + +/** + * Validates if data contains all required attributes from the attributeTypeMap. + * + * @param data - The data object to validate + * @param attributeTypeMap - Array of attribute metadata including required flag + * @returns true if all required attributes are present in data, false otherwise + */ +export function instanceOfType(data: any, attributeTypeMap: Array): boolean { + for (const attribute of attributeTypeMap) { + if (attribute.required && data[attribute.baseName] === undefined) { + return false; + } + } + + return true; +} + +/** + * Attempts to find a matching type from an array of possible types by validating + * the data against each type's attribute requirements. + * + * @param data - The data object to match + * @param types - Array of possible type constructors + * @returns The name of the matching type, or undefined if no match found + */ +export function findMatchingType(data: any, types: Array): string | undefined { + for (const type of types) { + if (instanceOfType(data, type.getAttributeTypeMap())) { + return type.name; + } + } + + return undefined; +} \ No newline at end of file diff --git a/samples/client/echo_api/typescript/build/models/all.ts b/samples/client/echo_api/typescript/build/models/all.ts index 6c43a5186e11..978e435b97dc 100644 --- a/samples/client/echo_api/typescript/build/models/all.ts +++ b/samples/client/echo_api/typescript/build/models/all.ts @@ -10,3 +10,5 @@ export * from '../models/Tag' export * from '../models/TestFormObjectMultipartRequestMarker' export * from '../models/TestQueryStyleDeepObjectExplodeTrueObjectAllOfQueryObjectParameter' export * from '../models/TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter' +export * from './TypeMatcher' +export * from './ModelTypes' \ No newline at end of file diff --git a/samples/client/others/typescript/builds/array-of-lists/.openapi-generator/FILES b/samples/client/others/typescript/builds/array-of-lists/.openapi-generator/FILES index 01213762e79b..854d23ea936d 100644 --- a/samples/client/others/typescript/builds/array-of-lists/.openapi-generator/FILES +++ b/samples/client/others/typescript/builds/array-of-lists/.openapi-generator/FILES @@ -14,7 +14,9 @@ index.ts middleware.ts models/List.ts models/ListPaged.ts +models/ModelTypes.ts models/ObjectSerializer.ts +models/TypeMatcher.ts models/all.ts package.json rxjsStub.ts diff --git a/samples/client/others/typescript/builds/array-of-lists/models/List.ts b/samples/client/others/typescript/builds/array-of-lists/models/List.ts index 4391b596c046..2ce48bc50c9e 100644 --- a/samples/client/others/typescript/builds/array-of-lists/models/List.ts +++ b/samples/client/others/typescript/builds/array-of-lists/models/List.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class List { @@ -19,12 +20,13 @@ export class List { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/client/others/typescript/builds/array-of-lists/models/ListPaged.ts b/samples/client/others/typescript/builds/array-of-lists/models/ListPaged.ts index e89b272d7f0f..05c4accd3f02 100644 --- a/samples/client/others/typescript/builds/array-of-lists/models/ListPaged.ts +++ b/samples/client/others/typescript/builds/array-of-lists/models/ListPaged.ts @@ -11,6 +11,7 @@ */ import { List } from '../models/List'; +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class ListPaged { @@ -20,12 +21,13 @@ export class ListPaged { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "data", "baseName": "data", "type": "Array", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/client/others/typescript/builds/array-of-lists/models/ModelTypes.ts b/samples/client/others/typescript/builds/array-of-lists/models/ModelTypes.ts new file mode 100644 index 000000000000..24a680aba301 --- /dev/null +++ b/samples/client/others/typescript/builds/array-of-lists/models/ModelTypes.ts @@ -0,0 +1,11 @@ +/** + * Represents a single attribute/property metadata entry in the attributeTypeMap. + * Used for validation and type matching in oneOf scenarios. + */ +export type AttributeTypeMapEntry = { + name: string; + baseName: string; + type: string; + format: string; + required: boolean; +}; diff --git a/samples/client/others/typescript/builds/array-of-lists/models/ObjectSerializer.ts b/samples/client/others/typescript/builds/array-of-lists/models/ObjectSerializer.ts index d10cdbc5eff7..816e65805a12 100644 --- a/samples/client/others/typescript/builds/array-of-lists/models/ObjectSerializer.ts +++ b/samples/client/others/typescript/builds/array-of-lists/models/ObjectSerializer.ts @@ -102,26 +102,37 @@ export class ObjectSerializer { // Check the discriminator let discriminatorProperty = typeMap[expectedType].discriminator; - if (discriminatorProperty == null) { - return expectedType; // the type does not have a discriminator. use it. - } else { - if (data[discriminatorProperty]) { - var discriminatorType = data[discriminatorProperty]; - let mapping = typeMap[expectedType].mapping; - if (mapping != undefined && mapping[discriminatorType]) { - return mapping[discriminatorType]; // use the type given in the discriminator - } else if(typeMap[discriminatorType]) { - return discriminatorType; - } else { - return expectedType; // discriminator did not map to a type + if (discriminatorProperty == null || !data[discriminatorProperty]) { + if (this.hasFindMatchingTypeMethod(typeMap[expectedType])) { + const foundType = typeMap[expectedType].findMatchingType(data); + if (foundType == undefined) { + throw new Error("Unable to determine a unique type for the provided object: oneOf type resolution failed. The object does not match exactly one schema. Consider adding a discriminator or making schemas mutually exclusive."); } + + return foundType; + } + return expectedType; // the type does not have a discriminator and findMatchingType method. use it. + } else { + let discriminatorType = data[discriminatorProperty]; + let mapping = typeMap[expectedType].mapping; + if (mapping != undefined && mapping[discriminatorType]) { + return mapping[discriminatorType]; // use the type given in the discriminator + } else if(typeMap[discriminatorType]) { + return discriminatorType; } else { - return expectedType; // discriminator was not present (or an empty string) + throw new Error(`Discriminator property '${discriminatorProperty}' has value '${discriminatorType}' which does not map to any known type in '${expectedType}'.`); } } } } + private static hasFindMatchingTypeMethod(klass: any): boolean { + if (typeof klass.findMatchingType === 'function') { + return true; + } + return false; + } + public static serialize(data: any, type: string, format: string): any { if (data == undefined) { return data; diff --git a/samples/client/others/typescript/builds/array-of-lists/models/TypeMatcher.ts b/samples/client/others/typescript/builds/array-of-lists/models/TypeMatcher.ts new file mode 100644 index 000000000000..2f1c20864a70 --- /dev/null +++ b/samples/client/others/typescript/builds/array-of-lists/models/TypeMatcher.ts @@ -0,0 +1,36 @@ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; + +/** + * Validates if data contains all required attributes from the attributeTypeMap. + * + * @param data - The data object to validate + * @param attributeTypeMap - Array of attribute metadata including required flag + * @returns true if all required attributes are present in data, false otherwise + */ +export function instanceOfType(data: any, attributeTypeMap: Array): boolean { + for (const attribute of attributeTypeMap) { + if (attribute.required && data[attribute.baseName] === undefined) { + return false; + } + } + + return true; +} + +/** + * Attempts to find a matching type from an array of possible types by validating + * the data against each type's attribute requirements. + * + * @param data - The data object to match + * @param types - Array of possible type constructors + * @returns The name of the matching type, or undefined if no match found + */ +export function findMatchingType(data: any, types: Array): string | undefined { + for (const type of types) { + if (instanceOfType(data, type.getAttributeTypeMap())) { + return type.name; + } + } + + return undefined; +} \ No newline at end of file diff --git a/samples/client/others/typescript/builds/array-of-lists/models/all.ts b/samples/client/others/typescript/builds/array-of-lists/models/all.ts index c4ae741b185c..10545bc1913a 100644 --- a/samples/client/others/typescript/builds/array-of-lists/models/all.ts +++ b/samples/client/others/typescript/builds/array-of-lists/models/all.ts @@ -1,2 +1,4 @@ export * from '../models/List' export * from '../models/ListPaged' +export * from './TypeMatcher' +export * from './ModelTypes' \ No newline at end of file diff --git a/samples/client/others/typescript/builds/enum-single-value/.openapi-generator/FILES b/samples/client/others/typescript/builds/enum-single-value/.openapi-generator/FILES index 832d1d1b6d4d..95e5be47e46a 100644 --- a/samples/client/others/typescript/builds/enum-single-value/.openapi-generator/FILES +++ b/samples/client/others/typescript/builds/enum-single-value/.openapi-generator/FILES @@ -10,9 +10,11 @@ http/http.ts http/isomorphic-fetch.ts index.ts middleware.ts +models/ModelTypes.ts models/ObjectSerializer.ts models/SingleValueEnum30.ts models/SingleValueEnum31.ts +models/TypeMatcher.ts models/all.ts package.json rxjsStub.ts diff --git a/samples/client/others/typescript/builds/enum-single-value/models/ModelTypes.ts b/samples/client/others/typescript/builds/enum-single-value/models/ModelTypes.ts new file mode 100644 index 000000000000..24a680aba301 --- /dev/null +++ b/samples/client/others/typescript/builds/enum-single-value/models/ModelTypes.ts @@ -0,0 +1,11 @@ +/** + * Represents a single attribute/property metadata entry in the attributeTypeMap. + * Used for validation and type matching in oneOf scenarios. + */ +export type AttributeTypeMapEntry = { + name: string; + baseName: string; + type: string; + format: string; + required: boolean; +}; diff --git a/samples/client/others/typescript/builds/enum-single-value/models/ObjectSerializer.ts b/samples/client/others/typescript/builds/enum-single-value/models/ObjectSerializer.ts index 5ecf3d4ac6e7..18d77bce47fd 100644 --- a/samples/client/others/typescript/builds/enum-single-value/models/ObjectSerializer.ts +++ b/samples/client/others/typescript/builds/enum-single-value/models/ObjectSerializer.ts @@ -104,26 +104,37 @@ export class ObjectSerializer { // Check the discriminator let discriminatorProperty = typeMap[expectedType].discriminator; - if (discriminatorProperty == null) { - return expectedType; // the type does not have a discriminator. use it. - } else { - if (data[discriminatorProperty]) { - var discriminatorType = data[discriminatorProperty]; - let mapping = typeMap[expectedType].mapping; - if (mapping != undefined && mapping[discriminatorType]) { - return mapping[discriminatorType]; // use the type given in the discriminator - } else if(typeMap[discriminatorType]) { - return discriminatorType; - } else { - return expectedType; // discriminator did not map to a type + if (discriminatorProperty == null || !data[discriminatorProperty]) { + if (this.hasFindMatchingTypeMethod(typeMap[expectedType])) { + const foundType = typeMap[expectedType].findMatchingType(data); + if (foundType == undefined) { + throw new Error("Unable to determine a unique type for the provided object: oneOf type resolution failed. The object does not match exactly one schema. Consider adding a discriminator or making schemas mutually exclusive."); } + + return foundType; + } + return expectedType; // the type does not have a discriminator and findMatchingType method. use it. + } else { + let discriminatorType = data[discriminatorProperty]; + let mapping = typeMap[expectedType].mapping; + if (mapping != undefined && mapping[discriminatorType]) { + return mapping[discriminatorType]; // use the type given in the discriminator + } else if(typeMap[discriminatorType]) { + return discriminatorType; } else { - return expectedType; // discriminator was not present (or an empty string) + throw new Error(`Discriminator property '${discriminatorProperty}' has value '${discriminatorType}' which does not map to any known type in '${expectedType}'.`); } } } } + private static hasFindMatchingTypeMethod(klass: any): boolean { + if (typeof klass.findMatchingType === 'function') { + return true; + } + return false; + } + public static serialize(data: any, type: string, format: string): any { if (data == undefined) { return data; diff --git a/samples/client/others/typescript/builds/enum-single-value/models/SingleValueEnum30.ts b/samples/client/others/typescript/builds/enum-single-value/models/SingleValueEnum30.ts index 2a40dcb41470..b23bc63b9168 100644 --- a/samples/client/others/typescript/builds/enum-single-value/models/SingleValueEnum30.ts +++ b/samples/client/others/typescript/builds/enum-single-value/models/SingleValueEnum30.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class SingleValueEnum30 { @@ -19,12 +20,13 @@ export class SingleValueEnum30 { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "type", "baseName": "type", "type": "SingleValueEnum30TypeEnum", - "format": "" + "format": "", + "required": true } ]; static getAttributeTypeMap() { diff --git a/samples/client/others/typescript/builds/enum-single-value/models/SingleValueEnum31.ts b/samples/client/others/typescript/builds/enum-single-value/models/SingleValueEnum31.ts index 3f465512a97c..8f20fbf1430d 100644 --- a/samples/client/others/typescript/builds/enum-single-value/models/SingleValueEnum31.ts +++ b/samples/client/others/typescript/builds/enum-single-value/models/SingleValueEnum31.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class SingleValueEnum31 { @@ -19,12 +20,13 @@ export class SingleValueEnum31 { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "type", "baseName": "type", "type": "SingleValueEnum31TypeEnum", - "format": "" + "format": "", + "required": true } ]; static getAttributeTypeMap() { diff --git a/samples/client/others/typescript/builds/enum-single-value/models/TypeMatcher.ts b/samples/client/others/typescript/builds/enum-single-value/models/TypeMatcher.ts new file mode 100644 index 000000000000..2f1c20864a70 --- /dev/null +++ b/samples/client/others/typescript/builds/enum-single-value/models/TypeMatcher.ts @@ -0,0 +1,36 @@ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; + +/** + * Validates if data contains all required attributes from the attributeTypeMap. + * + * @param data - The data object to validate + * @param attributeTypeMap - Array of attribute metadata including required flag + * @returns true if all required attributes are present in data, false otherwise + */ +export function instanceOfType(data: any, attributeTypeMap: Array): boolean { + for (const attribute of attributeTypeMap) { + if (attribute.required && data[attribute.baseName] === undefined) { + return false; + } + } + + return true; +} + +/** + * Attempts to find a matching type from an array of possible types by validating + * the data against each type's attribute requirements. + * + * @param data - The data object to match + * @param types - Array of possible type constructors + * @returns The name of the matching type, or undefined if no match found + */ +export function findMatchingType(data: any, types: Array): string | undefined { + for (const type of types) { + if (instanceOfType(data, type.getAttributeTypeMap())) { + return type.name; + } + } + + return undefined; +} \ No newline at end of file diff --git a/samples/client/others/typescript/builds/enum-single-value/models/all.ts b/samples/client/others/typescript/builds/enum-single-value/models/all.ts index dc9e55201d87..d529183a1325 100644 --- a/samples/client/others/typescript/builds/enum-single-value/models/all.ts +++ b/samples/client/others/typescript/builds/enum-single-value/models/all.ts @@ -1,2 +1,4 @@ export * from '../models/SingleValueEnum30' export * from '../models/SingleValueEnum31' +export * from './TypeMatcher' +export * from './ModelTypes' \ No newline at end of file diff --git a/samples/client/others/typescript/builds/null-types-simple/.openapi-generator/FILES b/samples/client/others/typescript/builds/null-types-simple/.openapi-generator/FILES index f586694f5f67..94f2efa32895 100644 --- a/samples/client/others/typescript/builds/null-types-simple/.openapi-generator/FILES +++ b/samples/client/others/typescript/builds/null-types-simple/.openapi-generator/FILES @@ -10,8 +10,10 @@ http/http.ts http/isomorphic-fetch.ts index.ts middleware.ts +models/ModelTypes.ts models/ObjectSerializer.ts models/SomeObject.ts +models/TypeMatcher.ts models/WithNullableType.ts models/all.ts package.json diff --git a/samples/client/others/typescript/builds/null-types-simple/models/ModelTypes.ts b/samples/client/others/typescript/builds/null-types-simple/models/ModelTypes.ts new file mode 100644 index 000000000000..24a680aba301 --- /dev/null +++ b/samples/client/others/typescript/builds/null-types-simple/models/ModelTypes.ts @@ -0,0 +1,11 @@ +/** + * Represents a single attribute/property metadata entry in the attributeTypeMap. + * Used for validation and type matching in oneOf scenarios. + */ +export type AttributeTypeMapEntry = { + name: string; + baseName: string; + type: string; + format: string; + required: boolean; +}; diff --git a/samples/client/others/typescript/builds/null-types-simple/models/ObjectSerializer.ts b/samples/client/others/typescript/builds/null-types-simple/models/ObjectSerializer.ts index 7cde51dbea02..10debfb2c5af 100644 --- a/samples/client/others/typescript/builds/null-types-simple/models/ObjectSerializer.ts +++ b/samples/client/others/typescript/builds/null-types-simple/models/ObjectSerializer.ts @@ -102,26 +102,37 @@ export class ObjectSerializer { // Check the discriminator let discriminatorProperty = typeMap[expectedType].discriminator; - if (discriminatorProperty == null) { - return expectedType; // the type does not have a discriminator. use it. - } else { - if (data[discriminatorProperty]) { - var discriminatorType = data[discriminatorProperty]; - let mapping = typeMap[expectedType].mapping; - if (mapping != undefined && mapping[discriminatorType]) { - return mapping[discriminatorType]; // use the type given in the discriminator - } else if(typeMap[discriminatorType]) { - return discriminatorType; - } else { - return expectedType; // discriminator did not map to a type + if (discriminatorProperty == null || !data[discriminatorProperty]) { + if (this.hasFindMatchingTypeMethod(typeMap[expectedType])) { + const foundType = typeMap[expectedType].findMatchingType(data); + if (foundType == undefined) { + throw new Error("Unable to determine a unique type for the provided object: oneOf type resolution failed. The object does not match exactly one schema. Consider adding a discriminator or making schemas mutually exclusive."); } + + return foundType; + } + return expectedType; // the type does not have a discriminator and findMatchingType method. use it. + } else { + let discriminatorType = data[discriminatorProperty]; + let mapping = typeMap[expectedType].mapping; + if (mapping != undefined && mapping[discriminatorType]) { + return mapping[discriminatorType]; // use the type given in the discriminator + } else if(typeMap[discriminatorType]) { + return discriminatorType; } else { - return expectedType; // discriminator was not present (or an empty string) + throw new Error(`Discriminator property '${discriminatorProperty}' has value '${discriminatorType}' which does not map to any known type in '${expectedType}'.`); } } } } + private static hasFindMatchingTypeMethod(klass: any): boolean { + if (typeof klass.findMatchingType === 'function') { + return true; + } + return false; + } + public static serialize(data: any, type: string, format: string): any { if (data == undefined) { return data; diff --git a/samples/client/others/typescript/builds/null-types-simple/models/SomeObject.ts b/samples/client/others/typescript/builds/null-types-simple/models/SomeObject.ts index af82708430ec..379950f444c7 100644 --- a/samples/client/others/typescript/builds/null-types-simple/models/SomeObject.ts +++ b/samples/client/others/typescript/builds/null-types-simple/models/SomeObject.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class SomeObject { @@ -19,12 +20,13 @@ export class SomeObject { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "data", "baseName": "data", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/client/others/typescript/builds/null-types-simple/models/TypeMatcher.ts b/samples/client/others/typescript/builds/null-types-simple/models/TypeMatcher.ts new file mode 100644 index 000000000000..2f1c20864a70 --- /dev/null +++ b/samples/client/others/typescript/builds/null-types-simple/models/TypeMatcher.ts @@ -0,0 +1,36 @@ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; + +/** + * Validates if data contains all required attributes from the attributeTypeMap. + * + * @param data - The data object to validate + * @param attributeTypeMap - Array of attribute metadata including required flag + * @returns true if all required attributes are present in data, false otherwise + */ +export function instanceOfType(data: any, attributeTypeMap: Array): boolean { + for (const attribute of attributeTypeMap) { + if (attribute.required && data[attribute.baseName] === undefined) { + return false; + } + } + + return true; +} + +/** + * Attempts to find a matching type from an array of possible types by validating + * the data against each type's attribute requirements. + * + * @param data - The data object to match + * @param types - Array of possible type constructors + * @returns The name of the matching type, or undefined if no match found + */ +export function findMatchingType(data: any, types: Array): string | undefined { + for (const type of types) { + if (instanceOfType(data, type.getAttributeTypeMap())) { + return type.name; + } + } + + return undefined; +} \ No newline at end of file diff --git a/samples/client/others/typescript/builds/null-types-simple/models/WithNullableType.ts b/samples/client/others/typescript/builds/null-types-simple/models/WithNullableType.ts index d29b7cc1767f..aa33c2d24713 100644 --- a/samples/client/others/typescript/builds/null-types-simple/models/WithNullableType.ts +++ b/samples/client/others/typescript/builds/null-types-simple/models/WithNullableType.ts @@ -11,6 +11,7 @@ */ import { SomeObject } from '../models/SomeObject'; +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class WithNullableType { @@ -22,24 +23,27 @@ export class WithNullableType { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "arrayDataOrNull", "baseName": "arrayDataOrNull", "type": "Array", - "format": "" + "format": "", + "required": true }, { "name": "stringDataOrNull", "baseName": "stringDataOrNull", "type": "string", - "format": "" + "format": "", + "required": true }, { "name": "oneofOrNull", "baseName": "oneofOrNull", "type": "SomeObject", - "format": "" + "format": "", + "required": true } ]; static getAttributeTypeMap() { diff --git a/samples/client/others/typescript/builds/null-types-simple/models/all.ts b/samples/client/others/typescript/builds/null-types-simple/models/all.ts index ed435990d1a4..483dc848534d 100644 --- a/samples/client/others/typescript/builds/null-types-simple/models/all.ts +++ b/samples/client/others/typescript/builds/null-types-simple/models/all.ts @@ -1,2 +1,4 @@ export * from '../models/SomeObject' export * from '../models/WithNullableType' +export * from './TypeMatcher' +export * from './ModelTypes' \ No newline at end of file diff --git a/samples/client/others/typescript/builds/with-unique-items/.openapi-generator/FILES b/samples/client/others/typescript/builds/with-unique-items/.openapi-generator/FILES index e770a65f9adc..967532c08b50 100644 --- a/samples/client/others/typescript/builds/with-unique-items/.openapi-generator/FILES +++ b/samples/client/others/typescript/builds/with-unique-items/.openapi-generator/FILES @@ -12,8 +12,10 @@ http/http.ts http/isomorphic-fetch.ts index.ts middleware.ts +models/ModelTypes.ts models/ObjectSerializer.ts models/Response.ts +models/TypeMatcher.ts models/all.ts package.json rxjsStub.ts diff --git a/samples/client/others/typescript/builds/with-unique-items/models/ModelTypes.ts b/samples/client/others/typescript/builds/with-unique-items/models/ModelTypes.ts new file mode 100644 index 000000000000..24a680aba301 --- /dev/null +++ b/samples/client/others/typescript/builds/with-unique-items/models/ModelTypes.ts @@ -0,0 +1,11 @@ +/** + * Represents a single attribute/property metadata entry in the attributeTypeMap. + * Used for validation and type matching in oneOf scenarios. + */ +export type AttributeTypeMapEntry = { + name: string; + baseName: string; + type: string; + format: string; + required: boolean; +}; diff --git a/samples/client/others/typescript/builds/with-unique-items/models/ObjectSerializer.ts b/samples/client/others/typescript/builds/with-unique-items/models/ObjectSerializer.ts index 1318620d22e9..3ff411a2428f 100644 --- a/samples/client/others/typescript/builds/with-unique-items/models/ObjectSerializer.ts +++ b/samples/client/others/typescript/builds/with-unique-items/models/ObjectSerializer.ts @@ -99,26 +99,37 @@ export class ObjectSerializer { // Check the discriminator let discriminatorProperty = typeMap[expectedType].discriminator; - if (discriminatorProperty == null) { - return expectedType; // the type does not have a discriminator. use it. - } else { - if (data[discriminatorProperty]) { - var discriminatorType = data[discriminatorProperty]; - let mapping = typeMap[expectedType].mapping; - if (mapping != undefined && mapping[discriminatorType]) { - return mapping[discriminatorType]; // use the type given in the discriminator - } else if(typeMap[discriminatorType]) { - return discriminatorType; - } else { - return expectedType; // discriminator did not map to a type + if (discriminatorProperty == null || !data[discriminatorProperty]) { + if (this.hasFindMatchingTypeMethod(typeMap[expectedType])) { + const foundType = typeMap[expectedType].findMatchingType(data); + if (foundType == undefined) { + throw new Error("Unable to determine a unique type for the provided object: oneOf type resolution failed. The object does not match exactly one schema. Consider adding a discriminator or making schemas mutually exclusive."); } + + return foundType; + } + return expectedType; // the type does not have a discriminator and findMatchingType method. use it. + } else { + let discriminatorType = data[discriminatorProperty]; + let mapping = typeMap[expectedType].mapping; + if (mapping != undefined && mapping[discriminatorType]) { + return mapping[discriminatorType]; // use the type given in the discriminator + } else if(typeMap[discriminatorType]) { + return discriminatorType; } else { - return expectedType; // discriminator was not present (or an empty string) + throw new Error(`Discriminator property '${discriminatorProperty}' has value '${discriminatorType}' which does not map to any known type in '${expectedType}'.`); } } } } + private static hasFindMatchingTypeMethod(klass: any): boolean { + if (typeof klass.findMatchingType === 'function') { + return true; + } + return false; + } + public static serialize(data: any, type: string, format: string): any { if (data == undefined) { return data; diff --git a/samples/client/others/typescript/builds/with-unique-items/models/Response.ts b/samples/client/others/typescript/builds/with-unique-items/models/Response.ts index 9ba6412f2445..e2b8f9e711f8 100644 --- a/samples/client/others/typescript/builds/with-unique-items/models/Response.ts +++ b/samples/client/others/typescript/builds/with-unique-items/models/Response.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class Response { @@ -20,18 +21,20 @@ export class Response { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "nonUniqueArray", "baseName": "non-unique-array", "type": "Array", - "format": "" + "format": "", + "required": false }, { "name": "uniqueArray", "baseName": "unique-array", "type": "Set", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/client/others/typescript/builds/with-unique-items/models/TypeMatcher.ts b/samples/client/others/typescript/builds/with-unique-items/models/TypeMatcher.ts new file mode 100644 index 000000000000..2f1c20864a70 --- /dev/null +++ b/samples/client/others/typescript/builds/with-unique-items/models/TypeMatcher.ts @@ -0,0 +1,36 @@ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; + +/** + * Validates if data contains all required attributes from the attributeTypeMap. + * + * @param data - The data object to validate + * @param attributeTypeMap - Array of attribute metadata including required flag + * @returns true if all required attributes are present in data, false otherwise + */ +export function instanceOfType(data: any, attributeTypeMap: Array): boolean { + for (const attribute of attributeTypeMap) { + if (attribute.required && data[attribute.baseName] === undefined) { + return false; + } + } + + return true; +} + +/** + * Attempts to find a matching type from an array of possible types by validating + * the data against each type's attribute requirements. + * + * @param data - The data object to match + * @param types - Array of possible type constructors + * @returns The name of the matching type, or undefined if no match found + */ +export function findMatchingType(data: any, types: Array): string | undefined { + for (const type of types) { + if (instanceOfType(data, type.getAttributeTypeMap())) { + return type.name; + } + } + + return undefined; +} \ No newline at end of file diff --git a/samples/client/others/typescript/builds/with-unique-items/models/all.ts b/samples/client/others/typescript/builds/with-unique-items/models/all.ts index fb6a6246f9a8..9a0dc8a32bc5 100644 --- a/samples/client/others/typescript/builds/with-unique-items/models/all.ts +++ b/samples/client/others/typescript/builds/with-unique-items/models/all.ts @@ -1 +1,3 @@ export * from '../models/Response' +export * from './TypeMatcher' +export * from './ModelTypes' \ No newline at end of file diff --git a/samples/client/others/typescript/encode-decode/build/.openapi-generator/FILES b/samples/client/others/typescript/encode-decode/build/.openapi-generator/FILES index b8c07c76c070..8da69f74835b 100644 --- a/samples/client/others/typescript/encode-decode/build/.openapi-generator/FILES +++ b/samples/client/others/typescript/encode-decode/build/.openapi-generator/FILES @@ -14,7 +14,9 @@ index.ts middleware.ts models/ComplexObject.ts models/CompositeObject.ts +models/ModelTypes.ts models/ObjectSerializer.ts +models/TypeMatcher.ts models/all.ts package.json rxjsStub.ts diff --git a/samples/client/others/typescript/encode-decode/build/models/ComplexObject.ts b/samples/client/others/typescript/encode-decode/build/models/ComplexObject.ts index f828c97ab7c5..3555e1d46838 100644 --- a/samples/client/others/typescript/encode-decode/build/models/ComplexObject.ts +++ b/samples/client/others/typescript/encode-decode/build/models/ComplexObject.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class ComplexObject { @@ -22,30 +23,34 @@ export class ComplexObject { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "requiredProperty", "baseName": "required_property", "type": "string", - "format": "" + "format": "", + "required": true }, { "name": "requiredNullableProperty", "baseName": "required_nullable_property", "type": "string", - "format": "" + "format": "", + "required": true }, { "name": "optionalProperty", "baseName": "optional_property", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "optionalNullableProperty", "baseName": "optional_nullable_property", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/client/others/typescript/encode-decode/build/models/CompositeObject.ts b/samples/client/others/typescript/encode-decode/build/models/CompositeObject.ts index 18aca6114d67..0db95a7eb08c 100644 --- a/samples/client/others/typescript/encode-decode/build/models/CompositeObject.ts +++ b/samples/client/others/typescript/encode-decode/build/models/CompositeObject.ts @@ -11,6 +11,7 @@ */ import { ComplexObject } from '../models/ComplexObject'; +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class CompositeObject { @@ -20,12 +21,13 @@ export class CompositeObject { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "optionalNullableInnerObject", "baseName": "optional_nullable_inner_object", "type": "ComplexObject", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/client/others/typescript/encode-decode/build/models/ModelTypes.ts b/samples/client/others/typescript/encode-decode/build/models/ModelTypes.ts new file mode 100644 index 000000000000..24a680aba301 --- /dev/null +++ b/samples/client/others/typescript/encode-decode/build/models/ModelTypes.ts @@ -0,0 +1,11 @@ +/** + * Represents a single attribute/property metadata entry in the attributeTypeMap. + * Used for validation and type matching in oneOf scenarios. + */ +export type AttributeTypeMapEntry = { + name: string; + baseName: string; + type: string; + format: string; + required: boolean; +}; diff --git a/samples/client/others/typescript/encode-decode/build/models/ObjectSerializer.ts b/samples/client/others/typescript/encode-decode/build/models/ObjectSerializer.ts index a907494c3961..b92e43e2f787 100644 --- a/samples/client/others/typescript/encode-decode/build/models/ObjectSerializer.ts +++ b/samples/client/others/typescript/encode-decode/build/models/ObjectSerializer.ts @@ -102,26 +102,37 @@ export class ObjectSerializer { // Check the discriminator let discriminatorProperty = typeMap[expectedType].discriminator; - if (discriminatorProperty == null) { - return expectedType; // the type does not have a discriminator. use it. - } else { - if (data[discriminatorProperty]) { - var discriminatorType = data[discriminatorProperty]; - let mapping = typeMap[expectedType].mapping; - if (mapping != undefined && mapping[discriminatorType]) { - return mapping[discriminatorType]; // use the type given in the discriminator - } else if(typeMap[discriminatorType]) { - return discriminatorType; - } else { - return expectedType; // discriminator did not map to a type + if (discriminatorProperty == null || !data[discriminatorProperty]) { + if (this.hasFindMatchingTypeMethod(typeMap[expectedType])) { + const foundType = typeMap[expectedType].findMatchingType(data); + if (foundType == undefined) { + throw new Error("Unable to determine a unique type for the provided object: oneOf type resolution failed. The object does not match exactly one schema. Consider adding a discriminator or making schemas mutually exclusive."); } + + return foundType; + } + return expectedType; // the type does not have a discriminator and findMatchingType method. use it. + } else { + let discriminatorType = data[discriminatorProperty]; + let mapping = typeMap[expectedType].mapping; + if (mapping != undefined && mapping[discriminatorType]) { + return mapping[discriminatorType]; // use the type given in the discriminator + } else if(typeMap[discriminatorType]) { + return discriminatorType; } else { - return expectedType; // discriminator was not present (or an empty string) + throw new Error(`Discriminator property '${discriminatorProperty}' has value '${discriminatorType}' which does not map to any known type in '${expectedType}'.`); } } } } + private static hasFindMatchingTypeMethod(klass: any): boolean { + if (typeof klass.findMatchingType === 'function') { + return true; + } + return false; + } + public static serialize(data: any, type: string, format: string): any { if (data == undefined) { return data; diff --git a/samples/client/others/typescript/encode-decode/build/models/TypeMatcher.ts b/samples/client/others/typescript/encode-decode/build/models/TypeMatcher.ts new file mode 100644 index 000000000000..2f1c20864a70 --- /dev/null +++ b/samples/client/others/typescript/encode-decode/build/models/TypeMatcher.ts @@ -0,0 +1,36 @@ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; + +/** + * Validates if data contains all required attributes from the attributeTypeMap. + * + * @param data - The data object to validate + * @param attributeTypeMap - Array of attribute metadata including required flag + * @returns true if all required attributes are present in data, false otherwise + */ +export function instanceOfType(data: any, attributeTypeMap: Array): boolean { + for (const attribute of attributeTypeMap) { + if (attribute.required && data[attribute.baseName] === undefined) { + return false; + } + } + + return true; +} + +/** + * Attempts to find a matching type from an array of possible types by validating + * the data against each type's attribute requirements. + * + * @param data - The data object to match + * @param types - Array of possible type constructors + * @returns The name of the matching type, or undefined if no match found + */ +export function findMatchingType(data: any, types: Array): string | undefined { + for (const type of types) { + if (instanceOfType(data, type.getAttributeTypeMap())) { + return type.name; + } + } + + return undefined; +} \ No newline at end of file diff --git a/samples/client/others/typescript/encode-decode/build/models/all.ts b/samples/client/others/typescript/encode-decode/build/models/all.ts index bcc447e6f4bf..1bed544a47ec 100644 --- a/samples/client/others/typescript/encode-decode/build/models/all.ts +++ b/samples/client/others/typescript/encode-decode/build/models/all.ts @@ -1,2 +1,4 @@ export * from '../models/ComplexObject' export * from '../models/CompositeObject' +export * from './TypeMatcher' +export * from './ModelTypes' \ No newline at end of file diff --git a/samples/openapi3/client/petstore/typescript/builds/browser/.openapi-generator/FILES b/samples/openapi3/client/petstore/typescript/builds/browser/.openapi-generator/FILES index 125c3a493a13..0207ab042492 100644 --- a/samples/openapi3/client/petstore/typescript/builds/browser/.openapi-generator/FILES +++ b/samples/openapi3/client/petstore/typescript/builds/browser/.openapi-generator/FILES @@ -18,10 +18,12 @@ index.ts middleware.ts models/ApiResponse.ts models/Category.ts +models/ModelTypes.ts models/ObjectSerializer.ts models/Order.ts models/Pet.ts models/Tag.ts +models/TypeMatcher.ts models/User.ts models/all.ts package.json diff --git a/samples/openapi3/client/petstore/typescript/builds/browser/models/ApiResponse.ts b/samples/openapi3/client/petstore/typescript/builds/browser/models/ApiResponse.ts index 3dd68507b210..ddfa26277fe4 100644 --- a/samples/openapi3/client/petstore/typescript/builds/browser/models/ApiResponse.ts +++ b/samples/openapi3/client/petstore/typescript/builds/browser/models/ApiResponse.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -24,24 +25,27 @@ export class ApiResponse { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "code", "baseName": "code", "type": "number", - "format": "int32" + "format": "int32", + "required": false }, { "name": "type", "baseName": "type", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "message", "baseName": "message", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/browser/models/Category.ts b/samples/openapi3/client/petstore/typescript/builds/browser/models/Category.ts index e025011174d3..ce325ffc3a2d 100644 --- a/samples/openapi3/client/petstore/typescript/builds/browser/models/Category.ts +++ b/samples/openapi3/client/petstore/typescript/builds/browser/models/Category.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -23,18 +24,20 @@ export class Category { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "name", "baseName": "name", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/browser/models/ModelTypes.ts b/samples/openapi3/client/petstore/typescript/builds/browser/models/ModelTypes.ts new file mode 100644 index 000000000000..24a680aba301 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/browser/models/ModelTypes.ts @@ -0,0 +1,11 @@ +/** + * Represents a single attribute/property metadata entry in the attributeTypeMap. + * Used for validation and type matching in oneOf scenarios. + */ +export type AttributeTypeMapEntry = { + name: string; + baseName: string; + type: string; + format: string; + required: boolean; +}; diff --git a/samples/openapi3/client/petstore/typescript/builds/browser/models/ObjectSerializer.ts b/samples/openapi3/client/petstore/typescript/builds/browser/models/ObjectSerializer.ts index fe462a298a3a..a8ba5820cc68 100644 --- a/samples/openapi3/client/petstore/typescript/builds/browser/models/ObjectSerializer.ts +++ b/samples/openapi3/client/petstore/typescript/builds/browser/models/ObjectSerializer.ts @@ -116,26 +116,37 @@ export class ObjectSerializer { // Check the discriminator let discriminatorProperty = typeMap[expectedType].discriminator; - if (discriminatorProperty == null) { - return expectedType; // the type does not have a discriminator. use it. - } else { - if (data[discriminatorProperty]) { - var discriminatorType = data[discriminatorProperty]; - let mapping = typeMap[expectedType].mapping; - if (mapping != undefined && mapping[discriminatorType]) { - return mapping[discriminatorType]; // use the type given in the discriminator - } else if(typeMap[discriminatorType]) { - return discriminatorType; - } else { - return expectedType; // discriminator did not map to a type + if (discriminatorProperty == null || !data[discriminatorProperty]) { + if (this.hasFindMatchingTypeMethod(typeMap[expectedType])) { + const foundType = typeMap[expectedType].findMatchingType(data); + if (foundType == undefined) { + throw new Error("Unable to determine a unique type for the provided object: oneOf type resolution failed. The object does not match exactly one schema. Consider adding a discriminator or making schemas mutually exclusive."); } + + return foundType; + } + return expectedType; // the type does not have a discriminator and findMatchingType method. use it. + } else { + let discriminatorType = data[discriminatorProperty]; + let mapping = typeMap[expectedType].mapping; + if (mapping != undefined && mapping[discriminatorType]) { + return mapping[discriminatorType]; // use the type given in the discriminator + } else if(typeMap[discriminatorType]) { + return discriminatorType; } else { - return expectedType; // discriminator was not present (or an empty string) + throw new Error(`Discriminator property '${discriminatorProperty}' has value '${discriminatorType}' which does not map to any known type in '${expectedType}'.`); } } } } + private static hasFindMatchingTypeMethod(klass: any): boolean { + if (typeof klass.findMatchingType === 'function') { + return true; + } + return false; + } + public static serialize(data: any, type: string, format: string): any { if (data == undefined) { return data; diff --git a/samples/openapi3/client/petstore/typescript/builds/browser/models/OneOfClass.ts b/samples/openapi3/client/petstore/typescript/builds/browser/models/OneOfClass.ts new file mode 100644 index 000000000000..5653fe3ef8d7 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/browser/models/OneOfClass.ts @@ -0,0 +1,13 @@ +export class OneOfClass { + public static instanceOf(data: any, attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string, required: boolean}>): boolean { + for (const attribute of attributeTypeMap) { + if (attribute.required) { + if (!(attribute.baseName in data) || data[attribute.baseName] === undefined) { + return false; + } + } + } + + return true; + } +} \ No newline at end of file diff --git a/samples/openapi3/client/petstore/typescript/builds/browser/models/Order.ts b/samples/openapi3/client/petstore/typescript/builds/browser/models/Order.ts index b8d4a26c7d47..4707dcaa7d1e 100644 --- a/samples/openapi3/client/petstore/typescript/builds/browser/models/Order.ts +++ b/samples/openapi3/client/petstore/typescript/builds/browser/models/Order.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -30,42 +31,48 @@ export class Order { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "petId", "baseName": "petId", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "quantity", "baseName": "quantity", "type": "number", - "format": "int32" + "format": "int32", + "required": false }, { "name": "shipDate", "baseName": "shipDate", "type": "Date", - "format": "date-time" + "format": "date-time", + "required": false }, { "name": "status", "baseName": "status", "type": "OrderStatusEnum", - "format": "" + "format": "", + "required": false }, { "name": "complete", "baseName": "complete", "type": "boolean", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/browser/models/Pet.ts b/samples/openapi3/client/petstore/typescript/builds/browser/models/Pet.ts index ddb68aa82a19..4b7c3b929646 100644 --- a/samples/openapi3/client/petstore/typescript/builds/browser/models/Pet.ts +++ b/samples/openapi3/client/petstore/typescript/builds/browser/models/Pet.ts @@ -12,6 +12,7 @@ import { Category } from '../models/Category'; import { Tag } from '../models/Tag'; +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -32,42 +33,48 @@ export class Pet { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "category", "baseName": "category", "type": "Category", - "format": "" + "format": "", + "required": false }, { "name": "name", "baseName": "name", "type": "string", - "format": "" + "format": "", + "required": true }, { "name": "photoUrls", "baseName": "photoUrls", "type": "Array", - "format": "" + "format": "", + "required": true }, { "name": "tags", "baseName": "tags", "type": "Array", - "format": "" + "format": "", + "required": false }, { "name": "status", "baseName": "status", "type": "PetStatusEnum", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/browser/models/Tag.ts b/samples/openapi3/client/petstore/typescript/builds/browser/models/Tag.ts index 7a7a36ba59aa..fdb52c40ddda 100644 --- a/samples/openapi3/client/petstore/typescript/builds/browser/models/Tag.ts +++ b/samples/openapi3/client/petstore/typescript/builds/browser/models/Tag.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -23,18 +24,20 @@ export class Tag { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "name", "baseName": "name", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/browser/models/TypeMatcher.ts b/samples/openapi3/client/petstore/typescript/builds/browser/models/TypeMatcher.ts new file mode 100644 index 000000000000..2f1c20864a70 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/browser/models/TypeMatcher.ts @@ -0,0 +1,36 @@ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; + +/** + * Validates if data contains all required attributes from the attributeTypeMap. + * + * @param data - The data object to validate + * @param attributeTypeMap - Array of attribute metadata including required flag + * @returns true if all required attributes are present in data, false otherwise + */ +export function instanceOfType(data: any, attributeTypeMap: Array): boolean { + for (const attribute of attributeTypeMap) { + if (attribute.required && data[attribute.baseName] === undefined) { + return false; + } + } + + return true; +} + +/** + * Attempts to find a matching type from an array of possible types by validating + * the data against each type's attribute requirements. + * + * @param data - The data object to match + * @param types - Array of possible type constructors + * @returns The name of the matching type, or undefined if no match found + */ +export function findMatchingType(data: any, types: Array): string | undefined { + for (const type of types) { + if (instanceOfType(data, type.getAttributeTypeMap())) { + return type.name; + } + } + + return undefined; +} \ No newline at end of file diff --git a/samples/openapi3/client/petstore/typescript/builds/browser/models/User.ts b/samples/openapi3/client/petstore/typescript/builds/browser/models/User.ts index 4dbe18f7fed4..a8338193852e 100644 --- a/samples/openapi3/client/petstore/typescript/builds/browser/models/User.ts +++ b/samples/openapi3/client/petstore/typescript/builds/browser/models/User.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -32,54 +33,62 @@ export class User { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "username", "baseName": "username", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "firstName", "baseName": "firstName", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "lastName", "baseName": "lastName", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "email", "baseName": "email", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "password", "baseName": "password", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "phone", "baseName": "phone", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "userStatus", "baseName": "userStatus", "type": "number", - "format": "int32" + "format": "int32", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/browser/models/all.ts b/samples/openapi3/client/petstore/typescript/builds/browser/models/all.ts index d63b43c96744..101927e7b61e 100644 --- a/samples/openapi3/client/petstore/typescript/builds/browser/models/all.ts +++ b/samples/openapi3/client/petstore/typescript/builds/browser/models/all.ts @@ -4,3 +4,5 @@ export * from '../models/Order' export * from '../models/Pet' export * from '../models/Tag' export * from '../models/User' +export * from './TypeMatcher' +export * from './ModelTypes' \ No newline at end of file diff --git a/samples/openapi3/client/petstore/typescript/builds/composed-schemas/.openapi-generator/FILES b/samples/openapi3/client/petstore/typescript/builds/composed-schemas/.openapi-generator/FILES index 9648ceadb6e4..a025fbe36856 100644 --- a/samples/openapi3/client/petstore/typescript/builds/composed-schemas/.openapi-generator/FILES +++ b/samples/openapi3/client/petstore/typescript/builds/composed-schemas/.openapi-generator/FILES @@ -15,11 +15,13 @@ middleware.ts models/Cat.ts models/Dog.ts models/FilePostRequest.ts +models/ModelTypes.ts models/ObjectSerializer.ts models/PetByAge.ts models/PetByType.ts models/PetsFilteredPatchRequest.ts models/PetsPatchRequest.ts +models/TypeMatcher.ts models/all.ts package.json rxjsStub.ts diff --git a/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/Cat.ts b/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/Cat.ts index 7812787becba..7cc59594ea25 100644 --- a/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/Cat.ts +++ b/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/Cat.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class Cat { @@ -20,18 +21,20 @@ export class Cat { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "hunts", "baseName": "hunts", "type": "boolean", - "format": "" + "format": "", + "required": false }, { "name": "age", "baseName": "age", "type": "number", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/Dog.ts b/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/Dog.ts index 8fc32b4bc122..2f318b01af12 100644 --- a/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/Dog.ts +++ b/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/Dog.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -23,18 +24,20 @@ export class Dog { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "bark", "baseName": "bark", "type": "boolean", - "format": "" + "format": "", + "required": false }, { "name": "breed", "baseName": "breed", "type": "DogBreedEnum", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/FilePostRequest.ts b/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/FilePostRequest.ts index 5a51233579e6..f8777b97e86c 100644 --- a/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/FilePostRequest.ts +++ b/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/FilePostRequest.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class FilePostRequest { @@ -19,12 +20,13 @@ export class FilePostRequest { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "file", "baseName": "file", "type": "any", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/ModelTypes.ts b/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/ModelTypes.ts new file mode 100644 index 000000000000..24a680aba301 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/ModelTypes.ts @@ -0,0 +1,11 @@ +/** + * Represents a single attribute/property metadata entry in the attributeTypeMap. + * Used for validation and type matching in oneOf scenarios. + */ +export type AttributeTypeMapEntry = { + name: string; + baseName: string; + type: string; + format: string; + required: boolean; +}; diff --git a/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/ObjectSerializer.ts b/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/ObjectSerializer.ts index 46d1a1994ba7..5129070f9232 100644 --- a/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/ObjectSerializer.ts +++ b/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/ObjectSerializer.ts @@ -121,26 +121,37 @@ export class ObjectSerializer { // Check the discriminator let discriminatorProperty = typeMap[expectedType].discriminator; - if (discriminatorProperty == null) { - return expectedType; // the type does not have a discriminator. use it. - } else { - if (data[discriminatorProperty]) { - var discriminatorType = data[discriminatorProperty]; - let mapping = typeMap[expectedType].mapping; - if (mapping != undefined && mapping[discriminatorType]) { - return mapping[discriminatorType]; // use the type given in the discriminator - } else if(typeMap[discriminatorType]) { - return discriminatorType; - } else { - return expectedType; // discriminator did not map to a type + if (discriminatorProperty == null || !data[discriminatorProperty]) { + if (this.hasFindMatchingTypeMethod(typeMap[expectedType])) { + const foundType = typeMap[expectedType].findMatchingType(data); + if (foundType == undefined) { + throw new Error("Unable to determine a unique type for the provided object: oneOf type resolution failed. The object does not match exactly one schema. Consider adding a discriminator or making schemas mutually exclusive."); } + + return foundType; + } + return expectedType; // the type does not have a discriminator and findMatchingType method. use it. + } else { + let discriminatorType = data[discriminatorProperty]; + let mapping = typeMap[expectedType].mapping; + if (mapping != undefined && mapping[discriminatorType]) { + return mapping[discriminatorType]; // use the type given in the discriminator + } else if(typeMap[discriminatorType]) { + return discriminatorType; } else { - return expectedType; // discriminator was not present (or an empty string) + throw new Error(`Discriminator property '${discriminatorProperty}' has value '${discriminatorType}' which does not map to any known type in '${expectedType}'.`); } } } } + private static hasFindMatchingTypeMethod(klass: any): boolean { + if (typeof klass.findMatchingType === 'function') { + return true; + } + return false; + } + public static serialize(data: any, type: string, format: string): any { if (data == undefined) { return data; diff --git a/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/PetByAge.ts b/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/PetByAge.ts index 5ddcb270eb2a..3e07c88324bb 100644 --- a/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/PetByAge.ts +++ b/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/PetByAge.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class PetByAge { @@ -20,18 +21,20 @@ export class PetByAge { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "age", "baseName": "age", "type": "number", - "format": "" + "format": "", + "required": true }, { "name": "nickname", "baseName": "nickname", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/PetByType.ts b/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/PetByType.ts index 60d1fd207e2d..f35e773a2bf8 100644 --- a/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/PetByType.ts +++ b/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/PetByType.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class PetByType { @@ -20,18 +21,20 @@ export class PetByType { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "petType", "baseName": "pet_type", "type": "PetByTypePetTypeEnum", - "format": "" + "format": "", + "required": true }, { "name": "hunts", "baseName": "hunts", "type": "boolean", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/PetsFilteredPatchRequest.ts b/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/PetsFilteredPatchRequest.ts index 067783a53328..8179b47cec58 100644 --- a/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/PetsFilteredPatchRequest.ts +++ b/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/PetsFilteredPatchRequest.ts @@ -12,6 +12,7 @@ import { PetByAge } from '../models/PetByAge'; import { PetByType } from '../models/PetByType'; +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class PetsFilteredPatchRequest { @@ -24,30 +25,34 @@ export class PetsFilteredPatchRequest { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "age", "baseName": "age", "type": "number", - "format": "" + "format": "", + "required": true }, { "name": "nickname", "baseName": "nickname", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "petType", "baseName": "pet_type", "type": "PetsFilteredPatchRequestPetTypeEnum", - "format": "" + "format": "", + "required": true }, { "name": "hunts", "baseName": "hunts", "type": "boolean", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/PetsPatchRequest.ts b/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/PetsPatchRequest.ts index 26d1ecd4445e..aa070f0052ac 100644 --- a/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/PetsPatchRequest.ts +++ b/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/PetsPatchRequest.ts @@ -12,7 +12,7 @@ import { Cat } from '../models/Cat'; import { Dog } from '../models/Dog'; -import { HttpFile } from '../http/http'; +import { findMatchingType } from '../models/TypeMatcher'; /** * @type PetsPatchRequest @@ -29,6 +29,18 @@ export class PetsPatchRequestClass { static readonly discriminator: string | undefined = "petType"; static readonly mapping: {[index: string]: string} | undefined = undefined; + + private static readonly arrayOfTypes: Array = [Cat, Dog]; + + /** + * Determines which oneOf schema matches the provided data. + * + * @param data - The data object to match against oneOf schemas + * @returns The name of the matching type, or undefined if no unique match is found + */ + public static findMatchingType(data: any): string | undefined { + return findMatchingType(data, this.arrayOfTypes); + } } diff --git a/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/TypeMatcher.ts b/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/TypeMatcher.ts new file mode 100644 index 000000000000..2f1c20864a70 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/TypeMatcher.ts @@ -0,0 +1,36 @@ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; + +/** + * Validates if data contains all required attributes from the attributeTypeMap. + * + * @param data - The data object to validate + * @param attributeTypeMap - Array of attribute metadata including required flag + * @returns true if all required attributes are present in data, false otherwise + */ +export function instanceOfType(data: any, attributeTypeMap: Array): boolean { + for (const attribute of attributeTypeMap) { + if (attribute.required && data[attribute.baseName] === undefined) { + return false; + } + } + + return true; +} + +/** + * Attempts to find a matching type from an array of possible types by validating + * the data against each type's attribute requirements. + * + * @param data - The data object to match + * @param types - Array of possible type constructors + * @returns The name of the matching type, or undefined if no match found + */ +export function findMatchingType(data: any, types: Array): string | undefined { + for (const type of types) { + if (instanceOfType(data, type.getAttributeTypeMap())) { + return type.name; + } + } + + return undefined; +} \ No newline at end of file diff --git a/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/all.ts b/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/all.ts index 195ee97a007b..87a1712a3d76 100644 --- a/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/all.ts +++ b/samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/all.ts @@ -5,3 +5,5 @@ export * from '../models/PetByAge' export * from '../models/PetByType' export * from '../models/PetsFilteredPatchRequest' export * from '../models/PetsPatchRequest' +export * from './TypeMatcher' +export * from './ModelTypes' \ No newline at end of file diff --git a/samples/openapi3/client/petstore/typescript/builds/default/.openapi-generator/FILES b/samples/openapi3/client/petstore/typescript/builds/default/.openapi-generator/FILES index 125c3a493a13..0207ab042492 100644 --- a/samples/openapi3/client/petstore/typescript/builds/default/.openapi-generator/FILES +++ b/samples/openapi3/client/petstore/typescript/builds/default/.openapi-generator/FILES @@ -18,10 +18,12 @@ index.ts middleware.ts models/ApiResponse.ts models/Category.ts +models/ModelTypes.ts models/ObjectSerializer.ts models/Order.ts models/Pet.ts models/Tag.ts +models/TypeMatcher.ts models/User.ts models/all.ts package.json diff --git a/samples/openapi3/client/petstore/typescript/builds/default/models/ApiResponse.ts b/samples/openapi3/client/petstore/typescript/builds/default/models/ApiResponse.ts index 3dd68507b210..ddfa26277fe4 100644 --- a/samples/openapi3/client/petstore/typescript/builds/default/models/ApiResponse.ts +++ b/samples/openapi3/client/petstore/typescript/builds/default/models/ApiResponse.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -24,24 +25,27 @@ export class ApiResponse { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "code", "baseName": "code", "type": "number", - "format": "int32" + "format": "int32", + "required": false }, { "name": "type", "baseName": "type", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "message", "baseName": "message", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/default/models/Category.ts b/samples/openapi3/client/petstore/typescript/builds/default/models/Category.ts index e025011174d3..ce325ffc3a2d 100644 --- a/samples/openapi3/client/petstore/typescript/builds/default/models/Category.ts +++ b/samples/openapi3/client/petstore/typescript/builds/default/models/Category.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -23,18 +24,20 @@ export class Category { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "name", "baseName": "name", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/default/models/ModelTypes.ts b/samples/openapi3/client/petstore/typescript/builds/default/models/ModelTypes.ts new file mode 100644 index 000000000000..24a680aba301 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/default/models/ModelTypes.ts @@ -0,0 +1,11 @@ +/** + * Represents a single attribute/property metadata entry in the attributeTypeMap. + * Used for validation and type matching in oneOf scenarios. + */ +export type AttributeTypeMapEntry = { + name: string; + baseName: string; + type: string; + format: string; + required: boolean; +}; diff --git a/samples/openapi3/client/petstore/typescript/builds/default/models/ObjectSerializer.ts b/samples/openapi3/client/petstore/typescript/builds/default/models/ObjectSerializer.ts index fe462a298a3a..a8ba5820cc68 100644 --- a/samples/openapi3/client/petstore/typescript/builds/default/models/ObjectSerializer.ts +++ b/samples/openapi3/client/petstore/typescript/builds/default/models/ObjectSerializer.ts @@ -116,26 +116,37 @@ export class ObjectSerializer { // Check the discriminator let discriminatorProperty = typeMap[expectedType].discriminator; - if (discriminatorProperty == null) { - return expectedType; // the type does not have a discriminator. use it. - } else { - if (data[discriminatorProperty]) { - var discriminatorType = data[discriminatorProperty]; - let mapping = typeMap[expectedType].mapping; - if (mapping != undefined && mapping[discriminatorType]) { - return mapping[discriminatorType]; // use the type given in the discriminator - } else if(typeMap[discriminatorType]) { - return discriminatorType; - } else { - return expectedType; // discriminator did not map to a type + if (discriminatorProperty == null || !data[discriminatorProperty]) { + if (this.hasFindMatchingTypeMethod(typeMap[expectedType])) { + const foundType = typeMap[expectedType].findMatchingType(data); + if (foundType == undefined) { + throw new Error("Unable to determine a unique type for the provided object: oneOf type resolution failed. The object does not match exactly one schema. Consider adding a discriminator or making schemas mutually exclusive."); } + + return foundType; + } + return expectedType; // the type does not have a discriminator and findMatchingType method. use it. + } else { + let discriminatorType = data[discriminatorProperty]; + let mapping = typeMap[expectedType].mapping; + if (mapping != undefined && mapping[discriminatorType]) { + return mapping[discriminatorType]; // use the type given in the discriminator + } else if(typeMap[discriminatorType]) { + return discriminatorType; } else { - return expectedType; // discriminator was not present (or an empty string) + throw new Error(`Discriminator property '${discriminatorProperty}' has value '${discriminatorType}' which does not map to any known type in '${expectedType}'.`); } } } } + private static hasFindMatchingTypeMethod(klass: any): boolean { + if (typeof klass.findMatchingType === 'function') { + return true; + } + return false; + } + public static serialize(data: any, type: string, format: string): any { if (data == undefined) { return data; diff --git a/samples/openapi3/client/petstore/typescript/builds/default/models/Order.ts b/samples/openapi3/client/petstore/typescript/builds/default/models/Order.ts index b8d4a26c7d47..4707dcaa7d1e 100644 --- a/samples/openapi3/client/petstore/typescript/builds/default/models/Order.ts +++ b/samples/openapi3/client/petstore/typescript/builds/default/models/Order.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -30,42 +31,48 @@ export class Order { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "petId", "baseName": "petId", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "quantity", "baseName": "quantity", "type": "number", - "format": "int32" + "format": "int32", + "required": false }, { "name": "shipDate", "baseName": "shipDate", "type": "Date", - "format": "date-time" + "format": "date-time", + "required": false }, { "name": "status", "baseName": "status", "type": "OrderStatusEnum", - "format": "" + "format": "", + "required": false }, { "name": "complete", "baseName": "complete", "type": "boolean", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/default/models/Pet.ts b/samples/openapi3/client/petstore/typescript/builds/default/models/Pet.ts index ddb68aa82a19..4b7c3b929646 100644 --- a/samples/openapi3/client/petstore/typescript/builds/default/models/Pet.ts +++ b/samples/openapi3/client/petstore/typescript/builds/default/models/Pet.ts @@ -12,6 +12,7 @@ import { Category } from '../models/Category'; import { Tag } from '../models/Tag'; +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -32,42 +33,48 @@ export class Pet { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "category", "baseName": "category", "type": "Category", - "format": "" + "format": "", + "required": false }, { "name": "name", "baseName": "name", "type": "string", - "format": "" + "format": "", + "required": true }, { "name": "photoUrls", "baseName": "photoUrls", "type": "Array", - "format": "" + "format": "", + "required": true }, { "name": "tags", "baseName": "tags", "type": "Array", - "format": "" + "format": "", + "required": false }, { "name": "status", "baseName": "status", "type": "PetStatusEnum", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/default/models/Tag.ts b/samples/openapi3/client/petstore/typescript/builds/default/models/Tag.ts index 7a7a36ba59aa..fdb52c40ddda 100644 --- a/samples/openapi3/client/petstore/typescript/builds/default/models/Tag.ts +++ b/samples/openapi3/client/petstore/typescript/builds/default/models/Tag.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -23,18 +24,20 @@ export class Tag { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "name", "baseName": "name", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/default/models/TypeMatcher.ts b/samples/openapi3/client/petstore/typescript/builds/default/models/TypeMatcher.ts new file mode 100644 index 000000000000..2f1c20864a70 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/default/models/TypeMatcher.ts @@ -0,0 +1,36 @@ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; + +/** + * Validates if data contains all required attributes from the attributeTypeMap. + * + * @param data - The data object to validate + * @param attributeTypeMap - Array of attribute metadata including required flag + * @returns true if all required attributes are present in data, false otherwise + */ +export function instanceOfType(data: any, attributeTypeMap: Array): boolean { + for (const attribute of attributeTypeMap) { + if (attribute.required && data[attribute.baseName] === undefined) { + return false; + } + } + + return true; +} + +/** + * Attempts to find a matching type from an array of possible types by validating + * the data against each type's attribute requirements. + * + * @param data - The data object to match + * @param types - Array of possible type constructors + * @returns The name of the matching type, or undefined if no match found + */ +export function findMatchingType(data: any, types: Array): string | undefined { + for (const type of types) { + if (instanceOfType(data, type.getAttributeTypeMap())) { + return type.name; + } + } + + return undefined; +} \ No newline at end of file diff --git a/samples/openapi3/client/petstore/typescript/builds/default/models/User.ts b/samples/openapi3/client/petstore/typescript/builds/default/models/User.ts index 4dbe18f7fed4..a8338193852e 100644 --- a/samples/openapi3/client/petstore/typescript/builds/default/models/User.ts +++ b/samples/openapi3/client/petstore/typescript/builds/default/models/User.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -32,54 +33,62 @@ export class User { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "username", "baseName": "username", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "firstName", "baseName": "firstName", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "lastName", "baseName": "lastName", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "email", "baseName": "email", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "password", "baseName": "password", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "phone", "baseName": "phone", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "userStatus", "baseName": "userStatus", "type": "number", - "format": "int32" + "format": "int32", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/default/models/all.ts b/samples/openapi3/client/petstore/typescript/builds/default/models/all.ts index d63b43c96744..101927e7b61e 100644 --- a/samples/openapi3/client/petstore/typescript/builds/default/models/all.ts +++ b/samples/openapi3/client/petstore/typescript/builds/default/models/all.ts @@ -4,3 +4,5 @@ export * from '../models/Order' export * from '../models/Pet' export * from '../models/Tag' export * from '../models/User' +export * from './TypeMatcher' +export * from './ModelTypes' \ No newline at end of file diff --git a/samples/openapi3/client/petstore/typescript/builds/deno/.openapi-generator/FILES b/samples/openapi3/client/petstore/typescript/builds/deno/.openapi-generator/FILES index ab37481dc8ed..e55e16b1c5e9 100644 --- a/samples/openapi3/client/petstore/typescript/builds/deno/.openapi-generator/FILES +++ b/samples/openapi3/client/petstore/typescript/builds/deno/.openapi-generator/FILES @@ -17,10 +17,12 @@ index.ts middleware.ts models/ApiResponse.ts models/Category.ts +models/ModelTypes.ts models/ObjectSerializer.ts models/Order.ts models/Pet.ts models/Tag.ts +models/TypeMatcher.ts models/User.ts models/all.ts rxjsStub.ts diff --git a/samples/openapi3/client/petstore/typescript/builds/deno/models/ApiResponse.ts b/samples/openapi3/client/petstore/typescript/builds/deno/models/ApiResponse.ts index 55426844f46a..3f8ccc7fd16c 100644 --- a/samples/openapi3/client/petstore/typescript/builds/deno/models/ApiResponse.ts +++ b/samples/openapi3/client/petstore/typescript/builds/deno/models/ApiResponse.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes.ts'; import { HttpFile } from '../http/http.ts'; /** @@ -24,24 +25,27 @@ export class ApiResponse { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "code", "baseName": "code", "type": "number", - "format": "int32" + "format": "int32", + "required": false }, { "name": "type", "baseName": "type", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "message", "baseName": "message", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/deno/models/Category.ts b/samples/openapi3/client/petstore/typescript/builds/deno/models/Category.ts index 69f46a847ef9..10bdd4f559b6 100644 --- a/samples/openapi3/client/petstore/typescript/builds/deno/models/Category.ts +++ b/samples/openapi3/client/petstore/typescript/builds/deno/models/Category.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes.ts'; import { HttpFile } from '../http/http.ts'; /** @@ -23,18 +24,20 @@ export class Category { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "name", "baseName": "name", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/deno/models/ModelTypes.ts b/samples/openapi3/client/petstore/typescript/builds/deno/models/ModelTypes.ts new file mode 100644 index 000000000000..24a680aba301 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/deno/models/ModelTypes.ts @@ -0,0 +1,11 @@ +/** + * Represents a single attribute/property metadata entry in the attributeTypeMap. + * Used for validation and type matching in oneOf scenarios. + */ +export type AttributeTypeMapEntry = { + name: string; + baseName: string; + type: string; + format: string; + required: boolean; +}; diff --git a/samples/openapi3/client/petstore/typescript/builds/deno/models/ObjectSerializer.ts b/samples/openapi3/client/petstore/typescript/builds/deno/models/ObjectSerializer.ts index 3f31d6689023..4a8495b7f734 100644 --- a/samples/openapi3/client/petstore/typescript/builds/deno/models/ObjectSerializer.ts +++ b/samples/openapi3/client/petstore/typescript/builds/deno/models/ObjectSerializer.ts @@ -116,26 +116,37 @@ export class ObjectSerializer { // Check the discriminator let discriminatorProperty = typeMap[expectedType].discriminator; - if (discriminatorProperty == null) { - return expectedType; // the type does not have a discriminator. use it. - } else { - if (data[discriminatorProperty]) { - var discriminatorType = data[discriminatorProperty]; - let mapping = typeMap[expectedType].mapping; - if (mapping != undefined && mapping[discriminatorType]) { - return mapping[discriminatorType]; // use the type given in the discriminator - } else if(typeMap[discriminatorType]) { - return discriminatorType; - } else { - return expectedType; // discriminator did not map to a type + if (discriminatorProperty == null || !data[discriminatorProperty]) { + if (this.hasFindMatchingTypeMethod(typeMap[expectedType])) { + const foundType = typeMap[expectedType].findMatchingType(data); + if (foundType == undefined) { + throw new Error("Unable to determine a unique type for the provided object: oneOf type resolution failed. The object does not match exactly one schema. Consider adding a discriminator or making schemas mutually exclusive."); } + + return foundType; + } + return expectedType; // the type does not have a discriminator and findMatchingType method. use it. + } else { + let discriminatorType = data[discriminatorProperty]; + let mapping = typeMap[expectedType].mapping; + if (mapping != undefined && mapping[discriminatorType]) { + return mapping[discriminatorType]; // use the type given in the discriminator + } else if(typeMap[discriminatorType]) { + return discriminatorType; } else { - return expectedType; // discriminator was not present (or an empty string) + throw new Error(`Discriminator property '${discriminatorProperty}' has value '${discriminatorType}' which does not map to any known type in '${expectedType}'.`); } } } } + private static hasFindMatchingTypeMethod(klass: any): boolean { + if (typeof klass.findMatchingType === 'function') { + return true; + } + return false; + } + public static serialize(data: any, type: string, format: string): any { if (data == undefined) { return data; diff --git a/samples/openapi3/client/petstore/typescript/builds/deno/models/Order.ts b/samples/openapi3/client/petstore/typescript/builds/deno/models/Order.ts index ca36df140b3c..5be30eff7749 100644 --- a/samples/openapi3/client/petstore/typescript/builds/deno/models/Order.ts +++ b/samples/openapi3/client/petstore/typescript/builds/deno/models/Order.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes.ts'; import { HttpFile } from '../http/http.ts'; /** @@ -30,42 +31,48 @@ export class Order { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "petId", "baseName": "petId", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "quantity", "baseName": "quantity", "type": "number", - "format": "int32" + "format": "int32", + "required": false }, { "name": "shipDate", "baseName": "shipDate", "type": "Date", - "format": "date-time" + "format": "date-time", + "required": false }, { "name": "status", "baseName": "status", "type": "OrderStatusEnum", - "format": "" + "format": "", + "required": false }, { "name": "complete", "baseName": "complete", "type": "boolean", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/deno/models/Pet.ts b/samples/openapi3/client/petstore/typescript/builds/deno/models/Pet.ts index 7cbaa216062f..67f2f5da9bc3 100644 --- a/samples/openapi3/client/petstore/typescript/builds/deno/models/Pet.ts +++ b/samples/openapi3/client/petstore/typescript/builds/deno/models/Pet.ts @@ -12,6 +12,7 @@ import { Category } from '../models/Category.ts'; import { Tag } from '../models/Tag.ts'; +import { AttributeTypeMapEntry } from '../models/ModelTypes.ts'; import { HttpFile } from '../http/http.ts'; /** @@ -32,42 +33,48 @@ export class Pet { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "category", "baseName": "category", "type": "Category", - "format": "" + "format": "", + "required": false }, { "name": "name", "baseName": "name", "type": "string", - "format": "" + "format": "", + "required": true }, { "name": "photoUrls", "baseName": "photoUrls", "type": "Array", - "format": "" + "format": "", + "required": true }, { "name": "tags", "baseName": "tags", "type": "Array", - "format": "" + "format": "", + "required": false }, { "name": "status", "baseName": "status", "type": "PetStatusEnum", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/deno/models/Tag.ts b/samples/openapi3/client/petstore/typescript/builds/deno/models/Tag.ts index e443aa102307..0ea9aa66a96b 100644 --- a/samples/openapi3/client/petstore/typescript/builds/deno/models/Tag.ts +++ b/samples/openapi3/client/petstore/typescript/builds/deno/models/Tag.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes.ts'; import { HttpFile } from '../http/http.ts'; /** @@ -23,18 +24,20 @@ export class Tag { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "name", "baseName": "name", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/deno/models/TypeMatcher.ts b/samples/openapi3/client/petstore/typescript/builds/deno/models/TypeMatcher.ts new file mode 100644 index 000000000000..1cdccc77d283 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/deno/models/TypeMatcher.ts @@ -0,0 +1,36 @@ +import { AttributeTypeMapEntry } from '../models/ModelTypes.ts'; + +/** + * Validates if data contains all required attributes from the attributeTypeMap. + * + * @param data - The data object to validate + * @param attributeTypeMap - Array of attribute metadata including required flag + * @returns true if all required attributes are present in data, false otherwise + */ +export function instanceOfType(data: any, attributeTypeMap: Array): boolean { + for (const attribute of attributeTypeMap) { + if (attribute.required && data[attribute.baseName] === undefined) { + return false; + } + } + + return true; +} + +/** + * Attempts to find a matching type from an array of possible types by validating + * the data against each type's attribute requirements. + * + * @param data - The data object to match + * @param types - Array of possible type constructors + * @returns The name of the matching type, or undefined if no match found + */ +export function findMatchingType(data: any, types: Array): string | undefined { + for (const type of types) { + if (instanceOfType(data, type.getAttributeTypeMap())) { + return type.name; + } + } + + return undefined; +} \ No newline at end of file diff --git a/samples/openapi3/client/petstore/typescript/builds/deno/models/User.ts b/samples/openapi3/client/petstore/typescript/builds/deno/models/User.ts index c728f6fd7634..479c58ddb30b 100644 --- a/samples/openapi3/client/petstore/typescript/builds/deno/models/User.ts +++ b/samples/openapi3/client/petstore/typescript/builds/deno/models/User.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes.ts'; import { HttpFile } from '../http/http.ts'; /** @@ -32,54 +33,62 @@ export class User { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "username", "baseName": "username", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "firstName", "baseName": "firstName", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "lastName", "baseName": "lastName", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "email", "baseName": "email", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "password", "baseName": "password", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "phone", "baseName": "phone", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "userStatus", "baseName": "userStatus", "type": "number", - "format": "int32" + "format": "int32", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/deno/models/all.ts b/samples/openapi3/client/petstore/typescript/builds/deno/models/all.ts index 374b1e44e2bf..66388d463ba6 100644 --- a/samples/openapi3/client/petstore/typescript/builds/deno/models/all.ts +++ b/samples/openapi3/client/petstore/typescript/builds/deno/models/all.ts @@ -4,3 +4,5 @@ export * from '../models/Order.ts' export * from '../models/Pet.ts' export * from '../models/Tag.ts' export * from '../models/User.ts' +export * from './TypeMatcher.ts' +export * from './ModelTypes.ts' \ No newline at end of file diff --git a/samples/openapi3/client/petstore/typescript/builds/deno_object_params/.openapi-generator/FILES b/samples/openapi3/client/petstore/typescript/builds/deno_object_params/.openapi-generator/FILES index ab37481dc8ed..e55e16b1c5e9 100644 --- a/samples/openapi3/client/petstore/typescript/builds/deno_object_params/.openapi-generator/FILES +++ b/samples/openapi3/client/petstore/typescript/builds/deno_object_params/.openapi-generator/FILES @@ -17,10 +17,12 @@ index.ts middleware.ts models/ApiResponse.ts models/Category.ts +models/ModelTypes.ts models/ObjectSerializer.ts models/Order.ts models/Pet.ts models/Tag.ts +models/TypeMatcher.ts models/User.ts models/all.ts rxjsStub.ts diff --git a/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/ApiResponse.ts b/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/ApiResponse.ts index 55426844f46a..3f8ccc7fd16c 100644 --- a/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/ApiResponse.ts +++ b/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/ApiResponse.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes.ts'; import { HttpFile } from '../http/http.ts'; /** @@ -24,24 +25,27 @@ export class ApiResponse { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "code", "baseName": "code", "type": "number", - "format": "int32" + "format": "int32", + "required": false }, { "name": "type", "baseName": "type", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "message", "baseName": "message", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/Category.ts b/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/Category.ts index 69f46a847ef9..10bdd4f559b6 100644 --- a/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/Category.ts +++ b/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/Category.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes.ts'; import { HttpFile } from '../http/http.ts'; /** @@ -23,18 +24,20 @@ export class Category { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "name", "baseName": "name", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/ModelTypes.ts b/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/ModelTypes.ts new file mode 100644 index 000000000000..24a680aba301 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/ModelTypes.ts @@ -0,0 +1,11 @@ +/** + * Represents a single attribute/property metadata entry in the attributeTypeMap. + * Used for validation and type matching in oneOf scenarios. + */ +export type AttributeTypeMapEntry = { + name: string; + baseName: string; + type: string; + format: string; + required: boolean; +}; diff --git a/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/ObjectSerializer.ts b/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/ObjectSerializer.ts index 3f31d6689023..4a8495b7f734 100644 --- a/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/ObjectSerializer.ts +++ b/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/ObjectSerializer.ts @@ -116,26 +116,37 @@ export class ObjectSerializer { // Check the discriminator let discriminatorProperty = typeMap[expectedType].discriminator; - if (discriminatorProperty == null) { - return expectedType; // the type does not have a discriminator. use it. - } else { - if (data[discriminatorProperty]) { - var discriminatorType = data[discriminatorProperty]; - let mapping = typeMap[expectedType].mapping; - if (mapping != undefined && mapping[discriminatorType]) { - return mapping[discriminatorType]; // use the type given in the discriminator - } else if(typeMap[discriminatorType]) { - return discriminatorType; - } else { - return expectedType; // discriminator did not map to a type + if (discriminatorProperty == null || !data[discriminatorProperty]) { + if (this.hasFindMatchingTypeMethod(typeMap[expectedType])) { + const foundType = typeMap[expectedType].findMatchingType(data); + if (foundType == undefined) { + throw new Error("Unable to determine a unique type for the provided object: oneOf type resolution failed. The object does not match exactly one schema. Consider adding a discriminator or making schemas mutually exclusive."); } + + return foundType; + } + return expectedType; // the type does not have a discriminator and findMatchingType method. use it. + } else { + let discriminatorType = data[discriminatorProperty]; + let mapping = typeMap[expectedType].mapping; + if (mapping != undefined && mapping[discriminatorType]) { + return mapping[discriminatorType]; // use the type given in the discriminator + } else if(typeMap[discriminatorType]) { + return discriminatorType; } else { - return expectedType; // discriminator was not present (or an empty string) + throw new Error(`Discriminator property '${discriminatorProperty}' has value '${discriminatorType}' which does not map to any known type in '${expectedType}'.`); } } } } + private static hasFindMatchingTypeMethod(klass: any): boolean { + if (typeof klass.findMatchingType === 'function') { + return true; + } + return false; + } + public static serialize(data: any, type: string, format: string): any { if (data == undefined) { return data; diff --git a/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/Order.ts b/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/Order.ts index ca36df140b3c..5be30eff7749 100644 --- a/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/Order.ts +++ b/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/Order.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes.ts'; import { HttpFile } from '../http/http.ts'; /** @@ -30,42 +31,48 @@ export class Order { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "petId", "baseName": "petId", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "quantity", "baseName": "quantity", "type": "number", - "format": "int32" + "format": "int32", + "required": false }, { "name": "shipDate", "baseName": "shipDate", "type": "Date", - "format": "date-time" + "format": "date-time", + "required": false }, { "name": "status", "baseName": "status", "type": "OrderStatusEnum", - "format": "" + "format": "", + "required": false }, { "name": "complete", "baseName": "complete", "type": "boolean", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/Pet.ts b/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/Pet.ts index 7cbaa216062f..67f2f5da9bc3 100644 --- a/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/Pet.ts +++ b/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/Pet.ts @@ -12,6 +12,7 @@ import { Category } from '../models/Category.ts'; import { Tag } from '../models/Tag.ts'; +import { AttributeTypeMapEntry } from '../models/ModelTypes.ts'; import { HttpFile } from '../http/http.ts'; /** @@ -32,42 +33,48 @@ export class Pet { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "category", "baseName": "category", "type": "Category", - "format": "" + "format": "", + "required": false }, { "name": "name", "baseName": "name", "type": "string", - "format": "" + "format": "", + "required": true }, { "name": "photoUrls", "baseName": "photoUrls", "type": "Array", - "format": "" + "format": "", + "required": true }, { "name": "tags", "baseName": "tags", "type": "Array", - "format": "" + "format": "", + "required": false }, { "name": "status", "baseName": "status", "type": "PetStatusEnum", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/Tag.ts b/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/Tag.ts index e443aa102307..0ea9aa66a96b 100644 --- a/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/Tag.ts +++ b/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/Tag.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes.ts'; import { HttpFile } from '../http/http.ts'; /** @@ -23,18 +24,20 @@ export class Tag { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "name", "baseName": "name", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/TypeMatcher.ts b/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/TypeMatcher.ts new file mode 100644 index 000000000000..1cdccc77d283 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/TypeMatcher.ts @@ -0,0 +1,36 @@ +import { AttributeTypeMapEntry } from '../models/ModelTypes.ts'; + +/** + * Validates if data contains all required attributes from the attributeTypeMap. + * + * @param data - The data object to validate + * @param attributeTypeMap - Array of attribute metadata including required flag + * @returns true if all required attributes are present in data, false otherwise + */ +export function instanceOfType(data: any, attributeTypeMap: Array): boolean { + for (const attribute of attributeTypeMap) { + if (attribute.required && data[attribute.baseName] === undefined) { + return false; + } + } + + return true; +} + +/** + * Attempts to find a matching type from an array of possible types by validating + * the data against each type's attribute requirements. + * + * @param data - The data object to match + * @param types - Array of possible type constructors + * @returns The name of the matching type, or undefined if no match found + */ +export function findMatchingType(data: any, types: Array): string | undefined { + for (const type of types) { + if (instanceOfType(data, type.getAttributeTypeMap())) { + return type.name; + } + } + + return undefined; +} \ No newline at end of file diff --git a/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/User.ts b/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/User.ts index c728f6fd7634..479c58ddb30b 100644 --- a/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/User.ts +++ b/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/User.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes.ts'; import { HttpFile } from '../http/http.ts'; /** @@ -32,54 +33,62 @@ export class User { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "username", "baseName": "username", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "firstName", "baseName": "firstName", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "lastName", "baseName": "lastName", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "email", "baseName": "email", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "password", "baseName": "password", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "phone", "baseName": "phone", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "userStatus", "baseName": "userStatus", "type": "number", - "format": "int32" + "format": "int32", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/all.ts b/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/all.ts index 374b1e44e2bf..66388d463ba6 100644 --- a/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/all.ts +++ b/samples/openapi3/client/petstore/typescript/builds/deno_object_params/models/all.ts @@ -4,3 +4,5 @@ export * from '../models/Order.ts' export * from '../models/Pet.ts' export * from '../models/Tag.ts' export * from '../models/User.ts' +export * from './TypeMatcher.ts' +export * from './ModelTypes.ts' \ No newline at end of file diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/.openapi-generator/FILES b/samples/openapi3/client/petstore/typescript/builds/explode-query/.openapi-generator/FILES index 8a9627dabd2a..7db49a938036 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/.openapi-generator/FILES +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/.openapi-generator/FILES @@ -53,6 +53,7 @@ models/MapTest.ts models/MixedPropertiesAndAdditionalPropertiesClass.ts models/Model200Response.ts models/ModelFile.ts +models/ModelTypes.ts models/Name.ts models/NullableClass.ts models/NumberOnly.ts @@ -71,6 +72,7 @@ models/Return.ts models/SingleRefType.ts models/SpecialModelName.ts models/Tag.ts +models/TypeMatcher.ts models/User.ts models/all.ts package.json diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/AdditionalPropertiesClass.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/AdditionalPropertiesClass.ts index b4bae2c85384..3b09628f229b 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/AdditionalPropertiesClass.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/AdditionalPropertiesClass.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class AdditionalPropertiesClass { @@ -20,18 +21,20 @@ export class AdditionalPropertiesClass { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "mapProperty", "baseName": "map_property", "type": "{ [key: string]: string; }", - "format": "" + "format": "", + "required": false }, { "name": "mapOfMapProperty", "baseName": "map_of_map_property", "type": "{ [key: string]: { [key: string]: string; }; }", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/AllOfWithSingleRef.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/AllOfWithSingleRef.ts index b06e4ea6fed9..61e3a66bfe0b 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/AllOfWithSingleRef.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/AllOfWithSingleRef.ts @@ -11,6 +11,7 @@ */ import { SingleRefType } from '../models/SingleRefType'; +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class AllOfWithSingleRef { @@ -21,18 +22,20 @@ export class AllOfWithSingleRef { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "username", "baseName": "username", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "singleRefType", "baseName": "SingleRefType", "type": "SingleRefType", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Animal.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Animal.ts index 3de5b5215fa8..8e2013e29dac 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Animal.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Animal.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class Animal { @@ -23,18 +24,20 @@ export class Animal { "DOG": "Dog", }; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "className", "baseName": "class_name", "type": "string", - "format": "" + "format": "", + "required": true }, { "name": "color", "baseName": "color", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ApiResponse.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ApiResponse.ts index 68663f287613..18ee94495e70 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ApiResponse.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ApiResponse.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class ApiResponse { @@ -21,24 +22,27 @@ export class ApiResponse { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "code", "baseName": "code", "type": "number", - "format": "int32" + "format": "int32", + "required": false }, { "name": "type", "baseName": "type", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "message", "baseName": "message", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ArrayOfArrayOfNumberOnly.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ArrayOfArrayOfNumberOnly.ts index 1e9a6043fc2d..69b09737a6da 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ArrayOfArrayOfNumberOnly.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ArrayOfArrayOfNumberOnly.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class ArrayOfArrayOfNumberOnly { @@ -19,12 +20,13 @@ export class ArrayOfArrayOfNumberOnly { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "arrayArrayNumber", "baseName": "ArrayArrayNumber", "type": "Array>", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ArrayOfNumberOnly.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ArrayOfNumberOnly.ts index 8df04a7f8016..1feefb311eab 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ArrayOfNumberOnly.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ArrayOfNumberOnly.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class ArrayOfNumberOnly { @@ -19,12 +20,13 @@ export class ArrayOfNumberOnly { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "arrayNumber", "baseName": "ArrayNumber", "type": "Array", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ArrayTest.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ArrayTest.ts index 6b27fa292b1d..97759d19760a 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ArrayTest.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ArrayTest.ts @@ -11,6 +11,7 @@ */ import { ReadOnlyFirst } from '../models/ReadOnlyFirst'; +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class ArrayTest { @@ -22,24 +23,27 @@ export class ArrayTest { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "arrayOfString", "baseName": "array_of_string", "type": "Array", - "format": "" + "format": "", + "required": false }, { "name": "arrayArrayOfInteger", "baseName": "array_array_of_integer", "type": "Array>", - "format": "int64" + "format": "int64", + "required": false }, { "name": "arrayArrayOfModel", "baseName": "array_array_of_model", "type": "Array>", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Capitalization.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Capitalization.ts index d468f2bbc67d..7ae5be12baaf 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Capitalization.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Capitalization.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class Capitalization { @@ -27,42 +28,48 @@ export class Capitalization { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "smallCamel", "baseName": "smallCamel", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "capitalCamel", "baseName": "CapitalCamel", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "smallSnake", "baseName": "small_Snake", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "capitalSnake", "baseName": "Capital_Snake", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "sCAETHFlowPoints", "baseName": "SCA_ETH_Flow_Points", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "ATT_NAME", "baseName": "ATT_NAME", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Cat.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Cat.ts index ee72367ff076..874b401679ed 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Cat.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Cat.ts @@ -11,6 +11,7 @@ */ import { Animal } from '../models/Animal'; +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class Cat extends Animal { @@ -20,12 +21,13 @@ export class Cat extends Animal { static override readonly mapping: {[index: string]: string} | undefined = undefined; - static override readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static override readonly attributeTypeMap: Array = [ { "name": "declawed", "baseName": "declawed", "type": "boolean", - "format": "" + "format": "", + "required": false } ]; static override getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Category.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Category.ts index c70345b198aa..d60ad396a6c2 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Category.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Category.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class Category { @@ -20,18 +21,20 @@ export class Category { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "name", "baseName": "name", "type": "string", - "format": "" + "format": "", + "required": true } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ClassModel.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ClassModel.ts index 05a609ba28e7..ef1fcea73792 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ClassModel.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ClassModel.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -22,12 +23,13 @@ export class ClassModel { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "_class", "baseName": "_class", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Client.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Client.ts index aff4177ab6c2..ed5e715a155e 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Client.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Client.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class Client { @@ -19,12 +20,13 @@ export class Client { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "client", "baseName": "client", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/DeprecatedObject.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/DeprecatedObject.ts index 47ca7f4e5826..f05ab7cbe88f 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/DeprecatedObject.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/DeprecatedObject.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class DeprecatedObject { @@ -19,12 +20,13 @@ export class DeprecatedObject { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "name", "baseName": "name", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Dog.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Dog.ts index 6a173270484c..b754cc79565d 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Dog.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Dog.ts @@ -11,6 +11,7 @@ */ import { Animal } from '../models/Animal'; +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class Dog extends Animal { @@ -20,12 +21,13 @@ export class Dog extends Animal { static override readonly mapping: {[index: string]: string} | undefined = undefined; - static override readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static override readonly attributeTypeMap: Array = [ { "name": "breed", "baseName": "breed", "type": "string", - "format": "" + "format": "", + "required": false } ]; static override getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/EnumArrays.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/EnumArrays.ts index dfb4cc2eee95..a9c9a9cf6153 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/EnumArrays.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/EnumArrays.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class EnumArrays { @@ -20,18 +21,20 @@ export class EnumArrays { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "justSymbol", "baseName": "just_symbol", "type": "EnumArraysJustSymbolEnum", - "format": "" + "format": "", + "required": false }, { "name": "arrayEnum", "baseName": "array_enum", "type": "Array", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/EnumClass.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/EnumClass.ts index 42ca4340d7d4..bf3fc2917a3a 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/EnumClass.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/EnumClass.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export enum EnumClass { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/EnumTest.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/EnumTest.ts index 805ec09e285b..0b47f16b1a44 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/EnumTest.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/EnumTest.ts @@ -14,6 +14,7 @@ import { OuterEnum } from '../models/OuterEnum'; import { OuterEnumDefaultValue } from '../models/OuterEnumDefaultValue'; import { OuterEnumInteger } from '../models/OuterEnumInteger'; import { OuterEnumIntegerDefaultValue } from '../models/OuterEnumIntegerDefaultValue'; +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class EnumTest { @@ -30,54 +31,62 @@ export class EnumTest { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "enumString", "baseName": "enum_string", "type": "EnumTestEnumStringEnum", - "format": "" + "format": "", + "required": false }, { "name": "enumStringRequired", "baseName": "enum_string_required", "type": "EnumTestEnumStringRequiredEnum", - "format": "" + "format": "", + "required": true }, { "name": "enumInteger", "baseName": "enum_integer", "type": "EnumTestEnumIntegerEnum", - "format": "int32" + "format": "int32", + "required": false }, { "name": "enumNumber", "baseName": "enum_number", "type": "EnumTestEnumNumberEnum", - "format": "double" + "format": "double", + "required": false }, { "name": "outerEnum", "baseName": "outerEnum", "type": "OuterEnum", - "format": "" + "format": "", + "required": false }, { "name": "outerEnumInteger", "baseName": "outerEnumInteger", "type": "OuterEnumInteger", - "format": "" + "format": "", + "required": false }, { "name": "outerEnumDefaultValue", "baseName": "outerEnumDefaultValue", "type": "OuterEnumDefaultValue", - "format": "" + "format": "", + "required": false }, { "name": "outerEnumIntegerDefaultValue", "baseName": "outerEnumIntegerDefaultValue", "type": "OuterEnumIntegerDefaultValue", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/FakeBigDecimalMap200Response.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/FakeBigDecimalMap200Response.ts index a9cf4595fb7b..26d94674c0d5 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/FakeBigDecimalMap200Response.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/FakeBigDecimalMap200Response.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class FakeBigDecimalMap200Response { @@ -20,18 +21,20 @@ export class FakeBigDecimalMap200Response { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "someId", "baseName": "someId", "type": "number", - "format": "" + "format": "", + "required": false }, { "name": "someMap", "baseName": "someMap", "type": "{ [key: string]: number; }", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/FileSchemaTestClass.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/FileSchemaTestClass.ts index f6fe132a51de..159b9bc90cf8 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/FileSchemaTestClass.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/FileSchemaTestClass.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class FileSchemaTestClass { @@ -20,18 +21,20 @@ export class FileSchemaTestClass { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "file", "baseName": "file", "type": "any", - "format": "" + "format": "", + "required": false }, { "name": "files", "baseName": "files", "type": "Array", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Foo.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Foo.ts index 22bc2bd58929..330e4030c1eb 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Foo.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Foo.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class Foo { @@ -19,12 +20,13 @@ export class Foo { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "bar", "baseName": "bar", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/FooGetDefaultResponse.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/FooGetDefaultResponse.ts index 996d74d388e1..20783fc97794 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/FooGetDefaultResponse.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/FooGetDefaultResponse.ts @@ -11,6 +11,7 @@ */ import { Foo } from '../models/Foo'; +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class FooGetDefaultResponse { @@ -20,12 +21,13 @@ export class FooGetDefaultResponse { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "string", "baseName": "string", "type": "Foo", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/FormatTest.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/FormatTest.ts index da5f14482202..992613ee6e9d 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/FormatTest.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/FormatTest.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class FormatTest { @@ -40,102 +41,118 @@ export class FormatTest { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "integer", "baseName": "integer", "type": "number", - "format": "" + "format": "", + "required": false }, { "name": "int32", "baseName": "int32", "type": "number", - "format": "int32" + "format": "int32", + "required": false }, { "name": "int64", "baseName": "int64", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "number", "baseName": "number", "type": "number", - "format": "" + "format": "", + "required": true }, { "name": "_float", "baseName": "float", "type": "number", - "format": "float" + "format": "float", + "required": false }, { "name": "_double", "baseName": "double", "type": "number", - "format": "double" + "format": "double", + "required": false }, { "name": "decimal", "baseName": "decimal", "type": "string", - "format": "number" + "format": "number", + "required": false }, { "name": "string", "baseName": "string", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "_byte", "baseName": "byte", "type": "string", - "format": "byte" + "format": "byte", + "required": true }, { "name": "binary", "baseName": "binary", "type": "HttpFile", - "format": "binary" + "format": "binary", + "required": false }, { "name": "date", "baseName": "date", "type": "string", - "format": "date" + "format": "date", + "required": true }, { "name": "dateTime", "baseName": "dateTime", "type": "Date", - "format": "date-time" + "format": "date-time", + "required": false }, { "name": "uuid", "baseName": "uuid", "type": "string", - "format": "uuid" + "format": "uuid", + "required": false }, { "name": "password", "baseName": "password", "type": "string", - "format": "password" + "format": "password", + "required": true }, { "name": "patternWithDigits", "baseName": "pattern_with_digits", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "patternWithDigitsAndDelimiter", "baseName": "pattern_with_digits_and_delimiter", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/HasOnlyReadOnly.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/HasOnlyReadOnly.ts index 402c7cb21467..f13e4a34a0a2 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/HasOnlyReadOnly.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/HasOnlyReadOnly.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class HasOnlyReadOnly { @@ -20,18 +21,20 @@ export class HasOnlyReadOnly { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "bar", "baseName": "bar", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "foo", "baseName": "foo", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/HealthCheckResult.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/HealthCheckResult.ts index 61330f3f1cd2..d99474691081 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/HealthCheckResult.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/HealthCheckResult.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -22,12 +23,13 @@ export class HealthCheckResult { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "nullableMessage", "baseName": "NullableMessage", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/List.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/List.ts index 50abb3d550d1..e8b683c6e947 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/List.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/List.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class List { @@ -19,12 +20,13 @@ export class List { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "_123list", "baseName": "123-list", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/MapTest.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/MapTest.ts index 512fae304c86..707a61fb613a 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/MapTest.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/MapTest.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class MapTest { @@ -22,30 +23,34 @@ export class MapTest { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "mapMapOfString", "baseName": "map_map_of_string", "type": "{ [key: string]: { [key: string]: string; }; }", - "format": "" + "format": "", + "required": false }, { "name": "mapOfEnumString", "baseName": "map_of_enum_string", "type": "{ [key: string]: string; }", - "format": "" + "format": "", + "required": false }, { "name": "directMap", "baseName": "direct_map", "type": "{ [key: string]: boolean; }", - "format": "" + "format": "", + "required": false }, { "name": "indirectMap", "baseName": "indirect_map", "type": "{ [key: string]: boolean; }", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/MixedPropertiesAndAdditionalPropertiesClass.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/MixedPropertiesAndAdditionalPropertiesClass.ts index f79146d2fd12..2217732ee9be 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/MixedPropertiesAndAdditionalPropertiesClass.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/MixedPropertiesAndAdditionalPropertiesClass.ts @@ -11,6 +11,7 @@ */ import { Animal } from '../models/Animal'; +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class MixedPropertiesAndAdditionalPropertiesClass { @@ -22,24 +23,27 @@ export class MixedPropertiesAndAdditionalPropertiesClass { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "uuid", "baseName": "uuid", "type": "string", - "format": "uuid" + "format": "uuid", + "required": false }, { "name": "dateTime", "baseName": "dateTime", "type": "Date", - "format": "date-time" + "format": "date-time", + "required": false }, { "name": "map", "baseName": "map", "type": "{ [key: string]: Animal; }", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Model200Response.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Model200Response.ts index 8112b17b5686..376ad2800f7e 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Model200Response.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Model200Response.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -23,18 +24,20 @@ export class Model200Response { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "name", "baseName": "name", "type": "number", - "format": "int32" + "format": "int32", + "required": false }, { "name": "_class", "baseName": "class", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ModelFile.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ModelFile.ts index a2af826e9d4f..d4d107ee43b2 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ModelFile.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ModelFile.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -25,12 +26,13 @@ export class ModelFile { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "sourceURI", "baseName": "sourceURI", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ModelTypes.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ModelTypes.ts new file mode 100644 index 000000000000..24a680aba301 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ModelTypes.ts @@ -0,0 +1,11 @@ +/** + * Represents a single attribute/property metadata entry in the attributeTypeMap. + * Used for validation and type matching in oneOf scenarios. + */ +export type AttributeTypeMapEntry = { + name: string; + baseName: string; + type: string; + format: string; + required: boolean; +}; diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Name.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Name.ts index 0254b92d9a54..073f9c465998 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Name.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Name.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -25,30 +26,34 @@ export class Name { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "name", "baseName": "name", "type": "number", - "format": "int32" + "format": "int32", + "required": true }, { "name": "snakeCase", "baseName": "snake_case", "type": "number", - "format": "int32" + "format": "int32", + "required": false }, { "name": "property", "baseName": "property", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "_123number", "baseName": "123Number", "type": "number", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/NullableClass.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/NullableClass.ts index 9630c721bbf0..0f6fd86dcf3f 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/NullableClass.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/NullableClass.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class NullableClass { @@ -30,78 +31,90 @@ export class NullableClass { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "integerProp", "baseName": "integer_prop", "type": "number", - "format": "" + "format": "", + "required": false }, { "name": "numberProp", "baseName": "number_prop", "type": "number", - "format": "" + "format": "", + "required": false }, { "name": "booleanProp", "baseName": "boolean_prop", "type": "boolean", - "format": "" + "format": "", + "required": false }, { "name": "stringProp", "baseName": "string_prop", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "dateProp", "baseName": "date_prop", "type": "string", - "format": "date" + "format": "date", + "required": false }, { "name": "datetimeProp", "baseName": "datetime_prop", "type": "Date", - "format": "date-time" + "format": "date-time", + "required": false }, { "name": "arrayNullableProp", "baseName": "array_nullable_prop", "type": "Array", - "format": "" + "format": "", + "required": false }, { "name": "arrayAndItemsNullableProp", "baseName": "array_and_items_nullable_prop", "type": "Array", - "format": "" + "format": "", + "required": false }, { "name": "arrayItemsNullable", "baseName": "array_items_nullable", "type": "Array", - "format": "" + "format": "", + "required": false }, { "name": "objectNullableProp", "baseName": "object_nullable_prop", "type": "{ [key: string]: any; }", - "format": "" + "format": "", + "required": false }, { "name": "objectAndItemsNullableProp", "baseName": "object_and_items_nullable_prop", "type": "{ [key: string]: any | null; }", - "format": "" + "format": "", + "required": false }, { "name": "objectItemsNullable", "baseName": "object_items_nullable", "type": "{ [key: string]: any | null; }", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/NumberOnly.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/NumberOnly.ts index 1b556ca63b60..a3a6f35e65fb 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/NumberOnly.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/NumberOnly.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class NumberOnly { @@ -19,12 +20,13 @@ export class NumberOnly { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "justNumber", "baseName": "JustNumber", "type": "number", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ObjectSerializer.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ObjectSerializer.ts index 9b1bff296530..2538540a62ee 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ObjectSerializer.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ObjectSerializer.ts @@ -246,26 +246,37 @@ export class ObjectSerializer { // Check the discriminator let discriminatorProperty = typeMap[expectedType].discriminator; - if (discriminatorProperty == null) { - return expectedType; // the type does not have a discriminator. use it. - } else { - if (data[discriminatorProperty]) { - var discriminatorType = data[discriminatorProperty]; - let mapping = typeMap[expectedType].mapping; - if (mapping != undefined && mapping[discriminatorType]) { - return mapping[discriminatorType]; // use the type given in the discriminator - } else if(typeMap[discriminatorType]) { - return discriminatorType; - } else { - return expectedType; // discriminator did not map to a type + if (discriminatorProperty == null || !data[discriminatorProperty]) { + if (this.hasFindMatchingTypeMethod(typeMap[expectedType])) { + const foundType = typeMap[expectedType].findMatchingType(data); + if (foundType == undefined) { + throw new Error("Unable to determine a unique type for the provided object: oneOf type resolution failed. The object does not match exactly one schema. Consider adding a discriminator or making schemas mutually exclusive."); } + + return foundType; + } + return expectedType; // the type does not have a discriminator and findMatchingType method. use it. + } else { + let discriminatorType = data[discriminatorProperty]; + let mapping = typeMap[expectedType].mapping; + if (mapping != undefined && mapping[discriminatorType]) { + return mapping[discriminatorType]; // use the type given in the discriminator + } else if(typeMap[discriminatorType]) { + return discriminatorType; } else { - return expectedType; // discriminator was not present (or an empty string) + throw new Error(`Discriminator property '${discriminatorProperty}' has value '${discriminatorType}' which does not map to any known type in '${expectedType}'.`); } } } } + private static hasFindMatchingTypeMethod(klass: any): boolean { + if (typeof klass.findMatchingType === 'function') { + return true; + } + return false; + } + public static serialize(data: any, type: string, format: string): any { if (data == undefined) { return data; diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ObjectWithDeprecatedFields.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ObjectWithDeprecatedFields.ts index 1a428428a1e2..1b5d79722ec3 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ObjectWithDeprecatedFields.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ObjectWithDeprecatedFields.ts @@ -11,6 +11,7 @@ */ import { DeprecatedObject } from '../models/DeprecatedObject'; +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class ObjectWithDeprecatedFields { @@ -23,30 +24,34 @@ export class ObjectWithDeprecatedFields { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "uuid", "baseName": "uuid", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "id", "baseName": "id", "type": "number", - "format": "" + "format": "", + "required": false }, { "name": "deprecatedRef", "baseName": "deprecatedRef", "type": "DeprecatedObject", - "format": "" + "format": "", + "required": false }, { "name": "bars", "baseName": "bars", "type": "Array", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Order.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Order.ts index 56ebae4d3851..cc8af6f8e039 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Order.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Order.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class Order { @@ -27,42 +28,48 @@ export class Order { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "petId", "baseName": "petId", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "quantity", "baseName": "quantity", "type": "number", - "format": "int32" + "format": "int32", + "required": false }, { "name": "shipDate", "baseName": "shipDate", "type": "Date", - "format": "date-time" + "format": "date-time", + "required": false }, { "name": "status", "baseName": "status", "type": "OrderStatusEnum", - "format": "" + "format": "", + "required": false }, { "name": "complete", "baseName": "complete", "type": "boolean", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/OuterComposite.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/OuterComposite.ts index 7245e4e995ef..72c65e10eb40 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/OuterComposite.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/OuterComposite.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class OuterComposite { @@ -21,24 +22,27 @@ export class OuterComposite { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "myNumber", "baseName": "my_number", "type": "number", - "format": "" + "format": "", + "required": false }, { "name": "myString", "baseName": "my_string", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "myBoolean", "baseName": "my_boolean", "type": "boolean", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/OuterEnum.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/OuterEnum.ts index 0bfae26e8d3f..3805999e3aa4 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/OuterEnum.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/OuterEnum.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export enum OuterEnum { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/OuterEnumDefaultValue.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/OuterEnumDefaultValue.ts index b379db29b9f6..e0c97fdf2bdf 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/OuterEnumDefaultValue.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/OuterEnumDefaultValue.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export enum OuterEnumDefaultValue { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/OuterEnumInteger.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/OuterEnumInteger.ts index ec865ea8193e..1042f600d74f 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/OuterEnumInteger.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/OuterEnumInteger.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export enum OuterEnumInteger { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/OuterEnumIntegerDefaultValue.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/OuterEnumIntegerDefaultValue.ts index 98dd2ab00b32..cef1a8967add 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/OuterEnumIntegerDefaultValue.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/OuterEnumIntegerDefaultValue.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export enum OuterEnumIntegerDefaultValue { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/OuterObjectWithEnumProperty.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/OuterObjectWithEnumProperty.ts index 4767bd8e646a..8ba0ff0a794b 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/OuterObjectWithEnumProperty.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/OuterObjectWithEnumProperty.ts @@ -11,6 +11,7 @@ */ import { OuterEnumInteger } from '../models/OuterEnumInteger'; +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class OuterObjectWithEnumProperty { @@ -20,12 +21,13 @@ export class OuterObjectWithEnumProperty { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "value", "baseName": "value", "type": "OuterEnumInteger", - "format": "" + "format": "", + "required": true } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Pet.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Pet.ts index 58eec958aa7e..aacaaf8281ee 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Pet.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Pet.ts @@ -12,6 +12,7 @@ import { Category } from '../models/Category'; import { Tag } from '../models/Tag'; +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class Pet { @@ -29,42 +30,48 @@ export class Pet { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "category", "baseName": "category", "type": "Category", - "format": "" + "format": "", + "required": false }, { "name": "name", "baseName": "name", "type": "string", - "format": "" + "format": "", + "required": true }, { "name": "photoUrls", "baseName": "photoUrls", "type": "Set", - "format": "" + "format": "", + "required": true }, { "name": "tags", "baseName": "tags", "type": "Array", - "format": "" + "format": "", + "required": false }, { "name": "status", "baseName": "status", "type": "PetStatusEnum", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ReadOnlyFirst.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ReadOnlyFirst.ts index 8b09cae0d231..da4277a922bc 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ReadOnlyFirst.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/ReadOnlyFirst.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class ReadOnlyFirst { @@ -20,18 +21,20 @@ export class ReadOnlyFirst { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "bar", "baseName": "bar", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "baz", "baseName": "baz", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Return.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Return.ts index 77981b6800ee..83d6be548f74 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Return.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Return.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -22,12 +23,13 @@ export class Return { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "_return", "baseName": "return", "type": "number", - "format": "int32" + "format": "int32", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/SingleRefType.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/SingleRefType.ts index 0771fd11fcd9..70f35224687a 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/SingleRefType.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/SingleRefType.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export enum SingleRefType { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/SpecialModelName.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/SpecialModelName.ts index eb610dddccbe..3c50f1ee1b1e 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/SpecialModelName.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/SpecialModelName.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class SpecialModelName { @@ -19,12 +20,13 @@ export class SpecialModelName { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "specialPropertyName", "baseName": "$special[property.name]", "type": "number", - "format": "int64" + "format": "int64", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Tag.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Tag.ts index ec4cfe6c2247..286ca3df57d7 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Tag.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/Tag.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class Tag { @@ -20,18 +21,20 @@ export class Tag { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "name", "baseName": "name", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/TypeMatcher.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/TypeMatcher.ts new file mode 100644 index 000000000000..2f1c20864a70 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/TypeMatcher.ts @@ -0,0 +1,36 @@ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; + +/** + * Validates if data contains all required attributes from the attributeTypeMap. + * + * @param data - The data object to validate + * @param attributeTypeMap - Array of attribute metadata including required flag + * @returns true if all required attributes are present in data, false otherwise + */ +export function instanceOfType(data: any, attributeTypeMap: Array): boolean { + for (const attribute of attributeTypeMap) { + if (attribute.required && data[attribute.baseName] === undefined) { + return false; + } + } + + return true; +} + +/** + * Attempts to find a matching type from an array of possible types by validating + * the data against each type's attribute requirements. + * + * @param data - The data object to match + * @param types - Array of possible type constructors + * @returns The name of the matching type, or undefined if no match found + */ +export function findMatchingType(data: any, types: Array): string | undefined { + for (const type of types) { + if (instanceOfType(data, type.getAttributeTypeMap())) { + return type.name; + } + } + + return undefined; +} \ No newline at end of file diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/User.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/User.ts index 627b15b8fd6d..170735b835fb 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/User.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/User.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class User { @@ -29,54 +30,62 @@ export class User { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "username", "baseName": "username", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "firstName", "baseName": "firstName", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "lastName", "baseName": "lastName", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "email", "baseName": "email", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "password", "baseName": "password", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "phone", "baseName": "phone", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "userStatus", "baseName": "userStatus", "type": "number", - "format": "int32" + "format": "int32", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/all.ts b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/all.ts index 0b1516d3ebcb..02953ba6d223 100644 --- a/samples/openapi3/client/petstore/typescript/builds/explode-query/models/all.ts +++ b/samples/openapi3/client/petstore/typescript/builds/explode-query/models/all.ts @@ -45,3 +45,5 @@ export * from '../models/SingleRefType' export * from '../models/SpecialModelName' export * from '../models/Tag' export * from '../models/User' +export * from './TypeMatcher' +export * from './ModelTypes' \ No newline at end of file diff --git a/samples/openapi3/client/petstore/typescript/builds/inversify/.openapi-generator/FILES b/samples/openapi3/client/petstore/typescript/builds/inversify/.openapi-generator/FILES index 6ea98493524d..8a99ffa26fb1 100644 --- a/samples/openapi3/client/petstore/typescript/builds/inversify/.openapi-generator/FILES +++ b/samples/openapi3/client/petstore/typescript/builds/inversify/.openapi-generator/FILES @@ -21,10 +21,12 @@ index.ts middleware.ts models/ApiResponse.ts models/Category.ts +models/ModelTypes.ts models/ObjectSerializer.ts models/Order.ts models/Pet.ts models/Tag.ts +models/TypeMatcher.ts models/User.ts models/all.ts package.json diff --git a/samples/openapi3/client/petstore/typescript/builds/inversify/models/ApiResponse.ts b/samples/openapi3/client/petstore/typescript/builds/inversify/models/ApiResponse.ts index 3dd68507b210..ddfa26277fe4 100644 --- a/samples/openapi3/client/petstore/typescript/builds/inversify/models/ApiResponse.ts +++ b/samples/openapi3/client/petstore/typescript/builds/inversify/models/ApiResponse.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -24,24 +25,27 @@ export class ApiResponse { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "code", "baseName": "code", "type": "number", - "format": "int32" + "format": "int32", + "required": false }, { "name": "type", "baseName": "type", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "message", "baseName": "message", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/inversify/models/Category.ts b/samples/openapi3/client/petstore/typescript/builds/inversify/models/Category.ts index e025011174d3..ce325ffc3a2d 100644 --- a/samples/openapi3/client/petstore/typescript/builds/inversify/models/Category.ts +++ b/samples/openapi3/client/petstore/typescript/builds/inversify/models/Category.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -23,18 +24,20 @@ export class Category { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "name", "baseName": "name", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/inversify/models/ModelTypes.ts b/samples/openapi3/client/petstore/typescript/builds/inversify/models/ModelTypes.ts new file mode 100644 index 000000000000..24a680aba301 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/inversify/models/ModelTypes.ts @@ -0,0 +1,11 @@ +/** + * Represents a single attribute/property metadata entry in the attributeTypeMap. + * Used for validation and type matching in oneOf scenarios. + */ +export type AttributeTypeMapEntry = { + name: string; + baseName: string; + type: string; + format: string; + required: boolean; +}; diff --git a/samples/openapi3/client/petstore/typescript/builds/inversify/models/ObjectSerializer.ts b/samples/openapi3/client/petstore/typescript/builds/inversify/models/ObjectSerializer.ts index fe462a298a3a..a8ba5820cc68 100644 --- a/samples/openapi3/client/petstore/typescript/builds/inversify/models/ObjectSerializer.ts +++ b/samples/openapi3/client/petstore/typescript/builds/inversify/models/ObjectSerializer.ts @@ -116,26 +116,37 @@ export class ObjectSerializer { // Check the discriminator let discriminatorProperty = typeMap[expectedType].discriminator; - if (discriminatorProperty == null) { - return expectedType; // the type does not have a discriminator. use it. - } else { - if (data[discriminatorProperty]) { - var discriminatorType = data[discriminatorProperty]; - let mapping = typeMap[expectedType].mapping; - if (mapping != undefined && mapping[discriminatorType]) { - return mapping[discriminatorType]; // use the type given in the discriminator - } else if(typeMap[discriminatorType]) { - return discriminatorType; - } else { - return expectedType; // discriminator did not map to a type + if (discriminatorProperty == null || !data[discriminatorProperty]) { + if (this.hasFindMatchingTypeMethod(typeMap[expectedType])) { + const foundType = typeMap[expectedType].findMatchingType(data); + if (foundType == undefined) { + throw new Error("Unable to determine a unique type for the provided object: oneOf type resolution failed. The object does not match exactly one schema. Consider adding a discriminator or making schemas mutually exclusive."); } + + return foundType; + } + return expectedType; // the type does not have a discriminator and findMatchingType method. use it. + } else { + let discriminatorType = data[discriminatorProperty]; + let mapping = typeMap[expectedType].mapping; + if (mapping != undefined && mapping[discriminatorType]) { + return mapping[discriminatorType]; // use the type given in the discriminator + } else if(typeMap[discriminatorType]) { + return discriminatorType; } else { - return expectedType; // discriminator was not present (or an empty string) + throw new Error(`Discriminator property '${discriminatorProperty}' has value '${discriminatorType}' which does not map to any known type in '${expectedType}'.`); } } } } + private static hasFindMatchingTypeMethod(klass: any): boolean { + if (typeof klass.findMatchingType === 'function') { + return true; + } + return false; + } + public static serialize(data: any, type: string, format: string): any { if (data == undefined) { return data; diff --git a/samples/openapi3/client/petstore/typescript/builds/inversify/models/Order.ts b/samples/openapi3/client/petstore/typescript/builds/inversify/models/Order.ts index b8d4a26c7d47..4707dcaa7d1e 100644 --- a/samples/openapi3/client/petstore/typescript/builds/inversify/models/Order.ts +++ b/samples/openapi3/client/petstore/typescript/builds/inversify/models/Order.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -30,42 +31,48 @@ export class Order { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "petId", "baseName": "petId", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "quantity", "baseName": "quantity", "type": "number", - "format": "int32" + "format": "int32", + "required": false }, { "name": "shipDate", "baseName": "shipDate", "type": "Date", - "format": "date-time" + "format": "date-time", + "required": false }, { "name": "status", "baseName": "status", "type": "OrderStatusEnum", - "format": "" + "format": "", + "required": false }, { "name": "complete", "baseName": "complete", "type": "boolean", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/inversify/models/Pet.ts b/samples/openapi3/client/petstore/typescript/builds/inversify/models/Pet.ts index ddb68aa82a19..4b7c3b929646 100644 --- a/samples/openapi3/client/petstore/typescript/builds/inversify/models/Pet.ts +++ b/samples/openapi3/client/petstore/typescript/builds/inversify/models/Pet.ts @@ -12,6 +12,7 @@ import { Category } from '../models/Category'; import { Tag } from '../models/Tag'; +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -32,42 +33,48 @@ export class Pet { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "category", "baseName": "category", "type": "Category", - "format": "" + "format": "", + "required": false }, { "name": "name", "baseName": "name", "type": "string", - "format": "" + "format": "", + "required": true }, { "name": "photoUrls", "baseName": "photoUrls", "type": "Array", - "format": "" + "format": "", + "required": true }, { "name": "tags", "baseName": "tags", "type": "Array", - "format": "" + "format": "", + "required": false }, { "name": "status", "baseName": "status", "type": "PetStatusEnum", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/inversify/models/Tag.ts b/samples/openapi3/client/petstore/typescript/builds/inversify/models/Tag.ts index 7a7a36ba59aa..fdb52c40ddda 100644 --- a/samples/openapi3/client/petstore/typescript/builds/inversify/models/Tag.ts +++ b/samples/openapi3/client/petstore/typescript/builds/inversify/models/Tag.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -23,18 +24,20 @@ export class Tag { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "name", "baseName": "name", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/inversify/models/TypeMatcher.ts b/samples/openapi3/client/petstore/typescript/builds/inversify/models/TypeMatcher.ts new file mode 100644 index 000000000000..2f1c20864a70 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/inversify/models/TypeMatcher.ts @@ -0,0 +1,36 @@ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; + +/** + * Validates if data contains all required attributes from the attributeTypeMap. + * + * @param data - The data object to validate + * @param attributeTypeMap - Array of attribute metadata including required flag + * @returns true if all required attributes are present in data, false otherwise + */ +export function instanceOfType(data: any, attributeTypeMap: Array): boolean { + for (const attribute of attributeTypeMap) { + if (attribute.required && data[attribute.baseName] === undefined) { + return false; + } + } + + return true; +} + +/** + * Attempts to find a matching type from an array of possible types by validating + * the data against each type's attribute requirements. + * + * @param data - The data object to match + * @param types - Array of possible type constructors + * @returns The name of the matching type, or undefined if no match found + */ +export function findMatchingType(data: any, types: Array): string | undefined { + for (const type of types) { + if (instanceOfType(data, type.getAttributeTypeMap())) { + return type.name; + } + } + + return undefined; +} \ No newline at end of file diff --git a/samples/openapi3/client/petstore/typescript/builds/inversify/models/User.ts b/samples/openapi3/client/petstore/typescript/builds/inversify/models/User.ts index 4dbe18f7fed4..a8338193852e 100644 --- a/samples/openapi3/client/petstore/typescript/builds/inversify/models/User.ts +++ b/samples/openapi3/client/petstore/typescript/builds/inversify/models/User.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -32,54 +33,62 @@ export class User { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "username", "baseName": "username", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "firstName", "baseName": "firstName", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "lastName", "baseName": "lastName", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "email", "baseName": "email", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "password", "baseName": "password", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "phone", "baseName": "phone", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "userStatus", "baseName": "userStatus", "type": "number", - "format": "int32" + "format": "int32", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/inversify/models/all.ts b/samples/openapi3/client/petstore/typescript/builds/inversify/models/all.ts index d63b43c96744..101927e7b61e 100644 --- a/samples/openapi3/client/petstore/typescript/builds/inversify/models/all.ts +++ b/samples/openapi3/client/petstore/typescript/builds/inversify/models/all.ts @@ -4,3 +4,5 @@ export * from '../models/Order' export * from '../models/Pet' export * from '../models/Tag' export * from '../models/User' +export * from './TypeMatcher' +export * from './ModelTypes' \ No newline at end of file diff --git a/samples/openapi3/client/petstore/typescript/builds/inversify/package-lock.json b/samples/openapi3/client/petstore/typescript/builds/inversify/package-lock.json index 1cb557a8cd38..e189805768ce 100644 --- a/samples/openapi3/client/petstore/typescript/builds/inversify/package-lock.json +++ b/samples/openapi3/client/petstore/typescript/builds/inversify/package-lock.json @@ -9,46 +9,31 @@ "version": "1.0.0", "license": "Unlicense", "dependencies": { - "@types/node": "^22.10.5", - "@types/node-fetch": "^2.5.7", + "@types/node": "^16.18.126", + "@types/node-fetch": "^2.6.13", "es6-promise": "^4.2.4", - "form-data": "^2.5.0", + "form-data": "^4.0.4", "inversify": "^6.0.1", - "node-fetch": "^2.6.0" + "node-fetch": "^2.7.0" }, "devDependencies": { "typescript": "^4.0" } }, "node_modules/@types/node": { - "version": "22.10.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.5.tgz", - "integrity": "sha512-F8Q+SeGimwOo86fiovQh8qiXfFEh2/ocYv7tU5pJ3EXMSSxk1Joj5wefpFK2fHTf/N6HKGSxIDBT9f3gCxXPkQ==", - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" - } + "version": "16.18.126", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.126.tgz", + "integrity": "sha512-OTcgaiwfGFBKacvfwuHzzn1KLxH/er8mluiy8/uM3sGXHaRe73RrSIj01jow9t4kJEW633Ov+cOexXeiApTyAw==", + "license": "MIT" }, "node_modules/@types/node-fetch": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.7.tgz", - "integrity": "sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw==", + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz", + "integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==", + "license": "MIT", "dependencies": { "@types/node": "*", - "form-data": "^3.0.0" - } - }, - "node_modules/@types/node-fetch/node_modules/form-data": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", - "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" + "form-data": "^4.0.4" } }, "node_modules/asynckit": { @@ -56,6 +41,19 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -75,22 +73,181 @@ "node": ">=0.4.0" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es6-promise": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" }, "node_modules/form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { - "node": ">= 0.12" + "node": ">= 6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/inversify": { @@ -99,6 +256,15 @@ "integrity": "sha512-i9m8j/7YIv4mDuYXUAcrpKPSaju/CIly9AHK5jvCBeoiM/2KEsuCQTTP+rzSWWpLYWRukdXFSl6ZTk2/uumbiA==", "license": "MIT" }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/mime-db": { "version": "1.44.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", @@ -119,13 +285,31 @@ } }, "node_modules/node-fetch": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", - "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, "engines": { "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, "node_modules/typescript": { "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", @@ -139,41 +323,36 @@ "node": ">=4.2.0" } }, - "node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "license": "MIT" + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } } }, "dependencies": { "@types/node": { - "version": "22.10.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.5.tgz", - "integrity": "sha512-F8Q+SeGimwOo86fiovQh8qiXfFEh2/ocYv7tU5pJ3EXMSSxk1Joj5wefpFK2fHTf/N6HKGSxIDBT9f3gCxXPkQ==", - "requires": { - "undici-types": "~6.20.0" - } + "version": "16.18.126", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.126.tgz", + "integrity": "sha512-OTcgaiwfGFBKacvfwuHzzn1KLxH/er8mluiy8/uM3sGXHaRe73RrSIj01jow9t4kJEW633Ov+cOexXeiApTyAw==" }, "@types/node-fetch": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.7.tgz", - "integrity": "sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw==", + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz", + "integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==", "requires": { "@types/node": "*", - "form-data": "^3.0.0" - }, - "dependencies": { - "form-data": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", - "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - } + "form-data": "^4.0.4" } }, "asynckit": { @@ -181,6 +360,15 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, + "call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "requires": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + } + }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -194,26 +382,129 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, + "dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "requires": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + } + }, + "es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==" + }, + "es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" + }, + "es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "requires": { + "es-errors": "^1.3.0" + } + }, + "es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "requires": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + } + }, "es6-promise": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" }, "form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", "requires": { "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" + }, + "get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "requires": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + } + }, + "get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "requires": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + } + }, + "gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==" + }, + "has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==" + }, + "has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "requires": { + "has-symbols": "^1.0.3" + } + }, + "hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "requires": { + "function-bind": "^1.1.2" + } + }, "inversify": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/inversify/-/inversify-6.0.2.tgz", "integrity": "sha512-i9m8j/7YIv4mDuYXUAcrpKPSaju/CIly9AHK5jvCBeoiM/2KEsuCQTTP+rzSWWpLYWRukdXFSl6ZTk2/uumbiA==" }, + "math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==" + }, "mime-db": { "version": "1.44.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", @@ -228,9 +519,17 @@ } }, "node-fetch": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", - "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, "typescript": { "version": "4.9.5", @@ -238,10 +537,19 @@ "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "dev": true }, - "undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==" + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } } } } diff --git a/samples/openapi3/client/petstore/typescript/builds/jquery/.openapi-generator/FILES b/samples/openapi3/client/petstore/typescript/builds/jquery/.openapi-generator/FILES index 40e160f71b6e..2b30774f025f 100644 --- a/samples/openapi3/client/petstore/typescript/builds/jquery/.openapi-generator/FILES +++ b/samples/openapi3/client/petstore/typescript/builds/jquery/.openapi-generator/FILES @@ -18,10 +18,12 @@ index.ts middleware.ts models/ApiResponse.ts models/Category.ts +models/ModelTypes.ts models/ObjectSerializer.ts models/Order.ts models/Pet.ts models/Tag.ts +models/TypeMatcher.ts models/User.ts models/all.ts package.json diff --git a/samples/openapi3/client/petstore/typescript/builds/jquery/models/ApiResponse.ts b/samples/openapi3/client/petstore/typescript/builds/jquery/models/ApiResponse.ts index 3dd68507b210..ddfa26277fe4 100644 --- a/samples/openapi3/client/petstore/typescript/builds/jquery/models/ApiResponse.ts +++ b/samples/openapi3/client/petstore/typescript/builds/jquery/models/ApiResponse.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -24,24 +25,27 @@ export class ApiResponse { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "code", "baseName": "code", "type": "number", - "format": "int32" + "format": "int32", + "required": false }, { "name": "type", "baseName": "type", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "message", "baseName": "message", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/jquery/models/Category.ts b/samples/openapi3/client/petstore/typescript/builds/jquery/models/Category.ts index e025011174d3..ce325ffc3a2d 100644 --- a/samples/openapi3/client/petstore/typescript/builds/jquery/models/Category.ts +++ b/samples/openapi3/client/petstore/typescript/builds/jquery/models/Category.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -23,18 +24,20 @@ export class Category { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "name", "baseName": "name", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/jquery/models/ModelTypes.ts b/samples/openapi3/client/petstore/typescript/builds/jquery/models/ModelTypes.ts new file mode 100644 index 000000000000..24a680aba301 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/jquery/models/ModelTypes.ts @@ -0,0 +1,11 @@ +/** + * Represents a single attribute/property metadata entry in the attributeTypeMap. + * Used for validation and type matching in oneOf scenarios. + */ +export type AttributeTypeMapEntry = { + name: string; + baseName: string; + type: string; + format: string; + required: boolean; +}; diff --git a/samples/openapi3/client/petstore/typescript/builds/jquery/models/ObjectSerializer.ts b/samples/openapi3/client/petstore/typescript/builds/jquery/models/ObjectSerializer.ts index fe462a298a3a..a8ba5820cc68 100644 --- a/samples/openapi3/client/petstore/typescript/builds/jquery/models/ObjectSerializer.ts +++ b/samples/openapi3/client/petstore/typescript/builds/jquery/models/ObjectSerializer.ts @@ -116,26 +116,37 @@ export class ObjectSerializer { // Check the discriminator let discriminatorProperty = typeMap[expectedType].discriminator; - if (discriminatorProperty == null) { - return expectedType; // the type does not have a discriminator. use it. - } else { - if (data[discriminatorProperty]) { - var discriminatorType = data[discriminatorProperty]; - let mapping = typeMap[expectedType].mapping; - if (mapping != undefined && mapping[discriminatorType]) { - return mapping[discriminatorType]; // use the type given in the discriminator - } else if(typeMap[discriminatorType]) { - return discriminatorType; - } else { - return expectedType; // discriminator did not map to a type + if (discriminatorProperty == null || !data[discriminatorProperty]) { + if (this.hasFindMatchingTypeMethod(typeMap[expectedType])) { + const foundType = typeMap[expectedType].findMatchingType(data); + if (foundType == undefined) { + throw new Error("Unable to determine a unique type for the provided object: oneOf type resolution failed. The object does not match exactly one schema. Consider adding a discriminator or making schemas mutually exclusive."); } + + return foundType; + } + return expectedType; // the type does not have a discriminator and findMatchingType method. use it. + } else { + let discriminatorType = data[discriminatorProperty]; + let mapping = typeMap[expectedType].mapping; + if (mapping != undefined && mapping[discriminatorType]) { + return mapping[discriminatorType]; // use the type given in the discriminator + } else if(typeMap[discriminatorType]) { + return discriminatorType; } else { - return expectedType; // discriminator was not present (or an empty string) + throw new Error(`Discriminator property '${discriminatorProperty}' has value '${discriminatorType}' which does not map to any known type in '${expectedType}'.`); } } } } + private static hasFindMatchingTypeMethod(klass: any): boolean { + if (typeof klass.findMatchingType === 'function') { + return true; + } + return false; + } + public static serialize(data: any, type: string, format: string): any { if (data == undefined) { return data; diff --git a/samples/openapi3/client/petstore/typescript/builds/jquery/models/Order.ts b/samples/openapi3/client/petstore/typescript/builds/jquery/models/Order.ts index b8d4a26c7d47..4707dcaa7d1e 100644 --- a/samples/openapi3/client/petstore/typescript/builds/jquery/models/Order.ts +++ b/samples/openapi3/client/petstore/typescript/builds/jquery/models/Order.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -30,42 +31,48 @@ export class Order { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "petId", "baseName": "petId", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "quantity", "baseName": "quantity", "type": "number", - "format": "int32" + "format": "int32", + "required": false }, { "name": "shipDate", "baseName": "shipDate", "type": "Date", - "format": "date-time" + "format": "date-time", + "required": false }, { "name": "status", "baseName": "status", "type": "OrderStatusEnum", - "format": "" + "format": "", + "required": false }, { "name": "complete", "baseName": "complete", "type": "boolean", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/jquery/models/Pet.ts b/samples/openapi3/client/petstore/typescript/builds/jquery/models/Pet.ts index ddb68aa82a19..4b7c3b929646 100644 --- a/samples/openapi3/client/petstore/typescript/builds/jquery/models/Pet.ts +++ b/samples/openapi3/client/petstore/typescript/builds/jquery/models/Pet.ts @@ -12,6 +12,7 @@ import { Category } from '../models/Category'; import { Tag } from '../models/Tag'; +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -32,42 +33,48 @@ export class Pet { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "category", "baseName": "category", "type": "Category", - "format": "" + "format": "", + "required": false }, { "name": "name", "baseName": "name", "type": "string", - "format": "" + "format": "", + "required": true }, { "name": "photoUrls", "baseName": "photoUrls", "type": "Array", - "format": "" + "format": "", + "required": true }, { "name": "tags", "baseName": "tags", "type": "Array", - "format": "" + "format": "", + "required": false }, { "name": "status", "baseName": "status", "type": "PetStatusEnum", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/jquery/models/Tag.ts b/samples/openapi3/client/petstore/typescript/builds/jquery/models/Tag.ts index 7a7a36ba59aa..fdb52c40ddda 100644 --- a/samples/openapi3/client/petstore/typescript/builds/jquery/models/Tag.ts +++ b/samples/openapi3/client/petstore/typescript/builds/jquery/models/Tag.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -23,18 +24,20 @@ export class Tag { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "name", "baseName": "name", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/jquery/models/TypeMatcher.ts b/samples/openapi3/client/petstore/typescript/builds/jquery/models/TypeMatcher.ts new file mode 100644 index 000000000000..2f1c20864a70 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/jquery/models/TypeMatcher.ts @@ -0,0 +1,36 @@ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; + +/** + * Validates if data contains all required attributes from the attributeTypeMap. + * + * @param data - The data object to validate + * @param attributeTypeMap - Array of attribute metadata including required flag + * @returns true if all required attributes are present in data, false otherwise + */ +export function instanceOfType(data: any, attributeTypeMap: Array): boolean { + for (const attribute of attributeTypeMap) { + if (attribute.required && data[attribute.baseName] === undefined) { + return false; + } + } + + return true; +} + +/** + * Attempts to find a matching type from an array of possible types by validating + * the data against each type's attribute requirements. + * + * @param data - The data object to match + * @param types - Array of possible type constructors + * @returns The name of the matching type, or undefined if no match found + */ +export function findMatchingType(data: any, types: Array): string | undefined { + for (const type of types) { + if (instanceOfType(data, type.getAttributeTypeMap())) { + return type.name; + } + } + + return undefined; +} \ No newline at end of file diff --git a/samples/openapi3/client/petstore/typescript/builds/jquery/models/User.ts b/samples/openapi3/client/petstore/typescript/builds/jquery/models/User.ts index 4dbe18f7fed4..a8338193852e 100644 --- a/samples/openapi3/client/petstore/typescript/builds/jquery/models/User.ts +++ b/samples/openapi3/client/petstore/typescript/builds/jquery/models/User.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -32,54 +33,62 @@ export class User { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "username", "baseName": "username", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "firstName", "baseName": "firstName", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "lastName", "baseName": "lastName", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "email", "baseName": "email", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "password", "baseName": "password", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "phone", "baseName": "phone", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "userStatus", "baseName": "userStatus", "type": "number", - "format": "int32" + "format": "int32", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/jquery/models/all.ts b/samples/openapi3/client/petstore/typescript/builds/jquery/models/all.ts index d63b43c96744..101927e7b61e 100644 --- a/samples/openapi3/client/petstore/typescript/builds/jquery/models/all.ts +++ b/samples/openapi3/client/petstore/typescript/builds/jquery/models/all.ts @@ -4,3 +4,5 @@ export * from '../models/Order' export * from '../models/Pet' export * from '../models/Tag' export * from '../models/User' +export * from './TypeMatcher' +export * from './ModelTypes' \ No newline at end of file diff --git a/samples/openapi3/client/petstore/typescript/builds/nullable-enum/.openapi-generator/FILES b/samples/openapi3/client/petstore/typescript/builds/nullable-enum/.openapi-generator/FILES index e770a65f9adc..967532c08b50 100644 --- a/samples/openapi3/client/petstore/typescript/builds/nullable-enum/.openapi-generator/FILES +++ b/samples/openapi3/client/petstore/typescript/builds/nullable-enum/.openapi-generator/FILES @@ -12,8 +12,10 @@ http/http.ts http/isomorphic-fetch.ts index.ts middleware.ts +models/ModelTypes.ts models/ObjectSerializer.ts models/Response.ts +models/TypeMatcher.ts models/all.ts package.json rxjsStub.ts diff --git a/samples/openapi3/client/petstore/typescript/builds/nullable-enum/models/ModelTypes.ts b/samples/openapi3/client/petstore/typescript/builds/nullable-enum/models/ModelTypes.ts new file mode 100644 index 000000000000..24a680aba301 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/nullable-enum/models/ModelTypes.ts @@ -0,0 +1,11 @@ +/** + * Represents a single attribute/property metadata entry in the attributeTypeMap. + * Used for validation and type matching in oneOf scenarios. + */ +export type AttributeTypeMapEntry = { + name: string; + baseName: string; + type: string; + format: string; + required: boolean; +}; diff --git a/samples/openapi3/client/petstore/typescript/builds/nullable-enum/models/ObjectSerializer.ts b/samples/openapi3/client/petstore/typescript/builds/nullable-enum/models/ObjectSerializer.ts index e02fd5f3757b..25f98324938d 100644 --- a/samples/openapi3/client/petstore/typescript/builds/nullable-enum/models/ObjectSerializer.ts +++ b/samples/openapi3/client/petstore/typescript/builds/nullable-enum/models/ObjectSerializer.ts @@ -100,26 +100,37 @@ export class ObjectSerializer { // Check the discriminator let discriminatorProperty = typeMap[expectedType].discriminator; - if (discriminatorProperty == null) { - return expectedType; // the type does not have a discriminator. use it. - } else { - if (data[discriminatorProperty]) { - var discriminatorType = data[discriminatorProperty]; - let mapping = typeMap[expectedType].mapping; - if (mapping != undefined && mapping[discriminatorType]) { - return mapping[discriminatorType]; // use the type given in the discriminator - } else if(typeMap[discriminatorType]) { - return discriminatorType; - } else { - return expectedType; // discriminator did not map to a type + if (discriminatorProperty == null || !data[discriminatorProperty]) { + if (this.hasFindMatchingTypeMethod(typeMap[expectedType])) { + const foundType = typeMap[expectedType].findMatchingType(data); + if (foundType == undefined) { + throw new Error("Unable to determine a unique type for the provided object: oneOf type resolution failed. The object does not match exactly one schema. Consider adding a discriminator or making schemas mutually exclusive."); } + + return foundType; + } + return expectedType; // the type does not have a discriminator and findMatchingType method. use it. + } else { + let discriminatorType = data[discriminatorProperty]; + let mapping = typeMap[expectedType].mapping; + if (mapping != undefined && mapping[discriminatorType]) { + return mapping[discriminatorType]; // use the type given in the discriminator + } else if(typeMap[discriminatorType]) { + return discriminatorType; } else { - return expectedType; // discriminator was not present (or an empty string) + throw new Error(`Discriminator property '${discriminatorProperty}' has value '${discriminatorType}' which does not map to any known type in '${expectedType}'.`); } } } } + private static hasFindMatchingTypeMethod(klass: any): boolean { + if (typeof klass.findMatchingType === 'function') { + return true; + } + return false; + } + public static serialize(data: any, type: string, format: string): any { if (data == undefined) { return data; diff --git a/samples/openapi3/client/petstore/typescript/builds/nullable-enum/models/Response.ts b/samples/openapi3/client/petstore/typescript/builds/nullable-enum/models/Response.ts index 80fb76ed3b99..521c856e7c96 100644 --- a/samples/openapi3/client/petstore/typescript/builds/nullable-enum/models/Response.ts +++ b/samples/openapi3/client/petstore/typescript/builds/nullable-enum/models/Response.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; export class Response { @@ -22,12 +23,13 @@ export class Response { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "enrichmentSource", "baseName": "enrichmentSource", "type": "ResponseEnrichmentSourceEnum", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/nullable-enum/models/TypeMatcher.ts b/samples/openapi3/client/petstore/typescript/builds/nullable-enum/models/TypeMatcher.ts new file mode 100644 index 000000000000..2f1c20864a70 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/nullable-enum/models/TypeMatcher.ts @@ -0,0 +1,36 @@ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; + +/** + * Validates if data contains all required attributes from the attributeTypeMap. + * + * @param data - The data object to validate + * @param attributeTypeMap - Array of attribute metadata including required flag + * @returns true if all required attributes are present in data, false otherwise + */ +export function instanceOfType(data: any, attributeTypeMap: Array): boolean { + for (const attribute of attributeTypeMap) { + if (attribute.required && data[attribute.baseName] === undefined) { + return false; + } + } + + return true; +} + +/** + * Attempts to find a matching type from an array of possible types by validating + * the data against each type's attribute requirements. + * + * @param data - The data object to match + * @param types - Array of possible type constructors + * @returns The name of the matching type, or undefined if no match found + */ +export function findMatchingType(data: any, types: Array): string | undefined { + for (const type of types) { + if (instanceOfType(data, type.getAttributeTypeMap())) { + return type.name; + } + } + + return undefined; +} \ No newline at end of file diff --git a/samples/openapi3/client/petstore/typescript/builds/nullable-enum/models/all.ts b/samples/openapi3/client/petstore/typescript/builds/nullable-enum/models/all.ts index fb6a6246f9a8..9a0dc8a32bc5 100644 --- a/samples/openapi3/client/petstore/typescript/builds/nullable-enum/models/all.ts +++ b/samples/openapi3/client/petstore/typescript/builds/nullable-enum/models/all.ts @@ -1 +1,3 @@ export * from '../models/Response' +export * from './TypeMatcher' +export * from './ModelTypes' \ No newline at end of file diff --git a/samples/openapi3/client/petstore/typescript/builds/object_params/.openapi-generator/FILES b/samples/openapi3/client/petstore/typescript/builds/object_params/.openapi-generator/FILES index 125c3a493a13..0207ab042492 100644 --- a/samples/openapi3/client/petstore/typescript/builds/object_params/.openapi-generator/FILES +++ b/samples/openapi3/client/petstore/typescript/builds/object_params/.openapi-generator/FILES @@ -18,10 +18,12 @@ index.ts middleware.ts models/ApiResponse.ts models/Category.ts +models/ModelTypes.ts models/ObjectSerializer.ts models/Order.ts models/Pet.ts models/Tag.ts +models/TypeMatcher.ts models/User.ts models/all.ts package.json diff --git a/samples/openapi3/client/petstore/typescript/builds/object_params/models/ApiResponse.ts b/samples/openapi3/client/petstore/typescript/builds/object_params/models/ApiResponse.ts index 3dd68507b210..ddfa26277fe4 100644 --- a/samples/openapi3/client/petstore/typescript/builds/object_params/models/ApiResponse.ts +++ b/samples/openapi3/client/petstore/typescript/builds/object_params/models/ApiResponse.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -24,24 +25,27 @@ export class ApiResponse { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "code", "baseName": "code", "type": "number", - "format": "int32" + "format": "int32", + "required": false }, { "name": "type", "baseName": "type", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "message", "baseName": "message", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/object_params/models/Category.ts b/samples/openapi3/client/petstore/typescript/builds/object_params/models/Category.ts index e025011174d3..ce325ffc3a2d 100644 --- a/samples/openapi3/client/petstore/typescript/builds/object_params/models/Category.ts +++ b/samples/openapi3/client/petstore/typescript/builds/object_params/models/Category.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -23,18 +24,20 @@ export class Category { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "name", "baseName": "name", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/object_params/models/ModelTypes.ts b/samples/openapi3/client/petstore/typescript/builds/object_params/models/ModelTypes.ts new file mode 100644 index 000000000000..24a680aba301 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/object_params/models/ModelTypes.ts @@ -0,0 +1,11 @@ +/** + * Represents a single attribute/property metadata entry in the attributeTypeMap. + * Used for validation and type matching in oneOf scenarios. + */ +export type AttributeTypeMapEntry = { + name: string; + baseName: string; + type: string; + format: string; + required: boolean; +}; diff --git a/samples/openapi3/client/petstore/typescript/builds/object_params/models/ObjectSerializer.ts b/samples/openapi3/client/petstore/typescript/builds/object_params/models/ObjectSerializer.ts index fe462a298a3a..a8ba5820cc68 100644 --- a/samples/openapi3/client/petstore/typescript/builds/object_params/models/ObjectSerializer.ts +++ b/samples/openapi3/client/petstore/typescript/builds/object_params/models/ObjectSerializer.ts @@ -116,26 +116,37 @@ export class ObjectSerializer { // Check the discriminator let discriminatorProperty = typeMap[expectedType].discriminator; - if (discriminatorProperty == null) { - return expectedType; // the type does not have a discriminator. use it. - } else { - if (data[discriminatorProperty]) { - var discriminatorType = data[discriminatorProperty]; - let mapping = typeMap[expectedType].mapping; - if (mapping != undefined && mapping[discriminatorType]) { - return mapping[discriminatorType]; // use the type given in the discriminator - } else if(typeMap[discriminatorType]) { - return discriminatorType; - } else { - return expectedType; // discriminator did not map to a type + if (discriminatorProperty == null || !data[discriminatorProperty]) { + if (this.hasFindMatchingTypeMethod(typeMap[expectedType])) { + const foundType = typeMap[expectedType].findMatchingType(data); + if (foundType == undefined) { + throw new Error("Unable to determine a unique type for the provided object: oneOf type resolution failed. The object does not match exactly one schema. Consider adding a discriminator or making schemas mutually exclusive."); } + + return foundType; + } + return expectedType; // the type does not have a discriminator and findMatchingType method. use it. + } else { + let discriminatorType = data[discriminatorProperty]; + let mapping = typeMap[expectedType].mapping; + if (mapping != undefined && mapping[discriminatorType]) { + return mapping[discriminatorType]; // use the type given in the discriminator + } else if(typeMap[discriminatorType]) { + return discriminatorType; } else { - return expectedType; // discriminator was not present (or an empty string) + throw new Error(`Discriminator property '${discriminatorProperty}' has value '${discriminatorType}' which does not map to any known type in '${expectedType}'.`); } } } } + private static hasFindMatchingTypeMethod(klass: any): boolean { + if (typeof klass.findMatchingType === 'function') { + return true; + } + return false; + } + public static serialize(data: any, type: string, format: string): any { if (data == undefined) { return data; diff --git a/samples/openapi3/client/petstore/typescript/builds/object_params/models/Order.ts b/samples/openapi3/client/petstore/typescript/builds/object_params/models/Order.ts index b8d4a26c7d47..4707dcaa7d1e 100644 --- a/samples/openapi3/client/petstore/typescript/builds/object_params/models/Order.ts +++ b/samples/openapi3/client/petstore/typescript/builds/object_params/models/Order.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -30,42 +31,48 @@ export class Order { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "petId", "baseName": "petId", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "quantity", "baseName": "quantity", "type": "number", - "format": "int32" + "format": "int32", + "required": false }, { "name": "shipDate", "baseName": "shipDate", "type": "Date", - "format": "date-time" + "format": "date-time", + "required": false }, { "name": "status", "baseName": "status", "type": "OrderStatusEnum", - "format": "" + "format": "", + "required": false }, { "name": "complete", "baseName": "complete", "type": "boolean", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/object_params/models/Pet.ts b/samples/openapi3/client/petstore/typescript/builds/object_params/models/Pet.ts index ddb68aa82a19..4b7c3b929646 100644 --- a/samples/openapi3/client/petstore/typescript/builds/object_params/models/Pet.ts +++ b/samples/openapi3/client/petstore/typescript/builds/object_params/models/Pet.ts @@ -12,6 +12,7 @@ import { Category } from '../models/Category'; import { Tag } from '../models/Tag'; +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -32,42 +33,48 @@ export class Pet { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "category", "baseName": "category", "type": "Category", - "format": "" + "format": "", + "required": false }, { "name": "name", "baseName": "name", "type": "string", - "format": "" + "format": "", + "required": true }, { "name": "photoUrls", "baseName": "photoUrls", "type": "Array", - "format": "" + "format": "", + "required": true }, { "name": "tags", "baseName": "tags", "type": "Array", - "format": "" + "format": "", + "required": false }, { "name": "status", "baseName": "status", "type": "PetStatusEnum", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/object_params/models/Tag.ts b/samples/openapi3/client/petstore/typescript/builds/object_params/models/Tag.ts index 7a7a36ba59aa..fdb52c40ddda 100644 --- a/samples/openapi3/client/petstore/typescript/builds/object_params/models/Tag.ts +++ b/samples/openapi3/client/petstore/typescript/builds/object_params/models/Tag.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -23,18 +24,20 @@ export class Tag { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "name", "baseName": "name", "type": "string", - "format": "" + "format": "", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/object_params/models/TypeMatcher.ts b/samples/openapi3/client/petstore/typescript/builds/object_params/models/TypeMatcher.ts new file mode 100644 index 000000000000..2f1c20864a70 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/object_params/models/TypeMatcher.ts @@ -0,0 +1,36 @@ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; + +/** + * Validates if data contains all required attributes from the attributeTypeMap. + * + * @param data - The data object to validate + * @param attributeTypeMap - Array of attribute metadata including required flag + * @returns true if all required attributes are present in data, false otherwise + */ +export function instanceOfType(data: any, attributeTypeMap: Array): boolean { + for (const attribute of attributeTypeMap) { + if (attribute.required && data[attribute.baseName] === undefined) { + return false; + } + } + + return true; +} + +/** + * Attempts to find a matching type from an array of possible types by validating + * the data against each type's attribute requirements. + * + * @param data - The data object to match + * @param types - Array of possible type constructors + * @returns The name of the matching type, or undefined if no match found + */ +export function findMatchingType(data: any, types: Array): string | undefined { + for (const type of types) { + if (instanceOfType(data, type.getAttributeTypeMap())) { + return type.name; + } + } + + return undefined; +} \ No newline at end of file diff --git a/samples/openapi3/client/petstore/typescript/builds/object_params/models/User.ts b/samples/openapi3/client/petstore/typescript/builds/object_params/models/User.ts index 4dbe18f7fed4..a8338193852e 100644 --- a/samples/openapi3/client/petstore/typescript/builds/object_params/models/User.ts +++ b/samples/openapi3/client/petstore/typescript/builds/object_params/models/User.ts @@ -10,6 +10,7 @@ * Do not edit the class manually. */ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; import { HttpFile } from '../http/http'; /** @@ -32,54 +33,62 @@ export class User { static readonly mapping: {[index: string]: string} | undefined = undefined; - static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [ + static readonly attributeTypeMap: Array = [ { "name": "id", "baseName": "id", "type": "number", - "format": "int64" + "format": "int64", + "required": false }, { "name": "username", "baseName": "username", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "firstName", "baseName": "firstName", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "lastName", "baseName": "lastName", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "email", "baseName": "email", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "password", "baseName": "password", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "phone", "baseName": "phone", "type": "string", - "format": "" + "format": "", + "required": false }, { "name": "userStatus", "baseName": "userStatus", "type": "number", - "format": "int32" + "format": "int32", + "required": false } ]; static getAttributeTypeMap() { diff --git a/samples/openapi3/client/petstore/typescript/builds/object_params/models/all.ts b/samples/openapi3/client/petstore/typescript/builds/object_params/models/all.ts index d63b43c96744..101927e7b61e 100644 --- a/samples/openapi3/client/petstore/typescript/builds/object_params/models/all.ts +++ b/samples/openapi3/client/petstore/typescript/builds/object_params/models/all.ts @@ -4,3 +4,5 @@ export * from '../models/Order' export * from '../models/Pet' export * from '../models/Tag' export * from '../models/User' +export * from './TypeMatcher' +export * from './ModelTypes' \ No newline at end of file diff --git a/samples/openapi3/client/petstore/typescript/builds/object_params/package-lock.json b/samples/openapi3/client/petstore/typescript/builds/object_params/package-lock.json index a35cc310ad6a..9db21b8632e9 100644 --- a/samples/openapi3/client/petstore/typescript/builds/object_params/package-lock.json +++ b/samples/openapi3/client/petstore/typescript/builds/object_params/package-lock.json @@ -9,41 +9,30 @@ "version": "1.0.0", "license": "Unlicense", "dependencies": { - "@types/node": "*", - "@types/node-fetch": "^2.5.7", + "@types/node": "^16.18.126", + "@types/node-fetch": "^2.6.13", "es6-promise": "^4.2.4", - "form-data": "^2.5.0", - "node-fetch": "^2.6.0" + "form-data": "^4.0.4", + "node-fetch": "^2.7.0" }, "devDependencies": { "typescript": "^4.0" } }, "node_modules/@types/node": { - "version": "14.0.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.6.tgz", - "integrity": "sha512-FbNmu4F67d3oZMWBV6Y4MaPER+0EpE9eIYf2yaHhCWovc1dlXCZkqGX4NLHfVVr6umt20TNBdRzrNJIzIKfdbw==" + "version": "16.18.126", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.126.tgz", + "integrity": "sha512-OTcgaiwfGFBKacvfwuHzzn1KLxH/er8mluiy8/uM3sGXHaRe73RrSIj01jow9t4kJEW633Ov+cOexXeiApTyAw==", + "license": "MIT" }, "node_modules/@types/node-fetch": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.7.tgz", - "integrity": "sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw==", + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz", + "integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==", + "license": "MIT", "dependencies": { "@types/node": "*", - "form-data": "^3.0.0" - } - }, - "node_modules/@types/node-fetch/node_modules/form-data": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", - "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" + "form-data": "^4.0.4" } }, "node_modules/asynckit": { @@ -51,6 +40,19 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -70,22 +72,190 @@ "node": ">=0.4.0" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es6-promise": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" }, "node_modules/form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { - "node": ">= 0.12" + "node": ">= 6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" } }, "node_modules/mime-db": { @@ -108,13 +278,31 @@ } }, "node_modules/node-fetch": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", - "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, "engines": { "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, "node_modules/typescript": { "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", @@ -127,33 +315,37 @@ "engines": { "node": ">=4.2.0" } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } } }, "dependencies": { "@types/node": { - "version": "14.0.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.6.tgz", - "integrity": "sha512-FbNmu4F67d3oZMWBV6Y4MaPER+0EpE9eIYf2yaHhCWovc1dlXCZkqGX4NLHfVVr6umt20TNBdRzrNJIzIKfdbw==" + "version": "16.18.126", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.126.tgz", + "integrity": "sha512-OTcgaiwfGFBKacvfwuHzzn1KLxH/er8mluiy8/uM3sGXHaRe73RrSIj01jow9t4kJEW633Ov+cOexXeiApTyAw==" }, "@types/node-fetch": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.7.tgz", - "integrity": "sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw==", + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz", + "integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==", "requires": { "@types/node": "*", - "form-data": "^3.0.0" - }, - "dependencies": { - "form-data": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", - "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - } + "form-data": "^4.0.4" } }, "asynckit": { @@ -161,6 +353,15 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, + "call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "requires": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + } + }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -174,21 +375,124 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, + "dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "requires": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + } + }, + "es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==" + }, + "es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" + }, + "es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "requires": { + "es-errors": "^1.3.0" + } + }, + "es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "requires": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + } + }, "es6-promise": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" }, "form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", "requires": { "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" + }, + "get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "requires": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + } + }, + "get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "requires": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + } + }, + "gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==" + }, + "has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==" + }, + "has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "requires": { + "has-symbols": "^1.0.3" + } + }, + "hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "requires": { + "function-bind": "^1.1.2" + } + }, + "math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==" + }, "mime-db": { "version": "1.44.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", @@ -203,15 +507,37 @@ } }, "node-fetch": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", - "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, "typescript": { "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "dev": true + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } } } } diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/.gitattributes b/samples/openapi3/client/petstore/typescript/builds/one-of/.gitattributes new file mode 100644 index 000000000000..7bf5a17b22f1 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/.gitattributes @@ -0,0 +1,8 @@ +**/* linguist-generated +*.md linguist-documentation + +.gitattributes text +.gitattributes export-ignore + +.gitignore text +.gitignore export-ignore diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/.gitignore b/samples/openapi3/client/petstore/typescript/builds/one-of/.gitignore new file mode 100644 index 000000000000..1521c8b7652b --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/.gitignore @@ -0,0 +1 @@ +dist diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/.openapi-generator-ignore b/samples/openapi3/client/petstore/typescript/builds/one-of/.openapi-generator-ignore new file mode 100644 index 000000000000..7484ee590a38 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/.openapi-generator-ignore @@ -0,0 +1,23 @@ +# OpenAPI Generator Ignore +# Generated by openapi-generator https://github.com/openapitools/openapi-generator + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/.openapi-generator/FILES b/samples/openapi3/client/petstore/typescript/builds/one-of/.openapi-generator/FILES new file mode 100644 index 000000000000..d8c28a3b613c --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/.openapi-generator/FILES @@ -0,0 +1,31 @@ +.gitattributes +.gitignore +.openapi-generator-ignore +DefaultApi.md +README.md +apis/DefaultApi.ts +apis/baseapi.ts +apis/exception.ts +auth/auth.ts +configuration.ts +git_push.sh +http/http.ts +http/isomorphic-fetch.ts +index.ts +middleware.ts +models/Cat.ts +models/Dog.ts +models/ModelTypes.ts +models/ObjectSerializer.ts +models/PetDiscriminatorResponse.ts +models/PetResponse.ts +models/TypeMatcher.ts +models/all.ts +package.json +rxjsStub.ts +servers.ts +tsconfig.json +types/ObjectParamAPI.ts +types/ObservableAPI.ts +types/PromiseAPI.ts +util.ts diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/.openapi-generator/VERSION b/samples/openapi3/client/petstore/typescript/builds/one-of/.openapi-generator/VERSION new file mode 100644 index 000000000000..9e0e9bce84b2 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/.openapi-generator/VERSION @@ -0,0 +1 @@ +7.17.0-SNAPSHOT diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/DefaultApi.md b/samples/openapi3/client/petstore/typescript/builds/one-of/DefaultApi.md new file mode 100644 index 000000000000..6cf991a374dd --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/DefaultApi.md @@ -0,0 +1,101 @@ +# petstore.DefaultApi + +All URIs are relative to *http://localhost:3000* + +Method | HTTP request | Description +------------- | ------------- | ------------- +[**testDiscriminator**](DefaultApi.md#testDiscriminator) | **GET** /test-discriminator | +[**testWithoutDiscriminator**](DefaultApi.md#testWithoutDiscriminator) | **GET** /test | + + +# **testDiscriminator** +> PetDiscriminatorResponse testDiscriminator() + + +### Example + + +```typescript +import { createConfiguration, DefaultApi } from 'ts-petstore-client'; + +const configuration = createConfiguration(); +const apiInstance = new DefaultApi(configuration); + +const request = {}; + +const data = await apiInstance.testDiscriminator(request); +console.log('API called successfully. Returned data:', data); +``` + + +### Parameters +This endpoint does not need any parameter. + + +### Return type + +**PetDiscriminatorResponse** + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: application/json + + +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | OK | - | + +[[Back to top]](#) [[Back to API list]](README.md#documentation-for-api-endpoints) [[Back to Model list]](README.md#documentation-for-models) [[Back to README]](README.md) + +# **testWithoutDiscriminator** +> PetResponse testWithoutDiscriminator() + + +### Example + + +```typescript +import { createConfiguration, DefaultApi } from 'ts-petstore-client'; + +const configuration = createConfiguration(); +const apiInstance = new DefaultApi(configuration); + +const request = {}; + +const data = await apiInstance.testWithoutDiscriminator(request); +console.log('API called successfully. Returned data:', data); +``` + + +### Parameters +This endpoint does not need any parameter. + + +### Return type + +**PetResponse** + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: application/json + + +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | OK | - | + +[[Back to top]](#) [[Back to API list]](README.md#documentation-for-api-endpoints) [[Back to Model list]](README.md#documentation-for-models) [[Back to README]](README.md) + + diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/README.md b/samples/openapi3/client/petstore/typescript/builds/one-of/README.md new file mode 100644 index 000000000000..325283a66322 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/README.md @@ -0,0 +1,80 @@ +## ts-petstore-client@1.0.0 + +This generator creates TypeScript/JavaScript client that utilizes fetch-api. + +### Building + +To build and compile the typescript sources to javascript use: +``` +npm install +npm run build +``` + +### Publishing + +First build the package then run ```npm publish``` + +### Consuming + +Navigate to the folder of your consuming project and run one of the following commands. + +_published:_ + +``` +npm install ts-petstore-client@1.0.0 --save +``` + +_unPublished (not recommended):_ + +``` +npm install PATH_TO_GENERATED_PACKAGE --save +``` + +### Usage + +Below code snippet shows exemplary usage of the configuration and the API based +on the typical `PetStore` example used for OpenAPI. + +``` +import * as your_api from 'your_api_package' + +// Covers all auth methods included in your OpenAPI yaml definition +const authConfig: your_api.AuthMethodsConfiguration = { + "api_key": "YOUR_API_KEY" +} + +// Implements a simple middleware to modify requests before (`pre`) they are sent +// and after (`post`) they have been received +class Test implements your_api.Middleware { + pre(context: your_api.RequestContext): Promise { + // Modify context here and return + return Promise.resolve(context); + } + + post(context: your_api.ResponseContext): Promise { + return Promise.resolve(context); + } + +} + +// Create configuration parameter object +const configurationParameters = { + httpApi: new your_api.JQueryHttpLibrary(), // Can also be ignored - default is usually fine + baseServer: your_api.servers[0], // First server is default + authMethods: authConfig, // No auth is default + promiseMiddleware: [new Test()], +} + +// Convert to actual configuration +const config = your_api.createConfiguration(configurationParameters); + +// Use configuration with your_api +const api = new your_api.PetApi(config); +your_api.Pet p = new your_api.Pet(); +p.name = "My new pet"; +p.photoUrls = []; +p.tags = []; +p.status = "available"; +Promise createdPet = api.addPet(p); + +``` diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/apis/DefaultApi.ts b/samples/openapi3/client/petstore/typescript/builds/one-of/apis/DefaultApi.ts new file mode 100644 index 000000000000..401da63300f2 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/apis/DefaultApi.ts @@ -0,0 +1,127 @@ +// TODO: better import syntax? +import {BaseAPIRequestFactory, RequiredError, COLLECTION_FORMATS} from './baseapi'; +import {Configuration} from '../configuration'; +import {RequestContext, HttpMethod, ResponseContext, HttpFile, HttpInfo} from '../http/http'; +import * as FormData from "form-data"; +import { URLSearchParams } from 'url'; +import {ObjectSerializer} from '../models/ObjectSerializer'; +import {ApiException} from './exception'; +import {canConsumeForm, isCodeInRange} from '../util'; +import {SecurityAuthentication} from '../auth/auth'; + + +import { PetDiscriminatorResponse } from '../models/PetDiscriminatorResponse'; +import { PetResponse } from '../models/PetResponse'; + +/** + * no description + */ +export class DefaultApiRequestFactory extends BaseAPIRequestFactory { + + /** + */ + public async testDiscriminator(_options?: Configuration): Promise { + let _config = _options || this.configuration; + + // Path Params + const localVarPath = '/test-discriminator'; + + // Make Request Context + const requestContext = _config.baseServer.makeRequestContext(localVarPath, HttpMethod.GET); + requestContext.setHeaderParam("Accept", "application/json, */*;q=0.8") + + + + const defaultAuth: SecurityAuthentication | undefined = _config?.authMethods?.default + if (defaultAuth?.applySecurityAuthentication) { + await defaultAuth?.applySecurityAuthentication(requestContext); + } + + return requestContext; + } + + /** + */ + public async testWithoutDiscriminator(_options?: Configuration): Promise { + let _config = _options || this.configuration; + + // Path Params + const localVarPath = '/test'; + + // Make Request Context + const requestContext = _config.baseServer.makeRequestContext(localVarPath, HttpMethod.GET); + requestContext.setHeaderParam("Accept", "application/json, */*;q=0.8") + + + + const defaultAuth: SecurityAuthentication | undefined = _config?.authMethods?.default + if (defaultAuth?.applySecurityAuthentication) { + await defaultAuth?.applySecurityAuthentication(requestContext); + } + + return requestContext; + } + +} + +export class DefaultApiResponseProcessor { + + /** + * Unwraps the actual response sent by the server from the response context and deserializes the response content + * to the expected objects + * + * @params response Response returned by the server for a request to testDiscriminator + * @throws ApiException if the response code was not in [200, 299] + */ + public async testDiscriminatorWithHttpInfo(response: ResponseContext): Promise> { + const contentType = ObjectSerializer.normalizeMediaType(response.headers["content-type"]); + if (isCodeInRange("200", response.httpStatusCode)) { + const body: PetDiscriminatorResponse = ObjectSerializer.deserialize( + ObjectSerializer.parse(await response.body.text(), contentType), + "PetDiscriminatorResponse", "" + ) as PetDiscriminatorResponse; + return new HttpInfo(response.httpStatusCode, response.headers, response.body, body); + } + + // Work around for missing responses in specification, e.g. for petstore.yaml + if (response.httpStatusCode >= 200 && response.httpStatusCode <= 299) { + const body: PetDiscriminatorResponse = ObjectSerializer.deserialize( + ObjectSerializer.parse(await response.body.text(), contentType), + "PetDiscriminatorResponse", "" + ) as PetDiscriminatorResponse; + return new HttpInfo(response.httpStatusCode, response.headers, response.body, body); + } + + throw new ApiException(response.httpStatusCode, "Unknown API Status Code!", await response.getBodyAsAny(), response.headers); + } + + /** + * Unwraps the actual response sent by the server from the response context and deserializes the response content + * to the expected objects + * + * @params response Response returned by the server for a request to testWithoutDiscriminator + * @throws ApiException if the response code was not in [200, 299] + */ + public async testWithoutDiscriminatorWithHttpInfo(response: ResponseContext): Promise> { + const contentType = ObjectSerializer.normalizeMediaType(response.headers["content-type"]); + if (isCodeInRange("200", response.httpStatusCode)) { + const body: PetResponse = ObjectSerializer.deserialize( + ObjectSerializer.parse(await response.body.text(), contentType), + "PetResponse", "" + ) as PetResponse; + return new HttpInfo(response.httpStatusCode, response.headers, response.body, body); + } + + // Work around for missing responses in specification, e.g. for petstore.yaml + if (response.httpStatusCode >= 200 && response.httpStatusCode <= 299) { + const body: PetResponse = ObjectSerializer.deserialize( + ObjectSerializer.parse(await response.body.text(), contentType), + "PetResponse", "" + ) as PetResponse; + return new HttpInfo(response.httpStatusCode, response.headers, response.body, body); + } + + throw new ApiException(response.httpStatusCode, "Unknown API Status Code!", await response.getBodyAsAny(), response.headers); + } + +} diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/apis/baseapi.ts b/samples/openapi3/client/petstore/typescript/builds/one-of/apis/baseapi.ts new file mode 100644 index 000000000000..4c47d7cb15a0 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/apis/baseapi.ts @@ -0,0 +1,37 @@ +import { Configuration } from '../configuration' + +/** + * + * @export + */ +export const COLLECTION_FORMATS = { + csv: ",", + ssv: " ", + tsv: "\t", + pipes: "|", +}; + + +/** + * + * @export + * @class BaseAPI + */ +export class BaseAPIRequestFactory { + + constructor(protected configuration: Configuration) { + } +}; + +/** + * + * @export + * @class RequiredError + * @extends {Error} + */ +export class RequiredError extends Error { + override name: "RequiredError" = "RequiredError"; + constructor(public api: string, public method: string, public field: string) { + super("Required parameter " + field + " was null or undefined when calling " + api + "." + method + "."); + } +} diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/apis/exception.ts b/samples/openapi3/client/petstore/typescript/builds/one-of/apis/exception.ts new file mode 100644 index 000000000000..00f294ce4564 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/apis/exception.ts @@ -0,0 +1,15 @@ +/** + * Represents an error caused by an api call i.e. it has attributes for a HTTP status code + * and the returned body object. + * + * Example + * API returns a ErrorMessageObject whenever HTTP status code is not in [200, 299] + * => ApiException(404, someErrorMessageObject) + * + */ +export class ApiException extends Error { + public constructor(public code: number, message: string, public body: T, public headers: { [key: string]: string; }) { + super("HTTP-Code: " + code + "\nMessage: " + message + "\nBody: " + JSON.stringify(body) + "\nHeaders: " + + JSON.stringify(headers)); + } +} \ No newline at end of file diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/auth/auth.ts b/samples/openapi3/client/petstore/typescript/builds/one-of/auth/auth.ts new file mode 100644 index 000000000000..99785a254177 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/auth/auth.ts @@ -0,0 +1,51 @@ +import { RequestContext } from "../http/http"; + +/** + * Interface authentication schemes. + */ +export interface SecurityAuthentication { + /* + * @return returns the name of the security authentication as specified in OAI + */ + getName(): string; + + /** + * Applies the authentication scheme to the request context + * + * @params context the request context which should use this authentication scheme + */ + applySecurityAuthentication(context: RequestContext): void | Promise; +} + +export interface TokenProvider { + getToken(): Promise | string; +} + +export type AuthMethods = { + "default"?: SecurityAuthentication, +} + +export type ApiKeyConfiguration = string; +export type HttpBasicConfiguration = { "username": string, "password": string }; +export type HttpBearerConfiguration = { tokenProvider: TokenProvider }; +export type OAuth2Configuration = { accessToken: string }; +export type HttpSignatureConfiguration = unknown; // TODO: Implement + +export type AuthMethodsConfiguration = { + "default"?: SecurityAuthentication, +} + +/** + * Creates the authentication methods from a swagger description. + * + */ +export function configureAuthMethods(config: AuthMethodsConfiguration | undefined): AuthMethods { + let authMethods: AuthMethods = {} + + if (!config) { + return authMethods; + } + authMethods["default"] = config["default"] + + return authMethods; +} \ No newline at end of file diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/configuration.ts b/samples/openapi3/client/petstore/typescript/builds/one-of/configuration.ts new file mode 100644 index 000000000000..4e654728905c --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/configuration.ts @@ -0,0 +1,143 @@ +import { HttpLibrary } from "./http/http"; +import { Middleware, PromiseMiddleware, PromiseMiddlewareWrapper } from "./middleware"; +import { IsomorphicFetchHttpLibrary as DefaultHttpLibrary } from "./http/isomorphic-fetch"; +import { BaseServerConfiguration, server1 } from "./servers"; +import { configureAuthMethods, AuthMethods, AuthMethodsConfiguration } from "./auth/auth"; + +export interface Configuration { + readonly baseServer: BaseServerConfiguration; + readonly httpApi: HttpLibrary; + readonly middleware: M[]; + readonly authMethods: AuthMethods; +} + +// Additional option specific to middleware merge strategy +export interface MiddlewareMergeOptions { + // default is `"replace"` for backwards compatibility + middlewareMergeStrategy?: "replace" | "append" | "prepend"; +} + +// Unify configuration options using Partial plus extra merge strategy +export type ConfigurationOptions = Partial> & MiddlewareMergeOptions; + +// aliases for convenience +export type StandardConfigurationOptions = ConfigurationOptions; +export type PromiseConfigurationOptions = ConfigurationOptions; + +/** + * Interface with which a configuration object can be configured. + */ +export interface ConfigurationParameters { + /** + * Default server to use - a list of available servers (according to the + * OpenAPI yaml definition) is included in the `servers` const in `./servers`. You can also + * create your own server with the `ServerConfiguration` class from the same + * file. + */ + baseServer?: BaseServerConfiguration; + /** + * HTTP library to use e.g. IsomorphicFetch. This can usually be skipped as + * all generators come with a default library. + * If available, additional libraries can be imported from `./http/*` + */ + httpApi?: HttpLibrary; + + /** + * The middlewares which will be applied to requests and responses. You can + * add any number of middleware components to modify requests before they + * are sent or before they are deserialized by implementing the `Middleware` + * interface defined in `./middleware` + */ + middleware?: Middleware[]; + /** + * Configures middleware functions that return promises instead of + * Observables (which are used by `middleware`). Otherwise allows for the + * same functionality as `middleware`, i.e., modifying requests before they + * are sent and before they are deserialized. + */ + promiseMiddleware?: PromiseMiddleware[]; + /** + * Configuration for the available authentication methods (e.g., api keys) + * according to the OpenAPI yaml definition. For the definition, please refer to + * `./auth/auth` + */ + authMethods?: AuthMethodsConfiguration +} + +/** + * Provide your `ConfigurationParameters` to this function to get a `Configuration` + * object that can be used to configure your APIs (in the constructor or + * for each request individually). + * + * If a property is not included in conf, a default is used: + * - baseServer: server1 + * - httpApi: IsomorphicFetchHttpLibrary + * - middleware: [] + * - promiseMiddleware: [] + * - authMethods: {} + * + * @param conf partial configuration + */ +export function createConfiguration(conf: ConfigurationParameters = {}): Configuration { + const configuration: Configuration = { + baseServer: conf.baseServer !== undefined ? conf.baseServer : server1, + httpApi: conf.httpApi || new DefaultHttpLibrary(), + middleware: conf.middleware || [], + authMethods: configureAuthMethods(conf.authMethods) + }; + if (conf.promiseMiddleware) { + conf.promiseMiddleware.forEach( + m => configuration.middleware.push(new PromiseMiddlewareWrapper(m)) + ); + } + return configuration; +} + +/** + * Merge configuration options into a configuration. + */ +export function mergeConfiguration(conf: Configuration, options?: ConfigurationOptions): Configuration { + if (!options) { + return conf; + } + return { + baseServer: options.baseServer || conf.baseServer, + httpApi: options.httpApi || conf.httpApi, + authMethods: options.authMethods || conf.authMethods, + middleware: mergeMiddleware(conf.middleware, options?.middleware, options?.middlewareMergeStrategy), + }; +} + +function mergeMiddleware(staticMiddleware: Middleware[], calltimeMiddleware?: Middleware[], strategy: "append" | "prepend" | "replace" = "replace") { + if (!calltimeMiddleware) { + return staticMiddleware; + } + switch(strategy) { + case "append": + return staticMiddleware.concat(calltimeMiddleware); + case "prepend": + return calltimeMiddleware.concat(staticMiddleware) + case "replace": + return calltimeMiddleware + default: + throw new Error(`Unrecognized middleware merge strategy '${strategy}'`) + } +} + +/** + * Convert Promise-based configuration options to Observable-based configuration options. + */ +export function wrapOptions(options?: PromiseConfigurationOptions): StandardConfigurationOptions | undefined { + if (options) { + return { + baseServer: options.baseServer, + httpApi: options.httpApi, + middleware: options.middleware?.map( + m => new PromiseMiddlewareWrapper(m) + ), + middlewareMergeStrategy: options.middlewareMergeStrategy, + authMethods: options.authMethods, + }; + } + return; +} diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/git_push.sh b/samples/openapi3/client/petstore/typescript/builds/one-of/git_push.sh new file mode 100644 index 000000000000..b253029754ed --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/git_push.sh @@ -0,0 +1,51 @@ +#!/bin/sh +# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/ +# +# Usage example: /bin/sh ./git_push.sh wing328 openapi-petstore-perl "minor update" + +git_user_id=$1 +git_repo_id=$2 +release_note=$3 + +if [ "$git_user_id" = "" ]; then + git_user_id="GIT_USER_ID" + echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id" +fi + +if [ "$git_repo_id" = "" ]; then + git_repo_id="GIT_REPO_ID" + echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id" +fi + +if [ "$release_note" = "" ]; then + release_note="Minor update" + echo "[INFO] No command line input provided. Set \$release_note to $release_note" +fi + +# Initialize the local directory as a Git repository +git init + +# Adds the files in the local repository and stages them for commit. +git add . + +# Commits the tracked changes and prepares them to be pushed to a remote repository. +git commit -m "$release_note" + +# Sets the new remote +git_remote=$(git remote) +if [ "$git_remote" = "" ]; then # git remote not defined + + if [ "$GIT_TOKEN" = "" ]; then + echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment." + git remote add origin https://github.com/${git_user_id}/${git_repo_id}.git + else + git remote add origin https://${git_user_id}:"${GIT_TOKEN}"@github.com/${git_user_id}/${git_repo_id}.git + fi + +fi + +git pull origin master + +# Pushes (Forces) the changes in the local repository up to the remote repository +echo "Git pushing to https://github.com/${git_user_id}/${git_repo_id}.git" +git push origin master 2>&1 | grep -v 'To https' diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/http/http.ts b/samples/openapi3/client/petstore/typescript/builds/one-of/http/http.ts new file mode 100644 index 000000000000..7eaf00563272 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/http/http.ts @@ -0,0 +1,266 @@ +// TODO: evaluate if we can easily get rid of this library +import * as FormData from "form-data"; +import { URL, URLSearchParams } from 'url'; +import * as http from 'http'; +import * as https from 'https'; +import { Observable, from } from '../rxjsStub'; + +export * from './isomorphic-fetch'; + +/** + * Represents an HTTP method. + */ +export enum HttpMethod { + GET = "GET", + HEAD = "HEAD", + POST = "POST", + PUT = "PUT", + DELETE = "DELETE", + CONNECT = "CONNECT", + OPTIONS = "OPTIONS", + TRACE = "TRACE", + PATCH = "PATCH" +} + +/** + * Represents an HTTP file which will be transferred from or to a server. + */ +export type HttpFile = { + data: Buffer, + name: string +}; + +export class HttpException extends Error { + public constructor(msg: string) { + super(msg); + } +} + +/** + * Represents the body of an outgoing HTTP request. + */ +export type RequestBody = undefined | string | FormData | URLSearchParams; + +type Headers = Record; + +function ensureAbsoluteUrl(url: string) { + if (url.startsWith("http://") || url.startsWith("https://")) { + return url; + } + throw new Error("You need to define an absolute base url for the server."); +} + +/** + * Represents an HTTP request context + */ +export class RequestContext { + private headers: Headers = {}; + private body: RequestBody = undefined; + private url: URL; + private signal: AbortSignal | undefined = undefined; + private agent: http.Agent | https.Agent | undefined = undefined; + + /** + * Creates the request context using a http method and request resource url + * + * @param url url of the requested resource + * @param httpMethod http method + */ + public constructor(url: string, private httpMethod: HttpMethod) { + this.url = new URL(ensureAbsoluteUrl(url)); + } + + /* + * Returns the url set in the constructor including the query string + * + */ + public getUrl(): string { + return this.url.toString().endsWith("/") ? + this.url.toString().slice(0, -1) + : this.url.toString(); + } + + /** + * Replaces the url set in the constructor with this url. + * + */ + public setUrl(url: string) { + this.url = new URL(ensureAbsoluteUrl(url)); + } + + /** + * Sets the body of the http request either as a string or FormData + * + * Note that setting a body on a HTTP GET, HEAD, DELETE, CONNECT or TRACE + * request is discouraged. + * https://httpwg.org/http-core/draft-ietf-httpbis-semantics-latest.html#rfc.section.7.3.1 + * + * @param body the body of the request + */ + public setBody(body: RequestBody) { + this.body = body; + } + + public getHttpMethod(): HttpMethod { + return this.httpMethod; + } + + public getHeaders(): Headers { + return this.headers; + } + + public getBody(): RequestBody { + return this.body; + } + + public setQueryParam(name: string, value: string) { + this.url.searchParams.set(name, value); + } + + public appendQueryParam(name: string, value: string) { + this.url.searchParams.append(name, value); + } + + /** + * Sets a cookie with the name and value. NO check for duplicate cookies is performed + * + */ + public addCookie(name: string, value: string): void { + if (!this.headers["Cookie"]) { + this.headers["Cookie"] = ""; + } + this.headers["Cookie"] += name + "=" + value + "; "; + } + + public setHeaderParam(key: string, value: string): void { + this.headers[key] = value; + } + + public setSignal(signal: AbortSignal): void { + this.signal = signal; + } + + public getSignal(): AbortSignal | undefined { + return this.signal; + } + + + public setAgent(agent: http.Agent | https.Agent) { + this.agent = agent; + } + + public getAgent(): http.Agent | https.Agent | undefined { + return this.agent; + } +} + +export interface ResponseBody { + text(): Promise; + binary(): Promise; +} + +/** + * Helper class to generate a `ResponseBody` from binary data + */ +export class SelfDecodingBody implements ResponseBody { + constructor(private dataSource: Promise) {} + + binary(): Promise { + return this.dataSource; + } + + async text(): Promise { + const data: Buffer = await this.dataSource; + return data.toString(); + } +} + +export class ResponseContext { + public constructor( + public httpStatusCode: number, + public headers: Headers, + public body: ResponseBody + ) {} + + /** + * Parse header value in the form `value; param1="value1"` + * + * E.g. for Content-Type or Content-Disposition + * Parameter names are converted to lower case + * The first parameter is returned with the key `""` + */ + public getParsedHeader(headerName: string): Headers { + const result: Headers = {}; + if (!this.headers[headerName]) { + return result; + } + + const parameters = this.headers[headerName]!.split(";"); + for (const parameter of parameters) { + let [key, value] = parameter.split("=", 2); + if (!key) { + continue; + } + key = key.toLowerCase().trim(); + if (value === undefined) { + result[""] = key; + } else { + value = value.trim(); + if (value.startsWith('"') && value.endsWith('"')) { + value = value.substring(1, value.length - 1); + } + result[key] = value; + } + } + return result; + } + + public async getBodyAsFile(): Promise { + const data = await this.body.binary(); + const fileName = this.getParsedHeader("content-disposition")["filename"] || ""; + return { data, name: fileName }; + } + + /** + * Use a heuristic to get a body of unknown data structure. + * Return as string if possible, otherwise as binary. + */ + public getBodyAsAny(): Promise { + try { + return this.body.text(); + } catch {} + + try { + return this.body.binary(); + } catch {} + + return Promise.resolve(undefined); + } +} + +export interface HttpLibrary { + send(request: RequestContext): Observable; +} + +export interface PromiseHttpLibrary { + send(request: RequestContext): Promise; +} + +export function wrapHttpLibrary(promiseHttpLibrary: PromiseHttpLibrary): HttpLibrary { + return { + send(request: RequestContext): Observable { + return from(promiseHttpLibrary.send(request)); + } + } +} + +export class HttpInfo extends ResponseContext { + public constructor( + httpStatusCode: number, + headers: Headers, + body: ResponseBody, + public data: T, + ) { + super(httpStatusCode, headers, body); + } +} diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/http/isomorphic-fetch.ts b/samples/openapi3/client/petstore/typescript/builds/one-of/http/isomorphic-fetch.ts new file mode 100644 index 000000000000..d7ce46e4bee8 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/http/isomorphic-fetch.ts @@ -0,0 +1,33 @@ +import {HttpLibrary, RequestContext, ResponseContext} from './http'; +import { from, Observable } from '../rxjsStub'; +import fetch from "node-fetch"; + +export class IsomorphicFetchHttpLibrary implements HttpLibrary { + + public send(request: RequestContext): Observable { + let method = request.getHttpMethod().toString(); + let body = request.getBody(); + + const resultPromise = fetch(request.getUrl(), { + method: method, + body: body as any, + headers: request.getHeaders(), + signal: request.getSignal(), + agent: request.getAgent(), + }).then((resp: any) => { + const headers: { [name: string]: string } = {}; + resp.headers.forEach((value: string, name: string) => { + headers[name] = value; + }); + + const body = { + text: () => resp.text(), + binary: () => resp.buffer() + }; + return new ResponseContext(resp.status, headers, body); + }); + + return from>(resultPromise); + + } +} diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/index.ts b/samples/openapi3/client/petstore/typescript/builds/one-of/index.ts new file mode 100644 index 000000000000..949fa4d5e4d4 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/index.ts @@ -0,0 +1,13 @@ +export * from "./http/http"; +export * from "./auth/auth"; +export * from "./models/all"; +export { createConfiguration } from "./configuration" +export type { Configuration, ConfigurationOptions, PromiseConfigurationOptions } from "./configuration" +export * from "./apis/exception"; +export * from "./servers"; +export { RequiredError } from "./apis/baseapi"; + +export type { PromiseMiddleware as Middleware, Middleware as ObservableMiddleware } from './middleware'; +export { Observable } from './rxjsStub'; +export { PromiseDefaultApi as DefaultApi } from './types/PromiseAPI'; + diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/middleware.ts b/samples/openapi3/client/petstore/typescript/builds/one-of/middleware.ts new file mode 100644 index 000000000000..399e823835be --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/middleware.ts @@ -0,0 +1,62 @@ +import {RequestContext, ResponseContext} from './http/http'; +import { Observable, from } from './rxjsStub'; + +/** + * Defines the contract for a middleware intercepting requests before + * they are sent (but after the RequestContext was created) + * and before the ResponseContext is unwrapped. + * + */ +export interface Middleware { + /** + * Modifies the request before the request is sent. + * + * @param context RequestContext of a request which is about to be sent to the server + * @returns an observable of the updated request context + * + */ + pre(context: RequestContext): Observable; + /** + * Modifies the returned response before it is deserialized. + * + * @param context ResponseContext of a sent request + * @returns an observable of the modified response context + */ + post(context: ResponseContext): Observable; +} + +export class PromiseMiddlewareWrapper implements Middleware { + public constructor(private middleware: PromiseMiddleware) {} + + pre(context: RequestContext): Observable { + return from(this.middleware.pre(context)); + } + + post(context: ResponseContext): Observable { + return from(this.middleware.post(context)); + } +} + +/** + * Defines the contract for a middleware intercepting requests before + * they are sent (but after the RequestContext was created) + * and before the ResponseContext is unwrapped. + * + */ +export interface PromiseMiddleware { + /** + * Modifies the request before the request is sent. + * + * @param context RequestContext of a request which is about to be sent to the server + * @returns an observable of the updated request context + * + */ + pre(context: RequestContext): Promise; + /** + * Modifies the returned response before it is deserialized. + * + * @param context ResponseContext of a sent request + * @returns an observable of the modified response context + */ + post(context: ResponseContext): Promise; +} diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/models/Cat.ts b/samples/openapi3/client/petstore/typescript/builds/one-of/models/Cat.ts new file mode 100644 index 000000000000..cc5630f3aade --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/models/Cat.ts @@ -0,0 +1,46 @@ +/** + * testing oneOf + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { AttributeTypeMapEntry } from '../models/ModelTypes'; +import { HttpFile } from '../http/http'; + +export class Cat { + 'name': string; + 'petType': string; + + static readonly discriminator: string | undefined = undefined; + + static readonly mapping: {[index: string]: string} | undefined = undefined; + + static readonly attributeTypeMap: Array = [ + { + "name": "name", + "baseName": "name", + "type": "string", + "format": "", + "required": true + }, + { + "name": "petType", + "baseName": "petType", + "type": "string", + "format": "", + "required": true + } ]; + + static getAttributeTypeMap() { + return Cat.attributeTypeMap; + } + + public constructor() { + } +} diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/models/Dog.ts b/samples/openapi3/client/petstore/typescript/builds/one-of/models/Dog.ts new file mode 100644 index 000000000000..3d510e86cfba --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/models/Dog.ts @@ -0,0 +1,46 @@ +/** + * testing oneOf + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { AttributeTypeMapEntry } from '../models/ModelTypes'; +import { HttpFile } from '../http/http'; + +export class Dog { + 'bark': string; + 'petType': string; + + static readonly discriminator: string | undefined = undefined; + + static readonly mapping: {[index: string]: string} | undefined = undefined; + + static readonly attributeTypeMap: Array = [ + { + "name": "bark", + "baseName": "bark", + "type": "string", + "format": "", + "required": true + }, + { + "name": "petType", + "baseName": "petType", + "type": "string", + "format": "", + "required": true + } ]; + + static getAttributeTypeMap() { + return Dog.attributeTypeMap; + } + + public constructor() { + } +} diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/models/ModelTypes.ts b/samples/openapi3/client/petstore/typescript/builds/one-of/models/ModelTypes.ts new file mode 100644 index 000000000000..24a680aba301 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/models/ModelTypes.ts @@ -0,0 +1,11 @@ +/** + * Represents a single attribute/property metadata entry in the attributeTypeMap. + * Used for validation and type matching in oneOf scenarios. + */ +export type AttributeTypeMapEntry = { + name: string; + baseName: string; + type: string; + format: string; + required: boolean; +}; diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/models/ObjectSerializer.ts b/samples/openapi3/client/petstore/typescript/builds/one-of/models/ObjectSerializer.ts new file mode 100644 index 000000000000..585f5137a0f9 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/models/ObjectSerializer.ts @@ -0,0 +1,331 @@ +export * from '../models/Cat'; +export * from '../models/Dog'; +export * from '../models/PetDiscriminatorResponse'; +export * from '../models/PetResponse'; + +import { Cat } from '../models/Cat'; +import { Dog } from '../models/Dog'; +import { PetDiscriminatorResponseClass } from '../models/PetDiscriminatorResponse'; +import { PetResponseClass } from '../models/PetResponse'; + +/* tslint:disable:no-unused-variable */ +let primitives = [ + "string", + "boolean", + "double", + "integer", + "long", + "float", + "number", + "any" + ]; + +let enumsMap: Set = new Set([ +]); + +let typeMap: {[index: string]: any} = { + "Cat": Cat, + "Dog": Dog, + "PetDiscriminatorResponse": PetDiscriminatorResponseClass, + "PetResponse": PetResponseClass, +} + +type MimeTypeDescriptor = { + type: string; + subtype: string; + subtypeTokens: string[]; +}; + +/** + * Every mime-type consists of a type, subtype, and optional parameters. + * The subtype can be composite, including information about the content format. + * For example: `application/json-patch+json`, `application/merge-patch+json`. + * + * This helper transforms a string mime-type into an internal representation. + * This simplifies the implementation of predicates that in turn define common rules for parsing or stringifying + * the payload. + */ +const parseMimeType = (mimeType: string): MimeTypeDescriptor => { + const [type = '', subtype = ''] = mimeType.split('/'); + return { + type, + subtype, + subtypeTokens: subtype.split('+'), + }; +}; + +type MimeTypePredicate = (mimeType: string) => boolean; + +// This factory creates a predicate function that checks a string mime-type against defined rules. +const mimeTypePredicateFactory = (predicate: (descriptor: MimeTypeDescriptor) => boolean): MimeTypePredicate => (mimeType) => predicate(parseMimeType(mimeType)); + +// Use this factory when you need to define a simple predicate based only on type and, if applicable, subtype. +const mimeTypeSimplePredicateFactory = (type: string, subtype?: string): MimeTypePredicate => mimeTypePredicateFactory((descriptor) => { + if (descriptor.type !== type) return false; + if (subtype != null && descriptor.subtype !== subtype) return false; + return true; +}); + +// Creating a set of named predicates that will help us determine how to handle different mime-types +const isTextLikeMimeType = mimeTypeSimplePredicateFactory('text'); +const isJsonMimeType = mimeTypeSimplePredicateFactory('application', 'json'); +const isJsonLikeMimeType = mimeTypePredicateFactory((descriptor) => descriptor.type === 'application' && descriptor.subtypeTokens.some((item) => item === 'json')); +const isOctetStreamMimeType = mimeTypeSimplePredicateFactory('application', 'octet-stream'); +const isFormUrlencodedMimeType = mimeTypeSimplePredicateFactory('application', 'x-www-form-urlencoded'); + +// Defining a list of mime-types in the order of prioritization for handling. +const supportedMimeTypePredicatesWithPriority: MimeTypePredicate[] = [ + isJsonMimeType, + isJsonLikeMimeType, + isTextLikeMimeType, + isOctetStreamMimeType, + isFormUrlencodedMimeType, +]; + +const nullableSuffix = " | null"; +const optionalSuffix = " | undefined"; +const arrayPrefix = "Array<"; +const arraySuffix = ">"; +const mapPrefix = "{ [key: string]: "; +const mapSuffix = "; }"; + +export class ObjectSerializer { + public static findCorrectType(data: any, expectedType: string) { + if (data == undefined) { + return expectedType; + } else if (primitives.indexOf(expectedType.toLowerCase()) !== -1) { + return expectedType; + } else if (expectedType === "Date") { + return expectedType; + } else { + if (enumsMap.has(expectedType)) { + return expectedType; + } + + if (!typeMap[expectedType]) { + return expectedType; // w/e we don't know the type + } + + // Check the discriminator + let discriminatorProperty = typeMap[expectedType].discriminator; + if (discriminatorProperty == null || !data[discriminatorProperty]) { + if (this.hasFindMatchingTypeMethod(typeMap[expectedType])) { + const foundType = typeMap[expectedType].findMatchingType(data); + if (foundType == undefined) { + throw new Error("Unable to determine a unique type for the provided object: oneOf type resolution failed. The object does not match exactly one schema. Consider adding a discriminator or making schemas mutually exclusive."); + } + + return foundType; + } + return expectedType; // the type does not have a discriminator and findMatchingType method. use it. + } else { + let discriminatorType = data[discriminatorProperty]; + let mapping = typeMap[expectedType].mapping; + if (mapping != undefined && mapping[discriminatorType]) { + return mapping[discriminatorType]; // use the type given in the discriminator + } else if(typeMap[discriminatorType]) { + return discriminatorType; + } else { + throw new Error(`Discriminator property '${discriminatorProperty}' has value '${discriminatorType}' which does not map to any known type in '${expectedType}'.`); + } + } + } + } + + private static hasFindMatchingTypeMethod(klass: any): boolean { + if (typeof klass.findMatchingType === 'function') { + return true; + } + return false; + } + + public static serialize(data: any, type: string, format: string): any { + if (data == undefined) { + return data; + } else if (primitives.indexOf(type.toLowerCase()) !== -1) { + return data; + } else if (type.endsWith(nullableSuffix)) { + let subType: string = type.slice(0, -nullableSuffix.length); // Type | null => Type + return ObjectSerializer.serialize(data, subType, format); + } else if (type.endsWith(optionalSuffix)) { + let subType: string = type.slice(0, -optionalSuffix.length); // Type | undefined => Type + return ObjectSerializer.serialize(data, subType, format); + } else if (type.startsWith(arrayPrefix)) { + let subType: string = type.slice(arrayPrefix.length, -arraySuffix.length); // Array => Type + let transformedData: any[] = []; + for (let date of data) { + transformedData.push(ObjectSerializer.serialize(date, subType, format)); + } + return transformedData; + } else if (type.startsWith(mapPrefix)) { + let subType: string = type.slice(mapPrefix.length, -mapSuffix.length); // { [key: string]: Type; } => Type + let transformedData: { [key: string]: any } = {}; + for (let key in data) { + transformedData[key] = ObjectSerializer.serialize( + data[key], + subType, + format, + ); + } + return transformedData; + } else if (type === "Date") { + if (!(data instanceof Date)) { + return data; + } + if (format == "date") { + let month = data.getMonth()+1 + let monthStr = month < 10 ? "0" + month.toString() : month.toString() + let day = data.getDate(); + let dayStr = day < 10 ? "0" + day.toString() : day.toString(); + + return data.getFullYear() + "-" + monthStr + "-" + dayStr; + } else { + return data.toISOString(); + } + } else { + if (enumsMap.has(type)) { + return data; + } + if (!typeMap[type]) { // in case we dont know the type + return data; + } + + // Get the actual type of this object + type = this.findCorrectType(data, type); + + // get the map for the correct type. + let attributeTypes = typeMap[type].getAttributeTypeMap(); + let instance: {[index: string]: any} = {}; + for (let attributeType of attributeTypes) { + instance[attributeType.baseName] = ObjectSerializer.serialize(data[attributeType.name], attributeType.type, attributeType.format); + } + return instance; + } + } + + public static deserialize(data: any, type: string, format: string): any { + // polymorphism may change the actual type. + type = ObjectSerializer.findCorrectType(data, type); + if (data == undefined) { + return data; + } else if (primitives.indexOf(type.toLowerCase()) !== -1) { + return data; + } else if (type.endsWith(nullableSuffix)) { + let subType: string = type.slice(0, -nullableSuffix.length); // Type | null => Type + return ObjectSerializer.deserialize(data, subType, format); + } else if (type.endsWith(optionalSuffix)) { + let subType: string = type.slice(0, -optionalSuffix.length); // Type | undefined => Type + return ObjectSerializer.deserialize(data, subType, format); + } else if (type.startsWith(arrayPrefix)) { + let subType: string = type.slice(arrayPrefix.length, -arraySuffix.length); // Array => Type + let transformedData: any[] = []; + for (let date of data) { + transformedData.push(ObjectSerializer.deserialize(date, subType, format)); + } + return transformedData; + } else if (type.startsWith(mapPrefix)) { + let subType: string = type.slice(mapPrefix.length, -mapSuffix.length); // { [key: string]: Type; } => Type + let transformedData: { [key: string]: any } = {}; + for (let key in data) { + transformedData[key] = ObjectSerializer.deserialize( + data[key], + subType, + format, + ); + } + return transformedData; + } else if (type === "Date") { + return new Date(data); + } else { + if (enumsMap.has(type)) {// is Enum + return data; + } + + if (!typeMap[type]) { // dont know the type + return data; + } + let instance = new typeMap[type](); + let attributeTypes = typeMap[type].getAttributeTypeMap(); + for (let attributeType of attributeTypes) { + let value = ObjectSerializer.deserialize(data[attributeType.baseName], attributeType.type, attributeType.format); + if (value !== undefined) { + instance[attributeType.name] = value; + } + } + return instance; + } + } + + + /** + * Normalize media type + * + * We currently do not handle any media types attributes, i.e. anything + * after a semicolon. All content is assumed to be UTF-8 compatible. + */ + public static normalizeMediaType(mediaType: string | undefined): string | undefined { + if (mediaType === undefined) { + return undefined; + } + return (mediaType.split(";")[0] ?? '').trim().toLowerCase(); + } + + /** + * From a list of possible media types, choose the one we can handle best. + * + * The order of the given media types does not have any impact on the choice + * made. + */ + public static getPreferredMediaType(mediaTypes: Array): string { + /** According to OAS 3 we should default to json */ + if (mediaTypes.length === 0) { + return "application/json"; + } + + const normalMediaTypes = mediaTypes.map(ObjectSerializer.normalizeMediaType); + + for (const predicate of supportedMimeTypePredicatesWithPriority) { + for (const mediaType of normalMediaTypes) { + if (mediaType != null && predicate(mediaType)) { + return mediaType; + } + } + } + + throw new Error("None of the given media types are supported: " + mediaTypes.join(", ")); + } + + /** + * Convert data to a string according the given media type + */ + public static stringify(data: any, mediaType: string): string { + if (isTextLikeMimeType(mediaType)) { + return String(data); + } + + if (isJsonLikeMimeType(mediaType)) { + return JSON.stringify(data); + } + + throw new Error("The mediaType " + mediaType + " is not supported by ObjectSerializer.stringify."); + } + + /** + * Parse data from a string according to the given media type + */ + public static parse(rawData: string, mediaType: string | undefined) { + if (mediaType === undefined) { + throw new Error("Cannot parse content. No Content-Type defined."); + } + + if (isTextLikeMimeType(mediaType)) { + return rawData; + } + + if (isJsonLikeMimeType(mediaType)) { + return JSON.parse(rawData); + } + + throw new Error("The mediaType " + mediaType + " is not supported by ObjectSerializer.parse."); + } +} diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/models/PetDiscriminatorResponse.ts b/samples/openapi3/client/petstore/typescript/builds/one-of/models/PetDiscriminatorResponse.ts new file mode 100644 index 000000000000..71b36a3f6b36 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/models/PetDiscriminatorResponse.ts @@ -0,0 +1,48 @@ +/** + * testing oneOf + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { Cat } from '../models/Cat'; +import { Dog } from '../models/Dog'; +import { findMatchingType } from '../models/TypeMatcher'; + +/** + * @type PetDiscriminatorResponse + * Type + * @export + */ +export type PetDiscriminatorResponse = Cat | Dog; + +/** +* @type PetDiscriminatorResponseClass +* @export +*/ +export class PetDiscriminatorResponseClass { + static readonly discriminator: string | undefined = "petType"; + + static readonly mapping: {[index: string]: string} | undefined = { + "cat": "Cat", + "dog": "Dog", + }; + + private static readonly arrayOfTypes: Array = [Cat, Dog]; + + /** + * Determines which oneOf schema matches the provided data. + * + * @param data - The data object to match against oneOf schemas + * @returns The name of the matching type, or undefined if no unique match is found + */ + public static findMatchingType(data: any): string | undefined { + return findMatchingType(data, this.arrayOfTypes); + } +} + diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/models/PetResponse.ts b/samples/openapi3/client/petstore/typescript/builds/one-of/models/PetResponse.ts new file mode 100644 index 000000000000..9f548c0f593a --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/models/PetResponse.ts @@ -0,0 +1,45 @@ +/** + * testing oneOf + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { Cat } from '../models/Cat'; +import { Dog } from '../models/Dog'; +import { findMatchingType } from '../models/TypeMatcher'; + +/** + * @type PetResponse + * Type + * @export + */ +export type PetResponse = Cat | Dog; + +/** +* @type PetResponseClass +* @export +*/ +export class PetResponseClass { + static readonly discriminator: string | undefined = undefined; + + static readonly mapping: {[index: string]: string} | undefined = undefined; + + private static readonly arrayOfTypes: Array = [Cat, Dog]; + + /** + * Determines which oneOf schema matches the provided data. + * + * @param data - The data object to match against oneOf schemas + * @returns The name of the matching type, or undefined if no unique match is found + */ + public static findMatchingType(data: any): string | undefined { + return findMatchingType(data, this.arrayOfTypes); + } +} + diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/models/TypeMatcher.ts b/samples/openapi3/client/petstore/typescript/builds/one-of/models/TypeMatcher.ts new file mode 100644 index 000000000000..2f1c20864a70 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/models/TypeMatcher.ts @@ -0,0 +1,36 @@ +import { AttributeTypeMapEntry } from '../models/ModelTypes'; + +/** + * Validates if data contains all required attributes from the attributeTypeMap. + * + * @param data - The data object to validate + * @param attributeTypeMap - Array of attribute metadata including required flag + * @returns true if all required attributes are present in data, false otherwise + */ +export function instanceOfType(data: any, attributeTypeMap: Array): boolean { + for (const attribute of attributeTypeMap) { + if (attribute.required && data[attribute.baseName] === undefined) { + return false; + } + } + + return true; +} + +/** + * Attempts to find a matching type from an array of possible types by validating + * the data against each type's attribute requirements. + * + * @param data - The data object to match + * @param types - Array of possible type constructors + * @returns The name of the matching type, or undefined if no match found + */ +export function findMatchingType(data: any, types: Array): string | undefined { + for (const type of types) { + if (instanceOfType(data, type.getAttributeTypeMap())) { + return type.name; + } + } + + return undefined; +} \ No newline at end of file diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/models/all.ts b/samples/openapi3/client/petstore/typescript/builds/one-of/models/all.ts new file mode 100644 index 000000000000..13dc61eeb447 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/models/all.ts @@ -0,0 +1,6 @@ +export * from '../models/Cat' +export * from '../models/Dog' +export * from '../models/PetDiscriminatorResponse' +export * from '../models/PetResponse' +export * from './TypeMatcher' +export * from './ModelTypes' \ No newline at end of file diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/package.json b/samples/openapi3/client/petstore/typescript/builds/one-of/package.json new file mode 100644 index 000000000000..be458020cd18 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/package.json @@ -0,0 +1,43 @@ +{ + "name": "ts-petstore-client", + "version": "1.0.0", + "description": "OpenAPI client for ts-petstore-client", + "author": "OpenAPI-Generator Contributors", + "repository": { + "type": "git", + "url": "https://github.com/GIT_USER_ID/GIT_REPO_ID.git" + }, + "keywords": [ + "fetch", + "typescript", + "openapi-client", + "openapi-generator" + ], + "license": "Unlicense", + "main": "./dist/index.js", + "type": "commonjs", + "exports": { + ".": { + "require": "./dist/index.js", + "types": "./dist/index.d.js" + } + }, + "files": [ + "dist" + ], + "typings": "./dist/index.d.ts", + "scripts": { + "build": "tsc", + "prepare": "npm run build" + }, + "dependencies": { + "node-fetch": "^2.7.0", + "@types/node-fetch": "^2.6.13", + "@types/node": "^16.18.126", + "form-data": "^4.0.4", + "es6-promise": "^4.2.4" + }, + "devDependencies": { + "typescript": "^4.0" + } +} diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/rxjsStub.ts b/samples/openapi3/client/petstore/typescript/builds/one-of/rxjsStub.ts new file mode 100644 index 000000000000..4c73715a2486 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/rxjsStub.ts @@ -0,0 +1,27 @@ +export class Observable { + constructor(private promise: Promise) {} + + toPromise() { + return this.promise; + } + + pipe(callback: (value: T) => S | Promise): Observable { + return new Observable(this.promise.then(callback)); + } +} + +export function from(promise: Promise) { + return new Observable(promise); +} + +export function of(value: T) { + return new Observable(Promise.resolve(value)); +} + +export function mergeMap(callback: (value: T) => Observable) { + return (value: T) => callback(value).toPromise(); +} + +export function map(callback: any) { + return callback; +} diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/servers.ts b/samples/openapi3/client/petstore/typescript/builds/one-of/servers.ts new file mode 100644 index 000000000000..b52dff31fba1 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/servers.ts @@ -0,0 +1,54 @@ +import { RequestContext, HttpMethod } from "./http/http"; + +export interface BaseServerConfiguration { + makeRequestContext(endpoint: string, httpMethod: HttpMethod): RequestContext; +} + +/** + * + * Represents the configuration of a server including its + * url template and variable configuration based on the url. + * + */ +export class ServerConfiguration implements BaseServerConfiguration { + public constructor(private url: string, private variableConfiguration: T) {} + + /** + * Sets the value of the variables of this server. Variables are included in + * the `url` of this ServerConfiguration in the form `{variableName}` + * + * @param variableConfiguration a partial variable configuration for the + * variables contained in the url + */ + public setVariables(variableConfiguration: Partial) { + Object.assign(this.variableConfiguration, variableConfiguration); + } + + public getConfiguration(): T { + return this.variableConfiguration + } + + private getUrl() { + let replacedUrl = this.url; + for (const [key, value] of Object.entries(this.variableConfiguration)) { + replacedUrl = replacedUrl.replaceAll(`{${key}}`, value); + } + return replacedUrl + } + + /** + * Creates a new request context for this server using the url with variables + * replaced with their respective values and the endpoint of the request appended. + * + * @param endpoint the endpoint to be queried on the server + * @param httpMethod httpMethod to be used + * + */ + public makeRequestContext(endpoint: string, httpMethod: HttpMethod): RequestContext { + return new RequestContext(this.getUrl() + endpoint, httpMethod); + } +} + +export const server1 = new ServerConfiguration<{ }>("http://localhost:3000", { }) + +export const servers = [server1]; diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/tsconfig.json b/samples/openapi3/client/petstore/typescript/builds/one-of/tsconfig.json new file mode 100644 index 000000000000..953996de3971 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/tsconfig.json @@ -0,0 +1,38 @@ +{ + "compilerOptions": { + "strict": true, + /* Basic Options */ + "target": "es5", + "moduleResolution": "node", + "declaration": true, + "typeRoots": [ + "node_modules/@types" + ], + + /* Additional Checks */ + "noUnusedLocals": false, /* Report errors on unused locals. */ // TODO: reenable (unused imports!) + "noUnusedParameters": false, /* Report errors on unused parameters. */ // TODO: set to true again + "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + + "removeComments": true, + "sourceMap": true, + "outDir": "./dist", + "noLib": false, + "lib": [ + "es6" + ,"ES2017.Object" + ,"ES2021.String" + ], + }, + "exclude": [ + "dist", + "node_modules" + ], + "filesGlob": [ + "./**/*.ts", + ] +} diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/types/ObjectParamAPI.ts b/samples/openapi3/client/petstore/typescript/builds/one-of/types/ObjectParamAPI.ts new file mode 100644 index 000000000000..411ac3ad2f5d --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/types/ObjectParamAPI.ts @@ -0,0 +1,54 @@ +import { ResponseContext, RequestContext, HttpFile, HttpInfo } from '../http/http'; +import { Configuration, ConfigurationOptions } from '../configuration' +import type { Middleware } from '../middleware'; + +import { Cat } from '../models/Cat'; +import { Dog } from '../models/Dog'; +import { PetDiscriminatorResponse } from '../models/PetDiscriminatorResponse'; +import { PetResponse } from '../models/PetResponse'; + +import { ObservableDefaultApi } from "./ObservableAPI"; +import { DefaultApiRequestFactory, DefaultApiResponseProcessor} from "../apis/DefaultApi"; + +export interface DefaultApiTestDiscriminatorRequest { +} + +export interface DefaultApiTestWithoutDiscriminatorRequest { +} + +export class ObjectDefaultApi { + private api: ObservableDefaultApi + + public constructor(configuration: Configuration, requestFactory?: DefaultApiRequestFactory, responseProcessor?: DefaultApiResponseProcessor) { + this.api = new ObservableDefaultApi(configuration, requestFactory, responseProcessor); + } + + /** + * @param param the request object + */ + public testDiscriminatorWithHttpInfo(param: DefaultApiTestDiscriminatorRequest = {}, options?: ConfigurationOptions): Promise> { + return this.api.testDiscriminatorWithHttpInfo( options).toPromise(); + } + + /** + * @param param the request object + */ + public testDiscriminator(param: DefaultApiTestDiscriminatorRequest = {}, options?: ConfigurationOptions): Promise { + return this.api.testDiscriminator( options).toPromise(); + } + + /** + * @param param the request object + */ + public testWithoutDiscriminatorWithHttpInfo(param: DefaultApiTestWithoutDiscriminatorRequest = {}, options?: ConfigurationOptions): Promise> { + return this.api.testWithoutDiscriminatorWithHttpInfo( options).toPromise(); + } + + /** + * @param param the request object + */ + public testWithoutDiscriminator(param: DefaultApiTestWithoutDiscriminatorRequest = {}, options?: ConfigurationOptions): Promise { + return this.api.testWithoutDiscriminator( options).toPromise(); + } + +} diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/types/ObservableAPI.ts b/samples/openapi3/client/petstore/typescript/builds/one-of/types/ObservableAPI.ts new file mode 100644 index 000000000000..acdf282307ec --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/types/ObservableAPI.ts @@ -0,0 +1,83 @@ +import { ResponseContext, RequestContext, HttpFile, HttpInfo } from '../http/http'; +import { Configuration, ConfigurationOptions, mergeConfiguration } from '../configuration' +import type { Middleware } from '../middleware'; +import { Observable, of, from } from '../rxjsStub'; +import {mergeMap, map} from '../rxjsStub'; +import { Cat } from '../models/Cat'; +import { Dog } from '../models/Dog'; +import { PetDiscriminatorResponse } from '../models/PetDiscriminatorResponse'; +import { PetResponse } from '../models/PetResponse'; + +import { DefaultApiRequestFactory, DefaultApiResponseProcessor} from "../apis/DefaultApi"; +export class ObservableDefaultApi { + private requestFactory: DefaultApiRequestFactory; + private responseProcessor: DefaultApiResponseProcessor; + private configuration: Configuration; + + public constructor( + configuration: Configuration, + requestFactory?: DefaultApiRequestFactory, + responseProcessor?: DefaultApiResponseProcessor + ) { + this.configuration = configuration; + this.requestFactory = requestFactory || new DefaultApiRequestFactory(configuration); + this.responseProcessor = responseProcessor || new DefaultApiResponseProcessor(); + } + + /** + */ + public testDiscriminatorWithHttpInfo(_options?: ConfigurationOptions): Observable> { + const _config = mergeConfiguration(this.configuration, _options); + + const requestContextPromise = this.requestFactory.testDiscriminator(_config); + // build promise chain + let middlewarePreObservable = from(requestContextPromise); + for (const middleware of _config.middleware) { + middlewarePreObservable = middlewarePreObservable.pipe(mergeMap((ctx: RequestContext) => middleware.pre(ctx))); + } + + return middlewarePreObservable.pipe(mergeMap((ctx: RequestContext) => _config.httpApi.send(ctx))). + pipe(mergeMap((response: ResponseContext) => { + let middlewarePostObservable = of(response); + for (const middleware of _config.middleware.reverse()) { + middlewarePostObservable = middlewarePostObservable.pipe(mergeMap((rsp: ResponseContext) => middleware.post(rsp))); + } + return middlewarePostObservable.pipe(map((rsp: ResponseContext) => this.responseProcessor.testDiscriminatorWithHttpInfo(rsp))); + })); + } + + /** + */ + public testDiscriminator(_options?: ConfigurationOptions): Observable { + return this.testDiscriminatorWithHttpInfo(_options).pipe(map((apiResponse: HttpInfo) => apiResponse.data)); + } + + /** + */ + public testWithoutDiscriminatorWithHttpInfo(_options?: ConfigurationOptions): Observable> { + const _config = mergeConfiguration(this.configuration, _options); + + const requestContextPromise = this.requestFactory.testWithoutDiscriminator(_config); + // build promise chain + let middlewarePreObservable = from(requestContextPromise); + for (const middleware of _config.middleware) { + middlewarePreObservable = middlewarePreObservable.pipe(mergeMap((ctx: RequestContext) => middleware.pre(ctx))); + } + + return middlewarePreObservable.pipe(mergeMap((ctx: RequestContext) => _config.httpApi.send(ctx))). + pipe(mergeMap((response: ResponseContext) => { + let middlewarePostObservable = of(response); + for (const middleware of _config.middleware.reverse()) { + middlewarePostObservable = middlewarePostObservable.pipe(mergeMap((rsp: ResponseContext) => middleware.post(rsp))); + } + return middlewarePostObservable.pipe(map((rsp: ResponseContext) => this.responseProcessor.testWithoutDiscriminatorWithHttpInfo(rsp))); + })); + } + + /** + */ + public testWithoutDiscriminator(_options?: ConfigurationOptions): Observable { + return this.testWithoutDiscriminatorWithHttpInfo(_options).pipe(map((apiResponse: HttpInfo) => apiResponse.data)); + } + +} diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/types/PromiseAPI.ts b/samples/openapi3/client/petstore/typescript/builds/one-of/types/PromiseAPI.ts new file mode 100644 index 000000000000..33478bfca351 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/types/PromiseAPI.ts @@ -0,0 +1,59 @@ +import { ResponseContext, RequestContext, HttpFile, HttpInfo } from '../http/http'; +import { Configuration, PromiseConfigurationOptions, wrapOptions } from '../configuration' +import { PromiseMiddleware, Middleware, PromiseMiddlewareWrapper } from '../middleware'; + +import { Cat } from '../models/Cat'; +import { Dog } from '../models/Dog'; +import { PetDiscriminatorResponse } from '../models/PetDiscriminatorResponse'; +import { PetResponse } from '../models/PetResponse'; +import { ObservableDefaultApi } from './ObservableAPI'; + +import { DefaultApiRequestFactory, DefaultApiResponseProcessor} from "../apis/DefaultApi"; +export class PromiseDefaultApi { + private api: ObservableDefaultApi + + public constructor( + configuration: Configuration, + requestFactory?: DefaultApiRequestFactory, + responseProcessor?: DefaultApiResponseProcessor + ) { + this.api = new ObservableDefaultApi(configuration, requestFactory, responseProcessor); + } + + /** + */ + public testDiscriminatorWithHttpInfo(_options?: PromiseConfigurationOptions): Promise> { + const observableOptions = wrapOptions(_options); + const result = this.api.testDiscriminatorWithHttpInfo(observableOptions); + return result.toPromise(); + } + + /** + */ + public testDiscriminator(_options?: PromiseConfigurationOptions): Promise { + const observableOptions = wrapOptions(_options); + const result = this.api.testDiscriminator(observableOptions); + return result.toPromise(); + } + + /** + */ + public testWithoutDiscriminatorWithHttpInfo(_options?: PromiseConfigurationOptions): Promise> { + const observableOptions = wrapOptions(_options); + const result = this.api.testWithoutDiscriminatorWithHttpInfo(observableOptions); + return result.toPromise(); + } + + /** + */ + public testWithoutDiscriminator(_options?: PromiseConfigurationOptions): Promise { + const observableOptions = wrapOptions(_options); + const result = this.api.testWithoutDiscriminator(observableOptions); + return result.toPromise(); + } + + +} + + + diff --git a/samples/openapi3/client/petstore/typescript/builds/one-of/util.ts b/samples/openapi3/client/petstore/typescript/builds/one-of/util.ts new file mode 100644 index 000000000000..96ea3dfdc770 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/builds/one-of/util.ts @@ -0,0 +1,37 @@ +/** + * Returns if a specific http code is in a given code range + * where the code range is defined as a combination of digits + * and "X" (the letter X) with a length of 3 + * + * @param codeRange string with length 3 consisting of digits and "X" (the letter X) + * @param code the http status code to be checked against the code range + */ +export function isCodeInRange(codeRange: string, code: number): boolean { + // This is how the default value is encoded in OAG + if (codeRange === "0") { + return true; + } + if (codeRange == code.toString()) { + return true; + } else { + const codeString = code.toString(); + if (codeString.length != codeRange.length) { + return false; + } + for (let i = 0; i < codeString.length; i++) { + if (codeRange.charAt(i) != "X" && codeRange.charAt(i) != codeString.charAt(i)) { + return false; + } + } + return true; + } +} + +/** +* Returns if it can consume form +* +* @param consumes array +*/ +export function canConsumeForm(contentTypes: string[]): boolean { + return contentTypes.indexOf('multipart/form-data') !== -1 +} diff --git a/samples/openapi3/client/petstore/typescript/tests/one-of/.gitignore b/samples/openapi3/client/petstore/typescript/tests/one-of/.gitignore new file mode 100644 index 000000000000..1521c8b7652b --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/tests/one-of/.gitignore @@ -0,0 +1 @@ +dist diff --git a/samples/openapi3/client/petstore/typescript/tests/one-of/package-lock.json b/samples/openapi3/client/petstore/typescript/tests/one-of/package-lock.json new file mode 100644 index 000000000000..653301bc0216 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/tests/one-of/package-lock.json @@ -0,0 +1,1560 @@ +{ + "name": "typescript-test", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "typescript-test", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "ts-node": "^10.9.2", + "ts-petstore-client": "file:../../builds/one-of" + }, + "devDependencies": { + "@types/chai": "^5.2.2", + "@types/mocha": "^10.0.10", + "@types/node": "^20", + "chai": "^6.2.0", + "mocha": "^11.7.4", + "nock": "^14.0.10", + "typescript": "^4.9.5" + } + }, + "../../builds/default": { + "name": "ts-petstore-client", + "version": "1.0.0", + "extraneous": true, + "license": "Unlicense", + "dependencies": { + "@types/node": "^16.18.126", + "@types/node-fetch": "^2.6.13", + "es6-promise": "^4.2.4", + "form-data": "^4.0.4", + "node-fetch": "^2.7.0" + }, + "devDependencies": { + "typescript": "^4.0" + } + }, + "../../builds/one-of": { + "name": "ts-petstore-client", + "version": "1.0.0", + "license": "Unlicense", + "dependencies": { + "@types/node": "^16.18.126", + "@types/node-fetch": "^2.6.13", + "es6-promise": "^4.2.4", + "form-data": "^4.0.4", + "node-fetch": "^2.7.0" + }, + "devDependencies": { + "typescript": "^4.0" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@mswjs/interceptors": { + "version": "0.39.8", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.39.8.tgz", + "integrity": "sha512-2+BzZbjRO7Ct61k8fMNHEtoKjeWI9pIlHFTqBwZ5icHpqszIgEZbjb1MW5Z0+bITTCTl3gk4PDBxs9tA/csXvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@open-draft/deferred-promise": "^2.2.0", + "@open-draft/logger": "^0.3.0", + "@open-draft/until": "^2.0.0", + "is-node-process": "^1.2.0", + "outvariant": "^1.4.3", + "strict-event-emitter": "^0.5.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@open-draft/deferred-promise": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", + "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@open-draft/logger": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", + "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-node-process": "^1.2.0", + "outvariant": "^1.4.0" + } + }, + "node_modules/@open-draft/until": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", + "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "license": "MIT" + }, + "node_modules/@types/chai": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.2.tgz", + "integrity": "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/mocha": { + "version": "10.0.10", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.10.tgz", + "integrity": "sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.17.27", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.27.tgz", + "integrity": "sha512-U58sbKhDrthHlxHRJw7ZLiLDZGmAUOZUbpw0S6nL27sYUdhvgBLCRu/keSd6qcTsfArd1sRFCCBxzWATGr/0UA==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true, + "license": "ISC" + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chai": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.0.tgz", + "integrity": "sha512-aUTnJc/JipRzJrNADXVvpVqi6CO0dn3nx4EVPxijri+fj3LUUDyZQOgVeW54Ob3Y1Xh9Iz8f+CgaCl8v0mn9bA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/diff": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-node-process": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", + "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, + "license": "ISC" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "license": "ISC" + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mocha": { + "version": "11.7.4", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.4.tgz", + "integrity": "sha512-1jYAaY8x0kAZ0XszLWu14pzsf4KV740Gld4HXkhNTXwcHx4AUEDkPzgEHg9CM5dVcW+zv036tjpsEbLraPJj4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "browser-stdout": "^1.3.1", + "chokidar": "^4.0.1", + "debug": "^4.3.5", + "diff": "^7.0.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^10.4.5", + "he": "^1.2.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^9.0.5", + "ms": "^2.1.3", + "picocolors": "^1.1.1", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^9.2.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1", + "yargs-unparser": "^2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nock": { + "version": "14.0.10", + "resolved": "https://registry.npmjs.org/nock/-/nock-14.0.10.tgz", + "integrity": "sha512-Q7HjkpyPeLa0ZVZC5qpxBt5EyLczFJ91MEewQiIi9taWuA0KB/MDJlUWtON+7dGouVdADTQsf9RA7TZk6D8VMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@mswjs/interceptors": "^0.39.5", + "json-stringify-safe": "^5.0.1", + "propagate": "^2.0.0" + }, + "engines": { + "node": ">=18.20.0 <20 || >=20.12.1" + } + }, + "node_modules/outvariant": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz", + "integrity": "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==", + "dev": true, + "license": "MIT" + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/propagate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", + "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/strict-event-emitter": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz", + "integrity": "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/ts-petstore-client": { + "resolved": "../../builds/one-of", + "link": true + }, + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "license": "MIT" + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "license": "MIT" + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/workerpool": { + "version": "9.3.4", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.4.tgz", + "integrity": "sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/samples/openapi3/client/petstore/typescript/tests/one-of/package.json b/samples/openapi3/client/petstore/typescript/tests/one-of/package.json new file mode 100644 index 000000000000..759b47190297 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/tests/one-of/package.json @@ -0,0 +1,28 @@ +{ + "private": true, + "dependencies": { + "ts-node": "^10.9.2", + "ts-petstore-client": "file:../../builds/one-of" + }, + "scripts": { + "test": "mocha test/**/*.ts -r ts-node/register --timeout 10000", + "build": "tsc" + }, + "devDependencies": { + "@types/chai": "^5.2.2", + "@types/mocha": "^10.0.10", + "@types/node": "^20", + "chai": "^6.2.0", + "mocha": "^11.7.4", + "nock": "^14.0.10", + "typescript": "^4.9.5" + }, + "name": "typescript-test", + "version": "1.0.0", + "directories": { + "test": "test" + }, + "author": "", + "license": "ISC", + "description": "" +} diff --git a/samples/openapi3/client/petstore/typescript/tests/one-of/pom.xml b/samples/openapi3/client/petstore/typescript/tests/one-of/pom.xml new file mode 100644 index 000000000000..4152f9e3a921 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/tests/one-of/pom.xml @@ -0,0 +1,73 @@ + + 4.0.0 + org.openapitools + TypeScriptDefaultPetstoreClientTests + pom + 1.0-SNAPSHOT + TS Petstore Test Client + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory} + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.2.1 + + + npm-install + pre-integration-test + + exec + + + npm + + install + + + + + npm-build + pre-integration-test + + exec + + + npm + + run + build + + + + + npm-test + integration-test + + exec + + + npm + + test + + + + + + + + diff --git a/samples/openapi3/client/petstore/typescript/tests/one-of/test/api/DefaultApi.test.ts b/samples/openapi3/client/petstore/typescript/tests/one-of/test/api/DefaultApi.test.ts new file mode 100644 index 000000000000..5c4e69adc816 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/tests/one-of/test/api/DefaultApi.test.ts @@ -0,0 +1,23 @@ +import * as petstore from 'ts-petstore-client' +import { BASE_URL } from './server'; +import { expect } from "chai"; + +const server = new petstore.ServerConfiguration(BASE_URL, {}) +const configuration = petstore.createConfiguration({ + baseServer: server +}) +const DefaultApi = new petstore.DefaultApi(configuration) + + +describe("Test oneOf API methods", () => { + + it("Without discriminator", async () => { + const response = await DefaultApi.testWithoutDiscriminator(); + expect(response).to.be.instanceof(petstore.Cat); + }) + + it("With discriminator", async () => { + const response = await DefaultApi.testDiscriminator(); + expect(response).to.be.instanceof(petstore.Dog); + }) +}) \ No newline at end of file diff --git a/samples/openapi3/client/petstore/typescript/tests/one-of/test/api/server.ts b/samples/openapi3/client/petstore/typescript/tests/one-of/test/api/server.ts new file mode 100644 index 000000000000..d7680d58d6c4 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/tests/one-of/test/api/server.ts @@ -0,0 +1,31 @@ +import nock from 'nock'; + +export const BASE_URL = 'http://localhost:1234'; + +// Prevent any unmocked requests from making actual HTTP requests. +nock.disableNetConnect(); + +const mockPath = (path: string, value: any) => { + const body = JSON.stringify(value); + const headers = { 'content-type': 'application/json' }; + nock(BASE_URL).get(path).reply(200, body, headers).persist(); +} + +mockPath( + '/test', + { + "petType": "Cat", + "name": "Misty" + } +) + +mockPath( + '/test-discriminator', + { + "petType": "dog", + "bark": "soft" + } +) + + + diff --git a/samples/openapi3/client/petstore/typescript/tests/one-of/tsconfig.json b/samples/openapi3/client/petstore/typescript/tests/one-of/tsconfig.json new file mode 100644 index 000000000000..cc053f907cf3 --- /dev/null +++ b/samples/openapi3/client/petstore/typescript/tests/one-of/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es6", + "noImplicitAny": true, + "sourceMap": false, + "esModuleInterop": true, + "outDir": "dist", + "types": [ + "mocha", + "node" + ], + "lib": [ + "es6", + "dom" + ] + }, + "exclude": [ + "node_modules" + ] +}