- Fixed configuration values beeing passed to partials when using composition

This commit is contained in:
Ferdi Koomen 2021-01-27 22:06:03 +01:00
parent ef9db3053e
commit 47d479f268
13 changed files with 85 additions and 59 deletions

View File

@ -36,6 +36,8 @@ const handlebarsPlugin = () => ({
notEquals: true,
containsSpaces: true,
union: true,
intersection: true,
enumerator: true,
},
});
return `export default ${templateSpec};`;

View File

@ -55,7 +55,11 @@ export async function generate({
}: Options): Promise<void> {
const openApi = isString(input) ? await getOpenApiSpec(input) : input;
const openApiVersion = getOpenApiVersion(openApi);
const templates = registerHandlebarTemplates();
const templates = registerHandlebarTemplates({
httpClient,
useUnionTypes,
useOptions,
});
switch (openApiVersion) {
case OpenApiVersion.V2: {

View File

@ -122,8 +122,8 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, isDefiniti
const composition = getModelComposition(openApi, definition, definition.allOf, 'all-of', getModel);
model.export = composition.type;
model.imports.push(...composition.imports);
model.enums.push(...composition.enums);
model.properties.push(...composition.properties);
model.enums.push(...composition.enums);
return model;
}
@ -136,6 +136,7 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, isDefiniti
const properties = getModelProperties(openApi, definition, getModel);
properties.forEach(property => {
model.imports.push(...property.imports);
model.enums.push(...property.enums);
model.properties.push(property);
if (property.export === 'enum') {
model.enums.push(property);

View File

@ -27,20 +27,6 @@ export function getOperationResponse(openApi: OpenApi, response: OpenApiResponse
properties: [],
};
// We support basic properties from response headers, since both
// fetch and XHR client just support string types.
if (response.headers) {
for (const name in response.headers) {
if (response.headers.hasOwnProperty(name)) {
operationResponse.in = 'header';
operationResponse.name = name;
operationResponse.type = 'string';
operationResponse.base = 'string';
return operationResponse;
}
}
}
// 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
@ -86,5 +72,19 @@ export function getOperationResponse(openApi: OpenApi, response: OpenApiResponse
}
}
// We support basic properties from response headers, since both
// fetch and XHR client just support string types.
if (response.headers) {
for (const name in response.headers) {
if (response.headers.hasOwnProperty(name)) {
operationResponse.in = 'header';
operationResponse.name = name;
operationResponse.type = 'string';
operationResponse.base = 'string';
return operationResponse;
}
}
}
return operationResponse;
}

View File

@ -130,8 +130,8 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, isDefiniti
const composition = getModelComposition(openApi, definition, definition.oneOf, 'one-of', getModel);
model.export = composition.type;
model.imports.push(...composition.imports);
model.enums.push(...composition.enums);
model.properties.push(...composition.properties);
model.enums.push(...composition.enums);
return model;
}
@ -139,8 +139,8 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, isDefiniti
const composition = getModelComposition(openApi, definition, definition.anyOf, 'any-of', getModel);
model.export = composition.type;
model.imports.push(...composition.imports);
model.enums.push(...composition.enums);
model.properties.push(...composition.properties);
model.enums.push(...composition.enums);
return model;
}
@ -148,8 +148,8 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, isDefiniti
const composition = getModelComposition(openApi, definition, definition.allOf, 'all-of', getModel);
model.export = composition.type;
model.imports.push(...composition.imports);
model.enums.push(...composition.enums);
model.properties.push(...composition.properties);
model.enums.push(...composition.enums);
return model;
}
@ -163,6 +163,7 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, isDefiniti
const properties = getModelProperties(openApi, definition, getModel);
properties.forEach(property => {
model.imports.push(...property.imports);
model.enums.push(...property.enums);
model.properties.push(property);
if (property.export === 'enum') {
model.enums.push(property);

View File

@ -28,20 +28,6 @@ export function getOperationResponse(openApi: OpenApi, response: OpenApiResponse
properties: [],
};
// We support basic properties from response headers, since both
// fetch and XHR client just support string types.
if (response.headers) {
for (const name in response.headers) {
if (response.headers.hasOwnProperty(name)) {
operationResponse.in = 'header';
operationResponse.name = name;
operationResponse.type = 'string';
operationResponse.base = 'string';
return operationResponse;
}
}
}
if (response.content) {
const schema = getContent(openApi, response.content);
if (schema) {
@ -86,5 +72,19 @@ export function getOperationResponse(openApi: OpenApi, response: OpenApiResponse
}
}
// We support basic properties from response headers, since both
// fetch and XHR client just support string types.
if (response.headers) {
for (const name in response.headers) {
if (response.headers.hasOwnProperty(name)) {
operationResponse.in = 'header';
operationResponse.name = name;
operationResponse.type = 'string';
operationResponse.base = 'string';
return operationResponse;
}
}
}
return operationResponse;
}

View File

@ -1,7 +1,2 @@
{{~#if @root.useUnionTypes~}}
{{#each enum}}{{{value}}}{{#unless @last}} | {{/unless}}{{/each}}{{>isNullable}}
{{~else if parent~}}
{{{parent}}}.{{{name}}}{{>isNullable}}
{{~else~}}
{{#each enum}}{{{value}}}{{#unless @last}} | {{/unless}}{{/each}}{{>isNullable}}
{{~/if~}}
{{#enumerator enum parent name}}{{this}}{{/enumerator}}{{>isNullable}}

View File

@ -1,5 +1 @@
{{~#if parent~}}
({{#each properties}}{{>type parent=../parent}}{{#unless @last}} & {{/unless}}{{/each}}){{>isNullable}}
{{~else~}}
({{#each properties}}{{>type}}{{#unless @last}} & {{/unless}}{{/each}}){{>isNullable}}
{{~/if~}}
({{#intersection properties parent}}{{this}}{{/intersection}}){{>isNullable}}

View File

@ -1,14 +1,20 @@
import * as Handlebars from 'handlebars/runtime';
import { HttpClient } from '../HttpClient';
import { registerHandlebarHelpers } from './registerHandlebarHelpers';
describe('registerHandlebarHelpers', () => {
it('should register the helpers', () => {
registerHandlebarHelpers();
registerHandlebarHelpers({
httpClient: HttpClient.FETCH,
useOptions: false,
useUnionTypes: false,
});
const helpers = Object.keys(Handlebars.helpers);
expect(helpers).toContain('equals');
expect(helpers).toContain('notEquals');
expect(helpers).toContain('containsSpaces');
expect(helpers).toContain('union');
expect(helpers).toContain('intersection');
});
});

View File

@ -1,9 +1,11 @@
import * as Handlebars from 'handlebars/runtime';
import { Enum } from '../client/interfaces/Enum';
import { Model } from '../client/interfaces/Model';
import { HttpClient } from '../HttpClient';
import { unique } from './unique';
export function registerHandlebarHelpers(): void {
export function registerHandlebarHelpers(root: { httpClient: HttpClient; useOptions: boolean; useUnionTypes: boolean }): void {
Handlebars.registerHelper('equals', function (this: any, a: string, b: string, options: Handlebars.HelperOptions): string {
return a === b ? options.fn(this) : options.inverse(this);
});
@ -18,12 +20,25 @@ export function registerHandlebarHelpers(): void {
Handlebars.registerHelper('union', function (this: any, properties: Model[], parent: string | undefined, options: Handlebars.HelperOptions) {
const type = Handlebars.partials['type'];
const types = properties.map(property =>
type({
...property,
parent,
})
);
const types = properties.map(property => type({ ...root, ...property, parent }));
return options.fn(types.filter(unique).join(' | '));
});
Handlebars.registerHelper('intersection', function (this: any, properties: Model[], parent: string | undefined, options: Handlebars.HelperOptions) {
const type = Handlebars.partials['type'];
const types = properties.map(property => type({ ...root, ...property, parent }));
return options.fn(types.filter(unique).join(' & '));
});
Handlebars.registerHelper('enumerator', function (this: any, enumerators: Enum[], parent: string | undefined, name: string | undefined, options: Handlebars.HelperOptions) {
if (!root.useUnionTypes && parent && name) {
return `${parent}.${name}`;
}
return options.fn(
enumerators
.map(enumerator => enumerator.value)
.filter(unique)
.join(' | ')
);
});
}

View File

@ -1,8 +1,13 @@
import { HttpClient } from '../HttpClient';
import { registerHandlebarTemplates } from './registerHandlebarTemplates';
describe('registerHandlebarTemplates', () => {
it('should return correct templates', () => {
const templates = registerHandlebarTemplates();
const templates = registerHandlebarTemplates({
httpClient: HttpClient.FETCH,
useOptions: false,
useUnionTypes: false,
});
expect(templates.index).toBeDefined();
expect(templates.exports.model).toBeDefined();
expect(templates.exports.schema).toBeDefined();

View File

@ -1,5 +1,6 @@
import * as Handlebars from 'handlebars/runtime';
import { HttpClient } from '../HttpClient';
import templateCoreApiError from '../templates/core/ApiError.hbs';
import templateCoreApiRequestOptions from '../templates/core/ApiRequestOptions.hbs';
import templateCoreApiResult from '../templates/core/ApiResult.hbs';
@ -87,8 +88,8 @@ export interface Templates {
* Read all the Handlebar templates that we need and return on wrapper object
* so we can easily access the templates in out generator / write functions.
*/
export function registerHandlebarTemplates(): Templates {
registerHandlebarHelpers();
export function registerHandlebarTemplates(root: { httpClient: HttpClient; useOptions: boolean; useUnionTypes: boolean }): Templates {
registerHandlebarHelpers(root);
// Main templates (entry points for the files we write to disk)
const templates: Templates = {

View File

@ -4961,13 +4961,13 @@ import { OpenAPI } from '../core/OpenAPI';
export class TypesService {
/**
* @param parameterObject This is an object parameter
* @param parameterArray This is an array parameter
* @param parameterDictionary This is a dictionary parameter
* @param parameterEnum This is an enum parameter
* @param parameterNumber This is a number parameter
* @param parameterString This is a string parameter
* @param parameterBoolean This is a boolean parameter
* @param parameterObject This is an object parameter
* @param id This is a number parameter
* @returns number Response is a simple number
* @returns string Response is a simple string
@ -4976,26 +4976,26 @@ export class TypesService {
* @throws ApiError
*/
public static async types(
parameterObject: any,
parameterArray: Array<string> | null,
parameterDictionary: any,
parameterEnum: 'Success' | 'Warning' | 'Error' | null,
parameterNumber: number = 123,
parameterString: string | null = 'default',
parameterBoolean: boolean | null = true,
parameterObject: any = null,
id?: number,
): Promise<number | string | boolean | any> {
const result = await __request({
method: 'GET',
path: \`/api/v\${OpenAPI.VERSION}/types\`,
query: {
'parameterObject': parameterObject,
'parameterArray': parameterArray,
'parameterDictionary': parameterDictionary,
'parameterEnum': parameterEnum,
'parameterNumber': parameterNumber,
'parameterString': parameterString,
'parameterBoolean': parameterBoolean,
'parameterObject': parameterObject,
},
});
return result.body;