diff --git a/src/client/interfaces/OperationParameter.d.ts b/src/client/interfaces/OperationParameter.d.ts index aa36df6c..f0969677 100644 --- a/src/client/interfaces/OperationParameter.d.ts +++ b/src/client/interfaces/OperationParameter.d.ts @@ -1,7 +1,19 @@ import { Model } from './Model'; +import { Enum } from './Enum'; -export interface OperationParameter extends Model { +export interface OperationParameter { prop: string; in: 'path' | 'query' | 'header' | 'formData' | 'body'; + name: string; + export: 'reference' | 'generic' | 'enum' | 'array' | 'dictionary' | 'interface'; + type: string; + base: string; + template: string | null; + description: string | null; + required: boolean; + nullable: boolean; + imports: string[]; + enum: Enum[]; + model: Model | null; default: any; } diff --git a/src/openApi/v2/interfaces/OpenApiItems.d.ts b/src/openApi/v2/interfaces/OpenApiItems.d.ts index ea6294ea..826f7f89 100644 --- a/src/openApi/v2/interfaces/OpenApiItems.d.ts +++ b/src/openApi/v2/interfaces/OpenApiItems.d.ts @@ -2,7 +2,7 @@ * https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#itemsObject */ export interface OpenApiItems { - type?: 'string' | 'number' | 'integer' | 'boolean' | 'array'; + type?: string; format?: 'int32' | 'int64' | 'float' | 'double' | 'string' | 'boolean' | 'byte' | 'binary' | 'date' | 'date-time' | 'password'; items?: OpenApiItems; collectionFormat?: 'csv' | 'ssv' | 'tsv' | 'pipes'; @@ -16,7 +16,7 @@ export interface OpenApiItems { pattern?: string; maxItems?: number; minItems?: number; - uniqueItems?: number; + uniqueItems?: boolean; enum?: string[]; multipleOf?: number; } diff --git a/src/openApi/v2/interfaces/OpenApiSchema.d.ts b/src/openApi/v2/interfaces/OpenApiSchema.d.ts index 809ee192..7b64637a 100644 --- a/src/openApi/v2/interfaces/OpenApiSchema.d.ts +++ b/src/openApi/v2/interfaces/OpenApiSchema.d.ts @@ -7,7 +7,6 @@ import { OpenApiReference } from './OpenApiReference'; * https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#schemaObject */ export interface OpenApiSchema extends OpenApiReference { - format?: 'int32' | 'int64' | 'float' | 'double' | 'string' | 'boolean' | 'byte' | 'binary' | 'date' | 'date-time' | 'password'; title?: string; description?: string; default?: any; @@ -21,12 +20,13 @@ export interface OpenApiSchema extends OpenApiReference { pattern?: string; maxItems?: number; minItems?: number; - uniqueItems?: number; + uniqueItems?: boolean; maxProperties?: number; minProperties?: number; required?: string[]; enum?: (string | number)[]; type?: string; + format?: 'int32' | 'int64' | 'float' | 'double' | 'string' | 'boolean' | 'byte' | 'binary' | 'date' | 'date-time' | 'password'; items?: OpenApiSchema; allOf?: OpenApiSchema[]; properties?: Dictionary; diff --git a/src/openApi/v2/parser/getOperation.ts b/src/openApi/v2/parser/getOperation.ts index 544ea9bf..f433681c 100644 --- a/src/openApi/v2/parser/getOperation.ts +++ b/src/openApi/v2/parser/getOperation.ts @@ -7,6 +7,10 @@ import { OpenApi } from '../interfaces/OpenApi'; import { getComment } from './getComment'; import { Operation } from '../../../client/interfaces/Operation'; import { PrimaryType } from './constants'; +import { getOperationParameters } from './getOperationParameters'; +import { getOperationResponses } from './getOperationResponses'; +import { getOperationResponse } from './getOperationResponse'; +import { getOperationErrors } from './getOperationErrors'; export function getOperation(openApi: OpenApi, url: string, method: string, op: OpenApiOperation): Operation { const serviceName = (op.tags && op.tags[0]) || 'Service'; @@ -37,24 +41,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 dad260ac..bfb000b1 100644 --- a/src/openApi/v2/parser/getOperationParameter.ts +++ b/src/openApi/v2/parser/getOperationParameter.ts @@ -4,6 +4,11 @@ import { getComment } from './getComment'; import { getOperationParameterName } from './getOperationParameterName'; import { OperationParameter } from '../../../client/interfaces/OperationParameter'; import { PrimaryType } from './constants'; +import { getType } from './getType'; +import { getEnum } from './getEnum'; +import { getEnumType } from './getEnumType'; +import { getEnumFromDescription } from './getEnumFromDescription'; +import { getModel } from './getModel'; export function getOperationParameter(openApi: OpenApi, parameter: OpenApiParameter): OperationParameter { const result: OperationParameter = { @@ -14,17 +19,87 @@ export function getOperationParameter(openApi: OpenApi, parameter: OpenApiParame type: PrimaryType.OBJECT, base: PrimaryType.OBJECT, template: null, - link: null, description: getComment(parameter.description), - readOnly: false, - required: false, + required: parameter.required || false, nullable: false, imports: [], - extends: [], enum: [], - enums: [], - properties: [], + model: null, default: null, }; + + if (parameter.$ref) { + const definitionRef = getType(parameter.$ref); + result.export = 'reference'; + result.type = definitionRef.type; + result.base = definitionRef.base; + result.template = definitionRef.template; + result.imports.push(...definitionRef.imports); + return result; + } + + if (parameter.enum) { + const enumerators = getEnum(parameter.enum); + if (enumerators.length) { + result.export = 'enum'; + result.type = getEnumType(enumerators); + result.base = PrimaryType.STRING; + result.enum.push(...enumerators); + return result; + } + } + + if ((parameter.type === 'int' || parameter.type === 'integer') && parameter.description) { + const enumerators = getEnumFromDescription(parameter.description); + if (enumerators.length) { + result.export = 'enum'; + result.type = getEnumType(enumerators); + result.base = PrimaryType.NUMBER; + result.enum.push(...enumerators); + return result; + } + } + + // if (parameter.type === 'array' && parameter.items) { + // const arrayItems = getModel(openApi, parameter.items); + // result.export = 'array'; + // result.type = arrayItems.type; + // result.base = arrayItems.base; + // result.template = arrayItems.template; + // result.link = arrayItems; + // result.imports.push(...arrayItems.imports); + // return result; + // } + + if (parameter.schema) { + if (parameter.schema.$ref) { + const model = getType(parameter.schema.$ref); + result.export = 'reference'; + result.type = model.type; + result.base = model.base; + result.template = model.template; + result.imports.push(...model.imports); + } else { + const model = getModel(openApi, parameter.schema); + result.export = 'interface'; + result.type = model.type; + result.base = model.base; + result.template = model.template; + result.imports.push(...model.imports); + result.model = model; + } + } + + // If the parameter has a type than it can be a basic or generic type. + if (parameter.type) { + const definitionType = getType(parameter.type); + result.export = 'generic'; + result.type = definitionType.type; + result.base = definitionType.base; + result.template = definitionType.template; + result.imports.push(...definitionType.imports); + return result; + } + return result; } diff --git a/src/openApi/v2/parser/getOperationResponses.ts b/src/openApi/v2/parser/getOperationResponses.ts index aaaad755..21b3b8fc 100644 --- a/src/openApi/v2/parser/getOperationResponses.ts +++ b/src/openApi/v2/parser/getOperationResponses.ts @@ -4,6 +4,8 @@ import { OpenApiResponse } from '../interfaces/OpenApiResponse'; import { getRef } from './getRef'; import { OpenApi } from '../interfaces/OpenApi'; import { OperationResponse } from '../../../client/interfaces/OperationResponse'; +import { getType } from './getType'; +import { getModel } from './getModel'; export function getOperationResponses(openApi: OpenApi, responses: OpenApiResponses): OperationResponse[] { const results: OperationResponse[] = []; @@ -20,27 +22,36 @@ 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', + template: null, + 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 // this reference type. Otherwise it might be a complex schema and // then we need to parse the schema! if (response.schema) { - // const responseSchema: SchemaReference = getSchemaReference(openApi, response.schema); - // result.type = responseSchema.type; - // result.base = responseSchema.base; - // result.template = responseSchema.template; - // result.imports.push(...responseSchema.imports); + if (response.schema.$ref) { + const model = getType(response.schema.$ref); + result.type = model.type; + result.base = model.base; + result.template = model.template; + result.imports.push(...model.imports); + } else { + const model = getModel(openApi, response.schema); + result.type = model.type; + result.base = model.base; + result.template = model.template; + result.imports.push(...model.imports); + } } - // results.push(result); + results.push(result); } } } diff --git a/src/templates/javascript/core/isValidRequiredParam.js b/src/templates/javascript/core/isValidRequiredParam.js deleted file mode 100644 index 6bd81d56..00000000 --- a/src/templates/javascript/core/isValidRequiredParam.js +++ /dev/null @@ -1,14 +0,0 @@ -/* istanbul ignore file */ -/* eslint-disable */ -/* prettier-ignore */ - -/** - * Check if a parameter is valid. - * @param param The parameter value. - * @param name The parameter name. - */ -export function isValidRequiredParam(param, name) { - if (param === undefined || param === null) { - throw new Error(`Required parameter '${name}' was undefined or null.`); - } -} diff --git a/src/templates/javascript/service.hbs b/src/templates/javascript/service.hbs index ef5197a6..1656784f 100644 --- a/src/templates/javascript/service.hbs +++ b/src/templates/javascript/service.hbs @@ -4,7 +4,6 @@ import { ApiError, catchGenericError } from '../core/ApiError'; import { request } from '../core/request'; -import { isValidRequiredParam } from '../core/isValidRequiredParam'; import { OpenAPI } from '../core/OpenAPI'; export class {{{name}}} { diff --git a/src/templates/typescript/core/isValidRequiredParam.ts b/src/templates/typescript/core/isValidRequiredParam.ts deleted file mode 100644 index 73ebc900..00000000 --- a/src/templates/typescript/core/isValidRequiredParam.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -/* prettier-ignore */ - -/** - * Check if a parameter is valid. - * @param param The parameter value. - * @param name The parameter name. - */ -export function isValidRequiredParam(param: any, name: string): void { - if (param === undefined || param === null) { - throw new Error(`Required parameter '${name}' was undefined or null.`); - } -} diff --git a/src/templates/typescript/service.hbs b/src/templates/typescript/service.hbs index a3ec164b..03993de6 100644 --- a/src/templates/typescript/service.hbs +++ b/src/templates/typescript/service.hbs @@ -10,7 +10,6 @@ import { {{{this}}} } from '../models/{{{this}}}'; {{/if}} import { ApiError, catchGenericError } from '../core/ApiError'; import { request } from '../core/request'; -import { isValidRequiredParam } from '../core/isValidRequiredParam'; import { OpenAPI } from '../core/OpenAPI'; import { Result } from '../core/Result'; @@ -33,16 +32,8 @@ export class {{{name}}} { {{/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}} - isValidRequiredParam({{{name}}}, '{{{name}}}'); - {{/if}} - {{/each}} - {{/if}} - - const result = await request({ + const result: Result<{{{result}}}> = await request({ method: '{{{method}}}', path: `{{{path}}}`, {{#if parametersHeader}} diff --git a/src/templates/typescript/typeForInterface.hbs b/src/templates/typescript/typeForInterface.hbs index 714249e5..7f937ca8 100644 --- a/src/templates/typescript/typeForInterface.hbs +++ b/src/templates/typescript/typeForInterface.hbs @@ -9,6 +9,6 @@ {{#if readOnly}}readonly {{/if}}{{{name}}}{{#unless required}}?{{/unless}}: {{>type child=true}}{{#if nullable}} | null{{/if}}, {{/each}} } -{{else~}} +{{~else~}} any {{~/if~}} diff --git a/src/templates/typescript/validationForInterface.hbs b/src/templates/typescript/validationForInterface.hbs index d0d6dc92..dbd3d2ee 100644 --- a/src/templates/typescript/validationForInterface.hbs +++ b/src/templates/typescript/validationForInterface.hbs @@ -7,7 +7,7 @@ {{#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}}), + {{{name}}}: yup.lazy(() => {{>validation child=true}}.default(undefined){{#if nullable}}.nullable(){{/if}}){{#if required}}.required(){{/if}}, {{/each}} }).noUnknown() {{else}} diff --git a/test/index.js b/test/index.js index 519da891..c8c07def 100755 --- a/test/index.js +++ b/test/index.js @@ -11,43 +11,43 @@ OpenAPI.generate( OpenAPI.HttpClient.FETCH, ); -OpenAPI.generate( - './test/mock/v2/test-addon.json', - './test/tmp/v2/ts/test-addon', - OpenAPI.Language.TYPESCRIPT, - OpenAPI.HttpClient.FETCH, -); - -OpenAPI.generate( - './test/mock/v2/test-docs.json', - './test/tmp/v2/ts/test-docs', - OpenAPI.Language.TYPESCRIPT, - OpenAPI.HttpClient.FETCH, -); - +// OpenAPI.generate( +// './test/mock/v2/test-addon.json', +// './test/tmp/v2/ts/test-addon', +// OpenAPI.Language.TYPESCRIPT, +// OpenAPI.HttpClient.FETCH, +// ); +// +// OpenAPI.generate( +// './test/mock/v2/test-docs.json', +// './test/tmp/v2/ts/test-docs', +// 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/ts/test-petstore-yaml', - OpenAPI.Language.TYPESCRIPT, - OpenAPI.HttpClient.FETCH, -); - -OpenAPI.compile('./test/tmp/v2/ts/spec'); - -OpenAPI.compile('./test/tmp/v2/ts/test-addon'); - -OpenAPI.compile('./test/tmp/v2/ts/test-docs'); - -OpenAPI.compile('./test/tmp/v2/ts/test-sites'); - -OpenAPI.compile('./test/tmp/v2/ts/test-petstore-yaml'); +// +// OpenAPI.generate( +// './test/mock/v2/test-petstore.yaml', +// './test/tmp/v2/ts/test-petstore-yaml', +// OpenAPI.Language.TYPESCRIPT, +// OpenAPI.HttpClient.FETCH, +// ); +// +// OpenAPI.compile('./test/tmp/v2/ts/spec'); +// +// OpenAPI.compile('./test/tmp/v2/ts/test-addon'); +// +// OpenAPI.compile('./test/tmp/v2/ts/test-docs'); +// +// OpenAPI.compile('./test/tmp/v2/ts/test-sites'); +// +// OpenAPI.compile('./test/tmp/v2/ts/test-petstore-yaml'); // OpenAPI.generate( // './test/mock/v3/test-petstore.json',