mirror of
https://github.com/ferdikoomen/openapi-typescript-codegen.git
synced 2025-12-08 20:16:21 +00:00
- Added switch for xhr anf fetch
This commit is contained in:
parent
f3bc279825
commit
20209f7aa2
1
.prettierignore
Normal file
1
.prettierignore
Normal file
@ -0,0 +1 @@
|
||||
src/templates
|
||||
10
src/index.ts
10
src/index.ts
@ -24,9 +24,9 @@ export enum HttpClient {
|
||||
* given language it will generate the client, including the typed models, validation schemas,
|
||||
* service layer, etc.
|
||||
* @param input The relative location of the OpenAPI spec.
|
||||
* @param output The relative location of the output directory
|
||||
* @param language: The language that should be generated (Typescript or Javascript)
|
||||
* @param httpClient: The selected httpClient (fetch or XHR)
|
||||
* @param output The relative location of the output directory.
|
||||
* @param language: The language that should be generated (Typescript or Javascript).
|
||||
* @param httpClient: The selected httpClient (fetch or XHR).
|
||||
*/
|
||||
export function generate(input: string, output: string, language: Language = Language.TYPESCRIPT, httpClient: HttpClient = HttpClient.FETCH): void {
|
||||
const inputPath = path.resolve(process.cwd(), input);
|
||||
@ -52,13 +52,13 @@ export function generate(input: string, output: string, language: Language = Lan
|
||||
// Generate and write version 2 client
|
||||
if (openApiVersion === OpenApiVersion.V2) {
|
||||
const clientV2 = parseV2(openApi);
|
||||
writeClient(clientV2, language, templates, outputPath);
|
||||
writeClient(clientV2, language, httpClient, templates, outputPath);
|
||||
}
|
||||
|
||||
// Generate and write version 3 client
|
||||
if (openApiVersion === OpenApiVersion.V3) {
|
||||
const clientV3 = parseV3(openApi);
|
||||
writeClient(clientV3, language, templates, outputPath);
|
||||
writeClient(clientV3, language, httpClient, templates, outputPath);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
@ -7,6 +7,7 @@ import { isSuccess } from './isSuccess';
|
||||
import { Result } from './Result';
|
||||
|
||||
export class ApiError extends Error {
|
||||
|
||||
public readonly url: string;
|
||||
public readonly status: number;
|
||||
public readonly statusText: string;
|
||||
@ -41,20 +42,13 @@ export namespace ApiError {
|
||||
*/
|
||||
export function catchGenericError(result: Result): void {
|
||||
switch (result.status) {
|
||||
case 400:
|
||||
throw new ApiError(result, ApiError.Message.BAD_REQUEST);
|
||||
case 401:
|
||||
throw new ApiError(result, ApiError.Message.UNAUTHORIZED);
|
||||
case 403:
|
||||
throw new ApiError(result, ApiError.Message.FORBIDDEN);
|
||||
case 404:
|
||||
throw new ApiError(result, ApiError.Message.NOT_FOUND);
|
||||
case 500:
|
||||
throw new ApiError(result, ApiError.Message.INTERNAL_SERVER_ERROR);
|
||||
case 502:
|
||||
throw new ApiError(result, ApiError.Message.BAD_GATEWAY);
|
||||
case 503:
|
||||
throw new ApiError(result, ApiError.Message.SERVICE_UNAVAILABLE);
|
||||
case 400: throw new ApiError(result, ApiError.Message.BAD_REQUEST);
|
||||
case 401: throw new ApiError(result, ApiError.Message.UNAUTHORIZED);
|
||||
case 403: throw new ApiError(result, ApiError.Message.FORBIDDEN);
|
||||
case 404: throw new ApiError(result, ApiError.Message.NOT_FOUND);
|
||||
case 500: throw new ApiError(result, ApiError.Message.INTERNAL_SERVER_ERROR);
|
||||
case 502: throw new ApiError(result, ApiError.Message.BAD_GATEWAY);
|
||||
case 503: throw new ApiError(result, ApiError.Message.SERVICE_UNAVAILABLE);
|
||||
}
|
||||
|
||||
if (!isSuccess(result.status)) {
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
/* prettier-ignore */
|
||||
|
||||
export interface RequestOptions {
|
||||
type: 'fetch' | 'xhr';
|
||||
method: string;
|
||||
path: string;
|
||||
headers?: { [key: string]: any };
|
||||
|
||||
@ -8,6 +8,7 @@ import { getQueryString } from './getQueryString';
|
||||
import { OpenAPI } from './OpenAPI';
|
||||
import { RequestOptions } from './RequestOptions';
|
||||
import { requestUsingFetch } from './requestUsingFetch';
|
||||
import { requestUsingXHR } from './requestUsingXHR';
|
||||
import { Result } from './Result';
|
||||
|
||||
/**
|
||||
@ -16,6 +17,7 @@ import { Result } from './Result';
|
||||
* @returns Result object (see above)
|
||||
*/
|
||||
export async function request<T = any>(options: Readonly<RequestOptions>): Promise<Result<T>> {
|
||||
|
||||
// Create the request URL
|
||||
let url = `${OpenAPI.BASE}${options.path}`;
|
||||
|
||||
@ -46,6 +48,7 @@ export async function request<T = any>(options: Readonly<RequestOptions>): Promi
|
||||
if (options.formData) {
|
||||
request.body = getFormData(options.formData);
|
||||
} else if (options.body) {
|
||||
|
||||
// If this is blob data, then pass it directly to the body and set content type.
|
||||
// Otherwise we just convert request data to JSON string (needed for fetch api)
|
||||
if (options.body instanceof Blob) {
|
||||
@ -60,7 +63,12 @@ export async function request<T = any>(options: Readonly<RequestOptions>): Promi
|
||||
}
|
||||
|
||||
try {
|
||||
return await requestUsingFetch<T>(url, request);
|
||||
switch (options.type) {
|
||||
case 'fetch':
|
||||
return await requestUsingFetch<T>(url, request);
|
||||
case 'xhr':
|
||||
return await requestUsingXHR<T>(url, request);
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
url,
|
||||
|
||||
@ -13,6 +13,7 @@ import { Result } from './Result';
|
||||
* @param request The request object, containing method, headers, body, etc.
|
||||
*/
|
||||
export async function requestUsingFetch<T = any>(url: string, request: Readonly<RequestInit>): Promise<Result<T>> {
|
||||
|
||||
// Fetch response using fetch API.
|
||||
const response = await fetch(url, request);
|
||||
|
||||
|
||||
@ -31,6 +31,7 @@ export async function requestUsingXHR<T = any>(url: string, request: Readonly<Re
|
||||
// Register the readystate handler, this will fire when the request is done.
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === XMLHttpRequest.DONE) {
|
||||
|
||||
// Create result object.
|
||||
const result: Result = {
|
||||
url,
|
||||
|
||||
@ -14,6 +14,7 @@ import { OpenAPI } from '../core/OpenAPI';
|
||||
import { Result } from '../core/Result';
|
||||
|
||||
export class {{{name}}} {
|
||||
|
||||
{{#each operations}}
|
||||
/**
|
||||
{{#if deprecated}}
|
||||
@ -30,10 +31,12 @@ export class {{{name}}} {
|
||||
* @param {{{name}}} {{{description}}}
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
* @return {{{result}}}
|
||||
*/
|
||||
public static async {{{name}}}({{#each parameters}}{{{name}}}{{#unless required}}?{{/unless}}: {{{type}}}{{#if nullable}} | null{{/if}}{{#unless @last}}, {{/unless}}{{/each}}): Promise<{{{result}}}> {
|
||||
|
||||
const result: Result<{{{result}}}> = await request({
|
||||
type: '{{{../httpClient}}}',
|
||||
method: '{{{method}}}',
|
||||
path: `{{{path}}}`,
|
||||
{{#if parametersHeader}}
|
||||
|
||||
@ -18,11 +18,13 @@ export interface Templates {
|
||||
export function readHandlebarsTemplates(language: Language): Templates {
|
||||
try {
|
||||
registerHandlebarHelpers();
|
||||
|
||||
const templates: Templates = {
|
||||
index: readHandlebarsTemplate(path.resolve(__dirname, `../../src/templates/${language}/index.hbs`)),
|
||||
model: readHandlebarsTemplate(path.resolve(__dirname, `../../src/templates/${language}/model.hbs`)),
|
||||
service: readHandlebarsTemplate(path.resolve(__dirname, `../../src/templates/${language}/service.hbs`)),
|
||||
};
|
||||
|
||||
Handlebars.registerPartial({
|
||||
exportGeneric: readHandlebarsTemplate(path.resolve(__dirname, `../../src/templates/${language}/exportGeneric.hbs`)),
|
||||
exportReference: readHandlebarsTemplate(path.resolve(__dirname, `../../src/templates/${language}/exportReference.hbs`)),
|
||||
@ -45,6 +47,7 @@ export function readHandlebarsTemplates(language: Language): Templates {
|
||||
typeForReference: readHandlebarsTemplate(path.resolve(__dirname, `../../src/templates/${language}/typeForReference.hbs`)),
|
||||
typeForGeneric: readHandlebarsTemplate(path.resolve(__dirname, `../../src/templates/${language}/typeForGeneric.hbs`)),
|
||||
});
|
||||
|
||||
return templates;
|
||||
} catch (e) {
|
||||
throw e;
|
||||
|
||||
@ -6,18 +6,19 @@ import * as mkdirp from 'mkdirp';
|
||||
import * as rimraf from 'rimraf';
|
||||
import { Templates } from './readHandlebarsTemplates';
|
||||
import { writeClientIndex } from './writeClientIndex';
|
||||
import { Language } from '../index';
|
||||
import { HttpClient, Language } from '../index';
|
||||
import * as fs from 'fs';
|
||||
import * as glob from 'glob';
|
||||
|
||||
/**
|
||||
* Write our OpenAPI client, using the given templates at the given output path
|
||||
* @param client: Client object with all the models, services, etc.
|
||||
* @param language: The output language (Typescript or javascript).
|
||||
* @param templates: Templates wrapper with all loaded Handlebars templates.
|
||||
* Write our OpenAPI client, using the given templates at the given output path.
|
||||
* @param client Client object with all the models, services, etc.
|
||||
* @param language The language that should be generated (Typescript or Javascript).
|
||||
* @param httpClient The selected httpClient (fetch or XHR).
|
||||
* @param templates Templates wrapper with all loaded Handlebars templates.
|
||||
* @param outputPath
|
||||
*/
|
||||
export function writeClient(client: Client, language: Language, templates: Templates, outputPath: string): void {
|
||||
export function writeClient(client: Client, language: Language, httpClient: HttpClient, templates: Templates, outputPath: string): void {
|
||||
const outputPathCore = path.resolve(outputPath, 'core');
|
||||
const outputPathModels = path.resolve(outputPath, 'models');
|
||||
const outputPathServices = path.resolve(outputPath, 'services');
|
||||
@ -52,8 +53,8 @@ export function writeClient(client: Client, language: Language, templates: Templ
|
||||
// Write the client files
|
||||
try {
|
||||
writeClientIndex(client, language, templates, outputPath);
|
||||
writeClientModels(client.models, language, templates, outputPathModels);
|
||||
writeClientServices(client.services, language, templates, outputPathServices);
|
||||
writeClientModels(client.models, language, httpClient, templates, outputPathModels);
|
||||
writeClientServices(client.services, language, httpClient, templates, outputPathServices);
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
@ -11,10 +11,10 @@ import { Templates } from './readHandlebarsTemplates';
|
||||
* Generate the OpenAPI client index file using the Handlebar template and write it to disk.
|
||||
* The index file just contains all the exports you need to use the client as a standalone
|
||||
* library. But yuo can also import individual models and services directly.
|
||||
* @param client: Client object, containing, models, schemas and services.
|
||||
* @param language: The output language (Typescript or javascript).
|
||||
* @param templates: The loaded handlebar templates.
|
||||
* @param outputPath:
|
||||
* @param client Client object, containing, models, schemas and services.
|
||||
* @param language The output language (Typescript or javascript).
|
||||
* @param templates The loaded handlebar templates.
|
||||
* @param outputPath
|
||||
*/
|
||||
export function writeClientIndex(client: Client, language: Language, templates: Templates, outputPath: string): void {
|
||||
const fileName = getFileName('index', language);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { writeClientModels } from './writeClientModels';
|
||||
import * as fs from 'fs';
|
||||
import { Model } from '../client/interfaces/Model';
|
||||
import { Language } from '../index';
|
||||
import { HttpClient, Language } from '../index';
|
||||
import { Templates } from './readHandlebarsTemplates';
|
||||
|
||||
jest.mock('fs');
|
||||
@ -33,7 +33,7 @@ describe('writeClientModels', () => {
|
||||
model: () => 'dummy',
|
||||
service: () => 'dummy',
|
||||
};
|
||||
writeClientModels(models, Language.TYPESCRIPT, templates, '/');
|
||||
writeClientModels(models, Language.TYPESCRIPT, HttpClient.FETCH, templates, '/');
|
||||
expect(fsWriteFileSync).toBeCalledWith('/Item.ts', 'dummy');
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import * as fs from 'fs';
|
||||
import { Model } from '../client/interfaces/Model';
|
||||
import * as path from 'path';
|
||||
import { Language } from '../index';
|
||||
import { HttpClient, Language } from '../index';
|
||||
import { getFileName } from './getFileName';
|
||||
import { exportModel } from './exportModel';
|
||||
import { Templates } from './readHandlebarsTemplates';
|
||||
@ -9,17 +9,22 @@ import { format } from './format';
|
||||
|
||||
/**
|
||||
* Generate Models using the Handlebar template and write to disk.
|
||||
* @param models: Array of Models to write.
|
||||
* @param language: The output language (Typescript or javascript).
|
||||
* @param templates: The loaded handlebar templates.
|
||||
* @param outputPath:
|
||||
* @param models Array of Models to write.
|
||||
* @param language The output language (Typescript or javascript).
|
||||
* @param httpClient The selected httpClient (fetch or XHR).
|
||||
* @param templates The loaded handlebar templates.
|
||||
* @param outputPath
|
||||
*/
|
||||
export function writeClientModels(models: Map<string, Model>, language: Language, templates: Templates, outputPath: string): void {
|
||||
export function writeClientModels(models: Map<string, Model>, language: Language, httpClient: HttpClient, templates: Templates, outputPath: string): void {
|
||||
models.forEach(model => {
|
||||
const fileName = getFileName(model.name, language);
|
||||
try {
|
||||
const templateData = exportModel(model);
|
||||
const templateResult = templates.model(templateData);
|
||||
const templateResult = templates.model({
|
||||
language,
|
||||
httpClient,
|
||||
...templateData,
|
||||
});
|
||||
fs.writeFileSync(path.resolve(outputPath, fileName), format(templateResult));
|
||||
} catch (e) {
|
||||
throw new Error(`Could not write model: "${fileName}"`);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { writeClientServices } from './writeClientServices';
|
||||
import * as fs from 'fs';
|
||||
import { Service } from '../client/interfaces/Service';
|
||||
import { Language } from '../index';
|
||||
import { HttpClient, Language } from '../index';
|
||||
import { Templates } from './readHandlebarsTemplates';
|
||||
|
||||
jest.mock('fs');
|
||||
@ -21,7 +21,7 @@ describe('writeClientServices', () => {
|
||||
model: () => 'dummy',
|
||||
service: () => 'dummy',
|
||||
};
|
||||
writeClientServices(services, Language.TYPESCRIPT, templates, '/');
|
||||
writeClientServices(services, Language.TYPESCRIPT, HttpClient.FETCH, templates, '/');
|
||||
expect(fsWriteFileSync).toBeCalledWith('/Item.ts', 'dummy');
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { Service } from '../client/interfaces/Service';
|
||||
import { Language } from '../index';
|
||||
import { HttpClient, Language } from '../index';
|
||||
import { getFileName } from './getFileName';
|
||||
import { exportService } from './exportService';
|
||||
import { Templates } from './readHandlebarsTemplates';
|
||||
@ -9,17 +9,22 @@ import { format } from './format';
|
||||
|
||||
/**
|
||||
* Generate Services using the Handlebar template and write to disk.
|
||||
* @param services: Array of Services to write.
|
||||
* @param language: The output language (Typescript or javascript).
|
||||
* @param templates: The loaded handlebar templates.
|
||||
* @param outputPath:
|
||||
* @param services Array of Services to write.
|
||||
* @param language The output language (Typescript or javascript).
|
||||
* @param httpClient The selected httpClient (fetch or XHR).
|
||||
* @param templates The loaded handlebar templates.
|
||||
* @param outputPath
|
||||
*/
|
||||
export function writeClientServices(services: Map<string, Service>, language: Language, templates: Templates, outputPath: string): void {
|
||||
export function writeClientServices(services: Map<string, Service>, language: Language, httpClient: HttpClient, templates: Templates, outputPath: string): void {
|
||||
services.forEach(service => {
|
||||
const fileName = getFileName(service.name, language);
|
||||
try {
|
||||
const templateData = exportService(service);
|
||||
const templateResult = templates.service(templateData);
|
||||
const templateResult = templates.service({
|
||||
language,
|
||||
httpClient,
|
||||
...templateData,
|
||||
});
|
||||
fs.writeFileSync(path.resolve(outputPath, fileName), format(templateResult));
|
||||
} catch (e) {
|
||||
throw new Error(`Could not write service: "${fileName}"`);
|
||||
|
||||
@ -25,12 +25,12 @@ OpenAPI.generate(
|
||||
// OpenAPI.HttpClient.FETCH,
|
||||
// );
|
||||
//
|
||||
OpenAPI.generate(
|
||||
'./test/mock/v2/test-sites.json',
|
||||
'./test/tmp/v2/ts/test-sites',
|
||||
OpenAPI.Language.TYPESCRIPT,
|
||||
OpenAPI.HttpClient.FETCH,
|
||||
);
|
||||
// OpenAPI.generate(
|
||||
// './test/mock/v2/test-sites.json',
|
||||
// './test/tmp/v2/ts/test-sites',
|
||||
// OpenAPI.Language.TYPESCRIPT,
|
||||
// OpenAPI.HttpClient.FETCH,
|
||||
// );
|
||||
//
|
||||
// OpenAPI.generate(
|
||||
// './test/mock/v2/test-petstore.yaml',
|
||||
|
||||
@ -10,6 +10,14 @@
|
||||
"http"
|
||||
],
|
||||
"paths": {
|
||||
"/api/v{api-version}/dummy": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Service"
|
||||
],
|
||||
"operationId": "GetCallWithoutParametersAndResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"SimpleInteger": {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user