From 614aac28717acc1f4cdafd149770ccb4b5f69f9b Mon Sep 17 00:00:00 2001 From: js2me Date: Wed, 30 Nov 2022 14:23:52 +0600 Subject: [PATCH] fix: try to fix problem with extracting enums --- src/code-gen-process.js | 92 +++------ src/data-contracts.js | 139 ++++++++++++++ .../base-schema-parsers/discriminator.js | 13 ++ src/schema-parser/base-schema-parsers/enum.js | 31 +-- .../base-schema-parsers/object.js | 10 +- src/schema-parser/mono-schema-parser.js | 3 + src/schema-parser/schema-parser-fabric.js | 26 ++- src/schema-parser/schema-parser.js | 3 + src/schema-parser/schema-utils.js | 61 ++++-- src/schema-routes/schema-routes.js | 180 +++++++++--------- src/type-name-formatter.js | 14 +- tests/spec/extract-enums/schema.ts | 74 +++---- 12 files changed, 408 insertions(+), 238 deletions(-) create mode 100644 src/data-contracts.js diff --git a/src/code-gen-process.js b/src/code-gen-process.js index a6fa5b29..d6c75333 100644 --- a/src/code-gen-process.js +++ b/src/code-gen-process.js @@ -16,6 +16,7 @@ const { CodeFormatter } = require("./code-formatter"); const { pascalCase } = require("./util/pascal-case"); const { internalCase } = require("./util/internal-case"); const { sortByProperty } = require("./util/sort-by-property"); +const { DataContracts } = require("./data-contracts"); const PATCHABLE_INSTANCES = [ "schemaWalker", @@ -52,6 +53,8 @@ class CodeGenProcess { templatesWorker; /** @type {SchemaWalker} */ schemaWalker; + /** @type {DataContracts} */ + dataContracts; /** @type {JavascriptTranslator} */ javascriptTranslator; @@ -70,9 +73,13 @@ class CodeGenProcess { this.templatesWorker = new TemplatesWorker(this); this.codeFormatter = new CodeFormatter(this); this.schemaParserFabric = new SchemaParserFabric(this); + this.dataContracts = new DataContracts(this); this.schemaRoutes = new SchemaRoutes(this); this.javascriptTranslator = new JavascriptTranslator(this); + this.config.componentTypeNameResolver.logger = this.logger; + this.schemaParserFabric.dataContracts = this.dataContracts; + this.schemaParserFabric.schemaUtils.dataContracts = this.dataContracts; } async start() { @@ -99,24 +106,16 @@ class CodeGenProcess { _.each(swagger.usageSchema.components, (component, componentName) => _.each(component, (rawTypeData, typeName) => { - this.schemaComponentsMap.createComponent( - this.schemaComponentsMap.createRef(["components", componentName, typeName]), - rawTypeData, - ); + this.dataContracts.add({ + schema: rawTypeData, + name: typeName, + contractType: componentName, + }); }), ); - const schemaComponents = this.schemaComponentsMap.filter("schemas"); - - const parsedSchemas = schemaComponents.map((schemaComponent) => { - const parsed = this.schemaParserFabric.parseSchema(schemaComponent.rawTypeData, schemaComponent.typeName); - schemaComponent.typeData = parsed; - return parsed; - }); - this.schemaRoutes.attachSchema({ usageSchema: swagger.usageSchema, - parsedSchemas, }); const rawConfiguration = { @@ -206,65 +205,22 @@ class CodeGenProcess { }; collectModelTypes = () => { - const components = this.schemaComponentsMap.getComponents(); - let modelTypes = []; - - const getSchemaComponentsCount = () => components.filter((c) => c.componentName === "schemas").length; - - let schemaComponentsCount = getSchemaComponentsCount(); - let processedCount = 0; - - while (processedCount < schemaComponentsCount) { - modelTypes = []; - processedCount = 0; - for (const component of components) { - if (component.componentName === "schemas") { - const modelType = this.prepareModelType(component); - if (modelType) { - modelTypes.push(modelType); - } - processedCount++; - } - } - schemaComponentsCount = getSchemaComponentsCount(); - } + let dataContracts = [...this.dataContracts.values]; if (this.config.sortTypes) { - return modelTypes.sort(sortByProperty("name")); + return dataContracts.sort(sortByProperty("name")); } - return modelTypes; - }; - - prepareModelType = (typeInfo) => { - if (typeInfo.$prepared) return typeInfo.$prepared; - - if (!typeInfo.typeData) { - typeInfo.typeData = this.schemaParserFabric.parseSchema(typeInfo.rawTypeData, typeInfo.typeName); - } - const rawTypeData = typeInfo.typeData; - const typeData = this.schemaParserFabric.schemaFormatters.base[rawTypeData.type] - ? this.schemaParserFabric.schemaFormatters.base[rawTypeData.type](rawTypeData) - : rawTypeData; - let { typeIdentifier, name: originalName, content, description } = typeData; - const name = this.typeNameFormatter.format(originalName); - - if (name === null) return null; - - const preparedModelType = { - ...typeData, - typeIdentifier, - name, - description, - $content: rawTypeData.content, - rawContent: rawTypeData.content, - content: content, - typeData, - }; - - typeInfo.$prepared = preparedModelType; - - return preparedModelType; + return dataContracts.map((dataContract) => { + return { + ...dataContract.schemas.parsed, + name: dataContract.name, + $content: dataContract.schemas.parsed.content, + rawContent: dataContract.schemas.parsed.content, + content: dataContract.content, + typeData: dataContract.schemas.parsed, + }; + }); }; /** diff --git a/src/data-contracts.js b/src/data-contracts.js new file mode 100644 index 00000000..99622838 --- /dev/null +++ b/src/data-contracts.js @@ -0,0 +1,139 @@ +const _ = require("lodash"); + +/** + * @typedef {{ + * $ref: string, + * schemas: { original: Record, parsed: Record, ref: Record }, + * content: Record | string, + * inlineContent: string, + * refContent: string, + * name: string, + * typeName: string, + * linkers: string[], + * }} DataContract + */ + +class DataContracts { + /** @type {CodeGenConfig} */ + config; + /** @type {Logger} */ + logger; + /** @type {SchemaParserFabric} */ + schemaParserFabric; + /** @type {TypeNameFormatter} */ + typeNameFormatter; + /** @type {SchemaUtils} */ + schemaUtils; + /** @type {SchemaComponentsMap} */ + schemaComponentsMap; + + /** @type {DataContract[]} */ + values; + + constructor({ config, logger, schemaParserFabric }) { + this.values = []; + this.config = config; + this.logger = logger; + this.schemaParserFabric = schemaParserFabric; + this.schemaUtils = this.schemaParserFabric.schemaUtils; + this.typeNameFormatter = this.schemaParserFabric.typeNameFormatter; + this.schemaComponentsMap = this.schemaParserFabric.schemaComponentsMap; + } + + _createDataContractNames = (name, builder) => { + if (!builder) { + const formatted = this.typeNameFormatter.format(name); + const usageName = this.config.componentTypeNameResolver.resolve([formatted]); + + return { formatted, usageName, originalName: name }; + } + + const { usageName, original, formatted } = builder(); + + return { formatted: formatted || usageName, usageName, originalName: original || null }; + }; + + /** + * + * @param schema + * @param name + * @param $ref + * @param {() => ({ usageName: string, formatted: string, original: string })} [nameBuilder] + * @returns {DataContract} + */ + add = ({ schema, name, nameBuilder, contractType = "schemas", schemaPath }) => { + const { formatted, usageName, originalName } = this._createDataContractNames(name, nameBuilder); + const parser = this.schemaParserFabric.createSchemaParser({ + schema, + typeName: originalName, + schemaPath, + }); + const parsed = parser.parseSchema(); + const $ref = this.schemaComponentsMap.createRef(["components", contractType, usageName]); + + const refContent = usageName; + + const linkers = _.uniq( + _.compact([ + originalName, + usageName, + formatted, + $ref, + originalName && this.typeNameFormatter.format(originalName, { onlyFormat: true }), + originalName && this.schemaComponentsMap.createRef(["components", "schemas", originalName]), + this.schemaComponentsMap.createRef(["components", "schemas", formatted]), + refContent, + ]), + ); + + /** + * @type {DataContract} + */ + const dataContract = { + $ref: $ref, + schemas: { + original: schema, + parsed, + }, + refContent, + content: parser.getParseContent(), + inlineContent: parser.getInlineParseContent(), + name: usageName, + typeName: usageName, + linkers: linkers, + }; + + this.values.push(dataContract); + + dataContract.schemas.ref = this.schemaParserFabric.parseSchema({ $ref: $ref }); + + return dataContract; + }; + + /** + * @param name + * @returns {DataContract | null} + */ + findByLinker = (name) => { + return this.values.find((value) => value.linkers.includes(name)) || null; + }; + + /** + * @param content + * @returns {DataContract | null} + */ + findByContent = (content) => { + return ( + this.values.find( + (value) => + _.isEqual(value.content, content) || + _.isEqual(value.inlineContent, content) || + _.isEqual(value.refContent, content), + ) || null + ); + }; +} + +module.exports = { + DataContracts, +}; diff --git a/src/schema-parser/base-schema-parsers/discriminator.js b/src/schema-parser/base-schema-parsers/discriminator.js index af45c082..137308b1 100644 --- a/src/schema-parser/base-schema-parsers/discriminator.js +++ b/src/schema-parser/base-schema-parsers/discriminator.js @@ -210,6 +210,19 @@ class DiscriminatorSchemaParser extends MonoSchemaParser { prefixes: this.config.extractingOptions.discriminatorAbstractPrefix, resolver: this.config.extractingOptions.discriminatorAbstractResolver, }); + this.dataContracts.add({ + schema: { ...schema, internal: true }, + nameBuilder: () => { + const usageName = this.schemaUtils.resolveTypeName(this.typeName, { + prefixes: this.config.extractingOptions.discriminatorAbstractPrefix, + resolver: this.config.extractingOptions.discriminatorAbstractResolver, + }); + return { + usageName, + original: this.typeName, + }; + }, + }); const component = this.schemaComponentsMap.createComponent( this.schemaComponentsMap.createRef(["components", "schemas", typeName]), { diff --git a/src/schema-parser/base-schema-parsers/enum.js b/src/schema-parser/base-schema-parsers/enum.js index ec5e78d1..46681043 100644 --- a/src/schema-parser/base-schema-parsers/enum.js +++ b/src/schema-parser/base-schema-parsers/enum.js @@ -14,17 +14,21 @@ class EnumSchemaParser extends MonoSchemaParser { } extractEnum = (pathTypeName) => { - const generatedTypeName = this.schemaUtils.resolveTypeName(pathTypeName, { - suffixes: this.config.extractingOptions.enumSuffix, - resolver: this.config.extractingOptions.enumNameResolver, - }); - const customComponent = this.schemaComponentsMap.createComponent( - this.schemaComponentsMap.createRef(["components", "schemas", generatedTypeName]), - { - ...this.schema, + const dataContract = this.dataContracts.add({ + schema: { ...this.schema }, + nameBuilder: () => { + const usageName = this.schemaUtils.resolveTypeName(pathTypeName, { + suffixes: this.config.extractingOptions.enumSuffix, + resolver: this.config.extractingOptions.enumNameResolver, + }); + + return { + usageName, + original: pathTypeName, + }; }, - ); - return this.schemaParserFabric.parseSchema(customComponent); + }); + return dataContract.schemas.ref; }; parse() { @@ -34,8 +38,7 @@ class EnumSchemaParser extends MonoSchemaParser { return this.extractEnum(pathTypeName); } - const refType = this.schemaUtils.getSchemaRefType(this.schema); - const $ref = (refType && refType.$ref) || null; + const dc = this.schemaUtils.findDataContract(this.schema); // fix schema when enum has length 1+ but value is [] if (Array.isArray(this.schema.enum)) { @@ -104,8 +107,8 @@ class EnumSchemaParser extends MonoSchemaParser { return { ...(_.isObject(this.schema) ? this.schema : {}), - $ref: $ref, - typeName: this.typeName || ($ref && refType.typeName) || null, + $ref: dc?.$ref, + typeName: this.typeName || (dc?.$ref && dc?.name) || null, $parsedSchema: true, schemaType: SCHEMA_TYPES.ENUM, type: SCHEMA_TYPES.ENUM, diff --git a/src/schema-parser/base-schema-parsers/object.js b/src/schema-parser/base-schema-parsers/object.js index fe28e137..43b41a21 100644 --- a/src/schema-parser/base-schema-parsers/object.js +++ b/src/schema-parser/base-schema-parsers/object.js @@ -24,9 +24,11 @@ class ObjectSchemaParser extends MonoSchemaParser { const { properties, additionalProperties } = schema || {}; const propertiesContent = _.map(properties, (property, name) => { + /** @type {DataContract|null} */ + const propDc = this.schemaUtils.findDataContract(property); const required = this.schemaUtils.isPropertyRequired(name, property, schema); - const rawTypeData = _.get(this.schemaUtils.getSchemaRefType(property), "rawTypeData", {}); - const nullable = !!(rawTypeData.nullable || property.nullable); + const parsedDcSchema = propDc?.schemas.parsed || {}; + const nullable = !!(parsedDcSchema.nullable || property.nullable); const fieldName = this.typeNameFormatter.isValidName(name) ? name : this.config.Ts.StringValue(name); const fieldValue = this.schemaParserFabric .createSchemaParser({ schema: property, schemaPath: [...this.schemaPath, name] }) @@ -40,8 +42,8 @@ class ObjectSchemaParser extends MonoSchemaParser { description: property.description || _.compact(_.map(property[this.schemaUtils.getComplexType(property)], "description"))[0] || - rawTypeData.description || - _.compact(_.map(rawTypeData[this.schemaUtils.getComplexType(rawTypeData)], "description"))[0] || + parsedDcSchema.description || + _.compact(_.map(parsedDcSchema[this.schemaUtils.getComplexType(parsedDcSchema)], "description"))[0] || "", isRequired: required, isNullable: nullable, diff --git a/src/schema-parser/mono-schema-parser.js b/src/schema-parser/mono-schema-parser.js index 66743463..f5c12f36 100644 --- a/src/schema-parser/mono-schema-parser.js +++ b/src/schema-parser/mono-schema-parser.js @@ -21,6 +21,8 @@ class MonoSchemaParser { config; /** @type {SchemaFormatters} */ schemaFormatters; + /** @type {DataContracts} */ + dataContracts; constructor(schemaParser, schema, typeName = null, schemaPath = []) { this.schemaParser = schemaParser; @@ -34,6 +36,7 @@ class MonoSchemaParser { this.schemaUtils = this.schemaParser.schemaUtils; this.config = this.schemaParser.config; this.schemaFormatters = this.schemaParser.schemaFormatters; + this.dataContracts = this.schemaParser.dataContracts; } parse() { diff --git a/src/schema-parser/schema-parser-fabric.js b/src/schema-parser/schema-parser-fabric.js index d6293c75..1b810c81 100644 --- a/src/schema-parser/schema-parser-fabric.js +++ b/src/schema-parser/schema-parser-fabric.js @@ -24,14 +24,25 @@ class SchemaParserFabric { schemaUtils; /** @type {SchemaWalker} */ schemaWalker; + /** @type {DataContracts} */ + dataContracts; - constructor({ config, logger, templatesWorker, schemaComponentsMap, typeNameFormatter, schemaWalker }) { + constructor({ + config, + logger, + templatesWorker, + schemaComponentsMap, + typeNameFormatter, + schemaWalker, + dataContracts, + }) { this.config = config; this.logger = logger; this.schemaComponentsMap = schemaComponentsMap; this.typeNameFormatter = typeNameFormatter; this.templatesWorker = templatesWorker; this.schemaWalker = schemaWalker; + this.dataContracts = dataContracts; this.schemaUtils = new SchemaUtils(this); this.schemaFormatters = new SchemaFormatters(this); } @@ -63,19 +74,6 @@ class SchemaParserFabric { return parser.schema; }; - createParsedComponent = ({ typeName, schema, schemaPath }) => { - const schemaCopy = _.cloneDeep(schema); - const customComponent = this.schemaComponentsMap.createComponent( - this.schemaComponentsMap.createRef(["components", "schemas", typeName]), - schemaCopy, - ); - const parsed = this.parseSchema(schemaCopy, null, schemaPath); - parsed.name = typeName; - customComponent.typeData = parsed; - - return customComponent; - }; - /** * * @param schema {any} diff --git a/src/schema-parser/schema-parser.js b/src/schema-parser/schema-parser.js index e00c471a..06afebfb 100644 --- a/src/schema-parser/schema-parser.js +++ b/src/schema-parser/schema-parser.js @@ -36,6 +36,8 @@ class SchemaParser { templatesWorker; /** @type {SchemaWalker} */ schemaWalker; + /** @type {DataContracts} */ + dataContracts; typeName; schema; @@ -51,6 +53,7 @@ class SchemaParser { this.schemaWalker = schemaParserFabric.schemaWalker; this.schemaFormatters = schemaParserFabric.schemaFormatters; this.schemaUtils = schemaParserFabric.schemaUtils; + this.dataContracts = schemaParserFabric.dataContracts; this.typeName = typeName || null; this.schema = schema; diff --git a/src/schema-parser/schema-utils.js b/src/schema-parser/schema-utils.js index 299a0494..a83b555d 100644 --- a/src/schema-parser/schema-utils.js +++ b/src/schema-parser/schema-utils.js @@ -13,12 +13,15 @@ class SchemaUtils { typeNameFormatter; /** @type {SchemaWalker} */ schemaWalker; + /** @type {DataContracts} */ + dataContracts; - constructor({ config, schemaComponentsMap, typeNameFormatter, schemaWalker }) { + constructor({ config, schemaComponentsMap, typeNameFormatter, schemaWalker, dataContracts }) { this.config = config; this.schemaComponentsMap = schemaComponentsMap; this.typeNameFormatter = typeNameFormatter; this.schemaWalker = schemaWalker; + this.dataContracts = dataContracts; } getRequiredProperties = (schema) => { @@ -33,10 +36,24 @@ class SchemaUtils { return schema["x-enumNames"] || schema["xEnumNames"] || schema["x-enumnames"] || schema["x-enum-varnames"]; }; + /** + * @param schema + * @returns {DataContract|null} + */ getSchemaRefType = (schema) => { if (!this.isRefSchema(schema)) return null; // const resolved = this.schemaWalker.findByRef(schema.$ref); - return this.schemaComponentsMap.get(schema.$ref); + return this.dataContracts.findByLinker(schema.$ref); + }; + + /** + * @param schema + * @returns {DataContract|null} + */ + findDataContract = (schema) => { + if (!this.isRefSchema(schema)) return null; + // const resolved = this.schemaWalker.findByRef(schema.$ref); + return this.dataContracts.findByLinker(schema.$ref); }; isPropertyRequired = (name, propertySchema, rootSchema) => { @@ -118,10 +135,11 @@ class SchemaUtils { const required = _.uniq([...this.getRequiredProperties(parentSchema), ...this.getRequiredProperties(childSchema)]); - const refData = this.getSchemaRefType(childSchema); + /** @type {DataContract | null} */ + const dc = this.findDataContract(childSchema); - if (refData) { - const refObjectProperties = _.keys((refData.rawTypeData && refData.rawTypeData.properties) || {}); + if (dc) { + const refObjectProperties = _.keys(dc.schemas.original?.properties || {}); const existedRequiredKeys = refObjectProperties.filter((key) => required.includes(key)); if (!existedRequiredKeys.length) return childSchema; @@ -156,8 +174,8 @@ class SchemaUtils { }); } else { return this.config.componentTypeNameResolver.resolve([ - ...(prefixes || []).map((prefix) => pascalCase(`${prefix} ${typeName}`)), - ...(suffixes || []).map((suffix) => pascalCase(`${typeName} ${suffix}`)), + ...(prefixes || []).map((prefix) => this.typeNameFormatter.format(pascalCase(`${prefix} ${typeName}`))), + ...(suffixes || []).map((suffix) => this.typeNameFormatter.format(pascalCase(`${typeName} ${suffix}`))), ]); } }; @@ -185,13 +203,10 @@ class SchemaUtils { getSchemaType = (schema) => { if (!schema) return this.config.Ts.Keyword.Any; - const refTypeInfo = this.getSchemaRefType(schema); + const dc = this.findDataContract(schema); - if (refTypeInfo) { - return this.checkAndAddRequiredKeys( - schema, - this.safeAddNullToType(schema, this.typeNameFormatter.format(refTypeInfo.typeName)), - ); + if (dc) { + return this.checkAndAddRequiredKeys(schema, this.safeAddNullToType(schema, dc.name)); } const primitiveType = this.getSchemaPrimitiveType(schema); @@ -223,6 +238,26 @@ class SchemaUtils { return pascalCase(camelCase(_.uniq([schemaPath[0], schemaPath[schemaPath.length - 1]]).join("_"))); }; + + getSchemaFromRequestType = (requestInfo) => { + const content = _.get(requestInfo, "content"); + + if (!content) return null; + + /* content: { "multipart/form-data": { schema: {...} }, "application/json": { schema: {...} } } */ + + /* for example: dataType = "multipart/form-data" */ + for (const dataType in content) { + if (content[dataType] && content[dataType].schema) { + return { + ...content[dataType].schema, + dataType, + }; + } + } + + return null; + }; } module.exports = { diff --git a/src/schema-routes/schema-routes.js b/src/schema-routes/schema-routes.js index ef42cbf3..885cba91 100644 --- a/src/schema-routes/schema-routes.js +++ b/src/schema-routes/schema-routes.js @@ -21,34 +21,22 @@ const CONTENT_KIND = { }; class SchemaRoutes { - /** - * @type {CodeGenConfig} - */ + /** @type {CodeGenConfig} */ config; - /** - * @type {SchemaParserFabric} - */ + /** @type {SchemaParserFabric} */ schemaParserFabric; - /** - * @type {SchemaUtils} - */ + /** @type {SchemaUtils} */ schemaUtils; - /** - * @type {TypeNameFormatter} - */ + /** @type {TypeNameFormatter} */ typeNameFormatter; - /** - * @type {SchemaComponentsMap} - */ + /** @type {SchemaComponentsMap} */ schemaComponentsMap; - /** - * @type {Logger} - */ + /** @type {Logger} */ logger; - /** - * @type {TemplatesWorker} - */ + /** @type {TemplatesWorker} */ templatesWorker; + /** @type {DataContracts} */ + dataContracts; FORM_DATA_TYPES = []; @@ -57,7 +45,15 @@ class SchemaRoutes { hasQueryRoutes = false; hasFormDataRoutes = false; - constructor({ config, schemaParserFabric, schemaComponentsMap, logger, templatesWorker, typeNameFormatter }) { + constructor({ + config, + schemaParserFabric, + schemaComponentsMap, + logger, + templatesWorker, + typeNameFormatter, + dataContracts, + }) { this.config = config; this.schemaParserFabric = schemaParserFabric; this.schemaUtils = this.schemaParserFabric.schemaUtils; @@ -65,6 +61,7 @@ class SchemaRoutes { this.schemaComponentsMap = schemaComponentsMap; this.logger = logger; this.templatesWorker = templatesWorker; + this.dataContracts = dataContracts; this.FORM_DATA_TYPES = _.uniq([ this.schemaUtils.getSchemaType({ type: "string", format: "file" }), @@ -193,17 +190,19 @@ class SchemaRoutes { }; _.each(parameters, (parameter) => { - const refTypeInfo = this.schemaParserFabric.schemaUtils.getSchemaRefType(parameter); + /** @type {DataContract | null} */ + const dc = this.schemaUtils.findDataContract(parameter); + const dcOrigSchema = dc?.schemas.original; let routeParam = null; - if (refTypeInfo && refTypeInfo.rawTypeData.in && refTypeInfo.rawTypeData) { - if (!routeParams[refTypeInfo.rawTypeData.in]) { - routeParams[refTypeInfo.rawTypeData.in] = []; + if (dcOrigSchema?.in) { + if (!routeParams[dcOrigSchema.in]) { + routeParams[dcOrigSchema.in] = []; } routeParam = { - ...refTypeInfo.rawTypeData, - ...(refTypeInfo.rawTypeData.schema || {}), + ...dcOrigSchema, + ...(dcOrigSchema.schema || {}), }; } else { if (!parameter.in) return; @@ -309,55 +308,51 @@ class SchemaRoutes { return null; }; - getTypeFromRequestInfo = ({ requestInfo, parsedSchemas, operationId, defaultType, typeName }) => { + getTypeFromRequestInfo = ({ requestInfo, operationId, defaultType, typeName }) => { // TODO: make more flexible pick schema without content type const schema = this.getSchemaFromRequestType(requestInfo); - const refTypeInfo = this.schemaParserFabric.schemaUtils.getSchemaRefType(requestInfo); + const dc = this.schemaUtils.findDataContract(requestInfo); if (schema) { const content = this.schemaParserFabric.getInlineParseContent(schema, typeName, [operationId]); - const foundedSchemaByName = _.find( - parsedSchemas, - (parsedSchema) => this.typeNameFormatter.format(parsedSchema.name) === content, - ); - const foundSchemaByContent = _.find(parsedSchemas, (parsedSchema) => _.isEqual(parsedSchema.content, content)); - - const foundSchema = foundedSchemaByName || foundSchemaByContent; + const dc = this.dataContracts.findByLinker(content) || this.dataContracts.findByContent(content); - return foundSchema ? this.typeNameFormatter.format(foundSchema.name) : content; + return dc ? dc.refContent : content; } - if (refTypeInfo) { + if (dc) { // const refTypeWithoutOpId = refType.replace(operationId, ''); // const foundedSchemaByName = _.find(parsedSchemas, ({ name }) => name === refType || name === refTypeWithoutOpId) // TODO:HACK fix problem of swagger2opeanpi - const typeNameWithoutOpId = _.replace(refTypeInfo.typeName, operationId, ""); - if (_.find(parsedSchemas, (schema) => schema.name === typeNameWithoutOpId)) { - return this.typeNameFormatter.format(typeNameWithoutOpId); + const typeNameWithoutOpId = _.replace(dc.typeName, operationId, ""); + + const dc = + this.dataContracts.findByLinker(typeNameWithoutOpId) || this.dataContracts.findByContent(typeNameWithoutOpId); + + if (dc) { + return dc.refContent; } - switch (refTypeInfo.componentName) { + switch (dc.componentName) { case "schemas": - return this.typeNameFormatter.format(refTypeInfo.typeName); + return name; case "responses": case "requestBodies": return this.schemaParserFabric.getInlineParseContent( - this.getSchemaFromRequestType(refTypeInfo.rawTypeData), - refTypeInfo.typeName || null, + this.getSchemaFromRequestType(dc.schemas.original), + dc.name || null, [operationId], ); default: - return this.schemaParserFabric.getInlineParseContent(refTypeInfo.rawTypeData, refTypeInfo.typeName || null, [ - operationId, - ]); + return dc.inlineContent; } } return defaultType || this.config.Ts.Keyword.Any; }; - getRequestInfoTypes = ({ requestInfos, parsedSchemas, operationId, defaultType }) => + getRequestInfoTypes = ({ requestInfos, operationId, defaultType }) => _.reduce( requestInfos, (acc, requestInfo, status) => { @@ -373,7 +368,6 @@ class SchemaRoutes { requestInfo, this.getTypeFromRequestInfo({ requestInfo, - parsedSchemas, operationId, defaultType, }), @@ -390,14 +384,13 @@ class SchemaRoutes { [], ); - getResponseBodyInfo = (routeInfo, routeParams, parsedSchemas) => { + getResponseBodyInfo = (routeInfo, routeParams) => { const { produces, operationId, responses } = routeInfo; const contentTypes = this.getContentTypes(responses, [...(produces || []), routeInfo["x-accepts"]]); const responseInfos = this.getRequestInfoTypes({ requestInfos: responses, - parsedSchemas, operationId, defaultType: this.config.defaultResponseType, }); @@ -479,7 +472,7 @@ class SchemaRoutes { ); }; - getRequestBodyInfo = (routeInfo, routeParams, parsedSchemas, routeName) => { + getRequestBodyInfo = (routeInfo, routeParams, routeName) => { const { requestBody, consumes, requestBodyName, operationId } = routeInfo; let schema = null; let content = null; @@ -509,7 +502,6 @@ class SchemaRoutes { requestBody, this.getTypeFromRequestInfo({ requestInfo: requestBody, - parsedSchemas, operationId, typeName, }), @@ -524,12 +516,16 @@ class SchemaRoutes { } if (schema && !schema.$ref && this.config.extractRequestBody) { - schema = this.schemaParserFabric.createParsedComponent({ - schema, - typeName, + const dc = this.dataContracts.add({ + schema: { ...schema }, + nameBuilder: () => ({ + original: routeName.usage, + usageName: typeName, + }), schemaPath: [operationId], }); - content = this.schemaParserFabric.getInlineParseContent({ $ref: schema.$ref }); + schema = dc.schemas.parsed; + content = dc.refContent; } return { @@ -594,15 +590,22 @@ class SchemaRoutes { if (fixedSchema) return fixedSchema; if (extractRequestParams) { - const generatedTypeName = this.schemaUtils.resolveTypeName(routeName.usage, { - suffixes: this.config.extractingOptions.requestParamsSuffix, - resolver: this.config.extractingOptions.requestParamsNameResolver, - }); + const dc = this.dataContracts.add({ + schema, + nameBuilder: () => { + const usageName = this.schemaUtils.resolveTypeName(routeName.usage, { + suffixes: this.config.extractingOptions.requestParamsSuffix, + resolver: this.config.extractingOptions.requestParamsNameResolver, + }); - return this.schemaParserFabric.createParsedComponent({ - typeName: generatedTypeName, - schema: schema, + return { + usageName, + original: routeName.usage, + }; + }, }); + + return dc.schemas.parsed; } return schema; @@ -610,23 +613,29 @@ class SchemaRoutes { extractResponseBodyIfItNeeded = (routeInfo, responseBodyInfo, routeName) => { if (responseBodyInfo.responses.length && responseBodyInfo.success && responseBodyInfo.success.schema) { - const typeName = this.schemaUtils.resolveTypeName(routeName.usage, { - suffixes: this.config.extractingOptions.responseBodySuffix, - resolver: this.config.extractingOptions.responseBodyNameResolver, - }); - const idx = responseBodyInfo.responses.indexOf(responseBodyInfo.success.schema); let successResponse = responseBodyInfo.success; if (successResponse.schema && !successResponse.schema.$ref) { const schema = this.getSchemaFromRequestType(successResponse.schema); - successResponse.schema = this.schemaParserFabric.createParsedComponent({ + const dc = this.dataContracts.add({ schema, - typeName, + nameBuilder: () => { + const usageName = this.schemaUtils.resolveTypeName(routeName.usage, { + suffixes: this.config.extractingOptions.responseBodySuffix, + resolver: this.config.extractingOptions.responseBodyNameResolver, + }); + + return { + usageName, + original: routeName.usage, + }; + }, schemaPath: [routeInfo.operationId], }); - successResponse.type = this.schemaParserFabric.getInlineParseContent({ $ref: successResponse.schema.$ref }); + successResponse.schema = dc.schemas.parsed; + successResponse.type = dc.refContent; if (idx > -1) { _.assign(responseBodyInfo.responses[idx], { @@ -664,12 +673,13 @@ class SchemaRoutes { null, [routeInfo.operationId], ); - const component = this.schemaComponentsMap.createComponent( - this.schemaComponentsMap.createRef(["components", "schemas", typeName]), - { ...schema }, - ); - responseBodyInfo.error.schemas = [component]; - responseBodyInfo.error.type = this.typeNameFormatter.format(component.typeName); + const dataContract = this.dataContracts.add({ + schema: { ...schema }, + $ref: this.schemaComponentsMap.createRef(["components", "schemas", typeName]), + name: typeName, + }); + responseBodyInfo.error.schemas = [dataContract.schemas.parsed]; + responseBodyInfo.error.type = dataContract.name; } }; @@ -710,7 +720,7 @@ class SchemaRoutes { return this.config.hooks.onCreateRouteName(routeNameInfo, rawRouteInfo) || routeNameInfo; }; - parseRouteInfo = (rawRouteName, routeInfo, method, usageSchema, parsedSchemas) => { + parseRouteInfo = (rawRouteName, routeInfo, method, usageSchema) => { const { security: globalSecurity } = usageSchema; const { moduleNameIndex, moduleNameFirstTag, extractRequestParams } = this.config; const { @@ -754,7 +764,7 @@ class SchemaRoutes { })); const pathArgsNames = pathArgs.map((arg) => arg.name); - const responseBodyInfo = this.getResponseBodyInfo(routeInfo, routeParams, parsedSchemas); + const responseBodyInfo = this.getResponseBodyInfo(routeInfo, routeParams); const rawRouteInfo = { ...otherInfo, @@ -779,7 +789,7 @@ class SchemaRoutes { const routeName = this.getRouteName(rawRouteInfo); - const requestBodyInfo = this.getRequestBodyInfo(routeInfo, routeParams, parsedSchemas, routeName); + const requestBodyInfo = this.getRequestBodyInfo(routeInfo, routeParams, routeName); const requestParamsSchema = this.createRequestParamsSchema({ queryParams: routeParams.query, @@ -881,7 +891,7 @@ class SchemaRoutes { }; }; - attachSchema = ({ usageSchema, parsedSchemas }) => { + attachSchema = ({ usageSchema }) => { this.config.routeNameDuplicatesMap.clear(); const pathsEntries = _.entries(usageSchema.paths); @@ -890,7 +900,7 @@ class SchemaRoutes { const routeInfosMap = this.createRequestsMap(routeInfoByMethodsMap); _.forEach(routeInfosMap, (routeInfo, method) => { - const parsedRouteInfo = this.parseRouteInfo(rawRouteName, routeInfo, method, usageSchema, parsedSchemas); + const parsedRouteInfo = this.parseRouteInfo(rawRouteName, routeInfo, method, usageSchema); const processedRouteInfo = this.config.hooks.onCreateRoute(parsedRouteInfo); const route = processedRouteInfo || parsedRouteInfo; diff --git a/src/type-name-formatter.js b/src/type-name-formatter.js index a7f8a508..74e6709c 100644 --- a/src/type-name-formatter.js +++ b/src/type-name-formatter.js @@ -21,7 +21,7 @@ class TypeNameFormatter { /** * @param name - * @param options {{ type?: FormattingSchemaType }} + * @param options {{ type?: FormattingSchemaType, onlyFormat?: boolean }} * @return {string} */ format = (name, options) => { @@ -32,8 +32,16 @@ class TypeNameFormatter { */ const schemaType = options.type || "type-name"; - const typePrefix = schemaType === "enum-key" ? this.config.enumKeyPrefix : this.config.typePrefix; - const typeSuffix = schemaType === "enum-key" ? this.config.enumKeySuffix : this.config.typeSuffix; + const typePrefix = options.onlyFormat + ? "" + : schemaType === "enum-key" + ? this.config.enumKeyPrefix + : this.config.typePrefix; + const typeSuffix = options.onlyFormat + ? "" + : schemaType === "enum-key" + ? this.config.enumKeySuffix + : this.config.typeSuffix; const hashKey = `${typePrefix}_${name}_${typeSuffix}`; diff --git a/tests/spec/extract-enums/schema.ts b/tests/spec/extract-enums/schema.ts index 2903a91c..f4481c50 100644 --- a/tests/spec/extract-enums/schema.ts +++ b/tests/spec/extract-enums/schema.ts @@ -19,6 +19,34 @@ export enum TNPEnumRootTNS { EKPTest2EKS = "test2", } +export enum TNPTreeModeEnumTNS { + EKPInvalidKey100644EKS = "100644", + EKPInvalidKey100755EKS = "100755", + EKPInvalidKey040000EKS = "040000", + EKPInvalidKey160000EKS = "160000", + EKPInvalidKey120000EKS = "120000", +} + +export enum TNPTreeModeNumEnumTNS { + EKPInvalidKey100644EKS = 100644, + EKPInvalidKey100755EKS = 100755, + EKPInvalidKey40000EKS = 40000, + EKPInvalidKey160000EKS = 160000, + EKPInvalidKey120000EKS = 120000, +} + +export enum TNPTreeTypeEnumTNS { + EKPBlobEKS = "blob", + EKPTreeEKS = "tree", + EKPCommitEKS = "commit", +} + +export enum TNPTreeBerekeEnumTNS { + EKPBlaEKS = "Bla", + EKPBlablaEKS = "Blabla", + EKPBoilerEKS = "Boiler", +} + export interface TNPTreeTNS { tree?: { mode?: TNPTreeModeEnumTNS; @@ -87,6 +115,12 @@ export enum TNPSomeInterestEnumTNS { EKP_HSDFDS_EKS = "HSDFDS", } +/** @example "APPROVED" */ +export enum TNPSuperDuperStructDtoStateEnumTNS { + EKP_NEW_EKS = "NEW", + EKP_PENDING_EKS = "PENDING", +} + export interface TNPSuperDuperStructDTOTNS { /** @example "100" */ id: number; @@ -96,49 +130,15 @@ export interface TNPSuperDuperStructDTOTNS { export type TNPNullableEnumTNS = null; -/** **Required when the state is dismissed.** The reason for dismissing or closing the alert. Can be one of: `false positive`, `won't fix`, and `used in tests`. */ -export type TNPCodeScanningAlertDismissedReasonTNS = TNPCodeScanningAlertDismissedReasonEnumTNS | null; - -export enum TNPTreeModeEnumTNS { - EKPInvalidKey100644EKS = "100644", - EKPInvalidKey100755EKS = "100755", - EKPInvalidKey040000EKS = "040000", - EKPInvalidKey160000EKS = "160000", - EKPInvalidKey120000EKS = "120000", -} - -export enum TNPTreeModeNumEnumTNS { - EKPInvalidKey100644EKS = 100644, - EKPInvalidKey100755EKS = 100755, - EKPInvalidKey40000EKS = 40000, - EKPInvalidKey160000EKS = 160000, - EKPInvalidKey120000EKS = 120000, -} - -export enum TNPTreeTypeEnumTNS { - EKPBlobEKS = "blob", - EKPTreeEKS = "tree", - EKPCommitEKS = "commit", -} - -export enum TNPTreeBerekeEnumTNS { - EKPBlaEKS = "Bla", - EKPBlablaEKS = "Blabla", - EKPBoilerEKS = "Boiler", -} - -/** @example "APPROVED" */ -export enum TNPSuperDuperStructDtoStateEnumTNS { - EKP_NEW_EKS = "NEW", - EKP_PENDING_EKS = "PENDING", -} - export enum TNPCodeScanningAlertDismissedReasonEnumTNS { EKPFalsePositiveEKS = "false positive", EKPWontFixEKS = "won't fix", EKPUsedInTestsEKS = "used in tests", } +/** **Required when the state is dismissed.** The reason for dismissing or closing the alert. Can be one of: `false positive`, `won't fix`, and `used in tests`. */ +export type TNPCodeScanningAlertDismissedReasonTNS = TNPCodeScanningAlertDismissedReasonEnumTNS | null; + /** @example "APPROVED" */ export enum TNPNameSpaceAddSuperDuperEnumTNS { EKP_NEW_EKS = "NEW", pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy