- Added request property

This commit is contained in:
Ferdi Koomen 2020-12-18 11:54:09 +01:00
parent 56f9289ff1
commit b0bea2daae
12 changed files with 53 additions and 104 deletions

View File

@ -12,13 +12,14 @@ program
.version(pkg.version)
.requiredOption('-i, --input <value>', 'OpenAPI specification, can be a path, url or string content (required)')
.requiredOption('-o, --output <value>', 'Output directory (required)')
.option('-c, --client <value>', 'HTTP client to generate [fetch, xhr, node] or path to custom request file', 'fetch')
.option('-c, --client <value>', '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 <value>', 'Write core files to disk', true)
.option('--exportServices <value>', 'Write services to disk', true)
.option('--exportModels <value>', 'Write models to disk', true)
.option('--exportSchemas <value>', 'Write schemas to disk', false)
.option('--request <value>', '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);

View File

@ -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",

View File

@ -13,13 +13,14 @@ export { HttpClient } from './HttpClient';
export type Options = {
input: string | Record<string, any>;
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<void> {
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;
}
}

View File

@ -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<void> {
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) {

View File

@ -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<void> {
export async function writeClientCore(client: Client, templates: Templates, outputPath: string, httpClient: HttpClient, request?: string): Promise<void> {
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'));
}
}

View File

@ -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<void> {
export async function writeClientModels(models: Model[], templates: Templates, outputPath: string, httpClient: HttpClient, useUnionTypes: boolean): Promise<void> {
for (const model of models) {
const file = resolve(outputPath, `${model.name}.ts`);
const templateResult = templates.exports.model({

View File

@ -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<void> {
export async function writeClientSchemas(models: Model[], templates: Templates, outputPath: string, httpClient: HttpClient, useUnionTypes: boolean): Promise<void> {
for (const model of models) {
const file = resolve(outputPath, `$${model.name}.ts`);
const templateResult = templates.exports.schema({

View File

@ -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<void> {
export async function writeClientServices(services: Service[], templates: Templates, outputPath: string, httpClient: HttpClient, useUnionTypes: boolean, useOptions: boolean): Promise<void> {
for (const service of services) {
const file = resolve(outputPath, `${service.name}.ts`);
const useVersion = service.operations.some(operation => operation.path.includes(VERSION_TEMPLATE_STRING));

View File

@ -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<string, any>;
readonly headers?: Record<string, any>;
readonly query?: Record<string, any>;
readonly formData?: Record<string, any>;
readonly body?: any;
readonly responseHeader?: string;
readonly errors?: Record<number, string>;
}
export async function request(options: ApiRequestOptions): Promise<ApiResult> {
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<TResult> {
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
},
};
}

View File

@ -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',
});
}

3
types/index.d.ts vendored
View File

@ -7,13 +7,14 @@ export declare enum HttpClient {
export type Options = {
input: string | Record<string, any>;
output: string;
httpClient?: string | HttpClient;
httpClient?: HttpClient;
useOptions?: boolean;
useUnionTypes?: boolean;
exportCore?: boolean;
exportServices?: boolean;
exportModels?: boolean;
exportSchemas?: boolean;
request?: string;
write?: boolean;
};

View File

@ -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"