diff --git a/client2/package.json b/client2/package.json index 71f4b70c..e15ab50a 100644 --- a/client2/package.json +++ b/client2/package.json @@ -76,7 +76,7 @@ "stylelint-webpack-plugin": "^2.1.1", "terser-webpack-plugin": "^5.0.0", "ts-loader": "^8.0.6", - "ts-morph": "^8.1.2", + "ts-morph": "^10.0.1", "ts-node": "^9.0.0", "typescript": "^4.0.3", "url-loader": "^4.1.1", diff --git a/client2/scripts/generator/index.ts b/client2/scripts/generator/index.ts index 19ac2256..b534173c 100644 --- a/client2/scripts/generator/index.ts +++ b/client2/scripts/generator/index.ts @@ -4,15 +4,16 @@ import { OPEN_API_PATH } from '../consts'; import EntitiesGenerator from './src/generateEntities'; import ApisGenerator from './src/generateApis'; +import { OpenApi } from './src/utils'; -const generateApi = (openApi: Record) => { +const generateApi = (openApi: OpenApi) => { const ent = new EntitiesGenerator(openApi); ent.save(); - const api = new ApisGenerator(openApi); - api.save(); + // const api = new ApisGenerator(openApi); + // api.save(); } -const openApiFile = fs.readFileSync(OPEN_API_PATH, 'utf8'); +const openApiFile = fs.readFileSync('./scripts/generator/v1.yaml', 'utf8'); generateApi(YAML.parse(openApiFile)); diff --git a/client2/scripts/generator/src/generateEntities.ts b/client2/scripts/generator/src/generateEntities.ts index 7ace9fa1..cd10693b 100644 --- a/client2/scripts/generator/src/generateEntities.ts +++ b/client2/scripts/generator/src/generateEntities.ts @@ -4,7 +4,7 @@ import * as path from 'path'; import * as morph from 'ts-morph'; import { ENT_DIR } from '../../consts'; -import { TYPES, toCamel, schemaParamParser, uncapitalize } from './utils'; +import { TYPES, toCamel, schemaParamParser, capitalize, OpenApi, Schema } from './utils'; const { Project, QuoteKind } = morph; @@ -17,7 +17,6 @@ if (!fs.existsSync(EntDir)) { class EntitiesGenerator { project = new Project({ tsConfigFilePath: './tsconfig.json', - addFilesFromTsConfig: false, manipulationSettings: { quoteKind: QuoteKind.Single, usePrefixAndSuffixTextForRename: false, @@ -25,15 +24,15 @@ class EntitiesGenerator { }, }); - openapi: Record; + openapi: OpenApi; - schemas: Record; + schemas: Record; schemaNames: string[]; entities: morph.SourceFile[] = []; - constructor(openapi: Record) { + constructor(openapi: OpenApi) { this.openapi = openapi; this.schemas = openapi.components.schemas; this.schemaNames = Object.keys(this.schemas); @@ -44,472 +43,395 @@ class EntitiesGenerator { this.schemaNames.forEach(this.generateEntity); }; - generateEntity = (sName: string) => { - const { properties, type, oneOf } = this.schemas[sName]; + generateEntity = (schemaName: string) => { + const { properties, type, oneOf, enum: en } = this.schemas[schemaName]; const notAClass = !properties && TYPES[type as keyof typeof TYPES]; if (oneOf) { - this.generateOneOf(sName); + this.generateOneOf(schemaName); return; } + if (en) { + this.generateEnum(schemaName); + return; + } + if (notAClass) { - this.generateEnum(sName); + this.generatePrimitive(schemaName) } else { - this.generateClass(sName); + this.generateClass(schemaName); } }; - generateEnum = (sName: string) => { - const entityFile = this.project.createSourceFile(`${EntDir}/${sName}.ts`); + generatePrimitive = (schemaName: string) => { + const entityFile = this.project.createSourceFile(`${EntDir}/${schemaName}.ts`); entityFile.addStatements([ '// This file was autogenerated. Please do not change.', - '// All changes will be overwrited on commit.', '', ]); + const { type: schemaType, description, pattern } = this.schemas[schemaName]; + if (description) { + entityFile.addStatements(['\n/*', `Description: ${description}`, '*/\n']); + } - const { enum: enumMembers } = this.schemas[sName]; + if (pattern) { + entityFile.addStatements(`const pattern = new RegExp('${pattern}')`); + } + + const type: string = TYPES[schemaType as keyof typeof TYPES]; + + const entityClass = entityFile.addClass({ + name: schemaName, + isDefaultExport: true, + extends: capitalize(type), + }); + + + + const ctor = entityClass.addConstructor({ + parameters: [{ + name: 'v', + type, + + }], + }); + ctor.setBodyText((w) => { + const { minLength, minimum, maxLength, maximum } = this.schemas[schemaName]; + + if (type === 'string') { + if (pattern) { + w.writeLine('if (!v.match(pattern)) {'); + w.writeLine(' throw new Error();'); + w.writeLine('}'); + } + if (typeof minLength === 'number') { + w.writeLine(`if (v.length < ${minLength}) {`); + w.writeLine(' throw new Error();'); + w.writeLine('}'); + } + if (typeof maxLength === 'number') { + w.writeLine(`if (v.length > ${maxLength}) {`); + w.writeLine(' throw new Error();'); + w.writeLine('}'); + } + } + if (type === 'number') { + if (typeof minimum === 'number') { + w.writeLine(`if (v.length < ${minimum}) {`); + w.writeLine(' throw new Error();'); + w.writeLine('}'); + } + if (typeof maximum === 'number') { + w.writeLine(`if (v.length > ${maximum}) {`); + w.writeLine(' throw new Error();'); + w.writeLine('}'); + } + } + w.writeLine('super(v);'); + }); + + this.entities.push(entityFile); + }; + + + generateEnum = (schemaName: string) => { + const entityFile = this.project.createSourceFile(`${EntDir}/${schemaName}.ts`); + entityFile.addStatements([ + '// This file was autogenerated. Please do not change.', + '', + ]); + const { enum: enumMembers, description, example } = this.schemas[schemaName]; + if (description) { + entityFile.addStatements(['\n/*', `Description: ${description}`, '*/\n']); + } entityFile.addEnum({ - name: sName, - members: enumMembers.map((e: string) => ({ name: e.toUpperCase(), value: e })), + name: schemaName, + members: enumMembers!.map((e: string) => ({ name: e.toUpperCase(), value: e })), isExported: true, }); this.entities.push(entityFile); }; - generateOneOf = (sName: string) => { - const entityFile = this.project.createSourceFile(`${EntDir}/${sName}.ts`); + generateOneOf = (schemaName: string) => { + const entityFile = this.project.createSourceFile(`${EntDir}/${schemaName}.ts`); entityFile.addStatements([ '// This file was autogenerated. Please do not change.', - '// All changes will be overwrited on commit.', '', ]); const importEntities: { type: string, isClass: boolean }[] = []; - const entities = this.schemas[sName].oneOf.map((elem: any) => { - const [ - pType, isArray, isClass, isImport, - ] = schemaParamParser(elem, this.openapi); - importEntities.push({ type: pType, isClass }); - return { type: pType, isArray }; + const entities = this.schemas[schemaName].oneOf.map((elem: any) => { + const { + type: type, isArray, isClass, isImport, + } = schemaParamParser(elem, this.openapi); + importEntities.push({ type: type, isClass }); + return { type: type, isArray }; }); entityFile.addTypeAlias({ - name: sName, + name: schemaName, isExported: true, type: entities.map((e: any) => e.isArray ? `I${e.type}[]` : `I${e.type}`).join(' | '), }) // add import importEntities.sort((a, b) => a.type > b.type ? 1 : -1).forEach((ie) => { - const { type: pType, isClass } = ie; + const { type: type, isClass } = ie; if (isClass) { entityFile.addImportDeclaration({ - moduleSpecifier: `./${pType}`, - namedImports: [`I${pType}`], + moduleSpecifier: `./${type}`, + namedImports: [`I${type}`], }); } else { entityFile.addImportDeclaration({ - moduleSpecifier: `./${pType}`, - namedImports: [pType], + moduleSpecifier: `./${type}`, + namedImports: [type], }); } }); this.entities.push(entityFile); } - generateClass = (sName: string) => { - const entityFile = this.project.createSourceFile(`${EntDir}/${sName}.ts`); + generateClass = (schemaName: string) => { + const entityFile = this.project.createSourceFile(`${EntDir}/${schemaName}.ts`); entityFile.addStatements([ '// This file was autogenerated. Please do not change.', - '// All changes will be overwrited on commit.', '', ]); + let { properties, required, allOf } = this.schemas[schemaName]; - const { properties: sProps, required, $ref, additionalProperties } = this.schemas[sName]; - if ($ref) { - const temp = $ref.split('/'); - const importSchemaName = `${temp[temp.length - 1]}`; - entityFile.addImportDeclaration({ - defaultImport: importSchemaName, - moduleSpecifier: `./${importSchemaName}`, - namedImports: [`I${importSchemaName}`], - }); + if (allOf) { + const refLink: string = allOf.find((obj: Record) => obj.$ref).$ref; + let ref: any = refLink.split('/') + ref = ref.pop(); + + const reasign = allOf.find((obj: Record) => !obj.$ref); + const newSchema: Schema = { ...this.schemas[ref], ...reasign }; - entityFile.addTypeAlias({ - name: `I${sName}`, - type: `I${importSchemaName}`, - isExported: true, - }) - - entityFile.addStatements(`export default ${importSchemaName};`); - this.entities.push(entityFile); - return; + properties = newSchema.properties; + required = newSchema.required; } + - const importEntities: { type: string, isClass: boolean }[] = []; const entityInterface = entityFile.addInterface({ - name: `I${sName}`, + name: `I${schemaName}`, isExported: true, }); - - const sortedSProps = Object.keys(sProps || {}).sort(); - const additionalPropsOnly = additionalProperties && sortedSProps.length === 0; + + const sortedProperties = Object.keys(properties || {}).sort(); + let importEntities: { type: string, isClass: boolean }[] = []; + + type SortedPropertiesTypesValues = ReturnType & { + computedType: string; + isRequired: boolean; + } + const sortedPropertiesTypes = sortedProperties.reduce((data, propertyName) => { + const isRequired = !!(required && required.includes(propertyName)); + const parsed = schemaParamParser(properties![propertyName], this.openapi); + data[propertyName] = { + ...parsed, + isRequired, + computedType: `${parsed.type}${parsed.isArray ? '[]' : ''}${isRequired ? '' : ' | undefined'}` + }; + return data; + }, {} as Record); // add server response interface to entityFile - sortedSProps.forEach((sPropName) => { - const [ - pType, isArray, isClass, isImport, isAdditional - ] = schemaParamParser(sProps[sPropName], this.openapi); + sortedProperties.forEach((propertyName) => { + const { + type, isArray, isClass, isImport + } = sortedPropertiesTypes[propertyName]; if (isImport) { - importEntities.push({ type: pType, isClass }); + importEntities.push({ type: type, isClass }); } - const propertyType = isAdditional - ? `{ [key: string]: ${isClass ? 'I' : ''}${pType}${isArray ? '[]' : ''} }` - : `${isClass ? 'I' : ''}${pType}${isArray ? '[]' : ''}`; entityInterface.addProperty({ - name: sPropName, - type: propertyType, + name: propertyName, + type: `${isClass ? 'I' : ''}${type}${isArray ? '[]' : ''}`, hasQuestionToken: !( - (required && required.includes(sPropName)) || sProps[sPropName].required + (required && required.includes(propertyName)) || properties![propertyName].required ), }); }); - if (additionalProperties) { - const [ - pType, isArray, isClass, isImport, isAdditional - ] = schemaParamParser(additionalProperties, this.openapi); - - if (isImport) { - importEntities.push({ type: pType, isClass }); - } - const type = isAdditional - ? `{ [key: string]: ${isClass ? 'I' : ''}${pType}${isArray ? '[]' : ''} }` - : `${isClass ? 'I' : ''}${pType}${isArray ? '[]' : ''}`; - entityInterface.addIndexSignature({ - keyName: 'key', - keyType: 'string', - returnType: additionalPropsOnly ? type : `${type} | undefined`, - }); - } // add import - const imports: { type: string, isClass: boolean }[] = []; const types: string[] = []; - importEntities.forEach((i) => { + importEntities = importEntities.filter((i) => { const { type } = i; if (!types.includes(type)) { - imports.push(i); types.push(type); + return true; } + return false; }); - imports.sort((a, b) => a.type > b.type ? 1 : -1).forEach((ie) => { - const { type: pType, isClass } = ie; + importEntities.sort((a, b) => a.type > b.type ? 1 : -1).forEach((ie) => { + const { type: type, isClass } = ie; if (isClass) { entityFile.addImportDeclaration({ - defaultImport: pType, - moduleSpecifier: `./${pType}`, - namedImports: [`I${pType}`], + defaultImport: type, + moduleSpecifier: `./${type}`, + namedImports: [`I${type}`], }); } else { entityFile.addImportDeclaration({ - moduleSpecifier: `./${pType}`, - namedImports: [pType], + moduleSpecifier: `./${type}`, + namedImports: [type], }); } }); const entityClass = entityFile.addClass({ - name: sName, + name: schemaName, isDefaultExport: true, }); // addProperties to class; - sortedSProps.forEach((sPropName) => { - const [pType, isArray, isClass, isImport, isAdditional] = schemaParamParser(sProps[sPropName], this.openapi); - - const isRequred = (required && required.includes(sPropName)) - || sProps[sPropName].required; - - const propertyType = isAdditional - ? `{ [key: string]: ${pType}${isArray ? '[]' : ''}${isRequred ? '' : ' | undefined'} }` - : `${pType}${isArray ? '[]' : ''}${isRequred ? '' : ' | undefined'}`; + sortedProperties.forEach((propertyName) => { + const { type, isArray, isClass, isEnum, isRequired, computedType } = sortedPropertiesTypes[propertyName]; entityClass.addProperty({ - name: `_${sPropName}`, + name: `_${propertyName}`, isReadonly: true, - type: propertyType, + type: computedType, }); + const getter = entityClass.addGetAccessor({ - name: toCamel(sPropName), - returnType: propertyType, - statements: [`return this._${sPropName};`], + name: toCamel(propertyName), + returnType: computedType, + statements: [`return this._${propertyName};`], }); - const { description, example, minItems, maxItems, maxLength, minLength, maximum, minimum } = sProps[sPropName]; + const { description, example, minItems, maxItems, maxLength, minLength, maximum, minimum } = properties![propertyName]; + if (description || example) { getter.addJsDoc(`${example ? `Description: ${description}` : ''}${example ? `\nExample: ${example}` : ''}`); } + if (minItems) { - entityClass.addGetAccessor({ + entityClass.addProperty({ isStatic: true, - name: `${toCamel(sPropName)}MinItems`, - statements: [`return ${minItems};`], + isReadonly: true, + name: `${capitalize(toCamel(propertyName))}MinItems`, + initializer: `${minItems}`, }); } if (maxItems) { - entityClass.addGetAccessor({ + entityClass.addProperty({ isStatic: true, - name: `${toCamel(sPropName)}MaxItems`, - statements: [`return ${maxItems};`], + isReadonly: true, + name: `${capitalize(toCamel(propertyName))}MaxItems`, + initializer: `${maxItems}`, }); } if (typeof minLength === 'number') { - entityClass.addGetAccessor({ + entityClass.addProperty({ isStatic: true, - name: `${toCamel(sPropName)}MinLength`, - statements: [`return ${minLength};`], + isReadonly: true, + name: `${capitalize(toCamel(propertyName))}MinLength`, + initializer: `${minLength}`, }); } if (maxLength) { - entityClass.addGetAccessor({ + entityClass.addProperty({ isStatic: true, - name: `${toCamel(sPropName)}MaxLength`, - statements: [`return ${maxLength};`], + isReadonly: true, + name: `${capitalize(toCamel(propertyName))}MaxLength`, + initializer: `${maxLength}`, }); } if (typeof minimum === 'number') { - entityClass.addGetAccessor({ + entityClass.addProperty({ isStatic: true, - name: `${toCamel(sPropName)}MinValue`, - statements: [`return ${minimum};`], + isReadonly: true, + name: `${capitalize(toCamel(propertyName))}MinValue`, + initializer: `${minimum}`, }); } if (maximum) { - entityClass.addGetAccessor({ + entityClass.addProperty({ isStatic: true, - name: `${toCamel(sPropName)}MaxValue`, - statements: [`return ${maximum};`], + isReadonly: true, + name: `${capitalize(toCamel(propertyName))}MaxValue`, + initializer: `${maximum}`, }); } - - if (!(isArray && isClass) && !isClass) { - const isEnum = !isClass && isImport; - const isRequired = (required && required.includes(sPropName)) || sProps[sPropName].required; - const { maxLength, minLength, maximum, minimum } = sProps[sPropName]; - const haveValidationFields = maxLength || typeof minLength === 'number' || maximum || typeof minimum === 'number'; - if (isRequired || haveValidationFields) { - const prop = toCamel(sPropName); - const validateField = entityClass.addMethod({ - isStatic: true, - name: `${prop}Validate`, - returnType: `boolean`, - parameters: [{ - name: prop, - type: `${pType}${isArray ? '[]' : ''}${isRequred ? '' : ' | undefined'}`, - }], - }) - - validateField.setBodyText((w) => { - w.write('return '); - const nonRequiredCall = isRequired ? prop : `!${prop} ? true : ${prop}`; - if (pType === 'string') { - if (isArray) { - w.write(`${nonRequiredCall}.reduce((result, p) => result && (typeof p === 'string' && !!p.trim()), true)`); - } else { - if (typeof minLength === 'number' && maxLength) { - w.write(`(${nonRequiredCall}.length >${minLength > 0 ? '=' : ''} ${minLength}) && (${nonRequiredCall}.length <= ${maxLength})`); - } - if (typeof minLength !== 'number' || !maxLength) { - w.write(`${isRequired ? `typeof ${prop} === 'string'` : `!${prop} ? true : typeof ${prop} === 'string'`} && !!${nonRequiredCall}.trim()`); - } - } - } else if (pType === 'number') { - if (isArray) { - w.write(`${nonRequiredCall}.reduce((result, p) => result && typeof p === 'number', true)`); - } else { - if (typeof minimum === 'number' && maximum) { - w.write(`${isRequired ? `${prop} >= ${minimum} && ${prop} <= ${maximum}` : `!${prop} ? true : ((${prop} >= ${minimum}) && (${prop} <= ${maximum}))`}`); - } - if (typeof minimum !== 'number' || !maximum) { - w.write(`${isRequired ? `typeof ${prop} === 'number'` : `!${prop} ? true : typeof ${prop} === 'number'`}`); - } - } - } else if (pType === 'boolean') { - w.write(`${isRequired ? `typeof ${prop} === 'boolean'` : `!${prop} ? true : typeof ${prop} === 'boolean'`}`); - } else if (isEnum) { - if (isArray){ - w.write(`${nonRequiredCall}.reduce((result, p) => result && Object.keys(${pType}).includes(${prop}), true)`); - } else { - w.write(`${isRequired ? `Object.keys(${pType}).includes(${prop})` : `!${prop} ? true : typeof ${prop} === 'boolean'`}`); - } - } - - w.write(';'); - }); - } - } }); - if (additionalProperties) { - const [ - pType, isArray, isClass, isImport, isAdditional - ] = schemaParamParser(additionalProperties, this.openapi); - const type = `Record`; - - entityClass.addProperty({ - name: additionalPropsOnly ? 'data' : `${uncapitalize(pType)}Data`, - isReadonly: true, - type: type, - }); - } + // add constructor; const ctor = entityClass.addConstructor({ parameters: [{ name: 'props', - type: `I${sName}`, + type: `I${schemaName}`, }], }); ctor.setBodyText((w) => { - if (additionalProperties) { - const [ - pType, isArray, isClass, isImport, isAdditional - ] = schemaParamParser(additionalProperties, this.openapi); - w.writeLine(`this.${additionalPropsOnly ? 'data' : `${uncapitalize(pType)}Data`} = Object.entries(props).reduce>((prev, [key, value]) => {`); - if (isClass) { - w.writeLine(` prev[key] = new ${pType}(value!);`); + sortedProperties.forEach((propertyName) => { + const { type, isArray, isClass, isRequired } = sortedPropertiesTypes[propertyName]; + + const indent = !isRequired ? ' ' : ''; + if (!isRequired) { + if ((type === 'boolean' || type === 'number' || type ==='string') && !isClass && !isArray) { + w.writeLine(`if (typeof props.${propertyName} === '${type}') {`); + } else { + w.writeLine(`if (props.${propertyName}) {`); + } + } + if (isArray && isClass) { + w.writeLine(`${indent}this._${propertyName} = props.${propertyName}.map((p) => new ${type}(p));`); + } else if (isClass) { + w.writeLine(`${indent}this._${propertyName} = new ${type}(props.${propertyName});`); } else { - w.writeLine(' prev[key] = value!;') - } - w.writeLine(' return prev;'); - w.writeLine('}, {})'); - return; - } - sortedSProps.forEach((sPropName) => { - const [ - pType, isArray, isClass, , isAdditional - ] = schemaParamParser(sProps[sPropName], this.openapi); - const req = (required && required.includes(sPropName)) - || sProps[sPropName].required; - if (!req) { - if ((pType === 'boolean' || pType === 'number' || pType ==='string') && !isClass && !isArray) { - w.writeLine(`if (typeof props.${sPropName} === '${pType}') {`); + if (type === 'string' && !isArray) { + w.writeLine(`${indent}this._${propertyName} = props.${propertyName}.trim();`); } else { - w.writeLine(`if (props.${sPropName}) {`); + w.writeLine(`${indent}this._${propertyName} = props.${propertyName};`); } } - if (isAdditional) { - if (isArray && isClass) { - w.writeLine(`${!req ? ' ' : ''}this._${sPropName} = props.${sPropName}.map((p) => Object.keys(p).reduce((prev, key) => { - return { ...prev, [key]: new ${pType}(p[key])}; - },{}))`); - } else if (isClass) { - w.writeLine(`${!req ? ' ' : ''}this._${sPropName} = Object.keys(props.${sPropName}).reduce((prev, key) => { - return { ...prev, [key]: new ${pType}(props.${sPropName}[key])}; - },{})`); - } else { - if (pType === 'string' && !isArray) { - w.writeLine(`${!req ? ' ' : ''}this._${sPropName} = Object.keys(props.${sPropName}).reduce((prev, key) => { - return { ...prev, [key]: props.${sPropName}[key].trim()}; - },{})`); - } else { - w.writeLine(`${!req ? ' ' : ''}this._${sPropName} = Object.keys(props.${sPropName}).reduce((prev, key) => { - return { ...prev, [key]: props.${sPropName}[key]}; - },{})`); - } - } - } else { - if (isArray && isClass) { - w.writeLine(`${!req ? ' ' : ''}this._${sPropName} = props.${sPropName}.map((p) => new ${pType}(p));`); - } else if (isClass) { - w.writeLine(`${!req ? ' ' : ''}this._${sPropName} = new ${pType}(props.${sPropName});`); - } else { - if (pType === 'string' && !isArray) { - w.writeLine(`${!req ? ' ' : ''}this._${sPropName} = props.${sPropName}.trim();`); - } else { - w.writeLine(`${!req ? ' ' : ''}this._${sPropName} = props.${sPropName};`); - } - } - } - if (!req) { + if (!isRequired) { w.writeLine('}'); } }); - }); // add serialize method; const serialize = entityClass.addMethod({ isStatic: false, name: 'serialize', - returnType: `I${sName}`, + returnType: `I${schemaName}`, }); serialize.setBodyText((w) => { - if (additionalProperties) { - const [ - pType, isArray, isClass, isImport, isAdditional - ] = schemaParamParser(additionalProperties, this.openapi); - w.writeLine(`return Object.entries(this.${additionalPropsOnly ? 'data' : `${uncapitalize(pType)}Data`}).reduce>((prev, [key, value]) => {`); - if (isClass) { - w.writeLine(` prev[key] = value.serialize();`); - } else { - w.writeLine(' prev[key] = value;') - } - w.writeLine(' return prev;'); - w.writeLine('}, {})'); - return; - } - w.writeLine(`const data: I${sName} = {`); + w.writeLine(`const data: I${schemaName} = {`); + const unReqFields: string[] = []; - sortedSProps.forEach((sPropName) => { - const req = (required && required.includes(sPropName)) - || sProps[sPropName].required; - const [, isArray, isClass, , isAdditional] = schemaParamParser(sProps[sPropName], this.openapi); - if (!req) { - unReqFields.push(sPropName); + + sortedProperties.forEach((propertyName) => { + const {isArray, isClass, isRequired } = sortedPropertiesTypes[propertyName]; + if (!isRequired) { + unReqFields.push(propertyName); return; } - if (isAdditional) { - if (isArray && isClass) { - w.writeLine(` ${sPropName}: this._${sPropName}.map((p) => Object.keys(p).reduce((prev, key) => ({ ...prev, [key]: p[key].serialize() }))),`); - } else if (isClass) { - w.writeLine(` ${sPropName}: Object.keys(this._${sPropName}).reduce>((prev, key) => ({ ...prev, [key]: this._${sPropName}[key].serialize() }), {}),`); - } else { - w.writeLine(` ${sPropName}: Object.keys(this._${sPropName}).reduce((prev, key) => ({ ...prev, [key]: this._${sPropName}[key] })),`); - } + if (isArray && isClass) { + w.writeLine(` ${propertyName}: this._${propertyName}.map((p) => p.serialize()),`); + } else if (isClass) { + w.writeLine(` ${propertyName}: this._${propertyName}.serialize(),`); } else { - if (isArray && isClass) { - w.writeLine(` ${sPropName}: this._${sPropName}.map((p) => p.serialize()),`); - } else if (isClass) { - w.writeLine(` ${sPropName}: this._${sPropName}.serialize(),`); - } else { - w.writeLine(` ${sPropName}: this._${sPropName},`); - } + w.writeLine(` ${propertyName}: this._${propertyName},`); + } - }); w.writeLine('};'); - unReqFields.forEach((sPropName) => { - const [, isArray, isClass, , isAdditional] = schemaParamParser(sProps[sPropName], this.openapi); - w.writeLine(`if (typeof this._${sPropName} !== 'undefined') {`); - if (isAdditional) { - if (isArray && isClass) { - w.writeLine(` data.${sPropName} = this._${sPropName}.map((p) => Object.keys(p).reduce((prev, key) => ({ ...prev, [key]: p[key].serialize() }), {}));`); - } else if (isClass) { - w.writeLine(` data.${sPropName} = Object.keys(this._${sPropName}).reduce((prev, key) => ({ ...prev, [key]: this._${sPropName}[key].serialize() }), {});`); - } else { - w.writeLine(` data.${sPropName} = Object.keys(this._${sPropName}).reduce((prev, key) => ({ ...prev, [key]: this._${sPropName}[key] }), {});`); - } + + unReqFields.forEach((propertyName) => { + const { isArray, isClass } = sortedPropertiesTypes[propertyName]; + w.writeLine(`if (typeof this._${propertyName} !== 'undefined') {`); + if (isArray && isClass) { + w.writeLine(` data.${propertyName} = this._${propertyName}.map((p) => p.serialize());`); + } else if (isClass) { + w.writeLine(` data.${propertyName} = this._${propertyName}.serialize();`); } else { - if (isArray && isClass) { - w.writeLine(` data.${sPropName} = this._${sPropName}.map((p) => p.serialize());`); - } else if (isClass) { - w.writeLine(` data.${sPropName} = this._${sPropName}.serialize();`); - } else { - w.writeLine(` data.${sPropName} = this._${sPropName};`); - - } + w.writeLine(` data.${propertyName} = this._${propertyName};`); + } - w.writeLine(`}`); }); w.writeLine('return data;'); @@ -522,74 +444,55 @@ class EntitiesGenerator { returnType: `string[]`, }) validate.setBodyText((w) => { - if (additionalPropsOnly) { - w.writeLine('return []') - return; - } - w.writeLine('const validate = {'); - Object.keys(sProps || {}).forEach((sPropName) => { - const [pType, isArray, isClass, , isAdditional] = schemaParamParser(sProps[sPropName], this.openapi); + w.writeLine('const validateRequired = {'); + Object.keys(properties || {}).forEach((propertyName) => { + const { isArray, isClass, type, isRequired } = sortedPropertiesTypes[propertyName]; + const { maxLength, minLength, maximum, minimum } = properties![propertyName]; - const { maxLength, minLength, maximum, minimum } = sProps[sPropName]; - - const isRequired = (required && required.includes(sPropName)) || sProps[sPropName].required; - const nonRequiredCall = isRequired ? `this._${sPropName}` : `!this._${sPropName} ? true : this._${sPropName}`; + const nonRequiredCall = isRequired ? `this._${propertyName}` : `!this._${propertyName} ? true : this._${propertyName}`; if (isArray && isClass) { - w.writeLine(` ${sPropName}: ${nonRequiredCall}.reduce((result, p) => result && p.validate().length === 0, true),`); - } else if (isClass && !isAdditional) { - w.writeLine(` ${sPropName}: ${nonRequiredCall}.validate().length === 0,`); + w.writeLine(` ${propertyName}: ${nonRequiredCall}.reduce((result, p) => result && p.validate().length === 0, true),`); + } else if (isClass) { + w.writeLine(` ${propertyName}: ${nonRequiredCall}.validate().length === 0,`); } else { - if (pType === 'string') { + if (type === 'string') { if (isArray) { - w.writeLine(` ${sPropName}: ${nonRequiredCall}.reduce((result, p) => result && typeof p === 'string', true),`); + w.writeLine(` ${propertyName}: ${nonRequiredCall}.reduce((result, p) => result && typeof p === 'string', true),`); } else { if (typeof minLength === 'number' && maxLength) { - w.writeLine(` ${sPropName}: (${nonRequiredCall}.length >${minLength > 0 ? '=' : ''} ${minLength}) && (${nonRequiredCall}.length <= ${maxLength}),`); + w.writeLine(` ${propertyName}: (${nonRequiredCall}.length >${minLength > 0 ? '=' : ''} ${minLength}) && (${nonRequiredCall}.length <= ${maxLength}),`); } if (typeof minLength !== 'number' || !maxLength) { - w.writeLine(` ${sPropName}: ${isRequired ? `typeof this._${sPropName} === 'string'` : `!this._${sPropName} ? true : typeof this._${sPropName} === 'string'`} && !this._${sPropName} ? true : this._${sPropName},`); + w.writeLine(` ${propertyName}: ${isRequired ? `typeof this._${propertyName} === 'string' && !!this._${propertyName}.trim()` : `!this._${propertyName} ? true : typeof this._${propertyName} === 'string'`},`); } } - } else if (pType === 'number') { + } else if (type === 'number') { if (isArray) { - w.writeLine(` ${sPropName}: ${nonRequiredCall}.reduce((result, p) => result && typeof p === 'number', true),`); + w.writeLine(` ${propertyName}: ${nonRequiredCall}.reduce((result, p) => result && typeof p === 'number', true),`); } else { if (typeof minimum === 'number' && maximum) { - w.writeLine(` ${sPropName}: ${isRequired ? `this._${sPropName} >= ${minimum} && this._${sPropName} <= ${maximum}` : `!this._${sPropName} ? true : ((this._${sPropName} >= ${minimum}) && (this._${sPropName} <= ${maximum}))`},`); + w.writeLine(` ${propertyName}: ${isRequired ? `this._${propertyName} >= ${minimum} && this._${propertyName} <= ${maximum}` : `!this._${propertyName} ? true : ((this._${propertyName} >= ${minimum}) && (this._${propertyName} <= ${maximum}))`},`); } if (typeof minimum !== 'number' || !maximum) { - w.writeLine(` ${sPropName}: ${isRequired ? `typeof this._${sPropName} === 'number'` : `!this._${sPropName} ? true : typeof this._${sPropName} === 'number'`},`); + w.writeLine(` ${propertyName}: ${isRequired ? `typeof this._${propertyName} === 'number'` : `!this._${propertyName} ? true : typeof this._${propertyName} === 'number'`},`); } } - } else if (pType === 'boolean') { - w.writeLine(` ${sPropName}: ${isRequired ? `typeof this._${sPropName} === 'boolean'` : `!this._${sPropName} ? true : typeof this._${sPropName} === 'boolean'`},`); + } else if (type === 'boolean') { + w.writeLine(` ${propertyName}: ${isRequired ? `typeof this._${propertyName} === 'boolean'` : `!this._${propertyName} ? true : typeof this._${propertyName} === 'boolean'`},`); } } }); w.writeLine('};'); - w.writeLine('const isError: string[] = [];') - w.writeLine('Object.keys(validate).forEach((key) => {'); - w.writeLine(' if (!(validate as any)[key]) {'); - w.writeLine(' isError.push(key);'); + w.writeLine('const errorInFields: string[] = [];') + w.writeLine('Object.keys(validateRequired).forEach((key) => {'); + w.writeLine(' if (!(validateRequired as any)[key]) {'); + w.writeLine(' errorInFields.push(key);'); w.writeLine(' }'); w.writeLine('});'); - w.writeLine('return isError;'); - + w.writeLine('return errorInFields;'); }); - // add update method; - const update = entityClass.addMethod({ - isStatic: false, - name: 'update', - returnType: `${sName}`, - }); - update.addParameter({ - name: 'props', - type: additionalPropsOnly ? `I${sName}` : `Partial`, - }); - update.setBodyText((w) => { w.writeLine(`return new ${sName}({ ...this.serialize(), ...props });`); }); - this.entities.push(entityFile); }; diff --git a/client2/scripts/generator/src/utils.ts b/client2/scripts/generator/src/utils.ts index 5183b6c5..e84b6b68 100644 --- a/client2/scripts/generator/src/utils.ts +++ b/client2/scripts/generator/src/utils.ts @@ -19,20 +19,106 @@ const TYPES = { boolean: 'boolean', }; +export enum SchemaType { + STRING = 'string', + OBJECT = 'object', + ARRAY = 'array', + BOOLEAN = 'boolean', + NUMBER = 'number', + INTEGER = 'integer', +} + +export interface Schema { + allOf?: any[]; + example?: string; + properties?: Record; + required?: string[]; + description?: string; + enum?: string[]; + type: SchemaType; + pattern?: string; + oneOf?: any + items?: Schema; + additionalProperties?: Schema; + $ref?: string; + minItems?: number; + maxItems?: number; + maxLength?: number; + minLength?: number; + maximum?: number; + minimum?: number; +} + +export interface Parametr { + description?: string; + example?: string; + in?: 'query' | 'body' | 'headers'; + name?: string; + schema?: Schema; + required?: boolean; +} + +export interface RequestBody { + content: { + 'application/json'?: { + schema: Schema; + example?: string; + }; + 'text/palin'?: { + example?: string; + } + } + required?: boolean; +} +export interface Response { + content: { + 'application/json'?: { + schema: Schema; + example?: string; + }; + 'text/palin'?: { + example?: string; + } + } + description?: string; +} + +export interface Schemas { + parameters: Record; + requestBodies: Record; + responses: Record; + schemas: Record; +} + +export interface OpenApi { + components: Schemas; + paths: any; +} + /** * @param schemaProp: valueof shema.properties[key] * @param openApi: openapi object * @returns [propType - basicType or import one, isArray, isClass, isImport] */ -const schemaParamParser = (schemaProp: any, openApi: any): [string, boolean, boolean, boolean, boolean] => { +interface SchemaParamParserReturn { + type: string; + isArray: boolean; + isClass: boolean; + isImport: boolean; + isAdditional: boolean; + isEnum: boolean; +} + +const schemaParamParser = (schemaProp: Schema, openApi: OpenApi): SchemaParamParserReturn => { let type = ''; let isImport = false; let isClass = false; let isArray = false; let isAdditional = false; + let isEnum = false; if (schemaProp.$ref || schemaProp.additionalProperties?.$ref) { - const temp = (schemaProp.$ref || schemaProp.additionalProperties?.$ref).split('/'); + const temp = (schemaProp.$ref || schemaProp.additionalProperties?.$ref)!.split('/'); if (schemaProp.additionalProperties) { isAdditional = true; @@ -40,44 +126,41 @@ const schemaParamParser = (schemaProp: any, openApi: any): [string, boolean, boo type = `${temp[temp.length - 1]}`; - const cl = openApi ? openApi.components.schemas[type] : {}; + const cl = openApi.components.schemas[type]; if (cl.$ref) { const link = schemaParamParser(cl, openApi); - link.shift(); - return [type, ...link] as any; + return {...link, type}; } if (cl.type === 'string' && cl.enum) { isImport = true; + isEnum = true; } if (cl.type === 'object' && !cl.oneOf) { isClass = true; isImport = true; } else if (cl.type === 'array') { - const temp: any = schemaParamParser(cl.items, openApi); - type = `${temp[0]}`; + const temp = schemaParamParser(cl.items!, openApi); + type = temp.type; isArray = true; - isClass = isClass || temp[2]; - isImport = isImport || temp[3]; + isClass = isClass || temp.isClass; + isImport = isImport || temp.isImport; + isEnum = isEnum || temp.isEnum; } } else if (schemaProp.type === 'array') { - const temp: any = schemaParamParser(schemaProp.items, openApi); - type = `${temp[0]}`; + const temp = schemaParamParser(schemaProp.items!, openApi); + type = temp.type isArray = true; - isClass = isClass || temp[2]; - isImport = isImport || temp[3]; + isClass = isClass || temp.isClass; + isImport = isImport || temp.isImport; + isEnum = isEnum || temp.isEnum; } else { type = (TYPES as Record)[schemaProp.type]; } - if (!type) { - // TODO: Fix bug with Error fields. - type = 'any'; - // throw new Error('Failed to find entity type'); - } - return [type, isArray, isClass, isImport, isAdditional]; + return { type, isArray, isClass, isImport, isAdditional, isEnum }; }; export { TYPES, toCamel, capitalize, uncapitalize, schemaParamParser }; diff --git a/client2/yarn.lock b/client2/yarn.lock index d171bb54..85ddc844 100644 --- a/client2/yarn.lock +++ b/client2/yarn.lock @@ -370,17 +370,16 @@ remark "^13.0.0" unist-util-find-all-after "^3.0.2" -"@ts-morph/common@~0.6.0": - version "0.6.0" - resolved "https://registry.yarnpkg.com/@ts-morph/common/-/common-0.6.0.tgz#cbd4ee57c5ef971511b9c5778e0bb8eb27de4783" - integrity sha512-pI35nZz5bs3tL3btSVX2cWkAE8rc80F+Fn4TwSC6bQvn7fgn9IyLXVcAfpG6X6NBY5wN9TkSWXn/QYUkBvR/Fw== +"@ts-morph/common@~0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@ts-morph/common/-/common-0.8.0.tgz#ae7b292df8258040465c50b378108ec8f09a9516" + integrity sha512-YbjWiMXLMKxWxcMqP47nwZVWVBwoF5B65dtRz0lya2LetjldAPxTxRbRo1n4Iszr2tSvzXeaa+f1AbULmfc5uA== dependencies: "@dsherret/to-absolute-glob" "^2.0.2" - fast-glob "^3.2.4" - fs-extra "^9.0.1" + fast-glob "^3.2.5" is-negated-glob "^1.0.0" - multimatch "^4.0.0" - typescript "~4.0.2" + mkdirp "^1.0.4" + multimatch "^5.0.0" "@types/anymatch@*": version "1.3.1" @@ -1172,11 +1171,6 @@ async@^2.6.2: dependencies: lodash "^4.17.14" -at-least-node@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" - integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== - atob@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" @@ -1593,7 +1587,7 @@ coa@^2.0.2: chalk "^2.4.1" q "^1.1.2" -code-block-writer@^10.1.0: +code-block-writer@^10.1.1: version "10.1.1" resolved "https://registry.yarnpkg.com/code-block-writer/-/code-block-writer-10.1.1.tgz#ad5684ed4bfb2b0783c8b131281ae84ee640a42f" integrity sha512-67ueh2IRGst/51p0n6FvPrnRjAGHY5F8xdjkgrYE7DDzpJe6qA07RYQ9VcoUeo5ATOjSOiWpSL3SWBRRbempMw== @@ -2910,9 +2904,9 @@ fastest-levenshtein@^1.0.12: integrity sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow== fastq@^1.6.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.10.0.tgz#74dbefccade964932cdf500473ef302719c652bb" - integrity sha512-NL2Qc5L3iQEsyYzweq7qfgy5OtXCmGzGvhElGEd/SoFWEMOEczNh5s5ocaF01HDetxz+p8ecjNPA6cZxxIHmzA== + version "1.11.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.11.0.tgz#bb9fb955a07130a918eb63c1f5161cc32a5d0858" + integrity sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g== dependencies: reusify "^1.0.4" @@ -3084,16 +3078,6 @@ fs-extra@^8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^9.0.1: - version "9.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" - integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== - dependencies: - at-least-node "^1.0.0" - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - fs-minipass@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" @@ -3267,11 +3251,16 @@ gonzales-pe@^4.3.0: dependencies: minimist "^1.2.5" -graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4: +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.2.4: version "4.2.4" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== +graceful-fs@^4.1.6, graceful-fs@^4.2.0: + version "4.2.6" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" + integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== + handle-thing@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" @@ -4145,15 +4134,6 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" -jsonfile@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" - integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== - dependencies: - universalify "^2.0.0" - optionalDependencies: - graceful-fs "^4.1.6" - "jsx-ast-utils@^2.4.1 || ^3.0.0": version "3.2.0" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.2.0.tgz#41108d2cec408c3453c1bbe8a4aae9e1e2bd8f82" @@ -4784,10 +4764,10 @@ multicast-dns@^6.0.1: dns-packet "^1.3.1" thunky "^1.0.2" -multimatch@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-4.0.0.tgz#8c3c0f6e3e8449ada0af3dd29efb491a375191b3" - integrity sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ== +multimatch@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-5.0.0.tgz#932b800963cea7a31a033328fa1e0c3a1874dbe6" + integrity sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA== dependencies: "@types/minimatch" "^3.0.3" array-differ "^3.0.0" @@ -6292,6 +6272,11 @@ querystringify@^2.1.1: resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== +queue-microtask@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.2.tgz#abf64491e6ecf0f38a6502403d4cda04f372dfd3" + integrity sha512-dB15eXv3p2jDlbOiNLyMabYg1/sXvppd8DP2J3EOCQ0AkuSXCW2tP7mnVouVLJKgUMY6yP0kcQDVpLCN13h4Xg== + quick-lru@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" @@ -7086,9 +7071,11 @@ rimraf@^3.0.2: glob "^7.1.3" run-parallel@^1.1.9: - version "1.1.10" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.10.tgz#60a51b2ae836636c81377df16cb107351bcd13ef" - integrity sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw== + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" @@ -7942,14 +7929,14 @@ ts-loader@^8.0.6: micromatch "^4.0.0" semver "^7.3.4" -ts-morph@^8.1.2: - version "8.2.0" - resolved "https://registry.yarnpkg.com/ts-morph/-/ts-morph-8.2.0.tgz#41d83cd501cbd897eb029ac489d6d5b927555c57" - integrity sha512-NHHWu+7I2/AOZiTni5w3f+xCfIxrkzPCcQbTGa81Yk3pr23a4h9xLLEE6tIGuYIubWjkjr9QVC3ITqgmA5touQ== +ts-morph@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/ts-morph/-/ts-morph-10.0.1.tgz#5a620cc4ef85e3e6d161989e690f44d0a0f723b0" + integrity sha512-T1zufImtp5goTLTFhzi7XuKR1y/f+Jwz1gSULzB045LFjXuoqVlR87sfkpyWow8u2JwgusCJrhOnwmHCFNutTQ== dependencies: "@dsherret/to-absolute-glob" "^2.0.2" - "@ts-morph/common" "~0.6.0" - code-block-writer "^10.1.0" + "@ts-morph/common" "~0.8.0" + code-block-writer "^10.1.1" ts-node@^9.0.0: version "9.1.1" @@ -8032,11 +8019,6 @@ typescript@^4.0.3: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.3.tgz#519d582bd94cba0cf8934c7d8e8467e473f53bb7" integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg== -typescript@~4.0.2: - version "4.0.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.5.tgz#ae9dddfd1069f1cb5beb3ef3b2170dd7c1332389" - integrity sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ== - unc-path-regex@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" @@ -8112,11 +8094,6 @@ universalify@^0.1.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== -universalify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" - integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== - unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"