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