kimu-core 0.4.1 → 0.5.0

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.
Files changed (75) hide show
  1. package/.editorconfig +116 -30
  2. package/.gitattributes +81 -11
  3. package/.github/FUNDING.yml +8 -8
  4. package/.github/kimu-copilot-instructions.md +3779 -3779
  5. package/.github/workflows/deploy-demo.yml +39 -39
  6. package/.nvmrc +1 -0
  7. package/.prettierignore +44 -0
  8. package/.prettierrc +16 -0
  9. package/FUNDING.md +31 -31
  10. package/icon.svg +10 -10
  11. package/kimu-core-0.5.0.tgz +0 -0
  12. package/package.json +10 -3
  13. package/scripts/minify-css-assets.js +82 -82
  14. package/src/core/index.ts +47 -47
  15. package/src/core/kimu-global-styles.ts +136 -136
  16. package/src/core/kimu-reactive.ts +196 -196
  17. package/src/extensions/{kimu-home → app-root}/component.ts +5 -5
  18. package/src/extensions/extensions-manifest.json +4 -4
  19. package/src/main.ts +3 -3
  20. package/src/modules-repository/api-axios/CHANGELOG.md +48 -48
  21. package/src/modules-repository/api-axios/QUICK-REFERENCE.md +178 -178
  22. package/src/modules-repository/api-axios/README.md +304 -304
  23. package/src/modules-repository/api-axios/api-axios-service.ts +355 -355
  24. package/src/modules-repository/api-axios/examples.ts +293 -293
  25. package/src/modules-repository/api-axios/index.ts +19 -19
  26. package/src/modules-repository/api-axios/interfaces.ts +71 -71
  27. package/src/modules-repository/api-axios/module.ts +41 -41
  28. package/src/modules-repository/api-core/CHANGELOG.md +42 -42
  29. package/src/modules-repository/api-core/QUICK-REFERENCE.md +192 -192
  30. package/src/modules-repository/api-core/README.md +435 -435
  31. package/src/modules-repository/api-core/api-core-service.ts +289 -289
  32. package/src/modules-repository/api-core/examples.ts +432 -432
  33. package/src/modules-repository/api-core/index.ts +8 -8
  34. package/src/modules-repository/api-core/interfaces.ts +83 -83
  35. package/src/modules-repository/api-core/module.ts +30 -30
  36. package/src/modules-repository/event-bus/README.md +273 -273
  37. package/src/modules-repository/event-bus/event-bus-service.ts +176 -176
  38. package/src/modules-repository/event-bus/module.ts +30 -30
  39. package/src/modules-repository/notification/README.md +423 -423
  40. package/src/modules-repository/notification/module.ts +30 -30
  41. package/src/modules-repository/notification/notification-service.ts +436 -436
  42. package/src/modules-repository/router/README.it.md +61 -10
  43. package/src/modules-repository/router/README.md +61 -10
  44. package/src/modules-repository/router/router-config.ts.example +61 -0
  45. package/src/modules-repository/router/router.ts +18 -0
  46. package/src/modules-repository/state/README.md +409 -409
  47. package/src/modules-repository/state/module.ts +30 -30
  48. package/src/modules-repository/state/state-service.ts +296 -296
  49. package/src/modules-repository/theme/README.md +311 -267
  50. package/src/modules-repository/theme/module.ts +30 -30
  51. package/src/modules-repository/theme/pre-build.js +40 -40
  52. package/src/modules-repository/theme/theme-service.ts +411 -389
  53. package/src/modules-repository/theme/themes/theme-cherry-blossom.css +78 -78
  54. package/src/modules-repository/theme/themes/theme-cozy.css +111 -111
  55. package/src/modules-repository/theme/themes/theme-cyberpunk.css +150 -150
  56. package/src/modules-repository/theme/themes/theme-dark.css +79 -79
  57. package/src/modules-repository/theme/themes/theme-forest.css +171 -171
  58. package/src/modules-repository/theme/themes/theme-gold.css +100 -100
  59. package/src/modules-repository/theme/themes/theme-high-contrast.css +126 -126
  60. package/src/modules-repository/theme/themes/theme-lava.css +101 -101
  61. package/src/modules-repository/theme/themes/theme-lavender.css +90 -90
  62. package/src/modules-repository/theme/themes/theme-light.css +79 -79
  63. package/src/modules-repository/theme/themes/theme-matrix.css +103 -103
  64. package/src/modules-repository/theme/themes/theme-midnight.css +81 -81
  65. package/src/modules-repository/theme/themes/theme-nord.css +94 -94
  66. package/src/modules-repository/theme/themes/theme-ocean.css +84 -84
  67. package/src/modules-repository/theme/themes/theme-retro80s.css +343 -343
  68. package/src/modules-repository/theme/themes/theme-sunset.css +62 -62
  69. package/src/modules-repository/theme/themes-config-default.json +19 -0
  70. package/src/modules-repository/theme/themes-config.d.ts +27 -27
  71. package/src/modules-repository/theme/{themes-config.json → themes-config.json.example} +223 -213
  72. /package/src/extensions/{kimu-home → app-root}/lang/en.json +0 -0
  73. /package/src/extensions/{kimu-home → app-root}/lang/it.json +0 -0
  74. /package/src/extensions/{kimu-home → app-root}/style.css +0 -0
  75. /package/src/extensions/{kimu-home → app-root}/view.html +0 -0
@@ -1,355 +1,355 @@
1
- /**
2
- * API Axios Service
3
- *
4
- * Advanced HTTP client based on Axios library.
5
- * Provides additional features over api-core:
6
- * - Request/response interceptors
7
- * - Automatic retries with exponential backoff
8
- * - Request cancellation
9
- * - Upload/download progress tracking
10
- * - Better error handling and transformation
11
- * - Request/response caching
12
- *
13
- * @module api-axios
14
- * @author UnicòVerso
15
- * @version 1.0.0
16
- */
17
-
18
- import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, CancelTokenSource, InternalAxiosRequestConfig } from 'axios';
19
- import {
20
- ApiRequestConfig,
21
- ApiResponse,
22
- ApiError,
23
- HttpMethod,
24
- RequestInterceptor,
25
- ResponseInterceptor,
26
- ErrorInterceptor
27
- } from './interfaces';
28
-
29
- /**
30
- * ApiAxiosService - Advanced HTTP client with Axios
31
- *
32
- * Features:
33
- * - Interceptors for requests and responses
34
- * - Automatic retry logic with exponential backoff
35
- * - Request cancellation support
36
- * - Progress tracking for uploads/downloads
37
- * - Response caching
38
- * - Better error handling
39
- */
40
- export class ApiAxiosService {
41
- private axiosInstance: AxiosInstance;
42
- private requestInterceptors: RequestInterceptor[] = [];
43
- private responseInterceptors: ResponseInterceptor[] = [];
44
- private errorInterceptors: ErrorInterceptor[] = [];
45
- private cache: Map<string, { data: any; timestamp: number }> = new Map();
46
- private cacheTTL: number = 5 * 60 * 1000; // 5 minutes default
47
-
48
- constructor() {
49
- this.axiosInstance = axios.create({
50
- timeout: 30000,
51
- headers: {
52
- 'Content-Type': 'application/json'
53
- }
54
- });
55
-
56
- this.setupInterceptors();
57
- }
58
-
59
- /**
60
- * Setup default Axios interceptors
61
- */
62
- private setupInterceptors(): void {
63
- // Request interceptor
64
- this.axiosInstance.interceptors.request.use(
65
- async (config: InternalAxiosRequestConfig) => {
66
- // Apply custom request interceptors
67
- for (const interceptor of this.requestInterceptors) {
68
- const modifiedConfig = await interceptor(config as any);
69
- Object.assign(config, modifiedConfig);
70
- }
71
- return config;
72
- },
73
- (error: any) => Promise.reject(error)
74
- );
75
-
76
- // Response interceptor
77
- this.axiosInstance.interceptors.response.use(
78
- async (response: AxiosResponse) => {
79
- const apiResponse = this.transformResponse(response);
80
-
81
- // Apply custom response interceptors
82
- for (const interceptor of this.responseInterceptors) {
83
- await interceptor(apiResponse);
84
- }
85
-
86
- return response;
87
- },
88
- async (error: any) => {
89
- const apiError = this.transformError(error);
90
-
91
- // Apply custom error interceptors
92
- for (const interceptor of this.errorInterceptors) {
93
- await interceptor(apiError);
94
- }
95
-
96
- return Promise.reject(apiError);
97
- }
98
- );
99
- }
100
-
101
- /**
102
- * Add a request interceptor
103
- */
104
- addRequestInterceptor(interceptor: RequestInterceptor): void {
105
- this.requestInterceptors.push(interceptor);
106
- }
107
-
108
- /**
109
- * Add a response interceptor
110
- */
111
- addResponseInterceptor(interceptor: ResponseInterceptor): void {
112
- this.responseInterceptors.push(interceptor);
113
- }
114
-
115
- /**
116
- * Add an error interceptor
117
- */
118
- addErrorInterceptor(interceptor: ErrorInterceptor): void {
119
- this.errorInterceptors.push(interceptor);
120
- }
121
-
122
- /**
123
- * Transform Axios response to ApiResponse format
124
- */
125
- private transformResponse(response: AxiosResponse): ApiResponse {
126
- return {
127
- data: response.data,
128
- status: response.status,
129
- statusText: response.statusText,
130
- headers: response.headers as Record<string, string>,
131
- config: response.config as ApiRequestConfig
132
- };
133
- }
134
-
135
- /**
136
- * Transform Axios error to ApiError format
137
- */
138
- private transformError(error: any): ApiError {
139
- if (error.response) {
140
- return {
141
- message: error.message || 'Request failed',
142
- status: error.response.status,
143
- data: error.response.data,
144
- originalError: error
145
- };
146
- }
147
-
148
- return {
149
- message: error.message || 'Network error',
150
- originalError: error
151
- };
152
- }
153
-
154
- /**
155
- * Generate cache key from URL and config
156
- */
157
- private getCacheKey(url: string, config?: ApiRequestConfig): string {
158
- const params = config?.params ? JSON.stringify(config.params) : '';
159
- return `${url}${params}`;
160
- }
161
-
162
- /**
163
- * Check if cached response is still valid
164
- */
165
- private isCacheValid(timestamp: number): boolean {
166
- return Date.now() - timestamp < this.cacheTTL;
167
- }
168
-
169
- /**
170
- * Set cache TTL (time-to-live) in milliseconds
171
- */
172
- setCacheTTL(ttl: number): void {
173
- this.cacheTTL = ttl;
174
- }
175
-
176
- /**
177
- * Clear all cached responses
178
- */
179
- clearCache(): void {
180
- this.cache.clear();
181
- }
182
-
183
- /**
184
- * Create a cancel token for request cancellation
185
- */
186
- createCancelToken(): CancelTokenSource {
187
- return axios.CancelToken.source();
188
- }
189
-
190
- /**
191
- * Perform HTTP GET request
192
- */
193
- async get<T = any>(url: string, config?: ApiRequestConfig & { useCache?: boolean }): Promise<ApiResponse<T>> {
194
- const useCache = config?.useCache ?? false;
195
- const cacheKey = this.getCacheKey(url, config);
196
-
197
- // Check cache
198
- if (useCache && this.cache.has(cacheKey)) {
199
- const cached = this.cache.get(cacheKey)!;
200
- if (this.isCacheValid(cached.timestamp)) {
201
- return {
202
- data: cached.data,
203
- status: 200,
204
- statusText: 'OK (cached)',
205
- headers: {},
206
- config: config || {}
207
- };
208
- }
209
- }
210
-
211
- const axiosConfig: AxiosRequestConfig = {
212
- ...config?.axiosConfig,
213
- headers: config?.headers,
214
- params: config?.params,
215
- timeout: config?.timeout,
216
- withCredentials: config?.withCredentials,
217
- responseType: config?.responseType,
218
- onUploadProgress: config?.onUploadProgress,
219
- onDownloadProgress: config?.onDownloadProgress
220
- };
221
-
222
- const response = await this.axiosInstance.get<T>(url, axiosConfig);
223
- const apiResponse = this.transformResponse(response);
224
-
225
- // Store in cache if enabled
226
- if (useCache) {
227
- this.cache.set(cacheKey, {
228
- data: apiResponse.data,
229
- timestamp: Date.now()
230
- });
231
- }
232
-
233
- return apiResponse;
234
- }
235
-
236
- /**
237
- * Perform HTTP POST request
238
- */
239
- async post<T = any>(url: string, data?: any, config?: ApiRequestConfig): Promise<ApiResponse<T>> {
240
- const axiosConfig: AxiosRequestConfig = {
241
- ...config?.axiosConfig,
242
- headers: config?.headers,
243
- params: config?.params,
244
- timeout: config?.timeout,
245
- withCredentials: config?.withCredentials,
246
- responseType: config?.responseType,
247
- onUploadProgress: config?.onUploadProgress,
248
- onDownloadProgress: config?.onDownloadProgress
249
- };
250
-
251
- const response = await this.axiosInstance.post<T>(url, data, axiosConfig);
252
- return this.transformResponse(response);
253
- }
254
-
255
- /**
256
- * Perform HTTP PUT request
257
- */
258
- async put<T = any>(url: string, data?: any, config?: ApiRequestConfig): Promise<ApiResponse<T>> {
259
- const axiosConfig: AxiosRequestConfig = {
260
- ...config?.axiosConfig,
261
- headers: config?.headers,
262
- params: config?.params,
263
- timeout: config?.timeout,
264
- withCredentials: config?.withCredentials,
265
- responseType: config?.responseType,
266
- onUploadProgress: config?.onUploadProgress,
267
- onDownloadProgress: config?.onDownloadProgress
268
- };
269
-
270
- const response = await this.axiosInstance.put<T>(url, data, axiosConfig);
271
- return this.transformResponse(response);
272
- }
273
-
274
- /**
275
- * Perform HTTP PATCH request
276
- */
277
- async patch<T = any>(url: string, data?: any, config?: ApiRequestConfig): Promise<ApiResponse<T>> {
278
- const axiosConfig: AxiosRequestConfig = {
279
- ...config?.axiosConfig,
280
- headers: config?.headers,
281
- params: config?.params,
282
- timeout: config?.timeout,
283
- withCredentials: config?.withCredentials,
284
- responseType: config?.responseType,
285
- onUploadProgress: config?.onUploadProgress,
286
- onDownloadProgress: config?.onDownloadProgress
287
- };
288
-
289
- const response = await this.axiosInstance.patch<T>(url, data, axiosConfig);
290
- return this.transformResponse(response);
291
- }
292
-
293
- /**
294
- * Perform HTTP DELETE request
295
- */
296
- async delete<T = any>(url: string, config?: ApiRequestConfig): Promise<ApiResponse<T>> {
297
- const axiosConfig: AxiosRequestConfig = {
298
- ...config?.axiosConfig,
299
- headers: config?.headers,
300
- params: config?.params,
301
- timeout: config?.timeout,
302
- withCredentials: config?.withCredentials,
303
- responseType: config?.responseType
304
- };
305
-
306
- const response = await this.axiosInstance.delete<T>(url, axiosConfig);
307
- return this.transformResponse(response);
308
- }
309
-
310
- /**
311
- * Perform a generic HTTP request with automatic retry
312
- */
313
- async request<T = any>(
314
- method: HttpMethod,
315
- url: string,
316
- data?: any,
317
- config?: ApiRequestConfig & { retries?: number; retryDelay?: number }
318
- ): Promise<ApiResponse<T>> {
319
- const retries = config?.retries ?? 0;
320
- const retryDelay = config?.retryDelay ?? 1000;
321
-
322
- let lastError: ApiError | null = null;
323
-
324
- for (let attempt = 0; attempt <= retries; attempt++) {
325
- try {
326
- switch (method) {
327
- case 'GET':
328
- return await this.get<T>(url, config);
329
- case 'POST':
330
- return await this.post<T>(url, data, config);
331
- case 'PUT':
332
- return await this.put<T>(url, data, config);
333
- case 'PATCH':
334
- return await this.patch<T>(url, data, config);
335
- case 'DELETE':
336
- return await this.delete<T>(url, config);
337
- default:
338
- throw new Error(`Unsupported HTTP method: ${method}`);
339
- }
340
- } catch (error: any) {
341
- lastError = error as ApiError;
342
-
343
- if (attempt < retries) {
344
- // Exponential backoff
345
- await new Promise(resolve => setTimeout(resolve, retryDelay * Math.pow(2, attempt)));
346
- }
347
- }
348
- }
349
-
350
- throw lastError;
351
- }
352
- }
353
-
354
- // Singleton instance
355
- export const apiAxiosService = new ApiAxiosService();
1
+ /**
2
+ * API Axios Service
3
+ *
4
+ * Advanced HTTP client based on Axios library.
5
+ * Provides additional features over api-core:
6
+ * - Request/response interceptors
7
+ * - Automatic retries with exponential backoff
8
+ * - Request cancellation
9
+ * - Upload/download progress tracking
10
+ * - Better error handling and transformation
11
+ * - Request/response caching
12
+ *
13
+ * @module api-axios
14
+ * @author UnicòVerso
15
+ * @version 1.0.0
16
+ */
17
+
18
+ import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, CancelTokenSource, InternalAxiosRequestConfig } from 'axios';
19
+ import {
20
+ ApiRequestConfig,
21
+ ApiResponse,
22
+ ApiError,
23
+ HttpMethod,
24
+ RequestInterceptor,
25
+ ResponseInterceptor,
26
+ ErrorInterceptor
27
+ } from './interfaces';
28
+
29
+ /**
30
+ * ApiAxiosService - Advanced HTTP client with Axios
31
+ *
32
+ * Features:
33
+ * - Interceptors for requests and responses
34
+ * - Automatic retry logic with exponential backoff
35
+ * - Request cancellation support
36
+ * - Progress tracking for uploads/downloads
37
+ * - Response caching
38
+ * - Better error handling
39
+ */
40
+ export class ApiAxiosService {
41
+ private axiosInstance: AxiosInstance;
42
+ private requestInterceptors: RequestInterceptor[] = [];
43
+ private responseInterceptors: ResponseInterceptor[] = [];
44
+ private errorInterceptors: ErrorInterceptor[] = [];
45
+ private cache: Map<string, { data: any; timestamp: number }> = new Map();
46
+ private cacheTTL: number = 5 * 60 * 1000; // 5 minutes default
47
+
48
+ constructor() {
49
+ this.axiosInstance = axios.create({
50
+ timeout: 30000,
51
+ headers: {
52
+ 'Content-Type': 'application/json'
53
+ }
54
+ });
55
+
56
+ this.setupInterceptors();
57
+ }
58
+
59
+ /**
60
+ * Setup default Axios interceptors
61
+ */
62
+ private setupInterceptors(): void {
63
+ // Request interceptor
64
+ this.axiosInstance.interceptors.request.use(
65
+ async (config: InternalAxiosRequestConfig) => {
66
+ // Apply custom request interceptors
67
+ for (const interceptor of this.requestInterceptors) {
68
+ const modifiedConfig = await interceptor(config as any);
69
+ Object.assign(config, modifiedConfig);
70
+ }
71
+ return config;
72
+ },
73
+ (error: any) => Promise.reject(error)
74
+ );
75
+
76
+ // Response interceptor
77
+ this.axiosInstance.interceptors.response.use(
78
+ async (response: AxiosResponse) => {
79
+ const apiResponse = this.transformResponse(response);
80
+
81
+ // Apply custom response interceptors
82
+ for (const interceptor of this.responseInterceptors) {
83
+ await interceptor(apiResponse);
84
+ }
85
+
86
+ return response;
87
+ },
88
+ async (error: any) => {
89
+ const apiError = this.transformError(error);
90
+
91
+ // Apply custom error interceptors
92
+ for (const interceptor of this.errorInterceptors) {
93
+ await interceptor(apiError);
94
+ }
95
+
96
+ return Promise.reject(apiError);
97
+ }
98
+ );
99
+ }
100
+
101
+ /**
102
+ * Add a request interceptor
103
+ */
104
+ addRequestInterceptor(interceptor: RequestInterceptor): void {
105
+ this.requestInterceptors.push(interceptor);
106
+ }
107
+
108
+ /**
109
+ * Add a response interceptor
110
+ */
111
+ addResponseInterceptor(interceptor: ResponseInterceptor): void {
112
+ this.responseInterceptors.push(interceptor);
113
+ }
114
+
115
+ /**
116
+ * Add an error interceptor
117
+ */
118
+ addErrorInterceptor(interceptor: ErrorInterceptor): void {
119
+ this.errorInterceptors.push(interceptor);
120
+ }
121
+
122
+ /**
123
+ * Transform Axios response to ApiResponse format
124
+ */
125
+ private transformResponse(response: AxiosResponse): ApiResponse {
126
+ return {
127
+ data: response.data,
128
+ status: response.status,
129
+ statusText: response.statusText,
130
+ headers: response.headers as Record<string, string>,
131
+ config: response.config as ApiRequestConfig
132
+ };
133
+ }
134
+
135
+ /**
136
+ * Transform Axios error to ApiError format
137
+ */
138
+ private transformError(error: any): ApiError {
139
+ if (error.response) {
140
+ return {
141
+ message: error.message || 'Request failed',
142
+ status: error.response.status,
143
+ data: error.response.data,
144
+ originalError: error
145
+ };
146
+ }
147
+
148
+ return {
149
+ message: error.message || 'Network error',
150
+ originalError: error
151
+ };
152
+ }
153
+
154
+ /**
155
+ * Generate cache key from URL and config
156
+ */
157
+ private getCacheKey(url: string, config?: ApiRequestConfig): string {
158
+ const params = config?.params ? JSON.stringify(config.params) : '';
159
+ return `${url}${params}`;
160
+ }
161
+
162
+ /**
163
+ * Check if cached response is still valid
164
+ */
165
+ private isCacheValid(timestamp: number): boolean {
166
+ return Date.now() - timestamp < this.cacheTTL;
167
+ }
168
+
169
+ /**
170
+ * Set cache TTL (time-to-live) in milliseconds
171
+ */
172
+ setCacheTTL(ttl: number): void {
173
+ this.cacheTTL = ttl;
174
+ }
175
+
176
+ /**
177
+ * Clear all cached responses
178
+ */
179
+ clearCache(): void {
180
+ this.cache.clear();
181
+ }
182
+
183
+ /**
184
+ * Create a cancel token for request cancellation
185
+ */
186
+ createCancelToken(): CancelTokenSource {
187
+ return axios.CancelToken.source();
188
+ }
189
+
190
+ /**
191
+ * Perform HTTP GET request
192
+ */
193
+ async get<T = any>(url: string, config?: ApiRequestConfig & { useCache?: boolean }): Promise<ApiResponse<T>> {
194
+ const useCache = config?.useCache ?? false;
195
+ const cacheKey = this.getCacheKey(url, config);
196
+
197
+ // Check cache
198
+ if (useCache && this.cache.has(cacheKey)) {
199
+ const cached = this.cache.get(cacheKey)!;
200
+ if (this.isCacheValid(cached.timestamp)) {
201
+ return {
202
+ data: cached.data,
203
+ status: 200,
204
+ statusText: 'OK (cached)',
205
+ headers: {},
206
+ config: config || {}
207
+ };
208
+ }
209
+ }
210
+
211
+ const axiosConfig: AxiosRequestConfig = {
212
+ ...config?.axiosConfig,
213
+ headers: config?.headers,
214
+ params: config?.params,
215
+ timeout: config?.timeout,
216
+ withCredentials: config?.withCredentials,
217
+ responseType: config?.responseType,
218
+ onUploadProgress: config?.onUploadProgress,
219
+ onDownloadProgress: config?.onDownloadProgress
220
+ };
221
+
222
+ const response = await this.axiosInstance.get<T>(url, axiosConfig);
223
+ const apiResponse = this.transformResponse(response);
224
+
225
+ // Store in cache if enabled
226
+ if (useCache) {
227
+ this.cache.set(cacheKey, {
228
+ data: apiResponse.data,
229
+ timestamp: Date.now()
230
+ });
231
+ }
232
+
233
+ return apiResponse;
234
+ }
235
+
236
+ /**
237
+ * Perform HTTP POST request
238
+ */
239
+ async post<T = any>(url: string, data?: any, config?: ApiRequestConfig): Promise<ApiResponse<T>> {
240
+ const axiosConfig: AxiosRequestConfig = {
241
+ ...config?.axiosConfig,
242
+ headers: config?.headers,
243
+ params: config?.params,
244
+ timeout: config?.timeout,
245
+ withCredentials: config?.withCredentials,
246
+ responseType: config?.responseType,
247
+ onUploadProgress: config?.onUploadProgress,
248
+ onDownloadProgress: config?.onDownloadProgress
249
+ };
250
+
251
+ const response = await this.axiosInstance.post<T>(url, data, axiosConfig);
252
+ return this.transformResponse(response);
253
+ }
254
+
255
+ /**
256
+ * Perform HTTP PUT request
257
+ */
258
+ async put<T = any>(url: string, data?: any, config?: ApiRequestConfig): Promise<ApiResponse<T>> {
259
+ const axiosConfig: AxiosRequestConfig = {
260
+ ...config?.axiosConfig,
261
+ headers: config?.headers,
262
+ params: config?.params,
263
+ timeout: config?.timeout,
264
+ withCredentials: config?.withCredentials,
265
+ responseType: config?.responseType,
266
+ onUploadProgress: config?.onUploadProgress,
267
+ onDownloadProgress: config?.onDownloadProgress
268
+ };
269
+
270
+ const response = await this.axiosInstance.put<T>(url, data, axiosConfig);
271
+ return this.transformResponse(response);
272
+ }
273
+
274
+ /**
275
+ * Perform HTTP PATCH request
276
+ */
277
+ async patch<T = any>(url: string, data?: any, config?: ApiRequestConfig): Promise<ApiResponse<T>> {
278
+ const axiosConfig: AxiosRequestConfig = {
279
+ ...config?.axiosConfig,
280
+ headers: config?.headers,
281
+ params: config?.params,
282
+ timeout: config?.timeout,
283
+ withCredentials: config?.withCredentials,
284
+ responseType: config?.responseType,
285
+ onUploadProgress: config?.onUploadProgress,
286
+ onDownloadProgress: config?.onDownloadProgress
287
+ };
288
+
289
+ const response = await this.axiosInstance.patch<T>(url, data, axiosConfig);
290
+ return this.transformResponse(response);
291
+ }
292
+
293
+ /**
294
+ * Perform HTTP DELETE request
295
+ */
296
+ async delete<T = any>(url: string, config?: ApiRequestConfig): Promise<ApiResponse<T>> {
297
+ const axiosConfig: AxiosRequestConfig = {
298
+ ...config?.axiosConfig,
299
+ headers: config?.headers,
300
+ params: config?.params,
301
+ timeout: config?.timeout,
302
+ withCredentials: config?.withCredentials,
303
+ responseType: config?.responseType
304
+ };
305
+
306
+ const response = await this.axiosInstance.delete<T>(url, axiosConfig);
307
+ return this.transformResponse(response);
308
+ }
309
+
310
+ /**
311
+ * Perform a generic HTTP request with automatic retry
312
+ */
313
+ async request<T = any>(
314
+ method: HttpMethod,
315
+ url: string,
316
+ data?: any,
317
+ config?: ApiRequestConfig & { retries?: number; retryDelay?: number }
318
+ ): Promise<ApiResponse<T>> {
319
+ const retries = config?.retries ?? 0;
320
+ const retryDelay = config?.retryDelay ?? 1000;
321
+
322
+ let lastError: ApiError | null = null;
323
+
324
+ for (let attempt = 0; attempt <= retries; attempt++) {
325
+ try {
326
+ switch (method) {
327
+ case 'GET':
328
+ return await this.get<T>(url, config);
329
+ case 'POST':
330
+ return await this.post<T>(url, data, config);
331
+ case 'PUT':
332
+ return await this.put<T>(url, data, config);
333
+ case 'PATCH':
334
+ return await this.patch<T>(url, data, config);
335
+ case 'DELETE':
336
+ return await this.delete<T>(url, config);
337
+ default:
338
+ throw new Error(`Unsupported HTTP method: ${method}`);
339
+ }
340
+ } catch (error: any) {
341
+ lastError = error as ApiError;
342
+
343
+ if (attempt < retries) {
344
+ // Exponential backoff
345
+ await new Promise(resolve => setTimeout(resolve, retryDelay * Math.pow(2, attempt)));
346
+ }
347
+ }
348
+ }
349
+
350
+ throw lastError;
351
+ }
352
+ }
353
+
354
+ // Singleton instance
355
+ export const apiAxiosService = new ApiAxiosService();