wsp-ms-core 1.0.76 → 1.0.78-beta

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.
package/dist/index.cjs CHANGED
@@ -29,15 +29,16 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
29
29
  // src/index.ts
30
30
  var src_exports = {};
31
31
  __export(src_exports, {
32
+ BaseEvent: () => BaseEvent,
32
33
  BaseObject: () => BaseObject,
33
34
  BasicUnitOfWork: () => BasicUnitOfWork,
34
35
  BasicUnitOfWorkFactory: () => BasicUnitOfWorkFactory,
36
+ Country: () => Country,
35
37
  Currency: () => Currency,
36
38
  DateTime: () => DateTime,
37
39
  DomainEntity: () => DomainEntity,
38
40
  DomainError: () => DomainError,
39
41
  DomainEvent: () => DomainEvent,
40
- DomainEventStatus: () => DomainEventStatus,
41
42
  Email: () => Email,
42
43
  ErrorManager: () => ErrorManager,
43
44
  EventBus: () => EventBus,
@@ -47,14 +48,18 @@ __export(src_exports, {
47
48
  FatalError: () => FatalError,
48
49
  HttpHealthCheckController: () => HttpHealthCheckController,
49
50
  HttpNotFoundController: () => HttpNotFoundController,
51
+ IntegrationEvent: () => IntegrationEvent,
50
52
  InternalError: () => InternalError,
51
53
  KafkaManager: () => KafkaManager,
52
54
  Language: () => Language,
53
55
  MysqlConnection: () => MysqlConnection,
54
56
  MysqlConnector: () => MysqlConnector,
57
+ OutboxRecord: () => OutboxRecord,
55
58
  PaymentGateway: () => PaymentGateway,
56
59
  PaymentStatus: () => PaymentStatus,
57
60
  Price: () => Price,
61
+ ProcessStatus: () => ProcessStatus,
62
+ StringVars: () => StringVars,
58
63
  UUID: () => UUID,
59
64
  UsageError: () => UsageError,
60
65
  ValueObject: () => ValueObject,
@@ -168,6 +173,13 @@ var _DateTime = class _DateTime extends ValueObject {
168
173
  getWeekdayName(locale = "en") {
169
174
  return this._dt.setLocale(locale).toFormat("cccc");
170
175
  }
176
+ format(format) {
177
+ if (!_DateTime.FORMATS.hasOwnProperty(format)) {
178
+ throw new Error(`Invalid format: ${format}`);
179
+ }
180
+ const formatString = _DateTime.FORMATS[format];
181
+ return this._dt.toFormat(formatString);
182
+ }
171
183
  toPrimitives() {
172
184
  return {
173
185
  value: this.value
@@ -193,8 +205,59 @@ var _DateTime = class _DateTime extends ValueObject {
193
205
  }
194
206
  };
195
207
  _DateTime.DEFAULT_FORMAT = "yyyy-MM-dd HH:mm:ss";
208
+ _DateTime.FORMAT = "Y-M-D H:M:S";
209
+ _DateTime.FORMAT_Y_M = "Y-M";
210
+ _DateTime.FORMAT_Y_M_D = "Y-M-D";
211
+ _DateTime.FORMAT_Y_M_D_H_m_s = "Y-M-D H:M:S";
212
+ _DateTime.FORMAT_D_M_Y = "D-M-Y";
213
+ _DateTime.FORMATS = {
214
+ "Y-M": "yyyy-MM",
215
+ "Y-M-D": "yyyy-MM-dd",
216
+ "D/M/Y": "dd/MM/yyyy",
217
+ "Y/M/D": "yyyy/MM/dd",
218
+ "D-M-Y": "dd-MM-yyyy",
219
+ "Y.M.D": "yyyy.MM.dd",
220
+ "D.M.Y": "dd.MM.yyyy",
221
+ "Y-M-D H:M": "yyyy-MM-dd HH:mm",
222
+ "D/M/Y H:M": "dd/MM/yyyy HH:mm",
223
+ "Y/M/D H:M": "yyyy/MM/dd HH:mm",
224
+ "D-M-Y H:M": "dd-MM-yyyy HH:mm",
225
+ "Y.M.D H:M": "yyyy.MM.dd HH:mm",
226
+ "D.M.Y H:M": "dd.MM.yyyy HH:mm",
227
+ "Y-M-D H:M:S": "yyyy-MM-dd HH:mm:ss",
228
+ "Y-M-D H:M:S:SSS": "yyyy-MM-dd HH:mm:ss.SSS",
229
+ "D/M/Y H:M:S": "dd/MM/yyyy HH:mm:ss",
230
+ "Y/M/D H:M:S": "yyyy/MM/dd HH:mm:ss",
231
+ "D-M-Y H:M:S": "dd-MM-yyyy HH:mm:ss",
232
+ "Y.M.D H:M:S": "yyyy.MM.dd HH:mm:ss",
233
+ "D.M.Y H:M:S": "dd.MM.yyyy HH:mm:ss",
234
+ "H:M": "HH:mm",
235
+ "H:M:S": "HH:mm:ss"
236
+ };
196
237
  var DateTime = _DateTime;
197
238
 
239
+ // src/domain/contracts/BaseEvent.ts
240
+ var BaseEvent = class {
241
+ constructor(version, type, payload) {
242
+ this._version = version;
243
+ this._type = type;
244
+ this._payload = payload;
245
+ this._occurredAt = DateTime.now();
246
+ }
247
+ get version() {
248
+ return this._version;
249
+ }
250
+ get type() {
251
+ return this._type;
252
+ }
253
+ get payload() {
254
+ return this._payload;
255
+ }
256
+ get ocurredAt() {
257
+ return this._occurredAt;
258
+ }
259
+ };
260
+
198
261
  // src/domain/contracts/DomainEntity.ts
199
262
  var DomainEntity = class {
200
263
  constructor(props) {
@@ -229,6 +292,13 @@ var DomainEntity = class {
229
292
  }
230
293
  };
231
294
 
295
+ // src/domain/contracts/BaseObject.ts
296
+ var BaseObject = class {
297
+ constructor(props) {
298
+ this.props = props;
299
+ }
300
+ };
301
+
232
302
  // src/domain/contracts/DomainError.ts
233
303
  var DomainError = class extends Error {
234
304
  constructor(type, message = "") {
@@ -237,6 +307,13 @@ var DomainError = class extends Error {
237
307
  }
238
308
  };
239
309
 
310
+ // src/domain/errors/FatalError.ts
311
+ var FatalError = class extends DomainError {
312
+ constructor(type, message = "") {
313
+ super(type, message);
314
+ }
315
+ };
316
+
240
317
  // src/domain/errors/InternalError.ts
241
318
  var InternalError = class extends DomainError {
242
319
  constructor(type, message = "") {
@@ -244,201 +321,410 @@ var InternalError = class extends DomainError {
244
321
  }
245
322
  };
246
323
 
247
- // src/domain/value-objects/UUID.ts
248
- var crypto = __toESM(require("crypto"));
249
- var _UUID = class _UUID extends ValueObject {
250
- constructor(value) {
251
- super(value);
324
+ // src/domain/errors/UsageError.ts
325
+ var UsageError = class extends DomainError {
326
+ constructor(type, vars = {}) {
327
+ super(type);
328
+ this.vars = vars;
252
329
  }
253
- validate(uuid) {
254
- if (!_UUID.isValid(uuid)) {
255
- throw new InternalError(`Invalid uuid <${uuid}>`);
256
- }
330
+ };
331
+
332
+ // src/domain/events/DomainEvent.ts
333
+ var DomainEvent = class extends BaseEvent {
334
+ constructor(version, type, payload, aggregateUuid, aggregateType) {
335
+ super(version, type, payload);
336
+ this._aggregateUuid = aggregateUuid;
337
+ this._aggregateType = aggregateType;
257
338
  }
258
- toPrimitives() {
259
- return { value: this.value };
339
+ get aggregateUuid() {
340
+ return this._aggregateUuid;
260
341
  }
261
- static create(uuid) {
262
- return new _UUID(uuid ?? crypto.randomUUID());
342
+ get aggregateType() {
343
+ return this._aggregateType;
263
344
  }
264
- static version(uuid) {
265
- const m = /^[0-9a-f]{8}-[0-9a-f]{4}-([1-8])[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.exec(uuid);
266
- return m ? Number(m[1]) : void 0;
345
+ };
346
+
347
+ // src/domain/value-objects/payments/PaymentGateway.ts
348
+ var _PaymentGateway = class _PaymentGateway extends ValueObject {
349
+ constructor(gateway) {
350
+ super(gateway);
267
351
  }
268
- static isNil(uuid) {
269
- return /^0{8}-0{4}-0{4}-0{4}-0{12}$/i.test(uuid);
352
+ validate(value) {
353
+ if (!_PaymentGateway.SUPPORTED.includes(value)) {
354
+ throw new InternalError(`Payment gateway <${value}> is not supported`);
355
+ }
270
356
  }
271
- static isRFCStyle(uuid) {
272
- return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(uuid);
357
+ isExternal() {
358
+ return _PaymentGateway.EXTERNALS.includes(this.value);
273
359
  }
274
- static isValid(uuid, opts = {}) {
275
- const allowed = opts.allowedVersions ?? [1, 2, 3, 4, 5, 6, 7, 8];
276
- const allowNil = opts.allowNil ?? false;
277
- if (allowNil && _UUID.isNil(uuid))
278
- return true;
279
- if (!_UUID.isRFCStyle(uuid))
280
- return false;
281
- const v = _UUID.version(uuid);
282
- return !!v && allowed.includes(v);
360
+ toPrimitives() {
361
+ return { value: this.value };
362
+ }
363
+ static create(gateway) {
364
+ return new _PaymentGateway(gateway.trim().toUpperCase());
283
365
  }
284
366
  };
285
- _UUID.NIL = "00000000-0000-0000-0000-000000000000";
286
- var UUID = _UUID;
367
+ _PaymentGateway.SUPPORTED = [
368
+ "MERCADOPAGO",
369
+ "HANDY",
370
+ "WONA_DEBIT",
371
+ "WONA_CARD",
372
+ "WONA_CASH",
373
+ "WONA_TRANSFER",
374
+ "WONA_MERCADOPAGO"
375
+ ];
376
+ _PaymentGateway.EXTERNALS = ["MERCADOPAGO", "STRIPE"];
377
+ _PaymentGateway.MERCADOPAGO = new _PaymentGateway("MERCADOPAGO");
378
+ _PaymentGateway.HANDY = new _PaymentGateway("HANDY");
379
+ _PaymentGateway.WONA_DEBIT = new _PaymentGateway("WONA_DEBIT");
380
+ _PaymentGateway.WONA_CARD = new _PaymentGateway("WONA_CARD");
381
+ _PaymentGateway.WONA_CASH = new _PaymentGateway("WONA_CASH");
382
+ _PaymentGateway.WONA_TRANSFER = new _PaymentGateway("WONA_TRANSFER");
383
+ _PaymentGateway.WONA_MERCADOPAGO = new _PaymentGateway("WONA_MERCADOPAGO");
384
+ var PaymentGateway = _PaymentGateway;
287
385
 
288
- // src/domain/value-objects/DomainEventStatus.ts
289
- var _DomainEventStatus = class _DomainEventStatus extends ValueObject {
386
+ // src/domain/value-objects/payments/PaymentStatus.ts
387
+ var _PaymentStatus = class _PaymentStatus extends ValueObject {
290
388
  constructor(status) {
291
- super(status.trim().toUpperCase());
389
+ super(status);
292
390
  }
293
- validate(value) {
294
- if (!_DomainEventStatus.SUPPORTED.includes(value)) {
295
- throw new InternalError(`Domain event status <${value}> is not supported`);
391
+ validate(status) {
392
+ if (!_PaymentStatus.SUPPORTED.includes(status)) {
393
+ throw new InternalError(`Payment status <${status}> is not supported`);
296
394
  }
297
395
  }
396
+ get isDone() {
397
+ return this.value === "DONE";
398
+ }
399
+ get isPending() {
400
+ return this.value === "PENDING";
401
+ }
402
+ get isInProgress() {
403
+ return this.value === "IN_PROGRESS";
404
+ }
405
+ get isFailed() {
406
+ return this.value === "FAILED";
407
+ }
408
+ get isCanceled() {
409
+ return this.value === "CANCELED";
410
+ }
411
+ get isHold() {
412
+ return this.value === "HOLD";
413
+ }
414
+ get isPendingRefund() {
415
+ return this.value === "PENDING_REFUND";
416
+ }
417
+ get isRefunded() {
418
+ return this.value === "REFUNDED";
419
+ }
298
420
  toPrimitives() {
299
- return void 0;
421
+ return { value: this.value };
300
422
  }
301
- static create(status) {
302
- return new _DomainEventStatus(status);
423
+ static create(gateway) {
424
+ return new _PaymentStatus(gateway.trim().toUpperCase());
303
425
  }
304
426
  };
305
- _DomainEventStatus.SUPPORTED = ["PENDING", "PROCESSING", "PROCESSED", "FAILED", "DEAD"];
306
- _DomainEventStatus.PENDING = new _DomainEventStatus("PENDING");
307
- _DomainEventStatus.PROCESSING = new _DomainEventStatus("PROCESSING");
308
- _DomainEventStatus.PROCESSED = new _DomainEventStatus("PROCESSED");
309
- _DomainEventStatus.FAILED = new _DomainEventStatus("FAILED");
310
- _DomainEventStatus.DEAD = new _DomainEventStatus("DEAD");
311
- var DomainEventStatus = _DomainEventStatus;
427
+ _PaymentStatus.SUPPORTED = ["DONE", "PENDING", "FAILED", "CANCELED", "HOLD", "PENDING_REFUND", "REFUNDED", "IN_PROGRESS"];
428
+ _PaymentStatus.DONE = new _PaymentStatus("DONE");
429
+ _PaymentStatus.PENDING = new _PaymentStatus("PENDING");
430
+ _PaymentStatus.IN_PROGRESS = new _PaymentStatus("IN_PROGRESS");
431
+ _PaymentStatus.FAILED = new _PaymentStatus("FAILED");
432
+ _PaymentStatus.CANCELED = new _PaymentStatus("CANCELED");
433
+ _PaymentStatus.HOLD = new _PaymentStatus("HOLD");
434
+ _PaymentStatus.PENDING_REFUND = new _PaymentStatus("PENDING_REFUND");
435
+ _PaymentStatus.REFUNDED = new _PaymentStatus("REFUNDED");
436
+ var PaymentStatus = _PaymentStatus;
312
437
 
313
- // src/domain/contracts/DomainEvent.ts
314
- var DomainEvent = class _DomainEvent {
315
- constructor(eventUuid, eventType, tenantUuid, aggregateUuid, aggregateType, topic, payload, status, attempts, errorMessage, publishedAt, lastAttempt, createdAt) {
316
- this._eventUuid = eventUuid;
317
- this._tenantUuid = tenantUuid;
318
- this._aggregateUuid = aggregateUuid;
319
- this._aggregateType = aggregateType;
320
- this._eventType = eventType;
321
- this._topic = topic;
322
- this._payload = payload;
323
- this._status = status;
324
- this._attempts = attempts;
325
- this._errorMessage = errorMessage;
326
- this._publishedAt = publishedAt;
327
- this._lastAttempt = lastAttempt;
328
- this._createdAt = createdAt;
438
+ // src/utils/StringVars.ts
439
+ var StringVars = class {
440
+ static parse(str, ob) {
441
+ const regex = /{{(.*?)}}/g;
442
+ return str.replace(regex, (match, variable) => {
443
+ if (ob.hasOwnProperty(variable.trim())) {
444
+ return ob[variable.trim()];
445
+ } else {
446
+ return match;
447
+ }
448
+ });
329
449
  }
330
- get eventUuid() {
331
- return this._eventUuid;
450
+ };
451
+
452
+ // src/infrastructure/errors/ErrorManager.ts
453
+ var _ErrorManager = class _ErrorManager {
454
+ constructor(logger = null) {
455
+ this.logger = logger;
332
456
  }
333
- get tenantUuid() {
334
- return this._tenantUuid;
457
+ getDefaultMessage(lang) {
458
+ return _ErrorManager.DEFAULT_MESSAGES[lang.value] || _ErrorManager.DEFAULT_MESSAGES[lang.base()] || "error";
335
459
  }
336
- get aggregateUuid() {
337
- return this._aggregateUuid;
460
+ onFatal(err, lang) {
461
+ this.logger?.fatal(err.type, err.message);
462
+ return { status: "ERROR", message: this.getDefaultMessage(lang) };
338
463
  }
339
- get aggregateType() {
340
- return this._aggregateType;
464
+ onInternal(err, lang) {
465
+ this.logger?.error(err.type, err.message);
466
+ return { status: "ERROR", message: this.getDefaultMessage(lang) };
341
467
  }
342
- get eventType() {
343
- return this._eventType;
468
+ onUsage(err, lang) {
469
+ const tmpl = _ErrorManager.TEMPLATES.get(err.type);
470
+ if (!tmpl) {
471
+ this.logger?.error("TEMPLATE_NOT_FOUND", `${err.type}`);
472
+ return { status: "ERROR", message: this.getDefaultMessage(lang) };
473
+ }
474
+ const code = lang.value;
475
+ const base = lang.base();
476
+ const rawMsg = tmpl.languages[code] ?? tmpl.languages[base] ?? this.getDefaultMessage(lang);
477
+ return {
478
+ status: 400,
479
+ message: StringVars.parse(rawMsg, err.vars)
480
+ };
344
481
  }
345
- get topic() {
346
- return this._topic;
482
+ onUnknown(err, lang) {
483
+ this.logger?.error("UNKNOWN_ERROR", err.message);
484
+ return { status: "ERROR", message: this.getDefaultMessage(lang) };
347
485
  }
348
- get payload() {
349
- return this._payload;
486
+ handle(err, lang) {
487
+ if (["local", "dev"].includes(process.env.ENVIRONMENT ?? "")) {
488
+ console.log(err);
489
+ }
490
+ if (err instanceof FatalError) {
491
+ return this.onFatal(err, lang);
492
+ }
493
+ if (err instanceof InternalError) {
494
+ return this.onInternal(err, lang);
495
+ }
496
+ if (err instanceof UsageError) {
497
+ return this.onUsage(err, lang);
498
+ }
499
+ return this.onUnknown(err, lang);
350
500
  }
351
- get status() {
352
- return this._status;
501
+ static addTemplate(template) {
502
+ _ErrorManager.TEMPLATES.set(template.type, template);
353
503
  }
354
- get attempts() {
355
- return this._attempts;
504
+ };
505
+ _ErrorManager.DEFAULT_MESSAGES = {
506
+ "es": "Ups, hemos encontrado un error. Nuestro equipo ya est\xE1 trabajando para solucionarlo",
507
+ "en": "Ups, we found an error. Our team is working on it.",
508
+ "pt": "Ops, encontramos um bug. Nossa equipe j\xE1 est\xE1 trabalhando para resolver isso."
509
+ };
510
+ _ErrorManager.APP_ERRORS = {
511
+ UNDEFINED: "UNDEFINED_ERROR",
512
+ PROCESS: "PROCESS_ERROR",
513
+ DATABASE: "DATABASE_ERROR"
514
+ };
515
+ _ErrorManager.TEMPLATES = /* @__PURE__ */ new Map();
516
+ var ErrorManager = _ErrorManager;
517
+
518
+ // src/domain/value-objects/Country.ts
519
+ ErrorManager.addTemplate({
520
+ type: "INVALID_COUNTRY",
521
+ languages: {
522
+ "es": "El pa\xEDs <{{country}}> no es v\xE1lido o no est\xE1 soportado",
523
+ "en": "Country <{{country}}> is not valid or not supported"
356
524
  }
357
- get errorMessage() {
358
- return this._errorMessage;
525
+ });
526
+ ErrorManager.addTemplate({
527
+ type: "COUNTRY_NOT_FOUND_BY_ALPHA2",
528
+ languages: {
529
+ "es": "No se encontr\xF3 pa\xEDs con c\xF3digo alpha2 <{{alpha2}}>",
530
+ "en": "Country not found with alpha2 code <{{alpha2}}>"
359
531
  }
360
- get publishedAt() {
361
- return this._publishedAt;
532
+ });
533
+ ErrorManager.addTemplate({
534
+ type: "COUNTRY_NOT_FOUND_BY_UUID",
535
+ languages: {
536
+ "es": "No se encontr\xF3 pa\xEDs con UUID <{{uuid}}>",
537
+ "en": "Country not found with UUID <{{uuid}}>"
362
538
  }
363
- get lastAttempt() {
364
- return this._lastAttempt;
539
+ });
540
+ var _Country = class _Country extends ValueObject {
541
+ constructor(country) {
542
+ const normalizedCountry = country.toUpperCase().trim();
543
+ super(normalizedCountry);
544
+ this._name = normalizedCountry;
545
+ this._alpha2 = _Country.COUNTRIES[normalizedCountry].alpha2;
546
+ this._alpha3 = _Country.COUNTRIES[normalizedCountry].alpha3;
547
+ this._numeric = _Country.COUNTRIES[normalizedCountry].numeric;
548
+ this._uuid = _Country.COUNTRIES[normalizedCountry].uuid;
549
+ this._phoneCode = _Country.COUNTRIES[normalizedCountry].phoneCode;
550
+ this._url = _Country.COUNTRIES[normalizedCountry].url;
551
+ }
552
+ validate(country) {
553
+ if (!_Country.NAMES.includes(country)) {
554
+ throw new UsageError("INVALID_COUNTRY", { country });
555
+ }
365
556
  }
366
- get createdAt() {
367
- return this._createdAt;
557
+ name() {
558
+ return this._name;
368
559
  }
369
- incrementAttempts() {
370
- this._attempts++;
371
- this._lastAttempt = DateTime.now();
560
+ alpha2() {
561
+ return this._alpha2;
372
562
  }
373
- markProcessed() {
374
- this._status = DomainEventStatus.PROCESSED;
375
- this._publishedAt = DateTime.now();
563
+ alpha3() {
564
+ return this._alpha3;
376
565
  }
377
- markProcessing() {
378
- this.incrementAttempts();
379
- this._status = DomainEventStatus.PROCESSING;
566
+ numeric() {
567
+ return this._numeric;
380
568
  }
381
- markWithError(error) {
382
- this._status = this.attempts < 5 ? DomainEventStatus.FAILED : DomainEventStatus.DEAD;
383
- this._errorMessage = error;
569
+ uuid() {
570
+ return this._uuid;
571
+ }
572
+ phoneCode() {
573
+ return this._phoneCode;
574
+ }
575
+ url() {
576
+ return this._url;
577
+ }
578
+ static findCountryByAlpha2(alpha2) {
579
+ for (const [country, codes] of Object.entries(_Country.COUNTRIES)) {
580
+ if (codes.alpha2 === alpha2.toUpperCase()) {
581
+ return new _Country(country);
582
+ }
583
+ }
584
+ throw new UsageError("COUNTRY_NOT_FOUND_BY_ALPHA2", { alpha2 });
585
+ }
586
+ static findCountryByUUID(uuid) {
587
+ for (const [country, codes] of Object.entries(_Country.COUNTRIES)) {
588
+ if (codes.uuid === uuid) {
589
+ return new _Country(country);
590
+ }
591
+ }
592
+ throw new UsageError("COUNTRY_NOT_FOUND_BY_UUID", { uuid });
593
+ }
594
+ static create(country) {
595
+ return new _Country(country);
596
+ }
597
+ static createOrDefault(country) {
598
+ try {
599
+ return new _Country(country);
600
+ } catch (error) {
601
+ return _Country.DEFAULT;
602
+ }
384
603
  }
385
604
  toPrimitives() {
386
605
  return {
387
- eventUuid: this.eventUuid.value,
388
- eventType: this.eventType,
389
- tenantUuid: this.tenantUuid.value,
390
- aggregateUuid: this.aggregateUuid.value,
391
- aggregateType: this.aggregateType,
392
- topic: this.topic,
393
- payload: this.payload,
394
- status: this.status.value,
395
- attempts: this.attempts,
396
- errorMessage: this.errorMessage ?? void 0,
397
- publishedAt: this.publishedAt?.value ?? void 0,
398
- lastAttempt: this.lastAttempt?.value ?? void 0,
399
- createdAt: this.createdAt.value
606
+ value: this.value,
607
+ name: this._name,
608
+ alpha2: this._alpha2,
609
+ alpha3: this._alpha3,
610
+ numeric: this._numeric,
611
+ uuid: this._uuid,
612
+ phoneCode: this._phoneCode,
613
+ url: this._url
400
614
  };
401
615
  }
402
- static reconstitute(data) {
403
- return new _DomainEvent(
404
- UUID.create(data.event_uuid),
405
- String(data.event_type),
406
- UUID.create(data.tenant_uuid),
407
- UUID.create(data.aggregate_uuid),
408
- String(data.aggregate_type),
409
- String(data.topic),
410
- String(data.payload),
411
- DomainEventStatus.create(data.status),
412
- Number(data.attempts),
413
- data.error_message ?? void 0,
414
- data.published_at ? DateTime.create(data.published_at) : void 0,
415
- data.last_attempt ? DateTime.create(data.last_attempt) : void 0,
416
- data.created_at ? DateTime.create(data.created_at) : void 0
417
- );
418
- }
419
- };
420
-
421
- // src/domain/contracts/BaseObject.ts
422
- var BaseObject = class {
423
- constructor(props) {
424
- this.props = props;
425
- }
426
- };
427
-
428
- // src/domain/errors/FatalError.ts
429
- var FatalError = class extends DomainError {
430
- constructor(type, message = "") {
431
- super(type, message);
616
+ static isValid(country) {
617
+ try {
618
+ _Country.create(country);
619
+ return true;
620
+ } catch {
621
+ return false;
622
+ }
432
623
  }
433
624
  };
434
-
435
- // src/domain/errors/UsageError.ts
436
- var UsageError = class extends DomainError {
437
- constructor(type, vars = {}) {
438
- super(type);
439
- this.vars = vars;
625
+ _Country.COUNTRIES = {
626
+ URUGUAY: {
627
+ alpha2: "UY",
628
+ alpha3: "URY",
629
+ numeric: "858",
630
+ phoneCode: "+598",
631
+ uuid: "5739ecc0-d12b-4db5-8897-e03a04a95c72",
632
+ url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/uruguay.png"
633
+ },
634
+ ARGENTINA: {
635
+ alpha2: "AR",
636
+ alpha3: "ARG",
637
+ numeric: "032",
638
+ phoneCode: "+54",
639
+ uuid: "66663efe-ab7a-4166-b971-9f36fd0ea6b2",
640
+ url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/argentina.png"
641
+ },
642
+ ECUADOR: {
643
+ alpha2: "EC",
644
+ alpha3: "ECU",
645
+ numeric: "218",
646
+ phoneCode: "+593",
647
+ uuid: "ee109239-0150-4e5f-9ff2-a85f270092b1",
648
+ url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/ecuador.png"
649
+ },
650
+ PERU: {
651
+ alpha2: "PE",
652
+ alpha3: "PER",
653
+ numeric: "604",
654
+ phoneCode: "+51",
655
+ uuid: "e4d61ef5-b92d-4f9c-8ec1-23f4beb50abd",
656
+ url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/peru.png"
657
+ },
658
+ BRASIL: {
659
+ alpha2: "BR",
660
+ alpha3: "BRA",
661
+ numeric: "076",
662
+ phoneCode: "+55",
663
+ uuid: "b7b91d72-deaf-4641-957c-a65003e33104",
664
+ url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/brasil.png"
665
+ },
666
+ CHILE: {
667
+ alpha2: "CL",
668
+ alpha3: "CHL",
669
+ numeric: "152",
670
+ phoneCode: "+56",
671
+ uuid: "f69b35f4-d734-4c76-866c-29a18bf000fb",
672
+ url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/chile.png"
673
+ },
674
+ VENEZUELA: {
675
+ alpha2: "VE",
676
+ alpha3: "VEN",
677
+ numeric: "862",
678
+ phoneCode: "+58",
679
+ uuid: "31b6c591-63f6-43db-8ea9-829bb03746c5",
680
+ url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/venezuela.png"
681
+ },
682
+ COLOMBIA: {
683
+ alpha2: "CO",
684
+ alpha3: "COL",
685
+ numeric: "170",
686
+ phoneCode: "+57",
687
+ uuid: "6fdfe34b-6726-4604-96af-665ea5fc9239",
688
+ url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/colombia.png"
689
+ },
690
+ BOLIVIA: {
691
+ alpha2: "BO",
692
+ alpha3: "BOL",
693
+ numeric: "068",
694
+ phoneCode: "+591",
695
+ uuid: "948886db-c280-4ba7-a777-a76c180b295b",
696
+ url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/bolivia.png"
697
+ },
698
+ PARAGUAY: {
699
+ alpha2: "PY",
700
+ alpha3: "PRY",
701
+ numeric: "600",
702
+ phoneCode: "+595",
703
+ uuid: "d67b3472-e38d-4900-8ae3-02d99cd1d884",
704
+ url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/paraguay.png"
705
+ },
706
+ USA: {
707
+ alpha2: "US",
708
+ alpha3: "USA",
709
+ numeric: "840",
710
+ phoneCode: "+1",
711
+ uuid: "16ac3b9b-8f7b-4c54-91d5-d62c7cd74ad4",
712
+ url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/usa.png"
440
713
  }
441
714
  };
715
+ _Country.NAMES = Object.keys(_Country.COUNTRIES);
716
+ _Country.DEFAULT = new _Country("URUGUAY");
717
+ _Country.ARGENTINA = new _Country("ARGENTINA");
718
+ _Country.ECUADOR = new _Country("ECUADOR");
719
+ _Country.PERU = new _Country("PERU");
720
+ _Country.BRASIL = new _Country("BRASIL");
721
+ _Country.CHILE = new _Country("CHILE");
722
+ _Country.VENEZUELA = new _Country("VENEZUELA");
723
+ _Country.COLOMBIA = new _Country("COLOMBIA");
724
+ _Country.BOLIVIA = new _Country("BOLIVIA");
725
+ _Country.PARAGUAY = new _Country("PARAGUAY");
726
+ _Country.USA = new _Country("USA");
727
+ var Country = _Country;
442
728
 
443
729
  // src/domain/value-objects/Currency.ts
444
730
  var _Currency = class _Currency extends ValueObject {
@@ -602,109 +888,29 @@ _Language.ENGLISH_IRELAND = new _Language("en-ie");
602
888
  _Language.ENGLISH_SOUTH_AFRICA = new _Language("en-za");
603
889
  _Language.ENGLISH_JAMAICA = new _Language("en-jm");
604
890
  _Language.ENGLISH_BELIZE = new _Language("en-bz");
605
- _Language.ENGLISH_TRINIDAD = new _Language("en-tt");
606
- _Language.PORTUGUESE_BRAZIL = new _Language("pt-br");
607
- _Language.PORTUGUESE_PORTUGAL = new _Language("pt");
608
- _Language.SPANISH = new _Language("es");
609
- _Language.SPANISH_ARGENTINA = new _Language("es-ar");
610
- _Language.SPANISH_GUATEMALA = new _Language("es-gt");
611
- _Language.SPANISH_COSTA_RICA = new _Language("es-cr");
612
- _Language.SPANISH_PANAMA = new _Language("es-pa");
613
- _Language.SPANISH_REPUBLICA_DOMINICANA = new _Language("es-do");
614
- _Language.SPANISH_MEXICO = new _Language("es-mx");
615
- _Language.SPANISH_VENEZUELA = new _Language("es-ve");
616
- _Language.SPANISH_COLOMBIA = new _Language("es-co");
617
- _Language.SPANISH_PERU = new _Language("es-pe");
618
- _Language.SPANISH_ECUADOR = new _Language("es-ec");
619
- _Language.SPANISH_CHILE = new _Language("es-cl");
620
- _Language.SPANISH_URUGUAY = new _Language("es-uy");
621
- _Language.SPANISH_PARAGUAY = new _Language("es-py");
622
- _Language.SPANISH_BOLIVIA = new _Language("es-bo");
623
- _Language.SPANISH_EL_SALVADOR = new _Language("es-sv");
624
- _Language.SPANISH_HONDURAS = new _Language("es-hn");
625
- _Language.SPANISH_NICARAGUA = new _Language("es-ni");
626
- _Language.SPANISH_PUERTO_RICO = new _Language("es-pr");
627
- var Language = _Language;
628
-
629
- // src/utils/StringVars.ts
630
- var StringVars = class {
631
- static parse(str, ob) {
632
- const regex = /{{(.*?)}}/g;
633
- return str.replace(regex, (match, variable) => {
634
- if (ob.hasOwnProperty(variable.trim())) {
635
- return ob[variable.trim()];
636
- } else {
637
- return match;
638
- }
639
- });
640
- }
641
- };
642
-
643
- // src/infrastructure/errors/ErrorManager.ts
644
- var _ErrorManager = class _ErrorManager {
645
- constructor(logger = null) {
646
- this.logger = logger;
647
- }
648
- getDefaultMessage(lang) {
649
- return _ErrorManager.DEFAULT_MESSAGES[lang.value] || _ErrorManager.DEFAULT_MESSAGES[lang.base()] || "error";
650
- }
651
- onFatal(err, lang) {
652
- this.logger?.fatal(err.type, err.message);
653
- return { status: "ERROR", message: this.getDefaultMessage(lang) };
654
- }
655
- onInternal(err, lang) {
656
- this.logger?.error(err.type, err.message);
657
- return { status: "ERROR", message: this.getDefaultMessage(lang) };
658
- }
659
- onUsage(err, lang) {
660
- const tmpl = _ErrorManager.TEMPLATES.get(err.type);
661
- if (!tmpl) {
662
- this.logger?.error("TEMPLATE_NOT_FOUND", `${err.type}`);
663
- return { status: "ERROR", message: this.getDefaultMessage(lang) };
664
- }
665
- const code = lang.value;
666
- const base = lang.base();
667
- const rawMsg = tmpl.languages[code] ?? tmpl.languages[base] ?? this.getDefaultMessage(lang);
668
- return {
669
- status: 400,
670
- message: StringVars.parse(rawMsg, err.vars)
671
- };
672
- }
673
- onUnknown(err, lang) {
674
- this.logger?.error("UNKNOWN_ERROR", err.message);
675
- return { status: "ERROR", message: this.getDefaultMessage(lang) };
676
- }
677
- handle(err, lang) {
678
- if (["local", "dev"].includes(process.env.ENVIRONMENT ?? "")) {
679
- console.log(err);
680
- }
681
- if (err instanceof FatalError) {
682
- return this.onFatal(err, lang);
683
- }
684
- if (err instanceof InternalError) {
685
- return this.onInternal(err, lang);
686
- }
687
- if (err instanceof UsageError) {
688
- return this.onUsage(err, lang);
689
- }
690
- return this.onUnknown(err, lang);
691
- }
692
- static addTemplate(template) {
693
- _ErrorManager.TEMPLATES.set(template.type, template);
694
- }
695
- };
696
- _ErrorManager.DEFAULT_MESSAGES = {
697
- "es": "Ups, hemos encontrado un error. Nuestro equipo ya est\xE1 trabajando para solucionarlo",
698
- "en": "Ups, we found an error. Our team is working on it.",
699
- "pt": "Ops, encontramos um bug. Nossa equipe j\xE1 est\xE1 trabalhando para resolver isso."
700
- };
701
- _ErrorManager.APP_ERRORS = {
702
- UNDEFINED: "UNDEFINED_ERROR",
703
- PROCESS: "PROCESS_ERROR",
704
- DATABASE: "DATABASE_ERROR"
705
- };
706
- _ErrorManager.TEMPLATES = /* @__PURE__ */ new Map();
707
- var ErrorManager = _ErrorManager;
891
+ _Language.ENGLISH_TRINIDAD = new _Language("en-tt");
892
+ _Language.PORTUGUESE_BRAZIL = new _Language("pt-br");
893
+ _Language.PORTUGUESE_PORTUGAL = new _Language("pt");
894
+ _Language.SPANISH = new _Language("es");
895
+ _Language.SPANISH_ARGENTINA = new _Language("es-ar");
896
+ _Language.SPANISH_GUATEMALA = new _Language("es-gt");
897
+ _Language.SPANISH_COSTA_RICA = new _Language("es-cr");
898
+ _Language.SPANISH_PANAMA = new _Language("es-pa");
899
+ _Language.SPANISH_REPUBLICA_DOMINICANA = new _Language("es-do");
900
+ _Language.SPANISH_MEXICO = new _Language("es-mx");
901
+ _Language.SPANISH_VENEZUELA = new _Language("es-ve");
902
+ _Language.SPANISH_COLOMBIA = new _Language("es-co");
903
+ _Language.SPANISH_PERU = new _Language("es-pe");
904
+ _Language.SPANISH_ECUADOR = new _Language("es-ec");
905
+ _Language.SPANISH_CHILE = new _Language("es-cl");
906
+ _Language.SPANISH_URUGUAY = new _Language("es-uy");
907
+ _Language.SPANISH_PARAGUAY = new _Language("es-py");
908
+ _Language.SPANISH_BOLIVIA = new _Language("es-bo");
909
+ _Language.SPANISH_EL_SALVADOR = new _Language("es-sv");
910
+ _Language.SPANISH_HONDURAS = new _Language("es-hn");
911
+ _Language.SPANISH_NICARAGUA = new _Language("es-ni");
912
+ _Language.SPANISH_PUERTO_RICO = new _Language("es-pr");
913
+ var Language = _Language;
708
914
 
709
915
  // src/domain/value-objects/Price.ts
710
916
  ErrorManager.addTemplate({
@@ -776,111 +982,110 @@ _Price.MIN_AMOUNT = -1e6;
776
982
  _Price.MAX_AMOUNT = 1e9;
777
983
  var Price = _Price;
778
984
 
779
- // src/domain/value-objects/payments/PaymentGateway.ts
780
- var _PaymentGateway = class _PaymentGateway extends ValueObject {
781
- constructor(gateway) {
782
- super(gateway);
985
+ // src/domain/value-objects/ProcessStatus.ts
986
+ var _ProcessStatus = class _ProcessStatus extends ValueObject {
987
+ constructor(status) {
988
+ super(status.trim().toUpperCase());
783
989
  }
784
990
  validate(value) {
785
- if (!_PaymentGateway.SUPPORTED.includes(value)) {
786
- throw new InternalError(`Payment gateway <${value}> is not supported`);
991
+ if (!_ProcessStatus.SUPPORTED.includes(value)) {
992
+ throw new InternalError(`Domain event status <${value}> is not supported`);
787
993
  }
788
994
  }
789
- isExternal() {
790
- return _PaymentGateway.EXTERNALS.includes(this.value);
791
- }
792
995
  toPrimitives() {
793
- return { value: this.value };
996
+ return void 0;
794
997
  }
795
- static create(gateway) {
796
- return new _PaymentGateway(gateway.trim().toUpperCase());
998
+ static create(status) {
999
+ return new _ProcessStatus(status);
797
1000
  }
798
1001
  };
799
- _PaymentGateway.SUPPORTED = [
800
- "MERCADOPAGO",
801
- "HANDY",
802
- "WONA_DEBIT",
803
- "WONA_CARD",
804
- "WONA_CASH",
805
- "WONA_TRANSFER",
806
- "WONA_MERCADOPAGO"
807
- ];
808
- _PaymentGateway.EXTERNALS = ["MERCADOPAGO", "STRIPE"];
809
- _PaymentGateway.MERCADOPAGO = new _PaymentGateway("MERCADOPAGO");
810
- _PaymentGateway.HANDY = new _PaymentGateway("HANDY");
811
- _PaymentGateway.WONA_DEBIT = new _PaymentGateway("WONA_DEBIT");
812
- _PaymentGateway.WONA_CARD = new _PaymentGateway("WONA_CARD");
813
- _PaymentGateway.WONA_CASH = new _PaymentGateway("WONA_CASH");
814
- _PaymentGateway.WONA_TRANSFER = new _PaymentGateway("WONA_TRANSFER");
815
- _PaymentGateway.WONA_MERCADOPAGO = new _PaymentGateway("WONA_MERCADOPAGO");
816
- var PaymentGateway = _PaymentGateway;
1002
+ _ProcessStatus.SUPPORTED = ["PENDING", "PROCESSING", "PROCESSED", "FAILED", "DEAD"];
1003
+ _ProcessStatus.PENDING = new _ProcessStatus("PENDING");
1004
+ _ProcessStatus.PROCESSING = new _ProcessStatus("PROCESSING");
1005
+ _ProcessStatus.PROCESSED = new _ProcessStatus("PROCESSED");
1006
+ _ProcessStatus.FAILED = new _ProcessStatus("FAILED");
1007
+ _ProcessStatus.DEAD = new _ProcessStatus("DEAD");
1008
+ var ProcessStatus = _ProcessStatus;
817
1009
 
818
- // src/domain/value-objects/payments/PaymentStatus.ts
819
- var _PaymentStatus = class _PaymentStatus extends ValueObject {
820
- constructor(status) {
821
- super(status);
1010
+ // src/domain/value-objects/UUID.ts
1011
+ var crypto = __toESM(require("crypto"));
1012
+ var _UUID = class _UUID extends ValueObject {
1013
+ constructor(value) {
1014
+ super(value);
822
1015
  }
823
- validate(status) {
824
- if (!_PaymentStatus.SUPPORTED.includes(status)) {
825
- throw new InternalError(`Payment status <${status}> is not supported`);
1016
+ validate(uuid) {
1017
+ if (!_UUID.isValid(uuid)) {
1018
+ throw new InternalError(`Invalid uuid <${uuid}>`);
826
1019
  }
827
1020
  }
828
- get isDone() {
829
- return this.value === "DONE";
830
- }
831
- get isPending() {
832
- return this.value === "PENDING";
1021
+ toPrimitives() {
1022
+ return { value: this.value };
833
1023
  }
834
- get isInProgress() {
835
- return this.value === "IN_PROGRESS";
1024
+ static create(uuid) {
1025
+ return new _UUID(uuid ?? crypto.randomUUID());
836
1026
  }
837
- get isFailed() {
838
- return this.value === "FAILED";
1027
+ static version(uuid) {
1028
+ const m = /^[0-9a-f]{8}-[0-9a-f]{4}-([1-8])[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.exec(uuid);
1029
+ return m ? Number(m[1]) : void 0;
839
1030
  }
840
- get isCanceled() {
841
- return this.value === "CANCELED";
1031
+ static isNil(uuid) {
1032
+ return /^0{8}-0{4}-0{4}-0{4}-0{12}$/i.test(uuid);
842
1033
  }
843
- get isHold() {
844
- return this.value === "HOLD";
1034
+ static isRFCStyle(uuid) {
1035
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(uuid);
845
1036
  }
846
- get isPendingRefund() {
847
- return this.value === "PENDING_REFUND";
1037
+ static isValid(uuid, opts = {}) {
1038
+ const allowed = opts.allowedVersions ?? [1, 2, 3, 4, 5, 6, 7, 8];
1039
+ const allowNil = opts.allowNil ?? false;
1040
+ if (allowNil && _UUID.isNil(uuid))
1041
+ return true;
1042
+ if (!_UUID.isRFCStyle(uuid))
1043
+ return false;
1044
+ const v = _UUID.version(uuid);
1045
+ return !!v && allowed.includes(v);
848
1046
  }
849
- get isRefunded() {
850
- return this.value === "REFUNDED";
1047
+ };
1048
+ _UUID.NIL = "00000000-0000-0000-0000-000000000000";
1049
+ var UUID = _UUID;
1050
+
1051
+ // src/application/contracts/IntegrationEvent.ts
1052
+ var IntegrationEvent = class extends BaseEvent {
1053
+ constructor(version, type, payload, aggregateUuid, aggregateType) {
1054
+ super(version, type, payload);
1055
+ this._aggregateUuid = aggregateUuid;
1056
+ this._aggregateType = aggregateType;
851
1057
  }
852
- toPrimitives() {
853
- return { value: this.value };
1058
+ get aggregateUuid() {
1059
+ return this._aggregateUuid;
854
1060
  }
855
- static create(gateway) {
856
- return new _PaymentStatus(gateway.trim().toUpperCase());
1061
+ get aggregateType() {
1062
+ return this._aggregateType;
857
1063
  }
858
1064
  };
859
- _PaymentStatus.SUPPORTED = ["DONE", "PENDING", "FAILED", "CANCELED", "HOLD", "PENDING_REFUND", "REFUNDED", "IN_PROGRESS"];
860
- _PaymentStatus.DONE = new _PaymentStatus("DONE");
861
- _PaymentStatus.PENDING = new _PaymentStatus("PENDING");
862
- _PaymentStatus.IN_PROGRESS = new _PaymentStatus("IN_PROGRESS");
863
- _PaymentStatus.FAILED = new _PaymentStatus("FAILED");
864
- _PaymentStatus.CANCELED = new _PaymentStatus("CANCELED");
865
- _PaymentStatus.HOLD = new _PaymentStatus("HOLD");
866
- _PaymentStatus.PENDING_REFUND = new _PaymentStatus("PENDING_REFUND");
867
- _PaymentStatus.REFUNDED = new _PaymentStatus("REFUNDED");
868
- var PaymentStatus = _PaymentStatus;
869
1065
 
870
1066
  // src/application/event-bus/EventBus.ts
871
- var EventBus = class {
1067
+ var _EventBus = class _EventBus {
872
1068
  constructor(repository) {
873
1069
  this.repository = repository;
874
1070
  }
875
1071
  async publish(event) {
876
- await this.repository.create(event);
1072
+ const mapper = _EventBus.MAPPERS.get(event.type);
1073
+ if (!mapper) {
1074
+ throw new InternalError(ErrorManager.APP_ERRORS.PROCESS, `Eventbus mapper not found for <${event.type}>`);
1075
+ }
1076
+ await this.repository.create(mapper(event));
877
1077
  }
878
1078
  async publishMany(events) {
879
1079
  for (let event of events) {
880
1080
  await this.publish(event);
881
1081
  }
882
1082
  }
1083
+ static addMapper(eventType, mapper) {
1084
+ _EventBus.MAPPERS.set(eventType, mapper);
1085
+ }
883
1086
  };
1087
+ _EventBus.MAPPERS = /* @__PURE__ */ new Map();
1088
+ var EventBus = _EventBus;
884
1089
 
885
1090
  // src/application/unit-of-work/BasicUnitOfWork.ts
886
1091
  var BasicUnitOfWork = class {
@@ -970,104 +1175,164 @@ var EventManager = class {
970
1175
  }
971
1176
  };
972
1177
 
973
- // src/infrastructure/mysql/Mysql.ts
974
- var import_promise = require("mysql2/promise");
975
- var _MysqlConnector = class _MysqlConnector {
976
- constructor(pool) {
977
- this._pool = pool ?? (0, import_promise.createPool)({
978
- host: process.env.DB_HOST,
979
- port: Number(process.env.DB_PORT ?? 3306),
980
- user: process.env.DB_USER,
981
- password: process.env.DB_PASSWORD,
982
- database: process.env.DB_DATABASE,
983
- dateStrings: true,
984
- connectionLimit: Number(process.env.DB_POOL_SIZE) || _MysqlConnector.DEFAULT_POOL_SIZE,
985
- decimalNumbers: true
986
- });
1178
+ // src/infrastructure/contracts/OutboxRecord.ts
1179
+ var OutboxRecord = class _OutboxRecord {
1180
+ constructor(eventUuid, eventType, tenantUuid, aggregateUuid, aggregateType, topic, payload, status, attempts, errorMessage, publishedAt, lastAttempt, createdAt) {
1181
+ this._eventUuid = eventUuid;
1182
+ this._tenantUuid = tenantUuid;
1183
+ this._aggregateUuid = aggregateUuid;
1184
+ this._aggregateType = aggregateType;
1185
+ this._eventType = eventType;
1186
+ this._topic = topic;
1187
+ this._payload = payload;
1188
+ this._status = status;
1189
+ this._attempts = attempts;
1190
+ this._errorMessage = errorMessage;
1191
+ this._publishedAt = publishedAt;
1192
+ this._lastAttempt = lastAttempt;
1193
+ this._createdAt = createdAt;
987
1194
  }
988
- async wrap(conn) {
989
- return new MysqlConnection(conn);
1195
+ get eventUuid() {
1196
+ return this._eventUuid;
990
1197
  }
991
- async query(sql, params = []) {
992
- const [rows] = await this._pool.query(sql, params);
993
- return rows;
1198
+ get tenantUuid() {
1199
+ return this._tenantUuid;
994
1200
  }
995
- async getConnection() {
996
- const conn = await this._pool.getConnection();
997
- return this.wrap(conn);
1201
+ get aggregateUuid() {
1202
+ return this._aggregateUuid;
998
1203
  }
999
- async closePool() {
1000
- await this._pool.end();
1204
+ get aggregateType() {
1205
+ return this._aggregateType;
1001
1206
  }
1002
- static async ping() {
1003
- const connector = new _MysqlConnector();
1004
- try {
1005
- const conn = await connector._pool.getConnection();
1006
- await conn.ping();
1007
- conn.release();
1008
- return true;
1009
- } catch {
1010
- return false;
1011
- } finally {
1012
- await connector.closePool();
1013
- }
1207
+ get eventType() {
1208
+ return this._eventType;
1014
1209
  }
1015
- };
1016
- _MysqlConnector.DEFAULT_POOL_SIZE = 20;
1017
- var MysqlConnector = _MysqlConnector;
1018
- var MysqlConnection = class {
1019
- constructor(conn) {
1020
- this._conn = conn;
1210
+ get topic() {
1211
+ return this._topic;
1021
1212
  }
1022
- async query(statement, params = []) {
1023
- const [rows] = await this._conn.query(statement, params);
1024
- return rows;
1213
+ get payload() {
1214
+ return this._payload;
1025
1215
  }
1026
- async begin() {
1027
- await this._conn.beginTransaction();
1216
+ get status() {
1217
+ return this._status;
1028
1218
  }
1029
- async commit() {
1030
- await this._conn.commit();
1219
+ get attempts() {
1220
+ return this._attempts;
1031
1221
  }
1032
- async rollback() {
1033
- await this._conn.rollback();
1222
+ get errorMessage() {
1223
+ return this._errorMessage;
1034
1224
  }
1035
- async transaction(fn) {
1036
- await this.begin();
1037
- try {
1038
- const result = await fn(this);
1039
- await this.commit();
1040
- return result;
1041
- } catch (err) {
1042
- await this.rollback();
1043
- throw err;
1044
- }
1225
+ get publishedAt() {
1226
+ return this._publishedAt;
1227
+ }
1228
+ get lastAttempt() {
1229
+ return this._lastAttempt;
1230
+ }
1231
+ get createdAt() {
1232
+ return this._createdAt;
1233
+ }
1234
+ incrementAttempts() {
1235
+ this._attempts++;
1236
+ this._lastAttempt = DateTime.now();
1237
+ }
1238
+ markProcessed() {
1239
+ this._status = ProcessStatus.PROCESSED;
1240
+ this._publishedAt = DateTime.now();
1241
+ }
1242
+ markProcessing() {
1243
+ this.incrementAttempts();
1244
+ this._status = ProcessStatus.PROCESSING;
1245
+ }
1246
+ markWithError(error) {
1247
+ this._status = this.attempts < 5 ? ProcessStatus.FAILED : ProcessStatus.DEAD;
1248
+ this._errorMessage = error;
1249
+ }
1250
+ toPrimitives() {
1251
+ return {
1252
+ eventUuid: this.eventUuid.value,
1253
+ eventType: this.eventType,
1254
+ tenantUuid: this.tenantUuid.value,
1255
+ aggregateUuid: this.aggregateUuid.value,
1256
+ aggregateType: this.aggregateType,
1257
+ topic: this.topic,
1258
+ payload: this.payload,
1259
+ status: this.status.value,
1260
+ attempts: this.attempts,
1261
+ errorMessage: this.errorMessage ?? void 0,
1262
+ publishedAt: this.publishedAt?.value ?? void 0,
1263
+ lastAttempt: this.lastAttempt?.value ?? void 0,
1264
+ createdAt: this.createdAt.value
1265
+ };
1045
1266
  }
1046
- async close() {
1047
- await this._conn.release();
1267
+ static reconstitute(data) {
1268
+ return new _OutboxRecord(
1269
+ UUID.create(data.event_uuid),
1270
+ String(data.event_type),
1271
+ UUID.create(data.tenant_uuid),
1272
+ UUID.create(data.aggregate_uuid),
1273
+ String(data.aggregate_type),
1274
+ String(data.topic),
1275
+ String(data.payload),
1276
+ ProcessStatus.create(data.status),
1277
+ Number(data.attempts),
1278
+ data.error_message ?? void 0,
1279
+ data.published_at ? DateTime.create(data.published_at) : void 0,
1280
+ data.last_attempt ? DateTime.create(data.last_attempt) : void 0,
1281
+ data.created_at ? DateTime.create(data.created_at) : void 0
1282
+ );
1048
1283
  }
1049
1284
  };
1050
1285
 
1051
- // src/infrastructure/http/DefaultController.ts
1052
- var HttpHealthCheckController = class {
1053
- async handle(request) {
1054
- return {
1055
- statusCode: 200,
1056
- body: {
1057
- date: DateTime.create().value,
1058
- code: 200
1059
- }
1060
- };
1286
+ // src/infrastructure/event-bus/EventBusMysqlRepository.ts
1287
+ var EventBusMysqlRepository = class {
1288
+ constructor(connection) {
1289
+ this.connection = connection;
1061
1290
  }
1062
- };
1063
- var HttpNotFoundController = class {
1064
- async handle(request) {
1065
- return {
1066
- statusCode: 404,
1067
- body: {
1068
- message: `Route ${request.headers.location} not found`
1069
- }
1070
- };
1291
+ eventToRowValues(e) {
1292
+ return [
1293
+ e.eventUuid.value,
1294
+ e.eventType,
1295
+ e.tenantUuid.value,
1296
+ e.aggregateUuid.value,
1297
+ e.aggregateType,
1298
+ e.topic,
1299
+ e.payload,
1300
+ e.status.value,
1301
+ e.attempts,
1302
+ e.errorMessage,
1303
+ e.publishedAt?.value,
1304
+ e.lastAttempt?.value,
1305
+ e.createdAt.value
1306
+ ];
1307
+ }
1308
+ async create(event) {
1309
+ const values = this.eventToRowValues(event);
1310
+ await this.connection.query(
1311
+ `INSERT INTO events_outbox (event_uuid, event_type, tenant_uuid, aggregate_uuid, aggregate_type, topic,
1312
+ payload, status, attempts, error_message, published_at, last_attempt, created_at)
1313
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
1314
+ values
1315
+ );
1316
+ }
1317
+ async update(event) {
1318
+ const values = [event.status.value, event.attempts, event.errorMessage, event.publishedAt?.value, event.lastAttempt?.value, event.eventUuid.value];
1319
+ await this.connection.query(
1320
+ `UPDATE events_outbox
1321
+ SET status = ?,
1322
+ attempts = ?,
1323
+ error_message = ?,
1324
+ published_at = ?,
1325
+ last_attempt = ?
1326
+ WHERE event_uuid = ?`,
1327
+ values
1328
+ );
1329
+ }
1330
+ async listPending(limit) {
1331
+ const result = await this.connection.query(
1332
+ `SELECT * FROM events_outbox WHERE status IN ('PENDING','FAILED') AND published_at IS NULL LIMIT 50`,
1333
+ []
1334
+ );
1335
+ return result.length > 0 ? result.map((r) => OutboxRecord.reconstitute(r)) : [];
1071
1336
  }
1072
1337
  };
1073
1338
 
@@ -1201,56 +1466,26 @@ function adaptExpressErrorHandler(errorManager) {
1201
1466
  };
1202
1467
  }
1203
1468
 
1204
- // src/infrastructure/event-bus/EventBusMysqlRepository.ts
1205
- var EventBusMysqlRepository = class {
1206
- constructor(connection) {
1207
- this.connection = connection;
1208
- }
1209
- eventToRowValues(e) {
1210
- return [
1211
- e.eventUuid.value,
1212
- e.eventType,
1213
- e.tenantUuid.value,
1214
- e.aggregateUuid.value,
1215
- e.aggregateType,
1216
- e.topic,
1217
- e.payload,
1218
- e.status.value,
1219
- e.attempts,
1220
- e.errorMessage,
1221
- e.publishedAt?.value,
1222
- e.lastAttempt?.value,
1223
- e.createdAt.value
1224
- ];
1225
- }
1226
- async create(event) {
1227
- const values = this.eventToRowValues(event);
1228
- await this.connection.query(
1229
- `INSERT INTO events_outbox (event_uuid, event_type, tenant_uuid, aggregate_uuid, aggregate_type, topic,
1230
- payload, status, attempts, error_message, published_at, last_attempt, created_at)
1231
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
1232
- values
1233
- );
1234
- }
1235
- async update(event) {
1236
- const values = [event.status.value, event.attempts, event.errorMessage, event.publishedAt?.value, event.lastAttempt?.value, event.eventUuid.value];
1237
- await this.connection.query(
1238
- `UPDATE events_outbox
1239
- SET status = ?,
1240
- attempts = ?,
1241
- error_message = ?,
1242
- published_at = ?,
1243
- last_attempt = ?
1244
- WHERE event_uuid = ?`,
1245
- values
1246
- );
1469
+ // src/infrastructure/http/DefaultController.ts
1470
+ var HttpHealthCheckController = class {
1471
+ async handle(request) {
1472
+ return {
1473
+ statusCode: 200,
1474
+ body: {
1475
+ date: DateTime.create().value,
1476
+ code: 200
1477
+ }
1478
+ };
1247
1479
  }
1248
- async listPending(limit) {
1249
- const result = await this.connection.query(
1250
- `SELECT * FROM events_outbox WHERE status IN ('PENDING','FAILED') AND published_at IS NULL LIMIT 50`,
1251
- []
1252
- );
1253
- return result.length > 0 ? result.map((r) => DomainEvent.reconstitute(r)) : [];
1480
+ };
1481
+ var HttpNotFoundController = class {
1482
+ async handle(request) {
1483
+ return {
1484
+ statusCode: 404,
1485
+ body: {
1486
+ message: `Route ${request.headers.location} not found`
1487
+ }
1488
+ };
1254
1489
  }
1255
1490
  };
1256
1491
 
@@ -1291,8 +1526,7 @@ var KafkaManager = class extends EventManager {
1291
1526
  eachMessage: async ({ topic, partition, message, heartbeat }) => {
1292
1527
  try {
1293
1528
  await this.execCallback(this._onMessage, `[New message detected for ${topic}]: ${message.value?.toString()}`);
1294
- const evt = JSON.parse(String(message.value?.toString()));
1295
- await this.execRoute(topic, evt);
1529
+ await this.execRoute(topic, String(message.value?.toString()));
1296
1530
  const next = (BigInt(message.offset) + 1n).toString();
1297
1531
  await this.consumer.commitOffsets([{ topic, partition, offset: next }]);
1298
1532
  await heartbeat();
@@ -1308,28 +1542,12 @@ var KafkaManager = class extends EventManager {
1308
1542
  await this.execCallback(this._onError, new InternalError(ErrorManager.APP_ERRORS.PROCESS, error.toString()));
1309
1543
  }
1310
1544
  }
1311
- async send(message) {
1312
- if (!message.producer) {
1313
- message.producer = process.env.NAME && process.env.ENVIRONMENT ? `${process.env.NAME}-${process.env.ENVIRONMENT}` : "unknown";
1314
- }
1315
- if (!message.date) {
1316
- message.date = DateTime.now().value;
1317
- }
1318
- try {
1319
- if (!this.producer) {
1320
- throw new InternalError(ErrorManager.APP_ERRORS.PROCESS, "Producer not initialized");
1321
- }
1322
- await this.producer.connect();
1323
- await this.producer.send({
1324
- topic: message.topic,
1325
- messages: [{ value: JSON.stringify({ producer: message.producer, data: message }) }]
1326
- });
1327
- await this.producer.disconnect();
1328
- } catch (error) {
1329
- throw new InternalError(error.toString());
1330
- }
1331
- }
1332
- async sendRaw(message, topic) {
1545
+ async send(topic, message) {
1546
+ const evt = {
1547
+ date: DateTime.now().value,
1548
+ producer: process.env.NAME && process.env.ENVIRONMENT ? `${process.env.NAME}-${process.env.ENVIRONMENT}` : "unknown",
1549
+ data: message
1550
+ };
1333
1551
  try {
1334
1552
  if (!this.producer) {
1335
1553
  throw new InternalError(ErrorManager.APP_ERRORS.PROCESS, "Producer not initialized");
@@ -1337,7 +1555,7 @@ var KafkaManager = class extends EventManager {
1337
1555
  await this.producer.connect();
1338
1556
  await this.producer.send({
1339
1557
  topic,
1340
- messages: [{ value: message }]
1558
+ messages: [{ value: JSON.stringify(evt) }]
1341
1559
  });
1342
1560
  await this.producer.disconnect();
1343
1561
  } catch (error) {
@@ -1361,6 +1579,84 @@ var KafkaManager = class extends EventManager {
1361
1579
  }
1362
1580
  };
1363
1581
 
1582
+ // src/infrastructure/mysql/Mysql.ts
1583
+ var import_promise = require("mysql2/promise");
1584
+ var _MysqlConnector = class _MysqlConnector {
1585
+ constructor(pool) {
1586
+ this._pool = pool ?? (0, import_promise.createPool)({
1587
+ host: process.env.DB_HOST,
1588
+ port: Number(process.env.DB_PORT ?? 3306),
1589
+ user: process.env.DB_USER,
1590
+ password: process.env.DB_PASSWORD,
1591
+ database: process.env.DB_DATABASE,
1592
+ dateStrings: true,
1593
+ connectionLimit: Number(process.env.DB_POOL_SIZE) || _MysqlConnector.DEFAULT_POOL_SIZE,
1594
+ decimalNumbers: true
1595
+ });
1596
+ }
1597
+ async wrap(conn) {
1598
+ return new MysqlConnection(conn);
1599
+ }
1600
+ async query(sql, params = []) {
1601
+ const [rows] = await this._pool.query(sql, params);
1602
+ return rows;
1603
+ }
1604
+ async getConnection() {
1605
+ const conn = await this._pool.getConnection();
1606
+ return this.wrap(conn);
1607
+ }
1608
+ async closePool() {
1609
+ await this._pool.end();
1610
+ }
1611
+ static async ping() {
1612
+ const connector = new _MysqlConnector();
1613
+ try {
1614
+ const conn = await connector._pool.getConnection();
1615
+ await conn.ping();
1616
+ conn.release();
1617
+ return true;
1618
+ } catch {
1619
+ return false;
1620
+ } finally {
1621
+ await connector.closePool();
1622
+ }
1623
+ }
1624
+ };
1625
+ _MysqlConnector.DEFAULT_POOL_SIZE = 20;
1626
+ var MysqlConnector = _MysqlConnector;
1627
+ var MysqlConnection = class {
1628
+ constructor(conn) {
1629
+ this._conn = conn;
1630
+ }
1631
+ async query(statement, params = []) {
1632
+ const [rows] = await this._conn.query(statement, params);
1633
+ return rows;
1634
+ }
1635
+ async begin() {
1636
+ await this._conn.beginTransaction();
1637
+ }
1638
+ async commit() {
1639
+ await this._conn.commit();
1640
+ }
1641
+ async rollback() {
1642
+ await this._conn.rollback();
1643
+ }
1644
+ async transaction(fn) {
1645
+ await this.begin();
1646
+ try {
1647
+ const result = await fn(this);
1648
+ await this.commit();
1649
+ return result;
1650
+ } catch (err) {
1651
+ await this.rollback();
1652
+ throw err;
1653
+ }
1654
+ }
1655
+ async close() {
1656
+ await this._conn.release();
1657
+ }
1658
+ };
1659
+
1364
1660
  // src/utils/ExchangeRates.ts
1365
1661
  var ExchangeRates = class _ExchangeRates extends BaseObject {
1366
1662
  constructor(props) {
@@ -1414,15 +1710,16 @@ var ExchangeRates = class _ExchangeRates extends BaseObject {
1414
1710
  };
1415
1711
  // Annotate the CommonJS export names for ESM import in node:
1416
1712
  0 && (module.exports = {
1713
+ BaseEvent,
1417
1714
  BaseObject,
1418
1715
  BasicUnitOfWork,
1419
1716
  BasicUnitOfWorkFactory,
1717
+ Country,
1420
1718
  Currency,
1421
1719
  DateTime,
1422
1720
  DomainEntity,
1423
1721
  DomainError,
1424
1722
  DomainEvent,
1425
- DomainEventStatus,
1426
1723
  Email,
1427
1724
  ErrorManager,
1428
1725
  EventBus,
@@ -1432,14 +1729,18 @@ var ExchangeRates = class _ExchangeRates extends BaseObject {
1432
1729
  FatalError,
1433
1730
  HttpHealthCheckController,
1434
1731
  HttpNotFoundController,
1732
+ IntegrationEvent,
1435
1733
  InternalError,
1436
1734
  KafkaManager,
1437
1735
  Language,
1438
1736
  MysqlConnection,
1439
1737
  MysqlConnector,
1738
+ OutboxRecord,
1440
1739
  PaymentGateway,
1441
1740
  PaymentStatus,
1442
1741
  Price,
1742
+ ProcessStatus,
1743
+ StringVars,
1443
1744
  UUID,
1444
1745
  UsageError,
1445
1746
  ValueObject,