@alba-cars/common-modules 3.0.0-alpha → 3.0.0-alpha.1

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.
@@ -0,0 +1,749 @@
1
+ // src/core/enums/HttpMethods.ts
2
+ var HttpMethods = {
3
+ OPTIONS: "OPTIONS",
4
+ GET: "GET",
5
+ POST: "POST",
6
+ PUT: "PUT",
7
+ PATCH: "PATCH",
8
+ DELETE: "DELETE",
9
+ HEAD: "HEAD",
10
+ CONNECT: "CONNECT",
11
+ TRACE: "TRACE"
12
+ };
13
+
14
+ // src/core/enums/HttpStatusCodes.ts
15
+ var HttpStatusCodes = {
16
+ OK: 200,
17
+ CREATED: 201,
18
+ ACCEPTED: 202,
19
+ NO_CONTENT: 204,
20
+ BAD_REQUEST: 400,
21
+ UNAUTHORIZED: 401,
22
+ FORBIDDEN: 403,
23
+ NOT_FOUND: 404,
24
+ METHOD_NOT_ALLOWED: 405,
25
+ INTERNAL_SERVER_ERROR: 500,
26
+ NOT_IMPLEMENTED: 501,
27
+ BAD_GATEWAY: 502,
28
+ SERVICE_UNAVAILABLE: 503,
29
+ GATEWAY_TIMEOUT: 504
30
+ };
31
+
32
+ // src/core/error-handling/AppError.ts
33
+ var ErrorType = /* @__PURE__ */ ((ErrorType2) => {
34
+ ErrorType2["VALIDATION_ERROR"] = "VALIDATION_ERROR";
35
+ ErrorType2["NOT_FOUND"] = "NOT_FOUND";
36
+ ErrorType2["UNAUTHORIZED"] = "UNAUTHORIZED";
37
+ ErrorType2["FORBIDDEN"] = "FORBIDDEN";
38
+ ErrorType2["INTERNAL_SERVER_ERROR"] = "INTERNAL_SERVER_ERROR";
39
+ ErrorType2["BAD_REQUEST"] = "BAD_REQUEST";
40
+ ErrorType2["AUTHENTICATION_ERROR"] = "AUTHENTICATION_ERROR";
41
+ ErrorType2["AUTHORIZATION_ERROR"] = "AUTHORIZATION_ERROR";
42
+ return ErrorType2;
43
+ })(ErrorType || {});
44
+ var AppError = class _AppError extends Error {
45
+ constructor(message, statusCode, type, details) {
46
+ super(message);
47
+ this.message = message;
48
+ this.statusCode = statusCode;
49
+ this.type = type;
50
+ this.details = details;
51
+ this.statusCode = statusCode;
52
+ this.type = type;
53
+ this.details = details;
54
+ this.name = this.constructor.name;
55
+ Error.captureStackTrace(this, this.constructor);
56
+ }
57
+ static badRequest(message, details) {
58
+ return new _AppError(message, 400, "BAD_REQUEST" /* BAD_REQUEST */, details);
59
+ }
60
+ static notFound(message, details) {
61
+ return new _AppError(message, 404, "NOT_FOUND" /* NOT_FOUND */, details);
62
+ }
63
+ static unauthorized(message, details) {
64
+ return new _AppError(message, 401, "UNAUTHORIZED" /* UNAUTHORIZED */, details);
65
+ }
66
+ static forbidden(message, details) {
67
+ return new _AppError(message, 403, "FORBIDDEN" /* FORBIDDEN */, details);
68
+ }
69
+ static internal(message, details) {
70
+ return new _AppError(message, 500, "INTERNAL_SERVER_ERROR" /* INTERNAL_SERVER_ERROR */, details);
71
+ }
72
+ static validationError(message, details) {
73
+ return new _AppError(message, 422, "VALIDATION_ERROR" /* VALIDATION_ERROR */, details);
74
+ }
75
+ };
76
+
77
+ // src/core/network/endpoint-config.ts
78
+ var API_ENDPOINTS = {
79
+ vehicle: {
80
+ getAll: `/vehicle`,
81
+ create: `/vehicle`,
82
+ getOne: (id) => `/vehicle/${id}`,
83
+ getOneBySlug: (slug) => `/vehicle/slug/${slug}`,
84
+ getOneByRef: (ref) => `/vehicle/ref/${ref}`,
85
+ getSimilar: (id) => `/vehicle/similar/${id}`,
86
+ deleteOne: (id) => `/vehicle/${id}`,
87
+ updateOne: (id) => `/vehicle/${id}`,
88
+ publishVehicle: (id) => `/vehicle/publish/${id}`,
89
+ unpublishVehicle: (id) => `/vehicle/unpublish/${id}`,
90
+ reserveVehicle: (id) => `/vehicle/reserve/${id}`,
91
+ selfReserveVehicle: (id) => `/vehicle/self-reserve/${id}`,
92
+ markVehicleSold: (id) => `/vehicle/mark-vehicle-sold/${id}`,
93
+ markVehicleDraft: (id) => `/vehicle/mark-vehicle-draft/${id}`
94
+ },
95
+ vehicleFinance: {
96
+ getAll: `/vehicle-finance`,
97
+ create: `/vehicle-finance`,
98
+ getOne: (id) => `/vehicle-finance/${id}`,
99
+ deleteOne: (id) => `/vehicle-finance/${id}`,
100
+ updateOne: (id) => `/vehicle-finance/${id}`
101
+ },
102
+ vehicleMake: {
103
+ getAll: `/vehicle/makes`,
104
+ create: `/vehicle/makes`,
105
+ getOne: (id) => `/vehicle/makes/${id}`,
106
+ getOneBySlug: (slug) => `/vehicle/makes/slug/${slug}`,
107
+ deleteOne: (id) => `/vehicle/makes/${id}`,
108
+ updateOne: (id) => `/vehicle/makes/${id}`
109
+ },
110
+ vehicleFeatures: {
111
+ getAll: `/vehicle/features`,
112
+ create: `/vehicle/features`,
113
+ getOne: (id) => `/vehicle/features/${id}`,
114
+ deleteOne: (id) => `/vehicle/features/${id}`,
115
+ updateOne: (id) => `/vehicle/features/${id}`,
116
+ changeIcon: (id) => `/vehicle/features/${id}/icon`
117
+ },
118
+ vehicleFeatureCategories: {
119
+ getAll: `/vehicle/feature-categories`,
120
+ create: `/vehicle/feature-categories`,
121
+ getOne: (id) => `/vehicle/feature-categories/${id}`,
122
+ deleteOne: (id) => `/vehicle/feature-categories/${id}`,
123
+ updateOne: (id) => `/vehicle/feature-categories/${id}`
124
+ },
125
+ vehicleModel: {
126
+ getAll: `/vehicle/models`,
127
+ create: `/vehicle/models`,
128
+ getOne: (id) => `/vehicle/models/${id}`,
129
+ deleteOne: (id) => `/vehicle/models/${id}`,
130
+ updateOne: (id) => `/vehicle/models/${id}`
131
+ },
132
+ vehicleMeta: {
133
+ getAll: `/vehicle-meta-data`,
134
+ create: `/vehicle-meta-data`,
135
+ getOne: (id) => `/vehicle-meta-data/${id}`,
136
+ deleteOne: (id) => `/vehicle-meta-data/${id}`,
137
+ updateOne: (id) => `/vehicle-meta-data/${id}`,
138
+ aiGenerateTitle: (id) => `/vehicle-meta-data/generate/title/${id}`,
139
+ aiGenerateDescription: (id) => `/vehicle-meta-data/generate/description/${id}`,
140
+ aiGenerateKeyword: (id) => `/vehicle-meta-data/generate/keywords/${id}`,
141
+ aiGenerateVehicleDescription: (id) => `/vehicle-meta-data/generate/vehicle-description/${id}`
142
+ },
143
+ TestDrive: {
144
+ getAll: `/test-drive-requests`,
145
+ create: `/test-drive-requests`,
146
+ getOne: (id) => `/test-drive-requests/${id}`,
147
+ deleteOne: (id) => `/test-drive-requests/${id}`,
148
+ updateOne: (id) => `/test-drive-requests/${id}`
149
+ },
150
+ vehicleOrder: {
151
+ getAll: `/vehicle-order`,
152
+ create: `/vehicle-order`,
153
+ getOne: (id) => `/vehicle-order/${id}`,
154
+ deleteOne: (id) => `/vehicle-order/${id}`,
155
+ updateOne: (id) => `/vehicle-order/${id}`
156
+ },
157
+ vehicleType: {
158
+ getAll: `/vehicle/body-types`,
159
+ create: `/vehicle/body-types`,
160
+ getOne: (id) => `/vehicle/body-types/${id}`,
161
+ deleteOne: (id) => `/vehicle/body-types/${id}`,
162
+ updateOne: (id) => `/vehicle/body-types/${id}`
163
+ },
164
+ vehicleInspection: {
165
+ getAll: `/vehicle-inspection`,
166
+ create: `/vehicle-inspection`,
167
+ getOne: (id) => `/vehicle-inspection/${id}`,
168
+ deleteOne: (id) => `/vehicle-inspection/${id}`,
169
+ updateOne: (id) => `/vehicle-inspection/${id}`
170
+ },
171
+ payment: {
172
+ getAll: `/payment`,
173
+ create: `/payment`,
174
+ getOne: (id) => `/payment/${id}`,
175
+ deleteOne: (id) => `/payment/${id}`,
176
+ updateOne: (id) => `/payment/${id}`
177
+ },
178
+ deposit: {
179
+ getAll: `/deposits`,
180
+ create: `/deposits`,
181
+ getOne: (id) => `/deposits/${id}`,
182
+ deleteOne: (id) => `/deposits/${id}`,
183
+ updateOne: (id) => `/deposits/${id}`,
184
+ initiateRefund: `/deposits/refund/`,
185
+ getOrCreateUserInformation: `/deposits/user-info`
186
+ },
187
+ leads: {
188
+ getAll: `/leads`,
189
+ create: `/leads`,
190
+ getOne: (id) => `/leads/${id}`,
191
+ deleteOne: (id) => `/leads/${id}`,
192
+ updateOne: (id) => `/leads/${id}`
193
+ },
194
+ leadPreferences: {
195
+ getAll: `/leads-preferences`,
196
+ create: `/leads-preferences`,
197
+ getOne: (id) => `/leads-preferences/${id}`,
198
+ deleteOne: (id) => `/leads-preferences/${id}`,
199
+ updateOne: (id) => `/leads-preferences/${id}`
200
+ },
201
+ agents: {
202
+ getAll: `/salesagent`,
203
+ create: `/salesagent`,
204
+ getOne: (id) => `/salesagent/${id}`,
205
+ deleteOne: (id) => `/salesagent/${id}`,
206
+ updateOne: (id) => `/salesagent/${id}`
207
+ },
208
+ blogs: {
209
+ getAll: `/blog`,
210
+ create: `/blog`,
211
+ getOne: (id) => `/blog/${id}`,
212
+ getOneBySlug: (slug) => `/blog/slug/${slug}`,
213
+ deleteOne: (id) => `/blog/${id}`,
214
+ updateOne: (id) => `/blog/${id}`
215
+ },
216
+ showroomVisit: {
217
+ getAll: `/showroomvisit`,
218
+ create: `/showroomvisit`,
219
+ getOne: (id) => `/showroomvisit/${id}`,
220
+ deleteOne: (id) => `/showroomvisit/${id}`,
221
+ updateOne: (id) => `/showroomvisit/${id}`
222
+ },
223
+ sellCarRequest: {
224
+ getAll: `/sell-car-request`,
225
+ create: `/sell-car-request`,
226
+ getOne: (id) => `/sell-car-request/${id}`,
227
+ deleteOne: (id) => `/sell-car-request/${id}`,
228
+ updateOne: (id) => `/sell-car-request/${id}`,
229
+ notifyAboutExistingLead: `/sell-car-request/notify`
230
+ },
231
+ financeEligibilityRequest: {
232
+ getAll: `/finance-eligibility-request`,
233
+ create: `/finance-eligibility-request`,
234
+ getOne: (id) => `/finance-eligibility-request/${id}`,
235
+ deleteOne: (id) => `/finance-eligibility-request/${id}`,
236
+ updateOne: (id) => `/finance-eligibility-request/${id}`,
237
+ updateStatus: (id) => `/finance-eligibility-request/${id}/status`
238
+ },
239
+ vehicleReservations: {
240
+ getAll: `/vehicle-reservation`,
241
+ create: `/vehicle-reservation`,
242
+ getOne: (id) => `/vehicle-reservation/${id}`,
243
+ deleteOne: (id) => `/vehicle-reservation/${id}`,
244
+ updateOne: (id) => `/vehicle-reservation/${id}`
245
+ },
246
+ languages: {
247
+ getAll: `/languages`,
248
+ create: `/languages`,
249
+ getOne: (id) => `/languages/${id}`,
250
+ deleteOne: (id) => `/languages/${id}`,
251
+ updateOne: (id) => `/languages/${id}`
252
+ },
253
+ user: {
254
+ getAll: `/user`,
255
+ create: `/user`,
256
+ getOne: (id) => `/user/${id}`,
257
+ deleteOne: (id) => `/user/${id}`,
258
+ updateOne: (id) => `/user/${id}`,
259
+ changeProfilePicture: (id) => `/user/${id}/profile-pic`,
260
+ deleteProfilePicture: (id) => `/user/${id}/profile-pic`
261
+ },
262
+ googleReview: {
263
+ getAll: `/google-reviews`,
264
+ create: `/google-reviews`,
265
+ getOne: (id) => `/google-reviews/${id}`,
266
+ deleteOne: (id) => `/google-reviews/${id}`,
267
+ updateOne: (id) => `/google-reviews/${id}`,
268
+ changeReviewShowPublic: (id) => `/google-reviews/show-public/${id}`
269
+ },
270
+ tickets: {
271
+ getAll: `/tickets`,
272
+ create: `/tickets`,
273
+ getOne: (id) => `/tickets/${id}`,
274
+ deleteOne: (id) => `/tickets/${id}`,
275
+ updateOne: (id) => `/tickets/${id}`,
276
+ getMyTickets: `/tickets/my`,
277
+ getUserTickets: (userId) => `/tickets/user/${userId}`,
278
+ getAgentTickets: (userId) => `/tickets/agent/${userId}`,
279
+ addMessage: (ticketId) => `/tickets/${ticketId}/messages`,
280
+ addDocument: (ticketId) => `/tickets/${ticketId}/documents`,
281
+ getDocuments: (ticketId) => `/tickets/${ticketId}/documents`,
282
+ reopenTicket: (ticketId) => `/tickets/${ticketId}/reopen`,
283
+ sendToKissFlow: `/tickets/kissflow`
284
+ },
285
+ faq: {
286
+ getAll: `/faqs`,
287
+ create: `/faqs`,
288
+ getOne: (id) => `/faqs/${id}`,
289
+ deleteOne: (id) => `/faqs/${id}`,
290
+ updateOne: (id) => `/faqs/${id}`
291
+ },
292
+ dealDrive: {
293
+ getAll: `/deal-drive`,
294
+ create: `/deal-drive`,
295
+ getOne: (id) => `/deal-drive/${id}`,
296
+ deleteOne: (id) => `/deal-drive/${id}`,
297
+ updateOne: (id) => `/deal-drive/${id}`,
298
+ getAllMakes: (id) => `/deal-drive/brands`,
299
+ getAllModels: (id) => `/deal-drive/models`
300
+ },
301
+ bankValuationRequest: {
302
+ getAll: `/bank-valuation-request`,
303
+ create: `/bank-valuation-request`,
304
+ getOne: (id) => `/bank-valuation-request/${id}`,
305
+ deleteOne: (id) => `/bank-valuation-request/${id}`,
306
+ updateOne: (id) => `/bank-valuation-request/${id}`,
307
+ // uses PUT
308
+ updateStatus: (id) => `/bank-valuation-request/${id}`,
309
+ // uses PATCH
310
+ approveValuation: (id) => `/bank-valuation-request/approve/${id}`,
311
+ rejectValuation: (id) => `/bank-valuation-request/reject/${id}`,
312
+ overridePayment: (id) => `/bank-valuation-request/${id}/override-payment`,
313
+ estimate: `/bank-valuation-request/estimate`,
314
+ rangeEstimate: `/bank-valuation-request/range-estimate`,
315
+ getStats: `/bank-valuation-request/stats`,
316
+ notifyAboutExistingLead: `/bank-valuation-request/notify`,
317
+ getCertificateEditableData: (id) => `/bank-valuation-request/${id}/certificates/issue/edit-data`,
318
+ previewCertificatePdf: (id) => `/bank-valuation-request/${id}/certificates/issue/preview`,
319
+ reissueCertificate: (id) => `/bank-valuation-request/${id}/certificates/issue`,
320
+ getRequestStatus: (id) => `/bank-valuation-request/${id}/status`,
321
+ checkRequestIsIncomplete: (id) => `/bank-valuation-request/${id}/status/incomplete`,
322
+ sendContinuationReminder: (id) => `/bank-valuation-request/${id}/send-continuation-reminder`
323
+ },
324
+ exchangeCarRequest: {
325
+ create: `/exchange-car-request`,
326
+ getAll: `/exchange-car-request/list`,
327
+ getOne: (id) => `/exchange-car-request/${id}`,
328
+ deleteOne: (id) => `/exchange-car-request/${id}`,
329
+ updateOne: (id) => `/exchange-car-request/${id}`
330
+ },
331
+ dubiCars: {
332
+ getAdByDubiCarsId: (id) => `/dubicars/${id}`,
333
+ checkVehicleAdStatus: (vehicleId) => `/dubicars/status/${vehicleId}`,
334
+ getAvailableModelsForMake: (make) => `/dubicars/${make}/models`,
335
+ postAd: `/dubicars`,
336
+ deleteAd: (adId) => `/dubicars/${adId}`,
337
+ deleteAdByVehicleId: (vehicleId) => `/dubicars/vehicle/${vehicleId}`,
338
+ doAction: (action) => `/dubicars/${action}`
339
+ },
340
+ colors: {
341
+ getAll: `/colors`,
342
+ list: `/colors/list`,
343
+ // meant to be used without pagination
344
+ create: `/colors`,
345
+ getOne: (id) => `/colors/${id}`,
346
+ deleteOne: (id) => `/colors/${id}`,
347
+ updateOne: (id) => `/colors/${id}`,
348
+ getBySlug: (slug) => `/colors/slug/${slug}`
349
+ },
350
+ bankValuationResult: {
351
+ getAll: `/bank-valuation-results`,
352
+ create: `/bank-valuation-results`,
353
+ getOne: (id) => `/bank-valuation-results/${id}`,
354
+ deleteOne: (id) => `/bank-valuation-results/${id}`,
355
+ updateOne: (id) => `/bank-valuation-results/${id}`
356
+ },
357
+ bank: {
358
+ getAll: `/partnered-banks`,
359
+ create: `/partnered-banks`,
360
+ getOne: (idOrSlug) => `/partnered-banks/${idOrSlug}`,
361
+ deleteOne: (idOrSlug) => `/partnered-banks/${idOrSlug}`,
362
+ updateOne: (idOrSlug) => `/partnered-banks/${idOrSlug}`
363
+ }
364
+ };
365
+ var utilRoutePrefix = "/utils";
366
+ var UTIL_ENDPOINTS = {
367
+ media: {
368
+ createS3Url: `${utilRoutePrefix}/get-upload-url`,
369
+ preprocessMediaUrl: `${utilRoutePrefix}/process-media`,
370
+ removeS3Media: `${utilRoutePrefix}/remove-s3`,
371
+ removeVehicleMedia: `${utilRoutePrefix}/remove-vehcile-media`,
372
+ removeByIdentifier: `${utilRoutePrefix}/remove-by-identifier`,
373
+ compressImage: `${utilRoutePrefix}/compress-image`
374
+ }
375
+ };
376
+ var authRoutePrefix = "/auth";
377
+ var AUTH_ENDPOINTS = {
378
+ login: `${authRoutePrefix}/login`,
379
+ register: `${authRoutePrefix}/register`,
380
+ refreshAccessToken: `${authRoutePrefix}/refresh-token`,
381
+ sendPhoneVerificationCode: `${authRoutePrefix}/phone/send-verification`,
382
+ verifyPhoneAndLogin: `${authRoutePrefix}/phone/verify-and-login`,
383
+ verifyAnyPhoneNumber: `${authRoutePrefix}/phone/verify`,
384
+ checkPhoneNumberExists: `${authRoutePrefix}/phone/check`
385
+ };
386
+
387
+ // src/core/network/fetch-api.ts
388
+ import qs from "qs";
389
+
390
+ // src/core/utils/global-utils.ts
391
+ var deepEqual = (obj1, obj2) => {
392
+ if (obj1 === obj2) {
393
+ return true;
394
+ }
395
+ if (typeof obj1 !== "object" || obj1 === null || typeof obj2 !== "object" || obj2 === null) {
396
+ return false;
397
+ }
398
+ const keys1 = Object.keys(obj1);
399
+ const keys2 = Object.keys(obj2);
400
+ if (keys1.length !== keys2.length) {
401
+ return false;
402
+ }
403
+ for (const key of keys1) {
404
+ if (!keys2.includes(key)) {
405
+ return false;
406
+ }
407
+ }
408
+ for (const key of keys1) {
409
+ const value1 = obj1[key];
410
+ const value2 = obj2[key];
411
+ if (!deepEqual(value1, value2)) {
412
+ return false;
413
+ }
414
+ }
415
+ return true;
416
+ };
417
+ var isPlainObject = (obj) => typeof obj === "object" && obj !== null && !Array.isArray(obj);
418
+ var isFunction = (value) => typeof value === "function";
419
+ var sortBy = (array, key) => {
420
+ const compareFn = typeof key === "function" ? key : (a, b) => a[key] - b[key];
421
+ return array.slice().sort(compareFn);
422
+ };
423
+ function generateRandomBase64(length) {
424
+ const randomBytes = new Uint8Array(length);
425
+ crypto.getRandomValues(randomBytes);
426
+ return btoa(String.fromCharCode(...Array.from(randomBytes)));
427
+ }
428
+ var formatValue = (n) => {
429
+ return Number(n).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
430
+ };
431
+ var timeAsMilliseconds = ({ minutes = 0, hours = 0, seconds = 0 }) => {
432
+ return minutes * 60 * 1e3 + hours * 60 * 60 * 1e3 + seconds * 1e3;
433
+ };
434
+ var timeAsSeconds = ({ minutes = 0, hours = 0, seconds = 0 }) => {
435
+ return minutes * 60 + hours * 60 * 60 + seconds;
436
+ };
437
+ function removeKeyFromObject(obj, keyToRemove) {
438
+ if (Array.isArray(obj)) {
439
+ return obj.map((item) => removeKeyFromObject(item, keyToRemove));
440
+ } else if (typeof obj === "object" && obj !== null) {
441
+ return Object.keys(obj).reduce((acc, key) => {
442
+ if (key !== keyToRemove) {
443
+ acc[key] = removeKeyFromObject(obj[key], keyToRemove);
444
+ }
445
+ return acc;
446
+ }, {});
447
+ }
448
+ return obj;
449
+ }
450
+ var currencyFormatter = ({ isDecimal, decimalPlaces = 2 }) => new Intl.NumberFormat(
451
+ "en-US",
452
+ {
453
+ style: "currency",
454
+ currency: "AED",
455
+ maximumFractionDigits: isDecimal ? decimalPlaces : 0
456
+ }
457
+ );
458
+ var safeParseNumber = (value) => {
459
+ if (typeof value === "number") return value;
460
+ if (typeof value !== "string") return 0;
461
+ return Number(value.trim().replace(/,/g, "")) || 0;
462
+ };
463
+ var formatNumberWithCommas = (value) => {
464
+ const number = value.replace(/[^\d]/g, "");
465
+ return number.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
466
+ };
467
+ var makeArray = (value) => {
468
+ return Array.isArray(value) ? value : [value];
469
+ };
470
+ var isEmpty = (value) => value === null || value === void 0 || value === "";
471
+ var isEmptyObject = (value) => Object.keys(value).length === 0 && value.constructor === Object;
472
+ var isEmptyArray = (value) => Array.isArray(value) && value.length === 0;
473
+ var hasValue = (value) => !isEmpty(value) && !isEmptyObject(value) && !isEmptyArray(value);
474
+ var getPlural = (value, singular, plural = null) => value === 1 ? `${value} ${singular}` : plural ? `${value} ${plural}` : `${value} ${singular}s`;
475
+ var sanitizeRegexString = (input) => input.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
476
+ var toPlainObject = (value) => JSON.parse(JSON.stringify(value));
477
+ var booleanize = (value) => [true, "true", "1"].includes(value) ? true : false;
478
+
479
+ // src/core/utils/global-constants.ts
480
+ var ONE_MINUTE_MILLIS = 1e3 * 60;
481
+ var ONE_HOUR_MILLIS = 1e3 * 60 * 60;
482
+ var FIFTEEN_MINUTES_MILLIS = 15 * 60 * 1e3;
483
+ var THIRTY_MINUTES_MILLIS = 30 * 60 * 1e3;
484
+ var ONE_HOUR = 3600;
485
+ var ONE_MINUTE = 60;
486
+
487
+ // src/core/utils/global_validators.ts
488
+ var validateChassisNumber = (value) => {
489
+ const chassisRegex = /^[A-HJ-NPR-Z0-9]{15,20}$/;
490
+ if (!chassisRegex.test(value)) {
491
+ return "Invalid Chassis Number";
492
+ }
493
+ return true;
494
+ };
495
+ var validateVIN = (value) => {
496
+ const vinRegex = /^[A-HJ-NPR-Z0-9]{8}$/;
497
+ if (!vinRegex.test(value)) {
498
+ return "Invalid VIN format";
499
+ }
500
+ return true;
501
+ };
502
+
503
+ // src/core/utils/formatCurrency.ts
504
+ var formatCurrency = (amount, options = {}) => {
505
+ if (amount == null) return "N/A";
506
+ const {
507
+ currency = "AED",
508
+ minimumFractionDigits = 0,
509
+ maximumFractionDigits = 0
510
+ } = options;
511
+ try {
512
+ const formatter = new Intl.NumberFormat("en-US", {
513
+ minimumFractionDigits,
514
+ maximumFractionDigits,
515
+ useGrouping: true
516
+ });
517
+ const formattedAmount = formatter.format(amount);
518
+ return `AED ${formattedAmount}`;
519
+ } catch (error) {
520
+ console.warn("Currency formatting failed, using basic formatting", error);
521
+ const baseFormatted = amount.toLocaleString("en-US", {
522
+ minimumFractionDigits,
523
+ maximumFractionDigits
524
+ });
525
+ return `AED ${baseFormatted}`;
526
+ }
527
+ };
528
+
529
+ // src/core/network/fetch-api.ts
530
+ var BASE_URL = process.env.NEXT_PUBLIC_API_URL;
531
+ var DEFAULT_TIMEOUT = timeAsMilliseconds({ seconds: 30 });
532
+ var InterceptorManager = class {
533
+ constructor() {
534
+ this.requestInterceptors = [];
535
+ this.responseInterceptors = [];
536
+ this.responseErrorInterceptors = [];
537
+ }
538
+ addRequestInterceptor(interceptor) {
539
+ return this.requestInterceptors.push(interceptor) - 1;
540
+ }
541
+ addResponseInterceptor(interceptor) {
542
+ return this.responseInterceptors.push(interceptor) - 1;
543
+ }
544
+ addResponseErrorInterceptor(interceptor) {
545
+ return this.responseErrorInterceptors.push(interceptor) - 1;
546
+ }
547
+ removeRequestInterceptor(index) {
548
+ if (index >= 0) {
549
+ this.requestInterceptors.splice(index, 1);
550
+ }
551
+ }
552
+ removeResponseInterceptor(index) {
553
+ if (index >= 0) {
554
+ this.responseInterceptors.splice(index, 1);
555
+ }
556
+ }
557
+ removeResponseErrorInterceptor(index) {
558
+ if (index >= 0) {
559
+ this.responseErrorInterceptors.splice(index, 1);
560
+ }
561
+ }
562
+ clearRequestInterceptors() {
563
+ this.requestInterceptors = [];
564
+ }
565
+ clearResponseInterceptors() {
566
+ this.responseInterceptors = [];
567
+ }
568
+ clearResponseErrorInterceptors() {
569
+ this.responseErrorInterceptors = [];
570
+ }
571
+ clearAllInterceptors() {
572
+ this.clearRequestInterceptors();
573
+ this.clearResponseInterceptors();
574
+ this.clearResponseErrorInterceptors();
575
+ }
576
+ async applyRequestInterceptors(config) {
577
+ let modifiedConfig = { ...config };
578
+ for (const interceptor of this.requestInterceptors) {
579
+ modifiedConfig = await interceptor(modifiedConfig);
580
+ }
581
+ return modifiedConfig;
582
+ }
583
+ async applyResponseInterceptors(response, requestConfig) {
584
+ let modifiedResponse = response;
585
+ for (const interceptor of this.responseInterceptors) {
586
+ modifiedResponse = await interceptor(modifiedResponse, requestConfig);
587
+ }
588
+ return modifiedResponse;
589
+ }
590
+ async applyResponseErrorInterceptors(error, requestConfig) {
591
+ let promise = Promise.reject(error);
592
+ for (const interceptor of this.responseErrorInterceptors) {
593
+ promise = promise.catch(
594
+ (currentError) => interceptor(currentError, requestConfig)
595
+ );
596
+ }
597
+ return promise;
598
+ }
599
+ async retryRequest(config) {
600
+ const retryConfig = {
601
+ ...config,
602
+ options: {
603
+ ...config.options,
604
+ isRetry: true
605
+ }
606
+ };
607
+ try {
608
+ const interceptedConfig = await this.applyRequestInterceptors(retryConfig);
609
+ const response = await fetch(interceptedConfig.url, interceptedConfig);
610
+ const interceptedResponse = await this.applyResponseInterceptors(
611
+ response,
612
+ interceptedConfig
613
+ );
614
+ const contentType = interceptedResponse.headers.get("content-type");
615
+ const responseData = (contentType == null ? void 0 : contentType.includes("application/json")) ? await interceptedResponse.json() : await interceptedResponse.text();
616
+ if (interceptedResponse.ok) {
617
+ return responseData;
618
+ }
619
+ const apiError = createApiError(interceptedResponse.status, responseData);
620
+ throw apiError;
621
+ } catch (error) {
622
+ if (config.options.isRetry) {
623
+ throw error;
624
+ }
625
+ return this.applyResponseErrorInterceptors(error, retryConfig);
626
+ }
627
+ }
628
+ };
629
+ var interceptors = new InterceptorManager();
630
+ var buildUrl = (endpoint, query) => {
631
+ let url = `${BASE_URL}${endpoint}`;
632
+ if (query && Object.keys(query).length > 0) {
633
+ url += `?${qs.stringify(query, {
634
+ allowDots: true,
635
+ arrayFormat: "brackets",
636
+ allowEmptyArrays: false,
637
+ skipNulls: true
638
+ })}`;
639
+ }
640
+ return url;
641
+ };
642
+ async function apiRequest(endpoint, options = {}) {
643
+ var _a;
644
+ let timeoutId;
645
+ const controller = options.timeout ? new AbortController() : void 0;
646
+ if (options.timeout && controller) {
647
+ timeoutId = setTimeout(() => {
648
+ controller.abort("Request timeout");
649
+ }, options.timeout || DEFAULT_TIMEOUT);
650
+ }
651
+ const signal = options.signal || (controller == null ? void 0 : controller.signal);
652
+ const headers = {
653
+ Accept: "application/json",
654
+ "Content-Type": "application/json",
655
+ ...options.headers
656
+ };
657
+ const config = {
658
+ method: (_a = options.method) != null ? _a : HttpMethods.GET,
659
+ headers,
660
+ ...signal && { signal },
661
+ ...options,
662
+ options
663
+ // Keep a reference to the original options
664
+ };
665
+ try {
666
+ const response = await makeRequest(endpoint, config);
667
+ return response;
668
+ } finally {
669
+ if (timeoutId) {
670
+ clearTimeout(timeoutId);
671
+ }
672
+ }
673
+ }
674
+ async function makeRequest(endpoint, config) {
675
+ const url = buildUrl(endpoint, config.options.query);
676
+ let requestConfig = await interceptors.applyRequestInterceptors({
677
+ ...config,
678
+ url
679
+ });
680
+ const interceptedUrl = requestConfig.url;
681
+ try {
682
+ const response = await fetch(interceptedUrl, requestConfig);
683
+ const interceptedResponse = await interceptors.applyResponseInterceptors(
684
+ response,
685
+ { ...requestConfig, url: interceptedUrl }
686
+ );
687
+ const contentType = interceptedResponse.headers.get("content-type");
688
+ const responseData = (contentType == null ? void 0 : contentType.includes("application/json")) ? await interceptedResponse.json() : await interceptedResponse.text();
689
+ if (interceptedResponse.ok) {
690
+ return responseData;
691
+ }
692
+ const apiError = createApiError(interceptedResponse.status, responseData);
693
+ throw apiError;
694
+ } catch (error) {
695
+ return interceptors.applyResponseErrorInterceptors(error, {
696
+ ...requestConfig,
697
+ url: interceptedUrl
698
+ });
699
+ }
700
+ }
701
+ function createApiError(status, responseData) {
702
+ const error = new Error(
703
+ typeof responseData === "object" ? responseData.message || "API Error" : "API Error"
704
+ );
705
+ error.status = status;
706
+ error.data = responseData;
707
+ return error;
708
+ }
709
+ export {
710
+ API_ENDPOINTS,
711
+ AUTH_ENDPOINTS,
712
+ AppError,
713
+ ErrorType,
714
+ FIFTEEN_MINUTES_MILLIS,
715
+ HttpMethods,
716
+ HttpStatusCodes,
717
+ ONE_HOUR,
718
+ ONE_HOUR_MILLIS,
719
+ ONE_MINUTE,
720
+ ONE_MINUTE_MILLIS,
721
+ THIRTY_MINUTES_MILLIS,
722
+ UTIL_ENDPOINTS,
723
+ apiRequest,
724
+ booleanize,
725
+ currencyFormatter,
726
+ deepEqual,
727
+ formatCurrency,
728
+ formatNumberWithCommas,
729
+ formatValue,
730
+ generateRandomBase64,
731
+ getPlural,
732
+ hasValue,
733
+ interceptors,
734
+ isEmpty,
735
+ isEmptyArray,
736
+ isEmptyObject,
737
+ isFunction,
738
+ isPlainObject,
739
+ makeArray,
740
+ removeKeyFromObject,
741
+ safeParseNumber,
742
+ sanitizeRegexString,
743
+ sortBy,
744
+ timeAsMilliseconds,
745
+ timeAsSeconds,
746
+ toPlainObject,
747
+ validateChassisNumber,
748
+ validateVIN
749
+ };