@xeno-js/shared 2.0.0 → 3.0.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.
@@ -0,0 +1,2402 @@
1
+ // src/shared/constants/concurrency.constants.ts
2
+ var DEFAULT_CONCURRENCY = Object.freeze({
3
+ /**
4
+ * @description Number of maximum retry attempts for handling concurrency conflicts in the pipeline. If the number of attempts exceeds this value, the pipeline will return a failed Result with an AppError indicating that the maximum retry attempts have been exceeded due to concurrency conflicts.
5
+
6
+ *
7
+ * @author Xeno
8
+ * @version 1.0.0
9
+ * @since 2025-09-30
10
+ * @link https://github.com/xeno-js/xeno-js
11
+ */
12
+ MAX_RETRIES: 3,
13
+ /**
14
+ * @description Base delay in milliseconds for retrying a request after a concurrency conflict is detected. The actual delay will be calculated using an exponential backoff strategy with added jitter to prevent thundering herd problems when multiple requests are retried simultaneously.
15
+
16
+ *
17
+ * @author Xeno
18
+ * @version 1.0.0
19
+ * @since 2025-09-30
20
+ * @link https://github.com/xeno-js/xeno-js
21
+ */
22
+ BASE_DELAY: 20,
23
+ /**
24
+ * @description Maximum jitter in milliseconds to be added to the base delay when retrying a request after a concurrency conflict is detected. This helps to randomize the retry attempts and reduce the likelihood of multiple requests being retried at the same time, which can lead to further conflicts. The actual delay for each retry will be calculated as baseDelayMs * (2 ** attempt) + randomJitter, where randomJitter is a random value between 0 and maxJitterMs.
25
+
26
+ *
27
+ * @author Xeno
28
+ * @version 1.0.0
29
+ * @since 2025-09-30
30
+ * @link https://github.com/xeno-js/xeno-js
31
+ */
32
+ MAX_JITTER: 30
33
+ });
34
+
35
+ // src/shared/constants/error.constants.ts
36
+ var ERROR_CODES = Object.freeze({
37
+ // ── Generic / System ─────────────────────────────────────────────────────
38
+ /** @description Unclassified or unexpected infrastructure-level failure.
39
+ *
40
+ * @author Xeno
41
+ * @version 1.0.0
42
+ * @since 2025-09-30
43
+ * @link https://github.com/xeno-js/xeno-js
44
+ */
45
+ SYSTEM_ERROR: "SYSTEM_ERROR",
46
+ /** @description An operation that has not yet been implemented was invoked.
47
+ *
48
+ * @author Xeno
49
+ * @version 1.0.0
50
+ * @since 2025-09-30
51
+ * @link https://github.com/xeno-js/xeno-js
52
+ */
53
+ NOT_IMPLEMENTED: "NOT_IMPLEMENTED",
54
+ /** @description An external API call failed due to network issues or a 5xx response.
55
+ *
56
+ * @author Xeno
57
+ * @version 1.0.0
58
+ * @since 2025-09-30
59
+ * @link https://github.com/xeno-js/xeno-js
60
+ */
61
+ EXTERNAL_SERVICE_ERROR: "EXTERNAL_SERVICE_ERROR",
62
+ /** @description One or more input fields failed invariant or schema validation.
63
+ *
64
+ * @author Xeno
65
+ * @version 1.0.0
66
+ * @since 2025-09-30
67
+ * @link https://github.com/xeno-js/xeno-js
68
+ */
69
+ VALIDATION_FAILED: "VALIDATION_FAILED",
70
+ /** @description Authentication failed due to invalid credentials or token.
71
+ *
72
+ * @author Xeno
73
+ * @version 1.0.0
74
+ * @since 2025-09-30
75
+ * @link https://github.com/xeno-js/xeno-js
76
+ */
77
+ AUTHENTICATION_FAILED: "AUTHENTICATION_FAILED",
78
+ /** @description The caller is not authenticated.
79
+ *
80
+ * @author Xeno
81
+ * @version 1.0.0
82
+ * @since 2025-09-30
83
+ * @link https://github.com/xeno-js/xeno-js
84
+ */
85
+ UNAUTHORIZED: "UNAUTHORIZED",
86
+ /** @description The caller is authenticated but lacks the required permissions.
87
+ *
88
+ * @author Xeno
89
+ * @version 1.0.0
90
+ * @since 2025-09-30
91
+ * @link https://github.com/xeno-js/xeno-js
92
+ */
93
+ FORBIDDEN: "FORBIDDEN",
94
+ /** @description The request was well-formed but semantically invalid.
95
+ *
96
+ * @author Xeno
97
+ * @version 1.0.0
98
+ * @since 2025-09-30
99
+ * @link https://github.com/xeno-js/xeno-js
100
+ */
101
+ BAD_REQUEST: "BAD_REQUEST",
102
+ /** @description The request was aborted before it could be processed.
103
+ *
104
+ * @author Xeno
105
+ * @version 1.0.0
106
+ * @since 2025-09-30
107
+ * @link https://github.com/xeno-js/xeno-js
108
+ */
109
+ ABORTED: "ABORTED",
110
+ /** @description Required service scope is not available in the request context.
111
+ *
112
+ * @author Xeno
113
+ * @version 1.0.0
114
+ * @since 2025-09-30
115
+ * @link https://github.com/xeno-js/xeno-js
116
+ */
117
+ SCOPE_NOT_AVAILABLE: "SCOPE_NOT_AVAILABLE",
118
+ /** @description The request conflicts with the current state of the resource.
119
+ *
120
+ * @author Xeno
121
+ * @version 1.0.0
122
+ * @since 2025-09-30
123
+ * @link https://github.com/xeno-js/xeno-js
124
+ */
125
+ CONFLICT: "CONFLICT",
126
+ /** @description The requested resource does not exist.
127
+ *
128
+ * @author Xeno
129
+ * @version 1.0.0
130
+ * @since 2025-09-30
131
+ * @link https://github.com/xeno-js/xeno-js
132
+ */
133
+ NOT_FOUND: "NOT_FOUND",
134
+ /** @description No handler was found for the given request type.
135
+ *
136
+ * @author Xeno
137
+ * @version 1.0.0
138
+ * @since 2025-09-30
139
+ * @link https://github.com/xeno-js/xeno-js
140
+ */
141
+ HANDLER_NOT_FOUND: "HANDLER_NOT_FOUND",
142
+ /** @description No pipeline behavior was found for the given request type.
143
+ *
144
+ * @author Xeno
145
+ * @version 1.0.0
146
+ * @since 2025-09-30
147
+ * @link https://github.com/xeno-js/xeno-js
148
+ */
149
+ PIPELINE_NOT_AVAILABLE: "PIPELINE_NOT_AVAILABLE",
150
+ NOT_ALLOWED: "METHOD_NOT_ALLOWED",
151
+ TOO_MANY_REQUESTS: "TOO_MANY_REQUESTS"
152
+ });
153
+ var STATUS_CODES = Object.freeze({
154
+ // ── 2xx Success ───────────────────────────────────────────────────────────
155
+ /** @description The request succeeded and a response body is present.
156
+ *
157
+ * @author Xeno
158
+ * @version 1.0.0
159
+ * @since 2025-09-30
160
+ * @link https://github.com/xeno-js/xeno-js
161
+ */
162
+ OK: 200,
163
+ /** @description A new resource has been successfully created.
164
+ *
165
+ * @author Xeno
166
+ * @version 1.0.0
167
+ * @since 2025-09-30
168
+ * @link https://github.com/xeno-js/xeno-js
169
+ */
170
+ CREATED: 201,
171
+ /** @description The request succeeded but there is no response body (e.g. DELETE).
172
+ *
173
+ * @author Xeno
174
+ * @version 1.0.0
175
+ * @since 2025-09-30
176
+ * @link https://github.com/xeno-js/xeno-js
177
+ */
178
+ NO_CONTENT: 204,
179
+ // ── 4xx Client Errors ─────────────────────────────────────────────────────
180
+ /** @description The request payload is malformed or contains invalid parameters.
181
+ *
182
+ * @author Xeno
183
+ * @version 1.0.0
184
+ * @since 2025-09-30
185
+ * @link https://github.com/xeno-js/xeno-js
186
+ */
187
+ BAD_REQUEST: 400,
188
+ /** @description Authentication credentials are missing or invalid.
189
+ *
190
+ * @author Xeno
191
+ * @version 1.0.0
192
+ * @since 2025-09-30
193
+ * @link https://github.com/xeno-js/xeno-js
194
+ */
195
+ UNAUTHORIZED: 401,
196
+ /** @description The caller lacks permission to perform the requested operation.
197
+ *
198
+ * @author Xeno
199
+ * @version 1.0.0
200
+ * @since 2025-09-30
201
+ * @link https://github.com/xeno-js/xeno-js
202
+ */
203
+ FORBIDDEN: 403,
204
+ /** @description The requested resource does not exist.
205
+ *
206
+ * @author Xeno
207
+ * @version 1.0.0
208
+ * @since 2025-09-30
209
+ * @link https://github.com/xeno-js/xeno-js
210
+ */
211
+ NOT_FOUND: 404,
212
+ NOT_ALLOWED: 405,
213
+ /** @description The request conflicts with the current state of the resource.
214
+ *
215
+ * @author Xeno
216
+ * @version 1.0.0
217
+ * @since 2025-09-30
218
+ * @link https://github.com/xeno-js/xeno-js
219
+ */
220
+ CONFLICT: 409,
221
+ /** @description The payload is syntactically valid but semantically unprocessable.
222
+ *
223
+ * @author Xeno
224
+ * @version 1.0.0
225
+ * @since 2025-09-30
226
+ * @link https://github.com/xeno-js/xeno-js
227
+ */
228
+ UNPROCESSABLE_ENTITY: 422,
229
+ /** @description The caller has exceeded its allowed rate limit.
230
+ *
231
+ * @author Xeno
232
+ * @version 1.0.0
233
+ * @since 2025-09-30
234
+ * @link https://github.com/xeno-js/xeno-js
235
+ */
236
+ TOO_MANY_REQUESTS: 429,
237
+ /** @description The client closed the connection before the server finished responding.
238
+ *
239
+ * @author Xeno
240
+ * @version 1.0.0
241
+ * @since 2025-09-30
242
+ * @link https://github.com/xeno-js/xeno-js
243
+ */
244
+ ABORTED: 499,
245
+ // ── 5xx Server Errors ─────────────────────────────────────────────────────
246
+ /** @description An unexpected condition was encountered by the server.
247
+ *
248
+ * @author Xeno
249
+ * @version 1.0.0
250
+ * @since 2025-09-30
251
+ * @link https://github.com/xeno-js/xeno-js
252
+ */
253
+ INTERNAL_SERVER_ERROR: 500,
254
+ /** @description A downstream dependency is temporarily unavailable.
255
+ *
256
+ * @author Xeno
257
+ * @version 1.0.0
258
+ * @since 2025-09-30
259
+ * @link https://github.com/xeno-js/xeno-js
260
+ */
261
+ SERVICE_UNAVAILABLE: 503
262
+ });
263
+ var ERROR_CODE_MESSAGES = Object.freeze({
264
+ [ERROR_CODES.SYSTEM_ERROR]: "errors.system_error",
265
+ [ERROR_CODES.NOT_IMPLEMENTED]: "errors.not_implemented",
266
+ [ERROR_CODES.EXTERNAL_SERVICE_ERROR]: "errors.external_service_error",
267
+ [ERROR_CODES.VALIDATION_FAILED]: "errors.validation_failed",
268
+ [ERROR_CODES.UNAUTHORIZED]: "errors.unauthorized",
269
+ [ERROR_CODES.FORBIDDEN]: "errors.forbidden",
270
+ [ERROR_CODES.BAD_REQUEST]: "errors.bad_request",
271
+ [ERROR_CODES.ABORTED]: "errors.aborted",
272
+ [ERROR_CODES.AUTHENTICATION_FAILED]: "errors.authentication_failed",
273
+ [ERROR_CODES.SCOPE_NOT_AVAILABLE]: "errors.scope_not_available",
274
+ [ERROR_CODES.CONFLICT]: "errors.conflict",
275
+ [ERROR_CODES.NOT_FOUND]: "errors.not_found",
276
+ [ERROR_CODES.HANDLER_NOT_FOUND]: "errors.handler_not_found",
277
+ [ERROR_CODES.PIPELINE_NOT_AVAILABLE]: "errors.pipeline_not_available",
278
+ [ERROR_CODES.NOT_ALLOWED]: "errors.method_not_allowed",
279
+ [ERROR_CODES.TOO_MANY_REQUESTS]: "errors.too_many_requests"
280
+ });
281
+
282
+ // src/shared/constants/roles.constants.ts
283
+ var ROLES = Object.freeze({
284
+ /** @description The SUPER_ADMIN role, which typically has the highest level of permissions and access within the application.
285
+ *
286
+ * @author Xeno
287
+ * @version 1.0.0
288
+ * @since 2025-09-30
289
+ * @link https://github.com/xeno-js/xeno-js
290
+ */
291
+ SUPER_ADMIN: "super_admin",
292
+ /** @description The ADMIN role, which typically has elevated permissions and access within the application, but may have some restrictions compared to the SUPER_ADMIN role.
293
+ *
294
+ * @author Xeno
295
+ * @version 1.0.0
296
+ * @since 2025-09-30
297
+ * @link https://github.com/xeno-js/xeno-js
298
+ */
299
+ ADMIN: "admin",
300
+ /** @description The USER role, which typically has standard permissions and access within the application, allowing them to perform regular user actions but with limited administrative capabilities.
301
+ *
302
+ * @author Xeno
303
+ * @version 1.0.0
304
+ * @since 2025-09-30
305
+ * @link https://github.com/xeno-js/xeno-js
306
+ */
307
+ USER: "user",
308
+ /** @description The GUEST role, which typically has the most limited permissions and access within the application, often used for unauthenticated users or users with very restricted access.
309
+ *
310
+ * @author Xeno
311
+ * @version 1.0.0
312
+ * @since 2025-09-30
313
+ * @link https://github.com/xeno-js/xeno-js
314
+ */
315
+ GUEST: "guest"
316
+ });
317
+ var PERMISSIONS = Object.freeze({
318
+ /** @description The READ permission, which typically allows access to resources or actions within the application that require read-only access.
319
+ *
320
+ * @author Xeno
321
+ * @version 1.0.0
322
+ * @since 2025-09-30
323
+ * @link https://github.com/xeno-js/xeno-js
324
+ */
325
+ READ: "read"
326
+ });
327
+
328
+ // src/shared/constants/guest.constants.ts
329
+ var GUEST = Object.freeze({
330
+ /** @description The unique identifier for the guest user, which is set to undefined since guest users do not have a specific user ID. This allows the application to differentiate between authenticated users with valid IDs and unauthenticated guest users.
331
+ *
332
+ * @author Xeno
333
+ * @version 1.0.0
334
+ * @since 2025-09-30
335
+ * @link https://github.com/xeno-js/xeno-js
336
+ */
337
+ userId: void 0,
338
+ /** @description The email for guest user, which is set to undefined since guest users do not have a specific email.
339
+ *
340
+ * @author Xeno
341
+ * @version 1.0.0
342
+ * @since 2025-09-30
343
+ * @link https://github.com/xeno-js/xeno-js
344
+ */
345
+ email: void 0,
346
+ /** @description The unique identifier for the tenant associated with the guest user, which is set to undefined since guest users do not belong to a specific tenant. This allows the application to handle multi-tenancy scenarios while still accommodating unauthenticated users who do not have an associated tenant.
347
+ *
348
+ * @author Xeno
349
+ * @version 1.0.0
350
+ * @since 2025-09-30
351
+ * @link https://github.com/xeno-js/xeno-js
352
+ */
353
+ tenantId: void 0,
354
+ /** @description An array of roles assigned to the guest user, which includes only the GUEST role. This indicates that the user has minimal access rights and is typically used to represent unauthenticated users or users with limited permissions in the application.
355
+ *
356
+ * @author Xeno
357
+ * @version 1.0.0
358
+ * @since 2025-09-30
359
+ * @link https://github.com/xeno-js/xeno-js
360
+ */
361
+ roles: [ROLES.GUEST],
362
+ /** @description An array of permissions assigned to the guest user, which is empty since guest users do not have any specific permissions. This reinforces the idea that guest users have minimal access rights and cannot perform actions that require specific permissions in the application.
363
+ *
364
+ * @author Xeno
365
+ * @version 1.0.0
366
+ * @since 2025-09-30
367
+ * @link https://github.com/xeno-js/xeno-js
368
+ */
369
+ permissions: [PERMISSIONS.READ]
370
+ });
371
+
372
+ // src/shared/constants/idempotency.constants.ts
373
+ var IDEMPOTENCY_CONSTANTS = Object.freeze({
374
+ /**
375
+ * @description Prefix for keys used to store locks in the idempotency store. This prefix is used to differentiate lock entries from other types of entries in the cache, allowing for efficient management of locks when acquiring and releasing them during command processing. The lock key prefix helps ensure that lock-related data is organized and easily identifiable within the caching mechanism.
376
+
377
+ *
378
+ * @author Xeno
379
+ * @version 1.0.0
380
+ * @since 2025-09-30
381
+ * @link https://github.com/xeno-js/xeno-js
382
+ */
383
+ LOCK_KEY_PREFIX: "idempotency_lock:",
384
+ /**
385
+ * @description Prefix for keys used to store processed command results in the idempotency store. This prefix is used to differentiate processed command entries from lock entries and other types of data in the cache, allowing for efficient retrieval of stored results when checking if a command has already been processed. The processed key prefix helps maintain a clear structure within the caching mechanism, making it easier to manage and query processed command data.
386
+
387
+ *
388
+ * @author Xeno
389
+ * @version 1.0.0
390
+ * @since 2025-09-30
391
+ * @link https://github.com/xeno-js/xeno-js
392
+ */
393
+ PROCESSED_KEY_PREFIX: "idempotency_processed:",
394
+ /**
395
+ * @description Default time-to-live (TTL) in seconds for locks and processed command entries in the idempotency store. This value is used when acquiring locks and marking commands as processed to specify how long the lock or stored result should remain valid before it expires. The default TTL helps ensure that locks and processed command entries do not persist indefinitely, allowing for automatic cleanup of stale data and preventing potential issues with long-lived locks or outdated results in the idempotency store.
396
+
397
+ *
398
+ * @author Xeno
399
+ * @version 1.0.0
400
+ * @since 2025-09-30
401
+ * @link https://github.com/xeno-js/xeno-js
402
+ */
403
+ DEFAULT_TTL_SECONDS: 86400,
404
+ /**
405
+ * @description Default time-to-live (TTL) in seconds for locks in the idempotency store. This value is used when acquiring locks to specify how long the lock should remain valid before it expires. The default lock TTL helps ensure that locks do not persist indefinitely, allowing for automatic cleanup of stale locks and preventing potential issues with long-lived locks in the idempotency mechanism.
406
+
407
+ *
408
+ * @author Xeno
409
+ * @version 1.0.0
410
+ * @since 2025-09-30
411
+ * @link https://github.com/xeno-js/xeno-js
412
+ */
413
+ DEFAULT_IDEMPOTENCY_LOCK_TTL_SECONDS: 60,
414
+ /**
415
+ * @description Standard value used to indicate that a lock has been acquired for a specific commandId in the idempotency store. This value is stored in the cache when a lock is successfully acquired, allowing other instances of the command to recognize that the command is currently being processed and prevent duplicate processing. The locked value serves as a marker for active locks in the idempotency mechanism, helping to manage concurrent command processing effectively.
416
+
417
+ *
418
+ * @author Xeno
419
+ * @version 1.0.0
420
+ * @since 2025-09-30
421
+ * @link https://github.com/xeno-js/xeno-js
422
+ */
423
+ LOCKED_VALUE: "LOCKED",
424
+ /**
425
+ * @description Standard value used to indicate that a command has been processed and its result has been stored in the idempotency store. This value is stored in the cache when a command is marked as processed, allowing subsequent attempts to process the same commandId to recognize that it has already been handled and return the stored result instead of executing the command again. The processed value serves as a marker for completed commands in the idempotency mechanism, helping to manage command processing outcomes and prevent redundant executions.
426
+
427
+ *
428
+ * @author Xeno
429
+ * @version 1.0.0
430
+ * @since 2025-09-30
431
+ * @link https://github.com/xeno-js/xeno-js
432
+ */
433
+ PROCESSED_VALUE: "PROCESSED"
434
+ });
435
+
436
+ // src/shared/constants/log-level.constants.ts
437
+ var LOG_LEVEL = Object.freeze({
438
+ /** * Debug level for detailed debugging information. This level is typically used during development and should be turned off in production to avoid verbose logging.
439
+
440
+ *
441
+ * @author Xeno
442
+ * @version 1.0.0
443
+ * @since 2025-09-30
444
+ * @link https://github.com/xeno-js/xeno-js
445
+ */
446
+ DEBUG: 0,
447
+ /** * Info level for general informational messages that highlight the progress of the application at a coarse-grained level. This level is suitable for production environments to track the normal operation of the application.
448
+
449
+ *
450
+ * @author Xeno
451
+ * @version 1.0.0
452
+ * @since 2025-09-30
453
+ * @link https://github.com/xeno-js/xeno-js
454
+ */
455
+ INFO: 1,
456
+ /** * Warn level for potentially harmful situations that are not necessarily errors but may require attention. This level is useful for identifying issues that could lead to errors if not addressed.
457
+
458
+ *
459
+ * @author Xeno
460
+ * @version 1.0.0
461
+ * @since 2025-09-30
462
+ * @link https://github.com/xeno-js/xeno-js
463
+ */
464
+ WARN: 2,
465
+ /** * Error level for serious issues that have caused or are likely to cause the application to fail. This level is critical for identifying and addressing problems that need immediate attention.
466
+
467
+ *
468
+ * @author Xeno
469
+ * @version 1.0.0
470
+ * @since 2025-09-30
471
+ * @link https://github.com/xeno-js/xeno-js
472
+ */
473
+ ERROR: 3
474
+ });
475
+ var LOG_LEVEL_NAMES = {
476
+ /** Debug level for detailed debugging information. This level is typically used during development and should be turned off in production to avoid verbose logging.
477
+ *
478
+ * @author Xeno
479
+ * @version 1.0.0
480
+ * @since 2025-09-30
481
+ * @link https://github.com/xeno-js/xeno-js
482
+ */
483
+ [LOG_LEVEL.DEBUG]: "DEBUG",
484
+ /** Info level for general informational messages that highlight the progress of the application at a coarse-grained level. This level is suitable for production environments to track the normal operation of the application.
485
+ *
486
+ * @author Xeno
487
+ * @version 1.0.0
488
+ * @since 2025-09-30
489
+ * @link https://github.com/xeno-js/xeno-js
490
+ */
491
+ [LOG_LEVEL.INFO]: "INFO",
492
+ /** Warn level for potentially harmful situations that are not necessarily errors but may require attention. This level is useful for identifying issues that could lead to errors if not addressed.
493
+ *
494
+ * @author Xeno
495
+ * @version 1.0.0
496
+ * @since 2025-09-30
497
+ * @link https://github.com/xeno-js/xeno-js
498
+ */
499
+ [LOG_LEVEL.WARN]: "WARN",
500
+ /** Error level for serious issues that have caused or are likely to cause the application to fail. This level is critical for identifying and addressing problems that need immediate attention.
501
+ *
502
+ * @author Xeno
503
+ * @version 1.0.0
504
+ * @since 2025-09-30
505
+ * @link https://github.com/xeno-js/xeno-js
506
+ */
507
+ [LOG_LEVEL.ERROR]: "ERROR"
508
+ };
509
+
510
+ // src/shared/constants/pagination.constants.ts
511
+ var DEFAULT_PAGE = 1;
512
+ var DEFAULT_PAGE_SIZE = 20;
513
+ var MAX_PAGE_SIZE = 100;
514
+ var PAGINATION_DEFAULTS = Object.freeze({
515
+ /** @description Default page index (1-based).
516
+ *
517
+ * @author Xeno
518
+ * @version 1.0.0
519
+ * @since 2025-09-30
520
+ * @link https://github.com/xeno-js/xeno-js
521
+ */
522
+ PAGE: DEFAULT_PAGE,
523
+ /** @description Default maximum items per page.
524
+ *
525
+ * @author Xeno
526
+ * @version 1.0.0
527
+ * @since 2025-09-30
528
+ * @link https://github.com/xeno-js/xeno-js
529
+ */
530
+ PAGE_SIZE: DEFAULT_PAGE_SIZE,
531
+ /** @description Hard ceiling on page size accepted by the system.
532
+ *
533
+ * @author Xeno
534
+ * @version 1.0.0
535
+ * @since 2025-09-30
536
+ * @link https://github.com/xeno-js/xeno-js
537
+ */
538
+ MAX_PAGE_SIZE
539
+ });
540
+ var SORT_DIRECTION = Object.freeze({
541
+ /** @description Ascending order (A → Z, 0 → 9, oldest → newest).
542
+ *
543
+ * @author Xeno
544
+ * @version 1.0.0
545
+ * @since 2025-09-30
546
+ * @link https://github.com/xeno-js/xeno-js
547
+ */
548
+ ASC: "asc",
549
+ /** @description Descending order (Z → A, 9 → 0, newest → oldest).
550
+ *
551
+ * @author Xeno
552
+ * @version 1.0.0
553
+ * @since 2025-09-30
554
+ * @link https://github.com/xeno-js/xeno-js
555
+ */
556
+ DESC: "desc"
557
+ });
558
+
559
+ // src/shared/constants/request.constants.ts
560
+ var REQUEST_TYPE = Object.freeze({
561
+ /** @description A request that intends to modify state (e.g. create, update, delete).
562
+ *
563
+ * @author Xeno
564
+ * @version 1.0.0
565
+ * @since 2025-09-30
566
+ * @link https://github.com/xeno-js/xeno-js
567
+ */
568
+ COMMAND: "COMMAND",
569
+ /** @description A request that intends to retrieve data without modifying state.
570
+ *
571
+ * @author Xeno
572
+ * @version 1.0.0
573
+ * @since 2025-09-30
574
+ * @link https://github.com/xeno-js/xeno-js
575
+ */
576
+ QUERY: "QUERY"
577
+ });
578
+
579
+ // src/shared/constants/resilience.constants.ts
580
+ var RESILIENCE_DEFAULTS = Object.freeze({
581
+ /** @description Default retry policy values.
582
+ *
583
+ * @author Xeno
584
+ * @version 1.0.0
585
+ * @since 2025-09-30
586
+ * @link https://github.com/xeno-js/xeno-js
587
+ */
588
+ RETRY: Object.freeze({
589
+ /** @description Default number of retry attempts.
590
+ *
591
+ * @author Xeno
592
+ * @version 1.0.0
593
+ * @since 2025-09-30
594
+ * @link https://github.com/xeno-js/xeno-js
595
+ */
596
+ ATTEMPTS: 3,
597
+ /** @description Default base delay in milliseconds for retry backoff.
598
+ *
599
+ * @author Xeno
600
+ * @version 1.0.0
601
+ * @since 2025-09-30
602
+ * @link https://github.com/xeno-js/xeno-js
603
+ */
604
+ BASE_DELAY_MS: 100,
605
+ /** @description Default maximum delay in milliseconds for retry backoff.
606
+ *
607
+ * @author Xeno
608
+ * @version 1.0.0
609
+ * @since 2025-09-30
610
+ * @link https://github.com/xeno-js/xeno-js
611
+ */
612
+ MAX_DELAY_MS: 1e3
613
+ }),
614
+ /** @description Default circuit breaker policy values.
615
+ *
616
+ * @author Xeno
617
+ * @version 1.0.0
618
+ * @since 2025-09-30
619
+ * @link https://github.com/xeno-js/xeno-js
620
+ */
621
+ CIRCUIT_BREAKER: Object.freeze({
622
+ /** @description Default number of consecutive failures before opening the circuit.
623
+ *
624
+ * @author Xeno
625
+ * @version 1.0.0
626
+ * @since 2025-09-30
627
+ * @link https://github.com/xeno-js/xeno-js
628
+ */
629
+ CONSECUTIVE_FAILURES: 5,
630
+ /** @description Default half-open timeout in milliseconds.
631
+ *
632
+ * @author Xeno
633
+ * @version 1.0.0
634
+ * @since 2025-09-30
635
+ * @link https://github.com/xeno-js/xeno-js
636
+ */
637
+ HALF_OPEN_TIMEOUT_MS: 3e4
638
+ }),
639
+ /** @description Default bulkhead policy values.
640
+ *
641
+ * @author Xeno
642
+ * @version 1.0.0
643
+ * @since 2025-09-30
644
+ * @link https://github.com/xeno-js/xeno-js
645
+ */
646
+ BULKHEAD: Object.freeze({
647
+ /** @description Default maximum number of concurrent operations.
648
+ *
649
+ * @author Xeno
650
+ * @version 1.0.0
651
+ * @since 2025-09-30
652
+ * @link https://github.com/xeno-js/xeno-js
653
+ */
654
+ MAX_CONCURRENT: 10
655
+ })
656
+ });
657
+
658
+ // src/shared/constants/tokens.constants.ts
659
+ var TOKENS = Object.freeze({
660
+ /** @description Token used to register and resolve the Extendend AuthService instance in the dependency injection container.
661
+ *
662
+ * @author Xeno
663
+ * @version 1.0.0
664
+ * @since 2025-09-30
665
+ * @link https://github.com/xeno-js/xeno-js
666
+ */
667
+ AUTH_SERVICE: "AUTH_SERVICE",
668
+ /** @description Token used to register and resolve the BaseAuthService instance in the dependency injection container.
669
+ *
670
+ * @author Xeno
671
+ * @version 1.0.0
672
+ * @since 2025-09-30
673
+ * @link https://github.com/xeno-js/xeno-js
674
+ */
675
+ BASE_AUTH_SERVICE: "BASE_AUTH_SERVICE",
676
+ /** @description Token used to register and resolve the InMemoryCache instance in the dependency injection container.
677
+ *
678
+ * @author Xeno
679
+ * @version 1.0.0
680
+ * @since 2025-09-30
681
+ * @link https://github.com/xeno-js/xeno-js
682
+ */
683
+ CACHE: "CACHE",
684
+ /** @description Token used to register and resolve the CacheKeyBuilder instance in the dependency injection container.
685
+ *
686
+ * @author Xeno
687
+ * @version 1.0.0
688
+ * @since 2025-09-30
689
+ * @link https://github.com/xeno-js/xeno-js
690
+ */
691
+ CACHE_KEY_BUILDER: "CACHE_KEY_BUILDER",
692
+ /** @description Token used to register and resolve command pipeline behaviors in the dependency injection container.
693
+ *
694
+ * @author Xeno
695
+ * @version 1.0.0
696
+ * @since 2025-09-30
697
+ * @link https://github.com/xeno-js/xeno-js
698
+ */
699
+ COMMAND_PIPELINES_BEHAVIOR: "COMMAND_PIPELINES_BEHAVIOR",
700
+ /** @description Token used to register and resolve the ConcurrencyService instance in the dependency injection container.
701
+ *
702
+ * @author Xeno
703
+ * @version 1.0.0
704
+ * @since 2025-09-30
705
+ * @link https://github.com/xeno-js/xeno-js
706
+ */
707
+ CONCURRENCY_SERVICE: "CONCURRENCY_SERVICE",
708
+ /** @description Token used to register and resolve the ConfigurationService instance in the dependency injection container.
709
+ *
710
+ * @author Xeno
711
+ * @version 1.0.0
712
+ * @since 2025-09-30
713
+ * @link https://github.com/xeno-js/xeno-js
714
+ */
715
+ CONFIGURATION_SERVICE: "CONFIGURATION_SERVICE",
716
+ /** @description Token used to register and resolve the ContextAccessor instance in the dependency injection container.
717
+ *
718
+ * @author Xeno
719
+ * @version 1.0.0
720
+ * @since 2025-09-30
721
+ * @link https://github.com/xeno-js/xeno-js
722
+ */
723
+ CONTEXT_ACCESSOR: "CONTEXT_ACCESSOR",
724
+ /** @description Token used to register and resolve the CryptoService instance in the dependency injection container.
725
+ *
726
+ * @author Xeno
727
+ * @version 1.0.0
728
+ * @since 2025-09-30
729
+ * @link https://github.com/xeno-js/xeno-js
730
+ */
731
+ CRYPTO_SERVICE: "CRYPTO_SERVICE",
732
+ /** @description Token used to register and resolve the CsrfTokenService instance in the dependency injection container.
733
+ *
734
+ * @author Xeno
735
+ * @version 1.0.0
736
+ * @since 2025-09-30
737
+ * @link https://github.com/xeno-js/xeno-js
738
+ */
739
+ CSRF_TOKEN_SERVICE: "CSRF_TOKEN_SERVICE",
740
+ /** @description Token used to register and resolve the DbContext instance in the dependency injection container.
741
+ *
742
+ * @author Xeno
743
+ * @version 1.0.0
744
+ * @since 2025-09-30
745
+ * @link https://github.com/xeno-js/xeno-js
746
+ */
747
+ DB_CONTEXT: "DB_CONTEXT",
748
+ /** @description Token used to register and resolve the IdentityAccessor instance in the dependency injection container.
749
+ *
750
+ * @author Xeno
751
+ * @version 1.0.0
752
+ * @since 2025-09-30
753
+ * @link https://github.com/xeno-js/xeno-js
754
+ */
755
+ IDENTITY_ACCESSOR: "IDENTITY_ACCESSOR",
756
+ /** @description Token used to register and resolve the Logger instance in the dependency injection container.
757
+ *
758
+ * @author Xeno
759
+ * @version 1.0.0
760
+ * @since 2025-09-30
761
+ * @link https://github.com/xeno-js/xeno-js
762
+ */
763
+ LOGGER: "LOGGER",
764
+ /** @description Token used to register and resolve the Mediator instance in the dependency injection container.
765
+ *
766
+ * @author Xeno
767
+ * @version 1.0.0
768
+ * @since 2025-09-30
769
+ * @link https://github.com/xeno-js/xeno-js
770
+ */
771
+ MEDIATOR: "MEDIATOR",
772
+ /** @description Token used to register and resolve the NetworkContextFactory in the dependency injection container.
773
+ *
774
+ * @author Xeno
775
+ * @version 1.0.0
776
+ * @since 2025-09-30
777
+ * @link https://github.com/xeno-js/xeno-js
778
+ */
779
+ NETWORK_CONTEXT_ACCESSOR: "NETWORK_CONTEXT_ACCESSOR",
780
+ /** @description Token used to register and resolve query pipeline behaviors in the dependency injection container.
781
+ *
782
+ * @author Xeno
783
+ * @version 1.0.0
784
+ * @since 2025-09-30
785
+ * @link https://github.com/xeno-js/xeno-js
786
+ */
787
+ QUERY_PIPELINES_BEHAVIOR: "QUERY_PIPELINES_BEHAVIOR",
788
+ /** @description Token used to register and resolve the RequestContext instance in the dependency injection container.
789
+ *
790
+ * @author Xeno
791
+ * @version 1.0.0
792
+ * @since 2025-09-30
793
+ * @link https://github.com/xeno-js/xeno-js
794
+ */
795
+ REQUEST_CONTEXT: "REQUEST_CONTEXT",
796
+ /** @description Token used to register and resolve the CompositeMiddleware in the dependency injection container.
797
+ *
798
+ * @author Xeno
799
+ * @version 1.0.0
800
+ * @since 2025-09-30
801
+ * @link https://github.com/xeno-js/xeno-js
802
+ */
803
+ MIDDLEWARE: "MIDDLEWARE",
804
+ /** @description Token used to register and resolve the IServiceResilience instance in the dependency injection container.
805
+ *
806
+ * @author Xeno
807
+ * @version 1.0.0
808
+ * @since 2025-09-30
809
+ * @link https://github.com/xeno-js/xeno-js
810
+ */
811
+ RESILIENCE_CLIENT: "RESILIENCE_CLIENT",
812
+ /** @description Token used to register and resolve the SchemaValidationStrategy instance in the dependency injection container.
813
+ *
814
+ * @author Xeno
815
+ * @version 1.0.0
816
+ * @since 2025-09-30
817
+ * @link https://github.com/xeno-js/xeno-js
818
+ */
819
+ SCHEMA_VALIDATION_STRATEGY: "SCHEMA_VALIDATION_STRATEGY",
820
+ /** @description Token used to register and resolve the ServiceContainer instance in the dependency injection container.
821
+ *
822
+ * @author Xeno
823
+ * @version 1.0.0
824
+ * @since 2025-09-30
825
+ * @link https://github.com/xeno-js/xeno-js
826
+ */
827
+ SERVICE_CONTAINER: "SERVICE_CONTAINER",
828
+ /** @description Token used to register and resolve the ServiceExtractor instance in the dependency injection container.
829
+ *
830
+ * @author Xeno
831
+ * @version 1.0.0
832
+ * @since 2025-09-30
833
+ * @link https://github.com/xeno-js/xeno-js
834
+ */
835
+ SERVICE_EXTRACTOR: "SERVICE_EXTRACTOR",
836
+ /** @description Token used to register and resolve the ServiceScopeAccessor in the dependency injection container.
837
+ *
838
+ * @author Xeno
839
+ * @version 1.0.0
840
+ * @since 2025-09-30
841
+ * @link https://github.com/xeno-js/xeno-js
842
+ */
843
+ SERVICE_SCOPE_ACCESSOR: "SERVICE_SCOPE_ACCESSOR",
844
+ /** @description Token used to register and resolve the UnitOfWork instance in the dependency injection container.
845
+ *
846
+ * @author Xeno
847
+ * @version 1.0.0
848
+ * @since 2025-09-30
849
+ * @link https://github.com/xeno-js/xeno-js
850
+ */
851
+ UNIT_OF_WORK: "UNIT_OF_WORK",
852
+ /** @description Token used to register and resolve the ValidatorService instance in the dependency injection container.
853
+ *
854
+ * @author Xeno
855
+ * @version 1.0.0
856
+ * @since 2025-09-30
857
+ * @link https://github.com/xeno-js/xeno-js
858
+ */
859
+ VALIDATOR_SERVICE: "VALIDATOR_SERVICE"
860
+ });
861
+
862
+ // src/shared/utils/guards.utils.ts
863
+ var OBJECT_TAG = "[object Object]";
864
+ var DATE_TAG = "[object Date]";
865
+ var Guards = Object.freeze({
866
+ /**
867
+ * @description Checks value is neither null nor undefined.
868
+ * @param value Candidate value.
869
+ * @returns True when value is defined.
870
+
871
+ *
872
+ * @author Xeno
873
+ * @version 1.0.0
874
+ * @since 2025-09-30
875
+ * @link https://github.com/xeno-js/xeno-js
876
+ */
877
+ isDefined(value) {
878
+ return value !== null && value !== void 0 && value !== "" && !Number.isNaN(value);
879
+ },
880
+ /**
881
+ * @description Checks value is null, undefined, empty string, or false.
882
+ * @param value Candidate value.
883
+ * @returns True when value is null, undefined, empty string, or false.
884
+
885
+ *
886
+ * @author Xeno
887
+ * @version 1.0.0
888
+ * @since 2025-09-30
889
+ * @link https://github.com/xeno-js/xeno-js
890
+ */
891
+ isNullOrEmpty(value) {
892
+ return !Guards.isDefined(value) || Guards.isString(value) && value.trim() === "" || Guards.isArray(value) && value.length === 0;
893
+ },
894
+ /**
895
+ * @description Throws an error if the value is null, undefined, empty string, or false.
896
+ * @param value Candidate value.
897
+ * @param errorMessage Error message to throw if the check fails.
898
+ * @throws Error with the provided message if the value is null, undefined, empty string, or false.
899
+
900
+ *
901
+ * @author Xeno
902
+ * @version 1.0.0
903
+ * @since 2025-09-30
904
+ * @link https://github.com/xeno-js/xeno-js
905
+ */
906
+ throwIfNullOrEmpty(value, errorMessage) {
907
+ if (Guards.isNullOrEmpty(value)) {
908
+ throw new Error(errorMessage);
909
+ }
910
+ },
911
+ /**
912
+ * @description Throws an error if the value is not a positive integer.
913
+ * @param value Candidate value.
914
+ * @param errorMessage Error message to throw if the check fails.
915
+ * @throws Error with the provided message if the value is not a positive integer.
916
+
917
+ *
918
+ * @author Xeno
919
+ * @version 1.0.0
920
+ * @since 2025-09-30
921
+ * @link https://github.com/xeno-js/xeno-js
922
+ */
923
+ throwIfNegative(value, errorMessage) {
924
+ if (Guards.isInteger(value) && value < 0) {
925
+ throw new Error(errorMessage);
926
+ }
927
+ },
928
+ /**
929
+ * @description Throws an error if the value is not an integer.
930
+ * @param value Candidate value.
931
+ * @param errorMessage Error message to throw if the check fails.
932
+ * @throws Error with the provided message if the value is not an integer.
933
+
934
+ *
935
+ * @author Xeno
936
+ * @version 1.0.0
937
+ * @since 2025-09-30
938
+ * @link https://github.com/xeno-js/xeno-js
939
+ */
940
+ throwIfNotInteger(value, errorMessage) {
941
+ if (!Guards.isInteger(value)) {
942
+ throw new Error(errorMessage);
943
+ }
944
+ },
945
+ /**
946
+ * @description Checks if an object has a method with the given name.
947
+ * @param obj Object to check.
948
+ * @param methodName Name of the method to look for.
949
+ * @returns True when obj has a function property named methodName.
950
+
951
+ *
952
+ * @author Xeno
953
+ * @version 1.0.0
954
+ * @since 2025-09-30
955
+ * @link https://github.com/xeno-js/xeno-js
956
+ */
957
+ hasMethod(obj, methodName) {
958
+ if (!this.isDefined(obj)) return false;
959
+ return Guards.isFunction(obj[methodName]);
960
+ },
961
+ /**
962
+ * @description Checks value is a string.
963
+ * @param value Candidate value.
964
+ * @returns True when value is string.
965
+
966
+ *
967
+ * @author Xeno
968
+ * @version 1.0.0
969
+ * @since 2025-09-30
970
+ * @link https://github.com/xeno-js/xeno-js
971
+ */
972
+ isString(value) {
973
+ return typeof value === "string";
974
+ },
975
+ /**
976
+ * @description Checks value is a finite number.
977
+ * @param value Candidate value.
978
+ * @returns True when value is finite number.
979
+
980
+ *
981
+ * @author Xeno
982
+ * @version 1.0.0
983
+ * @since 2025-09-30
984
+ * @link https://github.com/xeno-js/xeno-js
985
+ */
986
+ isNumber(value) {
987
+ return typeof value === "number" && Number.isFinite(value);
988
+ },
989
+ /**
990
+ * @description Checks value is an integer number.
991
+ * @param value Candidate value.
992
+ * @returns True when value is integer number.
993
+
994
+ *
995
+ * @author Xeno
996
+ * @version 1.0.0
997
+ * @since 2025-09-30
998
+ * @link https://github.com/xeno-js/xeno-js
999
+ */
1000
+ isInteger(value) {
1001
+ return Guards.isNumber(value) && Number.isInteger(value);
1002
+ },
1003
+ /**
1004
+ * @description Checks value is boolean.
1005
+ * @param value Candidate value.
1006
+ * @returns True when value is boolean.
1007
+
1008
+ *
1009
+ * @author Xeno
1010
+ * @version 1.0.0
1011
+ * @since 2025-09-30
1012
+ * @link https://github.com/xeno-js/xeno-js
1013
+ */
1014
+ isBoolean(value) {
1015
+ return typeof value === "boolean";
1016
+ },
1017
+ /**
1018
+ * @description Checks value is bigint.
1019
+ * @param value Candidate value.
1020
+ * @returns True when value is bigint.
1021
+
1022
+ *
1023
+ * @author Xeno
1024
+ * @version 1.0.0
1025
+ * @since 2025-09-30
1026
+ * @link https://github.com/xeno-js/xeno-js
1027
+ */
1028
+ isBigInt(value) {
1029
+ return typeof value === "bigint";
1030
+ },
1031
+ /**
1032
+ * @description Checks value is symbol.
1033
+ * @param value Candidate value.
1034
+ * @returns True when value is symbol.
1035
+
1036
+ *
1037
+ * @author Xeno
1038
+ * @version 1.0.0
1039
+ * @since 2025-09-30
1040
+ * @link https://github.com/xeno-js/xeno-js
1041
+ */
1042
+ isSymbol(value) {
1043
+ return typeof value === "symbol";
1044
+ },
1045
+ /**
1046
+ * @description Checks value is a function.
1047
+ * @param value Candidate value.
1048
+ * @returns True when value is function.
1049
+
1050
+ *
1051
+ * @author Xeno
1052
+ * @version 1.0.0
1053
+ * @since 2025-09-30
1054
+ * @link https://github.com/xeno-js/xeno-js
1055
+ */
1056
+ isFunction(value) {
1057
+ return typeof value === "function";
1058
+ },
1059
+ /**
1060
+ * @description Checks value is an array.
1061
+ * @param value Candidate value.
1062
+ * @returns True when value is array.
1063
+
1064
+ *
1065
+ * @author Xeno
1066
+ * @version 1.0.0
1067
+ * @since 2025-09-30
1068
+ * @link https://github.com/xeno-js/xeno-js
1069
+ */
1070
+ isArray(value) {
1071
+ return Array.isArray(value);
1072
+ },
1073
+ /**
1074
+ * @description Checks value is a Date instance with valid timestamp.
1075
+ * @param value Candidate value.
1076
+ * @returns True when value is valid Date.
1077
+
1078
+ *
1079
+ * @author Xeno
1080
+ * @version 1.0.0
1081
+ * @since 2025-09-30
1082
+ * @link https://github.com/xeno-js/xeno-js
1083
+ */
1084
+ isDate(value) {
1085
+ if (Object.prototype.toString.call(value) !== DATE_TAG) {
1086
+ return false;
1087
+ }
1088
+ return Number.isFinite(value.getTime());
1089
+ },
1090
+ /**
1091
+ * @description Checks value is an Error instance.
1092
+ * @param value Candidate value.
1093
+ * @returns True when value is Error.
1094
+
1095
+ *
1096
+ * @author Xeno
1097
+ * @version 1.0.0
1098
+ * @since 2025-09-30
1099
+ * @link https://github.com/xeno-js/xeno-js
1100
+ */
1101
+ isError(value) {
1102
+ return value instanceof Error;
1103
+ },
1104
+ /**
1105
+ * @description Checks value is a plain object record.
1106
+ * @param value Candidate value.
1107
+ * @returns True when value is object record.
1108
+
1109
+ *
1110
+ * @author Xeno
1111
+ * @version 1.0.0
1112
+ * @since 2025-09-30
1113
+ * @link https://github.com/xeno-js/xeno-js
1114
+ */
1115
+ isObjectRecord(value) {
1116
+ if (!Guards.isDefined(value)) {
1117
+ return false;
1118
+ }
1119
+ return Object.prototype.toString.call(value) === OBJECT_TAG;
1120
+ },
1121
+ /**
1122
+ * @description Checks value is an object (not null).
1123
+ * @param value Candidate value.
1124
+ * @returns True when value is object.
1125
+
1126
+ *
1127
+ * @author Xeno
1128
+ * @version 1.0.0
1129
+ * @since 2025-09-30
1130
+ * @link https://github.com/xeno-js/xeno-js
1131
+ */
1132
+ isObject(value) {
1133
+ return typeof value === "object" && Guards.isDefined(value);
1134
+ },
1135
+ /**
1136
+ * @description Checks value is PromiseLike.
1137
+ * @param value Candidate value.
1138
+ * @returns True when value has then function.
1139
+
1140
+ *
1141
+ * @author Xeno
1142
+ * @version 1.0.0
1143
+ * @since 2025-09-30
1144
+ * @link https://github.com/xeno-js/xeno-js
1145
+ */
1146
+ isPromiseLike(value) {
1147
+ if (!Guards.isDefined(value)) {
1148
+ return false;
1149
+ }
1150
+ if (!Guards.isObject(value) && !Guards.isFunction(value)) {
1151
+ return false;
1152
+ }
1153
+ const thenMember = value["then"];
1154
+ return Guards.isFunction(thenMember);
1155
+ }
1156
+ });
1157
+
1158
+ // src/shared/utils/abort.utils.ts
1159
+ var AbortSignalHelper = Object.freeze({
1160
+ /**
1161
+ * Executes a promise with an optional AbortSignal. If the signal is provided and is aborted, the promise will be rejected with the signal's reason.
1162
+ * @template T - The type of the promise's resolved value.
1163
+ * @param promise - The promise to execute.
1164
+ * @param signal - An optional AbortSignal to cancel the promise.
1165
+ * @returns A promise that resolves with the original promise's value or rejects if the signal is aborted.
1166
+ *
1167
+ * @author Xeno
1168
+ * @version 1.0.0
1169
+ * @since 2025-09-30
1170
+ * @link www.github.com/Mattia-Carcione/xeno-js
1171
+ */
1172
+ execute(promise, signal) {
1173
+ if (!Guards.isDefined(signal)) return promise;
1174
+ if (signal.aborted) return Promise.reject(new Error("Operation aborted"));
1175
+ return new Promise((resolve, reject) => {
1176
+ const onAbort = () => {
1177
+ signal.removeEventListener("abort", onAbort);
1178
+ reject(new Error("Operation aborted by the client."));
1179
+ };
1180
+ signal.addEventListener("abort", onAbort);
1181
+ promise.then((res) => {
1182
+ signal.removeEventListener("abort", onAbort);
1183
+ resolve(res);
1184
+ }).catch((_err) => {
1185
+ signal.removeEventListener("abort", onAbort);
1186
+ reject(new Error("Operation aborted by the client."));
1187
+ });
1188
+ });
1189
+ }
1190
+ });
1191
+
1192
+ // src/shared/utils/date.utils.ts
1193
+ var MS_PER_DAY = 864e5;
1194
+ var DateHelper = Object.freeze({
1195
+ /**
1196
+ * @description Converts a Date to an ISO 8601 string.
1197
+ * @param date Input date.
1198
+ * @returns ISO 8601 UTC string.
1199
+
1200
+ *
1201
+ * @author Xeno
1202
+ * @version 1.0.0
1203
+ * @since 2025-09-30
1204
+ * @link https://github.com/xeno-js/xeno-js
1205
+ */
1206
+ toISOString(date) {
1207
+ return date.toISOString();
1208
+ },
1209
+ /**
1210
+ * @description Returns a new Date with the given number of days added.
1211
+ * @param date Base date.
1212
+ * @param days Number of days to add (negative values subtract).
1213
+ * @returns New Date instance.
1214
+
1215
+ *
1216
+ * @author Xeno
1217
+ * @version 1.0.0
1218
+ * @since 2025-09-30
1219
+ * @link https://github.com/xeno-js/xeno-js
1220
+ */
1221
+ addDays(date, days) {
1222
+ return new Date(date.getTime() + days * MS_PER_DAY);
1223
+ },
1224
+ /**
1225
+ * @description Checks whether a date has elapsed relative to a reference time.
1226
+ * @param expiresAt Expiry date.
1227
+ * @param nowMs Reference epoch in milliseconds (defaults to Date.now()).
1228
+ * @returns True when expiresAt is in the past.
1229
+
1230
+ *
1231
+ * @author Xeno
1232
+ * @version 1.0.0
1233
+ * @since 2025-09-30
1234
+ * @link https://github.com/xeno-js/xeno-js
1235
+ */
1236
+ isExpired(expiresAt, nowMs) {
1237
+ const now = nowMs ?? Date.now();
1238
+ return expiresAt.getTime() < now;
1239
+ },
1240
+ /**
1241
+ * @description Checks if one date is after another.
1242
+ * @param after Date to check if it is after.
1243
+ * @param before Date to check against.
1244
+ * @returns True when after is after before.
1245
+
1246
+ *
1247
+ * @author Xeno
1248
+ * @version 1.0.0
1249
+ * @since 2025-09-30
1250
+ * @link https://github.com/xeno-js/xeno-js
1251
+ */
1252
+ isAfter(after, before) {
1253
+ return Guards.isDate(after) && Guards.isDate(before) && after.getTime() > before.getTime();
1254
+ },
1255
+ /**
1256
+ * @description Checks if a date is in the future relative to now.
1257
+ * @param date Date to check.
1258
+ * @returns True when date is in the future.
1259
+
1260
+ *
1261
+ * @author Xeno
1262
+ * @version 1.0.0
1263
+ * @since 2025-09-30
1264
+ * @link https://github.com/xeno-js/xeno-js
1265
+ */
1266
+ isFuture(date) {
1267
+ return Guards.isDate(date) && date.getTime() > Date.now();
1268
+ }
1269
+ });
1270
+
1271
+ // src/shared/utils/enumerable.utils.ts
1272
+ var Enumerable = Object.freeze({
1273
+ /**
1274
+ * Retrieves the first element of an array that satisfies the provided predicate function. If no predicate is provided, it returns the first element of the array. If the array is empty or no elements satisfy the predicate, an error is thrown.
1275
+ * @template T - The type of elements in the array.
1276
+ * @param array - The array to search.
1277
+ * @param predicate - An optional function to test each element.
1278
+ * @returns The first element that satisfies the predicate.
1279
+ * @throws {Error} If the array is empty or no elements satisfy the predicate.
1280
+ *
1281
+ * @author Xeno
1282
+ * @version 1.0.0
1283
+ * @since 2025-09-30
1284
+ * @link www.github.com/Mattia-Carcione/xeno-js
1285
+ */
1286
+ first(array, predicate) {
1287
+ const item = Guards.isDefined(predicate) ? array.find(predicate) : array[0];
1288
+ if (!Guards.isDefined(item)) {
1289
+ throw new Error("Sequence contains no elements.");
1290
+ }
1291
+ return item;
1292
+ },
1293
+ /**
1294
+ * Retrieves the first element of an array that satisfies the provided predicate function. If no predicate is provided, it returns the first element of the array. If the array is empty or no elements satisfy the predicate, undefined is returned.
1295
+ * @template T - The type of elements in the array.
1296
+ * @param array - The array to search.
1297
+ * @param predicate - An optional function to test each element.
1298
+ * @returns The first element that satisfies the predicate or undefined.
1299
+ *
1300
+ * @author Xeno
1301
+ * @version 1.0.0
1302
+ * @since 2025-09-30
1303
+ * @link www.github.com/Mattia-Carcione/xeno-js
1304
+ */
1305
+ firstOrDefault(array, predicate) {
1306
+ const item = Guards.isDefined(predicate) ? array.find(predicate) : array[0];
1307
+ return Guards.isDefined(item) ? item : void 0;
1308
+ }
1309
+ });
1310
+
1311
+ // src/shared/utils/guid.utils.ts
1312
+ var GuidHelper = Object.freeze({
1313
+ /**
1314
+ * @description Generates a cryptographically-random UUID v4.
1315
+ * @returns Lowercase UUID v4 string.
1316
+
1317
+ *
1318
+ * @author Xeno
1319
+ * @version 1.0.0
1320
+ * @since 2025-09-30
1321
+ * @link https://github.com/xeno-js/xeno-js
1322
+ */
1323
+ generate() {
1324
+ return crypto.randomUUID();
1325
+ },
1326
+ /**
1327
+ * @description Validates if a value is a valid GUID (UUID v4) and not empty.
1328
+ * @param value The value to validate.
1329
+ * @returns True if the value is a valid and non-empty GUID, false otherwise.
1330
+
1331
+ *
1332
+ * @author Xeno
1333
+ * @version 1.0.0
1334
+ * @since 2025-09-30
1335
+ * @link https://github.com/xeno-js/xeno-js
1336
+ */
1337
+ isValidGuid(value) {
1338
+ const guid = value.toString();
1339
+ return GuidHelper.isValid(guid) && !GuidHelper.isEmpty(guid);
1340
+ },
1341
+ /**
1342
+ * @description Validates if a string is a valid UUID v4.
1343
+ * @param value Candidate string to validate.
1344
+ * @returns True if the string is a valid UUID v4, false otherwise.
1345
+
1346
+ *
1347
+ * @author Xeno
1348
+ * @version 1.0.0
1349
+ * @since 2025-09-30
1350
+ * @link https://github.com/xeno-js/xeno-js
1351
+ */
1352
+ isValid(value) {
1353
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
1354
+ return uuidRegex.test(value);
1355
+ },
1356
+ /**
1357
+ * @description Converts a string to a GUID if it's valid.
1358
+ * @param value The string to convert.
1359
+ * @returns The GUID if the string is valid, otherwise undefined.
1360
+
1361
+ *
1362
+ * @author Xeno
1363
+ * @version 1.0.0
1364
+ * @since 2025-09-30
1365
+ * @link https://github.com/xeno-js/xeno-js
1366
+ */
1367
+ parse(value) {
1368
+ if (!Guards.isNullOrEmpty(value) && this.isValid(value) && !this.isEmpty(value)) {
1369
+ return value;
1370
+ }
1371
+ return void 0;
1372
+ },
1373
+ /**
1374
+ * @description Checks if a GUID is the empty GUID (all zeros).
1375
+ * @param value The GUID to check.
1376
+ * @returns True if the GUID is the empty GUID, false otherwise.
1377
+
1378
+ *
1379
+ * @author Xeno
1380
+ * @version 1.0.0
1381
+ * @since 2025-09-30
1382
+ * @link https://github.com/xeno-js/xeno-js
1383
+ */
1384
+ isEmpty(value) {
1385
+ const emptyGuid = "00000000-0000-0000-0000-000000000000";
1386
+ return value === emptyGuid;
1387
+ }
1388
+ });
1389
+
1390
+ // src/shared/utils/http.utils.ts
1391
+ var HttpHelper = Object.freeze({
1392
+ /**
1393
+ * @description A function that masks the IP address in the given headers object.
1394
+ * @param ip The IP address to mask.
1395
+ * @returns The masked IP address.
1396
+ */
1397
+ maskIp(ip) {
1398
+ if (!Guards.isDefined(ip)) return void 0;
1399
+ if (ip.includes(".")) {
1400
+ const parts = ip.split(".");
1401
+ if (parts.length === 4) {
1402
+ parts[3] = "x";
1403
+ return parts.join(".");
1404
+ }
1405
+ }
1406
+ if (ip.includes(":")) {
1407
+ const parts = ip.split(":");
1408
+ if (parts.length > 0) {
1409
+ parts[parts.length - 1] = "x";
1410
+ return parts.join(":");
1411
+ }
1412
+ }
1413
+ return ip;
1414
+ },
1415
+ /**
1416
+ * @description Normalizes HTTP headers by converting all header values to strings. If a header value is an array, it joins the array elements into a single string separated by commas. This method ensures that the headers are in a consistent format, which can be particularly useful when working with different HTTP client libraries that may represent headers in various ways. If the input headers are not defined or not an object, it returns an empty object.
1417
+ * @param headers The input headers to be normalized, which can be of any type. The method checks if the headers are defined and are an object before processing them.
1418
+ * @returns An object containing the normalized headers, where each header value is a string. If the input headers were not valid, it returns an empty object.
1419
+
1420
+ *
1421
+ * @author Xeno
1422
+ * @version 1.0.0
1423
+ * @since 2025-09-30
1424
+ * @link https://github.com/xeno-js/xeno-js
1425
+ */
1426
+ normalizeHeaders(headers) {
1427
+ if (!Guards.isDefined(headers) || !Guards.isObject(headers)) return {};
1428
+ const normalized = {};
1429
+ for (const [key, value] of Object.entries(headers)) {
1430
+ if (!Guards.isDefined(value)) {
1431
+ continue;
1432
+ }
1433
+ normalized[key] = Array.isArray(value) ? value.map((part) => String(part)).join(",") : String(value);
1434
+ }
1435
+ return normalized;
1436
+ },
1437
+ /**
1438
+ * @description Sanitizes the origin URL by parsing it and extracting the origin part. If the URL is not valid or cannot be parsed or does not contain an origin, it returns undefined.
1439
+ * @param url The URL to be sanitized.
1440
+ * @returns The sanitized origin URL or undefined if the URL is not valid or cannot be parsed or does not contain an origin.
1441
+ *
1442
+ *
1443
+ * @author Xeno
1444
+ * @version 1.0.0
1445
+ * @since 2025-09-30
1446
+ * @link https://github.com/xeno-js/xeno-js
1447
+ */
1448
+ sanitizeOriginUrl(url) {
1449
+ if (!Guards.isDefined(url)) return void 0;
1450
+ try {
1451
+ const parsed = new URL(url);
1452
+ return parsed.origin;
1453
+ } catch {
1454
+ return void 0;
1455
+ }
1456
+ },
1457
+ /**
1458
+ * @description Generates a standardized successful HTTP response with the provided data, status code, metadata, and custom headers. The response includes a success flag set to true, the data payload, and any additional metadata. The headers include a default 'Content-Type' of 'application/json' along with any custom headers provided.
1459
+ * @param data The actual data payload to be included in the successful response. This can be of any type and will be wrapped in a SuccessResponseDto structure.
1460
+ * @param status The HTTP status code for the response, defaulting to 200 (OK) if not provided. This allows for flexibility in indicating different types of successful responses (e.g., 201 for created, 204 for no content).
1461
+ * @param meta Optional metadata to be included in the response. This can contain additional information relevant to the response, such as pagination details, rate limit information, or any other contextual data that may be useful for clients consuming the API.
1462
+ * @param customHeaders Optional custom HTTP headers to be included in the response. This allows for adding any additional headers that may be necessary for specific responses, such as caching directives, custom authentication headers, or other relevant information.
1463
+ * @returns A ResponseDto object representing the successful HTTP response, containing the status code, success flag, headers, and data payload structured as a SuccessResponseDto.
1464
+
1465
+ *
1466
+ * @author Xeno
1467
+ * @version 1.0.0
1468
+ * @since 2025-09-30
1469
+ * @link https://github.com/xeno-js/xeno-js
1470
+ */
1471
+ success(data, status = 200, meta = {}, customHeaders = {}) {
1472
+ const successPayload = {
1473
+ success: true,
1474
+ data,
1475
+ meta
1476
+ };
1477
+ return {
1478
+ status,
1479
+ ok: true,
1480
+ headers: {
1481
+ ...customHeaders,
1482
+ "Content-Type": ["application/json"]
1483
+ },
1484
+ data: successPayload
1485
+ };
1486
+ },
1487
+ /**
1488
+ * @description Generates a standardized error HTTP response with the provided error details, status code, correlation ID, request ID, timestamp, and custom headers. The response includes a success flag set to false, an error object containing the error code, message, and optional details, as well as metadata such as correlation ID and request ID for tracking purposes. The headers include a default 'Content-Type' of 'application/json' along with any custom headers provided.
1489
+ * @param dto An object containing the error details, including the error code, message, optional details, and optional path. This information is structured as an ErrorResponseDto and provides context about the error that occurred.
1490
+ * @param status The HTTP status code for the response, defaulting to 500 (Internal Server Error) if not provided. This allows for flexibility in indicating different types of error responses (e.g., 400 for bad request, 404 for not found).
1491
+ * @param customHeaders Optional custom HTTP headers to be included in the response. This allows for adding any additional headers that may be necessary for specific error responses, such as caching directives, custom authentication headers, or other relevant information.
1492
+ * @returns A ResponseDto object representing the error HTTP response, containing the status code, success flag, headers, and data payload structured as an ErrorResponseDto.
1493
+
1494
+ *
1495
+ * @author Xeno
1496
+ * @version 1.0.0
1497
+ * @since 2025-09-30
1498
+ * @link https://github.com/xeno-js/xeno-js
1499
+ */
1500
+ error(dto, status = STATUS_CODES.INTERNAL_SERVER_ERROR, customHeaders = void 0) {
1501
+ const errorPayload = {
1502
+ success: false,
1503
+ error: {
1504
+ code: dto.error.code,
1505
+ message: dto.error.message,
1506
+ details: dto.error.details,
1507
+ path: dto.error.path
1508
+ },
1509
+ correlationId: dto.correlationId,
1510
+ requestId: dto.requestId,
1511
+ spanId: dto.spanId,
1512
+ timestamp: DateHelper.toISOString(/* @__PURE__ */ new Date())
1513
+ };
1514
+ return {
1515
+ status,
1516
+ ok: false,
1517
+ headers: {
1518
+ "Content-Type": ["application/json"],
1519
+ "X-Correlation-Id": [dto.correlationId],
1520
+ "X-Request-Id": [dto.requestId],
1521
+ "X-Span-Id": [dto.spanId ?? ""],
1522
+ "Cache-Control": ["no-store, no-cache, must-revalidate, proxy-revalidate"],
1523
+ "Pragma": ["no-cache"],
1524
+ "Expires": ["0"],
1525
+ ...customHeaders ?? {}
1526
+ },
1527
+ data: errorPayload
1528
+ };
1529
+ }
1530
+ });
1531
+
1532
+ // src/shared/utils/math.utils.ts
1533
+ var MathHelper = Object.freeze({
1534
+ /**
1535
+ * @description Constrains a value within an inclusive min-max range.
1536
+ * @param value Input value.
1537
+ * @param min Minimum bound.
1538
+ * @param max Maximum bound.
1539
+ * @returns Clamped value.
1540
+
1541
+ *
1542
+ * @author Xeno
1543
+ * @version 1.0.0
1544
+ * @since 2025-09-30
1545
+ * @link https://github.com/xeno-js/xeno-js
1546
+ */
1547
+ clamp(value, min, max) {
1548
+ return Math.min(Math.max(value, min), max);
1549
+ },
1550
+ /**
1551
+ * @description Rounds a number to the specified decimal precision.
1552
+ * @param value Input value.
1553
+ * @param decimals Number of decimal places.
1554
+ * @returns Rounded value.
1555
+
1556
+ *
1557
+ * @author Xeno
1558
+ * @version 1.0.0
1559
+ * @since 2025-09-30
1560
+ * @link https://github.com/xeno-js/xeno-js
1561
+ */
1562
+ roundTo(value, decimals) {
1563
+ const factor = 10 ** decimals;
1564
+ return Math.round(value * factor) / factor;
1565
+ },
1566
+ /**
1567
+ * @description Divides two numbers, returning a safe fallback on zero denominator.
1568
+ * @param numerator Numerator.
1569
+ * @param denominator Denominator.
1570
+ * @param fallback Return value when denominator is zero.
1571
+ * @returns Division result or fallback.
1572
+
1573
+ *
1574
+ * @author Xeno
1575
+ * @version 1.0.0
1576
+ * @since 2025-09-30
1577
+ * @link https://github.com/xeno-js/xeno-js
1578
+ */
1579
+ safeDivide(numerator, denominator, fallback = 0) {
1580
+ if (denominator === 0) return fallback;
1581
+ return numerator / denominator;
1582
+ },
1583
+ /**
1584
+ * @description Returns the percentage of part over total (0–100 scale).
1585
+ * @param part Part value.
1586
+ * @param total Total value.
1587
+ * @returns Percentage or 0 when total is zero.
1588
+
1589
+ *
1590
+ * @author Xeno
1591
+ * @version 1.0.0
1592
+ * @since 2025-09-30
1593
+ * @link https://github.com/xeno-js/xeno-js
1594
+ */
1595
+ toPercentage(part, total) {
1596
+ if (total === 0) return 0;
1597
+ return part / total * 100;
1598
+ },
1599
+ /**
1600
+ * @description Converts a value to a number, returning a fallback for non-numeric inputs.
1601
+ * @param value Input value.
1602
+ * @param fallback Fallback value for non-numeric inputs.
1603
+ * @returns Numeric value or fallback.
1604
+ *
1605
+ * @author Xeno
1606
+ * @version 1.0.0
1607
+ * @since 2025-09-30
1608
+ * @link https://github.com/xeno-js/xeno-js
1609
+ */
1610
+ toNumber(value, fallback = 0) {
1611
+ if (!Guards.isDefined(value) || !Guards.isNumber(value)) return fallback;
1612
+ const num = Number(value);
1613
+ return isNaN(num) ? fallback : num;
1614
+ }
1615
+ });
1616
+
1617
+ // src/shared/utils/promise.utils.ts
1618
+ var PromiseHelper = Object.freeze({
1619
+ /**
1620
+ * @description Sospende l'esecuzione asincrona per un numero esatto di millisecondi.
1621
+ * @param ms I millisecondi di attesa.
1622
+ * @returns Una Promise che si risolve al termine del tempo.
1623
+
1624
+ *
1625
+ * @author Xeno
1626
+ * @version 1.0.0
1627
+ * @since 2025-09-30
1628
+ * @link https://github.com/xeno-js/xeno-js
1629
+ */
1630
+ delay(ms) {
1631
+ return new Promise((resolve) => setTimeout(resolve, ms));
1632
+ },
1633
+ /**
1634
+ * @description Introduce un ritardo asincrono composto da un tempo base più una variazione casuale.
1635
+ * Fondamentale per mitigare il "Thundering Herd problem" (effetto gregge) distribuendo
1636
+ * nel tempo i retry simultanei di più client.
1637
+ * * @param baseDelayMs Il ritardo minimo garantito.
1638
+ * @param maxJitterMs La variazione massima casuale aggiuntiva.
1639
+ * @returns Una Promise che si risolve al termine del calcolo.
1640
+
1641
+ *
1642
+ * @author Xeno
1643
+ * @version 1.0.0
1644
+ * @since 2025-09-30
1645
+ * @link https://github.com/xeno-js/xeno-js
1646
+ */
1647
+ delayWithJitter(baseDelayMs, maxJitterMs) {
1648
+ const jitter = Math.floor(Math.random() * maxJitterMs);
1649
+ return new Promise((resolve) => setTimeout(resolve, baseDelayMs + jitter));
1650
+ }
1651
+ });
1652
+
1653
+ // src/shared/utils/sanitize.utils.ts
1654
+ var start = String.fromCharCode(0);
1655
+ var end = String.fromCharCode(31);
1656
+ var del = String.fromCharCode(127);
1657
+ var CONTROL_CHARS_REGEX = new RegExp(`[\\r\\n\\t${start}-${end}${del}]`, "g");
1658
+ var DANGEROUS_PROTOCOLS_REGEX = /^(javascript|data|vbscript):/i;
1659
+ var SanitizeHelper = Object.freeze({
1660
+ /**
1661
+ * @description Removes carriage returns, line feeds, null bytes, and non-printable control characters.
1662
+ * Mitigates Log Forging and Log Injection attacks (CWE-117).
1663
+ * @param value The candidate string to sanitize.
1664
+ * @param maxLength Maximum allowable length after sanitization. Defaults to 256.
1665
+ * @returns Sanitized string or undefined if empty/non-string.
1666
+ */
1667
+ stripControlChars(value, maxLength = 256) {
1668
+ if (Guards.isNullOrEmpty(value)) return void 0;
1669
+ const clean = value.replace(CONTROL_CHARS_REGEX, "").trim();
1670
+ if (Guards.isNullOrEmpty(clean)) return void 0;
1671
+ return clean.slice(0, maxLength);
1672
+ },
1673
+ /**
1674
+ * @description Sanitizes navigation paths and URLs, removing control characters
1675
+ * and preventing execution of dangerous pseudo-protocols (e.g. javascript:, data:).
1676
+ * @param path The path string to sanitize.
1677
+ * @param maxLength Maximum length of the path. Defaults to 512.
1678
+ * @returns Sanitized path or '/' fallback for unsafe inputs.
1679
+ */
1680
+ sanitizePath(path, maxLength = 512) {
1681
+ if (Guards.isNullOrEmpty(path)) return void 0;
1682
+ const clean = path.replace(CONTROL_CHARS_REGEX, "").trim();
1683
+ if (Guards.isNullOrEmpty(clean) || DANGEROUS_PROTOCOLS_REGEX.test(clean)) {
1684
+ return "/";
1685
+ }
1686
+ return clean.slice(0, maxLength);
1687
+ },
1688
+ /**
1689
+ * @description Sanitizes an array of strings (e.g. roles, permissions, scopes).
1690
+ * Strips control characters, filters out empty entries, and limits collection size.
1691
+ * @param items Array of strings to sanitize.
1692
+ * @param maxItemLength Maximum allowable character length per item. Defaults to 64.
1693
+ * @param maxItems Maximum total number of elements kept. Defaults to 50.
1694
+ * @returns Immutable array of sanitized strings.
1695
+ */
1696
+ sanitizeStringArray(items, maxItemLength = 64, maxItems = 50) {
1697
+ if (Guards.isNullOrEmpty(items)) return void 0;
1698
+ const sanitized = items.slice(0, maxItems).map((item) => SanitizeHelper.stripControlChars(item, maxItemLength)).filter((item) => Guards.isDefined(item));
1699
+ return sanitized;
1700
+ }
1701
+ });
1702
+
1703
+ // src/shared/utils/string.utils.ts
1704
+ var StringHelper = Object.freeze({
1705
+ /**
1706
+ * @description Safely converts a value to a JSON string, falling back to String() on failure.
1707
+ * @param value The value to stringify.
1708
+ * @returns A JSON string representation of the value, or a fallback string if serialization fails.
1709
+
1710
+ *
1711
+ * @author Xeno
1712
+ * @version 1.0.0
1713
+ * @since 2025-09-30
1714
+ * @link https://github.com/xeno-js/xeno-js
1715
+ */
1716
+ safeStringify(value) {
1717
+ try {
1718
+ return JSON.stringify(value);
1719
+ } catch {
1720
+ return String(value);
1721
+ }
1722
+ },
1723
+ /**
1724
+ * @description Safely parses a JSON string, returning a fallback value on failure.
1725
+ * @param input The JSON string to parse.
1726
+ * @param fallback Optional fallback value to return if parsing fails.
1727
+ * @returns The parsed value, or the fallback value if parsing fails.
1728
+
1729
+ *
1730
+ * @author Xeno
1731
+ * @version 1.0.0
1732
+ * @since 2025-09-30
1733
+ * @link https://github.com/xeno-js/xeno-js
1734
+ */
1735
+ safeParse(input, fallback = void 0) {
1736
+ try {
1737
+ return JSON.parse(input);
1738
+ } catch {
1739
+ return fallback ?? input;
1740
+ }
1741
+ },
1742
+ /**
1743
+ * @description Converts a string to camelCase.
1744
+ * @param input Input string (supports snake_case, kebab-case, or space-separated).
1745
+ * @returns camelCase string.
1746
+
1747
+ *
1748
+ * @author Xeno
1749
+ * @version 1.0.0
1750
+ * @since 2025-09-30
1751
+ * @link https://github.com/xeno-js/xeno-js
1752
+ */
1753
+ camelCase(input) {
1754
+ const segments = input.split(/[-_\s]+/);
1755
+ const [first, ...rest] = segments;
1756
+ const head = Guards.isDefined(first) ? first.toLowerCase() : "";
1757
+ return head + rest.map((seg) => seg.charAt(0).toUpperCase() + seg.slice(1)).join("");
1758
+ },
1759
+ /**
1760
+ * @description Interpolates {{key}} placeholders in a template string.
1761
+ * @param template Template string with {{key}} tokens.
1762
+ * @param vars Key-value substitution map.
1763
+ * @returns Interpolated string with resolved placeholders.
1764
+
1765
+ *
1766
+ * @author Xeno
1767
+ * @version 1.0.0
1768
+ * @since 2025-09-30
1769
+ * @link https://github.com/xeno-js/xeno-js
1770
+ */
1771
+ interpolate(template, vars) {
1772
+ return template.replace(/\{\{(\w+)\}\}/g, (_match, key) => {
1773
+ const value = vars[key];
1774
+ return Guards.isDefined(value) ? String(value) : `{{${key}}}`;
1775
+ });
1776
+ },
1777
+ /**
1778
+ * @description Truncates a string to maxLength, appending a suffix when truncated.
1779
+ * @param input Input string.
1780
+ * @param maxLength Maximum character length including the suffix.
1781
+ * @param suffix Appended suffix on truncation.
1782
+ * @returns Truncated string.
1783
+
1784
+ *
1785
+ * @author Xeno
1786
+ * @version 1.0.0
1787
+ * @since 2025-09-30
1788
+ * @link https://github.com/xeno-js/xeno-js
1789
+ */
1790
+ truncate(input, maxLength, suffix = "\u2026") {
1791
+ if (input.length <= maxLength) return input;
1792
+ const cutAt = Math.max(0, maxLength - suffix.length);
1793
+ return input.slice(0, cutAt) + suffix;
1794
+ },
1795
+ /**
1796
+ * @description Generates a reference code with a prefix, random alphanumeric part, and year.
1797
+ * @param prefix Custom prefix for the reference code (e.g., "TRV" for travel).
1798
+ * @returns Formatted reference code string.
1799
+
1800
+ *
1801
+ * @author Xeno
1802
+ * @version 1.0.0
1803
+ * @since 2025-09-30
1804
+ * @link https://github.com/xeno-js/xeno-js
1805
+ */
1806
+ generateReferenceCode(prefix) {
1807
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
1808
+ let randomPart = "";
1809
+ for (let i = 0; i < 6; i++) {
1810
+ randomPart += chars.charAt(Math.floor(Math.random() * chars.length));
1811
+ }
1812
+ const year = (/* @__PURE__ */ new Date()).getFullYear();
1813
+ return `${prefix}-${randomPart}-${year}`;
1814
+ },
1815
+ /**
1816
+ * @description Extracts a single string value from a header that may be a string or an array of strings.
1817
+ * @param value The header value, which can be a string or an array of strings.
1818
+ * @returns The first string value if it's an array, the string itself if it's a string, or undefined if it's empty or not defined.
1819
+
1820
+ *
1821
+ * @author Xeno
1822
+ * @version 1.0.0
1823
+ * @since 2025-09-30
1824
+ * @link https://github.com/xeno-js/xeno-js
1825
+ */
1826
+ getSingleValue(value, separator) {
1827
+ if (!Guards.isDefined(value)) return value;
1828
+ if (Guards.isArray(value)) {
1829
+ if (Guards.isNullOrEmpty(value)) {
1830
+ return void 0;
1831
+ }
1832
+ if (Guards.isDefined(separator))
1833
+ return StringHelper.getSingleValueWithSplit(value[0], separator);
1834
+ return value[0];
1835
+ }
1836
+ if (Guards.isDefined(separator)) return StringHelper.getSingleValueWithSplit(value, separator);
1837
+ return value;
1838
+ },
1839
+ getSingleValueWithSplit(value, separator) {
1840
+ if (value.includes(separator)) return value.split(separator)[0].trim();
1841
+ return value;
1842
+ }
1843
+ });
1844
+
1845
+ // src/infrastructure/auth/storage/cookie.storage.ts
1846
+ var createCookieStorage = (opts) => ({
1847
+ getItem: (key) => {
1848
+ if (!Guards.isDefined(document)) return null;
1849
+ const match = new RegExp(`(^| )${encodeURIComponent(key)}=([^;]+)`).exec(document.cookie);
1850
+ return Guards.isDefined(match) ? decodeURIComponent(match[2]) : null;
1851
+ },
1852
+ setItem: (key, value) => {
1853
+ if (!Guards.isDefined(document)) return;
1854
+ let cookieSuffix = "";
1855
+ if (Guards.isDefined(opts.path)) cookieSuffix += `; path=${opts.path}`;
1856
+ if (Guards.isDefined(opts.maxAge)) cookieSuffix += `; max-age=${opts.maxAge}`;
1857
+ if (Guards.isDefined(opts.domain)) cookieSuffix += `; domain=${opts.domain}`;
1858
+ if (Guards.isDefined(opts.secure)) cookieSuffix += `; Secure`;
1859
+ if (Guards.isDefined(opts.sameSite)) cookieSuffix += `; SameSite=${opts.sameSite}`;
1860
+ document.cookie = `${encodeURIComponent(key)}=${encodeURIComponent(value)}${cookieSuffix}`;
1861
+ },
1862
+ removeItem: (key) => {
1863
+ if (!Guards.isDefined(document)) return;
1864
+ document.cookie = `${encodeURIComponent(key)}=; path=${opts.path ?? "/"}; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
1865
+ }
1866
+ });
1867
+
1868
+ // src/infrastructure/auth/storage/memory.storage.ts
1869
+ var createMemoryStorage = () => {
1870
+ const store = /* @__PURE__ */ new Map();
1871
+ return {
1872
+ getItem: (key) => store.get(key) ?? null,
1873
+ setItem: (key, value) => {
1874
+ store.set(key, value);
1875
+ },
1876
+ removeItem: (key) => {
1877
+ store.delete(key);
1878
+ }
1879
+ };
1880
+ };
1881
+
1882
+ // src/infrastructure/auth/storage/storage.utils.ts
1883
+ var StorageHelper = Object.freeze({
1884
+ create(opts) {
1885
+ switch (opts.type) {
1886
+ case "memory":
1887
+ return createMemoryStorage();
1888
+ case "cookie":
1889
+ if (!Guards.isDefined(opts.cookieOpts)) throw new Error("At least ");
1890
+ return createCookieStorage(opts.cookieOpts);
1891
+ case "session":
1892
+ return sessionStorage;
1893
+ case "local":
1894
+ return localStorage;
1895
+ default:
1896
+ return opts.storage;
1897
+ }
1898
+ }
1899
+ });
1900
+
1901
+ // src/domain/errors/app-error.ts
1902
+ var AppError = class _AppError extends Error {
1903
+ /**
1904
+ * The error code representing the type of error.
1905
+
1906
+ *
1907
+ * @author Xeno
1908
+ * @version 1.0.0
1909
+ * @since 2025-09-30
1910
+ * @link https://github.com/xeno-js/xeno-js
1911
+ */
1912
+ code;
1913
+ /**
1914
+ * The HTTP status code associated with the error.
1915
+
1916
+ *
1917
+ * @author Xeno
1918
+ * @version 1.0.0
1919
+ * @since 2025-09-30
1920
+ * @link https://github.com/xeno-js/xeno-js
1921
+ */
1922
+ status;
1923
+ /**
1924
+ * Private constructor to prevent direct instantiation. Use the static methods `create` and `throw` to create instances.
1925
+ *
1926
+ * @param payload - The payload containing error details.
1927
+
1928
+ *
1929
+ * @author Xeno
1930
+ * @version 1.0.0
1931
+ * @since 2025-09-30
1932
+ * @link https://github.com/xeno-js/xeno-js
1933
+ */
1934
+ constructor(payload) {
1935
+ super(payload.message);
1936
+ this.code = payload.code;
1937
+ this.status = payload.status;
1938
+ Object.assign(this, payload);
1939
+ }
1940
+ /**
1941
+ * Creates an AppError instance with the given error payload.
1942
+ *
1943
+ * @param payload - The payload containing error details.
1944
+ * @returns An AppError instance representing the error.
1945
+
1946
+ *
1947
+ * @author Xeno
1948
+ * @version 1.0.0
1949
+ * @since 2025-09-30
1950
+ * @link https://github.com/xeno-js/xeno-js
1951
+ */
1952
+ static create(payload) {
1953
+ return new _AppError(payload);
1954
+ }
1955
+ /**
1956
+ * Creates an AppError instance and throws it immediately.
1957
+ * @param payload - The payload containing error details.
1958
+ * @throws An AppError instance representing the error.
1959
+
1960
+ *
1961
+ * @author Xeno
1962
+ * @version 1.0.0
1963
+ * @since 2025-09-30
1964
+ * @link https://github.com/xeno-js/xeno-js
1965
+ */
1966
+ static throw(payload) {
1967
+ throw new _AppError(payload);
1968
+ }
1969
+ /**
1970
+ * Creates an AppError instance representing an aborted request.
1971
+ * @param name - The name of the error, typically the class name or context where the error occurred.
1972
+ * @returns An AppError instance representing the aborted request error.
1973
+
1974
+ *
1975
+ * @author Xeno
1976
+ * @version 1.0.0
1977
+ * @since 2025-09-30
1978
+ * @link https://github.com/xeno-js/xeno-js
1979
+ */
1980
+ static aborted(name) {
1981
+ return new _AppError({
1982
+ code: ERROR_CODES.ABORTED,
1983
+ message: ERROR_CODE_MESSAGES[ERROR_CODES.ABORTED],
1984
+ status: STATUS_CODES.ABORTED,
1985
+ name,
1986
+ cause: new Error("The client closed the connection before the server finished responding.")
1987
+ });
1988
+ }
1989
+ /**
1990
+ * Utility method to check if an AbortSignal has been triggered and throw an AppError if it has.
1991
+ * @param signal - The AbortSignal to check for abortion.
1992
+ * @param name - The name of the error, typically the class name or context where the error occurred.
1993
+
1994
+ *
1995
+ * @author Xeno
1996
+ * @version 1.0.0
1997
+ * @since 2025-09-30
1998
+ * @link https://github.com/xeno-js/xeno-js
1999
+ */
2000
+ static throwIfAborted(signal, name) {
2001
+ if (Guards.isDefined(signal) && signal.aborted) {
2002
+ throw _AppError.aborted(name);
2003
+ }
2004
+ }
2005
+ /** @description Creates an AppError instance representing an unauthorized access error. This method is used to generate a standardized error response when a user attempts to access a resource or perform an action without the necessary authentication or authorization.
2006
+ * @param name The name of the error, typically the class name or context where the error occurred. This helps in identifying the source of the error in logs and error reports.
2007
+ * @param message A custom message describing the reason for the unauthorized access. This message is included in the AppError's cause for detailed error reporting.
2008
+ * @returns An AppError instance representing the unauthorized access error.
2009
+ *
2010
+ * @author Xeno
2011
+ * @version 1.0.0
2012
+ * @since 2025-09-30
2013
+ * @link https://github.com/xeno-js/xeno-js
2014
+ */
2015
+ static unauthorized(name, message) {
2016
+ return _AppError.create({
2017
+ code: ERROR_CODES.UNAUTHORIZED,
2018
+ message: ERROR_CODE_MESSAGES[ERROR_CODES.UNAUTHORIZED],
2019
+ status: STATUS_CODES.UNAUTHORIZED,
2020
+ name,
2021
+ cause: new Error(message),
2022
+ header: { "WWW-Authenticate": ['Bearer realm="api"'] }
2023
+ });
2024
+ }
2025
+ static notSupported(name, message) {
2026
+ return _AppError.create({
2027
+ code: ERROR_CODES.NOT_ALLOWED,
2028
+ message: ERROR_CODE_MESSAGES[ERROR_CODES.NOT_ALLOWED],
2029
+ status: STATUS_CODES.NOT_ALLOWED,
2030
+ name,
2031
+ cause: new Error(message)
2032
+ });
2033
+ }
2034
+ /** @description Creates an AppError instance representing a forbidden access error. This method is used to generate a standardized error response when a user attempts to access a resource or perform an action that they are not authorized to access, even if they are authenticated.
2035
+ * @param name The name of the error, typically the class name or context where the error occurred. This helps in identifying the source of the error in logs and error reports.
2036
+ * @param message A custom message describing the reason for the forbidden access. This message is included in the AppError's cause for detailed error reporting.
2037
+ * @returns An AppError instance representing the forbidden access error.
2038
+ *
2039
+ * @author Xeno
2040
+ * @version 1.0.0
2041
+ * @since 2025-09-30
2042
+ * @link https://github.com/xeno-js/xeno-js
2043
+ */
2044
+ static forbidden(name, message) {
2045
+ return _AppError.create({
2046
+ code: ERROR_CODES.FORBIDDEN,
2047
+ message: ERROR_CODE_MESSAGES[ERROR_CODES.FORBIDDEN],
2048
+ status: STATUS_CODES.FORBIDDEN,
2049
+ name,
2050
+ cause: new Error(message)
2051
+ });
2052
+ }
2053
+ /** @description Creates an AppError instance representing a bad request error. This method is used to generate a standardized error response when a request made by the client is invalid or cannot be processed due to client-side issues, such as validation errors or malformed requests.
2054
+ * @param name The name of the error, typically the class name or context where the error occurred. This helps in identifying the source of the error in logs and error reports.
2055
+ * @param message A custom message describing the reason for the bad request. This message is included in the AppError's cause for detailed error reporting.
2056
+ * @returns An AppError instance representing the bad request error.
2057
+ *
2058
+ * @author Xeno
2059
+ * @version 1.0.0
2060
+ * @since 2025-09-30
2061
+ * @link https://github.com/xeno-js/xeno-js
2062
+ */
2063
+ static badRequest(name, message) {
2064
+ return _AppError.create({
2065
+ code: ERROR_CODES.BAD_REQUEST,
2066
+ message: ERROR_CODE_MESSAGES[ERROR_CODES.BAD_REQUEST],
2067
+ status: STATUS_CODES.BAD_REQUEST,
2068
+ name,
2069
+ cause: new Error(message)
2070
+ });
2071
+ }
2072
+ /** @description Creates an AppError instance representing a validation error. This method is used to generate a standardized error response when one or more input fields fail invariant or schema validation, indicating that the request cannot be processed due to invalid data.
2073
+ * @param name The name of the error, typically the class name or context where the error occurred. This helps in identifying the source of the error in logs and error reports.
2074
+ * @param message A custom message describing the reason for the validation failure. This message is included in the AppError's cause for detailed error reporting.
2075
+ * @returns An AppError instance representing the validation error.
2076
+ *
2077
+ * @author Xeno
2078
+ * @version 1.0.0
2079
+ * @since 2025-09-30
2080
+ * @link https://github.com/xeno-js/xeno-js
2081
+ */
2082
+ static validationError(name, message) {
2083
+ return _AppError.create({
2084
+ code: ERROR_CODES.VALIDATION_FAILED,
2085
+ message: ERROR_CODE_MESSAGES[ERROR_CODES.VALIDATION_FAILED],
2086
+ status: STATUS_CODES.BAD_REQUEST,
2087
+ name,
2088
+ cause: new Error(message)
2089
+ });
2090
+ }
2091
+ /** @description Creates an AppError instance representing a conflict error. This method is used to generate a standardized error response when a request conflicts with the current state of the resource, such as when attempting to create a resource that already exists or update a resource that has been modified by another process.
2092
+ * @param name The name of the error, typically the class name or context where the error occurred. This helps in identifying the source of the error in logs and error reports.
2093
+ * @param message A custom message describing the reason for the conflict. This message is included in the AppError's cause for detailed error reporting.
2094
+ * @returns An AppError instance representing the conflict error.
2095
+ *
2096
+ * @author Xeno
2097
+ * @version 1.0.0
2098
+ * @since 2025-09-30
2099
+ * @link https://github.com/xeno-js/xeno-js
2100
+ */
2101
+ static conflict(name, message) {
2102
+ return _AppError.create({
2103
+ code: ERROR_CODES.CONFLICT,
2104
+ message: ERROR_CODE_MESSAGES[ERROR_CODES.CONFLICT],
2105
+ status: STATUS_CODES.CONFLICT,
2106
+ name,
2107
+ cause: new Error(message)
2108
+ });
2109
+ }
2110
+ /** @description Creates an AppError instance representing a not found error. This method is used to generate a standardized error response when a requested resource does not exist, indicating that the client attempted to access a resource that could not be found on the server.
2111
+ * @param name The name of the error, typically the class name or context where the error occurred. This helps in identifying the source of the error in logs and error reports.
2112
+ * @param message A custom message describing the reason for the not found error. This message is included in the AppError's cause for detailed error reporting.
2113
+ * @returns An AppError instance representing the not found error.
2114
+ *
2115
+ * @author Xeno
2116
+ * @version 1.0.0
2117
+ * @since 2025-09-30
2118
+ * @link https://github.com/xeno-js/xeno-js
2119
+ */
2120
+ static notFound(name, message) {
2121
+ return _AppError.create({
2122
+ code: ERROR_CODES.NOT_FOUND,
2123
+ message: ERROR_CODE_MESSAGES[ERROR_CODES.NOT_FOUND],
2124
+ status: STATUS_CODES.NOT_FOUND,
2125
+ name,
2126
+ cause: new Error(message)
2127
+ });
2128
+ }
2129
+ /** @description Creates an AppError instance representing a Authentication failed. This method is used to generate a standardized error response when an auth requested produce an error..
2130
+ * @param name The name of the error, typically the class name or context where the error occurred. This helps in identifying the source of the error in logs and error reports.
2131
+ * @param message A custom message describing the reason for the Authentication failed. This message is included in the AppError's cause for detailed error reporting.
2132
+ * @returns An AppError instance representing the Authentication failed.
2133
+ *
2134
+ * @author Xeno
2135
+ * @version 1.0.0
2136
+ * @since 2025-09-30
2137
+ * @link https://github.com/xeno-js/xeno-js
2138
+ */
2139
+ static authFailed(name, message) {
2140
+ return _AppError.create({
2141
+ code: ERROR_CODES.AUTHENTICATION_FAILED,
2142
+ message: ERROR_CODE_MESSAGES[ERROR_CODES.AUTHENTICATION_FAILED],
2143
+ name,
2144
+ status: STATUS_CODES.UNAUTHORIZED,
2145
+ cause: new Error(message)
2146
+ });
2147
+ }
2148
+ };
2149
+
2150
+ // src/domain/results/result.ts
2151
+ var Result = class _Result {
2152
+ /**
2153
+ * Indicates whether the operation was successful or not.
2154
+
2155
+ *
2156
+ * @author Xeno
2157
+ * @version 1.0.0
2158
+ * @since 2025-09-30
2159
+ * @link https://github.com/xeno-js/xeno-js
2160
+ */
2161
+ _isSuccess;
2162
+ /**
2163
+ * The error of the operation in case it failed.
2164
+
2165
+ *
2166
+ * @author Xeno
2167
+ * @version 1.0.0
2168
+ * @since 2025-09-30
2169
+ * @link https://github.com/xeno-js/xeno-js
2170
+ */
2171
+ _error;
2172
+ /**
2173
+ * The value of the operation in case it succeeded.
2174
+
2175
+ *
2176
+ * @author Xeno
2177
+ * @version 1.0.0
2178
+ * @since 2025-09-30
2179
+ * @link https://github.com/xeno-js/xeno-js
2180
+ */
2181
+ _value;
2182
+ /**
2183
+ * Private constructor to prevent direct instantiation. Use the static methods `ok` and `fail` to create instances.
2184
+ *
2185
+ * @param isSuccess - A boolean indicating whether the operation was successful.
2186
+ * @param error - The error of the operation in case it failed (optional).
2187
+ * @param value - The value of the operation in case it succeeded (optional).
2188
+
2189
+ *
2190
+ * @author Xeno
2191
+ * @version 1.0.0
2192
+ * @since 2025-09-30
2193
+ * @link https://github.com/xeno-js/xeno-js
2194
+ */
2195
+ constructor(isSuccess, error, value) {
2196
+ this._isSuccess = isSuccess;
2197
+ this._error = error;
2198
+ this._value = value;
2199
+ }
2200
+ /**
2201
+ * Creates a successful result with the given value.
2202
+ *
2203
+ * @param value - The value of the successful operation.
2204
+ * @returns A Result instance representing a successful operation.
2205
+
2206
+ *
2207
+ * @author Xeno
2208
+ * @version 1.0.0
2209
+ * @since 2025-09-30
2210
+ * @link https://github.com/xeno-js/xeno-js
2211
+ */
2212
+ static ok(value) {
2213
+ return new _Result(true, void 0, value);
2214
+ }
2215
+ /**
2216
+ * Creates a failed result with the given error.
2217
+ *
2218
+ * @param error - The error of the failed operation.
2219
+ * @returns A Result instance representing a failed operation.
2220
+
2221
+ *
2222
+ * @author Xeno
2223
+ * @version 1.0.0
2224
+ * @since 2025-09-30
2225
+ * @link https://github.com/xeno-js/xeno-js
2226
+ */
2227
+ static fail(error) {
2228
+ return new _Result(false, error, void 0);
2229
+ }
2230
+ /**
2231
+ * Checks if the result is a success.
2232
+ *
2233
+ * @returns True if the result is a success, false otherwise.
2234
+
2235
+ *
2236
+ * @author Xeno
2237
+ * @version 1.0.0
2238
+ * @since 2025-09-30
2239
+ * @link https://github.com/xeno-js/xeno-js
2240
+ */
2241
+ isOk() {
2242
+ return this._isSuccess;
2243
+ }
2244
+ /**
2245
+ * Gets the value of the result or throws an error if the result is a failure.
2246
+ *
2247
+ * @returns The value of the result.
2248
+ * @throws An error if the result is a failure.
2249
+
2250
+ *
2251
+ * @author Xeno
2252
+ * @version 1.0.0
2253
+ * @since 2025-09-30
2254
+ * @link https://github.com/xeno-js/xeno-js
2255
+ */
2256
+ getValueOrThrow() {
2257
+ if (!this._isSuccess) {
2258
+ throw new Error("Cannot get the value of a failed result.");
2259
+ }
2260
+ return this._value;
2261
+ }
2262
+ /**
2263
+ * Gets the error of the result or throws an error if the result is a success.
2264
+ *
2265
+ * @returns The error of the result.
2266
+ * @throws An error if the result is a success.
2267
+
2268
+ *
2269
+ * @author Xeno
2270
+ * @version 1.0.0
2271
+ * @since 2025-09-30
2272
+ * @link https://github.com/xeno-js/xeno-js
2273
+ */
2274
+ getErrorOrThrow() {
2275
+ if (this._isSuccess) {
2276
+ throw new Error("Cannot get the error of a successful result.");
2277
+ }
2278
+ return this._error;
2279
+ }
2280
+ };
2281
+
2282
+ // src/infrastructure/auth/supabase-auth.service.ts
2283
+ var SupabaseAuthService = class {
2284
+ constructor(_supabase, _mapper, _sessionMapper, _opts) {
2285
+ this._supabase = _supabase;
2286
+ this._mapper = _mapper;
2287
+ this._sessionMapper = _sessionMapper;
2288
+ this._opts = _opts;
2289
+ }
2290
+ _supabase;
2291
+ _mapper;
2292
+ _sessionMapper;
2293
+ _opts;
2294
+ async authenticate(token) {
2295
+ const { data, error } = await this._supabase.auth.getUser(token);
2296
+ if (Guards.isDefined(error) || !Guards.isDefined(data.user)) {
2297
+ return Result.fail(
2298
+ AppError.authFailed("SupabaseAuthenticationService", error?.message ?? "Unknown error")
2299
+ );
2300
+ }
2301
+ const user = data.user;
2302
+ const claims = this._mapper.map(user);
2303
+ return Result.ok(claims);
2304
+ }
2305
+ async isAuthenticated() {
2306
+ const session = await this._supabase.auth.getSession();
2307
+ return Guards.isDefined(session.data.session);
2308
+ }
2309
+ async exchangeCodeForSession(code) {
2310
+ const { data, error } = await this._supabase.auth.exchangeCodeForSession(code);
2311
+ if (Guards.isDefined(error) || !Guards.isDefined(data.session))
2312
+ return Result.fail(
2313
+ AppError.authFailed("SupabaseAuthenticationService", error?.message ?? "Unknown error")
2314
+ );
2315
+ const session = data.session;
2316
+ if (Guards.isDefined(session)) return Result.ok(this._sessionMapper.map(session));
2317
+ return Result.ok();
2318
+ }
2319
+ async signInWithProvider(provider) {
2320
+ const { data, error } = await this._supabase.auth.signInWithOAuth({
2321
+ provider,
2322
+ options: { redirectTo: this._opts.redirectTo }
2323
+ });
2324
+ if (Guards.isDefined(error) || Guards.isNullOrEmpty(data.url)) {
2325
+ return Result.fail(
2326
+ AppError.authFailed("SupabaseFrontendAuthService", error?.message ?? "Unexpected error")
2327
+ );
2328
+ }
2329
+ return Result.ok({ url: data.url });
2330
+ }
2331
+ async getSession() {
2332
+ const { data, error } = await this._supabase.auth.getSession();
2333
+ if (Guards.isDefined(error)) {
2334
+ return Result.fail(AppError.authFailed("SupabaseFrontendAuthService", error.message));
2335
+ }
2336
+ const session = data.session;
2337
+ if (Guards.isDefined(session)) return Result.ok(this._sessionMapper.map(data.session));
2338
+ return Result.ok();
2339
+ }
2340
+ async getUser() {
2341
+ const { data, error } = await this._supabase.auth.getUser();
2342
+ if (Guards.isDefined(error)) {
2343
+ return Result.fail(AppError.authFailed("SupabaseFrontendAuthService", error.message));
2344
+ }
2345
+ const user = data.user;
2346
+ if (Guards.isDefined(user)) return Result.ok(this._mapper.map(user));
2347
+ return Result.ok();
2348
+ }
2349
+ async signOut() {
2350
+ const { error } = await this._supabase.auth.signOut();
2351
+ if (Guards.isDefined(error)) {
2352
+ return Result.fail(AppError.authFailed("SupabaseFrontendAuthService", error.message));
2353
+ }
2354
+ return Result.ok();
2355
+ }
2356
+ async getSessionToken() {
2357
+ const sessionResult = await this.getSession();
2358
+ if (!sessionResult.isOk()) {
2359
+ return Result.fail(sessionResult.getErrorOrThrow());
2360
+ }
2361
+ const session = sessionResult.getValueOrThrow();
2362
+ return Result.ok(session?.accessToken);
2363
+ }
2364
+ };
2365
+
2366
+ // src/infrastructure/mappers/supabase-claims.mapper.ts
2367
+ var SupabaseClaimsMapper = class {
2368
+ map(user) {
2369
+ const appMetadata = user.app_metadata ?? {};
2370
+ return {
2371
+ sub: user.id,
2372
+ email: user.email,
2373
+ name: Guards.isString(user.user_metadata?.["name"]) ? user.user_metadata?.["name"] : void 0,
2374
+ tenantId: Guards.isString(appMetadata?.["tenant_id"]) ? appMetadata?.["tenant_id"] : void 0,
2375
+ roles: Guards.isArray(appMetadata["roles"]) ? appMetadata["roles"] : void 0,
2376
+ permissions: Guards.isArray(appMetadata["permissions"]) ? appMetadata["permissions"] : void 0
2377
+ };
2378
+ }
2379
+ };
2380
+
2381
+ // src/infrastructure/mappers/supabase-session.mapper.ts
2382
+ var SupabaseSessionMapper = class {
2383
+ constructor(_claimsMapper) {
2384
+ this._claimsMapper = _claimsMapper;
2385
+ }
2386
+ _claimsMapper;
2387
+ map(source) {
2388
+ const claims = this._claimsMapper.map(source.user);
2389
+ return {
2390
+ accessToken: source.access_token,
2391
+ refreshToken: source.refresh_token,
2392
+ expiresAt: source.expires_at,
2393
+ user: claims
2394
+ };
2395
+ }
2396
+ };
2397
+ export {
2398
+ SupabaseAuthService,
2399
+ SupabaseClaimsMapper,
2400
+ SupabaseSessionMapper
2401
+ };
2402
+ //# sourceMappingURL=supabase.js.map