@buenojs/bueno 0.8.4 → 0.8.6

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 (234) hide show
  1. package/README.md +264 -17
  2. package/dist/cli/{index.js → bin.js} +413 -332
  3. package/dist/container/index.js +273 -0
  4. package/dist/context/index.js +219 -0
  5. package/dist/database/index.js +493 -0
  6. package/dist/frontend/index.js +7697 -0
  7. package/dist/graphql/index.js +2156 -0
  8. package/dist/health/index.js +364 -0
  9. package/dist/i18n/index.js +345 -0
  10. package/dist/index.js +9694 -5047
  11. package/dist/jobs/index.js +819 -0
  12. package/dist/lock/index.js +367 -0
  13. package/dist/logger/index.js +281 -0
  14. package/dist/metrics/index.js +289 -0
  15. package/dist/middleware/index.js +77 -0
  16. package/dist/migrations/index.js +571 -0
  17. package/dist/modules/index.js +3411 -0
  18. package/dist/notification/index.js +484 -0
  19. package/dist/observability/index.js +331 -0
  20. package/dist/openapi/index.js +795 -0
  21. package/dist/orm/index.js +1356 -0
  22. package/dist/router/index.js +886 -0
  23. package/dist/rpc/index.js +691 -0
  24. package/dist/schema/index.js +400 -0
  25. package/dist/telemetry/index.js +595 -0
  26. package/dist/template/index.js +640 -0
  27. package/dist/templates/index.js +640 -0
  28. package/dist/testing/index.js +1111 -0
  29. package/dist/types/index.js +60 -0
  30. package/llms.txt +231 -0
  31. package/package.json +125 -27
  32. package/src/cache/index.ts +2 -1
  33. package/src/cli/ARCHITECTURE.md +3 -3
  34. package/src/cli/bin.ts +2 -2
  35. package/src/cli/commands/build.ts +183 -165
  36. package/src/cli/commands/dev.ts +96 -89
  37. package/src/cli/commands/generate.ts +142 -111
  38. package/src/cli/commands/help.ts +20 -16
  39. package/src/cli/commands/index.ts +3 -6
  40. package/src/cli/commands/migration.ts +124 -105
  41. package/src/cli/commands/new.ts +294 -232
  42. package/src/cli/commands/start.ts +81 -79
  43. package/src/cli/core/args.ts +68 -50
  44. package/src/cli/core/console.ts +89 -95
  45. package/src/cli/core/index.ts +4 -4
  46. package/src/cli/core/prompt.ts +65 -62
  47. package/src/cli/core/spinner.ts +23 -20
  48. package/src/cli/index.ts +46 -38
  49. package/src/cli/templates/database/index.ts +37 -18
  50. package/src/cli/templates/database/mysql.ts +3 -3
  51. package/src/cli/templates/database/none.ts +2 -2
  52. package/src/cli/templates/database/postgresql.ts +3 -3
  53. package/src/cli/templates/database/sqlite.ts +3 -3
  54. package/src/cli/templates/deploy.ts +29 -26
  55. package/src/cli/templates/docker.ts +41 -30
  56. package/src/cli/templates/frontend/index.ts +33 -15
  57. package/src/cli/templates/frontend/none.ts +2 -2
  58. package/src/cli/templates/frontend/react.ts +18 -18
  59. package/src/cli/templates/frontend/solid.ts +15 -15
  60. package/src/cli/templates/frontend/svelte.ts +17 -17
  61. package/src/cli/templates/frontend/vue.ts +15 -15
  62. package/src/cli/templates/generators/index.ts +29 -29
  63. package/src/cli/templates/generators/types.ts +21 -21
  64. package/src/cli/templates/index.ts +6 -6
  65. package/src/cli/templates/project/api.ts +37 -36
  66. package/src/cli/templates/project/default.ts +25 -25
  67. package/src/cli/templates/project/fullstack.ts +28 -26
  68. package/src/cli/templates/project/index.ts +55 -16
  69. package/src/cli/templates/project/minimal.ts +17 -12
  70. package/src/cli/templates/project/types.ts +10 -5
  71. package/src/cli/templates/project/website.ts +15 -15
  72. package/src/cli/utils/fs.ts +55 -41
  73. package/src/cli/utils/index.ts +3 -3
  74. package/src/cli/utils/strings.ts +47 -33
  75. package/src/cli/utils/version.ts +14 -8
  76. package/src/config/env-validation.ts +100 -0
  77. package/src/config/env.ts +169 -41
  78. package/src/config/index.ts +28 -20
  79. package/src/config/loader.ts +25 -16
  80. package/src/config/merge.ts +21 -10
  81. package/src/config/types.ts +566 -25
  82. package/src/config/validation.ts +215 -7
  83. package/src/container/forward-ref.ts +22 -22
  84. package/src/container/index.ts +34 -12
  85. package/src/context/index.ts +11 -1
  86. package/src/database/index.ts +7 -190
  87. package/src/database/orm/builder.ts +457 -0
  88. package/src/database/orm/casts/index.ts +130 -0
  89. package/src/database/orm/casts/types.ts +25 -0
  90. package/src/database/orm/compiler.ts +304 -0
  91. package/src/database/orm/hooks/index.ts +114 -0
  92. package/src/database/orm/index.ts +61 -0
  93. package/src/database/orm/model-registry.ts +59 -0
  94. package/src/database/orm/model.ts +821 -0
  95. package/src/database/orm/relationships/base.ts +146 -0
  96. package/src/database/orm/relationships/belongs-to-many.ts +179 -0
  97. package/src/database/orm/relationships/belongs-to.ts +56 -0
  98. package/src/database/orm/relationships/has-many.ts +45 -0
  99. package/src/database/orm/relationships/has-one.ts +41 -0
  100. package/src/database/orm/relationships/index.ts +11 -0
  101. package/src/database/orm/scopes/index.ts +55 -0
  102. package/src/events/__tests__/event-system.test.ts +235 -0
  103. package/src/events/config.ts +238 -0
  104. package/src/events/example-usage.ts +185 -0
  105. package/src/events/index.ts +278 -0
  106. package/src/events/manager.ts +385 -0
  107. package/src/events/registry.ts +182 -0
  108. package/src/events/types.ts +124 -0
  109. package/src/frontend/api-routes.ts +65 -23
  110. package/src/frontend/bundler.ts +76 -34
  111. package/src/frontend/console-client.ts +2 -2
  112. package/src/frontend/console-stream.ts +94 -38
  113. package/src/frontend/dev-server.ts +94 -46
  114. package/src/frontend/file-router.ts +61 -19
  115. package/src/frontend/frameworks/index.ts +37 -10
  116. package/src/frontend/frameworks/react.ts +10 -8
  117. package/src/frontend/frameworks/solid.ts +11 -9
  118. package/src/frontend/frameworks/svelte.ts +15 -9
  119. package/src/frontend/frameworks/vue.ts +13 -11
  120. package/src/frontend/hmr-client.ts +12 -10
  121. package/src/frontend/hmr.ts +146 -103
  122. package/src/frontend/index.ts +14 -5
  123. package/src/frontend/islands.ts +41 -22
  124. package/src/frontend/isr.ts +59 -37
  125. package/src/frontend/layout.ts +36 -21
  126. package/src/frontend/ssr/react.ts +74 -27
  127. package/src/frontend/ssr/solid.ts +54 -20
  128. package/src/frontend/ssr/svelte.ts +48 -14
  129. package/src/frontend/ssr/vue.ts +50 -18
  130. package/src/frontend/ssr.ts +83 -39
  131. package/src/frontend/types.ts +91 -56
  132. package/src/graphql/built-in-engine.ts +598 -0
  133. package/src/graphql/context-builder.ts +110 -0
  134. package/src/graphql/decorators.ts +358 -0
  135. package/src/graphql/execution-pipeline.ts +227 -0
  136. package/src/graphql/graphql-module.ts +563 -0
  137. package/src/graphql/index.ts +101 -0
  138. package/src/graphql/metadata.ts +237 -0
  139. package/src/graphql/schema-builder.ts +319 -0
  140. package/src/graphql/subscription-handler.ts +283 -0
  141. package/src/graphql/types.ts +324 -0
  142. package/src/health/index.ts +21 -9
  143. package/src/i18n/engine.ts +305 -0
  144. package/src/i18n/index.ts +38 -0
  145. package/src/i18n/loader.ts +218 -0
  146. package/src/i18n/middleware.ts +164 -0
  147. package/src/i18n/negotiator.ts +162 -0
  148. package/src/i18n/types.ts +158 -0
  149. package/src/index.ts +182 -27
  150. package/src/jobs/drivers/memory.ts +315 -0
  151. package/src/jobs/drivers/redis.ts +459 -0
  152. package/src/jobs/index.ts +30 -0
  153. package/src/jobs/queue.ts +281 -0
  154. package/src/jobs/types.ts +295 -0
  155. package/src/jobs/worker.ts +380 -0
  156. package/src/logger/index.ts +1 -3
  157. package/src/logger/transports/index.ts +62 -22
  158. package/src/metrics/index.ts +25 -16
  159. package/src/migrations/index.ts +9 -0
  160. package/src/modules/filters.ts +13 -17
  161. package/src/modules/guards.ts +49 -26
  162. package/src/modules/index.ts +457 -299
  163. package/src/modules/interceptors.ts +58 -20
  164. package/src/modules/lazy.ts +11 -19
  165. package/src/modules/lifecycle.ts +15 -7
  166. package/src/modules/metadata.ts +15 -5
  167. package/src/modules/pipes.ts +94 -72
  168. package/src/notification/channels/base.ts +68 -0
  169. package/src/notification/channels/email.ts +105 -0
  170. package/src/notification/channels/push.ts +104 -0
  171. package/src/notification/channels/sms.ts +105 -0
  172. package/src/notification/channels/whatsapp.ts +104 -0
  173. package/src/notification/index.ts +48 -0
  174. package/src/notification/service.ts +354 -0
  175. package/src/notification/types.ts +344 -0
  176. package/src/observability/__tests__/observability.test.ts +483 -0
  177. package/src/observability/breadcrumbs.ts +114 -0
  178. package/src/observability/index.ts +136 -0
  179. package/src/observability/interceptor.ts +85 -0
  180. package/src/observability/service.ts +303 -0
  181. package/src/observability/trace.ts +37 -0
  182. package/src/observability/types.ts +196 -0
  183. package/src/openapi/__tests__/decorators.test.ts +335 -0
  184. package/src/openapi/__tests__/document-builder.test.ts +285 -0
  185. package/src/openapi/__tests__/route-scanner.test.ts +334 -0
  186. package/src/openapi/__tests__/schema-generator.test.ts +275 -0
  187. package/src/openapi/decorators.ts +328 -0
  188. package/src/openapi/document-builder.ts +274 -0
  189. package/src/openapi/index.ts +112 -0
  190. package/src/openapi/metadata.ts +112 -0
  191. package/src/openapi/route-scanner.ts +289 -0
  192. package/src/openapi/schema-generator.ts +256 -0
  193. package/src/openapi/swagger-module.ts +166 -0
  194. package/src/openapi/types.ts +398 -0
  195. package/src/orm/index.ts +10 -0
  196. package/src/rpc/index.ts +3 -1
  197. package/src/schema/index.ts +9 -0
  198. package/src/security/index.ts +15 -6
  199. package/src/ssg/index.ts +9 -8
  200. package/src/telemetry/index.ts +76 -22
  201. package/src/template/index.ts +7 -0
  202. package/src/templates/engine.ts +224 -0
  203. package/src/templates/index.ts +9 -0
  204. package/src/templates/loader.ts +331 -0
  205. package/src/templates/renderers/markdown.ts +212 -0
  206. package/src/templates/renderers/simple.ts +269 -0
  207. package/src/templates/types.ts +154 -0
  208. package/src/testing/index.ts +100 -27
  209. package/src/types/optional-deps.d.ts +347 -187
  210. package/src/validation/index.ts +92 -2
  211. package/src/validation/schemas.ts +536 -0
  212. package/tests/integration/cli.test.ts +19 -19
  213. package/tests/integration/fullstack.test.ts +4 -4
  214. package/tests/unit/cli.test.ts +1 -1
  215. package/tests/unit/database.test.ts +2 -72
  216. package/tests/unit/env-validation.test.ts +166 -0
  217. package/tests/unit/events.test.ts +910 -0
  218. package/tests/unit/graphql.test.ts +991 -0
  219. package/tests/unit/i18n.test.ts +455 -0
  220. package/tests/unit/jobs.test.ts +493 -0
  221. package/tests/unit/notification.test.ts +988 -0
  222. package/tests/unit/observability.test.ts +453 -0
  223. package/tests/unit/orm/builder.test.ts +323 -0
  224. package/tests/unit/orm/casts.test.ts +179 -0
  225. package/tests/unit/orm/compiler.test.ts +220 -0
  226. package/tests/unit/orm/eager-loading.test.ts +285 -0
  227. package/tests/unit/orm/hooks.test.ts +191 -0
  228. package/tests/unit/orm/model.test.ts +373 -0
  229. package/tests/unit/orm/relationships.test.ts +303 -0
  230. package/tests/unit/orm/scopes.test.ts +74 -0
  231. package/tests/unit/templates-simple.test.ts +53 -0
  232. package/tests/unit/templates.test.ts +454 -0
  233. package/tests/unit/validation.test.ts +18 -24
  234. package/tsconfig.json +11 -3
@@ -0,0 +1,235 @@
1
+ import {
2
+ createEvent,
3
+ createEventCategory,
4
+ createEventListener,
5
+ createEventManager,
6
+ createEventRegistry,
7
+ deserializeEvent,
8
+ serializeEvent,
9
+ validateEvent,
10
+ } from "../index";
11
+
12
+ describe("Event System", () => {
13
+ let manager: any;
14
+ let registry: any;
15
+
16
+ beforeEach(() => {
17
+ manager = createEventManager();
18
+ registry = createEventRegistry();
19
+ });
20
+
21
+ describe("Event Manager", () => {
22
+ it("should emit and handle events", async () => {
23
+ const eventData = { message: "test" };
24
+ const event = createEvent("test.event", eventData);
25
+
26
+ const handler = jest.fn();
27
+ manager.on("test.event", handler);
28
+
29
+ await manager.emit(event);
30
+
31
+ expect(handler).toHaveBeenCalledWith(event);
32
+ expect(handler).toHaveBeenCalledTimes(1);
33
+ });
34
+
35
+ it("should support one-time listeners", async () => {
36
+ const eventData = { message: "test" };
37
+ const event = createEvent("test.event", eventData);
38
+
39
+ const handler = jest.fn();
40
+ manager.once("test.event", handler);
41
+
42
+ await manager.emit(event);
43
+ await manager.emit(event);
44
+
45
+ expect(handler).toHaveBeenCalledWith(event);
46
+ expect(handler).toHaveBeenCalledTimes(1);
47
+ });
48
+
49
+ it("should support event filtering", async () => {
50
+ const eventData1 = { type: "important" };
51
+ const eventData2 = { type: "normal" };
52
+ const event1 = createEvent("test.event", eventData1);
53
+ const event2 = createEvent("test.event", eventData2);
54
+
55
+ const handler = jest.fn();
56
+ const filter = (e: any) => e.data.type === "important";
57
+ manager.on("test.event", handler, { filter });
58
+
59
+ await manager.emit(event1);
60
+ await manager.emit(event2);
61
+
62
+ expect(handler).toHaveBeenCalledWith(event1);
63
+ expect(handler).toHaveBeenCalledTimes(1);
64
+ });
65
+
66
+ it("should support event middleware", async () => {
67
+ const eventData = { message: "test" };
68
+ const event = createEvent("test.event", eventData);
69
+
70
+ const middleware = jest.fn(async (e, next) => {
71
+ e.data.middleware = true;
72
+ await next();
73
+ });
74
+
75
+ manager.addMiddleware(middleware);
76
+ const handler = jest.fn();
77
+ manager.on("test.event", handler);
78
+
79
+ await manager.emit(event);
80
+
81
+ expect(middleware).toHaveBeenCalled();
82
+ expect(handler).toHaveBeenCalledWith(event);
83
+ expect(event.data.middleware).toBe(true);
84
+ });
85
+
86
+ it("should handle errors gracefully", async () => {
87
+ const eventData = { message: "test" };
88
+ const event = createEvent("test.event", eventData);
89
+
90
+ const failingHandler = jest.fn(() => {
91
+ throw new Error("Test error");
92
+ });
93
+ const successHandler = jest.fn();
94
+
95
+ manager.on("test.event", failingHandler);
96
+ manager.on("test.event", successHandler);
97
+
98
+ await manager.emit(event);
99
+
100
+ expect(failingHandler).toHaveBeenCalled();
101
+ expect(successHandler).toHaveBeenCalled();
102
+ });
103
+
104
+ it("should support event categories", () => {
105
+ const category = createEventCategory("database", "Database operations");
106
+ manager.registerEventCategory(category);
107
+
108
+ expect(manager.getEventCategories()).toContainEqual(category);
109
+ });
110
+ });
111
+
112
+ describe("Event Registry", () => {
113
+ it("should register and retrieve events", () => {
114
+ const eventData = { message: "test" };
115
+ const event = createEvent("test.event", eventData);
116
+
117
+ registry.registerEvent(event);
118
+
119
+ expect(registry.getEvent(event.id)).toEqual(event);
120
+ });
121
+
122
+ it("should support event cleanup", () => {
123
+ const eventData = { message: "test" };
124
+ const event = createEvent("test.event", eventData, {
125
+ timestamp: new Date(Date.now() - 25 * 60 * 60 * 1000), // 25 hours ago
126
+ });
127
+
128
+ registry.registerEvent(event);
129
+ registry.cleanupOldEvents();
130
+
131
+ expect(registry.getEvent(event.id)).toBeUndefined();
132
+ });
133
+
134
+ it("should support event search", () => {
135
+ const event1 = createEvent("user.created", { name: "John" });
136
+ const event2 = createEvent("user.deleted", { name: "Jane" });
137
+
138
+ registry.registerEvent(event1);
139
+ registry.registerEvent(event2);
140
+
141
+ const results = registry.searchEvents("user");
142
+
143
+ expect(results).toHaveLength(2);
144
+ expect(results).toContainEqual(event1);
145
+ expect(results).toContainEqual(event2);
146
+ });
147
+
148
+ it("should support event history", () => {
149
+ const events = [
150
+ createEvent(
151
+ "test.event",
152
+ { count: 1 },
153
+ { timestamp: new Date(Date.now() - 3000) },
154
+ ),
155
+ createEvent(
156
+ "test.event",
157
+ { count: 2 },
158
+ { timestamp: new Date(Date.now() - 2000) },
159
+ ),
160
+ createEvent(
161
+ "test.event",
162
+ { count: 3 },
163
+ { timestamp: new Date(Date.now() - 1000) },
164
+ ),
165
+ ];
166
+
167
+ events.forEach((event) => registry.registerEvent(event));
168
+
169
+ const history = registry.getEventHistory({
170
+ category: undefined,
171
+ startTime: new Date(Date.now() - 60 * 60 * 1000),
172
+ endTime: new Date(),
173
+ limit: 2,
174
+ });
175
+
176
+ expect(history).toHaveLength(2);
177
+ expect(history[0].data.count).toBe(3);
178
+ expect(history[1].data.count).toBe(2);
179
+ });
180
+ });
181
+
182
+ describe("Event Utilities", () => {
183
+ it("should create valid events", () => {
184
+ const eventData = { message: "test" };
185
+ const event = createEvent("test.event", eventData);
186
+
187
+ expect(event).toHaveProperty("id");
188
+ expect(event).toHaveProperty("name", "test.event");
189
+ expect(event).toHaveProperty("timestamp");
190
+ expect(event).toHaveProperty("data", eventData);
191
+ });
192
+
193
+ it("should validate events", () => {
194
+ const validEvent = createEvent("test.event", { message: "test" });
195
+ const invalidEvent = { name: "test", data: {} };
196
+
197
+ expect(validateEvent(validEvent)).toBe(true);
198
+ expect(validateEvent(invalidEvent)).toBe(false);
199
+ });
200
+
201
+ it("should serialize and deserialize events", () => {
202
+ const eventData = { message: "test" };
203
+ const event = createEvent("test.event", eventData);
204
+ const serialized = serializeEvent(event);
205
+ const deserialized = deserializeEvent(serialized);
206
+
207
+ expect(deserialized).toEqual(event);
208
+ });
209
+
210
+ it("should create event listeners", () => {
211
+ const handler = () => {};
212
+ const listener = createEventListener("test.listener", handler, {
213
+ priority: 10,
214
+ once: true,
215
+ });
216
+
217
+ expect(listener).toHaveProperty("id");
218
+ expect(listener).toHaveProperty("name", "test.listener");
219
+ expect(listener).toHaveProperty("handler", handler);
220
+ expect(listener).toHaveProperty("priority", 10);
221
+ expect(listener).toHaveProperty("once", true);
222
+ });
223
+
224
+ it("should create event categories", () => {
225
+ const category = createEventCategory("database", "Database operations", [
226
+ "query",
227
+ "mutation",
228
+ ]);
229
+
230
+ expect(category).toHaveProperty("name", "database");
231
+ expect(category).toHaveProperty("description", "Database operations");
232
+ expect(category).toHaveProperty("events", ["query", "mutation"]);
233
+ });
234
+ });
235
+ });
@@ -0,0 +1,238 @@
1
+ import {
2
+ EventManagerConfig,
3
+ type EventManagerOptions,
4
+ type EventRegistryOptions,
5
+ } from "./types";
6
+
7
+ export interface EventSystemConfig {
8
+ manager: EventManagerOptions;
9
+ registry: EventRegistryOptions;
10
+ defaultContext?: EventContext;
11
+ errorHandling?: "throw" | "log" | "ignore";
12
+ maxEventSize?: number;
13
+ eventCategories?: EventCategory[];
14
+ }
15
+
16
+ export const defaultEventSystemConfig: EventSystemConfig = {
17
+ manager: {
18
+ maxListeners: 100,
19
+ errorHandling: "log",
20
+ },
21
+ registry: {
22
+ maxEvents: 1000,
23
+ retentionPeriod: 24 * 60 * 60 * 1000, // 24 hours
24
+ cleanupInterval: 60 * 60 * 1000, // 1 hour
25
+ },
26
+ defaultContext: {
27
+ userId: undefined,
28
+ sessionId: undefined,
29
+ requestId: undefined,
30
+ ipAddress: undefined,
31
+ userAgent: undefined,
32
+ },
33
+ errorHandling: "log",
34
+ maxEventSize: 1024 * 1024, // 1MB
35
+ eventCategories: [
36
+ {
37
+ name: "database",
38
+ description: "Database operations and query lifecycle",
39
+ events: ["query", "mutation", "connection", "transaction"],
40
+ },
41
+ {
42
+ name: "job-queue",
43
+ description: "Background job processing and queue management",
44
+ events: ["job.created", "job.started", "job.completed", "job.failed"],
45
+ },
46
+ {
47
+ name: "notification",
48
+ description: "Multi-channel notification system",
49
+ events: [
50
+ "notification.sent",
51
+ "notification.delivered",
52
+ "notification.failed",
53
+ ],
54
+ },
55
+ {
56
+ name: "websocket",
57
+ description: "Real-time WebSocket communication",
58
+ events: ["connection", "message", "disconnection", "error"],
59
+ },
60
+ {
61
+ name: "http-rpc",
62
+ description: "HTTP and RPC request/response handling",
63
+ events: ["request.received", "response.sent", "error"],
64
+ },
65
+ {
66
+ name: "system",
67
+ description: "System-level events and health checks",
68
+ events: ["startup", "shutdown", "health.check"],
69
+ },
70
+ {
71
+ name: "cache",
72
+ description: "Caching operations and invalidation",
73
+ events: ["cache.set", "cache.get", "cache.delete", "cache.miss"],
74
+ },
75
+ {
76
+ name: "validation",
77
+ description: "Data validation and sanitization",
78
+ events: ["validation.passed", "validation.failed"],
79
+ },
80
+ {
81
+ name: "security",
82
+ description: "Security and authentication events",
83
+ events: ["login", "logout", "permission.granted", "permission.denied"],
84
+ },
85
+ {
86
+ name: "logging",
87
+ description: "Application logging and monitoring",
88
+ events: ["log.info", "log.warn", "log.error", "log.debug"],
89
+ },
90
+ ],
91
+ };
92
+
93
+ export function createEventSystemConfig(
94
+ customConfig: Partial<EventSystemConfig> = {},
95
+ ): EventSystemConfig {
96
+ return {
97
+ ...defaultEventSystemConfig,
98
+ ...customConfig,
99
+ manager: {
100
+ ...defaultEventSystemConfig.manager,
101
+ ...customConfig.manager,
102
+ },
103
+ registry: {
104
+ ...defaultEventSystemConfig.registry,
105
+ ...customConfig.registry,
106
+ },
107
+ defaultContext: {
108
+ ...defaultEventSystemConfig.defaultContext,
109
+ ...customConfig.defaultContext,
110
+ },
111
+ };
112
+ }
113
+
114
+ export function validateEventSystemConfig(config: EventSystemConfig): boolean {
115
+ if (!config || typeof config !== "object") return false;
116
+
117
+ // Validate manager config
118
+ if (!config.manager || typeof config.manager !== "object") return false;
119
+ if (
120
+ config.manager.maxListeners !== undefined &&
121
+ (typeof config.manager.maxListeners !== "number" ||
122
+ config.manager.maxListeners < 0)
123
+ ) {
124
+ return false;
125
+ }
126
+
127
+ // Validate registry config
128
+ if (!config.registry || typeof config.registry !== "object") return false;
129
+ if (
130
+ config.registry.maxEvents !== undefined &&
131
+ (typeof config.registry.maxEvents !== "number" ||
132
+ config.registry.maxEvents < 0)
133
+ ) {
134
+ return false;
135
+ }
136
+ if (
137
+ config.registry.retentionPeriod !== undefined &&
138
+ (typeof config.registry.retentionPeriod !== "number" ||
139
+ config.registry.retentionPeriod < 0)
140
+ ) {
141
+ return false;
142
+ }
143
+ if (
144
+ config.registry.cleanupInterval !== undefined &&
145
+ (typeof config.registry.cleanupInterval !== "number" ||
146
+ config.registry.cleanupInterval < 0)
147
+ ) {
148
+ return false;
149
+ }
150
+
151
+ // Validate error handling
152
+ if (
153
+ config.errorHandling &&
154
+ !["throw", "log", "ignore"].includes(config.errorHandling)
155
+ ) {
156
+ return false;
157
+ }
158
+
159
+ // Validate max event size
160
+ if (
161
+ config.maxEventSize !== undefined &&
162
+ (typeof config.maxEventSize !== "number" || config.maxEventSize < 0)
163
+ ) {
164
+ return false;
165
+ }
166
+
167
+ // Validate event categories
168
+ if (config.eventCategories) {
169
+ for (const category of config.eventCategories) {
170
+ if (!category.name || typeof category.name !== "string") return false;
171
+ if (!category.description || typeof category.description !== "string")
172
+ return false;
173
+ if (category.events && !Array.isArray(category.events)) return false;
174
+ }
175
+ }
176
+
177
+ return true;
178
+ }
179
+
180
+ export function loadEventSystemConfig(
181
+ configPath = "./config/event-system.json",
182
+ ): EventSystemConfig {
183
+ try {
184
+ const config = require(configPath);
185
+ if (validateEventSystemConfig(config)) {
186
+ return config;
187
+ }
188
+ console.warn("Invalid event system config, using defaults");
189
+ } catch (error) {
190
+ console.warn("Could not load event system config, using defaults");
191
+ }
192
+
193
+ return defaultEventSystemConfig;
194
+ }
195
+
196
+ export function saveEventSystemConfig(
197
+ config: EventSystemConfig,
198
+ configPath = "./config/event-system.json",
199
+ ): boolean {
200
+ try {
201
+ const fs = require("fs");
202
+ const path = require("path");
203
+
204
+ const dir = path.dirname(configPath);
205
+ if (!fs.existsSync(dir)) {
206
+ fs.mkdirSync(dir, { recursive: true });
207
+ }
208
+
209
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
210
+ return true;
211
+ } catch (error) {
212
+ console.error("Failed to save event system config:", error);
213
+ return false;
214
+ }
215
+ }
216
+
217
+ export function mergeEventSystemConfigs(
218
+ ...configs: Partial<EventSystemConfig>[]
219
+ ): EventSystemConfig {
220
+ return configs.reduce((merged, config) => {
221
+ return {
222
+ ...merged,
223
+ ...config,
224
+ manager: {
225
+ ...merged.manager,
226
+ ...config.manager,
227
+ },
228
+ registry: {
229
+ ...merged.registry,
230
+ ...config.registry,
231
+ },
232
+ defaultContext: {
233
+ ...merged.defaultContext,
234
+ ...config.defaultContext,
235
+ },
236
+ };
237
+ }, defaultEventSystemConfig);
238
+ }
@@ -0,0 +1,185 @@
1
+ import {
2
+ createEvent,
3
+ createEventCategory,
4
+ createEventContext,
5
+ createEventFilter,
6
+ createEventListener,
7
+ createEventManager,
8
+ createEventMiddleware,
9
+ createEventRegistry,
10
+ } from "./index";
11
+
12
+ // Create event manager and registry
13
+ const manager = createEventManager({
14
+ maxListeners: 200,
15
+ errorHandling: "log",
16
+ });
17
+
18
+ const registry = createEventRegistry({
19
+ maxEvents: 5000,
20
+ retentionPeriod: 7 * 24 * 60 * 60 * 1000, // 7 days
21
+ });
22
+
23
+ // Register event categories
24
+ const databaseCategory = createEventCategory(
25
+ "database",
26
+ "Database operations and query lifecycle",
27
+ ["query", "mutation", "connection", "transaction"],
28
+ );
29
+
30
+ const jobQueueCategory = createEventCategory(
31
+ "job-queue",
32
+ "Background job processing and queue management",
33
+ ["job.created", "job.started", "job.completed", "job.failed"],
34
+ );
35
+
36
+ manager.registerEventCategory(databaseCategory);
37
+ manager.registerEventCategory(jobQueueCategory);
38
+
39
+ // Create event context
40
+ const defaultContext = createEventContext({
41
+ userId: "user123",
42
+ sessionId: "session456",
43
+ ipAddress: "192.168.1.1",
44
+ });
45
+
46
+ // Create event middleware
47
+ const loggingMiddleware = createEventMiddleware(async (event, next) => {
48
+ console.log(`Event received: ${event.name}`);
49
+ await next();
50
+ });
51
+
52
+ const validationMiddleware = createEventMiddleware(async (event, next) => {
53
+ if (event.data && typeof event.data === "object") {
54
+ // Validate event data
55
+ if (Object.keys(event.data).length === 0) {
56
+ throw new Error("Event data cannot be empty");
57
+ }
58
+ }
59
+ await next();
60
+ });
61
+
62
+ manager.addMiddleware(loggingMiddleware);
63
+ manager.addMiddleware(validationMiddleware);
64
+
65
+ // Create event listeners
66
+ const queryListener = createEventListener(
67
+ "database.query",
68
+ async (event) => {
69
+ console.log("Query executed:", event.data.query);
70
+ // Log query to database
71
+ registry.registerEvent(event);
72
+ },
73
+ { priority: 10 },
74
+ );
75
+
76
+ const jobStartedListener = createEventListener("job.started", async (event) => {
77
+ console.log(`Job started: ${event.data.jobId}`);
78
+ // Update job status
79
+ });
80
+
81
+ const errorListener = createEventListener(
82
+ "error",
83
+ async (event) => {
84
+ console.error("Error occurred:", event.data.error);
85
+ },
86
+ { priority: 100 },
87
+ );
88
+
89
+ // Add listeners to manager
90
+ manager.addListener(queryListener);
91
+ manager.addListener(jobStartedListener);
92
+ manager.addListener(errorListener);
93
+
94
+ // Create event filters
95
+ const importantFilter = createEventFilter((event) => {
96
+ return event.data && event.data.importance === "high";
97
+ });
98
+
99
+ // Create filtered listener
100
+ const importantEventListener = createEventListener(
101
+ "important.event",
102
+ async (event) => {
103
+ console.log("Important event detected:", event.data);
104
+ // Send alert or notification
105
+ },
106
+ { filter: importantFilter },
107
+ );
108
+
109
+ manager.addListener(importantEventListener);
110
+
111
+ // Example event emission
112
+ async function exampleUsage() {
113
+ try {
114
+ // Database query event
115
+ const queryEvent = createEvent(
116
+ "database.query",
117
+ {
118
+ query: "SELECT * FROM users WHERE id = 1",
119
+ executionTime: 120,
120
+ },
121
+ { context: defaultContext },
122
+ );
123
+
124
+ await manager.emit(queryEvent);
125
+
126
+ // Job started event
127
+ const jobEvent = createEvent(
128
+ "job.started",
129
+ {
130
+ jobId: "job789",
131
+ type: "email-sender",
132
+ data: { userId: "user123" },
133
+ },
134
+ { context: defaultContext },
135
+ );
136
+
137
+ await manager.emit(jobEvent);
138
+
139
+ // Important event
140
+ const importantEvent = createEvent(
141
+ "important.event",
142
+ {
143
+ message: "System alert",
144
+ importance: "high",
145
+ details: "High memory usage detected",
146
+ },
147
+ { context: defaultContext },
148
+ );
149
+
150
+ await manager.emit(importantEvent);
151
+
152
+ // Error event
153
+ const errorEvent = createEvent(
154
+ "error",
155
+ {
156
+ error: new Error("Test error"),
157
+ source: "example-usage",
158
+ },
159
+ { context: defaultContext },
160
+ );
161
+
162
+ await manager.emit(errorEvent);
163
+
164
+ console.log("All events processed successfully!");
165
+ } catch (error) {
166
+ console.error("Error in example usage:", error);
167
+ }
168
+ }
169
+
170
+ // Run example
171
+ exampleUsage();
172
+
173
+ // Export for use in other modules
174
+ export {
175
+ manager,
176
+ registry,
177
+ defaultContext,
178
+ loggingMiddleware,
179
+ validationMiddleware,
180
+ queryListener,
181
+ jobStartedListener,
182
+ errorListener,
183
+ importantFilter,
184
+ importantEventListener,
185
+ };