mirror of
https://github.com/ferdikoomen/openapi-typescript-codegen.git
synced 2026-02-01 16:46:58 +00:00
- First draft ready
This commit is contained in:
parent
00158b4af7
commit
b16db33c92
@ -4,7 +4,7 @@ import { OpenApiResponse } from './OpenApiResponse';
|
||||
* https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#responsesObject
|
||||
*/
|
||||
export interface OpenApiResponses {
|
||||
[httpcode: string]: OpenApiResponse;
|
||||
|
||||
default?: OpenApiResponse;
|
||||
|
||||
[httpcode: string]: OpenApiResponse;
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, isProperty
|
||||
link: null,
|
||||
description: getComment(definition.description),
|
||||
isProperty: isProperty,
|
||||
isReadOnly: definition.readOnly || false,
|
||||
isReadOnly: definition.readOnly === true,
|
||||
isNullable: false,
|
||||
isRequired: false,
|
||||
imports: [],
|
||||
|
||||
@ -10,8 +10,7 @@ export function getModelProperties(openApi: OpenApi, definition: OpenApiSchema):
|
||||
for (const propertyName in definition.properties) {
|
||||
if (definition.properties.hasOwnProperty(propertyName)) {
|
||||
const property = definition.properties[propertyName];
|
||||
const propertyRequired = !!(definition.required && definition.required.includes(propertyName));
|
||||
const propertyReadOnly = !!property.readOnly;
|
||||
const propertyRequired = definition.required && definition.required.includes(propertyName);
|
||||
if (property.$ref) {
|
||||
const model = getType(property.$ref);
|
||||
models.push({
|
||||
@ -23,8 +22,8 @@ export function getModelProperties(openApi: OpenApi, definition: OpenApiSchema):
|
||||
link: null,
|
||||
description: getComment(property.description),
|
||||
isProperty: true,
|
||||
isReadOnly: propertyReadOnly,
|
||||
isRequired: propertyRequired,
|
||||
isReadOnly: property.readOnly === true,
|
||||
isRequired: propertyRequired === true,
|
||||
isNullable: false,
|
||||
imports: model.imports,
|
||||
extends: [],
|
||||
@ -43,8 +42,8 @@ export function getModelProperties(openApi: OpenApi, definition: OpenApiSchema):
|
||||
link: model.link,
|
||||
description: getComment(property.description),
|
||||
isProperty: true,
|
||||
isReadOnly: propertyReadOnly,
|
||||
isRequired: propertyRequired,
|
||||
isReadOnly: property.readOnly === true,
|
||||
isRequired: propertyRequired === true,
|
||||
isNullable: false,
|
||||
imports: model.imports,
|
||||
extends: model.extends,
|
||||
|
||||
@ -23,7 +23,7 @@ export function getOperation(openApi: OpenApi, url: string, method: string, op:
|
||||
name: operationName,
|
||||
summary: getComment(op.summary),
|
||||
description: getComment(op.description),
|
||||
deprecated: op.deprecated || false,
|
||||
deprecated: op.deprecated === true,
|
||||
method: method,
|
||||
path: operationPath,
|
||||
parameters: [],
|
||||
|
||||
@ -25,7 +25,7 @@ export function getOperationParameter(openApi: OpenApi, parameter: OpenApiParame
|
||||
default: getOperationParameterDefault(parameter.default),
|
||||
isProperty: false,
|
||||
isReadOnly: false,
|
||||
isRequired: parameter.required || false,
|
||||
isRequired: parameter.required === true,
|
||||
isNullable: false,
|
||||
imports: [],
|
||||
extends: [],
|
||||
|
||||
@ -10,7 +10,7 @@ export interface OpenApiParameter extends OpenApiReference {
|
||||
name: string;
|
||||
in: 'path' | 'query' | 'header' | 'cookie';
|
||||
description?: string;
|
||||
required: boolean;
|
||||
required?: boolean;
|
||||
deprecated?: boolean;
|
||||
allowEmptyValue?: boolean;
|
||||
style?: string;
|
||||
|
||||
@ -5,7 +5,7 @@ import { OpenApiResponse } from './OpenApiResponse';
|
||||
* https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#responsesObject
|
||||
*/
|
||||
export interface OpenApiResponses extends OpenApiReference {
|
||||
[httpcode: string]: OpenApiResponse;
|
||||
|
||||
default: OpenApiResponse;
|
||||
|
||||
[httpcode: string]: OpenApiResponse;
|
||||
}
|
||||
|
||||
@ -42,3 +42,10 @@ export enum Method {
|
||||
HEAD = 'head',
|
||||
PATCH = 'patch',
|
||||
}
|
||||
|
||||
export enum ContentType {
|
||||
APPLICATION_JSON_PATCH = 'application/json-patch+json',
|
||||
APPLICATION_JSON = 'application/json',
|
||||
TEXT_JSON = 'text/json',
|
||||
TEXT_PAIN = 'text/plain',
|
||||
}
|
||||
|
||||
22
src/openApi/v3/parser/getContent.ts
Normal file
22
src/openApi/v3/parser/getContent.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { ContentType } from './constants';
|
||||
import { Dictionary } from '../../../utils/types';
|
||||
import { OpenApi } from '../interfaces/OpenApi';
|
||||
import { OpenApiMediaType } from '../interfaces/OpenApiMediaType';
|
||||
import { OpenApiSchema } from '../interfaces/OpenApiSchema';
|
||||
|
||||
export function getContent(openApi: OpenApi, content: Dictionary<OpenApiMediaType>): OpenApiSchema | null {
|
||||
/* prettier-ignore */
|
||||
return (
|
||||
content[ContentType.APPLICATION_JSON_PATCH] &&
|
||||
content[ContentType.APPLICATION_JSON_PATCH].schema
|
||||
) || (
|
||||
content[ContentType.APPLICATION_JSON] &&
|
||||
content[ContentType.APPLICATION_JSON].schema
|
||||
) || (
|
||||
content[ContentType.TEXT_JSON] &&
|
||||
content[ContentType.TEXT_JSON].schema
|
||||
) || (
|
||||
content[ContentType.TEXT_PAIN] &&
|
||||
content[ContentType.TEXT_PAIN].schema
|
||||
) || null;
|
||||
}
|
||||
@ -19,8 +19,8 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, isProperty
|
||||
link: null,
|
||||
description: getComment(definition.description),
|
||||
isProperty: isProperty,
|
||||
isReadOnly: definition.readOnly || false,
|
||||
isNullable: definition.nullable || false,
|
||||
isReadOnly: definition.readOnly === true,
|
||||
isNullable: definition.nullable === true,
|
||||
isRequired: false,
|
||||
imports: [],
|
||||
extends: [],
|
||||
|
||||
@ -10,9 +10,7 @@ export function getModelProperties(openApi: OpenApi, definition: OpenApiSchema):
|
||||
for (const propertyName in definition.properties) {
|
||||
if (definition.properties.hasOwnProperty(propertyName)) {
|
||||
const property = definition.properties[propertyName];
|
||||
const propertyRequired = !!(definition.required && definition.required.includes(propertyName));
|
||||
const propertyReadOnly = !!property.readOnly;
|
||||
const propertyNullable = !!property.nullable;
|
||||
const propertyRequired = definition.required && definition.required.includes(propertyName);
|
||||
if (property.$ref) {
|
||||
const model = getType(property.$ref);
|
||||
models.push({
|
||||
@ -24,9 +22,9 @@ export function getModelProperties(openApi: OpenApi, definition: OpenApiSchema):
|
||||
link: null,
|
||||
description: getComment(property.description),
|
||||
isProperty: true,
|
||||
isReadOnly: propertyReadOnly,
|
||||
isRequired: propertyRequired,
|
||||
isNullable: propertyNullable,
|
||||
isReadOnly: property.readOnly === true,
|
||||
isRequired: propertyRequired === true,
|
||||
isNullable: property.nullable === true,
|
||||
imports: model.imports,
|
||||
extends: [],
|
||||
enum: [],
|
||||
@ -44,9 +42,9 @@ export function getModelProperties(openApi: OpenApi, definition: OpenApiSchema):
|
||||
link: model.link,
|
||||
description: getComment(property.description),
|
||||
isProperty: true,
|
||||
isReadOnly: propertyReadOnly,
|
||||
isRequired: propertyRequired,
|
||||
isNullable: propertyNullable,
|
||||
isReadOnly: property.readOnly === true,
|
||||
isRequired: propertyRequired === true,
|
||||
isNullable: property.nullable === true,
|
||||
imports: model.imports,
|
||||
extends: model.extends,
|
||||
enum: model.enum,
|
||||
|
||||
@ -6,6 +6,7 @@ import { getOperationErrors } from './getOperationErrors';
|
||||
import { getOperationName } from './getOperationName';
|
||||
import { getOperationParameters } from './getOperationParameters';
|
||||
import { getOperationPath } from './getOperationPath';
|
||||
import { getOperationRequestBody } from './getOperationRequestBody';
|
||||
import { getOperationResponses } from './getOperationResponses';
|
||||
import { getOperationResults } from './getOperationResults';
|
||||
import { getServiceClassName } from './getServiceClassName';
|
||||
@ -23,7 +24,7 @@ export function getOperation(openApi: OpenApi, url: string, method: string, op:
|
||||
name: operationName,
|
||||
summary: getComment(op.summary),
|
||||
description: getComment(op.description),
|
||||
deprecated: op.deprecated || false,
|
||||
deprecated: op.deprecated === true,
|
||||
method: method,
|
||||
path: operationPath,
|
||||
parameters: [],
|
||||
@ -49,6 +50,13 @@ export function getOperation(openApi: OpenApi, url: string, method: string, op:
|
||||
operation.parametersBody = parameters.parametersBody;
|
||||
}
|
||||
|
||||
if (op.requestBody) {
|
||||
const requestBody = getOperationRequestBody(openApi, op.requestBody);
|
||||
operation.imports.push(...requestBody.imports);
|
||||
operation.parameters.push(requestBody);
|
||||
operation.parametersBody = requestBody;
|
||||
}
|
||||
|
||||
// Parse the operation responses.
|
||||
if (op.responses) {
|
||||
const operationResponses = getOperationResponses(openApi, op.responses);
|
||||
|
||||
@ -21,7 +21,7 @@ export function getOperationParameter(openApi: OpenApi, parameter: OpenApiParame
|
||||
default: undefined,
|
||||
isProperty: false,
|
||||
isReadOnly: false,
|
||||
isRequired: parameter.required || false,
|
||||
isRequired: parameter.required === true,
|
||||
isNullable: false,
|
||||
imports: [],
|
||||
extends: [],
|
||||
|
||||
60
src/openApi/v3/parser/getOperationRequestBody.ts
Normal file
60
src/openApi/v3/parser/getOperationRequestBody.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import { OpenApi } from '../interfaces/OpenApi';
|
||||
import { OpenApiRequestBody } from '../interfaces/OpenApiRequestBody';
|
||||
import { OperationParameter } from '../../../client/interfaces/OperationParameter';
|
||||
import { PrimaryType } from './constants';
|
||||
import { getComment } from './getComment';
|
||||
import { getContent } from './getContent';
|
||||
import { getModel } from './getModel';
|
||||
import { getType } from './getType';
|
||||
|
||||
export function getOperationRequestBody(openApi: OpenApi, parameter: OpenApiRequestBody): OperationParameter {
|
||||
const requestBody: OperationParameter = {
|
||||
in: 'body',
|
||||
prop: 'body',
|
||||
export: 'interface',
|
||||
name: 'requestBody',
|
||||
type: PrimaryType.OBJECT,
|
||||
base: PrimaryType.OBJECT,
|
||||
template: null,
|
||||
link: null,
|
||||
description: getComment(parameter.description),
|
||||
default: undefined,
|
||||
isProperty: false,
|
||||
isReadOnly: false,
|
||||
isRequired: parameter.required === true,
|
||||
isNullable: false,
|
||||
imports: [],
|
||||
extends: [],
|
||||
enum: [],
|
||||
enums: [],
|
||||
properties: [],
|
||||
};
|
||||
|
||||
if (parameter.content) {
|
||||
const schema = getContent(openApi, parameter.content);
|
||||
if (schema) {
|
||||
if (schema && schema.$ref) {
|
||||
const model = getType(schema.$ref);
|
||||
requestBody.export = 'reference';
|
||||
requestBody.type = model.type;
|
||||
requestBody.base = model.base;
|
||||
requestBody.template = model.template;
|
||||
requestBody.imports.push(...model.imports);
|
||||
} else {
|
||||
const model = getModel(openApi, schema);
|
||||
requestBody.export = model.export;
|
||||
requestBody.type = model.type;
|
||||
requestBody.base = model.base;
|
||||
requestBody.template = model.template;
|
||||
requestBody.link = model.link;
|
||||
requestBody.imports.push(...model.imports);
|
||||
requestBody.extends.push(...model.extends);
|
||||
requestBody.enum.push(...model.enum);
|
||||
requestBody.enums.push(...model.enums);
|
||||
requestBody.properties.push(...model.properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requestBody;
|
||||
}
|
||||
@ -3,6 +3,9 @@ import { OpenApiResponse } from '../interfaces/OpenApiResponse';
|
||||
import { OperationResponse } from '../../../client/interfaces/OperationResponse';
|
||||
import { PrimaryType } from './constants';
|
||||
import { getComment } from './getComment';
|
||||
import { getContent } from './getContent';
|
||||
import { getModel } from './getModel';
|
||||
import { getType } from './getType';
|
||||
|
||||
export function getOperationResponse(openApi: OpenApi, response: OpenApiResponse, responseCode: number): OperationResponse {
|
||||
const operationResponse: OperationResponse = {
|
||||
@ -25,33 +28,31 @@ export function getOperationResponse(openApi: OpenApi, response: OpenApiResponse
|
||||
properties: [],
|
||||
};
|
||||
|
||||
// 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) {
|
||||
// if (response.schema.$ref) {
|
||||
// const model = getType(response.schema.$ref);
|
||||
// operationResponse.export = 'reference';
|
||||
// operationResponse.type = model.type;
|
||||
// operationResponse.base = model.base;
|
||||
// operationResponse.template = model.template;
|
||||
// operationResponse.imports.push(...model.imports);
|
||||
// } else {
|
||||
// const model = getModel(openApi, response.schema);
|
||||
// operationResponse.export = model.export;
|
||||
// operationResponse.type = model.type;
|
||||
// operationResponse.base = model.base;
|
||||
// operationResponse.template = model.template;
|
||||
// operationResponse.link = model.link;
|
||||
// operationResponse.imports.push(...model.imports);
|
||||
// operationResponse.extends.push(...model.extends);
|
||||
// operationResponse.enum.push(...model.enum);
|
||||
// operationResponse.enums.push(...model.enums);
|
||||
// operationResponse.properties.push(...model.properties);
|
||||
// }
|
||||
// }
|
||||
if (response.content) {
|
||||
const schema = getContent(openApi, response.content);
|
||||
if (schema) {
|
||||
if (schema && schema.$ref) {
|
||||
const model = getType(schema.$ref);
|
||||
operationResponse.export = 'reference';
|
||||
operationResponse.type = model.type;
|
||||
operationResponse.base = model.base;
|
||||
operationResponse.template = model.template;
|
||||
operationResponse.imports.push(...model.imports);
|
||||
} else {
|
||||
const model = getModel(openApi, schema);
|
||||
operationResponse.export = model.export;
|
||||
operationResponse.type = model.type;
|
||||
operationResponse.base = model.base;
|
||||
operationResponse.template = model.template;
|
||||
operationResponse.link = model.link;
|
||||
operationResponse.imports.push(...model.imports);
|
||||
operationResponse.extends.push(...model.extends);
|
||||
operationResponse.enum.push(...model.enum);
|
||||
operationResponse.enums.push(...model.enums);
|
||||
operationResponse.properties.push(...model.properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return operationResponse;
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import {PrimaryType} from './constants';
|
||||
import {Type} from '../../../client/interfaces/Type';
|
||||
import {getMappedType, hasMappedType} from './getMappedType';
|
||||
import {stripNamespace} from './stripNamespace';
|
||||
import { PrimaryType } from './constants';
|
||||
import { Type } from '../../../client/interfaces/Type';
|
||||
import { getMappedType, hasMappedType } from './getMappedType';
|
||||
import { stripNamespace } from './stripNamespace';
|
||||
|
||||
/**
|
||||
* Parse any string value into a type object.
|
||||
|
||||
@ -10,7 +10,7 @@ export interface {{{name}}}{{#if extends}} extends {{#each extends}}{{{this}}}{{
|
||||
* {{{description}}}
|
||||
*/
|
||||
{{/if}}
|
||||
{{#if readOnly}}readonly {{/if}}{{{name}}}{{#unless isRequired}}?{{/unless}}: {{>type parent=../name}}{{#if isNullable}} | null{{/if}};
|
||||
{{#if isReadOnly}}readonly {{/if}}{{{name}}}{{#unless isRequired}}?{{/unless}}: {{>type parent=../name}}{{#if isNullable}} | null{{/if}};
|
||||
{{/each}}
|
||||
}
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
* {{{description}}}
|
||||
*/
|
||||
{{/if}}
|
||||
{{#if readOnly}}readonly {{/if}}{{{name}}}{{#unless isRequired}}?{{/unless}}: {{>type}}{{#if isNullable}} | null{{/if}}{{#unless @last}},{{/unless}}
|
||||
{{#if isReadOnly}}readonly {{/if}}{{{name}}}{{#unless isRequired}}?{{/unless}}: {{>type}}{{#if isNullable}} | null{{/if}}{{#unless @last}},{{/unless}}
|
||||
{{/each}}
|
||||
}
|
||||
{{~else~}}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,19 @@
|
||||
const OpenAPI = require('../dist');
|
||||
|
||||
OpenAPI.generate(
|
||||
'./test/mock/spec-v2.json',
|
||||
'./test/result/v2/typescript/',
|
||||
OpenAPI.Language.TYPESCRIPT,
|
||||
OpenAPI.HttpClient.FETCH,
|
||||
);
|
||||
|
||||
OpenAPI.generate(
|
||||
'./test/mock/spec-v2.json',
|
||||
'./test/result/v2/javascript/',
|
||||
OpenAPI.Language.JAVASCRIPT,
|
||||
OpenAPI.HttpClient.XHR,
|
||||
);
|
||||
|
||||
OpenAPI.generate(
|
||||
'./test/mock/spec-v3.json',
|
||||
'./test/result/v3/typescript/',
|
||||
@ -7,18 +21,12 @@ OpenAPI.generate(
|
||||
OpenAPI.HttpClient.FETCH,
|
||||
);
|
||||
|
||||
// OpenAPI.generate(
|
||||
// './test/mock/spec-v2.json',
|
||||
// './test/result/v2/typescript/',
|
||||
// OpenAPI.Language.TYPESCRIPT,
|
||||
// OpenAPI.HttpClient.FETCH,
|
||||
// );
|
||||
OpenAPI.generate(
|
||||
'./test/mock/spec-v3.json',
|
||||
'./test/result/v3/javascript/',
|
||||
OpenAPI.Language.JAVASCRIPT,
|
||||
OpenAPI.HttpClient.XHR,
|
||||
);
|
||||
|
||||
// OpenAPI.generate(
|
||||
// './test/mock/spec-v2.json',
|
||||
// './test/result/v2/javascript/',
|
||||
// OpenAPI.Language.JAVASCRIPT,
|
||||
// OpenAPI.HttpClient.XHR,
|
||||
// );
|
||||
|
||||
// OpenAPI.compile('./test/result/v2/typescript/');
|
||||
OpenAPI.compile('./test/result/v2/typescript/');
|
||||
OpenAPI.compile('./test/result/v3/typescript/');
|
||||
|
||||
@ -618,18 +618,59 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"ModelWithProperties": {
|
||||
"description": "This is a model with one nested property",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"required",
|
||||
"requiredAndreadOnly"
|
||||
],
|
||||
"properties": {
|
||||
"required": {
|
||||
"type": "string"
|
||||
},
|
||||
"requiredAndreadOnly": {
|
||||
"type": "string",
|
||||
"readOnly": true
|
||||
},
|
||||
"string": {
|
||||
"type": "string"
|
||||
},
|
||||
"number": {
|
||||
"type": "number"
|
||||
},
|
||||
"boolean": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"reference": {
|
||||
"$ref": "#/definitions/ModelWithString"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ModelWithNestedProperties": {
|
||||
"description": "This is a model with one nested property",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"first"
|
||||
],
|
||||
"properties": {
|
||||
"first": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"second"
|
||||
],
|
||||
"readOnly": true,
|
||||
"properties": {
|
||||
"second": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"third"
|
||||
],
|
||||
"readOnly": true,
|
||||
"properties": {
|
||||
"third": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"readOnly": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user