@engjts/nexus 0.1.8 → 0.1.9

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 (205) hide show
  1. package/package.json +1 -1
  2. package/BENCHMARK_REPORT.md +0 -343
  3. package/documentation/01-getting-started.md +0 -240
  4. package/documentation/02-context.md +0 -335
  5. package/documentation/03-routing.md +0 -397
  6. package/documentation/04-middleware.md +0 -483
  7. package/documentation/05-validation.md +0 -514
  8. package/documentation/06-error-handling.md +0 -465
  9. package/documentation/07-performance.md +0 -364
  10. package/documentation/08-adapters.md +0 -470
  11. package/documentation/09-api-reference.md +0 -548
  12. package/documentation/10-examples.md +0 -582
  13. package/documentation/11-deployment.md +0 -477
  14. package/documentation/12-sentry.md +0 -620
  15. package/documentation/13-sentry-data-storage.md +0 -996
  16. package/documentation/14-sentry-data-reference.md +0 -457
  17. package/documentation/15-sentry-summary.md +0 -409
  18. package/documentation/16-alerts-system.md +0 -745
  19. package/documentation/17-alert-adapters.md +0 -696
  20. package/documentation/18-alerts-implementation-summary.md +0 -385
  21. package/documentation/19-class-based-routing.md +0 -840
  22. package/documentation/20-websocket-realtime.md +0 -813
  23. package/documentation/21-cache-system.md +0 -510
  24. package/documentation/22-job-queue.md +0 -772
  25. package/documentation/23-sentry-plugin.md +0 -551
  26. package/documentation/24-testing-utilities.md +0 -1287
  27. package/documentation/25-api-versioning.md +0 -533
  28. package/documentation/26-context-store.md +0 -607
  29. package/documentation/27-dependency-injection.md +0 -329
  30. package/documentation/28-lifecycle-hooks.md +0 -521
  31. package/documentation/29-package-structure.md +0 -196
  32. package/documentation/30-plugin-system.md +0 -414
  33. package/documentation/31-jwt-authentication.md +0 -597
  34. package/documentation/32-cli.md +0 -268
  35. package/documentation/ALERTS-COMPLETE-SUMMARY.md +0 -429
  36. package/documentation/ALERTS-INDEX.md +0 -330
  37. package/documentation/ALERTS-QUICK-REFERENCE.md +0 -286
  38. package/documentation/README.md +0 -178
  39. package/documentation/index.html +0 -34
  40. package/modern_framework_paper.md +0 -1870
  41. package/public/css/style.css +0 -87
  42. package/public/index.html +0 -34
  43. package/public/js/app.js +0 -27
  44. package/src/advanced/cache/InMemoryCacheStore.ts +0 -68
  45. package/src/advanced/cache/MultiTierCache.ts +0 -194
  46. package/src/advanced/cache/RedisCacheStore.ts +0 -341
  47. package/src/advanced/cache/index.ts +0 -5
  48. package/src/advanced/cache/types.ts +0 -40
  49. package/src/advanced/graphql/SimpleDataLoader.ts +0 -42
  50. package/src/advanced/graphql/index.ts +0 -22
  51. package/src/advanced/graphql/server.ts +0 -252
  52. package/src/advanced/graphql/types.ts +0 -42
  53. package/src/advanced/jobs/InMemoryQueueStore.ts +0 -68
  54. package/src/advanced/jobs/JobQueue.ts +0 -556
  55. package/src/advanced/jobs/RedisQueueStore.ts +0 -367
  56. package/src/advanced/jobs/index.ts +0 -5
  57. package/src/advanced/jobs/types.ts +0 -70
  58. package/src/advanced/observability/APMManager.ts +0 -163
  59. package/src/advanced/observability/AlertManager.ts +0 -109
  60. package/src/advanced/observability/MetricRegistry.ts +0 -151
  61. package/src/advanced/observability/ObservabilityCenter.ts +0 -304
  62. package/src/advanced/observability/StructuredLogger.ts +0 -154
  63. package/src/advanced/observability/TracingManager.ts +0 -117
  64. package/src/advanced/observability/adapters.ts +0 -304
  65. package/src/advanced/observability/createObservabilityMiddleware.ts +0 -63
  66. package/src/advanced/observability/index.ts +0 -11
  67. package/src/advanced/observability/types.ts +0 -174
  68. package/src/advanced/playground/extractPathParams.ts +0 -6
  69. package/src/advanced/playground/generateFieldExample.ts +0 -31
  70. package/src/advanced/playground/generatePlaygroundHTML.ts +0 -1956
  71. package/src/advanced/playground/generateSummary.ts +0 -19
  72. package/src/advanced/playground/getTagFromPath.ts +0 -9
  73. package/src/advanced/playground/index.ts +0 -8
  74. package/src/advanced/playground/playground.ts +0 -250
  75. package/src/advanced/playground/types.ts +0 -49
  76. package/src/advanced/playground/zodToExample.ts +0 -16
  77. package/src/advanced/playground/zodToParams.ts +0 -15
  78. package/src/advanced/postman/buildAuth.ts +0 -31
  79. package/src/advanced/postman/buildBody.ts +0 -15
  80. package/src/advanced/postman/buildQueryParams.ts +0 -27
  81. package/src/advanced/postman/buildRequestItem.ts +0 -36
  82. package/src/advanced/postman/buildResponses.ts +0 -11
  83. package/src/advanced/postman/buildUrl.ts +0 -33
  84. package/src/advanced/postman/capitalize.ts +0 -4
  85. package/src/advanced/postman/generateCollection.ts +0 -59
  86. package/src/advanced/postman/generateEnvironment.ts +0 -34
  87. package/src/advanced/postman/generateExampleFromZod.ts +0 -21
  88. package/src/advanced/postman/generateFieldExample.ts +0 -45
  89. package/src/advanced/postman/generateName.ts +0 -20
  90. package/src/advanced/postman/generateUUID.ts +0 -11
  91. package/src/advanced/postman/getTagFromPath.ts +0 -10
  92. package/src/advanced/postman/index.ts +0 -28
  93. package/src/advanced/postman/postman.ts +0 -156
  94. package/src/advanced/postman/slugify.ts +0 -7
  95. package/src/advanced/postman/types.ts +0 -140
  96. package/src/advanced/realtime/index.ts +0 -18
  97. package/src/advanced/realtime/websocket.ts +0 -231
  98. package/src/advanced/sentry/index.ts +0 -1236
  99. package/src/advanced/sentry/types.ts +0 -355
  100. package/src/advanced/static/generateDirectoryListing.ts +0 -47
  101. package/src/advanced/static/generateETag.ts +0 -7
  102. package/src/advanced/static/getMimeType.ts +0 -9
  103. package/src/advanced/static/index.ts +0 -32
  104. package/src/advanced/static/isSafePath.ts +0 -13
  105. package/src/advanced/static/publicDir.ts +0 -21
  106. package/src/advanced/static/serveStatic.ts +0 -225
  107. package/src/advanced/static/spa.ts +0 -24
  108. package/src/advanced/static/types.ts +0 -159
  109. package/src/advanced/swagger/SwaggerGenerator.ts +0 -66
  110. package/src/advanced/swagger/buildOperation.ts +0 -61
  111. package/src/advanced/swagger/buildParameters.ts +0 -61
  112. package/src/advanced/swagger/buildRequestBody.ts +0 -21
  113. package/src/advanced/swagger/buildResponses.ts +0 -54
  114. package/src/advanced/swagger/capitalize.ts +0 -5
  115. package/src/advanced/swagger/convertPath.ts +0 -9
  116. package/src/advanced/swagger/createSwagger.ts +0 -12
  117. package/src/advanced/swagger/generateOperationId.ts +0 -21
  118. package/src/advanced/swagger/generateSpec.ts +0 -105
  119. package/src/advanced/swagger/generateSummary.ts +0 -24
  120. package/src/advanced/swagger/generateSwaggerUI.ts +0 -70
  121. package/src/advanced/swagger/generateThemeCss.ts +0 -53
  122. package/src/advanced/swagger/index.ts +0 -25
  123. package/src/advanced/swagger/swagger.ts +0 -237
  124. package/src/advanced/swagger/types.ts +0 -206
  125. package/src/advanced/swagger/zodFieldToOpenAPI.ts +0 -94
  126. package/src/advanced/swagger/zodSchemaToOpenAPI.ts +0 -50
  127. package/src/advanced/swagger/zodToOpenAPI.ts +0 -22
  128. package/src/advanced/testing/factory.ts +0 -509
  129. package/src/advanced/testing/harness.ts +0 -612
  130. package/src/advanced/testing/index.ts +0 -430
  131. package/src/advanced/testing/load-test.ts +0 -618
  132. package/src/advanced/testing/mock-server.ts +0 -498
  133. package/src/advanced/testing/mock.ts +0 -670
  134. package/src/cli/bin.ts +0 -9
  135. package/src/cli/cli.ts +0 -158
  136. package/src/cli/commands/add.ts +0 -178
  137. package/src/cli/commands/build.ts +0 -73
  138. package/src/cli/commands/create.ts +0 -166
  139. package/src/cli/commands/dev.ts +0 -85
  140. package/src/cli/commands/generate.ts +0 -99
  141. package/src/cli/commands/help.ts +0 -95
  142. package/src/cli/commands/init.ts +0 -91
  143. package/src/cli/commands/version.ts +0 -38
  144. package/src/cli/index.ts +0 -6
  145. package/src/cli/templates/generators.ts +0 -359
  146. package/src/cli/templates/index.ts +0 -680
  147. package/src/cli/utils/exec.ts +0 -52
  148. package/src/cli/utils/file-system.ts +0 -78
  149. package/src/cli/utils/logger.ts +0 -111
  150. package/src/core/adapter.ts +0 -88
  151. package/src/core/application.ts +0 -1453
  152. package/src/core/context-pool.ts +0 -79
  153. package/src/core/context.ts +0 -856
  154. package/src/core/index.ts +0 -94
  155. package/src/core/middleware.ts +0 -272
  156. package/src/core/performance/buffer-pool.ts +0 -108
  157. package/src/core/performance/middleware-optimizer.ts +0 -162
  158. package/src/core/plugin/PluginManager.ts +0 -435
  159. package/src/core/plugin/builder.ts +0 -358
  160. package/src/core/plugin/index.ts +0 -50
  161. package/src/core/plugin/types.ts +0 -214
  162. package/src/core/router/file-router.ts +0 -623
  163. package/src/core/router/index.ts +0 -260
  164. package/src/core/router/radix-tree.ts +0 -242
  165. package/src/core/serializer.ts +0 -397
  166. package/src/core/store/index.ts +0 -30
  167. package/src/core/store/registry.ts +0 -178
  168. package/src/core/store/request-store.ts +0 -240
  169. package/src/core/store/types.ts +0 -233
  170. package/src/core/types.ts +0 -616
  171. package/src/database/adapter.ts +0 -35
  172. package/src/database/adapters/index.ts +0 -1
  173. package/src/database/adapters/mysql.ts +0 -669
  174. package/src/database/database.ts +0 -70
  175. package/src/database/dialect.ts +0 -388
  176. package/src/database/index.ts +0 -12
  177. package/src/database/migrations.ts +0 -86
  178. package/src/database/optimizer.ts +0 -125
  179. package/src/database/query-builder.ts +0 -404
  180. package/src/database/realtime.ts +0 -53
  181. package/src/database/schema.ts +0 -71
  182. package/src/database/transactions.ts +0 -56
  183. package/src/database/types.ts +0 -87
  184. package/src/deployment/cluster.ts +0 -471
  185. package/src/deployment/config.ts +0 -454
  186. package/src/deployment/docker.ts +0 -599
  187. package/src/deployment/graceful-shutdown.ts +0 -373
  188. package/src/deployment/index.ts +0 -56
  189. package/src/index.ts +0 -281
  190. package/src/security/adapter.ts +0 -318
  191. package/src/security/auth/JWTPlugin.ts +0 -234
  192. package/src/security/auth/JWTProvider.ts +0 -316
  193. package/src/security/auth/adapter.ts +0 -12
  194. package/src/security/auth/jwt.ts +0 -234
  195. package/src/security/auth/middleware.ts +0 -188
  196. package/src/security/csrf.ts +0 -220
  197. package/src/security/headers.ts +0 -108
  198. package/src/security/index.ts +0 -60
  199. package/src/security/rate-limit/adapter.ts +0 -7
  200. package/src/security/rate-limit/memory.ts +0 -108
  201. package/src/security/rate-limit/middleware.ts +0 -181
  202. package/src/security/sanitization.ts +0 -75
  203. package/src/security/types.ts +0 -240
  204. package/src/security/utils.ts +0 -52
  205. 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
- }