@nestjs-transactional/outbox 1.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +396 -0
  3. package/dist/api/completed-event-publications.d.ts +31 -0
  4. package/dist/api/completed-event-publications.js +58 -0
  5. package/dist/api/completed-event-publications.js.map +1 -0
  6. package/dist/api/failed-event-publications.d.ts +36 -0
  7. package/dist/api/failed-event-publications.js +75 -0
  8. package/dist/api/failed-event-publications.js.map +1 -0
  9. package/dist/api/incomplete-event-publications.d.ts +28 -0
  10. package/dist/api/incomplete-event-publications.js +72 -0
  11. package/dist/api/incomplete-event-publications.js.map +1 -0
  12. package/dist/decorators/inject-decorators.d.ts +85 -0
  13. package/dist/decorators/inject-decorators.js +100 -0
  14. package/dist/decorators/inject-decorators.js.map +1 -0
  15. package/dist/decorators/outbox-events-handler.decorator.d.ts +97 -0
  16. package/dist/decorators/outbox-events-handler.decorator.js +58 -0
  17. package/dist/decorators/outbox-events-handler.decorator.js.map +1 -0
  18. package/dist/dispatcher/data-source-outbox-publisher.d.ts +69 -0
  19. package/dist/dispatcher/data-source-outbox-publisher.js +127 -0
  20. package/dist/dispatcher/data-source-outbox-publisher.js.map +1 -0
  21. package/dist/dispatcher/event-publication-processor.d.ts +69 -0
  22. package/dist/dispatcher/event-publication-processor.js +192 -0
  23. package/dist/dispatcher/event-publication-processor.js.map +1 -0
  24. package/dist/dispatcher/outbox-event-publisher.d.ts +129 -0
  25. package/dist/dispatcher/outbox-event-publisher.js +172 -0
  26. package/dist/dispatcher/outbox-event-publisher.js.map +1 -0
  27. package/dist/dispatcher/processor-options.d.ts +24 -0
  28. package/dist/dispatcher/processor-options.js +15 -0
  29. package/dist/dispatcher/processor-options.js.map +1 -0
  30. package/dist/externalization/errors.d.ts +21 -0
  31. package/dist/externalization/errors.js +30 -0
  32. package/dist/externalization/errors.js.map +1 -0
  33. package/dist/externalization/event-externalizer.d.ts +49 -0
  34. package/dist/externalization/event-externalizer.js +14 -0
  35. package/dist/externalization/event-externalizer.js.map +1 -0
  36. package/dist/externalization/externalization-registry.d.ts +56 -0
  37. package/dist/externalization/externalization-registry.js +103 -0
  38. package/dist/externalization/externalization-registry.js.map +1 -0
  39. package/dist/externalization/externalized.decorator.d.ts +121 -0
  40. package/dist/externalization/externalized.decorator.js +87 -0
  41. package/dist/externalization/externalized.decorator.js.map +1 -0
  42. package/dist/externalization/types.d.ts +39 -0
  43. package/dist/externalization/types.js +3 -0
  44. package/dist/externalization/types.js.map +1 -0
  45. package/dist/index.d.ts +38 -0
  46. package/dist/index.js +58 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/interfaces/outbox-event-handler.interface.d.ts +32 -0
  49. package/dist/interfaces/outbox-event-handler.interface.js +3 -0
  50. package/dist/interfaces/outbox-event-handler.interface.js.map +1 -0
  51. package/dist/module/outbox-processing.module.d.ts +29 -0
  52. package/dist/module/outbox-processing.module.js +66 -0
  53. package/dist/module/outbox-processing.module.js.map +1 -0
  54. package/dist/module/outbox.module.d.ts +196 -0
  55. package/dist/module/outbox.module.js +604 -0
  56. package/dist/module/outbox.module.js.map +1 -0
  57. package/dist/recovery/staleness-monitor.d.ts +39 -0
  58. package/dist/recovery/staleness-monitor.js +118 -0
  59. package/dist/recovery/staleness-monitor.js.map +1 -0
  60. package/dist/recovery/startup-recovery.d.ts +37 -0
  61. package/dist/recovery/startup-recovery.js +55 -0
  62. package/dist/recovery/startup-recovery.js.map +1 -0
  63. package/dist/registry/event-publication-registry.d.ts +70 -0
  64. package/dist/registry/event-publication-registry.js +138 -0
  65. package/dist/registry/event-publication-registry.js.map +1 -0
  66. package/dist/registry/listener-registry.d.ts +52 -0
  67. package/dist/registry/listener-registry.js +67 -0
  68. package/dist/registry/listener-registry.js.map +1 -0
  69. package/dist/registry/multi-ds-listener-registrar.d.ts +78 -0
  70. package/dist/registry/multi-ds-listener-registrar.js +112 -0
  71. package/dist/registry/multi-ds-listener-registrar.js.map +1 -0
  72. package/dist/registry/outbox-listener-scanner.d.ts +66 -0
  73. package/dist/registry/outbox-listener-scanner.js +192 -0
  74. package/dist/registry/outbox-listener-scanner.js.map +1 -0
  75. package/dist/repository/event-publication-repository.d.ts +112 -0
  76. package/dist/repository/event-publication-repository.js +6 -0
  77. package/dist/repository/event-publication-repository.js.map +1 -0
  78. package/dist/serialization/event-serializer.d.ts +28 -0
  79. package/dist/serialization/event-serializer.js +6 -0
  80. package/dist/serialization/event-serializer.js.map +1 -0
  81. package/dist/serialization/event-type-registry.d.ts +41 -0
  82. package/dist/serialization/event-type-registry.js +79 -0
  83. package/dist/serialization/event-type-registry.js.map +1 -0
  84. package/dist/serialization/event-type-resolver.d.ts +43 -0
  85. package/dist/serialization/event-type-resolver.js +66 -0
  86. package/dist/serialization/event-type-resolver.js.map +1 -0
  87. package/dist/serialization/json-event-serializer.d.ts +20 -0
  88. package/dist/serialization/json-event-serializer.js +64 -0
  89. package/dist/serialization/json-event-serializer.js.map +1 -0
  90. package/dist/testing/assertable-published-events.d.ts +71 -0
  91. package/dist/testing/assertable-published-events.js +124 -0
  92. package/dist/testing/assertable-published-events.js.map +1 -0
  93. package/dist/testing/in-memory-repository.d.ts +52 -0
  94. package/dist/testing/in-memory-repository.js +230 -0
  95. package/dist/testing/in-memory-repository.js.map +1 -0
  96. package/dist/testing/index.d.ts +4 -0
  97. package/dist/testing/index.js +20 -0
  98. package/dist/testing/index.js.map +1 -0
  99. package/dist/testing/published-events.d.ts +62 -0
  100. package/dist/testing/published-events.js +110 -0
  101. package/dist/testing/published-events.js.map +1 -0
  102. package/dist/tokens/index.d.ts +2 -0
  103. package/dist/tokens/index.js +14 -0
  104. package/dist/tokens/index.js.map +1 -0
  105. package/dist/tokens/token-utils.d.ts +68 -0
  106. package/dist/tokens/token-utils.js +98 -0
  107. package/dist/tokens/token-utils.js.map +1 -0
  108. package/dist/types/completion-mode.d.ts +16 -0
  109. package/dist/types/completion-mode.js +20 -0
  110. package/dist/types/completion-mode.js.map +1 -0
  111. package/dist/types/errors.d.ts +50 -0
  112. package/dist/types/errors.js +64 -0
  113. package/dist/types/errors.js.map +1 -0
  114. package/dist/types/event-publication.d.ts +47 -0
  115. package/dist/types/event-publication.js +3 -0
  116. package/dist/types/event-publication.js.map +1 -0
  117. package/dist/types/publication-status.d.ts +26 -0
  118. package/dist/types/publication-status.js +30 -0
  119. package/dist/types/publication-status.js.map +1 -0
  120. package/dist/types/resubmission-options.d.ts +37 -0
  121. package/dist/types/resubmission-options.js +62 -0
  122. package/dist/types/resubmission-options.js.map +1 -0
  123. package/dist/types/staleness-config.d.ts +18 -0
  124. package/dist/types/staleness-config.js +10 -0
  125. package/dist/types/staleness-config.js.map +1 -0
  126. package/package.json +77 -0
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Behavior when a publication is successfully completed.
3
+ *
4
+ * - `UPDATE`: set `completion_date` on the record (default). Keeps the
5
+ * row for inspection of completed publications; requires manual
6
+ * purging eventually.
7
+ * - `DELETE`: delete the record. No audit of completed publications.
8
+ * - `ARCHIVE`: move the record to an archive table, keeping it for
9
+ * inspection without weighing down the hot queue.
10
+ */
11
+ export declare enum CompletionMode {
12
+ UPDATE = "UPDATE",
13
+ DELETE = "DELETE",
14
+ ARCHIVE = "ARCHIVE"
15
+ }
16
+ //# sourceMappingURL=completion-mode.d.ts.map
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CompletionMode = void 0;
4
+ /**
5
+ * Behavior when a publication is successfully completed.
6
+ *
7
+ * - `UPDATE`: set `completion_date` on the record (default). Keeps the
8
+ * row for inspection of completed publications; requires manual
9
+ * purging eventually.
10
+ * - `DELETE`: delete the record. No audit of completed publications.
11
+ * - `ARCHIVE`: move the record to an archive table, keeping it for
12
+ * inspection without weighing down the hot queue.
13
+ */
14
+ var CompletionMode;
15
+ (function (CompletionMode) {
16
+ CompletionMode["UPDATE"] = "UPDATE";
17
+ CompletionMode["DELETE"] = "DELETE";
18
+ CompletionMode["ARCHIVE"] = "ARCHIVE";
19
+ })(CompletionMode || (exports.CompletionMode = CompletionMode = {}));
20
+ //# sourceMappingURL=completion-mode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completion-mode.js","sourceRoot":"","sources":["../../src/types/completion-mode.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;GASG;AACH,IAAY,cAIX;AAJD,WAAY,cAAc;IACxB,mCAAiB,CAAA;IACjB,mCAAiB,CAAA;IACjB,qCAAmB,CAAA;AACrB,CAAC,EAJW,cAAc,8BAAd,cAAc,QAIzB"}
@@ -0,0 +1,50 @@
1
+ import { TransactionError } from '@nestjs-transactional/core';
2
+ import type { PublicationStatus } from './publication-status';
3
+ /**
4
+ * Base class for errors raised by `@nestjs-transactional/outbox`.
5
+ * Subclass for any specific failure mode so that callers can match on
6
+ * `code` without relying on string parsing.
7
+ */
8
+ export declare class OutboxError extends TransactionError {
9
+ readonly code: string;
10
+ }
11
+ /**
12
+ * Raised when a lookup by publication ID finds no matching record.
13
+ */
14
+ export declare class PublicationNotFoundError extends OutboxError {
15
+ readonly code = "PUBLICATION_NOT_FOUND";
16
+ constructor(id: string);
17
+ }
18
+ /**
19
+ * Raised when the registry is asked to move a publication to a state
20
+ * that is not reachable from its current one — e.g. `COMPLETED` →
21
+ * `PROCESSING`.
22
+ */
23
+ export declare class InvalidPublicationTransitionError extends OutboxError {
24
+ readonly code = "INVALID_PUBLICATION_TRANSITION";
25
+ constructor(from: PublicationStatus, to: PublicationStatus);
26
+ }
27
+ /**
28
+ * Raised when the serializer cannot encode an event payload — typically
29
+ * because the payload contains non-plain values (functions, cycles, ...).
30
+ */
31
+ export declare class SerializationError extends OutboxError {
32
+ readonly code = "SERIALIZATION_ERROR";
33
+ }
34
+ /**
35
+ * Raised when the serializer cannot decode a stored event payload —
36
+ * typically because the schema has drifted or the type is unregistered.
37
+ */
38
+ export declare class DeserializationError extends OutboxError {
39
+ readonly code = "DESERIALIZATION_ERROR";
40
+ }
41
+ /**
42
+ * Raised when two listeners are registered with the same id. Listener
43
+ * ids must be globally unique because they are stored on each
44
+ * `EventPublication` row and drive retry / resume resolution.
45
+ */
46
+ export declare class DuplicateListenerIdError extends OutboxError {
47
+ readonly code = "DUPLICATE_LISTENER_ID";
48
+ constructor(id: string);
49
+ }
50
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DuplicateListenerIdError = exports.DeserializationError = exports.SerializationError = exports.InvalidPublicationTransitionError = exports.PublicationNotFoundError = exports.OutboxError = void 0;
4
+ const core_1 = require("@nestjs-transactional/core");
5
+ /**
6
+ * Base class for errors raised by `@nestjs-transactional/outbox`.
7
+ * Subclass for any specific failure mode so that callers can match on
8
+ * `code` without relying on string parsing.
9
+ */
10
+ class OutboxError extends core_1.TransactionError {
11
+ code = 'OUTBOX_ERROR';
12
+ }
13
+ exports.OutboxError = OutboxError;
14
+ /**
15
+ * Raised when a lookup by publication ID finds no matching record.
16
+ */
17
+ class PublicationNotFoundError extends OutboxError {
18
+ code = 'PUBLICATION_NOT_FOUND';
19
+ constructor(id) {
20
+ super(`Publication not found: ${id}`);
21
+ }
22
+ }
23
+ exports.PublicationNotFoundError = PublicationNotFoundError;
24
+ /**
25
+ * Raised when the registry is asked to move a publication to a state
26
+ * that is not reachable from its current one — e.g. `COMPLETED` →
27
+ * `PROCESSING`.
28
+ */
29
+ class InvalidPublicationTransitionError extends OutboxError {
30
+ code = 'INVALID_PUBLICATION_TRANSITION';
31
+ constructor(from, to) {
32
+ super(`Invalid publication state transition: ${from} → ${to}`);
33
+ }
34
+ }
35
+ exports.InvalidPublicationTransitionError = InvalidPublicationTransitionError;
36
+ /**
37
+ * Raised when the serializer cannot encode an event payload — typically
38
+ * because the payload contains non-plain values (functions, cycles, ...).
39
+ */
40
+ class SerializationError extends OutboxError {
41
+ code = 'SERIALIZATION_ERROR';
42
+ }
43
+ exports.SerializationError = SerializationError;
44
+ /**
45
+ * Raised when the serializer cannot decode a stored event payload —
46
+ * typically because the schema has drifted or the type is unregistered.
47
+ */
48
+ class DeserializationError extends OutboxError {
49
+ code = 'DESERIALIZATION_ERROR';
50
+ }
51
+ exports.DeserializationError = DeserializationError;
52
+ /**
53
+ * Raised when two listeners are registered with the same id. Listener
54
+ * ids must be globally unique because they are stored on each
55
+ * `EventPublication` row and drive retry / resume resolution.
56
+ */
57
+ class DuplicateListenerIdError extends OutboxError {
58
+ code = 'DUPLICATE_LISTENER_ID';
59
+ constructor(id) {
60
+ super(`Listener with id '${id}' is already registered`);
61
+ }
62
+ }
63
+ exports.DuplicateListenerIdError = DuplicateListenerIdError;
64
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/types/errors.ts"],"names":[],"mappings":";;;AAAA,qDAA8D;AAI9D;;;;GAIG;AACH,MAAa,WAAY,SAAQ,uBAAgB;IACtC,IAAI,GAAW,cAAc,CAAC;CACxC;AAFD,kCAEC;AAED;;GAEG;AACH,MAAa,wBAAyB,SAAQ,WAAW;IAC9C,IAAI,GAAG,uBAAuB,CAAC;IAExC,YAAY,EAAU;QACpB,KAAK,CAAC,0BAA0B,EAAE,EAAE,CAAC,CAAC;IACxC,CAAC;CACF;AAND,4DAMC;AAED;;;;GAIG;AACH,MAAa,iCAAkC,SAAQ,WAAW;IACvD,IAAI,GAAG,gCAAgC,CAAC;IAEjD,YAAY,IAAuB,EAAE,EAAqB;QACxD,KAAK,CAAC,yCAAyC,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;IACjE,CAAC;CACF;AAND,8EAMC;AAED;;;GAGG;AACH,MAAa,kBAAmB,SAAQ,WAAW;IACxC,IAAI,GAAG,qBAAqB,CAAC;CACvC;AAFD,gDAEC;AAED;;;GAGG;AACH,MAAa,oBAAqB,SAAQ,WAAW;IAC1C,IAAI,GAAG,uBAAuB,CAAC;CACzC;AAFD,oDAEC;AAED;;;;GAIG;AACH,MAAa,wBAAyB,SAAQ,WAAW;IAC9C,IAAI,GAAG,uBAAuB,CAAC;IAExC,YAAY,EAAU;QACpB,KAAK,CAAC,qBAAqB,EAAE,yBAAyB,CAAC,CAAC;IAC1D,CAAC;CACF;AAND,4DAMC"}
@@ -0,0 +1,47 @@
1
+ import type { PublicationStatus } from './publication-status';
2
+ /**
3
+ * Persistent record of an event that was published and needs to be
4
+ * delivered to a listener.
5
+ *
6
+ * Inspired by Spring Modulith's `EventPublication`.
7
+ */
8
+ export interface EventPublication {
9
+ /** Opaque identifier (UUID). */
10
+ readonly id: string;
11
+ /**
12
+ * Qualified listener name, e.g. `"InventoryManagement.on(OrderCompletedEvent)"`.
13
+ * Used as a stable identity for retry / resume — see ADR-009 (planned).
14
+ */
15
+ readonly listenerId: string;
16
+ /** The event's class name (discriminator for deserialization). */
17
+ readonly eventType: string;
18
+ /** JSON-serialized event payload. */
19
+ readonly serializedEvent: string;
20
+ /** Wall-clock time at which the publication was created. */
21
+ readonly publicationDate: Date;
22
+ /** Current lifecycle state. */
23
+ readonly status: PublicationStatus;
24
+ /** When the publication reached {@link PublicationStatus.COMPLETED}. */
25
+ readonly completionDate: Date | null;
26
+ /** When the publication was last moved to {@link PublicationStatus.RESUBMITTED}. */
27
+ readonly lastResubmissionDate: Date | null;
28
+ /** Starts at 0, incremented each time a listener picks up the publication. */
29
+ readonly completionAttempts: number;
30
+ /** Error message from the most recent failure, if any. */
31
+ readonly failureReason: string | null;
32
+ }
33
+ /**
34
+ * Input accepted by the registry for creating a new publication.
35
+ *
36
+ * The registry fills in `id`, `status` (`PUBLISHED`), `completionDate`
37
+ * (`null`), `lastResubmissionDate` (`null`), `completionAttempts` (`0`),
38
+ * and `failureReason` (`null`). If `publicationDate` is omitted, the
39
+ * registry defaults it to "now".
40
+ */
41
+ export interface NewEventPublication {
42
+ readonly listenerId: string;
43
+ readonly eventType: string;
44
+ readonly serializedEvent: string;
45
+ readonly publicationDate?: Date;
46
+ }
47
+ //# sourceMappingURL=event-publication.d.ts.map
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=event-publication.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-publication.js","sourceRoot":"","sources":["../../src/types/event-publication.ts"],"names":[],"mappings":""}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Lifecycle state of an {@link EventPublication}.
3
+ *
4
+ * Inspired by Spring Modulith's Event Publication Registry.
5
+ *
6
+ * State transitions (normal flow):
7
+ *
8
+ * PUBLISHED → PROCESSING → COMPLETED
9
+ *
10
+ * State transitions (failure flow):
11
+ *
12
+ * PUBLISHED → PROCESSING → FAILED → RESUBMITTED → PROCESSING → COMPLETED
13
+ */
14
+ export declare enum PublicationStatus {
15
+ /** Created, waiting to be picked up by a listener. */
16
+ PUBLISHED = "PUBLISHED",
17
+ /** A listener has picked it up and is currently executing. */
18
+ PROCESSING = "PROCESSING",
19
+ /** Listener finished successfully. */
20
+ COMPLETED = "COMPLETED",
21
+ /** Listener threw an exception. */
22
+ FAILED = "FAILED",
23
+ /** Previously FAILED, now queued for retry. */
24
+ RESUBMITTED = "RESUBMITTED"
25
+ }
26
+ //# sourceMappingURL=publication-status.d.ts.map
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PublicationStatus = void 0;
4
+ /**
5
+ * Lifecycle state of an {@link EventPublication}.
6
+ *
7
+ * Inspired by Spring Modulith's Event Publication Registry.
8
+ *
9
+ * State transitions (normal flow):
10
+ *
11
+ * PUBLISHED → PROCESSING → COMPLETED
12
+ *
13
+ * State transitions (failure flow):
14
+ *
15
+ * PUBLISHED → PROCESSING → FAILED → RESUBMITTED → PROCESSING → COMPLETED
16
+ */
17
+ var PublicationStatus;
18
+ (function (PublicationStatus) {
19
+ /** Created, waiting to be picked up by a listener. */
20
+ PublicationStatus["PUBLISHED"] = "PUBLISHED";
21
+ /** A listener has picked it up and is currently executing. */
22
+ PublicationStatus["PROCESSING"] = "PROCESSING";
23
+ /** Listener finished successfully. */
24
+ PublicationStatus["COMPLETED"] = "COMPLETED";
25
+ /** Listener threw an exception. */
26
+ PublicationStatus["FAILED"] = "FAILED";
27
+ /** Previously FAILED, now queued for retry. */
28
+ PublicationStatus["RESUBMITTED"] = "RESUBMITTED";
29
+ })(PublicationStatus || (exports.PublicationStatus = PublicationStatus = {}));
30
+ //# sourceMappingURL=publication-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publication-status.js","sourceRoot":"","sources":["../../src/types/publication-status.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;GAYG;AACH,IAAY,iBAWX;AAXD,WAAY,iBAAiB;IAC3B,sDAAsD;IACtD,4CAAuB,CAAA;IACvB,8DAA8D;IAC9D,8CAAyB,CAAA;IACzB,sCAAsC;IACtC,4CAAuB,CAAA;IACvB,mCAAmC;IACnC,sCAAiB,CAAA;IACjB,+CAA+C;IAC/C,gDAA2B,CAAA;AAC7B,CAAC,EAXW,iBAAiB,iCAAjB,iBAAiB,QAW5B"}
@@ -0,0 +1,37 @@
1
+ import type { EventPublication } from './event-publication';
2
+ /**
3
+ * Predicate that decides whether a given publication should be included
4
+ * in a resubmission batch.
5
+ */
6
+ export type ResubmissionFilter = (publication: EventPublication) => boolean;
7
+ /**
8
+ * Builder-style configuration for a resubmission pass.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * ResubmissionOptions.defaults()
13
+ * .withBatchSize(50)
14
+ * .withMaxInFlight(5)
15
+ * .withMinAge(10_000)
16
+ * .withMaxAttempts(3);
17
+ * ```
18
+ */
19
+ export declare class ResubmissionOptions {
20
+ private _batchSize;
21
+ private _maxInFlight;
22
+ private _minAge;
23
+ private _maxCompletionAttempts;
24
+ private _filter;
25
+ static defaults(): ResubmissionOptions;
26
+ withBatchSize(size: number): this;
27
+ withMaxInFlight(n: number): this;
28
+ withMinAge(ms: number): this;
29
+ withMaxAttempts(n: number): this;
30
+ withFilter(filter: ResubmissionFilter): this;
31
+ get batchSize(): number;
32
+ get maxInFlight(): number;
33
+ get minAge(): number;
34
+ get maxCompletionAttempts(): number | null;
35
+ get filter(): ResubmissionFilter | null;
36
+ }
37
+ //# sourceMappingURL=resubmission-options.d.ts.map
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ResubmissionOptions = void 0;
4
+ /**
5
+ * Builder-style configuration for a resubmission pass.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * ResubmissionOptions.defaults()
10
+ * .withBatchSize(50)
11
+ * .withMaxInFlight(5)
12
+ * .withMinAge(10_000)
13
+ * .withMaxAttempts(3);
14
+ * ```
15
+ */
16
+ class ResubmissionOptions {
17
+ _batchSize = 100;
18
+ _maxInFlight = 10;
19
+ _minAge = 0;
20
+ _maxCompletionAttempts = null;
21
+ _filter = null;
22
+ static defaults() {
23
+ return new ResubmissionOptions();
24
+ }
25
+ withBatchSize(size) {
26
+ this._batchSize = size;
27
+ return this;
28
+ }
29
+ withMaxInFlight(n) {
30
+ this._maxInFlight = n;
31
+ return this;
32
+ }
33
+ withMinAge(ms) {
34
+ this._minAge = ms;
35
+ return this;
36
+ }
37
+ withMaxAttempts(n) {
38
+ this._maxCompletionAttempts = n;
39
+ return this;
40
+ }
41
+ withFilter(filter) {
42
+ this._filter = filter;
43
+ return this;
44
+ }
45
+ get batchSize() {
46
+ return this._batchSize;
47
+ }
48
+ get maxInFlight() {
49
+ return this._maxInFlight;
50
+ }
51
+ get minAge() {
52
+ return this._minAge;
53
+ }
54
+ get maxCompletionAttempts() {
55
+ return this._maxCompletionAttempts;
56
+ }
57
+ get filter() {
58
+ return this._filter;
59
+ }
60
+ }
61
+ exports.ResubmissionOptions = ResubmissionOptions;
62
+ //# sourceMappingURL=resubmission-options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resubmission-options.js","sourceRoot":"","sources":["../../src/types/resubmission-options.ts"],"names":[],"mappings":";;;AAQA;;;;;;;;;;;GAWG;AACH,MAAa,mBAAmB;IACtB,UAAU,GAAG,GAAG,CAAC;IACjB,YAAY,GAAG,EAAE,CAAC;IAClB,OAAO,GAAG,CAAC,CAAC;IACZ,sBAAsB,GAAkB,IAAI,CAAC;IAC7C,OAAO,GAA8B,IAAI,CAAC;IAElD,MAAM,CAAC,QAAQ;QACb,OAAO,IAAI,mBAAmB,EAAE,CAAC;IACnC,CAAC;IAED,aAAa,CAAC,IAAY;QACxB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,eAAe,CAAC,CAAS;QACvB,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,UAAU,CAAC,EAAU;QACnB,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,eAAe,CAAC,CAAS;QACvB,IAAI,CAAC,sBAAsB,GAAG,CAAC,CAAC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,UAAU,CAAC,MAA0B;QACnC,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,IAAI,qBAAqB;QACvB,OAAO,IAAI,CAAC,sBAAsB,CAAC;IACrC,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;CACF;AAvDD,kDAuDC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Configuration for detecting stale publications that should be marked
3
+ * as {@link PublicationStatus.FAILED}.
4
+ *
5
+ * Any value of `0` disables that specific staleness check.
6
+ */
7
+ export interface StalenessConfig {
8
+ /** Max duration (ms) in `PUBLISHED` state before marking as `FAILED`. */
9
+ readonly published: number;
10
+ /** Max duration (ms) in `PROCESSING` state before marking as `FAILED`. */
11
+ readonly processing: number;
12
+ /** Max duration (ms) in `RESUBMITTED` state before marking as `FAILED`. */
13
+ readonly resubmitted: number;
14
+ /** How often (ms) the staleness monitor runs. Defaults to 60000 (1 minute). */
15
+ readonly monitorInterval: number;
16
+ }
17
+ export declare const DEFAULT_STALENESS_CONFIG: StalenessConfig;
18
+ //# sourceMappingURL=staleness-config.d.ts.map
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_STALENESS_CONFIG = void 0;
4
+ exports.DEFAULT_STALENESS_CONFIG = {
5
+ published: 0,
6
+ processing: 0,
7
+ resubmitted: 0,
8
+ monitorInterval: 60_000,
9
+ };
10
+ //# sourceMappingURL=staleness-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"staleness-config.js","sourceRoot":"","sources":["../../src/types/staleness-config.ts"],"names":[],"mappings":";;;AAiBa,QAAA,wBAAwB,GAAoB;IACvD,SAAS,EAAE,CAAC;IACZ,UAAU,EAAE,CAAC;IACb,WAAW,EAAE,CAAC;IACd,eAAe,EAAE,MAAM;CACxB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,77 @@
1
+ {
2
+ "name": "@nestjs-transactional/outbox",
3
+ "version": "1.0.0-alpha.0",
4
+ "description": "Persistent Event Publication Registry for @nestjs-transactional — Spring Modulith equivalent (ORM-agnostic core)",
5
+ "license": "MIT",
6
+ "author": "Igor Golovanov",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/igorgolovanov/nestjs-transactional.git",
10
+ "directory": "packages/outbox"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/igorgolovanov/nestjs-transactional/issues"
14
+ },
15
+ "homepage": "https://github.com/igorgolovanov/nestjs-transactional/tree/main/packages/outbox#readme",
16
+ "keywords": [
17
+ "nestjs",
18
+ "outbox",
19
+ "event-publication-registry",
20
+ "spring-modulith",
21
+ "transactional-outbox",
22
+ "transaction"
23
+ ],
24
+ "engines": {
25
+ "node": ">=22.11.0"
26
+ },
27
+ "main": "dist/index.js",
28
+ "types": "dist/index.d.ts",
29
+ "files": [
30
+ "dist/**/*.js",
31
+ "dist/**/*.d.ts",
32
+ "dist/**/*.js.map",
33
+ "!dist/**/*.spec.*"
34
+ ],
35
+ "exports": {
36
+ ".": {
37
+ "types": "./dist/index.d.ts",
38
+ "default": "./dist/index.js"
39
+ },
40
+ "./testing": {
41
+ "types": "./dist/testing/index.d.ts",
42
+ "default": "./dist/testing/index.js"
43
+ }
44
+ },
45
+ "publishConfig": {
46
+ "access": "public",
47
+ "provenance": true
48
+ },
49
+ "peerDependencies": {
50
+ "@nestjs/common": "^10.0.0 || ^11.0.0",
51
+ "@nestjs/core": "^10.0.0 || ^11.0.0",
52
+ "reflect-metadata": "^0.1.13 || ^0.2.0",
53
+ "rxjs": "^7.0.0",
54
+ "@nestjs-transactional/core": "^1.0.0-alpha.0"
55
+ },
56
+ "devDependencies": {
57
+ "@nestjs/common": "^11.0.0",
58
+ "@nestjs/core": "^11.0.0",
59
+ "@nestjs/testing": "^11.0.0",
60
+ "@types/jest": "^29.5.14",
61
+ "jest": "^29.7.0",
62
+ "reflect-metadata": "^0.2.2",
63
+ "rxjs": "^7.8.1",
64
+ "ts-jest": "^29.2.5",
65
+ "typescript": "^5.5.4",
66
+ "@nestjs-transactional/core": "1.0.0-alpha.0"
67
+ },
68
+ "scripts": {
69
+ "build": "tsc -p tsconfig.build.json",
70
+ "clean": "rimraf dist *.tsbuildinfo coverage",
71
+ "test": "jest",
72
+ "test:watch": "jest --watch",
73
+ "test:cov": "jest --coverage",
74
+ "type-check": "tsc --noEmit",
75
+ "lint": "eslint \"src/**/*.ts\""
76
+ }
77
+ }