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.js CHANGED
@@ -103,6 +103,13 @@ var _DateTime = class _DateTime extends ValueObject {
103
103
  getWeekdayName(locale = "en") {
104
104
  return this._dt.setLocale(locale).toFormat("cccc");
105
105
  }
106
+ format(format) {
107
+ if (!_DateTime.FORMATS.hasOwnProperty(format)) {
108
+ throw new Error(`Invalid format: ${format}`);
109
+ }
110
+ const formatString = _DateTime.FORMATS[format];
111
+ return this._dt.toFormat(formatString);
112
+ }
106
113
  toPrimitives() {
107
114
  return {
108
115
  value: this.value
@@ -128,8 +135,59 @@ var _DateTime = class _DateTime extends ValueObject {
128
135
  }
129
136
  };
130
137
  _DateTime.DEFAULT_FORMAT = "yyyy-MM-dd HH:mm:ss";
138
+ _DateTime.FORMAT = "Y-M-D H:M:S";
139
+ _DateTime.FORMAT_Y_M = "Y-M";
140
+ _DateTime.FORMAT_Y_M_D = "Y-M-D";
141
+ _DateTime.FORMAT_Y_M_D_H_m_s = "Y-M-D H:M:S";
142
+ _DateTime.FORMAT_D_M_Y = "D-M-Y";
143
+ _DateTime.FORMATS = {
144
+ "Y-M": "yyyy-MM",
145
+ "Y-M-D": "yyyy-MM-dd",
146
+ "D/M/Y": "dd/MM/yyyy",
147
+ "Y/M/D": "yyyy/MM/dd",
148
+ "D-M-Y": "dd-MM-yyyy",
149
+ "Y.M.D": "yyyy.MM.dd",
150
+ "D.M.Y": "dd.MM.yyyy",
151
+ "Y-M-D H:M": "yyyy-MM-dd HH:mm",
152
+ "D/M/Y H:M": "dd/MM/yyyy HH:mm",
153
+ "Y/M/D H:M": "yyyy/MM/dd HH:mm",
154
+ "D-M-Y H:M": "dd-MM-yyyy HH:mm",
155
+ "Y.M.D H:M": "yyyy.MM.dd HH:mm",
156
+ "D.M.Y H:M": "dd.MM.yyyy HH:mm",
157
+ "Y-M-D H:M:S": "yyyy-MM-dd HH:mm:ss",
158
+ "Y-M-D H:M:S:SSS": "yyyy-MM-dd HH:mm:ss.SSS",
159
+ "D/M/Y H:M:S": "dd/MM/yyyy HH:mm:ss",
160
+ "Y/M/D H:M:S": "yyyy/MM/dd HH:mm:ss",
161
+ "D-M-Y H:M:S": "dd-MM-yyyy HH:mm:ss",
162
+ "Y.M.D H:M:S": "yyyy.MM.dd HH:mm:ss",
163
+ "D.M.Y H:M:S": "dd.MM.yyyy HH:mm:ss",
164
+ "H:M": "HH:mm",
165
+ "H:M:S": "HH:mm:ss"
166
+ };
131
167
  var DateTime = _DateTime;
132
168
 
169
+ // src/domain/contracts/BaseEvent.ts
170
+ var BaseEvent = class {
171
+ constructor(version, type, payload) {
172
+ this._version = version;
173
+ this._type = type;
174
+ this._payload = payload;
175
+ this._occurredAt = DateTime.now();
176
+ }
177
+ get version() {
178
+ return this._version;
179
+ }
180
+ get type() {
181
+ return this._type;
182
+ }
183
+ get payload() {
184
+ return this._payload;
185
+ }
186
+ get ocurredAt() {
187
+ return this._occurredAt;
188
+ }
189
+ };
190
+
133
191
  // src/domain/contracts/DomainEntity.ts
134
192
  var DomainEntity = class {
135
193
  constructor(props) {
@@ -164,6 +222,13 @@ var DomainEntity = class {
164
222
  }
165
223
  };
166
224
 
225
+ // src/domain/contracts/BaseObject.ts
226
+ var BaseObject = class {
227
+ constructor(props) {
228
+ this.props = props;
229
+ }
230
+ };
231
+
167
232
  // src/domain/contracts/DomainError.ts
168
233
  var DomainError = class extends Error {
169
234
  constructor(type, message = "") {
@@ -172,6 +237,13 @@ var DomainError = class extends Error {
172
237
  }
173
238
  };
174
239
 
240
+ // src/domain/errors/FatalError.ts
241
+ var FatalError = class extends DomainError {
242
+ constructor(type, message = "") {
243
+ super(type, message);
244
+ }
245
+ };
246
+
175
247
  // src/domain/errors/InternalError.ts
176
248
  var InternalError = class extends DomainError {
177
249
  constructor(type, message = "") {
@@ -179,201 +251,410 @@ var InternalError = class extends DomainError {
179
251
  }
180
252
  };
181
253
 
182
- // src/domain/value-objects/UUID.ts
183
- import * as crypto from "crypto";
184
- var _UUID = class _UUID extends ValueObject {
185
- constructor(value) {
186
- super(value);
254
+ // src/domain/errors/UsageError.ts
255
+ var UsageError = class extends DomainError {
256
+ constructor(type, vars = {}) {
257
+ super(type);
258
+ this.vars = vars;
187
259
  }
188
- validate(uuid) {
189
- if (!_UUID.isValid(uuid)) {
190
- throw new InternalError(`Invalid uuid <${uuid}>`);
191
- }
260
+ };
261
+
262
+ // src/domain/events/DomainEvent.ts
263
+ var DomainEvent = class extends BaseEvent {
264
+ constructor(version, type, payload, aggregateUuid, aggregateType) {
265
+ super(version, type, payload);
266
+ this._aggregateUuid = aggregateUuid;
267
+ this._aggregateType = aggregateType;
192
268
  }
193
- toPrimitives() {
194
- return { value: this.value };
269
+ get aggregateUuid() {
270
+ return this._aggregateUuid;
195
271
  }
196
- static create(uuid) {
197
- return new _UUID(uuid ?? crypto.randomUUID());
272
+ get aggregateType() {
273
+ return this._aggregateType;
198
274
  }
199
- static version(uuid) {
200
- 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);
201
- return m ? Number(m[1]) : void 0;
275
+ };
276
+
277
+ // src/domain/value-objects/payments/PaymentGateway.ts
278
+ var _PaymentGateway = class _PaymentGateway extends ValueObject {
279
+ constructor(gateway) {
280
+ super(gateway);
202
281
  }
203
- static isNil(uuid) {
204
- return /^0{8}-0{4}-0{4}-0{4}-0{12}$/i.test(uuid);
282
+ validate(value) {
283
+ if (!_PaymentGateway.SUPPORTED.includes(value)) {
284
+ throw new InternalError(`Payment gateway <${value}> is not supported`);
285
+ }
205
286
  }
206
- static isRFCStyle(uuid) {
207
- 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);
287
+ isExternal() {
288
+ return _PaymentGateway.EXTERNALS.includes(this.value);
208
289
  }
209
- static isValid(uuid, opts = {}) {
210
- const allowed = opts.allowedVersions ?? [1, 2, 3, 4, 5, 6, 7, 8];
211
- const allowNil = opts.allowNil ?? false;
212
- if (allowNil && _UUID.isNil(uuid))
213
- return true;
214
- if (!_UUID.isRFCStyle(uuid))
215
- return false;
216
- const v = _UUID.version(uuid);
217
- return !!v && allowed.includes(v);
290
+ toPrimitives() {
291
+ return { value: this.value };
292
+ }
293
+ static create(gateway) {
294
+ return new _PaymentGateway(gateway.trim().toUpperCase());
218
295
  }
219
296
  };
220
- _UUID.NIL = "00000000-0000-0000-0000-000000000000";
221
- var UUID = _UUID;
297
+ _PaymentGateway.SUPPORTED = [
298
+ "MERCADOPAGO",
299
+ "HANDY",
300
+ "WONA_DEBIT",
301
+ "WONA_CARD",
302
+ "WONA_CASH",
303
+ "WONA_TRANSFER",
304
+ "WONA_MERCADOPAGO"
305
+ ];
306
+ _PaymentGateway.EXTERNALS = ["MERCADOPAGO", "STRIPE"];
307
+ _PaymentGateway.MERCADOPAGO = new _PaymentGateway("MERCADOPAGO");
308
+ _PaymentGateway.HANDY = new _PaymentGateway("HANDY");
309
+ _PaymentGateway.WONA_DEBIT = new _PaymentGateway("WONA_DEBIT");
310
+ _PaymentGateway.WONA_CARD = new _PaymentGateway("WONA_CARD");
311
+ _PaymentGateway.WONA_CASH = new _PaymentGateway("WONA_CASH");
312
+ _PaymentGateway.WONA_TRANSFER = new _PaymentGateway("WONA_TRANSFER");
313
+ _PaymentGateway.WONA_MERCADOPAGO = new _PaymentGateway("WONA_MERCADOPAGO");
314
+ var PaymentGateway = _PaymentGateway;
222
315
 
223
- // src/domain/value-objects/DomainEventStatus.ts
224
- var _DomainEventStatus = class _DomainEventStatus extends ValueObject {
316
+ // src/domain/value-objects/payments/PaymentStatus.ts
317
+ var _PaymentStatus = class _PaymentStatus extends ValueObject {
225
318
  constructor(status) {
226
- super(status.trim().toUpperCase());
319
+ super(status);
227
320
  }
228
- validate(value) {
229
- if (!_DomainEventStatus.SUPPORTED.includes(value)) {
230
- throw new InternalError(`Domain event status <${value}> is not supported`);
321
+ validate(status) {
322
+ if (!_PaymentStatus.SUPPORTED.includes(status)) {
323
+ throw new InternalError(`Payment status <${status}> is not supported`);
231
324
  }
232
325
  }
326
+ get isDone() {
327
+ return this.value === "DONE";
328
+ }
329
+ get isPending() {
330
+ return this.value === "PENDING";
331
+ }
332
+ get isInProgress() {
333
+ return this.value === "IN_PROGRESS";
334
+ }
335
+ get isFailed() {
336
+ return this.value === "FAILED";
337
+ }
338
+ get isCanceled() {
339
+ return this.value === "CANCELED";
340
+ }
341
+ get isHold() {
342
+ return this.value === "HOLD";
343
+ }
344
+ get isPendingRefund() {
345
+ return this.value === "PENDING_REFUND";
346
+ }
347
+ get isRefunded() {
348
+ return this.value === "REFUNDED";
349
+ }
233
350
  toPrimitives() {
234
- return void 0;
351
+ return { value: this.value };
235
352
  }
236
- static create(status) {
237
- return new _DomainEventStatus(status);
353
+ static create(gateway) {
354
+ return new _PaymentStatus(gateway.trim().toUpperCase());
238
355
  }
239
356
  };
240
- _DomainEventStatus.SUPPORTED = ["PENDING", "PROCESSING", "PROCESSED", "FAILED", "DEAD"];
241
- _DomainEventStatus.PENDING = new _DomainEventStatus("PENDING");
242
- _DomainEventStatus.PROCESSING = new _DomainEventStatus("PROCESSING");
243
- _DomainEventStatus.PROCESSED = new _DomainEventStatus("PROCESSED");
244
- _DomainEventStatus.FAILED = new _DomainEventStatus("FAILED");
245
- _DomainEventStatus.DEAD = new _DomainEventStatus("DEAD");
246
- var DomainEventStatus = _DomainEventStatus;
357
+ _PaymentStatus.SUPPORTED = ["DONE", "PENDING", "FAILED", "CANCELED", "HOLD", "PENDING_REFUND", "REFUNDED", "IN_PROGRESS"];
358
+ _PaymentStatus.DONE = new _PaymentStatus("DONE");
359
+ _PaymentStatus.PENDING = new _PaymentStatus("PENDING");
360
+ _PaymentStatus.IN_PROGRESS = new _PaymentStatus("IN_PROGRESS");
361
+ _PaymentStatus.FAILED = new _PaymentStatus("FAILED");
362
+ _PaymentStatus.CANCELED = new _PaymentStatus("CANCELED");
363
+ _PaymentStatus.HOLD = new _PaymentStatus("HOLD");
364
+ _PaymentStatus.PENDING_REFUND = new _PaymentStatus("PENDING_REFUND");
365
+ _PaymentStatus.REFUNDED = new _PaymentStatus("REFUNDED");
366
+ var PaymentStatus = _PaymentStatus;
247
367
 
248
- // src/domain/contracts/DomainEvent.ts
249
- var DomainEvent = class _DomainEvent {
250
- constructor(eventUuid, eventType, tenantUuid, aggregateUuid, aggregateType, topic, payload, status, attempts, errorMessage, publishedAt, lastAttempt, createdAt) {
251
- this._eventUuid = eventUuid;
252
- this._tenantUuid = tenantUuid;
253
- this._aggregateUuid = aggregateUuid;
254
- this._aggregateType = aggregateType;
255
- this._eventType = eventType;
256
- this._topic = topic;
257
- this._payload = payload;
258
- this._status = status;
259
- this._attempts = attempts;
260
- this._errorMessage = errorMessage;
261
- this._publishedAt = publishedAt;
262
- this._lastAttempt = lastAttempt;
263
- this._createdAt = createdAt;
368
+ // src/utils/StringVars.ts
369
+ var StringVars = class {
370
+ static parse(str, ob) {
371
+ const regex = /{{(.*?)}}/g;
372
+ return str.replace(regex, (match, variable) => {
373
+ if (ob.hasOwnProperty(variable.trim())) {
374
+ return ob[variable.trim()];
375
+ } else {
376
+ return match;
377
+ }
378
+ });
264
379
  }
265
- get eventUuid() {
266
- return this._eventUuid;
380
+ };
381
+
382
+ // src/infrastructure/errors/ErrorManager.ts
383
+ var _ErrorManager = class _ErrorManager {
384
+ constructor(logger = null) {
385
+ this.logger = logger;
267
386
  }
268
- get tenantUuid() {
269
- return this._tenantUuid;
387
+ getDefaultMessage(lang) {
388
+ return _ErrorManager.DEFAULT_MESSAGES[lang.value] || _ErrorManager.DEFAULT_MESSAGES[lang.base()] || "error";
270
389
  }
271
- get aggregateUuid() {
272
- return this._aggregateUuid;
390
+ onFatal(err, lang) {
391
+ this.logger?.fatal(err.type, err.message);
392
+ return { status: "ERROR", message: this.getDefaultMessage(lang) };
273
393
  }
274
- get aggregateType() {
275
- return this._aggregateType;
394
+ onInternal(err, lang) {
395
+ this.logger?.error(err.type, err.message);
396
+ return { status: "ERROR", message: this.getDefaultMessage(lang) };
276
397
  }
277
- get eventType() {
278
- return this._eventType;
398
+ onUsage(err, lang) {
399
+ const tmpl = _ErrorManager.TEMPLATES.get(err.type);
400
+ if (!tmpl) {
401
+ this.logger?.error("TEMPLATE_NOT_FOUND", `${err.type}`);
402
+ return { status: "ERROR", message: this.getDefaultMessage(lang) };
403
+ }
404
+ const code = lang.value;
405
+ const base = lang.base();
406
+ const rawMsg = tmpl.languages[code] ?? tmpl.languages[base] ?? this.getDefaultMessage(lang);
407
+ return {
408
+ status: 400,
409
+ message: StringVars.parse(rawMsg, err.vars)
410
+ };
279
411
  }
280
- get topic() {
281
- return this._topic;
412
+ onUnknown(err, lang) {
413
+ this.logger?.error("UNKNOWN_ERROR", err.message);
414
+ return { status: "ERROR", message: this.getDefaultMessage(lang) };
282
415
  }
283
- get payload() {
284
- return this._payload;
416
+ handle(err, lang) {
417
+ if (["local", "dev"].includes(process.env.ENVIRONMENT ?? "")) {
418
+ console.log(err);
419
+ }
420
+ if (err instanceof FatalError) {
421
+ return this.onFatal(err, lang);
422
+ }
423
+ if (err instanceof InternalError) {
424
+ return this.onInternal(err, lang);
425
+ }
426
+ if (err instanceof UsageError) {
427
+ return this.onUsage(err, lang);
428
+ }
429
+ return this.onUnknown(err, lang);
285
430
  }
286
- get status() {
287
- return this._status;
431
+ static addTemplate(template) {
432
+ _ErrorManager.TEMPLATES.set(template.type, template);
288
433
  }
289
- get attempts() {
290
- return this._attempts;
434
+ };
435
+ _ErrorManager.DEFAULT_MESSAGES = {
436
+ "es": "Ups, hemos encontrado un error. Nuestro equipo ya est\xE1 trabajando para solucionarlo",
437
+ "en": "Ups, we found an error. Our team is working on it.",
438
+ "pt": "Ops, encontramos um bug. Nossa equipe j\xE1 est\xE1 trabalhando para resolver isso."
439
+ };
440
+ _ErrorManager.APP_ERRORS = {
441
+ UNDEFINED: "UNDEFINED_ERROR",
442
+ PROCESS: "PROCESS_ERROR",
443
+ DATABASE: "DATABASE_ERROR"
444
+ };
445
+ _ErrorManager.TEMPLATES = /* @__PURE__ */ new Map();
446
+ var ErrorManager = _ErrorManager;
447
+
448
+ // src/domain/value-objects/Country.ts
449
+ ErrorManager.addTemplate({
450
+ type: "INVALID_COUNTRY",
451
+ languages: {
452
+ "es": "El pa\xEDs <{{country}}> no es v\xE1lido o no est\xE1 soportado",
453
+ "en": "Country <{{country}}> is not valid or not supported"
291
454
  }
292
- get errorMessage() {
293
- return this._errorMessage;
455
+ });
456
+ ErrorManager.addTemplate({
457
+ type: "COUNTRY_NOT_FOUND_BY_ALPHA2",
458
+ languages: {
459
+ "es": "No se encontr\xF3 pa\xEDs con c\xF3digo alpha2 <{{alpha2}}>",
460
+ "en": "Country not found with alpha2 code <{{alpha2}}>"
294
461
  }
295
- get publishedAt() {
296
- return this._publishedAt;
462
+ });
463
+ ErrorManager.addTemplate({
464
+ type: "COUNTRY_NOT_FOUND_BY_UUID",
465
+ languages: {
466
+ "es": "No se encontr\xF3 pa\xEDs con UUID <{{uuid}}>",
467
+ "en": "Country not found with UUID <{{uuid}}>"
297
468
  }
298
- get lastAttempt() {
299
- return this._lastAttempt;
469
+ });
470
+ var _Country = class _Country extends ValueObject {
471
+ constructor(country) {
472
+ const normalizedCountry = country.toUpperCase().trim();
473
+ super(normalizedCountry);
474
+ this._name = normalizedCountry;
475
+ this._alpha2 = _Country.COUNTRIES[normalizedCountry].alpha2;
476
+ this._alpha3 = _Country.COUNTRIES[normalizedCountry].alpha3;
477
+ this._numeric = _Country.COUNTRIES[normalizedCountry].numeric;
478
+ this._uuid = _Country.COUNTRIES[normalizedCountry].uuid;
479
+ this._phoneCode = _Country.COUNTRIES[normalizedCountry].phoneCode;
480
+ this._url = _Country.COUNTRIES[normalizedCountry].url;
481
+ }
482
+ validate(country) {
483
+ if (!_Country.NAMES.includes(country)) {
484
+ throw new UsageError("INVALID_COUNTRY", { country });
485
+ }
300
486
  }
301
- get createdAt() {
302
- return this._createdAt;
487
+ name() {
488
+ return this._name;
303
489
  }
304
- incrementAttempts() {
305
- this._attempts++;
306
- this._lastAttempt = DateTime.now();
490
+ alpha2() {
491
+ return this._alpha2;
307
492
  }
308
- markProcessed() {
309
- this._status = DomainEventStatus.PROCESSED;
310
- this._publishedAt = DateTime.now();
493
+ alpha3() {
494
+ return this._alpha3;
311
495
  }
312
- markProcessing() {
313
- this.incrementAttempts();
314
- this._status = DomainEventStatus.PROCESSING;
496
+ numeric() {
497
+ return this._numeric;
315
498
  }
316
- markWithError(error) {
317
- this._status = this.attempts < 5 ? DomainEventStatus.FAILED : DomainEventStatus.DEAD;
318
- this._errorMessage = error;
499
+ uuid() {
500
+ return this._uuid;
501
+ }
502
+ phoneCode() {
503
+ return this._phoneCode;
504
+ }
505
+ url() {
506
+ return this._url;
507
+ }
508
+ static findCountryByAlpha2(alpha2) {
509
+ for (const [country, codes] of Object.entries(_Country.COUNTRIES)) {
510
+ if (codes.alpha2 === alpha2.toUpperCase()) {
511
+ return new _Country(country);
512
+ }
513
+ }
514
+ throw new UsageError("COUNTRY_NOT_FOUND_BY_ALPHA2", { alpha2 });
515
+ }
516
+ static findCountryByUUID(uuid) {
517
+ for (const [country, codes] of Object.entries(_Country.COUNTRIES)) {
518
+ if (codes.uuid === uuid) {
519
+ return new _Country(country);
520
+ }
521
+ }
522
+ throw new UsageError("COUNTRY_NOT_FOUND_BY_UUID", { uuid });
523
+ }
524
+ static create(country) {
525
+ return new _Country(country);
526
+ }
527
+ static createOrDefault(country) {
528
+ try {
529
+ return new _Country(country);
530
+ } catch (error) {
531
+ return _Country.DEFAULT;
532
+ }
319
533
  }
320
534
  toPrimitives() {
321
535
  return {
322
- eventUuid: this.eventUuid.value,
323
- eventType: this.eventType,
324
- tenantUuid: this.tenantUuid.value,
325
- aggregateUuid: this.aggregateUuid.value,
326
- aggregateType: this.aggregateType,
327
- topic: this.topic,
328
- payload: this.payload,
329
- status: this.status.value,
330
- attempts: this.attempts,
331
- errorMessage: this.errorMessage ?? void 0,
332
- publishedAt: this.publishedAt?.value ?? void 0,
333
- lastAttempt: this.lastAttempt?.value ?? void 0,
334
- createdAt: this.createdAt.value
536
+ value: this.value,
537
+ name: this._name,
538
+ alpha2: this._alpha2,
539
+ alpha3: this._alpha3,
540
+ numeric: this._numeric,
541
+ uuid: this._uuid,
542
+ phoneCode: this._phoneCode,
543
+ url: this._url
335
544
  };
336
545
  }
337
- static reconstitute(data) {
338
- return new _DomainEvent(
339
- UUID.create(data.event_uuid),
340
- String(data.event_type),
341
- UUID.create(data.tenant_uuid),
342
- UUID.create(data.aggregate_uuid),
343
- String(data.aggregate_type),
344
- String(data.topic),
345
- String(data.payload),
346
- DomainEventStatus.create(data.status),
347
- Number(data.attempts),
348
- data.error_message ?? void 0,
349
- data.published_at ? DateTime.create(data.published_at) : void 0,
350
- data.last_attempt ? DateTime.create(data.last_attempt) : void 0,
351
- data.created_at ? DateTime.create(data.created_at) : void 0
352
- );
353
- }
354
- };
355
-
356
- // src/domain/contracts/BaseObject.ts
357
- var BaseObject = class {
358
- constructor(props) {
359
- this.props = props;
360
- }
361
- };
362
-
363
- // src/domain/errors/FatalError.ts
364
- var FatalError = class extends DomainError {
365
- constructor(type, message = "") {
366
- super(type, message);
546
+ static isValid(country) {
547
+ try {
548
+ _Country.create(country);
549
+ return true;
550
+ } catch {
551
+ return false;
552
+ }
367
553
  }
368
554
  };
369
-
370
- // src/domain/errors/UsageError.ts
371
- var UsageError = class extends DomainError {
372
- constructor(type, vars = {}) {
373
- super(type);
374
- this.vars = vars;
555
+ _Country.COUNTRIES = {
556
+ URUGUAY: {
557
+ alpha2: "UY",
558
+ alpha3: "URY",
559
+ numeric: "858",
560
+ phoneCode: "+598",
561
+ uuid: "5739ecc0-d12b-4db5-8897-e03a04a95c72",
562
+ url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/uruguay.png"
563
+ },
564
+ ARGENTINA: {
565
+ alpha2: "AR",
566
+ alpha3: "ARG",
567
+ numeric: "032",
568
+ phoneCode: "+54",
569
+ uuid: "66663efe-ab7a-4166-b971-9f36fd0ea6b2",
570
+ url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/argentina.png"
571
+ },
572
+ ECUADOR: {
573
+ alpha2: "EC",
574
+ alpha3: "ECU",
575
+ numeric: "218",
576
+ phoneCode: "+593",
577
+ uuid: "ee109239-0150-4e5f-9ff2-a85f270092b1",
578
+ url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/ecuador.png"
579
+ },
580
+ PERU: {
581
+ alpha2: "PE",
582
+ alpha3: "PER",
583
+ numeric: "604",
584
+ phoneCode: "+51",
585
+ uuid: "e4d61ef5-b92d-4f9c-8ec1-23f4beb50abd",
586
+ url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/peru.png"
587
+ },
588
+ BRASIL: {
589
+ alpha2: "BR",
590
+ alpha3: "BRA",
591
+ numeric: "076",
592
+ phoneCode: "+55",
593
+ uuid: "b7b91d72-deaf-4641-957c-a65003e33104",
594
+ url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/brasil.png"
595
+ },
596
+ CHILE: {
597
+ alpha2: "CL",
598
+ alpha3: "CHL",
599
+ numeric: "152",
600
+ phoneCode: "+56",
601
+ uuid: "f69b35f4-d734-4c76-866c-29a18bf000fb",
602
+ url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/chile.png"
603
+ },
604
+ VENEZUELA: {
605
+ alpha2: "VE",
606
+ alpha3: "VEN",
607
+ numeric: "862",
608
+ phoneCode: "+58",
609
+ uuid: "31b6c591-63f6-43db-8ea9-829bb03746c5",
610
+ url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/venezuela.png"
611
+ },
612
+ COLOMBIA: {
613
+ alpha2: "CO",
614
+ alpha3: "COL",
615
+ numeric: "170",
616
+ phoneCode: "+57",
617
+ uuid: "6fdfe34b-6726-4604-96af-665ea5fc9239",
618
+ url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/colombia.png"
619
+ },
620
+ BOLIVIA: {
621
+ alpha2: "BO",
622
+ alpha3: "BOL",
623
+ numeric: "068",
624
+ phoneCode: "+591",
625
+ uuid: "948886db-c280-4ba7-a777-a76c180b295b",
626
+ url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/bolivia.png"
627
+ },
628
+ PARAGUAY: {
629
+ alpha2: "PY",
630
+ alpha3: "PRY",
631
+ numeric: "600",
632
+ phoneCode: "+595",
633
+ uuid: "d67b3472-e38d-4900-8ae3-02d99cd1d884",
634
+ url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/paraguay.png"
635
+ },
636
+ USA: {
637
+ alpha2: "US",
638
+ alpha3: "USA",
639
+ numeric: "840",
640
+ phoneCode: "+1",
641
+ uuid: "16ac3b9b-8f7b-4c54-91d5-d62c7cd74ad4",
642
+ url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/usa.png"
375
643
  }
376
644
  };
645
+ _Country.NAMES = Object.keys(_Country.COUNTRIES);
646
+ _Country.DEFAULT = new _Country("URUGUAY");
647
+ _Country.ARGENTINA = new _Country("ARGENTINA");
648
+ _Country.ECUADOR = new _Country("ECUADOR");
649
+ _Country.PERU = new _Country("PERU");
650
+ _Country.BRASIL = new _Country("BRASIL");
651
+ _Country.CHILE = new _Country("CHILE");
652
+ _Country.VENEZUELA = new _Country("VENEZUELA");
653
+ _Country.COLOMBIA = new _Country("COLOMBIA");
654
+ _Country.BOLIVIA = new _Country("BOLIVIA");
655
+ _Country.PARAGUAY = new _Country("PARAGUAY");
656
+ _Country.USA = new _Country("USA");
657
+ var Country = _Country;
377
658
 
378
659
  // src/domain/value-objects/Currency.ts
379
660
  var _Currency = class _Currency extends ValueObject {
@@ -537,109 +818,29 @@ _Language.ENGLISH_IRELAND = new _Language("en-ie");
537
818
  _Language.ENGLISH_SOUTH_AFRICA = new _Language("en-za");
538
819
  _Language.ENGLISH_JAMAICA = new _Language("en-jm");
539
820
  _Language.ENGLISH_BELIZE = new _Language("en-bz");
540
- _Language.ENGLISH_TRINIDAD = new _Language("en-tt");
541
- _Language.PORTUGUESE_BRAZIL = new _Language("pt-br");
542
- _Language.PORTUGUESE_PORTUGAL = new _Language("pt");
543
- _Language.SPANISH = new _Language("es");
544
- _Language.SPANISH_ARGENTINA = new _Language("es-ar");
545
- _Language.SPANISH_GUATEMALA = new _Language("es-gt");
546
- _Language.SPANISH_COSTA_RICA = new _Language("es-cr");
547
- _Language.SPANISH_PANAMA = new _Language("es-pa");
548
- _Language.SPANISH_REPUBLICA_DOMINICANA = new _Language("es-do");
549
- _Language.SPANISH_MEXICO = new _Language("es-mx");
550
- _Language.SPANISH_VENEZUELA = new _Language("es-ve");
551
- _Language.SPANISH_COLOMBIA = new _Language("es-co");
552
- _Language.SPANISH_PERU = new _Language("es-pe");
553
- _Language.SPANISH_ECUADOR = new _Language("es-ec");
554
- _Language.SPANISH_CHILE = new _Language("es-cl");
555
- _Language.SPANISH_URUGUAY = new _Language("es-uy");
556
- _Language.SPANISH_PARAGUAY = new _Language("es-py");
557
- _Language.SPANISH_BOLIVIA = new _Language("es-bo");
558
- _Language.SPANISH_EL_SALVADOR = new _Language("es-sv");
559
- _Language.SPANISH_HONDURAS = new _Language("es-hn");
560
- _Language.SPANISH_NICARAGUA = new _Language("es-ni");
561
- _Language.SPANISH_PUERTO_RICO = new _Language("es-pr");
562
- var Language = _Language;
563
-
564
- // src/utils/StringVars.ts
565
- var StringVars = class {
566
- static parse(str, ob) {
567
- const regex = /{{(.*?)}}/g;
568
- return str.replace(regex, (match, variable) => {
569
- if (ob.hasOwnProperty(variable.trim())) {
570
- return ob[variable.trim()];
571
- } else {
572
- return match;
573
- }
574
- });
575
- }
576
- };
577
-
578
- // src/infrastructure/errors/ErrorManager.ts
579
- var _ErrorManager = class _ErrorManager {
580
- constructor(logger = null) {
581
- this.logger = logger;
582
- }
583
- getDefaultMessage(lang) {
584
- return _ErrorManager.DEFAULT_MESSAGES[lang.value] || _ErrorManager.DEFAULT_MESSAGES[lang.base()] || "error";
585
- }
586
- onFatal(err, lang) {
587
- this.logger?.fatal(err.type, err.message);
588
- return { status: "ERROR", message: this.getDefaultMessage(lang) };
589
- }
590
- onInternal(err, lang) {
591
- this.logger?.error(err.type, err.message);
592
- return { status: "ERROR", message: this.getDefaultMessage(lang) };
593
- }
594
- onUsage(err, lang) {
595
- const tmpl = _ErrorManager.TEMPLATES.get(err.type);
596
- if (!tmpl) {
597
- this.logger?.error("TEMPLATE_NOT_FOUND", `${err.type}`);
598
- return { status: "ERROR", message: this.getDefaultMessage(lang) };
599
- }
600
- const code = lang.value;
601
- const base = lang.base();
602
- const rawMsg = tmpl.languages[code] ?? tmpl.languages[base] ?? this.getDefaultMessage(lang);
603
- return {
604
- status: 400,
605
- message: StringVars.parse(rawMsg, err.vars)
606
- };
607
- }
608
- onUnknown(err, lang) {
609
- this.logger?.error("UNKNOWN_ERROR", err.message);
610
- return { status: "ERROR", message: this.getDefaultMessage(lang) };
611
- }
612
- handle(err, lang) {
613
- if (["local", "dev"].includes(process.env.ENVIRONMENT ?? "")) {
614
- console.log(err);
615
- }
616
- if (err instanceof FatalError) {
617
- return this.onFatal(err, lang);
618
- }
619
- if (err instanceof InternalError) {
620
- return this.onInternal(err, lang);
621
- }
622
- if (err instanceof UsageError) {
623
- return this.onUsage(err, lang);
624
- }
625
- return this.onUnknown(err, lang);
626
- }
627
- static addTemplate(template) {
628
- _ErrorManager.TEMPLATES.set(template.type, template);
629
- }
630
- };
631
- _ErrorManager.DEFAULT_MESSAGES = {
632
- "es": "Ups, hemos encontrado un error. Nuestro equipo ya est\xE1 trabajando para solucionarlo",
633
- "en": "Ups, we found an error. Our team is working on it.",
634
- "pt": "Ops, encontramos um bug. Nossa equipe j\xE1 est\xE1 trabalhando para resolver isso."
635
- };
636
- _ErrorManager.APP_ERRORS = {
637
- UNDEFINED: "UNDEFINED_ERROR",
638
- PROCESS: "PROCESS_ERROR",
639
- DATABASE: "DATABASE_ERROR"
640
- };
641
- _ErrorManager.TEMPLATES = /* @__PURE__ */ new Map();
642
- var ErrorManager = _ErrorManager;
821
+ _Language.ENGLISH_TRINIDAD = new _Language("en-tt");
822
+ _Language.PORTUGUESE_BRAZIL = new _Language("pt-br");
823
+ _Language.PORTUGUESE_PORTUGAL = new _Language("pt");
824
+ _Language.SPANISH = new _Language("es");
825
+ _Language.SPANISH_ARGENTINA = new _Language("es-ar");
826
+ _Language.SPANISH_GUATEMALA = new _Language("es-gt");
827
+ _Language.SPANISH_COSTA_RICA = new _Language("es-cr");
828
+ _Language.SPANISH_PANAMA = new _Language("es-pa");
829
+ _Language.SPANISH_REPUBLICA_DOMINICANA = new _Language("es-do");
830
+ _Language.SPANISH_MEXICO = new _Language("es-mx");
831
+ _Language.SPANISH_VENEZUELA = new _Language("es-ve");
832
+ _Language.SPANISH_COLOMBIA = new _Language("es-co");
833
+ _Language.SPANISH_PERU = new _Language("es-pe");
834
+ _Language.SPANISH_ECUADOR = new _Language("es-ec");
835
+ _Language.SPANISH_CHILE = new _Language("es-cl");
836
+ _Language.SPANISH_URUGUAY = new _Language("es-uy");
837
+ _Language.SPANISH_PARAGUAY = new _Language("es-py");
838
+ _Language.SPANISH_BOLIVIA = new _Language("es-bo");
839
+ _Language.SPANISH_EL_SALVADOR = new _Language("es-sv");
840
+ _Language.SPANISH_HONDURAS = new _Language("es-hn");
841
+ _Language.SPANISH_NICARAGUA = new _Language("es-ni");
842
+ _Language.SPANISH_PUERTO_RICO = new _Language("es-pr");
843
+ var Language = _Language;
643
844
 
644
845
  // src/domain/value-objects/Price.ts
645
846
  ErrorManager.addTemplate({
@@ -711,111 +912,110 @@ _Price.MIN_AMOUNT = -1e6;
711
912
  _Price.MAX_AMOUNT = 1e9;
712
913
  var Price = _Price;
713
914
 
714
- // src/domain/value-objects/payments/PaymentGateway.ts
715
- var _PaymentGateway = class _PaymentGateway extends ValueObject {
716
- constructor(gateway) {
717
- super(gateway);
915
+ // src/domain/value-objects/ProcessStatus.ts
916
+ var _ProcessStatus = class _ProcessStatus extends ValueObject {
917
+ constructor(status) {
918
+ super(status.trim().toUpperCase());
718
919
  }
719
920
  validate(value) {
720
- if (!_PaymentGateway.SUPPORTED.includes(value)) {
721
- throw new InternalError(`Payment gateway <${value}> is not supported`);
921
+ if (!_ProcessStatus.SUPPORTED.includes(value)) {
922
+ throw new InternalError(`Domain event status <${value}> is not supported`);
722
923
  }
723
924
  }
724
- isExternal() {
725
- return _PaymentGateway.EXTERNALS.includes(this.value);
726
- }
727
925
  toPrimitives() {
728
- return { value: this.value };
926
+ return void 0;
729
927
  }
730
- static create(gateway) {
731
- return new _PaymentGateway(gateway.trim().toUpperCase());
928
+ static create(status) {
929
+ return new _ProcessStatus(status);
732
930
  }
733
931
  };
734
- _PaymentGateway.SUPPORTED = [
735
- "MERCADOPAGO",
736
- "HANDY",
737
- "WONA_DEBIT",
738
- "WONA_CARD",
739
- "WONA_CASH",
740
- "WONA_TRANSFER",
741
- "WONA_MERCADOPAGO"
742
- ];
743
- _PaymentGateway.EXTERNALS = ["MERCADOPAGO", "STRIPE"];
744
- _PaymentGateway.MERCADOPAGO = new _PaymentGateway("MERCADOPAGO");
745
- _PaymentGateway.HANDY = new _PaymentGateway("HANDY");
746
- _PaymentGateway.WONA_DEBIT = new _PaymentGateway("WONA_DEBIT");
747
- _PaymentGateway.WONA_CARD = new _PaymentGateway("WONA_CARD");
748
- _PaymentGateway.WONA_CASH = new _PaymentGateway("WONA_CASH");
749
- _PaymentGateway.WONA_TRANSFER = new _PaymentGateway("WONA_TRANSFER");
750
- _PaymentGateway.WONA_MERCADOPAGO = new _PaymentGateway("WONA_MERCADOPAGO");
751
- var PaymentGateway = _PaymentGateway;
932
+ _ProcessStatus.SUPPORTED = ["PENDING", "PROCESSING", "PROCESSED", "FAILED", "DEAD"];
933
+ _ProcessStatus.PENDING = new _ProcessStatus("PENDING");
934
+ _ProcessStatus.PROCESSING = new _ProcessStatus("PROCESSING");
935
+ _ProcessStatus.PROCESSED = new _ProcessStatus("PROCESSED");
936
+ _ProcessStatus.FAILED = new _ProcessStatus("FAILED");
937
+ _ProcessStatus.DEAD = new _ProcessStatus("DEAD");
938
+ var ProcessStatus = _ProcessStatus;
752
939
 
753
- // src/domain/value-objects/payments/PaymentStatus.ts
754
- var _PaymentStatus = class _PaymentStatus extends ValueObject {
755
- constructor(status) {
756
- super(status);
940
+ // src/domain/value-objects/UUID.ts
941
+ import * as crypto from "crypto";
942
+ var _UUID = class _UUID extends ValueObject {
943
+ constructor(value) {
944
+ super(value);
757
945
  }
758
- validate(status) {
759
- if (!_PaymentStatus.SUPPORTED.includes(status)) {
760
- throw new InternalError(`Payment status <${status}> is not supported`);
946
+ validate(uuid) {
947
+ if (!_UUID.isValid(uuid)) {
948
+ throw new InternalError(`Invalid uuid <${uuid}>`);
761
949
  }
762
950
  }
763
- get isDone() {
764
- return this.value === "DONE";
765
- }
766
- get isPending() {
767
- return this.value === "PENDING";
951
+ toPrimitives() {
952
+ return { value: this.value };
768
953
  }
769
- get isInProgress() {
770
- return this.value === "IN_PROGRESS";
954
+ static create(uuid) {
955
+ return new _UUID(uuid ?? crypto.randomUUID());
771
956
  }
772
- get isFailed() {
773
- return this.value === "FAILED";
957
+ static version(uuid) {
958
+ 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);
959
+ return m ? Number(m[1]) : void 0;
774
960
  }
775
- get isCanceled() {
776
- return this.value === "CANCELED";
961
+ static isNil(uuid) {
962
+ return /^0{8}-0{4}-0{4}-0{4}-0{12}$/i.test(uuid);
777
963
  }
778
- get isHold() {
779
- return this.value === "HOLD";
964
+ static isRFCStyle(uuid) {
965
+ 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);
780
966
  }
781
- get isPendingRefund() {
782
- return this.value === "PENDING_REFUND";
967
+ static isValid(uuid, opts = {}) {
968
+ const allowed = opts.allowedVersions ?? [1, 2, 3, 4, 5, 6, 7, 8];
969
+ const allowNil = opts.allowNil ?? false;
970
+ if (allowNil && _UUID.isNil(uuid))
971
+ return true;
972
+ if (!_UUID.isRFCStyle(uuid))
973
+ return false;
974
+ const v = _UUID.version(uuid);
975
+ return !!v && allowed.includes(v);
783
976
  }
784
- get isRefunded() {
785
- return this.value === "REFUNDED";
977
+ };
978
+ _UUID.NIL = "00000000-0000-0000-0000-000000000000";
979
+ var UUID = _UUID;
980
+
981
+ // src/application/contracts/IntegrationEvent.ts
982
+ var IntegrationEvent = class extends BaseEvent {
983
+ constructor(version, type, payload, aggregateUuid, aggregateType) {
984
+ super(version, type, payload);
985
+ this._aggregateUuid = aggregateUuid;
986
+ this._aggregateType = aggregateType;
786
987
  }
787
- toPrimitives() {
788
- return { value: this.value };
988
+ get aggregateUuid() {
989
+ return this._aggregateUuid;
789
990
  }
790
- static create(gateway) {
791
- return new _PaymentStatus(gateway.trim().toUpperCase());
991
+ get aggregateType() {
992
+ return this._aggregateType;
792
993
  }
793
994
  };
794
- _PaymentStatus.SUPPORTED = ["DONE", "PENDING", "FAILED", "CANCELED", "HOLD", "PENDING_REFUND", "REFUNDED", "IN_PROGRESS"];
795
- _PaymentStatus.DONE = new _PaymentStatus("DONE");
796
- _PaymentStatus.PENDING = new _PaymentStatus("PENDING");
797
- _PaymentStatus.IN_PROGRESS = new _PaymentStatus("IN_PROGRESS");
798
- _PaymentStatus.FAILED = new _PaymentStatus("FAILED");
799
- _PaymentStatus.CANCELED = new _PaymentStatus("CANCELED");
800
- _PaymentStatus.HOLD = new _PaymentStatus("HOLD");
801
- _PaymentStatus.PENDING_REFUND = new _PaymentStatus("PENDING_REFUND");
802
- _PaymentStatus.REFUNDED = new _PaymentStatus("REFUNDED");
803
- var PaymentStatus = _PaymentStatus;
804
995
 
805
996
  // src/application/event-bus/EventBus.ts
806
- var EventBus = class {
997
+ var _EventBus = class _EventBus {
807
998
  constructor(repository) {
808
999
  this.repository = repository;
809
1000
  }
810
1001
  async publish(event) {
811
- await this.repository.create(event);
1002
+ const mapper = _EventBus.MAPPERS.get(event.type);
1003
+ if (!mapper) {
1004
+ throw new InternalError(ErrorManager.APP_ERRORS.PROCESS, `Eventbus mapper not found for <${event.type}>`);
1005
+ }
1006
+ await this.repository.create(mapper(event));
812
1007
  }
813
1008
  async publishMany(events) {
814
1009
  for (let event of events) {
815
1010
  await this.publish(event);
816
1011
  }
817
1012
  }
1013
+ static addMapper(eventType, mapper) {
1014
+ _EventBus.MAPPERS.set(eventType, mapper);
1015
+ }
818
1016
  };
1017
+ _EventBus.MAPPERS = /* @__PURE__ */ new Map();
1018
+ var EventBus = _EventBus;
819
1019
 
820
1020
  // src/application/unit-of-work/BasicUnitOfWork.ts
821
1021
  var BasicUnitOfWork = class {
@@ -905,104 +1105,164 @@ var EventManager = class {
905
1105
  }
906
1106
  };
907
1107
 
908
- // src/infrastructure/mysql/Mysql.ts
909
- import { createPool } from "mysql2/promise";
910
- var _MysqlConnector = class _MysqlConnector {
911
- constructor(pool) {
912
- this._pool = pool ?? createPool({
913
- host: process.env.DB_HOST,
914
- port: Number(process.env.DB_PORT ?? 3306),
915
- user: process.env.DB_USER,
916
- password: process.env.DB_PASSWORD,
917
- database: process.env.DB_DATABASE,
918
- dateStrings: true,
919
- connectionLimit: Number(process.env.DB_POOL_SIZE) || _MysqlConnector.DEFAULT_POOL_SIZE,
920
- decimalNumbers: true
921
- });
1108
+ // src/infrastructure/contracts/OutboxRecord.ts
1109
+ var OutboxRecord = class _OutboxRecord {
1110
+ constructor(eventUuid, eventType, tenantUuid, aggregateUuid, aggregateType, topic, payload, status, attempts, errorMessage, publishedAt, lastAttempt, createdAt) {
1111
+ this._eventUuid = eventUuid;
1112
+ this._tenantUuid = tenantUuid;
1113
+ this._aggregateUuid = aggregateUuid;
1114
+ this._aggregateType = aggregateType;
1115
+ this._eventType = eventType;
1116
+ this._topic = topic;
1117
+ this._payload = payload;
1118
+ this._status = status;
1119
+ this._attempts = attempts;
1120
+ this._errorMessage = errorMessage;
1121
+ this._publishedAt = publishedAt;
1122
+ this._lastAttempt = lastAttempt;
1123
+ this._createdAt = createdAt;
922
1124
  }
923
- async wrap(conn) {
924
- return new MysqlConnection(conn);
1125
+ get eventUuid() {
1126
+ return this._eventUuid;
925
1127
  }
926
- async query(sql, params = []) {
927
- const [rows] = await this._pool.query(sql, params);
928
- return rows;
1128
+ get tenantUuid() {
1129
+ return this._tenantUuid;
929
1130
  }
930
- async getConnection() {
931
- const conn = await this._pool.getConnection();
932
- return this.wrap(conn);
1131
+ get aggregateUuid() {
1132
+ return this._aggregateUuid;
933
1133
  }
934
- async closePool() {
935
- await this._pool.end();
1134
+ get aggregateType() {
1135
+ return this._aggregateType;
936
1136
  }
937
- static async ping() {
938
- const connector = new _MysqlConnector();
939
- try {
940
- const conn = await connector._pool.getConnection();
941
- await conn.ping();
942
- conn.release();
943
- return true;
944
- } catch {
945
- return false;
946
- } finally {
947
- await connector.closePool();
948
- }
1137
+ get eventType() {
1138
+ return this._eventType;
949
1139
  }
950
- };
951
- _MysqlConnector.DEFAULT_POOL_SIZE = 20;
952
- var MysqlConnector = _MysqlConnector;
953
- var MysqlConnection = class {
954
- constructor(conn) {
955
- this._conn = conn;
1140
+ get topic() {
1141
+ return this._topic;
956
1142
  }
957
- async query(statement, params = []) {
958
- const [rows] = await this._conn.query(statement, params);
959
- return rows;
1143
+ get payload() {
1144
+ return this._payload;
960
1145
  }
961
- async begin() {
962
- await this._conn.beginTransaction();
1146
+ get status() {
1147
+ return this._status;
963
1148
  }
964
- async commit() {
965
- await this._conn.commit();
1149
+ get attempts() {
1150
+ return this._attempts;
966
1151
  }
967
- async rollback() {
968
- await this._conn.rollback();
1152
+ get errorMessage() {
1153
+ return this._errorMessage;
969
1154
  }
970
- async transaction(fn) {
971
- await this.begin();
972
- try {
973
- const result = await fn(this);
974
- await this.commit();
975
- return result;
976
- } catch (err) {
977
- await this.rollback();
978
- throw err;
979
- }
1155
+ get publishedAt() {
1156
+ return this._publishedAt;
1157
+ }
1158
+ get lastAttempt() {
1159
+ return this._lastAttempt;
1160
+ }
1161
+ get createdAt() {
1162
+ return this._createdAt;
1163
+ }
1164
+ incrementAttempts() {
1165
+ this._attempts++;
1166
+ this._lastAttempt = DateTime.now();
1167
+ }
1168
+ markProcessed() {
1169
+ this._status = ProcessStatus.PROCESSED;
1170
+ this._publishedAt = DateTime.now();
1171
+ }
1172
+ markProcessing() {
1173
+ this.incrementAttempts();
1174
+ this._status = ProcessStatus.PROCESSING;
1175
+ }
1176
+ markWithError(error) {
1177
+ this._status = this.attempts < 5 ? ProcessStatus.FAILED : ProcessStatus.DEAD;
1178
+ this._errorMessage = error;
1179
+ }
1180
+ toPrimitives() {
1181
+ return {
1182
+ eventUuid: this.eventUuid.value,
1183
+ eventType: this.eventType,
1184
+ tenantUuid: this.tenantUuid.value,
1185
+ aggregateUuid: this.aggregateUuid.value,
1186
+ aggregateType: this.aggregateType,
1187
+ topic: this.topic,
1188
+ payload: this.payload,
1189
+ status: this.status.value,
1190
+ attempts: this.attempts,
1191
+ errorMessage: this.errorMessage ?? void 0,
1192
+ publishedAt: this.publishedAt?.value ?? void 0,
1193
+ lastAttempt: this.lastAttempt?.value ?? void 0,
1194
+ createdAt: this.createdAt.value
1195
+ };
980
1196
  }
981
- async close() {
982
- await this._conn.release();
1197
+ static reconstitute(data) {
1198
+ return new _OutboxRecord(
1199
+ UUID.create(data.event_uuid),
1200
+ String(data.event_type),
1201
+ UUID.create(data.tenant_uuid),
1202
+ UUID.create(data.aggregate_uuid),
1203
+ String(data.aggregate_type),
1204
+ String(data.topic),
1205
+ String(data.payload),
1206
+ ProcessStatus.create(data.status),
1207
+ Number(data.attempts),
1208
+ data.error_message ?? void 0,
1209
+ data.published_at ? DateTime.create(data.published_at) : void 0,
1210
+ data.last_attempt ? DateTime.create(data.last_attempt) : void 0,
1211
+ data.created_at ? DateTime.create(data.created_at) : void 0
1212
+ );
983
1213
  }
984
1214
  };
985
1215
 
986
- // src/infrastructure/http/DefaultController.ts
987
- var HttpHealthCheckController = class {
988
- async handle(request) {
989
- return {
990
- statusCode: 200,
991
- body: {
992
- date: DateTime.create().value,
993
- code: 200
994
- }
995
- };
1216
+ // src/infrastructure/event-bus/EventBusMysqlRepository.ts
1217
+ var EventBusMysqlRepository = class {
1218
+ constructor(connection) {
1219
+ this.connection = connection;
996
1220
  }
997
- };
998
- var HttpNotFoundController = class {
999
- async handle(request) {
1000
- return {
1001
- statusCode: 404,
1002
- body: {
1003
- message: `Route ${request.headers.location} not found`
1004
- }
1005
- };
1221
+ eventToRowValues(e) {
1222
+ return [
1223
+ e.eventUuid.value,
1224
+ e.eventType,
1225
+ e.tenantUuid.value,
1226
+ e.aggregateUuid.value,
1227
+ e.aggregateType,
1228
+ e.topic,
1229
+ e.payload,
1230
+ e.status.value,
1231
+ e.attempts,
1232
+ e.errorMessage,
1233
+ e.publishedAt?.value,
1234
+ e.lastAttempt?.value,
1235
+ e.createdAt.value
1236
+ ];
1237
+ }
1238
+ async create(event) {
1239
+ const values = this.eventToRowValues(event);
1240
+ await this.connection.query(
1241
+ `INSERT INTO events_outbox (event_uuid, event_type, tenant_uuid, aggregate_uuid, aggregate_type, topic,
1242
+ payload, status, attempts, error_message, published_at, last_attempt, created_at)
1243
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
1244
+ values
1245
+ );
1246
+ }
1247
+ async update(event) {
1248
+ const values = [event.status.value, event.attempts, event.errorMessage, event.publishedAt?.value, event.lastAttempt?.value, event.eventUuid.value];
1249
+ await this.connection.query(
1250
+ `UPDATE events_outbox
1251
+ SET status = ?,
1252
+ attempts = ?,
1253
+ error_message = ?,
1254
+ published_at = ?,
1255
+ last_attempt = ?
1256
+ WHERE event_uuid = ?`,
1257
+ values
1258
+ );
1259
+ }
1260
+ async listPending(limit) {
1261
+ const result = await this.connection.query(
1262
+ `SELECT * FROM events_outbox WHERE status IN ('PENDING','FAILED') AND published_at IS NULL LIMIT 50`,
1263
+ []
1264
+ );
1265
+ return result.length > 0 ? result.map((r) => OutboxRecord.reconstitute(r)) : [];
1006
1266
  }
1007
1267
  };
1008
1268
 
@@ -1136,56 +1396,26 @@ function adaptExpressErrorHandler(errorManager) {
1136
1396
  };
1137
1397
  }
1138
1398
 
1139
- // src/infrastructure/event-bus/EventBusMysqlRepository.ts
1140
- var EventBusMysqlRepository = class {
1141
- constructor(connection) {
1142
- this.connection = connection;
1143
- }
1144
- eventToRowValues(e) {
1145
- return [
1146
- e.eventUuid.value,
1147
- e.eventType,
1148
- e.tenantUuid.value,
1149
- e.aggregateUuid.value,
1150
- e.aggregateType,
1151
- e.topic,
1152
- e.payload,
1153
- e.status.value,
1154
- e.attempts,
1155
- e.errorMessage,
1156
- e.publishedAt?.value,
1157
- e.lastAttempt?.value,
1158
- e.createdAt.value
1159
- ];
1160
- }
1161
- async create(event) {
1162
- const values = this.eventToRowValues(event);
1163
- await this.connection.query(
1164
- `INSERT INTO events_outbox (event_uuid, event_type, tenant_uuid, aggregate_uuid, aggregate_type, topic,
1165
- payload, status, attempts, error_message, published_at, last_attempt, created_at)
1166
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
1167
- values
1168
- );
1169
- }
1170
- async update(event) {
1171
- const values = [event.status.value, event.attempts, event.errorMessage, event.publishedAt?.value, event.lastAttempt?.value, event.eventUuid.value];
1172
- await this.connection.query(
1173
- `UPDATE events_outbox
1174
- SET status = ?,
1175
- attempts = ?,
1176
- error_message = ?,
1177
- published_at = ?,
1178
- last_attempt = ?
1179
- WHERE event_uuid = ?`,
1180
- values
1181
- );
1399
+ // src/infrastructure/http/DefaultController.ts
1400
+ var HttpHealthCheckController = class {
1401
+ async handle(request) {
1402
+ return {
1403
+ statusCode: 200,
1404
+ body: {
1405
+ date: DateTime.create().value,
1406
+ code: 200
1407
+ }
1408
+ };
1182
1409
  }
1183
- async listPending(limit) {
1184
- const result = await this.connection.query(
1185
- `SELECT * FROM events_outbox WHERE status IN ('PENDING','FAILED') AND published_at IS NULL LIMIT 50`,
1186
- []
1187
- );
1188
- return result.length > 0 ? result.map((r) => DomainEvent.reconstitute(r)) : [];
1410
+ };
1411
+ var HttpNotFoundController = class {
1412
+ async handle(request) {
1413
+ return {
1414
+ statusCode: 404,
1415
+ body: {
1416
+ message: `Route ${request.headers.location} not found`
1417
+ }
1418
+ };
1189
1419
  }
1190
1420
  };
1191
1421
 
@@ -1226,8 +1456,7 @@ var KafkaManager = class extends EventManager {
1226
1456
  eachMessage: async ({ topic, partition, message, heartbeat }) => {
1227
1457
  try {
1228
1458
  await this.execCallback(this._onMessage, `[New message detected for ${topic}]: ${message.value?.toString()}`);
1229
- const evt = JSON.parse(String(message.value?.toString()));
1230
- await this.execRoute(topic, evt);
1459
+ await this.execRoute(topic, String(message.value?.toString()));
1231
1460
  const next = (BigInt(message.offset) + 1n).toString();
1232
1461
  await this.consumer.commitOffsets([{ topic, partition, offset: next }]);
1233
1462
  await heartbeat();
@@ -1243,28 +1472,12 @@ var KafkaManager = class extends EventManager {
1243
1472
  await this.execCallback(this._onError, new InternalError(ErrorManager.APP_ERRORS.PROCESS, error.toString()));
1244
1473
  }
1245
1474
  }
1246
- async send(message) {
1247
- if (!message.producer) {
1248
- message.producer = process.env.NAME && process.env.ENVIRONMENT ? `${process.env.NAME}-${process.env.ENVIRONMENT}` : "unknown";
1249
- }
1250
- if (!message.date) {
1251
- message.date = DateTime.now().value;
1252
- }
1253
- try {
1254
- if (!this.producer) {
1255
- throw new InternalError(ErrorManager.APP_ERRORS.PROCESS, "Producer not initialized");
1256
- }
1257
- await this.producer.connect();
1258
- await this.producer.send({
1259
- topic: message.topic,
1260
- messages: [{ value: JSON.stringify({ producer: message.producer, data: message }) }]
1261
- });
1262
- await this.producer.disconnect();
1263
- } catch (error) {
1264
- throw new InternalError(error.toString());
1265
- }
1266
- }
1267
- async sendRaw(message, topic) {
1475
+ async send(topic, message) {
1476
+ const evt = {
1477
+ date: DateTime.now().value,
1478
+ producer: process.env.NAME && process.env.ENVIRONMENT ? `${process.env.NAME}-${process.env.ENVIRONMENT}` : "unknown",
1479
+ data: message
1480
+ };
1268
1481
  try {
1269
1482
  if (!this.producer) {
1270
1483
  throw new InternalError(ErrorManager.APP_ERRORS.PROCESS, "Producer not initialized");
@@ -1272,7 +1485,7 @@ var KafkaManager = class extends EventManager {
1272
1485
  await this.producer.connect();
1273
1486
  await this.producer.send({
1274
1487
  topic,
1275
- messages: [{ value: message }]
1488
+ messages: [{ value: JSON.stringify(evt) }]
1276
1489
  });
1277
1490
  await this.producer.disconnect();
1278
1491
  } catch (error) {
@@ -1296,6 +1509,84 @@ var KafkaManager = class extends EventManager {
1296
1509
  }
1297
1510
  };
1298
1511
 
1512
+ // src/infrastructure/mysql/Mysql.ts
1513
+ import { createPool } from "mysql2/promise";
1514
+ var _MysqlConnector = class _MysqlConnector {
1515
+ constructor(pool) {
1516
+ this._pool = pool ?? createPool({
1517
+ host: process.env.DB_HOST,
1518
+ port: Number(process.env.DB_PORT ?? 3306),
1519
+ user: process.env.DB_USER,
1520
+ password: process.env.DB_PASSWORD,
1521
+ database: process.env.DB_DATABASE,
1522
+ dateStrings: true,
1523
+ connectionLimit: Number(process.env.DB_POOL_SIZE) || _MysqlConnector.DEFAULT_POOL_SIZE,
1524
+ decimalNumbers: true
1525
+ });
1526
+ }
1527
+ async wrap(conn) {
1528
+ return new MysqlConnection(conn);
1529
+ }
1530
+ async query(sql, params = []) {
1531
+ const [rows] = await this._pool.query(sql, params);
1532
+ return rows;
1533
+ }
1534
+ async getConnection() {
1535
+ const conn = await this._pool.getConnection();
1536
+ return this.wrap(conn);
1537
+ }
1538
+ async closePool() {
1539
+ await this._pool.end();
1540
+ }
1541
+ static async ping() {
1542
+ const connector = new _MysqlConnector();
1543
+ try {
1544
+ const conn = await connector._pool.getConnection();
1545
+ await conn.ping();
1546
+ conn.release();
1547
+ return true;
1548
+ } catch {
1549
+ return false;
1550
+ } finally {
1551
+ await connector.closePool();
1552
+ }
1553
+ }
1554
+ };
1555
+ _MysqlConnector.DEFAULT_POOL_SIZE = 20;
1556
+ var MysqlConnector = _MysqlConnector;
1557
+ var MysqlConnection = class {
1558
+ constructor(conn) {
1559
+ this._conn = conn;
1560
+ }
1561
+ async query(statement, params = []) {
1562
+ const [rows] = await this._conn.query(statement, params);
1563
+ return rows;
1564
+ }
1565
+ async begin() {
1566
+ await this._conn.beginTransaction();
1567
+ }
1568
+ async commit() {
1569
+ await this._conn.commit();
1570
+ }
1571
+ async rollback() {
1572
+ await this._conn.rollback();
1573
+ }
1574
+ async transaction(fn) {
1575
+ await this.begin();
1576
+ try {
1577
+ const result = await fn(this);
1578
+ await this.commit();
1579
+ return result;
1580
+ } catch (err) {
1581
+ await this.rollback();
1582
+ throw err;
1583
+ }
1584
+ }
1585
+ async close() {
1586
+ await this._conn.release();
1587
+ }
1588
+ };
1589
+
1299
1590
  // src/utils/ExchangeRates.ts
1300
1591
  var ExchangeRates = class _ExchangeRates extends BaseObject {
1301
1592
  constructor(props) {
@@ -1348,15 +1639,16 @@ var ExchangeRates = class _ExchangeRates extends BaseObject {
1348
1639
  }
1349
1640
  };
1350
1641
  export {
1642
+ BaseEvent,
1351
1643
  BaseObject,
1352
1644
  BasicUnitOfWork,
1353
1645
  BasicUnitOfWorkFactory,
1646
+ Country,
1354
1647
  Currency,
1355
1648
  DateTime,
1356
1649
  DomainEntity,
1357
1650
  DomainError,
1358
1651
  DomainEvent,
1359
- DomainEventStatus,
1360
1652
  Email,
1361
1653
  ErrorManager,
1362
1654
  EventBus,
@@ -1366,14 +1658,18 @@ export {
1366
1658
  FatalError,
1367
1659
  HttpHealthCheckController,
1368
1660
  HttpNotFoundController,
1661
+ IntegrationEvent,
1369
1662
  InternalError,
1370
1663
  KafkaManager,
1371
1664
  Language,
1372
1665
  MysqlConnection,
1373
1666
  MysqlConnector,
1667
+ OutboxRecord,
1374
1668
  PaymentGateway,
1375
1669
  PaymentStatus,
1376
1670
  Price,
1671
+ ProcessStatus,
1672
+ StringVars,
1377
1673
  UUID,
1378
1674
  UsageError,
1379
1675
  ValueObject,