mirror of
https://github.com/ferdikoomen/openapi-typescript-codegen.git
synced 2025-12-08 20:16:21 +00:00
- First draft of the new client generation mechanism
This commit is contained in:
parent
8b15c1eed0
commit
2f8d8b0a59
@ -15,12 +15,12 @@ module.exports = {
|
||||
displayName: 'E2E',
|
||||
testEnvironment: 'node',
|
||||
testMatch: [
|
||||
// '<rootDir>/test/e2e/v2.fetch.spec.js',
|
||||
// '<rootDir>/test/e2e/v2.xhr.spec.js',
|
||||
'<rootDir>/test/e2e/v2.fetch.spec.js',
|
||||
'<rootDir>/test/e2e/v2.xhr.spec.js',
|
||||
'<rootDir>/test/e2e/v2.node.spec.js',
|
||||
// '<rootDir>/test/e2e/v3.fetch.spec.js',
|
||||
// '<rootDir>/test/e2e/v3.xhr.spec.js',
|
||||
// '<rootDir>/test/e2e/v3.node.spec.js',
|
||||
'<rootDir>/test/e2e/v3.fetch.spec.js',
|
||||
'<rootDir>/test/e2e/v3.xhr.spec.js',
|
||||
'<rootDir>/test/e2e/v3.node.spec.js',
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
17
src/generated/v3/fetch/core/ApiError.ts
Normal file
17
src/generated/v3/fetch/core/ApiError.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { ApiResult } from './ApiResult';
|
||||
|
||||
export class ApiError extends Error {
|
||||
public readonly url: string;
|
||||
public readonly status: number;
|
||||
public readonly statusText: string;
|
||||
public readonly body: any;
|
||||
|
||||
constructor(response: ApiResult, message: string) {
|
||||
super(message);
|
||||
|
||||
this.url = response.url;
|
||||
this.status = response.status;
|
||||
this.statusText = response.statusText;
|
||||
this.body = response.body;
|
||||
}
|
||||
}
|
||||
11
src/generated/v3/fetch/core/ApiRequestOptions.ts
Normal file
11
src/generated/v3/fetch/core/ApiRequestOptions.ts
Normal file
@ -0,0 +1,11 @@
|
||||
export interface ApiRequestOptions {
|
||||
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>;
|
||||
}
|
||||
7
src/generated/v3/fetch/core/ApiResult.ts
Normal file
7
src/generated/v3/fetch/core/ApiResult.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export interface ApiResult {
|
||||
readonly url: string;
|
||||
readonly ok: boolean;
|
||||
readonly status: number;
|
||||
readonly statusText: string;
|
||||
readonly body: any;
|
||||
}
|
||||
15
src/generated/v3/fetch/core/OpenAPI.ts
Normal file
15
src/generated/v3/fetch/core/OpenAPI.ts
Normal file
@ -0,0 +1,15 @@
|
||||
interface Config {
|
||||
BASE: string;
|
||||
VERSION: string;
|
||||
CLIENT: 'fetch' | 'xhr' | 'node';
|
||||
WITH_CREDENTIALS: boolean;
|
||||
TOKEN: string;
|
||||
}
|
||||
|
||||
export const OpenAPI: Config = {
|
||||
BASE: 'http://localhost:3000/base',
|
||||
VERSION: '1.0',
|
||||
CLIENT: 'fetch',
|
||||
WITH_CREDENTIALS: false,
|
||||
TOKEN: '',
|
||||
};
|
||||
176
src/generated/v3/fetch/core/request.ts
Normal file
176
src/generated/v3/fetch/core/request.ts
Normal file
@ -0,0 +1,176 @@
|
||||
import { ApiError } from './ApiError';
|
||||
import { ApiRequestOptions } from './ApiRequestOptions';
|
||||
import { ApiResult } from './ApiResult';
|
||||
import { OpenAPI } from './OpenAPI';
|
||||
|
||||
function isDefined<T>(value: T | null | undefined): value is Exclude<T, null | undefined> {
|
||||
return value !== undefined && value !== null;
|
||||
}
|
||||
function getQueryString(params: Record<string, any>): string {
|
||||
const qs: string[] = [];
|
||||
|
||||
Object.keys(params).forEach(key => {
|
||||
const value = params[key];
|
||||
if (isDefined(value)) {
|
||||
if (Array.isArray(value)) {
|
||||
value.forEach(value => {
|
||||
qs.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);
|
||||
});
|
||||
} else {
|
||||
qs.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (qs.length > 0) {
|
||||
return `?${qs.join('&')}`;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
function getUrl(options: ApiRequestOptions): string {
|
||||
const path = options.path.replace(/[:]/g, '_');
|
||||
const url = `${OpenAPI.BASE}${path}`;
|
||||
|
||||
if (options.query) {
|
||||
return url + getQueryString(options.query);
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
function getFormData(params: Record<string, any>): FormData {
|
||||
const formData = new FormData();
|
||||
|
||||
Object.keys(params).forEach(key => {
|
||||
const value = params[key];
|
||||
if (isDefined(value)) {
|
||||
formData.append(key, value);
|
||||
}
|
||||
});
|
||||
|
||||
return formData;
|
||||
}
|
||||
function getHeaders(options: ApiRequestOptions): Headers {
|
||||
const headers = new Headers({
|
||||
Accept: 'application/json',
|
||||
...options.headers,
|
||||
});
|
||||
|
||||
if (OpenAPI.TOKEN !== null && OpenAPI.TOKEN !== '') {
|
||||
headers.append('Authorization', `Bearer ${OpenAPI.TOKEN}`);
|
||||
}
|
||||
|
||||
if (options.body) {
|
||||
if (options.body instanceof Blob) {
|
||||
if (options.body.type) {
|
||||
headers.append('Content-Type', options.body.type);
|
||||
}
|
||||
} else if (typeof options.body === 'string') {
|
||||
headers.append('Content-Type', 'text/plain');
|
||||
} else {
|
||||
headers.append('Content-Type', 'application/json');
|
||||
}
|
||||
}
|
||||
|
||||
return headers;
|
||||
}
|
||||
function getRequestBody(options: ApiRequestOptions): BodyInit | undefined {
|
||||
if (options.formData) {
|
||||
return getFormData(options.formData);
|
||||
}
|
||||
|
||||
if (options.body) {
|
||||
if (options.body instanceof Blob) {
|
||||
return options.body;
|
||||
} else if (typeof options.body === 'string') {
|
||||
return options.body;
|
||||
} else {
|
||||
return JSON.stringify(options.body);
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
async function sendRequest(options: ApiRequestOptions, url: string): Promise<Response> {
|
||||
const request: RequestInit = {
|
||||
method: options.method,
|
||||
headers: getHeaders(options),
|
||||
body: getRequestBody(options),
|
||||
};
|
||||
|
||||
return await fetch(url, request);
|
||||
}
|
||||
function getResponseHeader(response: Response, responseHeader?: string): string | null {
|
||||
if (responseHeader) {
|
||||
const content = response.headers.get(responseHeader);
|
||||
if (typeof content === 'string') {
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
async function getResponseBody(response: Response): Promise<any> {
|
||||
try {
|
||||
const contentType = response.headers.get('Content-Type');
|
||||
if (contentType) {
|
||||
switch (contentType.toLowerCase()) {
|
||||
case 'application/json':
|
||||
case 'application/json; charset=utf-8':
|
||||
return await response.json();
|
||||
|
||||
default:
|
||||
return await response.text();
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
function catchErrors(options: ApiRequestOptions, result: ApiResult): void {
|
||||
const errors: Record<number, string> = {
|
||||
400: 'Bad Request',
|
||||
401: 'Unauthorized',
|
||||
403: 'Forbidden',
|
||||
404: 'Not Found',
|
||||
500: 'Internal Server Error',
|
||||
502: 'Bad Gateway',
|
||||
503: 'Service Unavailable',
|
||||
...options.errors,
|
||||
};
|
||||
|
||||
const error = errors[result.status];
|
||||
if (error) {
|
||||
throw new ApiError(result, error);
|
||||
}
|
||||
|
||||
if (!result.ok) {
|
||||
throw new ApiError(result, 'Generic Error');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request using fetch
|
||||
* @param options Request options
|
||||
* @result ApiResult
|
||||
* @throws ApiError
|
||||
*/
|
||||
export async function request(options: ApiRequestOptions): Promise<ApiResult> {
|
||||
const url = getUrl(options);
|
||||
const response = await sendRequest(options, url);
|
||||
const responseBody = await getResponseBody(response);
|
||||
const responseHeader = getResponseHeader(response, options.responseHeader);
|
||||
|
||||
const result: ApiResult = {
|
||||
url,
|
||||
ok: response.ok,
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
body: responseHeader || responseBody,
|
||||
};
|
||||
|
||||
catchErrors(options, result);
|
||||
return result;
|
||||
}
|
||||
17
src/generated/v3/node/core/ApiError.ts
Normal file
17
src/generated/v3/node/core/ApiError.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { ApiResult } from './ApiResult';
|
||||
|
||||
export class ApiError extends Error {
|
||||
public readonly url: string;
|
||||
public readonly status: number;
|
||||
public readonly statusText: string;
|
||||
public readonly body: any;
|
||||
|
||||
constructor(response: ApiResult, message: string) {
|
||||
super(message);
|
||||
|
||||
this.url = response.url;
|
||||
this.status = response.status;
|
||||
this.statusText = response.statusText;
|
||||
this.body = response.body;
|
||||
}
|
||||
}
|
||||
11
src/generated/v3/node/core/ApiRequestOptions.ts
Normal file
11
src/generated/v3/node/core/ApiRequestOptions.ts
Normal file
@ -0,0 +1,11 @@
|
||||
export interface ApiRequestOptions {
|
||||
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>;
|
||||
}
|
||||
7
src/generated/v3/node/core/ApiResult.ts
Normal file
7
src/generated/v3/node/core/ApiResult.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export interface ApiResult {
|
||||
readonly url: string;
|
||||
readonly ok: boolean;
|
||||
readonly status: number;
|
||||
readonly statusText: string;
|
||||
readonly body: any;
|
||||
}
|
||||
15
src/generated/v3/node/core/OpenAPI.ts
Normal file
15
src/generated/v3/node/core/OpenAPI.ts
Normal file
@ -0,0 +1,15 @@
|
||||
interface Config {
|
||||
BASE: string;
|
||||
VERSION: string;
|
||||
CLIENT: 'fetch' | 'xhr' | 'node';
|
||||
WITH_CREDENTIALS: boolean;
|
||||
TOKEN: string;
|
||||
}
|
||||
|
||||
export const OpenAPI: Config = {
|
||||
BASE: 'http://localhost:3000/base',
|
||||
VERSION: '1.0',
|
||||
CLIENT: 'node',
|
||||
WITH_CREDENTIALS: false,
|
||||
TOKEN: '',
|
||||
};
|
||||
179
src/generated/v3/node/core/request.ts
Normal file
179
src/generated/v3/node/core/request.ts
Normal file
@ -0,0 +1,179 @@
|
||||
import * as FormData from 'form-data';
|
||||
import fetch, { BodyInit, Headers, RequestInit, Response } from 'node-fetch';
|
||||
|
||||
import { ApiError } from './ApiError';
|
||||
import { ApiRequestOptions } from './ApiRequestOptions';
|
||||
import { ApiResult } from './ApiResult';
|
||||
import { OpenAPI } from './OpenAPI';
|
||||
|
||||
function isDefined<T>(value: T | null | undefined): value is Exclude<T, null | undefined> {
|
||||
return value !== undefined && value !== null;
|
||||
}
|
||||
function getQueryString(params: Record<string, any>): string {
|
||||
const qs: string[] = [];
|
||||
|
||||
Object.keys(params).forEach(key => {
|
||||
const value = params[key];
|
||||
if (isDefined(value)) {
|
||||
if (Array.isArray(value)) {
|
||||
value.forEach(value => {
|
||||
qs.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);
|
||||
});
|
||||
} else {
|
||||
qs.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (qs.length > 0) {
|
||||
return `?${qs.join('&')}`;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
function getUrl(options: ApiRequestOptions): string {
|
||||
const path = options.path.replace(/[:]/g, '_');
|
||||
const url = `${OpenAPI.BASE}${path}`;
|
||||
|
||||
if (options.query) {
|
||||
return url + getQueryString(options.query);
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
function getFormData(params: Record<string, any>): FormData {
|
||||
const formData = new FormData();
|
||||
|
||||
Object.keys(params).forEach(key => {
|
||||
const value = params[key];
|
||||
if (isDefined(value)) {
|
||||
formData.append(key, value);
|
||||
}
|
||||
});
|
||||
|
||||
return formData;
|
||||
}
|
||||
function getHeaders(options: ApiRequestOptions): Headers {
|
||||
const headers = new Headers({
|
||||
Accept: 'application/json',
|
||||
...options.headers,
|
||||
});
|
||||
|
||||
if (OpenAPI.TOKEN !== null && OpenAPI.TOKEN !== '') {
|
||||
headers.append('Authorization', `Bearer ${OpenAPI.TOKEN}`);
|
||||
}
|
||||
|
||||
if (options.body) {
|
||||
if (options.body instanceof Blob) {
|
||||
if (options.body.type) {
|
||||
headers.append('Content-Type', options.body.type);
|
||||
}
|
||||
} else if (typeof options.body === 'string') {
|
||||
headers.append('Content-Type', 'text/plain');
|
||||
} else {
|
||||
headers.append('Content-Type', 'application/json');
|
||||
}
|
||||
}
|
||||
|
||||
return headers;
|
||||
}
|
||||
function getRequestBody(options: ApiRequestOptions): BodyInit | undefined {
|
||||
if (options.formData) {
|
||||
return getFormData(options.formData);
|
||||
}
|
||||
|
||||
if (options.body) {
|
||||
if (options.body instanceof ArrayBuffer) {
|
||||
return options.body;
|
||||
} else if (typeof options.body === 'string') {
|
||||
return options.body;
|
||||
} else {
|
||||
return JSON.stringify(options.body);
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
async function sendRequest(options: ApiRequestOptions, url: string): Promise<Response> {
|
||||
const request: RequestInit = {
|
||||
method: options.method,
|
||||
headers: getHeaders(options),
|
||||
body: getRequestBody(options),
|
||||
};
|
||||
|
||||
return await fetch(url, request);
|
||||
}
|
||||
function getResponseHeader(response: Response, responseHeader?: string): string | null {
|
||||
if (responseHeader) {
|
||||
const content = response.headers.get(responseHeader);
|
||||
if (typeof content === 'string') {
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
async function getResponseBody(response: Response): Promise<any> {
|
||||
try {
|
||||
const contentType = response.headers.get('Content-Type');
|
||||
if (contentType) {
|
||||
switch (contentType.toLowerCase()) {
|
||||
case 'application/json':
|
||||
case 'application/json; charset=utf-8':
|
||||
return await response.json();
|
||||
|
||||
default:
|
||||
return await response.text();
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
function catchErrors(options: ApiRequestOptions, result: ApiResult): void {
|
||||
const errors: Record<number, string> = {
|
||||
400: 'Bad Request',
|
||||
401: 'Unauthorized',
|
||||
403: 'Forbidden',
|
||||
404: 'Not Found',
|
||||
500: 'Internal Server Error',
|
||||
502: 'Bad Gateway',
|
||||
503: 'Service Unavailable',
|
||||
...options.errors,
|
||||
};
|
||||
|
||||
const error = errors[result.status];
|
||||
if (error) {
|
||||
throw new ApiError(result, error);
|
||||
}
|
||||
|
||||
if (!result.ok) {
|
||||
throw new ApiError(result, 'Generic Error');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request using node-fetch
|
||||
* @param options Request options
|
||||
* @result ApiResult
|
||||
* @throws ApiError
|
||||
*/
|
||||
export async function request(options: ApiRequestOptions): Promise<ApiResult> {
|
||||
const url = getUrl(options);
|
||||
const response = await sendRequest(options, url);
|
||||
const responseBody = await getResponseBody(response);
|
||||
const responseHeader = getResponseHeader(response, options.responseHeader);
|
||||
|
||||
const result: ApiResult = {
|
||||
url,
|
||||
ok: response.ok,
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
body: responseHeader || responseBody,
|
||||
};
|
||||
|
||||
catchErrors(options, result);
|
||||
return result;
|
||||
}
|
||||
17
src/generated/v3/xhr/core/ApiError.ts
Normal file
17
src/generated/v3/xhr/core/ApiError.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { ApiResult } from './ApiResult';
|
||||
|
||||
export class ApiError extends Error {
|
||||
public readonly url: string;
|
||||
public readonly status: number;
|
||||
public readonly statusText: string;
|
||||
public readonly body: any;
|
||||
|
||||
constructor(response: ApiResult, message: string) {
|
||||
super(message);
|
||||
|
||||
this.url = response.url;
|
||||
this.status = response.status;
|
||||
this.statusText = response.statusText;
|
||||
this.body = response.body;
|
||||
}
|
||||
}
|
||||
11
src/generated/v3/xhr/core/ApiRequestOptions.ts
Normal file
11
src/generated/v3/xhr/core/ApiRequestOptions.ts
Normal file
@ -0,0 +1,11 @@
|
||||
export interface ApiRequestOptions {
|
||||
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>;
|
||||
}
|
||||
7
src/generated/v3/xhr/core/ApiResult.ts
Normal file
7
src/generated/v3/xhr/core/ApiResult.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export interface ApiResult {
|
||||
readonly url: string;
|
||||
readonly ok: boolean;
|
||||
readonly status: number;
|
||||
readonly statusText: string;
|
||||
readonly body: any;
|
||||
}
|
||||
15
src/generated/v3/xhr/core/OpenAPI.ts
Normal file
15
src/generated/v3/xhr/core/OpenAPI.ts
Normal file
@ -0,0 +1,15 @@
|
||||
interface Config {
|
||||
BASE: string;
|
||||
VERSION: string;
|
||||
CLIENT: 'fetch' | 'xhr' | 'node';
|
||||
WITH_CREDENTIALS: boolean;
|
||||
TOKEN: string;
|
||||
}
|
||||
|
||||
export const OpenAPI: Config = {
|
||||
BASE: 'http://localhost:3000/base',
|
||||
VERSION: '1.0',
|
||||
CLIENT: 'xhr',
|
||||
WITH_CREDENTIALS: false,
|
||||
TOKEN: '',
|
||||
};
|
||||
193
src/generated/v3/xhr/core/request.ts
Normal file
193
src/generated/v3/xhr/core/request.ts
Normal file
@ -0,0 +1,193 @@
|
||||
import { ApiError } from './ApiError';
|
||||
import { ApiRequestOptions } from './ApiRequestOptions';
|
||||
import { ApiResult } from './ApiResult';
|
||||
import { OpenAPI } from './OpenAPI';
|
||||
|
||||
function isDefined<T>(value: T | null | undefined): value is Exclude<T, null | undefined> {
|
||||
return value !== undefined && value !== null;
|
||||
}
|
||||
function isSuccess(status: number): boolean {
|
||||
return status >= 200 && status < 300;
|
||||
}
|
||||
function getQueryString(params: Record<string, any>): string {
|
||||
const qs: string[] = [];
|
||||
|
||||
Object.keys(params).forEach(key => {
|
||||
const value = params[key];
|
||||
if (isDefined(value)) {
|
||||
if (Array.isArray(value)) {
|
||||
value.forEach(value => {
|
||||
qs.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);
|
||||
});
|
||||
} else {
|
||||
qs.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (qs.length > 0) {
|
||||
return `?${qs.join('&')}`;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
function getUrl(options: ApiRequestOptions): string {
|
||||
const path = options.path.replace(/[:]/g, '_');
|
||||
const url = `${OpenAPI.BASE}${path}`;
|
||||
|
||||
if (options.query) {
|
||||
return url + getQueryString(options.query);
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
function getFormData(params: Record<string, any>): FormData {
|
||||
const formData = new FormData();
|
||||
|
||||
Object.keys(params).forEach(key => {
|
||||
const value = params[key];
|
||||
if (isDefined(value)) {
|
||||
formData.append(key, value);
|
||||
}
|
||||
});
|
||||
|
||||
return formData;
|
||||
}
|
||||
function getHeaders(options: ApiRequestOptions): Headers {
|
||||
const headers = new Headers({
|
||||
Accept: 'application/json',
|
||||
...options.headers,
|
||||
});
|
||||
|
||||
if (OpenAPI.TOKEN !== null && OpenAPI.TOKEN !== '') {
|
||||
headers.append('Authorization', `Bearer ${OpenAPI.TOKEN}`);
|
||||
}
|
||||
|
||||
if (options.body) {
|
||||
if (options.body instanceof Blob) {
|
||||
if (options.body.type) {
|
||||
headers.append('Content-Type', options.body.type);
|
||||
}
|
||||
} else if (typeof options.body === 'string') {
|
||||
headers.append('Content-Type', 'text/plain');
|
||||
} else {
|
||||
headers.append('Content-Type', 'application/json');
|
||||
}
|
||||
}
|
||||
|
||||
return headers;
|
||||
}
|
||||
function getRequestBody(options: ApiRequestOptions): any {
|
||||
if (options.formData) {
|
||||
return getFormData(options.formData);
|
||||
}
|
||||
|
||||
if (options.body) {
|
||||
if (options.body instanceof Blob) {
|
||||
return options.body;
|
||||
} else if (typeof options.body === 'string') {
|
||||
return options.body;
|
||||
} else {
|
||||
return JSON.stringify(options.body);
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
function sendRequest(options: ApiRequestOptions, url: string): Promise<XMLHttpRequest> {
|
||||
return new Promise<XMLHttpRequest>((resolve, reject) => {
|
||||
try {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open(options.method, url, true);
|
||||
xhr.withCredentials = OpenAPI.WITH_CREDENTIALS;
|
||||
|
||||
const headers = getHeaders(options);
|
||||
headers.forEach((value, key) => {
|
||||
xhr.setRequestHeader(key, value);
|
||||
});
|
||||
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === XMLHttpRequest.DONE) {
|
||||
resolve(xhr);
|
||||
}
|
||||
};
|
||||
|
||||
xhr.send(getRequestBody(options));
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
function getResponseHeader(xhr: XMLHttpRequest, responseHeader?: string): string | null {
|
||||
if (responseHeader) {
|
||||
const content = xhr.getResponseHeader(responseHeader);
|
||||
if (typeof content === 'string') {
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
function getResponseBody(xhr: XMLHttpRequest): any {
|
||||
try {
|
||||
const contentType = xhr.getResponseHeader('Content-Type');
|
||||
if (contentType) {
|
||||
switch (contentType.toLowerCase()) {
|
||||
case 'application/json':
|
||||
case 'application/json; charset=utf-8':
|
||||
return JSON.parse(xhr.responseText);
|
||||
|
||||
default:
|
||||
return xhr.responseText;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
function catchErrors(options: ApiRequestOptions, result: ApiResult): void {
|
||||
const errors: Record<number, string> = {
|
||||
400: 'Bad Request',
|
||||
401: 'Unauthorized',
|
||||
403: 'Forbidden',
|
||||
404: 'Not Found',
|
||||
500: 'Internal Server Error',
|
||||
502: 'Bad Gateway',
|
||||
503: 'Service Unavailable',
|
||||
...options.errors,
|
||||
};
|
||||
|
||||
const error = errors[result.status];
|
||||
if (error) {
|
||||
throw new ApiError(result, error);
|
||||
}
|
||||
|
||||
if (!result.ok) {
|
||||
throw new ApiError(result, 'Generic Error');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Request using XHR
|
||||
* @param options Request options
|
||||
* @result ApiResult
|
||||
* @throws ApiError
|
||||
*/
|
||||
export async function request(options: ApiRequestOptions): Promise<ApiResult> {
|
||||
const url = getUrl(options);
|
||||
const response = await sendRequest(options, url);
|
||||
const responseBody = getResponseBody(response);
|
||||
const responseHeader = getResponseHeader(response, options.responseHeader);
|
||||
|
||||
const result: ApiResult = {
|
||||
url,
|
||||
ok: isSuccess(response.status),
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
body: responseHeader || responseBody,
|
||||
};
|
||||
|
||||
catchErrors(options, result);
|
||||
return result;
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
{{>header}}
|
||||
|
||||
import { ApiResponse } from './ApiResponse';
|
||||
import { ApiResult } from './ApiResult';
|
||||
|
||||
export class ApiError extends Error {
|
||||
public readonly url: string;
|
||||
@ -8,7 +8,7 @@ export class ApiError extends Error {
|
||||
public readonly statusText: string;
|
||||
public readonly body: any;
|
||||
|
||||
constructor(response: ApiResponse, message: string) {
|
||||
constructor(response: ApiResult, message: string) {
|
||||
super(message);
|
||||
|
||||
this.url = response.url;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{{>header}}
|
||||
|
||||
export interface RequestOptions {
|
||||
export interface ApiRequestOptions {
|
||||
readonly method: 'GET' | 'PUT' | 'POST' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'PATCH';
|
||||
readonly path: string;
|
||||
readonly cookies?: Record<string, any>;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{{>header}}
|
||||
|
||||
export interface Response {
|
||||
export interface ApiResult {
|
||||
readonly url: string;
|
||||
readonly ok: boolean;
|
||||
readonly status: number;
|
||||
@ -1,8 +1,7 @@
|
||||
function getRequestBody(options: ApiRequestOptions): any {
|
||||
function getRequestBody(options: ApiRequestOptions): BodyInit | undefined {
|
||||
if (options.formData) {
|
||||
return getFormData(options.formData);
|
||||
}
|
||||
|
||||
if (options.body) {
|
||||
if (options.body instanceof Blob) {
|
||||
return options.body;
|
||||
@ -12,6 +11,5 @@ function getRequestBody(options: ApiRequestOptions): any {
|
||||
return JSON.stringify(options.body);
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
17
src/templates/core/fetch/getResponseBody.hbs
Normal file
17
src/templates/core/fetch/getResponseBody.hbs
Normal file
@ -0,0 +1,17 @@
|
||||
async function getResponseBody(response: Response): Promise<any> {
|
||||
try {
|
||||
const contentType = response.headers.get('Content-Type');
|
||||
if (contentType) {
|
||||
switch (contentType.toLowerCase()) {
|
||||
case 'application/json':
|
||||
case 'application/json; charset=utf-8':
|
||||
return await response.json();
|
||||
default:
|
||||
return await response.text();
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -5,6 +5,5 @@ function getResponseHeader(response: Response, responseHeader?: string): string
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
49
src/templates/core/fetch/request.hbs
Normal file
49
src/templates/core/fetch/request.hbs
Normal file
@ -0,0 +1,49 @@
|
||||
import { ApiError } from './ApiError';
|
||||
import { ApiRequestOptions } from './ApiRequestOptions';
|
||||
import { ApiResult } from './ApiResult';
|
||||
import { OpenAPI } from './OpenAPI';
|
||||
|
||||
{{>functions/isDefined}}
|
||||
|
||||
{{>functions/getQueryString}}
|
||||
|
||||
{{>functions/getUrl}}
|
||||
|
||||
{{>functions/getFormData}}
|
||||
|
||||
{{>functions/getHeaders}}
|
||||
|
||||
{{>fetch/getRequestBody}}
|
||||
|
||||
{{>fetch/sendRequest}}
|
||||
|
||||
{{>fetch/getResponseHeader}}
|
||||
|
||||
{{>fetch/getResponseBody}}
|
||||
|
||||
{{>functions/catchErrors}}
|
||||
|
||||
|
||||
/**
|
||||
* Request using fetch
|
||||
* @param options Request options
|
||||
* @result ApiResult
|
||||
* @throws ApiError
|
||||
*/
|
||||
export async function request(options: ApiRequestOptions): Promise<ApiResult> {
|
||||
const url = getUrl(options);
|
||||
const response = await sendRequest(options, url);
|
||||
const responseBody = await getResponseBody(response);
|
||||
const responseHeader = getResponseHeader(response, options.responseHeader);
|
||||
|
||||
const result: ApiResult = {
|
||||
url,
|
||||
ok: response.ok,
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
body: responseHeader || responseBody,
|
||||
};
|
||||
|
||||
catchErrors(options, result);
|
||||
return result;
|
||||
}
|
||||
8
src/templates/core/fetch/sendRequest.hbs
Normal file
8
src/templates/core/fetch/sendRequest.hbs
Normal file
@ -0,0 +1,8 @@
|
||||
async function sendRequest(options: ApiRequestOptions, url: string): Promise<Response> {
|
||||
const request: RequestInit = {
|
||||
method: options.method,
|
||||
headers: getHeaders(options),
|
||||
body: getRequestBody(options),
|
||||
};
|
||||
return await fetch(url, request);
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
function catchErrors(options: ApiRequestOptions, response: ApiResponse): void {
|
||||
const errors = {
|
||||
function catchErrors(options: ApiRequestOptions, result: ApiResult): void {
|
||||
const errors: Record<number, string> = {
|
||||
400: 'Bad Request',
|
||||
401: 'Unauthorized',
|
||||
403: 'Forbidden',
|
||||
@ -10,12 +10,12 @@ function catchErrors(options: ApiRequestOptions, response: ApiResponse): void {
|
||||
...options.errors,
|
||||
}
|
||||
|
||||
const error = errors[response.status];
|
||||
const error = errors[result.status];
|
||||
if (error) {
|
||||
throw new ApiError(response, error);
|
||||
throw new ApiError(result, error);
|
||||
}
|
||||
|
||||
if (!result.ok) {
|
||||
throw new ApiError(response, 'Generic Error');
|
||||
throw new ApiError(result, 'Generic Error');
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
function getFormData(params: Record<string, any>): FormData {
|
||||
const formData = new FormData();
|
||||
|
||||
Object.keys(params).forEach(key => {
|
||||
const value = params[key];
|
||||
if (isDefined(value)) {
|
||||
formData.append(key, value);
|
||||
}
|
||||
});
|
||||
|
||||
return formData;
|
||||
}
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
function getHeaders(options: ApiRequestOptions): Headers {
|
||||
const headers = new Headers({
|
||||
...options.headers,
|
||||
Accept: 'application/json',
|
||||
...options.headers,
|
||||
});
|
||||
|
||||
if (OpenAPI.TOKEN !== null && OpenAPI.TOKEN !== '') {
|
||||
if (isDefined(OpenAPI.TOKEN) && OpenAPI.TOKEN !== '') {
|
||||
headers.append('Authorization', `Bearer ${OpenAPI.TOKEN}`);
|
||||
}
|
||||
|
||||
@ -19,6 +19,5 @@ function getHeaders(options: ApiRequestOptions): Headers {
|
||||
headers.append('Content-Type', 'application/json');
|
||||
}
|
||||
}
|
||||
|
||||
return headers;
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
function getQueryString(params: Record<string, any>): string {
|
||||
const qs: string[] = [];
|
||||
|
||||
Object.keys(params).forEach(key => {
|
||||
const value = params[key];
|
||||
if (isDefined(value)) {
|
||||
@ -13,10 +12,8 @@ function getQueryString(params: Record<string, any>): string {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (qs.length > 0) {
|
||||
return `?${qs.join('&')}`;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
@ -5,6 +5,5 @@ function getUrl(options: ApiRequestOptions): string {
|
||||
if (options.query) {
|
||||
return url + getQueryString(options.query);
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
15
src/templates/core/node/getRequestBody.hbs
Normal file
15
src/templates/core/node/getRequestBody.hbs
Normal file
@ -0,0 +1,15 @@
|
||||
function getRequestBody(options: ApiRequestOptions): BodyInit | undefined {
|
||||
if (options.formData) {
|
||||
return getFormData(options.formData);
|
||||
}
|
||||
if (options.body) {
|
||||
if (options.body instanceof ArrayBuffer) {
|
||||
return options.body;
|
||||
} else if (typeof options.body === 'string') {
|
||||
return options.body;
|
||||
} else {
|
||||
return JSON.stringify(options.body);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
@ -11,9 +11,8 @@ async function getResponseBody(response: Response): Promise<any> {
|
||||
return await response.text();
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
9
src/templates/core/node/getResponseHeader.hbs
Normal file
9
src/templates/core/node/getResponseHeader.hbs
Normal file
@ -0,0 +1,9 @@
|
||||
function getResponseHeader(response: Response, responseHeader?: string): string | null {
|
||||
if (responseHeader) {
|
||||
const content = response.headers.get(responseHeader);
|
||||
if (typeof content === 'string') {
|
||||
return content;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
51
src/templates/core/node/request.hbs
Normal file
51
src/templates/core/node/request.hbs
Normal file
@ -0,0 +1,51 @@
|
||||
import { ApiError } from './ApiError';
|
||||
import { ApiRequestOptions } from './ApiRequestOptions';
|
||||
import { ApiResult } from './ApiResult';
|
||||
import { OpenAPI } from './OpenAPI';
|
||||
import fetch, { Headers, RequestInit, Response, BodyInit } from 'node-fetch';
|
||||
import * as FormData from 'form-data';
|
||||
|
||||
{{>functions/isDefined}}
|
||||
|
||||
{{>functions/getQueryString}}
|
||||
|
||||
{{>functions/getUrl}}
|
||||
|
||||
{{>functions/getFormData}}
|
||||
|
||||
{{>functions/getHeaders}}
|
||||
|
||||
{{>node/getRequestBody}}
|
||||
|
||||
{{>node/sendRequest}}
|
||||
|
||||
{{>node/getResponseHeader}}
|
||||
|
||||
{{>node/getResponseBody}}
|
||||
|
||||
{{>functions/catchErrors}}
|
||||
|
||||
|
||||
/**
|
||||
* Request using node-fetch
|
||||
* @param options Request options
|
||||
* @result ApiResult
|
||||
* @throws ApiError
|
||||
*/
|
||||
export async function request(options: ApiRequestOptions): Promise<ApiResult> {
|
||||
const url = getUrl(options);
|
||||
const response = await sendRequest(options, url);
|
||||
const responseBody = await getResponseBody(response);
|
||||
const responseHeader = getResponseHeader(response, options.responseHeader);
|
||||
|
||||
const result: ApiResult = {
|
||||
url,
|
||||
ok: response.ok,
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
body: responseHeader || responseBody,
|
||||
};
|
||||
|
||||
catchErrors(options, result);
|
||||
return result;
|
||||
}
|
||||
8
src/templates/core/node/sendRequest.hbs
Normal file
8
src/templates/core/node/sendRequest.hbs
Normal file
@ -0,0 +1,8 @@
|
||||
async function sendRequest(options: ApiRequestOptions, url: string): Promise<Response> {
|
||||
const request: RequestInit = {
|
||||
method: options.method,
|
||||
headers: getHeaders(options),
|
||||
body: getRequestBody(options),
|
||||
};
|
||||
return await fetch(url, request);
|
||||
}
|
||||
@ -1,2 +1,11 @@
|
||||
{{>header}}
|
||||
{{>requestUsingFetch}}
|
||||
|
||||
{{#equals httpClient 'fetch'}}
|
||||
{{>fetch/request}}
|
||||
{{/equals}}
|
||||
{{#equals httpClient 'xhr'}}
|
||||
{{>xhr/request}}
|
||||
{{/equals}}
|
||||
{{#equals httpClient 'node'}}
|
||||
{{>node/request}}
|
||||
{{/equals}}
|
||||
|
||||
@ -1,26 +0,0 @@
|
||||
function getRequest(options: ApiRequestOptions): RequestInit {
|
||||
const request: RequestInit = {
|
||||
headers: getHeaders(options),
|
||||
method: options.method,
|
||||
};
|
||||
|
||||
if (OpenAPI.WITH_CREDENTIALS) {
|
||||
request.credentials = 'include';
|
||||
}
|
||||
|
||||
if (options.formData) {
|
||||
request.body = getFormData(options.formData);
|
||||
}
|
||||
|
||||
if (options.body) {
|
||||
if (options.body instanceof Blob) {
|
||||
request.body = options.body;
|
||||
} else if (typeof options.body === 'string') {
|
||||
request.body = options.body;
|
||||
} else {
|
||||
request.body = JSON.stringify(options.body);
|
||||
}
|
||||
}
|
||||
|
||||
return request;
|
||||
}
|
||||
@ -1,55 +0,0 @@
|
||||
import { ApiError } from './ApiError';
|
||||
import { ApiRequestOptions } from './ApiRequestOptions';
|
||||
import { ApiResponse } from './ApiResponse';
|
||||
import { OpenAPI } from './OpenAPI';
|
||||
|
||||
import fetch, { Headers } from 'node-fetch';
|
||||
import FormData from 'form-data';
|
||||
|
||||
{{>isDefined}}
|
||||
|
||||
{{>isSuccess}}
|
||||
|
||||
{{>getQueryString}}
|
||||
|
||||
{{>getUrl}}
|
||||
|
||||
{{>catchErrors}}
|
||||
|
||||
{{>getFormData}}
|
||||
|
||||
{{>getHeaders}}
|
||||
|
||||
{{>getRequestBody}}
|
||||
|
||||
{{>getRequest}}
|
||||
|
||||
{{>getResponseHeader}}
|
||||
|
||||
{{>getResponseBody}}
|
||||
|
||||
/**
|
||||
* Request using fetch
|
||||
* @param options Request options
|
||||
* @result ApiResponse
|
||||
* @throws ApiError
|
||||
*/
|
||||
export async function request(options: ApiRequestOptions): Promise<ApiResponse> {
|
||||
const url = getUrl(options);
|
||||
const request = getRequest(options);
|
||||
const response = await fetch(url, request);
|
||||
const responseBody = await getResponseBody(response);
|
||||
const responseHeader = getResponseHeader(response, options.responseHeader);
|
||||
|
||||
const response: ApiResponse = {
|
||||
url,
|
||||
ok: isSuccess(xhr.status),
|
||||
status: xhr.status,
|
||||
statusText: xhr.statusText,
|
||||
body: responseHeader || responseBody,
|
||||
};
|
||||
|
||||
catchErrors(options, response);
|
||||
|
||||
return response;
|
||||
}
|
||||
@ -1,52 +0,0 @@
|
||||
import { ApiError } from './ApiError';
|
||||
import { ApiRequestOptions } from './ApiRequestOptions';
|
||||
import { ApiResponse } from './ApiResponse';
|
||||
import { OpenAPI } from './OpenAPI';
|
||||
|
||||
{{>isDefined}}
|
||||
|
||||
{{>isSuccess}}
|
||||
|
||||
{{>getQueryString}}
|
||||
|
||||
{{>getUrl}}
|
||||
|
||||
{{>catchErrors}}
|
||||
|
||||
{{>getFormData}}
|
||||
|
||||
{{>getHeaders}}
|
||||
|
||||
{{>getRequestBody}}
|
||||
|
||||
{{>getRequest}}
|
||||
|
||||
{{>getResponseHeader}}
|
||||
|
||||
{{>getResponseBody}}
|
||||
|
||||
/**
|
||||
* Request using XHR
|
||||
* @param options Request options
|
||||
* @result ApiResponse
|
||||
* @throws ApiError
|
||||
*/
|
||||
export async function request(options: ApiRequestOptions): Promise<ApiResponse> {
|
||||
const url = getUrl(options);
|
||||
|
||||
return await getRequest(options.method, url, xhr => {
|
||||
const responseBody = getResponseBody(response);
|
||||
const responseHeader = getResponseHeader(response, options.responseHeader);
|
||||
|
||||
const response: ApiResponse = {
|
||||
url,
|
||||
ok: isSuccess(xhr.status),
|
||||
status: xhr.status,
|
||||
statusText: xhr.statusText,
|
||||
body: responseHeader || responseBody,
|
||||
};
|
||||
|
||||
catchErrors(options, response);
|
||||
return response;
|
||||
});
|
||||
}
|
||||
@ -2,7 +2,6 @@ function getRequestBody(options: ApiRequestOptions): any {
|
||||
if (options.formData) {
|
||||
return getFormData(options.formData);
|
||||
}
|
||||
|
||||
if (options.body) {
|
||||
if (options.body instanceof Blob) {
|
||||
return options.body;
|
||||
@ -12,6 +11,5 @@ function getRequestBody(options: ApiRequestOptions): any {
|
||||
return JSON.stringify(options.body);
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
function getResponseBody(xhr: XMLHttpRequest): Promise<any> {
|
||||
function getResponseBody(xhr: XMLHttpRequest): any {
|
||||
try {
|
||||
const contentType = xhr.getResponseHeader('Content-Type');
|
||||
if (contentType) {
|
||||
@ -11,9 +11,8 @@ function getResponseBody(xhr: XMLHttpRequest): Promise<any> {
|
||||
return xhr.responseText;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
@ -5,6 +5,5 @@ function getResponseHeader(xhr: XMLHttpRequest, responseHeader?: string): string
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
50
src/templates/core/xhr/request.hbs
Normal file
50
src/templates/core/xhr/request.hbs
Normal file
@ -0,0 +1,50 @@
|
||||
import { ApiError } from './ApiError';
|
||||
import { ApiRequestOptions } from './ApiRequestOptions';
|
||||
import { ApiResult } from './ApiResult';
|
||||
import { OpenAPI } from './OpenAPI';
|
||||
|
||||
{{>functions/isDefined}}
|
||||
|
||||
{{>functions/isSuccess}}
|
||||
|
||||
{{>functions/getQueryString}}
|
||||
|
||||
{{>functions/getUrl}}
|
||||
|
||||
{{>functions/getFormData}}
|
||||
|
||||
{{>functions/getHeaders}}
|
||||
|
||||
{{>xhr/getRequestBody}}
|
||||
|
||||
{{>xhr/sendRequest}}
|
||||
|
||||
{{>xhr/getResponseHeader}}
|
||||
|
||||
{{>xhr/getResponseBody}}
|
||||
|
||||
{{>functions/catchErrors}}
|
||||
|
||||
/**
|
||||
* Request using XHR
|
||||
* @param options Request options
|
||||
* @result ApiResult
|
||||
* @throws ApiError
|
||||
*/
|
||||
export async function request(options: ApiRequestOptions): Promise<ApiResult> {
|
||||
const url = getUrl(options);
|
||||
const response = await sendRequest(options, url);
|
||||
const responseBody = getResponseBody(response);
|
||||
const responseHeader = getResponseHeader(response, options.responseHeader);
|
||||
|
||||
const result: ApiResult = {
|
||||
url,
|
||||
ok: isSuccess(response.status),
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
body: responseHeader || responseBody,
|
||||
};
|
||||
|
||||
catchErrors(options, result);
|
||||
return result;
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
function getRequest(options: ApiRequestOptions, url: string, listener: (xhr: XMLHttpRequest) => ApiResponse): Promise<ApiResponse> {
|
||||
return new Promise<ApiResponse>((resolve, reject) => {
|
||||
function sendRequest(options: ApiRequestOptions, url: string): Promise<XMLHttpRequest> {
|
||||
return new Promise<XMLHttpRequest>((resolve, reject) => {
|
||||
try {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open(options.method, url, true);
|
||||
@ -12,14 +12,13 @@ function getRequest(options: ApiRequestOptions, url: string, listener: (xhr: XML
|
||||
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === XMLHttpRequest.DONE) {
|
||||
const response = listener(xhr);
|
||||
resolve(response);
|
||||
resolve(xhr);
|
||||
}
|
||||
};
|
||||
|
||||
xhr.send(getRequestBody());
|
||||
xhr.send(getRequestBody(options));
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
@ -34,8 +34,7 @@ export class {{{name}}} {
|
||||
* @throws ApiError
|
||||
*/
|
||||
public static async {{{name}}}({{>parameters}}): Promise<{{>result}}> {
|
||||
|
||||
const response = await __request({
|
||||
const result = await __request({
|
||||
method: '{{{method}}}',
|
||||
path: `{{{path}}}`,
|
||||
{{#if parametersCookie~}}
|
||||
@ -80,8 +79,7 @@ export class {{{name}}} {
|
||||
},
|
||||
{{/if}}
|
||||
});
|
||||
|
||||
return response.body;
|
||||
return result.body;
|
||||
}
|
||||
|
||||
{{/each}}
|
||||
@ -9,13 +9,8 @@ describe('registerHandlebarTemplates', () => {
|
||||
expect(templates.exports.service).toBeDefined();
|
||||
expect(templates.core.settings).toBeDefined();
|
||||
expect(templates.core.apiError).toBeDefined();
|
||||
expect(templates.core.getFormData).toBeDefined();
|
||||
expect(templates.core.getQueryString).toBeDefined();
|
||||
expect(templates.core.isSuccess).toBeDefined();
|
||||
expect(templates.core.apiRequestOptions).toBeDefined();
|
||||
expect(templates.core.apiResult).toBeDefined();
|
||||
expect(templates.core.request).toBeDefined();
|
||||
expect(templates.core.requestOptions).toBeDefined();
|
||||
expect(templates.core.requestUsingFetch).toBeDefined();
|
||||
expect(templates.core.requestUsingXHR).toBeDefined();
|
||||
expect(templates.core.result).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,18 +1,32 @@
|
||||
import * as Handlebars from 'handlebars/runtime';
|
||||
|
||||
import templateCoreCatchGenericError from '../templates/core/catchGenericError.hbs';
|
||||
import templateCoreGetFormData from '../templates/core/functions/getFormData.hbs';
|
||||
import templateCoreGetQueryString from '../templates/core/functions/getQueryString.hbs';
|
||||
import templateCoreGetUrl from '../templates/core/functions/getUrl.hbs';
|
||||
import templateCoreIsSuccess from '../templates/core/functions/isSuccess.hbs';
|
||||
import templateCoreApiError from '../templates/core/ApiError.hbs';
|
||||
import templateCoreApiRequestOptions from '../templates/core/ApiRequestOptions.hbs';
|
||||
import templateCoreApiResult from '../templates/core/ApiResult.hbs';
|
||||
import fetchGetRequestBody from '../templates/core/fetch/getRequestBody.hbs';
|
||||
import fetchGetResponseBody from '../templates/core/fetch/getResponseBody.hbs';
|
||||
import fetchGetResponseHeader from '../templates/core/fetch/getResponseHeader.hbs';
|
||||
import fetchRequest from '../templates/core/fetch/request.hbs';
|
||||
import fetchSendRequest from '../templates/core/fetch/sendRequest.hbs';
|
||||
import functionCatchErrors from '../templates/core/functions/catchErrors.hbs';
|
||||
import functionGetFormData from '../templates/core/functions/getFormData.hbs';
|
||||
import functionGetHeaders from '../templates/core/functions/getHeaders.hbs';
|
||||
import functionGetQueryString from '../templates/core/functions/getQueryString.hbs';
|
||||
import functionGetUrl from '../templates/core/functions/getUrl.hbs';
|
||||
import functionIsDefined from '../templates/core/functions/isDefined.hbs';
|
||||
import functionIsSuccess from '../templates/core/functions/isSuccess.hbs';
|
||||
import nodeGetRequestBody from '../templates/core/node/getRequestBody.hbs';
|
||||
import nodeGetResponseBody from '../templates/core/node/getResponseBody.hbs';
|
||||
import nodeGetResponseHeader from '../templates/core/node/getResponseHeader.hbs';
|
||||
import nodeRequest from '../templates/core/node/request.hbs';
|
||||
import nodeSendRequest from '../templates/core/node/sendRequest.hbs';
|
||||
import templateCoreSettings from '../templates/core/OpenAPI.hbs';
|
||||
import templateCoreRequest from '../templates/core/request.hbs';
|
||||
import templateCoreRequestOptions from '../templates/core/RequestOptions.hbs';
|
||||
import templateCoreRequestUsingFetch from '../templates/core/functions/requestUsingFetch.hbs';
|
||||
import templateCoreRequestUsingNode from '../templates/core/functions/requestUsingNode.hbs';
|
||||
import templateCoreRequestUsingXHR from '../templates/core/functions/requestUsingXHR.hbs';
|
||||
import templateCoreResponse from '../templates/core/Response.hbs';
|
||||
import templateCoreResponseError from '../templates/core/ResponseError.hbs';
|
||||
import xhrGetRequestBody from '../templates/core/xhr/getRequestBody.hbs';
|
||||
import xhrGetResponseBody from '../templates/core/xhr/getResponseBody.hbs';
|
||||
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 templateExportSchema from '../templates/exportSchema.hbs';
|
||||
import templateExportService from '../templates/exportService.hbs';
|
||||
@ -21,6 +35,7 @@ import partialExportEnum from '../templates/partials/exportEnum.hbs';
|
||||
import partialExportInterface from '../templates/partials/exportInterface.hbs';
|
||||
import partialExportType from '../templates/partials/exportType.hbs';
|
||||
import partialExtends from '../templates/partials/extends.hbs';
|
||||
import partialHeader from '../templates/partials/header.hbs';
|
||||
import partialIsNullable from '../templates/partials/isNullable.hbs';
|
||||
import partialIsReadOnly from '../templates/partials/isReadOnly.hbs';
|
||||
import partialIsRequired from '../templates/partials/isRequired.hbs';
|
||||
@ -50,18 +65,10 @@ export interface Templates {
|
||||
};
|
||||
core: {
|
||||
settings: Handlebars.TemplateDelegate;
|
||||
getFormData: Handlebars.TemplateDelegate;
|
||||
getQueryString: Handlebars.TemplateDelegate;
|
||||
getUrl: Handlebars.TemplateDelegate;
|
||||
isSuccess: Handlebars.TemplateDelegate;
|
||||
catchGenericError: Handlebars.TemplateDelegate;
|
||||
apiError: Handlebars.TemplateDelegate;
|
||||
apiRequestOptions: Handlebars.TemplateDelegate;
|
||||
apiResult: Handlebars.TemplateDelegate;
|
||||
request: Handlebars.TemplateDelegate;
|
||||
requestOptions: Handlebars.TemplateDelegate;
|
||||
requestUsingFetch: Handlebars.TemplateDelegate;
|
||||
requestUsingXHR: Handlebars.TemplateDelegate;
|
||||
requestUsingNode: Handlebars.TemplateDelegate;
|
||||
response: Handlebars.TemplateDelegate;
|
||||
responseError: Handlebars.TemplateDelegate;
|
||||
};
|
||||
}
|
||||
|
||||
@ -72,6 +79,7 @@ export interface Templates {
|
||||
export function registerHandlebarTemplates(): Templates {
|
||||
registerHandlebarHelpers();
|
||||
|
||||
// Main templates (entry points for the files we write to disk)
|
||||
const templates: Templates = {
|
||||
index: Handlebars.template(templateIndex),
|
||||
exports: {
|
||||
@ -81,25 +89,19 @@ export function registerHandlebarTemplates(): Templates {
|
||||
},
|
||||
core: {
|
||||
settings: Handlebars.template(templateCoreSettings),
|
||||
getFormData: Handlebars.template(templateCoreGetFormData),
|
||||
getQueryString: Handlebars.template(templateCoreGetQueryString),
|
||||
getUrl: Handlebars.template(templateCoreGetUrl),
|
||||
isSuccess: Handlebars.template(templateCoreIsSuccess),
|
||||
catchGenericError: Handlebars.template(templateCoreCatchGenericError),
|
||||
apiError: Handlebars.template(templateCoreApiError),
|
||||
apiRequestOptions: Handlebars.template(templateCoreApiRequestOptions),
|
||||
apiResult: Handlebars.template(templateCoreApiResult),
|
||||
request: Handlebars.template(templateCoreRequest),
|
||||
requestOptions: Handlebars.template(templateCoreRequestOptions),
|
||||
requestUsingFetch: Handlebars.template(templateCoreRequestUsingFetch),
|
||||
requestUsingXHR: Handlebars.template(templateCoreRequestUsingXHR),
|
||||
requestUsingNode: Handlebars.template(templateCoreRequestUsingNode),
|
||||
response: Handlebars.template(templateCoreResponse),
|
||||
responseError: Handlebars.template(templateCoreResponseError),
|
||||
},
|
||||
};
|
||||
|
||||
// Partials for the generations of the models, services, etc.
|
||||
Handlebars.registerPartial('exportEnum', Handlebars.template(partialExportEnum));
|
||||
Handlebars.registerPartial('exportInterface', Handlebars.template(partialExportInterface));
|
||||
Handlebars.registerPartial('exportType', Handlebars.template(partialExportType));
|
||||
Handlebars.registerPartial('extends', Handlebars.template(partialExtends));
|
||||
Handlebars.registerPartial('header', Handlebars.template(partialHeader));
|
||||
Handlebars.registerPartial('isNullable', Handlebars.template(partialIsNullable));
|
||||
Handlebars.registerPartial('isReadOnly', Handlebars.template(partialIsReadOnly));
|
||||
Handlebars.registerPartial('isRequired', Handlebars.template(partialIsRequired));
|
||||
@ -119,5 +121,35 @@ export function registerHandlebarTemplates(): Templates {
|
||||
Handlebars.registerPartial('typeInterface', Handlebars.template(partialTypeInterface));
|
||||
Handlebars.registerPartial('typeReference', Handlebars.template(partialTypeReference));
|
||||
|
||||
// Generic functions used in 'request' file @see src/templates/core/request.hbs for more info
|
||||
Handlebars.registerPartial('functions/catchErrors', Handlebars.template(functionCatchErrors));
|
||||
Handlebars.registerPartial('functions/getFormData', Handlebars.template(functionGetFormData));
|
||||
Handlebars.registerPartial('functions/getHeaders', Handlebars.template(functionGetHeaders));
|
||||
Handlebars.registerPartial('functions/getQueryString', Handlebars.template(functionGetQueryString));
|
||||
Handlebars.registerPartial('functions/getUrl', Handlebars.template(functionGetUrl));
|
||||
Handlebars.registerPartial('functions/isDefined', Handlebars.template(functionIsDefined));
|
||||
Handlebars.registerPartial('functions/isSuccess', Handlebars.template(functionIsSuccess));
|
||||
|
||||
// Specific files for the fetch client implementation
|
||||
Handlebars.registerPartial('fetch/getRequestBody', Handlebars.template(fetchGetRequestBody));
|
||||
Handlebars.registerPartial('fetch/getResponseBody', Handlebars.template(fetchGetResponseBody));
|
||||
Handlebars.registerPartial('fetch/getResponseHeader', Handlebars.template(fetchGetResponseHeader));
|
||||
Handlebars.registerPartial('fetch/sendRequest', Handlebars.template(fetchSendRequest));
|
||||
Handlebars.registerPartial('fetch/request', Handlebars.template(fetchRequest));
|
||||
|
||||
// Specific files for the xhr client implementation
|
||||
Handlebars.registerPartial('xhr/getRequestBody', Handlebars.template(xhrGetRequestBody));
|
||||
Handlebars.registerPartial('xhr/getResponseBody', Handlebars.template(xhrGetResponseBody));
|
||||
Handlebars.registerPartial('xhr/getResponseHeader', Handlebars.template(xhrGetResponseHeader));
|
||||
Handlebars.registerPartial('xhr/sendRequest', Handlebars.template(xhrSendRequest));
|
||||
Handlebars.registerPartial('xhr/request', Handlebars.template(xhrRequest));
|
||||
|
||||
// Specific files for the node client implementation
|
||||
Handlebars.registerPartial('node/getRequestBody', Handlebars.template(nodeGetRequestBody));
|
||||
Handlebars.registerPartial('node/getResponseBody', Handlebars.template(nodeGetResponseBody));
|
||||
Handlebars.registerPartial('node/getResponseHeader', Handlebars.template(nodeGetResponseHeader));
|
||||
Handlebars.registerPartial('node/sendRequest', Handlebars.template(nodeSendRequest));
|
||||
Handlebars.registerPartial('node/request', Handlebars.template(nodeRequest));
|
||||
|
||||
return templates;
|
||||
}
|
||||
|
||||
@ -24,18 +24,10 @@ describe('writeClient', () => {
|
||||
},
|
||||
core: {
|
||||
settings: () => 'settings',
|
||||
getFormData: () => 'getFormData',
|
||||
getQueryString: () => 'getQueryString',
|
||||
getUrl: () => 'getUrl',
|
||||
isSuccess: () => 'isSuccess',
|
||||
catchGenericError: () => 'catchGenericError',
|
||||
apiError: () => 'apiError',
|
||||
apiRequestOptions: () => 'apiRequestOptions',
|
||||
apiResult: () => 'apiResult',
|
||||
request: () => 'request',
|
||||
requestOptions: () => 'requestOptions',
|
||||
requestUsingFetch: () => 'requestUsingFetch',
|
||||
requestUsingXHR: () => 'requestUsingXHR',
|
||||
requestUsingNode: () => 'requestUsingNode',
|
||||
response: () => 'response',
|
||||
responseError: () => 'responseError',
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@ -24,35 +24,19 @@ describe('writeClientCore', () => {
|
||||
},
|
||||
core: {
|
||||
settings: () => 'settings',
|
||||
getFormData: () => 'getFormData',
|
||||
getQueryString: () => 'getQueryString',
|
||||
getUrl: () => 'getUrl',
|
||||
isSuccess: () => 'isSuccess',
|
||||
catchGenericError: () => 'catchGenericError',
|
||||
apiError: () => 'apiError',
|
||||
apiRequestOptions: () => 'apiRequestOptions',
|
||||
apiResult: () => 'apiResult',
|
||||
request: () => 'request',
|
||||
requestOptions: () => 'requestOptions',
|
||||
requestUsingFetch: () => 'requestUsingFetch',
|
||||
requestUsingXHR: () => 'requestUsingXHR',
|
||||
requestUsingNode: () => 'requestUsingNode',
|
||||
response: () => 'response',
|
||||
responseError: () => 'responseError',
|
||||
},
|
||||
};
|
||||
|
||||
await writeClientCore(client, templates, '/', HttpClient.FETCH);
|
||||
|
||||
expect(writeFile).toBeCalledWith('/OpenAPI.ts', 'settings');
|
||||
expect(writeFile).toBeCalledWith('/getFormData.ts', 'getFormData');
|
||||
expect(writeFile).toBeCalledWith('/getQueryString.ts', 'getQueryString');
|
||||
expect(writeFile).toBeCalledWith('/getUrl.ts', 'getUrl');
|
||||
expect(writeFile).toBeCalledWith('/isSuccess.ts', 'isSuccess');
|
||||
expect(writeFile).toBeCalledWith('/catchGenericError.ts', 'catchGenericError');
|
||||
expect(writeFile).toBeCalledWith('/ApiError.ts', 'apiError');
|
||||
expect(writeFile).toBeCalledWith('/ApiRequestOptions.ts', 'apiRequestOptions');
|
||||
expect(writeFile).toBeCalledWith('/ApiResult.ts', 'apiResult');
|
||||
expect(writeFile).toBeCalledWith('/request.ts', 'request');
|
||||
expect(writeFile).toBeCalledWith('/RequestOptions.ts', 'requestOptions');
|
||||
expect(writeFile).toBeCalledWith('/requestUsingFetch.ts', 'requestUsingFetch');
|
||||
expect(writeFile).toBeCalledWith('/requestUsingXHR.ts', 'requestUsingXHR');
|
||||
expect(writeFile).toBeCalledWith('/requestUsingNode.ts', 'requestUsingNode');
|
||||
expect(writeFile).toBeCalledWith('/Response.ts', 'response');
|
||||
expect(writeFile).toBeCalledWith('/ResponseError.ts', 'responseError');
|
||||
});
|
||||
});
|
||||
|
||||
@ -19,16 +19,8 @@ export async function writeClientCore(client: Client, templates: Templates, outp
|
||||
version: client.version,
|
||||
};
|
||||
await writeFile(path.resolve(outputPath, 'OpenAPI.ts'), templates.core.settings(context));
|
||||
await writeFile(path.resolve(outputPath, 'getFormData.ts'), templates.core.getFormData(context));
|
||||
await writeFile(path.resolve(outputPath, 'getQueryString.ts'), templates.core.getQueryString(context));
|
||||
await writeFile(path.resolve(outputPath, 'getUrl.ts'), templates.core.getUrl(context));
|
||||
await writeFile(path.resolve(outputPath, 'isSuccess.ts'), templates.core.isSuccess(context));
|
||||
await writeFile(path.resolve(outputPath, 'catchGenericError.ts'), templates.core.catchGenericError(context));
|
||||
await writeFile(path.resolve(outputPath, 'ApiError.ts'), templates.core.apiError({}));
|
||||
await writeFile(path.resolve(outputPath, 'ApiRequestOptions.ts'), templates.core.apiRequestOptions({}));
|
||||
await writeFile(path.resolve(outputPath, 'ApiResult.ts'), templates.core.apiResult({}));
|
||||
await writeFile(path.resolve(outputPath, 'request.ts'), templates.core.request(context));
|
||||
await writeFile(path.resolve(outputPath, 'RequestOptions.ts'), templates.core.requestOptions(context));
|
||||
await writeFile(path.resolve(outputPath, 'requestUsingFetch.ts'), templates.core.requestUsingFetch(context));
|
||||
await writeFile(path.resolve(outputPath, 'requestUsingXHR.ts'), templates.core.requestUsingXHR(context));
|
||||
await writeFile(path.resolve(outputPath, 'requestUsingNode.ts'), templates.core.requestUsingNode(context));
|
||||
await writeFile(path.resolve(outputPath, 'Response.ts'), templates.core.response(context));
|
||||
await writeFile(path.resolve(outputPath, 'ResponseError.ts'), templates.core.responseError(context));
|
||||
}
|
||||
|
||||
@ -23,18 +23,10 @@ describe('writeClientIndex', () => {
|
||||
},
|
||||
core: {
|
||||
settings: () => 'settings',
|
||||
getFormData: () => 'getFormData',
|
||||
getQueryString: () => 'getQueryString',
|
||||
getUrl: () => 'getUrl',
|
||||
isSuccess: () => 'isSuccess',
|
||||
catchGenericError: () => 'catchGenericError',
|
||||
apiError: () => 'apiError',
|
||||
apiRequestOptions: () => 'apiRequestOptions',
|
||||
apiResult: () => 'apiResult',
|
||||
request: () => 'request',
|
||||
requestOptions: () => 'requestOptions',
|
||||
requestUsingFetch: () => 'requestUsingFetch',
|
||||
requestUsingXHR: () => 'requestUsingXHR',
|
||||
requestUsingNode: () => 'requestUsingNode',
|
||||
response: () => 'response',
|
||||
responseError: () => 'responseError',
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@ -37,18 +37,10 @@ describe('writeClientModels', () => {
|
||||
},
|
||||
core: {
|
||||
settings: () => 'settings',
|
||||
getFormData: () => 'getFormData',
|
||||
getQueryString: () => 'getQueryString',
|
||||
getUrl: () => 'getUrl',
|
||||
isSuccess: () => 'isSuccess',
|
||||
catchGenericError: () => 'catchGenericError',
|
||||
apiError: () => 'apiError',
|
||||
apiRequestOptions: () => 'apiRequestOptions',
|
||||
apiResult: () => 'apiResult',
|
||||
request: () => 'request',
|
||||
requestOptions: () => 'requestOptions',
|
||||
requestUsingFetch: () => 'requestUsingFetch',
|
||||
requestUsingXHR: () => 'requestUsingXHR',
|
||||
requestUsingNode: () => 'requestUsingNode',
|
||||
response: () => 'response',
|
||||
responseError: () => 'responseError',
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@ -37,18 +37,10 @@ describe('writeClientSchemas', () => {
|
||||
},
|
||||
core: {
|
||||
settings: () => 'settings',
|
||||
getFormData: () => 'getFormData',
|
||||
getQueryString: () => 'getQueryString',
|
||||
getUrl: () => 'getUrl',
|
||||
isSuccess: () => 'isSuccess',
|
||||
catchGenericError: () => 'catchGenericError',
|
||||
apiError: () => 'apiError',
|
||||
apiRequestOptions: () => 'apiRequestOptions',
|
||||
apiResult: () => 'apiResult',
|
||||
request: () => 'request',
|
||||
requestOptions: () => 'requestOptions',
|
||||
requestUsingFetch: () => 'requestUsingFetch',
|
||||
requestUsingXHR: () => 'requestUsingXHR',
|
||||
requestUsingNode: () => 'requestUsingNode',
|
||||
response: () => 'response',
|
||||
responseError: () => 'responseError',
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@ -24,18 +24,10 @@ describe('writeClientServices', () => {
|
||||
},
|
||||
core: {
|
||||
settings: () => 'settings',
|
||||
getFormData: () => 'getFormData',
|
||||
getQueryString: () => 'getQueryString',
|
||||
getUrl: () => 'getUrl',
|
||||
isSuccess: () => 'isSuccess',
|
||||
catchGenericError: () => 'catchGenericError',
|
||||
apiError: () => 'apiError',
|
||||
apiRequestOptions: () => 'apiRequestOptions',
|
||||
apiResult: () => 'apiResult',
|
||||
request: () => 'request',
|
||||
requestOptions: () => 'requestOptions',
|
||||
requestUsingFetch: () => 'requestUsingFetch',
|
||||
requestUsingXHR: () => 'requestUsingXHR',
|
||||
requestUsingNode: () => 'requestUsingNode',
|
||||
response: () => 'response',
|
||||
responseError: () => 'responseError',
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -31,6 +31,6 @@ describe('v2.fetch', () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
expect(result.url).toBeDefined();
|
||||
expect(result).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user