@haskou/ddd-kernel 0.1.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 (191) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +143 -0
  3. package/dist/Constructor-fyZLLIh8.d.cts +5 -0
  4. package/dist/Constructor-fyZLLIh8.d.ts +5 -0
  5. package/dist/Consumer-CC8ZRCsd.d.cts +17 -0
  6. package/dist/Consumer-CeT0Wbxb.d.ts +17 -0
  7. package/dist/DomainEvent-mXWEtr_J.d.cts +26 -0
  8. package/dist/DomainEvent-mXWEtr_J.d.ts +26 -0
  9. package/dist/DomainEventConsumer-3WBMSSr2.d.cts +7 -0
  10. package/dist/DomainEventConsumer-B4hkIUmP.d.ts +7 -0
  11. package/dist/DomainEventPublisher-8G0lvmdy.d.cts +7 -0
  12. package/dist/DomainEventPublisher-DhGgM3f2.d.ts +7 -0
  13. package/dist/HandlerContext-DUUExVo3.d.ts +20 -0
  14. package/dist/HandlerContext-Lm89pSeG.d.cts +20 -0
  15. package/dist/Kernel-BWUOUWWI.d.cts +70 -0
  16. package/dist/Kernel-CUaqHa1s.d.ts +70 -0
  17. package/dist/KernelLogger-BESOFrpW.d.cts +8 -0
  18. package/dist/KernelLogger-BESOFrpW.d.ts +8 -0
  19. package/dist/Log-36L3Z84a.d.cts +8 -0
  20. package/dist/Log-36L3Z84a.d.ts +8 -0
  21. package/dist/NoFailedMessagesError-0YJKRWPF.d.ts +45 -0
  22. package/dist/NoFailedMessagesError-Kz7CYWpT.d.cts +45 -0
  23. package/dist/Repository-D9CuAyCV.d.cts +7 -0
  24. package/dist/Repository-D9CuAyCV.d.ts +7 -0
  25. package/dist/Scheduler-oigqNOUJ.d.cts +27 -0
  26. package/dist/Scheduler-oigqNOUJ.d.ts +27 -0
  27. package/dist/ServiceClass-BmNw8fJj.d.cts +37 -0
  28. package/dist/ServiceClass-C7NCKdSS.d.ts +37 -0
  29. package/dist/ServiceResolver-D2Jz-l_Z.d.cts +5 -0
  30. package/dist/ServiceResolver-D2Jz-l_Z.d.ts +5 -0
  31. package/dist/ShutdownHook-BGskq2-q.d.ts +9 -0
  32. package/dist/ShutdownHook-Dib5uNKB.d.cts +9 -0
  33. package/dist/Subscription-Bwkb_did.d.ts +9 -0
  34. package/dist/Subscription-P9WROD_6.d.cts +9 -0
  35. package/dist/adapters/db/in-memory/index.cjs +46 -0
  36. package/dist/adapters/db/in-memory/index.cjs.map +1 -0
  37. package/dist/adapters/db/in-memory/index.d.cts +12 -0
  38. package/dist/adapters/db/in-memory/index.d.ts +12 -0
  39. package/dist/adapters/db/in-memory/index.js +19 -0
  40. package/dist/adapters/db/in-memory/index.js.map +1 -0
  41. package/dist/adapters/db/index.cjs +80 -0
  42. package/dist/adapters/db/index.cjs.map +1 -0
  43. package/dist/adapters/db/index.d.cts +4 -0
  44. package/dist/adapters/db/index.d.ts +4 -0
  45. package/dist/adapters/db/index.js +52 -0
  46. package/dist/adapters/db/index.js.map +1 -0
  47. package/dist/adapters/db/mongo/index.cjs +62 -0
  48. package/dist/adapters/db/mongo/index.cjs.map +1 -0
  49. package/dist/adapters/db/mongo/index.d.cts +22 -0
  50. package/dist/adapters/db/mongo/index.d.ts +22 -0
  51. package/dist/adapters/db/mongo/index.js +35 -0
  52. package/dist/adapters/db/mongo/index.js.map +1 -0
  53. package/dist/adapters/index.cjs +651 -0
  54. package/dist/adapters/index.cjs.map +1 -0
  55. package/dist/adapters/index.d.cts +26 -0
  56. package/dist/adapters/index.d.ts +26 -0
  57. package/dist/adapters/index.js +609 -0
  58. package/dist/adapters/index.js.map +1 -0
  59. package/dist/adapters/kernel/console/index.cjs +46 -0
  60. package/dist/adapters/kernel/console/index.cjs.map +1 -0
  61. package/dist/adapters/kernel/console/index.d.cts +10 -0
  62. package/dist/adapters/kernel/console/index.d.ts +10 -0
  63. package/dist/adapters/kernel/console/index.js +19 -0
  64. package/dist/adapters/kernel/console/index.js.map +1 -0
  65. package/dist/adapters/kernel/index.cjs +46 -0
  66. package/dist/adapters/kernel/index.cjs.map +1 -0
  67. package/dist/adapters/kernel/index.d.cts +2 -0
  68. package/dist/adapters/kernel/index.d.ts +2 -0
  69. package/dist/adapters/kernel/index.js +19 -0
  70. package/dist/adapters/kernel/index.js.map +1 -0
  71. package/dist/adapters/pubsub/amqp/index.cjs +724 -0
  72. package/dist/adapters/pubsub/amqp/index.cjs.map +1 -0
  73. package/dist/adapters/pubsub/amqp/index.d.cts +42 -0
  74. package/dist/adapters/pubsub/amqp/index.d.ts +42 -0
  75. package/dist/adapters/pubsub/amqp/index.js +691 -0
  76. package/dist/adapters/pubsub/amqp/index.js.map +1 -0
  77. package/dist/adapters/pubsub/in-memory/index.cjs +79 -0
  78. package/dist/adapters/pubsub/in-memory/index.cjs.map +1 -0
  79. package/dist/adapters/pubsub/in-memory/index.d.cts +21 -0
  80. package/dist/adapters/pubsub/in-memory/index.d.ts +21 -0
  81. package/dist/adapters/pubsub/in-memory/index.js +51 -0
  82. package/dist/adapters/pubsub/in-memory/index.js.map +1 -0
  83. package/dist/adapters/pubsub/index.cjs +492 -0
  84. package/dist/adapters/pubsub/index.cjs.map +1 -0
  85. package/dist/adapters/pubsub/index.d.cts +11 -0
  86. package/dist/adapters/pubsub/index.d.ts +11 -0
  87. package/dist/adapters/pubsub/index.js +456 -0
  88. package/dist/adapters/pubsub/index.js.map +1 -0
  89. package/dist/adapters/ui/express/index.cjs +126 -0
  90. package/dist/adapters/ui/express/index.cjs.map +1 -0
  91. package/dist/adapters/ui/express/index.d.cts +49 -0
  92. package/dist/adapters/ui/express/index.d.ts +49 -0
  93. package/dist/adapters/ui/express/index.js +98 -0
  94. package/dist/adapters/ui/express/index.js.map +1 -0
  95. package/dist/adapters/ui/index.cjs +489 -0
  96. package/dist/adapters/ui/index.cjs.map +1 -0
  97. package/dist/adapters/ui/index.d.cts +14 -0
  98. package/dist/adapters/ui/index.d.ts +14 -0
  99. package/dist/adapters/ui/index.js +455 -0
  100. package/dist/adapters/ui/index.js.map +1 -0
  101. package/dist/adapters/ui/routes/index.cjs +393 -0
  102. package/dist/adapters/ui/routes/index.cjs.map +1 -0
  103. package/dist/adapters/ui/routes/index.d.cts +5 -0
  104. package/dist/adapters/ui/routes/index.d.ts +5 -0
  105. package/dist/adapters/ui/routes/index.js +361 -0
  106. package/dist/adapters/ui/routes/index.js.map +1 -0
  107. package/dist/contracts/db/index.cjs +19 -0
  108. package/dist/contracts/db/index.cjs.map +1 -0
  109. package/dist/contracts/db/index.d.cts +7 -0
  110. package/dist/contracts/db/index.d.ts +7 -0
  111. package/dist/contracts/db/index.js +1 -0
  112. package/dist/contracts/db/index.js.map +1 -0
  113. package/dist/contracts/index.cjs +49 -0
  114. package/dist/contracts/index.cjs.map +1 -0
  115. package/dist/contracts/index.d.cts +11 -0
  116. package/dist/contracts/index.d.ts +11 -0
  117. package/dist/contracts/index.js +22 -0
  118. package/dist/contracts/index.js.map +1 -0
  119. package/dist/contracts/kernel/index.cjs +19 -0
  120. package/dist/contracts/kernel/index.cjs.map +1 -0
  121. package/dist/contracts/kernel/index.d.cts +9 -0
  122. package/dist/contracts/kernel/index.d.ts +9 -0
  123. package/dist/contracts/kernel/index.js +1 -0
  124. package/dist/contracts/kernel/index.js.map +1 -0
  125. package/dist/contracts/pubsub/index.cjs +19 -0
  126. package/dist/contracts/pubsub/index.cjs.map +1 -0
  127. package/dist/contracts/pubsub/index.d.cts +26 -0
  128. package/dist/contracts/pubsub/index.d.ts +26 -0
  129. package/dist/contracts/pubsub/index.js +1 -0
  130. package/dist/contracts/pubsub/index.js.map +1 -0
  131. package/dist/contracts/ui/index.cjs +49 -0
  132. package/dist/contracts/ui/index.cjs.map +1 -0
  133. package/dist/contracts/ui/index.d.cts +29 -0
  134. package/dist/contracts/ui/index.d.ts +29 -0
  135. package/dist/contracts/ui/index.js +22 -0
  136. package/dist/contracts/ui/index.js.map +1 -0
  137. package/dist/domain/index.cjs +121 -0
  138. package/dist/domain/index.cjs.map +1 -0
  139. package/dist/domain/index.d.cts +26 -0
  140. package/dist/domain/index.d.ts +26 -0
  141. package/dist/domain/index.js +89 -0
  142. package/dist/domain/index.js.map +1 -0
  143. package/dist/errors/index.cjs +58 -0
  144. package/dist/errors/index.cjs.map +1 -0
  145. package/dist/errors/index.d.cts +13 -0
  146. package/dist/errors/index.d.ts +13 -0
  147. package/dist/errors/index.js +29 -0
  148. package/dist/errors/index.js.map +1 -0
  149. package/dist/index.cjs +442 -0
  150. package/dist/index.cjs.map +1 -0
  151. package/dist/index.d.cts +19 -0
  152. package/dist/index.d.ts +19 -0
  153. package/dist/index.js +405 -0
  154. package/dist/index.js.map +1 -0
  155. package/dist/infrastructure/dependency-injection/index.cjs +169 -0
  156. package/dist/infrastructure/dependency-injection/index.cjs.map +1 -0
  157. package/dist/infrastructure/dependency-injection/index.d.cts +30 -0
  158. package/dist/infrastructure/dependency-injection/index.d.ts +30 -0
  159. package/dist/infrastructure/dependency-injection/index.js +137 -0
  160. package/dist/infrastructure/dependency-injection/index.js.map +1 -0
  161. package/dist/infrastructure/express/index.cjs +126 -0
  162. package/dist/infrastructure/express/index.cjs.map +1 -0
  163. package/dist/infrastructure/express/index.d.cts +14 -0
  164. package/dist/infrastructure/express/index.d.ts +14 -0
  165. package/dist/infrastructure/express/index.js +98 -0
  166. package/dist/infrastructure/express/index.js.map +1 -0
  167. package/dist/infrastructure/lifecycle/index.cjs +19 -0
  168. package/dist/infrastructure/lifecycle/index.cjs.map +1 -0
  169. package/dist/infrastructure/lifecycle/index.d.cts +9 -0
  170. package/dist/infrastructure/lifecycle/index.d.ts +9 -0
  171. package/dist/infrastructure/lifecycle/index.js +1 -0
  172. package/dist/infrastructure/lifecycle/index.js.map +1 -0
  173. package/dist/infrastructure/logs/index.cjs +144 -0
  174. package/dist/infrastructure/logs/index.cjs.map +1 -0
  175. package/dist/infrastructure/logs/index.d.cts +30 -0
  176. package/dist/infrastructure/logs/index.d.ts +30 -0
  177. package/dist/infrastructure/logs/index.js +107 -0
  178. package/dist/infrastructure/logs/index.js.map +1 -0
  179. package/dist/infrastructure/scheduler/index.cjs +461 -0
  180. package/dist/infrastructure/scheduler/index.cjs.map +1 -0
  181. package/dist/infrastructure/scheduler/index.d.cts +17 -0
  182. package/dist/infrastructure/scheduler/index.d.ts +17 -0
  183. package/dist/infrastructure/scheduler/index.js +426 -0
  184. package/dist/infrastructure/scheduler/index.js.map +1 -0
  185. package/dist/infrastructure/websocket/index.cjs +131 -0
  186. package/dist/infrastructure/websocket/index.cjs.map +1 -0
  187. package/dist/infrastructure/websocket/index.d.cts +56 -0
  188. package/dist/infrastructure/websocket/index.d.ts +56 -0
  189. package/dist/infrastructure/websocket/index.js +103 -0
  190. package/dist/infrastructure/websocket/index.js.map +1 -0
  191. package/package.json +248 -0
@@ -0,0 +1,724 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/adapters/pubsub/amqp/index.ts
31
+ var amqp_exports = {};
32
+ __export(amqp_exports, {
33
+ InvalidDomainEventError: () => InvalidDomainEventError,
34
+ NoFailedMessagesError: () => NoFailedMessagesError,
35
+ default: () => AmqpMessageBusAdapter
36
+ });
37
+ module.exports = __toCommonJS(amqp_exports);
38
+
39
+ // src/adapters/pubsub/amqp/AmqpMessageBusAdapter.ts
40
+ var import_amqplib = __toESM(require("amqplib"), 1);
41
+ var import_node_crypto = require("crypto");
42
+
43
+ // src/Kernel.ts
44
+ var import_node_path2 = __toESM(require("path"), 1);
45
+
46
+ // src/adapters/kernel/console/ConsoleKernelLogger.ts
47
+ var ConsoleKernelLogger = class {
48
+ debug(message) {
49
+ console.debug(message);
50
+ }
51
+ error(message) {
52
+ console.error(message);
53
+ }
54
+ info(message) {
55
+ console.info(message);
56
+ }
57
+ warn(message) {
58
+ console.warn(message);
59
+ }
60
+ };
61
+
62
+ // src/infrastructure/dependency-injection/DependencyInjection.ts
63
+ var import_fs_extra = __toESM(require("fs-extra"), 1);
64
+ var import_node_dependency_injection = require("node-dependency-injection");
65
+ var import_node_path = __toESM(require("path"), 1);
66
+ var DependencyInjection = class _DependencyInjection {
67
+ constructor(options = {
68
+ containerBuild: process.env.CONTAINER_BUILD === "true",
69
+ servicesYamlPath: import_node_path.default.resolve(
70
+ process.cwd(),
71
+ "config",
72
+ "container",
73
+ "services.yaml"
74
+ ),
75
+ sourceDirectory: import_node_path.default.resolve(process.cwd(), "src")
76
+ }) {
77
+ this.options = options;
78
+ this.container = new import_node_dependency_injection.ContainerBuilder(false, this.options.sourceDirectory);
79
+ }
80
+ options;
81
+ static configuredInstance;
82
+ autowire;
83
+ loader;
84
+ container;
85
+ static configure(options) {
86
+ _DependencyInjection.configuredInstance = new _DependencyInjection(options);
87
+ return _DependencyInjection.configuredInstance;
88
+ }
89
+ static get instance() {
90
+ if (!_DependencyInjection.configuredInstance) {
91
+ throw new Error("DependencyInjection has not been configured.");
92
+ }
93
+ return _DependencyInjection.configuredInstance;
94
+ }
95
+ get definitions() {
96
+ const container = this.container;
97
+ return container._definitions || /* @__PURE__ */ new Map();
98
+ }
99
+ get aliases() {
100
+ const container = this.container;
101
+ return container._alias || /* @__PURE__ */ new Map();
102
+ }
103
+ async ensureFolderExists(filePath) {
104
+ await import_fs_extra.default.mkdir(import_node_path.default.dirname(filePath), { recursive: true });
105
+ }
106
+ getServiceClassName(serviceName) {
107
+ return typeof serviceName === "function" ? serviceName.name : void 0;
108
+ }
109
+ parentMatchesService(parentId, serviceClassName) {
110
+ if (!parentId) {
111
+ return false;
112
+ }
113
+ const parentName = Buffer.from(parentId, "base64").toString("utf8");
114
+ return parentName.endsWith(`__${serviceClassName}__${serviceClassName}`);
115
+ }
116
+ serviceIdMatchesService(serviceId, serviceClassName) {
117
+ const serviceName = Buffer.from(serviceId, "base64").toString("utf8");
118
+ return serviceName.endsWith(`__${serviceClassName}__${serviceClassName}`);
119
+ }
120
+ findConcreteChildServiceId(serviceName) {
121
+ const serviceClassName = this.getServiceClassName(serviceName);
122
+ if (!serviceClassName) {
123
+ return void 0;
124
+ }
125
+ const matches = [...this.definitions.entries()].filter(([, definition]) => definition._abstract !== true).filter(
126
+ ([, definition]) => this.parentMatchesService(definition._parent, serviceClassName)
127
+ ).map(([id]) => id);
128
+ return matches[matches.length - 1];
129
+ }
130
+ findRegisteredServiceId(serviceName) {
131
+ const serviceClassName = this.getServiceClassName(serviceName);
132
+ if (!serviceClassName) {
133
+ return void 0;
134
+ }
135
+ const matches = [...this.definitions.keys()].filter(
136
+ (id) => this.serviceIdMatchesService(id, serviceClassName)
137
+ );
138
+ return matches[matches.length - 1];
139
+ }
140
+ findAliasServiceId(serviceName) {
141
+ const serviceClassName = this.getServiceClassName(serviceName);
142
+ if (!serviceClassName) {
143
+ return void 0;
144
+ }
145
+ const matches = [...this.aliases.keys()].filter(
146
+ (id) => this.serviceIdMatchesService(id, serviceClassName)
147
+ );
148
+ return matches[matches.length - 1];
149
+ }
150
+ registerParentAliases() {
151
+ for (const [id, definition] of this.definitions.entries()) {
152
+ if (definition._abstract === true || !definition._parent) {
153
+ continue;
154
+ }
155
+ this.container.setAlias(definition._parent, id);
156
+ }
157
+ }
158
+ async compile() {
159
+ if (this.options.containerBuild) {
160
+ await this.ensureFolderExists(this.options.servicesYamlPath);
161
+ this.autowire = new import_node_dependency_injection.Autowire(this.container);
162
+ this.autowire.serviceFile = new import_node_dependency_injection.ServiceFile(
163
+ this.options.servicesYamlPath,
164
+ false
165
+ );
166
+ await this.autowire.process();
167
+ } else {
168
+ this.loader = new import_node_dependency_injection.YamlFileLoader(this.container);
169
+ await this.loader.load(this.options.servicesYamlPath);
170
+ }
171
+ this.registerParentAliases();
172
+ await this.container.compile();
173
+ }
174
+ getService(serviceName) {
175
+ const childServiceId = this.findConcreteChildServiceId(serviceName);
176
+ if (childServiceId) {
177
+ return this.container.get(childServiceId);
178
+ }
179
+ const aliasServiceId = this.findAliasServiceId(serviceName);
180
+ if (aliasServiceId) {
181
+ return this.container.get(aliasServiceId);
182
+ }
183
+ const registeredServiceId = this.findRegisteredServiceId(serviceName);
184
+ if (registeredServiceId) {
185
+ return this.container.get(registeredServiceId);
186
+ }
187
+ return this.container.get(serviceName);
188
+ }
189
+ };
190
+
191
+ // src/Kernel.ts
192
+ var Kernel = class _Kernel {
193
+ constructor(options = {}) {
194
+ this.options = options;
195
+ this.loggerInstance = options.logger ?? new ConsoleKernelLogger();
196
+ this.dependencyInjectionInstance = options.di;
197
+ _Kernel.state.activeKernel = this;
198
+ }
199
+ options;
200
+ static stateKey = /* @__PURE__ */ Symbol.for(
201
+ "@haskou/ddd-kernel/kernel-state"
202
+ );
203
+ consumerMiddlewares = [];
204
+ consumersList = [];
205
+ loggerInstance;
206
+ routesList = [];
207
+ schedulersList = [];
208
+ shutdownHooks = [];
209
+ dependencyInjectionInstance;
210
+ static get state() {
211
+ const stateContainer = globalThis;
212
+ stateContainer[_Kernel.stateKey] = stateContainer[_Kernel.stateKey] ?? {};
213
+ return stateContainer[_Kernel.stateKey];
214
+ }
215
+ static get configDirectory() {
216
+ return import_node_path2.default.resolve(_Kernel.rootDirectory, "config");
217
+ }
218
+ static get consumers() {
219
+ return _Kernel.getActiveKernel().consumers;
220
+ }
221
+ static get consumerMiddleware() {
222
+ return _Kernel.getActiveKernel().consumerMiddleware;
223
+ }
224
+ static get di() {
225
+ return _Kernel.getActiveKernel().di;
226
+ }
227
+ static get logger() {
228
+ return _Kernel.getActiveKernel().logger;
229
+ }
230
+ static get rootDirectory() {
231
+ return process.cwd();
232
+ }
233
+ static get routes() {
234
+ return _Kernel.getActiveKernel().routes;
235
+ }
236
+ static get schedulers() {
237
+ return _Kernel.getActiveKernel().schedulers;
238
+ }
239
+ static get sourceDirectory() {
240
+ return import_node_path2.default.resolve(_Kernel.rootDirectory, "src");
241
+ }
242
+ static getActiveKernel() {
243
+ if (!_Kernel.state.activeKernel) {
244
+ _Kernel.state.activeKernel = new _Kernel();
245
+ }
246
+ return _Kernel.state.activeKernel;
247
+ }
248
+ async closeCandidate(candidate) {
249
+ if (candidate.shutdown) {
250
+ await candidate.shutdown();
251
+ return;
252
+ }
253
+ if (candidate.close) {
254
+ await candidate.close();
255
+ return;
256
+ }
257
+ if (candidate.stop) {
258
+ await candidate.stop();
259
+ return;
260
+ }
261
+ if (candidate.flush) {
262
+ await candidate.flush();
263
+ }
264
+ }
265
+ getConsumerFromClass(ClassDefinition) {
266
+ return this.di.getService(ClassDefinition);
267
+ }
268
+ getInitializerFromClass(ClassDefinition) {
269
+ return this.di.getService(ClassDefinition);
270
+ }
271
+ getRuntimeFromClass(ClassDefinition) {
272
+ return this.di.getService(ClassDefinition);
273
+ }
274
+ getSchedulerFromClass(ClassDefinition) {
275
+ return this.di.getService(ClassDefinition);
276
+ }
277
+ get consumers() {
278
+ return this.consumersList;
279
+ }
280
+ get consumerMiddleware() {
281
+ return this.consumerMiddlewares;
282
+ }
283
+ get di() {
284
+ if (!this.dependencyInjectionInstance) {
285
+ throw new Error("Kernel dependency injection has not been initialized.");
286
+ }
287
+ return this.dependencyInjectionInstance;
288
+ }
289
+ get logger() {
290
+ return this.loggerInstance;
291
+ }
292
+ get routes() {
293
+ return this.routesList;
294
+ }
295
+ get schedulers() {
296
+ return this.schedulersList;
297
+ }
298
+ async dependencyInjection() {
299
+ this.dependencyInjectionInstance = this.dependencyInjectionInstance ?? DependencyInjection.configure({
300
+ containerBuild: process.env.CONTAINER_BUILD === "true",
301
+ servicesYamlPath: this.options.servicesYamlPath ?? import_node_path2.default.resolve(_Kernel.configDirectory, "container", "services.yaml"),
302
+ sourceDirectory: this.options.sourceDirectory ?? _Kernel.sourceDirectory
303
+ });
304
+ await this.dependencyInjectionInstance.compile();
305
+ }
306
+ getRoutes() {
307
+ return this.routes;
308
+ }
309
+ registerConsumerMiddleware(...middlewares) {
310
+ this.consumerMiddlewares.push(...middlewares);
311
+ }
312
+ registerConsumers(...ClassDefinitions) {
313
+ for (const ClassDefinition of ClassDefinitions) {
314
+ this.consumersList.push(this.getConsumerFromClass(ClassDefinition));
315
+ }
316
+ }
317
+ registerConsumerInstances(...consumers) {
318
+ this.consumersList.push(...consumers);
319
+ }
320
+ registerRoutes(...ClassDefinitions) {
321
+ this.routesList.push(...ClassDefinitions);
322
+ }
323
+ registerSchedulers(...ClassDefinitions) {
324
+ for (const ClassDefinition of ClassDefinitions) {
325
+ this.schedulersList.push(this.getSchedulerFromClass(ClassDefinition));
326
+ }
327
+ }
328
+ registerSchedulerInstances(...schedulers) {
329
+ this.schedulersList.push(...schedulers);
330
+ }
331
+ registerShutdownHook(hook) {
332
+ this.shutdownHooks.push(hook);
333
+ }
334
+ removeConsumers() {
335
+ this.consumersList.length = 0;
336
+ }
337
+ removeRoutes() {
338
+ this.routesList.length = 0;
339
+ }
340
+ removeSchedulers() {
341
+ this.schedulersList.length = 0;
342
+ }
343
+ async runConsumers() {
344
+ for (const consumer of this.consumersList) {
345
+ await consumer.init();
346
+ }
347
+ }
348
+ async runInitializers(...ClassDefinitions) {
349
+ for (const ClassDefinition of ClassDefinitions) {
350
+ await this.getInitializerFromClass(ClassDefinition).ensure();
351
+ }
352
+ }
353
+ async runRuntimes(...ClassDefinitions) {
354
+ for (const ClassDefinition of ClassDefinitions) {
355
+ const runtime = this.getRuntimeFromClass(ClassDefinition);
356
+ await runtime.run();
357
+ this.registerShutdownHook(
358
+ () => this.closeCandidate(runtime)
359
+ );
360
+ }
361
+ }
362
+ async runSchedulerNowAndSchedule(ClassDefinition) {
363
+ const scheduler = this.getSchedulerFromClass(ClassDefinition);
364
+ await scheduler.runOnce();
365
+ await scheduler.init();
366
+ this.schedulersList.push(scheduler);
367
+ }
368
+ async runSchedulers() {
369
+ for (const scheduler of this.schedulersList) {
370
+ await scheduler.init();
371
+ }
372
+ }
373
+ async shutdown() {
374
+ for (const consumer of [...this.consumersList].reverse()) {
375
+ await this.closeCandidate(consumer);
376
+ }
377
+ for (const scheduler of [...this.schedulersList].reverse()) {
378
+ await this.closeCandidate(scheduler);
379
+ }
380
+ for (const hook of [...this.shutdownHooks].reverse()) {
381
+ await hook();
382
+ }
383
+ await this.closeCandidate(this.loggerInstance);
384
+ }
385
+ };
386
+
387
+ // src/adapters/pubsub/amqp/InvalidDomainEventError.ts
388
+ var InvalidDomainEventError = class extends Error {
389
+ constructor(message) {
390
+ super(`Invalid domain event: ${message}`);
391
+ this.name = "InvalidDomainEventError";
392
+ }
393
+ };
394
+
395
+ // src/adapters/pubsub/amqp/NoFailedMessagesError.ts
396
+ var NoFailedMessagesError = class extends Error {
397
+ constructor(queueName) {
398
+ super(`No failed messages found in "${queueName}".`);
399
+ this.name = "NoFailedMessagesError";
400
+ }
401
+ };
402
+
403
+ // src/adapters/pubsub/amqp/AmqpMessageBusAdapter.ts
404
+ var AmqpMessageBusAdapter = class {
405
+ constructor(options = {}) {
406
+ this.options = options;
407
+ this.exchange = options.exchange ?? options.serviceName ?? process.env.SERVICE_NAME ?? "";
408
+ }
409
+ options;
410
+ channelInstance;
411
+ connection;
412
+ delayConsumers = [];
413
+ exchange;
414
+ get dsn() {
415
+ return this.options.dsn ?? process.env.TRANSPORT_DSN ?? "";
416
+ }
417
+ get logger() {
418
+ return this.options.logger ?? Kernel.logger;
419
+ }
420
+ get maxRetries() {
421
+ const configuredRetries = this.options.maxRetries ?? process.env.TRANSPORT_MAX_RETRIES;
422
+ if (configuredRetries === void 0) {
423
+ return void 0;
424
+ }
425
+ return Number(configuredRetries);
426
+ }
427
+ get retryDelayInMilliseconds() {
428
+ const retryDelayFromEnv = Number(process.env.TRANSPORT_RETRY_DELAY);
429
+ return this.options.retryDelayInMilliseconds ?? (Number.isFinite(retryDelayFromEnv) ? retryDelayFromEnv : 1e3);
430
+ }
431
+ instanceDomainEvent(DomainEventInstance, message) {
432
+ if (!message) {
433
+ throw new InvalidDomainEventError(JSON.stringify(message));
434
+ }
435
+ return new DomainEventInstance(
436
+ message.aggregate_id,
437
+ message.attributes,
438
+ message.event_id,
439
+ message.occurred_on ? new Date(message.occurred_on) : /* @__PURE__ */ new Date(),
440
+ message.correlation_id,
441
+ message.causation_id
442
+ );
443
+ }
444
+ async handle(msg, context) {
445
+ const message = JSON.parse(msg.content.toString());
446
+ this.logger?.info(
447
+ `AMQP message bus (${context.queueName}) handling message: ${JSON.stringify(message)}`
448
+ );
449
+ try {
450
+ const domainEvent = this.instanceDomainEvent(
451
+ context.DomainEventInstance,
452
+ message
453
+ );
454
+ await context.handler(domainEvent);
455
+ } catch (error) {
456
+ await this.handleError(msg, message, context, error);
457
+ }
458
+ }
459
+ async handleError(msg, message, context, error) {
460
+ this.logger?.error(error instanceof Error ? error.message : String(error));
461
+ const headers = msg.properties.headers ?? {};
462
+ const retryCount = Number(headers.retries ?? 0);
463
+ if (this.maxRetries !== void 0 && retryCount <= this.maxRetries) {
464
+ await this.retry(message, headers, context);
465
+ return;
466
+ }
467
+ await this.sendToDlx(message, context, String(error));
468
+ }
469
+ async retry(message, headers, context) {
470
+ const retry = Number(headers.retries || 1);
471
+ const delayTimeInMs = retry * this.retryDelayInMilliseconds;
472
+ const delayedQueueName = `${context.queueName}_delayed_${delayTimeInMs}`;
473
+ const delayedRoutingKey = `${context.queueName}_${context.bindingKey}_delayed_${delayTimeInMs}`;
474
+ const consumerTag = `${delayedQueueName}_${(0, import_node_crypto.randomUUID)()}`;
475
+ this.logger?.info(`Retry # ${retry}`);
476
+ if (!this.delayConsumers.includes(delayedQueueName)) {
477
+ await this.registerDelayedConsumer(
478
+ delayedQueueName,
479
+ delayedRoutingKey,
480
+ delayTimeInMs,
481
+ consumerTag,
482
+ context
483
+ );
484
+ }
485
+ try {
486
+ const domainEvent = this.instanceDomainEvent(
487
+ context.DomainEventInstance,
488
+ message
489
+ );
490
+ context.channel.publish(
491
+ this.exchange,
492
+ delayedRoutingKey,
493
+ Buffer.from(JSON.stringify(message)),
494
+ this.opts(domainEvent, retry)
495
+ );
496
+ } catch (error) {
497
+ await context.channel.cancel(consumerTag);
498
+ this.logger?.error(
499
+ error instanceof Error ? error.message : String(error)
500
+ );
501
+ }
502
+ }
503
+ async registerDelayedConsumer(delayedQueueName, delayedRoutingKey, delayTimeInMs, consumerTag, context) {
504
+ await context.channel.assertExchange(this.exchange, "topic", {
505
+ durable: true
506
+ });
507
+ await context.channel.assertQueue(delayedQueueName, {
508
+ autoDelete: true,
509
+ deadLetterExchange: this.exchange,
510
+ deadLetterRoutingKey: delayedRoutingKey,
511
+ durable: false,
512
+ messageTtl: delayTimeInMs
513
+ });
514
+ await context.channel.bindQueue(
515
+ delayedQueueName,
516
+ this.exchange,
517
+ delayedRoutingKey
518
+ );
519
+ this.delayConsumers.push(delayedQueueName);
520
+ await context.channel.consume(
521
+ delayedQueueName,
522
+ async (msg) => {
523
+ if (!msg) {
524
+ return;
525
+ }
526
+ await new Promise((resolve) => setTimeout(resolve, delayTimeInMs));
527
+ await this.handle(msg, context);
528
+ this.removeDelayConsumer(delayedQueueName);
529
+ await context.channel.cancel(consumerTag);
530
+ },
531
+ { consumerTag, noAck: true }
532
+ );
533
+ }
534
+ removeDelayConsumer(delayedQueueName) {
535
+ const index = this.delayConsumers.indexOf(delayedQueueName);
536
+ if (index !== -1) {
537
+ this.delayConsumers.splice(index, 1);
538
+ }
539
+ }
540
+ async sendToDlx(message, context, error) {
541
+ await context.channel.assertExchange(this.exchange, "topic");
542
+ const dlxQueueName = `${context.queueName}_dlx`;
543
+ const dlxRoutingKey = `${context.queueName}_${context.bindingKey}_dlx`;
544
+ await context.channel.assertQueue(dlxQueueName, {
545
+ deadLetterExchange: this.exchange,
546
+ deadLetterRoutingKey: dlxRoutingKey,
547
+ durable: true
548
+ });
549
+ await context.channel.bindQueue(dlxQueueName, this.exchange, dlxRoutingKey);
550
+ try {
551
+ const domainEvent = this.instanceDomainEvent(
552
+ context.DomainEventInstance,
553
+ message
554
+ );
555
+ context.channel.publish(
556
+ this.exchange,
557
+ dlxRoutingKey,
558
+ Buffer.from(JSON.stringify(message)),
559
+ this.opts(domainEvent, message.retries, error)
560
+ );
561
+ } catch (publishError) {
562
+ this.logger?.error(
563
+ publishError instanceof Error ? publishError.message : String(publishError)
564
+ );
565
+ }
566
+ }
567
+ async connect() {
568
+ this.connection = await import_amqplib.default.connect(this.getConnectionDsn());
569
+ this.channelInstance = await this.connection.createChannel();
570
+ this.channelInstance.on("close", async () => {
571
+ this.logger?.error("AMQP message bus event close");
572
+ await this.reconnect();
573
+ }).on("error", async (error) => {
574
+ this.logger?.error(`AMQP message bus event error: ${error.message}`);
575
+ await this.reconnect();
576
+ });
577
+ }
578
+ async reconnect() {
579
+ await this.connect();
580
+ for (const consumer of Kernel.consumers) {
581
+ await consumer.init();
582
+ }
583
+ }
584
+ async channel(forceNew = false) {
585
+ if (forceNew) {
586
+ const connection = await import_amqplib.default.connect(this.getConnectionDsn());
587
+ return connection.createChannel();
588
+ }
589
+ if (!this.channelInstance) {
590
+ await this.connect();
591
+ }
592
+ if (!this.channelInstance) {
593
+ throw new Error("AMQP channel could not be created.");
594
+ }
595
+ await this.channelInstance.assertExchange(this.exchange, "topic", {
596
+ durable: true
597
+ });
598
+ return this.channelInstance;
599
+ }
600
+ getConnectionDsn() {
601
+ const separator = this.dsn.includes("?") ? "&" : "?";
602
+ return `${this.dsn}${separator}heartbeat=60`;
603
+ }
604
+ opts(event, retries, error) {
605
+ return {
606
+ appId: this.options.serviceName ?? process.env.SERVICE_NAME,
607
+ contentEncoding: "utf-8",
608
+ contentType: "application/json",
609
+ deliveryMode: 2,
610
+ headers: {
611
+ error,
612
+ retries: retries ? retries + 1 : 0
613
+ },
614
+ messageId: event.eventId,
615
+ priority: 0,
616
+ timestamp: event.occurredOn.getTime(),
617
+ type: event.eventName()
618
+ };
619
+ }
620
+ getMessagesToRetry(requestedMessagesToRetry, availableMessages) {
621
+ return requestedMessagesToRetry ?? availableMessages;
622
+ }
623
+ async retryDlxMessage(msg, DomainEventInstance, handler, channel) {
624
+ const content = msg.content.toString();
625
+ this.logger?.info(`Retrying message from DLX ${content}`);
626
+ try {
627
+ const message = JSON.parse(content);
628
+ const domainEvent = this.instanceDomainEvent(
629
+ DomainEventInstance,
630
+ message
631
+ );
632
+ await handler(domainEvent);
633
+ this.logger?.info(`${content} successfully handled.`);
634
+ channel.ack(msg);
635
+ } catch (error) {
636
+ const errorMessage = error instanceof Error ? error.message : String(error);
637
+ this.logger?.error(`${content} error with ${errorMessage}.`);
638
+ channel.nack(msg);
639
+ }
640
+ }
641
+ async areQueuesBound() {
642
+ if (Kernel.consumers.length === 0) {
643
+ return false;
644
+ }
645
+ const channel = await this.channel();
646
+ for (const consumer of Kernel.consumers) {
647
+ const queueChecker = await channel.checkQueue(consumer.queueName);
648
+ if (queueChecker.consumerCount !== 0) {
649
+ return false;
650
+ }
651
+ }
652
+ return true;
653
+ }
654
+ async consumeDlx(queueName, DomainEventInstance, handler, messagesToRetry) {
655
+ const dlxQueueName = `${queueName}_dlx`;
656
+ const channel = await this.channel(true);
657
+ channel.on("error", () => {
658
+ this.logger?.error("AMQP message bus event error");
659
+ });
660
+ const queue = await channel.checkQueue(dlxQueueName);
661
+ const messagesToRetryCount = this.getMessagesToRetry(
662
+ messagesToRetry,
663
+ queue.messageCount
664
+ );
665
+ this.logger?.info(
666
+ `Retrying ${messagesToRetryCount} messages from DLX ${dlxQueueName}`
667
+ );
668
+ if (messagesToRetryCount > 0 && queue.messageCount !== 0) {
669
+ for (let index = 0; index < messagesToRetryCount; index++) {
670
+ const msg = await channel.get(dlxQueueName);
671
+ if (msg === false) {
672
+ continue;
673
+ }
674
+ await this.retryDlxMessage(msg, DomainEventInstance, handler, channel);
675
+ }
676
+ return;
677
+ }
678
+ throw new NoFailedMessagesError(dlxQueueName);
679
+ }
680
+ async consume(queueName, bindingKey, DomainEventInstance, exchange, handler) {
681
+ const channel = await this.channel();
682
+ await channel.assertQueue(queueName, { durable: true });
683
+ await channel.assertExchange(exchange, "topic");
684
+ await channel.prefetch(1);
685
+ await channel.bindQueue(queueName, exchange, bindingKey);
686
+ const context = {
687
+ bindingKey,
688
+ channel,
689
+ DomainEventInstance,
690
+ handler,
691
+ queueName
692
+ };
693
+ await channel.consume(queueName, async (msg) => {
694
+ if (!msg) {
695
+ return;
696
+ }
697
+ await this.handle(msg, context);
698
+ channel.ack(msg);
699
+ });
700
+ }
701
+ async publish(domainEvents) {
702
+ const channel = await this.channel();
703
+ for (const event of domainEvents) {
704
+ channel.publish(
705
+ this.exchange,
706
+ event.eventName(),
707
+ Buffer.from(event.decode()),
708
+ this.opts(event)
709
+ );
710
+ }
711
+ }
712
+ async close() {
713
+ await this.channelInstance?.close();
714
+ await this.connection?.close();
715
+ this.channelInstance = void 0;
716
+ this.connection = void 0;
717
+ }
718
+ };
719
+ // Annotate the CommonJS export names for ESM import in node:
720
+ 0 && (module.exports = {
721
+ InvalidDomainEventError,
722
+ NoFailedMessagesError
723
+ });
724
+ //# sourceMappingURL=index.cjs.map