From e400bc106888519b175eef7c440da37c4e07bb22 Mon Sep 17 00:00:00 2001 From: VitoAlbano Date: Wed, 13 Aug 2025 18:21:15 +0100 Subject: [PATCH] [AAE-30882] - migrating from superagent to axios --- lib/js-api/src/alfrescoApiClient.ts | 5 +- ...ragentHttpClient.ts => axiosHttpClient.ts} | 242 ++++++++++-------- lib/js-api/test/bpmAuth.spec.ts | 9 +- .../test/mockObjects/oauth2/oauth.mock.ts | 41 ++- lib/js-api/test/superagentHttpClient.spec.ts | 24 +- package-lock.json | 122 +-------- package.json | 4 +- 7 files changed, 204 insertions(+), 243 deletions(-) rename lib/js-api/src/{superagentHttpClient.ts => axiosHttpClient.ts} (59%) diff --git a/lib/js-api/src/alfrescoApiClient.ts b/lib/js-api/src/alfrescoApiClient.ts index e21ec20b51..f679fbac45 100644 --- a/lib/js-api/src/alfrescoApiClient.ts +++ b/lib/js-api/src/alfrescoApiClient.ts @@ -18,10 +18,11 @@ import { EventEmitter } from 'eventemitter3'; import { AlfrescoApiConfig } from './alfrescoApiConfig'; import { Authentication } from './authentication/authentication'; -import { SuperagentHttpClient } from './superagentHttpClient'; + import { Emitters, HttpClient, LegacyHttpClient, RequestOptions, SecurityOptions } from './api-clients/http-client.interface'; import { paramToString } from './utils'; import { Storage } from './storage'; +import { AxiosHttpClient } from './axiosHttpClient'; declare const Buffer: any; @@ -106,7 +107,7 @@ export class AlfrescoApiClient implements LegacyHttpClient { this.host = host; this.storage = Storage.getInstance(); // fallback for backward compatibility - this.httpClient = httpClient || new SuperagentHttpClient(); + this.httpClient = httpClient || new AxiosHttpClient(); } // EventEmitter delegation methods diff --git a/lib/js-api/src/superagentHttpClient.ts b/lib/js-api/src/axiosHttpClient.ts similarity index 59% rename from lib/js-api/src/superagentHttpClient.ts rename to lib/js-api/src/axiosHttpClient.ts index e201067deb..316ad7b3b7 100644 --- a/lib/js-api/src/superagentHttpClient.ts +++ b/lib/js-api/src/axiosHttpClient.ts @@ -16,7 +16,7 @@ */ import { EventEmitter } from 'eventemitter3'; -import superagent, { Response, SuperAgentRequest } from 'superagent'; +import axios, { AxiosResponse, AxiosRequestConfig, AxiosError } from 'axios'; import { Authentication } from './authentication/authentication'; import { RequestOptions, HttpClient, SecurityOptions, Emitters } from './api-clients/http-client.interface'; import { Oauth2 } from './authentication/oauth2'; @@ -30,7 +30,7 @@ type EventEmitterInstance = InstanceType; const isProgressEvent = (event: ProgressEvent | unknown): event is ProgressEvent => (event as ProgressEvent)?.lengthComputable; -export class SuperagentHttpClient implements HttpClient { +export class AxiosHttpClient implements HttpClient { /** * The default HTTP timeout for all API calls. */ @@ -52,11 +52,11 @@ export class SuperagentHttpClient implements HttpClient { return this.request(url, { ...options, httpMethod: 'DELETE' }, securityOptions, emitters); } - request(url: string, options: RequestOptions, securityOptions: SecurityOptions, emitters: Emitters): Promise { + async request(url: string, options: RequestOptions, securityOptions: SecurityOptions, emitters: Emitters): Promise { const { httpMethod, queryParams, headerParams, formParams, bodyParam, contentType, accept, responseType, returnType } = options; const { eventEmitter, apiClientEmitter } = emitters; - let request = this.buildRequest( + const config = this.buildRequest( httpMethod, url, queryParams, @@ -71,54 +71,55 @@ export class SuperagentHttpClient implements HttpClient { securityOptions ); + const source = axios.CancelToken.source(); + config.cancelToken = source.token; + if (returnType === 'Binary') { - request = request.buffer(true).parse(superagent.parse['application/octet-stream']); + config.responseType = 'arraybuffer'; } - const promise: any = new Promise((resolve, reject) => { - request.on('abort', () => { - eventEmitter.emit('abort'); - }); - request.end((error: any, response: Response) => { - if (error) { - apiClientEmitter.emit('error', error); - eventEmitter.emit('error', error); - - if (error.status === 401) { - apiClientEmitter.emit('unauthorized'); - eventEmitter.emit('unauthorized'); - } - - if (response?.text) { - error = error || {}; - reject(Object.assign(error, { message: response.text })); - } else { - // eslint-disable-next-line prefer-promise-reject-errors - reject({ error }); + const promise: any = axios(config) + .then((response: AxiosResponse) => { + if (securityOptions.isBpmRequest) { + const hasSetCookie = response.headers['set-cookie']; + if (response.headers && hasSetCookie) { + // mutate the passed value from AlfrescoApiClient class for backward compatibility + securityOptions.authentications.cookie = hasSetCookie[0]; } + } + let data = {}; + if (response.headers['content-type']?.includes('text/html')) { + data = AxiosHttpClient.deserialize(response); } else { - if (securityOptions.isBpmRequest) { - const hasSetCookie = Object.prototype.hasOwnProperty.call(response.header, 'set-cookie'); - if (response.header && hasSetCookie) { - // mutate the passed value from AlfrescoApiClient class for backward compatibility - securityOptions.authentications.cookie = response.header['set-cookie'][0]; - } - } - let data = {}; - if (response.type === 'text/html') { - data = SuperagentHttpClient.deserialize(response); - } else { - data = SuperagentHttpClient.deserialize(response, returnType); - } + data = AxiosHttpClient.deserialize(response, returnType); + } - eventEmitter.emit('success', data); - resolve(data); + eventEmitter.emit('success', data); + return data; + }) + .catch((error: AxiosError) => { + apiClientEmitter.emit('error', error); + eventEmitter.emit('error', error); + + if (error.response?.status === 401) { + apiClientEmitter.emit('unauthorized'); + eventEmitter.emit('unauthorized'); + } + + if (error.response?.data) { + const responseError = error.response.data; + const enrichedError = Object.assign(error, { + message: typeof responseError === 'string' ? responseError : JSON.stringify(responseError) + }); + throw enrichedError; + } else { + throw { error }; } }); - }); promise.abort = function () { - request.abort(); + eventEmitter.emit('abort'); + source.cancel('Request aborted'); return this; }; @@ -139,128 +140,163 @@ export class SuperagentHttpClient implements HttpClient { eventEmitter: EventEmitterInstance, returnType: string, securityOptions: SecurityOptions - ) { - const request = superagent(httpMethod, url); - + ): AxiosRequestConfig { const { isBpmRequest, authentications, defaultHeaders = {}, enableCsrf, withCredentials = false } = securityOptions; + const config: AxiosRequestConfig = { + method: httpMethod as any, + url, + params: AxiosHttpClient.normalizeParams(queryParams), + headers: { + ...defaultHeaders, + ...AxiosHttpClient.normalizeParams(headerParams) + }, + timeout: typeof this.timeout === 'number' ? this.timeout : this.timeout?.response, + withCredentials + }; + // apply authentications - this.applyAuthToRequest(request, authentications); - - // set query parameters - request.query(SuperagentHttpClient.normalizeParams(queryParams)); - - // set header parameters - request.set(defaultHeaders).set(SuperagentHttpClient.normalizeParams(headerParams)); + this.applyAuthToRequest(config, authentications); if (isBpmRequest && enableCsrf) { - this.setCsrfToken(request); - } - - if (withCredentials) { - request.withCredentials(); + this.setCsrfToken(config); } // add cookie for activiti if (isBpmRequest) { - request.withCredentials(); + config.withCredentials = true; if (securityOptions.authentications.cookie) { if (!isBrowser()) { - request.set('Cookie', securityOptions.authentications.cookie); + config.headers = { + ...config.headers, + Cookie: securityOptions.authentications.cookie + }; } } } - // set request timeout - request.timeout(this.timeout); - if (contentType && contentType !== 'multipart/form-data') { - request.type(contentType); - } else if (!(request as any).header['Content-Type'] && contentType !== 'multipart/form-data') { - request.type('application/json'); + config.headers = { + ...config.headers, + 'Content-Type': contentType + }; + } else if (!config.headers?.['Content-Type'] && contentType !== 'multipart/form-data') { + config.headers = { + ...config.headers, + 'Content-Type': 'application/json' + }; } if (contentType === 'application/x-www-form-urlencoded') { - request.send(SuperagentHttpClient.normalizeParams(formParams)).on('progress', (event: any) => { - this.progress(event, eventEmitter); + const params = new URLSearchParams(); + const normalizedParams = AxiosHttpClient.normalizeParams(formParams); + Object.keys(normalizedParams).forEach((key) => { + params.append(key, normalizedParams[key]); }); + config.data = params; + + config.onUploadProgress = (progressEvent) => { + this.progress(progressEvent, eventEmitter); + }; } else if (contentType === 'multipart/form-data') { - const _formParams = SuperagentHttpClient.normalizeParams(formParams); + const formData = new FormData(); + const _formParams = AxiosHttpClient.normalizeParams(formParams); for (const key in _formParams) { if (Object.prototype.hasOwnProperty.call(_formParams, key)) { - if (SuperagentHttpClient.isFileParam(_formParams[key])) { + if (AxiosHttpClient.isFileParam(_formParams[key])) { // file field - request.attach(key, _formParams[key]).on('progress', (event: ProgressEvent) => { - // jshint ignore:line - this.progress(event, eventEmitter); - }); + formData.append(key, _formParams[key]); } else { - request.field(key, _formParams[key]).on('progress', (event: ProgressEvent) => { - // jshint ignore:line - this.progress(event, eventEmitter); - }); + formData.append(key, _formParams[key]); } } } + config.data = formData; + // Remove Content-Type header for multipart/form-data to let axios set the boundary + delete config.headers['Content-Type']; + + config.onUploadProgress = (progressEvent) => { + this.progress(progressEvent, eventEmitter); + }; } else if (bodyParam) { - request.send(bodyParam).on('progress', (event: any) => { - this.progress(event, eventEmitter); - }); + config.data = bodyParam; + + config.onUploadProgress = (progressEvent) => { + this.progress(progressEvent, eventEmitter); + }; } if (accept) { - request.accept(accept); + config.headers = { + ...config.headers, + Accept: accept + }; } if (returnType === 'blob' || returnType === 'Blob' || responseType === 'blob' || responseType === 'Blob') { - request.responseType('blob'); + config.responseType = 'blob'; } else if (returnType === 'String') { - request.responseType('string'); + config.responseType = 'text'; } - return request; + return config; } - setCsrfToken(request: SuperAgentRequest): void { - const token = SuperagentHttpClient.createCSRFToken(); - request.set('X-CSRF-TOKEN', token); + setCsrfToken(config: AxiosRequestConfig): void { + const token = AxiosHttpClient.createCSRFToken(); + config.headers = { + ...config.headers, + 'X-CSRF-TOKEN': token + }; if (!isBrowser()) { - request.set('Cookie', 'CSRF-TOKEN=' + token + ';path=/'); + config.headers = { + ...config.headers, + Cookie: `CSRF-TOKEN=${token};path=/` + }; } try { - document.cookie = 'CSRF-TOKEN=' + token + ';path=/'; - } catch { + document.cookie = `CSRF-TOKEN=${token};path=/`; + } catch (err) { /* continue regardless of error */ } } /** * Applies authentication headers to the request. - * @param request The request object created by a superagent() call. + * @param config The axios request config object. * @param authentications authentications */ - private applyAuthToRequest(request: SuperAgentRequest, authentications: Authentication) { + private applyAuthToRequest(config: AxiosRequestConfig, authentications: Authentication) { if (authentications) { switch (authentications.type) { case 'basic': { const basicAuth: BasicAuth = authentications.basicAuth; if (basicAuth.username || basicAuth.password) { - request.auth(basicAuth.username || '', basicAuth.password || ''); + config.auth = { + username: basicAuth.username || '', + password: basicAuth.password || '' + }; } break; } case 'activiti': { if (authentications.basicAuth.ticket) { - request.set({ Authorization: authentications.basicAuth.ticket }); + config.headers = { + ...config.headers, + Authorization: authentications.basicAuth.ticket + }; } break; } case 'oauth2': { const oauth2: Oauth2 = authentications.oauth2; if (oauth2.accessToken) { - request.set({ Authorization: 'Bearer ' + oauth2.accessToken }); + config.headers = { + ...config.headers, + Authorization: `Bearer ${oauth2.accessToken}` + }; } break; } @@ -287,34 +323,34 @@ export class SuperagentHttpClient implements HttpClient { private static createCSRFToken(a?: any): string { return a ? (a ^ ((Math.random() * 16) >> (a / 4))).toString(16) - : ([1e16] + (1e16).toString()).replace(/[01]/g, SuperagentHttpClient.createCSRFToken); + : ([1e16] + (1e16).toString()).replace(/[01]/g, AxiosHttpClient.createCSRFToken); } /** * Deserializes an HTTP response body into a value of the specified type. - * @param response A SuperAgent response object. + * @param response An Axios response object. * @param returnType The type to return. Pass a string for simple types * or the constructor function for a complex type. Pass an array containing the type name to return an array of that type. To * return an object, pass an object with one property whose name is the key type and whose value is the corresponding value type: * all properties on data will be converted to this type. * @returns A value of the specified type. */ - private static deserialize(response: Response, returnType?: any): any { + private static deserialize(response: AxiosResponse, returnType?: any): any { if (response === null) { return null; } - let data = response.body; + let data = response.data; if (data === null) { - data = response.text; + data = response.statusText; } if (returnType) { if (returnType === 'blob' && isBrowser()) { - data = new Blob([data], { type: response.header['content-type'] }); + data = new Blob([data], { type: response.headers['content-type'] }); } else if (returnType === 'blob' && !isBrowser()) { - data = new Buffer.from(data, 'binary'); + data = Buffer.from(data, 'binary'); } else if (Array.isArray(data)) { data = data.map((element) => new returnType(element)); } else { @@ -341,7 +377,7 @@ export class SuperagentHttpClient implements HttpClient { for (const key in params) { if (Object.prototype.hasOwnProperty.call(params, key) && params[key] !== undefined && params[key] !== null) { const value = params[key]; - if (SuperagentHttpClient.isFileParam(value) || Array.isArray(value)) { + if (AxiosHttpClient.isFileParam(value) || Array.isArray(value)) { newParams[key] = value; } else { newParams[key] = paramToString(value); diff --git a/lib/js-api/test/bpmAuth.spec.ts b/lib/js-api/test/bpmAuth.spec.ts index 14e03903f4..543d9def31 100644 --- a/lib/js-api/test/bpmAuth.spec.ts +++ b/lib/js-api/test/bpmAuth.spec.ts @@ -17,8 +17,9 @@ import assert from 'assert'; import { ProcessAuth } from '../src'; -import { SuperagentHttpClient } from '../src/superagentHttpClient'; + import { BpmAuthMock } from './mockObjects'; +import { AxiosHttpClient } from '../src/axiosHttpClient'; describe('Bpm Auth test', () => { const hostBpm = 'https://127.0.0.1:9999'; @@ -256,16 +257,16 @@ describe('Bpm Auth test', () => { let setCsrfTokenCalled = false; beforeEach(() => { - originalMethod = SuperagentHttpClient.prototype.setCsrfToken; + originalMethod = AxiosHttpClient.prototype.setCsrfToken; setCsrfTokenCalled = false; - SuperagentHttpClient.prototype.setCsrfToken = () => { + AxiosHttpClient.prototype.setCsrfToken = () => { setCsrfTokenCalled = true; }; }); afterEach(() => { - SuperagentHttpClient.prototype.setCsrfToken = originalMethod; + AxiosHttpClient.prototype.setCsrfToken = originalMethod; setCsrfTokenCalled = false; }); diff --git a/lib/js-api/test/mockObjects/oauth2/oauth.mock.ts b/lib/js-api/test/mockObjects/oauth2/oauth.mock.ts index 3d1afb6982..1171e04f29 100644 --- a/lib/js-api/test/mockObjects/oauth2/oauth.mock.ts +++ b/lib/js-api/test/mockObjects/oauth2/oauth.mock.ts @@ -29,18 +29,37 @@ export class OAuthMock extends BaseMock { } get200Response(mockToken?: string): void { + nock(this.host).options('/auth/realms/springboot/protocol/openid-connect/token').reply(200, '', { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS', + 'Access-Control-Allow-Headers': 'Content-Type, Authorization', + 'Access-Control-Max-Age': '86400' + }); nock(this.host, { encodedQueryParams: true }) .post('/auth/realms/springboot/protocol/openid-connect/token') - .reply(200, { - access_token: mockToken || 'test-token', - expires_in: 300, - refresh_expires_in: 1800, - refresh_token: - // eslint-disable-next-line max-len - 'eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0cHczOUltNE54dXZEN0ZqZ3JOQ3Q2ZkpaVDctQ3JWTzRkX3BLaXJlSTF3In0.eyJqdGkiOiI2MzQxMDc1ZC1lOTY4LTRmZTctOTkwZS05MTQ3NTUwOGEzZWIiLCJleHAiOjE1Mjk2MDkxMDYsIm5iZiI6MCwiaWF0IjoxNTI5NjA3MzA2LCJpc3MiOiJodHRwOi8vYTVlMmY5M2RlMTBhZjExZThhMDU2MGExYmVhNWI3YzgtMjM2NzA5NDMzLnVzLWVhc3QtMS5lbGIuYW1hem9uYXdzLmNvbTozMDA4MS9hdXRoL3JlYWxtcy9zcHJpbmdib290IiwiYXVkIjoiYWN0aXZpdGkiLCJzdWIiOiJlMjRjZjM0Mi1mYzUwLTRjYjEtYTBjMC01N2RhZWRiODI3NDkiLCJ0eXAiOiJSZWZyZXNoIiwiYXpwIjoiYWN0aXZpdGkiLCJhdXRoX3RpbWUiOjAsInNlc3Npb25fc3RhdGUiOiI5NDMzZTIwNi1kZjFhLTQ2YTMtYmU3ZS02NWIwNDVhMWMzNmIiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiYWRtaW4iLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7InJlYWxtLW1hbmFnZW1lbnQiOnsicm9sZXMiOlsidmlldy1pZGVudGl0eS1wcm92aWRlcnMiLCJ2aWV3LXJlYWxtIiwibWFuYWdlLWlkZW50aXR5LXByb3ZpZGVycyIsImltcGVyc29uYXRpb24iLCJyZWFsbS1hZG1pbiIsImNyZWF0ZS1jbGllbnQiLCJtYW5hZ2UtdXNlcnMiLCJxdWVyeS1yZWFsbXMiLCJ2aWV3LWF1dGhvcml6YXRpb24iLCJxdWVyeS1jbGllbnRzIiwicXVlcnktdXNlcnMiLCJtYW5hZ2UtZXZlbnRzIiwibWFuYWdlLXJlYWxtIiwidmlldy1ldmVudHMiLCJ2aWV3LXVzZXJzIiwidmlldy1jbGllbnRzIiwibWFuYWdlLWF1dGhvcml6YXRpb24iLCJtYW5hZ2UtY2xpZW50cyIsInF1ZXJ5LWdyb3VwcyJdfSwiYnJva2VyIjp7InJvbGVzIjpbInJlYWQtdG9rZW4iXX0sImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX19.mQ4Vi1yLG9KvcmmhHlgOowy8D30iaUsiO7--JTPY7Ol-R1eY4wvRn1cH5FllieXk8yltYGP23xXNtTC4M54guXGVtgRgo8AlRklFHL1BMlxpa0OPwcNmwthx1-P2n7c9XL1e8pt2uRhQJLxunr2TpLaQi0UpEmEyouXHfR7sxM1AzKAf3b9Nk7f7lrk__2BYlFsL3YcGlFDqDMgPfhNlDbR-rQGoxlOjt0YqS8ktYq4bneL5etpXnPh0oEt4B7FFK-WKKuOWR6rQ9791ACnn6puz6C_Ki261IkZ0a_Uu7tOA4Xi9xzoQKLgSTAlBeg4u86Wb5kjL5r2-3zTg-Dikew', - token_type: 'bearer', - 'not-before-policy': 0, - session_state: '9433e206-df1a-46a3-be7e-65b045a1c36b' - }); + .reply( + 200, + { + access_token: mockToken || 'test-token', + expires_in: 300, + refresh_expires_in: 1800, + refresh_token: + // eslint-disable-next-line max-len + 'eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0cHczOUltNE54dXZEN0ZqZ3JOQ3Q2ZkpaVDctQ3JWTzRkX3BLaXJlSTF3In0.eyJqdGkiOiI2MzQxMDc1ZC1lOTY4LTRmZTctOTkwZS05MTQ3NTUwOGEzZWIiLCJleHAiOjE1Mjk2MDkxMDYsIm5iZiI6MCwiaWF0IjoxNTI5NjA3MzA2LCJpc3MiOiJodHRwOi8vYTVlMmY5M2RlMTBhZjExZThhMDU2MGExYmVhNWI3YzgtMjM2NzA5NDMzLnVzLWVhc3QtMS5lbGIuYW1hem9uYXdzLmNvbTozMDA4MS9hdXRoL3JlYWxtcy9zcHJpbmdib290IiwiYXVkIjoiYWN0aXZpdGkiLCJzdWIiOiJlMjRjZjM0Mi1mYzUwLTRjYjEtYTBjMC01N2RhZWRiODI3NDkiLCJ0eXAiOiJSZWZyZXNoIiwiYXpwIjoiYWN0aXZpdGkiLCJhdXRoX3RpbWUiOjAsInNlc3Npb25fc3RhdGUiOiI5NDMzZTIwNi1kZjFhLTQ2YTMtYmU3ZS02NWIwNDVhMWMzNmIiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiYWRtaW4iLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7InJlYWxtLW1hbmFnZW1lbnQiOnsicm9sZXMiOlsidmlldy1pZGVudGl0eS1wcm92aWRlcnMiLCJ2aWV3LXJlYWxtIiwibWFuYWdlLWlkZW50aXR5LXByb3ZpZGVycyIsImltcGVyc29uYXRpb24iLCJyZWFsbS1hZG1pbiIsImNyZWF0ZS1jbGllbnQiLCJtYW5hZ2UtdXNlcnMiLCJxdWVyeS1yZWFsbXMiLCJ2aWV3LWF1dGhvcml6YXRpb24iLCJxdWVyeS1jbGllbnRzIiwicXVlcnktdXNlcnMiLCJtYW5hZ2UtZXZlbnRzIiwibWFuYWdlLXJlYWxtIiwidmlldy1ldmVudHMiLCJ2aWV3LXVzZXJzIiwidmlldy1jbGllbnRzIiwibWFuYWdlLWF1dGhvcml6YXRpb24iLCJtYW5hZ2UtY2xpZW50cyIsInF1ZXJ5LWdyb3VwcyJdfSwiYnJva2VyIjp7InJvbGVzIjpbInJlYWQtdG9rZW4iXX0sImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX19.mQ4Vi1yLG9KvcmmhHlgOowy8D30iaUsiO7--JTPY7Ol-R1eY4wvRn1cH5FllieXk8yltYGP23xXNtTC4M54guXGVtgRgo8AlRklFHL1BMlxpa0OPwcNmwthx1-P2n7c9XL1e8pt2uRhQJLxunr2TpLaQi0UpEmEyouXHfR7sxM1AzKAf3b9Nk7f7lrk__2BYlFsL3YcGlFDqDMgPfhNlDbR-rQGoxlOjt0YqS8ktYq4bneL5etpXnPh0oEt4B7FFK-WKKuOWR6rQ9791ACnn6puz6C_Ki261IkZ0a_Uu7tOA4Xi9xzoQKLgSTAlBeg4u86Wb5kjL5r2-3zTg-Dikew', + token_type: 'bearer', + 'not-before-policy': 0, + session_state: '9433e206-df1a-46a3-be7e-65b045a1c36b' + }, + { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS', + 'Access-Control-Allow-Headers': 'Content-Type, Authorization, X-Requested-With', + 'Content-Type': 'application/json' + } + ); + } + + cleanAll() { + nock.cleanAll(); } } diff --git a/lib/js-api/test/superagentHttpClient.spec.ts b/lib/js-api/test/superagentHttpClient.spec.ts index 5da64b7386..f35bc5a4ad 100644 --- a/lib/js-api/test/superagentHttpClient.spec.ts +++ b/lib/js-api/test/superagentHttpClient.spec.ts @@ -16,12 +16,12 @@ */ import assert from 'assert'; -import { SuperagentHttpClient } from '../src/superagentHttpClient'; -import { Response } from 'superagent'; +import { AxiosHttpClient } from '../src/axiosHttpClient'; +import { AxiosResponse } from 'axios'; -describe('SuperagentHttpClient', () => { +describe('AxiosHttpClient', () => { describe('#buildRequest', () => { - const client = new SuperagentHttpClient(); + const client = new AxiosHttpClient(); it('should create a request with response type blob', () => { const queryParams = {}; @@ -70,8 +70,8 @@ describe('SuperagentHttpClient', () => { describe('#deserialize', () => { it('should the deserializer return an array of object when the response is an array', () => { - const data = { - body: [ + const data: AxiosResponse = { + data: [ { id: '1', name: 'test1' @@ -80,9 +80,15 @@ describe('SuperagentHttpClient', () => { id: '2', name: 'test2' } - ] - } as Response; - const result = SuperagentHttpClient['deserialize'](data); + ], + status: 200, + statusText: 'OK', + headers: {}, + config: { + headers: undefined + } + }; + const result = AxiosHttpClient['deserialize'](data); const isArray = Array.isArray(result); assert.equal(isArray, true); }); diff --git a/package-lock.json b/package-lock.json index 8e1afec65e..da229a55e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,9 +25,11 @@ "@mat-datetimepicker/core": "15.0.2", "@ngx-translate/core": "^16.0.4", "@nx/webpack": "20.8.0", + "@types/axios": "^0.9.36", "angular-oauth2-oidc": "17.0.2", "angular-oauth2-oidc-jwks": "^17.0.2", "apollo-angular": "10.0.3", + "axios": "^1.11.0", "chart.js": "4.4.4", "cropperjs": "1.6.2", "date-fns": "^2.30.0", @@ -42,7 +44,6 @@ "pdfjs-dist": "5.1.91", "raphael": "2.3.0", "rxjs": "7.8.2", - "superagent": "^9.0.1", "ts-morph": "^26.0.0", "tslib": "2.8.1", "zone.js": "0.15.0" @@ -83,7 +84,6 @@ "@types/node": "^18.16.9", "@types/pdfjs-dist": "2.10.378", "@types/shelljs": "^0.8.15", - "@types/superagent": "^4.1.22", "@typescript-eslint/eslint-plugin": "6.21.0", "@typescript-eslint/parser": "6.21.0", "@typescript-eslint/typescript-estree": "8.41.0", @@ -7780,18 +7780,6 @@ "@angular/core": ">=16" } }, - "node_modules/@noble/hashes": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", - "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", - "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -13702,15 +13690,6 @@ "unist-util-visit": "^1.1.3" } }, - "node_modules/@paralleldrive/cuid2": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.2.2.tgz", - "integrity": "sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "^1.1.5" - } - }, "node_modules/@parcel/watcher": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz", @@ -16078,6 +16057,12 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/axios": { + "version": "0.9.36", + "resolved": "https://registry.npmjs.org/@types/axios/-/axios-0.9.36.tgz", + "integrity": "sha512-NLOpedx9o+rxo/X5ChbdiX6mS1atE4WHmEEIcR9NLenRVa5HoVjAvjafwU3FPTqnZEstpoqCaW7fagqSoTDNeg==", + "license": "MIT" + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -16161,13 +16146,6 @@ "@types/node": "*" } }, - "node_modules/@types/cookiejar": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz", - "integrity": "sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/cors": { "version": "2.8.19", "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", @@ -16634,17 +16612,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/superagent": { - "version": "4.1.24", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.24.tgz", - "integrity": "sha512-mEafCgyKiMFin24SDzWN7yAADt4gt6YawFiNMp0QS5ZPboORfyxFt0s3VzJKhTaKg9py/4FUmrHLTNfJKt9Rbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/cookiejar": "*", - "@types/node": "*" - } - }, "node_modules/@types/tough-cookie": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", @@ -18697,6 +18664,7 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true, "license": "MIT" }, "node_modules/assertion-error": { @@ -20485,15 +20453,6 @@ "dev": true, "license": "MIT" }, - "node_modules/component-emitter": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", - "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/compressible": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", @@ -20705,12 +20664,6 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "license": "MIT" }, - "node_modules/cookiejar": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", - "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", - "license": "MIT" - }, "node_modules/cookies": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.9.1.tgz", @@ -21735,6 +21688,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dev": true, "license": "ISC", "dependencies": { "asap": "^2.0.0", @@ -23486,12 +23440,6 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "license": "MIT" }, - "node_modules/fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", - "license": "MIT" - }, "node_modules/fast-uri": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", @@ -24086,23 +24034,6 @@ "node": ">=12.20.0" } }, - "node_modules/formidable": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.4.tgz", - "integrity": "sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==", - "license": "MIT", - "dependencies": { - "@paralleldrive/cuid2": "^2.2.2", - "dezalgo": "^1.0.4", - "once": "^1.4.0" - }, - "engines": { - "node": ">=14.0.0" - }, - "funding": { - "url": "https://ko-fi.com/tunnckoCore/commissions" - } - }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -37337,39 +37268,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/superagent": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-9.0.2.tgz", - "integrity": "sha512-xuW7dzkUpcJq7QnhOsnNUgtYp3xRwpt2F7abdRYIpCsAt0hhUqia0EdxyXZQQpNmGtsCzYHryaKSV3q3GJnq7w==", - "deprecated": "Please upgrade to superagent v10.2.2+, see release notes at https://github.com/forwardemail/superagent/releases/tag/v10.2.2 - maintenance is supported by Forward Email @ https://forwardemail.net", - "license": "MIT", - "dependencies": { - "component-emitter": "^1.3.0", - "cookiejar": "^2.1.4", - "debug": "^4.3.4", - "fast-safe-stringify": "^2.1.1", - "form-data": "^4.0.0", - "formidable": "^3.5.1", - "methods": "^1.1.2", - "mime": "2.6.0", - "qs": "^6.11.0" - }, - "engines": { - "node": ">=14.18.0" - } - }, - "node_modules/superagent/node_modules/mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", diff --git a/package.json b/package.json index c904f3f8f9..c1afe11f0e 100644 --- a/package.json +++ b/package.json @@ -45,9 +45,11 @@ "@mat-datetimepicker/core": "15.0.2", "@ngx-translate/core": "^16.0.4", "@nx/webpack": "20.8.0", + "@types/axios": "^0.9.36", "angular-oauth2-oidc": "17.0.2", "angular-oauth2-oidc-jwks": "^17.0.2", "apollo-angular": "10.0.3", + "axios": "^1.11.0", "chart.js": "4.4.4", "cropperjs": "1.6.2", "date-fns": "^2.30.0", @@ -62,7 +64,6 @@ "pdfjs-dist": "5.1.91", "raphael": "2.3.0", "rxjs": "7.8.2", - "superagent": "^9.0.1", "ts-morph": "^26.0.0", "tslib": "2.8.1", "zone.js": "0.15.0" @@ -103,7 +104,6 @@ "@types/node": "^18.16.9", "@types/pdfjs-dist": "2.10.378", "@types/shelljs": "^0.8.15", - "@types/superagent": "^4.1.22", "@typescript-eslint/eslint-plugin": "6.21.0", "@typescript-eslint/parser": "6.21.0", "@typescript-eslint/typescript-estree": "8.41.0",