From b0bea2daaebfec216180613709bb72f0f91531d0 Mon Sep 17 00:00:00 2001 From: Ferdi Koomen Date: Fri, 18 Dec 2020 11:54:09 +0100 Subject: [PATCH] - Added request property --- bin/index.js | 4 +- package.json | 3 +- src/index.ts | 9 +++-- src/utils/writeClient.ts | 8 ++-- src/utils/writeClientCore.ts | 25 +++++------- src/utils/writeClientModels.ts | 2 +- src/utils/writeClientSchemas.ts | 2 +- src/utils/writeClientServices.ts | 2 +- test/custom/request.ts | 67 +++++++------------------------- test/index.js | 2 + types/index.d.ts | 3 +- yarn.lock | 30 +++----------- 12 files changed, 53 insertions(+), 104 deletions(-) diff --git a/bin/index.js b/bin/index.js index 13bb3188..63815aa1 100755 --- a/bin/index.js +++ b/bin/index.js @@ -12,13 +12,14 @@ 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('-c, --client ', 'HTTP client to generate [fetch, xhr, node] or path to custom request file', 'fetch') + .option('-c, --client ', 'HTTP client to generate [fetch, xhr, node]', 'fetch') .option('--useOptions', 'Use options instead of arguments') .option('--useUnionTypes', 'Use union types instead of enums') .option('--exportCore ', 'Write core files to disk', true) .option('--exportServices ', 'Write services to disk', true) .option('--exportModels ', 'Write models to disk', true) .option('--exportSchemas ', 'Write schemas to disk', false) + .option('--request ', 'Path to custom request file') .parse(process.argv); const OpenAPI = require(path.resolve(__dirname, '../dist/index.js')); @@ -34,6 +35,7 @@ if (OpenAPI) { exportServices: JSON.parse(program.exportServices) === true, exportModels: JSON.parse(program.exportModels) === true, exportSchemas: JSON.parse(program.exportSchemas) === true, + request: program.request, }) .then(() => { process.exit(0); diff --git a/package.json b/package.json index 7ba3e3c4..3ce91643 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "openapi-typescript-codegen", - "version": "0.7.0", + "version": "0.7.1", "description": "Library that generates Typescript clients based on the OpenAPI specification.", "author": "Ferdi Koomen", "homepage": "https://github.com/ferdikoomen/openapi-typescript-codegen", @@ -91,7 +91,6 @@ "express": "4.17.1", "form-data": "3.0.0", "glob": "7.1.6", - "httpntlm": "1.7.6", "jest": "26.6.3", "jest-cli": "26.6.3", "node-fetch": "2.6.1", diff --git a/src/index.ts b/src/index.ts index 802a6341..f0714b74 100644 --- a/src/index.ts +++ b/src/index.ts @@ -13,13 +13,14 @@ export { HttpClient } from './HttpClient'; export type Options = { input: string | Record; output: string; - httpClient?: string | HttpClient; + httpClient?: HttpClient; useOptions?: boolean; useUnionTypes?: boolean; exportCore?: boolean; exportServices?: boolean; exportModels?: boolean; exportSchemas?: boolean; + request?: string; write?: boolean; }; @@ -36,6 +37,7 @@ export type Options = { * @param exportServices: Generate services * @param exportModels: Generate models * @param exportSchemas: Generate schemas + * @param request: Path to custom request file * @param write Write the files to disk (true or false) */ export async function generate({ @@ -48,6 +50,7 @@ export async function generate({ exportServices = true, exportModels = true, exportSchemas = false, + request, write = true, }: Options): Promise { const openApi = isString(input) ? await getOpenApiSpec(input) : input; @@ -59,7 +62,7 @@ export async function generate({ const client = parseV2(openApi); const clientFinal = postProcessClient(client); if (!write) break; - await writeClient(clientFinal, templates, output, httpClient, useOptions, useUnionTypes, exportCore, exportServices, exportModels, exportSchemas); + await writeClient(clientFinal, templates, output, httpClient, useOptions, useUnionTypes, exportCore, exportServices, exportModels, exportSchemas, request); break; } @@ -67,7 +70,7 @@ export async function generate({ const client = parseV3(openApi); const clientFinal = postProcessClient(client); if (!write) break; - await writeClient(clientFinal, templates, output, httpClient, useOptions, useUnionTypes, exportCore, exportServices, exportModels, exportSchemas); + await writeClient(clientFinal, templates, output, httpClient, useOptions, useUnionTypes, exportCore, exportServices, exportModels, exportSchemas, request); break; } } diff --git a/src/utils/writeClient.ts b/src/utils/writeClient.ts index f1affd10..2cfc4e36 100644 --- a/src/utils/writeClient.ts +++ b/src/utils/writeClient.ts @@ -23,18 +23,20 @@ import { writeClientServices } from './writeClientServices'; * @param exportServices: Generate services * @param exportModels: Generate models * @param exportSchemas: Generate schemas + * @param request: Path to custom request file */ export async function writeClient( client: Client, templates: Templates, output: string, - httpClient: string | HttpClient, + httpClient: HttpClient, useOptions: boolean, useUnionTypes: boolean, exportCore: boolean, exportServices: boolean, exportModels: boolean, - exportSchemas: boolean + exportSchemas: boolean, + request?: string ): Promise { const outputPath = resolve(process.cwd(), output); const outputPathCore = resolve(outputPath, 'core'); @@ -49,7 +51,7 @@ export async function writeClient( if (exportCore) { await rmdir(outputPathCore); await mkdir(outputPathCore); - await writeClientCore(client, templates, outputPathCore, httpClient); + await writeClientCore(client, templates, outputPathCore, httpClient, request); } if (exportServices) { diff --git a/src/utils/writeClientCore.ts b/src/utils/writeClientCore.ts index e30303b4..c7cac72f 100644 --- a/src/utils/writeClientCore.ts +++ b/src/utils/writeClientCore.ts @@ -11,8 +11,9 @@ import { Templates } from './registerHandlebarTemplates'; * @param templates The loaded handlebar templates * @param outputPath Directory to write the generated files to * @param httpClient The selected httpClient (fetch, xhr or node) + * @param request: Path to custom request file */ -export async function writeClientCore(client: Client, templates: Templates, outputPath: string, httpClient: string | HttpClient): Promise { +export async function writeClientCore(client: Client, templates: Templates, outputPath: string, httpClient: HttpClient, request?: string): Promise { const context = { httpClient, server: client.server, @@ -23,20 +24,14 @@ export async function writeClientCore(client: Client, templates: Templates, outp await writeFile(resolve(outputPath, 'ApiError.ts'), templates.core.apiError({})); await writeFile(resolve(outputPath, 'ApiRequestOptions.ts'), templates.core.apiRequestOptions({})); await writeFile(resolve(outputPath, 'ApiResult.ts'), templates.core.apiResult({})); + await writeFile(resolve(outputPath, 'request.ts'), templates.core.request(context)); - switch (httpClient) { - case HttpClient.FETCH: - case HttpClient.XHR: - case HttpClient.NODE: - await writeFile(resolve(outputPath, 'request.ts'), templates.core.request(context)); - break; - default: - const customRequestFile = resolve(process.cwd(), httpClient); - const customRequestFileExists = await exists(customRequestFile); - if (!customRequestFileExists) { - throw new Error(`Custom request file "${customRequestFile}" does not exists`); - } - await copyFile(customRequestFile, resolve(outputPath, 'request.ts')); - break; + if (request) { + const requestFile = resolve(process.cwd(), request); + const requestFileExists = await exists(requestFile); + if (!requestFileExists) { + throw new Error(`Custom request file "${requestFile}" does not exists`); + } + await copyFile(requestFile, resolve(outputPath, 'request.ts')); } } diff --git a/src/utils/writeClientModels.ts b/src/utils/writeClientModels.ts index 867bbf7b..7df9cdc4 100644 --- a/src/utils/writeClientModels.ts +++ b/src/utils/writeClientModels.ts @@ -14,7 +14,7 @@ import { Templates } from './registerHandlebarTemplates'; * @param httpClient The selected httpClient (fetch, xhr or node) * @param useUnionTypes Use union types instead of enums */ -export async function writeClientModels(models: Model[], templates: Templates, outputPath: string, httpClient: string | HttpClient, useUnionTypes: boolean): Promise { +export async function writeClientModels(models: Model[], templates: Templates, outputPath: string, httpClient: HttpClient, useUnionTypes: boolean): Promise { for (const model of models) { const file = resolve(outputPath, `${model.name}.ts`); const templateResult = templates.exports.model({ diff --git a/src/utils/writeClientSchemas.ts b/src/utils/writeClientSchemas.ts index 602d2fbc..048558d9 100644 --- a/src/utils/writeClientSchemas.ts +++ b/src/utils/writeClientSchemas.ts @@ -14,7 +14,7 @@ import { Templates } from './registerHandlebarTemplates'; * @param httpClient The selected httpClient (fetch, xhr or node) * @param useUnionTypes Use union types instead of enums */ -export async function writeClientSchemas(models: Model[], templates: Templates, outputPath: string, httpClient: string | HttpClient, useUnionTypes: boolean): Promise { +export async function writeClientSchemas(models: Model[], templates: Templates, outputPath: string, httpClient: HttpClient, useUnionTypes: boolean): Promise { for (const model of models) { const file = resolve(outputPath, `$${model.name}.ts`); const templateResult = templates.exports.schema({ diff --git a/src/utils/writeClientServices.ts b/src/utils/writeClientServices.ts index f429ec54..8f82e0ce 100644 --- a/src/utils/writeClientServices.ts +++ b/src/utils/writeClientServices.ts @@ -17,7 +17,7 @@ const VERSION_TEMPLATE_STRING = 'OpenAPI.VERSION'; * @param useUnionTypes Use union types instead of enums * @param useOptions Use options or arguments functions */ -export async function writeClientServices(services: Service[], templates: Templates, outputPath: string, httpClient: string | HttpClient, useUnionTypes: boolean, useOptions: boolean): Promise { +export async function writeClientServices(services: Service[], templates: Templates, outputPath: string, httpClient: HttpClient, useUnionTypes: boolean, useOptions: boolean): Promise { for (const service of services) { const file = resolve(outputPath, `${service.name}.ts`); const useVersion = service.operations.some(operation => operation.path.includes(VERSION_TEMPLATE_STRING)); diff --git a/test/custom/request.ts b/test/custom/request.ts index 88baee1e..0c246a6b 100644 --- a/test/custom/request.ts +++ b/test/custom/request.ts @@ -1,60 +1,23 @@ -// @ts-ignore -import httpntlm from 'httpntlm'; -import { promisify } from 'util'; -import { stringify } from 'qs'; +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { ApiRequestOptions } from './ApiRequestOptions'; +import type { ApiResult } from './ApiResult'; +import { OpenAPI } from './OpenAPI'; -type TRequestOptions = { - readonly method: 'GET' | 'PUT' | 'POST' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'PATCH'; - readonly path: string; - readonly cookies?: Record; - readonly headers?: Record; - readonly query?: Record; - readonly formData?: Record; - readonly body?: any; - readonly responseHeader?: string; - readonly errors?: Record; -} +export async function request(options: ApiRequestOptions): Promise { -type TResult = { - readonly url: string; - readonly ok: boolean; - readonly status: number; - readonly statusText: string; - readonly body: any; -} + const url = `${OpenAPI.BASE}${options.path}`; -export async function request(options: TRequestOptions): Promise { - - const path = options.path.replace(/[:]/g, '_'); - const query = stringify(options.query); - const host = 'http://localhost:8080'; - const url = `${host}${path}${query}`; - - const body = options.body && JSON.stringify(options.body); - const headers = { - ...options.headers, - 'Accept': 'application/json', - 'Content-Type': 'application/json; charset=utf-8', - 'Accept-Encoding': 'identity', - } - - const method = options.method.toLowerCase(); - const fetch = promisify(httpntlm[method]); - - const response = await fetch({ - url, - domain: 'domain', - username: 'username', - password: 'password', - headers, - body, - }); + // Do your request... return { url, - ok: response.ok, - status: response.statusCode, - statusText: response.statusText, - body: JSON.parse(response.body), + ok: true, + status: 200, + statusText: 'dummy', + body: { + ...options + }, }; } diff --git a/test/index.js b/test/index.js index 7c88334b..3f2fd866 100644 --- a/test/index.js +++ b/test/index.js @@ -13,6 +13,7 @@ async function generateV2() { exportSchemas: true, exportModels: true, exportServices: true, + request: './test/custom/request.ts', }); } @@ -27,6 +28,7 @@ async function generateV3() { exportSchemas: true, exportModels: true, exportServices: true, + request: './test/custom/request.ts', }); } diff --git a/types/index.d.ts b/types/index.d.ts index 5655511c..7bd587e9 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -7,13 +7,14 @@ export declare enum HttpClient { export type Options = { input: string | Record; output: string; - httpClient?: string | HttpClient; + httpClient?: HttpClient; useOptions?: boolean; useUnionTypes?: boolean; exportCore?: boolean; exportServices?: boolean; exportModels?: boolean; exportSchemas?: boolean; + request?: string; write?: boolean; }; diff --git a/yarn.lock b/yarn.lock index fcc2e41b..96cce344 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2345,9 +2345,9 @@ ee-first@1.1.1: integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= electron-to-chromium@^1.3.621: - version "1.3.628" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.628.tgz#be5a14ddf3a455de876274c84de0926439a287a7" - integrity sha512-fmhO4YGo/kapy+xL9Eq/cZwDASaTHZu3psIFYo4yc+RY1LzbZr84xjKlDImDrlrmWhOxsrDi98nX097U/xK/cQ== + version "1.3.629" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.629.tgz#a08d13b64d90e3c77ec5b9bffa3efbc5b4a00969" + integrity sha512-iSPPJtPvHrMAvYOt+9cdbDmTasPqwnwz4lkP8Dn200gDNUBQOLQ96xUsWXBwXslAo5XxdoXAoQQ3RAy4uao9IQ== emittery@^0.7.1: version "0.7.2" @@ -2939,9 +2939,9 @@ get-caller-file@^2.0.1: integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== get-intrinsic@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.1.tgz#94a9768fcbdd0595a1c9273aacf4c89d075631be" - integrity sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg== + version "1.0.2" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.2.tgz#6820da226e50b24894e08859469dc68361545d49" + integrity sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg== dependencies: function-bind "^1.1.1" has "^1.0.3" @@ -3174,19 +3174,6 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" -httpntlm@1.7.6: - version "1.7.6" - resolved "https://registry.yarnpkg.com/httpntlm/-/httpntlm-1.7.6.tgz#6991e8352836007d67101b83db8ed0f915f906d0" - integrity sha1-aZHoNSg2AH1nEBuD247Q+RX5BtA= - dependencies: - httpreq ">=0.4.22" - underscore "~1.7.0" - -httpreq@>=0.4.22: - version "0.4.24" - resolved "https://registry.yarnpkg.com/httpreq/-/httpreq-0.4.24.tgz#4335ffd82cd969668a39465c929ac61d6393627f" - integrity sha1-QzX/2CzZaWaKOUZckprGHWOTYn8= - https-proxy-agent@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz#702b71fb5520a132a66de1f67541d9e62154d82b" @@ -5724,11 +5711,6 @@ unbzip2-stream@^1.3.3: buffer "^5.2.1" through "^2.3.8" -underscore@~1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.7.0.tgz#6bbaf0877500d36be34ecaa584e0db9fef035209" - integrity sha1-a7rwh3UA02vjTsqlhODbn+8DUgk= - unicode-canonical-property-names-ecmascript@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818"