@engjts/nexus 0.1.8 → 0.1.10

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 (221) hide show
  1. package/dist/advanced/playground/playground.js.map +1 -1
  2. package/dist/advanced/static/generateDirectoryListing.d.ts +1 -1
  3. package/dist/advanced/static/generateDirectoryListing.d.ts.map +1 -1
  4. package/dist/advanced/static/generateDirectoryListing.js +12 -6
  5. package/dist/advanced/static/generateDirectoryListing.js.map +1 -1
  6. package/dist/advanced/static/index.d.ts +2 -0
  7. package/dist/advanced/static/index.d.ts.map +1 -1
  8. package/dist/advanced/static/index.js +4 -1
  9. package/dist/advanced/static/index.js.map +1 -1
  10. package/dist/advanced/static/serveStatic.d.ts.map +1 -1
  11. package/dist/advanced/static/serveStatic.js +7 -1
  12. package/dist/advanced/static/serveStatic.js.map +1 -1
  13. package/dist/index.d.ts +1 -1
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +3 -1
  16. package/dist/index.js.map +1 -1
  17. package/package.json +1 -1
  18. package/BENCHMARK_REPORT.md +0 -343
  19. package/documentation/01-getting-started.md +0 -240
  20. package/documentation/02-context.md +0 -335
  21. package/documentation/03-routing.md +0 -397
  22. package/documentation/04-middleware.md +0 -483
  23. package/documentation/05-validation.md +0 -514
  24. package/documentation/06-error-handling.md +0 -465
  25. package/documentation/07-performance.md +0 -364
  26. package/documentation/08-adapters.md +0 -470
  27. package/documentation/09-api-reference.md +0 -548
  28. package/documentation/10-examples.md +0 -582
  29. package/documentation/11-deployment.md +0 -477
  30. package/documentation/12-sentry.md +0 -620
  31. package/documentation/13-sentry-data-storage.md +0 -996
  32. package/documentation/14-sentry-data-reference.md +0 -457
  33. package/documentation/15-sentry-summary.md +0 -409
  34. package/documentation/16-alerts-system.md +0 -745
  35. package/documentation/17-alert-adapters.md +0 -696
  36. package/documentation/18-alerts-implementation-summary.md +0 -385
  37. package/documentation/19-class-based-routing.md +0 -840
  38. package/documentation/20-websocket-realtime.md +0 -813
  39. package/documentation/21-cache-system.md +0 -510
  40. package/documentation/22-job-queue.md +0 -772
  41. package/documentation/23-sentry-plugin.md +0 -551
  42. package/documentation/24-testing-utilities.md +0 -1287
  43. package/documentation/25-api-versioning.md +0 -533
  44. package/documentation/26-context-store.md +0 -607
  45. package/documentation/27-dependency-injection.md +0 -329
  46. package/documentation/28-lifecycle-hooks.md +0 -521
  47. package/documentation/29-package-structure.md +0 -196
  48. package/documentation/30-plugin-system.md +0 -414
  49. package/documentation/31-jwt-authentication.md +0 -597
  50. package/documentation/32-cli.md +0 -268
  51. package/documentation/ALERTS-COMPLETE-SUMMARY.md +0 -429
  52. package/documentation/ALERTS-INDEX.md +0 -330
  53. package/documentation/ALERTS-QUICK-REFERENCE.md +0 -286
  54. package/documentation/README.md +0 -178
  55. package/documentation/index.html +0 -34
  56. package/modern_framework_paper.md +0 -1870
  57. package/public/css/style.css +0 -87
  58. package/public/index.html +0 -34
  59. package/public/js/app.js +0 -27
  60. package/src/advanced/cache/InMemoryCacheStore.ts +0 -68
  61. package/src/advanced/cache/MultiTierCache.ts +0 -194
  62. package/src/advanced/cache/RedisCacheStore.ts +0 -341
  63. package/src/advanced/cache/index.ts +0 -5
  64. package/src/advanced/cache/types.ts +0 -40
  65. package/src/advanced/graphql/SimpleDataLoader.ts +0 -42
  66. package/src/advanced/graphql/index.ts +0 -22
  67. package/src/advanced/graphql/server.ts +0 -252
  68. package/src/advanced/graphql/types.ts +0 -42
  69. package/src/advanced/jobs/InMemoryQueueStore.ts +0 -68
  70. package/src/advanced/jobs/JobQueue.ts +0 -556
  71. package/src/advanced/jobs/RedisQueueStore.ts +0 -367
  72. package/src/advanced/jobs/index.ts +0 -5
  73. package/src/advanced/jobs/types.ts +0 -70
  74. package/src/advanced/observability/APMManager.ts +0 -163
  75. package/src/advanced/observability/AlertManager.ts +0 -109
  76. package/src/advanced/observability/MetricRegistry.ts +0 -151
  77. package/src/advanced/observability/ObservabilityCenter.ts +0 -304
  78. package/src/advanced/observability/StructuredLogger.ts +0 -154
  79. package/src/advanced/observability/TracingManager.ts +0 -117
  80. package/src/advanced/observability/adapters.ts +0 -304
  81. package/src/advanced/observability/createObservabilityMiddleware.ts +0 -63
  82. package/src/advanced/observability/index.ts +0 -11
  83. package/src/advanced/observability/types.ts +0 -174
  84. package/src/advanced/playground/extractPathParams.ts +0 -6
  85. package/src/advanced/playground/generateFieldExample.ts +0 -31
  86. package/src/advanced/playground/generatePlaygroundHTML.ts +0 -1956
  87. package/src/advanced/playground/generateSummary.ts +0 -19
  88. package/src/advanced/playground/getTagFromPath.ts +0 -9
  89. package/src/advanced/playground/index.ts +0 -8
  90. package/src/advanced/playground/playground.ts +0 -250
  91. package/src/advanced/playground/types.ts +0 -49
  92. package/src/advanced/playground/zodToExample.ts +0 -16
  93. package/src/advanced/playground/zodToParams.ts +0 -15
  94. package/src/advanced/postman/buildAuth.ts +0 -31
  95. package/src/advanced/postman/buildBody.ts +0 -15
  96. package/src/advanced/postman/buildQueryParams.ts +0 -27
  97. package/src/advanced/postman/buildRequestItem.ts +0 -36
  98. package/src/advanced/postman/buildResponses.ts +0 -11
  99. package/src/advanced/postman/buildUrl.ts +0 -33
  100. package/src/advanced/postman/capitalize.ts +0 -4
  101. package/src/advanced/postman/generateCollection.ts +0 -59
  102. package/src/advanced/postman/generateEnvironment.ts +0 -34
  103. package/src/advanced/postman/generateExampleFromZod.ts +0 -21
  104. package/src/advanced/postman/generateFieldExample.ts +0 -45
  105. package/src/advanced/postman/generateName.ts +0 -20
  106. package/src/advanced/postman/generateUUID.ts +0 -11
  107. package/src/advanced/postman/getTagFromPath.ts +0 -10
  108. package/src/advanced/postman/index.ts +0 -28
  109. package/src/advanced/postman/postman.ts +0 -156
  110. package/src/advanced/postman/slugify.ts +0 -7
  111. package/src/advanced/postman/types.ts +0 -140
  112. package/src/advanced/realtime/index.ts +0 -18
  113. package/src/advanced/realtime/websocket.ts +0 -231
  114. package/src/advanced/sentry/index.ts +0 -1236
  115. package/src/advanced/sentry/types.ts +0 -355
  116. package/src/advanced/static/generateDirectoryListing.ts +0 -47
  117. package/src/advanced/static/generateETag.ts +0 -7
  118. package/src/advanced/static/getMimeType.ts +0 -9
  119. package/src/advanced/static/index.ts +0 -32
  120. package/src/advanced/static/isSafePath.ts +0 -13
  121. package/src/advanced/static/publicDir.ts +0 -21
  122. package/src/advanced/static/serveStatic.ts +0 -225
  123. package/src/advanced/static/spa.ts +0 -24
  124. package/src/advanced/static/types.ts +0 -159
  125. package/src/advanced/swagger/SwaggerGenerator.ts +0 -66
  126. package/src/advanced/swagger/buildOperation.ts +0 -61
  127. package/src/advanced/swagger/buildParameters.ts +0 -61
  128. package/src/advanced/swagger/buildRequestBody.ts +0 -21
  129. package/src/advanced/swagger/buildResponses.ts +0 -54
  130. package/src/advanced/swagger/capitalize.ts +0 -5
  131. package/src/advanced/swagger/convertPath.ts +0 -9
  132. package/src/advanced/swagger/createSwagger.ts +0 -12
  133. package/src/advanced/swagger/generateOperationId.ts +0 -21
  134. package/src/advanced/swagger/generateSpec.ts +0 -105
  135. package/src/advanced/swagger/generateSummary.ts +0 -24
  136. package/src/advanced/swagger/generateSwaggerUI.ts +0 -70
  137. package/src/advanced/swagger/generateThemeCss.ts +0 -53
  138. package/src/advanced/swagger/index.ts +0 -25
  139. package/src/advanced/swagger/swagger.ts +0 -237
  140. package/src/advanced/swagger/types.ts +0 -206
  141. package/src/advanced/swagger/zodFieldToOpenAPI.ts +0 -94
  142. package/src/advanced/swagger/zodSchemaToOpenAPI.ts +0 -50
  143. package/src/advanced/swagger/zodToOpenAPI.ts +0 -22
  144. package/src/advanced/testing/factory.ts +0 -509
  145. package/src/advanced/testing/harness.ts +0 -612
  146. package/src/advanced/testing/index.ts +0 -430
  147. package/src/advanced/testing/load-test.ts +0 -618
  148. package/src/advanced/testing/mock-server.ts +0 -498
  149. package/src/advanced/testing/mock.ts +0 -670
  150. package/src/cli/bin.ts +0 -9
  151. package/src/cli/cli.ts +0 -158
  152. package/src/cli/commands/add.ts +0 -178
  153. package/src/cli/commands/build.ts +0 -73
  154. package/src/cli/commands/create.ts +0 -166
  155. package/src/cli/commands/dev.ts +0 -85
  156. package/src/cli/commands/generate.ts +0 -99
  157. package/src/cli/commands/help.ts +0 -95
  158. package/src/cli/commands/init.ts +0 -91
  159. package/src/cli/commands/version.ts +0 -38
  160. package/src/cli/index.ts +0 -6
  161. package/src/cli/templates/generators.ts +0 -359
  162. package/src/cli/templates/index.ts +0 -680
  163. package/src/cli/utils/exec.ts +0 -52
  164. package/src/cli/utils/file-system.ts +0 -78
  165. package/src/cli/utils/logger.ts +0 -111
  166. package/src/core/adapter.ts +0 -88
  167. package/src/core/application.ts +0 -1453
  168. package/src/core/context-pool.ts +0 -79
  169. package/src/core/context.ts +0 -856
  170. package/src/core/index.ts +0 -94
  171. package/src/core/middleware.ts +0 -272
  172. package/src/core/performance/buffer-pool.ts +0 -108
  173. package/src/core/performance/middleware-optimizer.ts +0 -162
  174. package/src/core/plugin/PluginManager.ts +0 -435
  175. package/src/core/plugin/builder.ts +0 -358
  176. package/src/core/plugin/index.ts +0 -50
  177. package/src/core/plugin/types.ts +0 -214
  178. package/src/core/router/file-router.ts +0 -623
  179. package/src/core/router/index.ts +0 -260
  180. package/src/core/router/radix-tree.ts +0 -242
  181. package/src/core/serializer.ts +0 -397
  182. package/src/core/store/index.ts +0 -30
  183. package/src/core/store/registry.ts +0 -178
  184. package/src/core/store/request-store.ts +0 -240
  185. package/src/core/store/types.ts +0 -233
  186. package/src/core/types.ts +0 -616
  187. package/src/database/adapter.ts +0 -35
  188. package/src/database/adapters/index.ts +0 -1
  189. package/src/database/adapters/mysql.ts +0 -669
  190. package/src/database/database.ts +0 -70
  191. package/src/database/dialect.ts +0 -388
  192. package/src/database/index.ts +0 -12
  193. package/src/database/migrations.ts +0 -86
  194. package/src/database/optimizer.ts +0 -125
  195. package/src/database/query-builder.ts +0 -404
  196. package/src/database/realtime.ts +0 -53
  197. package/src/database/schema.ts +0 -71
  198. package/src/database/transactions.ts +0 -56
  199. package/src/database/types.ts +0 -87
  200. package/src/deployment/cluster.ts +0 -471
  201. package/src/deployment/config.ts +0 -454
  202. package/src/deployment/docker.ts +0 -599
  203. package/src/deployment/graceful-shutdown.ts +0 -373
  204. package/src/deployment/index.ts +0 -56
  205. package/src/index.ts +0 -281
  206. package/src/security/adapter.ts +0 -318
  207. package/src/security/auth/JWTPlugin.ts +0 -234
  208. package/src/security/auth/JWTProvider.ts +0 -316
  209. package/src/security/auth/adapter.ts +0 -12
  210. package/src/security/auth/jwt.ts +0 -234
  211. package/src/security/auth/middleware.ts +0 -188
  212. package/src/security/csrf.ts +0 -220
  213. package/src/security/headers.ts +0 -108
  214. package/src/security/index.ts +0 -60
  215. package/src/security/rate-limit/adapter.ts +0 -7
  216. package/src/security/rate-limit/memory.ts +0 -108
  217. package/src/security/rate-limit/middleware.ts +0 -181
  218. package/src/security/sanitization.ts +0 -75
  219. package/src/security/types.ts +0 -240
  220. package/src/security/utils.ts +0 -52
  221. package/tsconfig.json +0 -39
@@ -1,367 +0,0 @@
1
- import { QueueStore, Job, JobState, QueueStats } from './types';
2
-
3
- /**
4
- * Redis queue store configuration
5
- */
6
- export interface RedisQueueConfig {
7
- /**
8
- * Redis connection URL
9
- * @example 'redis://localhost:6379'
10
- */
11
- url?: string;
12
-
13
- /**
14
- * Redis host
15
- * @default 'localhost'
16
- */
17
- host?: string;
18
-
19
- /**
20
- * Redis port
21
- * @default 6379
22
- */
23
- port?: number;
24
-
25
- /**
26
- * Redis password
27
- */
28
- password?: string;
29
-
30
- /**
31
- * Redis database number
32
- * @default 0
33
- */
34
- db?: number;
35
-
36
- /**
37
- * Key prefix for queue data
38
- * @default 'nexus:queue:'
39
- */
40
- prefix?: string;
41
-
42
- /**
43
- * Poll interval for delayed jobs in milliseconds
44
- * @default 1000
45
- */
46
- pollInterval?: number;
47
- }
48
-
49
- /**
50
- * Redis client interface (compatible with ioredis and node-redis)
51
- */
52
- export interface RedisClientLike {
53
- get(key: string): Promise<string | null>;
54
- set(key: string, value: string): Promise<any>;
55
- del(key: string | string[]): Promise<number>;
56
- keys(pattern: string): Promise<string[]>;
57
- lpush(key: string, ...values: string[]): Promise<number>;
58
- rpop(key: string): Promise<string | null>;
59
- lrange(key: string, start: number, stop: number): Promise<string[]>;
60
- lrem(key: string, count: number, value: string): Promise<number>;
61
- zadd(key: string, ...args: (string | number)[]): Promise<number>;
62
- zrangebyscore(key: string, min: number | string, max: number | string): Promise<string[]>;
63
- zrem(key: string, ...members: string[]): Promise<number>;
64
- hset(key: string, field: string, value: string): Promise<number>;
65
- hget(key: string, field: string): Promise<string | null>;
66
- hgetall(key: string): Promise<Record<string, string>>;
67
- hdel(key: string, ...fields: string[]): Promise<number>;
68
- incr(key: string): Promise<number>;
69
- expire(key: string, seconds: number): Promise<number>;
70
- quit?(): Promise<any>;
71
- disconnect?(): Promise<any>;
72
- }
73
-
74
- /**
75
- * Redis-based queue store implementation
76
- * Provides persistent job storage with support for distributed workers
77
- *
78
- * @example
79
- * ```typescript
80
- * import Redis from 'ioredis';
81
- * import { JobQueue, RedisQueueStore } from 'nexus';
82
- *
83
- * const redis = new Redis();
84
- * const store = new RedisQueueStore('emails', { client: redis });
85
- * const queue = new JobQueue('emails', { store });
86
- *
87
- * // Add a job
88
- * await queue.add('sendEmail', { to: 'user@example.com', subject: 'Hello' });
89
- *
90
- * // Process jobs
91
- * queue.process('sendEmail', async (job) => {
92
- * await sendEmail(job.data);
93
- * return { sent: true };
94
- * });
95
- * ```
96
- */
97
- export class RedisQueueStore<Data = any> implements QueueStore<Data> {
98
- private client: RedisClientLike;
99
- private prefix: string;
100
- private queueName: string;
101
- private pollInterval: number;
102
- private pollTimer?: NodeJS.Timeout;
103
-
104
- constructor(
105
- queueName: string,
106
- options: RedisQueueConfig & { client: RedisClientLike }
107
- ) {
108
- this.queueName = queueName;
109
- this.client = options.client;
110
- this.prefix = options.prefix ?? 'nexus:queue:';
111
- this.pollInterval = options.pollInterval ?? 1000;
112
- }
113
-
114
- /**
115
- * Build Redis key with prefix
116
- */
117
- private key(type: string): string {
118
- return `${this.prefix}${this.queueName}:${type}`;
119
- }
120
-
121
- /**
122
- * Serialize job to JSON
123
- */
124
- private serialize(job: Job<Data>): string {
125
- return JSON.stringify(job);
126
- }
127
-
128
- /**
129
- * Deserialize job from JSON
130
- */
131
- private deserialize(data: string): Job<Data> {
132
- return JSON.parse(data);
133
- }
134
-
135
- /**
136
- * Add a job to the queue
137
- */
138
- async enqueue(job: Job<Data>): Promise<void> {
139
- const serialized = this.serialize(job);
140
-
141
- // Store job data in hash
142
- await this.client.hset(this.key('jobs'), job.id, serialized);
143
-
144
- if (job.state === 'delayed') {
145
- // Add to delayed set with score = runAt timestamp
146
- await this.client.zadd(this.key('delayed'), job.runAt, job.id);
147
- } else if (job.state === 'waiting') {
148
- // Add to waiting list (with priority handling)
149
- await this.client.lpush(this.key(`waiting:${job.priority}`), job.id);
150
- }
151
-
152
- // Increment total counter
153
- await this.client.incr(this.key('total'));
154
- }
155
-
156
- /**
157
- * Get the next job to process
158
- */
159
- async dequeue(): Promise<Job<Data> | undefined> {
160
- // First, check delayed jobs that are now ready
161
- const now = Date.now();
162
- const readyDelayed = await this.client.zrangebyscore(
163
- this.key('delayed'),
164
- '-inf',
165
- now
166
- );
167
-
168
- // Move ready delayed jobs to waiting
169
- for (const jobId of readyDelayed) {
170
- const jobData = await this.client.hget(this.key('jobs'), jobId);
171
- if (jobData) {
172
- const job = this.deserialize(jobData);
173
- job.state = 'waiting';
174
- await this.client.hset(this.key('jobs'), jobId, this.serialize(job));
175
- await this.client.zrem(this.key('delayed'), jobId);
176
- await this.client.lpush(this.key(`waiting:${job.priority}`), jobId);
177
- }
178
- }
179
-
180
- // Check priority queues (high to low: 10, 5, 0, -5, -10, etc.)
181
- const priorities = [10, 5, 0, -5, -10];
182
-
183
- for (const priority of priorities) {
184
- const jobId = await this.client.rpop(this.key(`waiting:${priority}`));
185
- if (jobId) {
186
- const jobData = await this.client.hget(this.key('jobs'), jobId);
187
- if (jobData) {
188
- const job = this.deserialize(jobData);
189
- job.state = 'active';
190
- job.updatedAt = Date.now();
191
- await this.client.hset(this.key('jobs'), jobId, this.serialize(job));
192
- return job;
193
- }
194
- }
195
- }
196
-
197
- // Fallback: check default priority (0)
198
- const jobId = await this.client.rpop(this.key('waiting:0'));
199
- if (jobId) {
200
- const jobData = await this.client.hget(this.key('jobs'), jobId);
201
- if (jobData) {
202
- const job = this.deserialize(jobData);
203
- job.state = 'active';
204
- job.updatedAt = Date.now();
205
- await this.client.hset(this.key('jobs'), jobId, this.serialize(job));
206
- return job;
207
- }
208
- }
209
-
210
- return undefined;
211
- }
212
-
213
- /**
214
- * Update job state
215
- */
216
- async update(job: Job<Data>): Promise<void> {
217
- const serialized = this.serialize(job);
218
- await this.client.hset(this.key('jobs'), job.id, serialized);
219
-
220
- // Handle state-specific storage
221
- if (job.state === 'delayed') {
222
- await this.client.zadd(this.key('delayed'), job.runAt, job.id);
223
- } else if (job.state === 'waiting') {
224
- await this.client.lpush(this.key(`waiting:${job.priority}`), job.id);
225
- } else if (job.state === 'completed') {
226
- await this.client.lpush(this.key('completed'), job.id);
227
- // Set expiry for completed jobs (24 hours)
228
- await this.client.expire(this.key('completed'), 86400);
229
- } else if (job.state === 'failed') {
230
- await this.client.lpush(this.key('failed'), job.id);
231
- }
232
- }
233
-
234
- /**
235
- * Get a job by ID
236
- */
237
- async get(id: string): Promise<Job<Data> | undefined> {
238
- const data = await this.client.hget(this.key('jobs'), id);
239
- if (!data) return undefined;
240
- return this.deserialize(data);
241
- }
242
-
243
- /**
244
- * List jobs by state
245
- */
246
- async list(state?: JobState): Promise<Job<Data>[]> {
247
- const allJobs = await this.client.hgetall(this.key('jobs'));
248
- const jobs = Object.values(allJobs).map(data => this.deserialize(data));
249
-
250
- if (!state) {
251
- return jobs;
252
- }
253
-
254
- return jobs.filter(job => job.state === state);
255
- }
256
-
257
- /**
258
- * Get queue statistics
259
- */
260
- async stats(): Promise<QueueStats> {
261
- const allJobs = await this.client.hgetall(this.key('jobs'));
262
- const stats: QueueStats = {
263
- waiting: 0,
264
- active: 0,
265
- completed: 0,
266
- failed: 0,
267
- delayed: 0
268
- };
269
-
270
- for (const data of Object.values(allJobs)) {
271
- const job = this.deserialize(data);
272
- if (job.state in stats) {
273
- (stats as any)[job.state]++;
274
- }
275
- }
276
-
277
- return stats;
278
- }
279
-
280
- /**
281
- * Clean old completed/failed jobs
282
- */
283
- async clean(state: 'completed' | 'failed', olderThanMs: number = 86400000): Promise<number> {
284
- const cutoff = Date.now() - olderThanMs;
285
- const jobs = await this.list(state);
286
- let cleaned = 0;
287
-
288
- for (const job of jobs) {
289
- if (job.updatedAt < cutoff) {
290
- await this.client.hdel(this.key('jobs'), job.id);
291
- await this.client.lrem(this.key(state), 0, job.id);
292
- cleaned++;
293
- }
294
- }
295
-
296
- return cleaned;
297
- }
298
-
299
- /**
300
- * Disconnect from Redis
301
- */
302
- async disconnect(): Promise<void> {
303
- if (this.pollTimer) {
304
- clearInterval(this.pollTimer);
305
- }
306
- if (this.client.quit) {
307
- await this.client.quit();
308
- } else if (this.client.disconnect) {
309
- await this.client.disconnect();
310
- }
311
- }
312
- }
313
-
314
- /**
315
- * Create a Redis queue store with automatic client creation
316
- * Requires 'ioredis' or 'redis' package to be installed
317
- *
318
- * @example
319
- * ```typescript
320
- * const store = await createRedisQueueStore('emails', {
321
- * host: 'localhost',
322
- * port: 6379
323
- * });
324
- *
325
- * const queue = new JobQueue('emails', { store });
326
- * ```
327
- */
328
- export async function createRedisQueueStore<Data = any>(
329
- queueName: string,
330
- config: RedisQueueConfig = {}
331
- ): Promise<RedisQueueStore<Data>> {
332
- let client: RedisClientLike;
333
-
334
- // Try ioredis first
335
- try {
336
- const Redis = require('ioredis');
337
- client = new Redis({
338
- host: config.host ?? 'localhost',
339
- port: config.port ?? 6379,
340
- password: config.password,
341
- db: config.db ?? 0
342
- });
343
- } catch {
344
- // Try node-redis
345
- try {
346
- const { createClient } = require('redis');
347
- const url = config.url ?? `redis://${config.host ?? 'localhost'}:${config.port ?? 6379}`;
348
-
349
- client = createClient({
350
- url,
351
- password: config.password,
352
- database: config.db ?? 0
353
- });
354
-
355
- await (client as any).connect();
356
- } catch {
357
- throw new Error(
358
- 'Redis client not found. Please install either "ioredis" or "redis" package:\n' +
359
- ' npm install ioredis\n' +
360
- ' # or\n' +
361
- ' npm install redis'
362
- );
363
- }
364
- }
365
-
366
- return new RedisQueueStore<Data>(queueName, { ...config, client });
367
- }
@@ -1,5 +0,0 @@
1
- export { JobQueue, CronSchedule, ScheduledJobConfig } from './JobQueue';
2
- export { InMemoryQueueStore } from './InMemoryQueueStore';
3
- export { RedisQueueStore, createRedisQueueStore } from './RedisQueueStore';
4
- export type { RedisQueueConfig, RedisClientLike } from './RedisQueueStore';
5
- export * from './types';
@@ -1,70 +0,0 @@
1
- export type JobState = 'waiting' | 'delayed' | 'active' | 'completed' | 'failed' | 'paused';
2
-
3
-
4
- export interface Job<Data = any, Result = any> {
5
- id: string;
6
- name: string;
7
- data: Data;
8
- result?: Result;
9
- error?: { message: string; stack?: string };
10
- state: JobState;
11
- attemptsMade: number;
12
- maxAttempts: number;
13
- priority: number;
14
- createdAt: number;
15
- runAt: number;
16
- updatedAt: number;
17
- metadata?: Record<string, any>;
18
- }
19
-
20
- export interface RetryOptions {
21
- attempts?: number;
22
- backoff?: 'fixed' | 'exponential';
23
- delay?: number;
24
- maxDelay?: number;
25
- }
26
-
27
- export interface RateLimitOptions {
28
- max: number;
29
- duration: number;
30
- }
31
-
32
- export interface QueueHooks<Data = any> {
33
- onComplete?: (job: Job<Data>, result: any) => void | Promise<void>;
34
- onFailed?: (job: Job<Data>, error: Error) => void | Promise<void>;
35
- onRetry?: (job: Job<Data>, attempt: number, delay: number) => void | Promise<void>;
36
- }
37
-
38
- export interface QueueOptions<Data = any> {
39
- concurrency?: number;
40
- retry?: RetryOptions;
41
- limiter?: RateLimitOptions;
42
- hooks?: QueueHooks<Data>;
43
- store?: QueueStore<Data>;
44
- }
45
-
46
- export interface EnqueueOptions {
47
- delay?: number;
48
- priority?: number;
49
- metadata?: Record<string, any>;
50
- attempts?: number;
51
- }
52
-
53
- export type JobHandler<Data = any, Result = any> = (job: Job<Data>) => Promise<Result>;
54
-
55
- export interface QueueStore<Data = any> {
56
- enqueue(job: Job<Data>): Promise<void>;
57
- dequeue(): Promise<Job<Data> | undefined>;
58
- update(job: Job<Data>): Promise<void>;
59
- get(id: string): Promise<Job<Data> | undefined>;
60
- list(state?: JobState): Promise<Job<Data>[]>;
61
- stats(): Promise<QueueStats>;
62
- }
63
-
64
- export interface QueueStats {
65
- waiting: number;
66
- active: number;
67
- completed: number;
68
- failed: number;
69
- delayed: number;
70
- }
@@ -1,163 +0,0 @@
1
- import { APMOptions } from './types';
2
- import { getSentry, SentryClient } from '../sentry';
3
-
4
- /**
5
- * APM (Application Performance Monitoring) manager
6
- *
7
- * This is a lightweight wrapper that delegates to Sentry when available.
8
- * For full APM features (memory leak detection, slow query tracking),
9
- * use Sentry integration which has built-in APM support.
10
- *
11
- * @example
12
- * ```typescript
13
- * // Recommended: Use Sentry with APM
14
- * import { initSentry } from 'nexus';
15
- *
16
- * initSentry({
17
- * dsn: 'your-dsn',
18
- * apm: {
19
- * slowQueryThreshold: 500,
20
- * memoryLeakDetection: { enabled: true }
21
- * }
22
- * });
23
- *
24
- * // Then use APMManager as facade
25
- * const apm = new APMManager();
26
- * apm.recordQuery('SELECT * FROM users', 1200);
27
- * ```
28
- */
29
- export class APMManager {
30
- private options: APMOptions;
31
- private sentryClient?: SentryClient | null;
32
-
33
- // Fallback storage when Sentry is not available
34
- private slowQueries: Array<{ query: string; duration: number; timestamp: number; }> = [];
35
- private memorySnapshots: Array<{ timestamp: number; heapUsed: number; heapTotal: number; }> = [];
36
- private memoryCheckInterval?: NodeJS.Timeout;
37
-
38
- constructor(options: APMOptions = {}) {
39
- this.options = options;
40
- this.sentryClient = getSentry();
41
-
42
- // If Sentry is not available and memory leak detection is enabled, use fallback
43
- if (!this.sentryClient && options.memoryLeakDetection?.enabled) {
44
- this.startMemoryMonitoring();
45
- }
46
- }
47
-
48
- /**
49
- * Record a database/external query
50
- * Delegates to Sentry when available
51
- */
52
- recordQuery(query: string, durationMs: number, metadata?: Record<string, any>) {
53
- // Delegate to Sentry if available
54
- if (this.sentryClient) {
55
- this.sentryClient.recordQuery(query, durationMs, metadata);
56
- return;
57
- }
58
-
59
- // Fallback: store locally
60
- const threshold = this.options.slowQueryThreshold ?? 1000;
61
- if (durationMs >= threshold) {
62
- this.slowQueries.push({
63
- query,
64
- duration: durationMs,
65
- timestamp: Date.now()
66
- });
67
-
68
- // Keep last 100 slow queries
69
- if (this.slowQueries.length > 100) {
70
- this.slowQueries.shift();
71
- }
72
- }
73
- }
74
-
75
- /**
76
- * Get slow queries
77
- * Delegates to Sentry when available
78
- */
79
- getSlowQueries() {
80
- if (this.sentryClient) {
81
- return this.sentryClient.getSlowQueries();
82
- }
83
- return [...this.slowQueries];
84
- }
85
-
86
- private startMemoryMonitoring() {
87
- const interval = this.options.memoryLeakDetection?.interval ?? 60000;
88
-
89
- this.memoryCheckInterval = setInterval(() => {
90
- const usage = process.memoryUsage();
91
- this.memorySnapshots.push({
92
- timestamp: Date.now(),
93
- heapUsed: usage.heapUsed,
94
- heapTotal: usage.heapTotal
95
- });
96
-
97
- // Keep last 60 snapshots
98
- if (this.memorySnapshots.length > 60) {
99
- this.memorySnapshots.shift();
100
- }
101
-
102
- // Check for potential memory leak
103
- this.checkMemoryLeak();
104
- }, interval);
105
- }
106
-
107
- private checkMemoryLeak() {
108
- if (this.memorySnapshots.length < 10) return;
109
-
110
- const recent = this.memorySnapshots.slice(-10);
111
- const oldest = recent[0].heapUsed;
112
- const newest = recent[recent.length - 1].heapUsed;
113
- const growth = (newest - oldest) / oldest;
114
-
115
- // Parse threshold
116
- let threshold = 0.5;
117
- const thresholdConfig = this.options.memoryLeakDetection?.threshold;
118
- if (typeof thresholdConfig === 'string') {
119
- threshold = parseFloat(thresholdConfig.replace('%', '')) / 100;
120
- } else if (typeof thresholdConfig === 'number') {
121
- threshold = thresholdConfig;
122
- }
123
-
124
- // Alert if memory grew more than threshold in the monitoring window
125
- if (growth > threshold) {
126
- console.warn('[APM] Potential memory leak detected:', {
127
- growth: `${(growth * 100).toFixed(1)}%`,
128
- from: `${(oldest / 1024 / 1024).toFixed(1)}MB`,
129
- to: `${(newest / 1024 / 1024).toFixed(1)}MB`
130
- });
131
- }
132
- }
133
-
134
- /**
135
- * Get memory statistics
136
- * Delegates to Sentry when available
137
- */
138
- getMemoryStats() {
139
- if (this.sentryClient) {
140
- return this.sentryClient.getMemoryStats();
141
- }
142
-
143
- const current = process.memoryUsage();
144
- return {
145
- current: {
146
- heapUsed: current.heapUsed,
147
- heapTotal: current.heapTotal,
148
- external: current.external,
149
- rss: current.rss
150
- },
151
- history: this.memorySnapshots
152
- };
153
- }
154
-
155
- /**
156
- * Stop APM monitoring
157
- */
158
- stop() {
159
- if (this.memoryCheckInterval) {
160
- clearInterval(this.memoryCheckInterval);
161
- }
162
- }
163
- }