servcraft 0.1.0 → 0.1.1

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 (216) hide show
  1. package/.claude/settings.local.json +29 -0
  2. package/.github/CODEOWNERS +18 -0
  3. package/.github/PULL_REQUEST_TEMPLATE.md +46 -0
  4. package/.github/dependabot.yml +59 -0
  5. package/.github/workflows/ci.yml +188 -0
  6. package/.github/workflows/release.yml +195 -0
  7. package/AUDIT.md +602 -0
  8. package/README.md +1070 -1
  9. package/dist/cli/index.cjs +2026 -2168
  10. package/dist/cli/index.cjs.map +1 -1
  11. package/dist/cli/index.js +2026 -2168
  12. package/dist/cli/index.js.map +1 -1
  13. package/dist/index.cjs +595 -616
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.d.cts +114 -52
  16. package/dist/index.d.ts +114 -52
  17. package/dist/index.js +595 -616
  18. package/dist/index.js.map +1 -1
  19. package/docs/CLI-001_MULTI_DB_PLAN.md +546 -0
  20. package/docs/DATABASE_MULTI_ORM.md +399 -0
  21. package/docs/PHASE1_BREAKDOWN.md +346 -0
  22. package/docs/PROGRESS.md +550 -0
  23. package/docs/modules/ANALYTICS.md +226 -0
  24. package/docs/modules/API-VERSIONING.md +252 -0
  25. package/docs/modules/AUDIT.md +192 -0
  26. package/docs/modules/AUTH.md +431 -0
  27. package/docs/modules/CACHE.md +346 -0
  28. package/docs/modules/EMAIL.md +254 -0
  29. package/docs/modules/FEATURE-FLAG.md +291 -0
  30. package/docs/modules/I18N.md +294 -0
  31. package/docs/modules/MEDIA-PROCESSING.md +281 -0
  32. package/docs/modules/MFA.md +266 -0
  33. package/docs/modules/NOTIFICATION.md +311 -0
  34. package/docs/modules/OAUTH.md +237 -0
  35. package/docs/modules/PAYMENT.md +804 -0
  36. package/docs/modules/QUEUE.md +540 -0
  37. package/docs/modules/RATE-LIMIT.md +339 -0
  38. package/docs/modules/SEARCH.md +288 -0
  39. package/docs/modules/SECURITY.md +327 -0
  40. package/docs/modules/SESSION.md +382 -0
  41. package/docs/modules/SWAGGER.md +305 -0
  42. package/docs/modules/UPLOAD.md +296 -0
  43. package/docs/modules/USER.md +505 -0
  44. package/docs/modules/VALIDATION.md +294 -0
  45. package/docs/modules/WEBHOOK.md +270 -0
  46. package/docs/modules/WEBSOCKET.md +691 -0
  47. package/package.json +53 -38
  48. package/prisma/schema.prisma +395 -1
  49. package/src/cli/commands/add-module.ts +520 -87
  50. package/src/cli/commands/db.ts +3 -4
  51. package/src/cli/commands/docs.ts +256 -6
  52. package/src/cli/commands/generate.ts +12 -19
  53. package/src/cli/commands/init.ts +384 -214
  54. package/src/cli/index.ts +0 -4
  55. package/src/cli/templates/repository.ts +6 -1
  56. package/src/cli/templates/routes.ts +6 -21
  57. package/src/cli/utils/docs-generator.ts +6 -7
  58. package/src/cli/utils/env-manager.ts +717 -0
  59. package/src/cli/utils/field-parser.ts +16 -7
  60. package/src/cli/utils/interactive-prompt.ts +223 -0
  61. package/src/cli/utils/template-manager.ts +346 -0
  62. package/src/config/database.config.ts +183 -0
  63. package/src/config/env.ts +0 -10
  64. package/src/config/index.ts +0 -14
  65. package/src/core/server.ts +1 -1
  66. package/src/database/adapters/mongoose.adapter.ts +132 -0
  67. package/src/database/adapters/prisma.adapter.ts +118 -0
  68. package/src/database/connection.ts +190 -0
  69. package/src/database/interfaces/database.interface.ts +85 -0
  70. package/src/database/interfaces/index.ts +7 -0
  71. package/src/database/interfaces/repository.interface.ts +129 -0
  72. package/src/database/models/mongoose/index.ts +7 -0
  73. package/src/database/models/mongoose/payment.schema.ts +347 -0
  74. package/src/database/models/mongoose/user.schema.ts +154 -0
  75. package/src/database/prisma.ts +1 -4
  76. package/src/database/redis.ts +101 -0
  77. package/src/database/repositories/mongoose/index.ts +7 -0
  78. package/src/database/repositories/mongoose/payment.repository.ts +380 -0
  79. package/src/database/repositories/mongoose/user.repository.ts +255 -0
  80. package/src/database/seed.ts +6 -1
  81. package/src/index.ts +9 -20
  82. package/src/middleware/security.ts +2 -6
  83. package/src/modules/analytics/analytics.routes.ts +80 -0
  84. package/src/modules/analytics/analytics.service.ts +364 -0
  85. package/src/modules/analytics/index.ts +18 -0
  86. package/src/modules/analytics/types.ts +180 -0
  87. package/src/modules/api-versioning/index.ts +15 -0
  88. package/src/modules/api-versioning/types.ts +86 -0
  89. package/src/modules/api-versioning/versioning.middleware.ts +120 -0
  90. package/src/modules/api-versioning/versioning.routes.ts +54 -0
  91. package/src/modules/api-versioning/versioning.service.ts +189 -0
  92. package/src/modules/audit/audit.repository.ts +206 -0
  93. package/src/modules/audit/audit.service.ts +27 -59
  94. package/src/modules/auth/auth.controller.ts +2 -2
  95. package/src/modules/auth/auth.middleware.ts +3 -9
  96. package/src/modules/auth/auth.routes.ts +10 -107
  97. package/src/modules/auth/auth.service.ts +126 -23
  98. package/src/modules/auth/index.ts +3 -4
  99. package/src/modules/cache/cache.service.ts +367 -0
  100. package/src/modules/cache/index.ts +10 -0
  101. package/src/modules/cache/types.ts +44 -0
  102. package/src/modules/email/email.service.ts +3 -10
  103. package/src/modules/email/templates.ts +2 -8
  104. package/src/modules/feature-flag/feature-flag.repository.ts +303 -0
  105. package/src/modules/feature-flag/feature-flag.routes.ts +247 -0
  106. package/src/modules/feature-flag/feature-flag.service.ts +566 -0
  107. package/src/modules/feature-flag/index.ts +20 -0
  108. package/src/modules/feature-flag/types.ts +192 -0
  109. package/src/modules/i18n/i18n.middleware.ts +186 -0
  110. package/src/modules/i18n/i18n.routes.ts +191 -0
  111. package/src/modules/i18n/i18n.service.ts +456 -0
  112. package/src/modules/i18n/index.ts +18 -0
  113. package/src/modules/i18n/types.ts +118 -0
  114. package/src/modules/media-processing/index.ts +17 -0
  115. package/src/modules/media-processing/media-processing.routes.ts +111 -0
  116. package/src/modules/media-processing/media-processing.service.ts +245 -0
  117. package/src/modules/media-processing/types.ts +156 -0
  118. package/src/modules/mfa/index.ts +20 -0
  119. package/src/modules/mfa/mfa.repository.ts +206 -0
  120. package/src/modules/mfa/mfa.routes.ts +595 -0
  121. package/src/modules/mfa/mfa.service.ts +572 -0
  122. package/src/modules/mfa/totp.ts +150 -0
  123. package/src/modules/mfa/types.ts +57 -0
  124. package/src/modules/notification/index.ts +20 -0
  125. package/src/modules/notification/notification.repository.ts +356 -0
  126. package/src/modules/notification/notification.service.ts +483 -0
  127. package/src/modules/notification/types.ts +119 -0
  128. package/src/modules/oauth/index.ts +20 -0
  129. package/src/modules/oauth/oauth.repository.ts +219 -0
  130. package/src/modules/oauth/oauth.routes.ts +446 -0
  131. package/src/modules/oauth/oauth.service.ts +293 -0
  132. package/src/modules/oauth/providers/apple.provider.ts +250 -0
  133. package/src/modules/oauth/providers/facebook.provider.ts +181 -0
  134. package/src/modules/oauth/providers/github.provider.ts +248 -0
  135. package/src/modules/oauth/providers/google.provider.ts +189 -0
  136. package/src/modules/oauth/providers/twitter.provider.ts +214 -0
  137. package/src/modules/oauth/types.ts +94 -0
  138. package/src/modules/payment/index.ts +19 -0
  139. package/src/modules/payment/payment.repository.ts +733 -0
  140. package/src/modules/payment/payment.routes.ts +390 -0
  141. package/src/modules/payment/payment.service.ts +354 -0
  142. package/src/modules/payment/providers/mobile-money.provider.ts +274 -0
  143. package/src/modules/payment/providers/paypal.provider.ts +190 -0
  144. package/src/modules/payment/providers/stripe.provider.ts +215 -0
  145. package/src/modules/payment/types.ts +140 -0
  146. package/src/modules/queue/cron.ts +438 -0
  147. package/src/modules/queue/index.ts +87 -0
  148. package/src/modules/queue/queue.routes.ts +600 -0
  149. package/src/modules/queue/queue.service.ts +842 -0
  150. package/src/modules/queue/types.ts +222 -0
  151. package/src/modules/queue/workers.ts +366 -0
  152. package/src/modules/rate-limit/index.ts +59 -0
  153. package/src/modules/rate-limit/rate-limit.middleware.ts +134 -0
  154. package/src/modules/rate-limit/rate-limit.routes.ts +269 -0
  155. package/src/modules/rate-limit/rate-limit.service.ts +348 -0
  156. package/src/modules/rate-limit/stores/memory.store.ts +165 -0
  157. package/src/modules/rate-limit/stores/redis.store.ts +322 -0
  158. package/src/modules/rate-limit/types.ts +153 -0
  159. package/src/modules/search/adapters/elasticsearch.adapter.ts +326 -0
  160. package/src/modules/search/adapters/meilisearch.adapter.ts +261 -0
  161. package/src/modules/search/adapters/memory.adapter.ts +278 -0
  162. package/src/modules/search/index.ts +21 -0
  163. package/src/modules/search/search.service.ts +234 -0
  164. package/src/modules/search/types.ts +214 -0
  165. package/src/modules/security/index.ts +40 -0
  166. package/src/modules/security/sanitize.ts +223 -0
  167. package/src/modules/security/security-audit.service.ts +388 -0
  168. package/src/modules/security/security.middleware.ts +398 -0
  169. package/src/modules/session/index.ts +3 -0
  170. package/src/modules/session/session.repository.ts +159 -0
  171. package/src/modules/session/session.service.ts +340 -0
  172. package/src/modules/session/types.ts +38 -0
  173. package/src/modules/swagger/index.ts +7 -1
  174. package/src/modules/swagger/schema-builder.ts +16 -4
  175. package/src/modules/swagger/swagger.service.ts +9 -10
  176. package/src/modules/swagger/types.ts +0 -2
  177. package/src/modules/upload/index.ts +14 -0
  178. package/src/modules/upload/types.ts +83 -0
  179. package/src/modules/upload/upload.repository.ts +199 -0
  180. package/src/modules/upload/upload.routes.ts +311 -0
  181. package/src/modules/upload/upload.service.ts +448 -0
  182. package/src/modules/user/index.ts +3 -3
  183. package/src/modules/user/user.controller.ts +15 -9
  184. package/src/modules/user/user.repository.ts +237 -113
  185. package/src/modules/user/user.routes.ts +39 -164
  186. package/src/modules/user/user.service.ts +4 -3
  187. package/src/modules/validation/validator.ts +12 -17
  188. package/src/modules/webhook/index.ts +91 -0
  189. package/src/modules/webhook/retry.ts +196 -0
  190. package/src/modules/webhook/signature.ts +135 -0
  191. package/src/modules/webhook/types.ts +181 -0
  192. package/src/modules/webhook/webhook.repository.ts +358 -0
  193. package/src/modules/webhook/webhook.routes.ts +442 -0
  194. package/src/modules/webhook/webhook.service.ts +457 -0
  195. package/src/modules/websocket/features.ts +504 -0
  196. package/src/modules/websocket/index.ts +106 -0
  197. package/src/modules/websocket/middlewares.ts +298 -0
  198. package/src/modules/websocket/types.ts +181 -0
  199. package/src/modules/websocket/websocket.service.ts +692 -0
  200. package/src/utils/errors.ts +7 -0
  201. package/src/utils/pagination.ts +4 -1
  202. package/tests/helpers/db-check.ts +79 -0
  203. package/tests/integration/auth-redis.test.ts +94 -0
  204. package/tests/integration/cache-redis.test.ts +387 -0
  205. package/tests/integration/mongoose-repositories.test.ts +410 -0
  206. package/tests/integration/payment-prisma.test.ts +637 -0
  207. package/tests/integration/queue-bullmq.test.ts +417 -0
  208. package/tests/integration/user-prisma.test.ts +441 -0
  209. package/tests/integration/websocket-socketio.test.ts +552 -0
  210. package/tests/setup.ts +11 -9
  211. package/vitest.config.ts +3 -8
  212. package/npm-cache/_cacache/content-v2/sha512/1c/d0/03440d500a0487621aad1d6402978340698976602046db8e24fa03c01ee6c022c69b0582f969042d9442ee876ac35c038e960dd427d1e622fa24b8eb7dba +0 -0
  213. package/npm-cache/_cacache/content-v2/sha512/42/55/28b493ca491833e5aab0e9c3108d29ab3f36c248ca88f45d4630674fce9130959e56ae308797ac2b6328fa7f09a610b9550ed09cb971d039876d293fc69d +0 -0
  214. package/npm-cache/_cacache/content-v2/sha512/e0/12/f360dc9315ee5f17844a0c8c233ee6bf7c30837c4a02ea0d56c61c7f7ab21c0e958e50ed2c57c59f983c762b93056778c9009b2398ffc26def0183999b13 +0 -0
  215. package/npm-cache/_cacache/content-v2/sha512/ed/b0/fae1161902898f4c913c67d7f6cdf6be0665aec3b389b9c4f4f0a101ca1da59badf1b59c4e0030f5223023b8d63cfe501c46a32c20c895d4fb3f11ca2232 +0 -0
  216. package/npm-cache/_cacache/index-v5/58/94/c2cba79e0f16b4c10e95a87e32255741149e8222cc314a476aab67c39cc0 +0 -5
@@ -0,0 +1,222 @@
1
+ export type JobStatus = 'waiting' | 'active' | 'completed' | 'failed' | 'delayed' | 'paused';
2
+
3
+ export type JobPriority = 'low' | 'normal' | 'high' | 'critical';
4
+
5
+ export interface JobOptions {
6
+ /** Job priority */
7
+ priority?: JobPriority;
8
+ /** Delay in milliseconds before job starts */
9
+ delay?: number;
10
+ /** Number of retry attempts */
11
+ attempts?: number;
12
+ /** Backoff strategy for retries */
13
+ backoff?: {
14
+ type: 'fixed' | 'exponential';
15
+ delay: number;
16
+ };
17
+ /** Remove job on completion */
18
+ removeOnComplete?: boolean | number;
19
+ /** Remove job on failure */
20
+ removeOnFail?: boolean | number;
21
+ /** Job timeout in milliseconds */
22
+ timeout?: number;
23
+ /** Repeat job on cron schedule */
24
+ repeat?: {
25
+ cron?: string;
26
+ every?: number;
27
+ limit?: number;
28
+ immediately?: boolean;
29
+ };
30
+ }
31
+
32
+ export interface Job<T = any> {
33
+ /** Unique job ID */
34
+ id: string;
35
+ /** Queue name */
36
+ queueName: string;
37
+ /** Job name/type */
38
+ name: string;
39
+ /** Job data */
40
+ data: T;
41
+ /** Job options */
42
+ options: JobOptions;
43
+ /** Job status */
44
+ status: JobStatus;
45
+ /** Progress (0-100) */
46
+ progress?: number;
47
+ /** Number of attempts made */
48
+ attemptsMade: number;
49
+ /** Job result if completed */
50
+ result?: any;
51
+ /** Error if failed */
52
+ error?: string;
53
+ /** Stack trace if failed */
54
+ stacktrace?: string[];
55
+ /** Creation timestamp */
56
+ createdAt: Date;
57
+ /** Processing start timestamp */
58
+ processedAt?: Date;
59
+ /** Completion timestamp */
60
+ completedAt?: Date;
61
+ /** Failure timestamp */
62
+ failedAt?: Date;
63
+ /** Delay until (for delayed jobs) */
64
+ delayedUntil?: Date;
65
+ }
66
+
67
+ export interface QueueConfig {
68
+ /** Redis connection options */
69
+ redis?: {
70
+ host?: string;
71
+ port?: number;
72
+ password?: string;
73
+ db?: number;
74
+ };
75
+ /** Default job options */
76
+ defaultJobOptions?: JobOptions;
77
+ /** Queue prefix */
78
+ prefix?: string;
79
+ /** Enable metrics */
80
+ metrics?: boolean;
81
+ }
82
+
83
+ export interface QueueStats {
84
+ /** Queue name */
85
+ name: string;
86
+ /** Waiting jobs count */
87
+ waiting: number;
88
+ /** Active jobs count */
89
+ active: number;
90
+ /** Completed jobs count */
91
+ completed: number;
92
+ /** Failed jobs count */
93
+ failed: number;
94
+ /** Delayed jobs count */
95
+ delayed: number;
96
+ /** Paused jobs count */
97
+ paused: number;
98
+ }
99
+
100
+ export interface Worker<T = any> {
101
+ /** Worker name/type */
102
+ name: string;
103
+ /** Worker function */
104
+ process: (job: Job<T>) => Promise<any>;
105
+ /** Concurrency (parallel jobs) */
106
+ concurrency?: number;
107
+ }
108
+
109
+ export interface CronJob {
110
+ /** Unique cron job ID */
111
+ id: string;
112
+ /** Cron job name */
113
+ name: string;
114
+ /** Cron expression */
115
+ cron: string;
116
+ /** Job data */
117
+ data?: any;
118
+ /** Queue to add job to */
119
+ queueName: string;
120
+ /** Job name/type */
121
+ jobName: string;
122
+ /** Whether the cron is enabled */
123
+ enabled: boolean;
124
+ /** Last run timestamp */
125
+ lastRun?: Date;
126
+ /** Next run timestamp */
127
+ nextRun?: Date;
128
+ /** Creation timestamp */
129
+ createdAt: Date;
130
+ }
131
+
132
+ export interface EmailJobData {
133
+ to: string | string[];
134
+ subject: string;
135
+ html?: string;
136
+ text?: string;
137
+ from?: string;
138
+ cc?: string | string[];
139
+ bcc?: string | string[];
140
+ attachments?: Array<{
141
+ filename: string;
142
+ path?: string;
143
+ content?: Buffer | string;
144
+ }>;
145
+ template?: {
146
+ name: string;
147
+ data: Record<string, any>;
148
+ };
149
+ }
150
+
151
+ export interface ImageProcessingJobData {
152
+ /** Source image path or URL */
153
+ source: string;
154
+ /** Operations to perform */
155
+ operations: Array<{
156
+ type: 'resize' | 'crop' | 'rotate' | 'watermark' | 'compress';
157
+ options: Record<string, any>;
158
+ }>;
159
+ /** Output path */
160
+ output: string;
161
+ /** Output format */
162
+ format?: 'jpg' | 'png' | 'webp' | 'avif';
163
+ /** Quality (1-100) */
164
+ quality?: number;
165
+ }
166
+
167
+ export interface NotificationJobData {
168
+ userId: string;
169
+ type: 'push' | 'sms' | 'email';
170
+ title?: string;
171
+ message: string;
172
+ data?: Record<string, any>;
173
+ }
174
+
175
+ export interface WebhookJobData {
176
+ url: string;
177
+ method?: 'POST' | 'PUT' | 'PATCH';
178
+ headers?: Record<string, string>;
179
+ body: Record<string, any>;
180
+ retries?: number;
181
+ }
182
+
183
+ export interface QueueMetrics {
184
+ /** Total jobs processed */
185
+ totalProcessed: number;
186
+ /** Total jobs failed */
187
+ totalFailed: number;
188
+ /** Average processing time (ms) */
189
+ avgProcessingTime: number;
190
+ /** Jobs per minute */
191
+ throughput: number;
192
+ /** Peak concurrency */
193
+ peakConcurrency: number;
194
+ /** Current concurrency */
195
+ currentConcurrency: number;
196
+ /** Success rate (0-100) */
197
+ successRate: number;
198
+ }
199
+
200
+ export interface BulkJobOptions {
201
+ jobs: Array<{
202
+ name: string;
203
+ data: any;
204
+ opts?: JobOptions;
205
+ }>;
206
+ }
207
+
208
+ export interface JobFilter {
209
+ status?: JobStatus | JobStatus[];
210
+ name?: string;
211
+ limit?: number;
212
+ offset?: number;
213
+ startDate?: Date;
214
+ endDate?: Date;
215
+ }
216
+
217
+ export interface JobEvent {
218
+ event: 'added' | 'active' | 'completed' | 'failed' | 'progress' | 'stalled' | 'removed';
219
+ jobId: string;
220
+ data?: any;
221
+ timestamp: Date;
222
+ }
@@ -0,0 +1,366 @@
1
+ import { logger } from '../../core/logger.js';
2
+ import type {
3
+ Worker,
4
+ Job,
5
+ EmailJobData,
6
+ ImageProcessingJobData,
7
+ NotificationJobData,
8
+ WebhookJobData,
9
+ } from './types.js';
10
+
11
+ /**
12
+ * Email Worker
13
+ * Sends emails asynchronously
14
+ */
15
+ export const emailWorker: Worker<EmailJobData> = {
16
+ name: 'send-email',
17
+ concurrency: 5,
18
+ async process(job: Job<EmailJobData>): Promise<{ messageId: string }> {
19
+ const { to, subject } = job.data;
20
+
21
+ logger.info({ jobId: job.id, to, subject }, 'Processing email job');
22
+
23
+ // Simulate email sending
24
+ // In production, integrate with your email service (nodemailer, SendGrid, etc.)
25
+ await new Promise((resolve) => setTimeout(resolve, 500));
26
+
27
+ const messageId = `<${Date.now()}@servcraft.local>`;
28
+
29
+ logger.info({ jobId: job.id, messageId, to }, 'Email sent successfully');
30
+
31
+ return { messageId };
32
+ },
33
+ };
34
+
35
+ /**
36
+ * Image Processing Worker
37
+ * Processes images (resize, crop, watermark, etc.)
38
+ */
39
+ export const imageProcessingWorker: Worker<ImageProcessingJobData> = {
40
+ name: 'process-image',
41
+ concurrency: 3,
42
+ async process(job: Job<ImageProcessingJobData>): Promise<{ output: string; size: number }> {
43
+ const { source, operations, output } = job.data;
44
+
45
+ logger.info({ jobId: job.id, source, operations: operations.length }, 'Processing image job');
46
+
47
+ // Simulate image processing
48
+ // In production, use Sharp, Jimp, or similar library
49
+ for (const operation of operations) {
50
+ logger.debug(
51
+ { jobId: job.id, operation: operation.type },
52
+ `Applying ${operation.type} operation`
53
+ );
54
+ await new Promise((resolve) => setTimeout(resolve, 200));
55
+ }
56
+
57
+ const outputPath = output;
58
+ const fileSize = Math.floor(Math.random() * 1000000); // Mock file size
59
+
60
+ logger.info({ jobId: job.id, output: outputPath, size: fileSize }, 'Image processed');
61
+
62
+ return { output: outputPath, size: fileSize };
63
+ },
64
+ };
65
+
66
+ /**
67
+ * Notification Worker
68
+ * Sends push notifications, SMS, or emails
69
+ */
70
+ export const notificationWorker: Worker<NotificationJobData> = {
71
+ name: 'send-notification',
72
+ concurrency: 10,
73
+ async process(job: Job<NotificationJobData>): Promise<{ sent: boolean; notificationId: string }> {
74
+ const { userId, type } = job.data;
75
+
76
+ logger.info({ jobId: job.id, userId, type }, 'Processing notification job');
77
+
78
+ // Simulate notification sending
79
+ // In production, integrate with FCM, SNS, Twilio, etc.
80
+ await new Promise((resolve) => setTimeout(resolve, 300));
81
+
82
+ const notificationId = `notif_${Date.now()}`;
83
+
84
+ logger.info({ jobId: job.id, userId, notificationId }, 'Notification sent');
85
+
86
+ return { sent: true, notificationId };
87
+ },
88
+ };
89
+
90
+ /**
91
+ * Webhook Worker
92
+ * Sends HTTP webhooks to external URLs
93
+ */
94
+ export const webhookWorker: Worker<WebhookJobData> = {
95
+ name: 'send-webhook',
96
+ concurrency: 5,
97
+ async process(job: Job<WebhookJobData>): Promise<{ statusCode: number; response: unknown }> {
98
+ const { url, method = 'POST', headers = {}, body } = job.data;
99
+
100
+ logger.info({ jobId: job.id, url, method }, 'Processing webhook job');
101
+
102
+ try {
103
+ const response = await fetch(url, {
104
+ method,
105
+ headers: {
106
+ 'Content-Type': 'application/json',
107
+ ...headers,
108
+ },
109
+ body: JSON.stringify(body),
110
+ });
111
+
112
+ const responseData = await response.text().catch(() => '');
113
+
114
+ logger.info({ jobId: job.id, url, statusCode: response.status }, 'Webhook sent successfully');
115
+
116
+ return {
117
+ statusCode: response.status,
118
+ response: responseData,
119
+ };
120
+ } catch (error) {
121
+ logger.error({ jobId: job.id, url, error }, 'Webhook failed');
122
+ throw error;
123
+ }
124
+ },
125
+ };
126
+
127
+ /**
128
+ * Data Export Worker
129
+ * Exports data to CSV, Excel, PDF, etc.
130
+ */
131
+ export const dataExportWorker: Worker<{
132
+ type: 'csv' | 'excel' | 'pdf';
133
+ data: unknown[];
134
+ filename: string;
135
+ options?: Record<string, unknown>;
136
+ }> = {
137
+ name: 'export-data',
138
+ concurrency: 2,
139
+ async process(job): Promise<{ filename: string; size: number; url: string }> {
140
+ const { type, data, filename } = job.data;
141
+
142
+ logger.info({ jobId: job.id, type, rows: data.length, filename }, 'Processing export job');
143
+
144
+ // Simulate data export
145
+ // In production, use libraries like csv-writer, exceljs, pdfkit
146
+ await new Promise((resolve) => setTimeout(resolve, 1000));
147
+
148
+ const outputPath = `/exports/${filename}`;
149
+ const fileSize = data.length * 100; // Mock file size
150
+ const downloadUrl = `https://example.com${outputPath}`;
151
+
152
+ logger.info({ jobId: job.id, filename, size: fileSize }, 'Data exported');
153
+
154
+ return { filename: outputPath, size: fileSize, url: downloadUrl };
155
+ },
156
+ };
157
+
158
+ /**
159
+ * Report Generation Worker
160
+ * Generates reports (analytics, financial, etc.)
161
+ */
162
+ export const reportGenerationWorker: Worker<{
163
+ reportType: string;
164
+ parameters: Record<string, unknown>;
165
+ format: 'pdf' | 'html' | 'excel';
166
+ }> = {
167
+ name: 'generate-report',
168
+ concurrency: 2,
169
+ async process(job): Promise<{ reportUrl: string; generatedAt: Date }> {
170
+ const { reportType, format } = job.data;
171
+
172
+ logger.info({ jobId: job.id, reportType, format }, 'Processing report generation job');
173
+
174
+ // Simulate report generation
175
+ // In production, integrate with your reporting engine
176
+ await new Promise((resolve) => setTimeout(resolve, 2000));
177
+
178
+ const reportUrl = `/reports/${reportType}_${Date.now()}.${format}`;
179
+
180
+ logger.info({ jobId: job.id, reportType, reportUrl }, 'Report generated');
181
+
182
+ return { reportUrl, generatedAt: new Date() };
183
+ },
184
+ };
185
+
186
+ /**
187
+ * Database Backup Worker
188
+ * Creates database backups
189
+ */
190
+ export const databaseBackupWorker: Worker<{
191
+ databases: string[];
192
+ destination: string;
193
+ compress?: boolean;
194
+ }> = {
195
+ name: 'database-backup',
196
+ concurrency: 1, // Only one backup at a time
197
+ async process(
198
+ job
199
+ ): Promise<{ backups: Array<{ database: string; size: number; path: string }> }> {
200
+ const { databases, destination, compress = true } = job.data;
201
+
202
+ logger.info(
203
+ { jobId: job.id, databases, destination, compress },
204
+ 'Processing database backup job'
205
+ );
206
+
207
+ const backups = [];
208
+
209
+ for (const database of databases) {
210
+ logger.debug({ jobId: job.id, database }, `Backing up database: ${database}`);
211
+
212
+ // Simulate backup
213
+ await new Promise((resolve) => setTimeout(resolve, 3000));
214
+
215
+ const backupPath = `${destination}/${database}_${Date.now()}.sql${compress ? '.gz' : ''}`;
216
+ const size = Math.floor(Math.random() * 50000000); // Mock size
217
+
218
+ backups.push({ database, size, path: backupPath });
219
+
220
+ logger.info({ jobId: job.id, database, size, path: backupPath }, 'Database backed up');
221
+ }
222
+
223
+ return { backups };
224
+ },
225
+ };
226
+
227
+ /**
228
+ * Cache Warming Worker
229
+ * Warms up cache with frequently accessed data
230
+ */
231
+ export const cacheWarmingWorker: Worker<{
232
+ keys: string[];
233
+ ttl?: number;
234
+ }> = {
235
+ name: 'warm-cache',
236
+ concurrency: 5,
237
+ async process(job): Promise<{ warmed: number; failed: number }> {
238
+ const { keys, ttl = 3600 } = job.data;
239
+
240
+ logger.info({ jobId: job.id, keys: keys.length, ttl }, 'Processing cache warming job');
241
+
242
+ let warmed = 0;
243
+ let failed = 0;
244
+
245
+ for (const key of keys) {
246
+ try {
247
+ // Simulate cache warming
248
+ await new Promise((resolve) => setTimeout(resolve, 100));
249
+ warmed++;
250
+ } catch (error) {
251
+ failed++;
252
+ logger.warn({ jobId: job.id, key, error }, 'Failed to warm cache key');
253
+ }
254
+ }
255
+
256
+ logger.info({ jobId: job.id, warmed, failed }, 'Cache warming completed');
257
+
258
+ return { warmed, failed };
259
+ },
260
+ };
261
+
262
+ /**
263
+ * Data Cleanup Worker
264
+ * Cleans up old data (logs, temp files, etc.)
265
+ */
266
+ export const dataCleanupWorker: Worker<{
267
+ targets: Array<{
268
+ type: 'database' | 'files' | 'logs';
269
+ table?: string;
270
+ directory?: string;
271
+ olderThanDays: number;
272
+ }>;
273
+ }> = {
274
+ name: 'cleanup-data',
275
+ concurrency: 1,
276
+ async process(job): Promise<{ cleaned: Array<{ type: string; count: number; size: number }> }> {
277
+ const { targets } = job.data;
278
+
279
+ logger.info({ jobId: job.id, targets: targets.length }, 'Processing data cleanup job');
280
+
281
+ const cleaned = [];
282
+
283
+ for (const target of targets) {
284
+ logger.debug({ jobId: job.id, target }, `Cleaning up ${target.type}`);
285
+
286
+ // Simulate cleanup
287
+ await new Promise((resolve) => setTimeout(resolve, 500));
288
+
289
+ const count = Math.floor(Math.random() * 1000);
290
+ const size = count * 1024; // Mock size
291
+
292
+ cleaned.push({
293
+ type: target.type,
294
+ count,
295
+ size,
296
+ });
297
+
298
+ logger.info({ jobId: job.id, target: target.type, count, size }, 'Cleanup completed');
299
+ }
300
+
301
+ return { cleaned };
302
+ },
303
+ };
304
+
305
+ /**
306
+ * Batch Processing Worker
307
+ * Processes items in batches
308
+ */
309
+ export const batchProcessingWorker: Worker<{
310
+ items: unknown[];
311
+ batchSize: number;
312
+ processor: 'validate' | 'transform' | 'import';
313
+ }> = {
314
+ name: 'batch-process',
315
+ concurrency: 3,
316
+ async process(job): Promise<{ processed: number; failed: number; errors: unknown[] }> {
317
+ const { items, batchSize, processor } = job.data;
318
+
319
+ logger.info(
320
+ { jobId: job.id, items: items.length, batchSize, processor },
321
+ 'Processing batch job'
322
+ );
323
+
324
+ let processed = 0;
325
+ let failed = 0;
326
+ const errors = [];
327
+
328
+ for (let i = 0; i < items.length; i += batchSize) {
329
+ const batch = items.slice(i, i + batchSize);
330
+
331
+ try {
332
+ // Simulate batch processing
333
+ await new Promise((resolve) => setTimeout(resolve, 200));
334
+ processed += batch.length;
335
+
336
+ // Update progress
337
+ const progress = Math.floor(((i + batch.length) / items.length) * 100);
338
+ logger.debug({ jobId: job.id, progress }, `Batch progress: ${progress}%`);
339
+ } catch (error) {
340
+ failed += batch.length;
341
+ errors.push({ batch: i / batchSize, error });
342
+ logger.warn({ jobId: job.id, batch: i / batchSize, error }, 'Batch failed');
343
+ }
344
+ }
345
+
346
+ logger.info({ jobId: job.id, processed, failed }, 'Batch processing completed');
347
+
348
+ return { processed, failed, errors };
349
+ },
350
+ };
351
+
352
+ /**
353
+ * Export all default workers
354
+ */
355
+ export const defaultWorkers = [
356
+ emailWorker,
357
+ imageProcessingWorker,
358
+ notificationWorker,
359
+ webhookWorker,
360
+ dataExportWorker,
361
+ reportGenerationWorker,
362
+ databaseBackupWorker,
363
+ cacheWarmingWorker,
364
+ dataCleanupWorker,
365
+ batchProcessingWorker,
366
+ ];
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Rate Limiting Module
3
+ *
4
+ * Provides advanced rate limiting capabilities with multiple algorithms:
5
+ * - Fixed Window: Simple, but can allow bursts at boundaries
6
+ * - Sliding Window: More accurate, prevents boundary bursts
7
+ * - Token Bucket: Allows controlled bursts while enforcing average rate
8
+ *
9
+ * Features:
10
+ * - IP-based, user-based, or custom key rate limiting
11
+ * - Whitelist/blacklist support
12
+ * - Custom limits per endpoint or user role
13
+ * - Memory or Redis storage
14
+ * - Admin routes for management
15
+ * - Standard rate limit headers
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * import { createRateLimiter, RateLimitService } from './modules/rate-limit';
20
+ *
21
+ * // Basic usage
22
+ * app.use(createRateLimiter({
23
+ * max: 100,
24
+ * windowMs: 60 * 1000, // 1 minute
25
+ * algorithm: 'sliding-window'
26
+ * }));
27
+ *
28
+ * // Pre-configured limiters
29
+ * import { strictRateLimit, authRateLimit } from './modules/rate-limit';
30
+ * app.post('/login', authRateLimit, loginHandler);
31
+ * app.post('/sensitive', strictRateLimit, sensitiveHandler);
32
+ * ```
33
+ */
34
+
35
+ // Types
36
+ export * from './types.js';
37
+
38
+ // Service
39
+ export { RateLimitService } from './rate-limit.service.js';
40
+
41
+ // Middleware
42
+ export {
43
+ createRateLimiter,
44
+ rateLimitEndpoint,
45
+ strictRateLimit,
46
+ standardRateLimit,
47
+ relaxedRateLimit,
48
+ authRateLimit,
49
+ ipRateLimit,
50
+ userRateLimit,
51
+ apiKeyRateLimit,
52
+ } from './rate-limit.middleware.js';
53
+
54
+ // Routes
55
+ export { createRateLimitRoutes } from './rate-limit.routes.js';
56
+
57
+ // Stores
58
+ export { MemoryStore } from './stores/memory.store.js';
59
+ export { RedisStore } from './stores/redis.store.js';