From 2bd568a5028d59a3256d1a0e72b63131a857e82c Mon Sep 17 00:00:00 2001 From: Oskar Asplin Date: Sat, 20 May 2023 06:32:47 +0200 Subject: [PATCH 1/3] Fix case conversion for all fields --- src/Case.ts | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/Case.ts b/src/Case.ts index e98def5c7..1832a439a 100644 --- a/src/Case.ts +++ b/src/Case.ts @@ -1,3 +1,4 @@ +import { Enum } from './client/interfaces/Enum'; import { Model } from './client/interfaces/Model'; export enum Case { @@ -23,16 +24,19 @@ const transforms = { // A recursive function that looks at the models and their properties and // converts each property name using the provided transform function. export const convertModelNames = (model: Model, type: Exclude): Model => { - if (!model.properties.length) { - return { - ...model, - name: transforms[type](model.name), - }; - } return { ...model, - properties: model.properties.map(property => { - return convertModelNames(property, type); - }), + name: transforms[type](model.name), + link: model.link ? convertModelNames(model.link, type) : null, + enum: model.enum.map(modelEnum => convertEnumName(modelEnum, type)), + enums: model.enums.map(property => convertModelNames(property, type)), + properties: model.properties.map(property => convertModelNames(property, type)), + }; +}; + +const convertEnumName = (modelEnum: Enum, type: Exclude): Enum => { + return { + ...modelEnum, + name: transforms[type](modelEnum.name), }; }; From 478165499c4f815ba84ac13f16f4a1b2e8fdf827 Mon Sep 17 00:00:00 2001 From: Oskar Asplin Date: Tue, 30 May 2023 12:33:24 +0200 Subject: [PATCH 2/3] Rename transformModelCase to transformCase and add to Readme --- README.md | 1 + bin/index.js | 4 ++-- src/index.ts | 10 +++++----- src/utils/writeClient.ts | 6 +++--- src/utils/writeClientModels.ts | 6 +++--- 5 files changed, 14 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 429f905ee..6a839285c 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,7 @@ $ openapi --help --postfixServices Service name postfix (default: "Service") --postfixModels Model name postfix --request Path to custom request file + --transformCase Transforms field names to specified case [camel, snake] (default: none) -h, --help display help for command Examples diff --git a/bin/index.js b/bin/index.js index 7bdb59aeb..2ac0b54e0 100755 --- a/bin/index.js +++ b/bin/index.js @@ -24,7 +24,7 @@ const params = program .option('--postfix ', 'Deprecated: Use --postfixServices instead. Service name postfix', 'Service') .option('--postfixServices ', 'Service name postfix', 'Service') .option('--postfixModels ', 'Model name postfix') - .option('--transformModelCase ', 'Transform model case [camel, snake]', 'none') + .option('--transformCase ', 'Transforms field names to specified case [camel, snake]', 'none') .option('--request ', 'Path to custom request file') .parse(process.argv) .opts(); @@ -46,7 +46,7 @@ if (OpenAPI) { indent: params.indent, postfixServices: params.postfixServices ?? params.postfix, postfixModels: params.postfixModels, - transformModelCase: params.transformModelCase, + transformCase: params.transformCase, request: params.request, }) .then(() => { diff --git a/src/index.ts b/src/index.ts index cf176eada..a02110d43 100644 --- a/src/index.ts +++ b/src/index.ts @@ -27,7 +27,7 @@ export type Options = { indent?: Indent; postfixServices?: string; postfixModels?: string; - transformModelCase?: Case; + transformCase?: Case; request?: string; write?: boolean; }; @@ -49,7 +49,7 @@ export type Options = { * @param indent Indentation options (4, 2 or tab) * @param postfixServices Service name postfix * @param postfixModels Model name postfix - * @param transformModelCase Transform model case (camel, snake) + * @param transformCase Transform case (camel, snake) * @param request Path to custom request file * @param write Write the files to disk (true or false) */ @@ -67,7 +67,7 @@ export const generate = async ({ indent = Indent.SPACE_4, postfixServices = 'Service', postfixModels = '', - transformModelCase = Case.NONE, + transformCase = Case.NONE, request, write = true, }: Options): Promise => { @@ -98,7 +98,7 @@ export const generate = async ({ indent, postfixServices, postfixModels, - transformModelCase, + transformCase, clientName, request ); @@ -123,7 +123,7 @@ export const generate = async ({ indent, postfixServices, postfixModels, - transformModelCase, + transformCase, clientName, request ); diff --git a/src/utils/writeClient.ts b/src/utils/writeClient.ts index 2e046468c..bcdfcde42 100644 --- a/src/utils/writeClient.ts +++ b/src/utils/writeClient.ts @@ -31,7 +31,7 @@ import { writeClientServices } from './writeClientServices'; * @param indent Indentation options (4, 2 or tab) * @param postfixServices Service name postfix * @param postfixModels Model name postfix - * @param transformModelCase Transform model case (camel, snake) + * @param transformCase Transform model case (camel, snake) * @param clientName Custom client class name * @param request Path to custom request file */ @@ -49,7 +49,7 @@ export const writeClient = async ( indent: Indent, postfixServices: string, postfixModels: string, - transformModelCase: Case, + transformCase: Case, clientName?: string, request?: string ): Promise => { @@ -101,7 +101,7 @@ export const writeClient = async ( httpClient, useUnionTypes, indent, - transformModelCase + transformCase ); } diff --git a/src/utils/writeClientModels.ts b/src/utils/writeClientModels.ts index 28f399c29..d3af0be89 100644 --- a/src/utils/writeClientModels.ts +++ b/src/utils/writeClientModels.ts @@ -17,7 +17,7 @@ import type { Templates } from './registerHandlebarTemplates'; * @param httpClient The selected httpClient (fetch, xhr, node or axios) * @param useUnionTypes Use union types instead of enums * @param indent Indentation options (4, 2 or tab) - * @param transformModelCase Transform model case (camel, snake) + * @param transformCase Transform model case (camel, snake) */ export const writeClientModels = async ( models: Model[], @@ -26,10 +26,10 @@ export const writeClientModels = async ( httpClient: HttpClient, useUnionTypes: boolean, indent: Indent, - transformModelCase: Case + transformCase: Case ): Promise => { for (const model of models) { - const newModel = transformModelCase === Case.NONE ? model : convertModelNames(model, transformModelCase); + const newModel = transformCase === Case.NONE ? model : convertModelNames(model, transformCase); const file = resolve(outputPath, `${model.name}.ts`); const templateResult = templates.exports.model({ ...newModel, From 0ddbecc152eaf8ab23fad0b54c87683fc12a6795 Mon Sep 17 00:00:00 2001 From: Oskar Asplin Date: Tue, 30 May 2023 14:40:16 +0200 Subject: [PATCH 3/3] Fix case conversion for service operation response body --- src/Case.ts | 16 ++++++++++++++-- src/utils/writeClient.ts | 1 + src/utils/writeClientServices.spec.ts | 13 ++++++++++++- src/utils/writeClientServices.ts | 6 +++++- 4 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/Case.ts b/src/Case.ts index 1832a439a..da648c3ad 100644 --- a/src/Case.ts +++ b/src/Case.ts @@ -1,12 +1,14 @@ import { Enum } from './client/interfaces/Enum'; import { Model } from './client/interfaces/Model'; +import { OperationResponse } from './client/interfaces/OperationResponse'; +import { Service } from './client/interfaces/Service'; export enum Case { NONE = 'none', CAMEL = 'camel', SNAKE = 'snake', } -// Convert a string from snake case or pascal case to camel case. +// Convert a string from snake case to camel case. const toCamelCase = (str: string): string => { return str.replace(/_([a-z])/g, match => match[1].toUpperCase()); }; @@ -23,7 +25,7 @@ const transforms = { // A recursive function that looks at the models and their properties and // converts each property name using the provided transform function. -export const convertModelNames = (model: Model, type: Exclude): Model => { +export const convertModelNames = (model: T, type: Exclude): T => { return { ...model, name: transforms[type](model.name), @@ -40,3 +42,13 @@ const convertEnumName = (modelEnum: Enum, type: Exclude): Enum name: transforms[type](modelEnum.name), }; }; + +export const convertServiceCase = (service: Service, type: Exclude): Service => { + return { + ...service, + operations: service.operations.map(op => ({ + ...op, + results: op.results.map(results => convertModelNames(results, type)), + })), + }; +}; diff --git a/src/utils/writeClient.ts b/src/utils/writeClient.ts index bcdfcde42..284d0a71e 100644 --- a/src/utils/writeClient.ts +++ b/src/utils/writeClient.ts @@ -81,6 +81,7 @@ export const writeClient = async ( useOptions, indent, postfixServices, + transformCase, clientName ); } diff --git a/src/utils/writeClientServices.spec.ts b/src/utils/writeClientServices.spec.ts index b7ebbfe6c..c125493e4 100644 --- a/src/utils/writeClientServices.spec.ts +++ b/src/utils/writeClientServices.spec.ts @@ -1,5 +1,6 @@ import { EOL } from 'os'; +import { Case } from '../Case'; import type { Service } from '../client/interfaces/Service'; import { HttpClient } from '../HttpClient'; import { Indent } from '../Indent'; @@ -39,7 +40,17 @@ describe('writeClientServices', () => { }, }; - await writeClientServices(services, templates, '/', HttpClient.FETCH, false, false, Indent.SPACE_4, 'Service'); + await writeClientServices( + services, + templates, + '/', + HttpClient.FETCH, + false, + false, + Indent.SPACE_4, + 'Service', + Case.NONE + ); expect(writeFile).toBeCalledWith('/UserService.ts', `service${EOL}`); }); diff --git a/src/utils/writeClientServices.ts b/src/utils/writeClientServices.ts index 2f95341d2..02f589c52 100644 --- a/src/utils/writeClientServices.ts +++ b/src/utils/writeClientServices.ts @@ -1,5 +1,6 @@ import { resolve } from 'path'; +import { Case, convertServiceCase } from '../Case'; import type { Service } from '../client/interfaces/Service'; import type { HttpClient } from '../HttpClient'; import type { Indent } from '../Indent'; @@ -19,6 +20,7 @@ import type { Templates } from './registerHandlebarTemplates'; * @param useOptions Use options or arguments functions * @param indent Indentation options (4, 2 or tab) * @param postfix Service name postfix + * @param transformCase Transform model case (camel, snake) * @param clientName Custom client class name */ export const writeClientServices = async ( @@ -30,12 +32,14 @@ export const writeClientServices = async ( useOptions: boolean, indent: Indent, postfix: string, + transformCase: Case, clientName?: string ): Promise => { for (const service of services) { + const newService = transformCase === Case.NONE ? service : convertServiceCase(service, transformCase); const file = resolve(outputPath, `${service.name}${postfix}.ts`); const templateResult = templates.exports.service({ - ...service, + ...newService, httpClient, useUnionTypes, useOptions,