From 843afc4e730cc34205aa117676f945d82910fabb Mon Sep 17 00:00:00 2001 From: Yonatan Refaeli Date: Wed, 1 Jun 2022 00:12:14 -0400 Subject: [PATCH 01/23] Add server interface generation feature --- bin/index.js | 12 ++++ rollup.config.js | 3 + src/index.ts | 32 ++++++++++ .../core/functions/hasNonBodyParams.hbs | 3 + .../core/functions/hasRequestBody.hbs | 3 + src/templates/exportQueryModel.hbs | 14 +++++ src/templates/exportServerInterface.hbs | 38 ++++++++++++ src/utils/hyphenCase.ts | 5 ++ src/utils/registerHandlebarHelpers.spec.ts | 1 + src/utils/registerHandlebarHelpers.ts | 18 ++++++ src/utils/registerHandlebarTemplates.ts | 8 +++ src/utils/writeClient.spec.ts | 10 ++++ src/utils/writeClient.ts | 36 ++++++++++++ src/utils/writeClientClass.spec.ts | 2 + src/utils/writeClientCore.spec.ts | 2 + src/utils/writeClientIndex.spec.ts | 2 + src/utils/writeClientModels.spec.ts | 2 + src/utils/writeClientModels.ts | 3 +- src/utils/writeClientSchemas.spec.ts | 2 + src/utils/writeClientServices.spec.ts | 2 + src/utils/writeQueryModels.ts | 48 +++++++++++++++ src/utils/writeServerInterfaces.ts | 58 +++++++++++++++++++ 22 files changed, 303 insertions(+), 1 deletion(-) create mode 100644 src/templates/core/functions/hasNonBodyParams.hbs create mode 100644 src/templates/core/functions/hasRequestBody.hbs create mode 100644 src/templates/exportQueryModel.hbs create mode 100644 src/templates/exportServerInterface.hbs create mode 100644 src/utils/hyphenCase.ts create mode 100644 src/utils/writeQueryModels.ts create mode 100644 src/utils/writeServerInterfaces.ts diff --git a/bin/index.js b/bin/index.js index decf79420..d4647aa97 100755 --- a/bin/index.js +++ b/bin/index.js @@ -12,6 +12,12 @@ const params = program .version(pkg.version) .requiredOption('-i, --input ', 'OpenAPI specification, can be a path, url or string content (required)') .requiredOption('-o, --output ', 'Output directory (required)') + .option('--serverOutput ', 'Server output directory') + .option('--serverDirName ', 'Server directory name') + .option('--serverModelImportPath ', 'Server model import path') + .option('--serverApiTypesImportPath ', 'Server Api Types import path') + .option('--serverReqTypeName ', 'Name of Server Request type to use') + .option('--serverResTypeName ', 'Name of Server Response type to use') .option('-c, --client ', 'HTTP client to generate [fetch, xhr, node, axios, angular]', 'fetch') .option('--name ', 'Custom client class name') .option('--useOptions', 'Use options instead of arguments') @@ -32,6 +38,12 @@ if (OpenAPI) { OpenAPI.generate({ input: params.input, output: params.output, + serverOutput: params.serverOutput, + serverDirName: params.serverDirName, + serverModelImportPath: params.serverModelImportPath, + serverApiTypesImportPath: params.serverApiTypesImportPath, + serverReqTypeName: params.serverReqTypeName, + serverResTypeName: params.serverResTypeName, httpClient: params.client, clientName: params.name, useOptions: params.useOptions, diff --git a/rollup.config.js b/rollup.config.js index 6f085f8d8..98b784f66 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -37,6 +37,9 @@ const handlebarsPlugin = () => ({ escapeComment: true, escapeDescription: true, camelCase: true, + pascalCase: true, + hyphenCase: true, + hasNonBodyParams: true, }, }); return `export default ${templateSpec};`; diff --git a/src/index.ts b/src/index.ts index ef7a8b1bf..4cdfee428 100644 --- a/src/index.ts +++ b/src/index.ts @@ -15,13 +15,21 @@ export { Indent } from './Indent'; export type Options = { input: string | Record; output: string; + serverOutput?: string; + serverDirName?: string; + serverModelImportPath?: string; + serverApiTypesImportPath?: string; + serverReqTypeName?: string; + serverResTypeName?: string; httpClient?: HttpClient; clientName?: string; useOptions?: boolean; useUnionTypes?: boolean; exportCore?: boolean; exportServices?: boolean; + exportServerInterfaces?: boolean; exportModels?: boolean; + exportQueryModels?: boolean; exportSchemas?: boolean; indent?: Indent; postfix?: string; @@ -51,6 +59,12 @@ export type Options = { export const generate = async ({ input, output, + serverOutput, + serverDirName = 'server', + serverModelImportPath = '', + serverApiTypesImportPath = '', + serverReqTypeName = 'ApiRequestWrapper', + serverResTypeName = 'ApiResponseWrapper', httpClient = HttpClient.FETCH, clientName, useOptions = false, @@ -58,7 +72,9 @@ export const generate = async ({ exportCore = true, exportServices = true, exportModels = true, + exportQueryModels = true, exportSchemas = false, + exportServerInterfaces = true, indent = Indent.SPACE_4, postfix = 'Service', request, @@ -81,12 +97,20 @@ export const generate = async ({ clientFinal, templates, output, + serverOutput ?? output, + serverDirName, + serverModelImportPath, + serverApiTypesImportPath, + serverReqTypeName, + serverResTypeName, httpClient, useOptions, useUnionTypes, exportCore, exportServices, + exportServerInterfaces, exportModels, + exportQueryModels, exportSchemas, indent, postfix, @@ -104,12 +128,20 @@ export const generate = async ({ clientFinal, templates, output, + serverOutput ?? output, + serverDirName, + serverModelImportPath, + serverApiTypesImportPath, + serverReqTypeName, + serverResTypeName, httpClient, useOptions, useUnionTypes, exportCore, exportServices, + exportServerInterfaces, exportModels, + exportQueryModels, exportSchemas, indent, postfix, diff --git a/src/templates/core/functions/hasNonBodyParams.hbs b/src/templates/core/functions/hasNonBodyParams.hbs new file mode 100644 index 000000000..db9506574 --- /dev/null +++ b/src/templates/core/functions/hasNonBodyParams.hbs @@ -0,0 +1,3 @@ +const hasNonBodyParams = (op: any): boolean => { + op.parameters && op.parameters.length > 0 && !op.parametersBody; +}; diff --git a/src/templates/core/functions/hasRequestBody.hbs b/src/templates/core/functions/hasRequestBody.hbs new file mode 100644 index 000000000..2510302e2 --- /dev/null +++ b/src/templates/core/functions/hasRequestBody.hbs @@ -0,0 +1,3 @@ +const hasRequestBody = (values: any): boolean => { + return values.some((val, key) => key === 'requestBody'); +}; diff --git a/src/templates/exportQueryModel.hbs b/src/templates/exportQueryModel.hbs new file mode 100644 index 000000000..f72b05ddf --- /dev/null +++ b/src/templates/exportQueryModel.hbs @@ -0,0 +1,14 @@ +{{>header}} + +export interface {{{pascalCase name}}}Params { + {{#each parameters}} + {{#notEquals this.in 'body'}} + {{#if description}} + /** + * {{{escapeComment description}}} + */ + {{/if}} + {{{prop}}}{{>isRequired}}: {{{type}}}, + {{/notEquals}} + {{/each}} +} diff --git a/src/templates/exportServerInterface.hbs b/src/templates/exportServerInterface.hbs new file mode 100644 index 000000000..ea7cc613c --- /dev/null +++ b/src/templates/exportServerInterface.hbs @@ -0,0 +1,38 @@ +{{>header}} + +import { {{{serverReqTypeName}}}, {{{serverResTypeName}}} } from '{{{serverApiTypesImportPath}}}'; + +{{#if imports}} +{{#each imports}} +import type { {{{this}}} } from '{{{@root.serverModelImportPath}}}/{{{hyphenCase this}}}'; +{{/each}} +{{/if}} + +{{#each operations}} +{{#hasNonBodyParams this}} +import { {{{pascalCase name}}}Params } from '{{{@root.serverModelImportPath}}}/{{{hyphenCase name}}}-params'; +{{/hasNonBodyParams}} +{{/each}} + +export interface I{{{name}}}{{{@root.postfix}}} { + {{#each operations}} + /** + {{#if deprecated}} + * @deprecated + {{/if}} + {{#if summary}} + * {{{escapeComment summary}}} + {{/if}} + {{#if description}} + * {{{escapeComment description}}} + {{/if}} + * @param req {{{escapeComment 'The API request'}}} + {{#each results}} + * @returns {{{type}}} {{#if description}}{{{escapeComment description}}}{{/if}} + {{/each}} + * @throws ApiError + */ + {{{name}}}(req: {{{@root.serverReqTypeName}}}<{{#hasNonBodyParams this}}{{{pascalCase name}}}Params{{else}}never{{/hasNonBodyParams}}{{#if parametersBody}}, {{{parametersBody.type}}}{{/if}}>): {{{@root.serverResTypeName}}}<{{>result}}>; + + {{/each}} +} diff --git a/src/utils/hyphenCase.ts b/src/utils/hyphenCase.ts new file mode 100644 index 000000000..6fe324aa7 --- /dev/null +++ b/src/utils/hyphenCase.ts @@ -0,0 +1,5 @@ +export const toHyphenCase = (str: string): string => + str + .replace(/([a-z])([A-Z])/g, '$1-$2') + .replace(/[\s_]+/g, '-') + .toLowerCase(); diff --git a/src/utils/registerHandlebarHelpers.spec.ts b/src/utils/registerHandlebarHelpers.spec.ts index f71ca0008..d9b4a9bd0 100644 --- a/src/utils/registerHandlebarHelpers.spec.ts +++ b/src/utils/registerHandlebarHelpers.spec.ts @@ -20,5 +20,6 @@ describe('registerHandlebarHelpers', () => { expect(helpers).toContain('escapeComment'); expect(helpers).toContain('escapeDescription'); expect(helpers).toContain('camelCase'); + expect(helpers).toContain('pascalCase'); }); }); diff --git a/src/utils/registerHandlebarHelpers.ts b/src/utils/registerHandlebarHelpers.ts index 58b2ad189..35eba109f 100644 --- a/src/utils/registerHandlebarHelpers.ts +++ b/src/utils/registerHandlebarHelpers.ts @@ -5,6 +5,7 @@ import { EOL } from 'os'; import type { Enum } from '../client/interfaces/Enum'; import type { Model } from '../client/interfaces/Model'; import type { HttpClient } from '../HttpClient'; +import { toHyphenCase } from './hyphenCase'; import { unique } from './unique'; export const registerHandlebarHelpers = (root: { @@ -96,4 +97,21 @@ export const registerHandlebarHelpers = (root: { Handlebars.registerHelper('camelCase', function (value: string): string { return camelCase(value); }); + + Handlebars.registerHelper('pascalCase', function (value: string): string { + return camelCase(value, { pascalCase: true }); + }); + + Handlebars.registerHelper('hyphenCase', function (value: string): string { + return toHyphenCase(value); + }); + + Handlebars.registerHelper( + 'hasNonBodyParams', + function (this: any, op: any, options: Handlebars.HelperOptions): string { + return op.parameters && op.parameters.length > 0 && !op.parametersBody + ? options.fn(this) + : options.inverse(this); + } + ); }; diff --git a/src/utils/registerHandlebarTemplates.ts b/src/utils/registerHandlebarTemplates.ts index bf77cbdc1..28ce54611 100644 --- a/src/utils/registerHandlebarTemplates.ts +++ b/src/utils/registerHandlebarTemplates.ts @@ -30,6 +30,7 @@ import functionCatchErrorCodes from '../templates/core/functions/catchErrorCodes import functionGetFormData from '../templates/core/functions/getFormData.hbs'; import functionGetQueryString from '../templates/core/functions/getQueryString.hbs'; import functionGetUrl from '../templates/core/functions/getUrl.hbs'; +import functionHasNonBodyParams from '../templates/core/functions/hasNonBodyParams.hbs'; import functionIsBlob from '../templates/core/functions/isBlob.hbs'; import functionIsDefined from '../templates/core/functions/isDefined.hbs'; import functionIsFormData from '../templates/core/functions/isFormData.hbs'; @@ -53,7 +54,9 @@ import xhrGetResponseHeader from '../templates/core/xhr/getResponseHeader.hbs'; import xhrRequest from '../templates/core/xhr/request.hbs'; import xhrSendRequest from '../templates/core/xhr/sendRequest.hbs'; import templateExportModel from '../templates/exportModel.hbs'; +import templateExportQueryModel from '../templates/exportQueryModel.hbs'; import templateExportSchema from '../templates/exportSchema.hbs'; +import templateExportServerInterface from '../templates/exportServerInterface.hbs'; import templateExportService from '../templates/exportService.hbs'; import templateIndex from '../templates/index.hbs'; import partialBase from '../templates/partials/base.hbs'; @@ -90,8 +93,10 @@ export interface Templates { client: Handlebars.TemplateDelegate; exports: { model: Handlebars.TemplateDelegate; + queryModel: Handlebars.TemplateDelegate; schema: Handlebars.TemplateDelegate; service: Handlebars.TemplateDelegate; + serverInterface: Handlebars.TemplateDelegate; }; core: { settings: Handlebars.TemplateDelegate; @@ -122,8 +127,10 @@ export const registerHandlebarTemplates = (root: { client: Handlebars.template(templateClient), exports: { model: Handlebars.template(templateExportModel), + queryModel: Handlebars.template(templateExportQueryModel), schema: Handlebars.template(templateExportSchema), service: Handlebars.template(templateExportService), + serverInterface: Handlebars.template(templateExportServerInterface), }, core: { settings: Handlebars.template(templateCoreSettings), @@ -170,6 +177,7 @@ export const registerHandlebarTemplates = (root: { Handlebars.registerPartial('functions/catchErrorCodes', Handlebars.template(functionCatchErrorCodes)); Handlebars.registerPartial('functions/getFormData', Handlebars.template(functionGetFormData)); Handlebars.registerPartial('functions/getQueryString', Handlebars.template(functionGetQueryString)); + Handlebars.registerPartial('functions/hasNonBodyParams', Handlebars.template(functionHasNonBodyParams)); Handlebars.registerPartial('functions/getUrl', Handlebars.template(functionGetUrl)); Handlebars.registerPartial('functions/isBlob', Handlebars.template(functionIsBlob)); Handlebars.registerPartial('functions/isDefined', Handlebars.template(functionIsDefined)); diff --git a/src/utils/writeClient.spec.ts b/src/utils/writeClient.spec.ts index 3c06a95a5..6fffb21ae 100644 --- a/src/utils/writeClient.spec.ts +++ b/src/utils/writeClient.spec.ts @@ -21,8 +21,10 @@ describe('writeClient', () => { client: () => 'client', exports: { model: () => 'model', + queryModel: () => 'model', schema: () => 'schema', service: () => 'service', + serverInterface: () => 'serverInterface', }, core: { settings: () => 'settings', @@ -40,6 +42,12 @@ describe('writeClient', () => { client, templates, './dist', + './dist', + 'server', + '../models', + '', + 'ApiRequestWrapper', + 'ApiResponseWrapper', HttpClient.FETCH, false, false, @@ -47,6 +55,8 @@ describe('writeClient', () => { true, true, true, + true, + true, Indent.SPACE_4, 'Service', 'AppClient' diff --git a/src/utils/writeClient.ts b/src/utils/writeClient.ts index a0ffc1821..93103c24c 100644 --- a/src/utils/writeClient.ts +++ b/src/utils/writeClient.ts @@ -13,6 +13,8 @@ import { writeClientIndex } from './writeClientIndex'; import { writeClientModels } from './writeClientModels'; import { writeClientSchemas } from './writeClientSchemas'; import { writeClientServices } from './writeClientServices'; +import { writeQueryModels } from './writeQueryModels'; +import { writeServerInterfaces } from './writeServerInterfaces'; /** * Write our OpenAPI client, using the given templates at the given output @@ -36,12 +38,20 @@ export const writeClient = async ( client: Client, templates: Templates, output: string, + serverOutput: string, + serverDirName: string, + serverModelImportPath: string, + serverApiTypesImportPath: string, + serverReqTypeName: string, + serverResTypeName: string, httpClient: HttpClient, useOptions: boolean, useUnionTypes: boolean, exportCore: boolean, exportServices: boolean, + exportServerInterfaces: boolean, exportModels: boolean, + exportQueryModels: boolean, exportSchemas: boolean, indent: Indent, postfix: string, @@ -49,10 +59,12 @@ export const writeClient = async ( request?: string ): Promise => { const outputPath = resolve(process.cwd(), output); + const serverOutputPath = resolve(process.cwd(), serverOutput); const outputPathCore = resolve(outputPath, 'core'); const outputPathModels = resolve(outputPath, 'models'); const outputPathSchemas = resolve(outputPath, 'schemas'); const outputPathServices = resolve(outputPath, 'services'); + const outputPathServerInterfaces = resolve(serverOutputPath, serverDirName); if (!isSubDirectory(process.cwd(), output)) { throw new Error(`Output folder is not a subdirectory of the current working directory`); @@ -80,6 +92,26 @@ export const writeClient = async ( ); } + if (exportServerInterfaces) { + // await rmdir(outputPathServerInterfaces); + // await mkdir(outputPathServerInterfaces); + await writeServerInterfaces( + client.services, + templates, + outputPathServerInterfaces, + serverModelImportPath, + serverApiTypesImportPath, + serverReqTypeName, + serverResTypeName, + httpClient, + useUnionTypes, + useOptions, + indent, + postfix, + clientName + ); + } + if (exportSchemas) { await rmdir(outputPathSchemas); await mkdir(outputPathSchemas); @@ -92,6 +124,10 @@ export const writeClient = async ( await writeClientModels(client.models, templates, outputPathModels, httpClient, useUnionTypes, indent); } + if (exportModels && exportQueryModels) { + await writeQueryModels(client.services, templates, outputPathModels, httpClient, useUnionTypes, indent); + } + if (isDefined(clientName)) { await mkdir(outputPath); await writeClientClass(client, templates, outputPath, httpClient, clientName, indent, postfix); diff --git a/src/utils/writeClientClass.spec.ts b/src/utils/writeClientClass.spec.ts index 102f2eb57..9ab157699 100644 --- a/src/utils/writeClientClass.spec.ts +++ b/src/utils/writeClientClass.spec.ts @@ -21,8 +21,10 @@ describe('writeClientClass', () => { client: () => 'client', exports: { model: () => 'model', + queryModel: () => 'model', schema: () => 'schema', service: () => 'service', + serverInterface: () => 'serverInterface', }, core: { settings: () => 'settings', diff --git a/src/utils/writeClientCore.spec.ts b/src/utils/writeClientCore.spec.ts index cb2cc2925..0283703f5 100644 --- a/src/utils/writeClientCore.spec.ts +++ b/src/utils/writeClientCore.spec.ts @@ -21,8 +21,10 @@ describe('writeClientCore', () => { client: () => 'client', exports: { model: () => 'model', + queryModel: () => 'model', schema: () => 'schema', service: () => 'service', + serverInterface: () => 'serverInterface', }, core: { settings: () => 'settings', diff --git a/src/utils/writeClientIndex.spec.ts b/src/utils/writeClientIndex.spec.ts index 6284dfd2e..450ad629f 100644 --- a/src/utils/writeClientIndex.spec.ts +++ b/src/utils/writeClientIndex.spec.ts @@ -19,8 +19,10 @@ describe('writeClientIndex', () => { client: () => 'client', exports: { model: () => 'model', + queryModel: () => 'model', schema: () => 'schema', service: () => 'service', + serverInterface: () => 'serverInterface', }, core: { settings: () => 'settings', diff --git a/src/utils/writeClientModels.spec.ts b/src/utils/writeClientModels.spec.ts index 81b7b58b6..ecb946bbd 100644 --- a/src/utils/writeClientModels.spec.ts +++ b/src/utils/writeClientModels.spec.ts @@ -34,8 +34,10 @@ describe('writeClientModels', () => { client: () => 'client', exports: { model: () => 'model', + queryModel: () => 'model', schema: () => 'schema', service: () => 'service', + serverInterface: () => 'serverInterface', }, core: { settings: () => 'settings', diff --git a/src/utils/writeClientModels.ts b/src/utils/writeClientModels.ts index 997569b9f..fe39571ad 100644 --- a/src/utils/writeClientModels.ts +++ b/src/utils/writeClientModels.ts @@ -6,6 +6,7 @@ import type { Indent } from '../Indent'; import { writeFile } from './fileSystem'; import { formatCode as f } from './formatCode'; import { formatIndentation as i } from './formatIndentation'; +import { toHyphenCase } from './hyphenCase'; import type { Templates } from './registerHandlebarTemplates'; /** @@ -26,7 +27,7 @@ export const writeClientModels = async ( indent: Indent ): Promise => { for (const model of models) { - const file = resolve(outputPath, `${model.name}.ts`); + const file = resolve(outputPath, `${toHyphenCase(model.name)}.ts`); const templateResult = templates.exports.model({ ...model, httpClient, diff --git a/src/utils/writeClientSchemas.spec.ts b/src/utils/writeClientSchemas.spec.ts index 499aba3e8..8568486c4 100644 --- a/src/utils/writeClientSchemas.spec.ts +++ b/src/utils/writeClientSchemas.spec.ts @@ -34,8 +34,10 @@ describe('writeClientSchemas', () => { client: () => 'client', exports: { model: () => 'model', + queryModel: () => 'model', schema: () => 'schema', service: () => 'service', + serverInterface: () => 'serverInterface', }, core: { settings: () => 'settings', diff --git a/src/utils/writeClientServices.spec.ts b/src/utils/writeClientServices.spec.ts index 38a649483..db52208df 100644 --- a/src/utils/writeClientServices.spec.ts +++ b/src/utils/writeClientServices.spec.ts @@ -22,8 +22,10 @@ describe('writeClientServices', () => { client: () => 'client', exports: { model: () => 'model', + queryModel: () => 'model', schema: () => 'schema', service: () => 'service', + serverInterface: () => 'serverInterface', }, core: { settings: () => 'settings', diff --git a/src/utils/writeQueryModels.ts b/src/utils/writeQueryModels.ts new file mode 100644 index 000000000..b9fe31419 --- /dev/null +++ b/src/utils/writeQueryModels.ts @@ -0,0 +1,48 @@ +import camelcase from 'camelcase'; +import { resolve } from 'path'; + +import type { Model } from '../client/interfaces/Model'; +import { Service } from '../client/interfaces/Service'; +import type { HttpClient } from '../HttpClient'; +import type { Indent } from '../Indent'; +import { writeFile } from './fileSystem'; +import { formatCode as f } from './formatCode'; +import { formatIndentation as i } from './formatIndentation'; +import { toHyphenCase } from './hyphenCase'; +import type { Templates } from './registerHandlebarTemplates'; + +/** + * Generate Models using the Handlebar template and write to disk. + * @param models Array of Models to write + * @param templates The loaded handlebar templates + * @param outputPath Directory to write the generated files to + * @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) + */ +export const writeQueryModels = async ( + services: Service[], + templates: Templates, + outputPath: string, + httpClient: HttpClient, + useUnionTypes: boolean, + indent: Indent +): Promise => { + for (const service of services) { + for (const operation of service.operations) { + if (operation.parameters.filter(param => param.in !== 'body').length === 0) { + continue; + } + const modelName = camelcase(operation.name, { pascalCase: true }); + const modelNameHyphens = toHyphenCase(modelName); + const file = resolve(outputPath, `${modelNameHyphens}-params.ts`); + + const templateResult = templates.exports.queryModel({ + ...operation, + httpClient, + useUnionTypes, + }); + await writeFile(file, i(f(templateResult), indent)); + } + } +}; diff --git a/src/utils/writeServerInterfaces.ts b/src/utils/writeServerInterfaces.ts new file mode 100644 index 000000000..1dd8ddd92 --- /dev/null +++ b/src/utils/writeServerInterfaces.ts @@ -0,0 +1,58 @@ +import { resolve } from 'path'; + +import type { Service } from '../client/interfaces/Service'; +import type { HttpClient } from '../HttpClient'; +import type { Indent } from '../Indent'; +import { writeFile } from './fileSystem'; +import { formatCode as f } from './formatCode'; +import { formatIndentation as i } from './formatIndentation'; +import { toHyphenCase } from './hyphenCase'; +import { isDefined } from './isDefined'; +import type { Templates } from './registerHandlebarTemplates'; + +/** + * Generate Services using the Handlebar template and write to disk. + * @param services Array of Services to write + * @param templates The loaded handlebar templates + * @param outputPath Directory to write the generated files to + * @param httpClient The selected httpClient (fetch, xhr, node or axios) + * @param useUnionTypes Use union types instead of enums + * @param useOptions Use options or arguments functions + * @param indent Indentation options (4, 2 or tab) + * @param postfix Service name postfix + * @param clientName Custom client class name + */ +export const writeServerInterfaces = async ( + services: Service[], + templates: Templates, + outputPath: string, + serverModelImportPath: string, + serverApiTypesImportPath: string, + serverReqTypeName: string, + serverResTypeName: string, + httpClient: HttpClient, + useUnionTypes: boolean, + useOptions: boolean, + indent: Indent, + postfix: string, + clientName?: string +): Promise => { + for (const service of services) { + const serviceNameHyphens = toHyphenCase(service.name); + const file = resolve(outputPath, `${serviceNameHyphens}-${toHyphenCase(postfix)}.ts`); + serverModelImportPath = serverModelImportPath; + const templateResult = templates.exports.serverInterface({ + ...service, + serverModelImportPath, + serverApiTypesImportPath, + serverReqTypeName, + serverResTypeName, + httpClient, + useUnionTypes, + useOptions, + postfix, + exportClient: isDefined(clientName), + }); + await writeFile(file, i(f(templateResult), indent)); + } +}; From 341bcf0e4b83200cdf6a065ed96a63b8ae8bc835 Mon Sep 17 00:00:00 2001 From: Yonatan Refaeli Date: Thu, 2 Jun 2022 03:10:27 -0400 Subject: [PATCH 02/23] Add createIndex and modelsDirName options --- bin/index.js | 4 ++++ src/index.ts | 11 ++++++++++- src/utils/writeClient.spec.ts | 1 + src/utils/writeClient.ts | 16 ++++++++++------ 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/bin/index.js b/bin/index.js index d4647aa97..d7708b6ac 100755 --- a/bin/index.js +++ b/bin/index.js @@ -12,6 +12,7 @@ const params = program .version(pkg.version) .requiredOption('-i, --input ', 'OpenAPI specification, can be a path, url or string content (required)') .requiredOption('-o, --output ', 'Output directory (required)') + .option('--modelsDirName ', 'Models directory name') .option('--serverOutput ', 'Server output directory') .option('--serverDirName ', 'Server directory name') .option('--serverModelImportPath ', 'Server model import path') @@ -29,6 +30,7 @@ const params = program .option('--indent ', 'Indentation options [4, 2, tabs]', '4') .option('--postfix ', 'Service name postfix', 'Service') .option('--request ', 'Path to custom request file') + .option('--createIndex ', 'Generate barrel index file', true) .parse(process.argv) .opts(); @@ -39,6 +41,7 @@ if (OpenAPI) { input: params.input, output: params.output, serverOutput: params.serverOutput, + modelsDirName: params.modelsDirName, serverDirName: params.serverDirName, serverModelImportPath: params.serverModelImportPath, serverApiTypesImportPath: params.serverApiTypesImportPath, @@ -55,6 +58,7 @@ if (OpenAPI) { indent: params.indent, postfix: params.postfix, request: params.request, + createIndex: params.createIndex, }) .then(() => { process.exit(0); diff --git a/src/index.ts b/src/index.ts index 4cdfee428..9996bc188 100644 --- a/src/index.ts +++ b/src/index.ts @@ -15,6 +15,7 @@ export { Indent } from './Indent'; export type Options = { input: string | Record; output: string; + modelsDirName?: string; serverOutput?: string; serverDirName?: string; serverModelImportPath?: string; @@ -35,6 +36,7 @@ export type Options = { postfix?: string; request?: string; write?: boolean; + createIndex?: boolean; }; /** @@ -43,6 +45,7 @@ export type Options = { * service layer, etc. * @param input The relative location of the OpenAPI spec * @param output The relative location of the output directory + * @param modelsDirName Models directory name * @param httpClient The selected httpClient (fetch, xhr, node or axios) * @param clientName Custom client class name * @param useOptions Use options or arguments functions @@ -55,10 +58,12 @@ export type Options = { * @param postfix Service name postfix * @param request Path to custom request file * @param write Write the files to disk (true or false) + * @param createIndex Generate barrel index file */ export const generate = async ({ input, output, + modelsDirName = 'models', serverOutput, serverDirName = 'server', serverModelImportPath = '', @@ -79,6 +84,7 @@ export const generate = async ({ postfix = 'Service', request, write = true, + createIndex = true, }: Options): Promise => { const openApi = isString(input) ? await getOpenApiSpec(input) : input; const openApiVersion = getOpenApiVersion(openApi); @@ -97,6 +103,7 @@ export const generate = async ({ clientFinal, templates, output, + modelsDirName, serverOutput ?? output, serverDirName, serverModelImportPath, @@ -115,7 +122,8 @@ export const generate = async ({ indent, postfix, clientName, - request + request, + createIndex ); break; } @@ -128,6 +136,7 @@ export const generate = async ({ clientFinal, templates, output, + modelsDirName, serverOutput ?? output, serverDirName, serverModelImportPath, diff --git a/src/utils/writeClient.spec.ts b/src/utils/writeClient.spec.ts index 6fffb21ae..edb319a01 100644 --- a/src/utils/writeClient.spec.ts +++ b/src/utils/writeClient.spec.ts @@ -42,6 +42,7 @@ describe('writeClient', () => { client, templates, './dist', + 'models', './dist', 'server', '../models', diff --git a/src/utils/writeClient.ts b/src/utils/writeClient.ts index 93103c24c..f33b9fa11 100644 --- a/src/utils/writeClient.ts +++ b/src/utils/writeClient.ts @@ -26,18 +26,21 @@ import { writeServerInterfaces } from './writeServerInterfaces'; * @param useUnionTypes Use union types instead of enums * @param exportCore Generate core client classes * @param exportServices Generate services + * @param exportServerInterfaces Generate server interfaces * @param exportModels Generate models - * @param exportSchemas Generate schemas + * @param exportQueryModels Generate query models * @param exportSchemas Generate schemas * @param indent Indentation options (4, 2 or tab) * @param postfix Service name postfix * @param clientName Custom client class name * @param request Path to custom request file + * @param createIndex Generate barrel index file */ export const writeClient = async ( client: Client, templates: Templates, output: string, + modelsDirName: string, serverOutput: string, serverDirName: string, serverModelImportPath: string, @@ -56,12 +59,13 @@ export const writeClient = async ( indent: Indent, postfix: string, clientName?: string, - request?: string + request?: string, + createIndex?: boolean ): Promise => { const outputPath = resolve(process.cwd(), output); const serverOutputPath = resolve(process.cwd(), serverOutput); const outputPathCore = resolve(outputPath, 'core'); - const outputPathModels = resolve(outputPath, 'models'); + const outputPathModels = resolve(outputPath, modelsDirName); const outputPathSchemas = resolve(outputPath, 'schemas'); const outputPathServices = resolve(outputPath, 'services'); const outputPathServerInterfaces = resolve(serverOutputPath, serverDirName); @@ -119,8 +123,8 @@ export const writeClient = async ( } if (exportModels) { - await rmdir(outputPathModels); - await mkdir(outputPathModels); + // await rmdir(outputPathModels); + // await mkdir(outputPathModels); await writeClientModels(client.models, templates, outputPathModels, httpClient, useUnionTypes, indent); } @@ -133,7 +137,7 @@ export const writeClient = async ( await writeClientClass(client, templates, outputPath, httpClient, clientName, indent, postfix); } - if (exportCore || exportServices || exportSchemas || exportModels) { + if (createIndex && (exportCore || exportServices || exportSchemas || exportModels)) { await mkdir(outputPath); await writeClientIndex( client, From d66c795bef48f7cbace2940a070f74aed6314f1e Mon Sep 17 00:00:00 2001 From: Yonatan Refaeli Date: Mon, 6 Jun 2022 20:04:26 -0400 Subject: [PATCH 03/23] Add routeHandler generator and additional options --- bin/index.js | 6 +++ package.json | 3 +- src/index.ts | 12 +++++ src/templates/exportRouteHandler.hbs | 17 +++++++ src/utils/formatCode.ts | 2 +- src/utils/registerHandlebarTemplates.ts | 3 ++ src/utils/writeClient.spec.ts | 4 ++ src/utils/writeClient.ts | 25 ++++++++++ src/utils/writeClientClass.spec.ts | 1 + src/utils/writeClientCore.spec.ts | 1 + src/utils/writeClientIndex.spec.ts | 1 + src/utils/writeClientModels.spec.ts | 1 + src/utils/writeClientSchemas.spec.ts | 1 + src/utils/writeClientServices.spec.ts | 1 + src/utils/writeRouteHandler.ts | 61 +++++++++++++++++++++++++ src/utils/writeServerInterfaces.ts | 2 +- 16 files changed, 138 insertions(+), 3 deletions(-) create mode 100644 src/templates/exportRouteHandler.hbs create mode 100644 src/utils/writeRouteHandler.ts diff --git a/bin/index.js b/bin/index.js index d7708b6ac..1d2101949 100755 --- a/bin/index.js +++ b/bin/index.js @@ -19,6 +19,9 @@ const params = program .option('--serverApiTypesImportPath ', 'Server Api Types import path') .option('--serverReqTypeName ', 'Name of Server Request type to use') .option('--serverResTypeName ', 'Name of Server Response type to use') + .option('--exportRouteHandler', 'create a route handler to map routes to controller methods') + .option('--transformFuncName ', 'Name of request transformation function') + .option('--transformFuncPath ', 'Import path of request transformation function') .option('-c, --client ', 'HTTP client to generate [fetch, xhr, node, axios, angular]', 'fetch') .option('--name ', 'Custom client class name') .option('--useOptions', 'Use options instead of arguments') @@ -47,6 +50,9 @@ if (OpenAPI) { serverApiTypesImportPath: params.serverApiTypesImportPath, serverReqTypeName: params.serverReqTypeName, serverResTypeName: params.serverResTypeName, + exportRouteHandler: params.exportRouteHandler, + transformFuncName: params.transformFuncName, + transformFuncPath: params.transformFuncPath, httpClient: params.client, clientName: params.name, useOptions: params.useOptions, diff --git a/package.json b/package.json index 53dd7cd54..78d1c31b1 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,8 @@ "eslint": "eslint .", "eslint:fix": "eslint . --fix", "prepublishOnly": "npm run clean && npm run release", - "codecov": "codecov --token=66c30c23-8954-4892-bef9-fbaed0a2e42b" + "codecov": "codecov --token=66c30c23-8954-4892-bef9-fbaed0a2e42b", + "generate": "node ./test-script" }, "dependencies": { "camelcase": "^6.3.0", diff --git a/src/index.ts b/src/index.ts index 9996bc188..61a584951 100644 --- a/src/index.ts +++ b/src/index.ts @@ -22,6 +22,9 @@ export type Options = { serverApiTypesImportPath?: string; serverReqTypeName?: string; serverResTypeName?: string; + exportRouteHandler?: boolean; + transformFuncName?: string; + transformFuncPath?: string; httpClient?: HttpClient; clientName?: string; useOptions?: boolean; @@ -70,6 +73,9 @@ export const generate = async ({ serverApiTypesImportPath = '', serverReqTypeName = 'ApiRequestWrapper', serverResTypeName = 'ApiResponseWrapper', + exportRouteHandler = false, + transformFuncName = 'transformApiRequest', + transformFuncPath = './util/transform-api-request', httpClient = HttpClient.FETCH, clientName, useOptions = false, @@ -110,6 +116,9 @@ export const generate = async ({ serverApiTypesImportPath, serverReqTypeName, serverResTypeName, + exportRouteHandler, + transformFuncName, + transformFuncPath, httpClient, useOptions, useUnionTypes, @@ -143,6 +152,9 @@ export const generate = async ({ serverApiTypesImportPath, serverReqTypeName, serverResTypeName, + exportRouteHandler, + transformFuncName, + transformFuncPath, httpClient, useOptions, useUnionTypes, diff --git a/src/templates/exportRouteHandler.hbs b/src/templates/exportRouteHandler.hbs new file mode 100644 index 000000000..83a4b7118 --- /dev/null +++ b/src/templates/exportRouteHandler.hbs @@ -0,0 +1,17 @@ +{{#each services}} +import { {{{pascalCase name}}}{{{@root.postfix}}} } from './{{{@root.serverDirName}}}/{{{hyphenCase name}}}-{{{hyphenCase @root.postfix}}}'; +{{/each}} +import { {{{transformFuncName}}} as transformOutbound } from '{{{transformFuncPath}}}'; + +export class RouteHandler { + constructor( + {{#each services}} + private {{{camelCase name}}}: {{{pascalCase name}}}{{{@root.postfix}}}, + {{/each}} + ) { } +{{#each services}} +{{#each operations}} + {{{name}}} = req => this.{{{camelCase service}}}.{{{name}}}(transformOutbound(req)); +{{/each}} +{{/each}} +} diff --git a/src/utils/formatCode.ts b/src/utils/formatCode.ts index 42cfd5cf4..9791b7163 100644 --- a/src/utils/formatCode.ts +++ b/src/utils/formatCode.ts @@ -19,5 +19,5 @@ export const formatCode = (s: string): string => { } return result; }); - return lines.join(EOL); + return lines.join(EOL) + EOL; }; diff --git a/src/utils/registerHandlebarTemplates.ts b/src/utils/registerHandlebarTemplates.ts index 28ce54611..418e2cb37 100644 --- a/src/utils/registerHandlebarTemplates.ts +++ b/src/utils/registerHandlebarTemplates.ts @@ -55,6 +55,7 @@ import xhrRequest from '../templates/core/xhr/request.hbs'; import xhrSendRequest from '../templates/core/xhr/sendRequest.hbs'; import templateExportModel from '../templates/exportModel.hbs'; import templateExportQueryModel from '../templates/exportQueryModel.hbs'; +import templateExportRouteHandler from '../templates/exportRouteHandler.hbs'; import templateExportSchema from '../templates/exportSchema.hbs'; import templateExportServerInterface from '../templates/exportServerInterface.hbs'; import templateExportService from '../templates/exportService.hbs'; @@ -97,6 +98,7 @@ export interface Templates { schema: Handlebars.TemplateDelegate; service: Handlebars.TemplateDelegate; serverInterface: Handlebars.TemplateDelegate; + routeHandler: Handlebars.TemplateDelegate; }; core: { settings: Handlebars.TemplateDelegate; @@ -131,6 +133,7 @@ export const registerHandlebarTemplates = (root: { schema: Handlebars.template(templateExportSchema), service: Handlebars.template(templateExportService), serverInterface: Handlebars.template(templateExportServerInterface), + routeHandler: Handlebars.template(templateExportRouteHandler), }, core: { settings: Handlebars.template(templateCoreSettings), diff --git a/src/utils/writeClient.spec.ts b/src/utils/writeClient.spec.ts index edb319a01..722fff24a 100644 --- a/src/utils/writeClient.spec.ts +++ b/src/utils/writeClient.spec.ts @@ -25,6 +25,7 @@ describe('writeClient', () => { schema: () => 'schema', service: () => 'service', serverInterface: () => 'serverInterface', + routeHandler: () => 'routeHandler', }, core: { settings: () => 'settings', @@ -49,6 +50,9 @@ describe('writeClient', () => { '', 'ApiRequestWrapper', 'ApiResponseWrapper', + false, + '', + '', HttpClient.FETCH, false, false, diff --git a/src/utils/writeClient.ts b/src/utils/writeClient.ts index f33b9fa11..cf1459dbb 100644 --- a/src/utils/writeClient.ts +++ b/src/utils/writeClient.ts @@ -14,6 +14,7 @@ import { writeClientModels } from './writeClientModels'; import { writeClientSchemas } from './writeClientSchemas'; import { writeClientServices } from './writeClientServices'; import { writeQueryModels } from './writeQueryModels'; +import { writeRouteHandler } from './writeRouteHandler'; import { writeServerInterfaces } from './writeServerInterfaces'; /** @@ -47,6 +48,9 @@ export const writeClient = async ( serverApiTypesImportPath: string, serverReqTypeName: string, serverResTypeName: string, + exportRouteHandler: boolean, + transformFuncName: string, + transformFuncPath: string, httpClient: HttpClient, useOptions: boolean, useUnionTypes: boolean, @@ -116,6 +120,27 @@ export const writeClient = async ( ); } + if (exportRouteHandler) { + await writeRouteHandler( + client.services, + templates, + serverOutputPath, + serverDirName, + serverModelImportPath, + serverApiTypesImportPath, + serverReqTypeName, + serverResTypeName, + transformFuncName, + transformFuncPath, + httpClient, + useUnionTypes, + useOptions, + indent, + postfix, + clientName + ); + } + if (exportSchemas) { await rmdir(outputPathSchemas); await mkdir(outputPathSchemas); diff --git a/src/utils/writeClientClass.spec.ts b/src/utils/writeClientClass.spec.ts index 9ab157699..a1cbb6a90 100644 --- a/src/utils/writeClientClass.spec.ts +++ b/src/utils/writeClientClass.spec.ts @@ -25,6 +25,7 @@ describe('writeClientClass', () => { schema: () => 'schema', service: () => 'service', serverInterface: () => 'serverInterface', + routeHandler: () => 'routeHandler', }, core: { settings: () => 'settings', diff --git a/src/utils/writeClientCore.spec.ts b/src/utils/writeClientCore.spec.ts index 0283703f5..c700f6863 100644 --- a/src/utils/writeClientCore.spec.ts +++ b/src/utils/writeClientCore.spec.ts @@ -25,6 +25,7 @@ describe('writeClientCore', () => { schema: () => 'schema', service: () => 'service', serverInterface: () => 'serverInterface', + routeHandler: () => 'routeHandler', }, core: { settings: () => 'settings', diff --git a/src/utils/writeClientIndex.spec.ts b/src/utils/writeClientIndex.spec.ts index 450ad629f..09dcbec4f 100644 --- a/src/utils/writeClientIndex.spec.ts +++ b/src/utils/writeClientIndex.spec.ts @@ -23,6 +23,7 @@ describe('writeClientIndex', () => { schema: () => 'schema', service: () => 'service', serverInterface: () => 'serverInterface', + routeHandler: () => 'routeHandler', }, core: { settings: () => 'settings', diff --git a/src/utils/writeClientModels.spec.ts b/src/utils/writeClientModels.spec.ts index ecb946bbd..4e40b4bd9 100644 --- a/src/utils/writeClientModels.spec.ts +++ b/src/utils/writeClientModels.spec.ts @@ -38,6 +38,7 @@ describe('writeClientModels', () => { schema: () => 'schema', service: () => 'service', serverInterface: () => 'serverInterface', + routeHandler: () => 'routeHandler', }, core: { settings: () => 'settings', diff --git a/src/utils/writeClientSchemas.spec.ts b/src/utils/writeClientSchemas.spec.ts index 8568486c4..083c462db 100644 --- a/src/utils/writeClientSchemas.spec.ts +++ b/src/utils/writeClientSchemas.spec.ts @@ -38,6 +38,7 @@ describe('writeClientSchemas', () => { schema: () => 'schema', service: () => 'service', serverInterface: () => 'serverInterface', + routeHandler: () => 'routeHandler', }, core: { settings: () => 'settings', diff --git a/src/utils/writeClientServices.spec.ts b/src/utils/writeClientServices.spec.ts index db52208df..89707737d 100644 --- a/src/utils/writeClientServices.spec.ts +++ b/src/utils/writeClientServices.spec.ts @@ -26,6 +26,7 @@ describe('writeClientServices', () => { schema: () => 'schema', service: () => 'service', serverInterface: () => 'serverInterface', + routeHandler: () => 'routeHandler', }, core: { settings: () => 'settings', diff --git a/src/utils/writeRouteHandler.ts b/src/utils/writeRouteHandler.ts new file mode 100644 index 000000000..b2d96ffc0 --- /dev/null +++ b/src/utils/writeRouteHandler.ts @@ -0,0 +1,61 @@ +import { resolve } from 'path'; + +import type { Service } from '../client/interfaces/Service'; +import type { HttpClient } from '../HttpClient'; +import type { Indent } from '../Indent'; +import { writeFile } from './fileSystem'; +import { formatCode as f } from './formatCode'; +import { formatIndentation as i } from './formatIndentation'; +import { isDefined } from './isDefined'; +import type { Templates } from './registerHandlebarTemplates'; + +/** + * Generate Services using the Handlebar template and write to disk. + * @param services Array of Services to write + * @param templates The loaded handlebar templates + * @param outputPath Directory to write the generated files to + * @param httpClient The selected httpClient (fetch, xhr, node or axios) + * @param useUnionTypes Use union types instead of enums + * @param useOptions Use options or arguments functions + * @param indent Indentation options (4, 2 or tab) + * @param postfix Service name postfix + * @param clientName Custom client class name + */ +export const writeRouteHandler = async ( + services: Service[], + templates: Templates, + outputPath: string, + serverDirName: string, + serverModelImportPath: string, + serverApiTypesImportPath: string, + serverReqTypeName: string, + serverResTypeName: string, + transformFuncName: string, + transformFuncPath: string, + httpClient: HttpClient, + useUnionTypes: boolean, + useOptions: boolean, + indent: Indent, + postfix: string, + clientName?: string +): Promise => { + // const serviceNameHyphens = toHyphenCase(service.name); + const file = resolve(outputPath, `route-handler.ts`); + serverModelImportPath = serverModelImportPath; + const templateResult = templates.exports.routeHandler({ + services, + serverDirName, + serverModelImportPath, + serverApiTypesImportPath, + serverReqTypeName, + serverResTypeName, + transformFuncName, + transformFuncPath, + httpClient, + useUnionTypes, + useOptions, + postfix, + exportClient: isDefined(clientName), + }); + await writeFile(file, i(f(templateResult), indent)); +}; diff --git a/src/utils/writeServerInterfaces.ts b/src/utils/writeServerInterfaces.ts index 1dd8ddd92..b691846a4 100644 --- a/src/utils/writeServerInterfaces.ts +++ b/src/utils/writeServerInterfaces.ts @@ -39,7 +39,7 @@ export const writeServerInterfaces = async ( ): Promise => { for (const service of services) { const serviceNameHyphens = toHyphenCase(service.name); - const file = resolve(outputPath, `${serviceNameHyphens}-${toHyphenCase(postfix)}.ts`); + const file = resolve(outputPath, `i-${serviceNameHyphens}-${toHyphenCase(postfix)}.ts`); serverModelImportPath = serverModelImportPath; const templateResult = templates.exports.serverInterface({ ...service, From 853c36328f5b1de2a0e9eb09bfd0289258657a95 Mon Sep 17 00:00:00 2001 From: Yonatan Refaeli Date: Tue, 7 Jun 2022 02:50:03 -0400 Subject: [PATCH 04/23] Update package version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 78d1c31b1..d5516b4cc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "openapi-typescript-codegen", - "version": "0.22.0", + "version": "0.2.0", "description": "Library that generates Typescript clients based on the OpenAPI specification.", "author": "Ferdi Koomen", "homepage": "https://github.com/ferdikoomen/openapi-typescript-codegen", From e8703ae28c7dfb7883366cdbc1b2fe38a74cbb34 Mon Sep 17 00:00:00 2001 From: Yonatan Refaeli Date: Wed, 8 Jun 2022 17:44:23 -0400 Subject: [PATCH 05/23] remove npm script for generate --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index d5516b4cc..7b7e36a4d 100644 --- a/package.json +++ b/package.json @@ -56,8 +56,7 @@ "eslint": "eslint .", "eslint:fix": "eslint . --fix", "prepublishOnly": "npm run clean && npm run release", - "codecov": "codecov --token=66c30c23-8954-4892-bef9-fbaed0a2e42b", - "generate": "node ./test-script" + "codecov": "codecov --token=66c30c23-8954-4892-bef9-fbaed0a2e42b" }, "dependencies": { "camelcase": "^6.3.0", From 8a10e2b1dfd41d55b1dee431dc3e0b98ffbb7d39 Mon Sep 17 00:00:00 2001 From: Yonatan Refaeli Date: Wed, 8 Jun 2022 17:51:44 -0400 Subject: [PATCH 06/23] Update package metadata --- package.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 7b7e36a4d..35ac70090 100644 --- a/package.json +++ b/package.json @@ -1,15 +1,15 @@ { - "name": "openapi-typescript-codegen", + "name": "@yrefaeli/openapi-typescript-codegen", "version": "0.2.0", "description": "Library that generates Typescript clients based on the OpenAPI specification.", - "author": "Ferdi Koomen", - "homepage": "https://github.com/ferdikoomen/openapi-typescript-codegen", + "author": "Yon Refaeli", + "homepage": "https://github.com/yrefaeli/openapi-typescript-codegen", "repository": { "type": "git", - "url": "git+https://github.com/ferdikoomen/openapi-typescript-codegen.git" + "url": "git+https://github.com/yrefaeli/openapi-typescript-codegen.git" }, "bugs": { - "url": "https://github.com/ferdikoomen/openapi-typescript-codegen/issues" + "url": "https://github.com/yrefaeli/openapi-typescript-codegen/issues" }, "license": "MIT", "keywords": [ @@ -27,8 +27,8 @@ ], "maintainers": [ { - "name": "Ferdi Koomen", - "email": "info@madebyferdi.com" + "name": "Yon Refaeli", + "email": "yondev001@gmail.com" } ], "main": "dist/index.js", From 5a3b833dd5fac70918b52d9595f6a671062ba980 Mon Sep 17 00:00:00 2001 From: Yonatan Refaeli Date: Sun, 12 Jun 2022 01:52:59 -0400 Subject: [PATCH 07/23] Add transformResFuncName param --- bin/index.js | 6 ++++-- src/index.ts | 12 ++++++++---- src/templates/exportRouteHandler.hbs | 15 +++++++++++++-- src/utils/writeClient.spec.ts | 1 + src/utils/writeClient.ts | 6 ++++-- src/utils/writeRouteHandler.ts | 6 ++++-- 6 files changed, 34 insertions(+), 12 deletions(-) diff --git a/bin/index.js b/bin/index.js index 1d2101949..cc5ca5748 100755 --- a/bin/index.js +++ b/bin/index.js @@ -20,7 +20,8 @@ const params = program .option('--serverReqTypeName ', 'Name of Server Request type to use') .option('--serverResTypeName ', 'Name of Server Response type to use') .option('--exportRouteHandler', 'create a route handler to map routes to controller methods') - .option('--transformFuncName ', 'Name of request transformation function') + .option('--transformReqFuncName ', 'Name of request transformation function') + .option('--transformResFuncName ', 'Name of response transformation function') .option('--transformFuncPath ', 'Import path of request transformation function') .option('-c, --client ', 'HTTP client to generate [fetch, xhr, node, axios, angular]', 'fetch') .option('--name ', 'Custom client class name') @@ -51,7 +52,8 @@ if (OpenAPI) { serverReqTypeName: params.serverReqTypeName, serverResTypeName: params.serverResTypeName, exportRouteHandler: params.exportRouteHandler, - transformFuncName: params.transformFuncName, + transformReqFuncName: params.transformReqFuncName, + transformResFuncName: params.transformResFuncName, transformFuncPath: params.transformFuncPath, httpClient: params.client, clientName: params.name, diff --git a/src/index.ts b/src/index.ts index 61a584951..f9a674354 100644 --- a/src/index.ts +++ b/src/index.ts @@ -23,7 +23,8 @@ export type Options = { serverReqTypeName?: string; serverResTypeName?: string; exportRouteHandler?: boolean; - transformFuncName?: string; + transformReqFuncName?: string; + transformResFuncName?: string; transformFuncPath?: string; httpClient?: HttpClient; clientName?: string; @@ -74,7 +75,8 @@ export const generate = async ({ serverReqTypeName = 'ApiRequestWrapper', serverResTypeName = 'ApiResponseWrapper', exportRouteHandler = false, - transformFuncName = 'transformApiRequest', + transformReqFuncName = 'transformApiRequest', + transformResFuncName = 'transformApiResponse', transformFuncPath = './util/transform-api-request', httpClient = HttpClient.FETCH, clientName, @@ -117,7 +119,8 @@ export const generate = async ({ serverReqTypeName, serverResTypeName, exportRouteHandler, - transformFuncName, + transformReqFuncName, + transformResFuncName, transformFuncPath, httpClient, useOptions, @@ -153,7 +156,8 @@ export const generate = async ({ serverReqTypeName, serverResTypeName, exportRouteHandler, - transformFuncName, + transformReqFuncName, + transformResFuncName, transformFuncPath, httpClient, useOptions, diff --git a/src/templates/exportRouteHandler.hbs b/src/templates/exportRouteHandler.hbs index 83a4b7118..8eb3dfac3 100644 --- a/src/templates/exportRouteHandler.hbs +++ b/src/templates/exportRouteHandler.hbs @@ -1,7 +1,10 @@ {{#each services}} import { {{{pascalCase name}}}{{{@root.postfix}}} } from './{{{@root.serverDirName}}}/{{{hyphenCase name}}}-{{{hyphenCase @root.postfix}}}'; {{/each}} -import { {{{transformFuncName}}} as transformOutbound } from '{{{transformFuncPath}}}'; +import { + {{{transformReqFuncName}}} as transformRequest, + {{{transformResFuncName}}} as transformResponse +} from '{{{transformFuncPath}}}'; export class RouteHandler { constructor( @@ -9,9 +12,17 @@ export class RouteHandler { private {{{camelCase name}}}: {{{pascalCase name}}}{{{@root.postfix}}}, {{/each}} ) { } + + private applyTransforms(req, reply, handlerFunc) { + const transformedRequest = transformRequest(req); + const handlerResponse = handlerFunc(transformedRequest); + const transformedResponse = transformResponse(handlerResponse, reply); + return transformedResponse; + } + {{#each services}} {{#each operations}} - {{{name}}} = req => this.{{{camelCase service}}}.{{{name}}}(transformOutbound(req)); + {{{name}}} = (req, reply) => (req, reply, this.{{{camelCase service}}}.{{{name}}}); {{/each}} {{/each}} } diff --git a/src/utils/writeClient.spec.ts b/src/utils/writeClient.spec.ts index 722fff24a..64933eb75 100644 --- a/src/utils/writeClient.spec.ts +++ b/src/utils/writeClient.spec.ts @@ -53,6 +53,7 @@ describe('writeClient', () => { false, '', '', + '', HttpClient.FETCH, false, false, diff --git a/src/utils/writeClient.ts b/src/utils/writeClient.ts index cf1459dbb..897ae7234 100644 --- a/src/utils/writeClient.ts +++ b/src/utils/writeClient.ts @@ -49,7 +49,8 @@ export const writeClient = async ( serverReqTypeName: string, serverResTypeName: string, exportRouteHandler: boolean, - transformFuncName: string, + transformReqFuncName: string, + transformResFuncName: string, transformFuncPath: string, httpClient: HttpClient, useOptions: boolean, @@ -130,7 +131,8 @@ export const writeClient = async ( serverApiTypesImportPath, serverReqTypeName, serverResTypeName, - transformFuncName, + transformReqFuncName, + transformResFuncName, transformFuncPath, httpClient, useUnionTypes, diff --git a/src/utils/writeRouteHandler.ts b/src/utils/writeRouteHandler.ts index b2d96ffc0..830e2736d 100644 --- a/src/utils/writeRouteHandler.ts +++ b/src/utils/writeRouteHandler.ts @@ -30,7 +30,8 @@ export const writeRouteHandler = async ( serverApiTypesImportPath: string, serverReqTypeName: string, serverResTypeName: string, - transformFuncName: string, + transformReqFuncName: string, + transformResFuncName: string, transformFuncPath: string, httpClient: HttpClient, useUnionTypes: boolean, @@ -49,7 +50,8 @@ export const writeRouteHandler = async ( serverApiTypesImportPath, serverReqTypeName, serverResTypeName, - transformFuncName, + transformReqFuncName, + transformResFuncName, transformFuncPath, httpClient, useUnionTypes, From 5f67b109f53b9205455b6a38173df27a88e05e0c Mon Sep 17 00:00:00 2001 From: Yonatan Refaeli Date: Sun, 12 Jun 2022 02:22:52 -0400 Subject: [PATCH 08/23] update version to 0.2.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 35ac70090..e8cf8879e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@yrefaeli/openapi-typescript-codegen", - "version": "0.2.0", + "version": "0.2.1", "description": "Library that generates Typescript clients based on the OpenAPI specification.", "author": "Yon Refaeli", "homepage": "https://github.com/yrefaeli/openapi-typescript-codegen", From 40c95a9adaa7ae65f0943d60b6771524dd0ca4f6 Mon Sep 17 00:00:00 2001 From: Yonatan Refaeli Date: Sun, 12 Jun 2022 02:45:38 -0400 Subject: [PATCH 09/23] Fix missing function name --- src/templates/exportRouteHandler.hbs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/templates/exportRouteHandler.hbs b/src/templates/exportRouteHandler.hbs index 8eb3dfac3..94bb0fd7b 100644 --- a/src/templates/exportRouteHandler.hbs +++ b/src/templates/exportRouteHandler.hbs @@ -22,7 +22,7 @@ export class RouteHandler { {{#each services}} {{#each operations}} - {{{name}}} = (req, reply) => (req, reply, this.{{{camelCase service}}}.{{{name}}}); + {{{name}}} = (req, reply) => this.applyTransforms(req, reply, this.{{{camelCase service}}}.{{{name}}}); {{/each}} {{/each}} } From 70581672cd3120e03cf06533556f7a26ea41a60b Mon Sep 17 00:00:00 2001 From: Yonatan Refaeli Date: Sun, 12 Jun 2022 02:54:06 -0400 Subject: [PATCH 10/23] Update version to 0.2.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e8cf8879e..7f4d0987b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@yrefaeli/openapi-typescript-codegen", - "version": "0.2.1", + "version": "0.2.2", "description": "Library that generates Typescript clients based on the OpenAPI specification.", "author": "Yon Refaeli", "homepage": "https://github.com/yrefaeli/openapi-typescript-codegen", From 07b3716388e0ebf6340219bbc4820825088a91bf Mon Sep 17 00:00:00 2001 From: Yonatan Refaeli Date: Sun, 12 Jun 2022 03:01:58 -0400 Subject: [PATCH 11/23] update version to 0.2.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7f4d0987b..338ec0a15 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@yrefaeli/openapi-typescript-codegen", - "version": "0.2.2", + "version": "0.2.3", "description": "Library that generates Typescript clients based on the OpenAPI specification.", "author": "Yon Refaeli", "homepage": "https://github.com/yrefaeli/openapi-typescript-codegen", From 364b363f2e4b0eae4d538bd908c070b7d3b7c6aa Mon Sep 17 00:00:00 2001 From: Yonatan Refaeli Date: Wed, 15 Jun 2022 15:24:02 -0400 Subject: [PATCH 12/23] add di capabilities --- src/templates/exportRouteHandler.hbs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/templates/exportRouteHandler.hbs b/src/templates/exportRouteHandler.hbs index 94bb0fd7b..3d0db5ae0 100644 --- a/src/templates/exportRouteHandler.hbs +++ b/src/templates/exportRouteHandler.hbs @@ -5,11 +5,13 @@ import { {{{transformReqFuncName}}} as transformRequest, {{{transformResFuncName}}} as transformResponse } from '{{{transformFuncPath}}}'; +import { inject, injectable } from 'tsyringe'; +@injectable() export class RouteHandler { constructor( {{#each services}} - private {{{camelCase name}}}: {{{pascalCase name}}}{{{@root.postfix}}}, + @inject("{{{pascalCase name}}}{{{@root.postfix}}}") private {{{camelCase name}}}: {{{pascalCase name}}}{{{@root.postfix}}}, {{/each}} ) { } From 1bcfcb70e0611a51de00d3920f13a7fa589a9165 Mon Sep 17 00:00:00 2001 From: Yonatan Refaeli Date: Wed, 15 Jun 2022 15:24:59 -0400 Subject: [PATCH 13/23] Update version to 0.2.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7f4d0987b..608a8f632 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@yrefaeli/openapi-typescript-codegen", - "version": "0.2.2", + "version": "0.2.4", "description": "Library that generates Typescript clients based on the OpenAPI specification.", "author": "Yon Refaeli", "homepage": "https://github.com/yrefaeli/openapi-typescript-codegen", From cd3d270a6839aa1c427b2d883881c779d6bc6a0d Mon Sep 17 00:00:00 2001 From: Yonatan Refaeli Date: Wed, 15 Jun 2022 15:38:14 -0400 Subject: [PATCH 14/23] Add 'i' to controller interface names and update version to 0.2.5 --- package.json | 2 +- src/templates/exportRouteHandler.hbs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 608a8f632..e92494712 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@yrefaeli/openapi-typescript-codegen", - "version": "0.2.4", + "version": "0.2.5", "description": "Library that generates Typescript clients based on the OpenAPI specification.", "author": "Yon Refaeli", "homepage": "https://github.com/yrefaeli/openapi-typescript-codegen", diff --git a/src/templates/exportRouteHandler.hbs b/src/templates/exportRouteHandler.hbs index 3d0db5ae0..404cdec0a 100644 --- a/src/templates/exportRouteHandler.hbs +++ b/src/templates/exportRouteHandler.hbs @@ -1,5 +1,5 @@ {{#each services}} -import { {{{pascalCase name}}}{{{@root.postfix}}} } from './{{{@root.serverDirName}}}/{{{hyphenCase name}}}-{{{hyphenCase @root.postfix}}}'; +import { I{{{pascalCase name}}}{{{@root.postfix}}} } from './i-{{{@root.serverDirName}}}/{{{hyphenCase name}}}-{{{hyphenCase @root.postfix}}}'; {{/each}} import { {{{transformReqFuncName}}} as transformRequest, @@ -11,7 +11,7 @@ import { inject, injectable } from 'tsyringe'; export class RouteHandler { constructor( {{#each services}} - @inject("{{{pascalCase name}}}{{{@root.postfix}}}") private {{{camelCase name}}}: {{{pascalCase name}}}{{{@root.postfix}}}, + @inject('I{{{pascalCase name}}}{{{@root.postfix}}}') private {{{camelCase name}}}: I{{{pascalCase name}}}{{{@root.postfix}}}, {{/each}} ) { } From ec00cf510376d1296ea25172701e2c5c1431d3c3 Mon Sep 17 00:00:00 2001 From: Yonatan Refaeli Date: Wed, 15 Jun 2022 15:52:39 -0400 Subject: [PATCH 15/23] add 'i-' to controller interface filename and update version to 0.2.6 --- package.json | 2 +- src/templates/exportRouteHandler.hbs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index e92494712..8d130a7fb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@yrefaeli/openapi-typescript-codegen", - "version": "0.2.5", + "version": "0.2.6", "description": "Library that generates Typescript clients based on the OpenAPI specification.", "author": "Yon Refaeli", "homepage": "https://github.com/yrefaeli/openapi-typescript-codegen", diff --git a/src/templates/exportRouteHandler.hbs b/src/templates/exportRouteHandler.hbs index 404cdec0a..907260485 100644 --- a/src/templates/exportRouteHandler.hbs +++ b/src/templates/exportRouteHandler.hbs @@ -1,5 +1,5 @@ {{#each services}} -import { I{{{pascalCase name}}}{{{@root.postfix}}} } from './i-{{{@root.serverDirName}}}/{{{hyphenCase name}}}-{{{hyphenCase @root.postfix}}}'; +import { I{{{pascalCase name}}}{{{@root.postfix}}} } from './{{{@root.serverDirName}}}/i-{{{hyphenCase name}}}-{{{hyphenCase @root.postfix}}}'; {{/each}} import { {{{transformReqFuncName}}} as transformRequest, From 39c8e6c8e14cb6d08cb12e2073fb7055366459a0 Mon Sep 17 00:00:00 2001 From: Yonatan Refaeli Date: Fri, 17 Jun 2022 14:25:43 -0400 Subject: [PATCH 16/23] Hyphen-case model imports and update version to 0.2.7 --- package.json | 2 +- src/templates/exportModel.hbs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 8d130a7fb..07f80ed92 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@yrefaeli/openapi-typescript-codegen", - "version": "0.2.6", + "version": "0.2.7", "description": "Library that generates Typescript clients based on the OpenAPI specification.", "author": "Yon Refaeli", "homepage": "https://github.com/yrefaeli/openapi-typescript-codegen", diff --git a/src/templates/exportModel.hbs b/src/templates/exportModel.hbs index 7ddb2c3e8..e6cf2d659 100644 --- a/src/templates/exportModel.hbs +++ b/src/templates/exportModel.hbs @@ -3,7 +3,7 @@ {{#if imports}} {{#each imports}} -import type { {{{this}}} } from './{{{this}}}'; +import type { {{{this}}} } from './{{{hyphenCase this}}}'; {{/each}} {{/if}} From 0395bce7f72d3b84d79fb1ab0ec210376f48b1eb Mon Sep 17 00:00:00 2001 From: Yonatan Refaeli Date: Wed, 22 Jun 2022 15:03:28 -0400 Subject: [PATCH 17/23] Add async and promises to route handler, controller interfaces and update version to 0.2.8 --- package.json | 2 +- src/templates/exportRouteHandler.hbs | 6 +++--- src/templates/exportServerInterface.hbs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 07f80ed92..6e883d84e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@yrefaeli/openapi-typescript-codegen", - "version": "0.2.7", + "version": "0.2.8", "description": "Library that generates Typescript clients based on the OpenAPI specification.", "author": "Yon Refaeli", "homepage": "https://github.com/yrefaeli/openapi-typescript-codegen", diff --git a/src/templates/exportRouteHandler.hbs b/src/templates/exportRouteHandler.hbs index 907260485..b1d401c48 100644 --- a/src/templates/exportRouteHandler.hbs +++ b/src/templates/exportRouteHandler.hbs @@ -15,16 +15,16 @@ export class RouteHandler { {{/each}} ) { } - private applyTransforms(req, reply, handlerFunc) { + private async applyTransforms(req, reply, handlerFunc) { const transformedRequest = transformRequest(req); - const handlerResponse = handlerFunc(transformedRequest); + const handlerResponse = await handlerFunc(transformedRequest); const transformedResponse = transformResponse(handlerResponse, reply); return transformedResponse; } {{#each services}} {{#each operations}} - {{{name}}} = (req, reply) => this.applyTransforms(req, reply, this.{{{camelCase service}}}.{{{name}}}); + {{{name}}} = async (req, reply) => await this.applyTransforms(req, reply, this.{{{camelCase service}}}.{{{name}}}); {{/each}} {{/each}} } diff --git a/src/templates/exportServerInterface.hbs b/src/templates/exportServerInterface.hbs index ea7cc613c..15a5c01b2 100644 --- a/src/templates/exportServerInterface.hbs +++ b/src/templates/exportServerInterface.hbs @@ -32,7 +32,7 @@ export interface I{{{name}}}{{{@root.postfix}}} { {{/each}} * @throws ApiError */ - {{{name}}}(req: {{{@root.serverReqTypeName}}}<{{#hasNonBodyParams this}}{{{pascalCase name}}}Params{{else}}never{{/hasNonBodyParams}}{{#if parametersBody}}, {{{parametersBody.type}}}{{/if}}>): {{{@root.serverResTypeName}}}<{{>result}}>; + {{{name}}}(req: {{{@root.serverReqTypeName}}}<{{#hasNonBodyParams this}}{{{pascalCase name}}}Params{{else}}never{{/hasNonBodyParams}}{{#if parametersBody}}, {{{parametersBody.type}}}{{/if}}>): Promise<{{{@root.serverResTypeName}}}<{{>result}}>>; {{/each}} } From a78493103dadc0bae79ad9122d99e5d31ef0d539 Mon Sep 17 00:00:00 2001 From: Yonatan Refaeli Date: Wed, 29 Jun 2022 18:26:29 -0400 Subject: [PATCH 18/23] Fix hasNonBodyParams function --- src/templates/core/functions/hasNonBodyParams.hbs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/templates/core/functions/hasNonBodyParams.hbs b/src/templates/core/functions/hasNonBodyParams.hbs index db9506574..b155e6686 100644 --- a/src/templates/core/functions/hasNonBodyParams.hbs +++ b/src/templates/core/functions/hasNonBodyParams.hbs @@ -1,3 +1,4 @@ const hasNonBodyParams = (op: any): boolean => { - op.parameters && op.parameters.length > 0 && !op.parametersBody; + op.parameters + && op.parameters.filter(param => param.in !== 'body').length > 0 }; From 5158c5408620b71568b0e091f10c23eaea32c20a Mon Sep 17 00:00:00 2001 From: Yonatan Refaeli Date: Wed, 29 Jun 2022 18:27:24 -0400 Subject: [PATCH 19/23] Update version to 0.2.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6e883d84e..0b2e6e134 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@yrefaeli/openapi-typescript-codegen", - "version": "0.2.8", + "version": "0.2.9", "description": "Library that generates Typescript clients based on the OpenAPI specification.", "author": "Yon Refaeli", "homepage": "https://github.com/yrefaeli/openapi-typescript-codegen", From 1be7b8ec64582f0530f4af99d2da608236ff7365 Mon Sep 17 00:00:00 2001 From: Yonatan Refaeli Date: Wed, 29 Jun 2022 18:35:15 -0400 Subject: [PATCH 20/23] Update version to 0.2.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0b2e6e134..cfac29a95 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@yrefaeli/openapi-typescript-codegen", - "version": "0.2.9", + "version": "0.2.10", "description": "Library that generates Typescript clients based on the OpenAPI specification.", "author": "Yon Refaeli", "homepage": "https://github.com/yrefaeli/openapi-typescript-codegen", From 2cceaf8f05bf67c2b4499b18ee512ceecce6f69e Mon Sep 17 00:00:00 2001 From: Yon Refaeli Date: Fri, 12 May 2023 05:08:12 -0400 Subject: [PATCH 21/23] Add error handling to RouteHandler --- src/templates/exportRouteHandler.hbs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/templates/exportRouteHandler.hbs b/src/templates/exportRouteHandler.hbs index b1d401c48..d441e104d 100644 --- a/src/templates/exportRouteHandler.hbs +++ b/src/templates/exportRouteHandler.hbs @@ -6,6 +6,8 @@ import { {{{transformResFuncName}}} as transformResponse } from '{{{transformFuncPath}}}'; import { inject, injectable } from 'tsyringe'; +import { ErrorResponse } from '@digital/domain/models/api/error-response'; +import { IcHttpResponse } from '@digital/ic-digital-core'; @injectable() export class RouteHandler { @@ -17,9 +19,21 @@ export class RouteHandler { private async applyTransforms(req, reply, handlerFunc) { const transformedRequest = transformRequest(req); - const handlerResponse = await handlerFunc(transformedRequest); - const transformedResponse = transformResponse(handlerResponse, reply); - return transformedResponse; + + try { + const handlerResponse = await handlerFunc(transformedRequest); + const transformedResponse = transformResponse(handlerResponse, reply); + return transformedResponse; + } catch (e) { + const error = e as IcHttpResponse; + + throw { + timestamp: new Date().toISOString(), + message: error?.message, + body: error?.body || {}, + statusCode: error?.status + } as ErrorResponse; + } } {{#each services}} From d4c206a66f83ac5ec200e934cbcf1b0ba9e08c11 Mon Sep 17 00:00:00 2001 From: Yon Refaeli Date: Fri, 12 May 2023 05:33:51 -0400 Subject: [PATCH 22/23] 0.2.11 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index f4b0b6ad7..6205028d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "openapi-typescript-codegen", - "version": "0.21.0", + "version": "0.2.11", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "openapi-typescript-codegen", - "version": "0.21.0", + "version": "0.2.11", "license": "MIT", "dependencies": { "camelcase": "^6.3.0", diff --git a/package.json b/package.json index cfac29a95..d57a0bad4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@yrefaeli/openapi-typescript-codegen", - "version": "0.2.10", + "version": "0.2.11", "description": "Library that generates Typescript clients based on the OpenAPI specification.", "author": "Yon Refaeli", "homepage": "https://github.com/yrefaeli/openapi-typescript-codegen", From 9d90eac011dde13be1fa20aeafb2f8f0b0183bcd Mon Sep 17 00:00:00 2001 From: Nicholas Marshall Date: Sat, 17 Jun 2023 23:07:33 -0400 Subject: [PATCH 23/23] formData generation fix --- package.json | 2 +- src/templates/exportQueryModel.hbs | 10 ++++++++++ src/templates/exportRouteHandler.hbs | 19 ++----------------- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index d57a0bad4..31a2ee203 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@yrefaeli/openapi-typescript-codegen", - "version": "0.2.11", + "version": "0.2.12", "description": "Library that generates Typescript clients based on the OpenAPI specification.", "author": "Yon Refaeli", "homepage": "https://github.com/yrefaeli/openapi-typescript-codegen", diff --git a/src/templates/exportQueryModel.hbs b/src/templates/exportQueryModel.hbs index f72b05ddf..e03a54f5b 100644 --- a/src/templates/exportQueryModel.hbs +++ b/src/templates/exportQueryModel.hbs @@ -1,5 +1,15 @@ {{>header}} +{{#each parameters}} +{{#notEquals this.in 'body'}} +{{#if this.imports}} +{{#each this.imports}} +import { {{{this}}} } from './{{{hyphenCase this}}}'; +{{/each}} +{{/if}} +{{/notEquals}} +{{/each}} + export interface {{{pascalCase name}}}Params { {{#each parameters}} {{#notEquals this.in 'body'}} diff --git a/src/templates/exportRouteHandler.hbs b/src/templates/exportRouteHandler.hbs index d441e104d..348d4af17 100644 --- a/src/templates/exportRouteHandler.hbs +++ b/src/templates/exportRouteHandler.hbs @@ -6,8 +6,6 @@ import { {{{transformResFuncName}}} as transformResponse } from '{{{transformFuncPath}}}'; import { inject, injectable } from 'tsyringe'; -import { ErrorResponse } from '@digital/domain/models/api/error-response'; -import { IcHttpResponse } from '@digital/ic-digital-core'; @injectable() export class RouteHandler { @@ -19,21 +17,8 @@ export class RouteHandler { private async applyTransforms(req, reply, handlerFunc) { const transformedRequest = transformRequest(req); - - try { - const handlerResponse = await handlerFunc(transformedRequest); - const transformedResponse = transformResponse(handlerResponse, reply); - return transformedResponse; - } catch (e) { - const error = e as IcHttpResponse; - - throw { - timestamp: new Date().toISOString(), - message: error?.message, - body: error?.body || {}, - statusCode: error?.status - } as ErrorResponse; - } + const handlerResponse = await handlerFunc(transformedRequest); + return transformResponse(handlerResponse, reply); } {{#each services}}