diff --git a/.eslintrc.json b/.eslintrc.json index 2a9d3ca7..bd4d9ab0 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -14,6 +14,7 @@ "@typescript-eslint/no-explicit-any": 0, "@typescript-eslint/no-inferrable-types": 0, "@typescript-eslint/no-non-null-assertion": 0, + "@typescript-eslint/ban-ts-ignore": 0, "@typescript-eslint/explicit-function-return-type": 0, "prettier/prettier": [ "error" diff --git a/src/client/interfaces/OperationParameter.d.ts b/src/client/interfaces/OperationParameter.d.ts index e2e5db91..aa36df6c 100644 --- a/src/client/interfaces/OperationParameter.d.ts +++ b/src/client/interfaces/OperationParameter.d.ts @@ -1,13 +1,7 @@ -export interface OperationParameter { +import { Model } from './Model'; + +export interface OperationParameter extends Model { prop: string; in: 'path' | 'query' | 'header' | 'formData' | 'body'; - name: string; - type: string; - base: string; - template: string | null; - description: string | null; default: any; - required: boolean; - nullable: boolean; - imports: string[]; } diff --git a/src/openApi/v2/interfaces/OpenApiParameter.d.ts b/src/openApi/v2/interfaces/OpenApiParameter.d.ts index 1f97a683..cffa15c5 100644 --- a/src/openApi/v2/interfaces/OpenApiParameter.d.ts +++ b/src/openApi/v2/interfaces/OpenApiParameter.d.ts @@ -1,5 +1,6 @@ import { OpenApiItems } from './OpenApiItems'; import { OpenApiSchema } from './OpenApiSchema'; +import { OpenApiReference } from './OpenApiReference'; /** * https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#parameterObject diff --git a/src/openApi/v2/parser/getModel.ts b/src/openApi/v2/parser/getModel.ts index 4a156ecd..bcc8ac95 100644 --- a/src/openApi/v2/parser/getModel.ts +++ b/src/openApi/v2/parser/getModel.ts @@ -49,7 +49,7 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, name: stri } } - if (definition.type === 'int' && definition.description) { + if ((definition.type === 'int' || definition.type === 'integer') && definition.description) { const enumerators = getEnumFromDescription(definition.description); if (enumerators.length) { result.export = 'enum'; @@ -119,6 +119,9 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, name: stri properties.forEach(property => { result.properties.push(property); result.imports.push(...property.imports); + if (property.export === 'enum') { + result.enums.push(property); + } }); } }); @@ -129,6 +132,9 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, name: stri properties.forEach(property => { result.properties.push(property); result.imports.push(...property.imports); + if (property.export === 'enum') { + result.enums.push(property); + } }); } diff --git a/src/openApi/v2/parser/getOperation.ts b/src/openApi/v2/parser/getOperation.ts index 21752df5..544ea9bf 100644 --- a/src/openApi/v2/parser/getOperation.ts +++ b/src/openApi/v2/parser/getOperation.ts @@ -3,12 +3,8 @@ import { getServiceClassName } from './getServiceClassName'; import { OpenApiOperation } from '../interfaces/OpenApiOperation'; import { getOperationName } from './getOperationName'; import { getOperationPath } from './getOperationPath'; -import { getOperationParameters } from './getOperationParameters'; import { OpenApi } from '../interfaces/OpenApi'; import { getComment } from './getComment'; -import { getOperationResponses } from './getOperationResponses'; -import { getOperationResponse } from './getOperationResponse'; -import { getOperationErrors } from './getOperationErrors'; import { Operation } from '../../../client/interfaces/Operation'; import { PrimaryType } from './constants'; @@ -41,24 +37,24 @@ export function getOperation(openApi: OpenApi, url: string, method: string, op: // Parse the operation parameters (path, query, body, etc). if (op.parameters) { - const parameters = getOperationParameters(openApi, op.parameters); - result.imports.push(...parameters.imports); - result.parameters.push(...parameters.parameters); - result.parametersPath.push(...parameters.parametersPath); - result.parametersQuery.push(...parameters.parametersQuery); - result.parametersForm.push(...parameters.parametersForm); - result.parametersHeader.push(...parameters.parametersHeader); - result.parametersBody = parameters.parametersBody; + // const parameters = getOperationParameters(openApi, op.parameters); + // result.imports.push(...parameters.imports); + // result.parameters.push(...parameters.parameters); + // result.parametersPath.push(...parameters.parametersPath); + // result.parametersQuery.push(...parameters.parametersQuery); + // result.parametersForm.push(...parameters.parametersForm); + // result.parametersHeader.push(...parameters.parametersHeader); + // result.parametersBody = parameters.parametersBody; } // Parse the operation responses. if (op.responses) { - const responses = getOperationResponses(openApi, op.responses); - const response = getOperationResponse(responses); - const errors = getOperationErrors(responses); - result.imports.push(...response.imports); - result.errors = errors; - result.result = response.type; + // const responses = getOperationResponses(openApi, op.responses); + // const response = getOperationResponse(responses); + // const errors = getOperationErrors(responses); + // result.imports.push(...response.imports); + // result.errors = errors; + // result.result = response.type; } return result; diff --git a/src/openApi/v2/parser/getOperationParameter.ts b/src/openApi/v2/parser/getOperationParameter.ts index c8b6d14e..dad260ac 100644 --- a/src/openApi/v2/parser/getOperationParameter.ts +++ b/src/openApi/v2/parser/getOperationParameter.ts @@ -1,76 +1,30 @@ import { OpenApiParameter } from '../interfaces/OpenApiParameter'; -import { getType } from './getType'; import { OpenApi } from '../interfaces/OpenApi'; import { getComment } from './getComment'; import { getOperationParameterName } from './getOperationParameterName'; import { OperationParameter } from '../../../client/interfaces/OperationParameter'; +import { PrimaryType } from './constants'; export function getOperationParameter(openApi: OpenApi, parameter: OpenApiParameter): OperationParameter { const result: OperationParameter = { in: parameter.in, prop: parameter.name, name: getOperationParameterName(parameter.name), - type: 'any', - base: 'any', + export: 'interface', + type: PrimaryType.OBJECT, + base: PrimaryType.OBJECT, template: null, + link: null, description: getComment(parameter.description), - default: parameter.default, - required: parameter.required || false, + readOnly: false, + required: false, nullable: false, imports: [], + extends: [], + enum: [], + enums: [], + properties: [], + default: null, }; - - // If the parameter has a type than it can be a basic or generic type. - if (parameter.type) { - const parameterType = getType(parameter.type); - result.type = parameterType.type; - result.base = parameterType.base; - result.template = parameterType.template; - result.imports.push(...parameterType.imports); - - // If the parameter is an Array type, we check for the child type, - // so we can create a typed array, otherwise this will be a "any[]". - if (parameter.type === 'array' && parameter.items) { - // TODO: Check getSchema - // const arrayType: ArrayType = getArrayType(parameter.items); - // result.type = `${arrayType.type}[]`; - // result.base = arrayType.base; - // result.template = arrayType.template; - // result.imports.push(...arrayType.imports); - } - } - - // If this parameter has a schema, then we need to check two things: - // if this is a reference then the parameter is just the 'name' of - // this reference type. Otherwise it might be a complex schema and - // then we need to parse the schema! - if (parameter.schema) { - // TODO: Check getSchema - // const parameterSchema: SchemaReference = getSchemaReference(openApi, parameter.schema); - // result.type = parameterSchema.type; - // result.base = parameterSchema.base; - // result.template = parameterSchema.template; - // result.imports.push(...parameterSchema.imports); - } - - // Check if this could be a special enum where values are documented in the description. - if (parameter.enum && parameter.description && parameter.type === 'int') { - // TODO: Check getSchema - // const enumType: string | null = getEnumTypeFromDescription(parameter.description); - // if (enumType) { - // result.type = enumType; - // result.base = 'number'; - // result.imports = []; - // } - } - - // If the param is a enum then return the values as an inline type. - if (parameter.enum) { - // TODO: Check getSchema - // result.type = getEnumType(parameter.enum); - // result.base = 'string'; - // result.imports = []; - } - return result; } diff --git a/src/openApi/v2/parser/getOperationResponses.ts b/src/openApi/v2/parser/getOperationResponses.ts index 1de667c8..aaaad755 100644 --- a/src/openApi/v2/parser/getOperationResponses.ts +++ b/src/openApi/v2/parser/getOperationResponses.ts @@ -20,13 +20,13 @@ export function getOperationResponses(openApi: OpenApi, responses: OpenApiRespon // if there is no typed data, we just return so the user is still // free to do their own casting if needed. if (responseCode) { - const result: OperationResponse = { - code: responseCode, - text: response.description || '', - type: 'any', - base: 'any', - imports: [], - }; + // const result: OperationResponse = { + // code: responseCode, + // text: response.description || '', + // type: 'any', + // base: 'any', + // imports: [], + // }; // If this response has a schema, then we need to check two things: // if this is a reference then the parameter is just the 'name' of @@ -40,7 +40,7 @@ export function getOperationResponses(openApi: OpenApi, responses: OpenApiRespon // result.imports.push(...responseSchema.imports); } - results.push(result); + // results.push(result); } } } diff --git a/src/openApi/v2/parser/getServices.ts b/src/openApi/v2/parser/getServices.ts index 4de12b2c..e9905a5e 100644 --- a/src/openApi/v2/parser/getServices.ts +++ b/src/openApi/v2/parser/getServices.ts @@ -1,6 +1,7 @@ import { Service } from '../../../client/interfaces/Service'; import { OpenApi } from '../interfaces/OpenApi'; import { Method } from './constants'; +import { getOperation } from './getOperation'; /** * Get the OpenAPI services @@ -21,23 +22,23 @@ export function getServices(openApi: OpenApi): Map { case Method.HEAD: case Method.PATCH: // Each method contains an OpenAPI operation, we parse the operation - // const op: OpenApiOperation = path[method]!; - // const operation: Operation = getOperation(openApi, url, method, op); + const op = path[method]!; + const operation = getOperation(openApi, url, method, op); // If we have already declared a service, then we should fetch that and // append the new method to it. Otherwise we should create a new service object. - // const service = - // services.get(operation.service) || - // ({ - // name: operation.service, - // operations: [], - // imports: [], - // } as Service); + const service = + services.get(operation.service) || + ({ + name: operation.service, + operations: [], + imports: [], + } as Service); // Push the operation in the service - // service.operations.push(operation); - // service.imports.push(...operation.imports); - // services.set(operation.service, service); + service.operations.push(operation); + service.imports.push(...operation.imports); + services.set(operation.service, service); break; } } diff --git a/src/templates/typescript/exportArray.hbs b/src/templates/typescript/exportArray.hbs index d7eb200a..aa164c47 100644 --- a/src/templates/typescript/exportArray.hbs +++ b/src/templates/typescript/exportArray.hbs @@ -1,12 +1,12 @@ -{{~#if description}} +{{#if description}} /** * {{{description}}} */ -{{~/if}} +{{/if}} export type {{{name}}} = {{>type}}{{#if nullable}} | null{{/if}}; export namespace {{{name}}} { -{{#indent}} + export const schema = {{>validation}}; export async function validate(value: any): Promise<{{{name}}}{{#if nullable}} | null{{/if}}> { @@ -16,5 +16,4 @@ export namespace {{{name}}} { export function validateSync(value: any): {{{name}}}{{#if nullable}} | null{{/if}} { return schema.validateSync(value, { strict: true }); } -{{/indent}} } diff --git a/src/templates/typescript/exportDictionary.hbs b/src/templates/typescript/exportDictionary.hbs index d7eb200a..aa164c47 100644 --- a/src/templates/typescript/exportDictionary.hbs +++ b/src/templates/typescript/exportDictionary.hbs @@ -1,12 +1,12 @@ -{{~#if description}} +{{#if description}} /** * {{{description}}} */ -{{~/if}} +{{/if}} export type {{{name}}} = {{>type}}{{#if nullable}} | null{{/if}}; export namespace {{{name}}} { -{{#indent}} + export const schema = {{>validation}}; export async function validate(value: any): Promise<{{{name}}}{{#if nullable}} | null{{/if}}> { @@ -16,5 +16,4 @@ export namespace {{{name}}} { export function validateSync(value: any): {{{name}}}{{#if nullable}} | null{{/if}} { return schema.validateSync(value, { strict: true }); } -{{/indent}} } diff --git a/src/templates/typescript/exportEnum.hbs b/src/templates/typescript/exportEnum.hbs index 8fea6577..9d449ef8 100644 --- a/src/templates/typescript/exportEnum.hbs +++ b/src/templates/typescript/exportEnum.hbs @@ -1,16 +1,16 @@ -{{~#if description}} +{{#if description}} /** * {{{description}}} */ -{{~/if}} +{{/if}} export enum {{{name}}} { - {{~#each enum}} + {{#each enum}} {{{name}}} = {{{value}}}, - {{~/each}} + {{/each}} } export namespace {{{name}}} { -{{#indent}} + export const schema = {{>validation}}; export async function validate(value: any): Promise<{{{name}}}> { @@ -20,5 +20,4 @@ export namespace {{{name}}} { export function validateSync(value: any): {{{name}}} { return schema.validateSync(value, { strict: true }); } -{{/indent}} } diff --git a/src/templates/typescript/exportGeneric.hbs b/src/templates/typescript/exportGeneric.hbs index d7eb200a..aa164c47 100644 --- a/src/templates/typescript/exportGeneric.hbs +++ b/src/templates/typescript/exportGeneric.hbs @@ -1,12 +1,12 @@ -{{~#if description}} +{{#if description}} /** * {{{description}}} */ -{{~/if}} +{{/if}} export type {{{name}}} = {{>type}}{{#if nullable}} | null{{/if}}; export namespace {{{name}}} { -{{#indent}} + export const schema = {{>validation}}; export async function validate(value: any): Promise<{{{name}}}{{#if nullable}} | null{{/if}}> { @@ -16,5 +16,4 @@ export namespace {{{name}}} { export function validateSync(value: any): {{{name}}}{{#if nullable}} | null{{/if}} { return schema.validateSync(value, { strict: true }); } -{{/indent}} } diff --git a/src/templates/typescript/exportInterface.hbs b/src/templates/typescript/exportInterface.hbs index f9143227..937014db 100644 --- a/src/templates/typescript/exportInterface.hbs +++ b/src/templates/typescript/exportInterface.hbs @@ -1,47 +1,41 @@ -{{~#if description}} +{{#if description}} /** * {{{description}}} */ -{{~/if}} -export interface {{{name}}}{{{template}}}{{#if extends}} extends {{#each extends}}{{{this}}}{{#unless @last}}, {{/unless}}{{/each}}{{/if}} { -{{~#indent}} - {{~#each properties}} - {{~#if description}} +{{/if}} +export interface {{{name}}}{{#if extends}} extends {{#each extends}}{{{this}}}{{#unless @last}}, {{/unless}}{{/each}}{{/if}} { + {{#each properties}} + {{#if description}} /** * {{{description}}} */ - {{~/if}} - {{#if readOnly}}readonly {{/if}}{{{name}}}{{#unless required}}?{{/unless}}: {{>type}}{{#if nullable}} | null{{/if}}; - {{~/each}} -{{~/indent}} + {{/if}} + {{#if readOnly}}readonly {{/if}}{{{name}}}{{#unless required}}?{{/unless}}: {{>type parent=../name}}{{#if nullable}} | null{{/if}}; + {{/each}} } export namespace {{{name}}} { -{{#indent}} - {{~#each enums}} - {{~#if description}} + + {{#each enums}} + {{#if description}} /** * {{{description}}} */ - {{~/if}} + {{/if}} export enum {{{name}}} { - {{~#each values}} + {{#each enum}} {{{name}}} = {{{value}}}, - {{~/each}} + {{/each}} } - {{/each}} - export const schema: yup.ObjectSchema<{{{name}}}{{{template}}}> = ( - {{~#indent}} - {{>validation}} - {{~/indent}} - ); - export async function validate(value: any): Promise<{{{name}}}{{{template}}}> { + {{/each}} + export const schema: yup.ObjectSchema<{{{name}}}> = {{>validation}}; + + export async function validate(value: any): Promise<{{{name}}}> { return schema.validate(value, { strict: true }); } - export function validateSync(value: any): {{{name}}}{{{template}}} { + export function validateSync(value: any): {{{name}}} { return schema.validateSync(value, { strict: true }); } -{{/indent}} } diff --git a/src/templates/typescript/exportReference.hbs b/src/templates/typescript/exportReference.hbs index d7eb200a..aa164c47 100644 --- a/src/templates/typescript/exportReference.hbs +++ b/src/templates/typescript/exportReference.hbs @@ -1,12 +1,12 @@ -{{~#if description}} +{{#if description}} /** * {{{description}}} */ -{{~/if}} +{{/if}} export type {{{name}}} = {{>type}}{{#if nullable}} | null{{/if}}; export namespace {{{name}}} { -{{#indent}} + export const schema = {{>validation}}; export async function validate(value: any): Promise<{{{name}}}{{#if nullable}} | null{{/if}}> { @@ -16,5 +16,4 @@ export namespace {{{name}}} { export function validateSync(value: any): {{{name}}}{{#if nullable}} | null{{/if}} { return schema.validateSync(value, { strict: true }); } -{{/indent}} } diff --git a/src/templates/typescript/index.hbs b/src/templates/typescript/index.hbs index 0d87e066..637cf9f4 100644 --- a/src/templates/typescript/index.hbs +++ b/src/templates/typescript/index.hbs @@ -7,12 +7,14 @@ export { ApiError } from './core/ApiError'; export { isSuccess } from './core/isSuccess'; export { OpenAPI } from './core/OpenAPI'; {{#if models}} -{{~#each models}} + +{{#each models}} export { {{{this}}} } from './models/{{{this}}}'; -{{~/each}} -{{~/if}} +{{/each}} +{{/if}} {{#if services}} -{{~#each services}} + +{{#each services}} export { {{{this}}} } from './services/{{{this}}}'; -{{~/each}} -{{~/if}} +{{/each}} +{{/if}} diff --git a/src/templates/typescript/model.hbs b/src/templates/typescript/model.hbs index 82138964..f04c206b 100644 --- a/src/templates/typescript/model.hbs +++ b/src/templates/typescript/model.hbs @@ -3,21 +3,23 @@ /* eslint-disable */ /* prettier-ignore */ {{#if imports}} -{{~#each imports}} + +{{#each imports}} import { {{{this}}} } from '../models/{{{this}}}'; -{{~/each}} -{{~/if}} +{{/each}} +{{/if}} import * as yup from 'yup'; + {{#eq export 'reference'}} -{{~>exportReference}} -{{~else eq export 'generic'}} -{{~>exportGeneric}} -{{~else eq export 'enum'}} -{{~>exportEnum}} -{{~else eq export 'array'}} -{{~>exportArray}} -{{~else eq export 'dictionary'}} -{{~>exportDictionary}} -{{~else eq export 'interface'}} -{{~>exportInterface}} -{{~/eq}} +{{>exportReference}} +{{else eq export 'generic'}} +{{>exportGeneric}} +{{else eq export 'enum'}} +{{>exportEnum}} +{{else eq export 'array'}} +{{>exportArray}} +{{else eq export 'dictionary'}} +{{>exportDictionary}} +{{else eq export 'interface'}} +{{>exportInterface}} +{{/eq}} diff --git a/src/templates/typescript/service.hbs b/src/templates/typescript/service.hbs index eaa72ab4..a53df1fb 100644 --- a/src/templates/typescript/service.hbs +++ b/src/templates/typescript/service.hbs @@ -3,10 +3,11 @@ /* eslint-disable */ /* prettier-ignore */ {{#if imports}} -{{~#each imports}} + +{{#each imports}} import { {{{this}}} } from '../models/{{{this}}}'; -{{~/each}} -{{~/if}} +{{/each}} +{{/if}} import { ApiError, catchGenericError } from '../core/ApiError'; import { request } from '../core/request'; import { isValidRequiredParam } from '../core/isValidRequiredParam'; @@ -14,60 +15,60 @@ import { OpenAPI } from '../core/OpenAPI'; import { Result } from '../core/Result'; export class {{{name}}} { - {{~#each operations}} + {{#each operations}} /** - {{~#if deprecated}} + {{#if deprecated}} * @deprecated - {{~/if}} - {{~#if summary}} + {{/if}} + {{#if summary}} * {{{summary}}} - {{~/if}} - {{~#if description}} + {{/if}} + {{#if description}} * {{{description}}} - {{~/if}} - {{~#if parameters}} - {{~#each parameters}} + {{/if}} + {{#if parameters}} + {{#each parameters}} * @param {{{name}}} {{{description}}} - {{~/each}} - {{~/if}} + {{/each}} + {{/if}} */ public static async {{{name}}}({{#each parameters}}{{{name}}}{{#unless required}}?{{/unless}}: {{{type}}}{{#if nullable}} | null{{/if}}{{#unless @last}}, {{/unless}}{{/each}}): Promise<{{{result}}}> { {{#if parameters}} - {{~#each parameters}} - {{~#if required}} + {{#each parameters}} + {{#if required}} isValidRequiredParam({{{name}}}, '{{{name}}}'); - {{~/if}} - {{~/each}} + {{/if}} + {{/each}} {{/if}} const result = await request({ method: '{{{method}}}', path: `{{{path}}}`, - {{~#if parametersHeader~}} + {{#if parametersHeader}} headers: { - {{~#each parametersHeader}} + {{#each parametersHeader}} '{{{prop}}}': {{{name}}}, - {{~/each}} + {{/each}} }, - {{~/if}} - {{~#if parametersQuery}} + {{/if}} + {{#if parametersQuery}} query: { - {{~#each parametersQuery}} + {{#each parametersQuery}} '{{{prop}}}': {{{name}}}, - {{~/each}} + {{/each}} }, - {{~/if}} - {{~#if parametersForm}} + {{/if}} + {{#if parametersForm}} formData: { - {{~#each parametersForm}} + {{#each parametersForm}} '{{{prop}}}': {{{name}}}, - {{~/each}} + {{/each}} }, - {{~/if}} - {{~#if parametersBody}} + {{/if}} + {{#if parametersBody}} body: {{{parametersBody.name}}}, - {{~/if}} + {{/if}} }); - {{~#if errors}} + {{#if errors}} if (!result.ok) { switch (result.status) { {{#each errors}} @@ -75,10 +76,10 @@ export class {{{name}}} { {{/each}} } } - {{~/if}} + {{/if}} catchGenericError(result); return result.body; } - {{~/each}} + {{/each}} } diff --git a/src/templates/typescript/type.hbs b/src/templates/typescript/type.hbs index a6df9f21..25b48568 100644 --- a/src/templates/typescript/type.hbs +++ b/src/templates/typescript/type.hbs @@ -1,13 +1,13 @@ -{{~#eq export 'reference'}} -{{~>typeForReference}} -{{~else eq export 'generic'}} -{{~>typeForGeneric}} -{{~else eq export 'enum'}} -{{~>typeForEnum}} -{{~else eq export 'array'}} -{{~>typeForArray}} -{{~else eq export 'dictionary'}} -{{~>typeForDictionary}} -{{~else eq export 'interface'}} -{{~>typeForInterface}} -{{~/eq}} +{{#eq export 'reference'}} +{{>typeForReference}} +{{else eq export 'generic'}} +{{>typeForGeneric}} +{{else eq export 'enum'}} +{{>typeForEnum}} +{{else eq export 'array'}} +{{>typeForArray}} +{{else eq export 'dictionary'}} +{{>typeForDictionary}} +{{else eq export 'interface'}} +{{>typeForInterface}} +{{/eq}} diff --git a/src/templates/typescript/typeForArray.hbs b/src/templates/typescript/typeForArray.hbs index 0fd14c91..784faf7a 100644 --- a/src/templates/typescript/typeForArray.hbs +++ b/src/templates/typescript/typeForArray.hbs @@ -1,5 +1,5 @@ {{~#if link~}} -Array<{{>type link}}> +Array<{{>type link child=true}}> {{~else~}} Array<{{{type}}}> {{~/if~}} diff --git a/src/templates/typescript/typeForDictionary.hbs b/src/templates/typescript/typeForDictionary.hbs index 413903ee..a213c65d 100644 --- a/src/templates/typescript/typeForDictionary.hbs +++ b/src/templates/typescript/typeForDictionary.hbs @@ -1,5 +1,5 @@ {{~#if link~}} -Dictionary<{{>type link}}> +Dictionary<{{>type link child=true}}> {{~else~}} Dictionary<{{{type}}}> {{~/if~}} diff --git a/src/templates/typescript/typeForEnum.hbs b/src/templates/typescript/typeForEnum.hbs index faba42a4..6fdb3569 100644 --- a/src/templates/typescript/typeForEnum.hbs +++ b/src/templates/typescript/typeForEnum.hbs @@ -1 +1,5 @@ -any +{{~#if parent~}} +{{{parent}}}.{{{name}}} +{{~else~}} +{{{type}}} +{{~/if~}} diff --git a/src/templates/typescript/typeForInterface.hbs b/src/templates/typescript/typeForInterface.hbs index a9b1d150..714249e5 100644 --- a/src/templates/typescript/typeForInterface.hbs +++ b/src/templates/typescript/typeForInterface.hbs @@ -1,12 +1,14 @@ +{{~#if properties~}} { -{{#indent}} - {{~#each properties}} - {{~#if description}} - /** - * {{{description}}} - */ - {{~/if}} - {{#if readOnly}}readonly {{/if}}{{{name}}}{{#unless required}}?{{/unless}}: {{>type}}{{#if nullable}} | null{{/if}}, - {{~/each}} -{{/indent}} +{{#each properties}} +{{#if description}} +/** + * {{{description}}} + */ +{{/if}} +{{#if readOnly}}readonly {{/if}}{{{name}}}{{#unless required}}?{{/unless}}: {{>type child=true}}{{#if nullable}} | null{{/if}}, +{{/each}} } +{{else~}} +any +{{~/if~}} diff --git a/src/templates/typescript/validation.hbs b/src/templates/typescript/validation.hbs index 76691640..76eb8b50 100644 --- a/src/templates/typescript/validation.hbs +++ b/src/templates/typescript/validation.hbs @@ -1,13 +1,13 @@ -{{~#eq export 'reference'~}} +{{#eq export 'reference'}} {{>validationForReference}} -{{~else eq export 'generic'~}} +{{else eq export 'generic'}} {{>validationForGeneric}} -{{~else eq export 'enum'~}} +{{else eq export 'enum'}} {{>validationForEnum}} -{{~else eq export 'array'~}} +{{else eq export 'array'}} {{>validationForArray}} -{{~else eq export 'dictionary'~}} +{{else eq export 'dictionary'}} {{>validationForDictionary}} -{{~else eq export 'interface'~}} +{{else eq export 'interface'}} {{>validationForInterface}} -{{~/eq~}} +{{/eq}} diff --git a/src/templates/typescript/validationForArray.hbs b/src/templates/typescript/validationForArray.hbs index a51849a9..a88f311d 100644 --- a/src/templates/typescript/validationForArray.hbs +++ b/src/templates/typescript/validationForArray.hbs @@ -1,5 +1,5 @@ {{~#if link~}} -yup.array<{{>type link}}>().of({{>validation link}}) +yup.array<{{>type link child=true}}>().of({{>validation link child=true}}) {{~else~}} yup.array<{{{type}}}>().of({{{base}}}.schema) {{~/if~}} diff --git a/src/templates/typescript/validationForDictionary.hbs b/src/templates/typescript/validationForDictionary.hbs index 97a0d4f0..9e4139ca 100644 --- a/src/templates/typescript/validationForDictionary.hbs +++ b/src/templates/typescript/validationForDictionary.hbs @@ -1,31 +1,19 @@ -{{~#if link}} -yup.lazytype link}}>>(value => -{{#indent}} - yup.objecttype link}}>>().shape( - {{#indent}} +{{~#if link~}} +yup.lazytype link child=true}}>>(value => { + return yup.objecttype link child=true}}>>().shape( Object.entries(value).reduce((obj, item) => ({ - {{#indent}} ...obj, - [item[0]]: {{>validation link}}, - {{/indent}} + [item[0]]: {{>validation link child=true}}, }), {}) - {{/indent}} - ) -{{/indent}} -) -{{~else}} -yup.lazy>(value => -{{#indent}} - yup.object>().shape( - {{#indent}} + ); +}) +{{~else~}} +yup.lazy>(value => { + return yup.object>().shape( Object.entries(value).reduce((obj, item) => ({ - {{#indent}} ...obj, [item[0]]: {{{base}}}.schema, - {{/indent}} }), {}) - {{/indent}} - ) -{{/indent}} -) -{{~/if}} + ); +}) +{{~/if~}} diff --git a/src/templates/typescript/validationForEnum.hbs b/src/templates/typescript/validationForEnum.hbs index 83cf725a..7dd5c8d4 100644 --- a/src/templates/typescript/validationForEnum.hbs +++ b/src/templates/typescript/validationForEnum.hbs @@ -1,9 +1,9 @@ -yup.mixed{{#if name}}<{{{name}}}>{{/if}}().oneOf([ - {{~#each enum}} - {{~#if ../name}} +yup.mixed<{{{name}}}>().oneOf([ + {{#each enum}} + {{#unless child}} {{{../name}}}.{{{name}}}, - {{~else}} + {{else}} {{{value}}}, - {{~/if}} - {{~/each}} + {{/unless}} + {{/each}} ]) diff --git a/src/templates/typescript/validationForInterface.hbs b/src/templates/typescript/validationForInterface.hbs index c01ff915..d0d6dc92 100644 --- a/src/templates/typescript/validationForInterface.hbs +++ b/src/templates/typescript/validationForInterface.hbs @@ -1,17 +1,21 @@ -{{~#if extends}} -{{~#each extends}} +( +{{#if extends}} +{{#each extends}} {{{this}}}.schema.concat( -{{~/each}} -{{~/if}} -yup.object{{#if name}}<{{{name}}}>{{/if}}().shape({ -{{#indent}} - {{~#each properties}} - {{{name}}}: yup.lazy(() => {{>validation}}.default(undefined)){{#if required}}.required(){{/if}}{{#if nullable}}.nullable(){{/if}}, - {{~/each}} -{{/indent}} +{{/each}} +{{/if}} +{{#if properties}} +yup.object{{#unless child}}<{{{name}}}>{{/unless}}().shape({ + {{#each properties}} + {{{name}}}: yup.lazy(() => {{>validation child=true}}.default(undefined){{#if required}}.required(){{/if}}{{#if nullable}}.nullable(){{/if}}), + {{/each}} }).noUnknown() -{{~#if extends}} -{{~#each extends}} +{{else}} +yup.object() +{{/if}} +{{#if extends}} +{{#each extends}} +) +{{/each}} +{{/if}} ) -{{~/each}} -{{~/if}} diff --git a/src/utils/fixIndentation.ts b/src/utils/fixIndentation.ts deleted file mode 100644 index d8b89db7..00000000 --- a/src/utils/fixIndentation.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Replace " /**/}" with "}" -// Replace " /**/)" with ")" -// Replace " /**/]" with "]" - -export function fixIndentation(s: string): string { - return s - .replace(/\s{4}\/\*\*\/\}/g, '}') - .replace(/\s{4}\/\*\*\/\)/g, ')') - .replace(/\s{4}\/\*\*\/\]/g, ']'); -} diff --git a/src/utils/format.ts b/src/utils/format.ts new file mode 100644 index 00000000..4513923d --- /dev/null +++ b/src/utils/format.ts @@ -0,0 +1,19 @@ +import { EOL } from 'os'; + +export function format(s: string): string { + let indent: number = 0; + let lines = s.split(EOL); + lines = lines.map(line => { + line = line.trim().replace(/^\*/g, ' *'); + let i = indent; + if (line.endsWith('(') || line.endsWith('{') || line.endsWith('[')) { + indent++; + } + if (line.startsWith(')') || line.startsWith('}') || line.startsWith(']')) { + indent--; + i--; + } + return `${' '.repeat(i)}${line}`; + }); + return lines.join(EOL); +} diff --git a/src/utils/readHandlebarsTemplate.ts b/src/utils/readHandlebarsTemplate.ts index 1c8c6aae..2498e9d1 100644 --- a/src/utils/readHandlebarsTemplate.ts +++ b/src/utils/readHandlebarsTemplate.ts @@ -16,7 +16,6 @@ export function readHandlebarsTemplate(filePath: string): Handlebars.TemplateDel strict: true, noEscape: true, preventIndent: true, - ignoreStandalone: true, knownHelpersOnly: true, knownHelpers: { indent: true, diff --git a/src/utils/registerHandlebarHelpers.ts b/src/utils/registerHandlebarHelpers.ts index 8d18feb9..f3815105 100644 --- a/src/utils/registerHandlebarHelpers.ts +++ b/src/utils/registerHandlebarHelpers.ts @@ -1,22 +1,7 @@ import * as Handlebars from 'handlebars'; -import {EOL} from 'os'; export function registerHandlebarHelpers(): void { - - Handlebars.registerHelper('indent', function (options: Handlebars.HelperOptions): string { - // eslint-disable - // prettier-ignore - // @ts-ignore - return options.fn(this) - .split(EOL) - .map(line => line.replace(/^\s{4}/g, '')) - .map(line => `/**/${line}`) - .join(EOL); - }); - - Handlebars.registerHelper('eq', function (a: string, b: string, options: Handlebars.HelperOptions): string { - // eslint-disable - // prettier-ignore + Handlebars.registerHelper('eq', function(a: string, b: string, options: Handlebars.HelperOptions): string { // @ts-ignore return a === b ? options.fn(this) : options.inverse(this); }); diff --git a/src/utils/writeClient.ts b/src/utils/writeClient.ts index b513a69f..20c42e8e 100644 --- a/src/utils/writeClient.ts +++ b/src/utils/writeClient.ts @@ -1,12 +1,12 @@ -import {writeClientModels} from './writeClientModels'; -import {writeClientServices} from './writeClientServices'; -import {Client} from '../client/interfaces/Client'; +import { writeClientModels } from './writeClientModels'; +import { writeClientServices } from './writeClientServices'; +import { Client } from '../client/interfaces/Client'; import * as path from 'path'; import * as mkdirp from 'mkdirp'; import * as rimraf from 'rimraf'; -import {Templates} from './readHandlebarsTemplates'; -import {writeClientIndex} from './writeClientIndex'; -import {Language} from '../index'; +import { Templates } from './readHandlebarsTemplates'; +import { writeClientIndex } from './writeClientIndex'; +import { Language } from '../index'; import * as fs from 'fs'; import * as glob from 'glob'; @@ -41,7 +41,7 @@ export function writeClient(client: Client, language: Language, templates: Templ // Copy all support files const supportFiles = path.resolve(__dirname, `../../src/templates/${language}/`); - const supportFilesList = glob.sync('**/*.{ts,js}', {cwd: supportFiles}); + const supportFilesList = glob.sync('**/*.{ts,js}', { cwd: supportFiles }); supportFilesList.forEach(file => fs.copyFileSync( path.resolve(supportFiles, file), // From input path diff --git a/src/utils/writeClientModels.ts b/src/utils/writeClientModels.ts index 7379785a..6d7c108c 100644 --- a/src/utils/writeClientModels.ts +++ b/src/utils/writeClientModels.ts @@ -5,7 +5,7 @@ import { Language } from '../index'; import { getFileName } from './getFileName'; import { exportModel } from './exportModel'; import { Templates } from './readHandlebarsTemplates'; -import { fixIndentation } from './fixIndentation'; +import { format } from './format'; /** * Generate Models using the Handlebar template and write to disk. @@ -20,7 +20,7 @@ export function writeClientModels(models: Map, language: Language try { const templateData = exportModel(model); const templateResult = templates.model(templateData); - fs.writeFileSync(path.resolve(outputPath, fileName), fixIndentation(templateResult)); + fs.writeFileSync(path.resolve(outputPath, fileName), format(templateResult)); } catch (e) { throw new Error(`Could not write model: "${fileName}"`); } diff --git a/src/utils/writeClientServices.ts b/src/utils/writeClientServices.ts index 3d705f0b..410abc8a 100644 --- a/src/utils/writeClientServices.ts +++ b/src/utils/writeClientServices.ts @@ -5,7 +5,7 @@ import { Language } from '../index'; import { getFileName } from './getFileName'; import { exportService } from './exportService'; import { Templates } from './readHandlebarsTemplates'; -import { fixIndentation } from './fixIndentation'; +import { format } from './format'; /** * Generate Services using the Handlebar template and write to disk. @@ -20,7 +20,7 @@ export function writeClientServices(services: Map, language: La try { const templateData = exportService(service); const templateResult = templates.model(templateData); - fs.writeFileSync(path.resolve(outputPath, fileName), fixIndentation(templateResult)); + fs.writeFileSync(path.resolve(outputPath, fileName), format(templateResult)); } catch (e) { throw new Error(`Could not write service: "${fileName}"`); } diff --git a/test/index.js b/test/index.js index 906fb0ca..cc1a7a6e 100755 --- a/test/index.js +++ b/test/index.js @@ -6,7 +6,7 @@ const OpenAPI = require('../dist'); OpenAPI.generate( './test/mock/v2/spec.json', - './test/tmp/v2/spec', + './test/tmp/v2/ts/spec', OpenAPI.Language.TYPESCRIPT, OpenAPI.HttpClient.FETCH, ); @@ -25,16 +25,16 @@ OpenAPI.generate( // OpenAPI.HttpClient.FETCH, // ); // -// OpenAPI.generate( -// './test/mock/v2/test-sites.json', -// './test/tmp/v2/ts/test-sites', -// OpenAPI.Language.TYPESCRIPT, -// OpenAPI.HttpClient.FETCH, -// ); - +OpenAPI.generate( + './test/mock/v2/test-sites.json', + './test/tmp/v2/ts/test-sites', + OpenAPI.Language.TYPESCRIPT, + OpenAPI.HttpClient.FETCH, +); +// // OpenAPI.generate( // './test/mock/v2/test-petstore.yaml', -// './test/tmp/v2/test-petstore-yaml', +// './test/tmp/v2/ts/test-petstore-yaml', // OpenAPI.Language.TYPESCRIPT, // OpenAPI.HttpClient.FETCH, // ); diff --git a/test/mock/v2/spec.json b/test/mock/v2/spec.json index d5a9cd93..5108c7d3 100644 --- a/test/mock/v2/spec.json +++ b/test/mock/v2/spec.json @@ -188,7 +188,7 @@ "description": "This is a model with one enum", "type": "object", "properties": { - "prop": { + "Test": { "description": "This is a simple enum with strings", "enum": [ "Success", @@ -202,7 +202,7 @@ "description": "This is a model with one enum", "type": "object", "properties": { - "prop": { + "Test": { "type": "integer", "description": "Success=1,Warning=2,Error=3" }