- Testing new templates

This commit is contained in:
Ferdi Koomen 2020-09-26 11:38:57 +02:00
parent d83377719a
commit 8b15c1eed0
70 changed files with 485 additions and 459 deletions

View File

@ -15,11 +15,11 @@ 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.node.spec.js',
'<rootDir>/test/e2e/v3.fetch.spec.js',
'<rootDir>/test/e2e/v3.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',
],
},

View File

@ -63,11 +63,14 @@
"aap": "node test/e2e/index.js"
},
"dependencies": {
"@types/node-fetch": "2.5.7",
"camelcase": "6.0.0",
"commander": "6.1.0",
"form-data": "3.0.0",
"handlebars": "4.7.6",
"js-yaml": "3.14.0",
"mkdirp": "1.0.4",
"node-fetch": "2.6.1",
"path": "0.12.7",
"rimraf": "3.0.2"
},

View File

@ -26,7 +26,7 @@ export function getOperation(openApi: OpenApi, url: string, method: string, op:
summary: getComment(op.summary),
description: getComment(op.description),
deprecated: op.deprecated === true,
method: method,
method: method.toUpperCase(),
path: operationPath,
parameters: [...pathParams.parameters],
parametersPath: [...pathParams.parametersPath],

View File

@ -30,7 +30,7 @@ export function getOperation(openApi: OpenApi, url: string, method: string, op:
summary: getComment(op.summary),
description: getComment(op.description),
deprecated: op.deprecated === true,
method: method,
method: method.toUpperCase(),
path: operationPath,
parameters: [...pathParams.parameters],
parametersPath: [...pathParams.parametersPath],

View File

@ -1,43 +1,19 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
{{>header}}
import { isSuccess } from './isSuccess';
import { Result } from './Result';
import { ApiResponse } from './ApiResponse';
export class ApiError extends Error {
public readonly url: string;
public readonly status: number;
public readonly statusText: string;
public readonly body: any;
constructor(result: Readonly<Result>, message: string) {
constructor(response: ApiResponse, message: string) {
super(message);
this.url = result.url;
this.status = result.status;
this.statusText = result.statusText;
this.body = result.body;
}
}
/**
* Catch common errors (based on status code).
* @param result
*/
export function catchGenericError(result: Result): void {
switch (result.status) {
case 400: throw new ApiError(result, 'Bad Request');
case 401: throw new ApiError(result, 'Unauthorized');
case 403: throw new ApiError(result, 'Forbidden');
case 404: throw new ApiError(result, 'Not Found');
case 500: throw new ApiError(result, 'Internal Server Error');
case 502: throw new ApiError(result, 'Bad Gateway');
case 503: throw new ApiError(result, 'Service Unavailable');
}
if (!isSuccess(result.status)) {
throw new ApiError(result, 'Generic Error');
this.url = response.url;
this.status = response.status;
this.statusText = response.statusText;
this.body = response.body;
}
}

View File

@ -0,0 +1,13 @@
{{>header}}
export interface RequestOptions {
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>;
}

View File

@ -0,0 +1,9 @@
{{>header}}
export interface Response {
readonly url: string;
readonly ok: boolean;
readonly status: number;
readonly statusText: string;
readonly body: any;
}

View File

@ -1,6 +1,4 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
{{>header}}
interface Config {
BASE: string;

View File

@ -1,14 +0,0 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export interface RequestOptions {
method: 'get' | 'put' | 'post' | 'delete' | 'options' | 'head' | 'patch';
path: string;
cookies?: { [key: string]: any };
headers?: { [key: string]: any };
query?: { [key: string]: any };
formData?: { [key: string]: any };
body?: any;
responseHeader?: string;
}

View File

@ -1,11 +0,0 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export interface Result {
url: string;
ok: boolean;
status: number;
statusText: string;
body: any;
}

View File

@ -0,0 +1,21 @@
function catchErrors(options: ApiRequestOptions, response: ApiResponse): void {
const errors = {
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[response.status];
if (error) {
throw new ApiError(response, error);
}
if (!result.ok) {
throw new ApiError(response, 'Generic Error');
}
}

View File

@ -0,0 +1,12 @@
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;
}

View File

@ -0,0 +1,24 @@
function getHeaders(options: ApiRequestOptions): Headers {
const headers = new Headers({
...options.headers,
Accept: 'application/json',
});
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;
}

View File

@ -0,0 +1,22 @@
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 '';
}

View File

@ -0,0 +1,10 @@
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;
}

View File

@ -0,0 +1,3 @@
function isDefined<T>(value: T | null | undefined): value is Exclude<T, null | undefined> {
return value !== undefined && value !== null;
}

View File

@ -0,0 +1,3 @@
function isSuccess(status: number): boolean {
return status >= 200 && status < 300;
}

View File

@ -1,21 +0,0 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
/**
* Get FormData from object. This method is needed to upload
* multipart form data to the REST API.
* @param params Key value based object.
*/
export function getFormData(params: { [key: string]: any }): FormData {
const formData = new FormData();
for (const key in params) {
if (typeof params[key] !== 'undefined') {
const value: any = params[key];
if (value !== undefined && value !== null) {
formData.append(key, value);
}
}
}
return formData;
}

View File

@ -1,30 +0,0 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
/**
* Get query string from query parameters object. This method also
* supports multi-value items by creating a key for each item.
* @param params Key value based object.
*/
export function getQueryString(params: { [key: string]: any }): string {
const qs: string[] = [];
for (const key in params) {
if (typeof params[key] !== 'undefined') {
const value: any = params[key];
if (value !== undefined && value !== null) {
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 '';
}

View File

@ -1,11 +0,0 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
/**
* Check success response code.
* @param status Status code
*/
export function isSuccess(status: number): boolean {
return status >= 200 && status < 300;
}

View File

@ -1,92 +1,2 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import { getFormData } from './getFormData';
import { getQueryString } from './getQueryString';
import { OpenAPI } from './OpenAPI';
import { RequestOptions } from './RequestOptions';
import { requestUsingFetch } from './requestUsingFetch';
import { requestUsingXHR } from './requestUsingXHR';
import { Result } from './Result';
/**
* Create the request.
* @param options Request method options.
* @returns Result object (see above)
*/
export async function request(options: Readonly<RequestOptions>): Promise<Result> {
// Escape path (RFC3986) and create the request URL
let path = options.path.replace(/[:]/g, '_');
let url = `${OpenAPI.BASE}${path}`;
// Create request headers
const headers = new Headers({
...options.headers,
Accept: 'application/json',
});
// Create request settings
const request: RequestInit = {
headers,
method: options.method,
};
// If we specified to send requests with credentials, then we
// set the request credentials options to include. This is only
// needed if you make cross-origin calls.
if (OpenAPI.WITH_CREDENTIALS) {
request.credentials = 'include';
}
// If we have a bearer token then we set the authentication header.
if (OpenAPI.TOKEN !== null && OpenAPI.TOKEN !== '') {
headers.append('Authorization', `Bearer ${OpenAPI.TOKEN}`);
}
// Add the query parameters (if defined).
if (options.query) {
url += getQueryString(options.query);
}
// Append formData as body, this needs to be parsed to key=value pairs
// so the backend can parse this just like a regular HTML form.
if (options.formData) {
request.body = getFormData(options.formData);
headers.append('Content-Type', 'application/x-www-form-urlencoded');
} 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) {
request.body = options.body;
if (options.body.type) {
headers.append('Content-Type', options.body.type);
}
} else if (typeof options.body === 'string') {
request.body = options.body;
headers.append('Content-Type', 'text/plain');
} else {
request.body = JSON.stringify(options.body);
headers.append('Content-Type', 'application/json');
}
}
try {
switch (OpenAPI.CLIENT) {
case 'xhr':
return await requestUsingXHR(url, request, options.responseHeader);
default:
return await requestUsingFetch(url, request, options.responseHeader);
}
} catch (error) {
return {
url,
ok: false,
status: 0,
statusText: '',
body: error,
};
}
}
{{>header}}
{{>requestUsingFetch}}

View File

@ -1,72 +0,0 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import { Result } from './Result';
/**
* Try to parse the content for any response status code.
* We check the "Content-Type" header to see if we need to parse the
* content as json or as plain text.
* @param response Response object from fetch
*/
async function parseBody(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;
}
/**
* Fetch the response header (if specified)
* @param response Response object from fetch
* @param responseHeader The name of the header to fetch
*/
function parseHeader(response: Response, responseHeader?: string): string | null {
if (responseHeader) {
const content = response.headers.get(responseHeader);
if (typeof content === 'string') {
return content;
}
}
return null;
}
/**
* Request content using the new Fetch API. This is the default API that is used and
* is create for all JSON, XML and text objects. However it is limited to UTF-8.
* This is a problem for some of the Docs content, since that requires UTF-16!
* @param url The url to request.
* @param request The request object, containing method, headers, body, etc.
* @param responseHeader The header we want to parse.
*/
export async function requestUsingFetch(url: string, request: Readonly<RequestInit>, responseHeader?: string): Promise<Result> {
// Fetch response using fetch API.
const response = await fetch(url, request);
// Get content of response header or response body
const contentHeader = parseHeader(response, responseHeader);
const contentBody = await parseBody(response);
// Create result object.
return {
url,
ok: response.ok,
status: response.status,
statusText: response.statusText,
body: contentHeader || contentBody,
};
}

View File

@ -0,0 +1,26 @@
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;
}

View File

@ -0,0 +1,17 @@
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;
}

View File

@ -0,0 +1,19 @@
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;
}

View File

@ -0,0 +1,10 @@
function getResponseHeader(response: Response, responseHeader?: string): string | null {
if (responseHeader) {
const content = response.headers.get(responseHeader);
if (typeof content === 'string') {
return content;
}
}
return null;
}

View File

@ -0,0 +1,55 @@
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;
}

View File

@ -1,101 +0,0 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import { isSuccess } from './isSuccess';
import { Result } from './Result';
/**
* Try to parse the content for any response status code.
* We check the "Content-Type" header to see if we need to parse the
* content as json or as plain text.
* @param xhr XHR request object
*/
function parseBody(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;
}
/**
* Fetch the response header (if specified)
* @param xhr XHR request object
* @param responseHeader The name of the header to fetch
*/
function parseHeader(xhr: XMLHttpRequest, responseHeader?: string): string | null {
if (responseHeader) {
const content = xhr.getResponseHeader(responseHeader);
if (typeof content === 'string') {
return content;
}
}
return null;
}
/**
* Request content using the new legacy XMLHttpRequest API. This method is useful
* when we want to request UTF-16 content, since it natively supports loading UTF-16.
* We could do the same with the Fetch API, but then we will need to convert the
* content using JavaScript... And that is very very slow.
* @param url The url to request.
* @param request The request object, containing method, headers, body, etc.
* @param responseHeader The header we want to parse.
*/
export async function requestUsingXHR(url: string, request: Readonly<RequestInit>, responseHeader?: string): Promise<Result> {
return new Promise(resolve => {
const xhr = new XMLHttpRequest();
// Open the request, remember to do this before adding any headers,
// because the request needs to be initialized!
xhr.open(request.method!, url, true);
// When request credentials are set to include then this is
// the same behaviour as withCredentials = true in XHR:
// https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials
xhr.withCredentials = request.credentials === 'include';
// Add the headers (required when dealing with JSON)
const headers = request.headers as Headers;
headers.forEach((value: string, key: string): void => {
xhr.setRequestHeader(key, value);
});
// Register the readystate handler, this will fire when the request is done.
xhr.onreadystatechange = () => {
if (xhr.readyState === XMLHttpRequest.DONE) {
// Get content of response header or response body
const contentHeader = parseHeader(xhr, responseHeader);
const contentBody = parseBody(xhr);
// Create result object.
const result: Result = {
url,
ok: isSuccess(xhr.status),
status: xhr.status,
statusText: xhr.statusText,
body: contentHeader || contentBody,
};
// Done!
resolve(result);
}
};
// Start the request!
xhr.send(request.body);
});
}

View File

@ -0,0 +1,25 @@
function getRequest(options: ApiRequestOptions, url: string, listener: (xhr: XMLHttpRequest) => ApiResponse): Promise<ApiResponse> {
return new Promise<ApiResponse>((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) {
const response = listener(xhr);
resolve(response);
}
};
xhr.send(getRequestBody());
} catch (error) {
reject(error);
}
);
}

View File

@ -0,0 +1,17 @@
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;
}

View File

@ -0,0 +1,19 @@
function getResponseBody(xhr: XMLHttpRequest): Promise<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;
}

View File

@ -0,0 +1,10 @@
function getResponseHeader(xhr: XMLHttpRequest, responseHeader?: string): string | null {
if (responseHeader) {
const content = xhr.getResponseHeader(responseHeader);
if (typeof content === 'string') {
return content;
}
}
return null;
}

View File

@ -0,0 +1,52 @@
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;
});
}

View File

@ -1,8 +1,6 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
{{>header}}
{{#if imports}}
{{#each imports}}
import { {{{this}}} } from './{{{this}}}';
{{/each}}

View File

@ -1,6 +1,4 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
{{>header}}
{{#if extends}}
{{#each extends}}

View File

@ -1,19 +1,12 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
{{>header}}
{{#if imports}}
{{#each imports}}
import { {{{this}}} } from '../models/{{{this}}}';
{{/each}}
{{/if}}
{{#if hasApiErrors}}
import { ApiError, catchGenericError } from '../core/ApiError';
{{else}}
import { catchGenericError } from '../core/ApiError';
{{/if}}
import { request as __request } from '../core/request';
{{#if hasApiVersion}}
{{#if useVersion}}
import { OpenAPI } from '../core/OpenAPI';
{{/if}}
@ -42,7 +35,7 @@ export class {{{name}}} {
*/
public static async {{{name}}}({{>parameters}}): Promise<{{>result}}> {
const result = await __request({
const response = await __request({
method: '{{{method}}}',
path: `{{{path}}}`,
{{#if parametersCookie~}}
@ -79,21 +72,16 @@ export class {{{name}}} {
{{#if responseHeader~}}
responseHeader: '{{{responseHeader}}}',
{{/if}}
});
{{#if errors}}
if (!result.ok) {
switch (result.status) {
{{#if errors~}}
errors: {
{{#each errors}}
case {{{code}}}: throw new ApiError(result, `{{{description}}}`);
{{{code}}}: `{{{description}}}`,
{{/each}}
}
}
{{/if}}
},
{{/if}}
});
catchGenericError(result);
return result.body;
return response.body;
}
{{/each}}

View File

@ -1,10 +1,7 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
{{>header}}
{{#if exportCore}}
export { ApiError } from './core/ApiError';
export { isSuccess } from './core/isSuccess';
export { OpenAPI } from './core/OpenAPI';
{{/if}}
{{#if exportModels}}

View File

@ -0,0 +1,3 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */

View File

@ -1,15 +1,18 @@
import * as Handlebars from 'handlebars/runtime';
import templateCoreApiError from '../templates/core/ApiError.hbs';
import templateCoreGetFormData from '../templates/core/getFormData.hbs';
import templateCoreGetQueryString from '../templates/core/getQueryString.hbs';
import templateCoreIsSuccess from '../templates/core/isSuccess.hbs';
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 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/requestUsingFetch.hbs';
import templateCoreRequestUsingXHR from '../templates/core/requestUsingXHR.hbs';
import templateCoreResult from '../templates/core/Result.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 templateExportModel from '../templates/exportModel.hbs';
import templateExportSchema from '../templates/exportSchema.hbs';
import templateExportService from '../templates/exportService.hbs';
@ -47,15 +50,18 @@ export interface Templates {
};
core: {
settings: Handlebars.TemplateDelegate;
apiError: Handlebars.TemplateDelegate;
getFormData: Handlebars.TemplateDelegate;
getQueryString: Handlebars.TemplateDelegate;
getUrl: Handlebars.TemplateDelegate;
isSuccess: Handlebars.TemplateDelegate;
catchGenericError: Handlebars.TemplateDelegate;
request: Handlebars.TemplateDelegate;
requestOptions: Handlebars.TemplateDelegate;
requestUsingFetch: Handlebars.TemplateDelegate;
requestUsingXHR: Handlebars.TemplateDelegate;
result: Handlebars.TemplateDelegate;
requestUsingNode: Handlebars.TemplateDelegate;
response: Handlebars.TemplateDelegate;
responseError: Handlebars.TemplateDelegate;
};
}
@ -75,15 +81,18 @@ export function registerHandlebarTemplates(): Templates {
},
core: {
settings: Handlebars.template(templateCoreSettings),
apiError: Handlebars.template(templateCoreApiError),
getFormData: Handlebars.template(templateCoreGetFormData),
getQueryString: Handlebars.template(templateCoreGetQueryString),
getUrl: Handlebars.template(templateCoreGetUrl),
isSuccess: Handlebars.template(templateCoreIsSuccess),
catchGenericError: Handlebars.template(templateCoreCatchGenericError),
request: Handlebars.template(templateCoreRequest),
requestOptions: Handlebars.template(templateCoreRequestOptions),
requestUsingFetch: Handlebars.template(templateCoreRequestUsingFetch),
requestUsingXHR: Handlebars.template(templateCoreRequestUsingXHR),
result: Handlebars.template(templateCoreResult),
requestUsingNode: Handlebars.template(templateCoreRequestUsingNode),
response: Handlebars.template(templateCoreResponse),
responseError: Handlebars.template(templateCoreResponseError),
},
};

View File

@ -24,15 +24,18 @@ describe('writeClient', () => {
},
core: {
settings: () => 'settings',
apiError: () => 'apiError',
getFormData: () => 'getFormData',
getQueryString: () => 'getQueryString',
getUrl: () => 'getUrl',
isSuccess: () => 'isSuccess',
catchGenericError: () => 'catchGenericError',
request: () => 'request',
requestOptions: () => 'requestOptions',
requestUsingFetch: () => 'requestUsingFetch',
requestUsingXHR: () => 'requestUsingXHR',
result: () => 'result',
requestUsingNode: () => 'requestUsingNode',
response: () => 'response',
responseError: () => 'responseError',
},
};

View File

@ -24,29 +24,35 @@ describe('writeClientCore', () => {
},
core: {
settings: () => 'settings',
apiError: () => 'apiError',
getFormData: () => 'getFormData',
getQueryString: () => 'getQueryString',
getUrl: () => 'getUrl',
isSuccess: () => 'isSuccess',
catchGenericError: () => 'catchGenericError',
request: () => 'request',
requestOptions: () => 'requestOptions',
requestUsingFetch: () => 'requestUsingFetch',
requestUsingXHR: () => 'requestUsingXHR',
result: () => 'result',
requestUsingNode: () => 'requestUsingNode',
response: () => 'response',
responseError: () => 'responseError',
},
};
await writeClientCore(client, templates, '/', HttpClient.FETCH);
expect(writeFile).toBeCalledWith('/OpenAPI.ts', 'settings');
expect(writeFile).toBeCalledWith('/ApiError.ts', 'apiError');
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('/request.ts', 'request');
expect(writeFile).toBeCalledWith('/RequestOptions.ts', 'requestOptions');
expect(writeFile).toBeCalledWith('/requestUsingFetch.ts', 'requestUsingFetch');
expect(writeFile).toBeCalledWith('/requestUsingXHR.ts', 'requestUsingXHR');
expect(writeFile).toBeCalledWith('/Result.ts', 'result');
expect(writeFile).toBeCalledWith('/requestUsingNode.ts', 'requestUsingNode');
expect(writeFile).toBeCalledWith('/Response.ts', 'response');
expect(writeFile).toBeCalledWith('/ResponseError.ts', 'responseError');
});
});

View File

@ -19,13 +19,16 @@ 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, 'ApiError.ts'), templates.core.apiError(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, '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, 'Result.ts'), templates.core.result(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));
}

View File

@ -23,15 +23,18 @@ describe('writeClientIndex', () => {
},
core: {
settings: () => 'settings',
apiError: () => 'apiError',
getFormData: () => 'getFormData',
getQueryString: () => 'getQueryString',
getUrl: () => 'getUrl',
isSuccess: () => 'isSuccess',
catchGenericError: () => 'catchGenericError',
request: () => 'request',
requestOptions: () => 'requestOptions',
requestUsingFetch: () => 'requestUsingFetch',
requestUsingXHR: () => 'requestUsingXHR',
result: () => 'result',
requestUsingNode: () => 'requestUsingNode',
response: () => 'response',
responseError: () => 'responseError',
},
};

View File

@ -37,15 +37,18 @@ describe('writeClientModels', () => {
},
core: {
settings: () => 'settings',
apiError: () => 'apiError',
getFormData: () => 'getFormData',
getQueryString: () => 'getQueryString',
getUrl: () => 'getUrl',
isSuccess: () => 'isSuccess',
catchGenericError: () => 'catchGenericError',
request: () => 'request',
requestOptions: () => 'requestOptions',
requestUsingFetch: () => 'requestUsingFetch',
requestUsingXHR: () => 'requestUsingXHR',
result: () => 'result',
requestUsingNode: () => 'requestUsingNode',
response: () => 'response',
responseError: () => 'responseError',
},
};

View File

@ -37,15 +37,18 @@ describe('writeClientSchemas', () => {
},
core: {
settings: () => 'settings',
apiError: () => 'apiError',
getFormData: () => 'getFormData',
getQueryString: () => 'getQueryString',
getUrl: () => 'getUrl',
isSuccess: () => 'isSuccess',
catchGenericError: () => 'catchGenericError',
request: () => 'request',
requestOptions: () => 'requestOptions',
requestUsingFetch: () => 'requestUsingFetch',
requestUsingXHR: () => 'requestUsingXHR',
result: () => 'result',
requestUsingNode: () => 'requestUsingNode',
response: () => 'response',
responseError: () => 'responseError',
},
};

View File

@ -24,15 +24,18 @@ describe('writeClientServices', () => {
},
core: {
settings: () => 'settings',
apiError: () => 'apiError',
getFormData: () => 'getFormData',
getQueryString: () => 'getQueryString',
getUrl: () => 'getUrl',
isSuccess: () => 'isSuccess',
catchGenericError: () => 'catchGenericError',
request: () => 'request',
requestOptions: () => 'requestOptions',
requestUsingFetch: () => 'requestUsingFetch',
requestUsingXHR: () => 'requestUsingXHR',
result: () => 'result',
requestUsingNode: () => 'requestUsingNode',
response: () => 'response',
responseError: () => 'responseError',
},
};

View File

@ -17,12 +17,10 @@ const VERSION_TEMPLATE_STRING = 'OpenAPI.VERSION';
export async function writeClientServices(services: Service[], templates: Templates, outputPath: string, useOptions: boolean): Promise<void> {
for (const service of services) {
const file = path.resolve(outputPath, `${service.name}.ts`);
const hasApiErrors = service.operations.some(operation => operation.errors.length);
const hasApiVersion = service.operations.some(operation => operation.path.includes(VERSION_TEMPLATE_STRING));
const useVersion = service.operations.some(operation => operation.path.includes(VERSION_TEMPLATE_STRING));
const templateResult = templates.exports.service({
...service,
hasApiErrors,
hasApiVersion,
useVersion,
useOptions,
});
await writeFile(file, format(templateResult));

View File

@ -1325,6 +1325,14 @@
dependencies:
"@types/node" "*"
"@types/node-fetch@2.5.7":
version "2.5.7"
resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.7.tgz#20a2afffa882ab04d44ca786449a276f9f6bbf3c"
integrity sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw==
dependencies:
"@types/node" "*"
form-data "^3.0.0"
"@types/node@*", "@types/node@14.11.2":
version "14.11.2"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.11.2.tgz#2de1ed6670439387da1c9f549a2ade2b0a799256"
@ -2024,7 +2032,7 @@ color-name@~1.1.4:
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
combined-stream@^1.0.6, combined-stream@~1.0.6:
combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6:
version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
@ -2845,6 +2853,15 @@ forever-agent@~0.6.1:
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
form-data@3.0.0, form-data@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.0.tgz#31b7e39c85f1355b7139ee0c647cf0de7f83c682"
integrity sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.8"
mime-types "^2.1.12"
form-data@~2.3.2:
version "2.3.3"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
@ -4288,7 +4305,7 @@ nice-try@^1.0.4:
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
node-fetch@^2.2.0:
node-fetch@2.6.1, node-fetch@^2.2.0:
version "2.6.1"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==