wsp-ms-core 1.0.6 → 1.0.8-7.5
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 +1521 -198
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +680 -0
- package/dist/index.d.ts +443 -71
- package/dist/index.js +1491 -196
- package/dist/index.js.map +1 -1
- package/package.json +17 -28
- package/dist/index.d.cts +0 -308
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
1
2
|
var __defProp = Object.defineProperty;
|
|
2
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
4
6
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
7
|
var __export = (target, all) => {
|
|
6
8
|
for (var name in all)
|
|
@@ -14,31 +16,57 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
14
16
|
}
|
|
15
17
|
return to;
|
|
16
18
|
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
17
27
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
28
|
|
|
19
29
|
// src/index.ts
|
|
20
30
|
var src_exports = {};
|
|
21
31
|
__export(src_exports, {
|
|
32
|
+
BaseEvent: () => BaseEvent,
|
|
33
|
+
BaseObject: () => BaseObject,
|
|
34
|
+
BasicUnitOfWork: () => BasicUnitOfWork,
|
|
35
|
+
BasicUnitOfWorkFactory: () => BasicUnitOfWorkFactory,
|
|
36
|
+
Country: () => Country,
|
|
22
37
|
Currency: () => Currency,
|
|
23
38
|
DateTime: () => DateTime,
|
|
39
|
+
DefaultMysqlInboxRunner: () => DefaultMysqlInboxRunner,
|
|
40
|
+
DefaultMysqlOutboxRunner: () => DefaultMysqlOutboxRunner,
|
|
24
41
|
DomainEntity: () => DomainEntity,
|
|
25
42
|
DomainError: () => DomainError,
|
|
26
43
|
DomainEvent: () => DomainEvent,
|
|
27
44
|
Email: () => Email,
|
|
28
45
|
ErrorManager: () => ErrorManager,
|
|
46
|
+
EventBus: () => EventBus,
|
|
47
|
+
EventBusMysqlRepository: () => EventBusMysqlRepository,
|
|
48
|
+
EventManager: () => EventManager,
|
|
49
|
+
ExchangeRates: () => ExchangeRates,
|
|
29
50
|
FatalError: () => FatalError,
|
|
30
|
-
HttpErrorController: () => HttpErrorController,
|
|
31
51
|
HttpHealthCheckController: () => HttpHealthCheckController,
|
|
32
52
|
HttpNotFoundController: () => HttpNotFoundController,
|
|
53
|
+
InboxRecord: () => InboxRecord,
|
|
54
|
+
IntegrationEvent: () => IntegrationEvent,
|
|
33
55
|
InternalError: () => InternalError,
|
|
56
|
+
KafkaManager: () => KafkaManager,
|
|
34
57
|
Language: () => Language,
|
|
35
58
|
MysqlConnection: () => MysqlConnection,
|
|
36
59
|
MysqlConnector: () => MysqlConnector,
|
|
60
|
+
OutboxRecord: () => OutboxRecord,
|
|
61
|
+
PaymentGateway: () => PaymentGateway,
|
|
62
|
+
PaymentStatus: () => PaymentStatus,
|
|
37
63
|
Price: () => Price,
|
|
64
|
+
ProcessStatus: () => ProcessStatus,
|
|
65
|
+
StringVars: () => StringVars,
|
|
38
66
|
UUID: () => UUID,
|
|
39
67
|
UsageError: () => UsageError,
|
|
40
68
|
ValueObject: () => ValueObject,
|
|
41
|
-
|
|
69
|
+
adaptExpressErrorHandler: () => adaptExpressErrorHandler,
|
|
42
70
|
adaptExpressRoute: () => adaptExpressRoute
|
|
43
71
|
});
|
|
44
72
|
module.exports = __toCommonJS(src_exports);
|
|
@@ -52,6 +80,9 @@ var ValueObject = class {
|
|
|
52
80
|
this.validate(value);
|
|
53
81
|
this._value = Object.freeze(value);
|
|
54
82
|
}
|
|
83
|
+
toProps() {
|
|
84
|
+
return this._value;
|
|
85
|
+
}
|
|
55
86
|
get value() {
|
|
56
87
|
return this._value;
|
|
57
88
|
}
|
|
@@ -145,6 +176,21 @@ var _DateTime = class _DateTime extends ValueObject {
|
|
|
145
176
|
getWeekdayName(locale = "en") {
|
|
146
177
|
return this._dt.setLocale(locale).toFormat("cccc");
|
|
147
178
|
}
|
|
179
|
+
getDayName(locale = "en") {
|
|
180
|
+
return this._dt.setLocale(locale).toFormat("EEEE");
|
|
181
|
+
}
|
|
182
|
+
format(format) {
|
|
183
|
+
if (!_DateTime.FORMATS.hasOwnProperty(format)) {
|
|
184
|
+
throw new Error(`Invalid format: ${format}`);
|
|
185
|
+
}
|
|
186
|
+
const formatString = _DateTime.FORMATS[format];
|
|
187
|
+
return this._dt.toFormat(formatString);
|
|
188
|
+
}
|
|
189
|
+
toPrimitives() {
|
|
190
|
+
return {
|
|
191
|
+
value: this.value
|
|
192
|
+
};
|
|
193
|
+
}
|
|
148
194
|
static create(input) {
|
|
149
195
|
if (input === void 0) {
|
|
150
196
|
return new _DateTime(_DateTime.toUtcFormat(import_luxon.DateTime.now()));
|
|
@@ -160,39 +206,106 @@ var _DateTime = class _DateTime extends ValueObject {
|
|
|
160
206
|
}
|
|
161
207
|
return new _DateTime(input);
|
|
162
208
|
}
|
|
209
|
+
static now() {
|
|
210
|
+
return _DateTime.create();
|
|
211
|
+
}
|
|
163
212
|
};
|
|
164
213
|
_DateTime.DEFAULT_FORMAT = "yyyy-MM-dd HH:mm:ss";
|
|
214
|
+
_DateTime.FORMAT = "Y-M-D H:M:S";
|
|
215
|
+
_DateTime.FORMAT_Y_M = "Y-M";
|
|
216
|
+
_DateTime.FORMAT_Y_M_D = "Y-M-D";
|
|
217
|
+
_DateTime.FORMAT_Y_M_D_H_m_s = "Y-M-D H:M:S";
|
|
218
|
+
_DateTime.FORMAT_D_M_Y = "D-M-Y";
|
|
219
|
+
_DateTime.FORMATS = {
|
|
220
|
+
"Y-M": "yyyy-MM",
|
|
221
|
+
"Y-M-D": "yyyy-MM-dd",
|
|
222
|
+
"D/M/Y": "dd/MM/yyyy",
|
|
223
|
+
"Y/M/D": "yyyy/MM/dd",
|
|
224
|
+
"D-M-Y": "dd-MM-yyyy",
|
|
225
|
+
"Y.M.D": "yyyy.MM.dd",
|
|
226
|
+
"D.M.Y": "dd.MM.yyyy",
|
|
227
|
+
"Y-M-D H:M": "yyyy-MM-dd HH:mm",
|
|
228
|
+
"D/M/Y H:M": "dd/MM/yyyy HH:mm",
|
|
229
|
+
"Y/M/D H:M": "yyyy/MM/dd HH:mm",
|
|
230
|
+
"D-M-Y H:M": "dd-MM-yyyy HH:mm",
|
|
231
|
+
"Y.M.D H:M": "yyyy.MM.dd HH:mm",
|
|
232
|
+
"D.M.Y H:M": "dd.MM.yyyy HH:mm",
|
|
233
|
+
"Y-M-D H:M:S": "yyyy-MM-dd HH:mm:ss",
|
|
234
|
+
"Y-M-D H:M:S:SSS": "yyyy-MM-dd HH:mm:ss.SSS",
|
|
235
|
+
"D/M/Y H:M:S": "dd/MM/yyyy HH:mm:ss",
|
|
236
|
+
"Y/M/D H:M:S": "yyyy/MM/dd HH:mm:ss",
|
|
237
|
+
"D-M-Y H:M:S": "dd-MM-yyyy HH:mm:ss",
|
|
238
|
+
"Y.M.D H:M:S": "yyyy.MM.dd HH:mm:ss",
|
|
239
|
+
"D.M.Y H:M:S": "dd.MM.yyyy HH:mm:ss",
|
|
240
|
+
"H:M": "HH:mm",
|
|
241
|
+
"H:M:S": "HH:mm:ss"
|
|
242
|
+
};
|
|
165
243
|
var DateTime = _DateTime;
|
|
166
244
|
|
|
245
|
+
// src/domain/contracts/BaseEvent.ts
|
|
246
|
+
var BaseEvent = class {
|
|
247
|
+
constructor(tenantUuid, version, type, payload) {
|
|
248
|
+
this._tenantUuid = tenantUuid;
|
|
249
|
+
this._version = version;
|
|
250
|
+
this._type = type;
|
|
251
|
+
this._payload = payload;
|
|
252
|
+
this._occurredAt = DateTime.now();
|
|
253
|
+
}
|
|
254
|
+
get tenantUuid() {
|
|
255
|
+
return this._tenantUuid;
|
|
256
|
+
}
|
|
257
|
+
get version() {
|
|
258
|
+
return this._version;
|
|
259
|
+
}
|
|
260
|
+
get type() {
|
|
261
|
+
return this._type;
|
|
262
|
+
}
|
|
263
|
+
get payload() {
|
|
264
|
+
return this._payload;
|
|
265
|
+
}
|
|
266
|
+
get ocurredAt() {
|
|
267
|
+
return this._occurredAt;
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
|
|
167
271
|
// src/domain/contracts/DomainEntity.ts
|
|
168
272
|
var DomainEntity = class {
|
|
169
|
-
constructor(
|
|
170
|
-
this.
|
|
273
|
+
constructor(props) {
|
|
274
|
+
this._events = [];
|
|
171
275
|
this.props = props;
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
this.
|
|
276
|
+
}
|
|
277
|
+
recordEvent(event) {
|
|
278
|
+
this._events.push(event);
|
|
175
279
|
}
|
|
176
280
|
touch() {
|
|
177
|
-
this.
|
|
281
|
+
this.props.updatedAt = DateTime.now();
|
|
282
|
+
}
|
|
283
|
+
get uuid() {
|
|
284
|
+
return this.props.uuid;
|
|
178
285
|
}
|
|
179
286
|
get createdAt() {
|
|
180
|
-
return this.
|
|
287
|
+
return this.props.createdAt;
|
|
181
288
|
}
|
|
182
289
|
get updatedAt() {
|
|
183
|
-
return this.
|
|
290
|
+
return this.props.updatedAt;
|
|
184
291
|
}
|
|
185
292
|
get deletedAt() {
|
|
186
|
-
return this.
|
|
293
|
+
return this.props.deletedAt;
|
|
187
294
|
}
|
|
188
295
|
get isDeleted() {
|
|
189
|
-
return Boolean(this.
|
|
296
|
+
return Boolean(this.props.deletedAt);
|
|
190
297
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
298
|
+
pullEvents() {
|
|
299
|
+
const events = this._events;
|
|
300
|
+
this._events = [];
|
|
301
|
+
return events;
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
// src/domain/contracts/BaseObject.ts
|
|
306
|
+
var BaseObject = class {
|
|
307
|
+
constructor(props) {
|
|
308
|
+
this.props = props;
|
|
196
309
|
}
|
|
197
310
|
};
|
|
198
311
|
|
|
@@ -204,20 +317,6 @@ var DomainError = class extends Error {
|
|
|
204
317
|
}
|
|
205
318
|
};
|
|
206
319
|
|
|
207
|
-
// src/domain/contracts/DomainEvent.ts
|
|
208
|
-
var DomainEvent = class {
|
|
209
|
-
constructor(payload) {
|
|
210
|
-
this._payload = payload;
|
|
211
|
-
this._occurredAt = DateTime.create();
|
|
212
|
-
}
|
|
213
|
-
get payload() {
|
|
214
|
-
return this._payload;
|
|
215
|
-
}
|
|
216
|
-
get occurredAt() {
|
|
217
|
-
return this._occurredAt;
|
|
218
|
-
}
|
|
219
|
-
};
|
|
220
|
-
|
|
221
320
|
// src/domain/errors/FatalError.ts
|
|
222
321
|
var FatalError = class extends DomainError {
|
|
223
322
|
constructor(type, message = "") {
|
|
@@ -240,6 +339,424 @@ var UsageError = class extends DomainError {
|
|
|
240
339
|
}
|
|
241
340
|
};
|
|
242
341
|
|
|
342
|
+
// src/domain/events/DomainEvent.ts
|
|
343
|
+
var DomainEvent = class extends BaseEvent {
|
|
344
|
+
constructor(tenantUuid, version, type, payload, aggregateUuid, aggregateType) {
|
|
345
|
+
super(tenantUuid, version, type, payload);
|
|
346
|
+
this._aggregateUuid = aggregateUuid;
|
|
347
|
+
this._aggregateType = aggregateType;
|
|
348
|
+
}
|
|
349
|
+
get aggregateUuid() {
|
|
350
|
+
return this._aggregateUuid;
|
|
351
|
+
}
|
|
352
|
+
get aggregateType() {
|
|
353
|
+
return this._aggregateType;
|
|
354
|
+
}
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
// src/domain/value-objects/payments/PaymentGateway.ts
|
|
358
|
+
var _PaymentGateway = class _PaymentGateway extends ValueObject {
|
|
359
|
+
constructor(gateway) {
|
|
360
|
+
super(gateway);
|
|
361
|
+
}
|
|
362
|
+
validate(value) {
|
|
363
|
+
if (!_PaymentGateway.SUPPORTED.includes(value)) {
|
|
364
|
+
throw new InternalError(`Payment gateway <${value}> is not supported`);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
isExternal() {
|
|
368
|
+
return _PaymentGateway.EXTERNALS.includes(this.value);
|
|
369
|
+
}
|
|
370
|
+
get isMercadoPago() {
|
|
371
|
+
return this.equals(_PaymentGateway.MERCADOPAGO);
|
|
372
|
+
}
|
|
373
|
+
get isHandy() {
|
|
374
|
+
return this.equals(_PaymentGateway.HANDY);
|
|
375
|
+
}
|
|
376
|
+
get isWonaDebit() {
|
|
377
|
+
return this.equals(_PaymentGateway.WONA_DEBIT);
|
|
378
|
+
}
|
|
379
|
+
get isWonaCard() {
|
|
380
|
+
return this.equals(_PaymentGateway.WONA_CARD);
|
|
381
|
+
}
|
|
382
|
+
get isWonaCash() {
|
|
383
|
+
return this.equals(_PaymentGateway.WONA_CASH);
|
|
384
|
+
}
|
|
385
|
+
get isWonaTransfer() {
|
|
386
|
+
return this.equals(_PaymentGateway.WONA_TRANSFER);
|
|
387
|
+
}
|
|
388
|
+
get isWonaMercadoPago() {
|
|
389
|
+
return this.equals(_PaymentGateway.WONA_MERCADOPAGO);
|
|
390
|
+
}
|
|
391
|
+
toPrimitives() {
|
|
392
|
+
return { value: this.value };
|
|
393
|
+
}
|
|
394
|
+
static create(gateway) {
|
|
395
|
+
return new _PaymentGateway(gateway.trim().toUpperCase());
|
|
396
|
+
}
|
|
397
|
+
};
|
|
398
|
+
_PaymentGateway.SUPPORTED = [
|
|
399
|
+
"MERCADOPAGO",
|
|
400
|
+
"HANDY",
|
|
401
|
+
"WONA_DEBIT",
|
|
402
|
+
"WONA_CARD",
|
|
403
|
+
"WONA_CASH",
|
|
404
|
+
"WONA_TRANSFER",
|
|
405
|
+
"WONA_MERCADOPAGO"
|
|
406
|
+
];
|
|
407
|
+
_PaymentGateway.EXTERNALS = ["MERCADOPAGO", "STRIPE"];
|
|
408
|
+
_PaymentGateway.MERCADOPAGO = new _PaymentGateway("MERCADOPAGO");
|
|
409
|
+
_PaymentGateway.HANDY = new _PaymentGateway("HANDY");
|
|
410
|
+
_PaymentGateway.WONA_DEBIT = new _PaymentGateway("WONA_DEBIT");
|
|
411
|
+
_PaymentGateway.WONA_CARD = new _PaymentGateway("WONA_CARD");
|
|
412
|
+
_PaymentGateway.WONA_CASH = new _PaymentGateway("WONA_CASH");
|
|
413
|
+
_PaymentGateway.WONA_TRANSFER = new _PaymentGateway("WONA_TRANSFER");
|
|
414
|
+
_PaymentGateway.WONA_MERCADOPAGO = new _PaymentGateway("WONA_MERCADOPAGO");
|
|
415
|
+
var PaymentGateway = _PaymentGateway;
|
|
416
|
+
|
|
417
|
+
// src/domain/value-objects/payments/PaymentStatus.ts
|
|
418
|
+
var _PaymentStatus = class _PaymentStatus extends ValueObject {
|
|
419
|
+
constructor(status) {
|
|
420
|
+
super(status);
|
|
421
|
+
}
|
|
422
|
+
validate(status) {
|
|
423
|
+
if (!_PaymentStatus.SUPPORTED.includes(status)) {
|
|
424
|
+
throw new InternalError(`Payment status <${status}> is not supported`);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
get isDone() {
|
|
428
|
+
return this.value === "DONE";
|
|
429
|
+
}
|
|
430
|
+
get isPending() {
|
|
431
|
+
return this.value === "PENDING";
|
|
432
|
+
}
|
|
433
|
+
get isInProgress() {
|
|
434
|
+
return this.value === "IN_PROGRESS";
|
|
435
|
+
}
|
|
436
|
+
get isFailed() {
|
|
437
|
+
return this.value === "FAILED";
|
|
438
|
+
}
|
|
439
|
+
get isCanceled() {
|
|
440
|
+
return this.value === "CANCELED";
|
|
441
|
+
}
|
|
442
|
+
get isHold() {
|
|
443
|
+
return this.value === "HOLD";
|
|
444
|
+
}
|
|
445
|
+
get isPendingRefund() {
|
|
446
|
+
return this.value === "PENDING_REFUND";
|
|
447
|
+
}
|
|
448
|
+
get isRefunded() {
|
|
449
|
+
return this.value === "REFUNDED";
|
|
450
|
+
}
|
|
451
|
+
toPrimitives() {
|
|
452
|
+
return { value: this.value };
|
|
453
|
+
}
|
|
454
|
+
static create(gateway) {
|
|
455
|
+
return new _PaymentStatus(gateway.trim().toUpperCase());
|
|
456
|
+
}
|
|
457
|
+
};
|
|
458
|
+
_PaymentStatus.SUPPORTED = ["DONE", "PENDING", "FAILED", "CANCELED", "HOLD", "PENDING_REFUND", "REFUNDED", "IN_PROGRESS"];
|
|
459
|
+
_PaymentStatus.DONE = new _PaymentStatus("DONE");
|
|
460
|
+
_PaymentStatus.PENDING = new _PaymentStatus("PENDING");
|
|
461
|
+
_PaymentStatus.IN_PROGRESS = new _PaymentStatus("IN_PROGRESS");
|
|
462
|
+
_PaymentStatus.FAILED = new _PaymentStatus("FAILED");
|
|
463
|
+
_PaymentStatus.CANCELED = new _PaymentStatus("CANCELED");
|
|
464
|
+
_PaymentStatus.HOLD = new _PaymentStatus("HOLD");
|
|
465
|
+
_PaymentStatus.PENDING_REFUND = new _PaymentStatus("PENDING_REFUND");
|
|
466
|
+
_PaymentStatus.REFUNDED = new _PaymentStatus("REFUNDED");
|
|
467
|
+
var PaymentStatus = _PaymentStatus;
|
|
468
|
+
|
|
469
|
+
// src/utils/StringVars.ts
|
|
470
|
+
var StringVars = class {
|
|
471
|
+
static parse(str, ob) {
|
|
472
|
+
const regex = /{{(.*?)}}/g;
|
|
473
|
+
return str.replace(regex, (match, variable) => {
|
|
474
|
+
if (ob.hasOwnProperty(variable.trim())) {
|
|
475
|
+
return ob[variable.trim()];
|
|
476
|
+
} else {
|
|
477
|
+
return match;
|
|
478
|
+
}
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
};
|
|
482
|
+
|
|
483
|
+
// src/infrastructure/errors/ErrorManager.ts
|
|
484
|
+
var _ErrorManager = class _ErrorManager {
|
|
485
|
+
constructor(logger = null) {
|
|
486
|
+
this.logger = logger;
|
|
487
|
+
}
|
|
488
|
+
getDefaultMessage(lang) {
|
|
489
|
+
return _ErrorManager.DEFAULT_MESSAGES[lang.value] || _ErrorManager.DEFAULT_MESSAGES[lang.base()] || "error";
|
|
490
|
+
}
|
|
491
|
+
onFatal(err, lang) {
|
|
492
|
+
this.logger?.fatal(err.type, err.message);
|
|
493
|
+
return { status: "ERROR", message: this.getDefaultMessage(lang) };
|
|
494
|
+
}
|
|
495
|
+
onInternal(err, lang) {
|
|
496
|
+
this.logger?.error(err.type, err.message);
|
|
497
|
+
return { status: "ERROR", message: this.getDefaultMessage(lang) };
|
|
498
|
+
}
|
|
499
|
+
onUsage(err, lang) {
|
|
500
|
+
const tmpl = _ErrorManager.TEMPLATES.get(err.type);
|
|
501
|
+
if (!tmpl) {
|
|
502
|
+
this.logger?.error("TEMPLATE_NOT_FOUND", `${err.type}`);
|
|
503
|
+
return { status: "ERROR", message: this.getDefaultMessage(lang) };
|
|
504
|
+
}
|
|
505
|
+
const code = lang.value;
|
|
506
|
+
const base = lang.base();
|
|
507
|
+
const rawMsg = tmpl.languages[code] ?? tmpl.languages[base] ?? this.getDefaultMessage(lang);
|
|
508
|
+
return {
|
|
509
|
+
status: 400,
|
|
510
|
+
message: StringVars.parse(rawMsg, err.vars)
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
onUnknown(err, lang) {
|
|
514
|
+
this.logger?.error("UNKNOWN_ERROR", err.message);
|
|
515
|
+
return { status: "ERROR", message: this.getDefaultMessage(lang) };
|
|
516
|
+
}
|
|
517
|
+
handle(err, lang) {
|
|
518
|
+
if (["local", "dev"].includes(process.env.ENVIRONMENT ?? "")) {
|
|
519
|
+
console.log(err);
|
|
520
|
+
}
|
|
521
|
+
if (err instanceof FatalError) {
|
|
522
|
+
return this.onFatal(err, lang);
|
|
523
|
+
}
|
|
524
|
+
if (err instanceof InternalError) {
|
|
525
|
+
return this.onInternal(err, lang);
|
|
526
|
+
}
|
|
527
|
+
if (err instanceof UsageError) {
|
|
528
|
+
return this.onUsage(err, lang);
|
|
529
|
+
}
|
|
530
|
+
return this.onUnknown(err, lang);
|
|
531
|
+
}
|
|
532
|
+
static addTemplate(template) {
|
|
533
|
+
_ErrorManager.TEMPLATES.set(template.type, template);
|
|
534
|
+
}
|
|
535
|
+
};
|
|
536
|
+
_ErrorManager.DEFAULT_MESSAGES = {
|
|
537
|
+
"es": "Ups, hemos encontrado un error. Nuestro equipo ya est\xE1 trabajando para solucionarlo",
|
|
538
|
+
"en": "Ups, we found an error. Our team is working on it.",
|
|
539
|
+
"pt": "Ops, encontramos um bug. Nossa equipe j\xE1 est\xE1 trabalhando para resolver isso."
|
|
540
|
+
};
|
|
541
|
+
_ErrorManager.APP_ERRORS = {
|
|
542
|
+
UNDEFINED: "UNDEFINED_ERROR",
|
|
543
|
+
PROCESS: "PROCESS_ERROR",
|
|
544
|
+
DATABASE: "DATABASE_ERROR"
|
|
545
|
+
};
|
|
546
|
+
_ErrorManager.TEMPLATES = /* @__PURE__ */ new Map();
|
|
547
|
+
var ErrorManager = _ErrorManager;
|
|
548
|
+
|
|
549
|
+
// src/domain/value-objects/Country.ts
|
|
550
|
+
ErrorManager.addTemplate({
|
|
551
|
+
type: "INVALID_COUNTRY",
|
|
552
|
+
languages: {
|
|
553
|
+
"es": "El pa\xEDs <{{country}}> no es v\xE1lido o no est\xE1 soportado",
|
|
554
|
+
"en": "Country <{{country}}> is not valid or not supported"
|
|
555
|
+
}
|
|
556
|
+
});
|
|
557
|
+
ErrorManager.addTemplate({
|
|
558
|
+
type: "COUNTRY_NOT_FOUND_BY_ALPHA2",
|
|
559
|
+
languages: {
|
|
560
|
+
"es": "No se encontr\xF3 pa\xEDs con c\xF3digo alpha2 <{{alpha2}}>",
|
|
561
|
+
"en": "Country not found with alpha2 code <{{alpha2}}>"
|
|
562
|
+
}
|
|
563
|
+
});
|
|
564
|
+
ErrorManager.addTemplate({
|
|
565
|
+
type: "COUNTRY_NOT_FOUND_BY_UUID",
|
|
566
|
+
languages: {
|
|
567
|
+
"es": "No se encontr\xF3 pa\xEDs con UUID <{{uuid}}>",
|
|
568
|
+
"en": "Country not found with UUID <{{uuid}}>"
|
|
569
|
+
}
|
|
570
|
+
});
|
|
571
|
+
var _Country = class _Country extends ValueObject {
|
|
572
|
+
constructor(country) {
|
|
573
|
+
const normalizedCountry = country.toUpperCase().trim();
|
|
574
|
+
super(normalizedCountry);
|
|
575
|
+
this._name = normalizedCountry;
|
|
576
|
+
this._alpha2 = _Country.COUNTRIES[normalizedCountry].alpha2;
|
|
577
|
+
this._alpha3 = _Country.COUNTRIES[normalizedCountry].alpha3;
|
|
578
|
+
this._numeric = _Country.COUNTRIES[normalizedCountry].numeric;
|
|
579
|
+
this._uuid = _Country.COUNTRIES[normalizedCountry].uuid;
|
|
580
|
+
this._phoneCode = _Country.COUNTRIES[normalizedCountry].phoneCode;
|
|
581
|
+
this._url = _Country.COUNTRIES[normalizedCountry].url;
|
|
582
|
+
}
|
|
583
|
+
validate(country) {
|
|
584
|
+
if (!_Country.NAMES.includes(country)) {
|
|
585
|
+
throw new UsageError("INVALID_COUNTRY", { country });
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
name() {
|
|
589
|
+
return this._name;
|
|
590
|
+
}
|
|
591
|
+
alpha2() {
|
|
592
|
+
return this._alpha2;
|
|
593
|
+
}
|
|
594
|
+
alpha3() {
|
|
595
|
+
return this._alpha3;
|
|
596
|
+
}
|
|
597
|
+
numeric() {
|
|
598
|
+
return this._numeric;
|
|
599
|
+
}
|
|
600
|
+
uuid() {
|
|
601
|
+
return this._uuid;
|
|
602
|
+
}
|
|
603
|
+
phoneCode() {
|
|
604
|
+
return this._phoneCode;
|
|
605
|
+
}
|
|
606
|
+
url() {
|
|
607
|
+
return this._url;
|
|
608
|
+
}
|
|
609
|
+
static findCountryByAlpha2(alpha2) {
|
|
610
|
+
for (const [country, codes] of Object.entries(_Country.COUNTRIES)) {
|
|
611
|
+
if (codes.alpha2 === alpha2.toUpperCase()) {
|
|
612
|
+
return new _Country(country);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
throw new UsageError("COUNTRY_NOT_FOUND_BY_ALPHA2", { alpha2 });
|
|
616
|
+
}
|
|
617
|
+
static findCountryByUUID(uuid) {
|
|
618
|
+
for (const [country, codes] of Object.entries(_Country.COUNTRIES)) {
|
|
619
|
+
if (codes.uuid === uuid) {
|
|
620
|
+
return new _Country(country);
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
throw new UsageError("COUNTRY_NOT_FOUND_BY_UUID", { uuid });
|
|
624
|
+
}
|
|
625
|
+
static create(country) {
|
|
626
|
+
return new _Country(country);
|
|
627
|
+
}
|
|
628
|
+
static createOrDefault(country) {
|
|
629
|
+
try {
|
|
630
|
+
return new _Country(country);
|
|
631
|
+
} catch (error) {
|
|
632
|
+
return _Country.DEFAULT;
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
toPrimitives() {
|
|
636
|
+
return {
|
|
637
|
+
value: this.value,
|
|
638
|
+
name: this._name,
|
|
639
|
+
alpha2: this._alpha2,
|
|
640
|
+
alpha3: this._alpha3,
|
|
641
|
+
numeric: this._numeric,
|
|
642
|
+
uuid: this._uuid,
|
|
643
|
+
phoneCode: this._phoneCode,
|
|
644
|
+
url: this._url
|
|
645
|
+
};
|
|
646
|
+
}
|
|
647
|
+
static isValid(country) {
|
|
648
|
+
try {
|
|
649
|
+
_Country.create(country);
|
|
650
|
+
return true;
|
|
651
|
+
} catch {
|
|
652
|
+
return false;
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
};
|
|
656
|
+
_Country.COUNTRIES = {
|
|
657
|
+
URUGUAY: {
|
|
658
|
+
alpha2: "UY",
|
|
659
|
+
alpha3: "URY",
|
|
660
|
+
numeric: "858",
|
|
661
|
+
phoneCode: "+598",
|
|
662
|
+
uuid: "5739ecc0-d12b-4db5-8897-e03a04a95c72",
|
|
663
|
+
url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/uruguay.png"
|
|
664
|
+
},
|
|
665
|
+
ARGENTINA: {
|
|
666
|
+
alpha2: "AR",
|
|
667
|
+
alpha3: "ARG",
|
|
668
|
+
numeric: "032",
|
|
669
|
+
phoneCode: "+54",
|
|
670
|
+
uuid: "66663efe-ab7a-4166-b971-9f36fd0ea6b2",
|
|
671
|
+
url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/argentina.png"
|
|
672
|
+
},
|
|
673
|
+
ECUADOR: {
|
|
674
|
+
alpha2: "EC",
|
|
675
|
+
alpha3: "ECU",
|
|
676
|
+
numeric: "218",
|
|
677
|
+
phoneCode: "+593",
|
|
678
|
+
uuid: "ee109239-0150-4e5f-9ff2-a85f270092b1",
|
|
679
|
+
url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/ecuador.png"
|
|
680
|
+
},
|
|
681
|
+
PERU: {
|
|
682
|
+
alpha2: "PE",
|
|
683
|
+
alpha3: "PER",
|
|
684
|
+
numeric: "604",
|
|
685
|
+
phoneCode: "+51",
|
|
686
|
+
uuid: "e4d61ef5-b92d-4f9c-8ec1-23f4beb50abd",
|
|
687
|
+
url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/peru.png"
|
|
688
|
+
},
|
|
689
|
+
BRASIL: {
|
|
690
|
+
alpha2: "BR",
|
|
691
|
+
alpha3: "BRA",
|
|
692
|
+
numeric: "076",
|
|
693
|
+
phoneCode: "+55",
|
|
694
|
+
uuid: "b7b91d72-deaf-4641-957c-a65003e33104",
|
|
695
|
+
url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/brasil.png"
|
|
696
|
+
},
|
|
697
|
+
CHILE: {
|
|
698
|
+
alpha2: "CL",
|
|
699
|
+
alpha3: "CHL",
|
|
700
|
+
numeric: "152",
|
|
701
|
+
phoneCode: "+56",
|
|
702
|
+
uuid: "f69b35f4-d734-4c76-866c-29a18bf000fb",
|
|
703
|
+
url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/chile.png"
|
|
704
|
+
},
|
|
705
|
+
VENEZUELA: {
|
|
706
|
+
alpha2: "VE",
|
|
707
|
+
alpha3: "VEN",
|
|
708
|
+
numeric: "862",
|
|
709
|
+
phoneCode: "+58",
|
|
710
|
+
uuid: "31b6c591-63f6-43db-8ea9-829bb03746c5",
|
|
711
|
+
url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/venezuela.png"
|
|
712
|
+
},
|
|
713
|
+
COLOMBIA: {
|
|
714
|
+
alpha2: "CO",
|
|
715
|
+
alpha3: "COL",
|
|
716
|
+
numeric: "170",
|
|
717
|
+
phoneCode: "+57",
|
|
718
|
+
uuid: "6fdfe34b-6726-4604-96af-665ea5fc9239",
|
|
719
|
+
url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/colombia.png"
|
|
720
|
+
},
|
|
721
|
+
BOLIVIA: {
|
|
722
|
+
alpha2: "BO",
|
|
723
|
+
alpha3: "BOL",
|
|
724
|
+
numeric: "068",
|
|
725
|
+
phoneCode: "+591",
|
|
726
|
+
uuid: "948886db-c280-4ba7-a777-a76c180b295b",
|
|
727
|
+
url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/bolivia.png"
|
|
728
|
+
},
|
|
729
|
+
PARAGUAY: {
|
|
730
|
+
alpha2: "PY",
|
|
731
|
+
alpha3: "PRY",
|
|
732
|
+
numeric: "600",
|
|
733
|
+
phoneCode: "+595",
|
|
734
|
+
uuid: "d67b3472-e38d-4900-8ae3-02d99cd1d884",
|
|
735
|
+
url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/paraguay.png"
|
|
736
|
+
},
|
|
737
|
+
USA: {
|
|
738
|
+
alpha2: "US",
|
|
739
|
+
alpha3: "USA",
|
|
740
|
+
numeric: "840",
|
|
741
|
+
phoneCode: "+1",
|
|
742
|
+
uuid: "16ac3b9b-8f7b-4c54-91d5-d62c7cd74ad4",
|
|
743
|
+
url: "https://dev-wonasports.s3.us-east-2.amazonaws.com/assets/usa.png"
|
|
744
|
+
}
|
|
745
|
+
};
|
|
746
|
+
_Country.NAMES = Object.keys(_Country.COUNTRIES);
|
|
747
|
+
_Country.DEFAULT = new _Country("URUGUAY");
|
|
748
|
+
_Country.ARGENTINA = new _Country("ARGENTINA");
|
|
749
|
+
_Country.ECUADOR = new _Country("ECUADOR");
|
|
750
|
+
_Country.PERU = new _Country("PERU");
|
|
751
|
+
_Country.BRASIL = new _Country("BRASIL");
|
|
752
|
+
_Country.CHILE = new _Country("CHILE");
|
|
753
|
+
_Country.VENEZUELA = new _Country("VENEZUELA");
|
|
754
|
+
_Country.COLOMBIA = new _Country("COLOMBIA");
|
|
755
|
+
_Country.BOLIVIA = new _Country("BOLIVIA");
|
|
756
|
+
_Country.PARAGUAY = new _Country("PARAGUAY");
|
|
757
|
+
_Country.USA = new _Country("USA");
|
|
758
|
+
var Country = _Country;
|
|
759
|
+
|
|
243
760
|
// src/domain/value-objects/Currency.ts
|
|
244
761
|
var _Currency = class _Currency extends ValueObject {
|
|
245
762
|
constructor(alpha) {
|
|
@@ -255,6 +772,11 @@ var _Currency = class _Currency extends ValueObject {
|
|
|
255
772
|
throw new Error(`Currency <${code}> is not supported`);
|
|
256
773
|
}
|
|
257
774
|
}
|
|
775
|
+
toPrimitives() {
|
|
776
|
+
return {
|
|
777
|
+
value: this.value
|
|
778
|
+
};
|
|
779
|
+
}
|
|
258
780
|
static create(raw) {
|
|
259
781
|
if (typeof raw === "number" || _Currency.NUM_REGEX.test(raw)) {
|
|
260
782
|
const num = Number(raw);
|
|
@@ -308,6 +830,11 @@ var _Email = class _Email extends ValueObject {
|
|
|
308
830
|
throw new Error(`Email <${value}> is not a valid address`);
|
|
309
831
|
}
|
|
310
832
|
}
|
|
833
|
+
toPrimitives() {
|
|
834
|
+
return {
|
|
835
|
+
value: this.value
|
|
836
|
+
};
|
|
837
|
+
}
|
|
311
838
|
static create(raw) {
|
|
312
839
|
return new _Email(raw);
|
|
313
840
|
}
|
|
@@ -325,12 +852,18 @@ var _Language = class _Language extends ValueObject {
|
|
|
325
852
|
}
|
|
326
853
|
validate(value) {
|
|
327
854
|
if (!_Language.SUPPORTED.includes(value)) {
|
|
328
|
-
throw new
|
|
855
|
+
throw new InternalError(`Language <${value}> is not supported`);
|
|
329
856
|
}
|
|
330
857
|
}
|
|
331
858
|
base() {
|
|
332
859
|
return this.value.split("-")[0];
|
|
333
860
|
}
|
|
861
|
+
toPrimitives() {
|
|
862
|
+
return {
|
|
863
|
+
base: this.base(),
|
|
864
|
+
value: this.value
|
|
865
|
+
};
|
|
866
|
+
}
|
|
334
867
|
static create(raw) {
|
|
335
868
|
const normalized = raw.trim().toLowerCase().replace("_", "-");
|
|
336
869
|
try {
|
|
@@ -411,25 +944,43 @@ _Language.SPANISH_PUERTO_RICO = new _Language("es-pr");
|
|
|
411
944
|
var Language = _Language;
|
|
412
945
|
|
|
413
946
|
// src/domain/value-objects/Price.ts
|
|
947
|
+
ErrorManager.addTemplate({
|
|
948
|
+
type: "INVALID_PRICE_AMOUNT",
|
|
949
|
+
languages: {
|
|
950
|
+
"es": "El precio <{{amount}}> no es v\xE1lido",
|
|
951
|
+
"en": "Price amount <{{amount}}> is not a valid number"
|
|
952
|
+
}
|
|
953
|
+
});
|
|
954
|
+
ErrorManager.addTemplate({
|
|
955
|
+
type: "INVALID_PRICE_RANGE",
|
|
956
|
+
languages: {
|
|
957
|
+
"es": "El precio <{{amount}}> debe ser \u2265 {{min}} y \u2264 {{max}}",
|
|
958
|
+
"en": "Price amount <{{amount}}> must be \u2265 {{min}} and \u2264 {{max}}"
|
|
959
|
+
}
|
|
960
|
+
});
|
|
414
961
|
var _Price = class _Price extends ValueObject {
|
|
415
962
|
constructor(amount, currency) {
|
|
416
963
|
super({ amount, currency });
|
|
417
|
-
this.amount = amount;
|
|
418
|
-
this.currency = currency;
|
|
419
964
|
}
|
|
420
965
|
validate(props) {
|
|
421
966
|
const { amount, currency } = props;
|
|
422
967
|
if (typeof amount !== "number" || Number.isNaN(amount) || !Number.isFinite(amount)) {
|
|
423
|
-
throw new
|
|
968
|
+
throw new UsageError("INVALID_PRICE_AMOUNT", { amount });
|
|
424
969
|
}
|
|
425
|
-
if (amount < _Price.MIN_AMOUNT) {
|
|
426
|
-
throw new
|
|
970
|
+
if (amount < _Price.MIN_AMOUNT || amount > _Price.MAX_AMOUNT) {
|
|
971
|
+
throw new UsageError("INVALID_PRICE_RANGE", { amount, min: _Price.MIN_AMOUNT, max: _Price.MAX_AMOUNT });
|
|
427
972
|
}
|
|
428
973
|
}
|
|
974
|
+
get amount() {
|
|
975
|
+
return this._value.amount;
|
|
976
|
+
}
|
|
977
|
+
get currency() {
|
|
978
|
+
return this._value.currency;
|
|
979
|
+
}
|
|
429
980
|
equals(other) {
|
|
430
981
|
if (!other)
|
|
431
982
|
return false;
|
|
432
|
-
return this.amount === other.amount && this.currency.equals(other.currency);
|
|
983
|
+
return this._value.amount === other.amount && this.currency.equals(other.currency);
|
|
433
984
|
}
|
|
434
985
|
assertSameCurrency(other) {
|
|
435
986
|
if (!this.currency.equals(other.currency)) {
|
|
@@ -444,190 +995,537 @@ var _Price = class _Price extends ValueObject {
|
|
|
444
995
|
this.assertSameCurrency(other);
|
|
445
996
|
return _Price.create(this.amount - other.amount, this.currency);
|
|
446
997
|
}
|
|
998
|
+
toPrimitives() {
|
|
999
|
+
return {
|
|
1000
|
+
amount: this.amount,
|
|
1001
|
+
currency: this.currency.value
|
|
1002
|
+
};
|
|
1003
|
+
}
|
|
447
1004
|
static create(amount, currency) {
|
|
448
1005
|
const cur = currency instanceof Currency ? currency : Currency.create(currency);
|
|
449
1006
|
return new _Price(amount, cur);
|
|
450
1007
|
}
|
|
1008
|
+
static createFromPrimitives(data) {
|
|
1009
|
+
return new _Price(Number(data.amount), Currency.create(String(data.currency)));
|
|
1010
|
+
}
|
|
451
1011
|
};
|
|
452
1012
|
_Price.MIN_AMOUNT = -1e6;
|
|
1013
|
+
_Price.MAX_AMOUNT = 1e9;
|
|
453
1014
|
var Price = _Price;
|
|
454
1015
|
|
|
1016
|
+
// src/domain/value-objects/ProcessStatus.ts
|
|
1017
|
+
var _ProcessStatus = class _ProcessStatus extends ValueObject {
|
|
1018
|
+
constructor(status) {
|
|
1019
|
+
super(status.trim().toUpperCase());
|
|
1020
|
+
}
|
|
1021
|
+
validate(value) {
|
|
1022
|
+
if (!_ProcessStatus.SUPPORTED.includes(value)) {
|
|
1023
|
+
throw new InternalError(`Domain event status <${value}> is not supported`);
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
toPrimitives() {
|
|
1027
|
+
return void 0;
|
|
1028
|
+
}
|
|
1029
|
+
static create(status) {
|
|
1030
|
+
return new _ProcessStatus(status);
|
|
1031
|
+
}
|
|
1032
|
+
};
|
|
1033
|
+
_ProcessStatus.SUPPORTED = ["PENDING", "PROCESSING", "PROCESSED", "FAILED", "DEAD"];
|
|
1034
|
+
_ProcessStatus.PENDING = new _ProcessStatus("PENDING");
|
|
1035
|
+
_ProcessStatus.PROCESSING = new _ProcessStatus("PROCESSING");
|
|
1036
|
+
_ProcessStatus.PROCESSED = new _ProcessStatus("PROCESSED");
|
|
1037
|
+
_ProcessStatus.FAILED = new _ProcessStatus("FAILED");
|
|
1038
|
+
_ProcessStatus.DEAD = new _ProcessStatus("DEAD");
|
|
1039
|
+
var ProcessStatus = _ProcessStatus;
|
|
1040
|
+
|
|
455
1041
|
// src/domain/value-objects/UUID.ts
|
|
456
|
-
var
|
|
1042
|
+
var crypto = __toESM(require("crypto"));
|
|
1043
|
+
var _UUID = class _UUID extends ValueObject {
|
|
457
1044
|
constructor(value) {
|
|
458
1045
|
super(value);
|
|
459
1046
|
}
|
|
460
1047
|
validate(uuid) {
|
|
461
1048
|
if (!_UUID.isValid(uuid)) {
|
|
462
|
-
throw new
|
|
1049
|
+
throw new InternalError(`Invalid uuid <${uuid}>`);
|
|
463
1050
|
}
|
|
464
1051
|
}
|
|
1052
|
+
toPrimitives() {
|
|
1053
|
+
return { value: this.value };
|
|
1054
|
+
}
|
|
465
1055
|
static create(uuid) {
|
|
466
1056
|
return new _UUID(uuid ?? crypto.randomUUID());
|
|
467
1057
|
}
|
|
468
|
-
static
|
|
469
|
-
|
|
1058
|
+
static version(uuid) {
|
|
1059
|
+
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);
|
|
1060
|
+
return m ? Number(m[1]) : void 0;
|
|
1061
|
+
}
|
|
1062
|
+
static isNil(uuid) {
|
|
1063
|
+
return /^0{8}-0{4}-0{4}-0{4}-0{12}$/i.test(uuid);
|
|
1064
|
+
}
|
|
1065
|
+
static isRFCStyle(uuid) {
|
|
1066
|
+
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);
|
|
1067
|
+
}
|
|
1068
|
+
static isValid(uuid, opts = {}) {
|
|
1069
|
+
const allowed = opts.allowedVersions ?? [1, 2, 3, 4, 5, 6, 7, 8];
|
|
1070
|
+
const allowNil = opts.allowNil ?? false;
|
|
1071
|
+
if (allowNil && _UUID.isNil(uuid))
|
|
1072
|
+
return true;
|
|
1073
|
+
if (!_UUID.isRFCStyle(uuid))
|
|
1074
|
+
return false;
|
|
1075
|
+
const v = _UUID.version(uuid);
|
|
1076
|
+
return !!v && allowed.includes(v);
|
|
470
1077
|
}
|
|
471
1078
|
};
|
|
1079
|
+
_UUID.NIL = "00000000-0000-0000-0000-000000000000";
|
|
1080
|
+
var UUID = _UUID;
|
|
472
1081
|
|
|
473
|
-
// src/
|
|
474
|
-
var
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
1082
|
+
// src/application/contracts/IntegrationEvent.ts
|
|
1083
|
+
var IntegrationEvent = class extends BaseEvent {
|
|
1084
|
+
constructor(tenantUuid, version, type, payload, aggregateUuid, aggregateType) {
|
|
1085
|
+
super(tenantUuid, version, type, payload);
|
|
1086
|
+
this._aggregateUuid = aggregateUuid;
|
|
1087
|
+
this._aggregateType = aggregateType;
|
|
1088
|
+
}
|
|
1089
|
+
get aggregateUuid() {
|
|
1090
|
+
return this._aggregateUuid;
|
|
1091
|
+
}
|
|
1092
|
+
get aggregateType() {
|
|
1093
|
+
return this._aggregateType;
|
|
484
1094
|
}
|
|
485
1095
|
};
|
|
486
1096
|
|
|
487
|
-
// src/
|
|
488
|
-
var
|
|
489
|
-
constructor(
|
|
490
|
-
this.
|
|
1097
|
+
// src/application/event-bus/EventBus.ts
|
|
1098
|
+
var _EventBus = class _EventBus {
|
|
1099
|
+
constructor(repository) {
|
|
1100
|
+
this.repository = repository;
|
|
1101
|
+
}
|
|
1102
|
+
async publish(event) {
|
|
1103
|
+
const mapper = _EventBus.MAPPERS.get(event.type);
|
|
1104
|
+
if (!mapper) {
|
|
1105
|
+
throw new InternalError(ErrorManager.APP_ERRORS.PROCESS, `Eventbus mapper not found for <${event.type}>`);
|
|
1106
|
+
}
|
|
1107
|
+
await this.repository.create(mapper(event));
|
|
491
1108
|
}
|
|
492
|
-
|
|
493
|
-
|
|
1109
|
+
async publishMany(events) {
|
|
1110
|
+
for (let event of events) {
|
|
1111
|
+
await this.publish(event);
|
|
1112
|
+
}
|
|
494
1113
|
}
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
return { status: "ERROR", message: this.getDefaultMessage(lang) };
|
|
1114
|
+
static addMapper(eventType, mapper) {
|
|
1115
|
+
_EventBus.MAPPERS.set(eventType, mapper);
|
|
498
1116
|
}
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
1117
|
+
};
|
|
1118
|
+
_EventBus.MAPPERS = /* @__PURE__ */ new Map();
|
|
1119
|
+
var EventBus = _EventBus;
|
|
1120
|
+
|
|
1121
|
+
// src/application/unit-of-work/BasicUnitOfWork.ts
|
|
1122
|
+
var BasicUnitOfWork = class {
|
|
1123
|
+
constructor(conn) {
|
|
1124
|
+
this.connection = conn;
|
|
502
1125
|
}
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
1126
|
+
async execute(fn) {
|
|
1127
|
+
await this.connection.begin();
|
|
1128
|
+
try {
|
|
1129
|
+
const result = await fn();
|
|
1130
|
+
await this.connection.commit();
|
|
1131
|
+
return result;
|
|
1132
|
+
} catch (err) {
|
|
1133
|
+
await this.connection.rollback();
|
|
1134
|
+
throw err;
|
|
1135
|
+
} finally {
|
|
1136
|
+
await this.connection.close();
|
|
508
1137
|
}
|
|
509
|
-
const code = lang.value;
|
|
510
|
-
const base = lang.base();
|
|
511
|
-
const rawMsg = tmpl.languages[code] ?? tmpl.languages[base] ?? this.getDefaultMessage(lang);
|
|
512
|
-
return {
|
|
513
|
-
status: "ERROR",
|
|
514
|
-
message: StringVars.parse(rawMsg, err.vars)
|
|
515
|
-
};
|
|
516
1138
|
}
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
1139
|
+
};
|
|
1140
|
+
|
|
1141
|
+
// src/application/unit-of-work/BasicUnitOfWorkFactory.ts
|
|
1142
|
+
var BasicUnitOfWorkFactory = class {
|
|
1143
|
+
constructor(connector) {
|
|
1144
|
+
this.connector = connector;
|
|
520
1145
|
}
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
1146
|
+
async create() {
|
|
1147
|
+
const conn = await this.connector.getConnection();
|
|
1148
|
+
return new BasicUnitOfWork(conn);
|
|
1149
|
+
}
|
|
1150
|
+
};
|
|
1151
|
+
|
|
1152
|
+
// src/infrastructure/contracts/EventManager.ts
|
|
1153
|
+
var EventManager = class {
|
|
1154
|
+
constructor(connection) {
|
|
1155
|
+
this._connection = connection;
|
|
1156
|
+
this._topics = [];
|
|
1157
|
+
this._callbackList = {};
|
|
1158
|
+
this._onStart = null;
|
|
1159
|
+
this._onConnected = null;
|
|
1160
|
+
this._onSubscribe = null;
|
|
1161
|
+
this._onMessage = null;
|
|
1162
|
+
this._onError = null;
|
|
1163
|
+
this._onCrash = null;
|
|
1164
|
+
this._onReconnect = null;
|
|
1165
|
+
}
|
|
1166
|
+
async execRoute(topic, event) {
|
|
1167
|
+
if (this._callbackList[topic]) {
|
|
1168
|
+
await this._callbackList[topic](event);
|
|
530
1169
|
}
|
|
531
|
-
|
|
532
|
-
|
|
1170
|
+
}
|
|
1171
|
+
async execCallback(callback, data) {
|
|
1172
|
+
if (callback) {
|
|
1173
|
+
await callback(data);
|
|
533
1174
|
}
|
|
534
|
-
return this.onUnknown(err, lang);
|
|
535
1175
|
}
|
|
536
|
-
|
|
537
|
-
|
|
1176
|
+
route(topic, callback) {
|
|
1177
|
+
this._topics.push(topic);
|
|
1178
|
+
this._callbackList[topic] = callback;
|
|
1179
|
+
}
|
|
1180
|
+
onStart(callback) {
|
|
1181
|
+
this._onStart = callback;
|
|
1182
|
+
}
|
|
1183
|
+
onConnected(callback) {
|
|
1184
|
+
this._onConnected = callback;
|
|
1185
|
+
}
|
|
1186
|
+
onSubscribe(callback) {
|
|
1187
|
+
this._onSubscribe = callback;
|
|
1188
|
+
}
|
|
1189
|
+
onMessage(callback) {
|
|
1190
|
+
this._onMessage = callback;
|
|
1191
|
+
}
|
|
1192
|
+
onError(callback) {
|
|
1193
|
+
this._onError = callback;
|
|
1194
|
+
}
|
|
1195
|
+
onCrash(callback) {
|
|
1196
|
+
this._onCrash = callback;
|
|
1197
|
+
}
|
|
1198
|
+
onReconnect(callback) {
|
|
1199
|
+
this._onReconnect = callback;
|
|
1200
|
+
}
|
|
1201
|
+
get topics() {
|
|
1202
|
+
return this._topics;
|
|
1203
|
+
}
|
|
1204
|
+
get callbackList() {
|
|
1205
|
+
return this._callbackList;
|
|
538
1206
|
}
|
|
539
1207
|
};
|
|
540
|
-
_ErrorManager.DEFAULT_MESSAGES = {
|
|
541
|
-
"es": "Ups, hemos encontrado un error. Nuestro equipo ya est\xE1 trabajando para solucionarlo",
|
|
542
|
-
"en": "Ups, we found an error. Our team is working on it.",
|
|
543
|
-
"pt": "Ops, encontramos um bug. Nossa equipe j\xE1 est\xE1 trabalhando para resolver isso."
|
|
544
|
-
};
|
|
545
|
-
_ErrorManager.APP_ERRORS = {
|
|
546
|
-
UNDEFINED: "UNDEFINED_ERROR",
|
|
547
|
-
PROCESS: "PROCESS_ERROR",
|
|
548
|
-
DATABASE: "DATABASE_ERROR"
|
|
549
|
-
};
|
|
550
|
-
_ErrorManager.TEMPLATES = /* @__PURE__ */ new Map();
|
|
551
|
-
var ErrorManager = _ErrorManager;
|
|
552
|
-
|
|
553
|
-
// src/infrastructure/mysql/MysqlConnector.ts
|
|
554
|
-
var import_promise = require("mysql2/promise");
|
|
555
1208
|
|
|
556
|
-
// src/infrastructure/
|
|
557
|
-
var
|
|
558
|
-
constructor(
|
|
559
|
-
this.
|
|
1209
|
+
// src/infrastructure/contracts/OutboxRecord.ts
|
|
1210
|
+
var OutboxRecord = class _OutboxRecord {
|
|
1211
|
+
constructor(eventUuid, eventType, tenantUuid, aggregateUuid, aggregateType, topic, payload, status, attempts, errorMessage, publishedAt, lastAttempt, createdAt) {
|
|
1212
|
+
this._eventUuid = eventUuid;
|
|
1213
|
+
this._tenantUuid = tenantUuid;
|
|
1214
|
+
this._aggregateUuid = aggregateUuid;
|
|
1215
|
+
this._aggregateType = aggregateType;
|
|
1216
|
+
this._eventType = eventType;
|
|
1217
|
+
this._topic = topic;
|
|
1218
|
+
this._payload = payload;
|
|
1219
|
+
this._status = status;
|
|
1220
|
+
this._attempts = attempts;
|
|
1221
|
+
this._errorMessage = errorMessage;
|
|
1222
|
+
this._publishedAt = publishedAt;
|
|
1223
|
+
this._lastAttempt = lastAttempt;
|
|
1224
|
+
this._createdAt = createdAt ?? DateTime.now();
|
|
560
1225
|
}
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
return rows;
|
|
1226
|
+
get eventUuid() {
|
|
1227
|
+
return this._eventUuid;
|
|
564
1228
|
}
|
|
565
|
-
|
|
566
|
-
|
|
1229
|
+
get tenantUuid() {
|
|
1230
|
+
return this._tenantUuid;
|
|
567
1231
|
}
|
|
568
|
-
|
|
569
|
-
|
|
1232
|
+
get aggregateUuid() {
|
|
1233
|
+
return this._aggregateUuid;
|
|
570
1234
|
}
|
|
571
|
-
|
|
572
|
-
|
|
1235
|
+
get aggregateType() {
|
|
1236
|
+
return this._aggregateType;
|
|
573
1237
|
}
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
try {
|
|
577
|
-
const result = await fn(this);
|
|
578
|
-
await this.commit();
|
|
579
|
-
return result;
|
|
580
|
-
} catch (err) {
|
|
581
|
-
await this.rollback();
|
|
582
|
-
throw err;
|
|
583
|
-
}
|
|
1238
|
+
get eventType() {
|
|
1239
|
+
return this._eventType;
|
|
584
1240
|
}
|
|
585
|
-
|
|
586
|
-
this.
|
|
1241
|
+
get topic() {
|
|
1242
|
+
return this._topic;
|
|
1243
|
+
}
|
|
1244
|
+
get payload() {
|
|
1245
|
+
return this._payload;
|
|
1246
|
+
}
|
|
1247
|
+
get status() {
|
|
1248
|
+
return this._status;
|
|
1249
|
+
}
|
|
1250
|
+
get attempts() {
|
|
1251
|
+
return this._attempts;
|
|
1252
|
+
}
|
|
1253
|
+
get errorMessage() {
|
|
1254
|
+
return this._errorMessage;
|
|
1255
|
+
}
|
|
1256
|
+
get publishedAt() {
|
|
1257
|
+
return this._publishedAt;
|
|
1258
|
+
}
|
|
1259
|
+
get lastAttempt() {
|
|
1260
|
+
return this._lastAttempt;
|
|
1261
|
+
}
|
|
1262
|
+
get createdAt() {
|
|
1263
|
+
return this._createdAt;
|
|
1264
|
+
}
|
|
1265
|
+
incrementAttempts() {
|
|
1266
|
+
this._attempts++;
|
|
1267
|
+
this._lastAttempt = DateTime.now();
|
|
1268
|
+
}
|
|
1269
|
+
markProcessed() {
|
|
1270
|
+
this._status = ProcessStatus.PROCESSED;
|
|
1271
|
+
this._publishedAt = DateTime.now();
|
|
1272
|
+
}
|
|
1273
|
+
markProcessing() {
|
|
1274
|
+
this.incrementAttempts();
|
|
1275
|
+
this._status = ProcessStatus.PROCESSING;
|
|
1276
|
+
}
|
|
1277
|
+
markWithError(error) {
|
|
1278
|
+
this._status = this.attempts < 5 ? ProcessStatus.FAILED : ProcessStatus.DEAD;
|
|
1279
|
+
this._errorMessage = error;
|
|
1280
|
+
}
|
|
1281
|
+
toPrimitives() {
|
|
1282
|
+
return {
|
|
1283
|
+
eventUuid: this.eventUuid.value,
|
|
1284
|
+
eventType: this.eventType,
|
|
1285
|
+
tenantUuid: this.tenantUuid.value,
|
|
1286
|
+
aggregateUuid: this.aggregateUuid.value,
|
|
1287
|
+
aggregateType: this.aggregateType,
|
|
1288
|
+
topic: this.topic,
|
|
1289
|
+
payload: this.payload,
|
|
1290
|
+
status: this.status.value,
|
|
1291
|
+
attempts: this.attempts,
|
|
1292
|
+
errorMessage: this.errorMessage ?? void 0,
|
|
1293
|
+
publishedAt: this.publishedAt?.value ?? void 0,
|
|
1294
|
+
lastAttempt: this.lastAttempt?.value ?? void 0,
|
|
1295
|
+
createdAt: this.createdAt.value
|
|
1296
|
+
};
|
|
1297
|
+
}
|
|
1298
|
+
static reconstitute(data) {
|
|
1299
|
+
return new _OutboxRecord(
|
|
1300
|
+
UUID.create(data.event_uuid),
|
|
1301
|
+
String(data.event_type),
|
|
1302
|
+
UUID.create(data.tenant_uuid),
|
|
1303
|
+
UUID.create(data.aggregate_uuid),
|
|
1304
|
+
String(data.aggregate_type),
|
|
1305
|
+
String(data.topic),
|
|
1306
|
+
String(data.payload),
|
|
1307
|
+
ProcessStatus.create(data.status),
|
|
1308
|
+
Number(data.attempts),
|
|
1309
|
+
data.error_message ?? void 0,
|
|
1310
|
+
data.published_at ? DateTime.create(data.published_at) : void 0,
|
|
1311
|
+
data.last_attempt ? DateTime.create(data.last_attempt) : void 0,
|
|
1312
|
+
data.created_at ? DateTime.create(data.created_at) : void 0
|
|
1313
|
+
);
|
|
587
1314
|
}
|
|
588
1315
|
};
|
|
589
1316
|
|
|
590
|
-
// src/infrastructure/
|
|
591
|
-
var
|
|
592
|
-
constructor(
|
|
593
|
-
this.
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
1317
|
+
// src/infrastructure/contracts/InboxRecord.ts
|
|
1318
|
+
var InboxRecord = class _InboxRecord {
|
|
1319
|
+
constructor(eventUuid, tenantUuid, topic, producer, payload, status, attempts, errorMessage, lastAttempt, processedAt, createdAt) {
|
|
1320
|
+
this._eventUuid = eventUuid;
|
|
1321
|
+
this._tenantUuid = tenantUuid;
|
|
1322
|
+
this._topic = topic;
|
|
1323
|
+
this._producer = producer;
|
|
1324
|
+
this._payload = payload;
|
|
1325
|
+
this._status = status;
|
|
1326
|
+
this._attempts = attempts ?? 0;
|
|
1327
|
+
this._errorMessage = errorMessage ?? void 0;
|
|
1328
|
+
this._lastAttempt = lastAttempt ?? void 0;
|
|
1329
|
+
this._processedAt = processedAt ?? void 0;
|
|
1330
|
+
this._createdAt = createdAt ?? DateTime.now();
|
|
602
1331
|
}
|
|
603
|
-
|
|
604
|
-
return
|
|
1332
|
+
get eventUuid() {
|
|
1333
|
+
return this._eventUuid;
|
|
605
1334
|
}
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
return this.wrap(conn);
|
|
1335
|
+
get tenantUuid() {
|
|
1336
|
+
return this._tenantUuid;
|
|
609
1337
|
}
|
|
610
|
-
|
|
611
|
-
|
|
1338
|
+
get topic() {
|
|
1339
|
+
return this._topic;
|
|
612
1340
|
}
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
1341
|
+
get producer() {
|
|
1342
|
+
return this._producer;
|
|
1343
|
+
}
|
|
1344
|
+
get payload() {
|
|
1345
|
+
return this._payload;
|
|
1346
|
+
}
|
|
1347
|
+
get status() {
|
|
1348
|
+
return this._status;
|
|
1349
|
+
}
|
|
1350
|
+
get attempts() {
|
|
1351
|
+
return this._attempts;
|
|
1352
|
+
}
|
|
1353
|
+
get errorMessage() {
|
|
1354
|
+
return this._errorMessage;
|
|
1355
|
+
}
|
|
1356
|
+
get lastAttempt() {
|
|
1357
|
+
return this._lastAttempt;
|
|
1358
|
+
}
|
|
1359
|
+
get processedAt() {
|
|
1360
|
+
return this._processedAt;
|
|
1361
|
+
}
|
|
1362
|
+
get createdAt() {
|
|
1363
|
+
return this._createdAt;
|
|
1364
|
+
}
|
|
1365
|
+
incrementAttempts() {
|
|
1366
|
+
this._attempts++;
|
|
1367
|
+
this._lastAttempt = DateTime.now();
|
|
1368
|
+
}
|
|
1369
|
+
markProcessed() {
|
|
1370
|
+
this._status = ProcessStatus.PROCESSED;
|
|
1371
|
+
this._processedAt = DateTime.now();
|
|
1372
|
+
}
|
|
1373
|
+
markProcessing() {
|
|
1374
|
+
this.incrementAttempts();
|
|
1375
|
+
this._status = ProcessStatus.PROCESSING;
|
|
1376
|
+
}
|
|
1377
|
+
markWithError(error) {
|
|
1378
|
+
this._status = this.attempts < 5 ? ProcessStatus.FAILED : ProcessStatus.DEAD;
|
|
1379
|
+
this._errorMessage = error;
|
|
1380
|
+
}
|
|
1381
|
+
toPrimitives() {
|
|
1382
|
+
return {
|
|
1383
|
+
eventUuid: this.eventUuid.value,
|
|
1384
|
+
tenantUuid: this.tenantUuid.value,
|
|
1385
|
+
topic: this.topic,
|
|
1386
|
+
producer: this.producer,
|
|
1387
|
+
payload: this.payload,
|
|
1388
|
+
status: this.status.value,
|
|
1389
|
+
attempts: this.attempts,
|
|
1390
|
+
errorMessage: this.errorMessage ?? void 0,
|
|
1391
|
+
lastAttempt: this.lastAttempt?.value ?? void 0,
|
|
1392
|
+
processedAt: this.processedAt?.value ?? void 0,
|
|
1393
|
+
createdAt: this.createdAt.value
|
|
1394
|
+
};
|
|
1395
|
+
}
|
|
1396
|
+
static reconstitute(data) {
|
|
1397
|
+
return new _InboxRecord(
|
|
1398
|
+
UUID.create(data.event_uuid),
|
|
1399
|
+
UUID.create(data.tenant_uuid),
|
|
1400
|
+
String(data.topic),
|
|
1401
|
+
String(data.producer),
|
|
1402
|
+
String(data.payload),
|
|
1403
|
+
ProcessStatus.create(data.status),
|
|
1404
|
+
Number(data.attempts),
|
|
1405
|
+
data.error_message ?? void 0,
|
|
1406
|
+
data.last_attempt ? DateTime.create(data.last_attempt) : void 0,
|
|
1407
|
+
data.processed_at ? DateTime.create(data.processed_at) : void 0,
|
|
1408
|
+
data.created_at ? DateTime.create(data.created_at) : void 0
|
|
1409
|
+
);
|
|
1410
|
+
}
|
|
1411
|
+
};
|
|
1412
|
+
|
|
1413
|
+
// src/infrastructure/event-bus/EventBusMysqlRepository.ts
|
|
1414
|
+
var EventBusMysqlRepository = class {
|
|
1415
|
+
constructor(connection) {
|
|
1416
|
+
this.connection = connection;
|
|
1417
|
+
}
|
|
1418
|
+
recordToRowValues(record) {
|
|
1419
|
+
return [
|
|
1420
|
+
record.eventUuid.value,
|
|
1421
|
+
record.eventType,
|
|
1422
|
+
record.tenantUuid.value,
|
|
1423
|
+
record.aggregateUuid.value,
|
|
1424
|
+
record.aggregateType,
|
|
1425
|
+
record.topic,
|
|
1426
|
+
record.payload,
|
|
1427
|
+
record.status.value,
|
|
1428
|
+
record.attempts,
|
|
1429
|
+
record.errorMessage,
|
|
1430
|
+
record.publishedAt?.value,
|
|
1431
|
+
record.lastAttempt?.value,
|
|
1432
|
+
record.createdAt.value
|
|
1433
|
+
];
|
|
1434
|
+
}
|
|
1435
|
+
async create(record) {
|
|
1436
|
+
const values = this.recordToRowValues(record);
|
|
1437
|
+
await this.connection.query(
|
|
1438
|
+
`INSERT INTO events_outbox (event_uuid, event_type, tenant_uuid, aggregate_uuid, aggregate_type, topic,
|
|
1439
|
+
payload, status, attempts, error_message, published_at, last_attempt, created_at)
|
|
1440
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
1441
|
+
values
|
|
1442
|
+
);
|
|
1443
|
+
}
|
|
1444
|
+
async update(record) {
|
|
1445
|
+
const values = [record.status.value, record.attempts, record.errorMessage, record.publishedAt?.value, record.lastAttempt?.value, record.eventUuid.value];
|
|
1446
|
+
await this.connection.query(
|
|
1447
|
+
`UPDATE events_outbox
|
|
1448
|
+
SET status = ?,
|
|
1449
|
+
attempts = ?,
|
|
1450
|
+
error_message = ?,
|
|
1451
|
+
published_at = ?,
|
|
1452
|
+
last_attempt = ?
|
|
1453
|
+
WHERE event_uuid = ?`,
|
|
1454
|
+
values
|
|
1455
|
+
);
|
|
1456
|
+
}
|
|
1457
|
+
async listPending(limit) {
|
|
1458
|
+
const result = await this.connection.query(
|
|
1459
|
+
`SELECT * FROM events_outbox WHERE status IN ('PENDING','FAILED') AND published_at IS NULL LIMIT ${limit}`,
|
|
1460
|
+
[]
|
|
1461
|
+
);
|
|
1462
|
+
return result.length > 0 ? result.map((r) => OutboxRecord.reconstitute(r)) : [];
|
|
625
1463
|
}
|
|
626
1464
|
};
|
|
627
|
-
_MysqlConnector.DEFAULT_POOL_SIZE = 10;
|
|
628
|
-
var MysqlConnector = _MysqlConnector;
|
|
629
1465
|
|
|
630
1466
|
// src/infrastructure/express/ExpressAdapters.ts
|
|
1467
|
+
var BOOL_TRUE = /* @__PURE__ */ new Set(["1", "true", "yes", "y", "on"]);
|
|
1468
|
+
var BOOL_FALSE = /* @__PURE__ */ new Set(["0", "false", "no", "n", "off"]);
|
|
1469
|
+
var NUMERIC_KEY_RE = /^(?:page|qty|limit|offset|total|amount|price|count|rounding|min[A-Z_].*|max[A-Z_].*)$/i;
|
|
1470
|
+
var DATE_KEY_RE = /(At|Date|_at|_date)$/i;
|
|
1471
|
+
function toUtcDateTimeString(raw) {
|
|
1472
|
+
const s = raw.trim();
|
|
1473
|
+
if (/^\d{4}-\d{2}-\d{2}$/.test(s))
|
|
1474
|
+
return `${s} 00:00:00`;
|
|
1475
|
+
if (/^\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2}$/.test(s))
|
|
1476
|
+
return s;
|
|
1477
|
+
const d = new Date(s);
|
|
1478
|
+
if (Number.isNaN(d.getTime()))
|
|
1479
|
+
return void 0;
|
|
1480
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
1481
|
+
return `${d.getUTCFullYear()}-${pad(d.getUTCMonth() + 1)}-${pad(d.getUTCDate())} ${pad(d.getUTCHours())}:${pad(d.getUTCMinutes())}:${pad(d.getUTCSeconds())}`;
|
|
1482
|
+
}
|
|
1483
|
+
function coerceScalar(key, v) {
|
|
1484
|
+
if (v == null)
|
|
1485
|
+
return void 0;
|
|
1486
|
+
if (typeof v !== "string")
|
|
1487
|
+
return v;
|
|
1488
|
+
const s = v.trim();
|
|
1489
|
+
if (s === "")
|
|
1490
|
+
return void 0;
|
|
1491
|
+
if (s.toLowerCase() === "null")
|
|
1492
|
+
return null;
|
|
1493
|
+
const low = s.toLowerCase();
|
|
1494
|
+
if (BOOL_TRUE.has(low))
|
|
1495
|
+
return true;
|
|
1496
|
+
if (BOOL_FALSE.has(low))
|
|
1497
|
+
return false;
|
|
1498
|
+
if (NUMERIC_KEY_RE.test(key) && /^-?\d+(\.\d+)?$/.test(s)) {
|
|
1499
|
+
const n = Number(s);
|
|
1500
|
+
if (Number.isFinite(n))
|
|
1501
|
+
return n;
|
|
1502
|
+
}
|
|
1503
|
+
if (DATE_KEY_RE.test(key)) {
|
|
1504
|
+
return toUtcDateTimeString(s) ?? s;
|
|
1505
|
+
}
|
|
1506
|
+
return s;
|
|
1507
|
+
}
|
|
1508
|
+
function normalizeQuery(q) {
|
|
1509
|
+
const out = {};
|
|
1510
|
+
for (const [key, raw] of Object.entries(q)) {
|
|
1511
|
+
const values = Array.isArray(raw) ? raw : typeof raw === "string" && raw.includes(",") ? raw.split(",").map((s) => s.trim()).filter(Boolean) : [raw];
|
|
1512
|
+
const coerced = values.map((v) => coerceScalar(key, v)).filter((v) => v !== void 0);
|
|
1513
|
+
if (coerced.length === 1)
|
|
1514
|
+
out[key] = coerced[0];
|
|
1515
|
+
else if (coerced.length > 1)
|
|
1516
|
+
out[key] = coerced;
|
|
1517
|
+
}
|
|
1518
|
+
return out;
|
|
1519
|
+
}
|
|
1520
|
+
function isReadableStream(x) {
|
|
1521
|
+
return x && typeof x.pipe === "function";
|
|
1522
|
+
}
|
|
1523
|
+
function hasHeader(headers, name) {
|
|
1524
|
+
if (!headers)
|
|
1525
|
+
return false;
|
|
1526
|
+
const lname = name.toLowerCase();
|
|
1527
|
+
return Object.keys(headers).some((h) => h.toLowerCase() === lname);
|
|
1528
|
+
}
|
|
631
1529
|
function adaptExpressRoute(Controller) {
|
|
632
1530
|
return async (req, res, next) => {
|
|
633
1531
|
const rawLangHeader = req.headers["accept-language"] ?? req.headers["Accept-Language"] ?? "es";
|
|
@@ -636,20 +1534,55 @@ function adaptExpressRoute(Controller) {
|
|
|
636
1534
|
const httpRequest = {
|
|
637
1535
|
headers: req.headers,
|
|
638
1536
|
params: req.params,
|
|
639
|
-
query:
|
|
1537
|
+
query: normalizeQuery(req.query),
|
|
640
1538
|
lang,
|
|
641
1539
|
body: req.body
|
|
642
1540
|
};
|
|
643
1541
|
try {
|
|
644
1542
|
const controller = new Controller();
|
|
645
|
-
const { statusCode, body } = await controller.handle(httpRequest);
|
|
646
|
-
|
|
1543
|
+
const { statusCode, body, headers } = await controller.handle(httpRequest);
|
|
1544
|
+
if (headers)
|
|
1545
|
+
res.set(headers);
|
|
1546
|
+
if (isReadableStream(body)) {
|
|
1547
|
+
if (!hasHeader(headers, "Content-Type"))
|
|
1548
|
+
res.set("Content-Type", "application/octet-stream");
|
|
1549
|
+
res.status(statusCode);
|
|
1550
|
+
body.on("error", next);
|
|
1551
|
+
body.pipe(res);
|
|
1552
|
+
return;
|
|
1553
|
+
}
|
|
1554
|
+
const isArrayBuffer = typeof body === "object" && body instanceof ArrayBuffer;
|
|
1555
|
+
const isArrayBufferView = typeof body === "object" && body != null && ArrayBuffer.isView(body);
|
|
1556
|
+
if (Buffer.isBuffer(body) || isArrayBuffer || isArrayBufferView) {
|
|
1557
|
+
let buf;
|
|
1558
|
+
if (Buffer.isBuffer(body)) {
|
|
1559
|
+
buf = body;
|
|
1560
|
+
} else if (isArrayBuffer) {
|
|
1561
|
+
buf = Buffer.from(body);
|
|
1562
|
+
} else {
|
|
1563
|
+
const view = body;
|
|
1564
|
+
buf = Buffer.from(view.buffer, view.byteOffset, view.byteLength);
|
|
1565
|
+
}
|
|
1566
|
+
if (!hasHeader(headers, "Content-Type"))
|
|
1567
|
+
res.set("Content-Type", "application/octet-stream");
|
|
1568
|
+
if (!res.getHeader("Content-Length"))
|
|
1569
|
+
res.set("Content-Length", String(buf.length));
|
|
1570
|
+
res.status(statusCode);
|
|
1571
|
+
res.end(buf);
|
|
1572
|
+
return;
|
|
1573
|
+
}
|
|
1574
|
+
const hasCT = hasHeader(headers, "Content-Type");
|
|
1575
|
+
if (typeof body === "string" || hasCT) {
|
|
1576
|
+
res.status(statusCode).send(body);
|
|
1577
|
+
return;
|
|
1578
|
+
}
|
|
1579
|
+
res.status(statusCode).json(body ?? {});
|
|
647
1580
|
} catch (err) {
|
|
648
1581
|
next(err);
|
|
649
1582
|
}
|
|
650
1583
|
};
|
|
651
1584
|
}
|
|
652
|
-
function
|
|
1585
|
+
function adaptExpressErrorHandler(errorManager) {
|
|
653
1586
|
return (err, req, res, next) => {
|
|
654
1587
|
const raw = req.headers["accept-language"] ?? req.headers["Accept-Language"] ?? "es";
|
|
655
1588
|
const rawLang = Array.isArray(raw) ? raw[0] : raw ?? "";
|
|
@@ -660,75 +1593,465 @@ function adaptErrorHandler(errorManager) {
|
|
|
660
1593
|
};
|
|
661
1594
|
}
|
|
662
1595
|
|
|
663
|
-
// src/infrastructure/http/
|
|
1596
|
+
// src/infrastructure/http/DefaultController.ts
|
|
1597
|
+
var HttpHealthCheckController = class {
|
|
1598
|
+
async handle(request) {
|
|
1599
|
+
return {
|
|
1600
|
+
statusCode: 200,
|
|
1601
|
+
body: {
|
|
1602
|
+
date: DateTime.create().value,
|
|
1603
|
+
code: 200
|
|
1604
|
+
}
|
|
1605
|
+
};
|
|
1606
|
+
}
|
|
1607
|
+
};
|
|
664
1608
|
var HttpNotFoundController = class {
|
|
665
1609
|
async handle(request) {
|
|
666
1610
|
return {
|
|
667
1611
|
statusCode: 404,
|
|
668
1612
|
body: {
|
|
669
|
-
status: "NOT_FOUND",
|
|
670
1613
|
message: `Route ${request.headers.location} not found`
|
|
671
1614
|
}
|
|
672
1615
|
};
|
|
673
1616
|
}
|
|
674
1617
|
};
|
|
675
1618
|
|
|
676
|
-
// src/infrastructure/
|
|
677
|
-
var
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
1619
|
+
// src/infrastructure/kafka/KafkaManager.ts
|
|
1620
|
+
var import_kafkajs = require("kafkajs");
|
|
1621
|
+
var KafkaManager = class extends EventManager {
|
|
1622
|
+
constructor(connection) {
|
|
1623
|
+
super(connection);
|
|
1624
|
+
this.kafka = new import_kafkajs.Kafka({
|
|
1625
|
+
brokers: this._connection.brokers,
|
|
1626
|
+
ssl: true,
|
|
1627
|
+
sasl: {
|
|
1628
|
+
mechanism: "scram-sha-256",
|
|
1629
|
+
username: this._connection.userName,
|
|
1630
|
+
password: this._connection.password
|
|
1631
|
+
},
|
|
1632
|
+
logLevel: import_kafkajs.logLevel.ERROR
|
|
1633
|
+
});
|
|
1634
|
+
this.consumer = this.kafka.consumer({ groupId: process.env.KAFKA_GROUP || "default" });
|
|
1635
|
+
this.producer = this.kafka.producer();
|
|
1636
|
+
}
|
|
1637
|
+
async run(autocommit) {
|
|
1638
|
+
const __run = async () => {
|
|
1639
|
+
await this.execCallback(this._onStart, { message: `--- ${this.constructor.name} started ---` });
|
|
1640
|
+
await this.consumer.connect();
|
|
1641
|
+
await this.execCallback(this._onConnected, { message: `--- ${this.constructor.name} connected to ${this._connection.brokers} ---` });
|
|
1642
|
+
for (let topic of this._topics) {
|
|
1643
|
+
try {
|
|
1644
|
+
await this.consumer.subscribe({ topic, fromBeginning: true });
|
|
1645
|
+
await this.execCallback(this._onSubscribe, { message: `--- ${this.constructor.name} subscribed to ${topic} ---` });
|
|
1646
|
+
} catch (error) {
|
|
1647
|
+
await this.execCallback(this._onConnected, { message: `Error on subscribe to kafka topic: ${topic}` });
|
|
1648
|
+
}
|
|
685
1649
|
}
|
|
1650
|
+
await this.consumer.run({
|
|
1651
|
+
autoCommit: autocommit,
|
|
1652
|
+
// @ts-ignore
|
|
1653
|
+
eachMessage: async ({ topic, partition, message, heartbeat }) => {
|
|
1654
|
+
try {
|
|
1655
|
+
await this.execCallback(this._onMessage, `[New message detected for ${topic}]: ${message.value?.toString()}`);
|
|
1656
|
+
const json = JSON.parse(String(message.value?.toString()));
|
|
1657
|
+
await this.execRoute(topic, {
|
|
1658
|
+
topic: String(json.topic),
|
|
1659
|
+
producer: String(json.producer),
|
|
1660
|
+
tenant: UUID.create(String(json.tenant)),
|
|
1661
|
+
message: json.message
|
|
1662
|
+
});
|
|
1663
|
+
const next = (BigInt(message.offset) + 1n).toString();
|
|
1664
|
+
await this.consumer.commitOffsets([{ topic, partition, offset: next }]);
|
|
1665
|
+
await heartbeat();
|
|
1666
|
+
} catch (error) {
|
|
1667
|
+
await this.execCallback(this._onError, error);
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
});
|
|
686
1671
|
};
|
|
1672
|
+
try {
|
|
1673
|
+
await __run();
|
|
1674
|
+
} catch (error) {
|
|
1675
|
+
await this.execCallback(this._onError, new InternalError(ErrorManager.APP_ERRORS.PROCESS, error.toString()));
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
async send(e) {
|
|
1679
|
+
const evt = {
|
|
1680
|
+
date: DateTime.now().value,
|
|
1681
|
+
tenant: e.tenant.value,
|
|
1682
|
+
producer: e.producer,
|
|
1683
|
+
data: JSON.parse(e.message)
|
|
1684
|
+
};
|
|
1685
|
+
try {
|
|
1686
|
+
if (!this.producer) {
|
|
1687
|
+
throw new InternalError(ErrorManager.APP_ERRORS.PROCESS, "Producer not initialized");
|
|
1688
|
+
}
|
|
1689
|
+
await this.producer.connect();
|
|
1690
|
+
await this.producer.send({
|
|
1691
|
+
topic: e.topic,
|
|
1692
|
+
messages: [{ value: JSON.stringify(evt) }]
|
|
1693
|
+
});
|
|
1694
|
+
await this.producer.disconnect();
|
|
1695
|
+
} catch (error) {
|
|
1696
|
+
throw new InternalError(error.toString());
|
|
1697
|
+
}
|
|
1698
|
+
}
|
|
1699
|
+
async start(autocommit = false) {
|
|
1700
|
+
this.consumer.on(this.consumer.events.CRASH, async (error) => {
|
|
1701
|
+
await this.execCallback(this._onError, new InternalError(ErrorManager.APP_ERRORS.PROCESS, error.payload.error.stack));
|
|
1702
|
+
});
|
|
1703
|
+
await this.run(autocommit);
|
|
1704
|
+
}
|
|
1705
|
+
async pause() {
|
|
1706
|
+
}
|
|
1707
|
+
async restart() {
|
|
1708
|
+
await this.consumer.stop();
|
|
1709
|
+
await this.start();
|
|
1710
|
+
}
|
|
1711
|
+
async stop() {
|
|
1712
|
+
await this.consumer.stop();
|
|
687
1713
|
}
|
|
688
1714
|
};
|
|
689
1715
|
|
|
690
|
-
// src/infrastructure/
|
|
691
|
-
var
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
this.
|
|
1716
|
+
// src/infrastructure/mysql/Mysql.ts
|
|
1717
|
+
var import_promise = require("mysql2/promise");
|
|
1718
|
+
var _MysqlConnector = class _MysqlConnector {
|
|
1719
|
+
constructor(pool) {
|
|
1720
|
+
this._pool = pool ?? (0, import_promise.createPool)({
|
|
1721
|
+
host: process.env.DB_HOST,
|
|
1722
|
+
port: Number(process.env.DB_PORT ?? 3306),
|
|
1723
|
+
user: process.env.DB_USER,
|
|
1724
|
+
password: process.env.DB_PASSWORD,
|
|
1725
|
+
database: process.env.DB_DATABASE,
|
|
1726
|
+
dateStrings: true,
|
|
1727
|
+
connectionLimit: Number(process.env.DB_POOL_SIZE ?? _MysqlConnector.DEFAULT_POOL_SIZE),
|
|
1728
|
+
decimalNumbers: true
|
|
1729
|
+
});
|
|
695
1730
|
}
|
|
696
|
-
async
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
1731
|
+
async wrap(conn) {
|
|
1732
|
+
return new MysqlConnection(conn);
|
|
1733
|
+
}
|
|
1734
|
+
async query(sql, params = []) {
|
|
1735
|
+
const [rows] = await this._pool.query(sql, params);
|
|
1736
|
+
return rows;
|
|
1737
|
+
}
|
|
1738
|
+
async getConnection() {
|
|
1739
|
+
const conn = await this._pool.getConnection();
|
|
1740
|
+
return this.wrap(conn);
|
|
1741
|
+
}
|
|
1742
|
+
async closePool() {
|
|
1743
|
+
await this._pool.end();
|
|
1744
|
+
}
|
|
1745
|
+
static async ping() {
|
|
1746
|
+
const connector = new _MysqlConnector();
|
|
1747
|
+
try {
|
|
1748
|
+
const conn = await connector._pool.getConnection();
|
|
1749
|
+
await conn.ping();
|
|
1750
|
+
conn.release();
|
|
1751
|
+
return true;
|
|
1752
|
+
} catch {
|
|
1753
|
+
return false;
|
|
1754
|
+
} finally {
|
|
1755
|
+
await connector.closePool();
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
};
|
|
1759
|
+
_MysqlConnector.DEFAULT_POOL_SIZE = 20;
|
|
1760
|
+
var MysqlConnector = _MysqlConnector;
|
|
1761
|
+
var MysqlConnection = class {
|
|
1762
|
+
constructor(conn) {
|
|
1763
|
+
this._conn = conn;
|
|
1764
|
+
}
|
|
1765
|
+
async query(statement, params = []) {
|
|
1766
|
+
const [rows] = await this._conn.query(statement, params);
|
|
1767
|
+
return rows;
|
|
1768
|
+
}
|
|
1769
|
+
async begin() {
|
|
1770
|
+
await this._conn.beginTransaction();
|
|
1771
|
+
}
|
|
1772
|
+
async commit() {
|
|
1773
|
+
await this._conn.commit();
|
|
1774
|
+
}
|
|
1775
|
+
async rollback() {
|
|
1776
|
+
await this._conn.rollback();
|
|
1777
|
+
}
|
|
1778
|
+
async transaction(fn) {
|
|
1779
|
+
await this.begin();
|
|
1780
|
+
try {
|
|
1781
|
+
const result = await fn(this);
|
|
1782
|
+
await this.commit();
|
|
1783
|
+
return result;
|
|
1784
|
+
} catch (err) {
|
|
1785
|
+
await this.rollback();
|
|
1786
|
+
throw err;
|
|
1787
|
+
}
|
|
1788
|
+
}
|
|
1789
|
+
async close() {
|
|
1790
|
+
await this._conn.release();
|
|
1791
|
+
}
|
|
1792
|
+
};
|
|
1793
|
+
|
|
1794
|
+
// src/infrastructure/runners/default-mysql-outbox-runner.ts
|
|
1795
|
+
var DefaultMysqlOutboxRunner = class {
|
|
1796
|
+
constructor(uowFactory, eventManager) {
|
|
1797
|
+
this.errors = [];
|
|
1798
|
+
this.uowFactory = uowFactory;
|
|
1799
|
+
this.eventManager = eventManager;
|
|
1800
|
+
this.interval = Number(process.env.OUTBOX_RUNNER_INTERVAL_MS || 5e3);
|
|
1801
|
+
this.maxEvents = Number(process.env.OUTBOX_RUNNER_MAX_EVENTS || 20);
|
|
1802
|
+
}
|
|
1803
|
+
addError(error) {
|
|
1804
|
+
this.errors.push(error);
|
|
1805
|
+
}
|
|
1806
|
+
logErrors() {
|
|
1807
|
+
if (this.errors.length > 0) {
|
|
1808
|
+
console.error(this.errors);
|
|
1809
|
+
this.errors = [];
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1812
|
+
async sleep() {
|
|
1813
|
+
return new Promise((r) => setTimeout(r, this.maxEvents));
|
|
1814
|
+
}
|
|
1815
|
+
async processOutboxRecord(e, eventBusRepository) {
|
|
1816
|
+
try {
|
|
1817
|
+
e.markProcessing();
|
|
1818
|
+
await eventBusRepository.update(e);
|
|
1819
|
+
await this.eventManager.send({
|
|
1820
|
+
topic: e.topic,
|
|
1821
|
+
producer: process.env.NAME && process.env.ENVIRONMENT ? `${process.env.NAME}-${process.env.ENVIRONMENT}` : "unknown",
|
|
1822
|
+
tenant: e.tenantUuid,
|
|
1823
|
+
message: e.payload
|
|
1824
|
+
});
|
|
1825
|
+
e.markProcessed();
|
|
1826
|
+
} catch (error) {
|
|
1827
|
+
const type = String(error.type);
|
|
1828
|
+
e.markWithError(type);
|
|
1829
|
+
throw new Error(type);
|
|
1830
|
+
} finally {
|
|
1831
|
+
await eventBusRepository.update(e);
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
async process() {
|
|
1835
|
+
const uow = await this.uowFactory.create();
|
|
1836
|
+
const eventBusRepository = new EventBusMysqlRepository(uow.connection);
|
|
1837
|
+
await uow.execute(async () => {
|
|
1838
|
+
const records = await eventBusRepository.listPending(this.maxEvents);
|
|
1839
|
+
for (let record of records) {
|
|
1840
|
+
try {
|
|
1841
|
+
await this.processOutboxRecord(record, eventBusRepository);
|
|
1842
|
+
} catch (error) {
|
|
1843
|
+
this.addError({ eventUuid: record.eventUuid.value, error: error.toString() });
|
|
1844
|
+
}
|
|
1845
|
+
}
|
|
1846
|
+
this.logErrors();
|
|
1847
|
+
});
|
|
1848
|
+
}
|
|
1849
|
+
async start() {
|
|
1850
|
+
console.log("[outbox-runner]: start");
|
|
1851
|
+
for (; ; ) {
|
|
1852
|
+
await this.process();
|
|
1853
|
+
await this.sleep();
|
|
1854
|
+
}
|
|
1855
|
+
}
|
|
1856
|
+
};
|
|
1857
|
+
|
|
1858
|
+
// src/infrastructure/inbox/InboxMysqlRepository.ts
|
|
1859
|
+
var InboxMysqlRepository = class {
|
|
1860
|
+
constructor(connection) {
|
|
1861
|
+
this.connection = connection;
|
|
1862
|
+
}
|
|
1863
|
+
recordToRowValues(record) {
|
|
1864
|
+
return [
|
|
1865
|
+
record.eventUuid.value,
|
|
1866
|
+
record.tenantUuid.value,
|
|
1867
|
+
record.topic,
|
|
1868
|
+
record.producer,
|
|
1869
|
+
record.payload,
|
|
1870
|
+
record.status.value,
|
|
1871
|
+
record.attempts,
|
|
1872
|
+
record.errorMessage,
|
|
1873
|
+
record.lastAttempt?.value ?? null,
|
|
1874
|
+
record.processedAt?.value ?? null,
|
|
1875
|
+
record.createdAt.value
|
|
1876
|
+
];
|
|
1877
|
+
}
|
|
1878
|
+
async create(record) {
|
|
1879
|
+
const values = this.recordToRowValues(record);
|
|
1880
|
+
await this.connection.query(
|
|
1881
|
+
`INSERT INTO events_inbox (event_uuid, tenant_uuid, topic, producer,
|
|
1882
|
+
payload, status, attempts, error_message, last_attempt, processed_at, created_at)
|
|
1883
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
1884
|
+
values
|
|
700
1885
|
);
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
1886
|
+
}
|
|
1887
|
+
async update(record) {
|
|
1888
|
+
const values = [record.status.value, record.attempts, record.errorMessage, record.processedAt?.value, record.lastAttempt?.value, record.eventUuid.value];
|
|
1889
|
+
await this.connection.query(
|
|
1890
|
+
`UPDATE events_inbox
|
|
1891
|
+
SET status = ?,
|
|
1892
|
+
attempts = ?,
|
|
1893
|
+
error_message = ?,
|
|
1894
|
+
processed_at = ?,
|
|
1895
|
+
last_attempt = ?
|
|
1896
|
+
WHERE event_uuid = ?`,
|
|
1897
|
+
values
|
|
1898
|
+
);
|
|
1899
|
+
}
|
|
1900
|
+
async listPending(limit) {
|
|
1901
|
+
const result = await this.connection.query(
|
|
1902
|
+
`SELECT * FROM events_inbox WHERE status IN ('PENDING','FAILED') AND events_inbox.processed_at IS NULL LIMIT ${limit}`,
|
|
1903
|
+
[]
|
|
1904
|
+
);
|
|
1905
|
+
return result.length > 0 ? result.map((r) => InboxRecord.reconstitute(r)) : [];
|
|
1906
|
+
}
|
|
1907
|
+
};
|
|
1908
|
+
|
|
1909
|
+
// src/infrastructure/runners/default-mysql-inbox-runner.ts
|
|
1910
|
+
var DefaultMysqlInboxRunner = class {
|
|
1911
|
+
constructor(uowFactory, eventManager) {
|
|
1912
|
+
this.topics = [];
|
|
1913
|
+
this.uowFactory = uowFactory;
|
|
1914
|
+
this.eventManager = eventManager;
|
|
1915
|
+
this.interval = Number(process.env.OUTBOX_RUNNER_INTERVAL_MS || 5e3);
|
|
1916
|
+
this.maxEvents = Number(process.env.OUTBOX_RUNNER_MAX_EVENTS || 20);
|
|
1917
|
+
}
|
|
1918
|
+
async saveEvent(e, repository) {
|
|
1919
|
+
let record = new InboxRecord(
|
|
1920
|
+
UUID.create(),
|
|
1921
|
+
e.tenant,
|
|
1922
|
+
e.topic,
|
|
1923
|
+
e.producer,
|
|
1924
|
+
JSON.stringify(e.message),
|
|
1925
|
+
ProcessStatus.PENDING
|
|
1926
|
+
);
|
|
1927
|
+
try {
|
|
1928
|
+
await repository.create(record);
|
|
1929
|
+
} catch (error) {
|
|
1930
|
+
const type = String(error.type);
|
|
1931
|
+
record.markWithError(type);
|
|
1932
|
+
throw new Error(type);
|
|
1933
|
+
} finally {
|
|
1934
|
+
await repository.update(record);
|
|
1935
|
+
}
|
|
1936
|
+
}
|
|
1937
|
+
subscribeTo(topic) {
|
|
1938
|
+
this.topics.push(topic);
|
|
1939
|
+
}
|
|
1940
|
+
async process() {
|
|
1941
|
+
const uow = await this.uowFactory.create();
|
|
1942
|
+
const inboxRepository = new InboxMysqlRepository(uow.connection);
|
|
1943
|
+
await uow.execute(async () => {
|
|
1944
|
+
for (let topic of this.topics) {
|
|
1945
|
+
try {
|
|
1946
|
+
this.eventManager.route(topic, async (e) => {
|
|
1947
|
+
await this.saveEvent(e, inboxRepository);
|
|
1948
|
+
});
|
|
1949
|
+
} catch (error) {
|
|
1950
|
+
console.log(error.toString());
|
|
1951
|
+
}
|
|
706
1952
|
}
|
|
1953
|
+
await this.eventManager.start();
|
|
1954
|
+
});
|
|
1955
|
+
}
|
|
1956
|
+
async start() {
|
|
1957
|
+
console.log("[inbox-runner]: start");
|
|
1958
|
+
for (; ; ) {
|
|
1959
|
+
await this.process();
|
|
1960
|
+
}
|
|
1961
|
+
}
|
|
1962
|
+
};
|
|
1963
|
+
|
|
1964
|
+
// src/utils/ExchangeRates.ts
|
|
1965
|
+
var ExchangeRates = class _ExchangeRates extends BaseObject {
|
|
1966
|
+
constructor(props) {
|
|
1967
|
+
super(props);
|
|
1968
|
+
}
|
|
1969
|
+
getRate(currency) {
|
|
1970
|
+
if (Object.keys(this.props.rates).includes(currency.value)) {
|
|
1971
|
+
return this.props.rates[currency.value];
|
|
1972
|
+
}
|
|
1973
|
+
return null;
|
|
1974
|
+
}
|
|
1975
|
+
get base() {
|
|
1976
|
+
return this.props.base;
|
|
1977
|
+
}
|
|
1978
|
+
get rates() {
|
|
1979
|
+
return this.props.rates;
|
|
1980
|
+
}
|
|
1981
|
+
get date() {
|
|
1982
|
+
return this.props.date;
|
|
1983
|
+
}
|
|
1984
|
+
toProps() {
|
|
1985
|
+
return this.props;
|
|
1986
|
+
}
|
|
1987
|
+
toPrimitives() {
|
|
1988
|
+
return {
|
|
1989
|
+
base: this.props.base.value,
|
|
1990
|
+
rates: this.props.rates,
|
|
1991
|
+
date: this.props.date.value
|
|
707
1992
|
};
|
|
708
1993
|
}
|
|
1994
|
+
exchangeToBase(price) {
|
|
1995
|
+
const rate = this.getRate(price.currency);
|
|
1996
|
+
if (!rate) {
|
|
1997
|
+
throw new InternalError("INVALID_EXCHANGE_RATE_CURRENCY", `Avaiable rates: ${this.props.rates} - Base Currency:${this.props.base.value} - Price Currency: ${price.currency.value}`);
|
|
1998
|
+
}
|
|
1999
|
+
if (price.currency.value === this.props.base.value) {
|
|
2000
|
+
return price;
|
|
2001
|
+
}
|
|
2002
|
+
return Price.create(parseFloat((price.amount / rate).toFixed(2)), this.props.base.value);
|
|
2003
|
+
}
|
|
2004
|
+
static create(props) {
|
|
2005
|
+
return new _ExchangeRates(props);
|
|
2006
|
+
}
|
|
2007
|
+
static createFromPrimitives(data) {
|
|
2008
|
+
return _ExchangeRates.create({
|
|
2009
|
+
base: Currency.create(data.base),
|
|
2010
|
+
rates: data.rates ?? [],
|
|
2011
|
+
date: DateTime.create(data.date ?? "")
|
|
2012
|
+
});
|
|
2013
|
+
}
|
|
709
2014
|
};
|
|
710
2015
|
// Annotate the CommonJS export names for ESM import in node:
|
|
711
2016
|
0 && (module.exports = {
|
|
2017
|
+
BaseEvent,
|
|
2018
|
+
BaseObject,
|
|
2019
|
+
BasicUnitOfWork,
|
|
2020
|
+
BasicUnitOfWorkFactory,
|
|
2021
|
+
Country,
|
|
712
2022
|
Currency,
|
|
713
2023
|
DateTime,
|
|
2024
|
+
DefaultMysqlInboxRunner,
|
|
2025
|
+
DefaultMysqlOutboxRunner,
|
|
714
2026
|
DomainEntity,
|
|
715
2027
|
DomainError,
|
|
716
2028
|
DomainEvent,
|
|
717
2029
|
Email,
|
|
718
2030
|
ErrorManager,
|
|
2031
|
+
EventBus,
|
|
2032
|
+
EventBusMysqlRepository,
|
|
2033
|
+
EventManager,
|
|
2034
|
+
ExchangeRates,
|
|
719
2035
|
FatalError,
|
|
720
|
-
HttpErrorController,
|
|
721
2036
|
HttpHealthCheckController,
|
|
722
2037
|
HttpNotFoundController,
|
|
2038
|
+
InboxRecord,
|
|
2039
|
+
IntegrationEvent,
|
|
723
2040
|
InternalError,
|
|
2041
|
+
KafkaManager,
|
|
724
2042
|
Language,
|
|
725
2043
|
MysqlConnection,
|
|
726
2044
|
MysqlConnector,
|
|
2045
|
+
OutboxRecord,
|
|
2046
|
+
PaymentGateway,
|
|
2047
|
+
PaymentStatus,
|
|
727
2048
|
Price,
|
|
2049
|
+
ProcessStatus,
|
|
2050
|
+
StringVars,
|
|
728
2051
|
UUID,
|
|
729
2052
|
UsageError,
|
|
730
2053
|
ValueObject,
|
|
731
|
-
|
|
2054
|
+
adaptExpressErrorHandler,
|
|
732
2055
|
adaptExpressRoute
|
|
733
2056
|
});
|
|
734
2057
|
//# sourceMappingURL=index.cjs.map
|