mirror of
https://github.com/ferdikoomen/openapi-typescript-codegen.git
synced 2025-12-08 20:16:21 +00:00
- Fixed Angular client
This commit is contained in:
parent
dc5e69abca
commit
8e05e64a72
@ -33,7 +33,7 @@ const config: Config.InitialOptions = {
|
||||
'<rootDir>/test/e2e/client.axios.spec.ts',
|
||||
'<rootDir>/test/e2e/client.babel.spec.ts',
|
||||
],
|
||||
modulePathIgnorePatterns: ['<rootDir>/test/e2e/generated'],
|
||||
modulePathIgnorePatterns: ['<rootDir>/test/e2e/generated'],
|
||||
},
|
||||
],
|
||||
collectCoverageFrom: ['<rootDir>/src/**/*.ts', '!<rootDir>/src/**/*.d.ts', '!<rootDir>/bin', '!<rootDir>/dist'],
|
||||
|
||||
@ -51,7 +51,7 @@
|
||||
"test:update": "jest --selectProjects UNIT --updateSnapshot",
|
||||
"test:watch": "jest --selectProjects UNIT --watch",
|
||||
"test:coverage": "jest --selectProjects UNIT --coverage",
|
||||
"test:e2e": "jest --selectProjects E2E --runInBand",
|
||||
"test:e2e": "jest --selectProjects E2E --runInBand --verbose",
|
||||
"eslint": "eslint .",
|
||||
"eslint:fix": "eslint . --fix",
|
||||
"prepublishOnly": "yarn run clean && yarn run release",
|
||||
|
||||
@ -1,40 +1,45 @@
|
||||
const getHeaders = async (config: OpenAPIConfig, options: ApiRequestOptions): Promise<HttpHeaders> => {
|
||||
const token = await resolve(options, config.TOKEN);
|
||||
const username = await resolve(options, config.USERNAME);
|
||||
const password = await resolve(options, config.PASSWORD);
|
||||
const additionalHeaders = await resolve(options, config.HEADERS);
|
||||
|
||||
const headers = Object.entries({
|
||||
Accept: 'application/json',
|
||||
...additionalHeaders,
|
||||
...options.headers,
|
||||
const getHeaders = (config: OpenAPIConfig, options: ApiRequestOptions): Observable<HttpHeaders> => {
|
||||
return forkJoin({
|
||||
token: resolve(options, config.TOKEN),
|
||||
username: resolve(options, config.USERNAME),
|
||||
password: resolve(options, config.PASSWORD),
|
||||
additionalHeaders: resolve(options, config.HEADERS),
|
||||
})
|
||||
.filter(([_, value]) => isDefined(value))
|
||||
.reduce((headers, [key, value]) => ({
|
||||
...headers,
|
||||
[key]: String(value),
|
||||
}), {} as Record<string, string>);
|
||||
.pipe(
|
||||
map(({ token, username, password, additionalHeaders }) => {
|
||||
const headers = Object.entries({
|
||||
Accept: 'application/json',
|
||||
...additionalHeaders,
|
||||
...options.headers,
|
||||
})
|
||||
.filter(([_, value]) => isDefined(value))
|
||||
.reduce((headers, [key, value]) => ({
|
||||
...headers,
|
||||
[key]: String(value),
|
||||
}), {} as Record<string, string>);
|
||||
|
||||
if (isStringWithValue(token)) {
|
||||
headers['Authorization'] = `Bearer ${token}`;
|
||||
}
|
||||
if (isStringWithValue(token)) {
|
||||
headers['Authorization'] = `Bearer ${token}`;
|
||||
}
|
||||
|
||||
if (isStringWithValue(username) && isStringWithValue(password)) {
|
||||
const credentials = base64(`${username}:${password}`);
|
||||
headers['Authorization'] = `Basic ${credentials}`;
|
||||
}
|
||||
if (isStringWithValue(username) && isStringWithValue(password)) {
|
||||
const credentials = base64(`${username}:${password}`);
|
||||
headers['Authorization'] = `Basic ${credentials}`;
|
||||
}
|
||||
|
||||
if (options.body) {
|
||||
if (options.mediaType) {
|
||||
headers['Content-Type'] = options.mediaType;
|
||||
} else if (isBlob(options.body)) {
|
||||
headers['Content-Type'] = options.body.type || 'application/octet-stream';
|
||||
} else if (isString(options.body)) {
|
||||
headers['Content-Type'] = 'text/plain';
|
||||
} else if (!isFormData(options.body)) {
|
||||
headers['Content-Type'] = 'application/json';
|
||||
}
|
||||
}
|
||||
if (options.body) {
|
||||
if (options.mediaType) {
|
||||
headers['Content-Type'] = options.mediaType;
|
||||
} else if (isBlob(options.body)) {
|
||||
headers['Content-Type'] = options.body.type || 'application/octet-stream';
|
||||
} else if (isString(options.body)) {
|
||||
headers['Content-Type'] = 'text/plain';
|
||||
} else if (!isFormData(options.body)) {
|
||||
headers['Content-Type'] = 'application/json';
|
||||
}
|
||||
}
|
||||
|
||||
return new HttpHeaders(headers);
|
||||
return new HttpHeaders(headers);
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
{{>header}}
|
||||
|
||||
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
||||
import type { HttpResponse } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import type { HttpResponse, HttpErrorResponse } from '@angular/common/http';
|
||||
import { catchError, forkJoin, map, mergeMap, of, throwError } from 'rxjs';
|
||||
import type { Observable } from 'rxjs';
|
||||
|
||||
import { ApiError } from './ApiError';
|
||||
import type { ApiRequestOptions } from './ApiRequestOptions';
|
||||
@ -54,7 +55,7 @@ import type { OpenAPIConfig } from './OpenAPI';
|
||||
{{>angular/getResponseBody}}
|
||||
|
||||
|
||||
{{>functions/catchErrors}}
|
||||
{{>functions/catchErrorCodes}}
|
||||
|
||||
|
||||
/**
|
||||
@ -62,38 +63,47 @@ import type { OpenAPIConfig } from './OpenAPI';
|
||||
* @param config The OpenAPI configuration object
|
||||
* @param http The Angular HTTP client
|
||||
* @param options The request options from the service
|
||||
* @returns CancelablePromise<T>
|
||||
* @returns Observable<T>
|
||||
* @throws ApiError
|
||||
*/
|
||||
export const request = <T>(config: OpenAPIConfig, http: HttpClient, options: ApiRequestOptions): Observable<T> => {
|
||||
return new Observable<T>(subscriber => {
|
||||
try {
|
||||
const url = getUrl(config, options);
|
||||
const formData = getFormData(options);
|
||||
const body = getRequestBody(options);
|
||||
getHeaders(config, options).then(headers => {
|
||||
const url = getUrl(config, options);
|
||||
const formData = getFormData(options);
|
||||
const body = getRequestBody(options);
|
||||
|
||||
sendRequest<T>(config, options, http, url, formData, body, headers)
|
||||
.subscribe(response => {
|
||||
const responseBody = 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);
|
||||
|
||||
subscriber.next(result.body);
|
||||
});
|
||||
});
|
||||
} catch (error) {
|
||||
subscriber.error(error);
|
||||
}
|
||||
});
|
||||
return getHeaders(config, options).pipe(
|
||||
mergeMap( headers => {
|
||||
return sendRequest<T>(config, options, http, url, formData, body, headers);
|
||||
}),
|
||||
map(response => {
|
||||
const responseBody = getResponseBody(response);
|
||||
const responseHeader = getResponseHeader(response, options.responseHeader);
|
||||
return {
|
||||
url,
|
||||
ok: response.ok,
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
body: responseHeader ?? responseBody,
|
||||
} as ApiResult;
|
||||
}),
|
||||
catchError((error: HttpErrorResponse) => {
|
||||
if (!error.status) {
|
||||
return throwError(() => error);
|
||||
}
|
||||
return of({
|
||||
url,
|
||||
ok: error.ok,
|
||||
status: error.status,
|
||||
statusText: error.statusText,
|
||||
body: error.statusText,
|
||||
} as ApiResult);
|
||||
}),
|
||||
map(result => {
|
||||
catchErrorCodes(options, result);
|
||||
return result.body as T;
|
||||
}),
|
||||
catchError((error: ApiError) => {
|
||||
return throwError(() => error);
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -55,7 +55,7 @@ import type { OpenAPIConfig } from './OpenAPI';
|
||||
{{>axios/getResponseBody}}
|
||||
|
||||
|
||||
{{>functions/catchErrors}}
|
||||
{{>functions/catchErrorCodes}}
|
||||
|
||||
|
||||
/**
|
||||
@ -86,7 +86,7 @@ export const request = <T>(config: OpenAPIConfig, options: ApiRequestOptions): C
|
||||
body: responseHeader ?? responseBody,
|
||||
};
|
||||
|
||||
catchErrors(options, result);
|
||||
catchErrorCodes(options, result);
|
||||
|
||||
resolve(result.body);
|
||||
}
|
||||
|
||||
@ -52,7 +52,7 @@ import type { OpenAPIConfig } from './OpenAPI';
|
||||
{{>fetch/getResponseBody}}
|
||||
|
||||
|
||||
{{>functions/catchErrors}}
|
||||
{{>functions/catchErrorCodes}}
|
||||
|
||||
|
||||
/**
|
||||
@ -83,7 +83,7 @@ export const request = <T>(config: OpenAPIConfig, options: ApiRequestOptions): C
|
||||
body: responseHeader ?? responseBody,
|
||||
};
|
||||
|
||||
catchErrors(options, result);
|
||||
catchErrorCodes(options, result);
|
||||
|
||||
resolve(result.body);
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
const catchErrors = (options: ApiRequestOptions, result: ApiResult): void => {
|
||||
const catchErrorCodes = (options: ApiRequestOptions, result: ApiResult): void => {
|
||||
const errors: Record<number, string> = {
|
||||
400: 'Bad Request',
|
||||
401: 'Unauthorized',
|
||||
@ -56,7 +56,7 @@ import type { OpenAPIConfig } from './OpenAPI';
|
||||
{{>node/getResponseBody}}
|
||||
|
||||
|
||||
{{>functions/catchErrors}}
|
||||
{{>functions/catchErrorCodes}}
|
||||
|
||||
|
||||
/**
|
||||
@ -87,7 +87,7 @@ export const request = <T>(config: OpenAPIConfig, options: ApiRequestOptions): C
|
||||
body: responseHeader ?? responseBody,
|
||||
};
|
||||
|
||||
catchErrors(options, result);
|
||||
catchErrorCodes(options, result);
|
||||
|
||||
resolve(result.body);
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ import type { OpenAPIConfig } from './OpenAPI';
|
||||
{{>xhr/getResponseBody}}
|
||||
|
||||
|
||||
{{>functions/catchErrors}}
|
||||
{{>functions/catchErrorCodes}}
|
||||
|
||||
|
||||
/**
|
||||
@ -86,7 +86,7 @@ export const request = <T>(config: OpenAPIConfig, options: ApiRequestOptions): C
|
||||
body: responseHeader ?? responseBody,
|
||||
};
|
||||
|
||||
catchErrors(options, result);
|
||||
catchErrorCodes(options, result);
|
||||
|
||||
resolve(result.body);
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@ import fetchGetResponseHeader from '../templates/core/fetch/getResponseHeader.hb
|
||||
import fetchRequest from '../templates/core/fetch/request.hbs';
|
||||
import fetchSendRequest from '../templates/core/fetch/sendRequest.hbs';
|
||||
import functionBase64 from '../templates/core/functions/base64.hbs';
|
||||
import functionCatchErrors from '../templates/core/functions/catchErrors.hbs';
|
||||
import functionCatchErrorCodes from '../templates/core/functions/catchErrorCodes.hbs';
|
||||
import functionGetFormData from '../templates/core/functions/getFormData.hbs';
|
||||
import functionGetQueryString from '../templates/core/functions/getQueryString.hbs';
|
||||
import functionGetUrl from '../templates/core/functions/getUrl.hbs';
|
||||
@ -167,7 +167,7 @@ export const registerHandlebarTemplates = (root: {
|
||||
Handlebars.registerPartial('base', Handlebars.template(partialBase));
|
||||
|
||||
// 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/catchErrorCodes', Handlebars.template(functionCatchErrorCodes));
|
||||
Handlebars.registerPartial('functions/getFormData', Handlebars.template(functionGetFormData));
|
||||
Handlebars.registerPartial('functions/getQueryString', Handlebars.template(functionGetQueryString));
|
||||
Handlebars.registerPartial('functions/getUrl', Handlebars.template(functionGetUrl));
|
||||
|
||||
@ -469,7 +469,7 @@ const getResponseBody = async (response: Response): Promise<any> => {
|
||||
return;
|
||||
};
|
||||
|
||||
const catchErrors = (options: ApiRequestOptions, result: ApiResult): void => {
|
||||
const catchErrorCodes = (options: ApiRequestOptions, result: ApiResult): void => {
|
||||
const errors: Record<number, string> = {
|
||||
400: 'Bad Request',
|
||||
401: 'Unauthorized',
|
||||
@ -519,7 +519,7 @@ export const request = <T>(config: OpenAPIConfig, options: ApiRequestOptions): C
|
||||
body: responseHeader ?? responseBody,
|
||||
};
|
||||
|
||||
catchErrors(options, result);
|
||||
catchErrorCodes(options, result);
|
||||
|
||||
resolve(result.body);
|
||||
}
|
||||
@ -3370,7 +3370,7 @@ const getResponseBody = async (response: Response): Promise<any> => {
|
||||
return;
|
||||
};
|
||||
|
||||
const catchErrors = (options: ApiRequestOptions, result: ApiResult): void => {
|
||||
const catchErrorCodes = (options: ApiRequestOptions, result: ApiResult): void => {
|
||||
const errors: Record<number, string> = {
|
||||
400: 'Bad Request',
|
||||
401: 'Unauthorized',
|
||||
@ -3420,7 +3420,7 @@ export const request = <T>(config: OpenAPIConfig, options: ApiRequestOptions): C
|
||||
body: responseHeader ?? responseBody,
|
||||
};
|
||||
|
||||
catchErrors(options, result);
|
||||
catchErrorCodes(options, result);
|
||||
|
||||
resolve(result.body);
|
||||
}
|
||||
|
||||
@ -51,4 +51,68 @@ describe('v2.angular', () => {
|
||||
});
|
||||
expect(result).toBeDefined();
|
||||
});
|
||||
|
||||
it('should throw known error (500)', async () => {
|
||||
const error = await browser.evaluate(async () => {
|
||||
try {
|
||||
await new Promise<any>((resolve, reject) => {
|
||||
const { ErrorService } = (window as any).api;
|
||||
ErrorService.testErrorCode(500).subscribe(resolve, reject);
|
||||
});
|
||||
} catch (e) {
|
||||
const error = e as any;
|
||||
return JSON.stringify({
|
||||
name: error.name,
|
||||
message: error.message,
|
||||
url: error.url,
|
||||
status: error.status,
|
||||
statusText: error.statusText,
|
||||
body: error.body,
|
||||
});
|
||||
}
|
||||
return;
|
||||
});
|
||||
expect(error).toBe(
|
||||
JSON.stringify({
|
||||
name: 'ApiError',
|
||||
message: 'Custom message: Internal Server Error',
|
||||
url: 'http://localhost:3000/base/api/v1.0/error?status=500',
|
||||
status: 500,
|
||||
statusText: 'Internal Server Error',
|
||||
body: 'Internal Server Error',
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw unknown error (409)', async () => {
|
||||
const error = await browser.evaluate(async () => {
|
||||
try {
|
||||
await new Promise<any>((resolve, reject) => {
|
||||
const { ErrorService } = (window as any).api;
|
||||
ErrorService.testErrorCode(409).subscribe(resolve, reject);
|
||||
});
|
||||
} catch (e) {
|
||||
const error = e as any;
|
||||
return JSON.stringify({
|
||||
name: error.name,
|
||||
message: error.message,
|
||||
url: error.url,
|
||||
status: error.status,
|
||||
statusText: error.statusText,
|
||||
body: error.body,
|
||||
});
|
||||
}
|
||||
return;
|
||||
});
|
||||
expect(error).toBe(
|
||||
JSON.stringify({
|
||||
name: 'ApiError',
|
||||
message: 'Generic Error',
|
||||
url: 'http://localhost:3000/base/api/v1.0/error?status=409',
|
||||
status: 409,
|
||||
statusText: 'Conflict',
|
||||
body: 'Conflict',
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@ -83,4 +83,70 @@ describe('v3.angular', () => {
|
||||
});
|
||||
expect(result).toBeDefined();
|
||||
});
|
||||
|
||||
it('should throw known error (500)', async () => {
|
||||
const error = await browser.evaluate(async () => {
|
||||
try {
|
||||
await new Promise<any>((resolve, reject) => {
|
||||
const { ErrorService } = (window as any).api;
|
||||
ErrorService.testErrorCode(500).subscribe(resolve, reject);
|
||||
});
|
||||
} catch (e) {
|
||||
const error = e as any;
|
||||
return JSON.stringify({
|
||||
name: error.name,
|
||||
message: error.message,
|
||||
url: error.url,
|
||||
status: error.status,
|
||||
statusText: error.statusText,
|
||||
body: error.body,
|
||||
});
|
||||
}
|
||||
return;
|
||||
});
|
||||
expect(error).toBe(
|
||||
JSON.stringify({
|
||||
name: 'ApiError',
|
||||
message: 'Custom message: Internal Server Error',
|
||||
url: 'http://localhost:3000/base/api/v1.0/error?status=500',
|
||||
status: 500,
|
||||
statusText: 'Internal Server Error',
|
||||
body: 'Internal Server Error',
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw unknown error (409)', async () => {
|
||||
const error = await browser.evaluate(async () => {
|
||||
const { ErrorService } = (window as any).api;
|
||||
ErrorService.testErrorCode(409).subscribe(console.log, console.log);
|
||||
try {
|
||||
await new Promise<any>((resolve, reject) => {
|
||||
// const { ErrorService } = (window as any).api;
|
||||
ErrorService.testErrorCode(409).subscribe(resolve, reject);
|
||||
});
|
||||
} catch (e) {
|
||||
const error = e as any;
|
||||
return JSON.stringify({
|
||||
name: error.name,
|
||||
message: error.message,
|
||||
url: error.url,
|
||||
status: error.status,
|
||||
statusText: error.statusText,
|
||||
body: error.body,
|
||||
});
|
||||
}
|
||||
return;
|
||||
});
|
||||
expect(error).toBe(
|
||||
JSON.stringify({
|
||||
name: 'ApiError',
|
||||
message: 'Generic Error',
|
||||
url: 'http://localhost:3000/base/api/v1.0/error?status=409',
|
||||
status: 409,
|
||||
statusText: 'Conflict',
|
||||
body: 'Conflict',
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user