mirror of
https://github.com/ferdikoomen/openapi-typescript-codegen.git
synced 2025-12-08 20:16:21 +00:00
- Added service generation test cases
- Cleanup of models - Cleanup of comma generatiom - Formatted results
This commit is contained in:
parent
20209f7aa2
commit
fbd354ebfb
17
src/client/interfaces/Model.d.ts
vendored
17
src/client/interfaces/Model.d.ts
vendored
@ -1,17 +1,12 @@
|
||||
import { Enum } from './Enum';
|
||||
import { Schema } from './Schema';
|
||||
|
||||
export interface Model {
|
||||
export interface Model extends Schema {
|
||||
name: string;
|
||||
export: 'reference' | 'generic' | 'enum' | 'array' | 'dictionary' | 'interface';
|
||||
type: string;
|
||||
base: string;
|
||||
template: string | null;
|
||||
link: Model | null;
|
||||
description: string | null;
|
||||
readOnly: boolean;
|
||||
required: boolean;
|
||||
nullable: boolean;
|
||||
imports: string[];
|
||||
isProperty: boolean;
|
||||
isReadOnly: boolean;
|
||||
isRequired: boolean;
|
||||
isNullable: boolean;
|
||||
extends: string[];
|
||||
enum: Enum[];
|
||||
enums: Model[];
|
||||
|
||||
3
src/client/interfaces/Operation.d.ts
vendored
3
src/client/interfaces/Operation.d.ts
vendored
@ -1,5 +1,6 @@
|
||||
import { OperationError } from './OperationError';
|
||||
import { OperationParameters } from './OperationParameters';
|
||||
import { OperationResponse } from './OperationResponse';
|
||||
|
||||
export interface Operation extends OperationParameters {
|
||||
service: string;
|
||||
@ -10,5 +11,5 @@ export interface Operation extends OperationParameters {
|
||||
method: string;
|
||||
path: string;
|
||||
errors: OperationError[];
|
||||
result: string;
|
||||
results: OperationResponse[];
|
||||
}
|
||||
|
||||
2
src/client/interfaces/OperationError.d.ts
vendored
2
src/client/interfaces/OperationError.d.ts
vendored
@ -1,4 +1,4 @@
|
||||
export interface OperationError {
|
||||
code: number;
|
||||
text: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
17
src/client/interfaces/OperationParameter.d.ts
vendored
17
src/client/interfaces/OperationParameter.d.ts
vendored
@ -1,19 +1,12 @@
|
||||
import { Model } from './Model';
|
||||
import { Enum } from './Enum';
|
||||
import { Schema } from './Schema';
|
||||
|
||||
export interface OperationParameter {
|
||||
export interface OperationParameter extends Schema {
|
||||
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;
|
||||
isRequired: boolean;
|
||||
isNullable: boolean;
|
||||
enum: Enum[];
|
||||
}
|
||||
|
||||
9
src/client/interfaces/OperationResponse.d.ts
vendored
9
src/client/interfaces/OperationResponse.d.ts
vendored
@ -1,8 +1,5 @@
|
||||
export interface OperationResponse {
|
||||
import { Schema } from './Schema';
|
||||
|
||||
export interface OperationResponse extends Schema {
|
||||
code: number;
|
||||
text: string;
|
||||
type: string;
|
||||
base: string;
|
||||
template: string | null;
|
||||
imports: string[];
|
||||
}
|
||||
|
||||
11
src/client/interfaces/Schema.ts
Normal file
11
src/client/interfaces/Schema.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { Model } from './Model';
|
||||
|
||||
export interface Schema {
|
||||
export: 'reference' | 'generic' | 'enum' | 'array' | 'dictionary' | 'interface';
|
||||
type: string;
|
||||
base: string;
|
||||
template: string | null;
|
||||
link: Model | null;
|
||||
description: string | null;
|
||||
imports: string[];
|
||||
}
|
||||
6
src/client/interfaces/Validation.d.ts
vendored
6
src/client/interfaces/Validation.d.ts
vendored
@ -1,6 +0,0 @@
|
||||
export interface Validation {
|
||||
type: 'ref' | 'type' | 'enum' | 'array' | 'dictionary' | 'properties';
|
||||
childType: string | null;
|
||||
childBase: string | null;
|
||||
childValidation: Validation | null;
|
||||
}
|
||||
@ -3,6 +3,7 @@ import { Client } from '../../client/interfaces/Client';
|
||||
import { getServer } from './parser/getServer';
|
||||
import { getServices } from './parser/getServices';
|
||||
import { getModels } from './parser/getModels';
|
||||
import { getServiceVersion } from './parser/getServiceVersion';
|
||||
|
||||
/**
|
||||
* Parse the OpenAPI specification to a Client model that contains
|
||||
@ -11,7 +12,7 @@ import { getModels } from './parser/getModels';
|
||||
*/
|
||||
export function parse(openApi: OpenApi): Client {
|
||||
return {
|
||||
version: openApi.info.version,
|
||||
version: getServiceVersion(openApi.info.version),
|
||||
server: getServer(openApi),
|
||||
models: getModels(openApi),
|
||||
services: getServices(openApi),
|
||||
|
||||
@ -9,18 +9,19 @@ import { getEnum } from './getEnum';
|
||||
import { getEnumFromDescription } from './getEnumFromDescription';
|
||||
import { getModelProperties } from './getModelProperties';
|
||||
|
||||
export function getModel(openApi: OpenApi, definition: OpenApiSchema, name: string = ''): Model {
|
||||
const result: Model = {
|
||||
name,
|
||||
export function getModel(openApi: OpenApi, definition: OpenApiSchema, isProperty: boolean = false, name: string = ''): Model {
|
||||
const model: Model = {
|
||||
name: name,
|
||||
export: 'interface',
|
||||
type: PrimaryType.OBJECT,
|
||||
base: PrimaryType.OBJECT,
|
||||
template: null,
|
||||
link: null,
|
||||
description: getComment(definition.description),
|
||||
readOnly: definition.readOnly || false,
|
||||
required: false,
|
||||
nullable: false,
|
||||
isProperty: isProperty,
|
||||
isReadOnly: definition.readOnly || false,
|
||||
isRequired: false,
|
||||
isNullable: false,
|
||||
imports: [],
|
||||
extends: [],
|
||||
enum: [],
|
||||
@ -30,97 +31,99 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, name: stri
|
||||
|
||||
if (definition.$ref) {
|
||||
const definitionRef = getType(definition.$ref);
|
||||
result.export = 'reference';
|
||||
result.type = definitionRef.type;
|
||||
result.base = definitionRef.base;
|
||||
result.template = definitionRef.template;
|
||||
result.imports.push(...definitionRef.imports);
|
||||
return result;
|
||||
model.export = 'reference';
|
||||
model.type = definitionRef.type;
|
||||
model.base = definitionRef.base;
|
||||
model.template = definitionRef.template;
|
||||
model.imports.push(...definitionRef.imports);
|
||||
return model;
|
||||
}
|
||||
|
||||
if (definition.enum) {
|
||||
const enumerators = getEnum(definition.enum);
|
||||
if (enumerators.length) {
|
||||
result.export = 'enum';
|
||||
result.type = getEnumType(enumerators);
|
||||
result.base = PrimaryType.STRING;
|
||||
result.enum.push(...enumerators);
|
||||
return result;
|
||||
model.export = 'enum';
|
||||
model.type = getEnumType(enumerators);
|
||||
model.base = PrimaryType.STRING;
|
||||
model.enum.push(...enumerators);
|
||||
return model;
|
||||
}
|
||||
}
|
||||
|
||||
if ((definition.type === 'int' || definition.type === 'integer') && definition.description) {
|
||||
const enumerators = getEnumFromDescription(definition.description);
|
||||
if (enumerators.length) {
|
||||
result.export = 'enum';
|
||||
result.type = getEnumType(enumerators);
|
||||
result.base = PrimaryType.NUMBER;
|
||||
result.enum.push(...enumerators);
|
||||
return result;
|
||||
model.export = 'enum';
|
||||
model.type = getEnumType(enumerators);
|
||||
model.base = PrimaryType.NUMBER;
|
||||
model.enum.push(...enumerators);
|
||||
return model;
|
||||
}
|
||||
}
|
||||
|
||||
if (definition.type === 'array' && definition.items) {
|
||||
if (definition.items.$ref) {
|
||||
const arrayItems = getType(definition.items.$ref);
|
||||
result.export = 'array';
|
||||
result.type = arrayItems.type;
|
||||
result.base = arrayItems.base;
|
||||
result.template = arrayItems.template;
|
||||
result.imports.push(...arrayItems.imports);
|
||||
model.export = 'array';
|
||||
model.type = arrayItems.type;
|
||||
model.base = arrayItems.base;
|
||||
model.template = arrayItems.template;
|
||||
model.imports.push(...arrayItems.imports);
|
||||
return model;
|
||||
} else {
|
||||
const arrayItems = getModel(openApi, definition.items);
|
||||
result.export = 'array';
|
||||
result.type = arrayItems.type;
|
||||
result.base = arrayItems.base;
|
||||
result.template = arrayItems.template;
|
||||
result.link = arrayItems;
|
||||
result.imports.push(...arrayItems.imports);
|
||||
const arrayItems = getModel(openApi, definition.items, true);
|
||||
model.export = 'array';
|
||||
model.type = arrayItems.type;
|
||||
model.base = arrayItems.base;
|
||||
model.template = arrayItems.template;
|
||||
model.link = arrayItems;
|
||||
model.imports.push(...arrayItems.imports);
|
||||
return model;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
if (definition.type === 'object' && definition.additionalProperties && typeof definition.additionalProperties === 'object') {
|
||||
if (definition.additionalProperties.$ref) {
|
||||
const additionalProperties = getType(definition.additionalProperties.$ref);
|
||||
result.export = 'dictionary';
|
||||
result.type = additionalProperties.type;
|
||||
result.base = additionalProperties.base;
|
||||
result.template = additionalProperties.template;
|
||||
result.imports.push(...additionalProperties.imports);
|
||||
result.imports.push('Dictionary');
|
||||
model.export = 'dictionary';
|
||||
model.type = additionalProperties.type;
|
||||
model.base = additionalProperties.base;
|
||||
model.template = additionalProperties.template;
|
||||
model.imports.push(...additionalProperties.imports);
|
||||
model.imports.push('Dictionary');
|
||||
return model;
|
||||
} else {
|
||||
const additionalProperties = getModel(openApi, definition.additionalProperties);
|
||||
result.export = 'dictionary';
|
||||
result.type = additionalProperties.type;
|
||||
result.base = additionalProperties.base;
|
||||
result.template = additionalProperties.template;
|
||||
result.link = additionalProperties;
|
||||
result.imports.push(...additionalProperties.imports);
|
||||
result.imports.push('Dictionary');
|
||||
model.export = 'dictionary';
|
||||
model.type = additionalProperties.type;
|
||||
model.base = additionalProperties.base;
|
||||
model.template = additionalProperties.template;
|
||||
model.link = additionalProperties;
|
||||
model.imports.push(...additionalProperties.imports);
|
||||
model.imports.push('Dictionary');
|
||||
return model;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
if (definition.type === 'object') {
|
||||
result.export = 'interface';
|
||||
result.type = PrimaryType.OBJECT;
|
||||
result.base = PrimaryType.OBJECT;
|
||||
model.export = 'interface';
|
||||
model.type = PrimaryType.OBJECT;
|
||||
model.base = PrimaryType.OBJECT;
|
||||
|
||||
if (definition.allOf) {
|
||||
definition.allOf.forEach(parent => {
|
||||
if (parent.$ref) {
|
||||
const parentRef = getType(parent.$ref);
|
||||
result.extends.push(parentRef.type);
|
||||
result.imports.push(parentRef.base);
|
||||
model.extends.push(parentRef.type);
|
||||
model.imports.push(parentRef.base);
|
||||
}
|
||||
if (parent.type === 'object' && parent.properties) {
|
||||
const properties = getModelProperties(openApi, parent);
|
||||
properties.forEach(property => {
|
||||
result.properties.push(property);
|
||||
result.imports.push(...property.imports);
|
||||
model.properties.push(property);
|
||||
model.imports.push(...property.imports);
|
||||
if (property.export === 'enum') {
|
||||
result.enums.push(property);
|
||||
model.enums.push(property);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -130,27 +133,27 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, name: stri
|
||||
if (definition.properties) {
|
||||
const properties = getModelProperties(openApi, definition);
|
||||
properties.forEach(property => {
|
||||
result.properties.push(property);
|
||||
result.imports.push(...property.imports);
|
||||
model.properties.push(property);
|
||||
model.imports.push(...property.imports);
|
||||
if (property.export === 'enum') {
|
||||
result.enums.push(property);
|
||||
model.enums.push(property);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
return model;
|
||||
}
|
||||
|
||||
// If the schema has a type than it can be a basic or generic type.
|
||||
if (definition.type) {
|
||||
const definitionType = getType(definition.type);
|
||||
result.export = 'generic';
|
||||
result.type = definitionType.type;
|
||||
result.base = definitionType.base;
|
||||
result.template = definitionType.template;
|
||||
result.imports.push(...definitionType.imports);
|
||||
return result;
|
||||
model.export = 'generic';
|
||||
model.type = definitionType.type;
|
||||
model.base = definitionType.base;
|
||||
model.template = definitionType.template;
|
||||
model.imports.push(...definitionType.imports);
|
||||
return model;
|
||||
}
|
||||
|
||||
return result;
|
||||
return model;
|
||||
}
|
||||
|
||||
@ -6,53 +6,55 @@ import { Model } from '../../../client/interfaces/Model';
|
||||
import { getModel } from './getModel';
|
||||
|
||||
export function getModelProperties(openApi: OpenApi, definition: OpenApiSchema): Model[] {
|
||||
const result: Model[] = [];
|
||||
const models: Model[] = [];
|
||||
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;
|
||||
if (property.$ref) {
|
||||
const prop = getType(property.$ref);
|
||||
result.push({
|
||||
const model = getType(property.$ref);
|
||||
models.push({
|
||||
name: propertyName,
|
||||
export: 'reference',
|
||||
type: prop.type,
|
||||
base: prop.base,
|
||||
template: prop.template,
|
||||
type: model.type,
|
||||
base: model.base,
|
||||
template: model.template,
|
||||
link: null,
|
||||
description: getComment(property.description),
|
||||
readOnly: propertyReadOnly,
|
||||
required: propertyRequired,
|
||||
nullable: false,
|
||||
imports: prop.imports,
|
||||
isProperty: true,
|
||||
isReadOnly: propertyReadOnly,
|
||||
isRequired: propertyRequired,
|
||||
isNullable: false,
|
||||
imports: model.imports,
|
||||
extends: [],
|
||||
enum: [],
|
||||
enums: [],
|
||||
properties: [],
|
||||
});
|
||||
} else {
|
||||
const prop = getModel(openApi, property);
|
||||
result.push({
|
||||
const model = getModel(openApi, property);
|
||||
models.push({
|
||||
name: propertyName,
|
||||
export: prop.export,
|
||||
type: prop.type,
|
||||
base: prop.base,
|
||||
template: prop.template,
|
||||
link: prop.link,
|
||||
export: model.export,
|
||||
type: model.type,
|
||||
base: model.base,
|
||||
template: model.template,
|
||||
link: model.link,
|
||||
description: getComment(property.description),
|
||||
readOnly: propertyReadOnly,
|
||||
required: propertyRequired,
|
||||
nullable: false,
|
||||
imports: prop.imports,
|
||||
extends: prop.extends,
|
||||
enum: prop.enum,
|
||||
enums: prop.enums,
|
||||
properties: prop.properties,
|
||||
isProperty: true,
|
||||
isReadOnly: propertyReadOnly,
|
||||
isRequired: propertyRequired,
|
||||
isNullable: false,
|
||||
imports: model.imports,
|
||||
extends: model.extends,
|
||||
enum: model.enum,
|
||||
enums: model.enums,
|
||||
properties: model.properties,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return models;
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@ export function getModels(openApi: OpenApi): Map<string, Model> {
|
||||
if (openApi.definitions.hasOwnProperty(definitionName)) {
|
||||
const definition = openApi.definitions[definitionName];
|
||||
const definitionType = getType(definitionName);
|
||||
const model = getModel(openApi, definition, definitionType.base);
|
||||
const model = getModel(openApi, definition, false, definitionType.base);
|
||||
models.set(definitionType.base, model);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,10 +6,9 @@ import { getOperationPath } from './getOperationPath';
|
||||
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 { getOperationResults } from './getOperationResults';
|
||||
import { getOperationErrors } from './getOperationErrors';
|
||||
|
||||
export function getOperation(openApi: OpenApi, url: string, method: string, op: OpenApiOperation): Operation {
|
||||
@ -20,7 +19,7 @@ export function getOperation(openApi: OpenApi, url: string, method: string, op:
|
||||
const operationPath = getOperationPath(url);
|
||||
|
||||
// Create a new operation object for this method.
|
||||
const result: Operation = {
|
||||
const operation: Operation = {
|
||||
service: serviceClassName,
|
||||
name: operationName,
|
||||
summary: getComment(op.summary),
|
||||
@ -36,30 +35,31 @@ export function getOperation(openApi: OpenApi, url: string, method: string, op:
|
||||
parametersBody: null,
|
||||
imports: [],
|
||||
errors: [],
|
||||
result: PrimaryType.VOID,
|
||||
results: [],
|
||||
};
|
||||
|
||||
// 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;
|
||||
operation.imports.push(...parameters.imports);
|
||||
operation.parameters.push(...parameters.parameters);
|
||||
operation.parametersPath.push(...parameters.parametersPath);
|
||||
operation.parametersQuery.push(...parameters.parametersQuery);
|
||||
operation.parametersForm.push(...parameters.parametersForm);
|
||||
operation.parametersHeader.push(...parameters.parametersHeader);
|
||||
operation.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 operationResponses = getOperationResponses(openApi, op.responses);
|
||||
const operationResults = getOperationResults(operationResponses);
|
||||
operation.errors = getOperationErrors(operationResponses);
|
||||
operationResults.forEach(operationResult => {
|
||||
operation.results.push(operationResult);
|
||||
operation.imports.push(...operationResult.imports);
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
return operation;
|
||||
}
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import { OperationResponse } from '../../../client/interfaces/OperationResponse';
|
||||
import { OperationError } from '../../../client/interfaces/OperationError';
|
||||
|
||||
export function getOperationErrors(responses: OperationResponse[]): OperationError[] {
|
||||
return responses
|
||||
.filter(response => {
|
||||
return response.code >= 300 && response.text !== undefined && response.text !== '';
|
||||
export function getOperationErrors(operationResponses: OperationResponse[]): OperationError[] {
|
||||
return operationResponses
|
||||
.filter(operationResponse => {
|
||||
return operationResponse.code >= 300 && operationResponse.description;
|
||||
})
|
||||
.map(response => ({
|
||||
code: response.code,
|
||||
text: response.text,
|
||||
description: response.description!,
|
||||
}));
|
||||
}
|
||||
|
||||
@ -11,95 +11,106 @@ import { getEnumFromDescription } from './getEnumFromDescription';
|
||||
import { getModel } from './getModel';
|
||||
|
||||
export function getOperationParameter(openApi: OpenApi, parameter: OpenApiParameter): OperationParameter {
|
||||
const result: OperationParameter = {
|
||||
const operationParameter: OperationParameter = {
|
||||
in: parameter.in,
|
||||
prop: parameter.name,
|
||||
name: getOperationParameterName(parameter.name),
|
||||
export: 'interface',
|
||||
name: getOperationParameterName(parameter.name),
|
||||
type: PrimaryType.OBJECT,
|
||||
base: PrimaryType.OBJECT,
|
||||
template: null,
|
||||
link: null,
|
||||
description: getComment(parameter.description),
|
||||
required: parameter.required || false,
|
||||
nullable: false,
|
||||
default: parameter.default,
|
||||
isRequired: parameter.required || false,
|
||||
isNullable: false,
|
||||
imports: [],
|
||||
enum: [],
|
||||
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;
|
||||
operationParameter.export = 'reference';
|
||||
operationParameter.type = definitionRef.type;
|
||||
operationParameter.base = definitionRef.base;
|
||||
operationParameter.template = definitionRef.template;
|
||||
operationParameter.imports.push(...definitionRef.imports);
|
||||
return operationParameter;
|
||||
}
|
||||
|
||||
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;
|
||||
operationParameter.export = 'enum';
|
||||
operationParameter.type = getEnumType(enumerators);
|
||||
operationParameter.base = PrimaryType.STRING;
|
||||
operationParameter.enum.push(...enumerators);
|
||||
return operationParameter;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
operationParameter.export = 'enum';
|
||||
operationParameter.type = getEnumType(enumerators);
|
||||
operationParameter.base = PrimaryType.NUMBER;
|
||||
operationParameter.enum.push(...enumerators);
|
||||
return operationParameter;
|
||||
}
|
||||
}
|
||||
|
||||
// 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.type === 'array' && parameter.items) {
|
||||
const items = getType(parameter.items.type);
|
||||
operationParameter.export = 'array';
|
||||
operationParameter.type = items.type;
|
||||
operationParameter.base = items.base;
|
||||
operationParameter.template = items.template;
|
||||
operationParameter.imports.push(...items.imports);
|
||||
return operationParameter;
|
||||
}
|
||||
|
||||
if (parameter.type === 'object' && parameter.items) {
|
||||
const items = getType(parameter.items.type);
|
||||
operationParameter.export = 'dictionary';
|
||||
operationParameter.type = items.type;
|
||||
operationParameter.base = items.base;
|
||||
operationParameter.template = items.template;
|
||||
operationParameter.imports.push(...items.imports);
|
||||
return operationParameter;
|
||||
}
|
||||
|
||||
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);
|
||||
operationParameter.export = 'reference';
|
||||
operationParameter.type = model.type;
|
||||
operationParameter.base = model.base;
|
||||
operationParameter.template = model.template;
|
||||
operationParameter.imports.push(...model.imports);
|
||||
return operationParameter;
|
||||
} 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;
|
||||
operationParameter.export = 'interface';
|
||||
operationParameter.type = model.type;
|
||||
operationParameter.base = model.base;
|
||||
operationParameter.template = model.template;
|
||||
operationParameter.imports.push(...model.imports);
|
||||
operationParameter.link = model;
|
||||
return operationParameter;
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
operationParameter.export = 'generic';
|
||||
operationParameter.type = definitionType.type;
|
||||
operationParameter.base = definitionType.base;
|
||||
operationParameter.template = definitionType.template;
|
||||
operationParameter.imports.push(...definitionType.imports);
|
||||
return operationParameter;
|
||||
}
|
||||
|
||||
return result;
|
||||
return operationParameter;
|
||||
}
|
||||
|
||||
@ -6,11 +6,11 @@ import { OperationParameter } from '../../../client/interfaces/OperationParamete
|
||||
import { getOperationParameter } from './getOperationParameter';
|
||||
|
||||
function sortByRequired(a: OperationParameter, b: OperationParameter): number {
|
||||
return a.required && !b.required ? -1 : !a.required && b.required ? 1 : 0;
|
||||
return a.isRequired && !b.isRequired ? -1 : !a.isRequired && b.isRequired ? 1 : 0;
|
||||
}
|
||||
|
||||
export function getOperationParameters(openApi: OpenApi, parameters: OpenApiParameter[]): OperationParameters {
|
||||
const result: OperationParameters = {
|
||||
const operationParameters: OperationParameters = {
|
||||
imports: [],
|
||||
parameters: [],
|
||||
parametersPath: [],
|
||||
@ -30,42 +30,42 @@ export function getOperationParameters(openApi: OpenApi, parameters: OpenApiPara
|
||||
if (param.prop !== 'api-version') {
|
||||
switch (parameter.in) {
|
||||
case 'path':
|
||||
result.parametersPath.push(param);
|
||||
result.parameters.push(param);
|
||||
result.imports.push(...param.imports);
|
||||
operationParameters.parametersPath.push(param);
|
||||
operationParameters.parameters.push(param);
|
||||
operationParameters.imports.push(...param.imports);
|
||||
break;
|
||||
|
||||
case 'query':
|
||||
result.parametersQuery.push(param);
|
||||
result.parameters.push(param);
|
||||
result.imports.push(...param.imports);
|
||||
operationParameters.parametersQuery.push(param);
|
||||
operationParameters.parameters.push(param);
|
||||
operationParameters.imports.push(...param.imports);
|
||||
break;
|
||||
|
||||
case 'header':
|
||||
result.parametersHeader.push(param);
|
||||
result.parameters.push(param);
|
||||
result.imports.push(...param.imports);
|
||||
operationParameters.parametersHeader.push(param);
|
||||
operationParameters.parameters.push(param);
|
||||
operationParameters.imports.push(...param.imports);
|
||||
break;
|
||||
|
||||
case 'formData':
|
||||
result.parametersForm.push(param);
|
||||
result.parameters.push(param);
|
||||
result.imports.push(...param.imports);
|
||||
operationParameters.parametersForm.push(param);
|
||||
operationParameters.parameters.push(param);
|
||||
operationParameters.imports.push(...param.imports);
|
||||
break;
|
||||
|
||||
case 'body':
|
||||
result.parametersBody = param;
|
||||
result.parameters.push(param);
|
||||
result.imports.push(...param.imports);
|
||||
operationParameters.parametersBody = param;
|
||||
operationParameters.parameters.push(param);
|
||||
operationParameters.imports.push(...param.imports);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
result.parameters = result.parameters.sort(sortByRequired);
|
||||
result.parametersPath = result.parametersPath.sort(sortByRequired);
|
||||
result.parametersQuery = result.parametersQuery.sort(sortByRequired);
|
||||
result.parametersForm = result.parametersForm.sort(sortByRequired);
|
||||
result.parametersHeader = result.parametersHeader.sort(sortByRequired);
|
||||
return result;
|
||||
operationParameters.parameters = operationParameters.parameters.sort(sortByRequired);
|
||||
operationParameters.parametersPath = operationParameters.parametersPath.sort(sortByRequired);
|
||||
operationParameters.parametersQuery = operationParameters.parametersQuery.sort(sortByRequired);
|
||||
operationParameters.parametersForm = operationParameters.parametersForm.sort(sortByRequired);
|
||||
operationParameters.parametersHeader = operationParameters.parametersHeader.sort(sortByRequired);
|
||||
return operationParameters;
|
||||
}
|
||||
|
||||
@ -1,19 +0,0 @@
|
||||
import { PrimaryType } from './constants';
|
||||
import { OperationResponse } from '../../../client/interfaces/OperationResponse';
|
||||
|
||||
export function getOperationResponse(responses: OperationResponse[]): OperationResponse {
|
||||
// Fetch the first valid (2XX range) response code and return that type.
|
||||
const result = responses.find(response => response.code && response.code >= 200 && response.code < 300);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return {
|
||||
code: 200,
|
||||
text: '',
|
||||
type: PrimaryType.OBJECT,
|
||||
base: PrimaryType.OBJECT,
|
||||
template: null,
|
||||
imports: [],
|
||||
};
|
||||
}
|
||||
@ -6,9 +6,11 @@ import { OpenApi } from '../interfaces/OpenApi';
|
||||
import { OperationResponse } from '../../../client/interfaces/OperationResponse';
|
||||
import { getType } from './getType';
|
||||
import { getModel } from './getModel';
|
||||
import { getComment } from './getComment';
|
||||
import { PrimaryType } from './constants';
|
||||
|
||||
export function getOperationResponses(openApi: OpenApi, responses: OpenApiResponses): OperationResponse[] {
|
||||
const results: OperationResponse[] = [];
|
||||
const operationResponses: OperationResponse[] = [];
|
||||
|
||||
// Iterate over each response code and get the
|
||||
// status code and response message (if any).
|
||||
@ -22,12 +24,14 @@ export function getOperationResponses(openApi: OpenApi, responses: OpenApiRespon
|
||||
// if there is no typed data, we just return <any> so the user is still
|
||||
// free to do their own casting if needed.
|
||||
if (responseCode) {
|
||||
const result: OperationResponse = {
|
||||
const operationResponse: OperationResponse = {
|
||||
code: responseCode,
|
||||
text: response.description || '',
|
||||
type: 'any',
|
||||
base: 'any',
|
||||
description: getComment(response.description)!,
|
||||
export: 'generic',
|
||||
type: PrimaryType.OBJECT,
|
||||
base: PrimaryType.OBJECT,
|
||||
template: null,
|
||||
link: null,
|
||||
imports: [],
|
||||
};
|
||||
|
||||
@ -38,26 +42,29 @@ export function getOperationResponses(openApi: OpenApi, responses: OpenApiRespon
|
||||
if (response.schema) {
|
||||
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);
|
||||
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);
|
||||
result.type = model.type;
|
||||
result.base = model.base;
|
||||
result.template = model.template;
|
||||
result.imports.push(...model.imports);
|
||||
operationResponse.export = model.export;
|
||||
operationResponse.type = model.type;
|
||||
operationResponse.base = model.base;
|
||||
operationResponse.template = model.template;
|
||||
operationResponse.imports.push(...model.imports);
|
||||
operationResponse.link = model;
|
||||
}
|
||||
}
|
||||
|
||||
results.push(result);
|
||||
operationResponses.push(operationResponse);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort the responses to 2XX success codes come before 4XX and 5XX error codes.
|
||||
return results.sort((a, b): number => {
|
||||
return operationResponses.sort((a, b): number => {
|
||||
return a.code < b.code ? -1 : a.code > b.code ? 1 : 0;
|
||||
});
|
||||
}
|
||||
|
||||
38
src/openApi/v2/parser/getOperationResults.ts
Normal file
38
src/openApi/v2/parser/getOperationResults.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import { PrimaryType } from './constants';
|
||||
import { OperationResponse } from '../../../client/interfaces/OperationResponse';
|
||||
import { Schema } from '../../../client/interfaces/Schema';
|
||||
|
||||
function areEqual(a: Schema, b: Schema): boolean {
|
||||
return a.type === b.type && a.base === b.base && a.template === b.template;
|
||||
}
|
||||
|
||||
export function getOperationResults(operationResponses: OperationResponse[]): OperationResponse[] {
|
||||
const operationResults: OperationResponse[] = [];
|
||||
|
||||
operationResponses.forEach(operationResponse => {
|
||||
if (operationResponse.code && operationResponse.code >= 200 && operationResponse.code < 300) {
|
||||
operationResults.push(operationResponse);
|
||||
}
|
||||
});
|
||||
|
||||
if (!operationResults.length) {
|
||||
operationResults.push({
|
||||
code: 200,
|
||||
description: '',
|
||||
export: 'interface',
|
||||
type: PrimaryType.OBJECT,
|
||||
base: PrimaryType.OBJECT,
|
||||
template: null,
|
||||
imports: [],
|
||||
link: null,
|
||||
});
|
||||
}
|
||||
|
||||
return operationResults.filter((operationResult, index, arr) => {
|
||||
return (
|
||||
arr.findIndex(item => {
|
||||
return areEqual(item, operationResult);
|
||||
}) === index
|
||||
);
|
||||
});
|
||||
}
|
||||
@ -3,6 +3,7 @@ import { Client } from '../../client/interfaces/Client';
|
||||
import { getServer } from './parser/getServer';
|
||||
import { getModels } from './parser/getModels';
|
||||
import { getServices } from './parser/getServices';
|
||||
import { getServiceVersion } from './parser/getServiceVersion';
|
||||
|
||||
/**
|
||||
* Parse the OpenAPI specification to a Client model that contains
|
||||
@ -11,7 +12,7 @@ import { getServices } from './parser/getServices';
|
||||
*/
|
||||
export function parse(openApi: OpenApi): Client {
|
||||
return {
|
||||
version: openApi.info.version,
|
||||
version: getServiceVersion(openApi.info.version),
|
||||
server: getServer(openApi),
|
||||
models: getModels(openApi),
|
||||
services: getServices(openApi),
|
||||
|
||||
9
src/openApi/v3/parser/getServiceVersion.spec.ts
Normal file
9
src/openApi/v3/parser/getServiceVersion.spec.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { getServiceVersion } from './getServiceVersion';
|
||||
|
||||
describe('getServiceVersion', () => {
|
||||
it('should produce correct result', () => {
|
||||
expect(getServiceVersion('1.0')).toEqual('1.0');
|
||||
expect(getServiceVersion('v1.0')).toEqual('1.0');
|
||||
expect(getServiceVersion('V1.0')).toEqual('1.0');
|
||||
});
|
||||
});
|
||||
8
src/openApi/v3/parser/getServiceVersion.ts
Normal file
8
src/openApi/v3/parser/getServiceVersion.ts
Normal file
@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Convert the service version to 'normal' version.
|
||||
* This basically removes any "v" prefix from the version string.
|
||||
* @param version
|
||||
*/
|
||||
export function getServiceVersion(version = '1.0'): string {
|
||||
return version.replace(/^v/gi, '');
|
||||
}
|
||||
11
src/templates/typescript/core/OpenAPI.hbs
Normal file
11
src/templates/typescript/core/OpenAPI.hbs
Normal file
@ -0,0 +1,11 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
|
||||
export namespace OpenAPI {
|
||||
export let BASE = '{{{server}}}';
|
||||
export let VERSION = '{{{version}}}';
|
||||
export let CLIENT = '{{{httpClient}}}';
|
||||
export let TOKEN = '';
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
|
||||
export namespace OpenAPI {
|
||||
export let BASE: string = '';
|
||||
export let TOKEN: string = '';
|
||||
export let VERSION: string = '{VERSION}';
|
||||
}
|
||||
@ -4,8 +4,7 @@
|
||||
/* prettier-ignore */
|
||||
|
||||
export interface RequestOptions {
|
||||
type: 'fetch' | 'xhr';
|
||||
method: string;
|
||||
method: 'get' | 'put' | 'post' | 'delete' | 'options' | 'head' | 'patch';
|
||||
path: string;
|
||||
headers?: { [key: string]: any };
|
||||
query?: { [key: string]: any };
|
||||
|
||||
@ -3,13 +3,13 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
|
||||
import { getFormData } from './getFormData';
|
||||
import { getQueryString } from './getQueryString';
|
||||
import { OpenAPI } from './OpenAPI';
|
||||
import { RequestOptions } from './RequestOptions';
|
||||
import { requestUsingFetch } from './requestUsingFetch';
|
||||
import { requestUsingXHR } from './requestUsingXHR';
|
||||
import { Result } from './Result';
|
||||
import {getFormData} from './getFormData';
|
||||
import {getQueryString} from './getQueryString';
|
||||
import {OpenAPI} from './OpenAPI';
|
||||
import {RequestOptions} from './RequestOptions';
|
||||
import {requestUsingFetch} from './requestUsingFetch';
|
||||
import {requestUsingXHR} from './requestUsingXHR';
|
||||
import {Result} from './Result';
|
||||
|
||||
/**
|
||||
* Create the request.
|
||||
@ -24,14 +24,14 @@ export async function request<T = any>(options: Readonly<RequestOptions>): Promi
|
||||
// Create request headers
|
||||
const headers = new Headers({
|
||||
...options.headers,
|
||||
Accept: 'application/json',
|
||||
Accept: 'application/json'
|
||||
});
|
||||
|
||||
// Create request settings
|
||||
const request: RequestInit = {
|
||||
headers,
|
||||
method: options.method,
|
||||
credentials: 'same-origin',
|
||||
credentials: 'same-origin'
|
||||
};
|
||||
|
||||
// If we have a bearer token then we set the authentication header.
|
||||
@ -63,11 +63,11 @@ export async function request<T = any>(options: Readonly<RequestOptions>): Promi
|
||||
}
|
||||
|
||||
try {
|
||||
switch (options.type) {
|
||||
case 'fetch':
|
||||
return await requestUsingFetch<T>(url, request);
|
||||
switch (OpenAPI.CLIENT) {
|
||||
case 'xhr':
|
||||
return await requestUsingXHR<T>(url, request);
|
||||
default:
|
||||
return await requestUsingFetch<T>(url, request);
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
@ -75,7 +75,7 @@ export async function request<T = any>(options: Readonly<RequestOptions>): Promi
|
||||
ok: false,
|
||||
status: 0,
|
||||
statusText: '',
|
||||
body: error,
|
||||
body: error
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,7 +23,7 @@ export async function requestUsingFetch<T = any>(url: string, request: Readonly<
|
||||
ok: response.ok,
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
body: null,
|
||||
body: null
|
||||
};
|
||||
|
||||
// Try to parse the content for any response status code.
|
||||
|
||||
@ -38,7 +38,7 @@ export async function requestUsingXHR<T = any>(url: string, request: Readonly<Re
|
||||
ok: isSuccess(xhr.status),
|
||||
status: xhr.status,
|
||||
statusText: xhr.statusText,
|
||||
body: null,
|
||||
body: null
|
||||
};
|
||||
|
||||
// Try to parse the content for any response status code.
|
||||
|
||||
@ -2,8 +2,8 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
{{#if imports}}
|
||||
|
||||
{{#if imports}}
|
||||
{{#each imports}}
|
||||
import { {{{this}}} } from '../models/{{{this}}}';
|
||||
{{/each}}
|
||||
|
||||
@ -3,17 +3,17 @@
|
||||
* {{{description}}}
|
||||
*/
|
||||
{{/if}}
|
||||
export type {{{name}}} = {{>type}}{{#if nullable}} | null{{/if}};
|
||||
export type {{{name}}} = {{>type}}{{#if isNullable}} | null{{/if}};
|
||||
|
||||
export namespace {{{name}}} {
|
||||
|
||||
export const schema = {{>validation}};
|
||||
|
||||
export async function validate(value: any): Promise<{{{name}}}{{#if nullable}} | null{{/if}}> {
|
||||
export async function validate(value: any): Promise<{{{name}}}{{#if isNullable}} | null{{/if}}> {
|
||||
return schema.validate(value, { strict: true });
|
||||
}
|
||||
|
||||
export function validateSync(value: any): {{{name}}}{{#if nullable}} | null{{/if}} {
|
||||
export function validateSync(value: any): {{{name}}}{{#if isNullable}} | null{{/if}} {
|
||||
return schema.validateSync(value, { strict: true });
|
||||
}
|
||||
}
|
||||
@ -3,17 +3,17 @@
|
||||
* {{{description}}}
|
||||
*/
|
||||
{{/if}}
|
||||
export type {{{name}}} = {{>type}}{{#if nullable}} | null{{/if}};
|
||||
export type {{{name}}} = {{>type}}{{#if isNullable}} | null{{/if}};
|
||||
|
||||
export namespace {{{name}}} {
|
||||
|
||||
export const schema = {{>validation}};
|
||||
|
||||
export async function validate(value: any): Promise<{{{name}}}{{#if nullable}} | null{{/if}}> {
|
||||
export async function validate(value: any): Promise<{{{name}}}{{#if isNullable}} | null{{/if}}> {
|
||||
return schema.validate(value, { strict: true });
|
||||
}
|
||||
|
||||
export function validateSync(value: any): {{{name}}}{{#if nullable}} | null{{/if}} {
|
||||
export function validateSync(value: any): {{{name}}}{{#if isNullable}} | null{{/if}} {
|
||||
return schema.validateSync(value, { strict: true });
|
||||
}
|
||||
}
|
||||
@ -5,7 +5,7 @@
|
||||
{{/if}}
|
||||
export enum {{{name}}} {
|
||||
{{#each enum}}
|
||||
{{{name}}} = {{{value}}},
|
||||
{{{name}}} = {{{value}}}{{#unless @last}},{{/unless}}
|
||||
{{/each}}
|
||||
}
|
||||
|
||||
@ -3,17 +3,17 @@
|
||||
* {{{description}}}
|
||||
*/
|
||||
{{/if}}
|
||||
export type {{{name}}} = {{>type}}{{#if nullable}} | null{{/if}};
|
||||
export type {{{name}}} = {{>type}}{{#if isNullable}} | null{{/if}};
|
||||
|
||||
export namespace {{{name}}} {
|
||||
|
||||
export const schema = {{>validation}};
|
||||
|
||||
export async function validate(value: any): Promise<{{{name}}}{{#if nullable}} | null{{/if}}> {
|
||||
export async function validate(value: any): Promise<{{{name}}}{{#if isNullable}} | null{{/if}}> {
|
||||
return schema.validate(value, { strict: true });
|
||||
}
|
||||
|
||||
export function validateSync(value: any): {{{name}}}{{#if nullable}} | null{{/if}} {
|
||||
export function validateSync(value: any): {{{name}}}{{#if isNullable}} | null{{/if}} {
|
||||
return schema.validateSync(value, { strict: true });
|
||||
}
|
||||
}
|
||||
@ -10,7 +10,7 @@ export interface {{{name}}}{{#if extends}} extends {{#each extends}}{{{this}}}{{
|
||||
* {{{description}}}
|
||||
*/
|
||||
{{/if}}
|
||||
{{#if readOnly}}readonly {{/if}}{{{name}}}{{#unless required}}?{{/unless}}: {{>type parent=../name}}{{#if nullable}} | null{{/if}};
|
||||
{{#if readOnly}}readonly {{/if}}{{{name}}}{{#unless isRequired}}?{{/unless}}: {{>type parent=../name}}{{#if isNullable}} | null{{/if}};
|
||||
{{/each}}
|
||||
}
|
||||
|
||||
@ -24,7 +24,7 @@ export namespace {{{name}}} {
|
||||
{{/if}}
|
||||
export enum {{{name}}} {
|
||||
{{#each enum}}
|
||||
{{{name}}} = {{{value}}},
|
||||
{{{name}}} = {{{value}}}{{#unless @last}},{{/unless}}
|
||||
{{/each}}
|
||||
}
|
||||
|
||||
@ -3,17 +3,17 @@
|
||||
* {{{description}}}
|
||||
*/
|
||||
{{/if}}
|
||||
export type {{{name}}} = {{>type}}{{#if nullable}} | null{{/if}};
|
||||
export type {{{name}}} = {{>type}}{{#if isNullable}} | null{{/if}};
|
||||
|
||||
export namespace {{{name}}} {
|
||||
|
||||
export const schema = {{>validation}};
|
||||
|
||||
export async function validate(value: any): Promise<{{{name}}}{{#if nullable}} | null{{/if}}> {
|
||||
export async function validate(value: any): Promise<{{{name}}}{{#if isNullable}} | null{{/if}}> {
|
||||
return schema.validate(value, { strict: true });
|
||||
}
|
||||
|
||||
export function validateSync(value: any): {{{name}}}{{#if nullable}} | null{{/if}} {
|
||||
export function validateSync(value: any): {{{name}}}{{#if isNullable}} | null{{/if}} {
|
||||
return schema.validateSync(value, { strict: true });
|
||||
}
|
||||
}
|
||||
5
src/templates/typescript/partials/result.hbs
Normal file
5
src/templates/typescript/partials/result.hbs
Normal file
@ -0,0 +1,5 @@
|
||||
{{~#if results~}}
|
||||
{{#each results}}{{>type}}{{#unless @last}} | {{/unless}}{{/each}}
|
||||
{{~else~}}
|
||||
void
|
||||
{{~/if~}}
|
||||
@ -1,13 +1,13 @@
|
||||
{{#eq export 'reference'}}
|
||||
{{>typeForReference}}
|
||||
{{>typeReference}}
|
||||
{{else eq export 'generic'}}
|
||||
{{>typeForGeneric}}
|
||||
{{>typeGeneric}}
|
||||
{{else eq export 'enum'}}
|
||||
{{>typeForEnum}}
|
||||
{{>typeEnum}}
|
||||
{{else eq export 'array'}}
|
||||
{{>typeForArray}}
|
||||
{{>typeArray}}
|
||||
{{else eq export 'dictionary'}}
|
||||
{{>typeForDictionary}}
|
||||
{{>typeDictionary}}
|
||||
{{else eq export 'interface'}}
|
||||
{{>typeForInterface}}
|
||||
{{>typeInterface}}
|
||||
{{/eq}}
|
||||
@ -1,5 +1,5 @@
|
||||
{{~#if link~}}
|
||||
Array<{{>type link child=true}}>
|
||||
Array<{{>type link}}>
|
||||
{{~else~}}
|
||||
Array<{{{type}}}>
|
||||
{{~/if~}}
|
||||
@ -1,5 +1,5 @@
|
||||
{{~#if link~}}
|
||||
Dictionary<{{>type link child=true}}>
|
||||
Dictionary<{{>type link}}>
|
||||
{{~else~}}
|
||||
Dictionary<{{{type}}}>
|
||||
{{~/if~}}
|
||||
14
src/templates/typescript/partials/typeInterface.hbs
Normal file
14
src/templates/typescript/partials/typeInterface.hbs
Normal file
@ -0,0 +1,14 @@
|
||||
{{~#if properties~}}
|
||||
{
|
||||
{{#each properties}}
|
||||
{{#if description}}
|
||||
/**
|
||||
* {{{description}}}
|
||||
*/
|
||||
{{/if}}
|
||||
{{#if readOnly}}readonly {{/if}}{{{name}}}{{#unless isRequired}}?{{/unless}}: {{>type}}{{#if isNullable}} | null{{/if}}{{#unless @last}},{{/unless}}
|
||||
{{/each}}
|
||||
}
|
||||
{{~else~}}
|
||||
any
|
||||
{{~/if~}}
|
||||
@ -1,13 +1,13 @@
|
||||
{{#eq export 'reference'}}
|
||||
{{>validationForReference}}
|
||||
{{>validationReference}}
|
||||
{{else eq export 'generic'}}
|
||||
{{>validationForGeneric}}
|
||||
{{>validationGeneric}}
|
||||
{{else eq export 'enum'}}
|
||||
{{>validationForEnum}}
|
||||
{{>validationEnum}}
|
||||
{{else eq export 'array'}}
|
||||
{{>validationForArray}}
|
||||
{{>validationArray}}
|
||||
{{else eq export 'dictionary'}}
|
||||
{{>validationForDictionary}}
|
||||
{{>validationDictionary}}
|
||||
{{else eq export 'interface'}}
|
||||
{{>validationForInterface}}
|
||||
{{>validationInterface}}
|
||||
{{/eq}}
|
||||
@ -1,5 +1,5 @@
|
||||
{{~#if link~}}
|
||||
yup.array<{{>type link child=true}}>().of({{>validation link child=true}})
|
||||
yup.array<{{>type link}}>().of({{>validation link}})
|
||||
{{~else~}}
|
||||
yup.array<{{{type}}}>().of({{{base}}}.schema)
|
||||
{{~/if~}}
|
||||
@ -1,9 +1,9 @@
|
||||
{{~#if link~}}
|
||||
yup.lazy<Dictionary<{{>type link child=true}}>>(value => {
|
||||
return yup.object<Dictionary<{{>type link child=true}}>>().shape(
|
||||
yup.lazy<Dictionary<{{>type link}}>>(value => {
|
||||
return yup.object<Dictionary<{{>type link}}>>().shape(
|
||||
Object.entries(value).reduce((obj, item) => ({
|
||||
...obj,
|
||||
[item[0]]: {{>validation link child=true}},
|
||||
[item[0]]: {{>validation link}}
|
||||
}), {})
|
||||
);
|
||||
})
|
||||
@ -12,7 +12,7 @@ yup.lazy<Dictionary<{{{type}}}>>(value => {
|
||||
return yup.object<Dictionary<{{{type}}}>>().shape(
|
||||
Object.entries(value).reduce((obj, item) => ({
|
||||
...obj,
|
||||
[item[0]]: {{{base}}}.schema,
|
||||
[item[0]]: {{{base}}}.schema
|
||||
}), {})
|
||||
);
|
||||
})
|
||||
9
src/templates/typescript/partials/validationEnum.hbs
Normal file
9
src/templates/typescript/partials/validationEnum.hbs
Normal file
@ -0,0 +1,9 @@
|
||||
yup.mixed<{{{name}}}>().oneOf([
|
||||
{{#each enum}}
|
||||
{{#eq ../name name}}
|
||||
{{{value}}}{{#unless @last}},{{/unless}}
|
||||
{{else}}
|
||||
{{{../name}}}.{{{name}}}{{#unless @last}},{{/unless}}
|
||||
{{/eq}}
|
||||
{{/each}}
|
||||
])
|
||||
21
src/templates/typescript/partials/validationInterface.hbs
Normal file
21
src/templates/typescript/partials/validationInterface.hbs
Normal file
@ -0,0 +1,21 @@
|
||||
(
|
||||
{{#if extends}}
|
||||
{{#each extends}}
|
||||
{{{this}}}.schema.concat(
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
{{#if properties}}
|
||||
yup.object{{#unless isProperty}}{{#if name}}<{{{name}}}>{{/if}}{{/unless}}().shape({
|
||||
{{#each properties}}
|
||||
{{{name}}}: yup.lazy(() => {{>validation}}.default(undefined){{#if isNullable}}.isNullable(){{/if}}){{#if isRequired}}.isRequired(){{/if}}{{#unless @last}},{{/unless}}
|
||||
{{/each}}
|
||||
}).noUnknown()
|
||||
{{else}}
|
||||
yup.object<any>()
|
||||
{{/if}}
|
||||
{{#if extends}}
|
||||
{{#each extends}}
|
||||
)
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
)
|
||||
@ -2,8 +2,8 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
{{#if imports}}
|
||||
|
||||
{{#if imports}}
|
||||
{{#each imports}}
|
||||
import { {{{this}}} } from '../models/{{{this}}}';
|
||||
{{/each}}
|
||||
@ -11,7 +11,6 @@ import { {{{this}}} } from '../models/{{{this}}}';
|
||||
import { ApiError, catchGenericError } from '../core/ApiError';
|
||||
import { request } from '../core/request';
|
||||
import { OpenAPI } from '../core/OpenAPI';
|
||||
import { Result } from '../core/Result';
|
||||
|
||||
export class {{{name}}} {
|
||||
|
||||
@ -31,37 +30,43 @@ export class {{{name}}} {
|
||||
* @param {{{name}}} {{{description}}}
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
* @return {{{result}}}
|
||||
{{#each results}}
|
||||
* @result {{{type}}} {{{description}}}
|
||||
{{/each}}
|
||||
* @throws ApiError
|
||||
*/
|
||||
public static async {{{name}}}({{#each parameters}}{{{name}}}{{#unless required}}?{{/unless}}: {{{type}}}{{#if nullable}} | null{{/if}}{{#unless @last}}, {{/unless}}{{/each}}): Promise<{{{result}}}> {
|
||||
public static async {{{name}}}({{#if parameters}}
|
||||
{{#each parameters}}
|
||||
{{{name}}}{{#unless isRequired}}?{{/unless}}: {{>type}}{{#if isNullable}} | null{{/if}}{{#if default}} = {{{default}}}{{/if}}{{#unless @last}},{{/unless}}
|
||||
{{/each}}
|
||||
{{/if}}): Promise<{{>result}}> {
|
||||
|
||||
const result: Result<{{{result}}}> = await request({
|
||||
type: '{{{../httpClient}}}',
|
||||
const result = await request({
|
||||
method: '{{{method}}}',
|
||||
path: `{{{path}}}`,
|
||||
{{#if parametersHeader}}
|
||||
path: `{{{path}}}`
|
||||
{{~#if parametersHeader~}},
|
||||
headers: {
|
||||
{{#each parametersHeader}}
|
||||
'{{{prop}}}': {{{name}}},
|
||||
'{{{prop}}}': {{{name}}}{{#unless @last}},{{/unless}}
|
||||
{{/each}}
|
||||
},
|
||||
{{/if}}
|
||||
{{#if parametersQuery}}
|
||||
}
|
||||
{{~/if~}}
|
||||
{{~#if parametersQuery~}},
|
||||
query: {
|
||||
{{#each parametersQuery}}
|
||||
'{{{prop}}}': {{{name}}},
|
||||
'{{{prop}}}': {{{name}}}{{#unless @last}},{{/unless}}
|
||||
{{/each}}
|
||||
},
|
||||
{{/if}}
|
||||
{{#if parametersForm}}
|
||||
}
|
||||
{{~/if~}}
|
||||
{{~#if parametersForm~}},
|
||||
formData: {
|
||||
{{#each parametersForm}}
|
||||
'{{{prop}}}': {{{name}}},
|
||||
'{{{prop}}}': {{{name}}}{{#unless @last}},{{/unless}}
|
||||
{{/each}}
|
||||
},
|
||||
{{/if}}
|
||||
{{#if parametersBody}}
|
||||
body: {{{parametersBody.name}}},
|
||||
}
|
||||
{{~/if~}}
|
||||
{{~#if parametersBody~}},
|
||||
body: {{{parametersBody.name}}}
|
||||
{{/if}}
|
||||
});
|
||||
{{#if errors}}
|
||||
@ -69,7 +74,7 @@ export class {{{name}}} {
|
||||
if (!result.ok) {
|
||||
switch (result.status) {
|
||||
{{#each errors}}
|
||||
case {{{code}}}: throw new ApiError(result, `{{{text}}}`);
|
||||
case {{{code}}}: throw new ApiError(result, `{{{description}}}`);
|
||||
{{/each}}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,14 +0,0 @@
|
||||
{{~#if properties~}}
|
||||
{
|
||||
{{#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~}}
|
||||
@ -1,9 +0,0 @@
|
||||
yup.mixed<{{{name}}}>().oneOf([
|
||||
{{#each enum}}
|
||||
{{#unless child}}
|
||||
{{{../name}}}.{{{name}}},
|
||||
{{else}}
|
||||
{{{value}}},
|
||||
{{/unless}}
|
||||
{{/each}}
|
||||
])
|
||||
@ -1,21 +0,0 @@
|
||||
(
|
||||
{{#if extends}}
|
||||
{{#each extends}}
|
||||
{{{this}}}.schema.concat(
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
{{#if properties}}
|
||||
yup.object{{#unless child}}<{{{name}}}>{{/unless}}().shape({
|
||||
{{#each properties}}
|
||||
{{{name}}}: yup.lazy(() => {{>validation child=true}}.default(undefined){{#if nullable}}.nullable(){{/if}}){{#if required}}.required(){{/if}},
|
||||
{{/each}}
|
||||
}).noUnknown()
|
||||
{{else}}
|
||||
yup.object<any>()
|
||||
{{/if}}
|
||||
{{#if extends}}
|
||||
{{#each extends}}
|
||||
)
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
)
|
||||
@ -9,7 +9,7 @@ export function format(s: string): string {
|
||||
if (line.endsWith('(') || line.endsWith('{') || line.endsWith('[')) {
|
||||
indent++;
|
||||
}
|
||||
if (line.startsWith(')') || line.startsWith('}') || line.startsWith(']')) {
|
||||
if ((line.startsWith(')') || line.startsWith('}') || line.startsWith(']')) && i) {
|
||||
indent--;
|
||||
i--;
|
||||
}
|
||||
|
||||
@ -12,9 +12,10 @@ describe('getModelNames', () => {
|
||||
template: null,
|
||||
link: null,
|
||||
description: null,
|
||||
readOnly: false,
|
||||
required: false,
|
||||
nullable: false,
|
||||
isProperty: false,
|
||||
isReadOnly: false,
|
||||
isRequired: false,
|
||||
isNullable: false,
|
||||
imports: [],
|
||||
extends: [],
|
||||
enum: [],
|
||||
@ -29,9 +30,10 @@ describe('getModelNames', () => {
|
||||
template: null,
|
||||
link: null,
|
||||
description: null,
|
||||
readOnly: false,
|
||||
required: false,
|
||||
nullable: false,
|
||||
isProperty: false,
|
||||
isReadOnly: false,
|
||||
isRequired: false,
|
||||
isNullable: false,
|
||||
imports: [],
|
||||
extends: [],
|
||||
enum: [],
|
||||
@ -46,9 +48,10 @@ describe('getModelNames', () => {
|
||||
template: null,
|
||||
link: null,
|
||||
description: null,
|
||||
readOnly: false,
|
||||
required: false,
|
||||
nullable: false,
|
||||
isProperty: false,
|
||||
isReadOnly: false,
|
||||
isRequired: false,
|
||||
isNullable: false,
|
||||
imports: [],
|
||||
extends: [],
|
||||
enum: [],
|
||||
|
||||
@ -3,11 +3,13 @@ import { readHandlebarsTemplate } from './readHandlebarsTemplate';
|
||||
import { Language } from '../index';
|
||||
import * as path from 'path';
|
||||
import { registerHandlebarHelpers } from './registerHandlebarHelpers';
|
||||
import * as glob from 'glob';
|
||||
|
||||
export interface Templates {
|
||||
index: Handlebars.TemplateDelegate;
|
||||
model: Handlebars.TemplateDelegate;
|
||||
service: Handlebars.TemplateDelegate;
|
||||
settings: Handlebars.TemplateDelegate;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -23,33 +25,17 @@ export function readHandlebarsTemplates(language: Language): Templates {
|
||||
index: readHandlebarsTemplate(path.resolve(__dirname, `../../src/templates/${language}/index.hbs`)),
|
||||
model: readHandlebarsTemplate(path.resolve(__dirname, `../../src/templates/${language}/model.hbs`)),
|
||||
service: readHandlebarsTemplate(path.resolve(__dirname, `../../src/templates/${language}/service.hbs`)),
|
||||
settings: readHandlebarsTemplate(path.resolve(__dirname, `../../src/templates/${language}/core/OpenAPI.hbs`)),
|
||||
};
|
||||
|
||||
Handlebars.registerPartial({
|
||||
exportGeneric: readHandlebarsTemplate(path.resolve(__dirname, `../../src/templates/${language}/exportGeneric.hbs`)),
|
||||
exportReference: readHandlebarsTemplate(path.resolve(__dirname, `../../src/templates/${language}/exportReference.hbs`)),
|
||||
exportInterface: readHandlebarsTemplate(path.resolve(__dirname, `../../src/templates/${language}/exportInterface.hbs`)),
|
||||
exportEnum: readHandlebarsTemplate(path.resolve(__dirname, `../../src/templates/${language}/exportEnum.hbs`)),
|
||||
exportDictionary: readHandlebarsTemplate(path.resolve(__dirname, `../../src/templates/${language}/exportDictionary.hbs`)),
|
||||
exportArray: readHandlebarsTemplate(path.resolve(__dirname, `../../src/templates/${language}/exportArray.hbs`)),
|
||||
validation: readHandlebarsTemplate(path.resolve(__dirname, `../../src/templates/${language}/validation.hbs`)),
|
||||
validationForGeneric: readHandlebarsTemplate(path.resolve(__dirname, `../../src/templates/${language}/validationForGeneric.hbs`)),
|
||||
validationForReference: readHandlebarsTemplate(path.resolve(__dirname, `../../src/templates/${language}/validationForReference.hbs`)),
|
||||
validationForEnum: readHandlebarsTemplate(path.resolve(__dirname, `../../src/templates/${language}/validationForEnum.hbs`)),
|
||||
validationForInterface: readHandlebarsTemplate(path.resolve(__dirname, `../../src/templates/${language}/validationForInterface.hbs`)),
|
||||
validationForDictionary: readHandlebarsTemplate(path.resolve(__dirname, `../../src/templates/${language}/validationForDictionary.hbs`)),
|
||||
validationForArray: readHandlebarsTemplate(path.resolve(__dirname, `../../src/templates/${language}/validationForArray.hbs`)),
|
||||
type: readHandlebarsTemplate(path.resolve(__dirname, `../../src/templates/${language}/type.hbs`)),
|
||||
typeForArray: readHandlebarsTemplate(path.resolve(__dirname, `../../src/templates/${language}/typeForArray.hbs`)),
|
||||
typeForDictionary: readHandlebarsTemplate(path.resolve(__dirname, `../../src/templates/${language}/typeForDictionary.hbs`)),
|
||||
typeForEnum: readHandlebarsTemplate(path.resolve(__dirname, `../../src/templates/${language}/typeForEnum.hbs`)),
|
||||
typeForInterface: readHandlebarsTemplate(path.resolve(__dirname, `../../src/templates/${language}/typeForInterface.hbs`)),
|
||||
typeForReference: readHandlebarsTemplate(path.resolve(__dirname, `../../src/templates/${language}/typeForReference.hbs`)),
|
||||
typeForGeneric: readHandlebarsTemplate(path.resolve(__dirname, `../../src/templates/${language}/typeForGeneric.hbs`)),
|
||||
const partials = path.resolve(__dirname, `../../src/templates/${language}/partials`);
|
||||
const partialsFiles = glob.sync('*.hbs', { cwd: partials });
|
||||
partialsFiles.forEach(partial => {
|
||||
Handlebars.registerPartial(path.basename(partial, '.hbs'), readHandlebarsTemplate(path.resolve(partials, partial)));
|
||||
});
|
||||
|
||||
return templates;
|
||||
} catch (e) {
|
||||
throw e;
|
||||
throw new Error(`Could not read Handlebar templates`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ import * as rimraf from 'rimraf';
|
||||
import * as fs from 'fs';
|
||||
import { Client } from '../client/interfaces/Client';
|
||||
import { Templates } from './readHandlebarsTemplates';
|
||||
import { Language } from '../index';
|
||||
import { HttpClient, Language } from '../index';
|
||||
import * as glob from 'glob';
|
||||
import { Model } from '../client/interfaces/Model';
|
||||
import { Service } from '../client/interfaces/Service';
|
||||
@ -32,11 +32,12 @@ describe('writeClient', () => {
|
||||
index: () => 'dummy',
|
||||
model: () => 'dummy',
|
||||
service: () => 'dummy',
|
||||
settings: () => 'dummy',
|
||||
};
|
||||
|
||||
globSync.mockReturnValue([]);
|
||||
|
||||
writeClient(client, Language.TYPESCRIPT, templates, '/');
|
||||
writeClient(client, Language.TYPESCRIPT, HttpClient.FETCH, templates, '/');
|
||||
|
||||
expect(rimrafSync).toBeCalled();
|
||||
expect(mkdirpSync).toBeCalled();
|
||||
|
||||
@ -9,6 +9,7 @@ import { writeClientIndex } from './writeClientIndex';
|
||||
import { HttpClient, Language } from '../index';
|
||||
import * as fs from 'fs';
|
||||
import * as glob from 'glob';
|
||||
import { writeClientSettings } from './writeClientSettings';
|
||||
|
||||
/**
|
||||
* Write our OpenAPI client, using the given templates at the given output path.
|
||||
@ -43,18 +44,19 @@ export function writeClient(client: Client, language: Language, httpClient: Http
|
||||
// Copy all support files
|
||||
const supportFiles = path.resolve(__dirname, `../../src/templates/${language}/`);
|
||||
const supportFilesList = glob.sync('**/*.{ts,js}', { cwd: supportFiles });
|
||||
supportFilesList.forEach(file =>
|
||||
supportFilesList.forEach(file => {
|
||||
fs.copyFileSync(
|
||||
path.resolve(supportFiles, file), // From input path
|
||||
path.resolve(outputPath, file) // To output path
|
||||
)
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
// Write the client files
|
||||
try {
|
||||
writeClientIndex(client, language, templates, outputPath);
|
||||
writeClientModels(client.models, language, httpClient, templates, outputPathModels);
|
||||
writeClientServices(client.services, language, httpClient, templates, outputPathServices);
|
||||
writeClientModels(client.models, language, templates, outputPathModels);
|
||||
writeClientServices(client.services, language, templates, outputPathServices);
|
||||
writeClientSettings(client, language, httpClient, templates, outputPathCore);
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@ describe('writeClientIndex', () => {
|
||||
it('should write to filesystem', () => {
|
||||
const client: Client = {
|
||||
server: 'http://localhost:8080',
|
||||
version: 'v1',
|
||||
version: '1.0',
|
||||
models: new Map<string, Model>(),
|
||||
services: new Map<string, Service>(),
|
||||
};
|
||||
@ -22,6 +22,7 @@ describe('writeClientIndex', () => {
|
||||
index: () => 'dummy',
|
||||
model: () => 'dummy',
|
||||
service: () => 'dummy',
|
||||
settings: () => 'dummy',
|
||||
};
|
||||
writeClientIndex(client, Language.TYPESCRIPT, templates, '/');
|
||||
expect(fsWriteFileSync).toBeCalledWith('/index.ts', 'dummy');
|
||||
|
||||
@ -29,6 +29,7 @@ export function writeClientIndex(client: Client, language: Language, templates:
|
||||
})
|
||||
);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
throw new Error(`Could not write index: "${fileName}"`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { writeClientModels } from './writeClientModels';
|
||||
import * as fs from 'fs';
|
||||
import { Model } from '../client/interfaces/Model';
|
||||
import { HttpClient, Language } from '../index';
|
||||
import { Language } from '../index';
|
||||
import { Templates } from './readHandlebarsTemplates';
|
||||
|
||||
jest.mock('fs');
|
||||
@ -19,9 +19,10 @@ describe('writeClientModels', () => {
|
||||
template: null,
|
||||
link: null,
|
||||
description: null,
|
||||
readOnly: false,
|
||||
required: false,
|
||||
nullable: false,
|
||||
isProperty: false,
|
||||
isReadOnly: false,
|
||||
isRequired: false,
|
||||
isNullable: false,
|
||||
imports: [],
|
||||
extends: [],
|
||||
enum: [],
|
||||
@ -32,8 +33,9 @@ describe('writeClientModels', () => {
|
||||
index: () => 'dummy',
|
||||
model: () => 'dummy',
|
||||
service: () => 'dummy',
|
||||
settings: () => 'dummy',
|
||||
};
|
||||
writeClientModels(models, Language.TYPESCRIPT, HttpClient.FETCH, templates, '/');
|
||||
writeClientModels(models, Language.TYPESCRIPT, templates, '/');
|
||||
expect(fsWriteFileSync).toBeCalledWith('/Item.ts', 'dummy');
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import * as fs from 'fs';
|
||||
import { Model } from '../client/interfaces/Model';
|
||||
import * as path from 'path';
|
||||
import { HttpClient, Language } from '../index';
|
||||
import { Language } from '../index';
|
||||
import { getFileName } from './getFileName';
|
||||
import { exportModel } from './exportModel';
|
||||
import { Templates } from './readHandlebarsTemplates';
|
||||
@ -11,22 +11,18 @@ import { format } from './format';
|
||||
* Generate Models using the Handlebar template and write to disk.
|
||||
* @param models Array of Models to write.
|
||||
* @param language The output language (Typescript or javascript).
|
||||
* @param httpClient The selected httpClient (fetch or XHR).
|
||||
* @param templates The loaded handlebar templates.
|
||||
* @param outputPath
|
||||
*/
|
||||
export function writeClientModels(models: Map<string, Model>, language: Language, httpClient: HttpClient, templates: Templates, outputPath: string): void {
|
||||
export function writeClientModels(models: Map<string, Model>, language: Language, templates: Templates, outputPath: string): void {
|
||||
models.forEach(model => {
|
||||
const fileName = getFileName(model.name, language);
|
||||
try {
|
||||
const templateData = exportModel(model);
|
||||
const templateResult = templates.model({
|
||||
language,
|
||||
httpClient,
|
||||
...templateData,
|
||||
});
|
||||
const templateResult = templates.model(templateData);
|
||||
fs.writeFileSync(path.resolve(outputPath, fileName), format(templateResult));
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
throw new Error(`Could not write model: "${fileName}"`);
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { writeClientServices } from './writeClientServices';
|
||||
import * as fs from 'fs';
|
||||
import { Service } from '../client/interfaces/Service';
|
||||
import { HttpClient, Language } from '../index';
|
||||
import { Language } from '../index';
|
||||
import { Templates } from './readHandlebarsTemplates';
|
||||
|
||||
jest.mock('fs');
|
||||
@ -20,8 +20,9 @@ describe('writeClientServices', () => {
|
||||
index: () => 'dummy',
|
||||
model: () => 'dummy',
|
||||
service: () => 'dummy',
|
||||
settings: () => 'dummy',
|
||||
};
|
||||
writeClientServices(services, Language.TYPESCRIPT, HttpClient.FETCH, templates, '/');
|
||||
writeClientServices(services, Language.TYPESCRIPT, templates, '/');
|
||||
expect(fsWriteFileSync).toBeCalledWith('/Item.ts', 'dummy');
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { Service } from '../client/interfaces/Service';
|
||||
import { HttpClient, Language } from '../index';
|
||||
import { Language } from '../index';
|
||||
import { getFileName } from './getFileName';
|
||||
import { exportService } from './exportService';
|
||||
import { Templates } from './readHandlebarsTemplates';
|
||||
@ -11,22 +11,18 @@ import { format } from './format';
|
||||
* Generate Services using the Handlebar template and write to disk.
|
||||
* @param services Array of Services to write.
|
||||
* @param language The output language (Typescript or javascript).
|
||||
* @param httpClient The selected httpClient (fetch or XHR).
|
||||
* @param templates The loaded handlebar templates.
|
||||
* @param outputPath
|
||||
*/
|
||||
export function writeClientServices(services: Map<string, Service>, language: Language, httpClient: HttpClient, templates: Templates, outputPath: string): void {
|
||||
export function writeClientServices(services: Map<string, Service>, language: Language, templates: Templates, outputPath: string): void {
|
||||
services.forEach(service => {
|
||||
const fileName = getFileName(service.name, language);
|
||||
try {
|
||||
const templateData = exportService(service);
|
||||
const templateResult = templates.service({
|
||||
language,
|
||||
httpClient,
|
||||
...templateData,
|
||||
});
|
||||
const templateResult = templates.service(templateData);
|
||||
fs.writeFileSync(path.resolve(outputPath, fileName), format(templateResult));
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
throw new Error(`Could not write service: "${fileName}"`);
|
||||
}
|
||||
});
|
||||
|
||||
24
src/utils/writeClientSettings.ts
Normal file
24
src/utils/writeClientSettings.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { Client } from '../client/interfaces/Client';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { HttpClient, Language } from '../index';
|
||||
import { getFileName } from './getFileName';
|
||||
import { Templates } from './readHandlebarsTemplates';
|
||||
|
||||
export function writeClientSettings(client: Client, language: Language, httpClient: HttpClient, templates: Templates, outputPath: string): void {
|
||||
const fileName = getFileName('OpenAPI', language);
|
||||
try {
|
||||
fs.writeFileSync(
|
||||
path.resolve(outputPath, fileName),
|
||||
templates.settings({
|
||||
language,
|
||||
httpClient,
|
||||
server: client.server,
|
||||
version: client.version,
|
||||
})
|
||||
);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
throw new Error(`Could not write settings: "${fileName}"`);
|
||||
}
|
||||
}
|
||||
@ -10,12 +10,203 @@
|
||||
"http"
|
||||
],
|
||||
"paths": {
|
||||
"/api/v{api-version}/dummy": {
|
||||
"/api/v{api-version}/simple": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Service"
|
||||
"Simple"
|
||||
],
|
||||
"operationId": "GetCallWithoutParametersAndResponse"
|
||||
},
|
||||
"put": {
|
||||
"tags": [
|
||||
"Simple"
|
||||
],
|
||||
"operationId": "PutCallWithoutParametersAndResponse"
|
||||
},
|
||||
"post": {
|
||||
"tags": [
|
||||
"Simple"
|
||||
],
|
||||
"operationId": "PostCallWithoutParametersAndResponse"
|
||||
},
|
||||
"delete": {
|
||||
"tags": [
|
||||
"Simple"
|
||||
],
|
||||
"operationId": "DeleteCallWithoutParametersAndResponse"
|
||||
},
|
||||
"options": {
|
||||
"tags": [
|
||||
"Simple"
|
||||
],
|
||||
"operationId": "OptionsCallWithoutParametersAndResponse"
|
||||
},
|
||||
"head": {
|
||||
"tags": [
|
||||
"Simple"
|
||||
],
|
||||
"operationId": "HeadCallWithoutParametersAndResponse"
|
||||
},
|
||||
"patch": {
|
||||
"tags": [
|
||||
"Simple"
|
||||
],
|
||||
"operationId": "PatchCallWithoutParametersAndResponse"
|
||||
}
|
||||
},
|
||||
"/api/v{api-version}/parameters": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Parameters"
|
||||
],
|
||||
"operationId": "CallWithParameters",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "This is the parameter that goes into the request header",
|
||||
"name": "parameterHeader",
|
||||
"in": "header",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"description": "This is the parameter that goes into the request query params",
|
||||
"name": "parameterQuery",
|
||||
"in": "query",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"description": "This is the parameter that goes into the request form data",
|
||||
"name": "parameterForm",
|
||||
"in": "formData",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"description": "This is the parameter that is send as request body",
|
||||
"name": "parameterBody",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "api-version",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v{api-version}/response": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Response"
|
||||
],
|
||||
"operationId": "CallWithResponse",
|
||||
"responses": {
|
||||
"default": {
|
||||
"description": "Message for default response",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ModelWithString"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"tags": [
|
||||
"Response"
|
||||
],
|
||||
"operationId": "CallWithDuplicateResponses",
|
||||
"responses": {
|
||||
"default": {
|
||||
"description": "Message for default response",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ModelWithString"
|
||||
}
|
||||
},
|
||||
"201": {
|
||||
"description": "Message for 201 response",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ModelWithString"
|
||||
}
|
||||
},
|
||||
"202": {
|
||||
"description": "Message for 202 response",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ModelWithString"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Message for 500 error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ModelWithString"
|
||||
}
|
||||
},
|
||||
"501": {
|
||||
"description": "Message for 501 error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ModelWithString"
|
||||
}
|
||||
},
|
||||
"502": {
|
||||
"description": "Message for 502 error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ModelWithString"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"put": {
|
||||
"tags": [
|
||||
"Response"
|
||||
],
|
||||
"operationId": "CallWithResponses",
|
||||
"responses": {
|
||||
"default": {
|
||||
"description": "Message for default response",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ModelWithString"
|
||||
}
|
||||
},
|
||||
"201": {
|
||||
"description": "Message for 201 response",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ModelThatExtends"
|
||||
}
|
||||
},
|
||||
"202": {
|
||||
"description": "Message for 202 response",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ModelThatExtendsExtends"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Message for 500 error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ModelWithString"
|
||||
}
|
||||
},
|
||||
"501": {
|
||||
"description": "Message for 501 error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ModelWithString"
|
||||
}
|
||||
},
|
||||
"502": {
|
||||
"description": "Message for 502 error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ModelWithString"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v{api-version}/complex": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Complex"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user