datastake-daf 0.6.491 → 0.6.493

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,6 +3,7 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  require('react/jsx-runtime');
6
+ require('antd');
6
7
 
7
8
  var global$1 = (typeof global !== "undefined" ? global :
8
9
  typeof self !== "undefined" ? self :
@@ -6095,6 +6096,32 @@ const isProxy = () => {
6095
6096
  };
6096
6097
  const getToken = () => isProxy() ? StorageManager.get('proxy_token') : StorageManager.get('token');
6097
6098
 
6099
+ /**
6100
+ * Custom params serializer to maintain JSON format for nested objects
6101
+ * Ensures consistent behavior across all axios versions
6102
+ */
6103
+ const paramsSerializer = params => {
6104
+ const parts = [];
6105
+ Object.keys(params).forEach(key => {
6106
+ const value = params[key];
6107
+ if (value !== null && value !== undefined) {
6108
+ if (typeof value === 'object' && !Array.isArray(value)) {
6109
+ // Serialize objects as JSON strings
6110
+ parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(JSON.stringify(value))}`);
6111
+ } else if (Array.isArray(value)) {
6112
+ // Handle arrays
6113
+ value.forEach(val => {
6114
+ parts.push(`${encodeURIComponent(key)}[]=${encodeURIComponent(val)}`);
6115
+ });
6116
+ } else {
6117
+ // Handle primitive values
6118
+ parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);
6119
+ }
6120
+ }
6121
+ });
6122
+ return parts.join('&');
6123
+ };
6124
+
6098
6125
  /**
6099
6126
  * Base HTTP Service Class
6100
6127
  * Provides axios wrapper with token management, cancel tokens, and interceptors
@@ -6130,6 +6157,7 @@ class BaseHTTPService {
6130
6157
  baseURL: this.getBaseURL(),
6131
6158
  headers,
6132
6159
  timeout: this.timeout,
6160
+ paramsSerializer: paramsSerializer,
6133
6161
  ...this.customAxiosConfig
6134
6162
  });
6135
6163
  this.setupInterceptors();
@@ -6151,6 +6179,7 @@ class BaseHTTPService {
6151
6179
  const options = {
6152
6180
  baseURL: this.getBaseURL(),
6153
6181
  timeout: this.timeout,
6182
+ paramsSerializer: paramsSerializer,
6154
6183
  ...this.customAxiosConfig
6155
6184
  };
6156
6185
  if (token) {
@@ -6334,5 +6363,185 @@ class ErrorHandler {
6334
6363
  }
6335
6364
  }
6336
6365
 
6366
+ let globalConfig = {
6367
+ application: null,
6368
+ mainApiUrl: null,
6369
+ storeUrl: null,
6370
+ language: 'en',
6371
+ onError: null,
6372
+ messageHandler: null,
6373
+ store: null,
6374
+ addToastAction: null
6375
+ };
6376
+ const configureServices = config => {
6377
+ globalConfig = {
6378
+ ...globalConfig,
6379
+ ...config
6380
+ };
6381
+ };
6382
+ const getConfig = () => globalConfig;
6383
+
6384
+ /**
6385
+ * Generic error handler factory for axios requests
6386
+ * Highly configurable to adapt to different project needs
6387
+ */
6388
+ const createErrorHandler = (config = {}) => {
6389
+ const {
6390
+ onUnauthorized,
6391
+ handleError,
6392
+ getStorageManager,
6393
+ checkTokenValidity = true,
6394
+ unauthorizedRedirect = '/',
6395
+ tokenStorageKey = 'token',
6396
+ handleNetworkError = true
6397
+ } = config;
6398
+ return (error, customOnUnauthorized) => {
6399
+ // Handle cases where error.response doesn't exist (network errors)
6400
+ if (!error.response) {
6401
+ if (handleNetworkError && handleError) {
6402
+ handleError({
6403
+ status: 0,
6404
+ statusText: "Network Error",
6405
+ data: ["Please check your internet connection."]
6406
+ });
6407
+ }
6408
+ return Promise.reject(error);
6409
+ }
6410
+ const {
6411
+ status,
6412
+ statusText,
6413
+ data: {
6414
+ errors,
6415
+ message
6416
+ } = {}
6417
+ } = error.response || {
6418
+ data: {}
6419
+ };
6420
+
6421
+ // Handle 401 Unauthorized
6422
+ if (status === 401) {
6423
+ if (checkTokenValidity && getStorageManager) {
6424
+ const token = getStorageManager().get(tokenStorageKey);
6425
+ if (token) {
6426
+ if (typeof customOnUnauthorized === 'function') {
6427
+ customOnUnauthorized();
6428
+ } else if (typeof onUnauthorized === 'function') {
6429
+ onUnauthorized();
6430
+ } else {
6431
+ getStorageManager().clearOne(tokenStorageKey);
6432
+ if (typeof window !== 'undefined') {
6433
+ window.location.href = unauthorizedRedirect;
6434
+ }
6435
+ }
6436
+ }
6437
+ }
6438
+ }
6439
+
6440
+ // Handle 4xx and 5xx errors
6441
+ if (status >= 400 && status <= 500) {
6442
+ if (handleError) {
6443
+ handleError({
6444
+ status,
6445
+ statusText: message || statusText,
6446
+ data: errors || []
6447
+ });
6448
+ }
6449
+ }
6450
+ return Promise.reject(error);
6451
+ };
6452
+ };
6453
+
6454
+ class ErrorService {
6455
+ static handle({
6456
+ status,
6457
+ statusText,
6458
+ data
6459
+ }) {
6460
+ const config = getConfig();
6461
+ if (config.store && config.addToastAction) {
6462
+ config.store.dispatch(config.addToastAction({
6463
+ title: statusText,
6464
+ type: 'danger',
6465
+ body: this.formatData(data)
6466
+ }));
6467
+ }
6468
+ }
6469
+ static formatData(errors) {
6470
+ const e = [];
6471
+ errors?.forEach(error => {
6472
+ Object.keys(error.constraints || {}).forEach(key => e.push(error.constraints[key]));
6473
+ });
6474
+ return e.join('\n');
6475
+ }
6476
+ }
6477
+
6478
+ class BaseService extends BaseHTTPService {
6479
+ constructor() {
6480
+ const config = getConfig();
6481
+ const onError = createErrorHandler({
6482
+ getStorageManager: () => StorageManager,
6483
+ handleError: ({
6484
+ status,
6485
+ statusText,
6486
+ data
6487
+ }) => {
6488
+ ErrorService.handle({
6489
+ status,
6490
+ statusText,
6491
+ data
6492
+ });
6493
+ },
6494
+ tokenStorageKey: 'token',
6495
+ unauthorizedRedirect: '/',
6496
+ checkTokenValidity: true,
6497
+ handleNetworkError: true
6498
+ });
6499
+ super({
6500
+ getToken: () => getToken(),
6501
+ getHeaders: () => ({
6502
+ Language: config.language || StorageManager.get('datastakeLng') || 'en',
6503
+ 'ngrok-skip-browser-warning': true,
6504
+ Application: config.application
6505
+ }),
6506
+ getBaseURL: options => {
6507
+ if (options?.isStore) return config.storeUrl;
6508
+ return config.mainApiUrl;
6509
+ },
6510
+ onError: onError,
6511
+ timeout: 300000
6512
+ });
6513
+ this.config = config;
6514
+ }
6515
+ apiGet(options) {
6516
+ const token = getToken();
6517
+ const config = this.config;
6518
+ if (token !== this.token || !token) {
6519
+ this.reloadAxios();
6520
+ }
6521
+ const {
6522
+ url,
6523
+ ...restConfig
6524
+ } = options;
6525
+ const baseURL = options.isStore ? config.storeUrl : config.mainApiUrl;
6526
+ return this.formatResponse(this.api.get(url, {
6527
+ ...restConfig,
6528
+ baseURL,
6529
+ headers: options.isStore ? {
6530
+ Authorization: `Bearer ${getToken()}`,
6531
+ ...(restConfig?.headers || {})
6532
+ } : {
6533
+ Authorization: `Bearer ${getToken()}`,
6534
+ Language: config.language || StorageManager.get('datastakeLng') || 'en',
6535
+ Application: config.application,
6536
+ ...(restConfig?.headers || {})
6537
+ }
6538
+ }).catch(err => this.onError(err)));
6539
+ }
6540
+ }
6541
+
6337
6542
  exports.BaseHTTPService = BaseHTTPService;
6543
+ exports.BaseService = BaseService;
6338
6544
  exports.ErrorHandler = ErrorHandler;
6545
+ exports.ErrorService = ErrorService;
6546
+ exports.configureServices = configureServices;
6547
+ exports.getConfig = getConfig;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "datastake-daf",
3
- "version": "0.6.491",
3
+ "version": "0.6.493",
4
4
  "dependencies": {
5
5
  "@ant-design/icons": "^5.2.5",
6
6
  "@antv/g2": "^5.1.1",
@@ -0,0 +1,69 @@
1
+ import { BaseHTTPService } from './helpers/BaseHTTPService.js';
2
+ import { getToken } from '../../helpers/Token.js';
3
+ import { createErrorHandler } from '../../helpers/errorHandling.js';
4
+ import { StorageManager } from '../../helpers/StorageManager.js';
5
+ import { getConfig } from './helpers/config.js';
6
+ import { ErrorService } from './ErrorService.js';
7
+
8
+ export class BaseService extends BaseHTTPService {
9
+ constructor() {
10
+ const config = getConfig();
11
+
12
+ const onError = createErrorHandler({
13
+ getStorageManager: () => StorageManager,
14
+ handleError: ({ status, statusText, data }) => {
15
+ ErrorService.handle({ status, statusText, data });
16
+ },
17
+ tokenStorageKey: 'token',
18
+ unauthorizedRedirect: '/',
19
+ checkTokenValidity: true,
20
+ handleNetworkError: true,
21
+ });
22
+
23
+ super({
24
+ getToken: () => getToken(),
25
+ getHeaders: () => ({
26
+ Language: config.language || StorageManager.get('datastakeLng') || 'en',
27
+ 'ngrok-skip-browser-warning': true,
28
+ Application: config.application,
29
+ }),
30
+ getBaseURL: (options) => {
31
+ if (options?.isStore) return config.storeUrl;
32
+ return config.mainApiUrl;
33
+ },
34
+ onError: onError,
35
+ timeout: 300000,
36
+ });
37
+
38
+ this.config = config;
39
+ }
40
+
41
+ apiGet(options) {
42
+ const token = getToken();
43
+ const config = this.config;
44
+
45
+ if (token !== this.token || !token) {
46
+ this.reloadAxios();
47
+ }
48
+
49
+ const { url, ...restConfig } = options;
50
+ const baseURL = options.isStore ? config.storeUrl : config.mainApiUrl;
51
+
52
+ return this.formatResponse(
53
+ this.api.get(url, {
54
+ ...restConfig,
55
+ baseURL,
56
+ headers: options.isStore ? {
57
+ Authorization: `Bearer ${getToken()}`,
58
+ ...(restConfig?.headers || {}),
59
+ } : {
60
+ Authorization: `Bearer ${getToken()}`,
61
+ Language: config.language || StorageManager.get('datastakeLng') || 'en',
62
+ Application: config.application,
63
+ ...(restConfig?.headers || {}),
64
+ }
65
+ })
66
+ .catch((err) => this.onError(err))
67
+ );
68
+ }
69
+ }
@@ -0,0 +1,29 @@
1
+ import { getConfig } from './helpers/config.js';
2
+
3
+ export class ErrorService {
4
+ static handle({ status, statusText, data }) {
5
+ const config = getConfig();
6
+
7
+ if (config.store && config.addToastAction) {
8
+ config.store.dispatch(config.addToastAction({
9
+ title: statusText,
10
+ type: 'danger',
11
+ body: this.formatData(data)
12
+ }));
13
+ }
14
+ }
15
+
16
+ static formatData(errors) {
17
+ const e = [];
18
+ errors?.forEach(error => {
19
+ Object.keys(error.constraints || {})
20
+ .forEach(key => e.push(error.constraints[key]));
21
+ });
22
+ return e.join('\n');
23
+ }
24
+ }
25
+
26
+ export const handleError = (err) => {
27
+ const config = getConfig();
28
+ config.messageHandler?.error(err?.response?.data?.message);
29
+ };
@@ -1,7 +1,33 @@
1
1
  import axios from 'axios';
2
- import { cleanJSON } from '../../helpers/StringHelper.js';
3
- import { assignParamsToUrl } from '../../helpers/urlHelpers.js';
4
- import { getToken } from '../../helpers/Token.js';
2
+ import { cleanJSON } from '../../../helpers/StringHelper.js';
3
+ import { assignParamsToUrl } from '../../../helpers/urlHelpers.js';
4
+ import { getToken } from '../../../helpers/Token.js';
5
+
6
+ /**
7
+ * Custom params serializer to maintain JSON format for nested objects
8
+ * Ensures consistent behavior across all axios versions
9
+ */
10
+ const paramsSerializer = (params) => {
11
+ const parts = [];
12
+ Object.keys(params).forEach(key => {
13
+ const value = params[key];
14
+ if (value !== null && value !== undefined) {
15
+ if (typeof value === 'object' && !Array.isArray(value)) {
16
+ // Serialize objects as JSON strings
17
+ parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(JSON.stringify(value))}`);
18
+ } else if (Array.isArray(value)) {
19
+ // Handle arrays
20
+ value.forEach(val => {
21
+ parts.push(`${encodeURIComponent(key)}[]=${encodeURIComponent(val)}`);
22
+ });
23
+ } else {
24
+ // Handle primitive values
25
+ parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);
26
+ }
27
+ }
28
+ });
29
+ return parts.join('&');
30
+ };
5
31
 
6
32
  /**
7
33
  * Base HTTP Service Class
@@ -36,6 +62,7 @@ export class BaseHTTPService {
36
62
  baseURL: this.getBaseURL(),
37
63
  headers,
38
64
  timeout: this.timeout,
65
+ paramsSerializer: paramsSerializer,
39
66
  ...this.customAxiosConfig,
40
67
  });
41
68
 
@@ -43,7 +70,8 @@ export class BaseHTTPService {
43
70
  }
44
71
 
45
72
  setupInterceptors() {
46
- this.api.interceptors.response.use((response) => response,
73
+ this.api.interceptors.response.use(
74
+ (response) => response,
47
75
  (error) => Promise.reject(error)
48
76
  );
49
77
 
@@ -67,6 +95,7 @@ export class BaseHTTPService {
67
95
  const options = {
68
96
  baseURL: this.getBaseURL(),
69
97
  timeout: this.timeout,
98
+ paramsSerializer: paramsSerializer,
70
99
  ...this.customAxiosConfig,
71
100
  };
72
101
 
@@ -221,9 +250,8 @@ export class BaseHTTPService {
221
250
  );
222
251
  }
223
252
 
224
-
225
253
  // Utility method
226
254
  assignParamsToUrl(path, params) {
227
255
  return assignParamsToUrl(path, params);
228
256
  }
229
- }
257
+ }
@@ -0,0 +1,16 @@
1
+ let globalConfig = {
2
+ application: null,
3
+ mainApiUrl: null,
4
+ storeUrl: null,
5
+ language: 'en',
6
+ onError: null,
7
+ messageHandler: null,
8
+ store: null,
9
+ addToastAction: null,
10
+ };
11
+
12
+ export const configureServices = (config) => {
13
+ globalConfig = { ...globalConfig, ...config };
14
+ };
15
+
16
+ export const getConfig = () => globalConfig;
package/src/services.js CHANGED
@@ -1,2 +1,8 @@
1
- export { BaseHTTPService } from './@daf/services/BaseHTTPService.js';
2
- export { ErrorHandler } from './@daf/services/ErrorHandler.js';
1
+ // HELPERS
2
+ export { BaseHTTPService } from './@daf/services/helpers/BaseHTTPService.js';
3
+ export { ErrorHandler } from './@daf/services/helpers/ErrorHandler.js';
4
+ export { configureServices, getConfig } from './@daf/services/helpers/config.js';
5
+
6
+ // SERVICES
7
+ export { BaseService } from './@daf/services/BaseService.js';
8
+ export { ErrorService } from './@daf/services/ErrorService.js';