servcraft 0.1.0 → 0.1.3

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 (217) hide show
  1. package/.claude/settings.local.json +30 -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/LICENSE +21 -0
  9. package/README.md +1102 -1
  10. package/dist/cli/index.cjs +2026 -2168
  11. package/dist/cli/index.cjs.map +1 -1
  12. package/dist/cli/index.js +2026 -2168
  13. package/dist/cli/index.js.map +1 -1
  14. package/dist/index.cjs +595 -616
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +114 -52
  17. package/dist/index.d.ts +114 -52
  18. package/dist/index.js +595 -616
  19. package/dist/index.js.map +1 -1
  20. package/docs/CLI-001_MULTI_DB_PLAN.md +546 -0
  21. package/docs/DATABASE_MULTI_ORM.md +399 -0
  22. package/docs/PHASE1_BREAKDOWN.md +346 -0
  23. package/docs/PROGRESS.md +550 -0
  24. package/docs/modules/ANALYTICS.md +226 -0
  25. package/docs/modules/API-VERSIONING.md +252 -0
  26. package/docs/modules/AUDIT.md +192 -0
  27. package/docs/modules/AUTH.md +431 -0
  28. package/docs/modules/CACHE.md +346 -0
  29. package/docs/modules/EMAIL.md +254 -0
  30. package/docs/modules/FEATURE-FLAG.md +291 -0
  31. package/docs/modules/I18N.md +294 -0
  32. package/docs/modules/MEDIA-PROCESSING.md +281 -0
  33. package/docs/modules/MFA.md +266 -0
  34. package/docs/modules/NOTIFICATION.md +311 -0
  35. package/docs/modules/OAUTH.md +237 -0
  36. package/docs/modules/PAYMENT.md +804 -0
  37. package/docs/modules/QUEUE.md +540 -0
  38. package/docs/modules/RATE-LIMIT.md +339 -0
  39. package/docs/modules/SEARCH.md +288 -0
  40. package/docs/modules/SECURITY.md +327 -0
  41. package/docs/modules/SESSION.md +382 -0
  42. package/docs/modules/SWAGGER.md +305 -0
  43. package/docs/modules/UPLOAD.md +296 -0
  44. package/docs/modules/USER.md +505 -0
  45. package/docs/modules/VALIDATION.md +294 -0
  46. package/docs/modules/WEBHOOK.md +270 -0
  47. package/docs/modules/WEBSOCKET.md +691 -0
  48. package/package.json +53 -38
  49. package/prisma/schema.prisma +395 -1
  50. package/src/cli/commands/add-module.ts +520 -87
  51. package/src/cli/commands/db.ts +3 -4
  52. package/src/cli/commands/docs.ts +256 -6
  53. package/src/cli/commands/generate.ts +12 -19
  54. package/src/cli/commands/init.ts +384 -214
  55. package/src/cli/index.ts +0 -4
  56. package/src/cli/templates/repository.ts +6 -1
  57. package/src/cli/templates/routes.ts +6 -21
  58. package/src/cli/utils/docs-generator.ts +6 -7
  59. package/src/cli/utils/env-manager.ts +717 -0
  60. package/src/cli/utils/field-parser.ts +16 -7
  61. package/src/cli/utils/interactive-prompt.ts +223 -0
  62. package/src/cli/utils/template-manager.ts +346 -0
  63. package/src/config/database.config.ts +183 -0
  64. package/src/config/env.ts +0 -10
  65. package/src/config/index.ts +0 -14
  66. package/src/core/server.ts +1 -1
  67. package/src/database/adapters/mongoose.adapter.ts +132 -0
  68. package/src/database/adapters/prisma.adapter.ts +118 -0
  69. package/src/database/connection.ts +190 -0
  70. package/src/database/interfaces/database.interface.ts +85 -0
  71. package/src/database/interfaces/index.ts +7 -0
  72. package/src/database/interfaces/repository.interface.ts +129 -0
  73. package/src/database/models/mongoose/index.ts +7 -0
  74. package/src/database/models/mongoose/payment.schema.ts +347 -0
  75. package/src/database/models/mongoose/user.schema.ts +154 -0
  76. package/src/database/prisma.ts +1 -4
  77. package/src/database/redis.ts +101 -0
  78. package/src/database/repositories/mongoose/index.ts +7 -0
  79. package/src/database/repositories/mongoose/payment.repository.ts +380 -0
  80. package/src/database/repositories/mongoose/user.repository.ts +255 -0
  81. package/src/database/seed.ts +6 -1
  82. package/src/index.ts +9 -20
  83. package/src/middleware/security.ts +2 -6
  84. package/src/modules/analytics/analytics.routes.ts +80 -0
  85. package/src/modules/analytics/analytics.service.ts +364 -0
  86. package/src/modules/analytics/index.ts +18 -0
  87. package/src/modules/analytics/types.ts +180 -0
  88. package/src/modules/api-versioning/index.ts +15 -0
  89. package/src/modules/api-versioning/types.ts +86 -0
  90. package/src/modules/api-versioning/versioning.middleware.ts +120 -0
  91. package/src/modules/api-versioning/versioning.routes.ts +54 -0
  92. package/src/modules/api-versioning/versioning.service.ts +189 -0
  93. package/src/modules/audit/audit.repository.ts +206 -0
  94. package/src/modules/audit/audit.service.ts +27 -59
  95. package/src/modules/auth/auth.controller.ts +2 -2
  96. package/src/modules/auth/auth.middleware.ts +3 -9
  97. package/src/modules/auth/auth.routes.ts +10 -107
  98. package/src/modules/auth/auth.service.ts +126 -23
  99. package/src/modules/auth/index.ts +3 -4
  100. package/src/modules/cache/cache.service.ts +367 -0
  101. package/src/modules/cache/index.ts +10 -0
  102. package/src/modules/cache/types.ts +44 -0
  103. package/src/modules/email/email.service.ts +3 -10
  104. package/src/modules/email/templates.ts +2 -8
  105. package/src/modules/feature-flag/feature-flag.repository.ts +303 -0
  106. package/src/modules/feature-flag/feature-flag.routes.ts +247 -0
  107. package/src/modules/feature-flag/feature-flag.service.ts +566 -0
  108. package/src/modules/feature-flag/index.ts +20 -0
  109. package/src/modules/feature-flag/types.ts +192 -0
  110. package/src/modules/i18n/i18n.middleware.ts +186 -0
  111. package/src/modules/i18n/i18n.routes.ts +191 -0
  112. package/src/modules/i18n/i18n.service.ts +456 -0
  113. package/src/modules/i18n/index.ts +18 -0
  114. package/src/modules/i18n/types.ts +118 -0
  115. package/src/modules/media-processing/index.ts +17 -0
  116. package/src/modules/media-processing/media-processing.routes.ts +111 -0
  117. package/src/modules/media-processing/media-processing.service.ts +245 -0
  118. package/src/modules/media-processing/types.ts +156 -0
  119. package/src/modules/mfa/index.ts +20 -0
  120. package/src/modules/mfa/mfa.repository.ts +206 -0
  121. package/src/modules/mfa/mfa.routes.ts +595 -0
  122. package/src/modules/mfa/mfa.service.ts +572 -0
  123. package/src/modules/mfa/totp.ts +150 -0
  124. package/src/modules/mfa/types.ts +57 -0
  125. package/src/modules/notification/index.ts +20 -0
  126. package/src/modules/notification/notification.repository.ts +356 -0
  127. package/src/modules/notification/notification.service.ts +483 -0
  128. package/src/modules/notification/types.ts +119 -0
  129. package/src/modules/oauth/index.ts +20 -0
  130. package/src/modules/oauth/oauth.repository.ts +219 -0
  131. package/src/modules/oauth/oauth.routes.ts +446 -0
  132. package/src/modules/oauth/oauth.service.ts +293 -0
  133. package/src/modules/oauth/providers/apple.provider.ts +250 -0
  134. package/src/modules/oauth/providers/facebook.provider.ts +181 -0
  135. package/src/modules/oauth/providers/github.provider.ts +248 -0
  136. package/src/modules/oauth/providers/google.provider.ts +189 -0
  137. package/src/modules/oauth/providers/twitter.provider.ts +214 -0
  138. package/src/modules/oauth/types.ts +94 -0
  139. package/src/modules/payment/index.ts +19 -0
  140. package/src/modules/payment/payment.repository.ts +733 -0
  141. package/src/modules/payment/payment.routes.ts +390 -0
  142. package/src/modules/payment/payment.service.ts +354 -0
  143. package/src/modules/payment/providers/mobile-money.provider.ts +274 -0
  144. package/src/modules/payment/providers/paypal.provider.ts +190 -0
  145. package/src/modules/payment/providers/stripe.provider.ts +215 -0
  146. package/src/modules/payment/types.ts +140 -0
  147. package/src/modules/queue/cron.ts +438 -0
  148. package/src/modules/queue/index.ts +87 -0
  149. package/src/modules/queue/queue.routes.ts +600 -0
  150. package/src/modules/queue/queue.service.ts +842 -0
  151. package/src/modules/queue/types.ts +222 -0
  152. package/src/modules/queue/workers.ts +366 -0
  153. package/src/modules/rate-limit/index.ts +59 -0
  154. package/src/modules/rate-limit/rate-limit.middleware.ts +134 -0
  155. package/src/modules/rate-limit/rate-limit.routes.ts +269 -0
  156. package/src/modules/rate-limit/rate-limit.service.ts +348 -0
  157. package/src/modules/rate-limit/stores/memory.store.ts +165 -0
  158. package/src/modules/rate-limit/stores/redis.store.ts +322 -0
  159. package/src/modules/rate-limit/types.ts +153 -0
  160. package/src/modules/search/adapters/elasticsearch.adapter.ts +326 -0
  161. package/src/modules/search/adapters/meilisearch.adapter.ts +261 -0
  162. package/src/modules/search/adapters/memory.adapter.ts +278 -0
  163. package/src/modules/search/index.ts +21 -0
  164. package/src/modules/search/search.service.ts +234 -0
  165. package/src/modules/search/types.ts +214 -0
  166. package/src/modules/security/index.ts +40 -0
  167. package/src/modules/security/sanitize.ts +223 -0
  168. package/src/modules/security/security-audit.service.ts +388 -0
  169. package/src/modules/security/security.middleware.ts +398 -0
  170. package/src/modules/session/index.ts +3 -0
  171. package/src/modules/session/session.repository.ts +159 -0
  172. package/src/modules/session/session.service.ts +340 -0
  173. package/src/modules/session/types.ts +38 -0
  174. package/src/modules/swagger/index.ts +7 -1
  175. package/src/modules/swagger/schema-builder.ts +16 -4
  176. package/src/modules/swagger/swagger.service.ts +9 -10
  177. package/src/modules/swagger/types.ts +0 -2
  178. package/src/modules/upload/index.ts +14 -0
  179. package/src/modules/upload/types.ts +83 -0
  180. package/src/modules/upload/upload.repository.ts +199 -0
  181. package/src/modules/upload/upload.routes.ts +311 -0
  182. package/src/modules/upload/upload.service.ts +448 -0
  183. package/src/modules/user/index.ts +3 -3
  184. package/src/modules/user/user.controller.ts +15 -9
  185. package/src/modules/user/user.repository.ts +237 -113
  186. package/src/modules/user/user.routes.ts +39 -164
  187. package/src/modules/user/user.service.ts +4 -3
  188. package/src/modules/validation/validator.ts +12 -17
  189. package/src/modules/webhook/index.ts +91 -0
  190. package/src/modules/webhook/retry.ts +196 -0
  191. package/src/modules/webhook/signature.ts +135 -0
  192. package/src/modules/webhook/types.ts +181 -0
  193. package/src/modules/webhook/webhook.repository.ts +358 -0
  194. package/src/modules/webhook/webhook.routes.ts +442 -0
  195. package/src/modules/webhook/webhook.service.ts +457 -0
  196. package/src/modules/websocket/features.ts +504 -0
  197. package/src/modules/websocket/index.ts +106 -0
  198. package/src/modules/websocket/middlewares.ts +298 -0
  199. package/src/modules/websocket/types.ts +181 -0
  200. package/src/modules/websocket/websocket.service.ts +692 -0
  201. package/src/utils/errors.ts +7 -0
  202. package/src/utils/pagination.ts +4 -1
  203. package/tests/helpers/db-check.ts +79 -0
  204. package/tests/integration/auth-redis.test.ts +94 -0
  205. package/tests/integration/cache-redis.test.ts +387 -0
  206. package/tests/integration/mongoose-repositories.test.ts +410 -0
  207. package/tests/integration/payment-prisma.test.ts +637 -0
  208. package/tests/integration/queue-bullmq.test.ts +417 -0
  209. package/tests/integration/user-prisma.test.ts +441 -0
  210. package/tests/integration/websocket-socketio.test.ts +552 -0
  211. package/tests/setup.ts +11 -9
  212. package/vitest.config.ts +3 -8
  213. package/npm-cache/_cacache/content-v2/sha512/1c/d0/03440d500a0487621aad1d6402978340698976602046db8e24fa03c01ee6c022c69b0582f969042d9442ee876ac35c038e960dd427d1e622fa24b8eb7dba +0 -0
  214. package/npm-cache/_cacache/content-v2/sha512/42/55/28b493ca491833e5aab0e9c3108d29ab3f36c248ca88f45d4630674fce9130959e56ae308797ac2b6328fa7f09a610b9550ed09cb971d039876d293fc69d +0 -0
  215. package/npm-cache/_cacache/content-v2/sha512/e0/12/f360dc9315ee5f17844a0c8c233ee6bf7c30837c4a02ea0d56c61c7f7ab21c0e958e50ed2c57c59f983c762b93056778c9009b2398ffc26def0183999b13 +0 -0
  216. package/npm-cache/_cacache/content-v2/sha512/ed/b0/fae1161902898f4c913c67d7f6cdf6be0665aec3b389b9c4f4f0a101ca1da59badf1b59c4e0030f5223023b8d63cfe501c46a32c20c895d4fb3f11ca2232 +0 -0
  217. package/npm-cache/_cacache/index-v5/58/94/c2cba79e0f16b4c10e95a87e32255741149e8222cc314a476aab67c39cc0 +0 -5
@@ -0,0 +1,346 @@
1
+ # Cache Module Documentation
2
+
3
+ ## Overview
4
+
5
+ The Cache module provides a flexible caching layer with support for both in-memory and Redis-based caching. It offers a unified API for caching operations with TTL support, statistics tracking, and automatic cleanup.
6
+
7
+ ## Features
8
+
9
+ - ✅ Dual provider support (Memory + Redis)
10
+ - ✅ Redis integration with ioredis
11
+ - ✅ TTL (Time To Live) support per key
12
+ - ✅ Automatic expiration and cleanup
13
+ - ✅ Cache statistics (hits/misses)
14
+ - ✅ Prefix support for key namespacing
15
+ - ✅ Batch operations (mget/mset)
16
+ - ✅ Counter operations (increment/decrement)
17
+ - ✅ Connection resilience with retry strategy
18
+ - ✅ Tag-based invalidation
19
+
20
+ ## Configuration
21
+
22
+ ### Memory Cache
23
+
24
+ ```typescript
25
+ import { CacheService } from './modules/cache/cache.service.js';
26
+
27
+ const cache = new CacheService({
28
+ provider: 'memory',
29
+ ttl: 3600, // 1 hour default
30
+ prefix: 'myapp:',
31
+ memory: {
32
+ maxSize: 1000, // Max 1000 items
33
+ checkPeriod: 60, // Cleanup every 60 seconds
34
+ },
35
+ });
36
+ ```
37
+
38
+ ### Redis Cache
39
+
40
+ ```typescript
41
+ const cache = new CacheService({
42
+ provider: 'redis',
43
+ ttl: 3600,
44
+ prefix: 'myapp:',
45
+ redis: {
46
+ host: 'localhost',
47
+ port: 6379,
48
+ password: process.env.REDIS_PASSWORD,
49
+ db: 0,
50
+ connectTimeout: 10000,
51
+ maxRetries: 10,
52
+ tls: false,
53
+ },
54
+ });
55
+ ```
56
+
57
+ ## API Reference
58
+
59
+ ### Basic Operations
60
+
61
+ #### `set<T>(key: string, value: T, options?): Promise<void>`
62
+
63
+ Store a value in cache with optional TTL.
64
+
65
+ ```typescript
66
+ await cache.set('user:123', { name: 'John', age: 30 });
67
+ await cache.set('session:abc', sessionData, { ttl: 1800 }); // 30 minutes
68
+ ```
69
+
70
+ #### `get<T>(key: string): Promise<T | null>`
71
+
72
+ Retrieve a value from cache.
73
+
74
+ ```typescript
75
+ const user = await cache.get<User>('user:123');
76
+ if (user) {
77
+ console.log(user.name);
78
+ }
79
+ ```
80
+
81
+ #### `delete(key: string): Promise<boolean>`
82
+
83
+ Delete a key from cache.
84
+
85
+ ```typescript
86
+ const deleted = await cache.delete('user:123');
87
+ ```
88
+
89
+ #### `exists(key: string): Promise<boolean>`
90
+
91
+ Check if a key exists.
92
+
93
+ ```typescript
94
+ const exists = await cache.exists('user:123');
95
+ ```
96
+
97
+ #### `clear(): Promise<void>`
98
+
99
+ Clear all keys with the configured prefix.
100
+
101
+ ```typescript
102
+ await cache.clear();
103
+ ```
104
+
105
+ ### Advanced Operations
106
+
107
+ #### `getOrSet<T>(key, factory, options?): Promise<T>`
108
+
109
+ Get from cache or compute and store.
110
+
111
+ ```typescript
112
+ const user = await cache.getOrSet(
113
+ 'user:123',
114
+ async () => await db.users.findById(123),
115
+ { ttl: 3600 }
116
+ );
117
+ ```
118
+
119
+ #### `mget<T>(keys: string[]): Promise<(T | null)[]>`
120
+
121
+ Get multiple keys at once.
122
+
123
+ ```typescript
124
+ const values = await cache.mget<string>(['key1', 'key2', 'key3']);
125
+ ```
126
+
127
+ #### `mset<T>(entries): Promise<void>`
128
+
129
+ Set multiple keys at once.
130
+
131
+ ```typescript
132
+ await cache.mset([
133
+ { key: 'key1', value: 'val1', ttl: 60 },
134
+ { key: 'key2', value: 'val2', ttl: 120 },
135
+ ]);
136
+ ```
137
+
138
+ #### `increment(key, delta?): Promise<number>`
139
+
140
+ Increment a counter.
141
+
142
+ ```typescript
143
+ const views = await cache.increment('page:views');
144
+ const score = await cache.increment('user:score', 10);
145
+ ```
146
+
147
+ #### `decrement(key, delta?): Promise<number>`
148
+
149
+ Decrement a counter.
150
+
151
+ ```typescript
152
+ const remaining = await cache.decrement('rate:limit');
153
+ ```
154
+
155
+ ### Statistics
156
+
157
+ #### `getStats(): CacheStats`
158
+
159
+ Get cache statistics.
160
+
161
+ ```typescript
162
+ const stats = cache.getStats();
163
+ console.log(`Hits: ${stats.hits}, Misses: ${stats.misses}`);
164
+ console.log(`Hit Rate: ${(stats.hits / (stats.hits + stats.misses) * 100).toFixed(2)}%`);
165
+ ```
166
+
167
+ ### Connection Management
168
+
169
+ #### `close(): Promise<void>`
170
+
171
+ Close Redis connection (for Redis provider only).
172
+
173
+ ```typescript
174
+ await cache.close();
175
+ ```
176
+
177
+ ## Migration from In-Memory
178
+
179
+ **Before (v0.1.0):**
180
+ ```typescript
181
+ // Placeholder Redis - not actually connected
182
+ const cache = new CacheService({ provider: 'redis', ... });
183
+ // Redis methods were placeholders
184
+ ```
185
+
186
+ **After (v0.2.0):**
187
+ ```typescript
188
+ // Real Redis connection with ioredis
189
+ const cache = new CacheService({ provider: 'redis', ... });
190
+ // Fully functional Redis operations
191
+ ```
192
+
193
+ ## Usage Examples
194
+
195
+ ### Session Caching
196
+
197
+ ```typescript
198
+ // Store session
199
+ await cache.set(\`session:\${sessionId}\`, sessionData, { ttl: 1800 });
200
+
201
+ // Retrieve session
202
+ const session = await cache.get<Session>(\`session:\${sessionId}\`);
203
+
204
+ // Delete session (logout)
205
+ await cache.delete(\`session:\${sessionId}\`);
206
+ ```
207
+
208
+ ### API Response Caching
209
+
210
+ ```typescript
211
+ async function getUsers() {
212
+ return cache.getOrSet(
213
+ 'api:users',
214
+ async () => await db.users.findAll(),
215
+ { ttl: 300 } // 5 minutes
216
+ );
217
+ }
218
+ ```
219
+
220
+ ### Rate Limiting
221
+
222
+ ```typescript
223
+ const key = \`rate:\${userId}:\${endpoint}\`;
224
+ const count = await cache.increment(key);
225
+
226
+ if (count === 1) {
227
+ await cache.set(key, count, { ttl: 60 }); // Reset after 1 minute
228
+ }
229
+
230
+ if (count > 100) {
231
+ throw new Error('Rate limit exceeded');
232
+ }
233
+ ```
234
+
235
+ ### Page View Counter
236
+
237
+ ```typescript
238
+ await cache.increment(\`page:\${pageId}:views\`);
239
+ const views = await cache.get<number>(\`page:\${pageId}:views\`) || 0;
240
+ ```
241
+
242
+ ## Environment Variables
243
+
244
+ ```bash
245
+ # Redis Configuration
246
+ REDIS_HOST=localhost
247
+ REDIS_PORT=6379
248
+ REDIS_PASSWORD=your_password
249
+ REDIS_DB=0
250
+ ```
251
+
252
+ ## Production Checklist
253
+
254
+ - [x] Redis client connected with ioredis
255
+ - [x] Connection retry strategy implemented
256
+ - [x] Error handling for Redis operations
257
+ - [ ] Redis instance deployed (Docker/Cloud)
258
+ - [ ] Connection pooling configured
259
+ - [ ] Monitoring and alerts set up
260
+ - [ ] Cache invalidation strategy defined
261
+ - [ ] TTL values optimized for use case
262
+
263
+ ## Performance Considerations
264
+
265
+ ### Redis vs Memory
266
+
267
+ | Feature | Memory | Redis |
268
+ |---------|--------|-------|
269
+ | Speed | Very Fast | Fast |
270
+ | Persistence | No | Yes |
271
+ | Multi-instance | No | Yes |
272
+ | Max Size | RAM limited | Disk limited |
273
+ | TTL Cleanup | Manual | Automatic |
274
+
275
+ ### Best Practices
276
+
277
+ 1. **Use appropriate TTLs**: Short for frequently changing data
278
+ 2. **Set maxSize for memory cache**: Prevent memory leaks
279
+ 3. **Use prefixes**: Namespace keys per module
280
+ 4. **Monitor hit rate**: Optimize caching strategy
281
+ 5. **Handle cache misses**: Always have a fallback
282
+
283
+ ## Troubleshooting
284
+
285
+ ### Redis connection failed
286
+
287
+ **Problem**: Can't connect to Redis server.
288
+
289
+ **Solution**:
290
+ 1. Check if Redis is running: `redis-cli ping`
291
+ 2. Verify host/port in config
292
+ 3. Check firewall rules
293
+ 4. Verify password if set
294
+
295
+ ### High memory usage
296
+
297
+ **Problem**: Memory cache consuming too much RAM.
298
+
299
+ **Solution**:
300
+ - Set `maxSize` in memory config
301
+ - Reduce TTL values
302
+ - Switch to Redis for large datasets
303
+
304
+ ### Low hit rate
305
+
306
+ **Problem**: Cache not being used effectively.
307
+
308
+ **Solution**:
309
+ - Increase TTL values
310
+ - Verify keys are consistent
311
+ - Check if data is too dynamic for caching
312
+
313
+ ## Testing
314
+
315
+ Run cache integration tests:
316
+ ```bash
317
+ # Ensure Redis is running
318
+ docker run -d -p 6379:6379 redis:7-alpine
319
+
320
+ # Run tests
321
+ npm test tests/integration/cache-redis.test.ts
322
+ ```
323
+
324
+ ## Related Modules
325
+
326
+ - **Auth Module**: Session caching
327
+ - **Rate Limit Module**: Request counting
328
+ - **API Module**: Response caching
329
+
330
+ ## Changelog
331
+
332
+ ### v0.2.0 (2025-12-19)
333
+
334
+ **CACHE-001 Completed:**
335
+ - ✅ Connected real Redis with ioredis
336
+ - ✅ Removed placeholder implementation
337
+ - ✅ Added connection retry strategy
338
+ - ✅ Added error handling and logging
339
+ - ✅ Added comprehensive integration tests
340
+ - ✅ Added this documentation
341
+
342
+ ### v0.1.0 (Initial)
343
+
344
+ - Placeholder Redis implementation
345
+ - Memory cache only functional
346
+ - No real Redis connection
@@ -0,0 +1,254 @@
1
+ # Email Module
2
+
3
+ SMTP email service with templates and common transactional emails.
4
+
5
+ ## Features
6
+
7
+ - **SMTP Support** - Works with any SMTP provider
8
+ - **Templates** - Built-in email templates
9
+ - **Auto Plain Text** - Generates plain text from HTML
10
+ - **Attachments** - Support for file attachments
11
+ - **Connection Verification** - Verify SMTP connection
12
+
13
+ ## Usage
14
+
15
+ ### Configuration
16
+
17
+ ```typescript
18
+ import { createEmailService } from 'servcraft/modules/email';
19
+
20
+ const emailService = createEmailService({
21
+ host: 'smtp.example.com',
22
+ port: 587,
23
+ auth: {
24
+ user: 'apikey',
25
+ pass: process.env.SMTP_PASSWORD!,
26
+ },
27
+ from: 'noreply@myapp.com',
28
+ });
29
+
30
+ // Verify connection
31
+ const isConnected = await emailService.verify();
32
+ ```
33
+
34
+ ### Sending Emails
35
+
36
+ ```typescript
37
+ // Simple email
38
+ const result = await emailService.send({
39
+ to: 'user@example.com',
40
+ subject: 'Hello!',
41
+ text: 'This is a plain text email.',
42
+ html: '<h1>Hello!</h1><p>This is an HTML email.</p>',
43
+ });
44
+
45
+ // Multiple recipients
46
+ await emailService.send({
47
+ to: ['user1@example.com', 'user2@example.com'],
48
+ cc: 'manager@example.com',
49
+ bcc: 'archive@example.com',
50
+ subject: 'Team Update',
51
+ html: '<p>Weekly update...</p>',
52
+ });
53
+
54
+ // With attachments
55
+ await emailService.send({
56
+ to: 'user@example.com',
57
+ subject: 'Your Invoice',
58
+ html: '<p>Please find your invoice attached.</p>',
59
+ attachments: [
60
+ {
61
+ filename: 'invoice.pdf',
62
+ path: '/path/to/invoice.pdf',
63
+ },
64
+ {
65
+ filename: 'data.json',
66
+ content: JSON.stringify(data),
67
+ },
68
+ ],
69
+ });
70
+ ```
71
+
72
+ ### Built-in Templates
73
+
74
+ ```typescript
75
+ // Welcome email
76
+ await emailService.sendWelcome(
77
+ 'user@example.com',
78
+ 'John',
79
+ 'https://myapp.com/verify?token=xyz'
80
+ );
81
+
82
+ // Email verification
83
+ await emailService.sendVerifyEmail(
84
+ 'user@example.com',
85
+ 'John',
86
+ 'https://myapp.com/verify?token=xyz'
87
+ );
88
+
89
+ // Password reset
90
+ await emailService.sendPasswordReset(
91
+ 'user@example.com',
92
+ 'John',
93
+ 'https://myapp.com/reset?token=xyz'
94
+ );
95
+
96
+ // Password changed notification
97
+ await emailService.sendPasswordChanged(
98
+ 'user@example.com',
99
+ 'John',
100
+ '192.168.1.1',
101
+ 'Chrome on Windows'
102
+ );
103
+
104
+ // Login alert
105
+ await emailService.sendLoginAlert(
106
+ 'user@example.com',
107
+ 'John',
108
+ '192.168.1.1',
109
+ 'Chrome on Windows',
110
+ 'New York, US'
111
+ );
112
+ ```
113
+
114
+ ### Custom Templates
115
+
116
+ ```typescript
117
+ // Using template with data
118
+ await emailService.send({
119
+ to: 'user@example.com',
120
+ subject: 'Order Confirmation',
121
+ template: 'order-confirmation',
122
+ data: {
123
+ orderId: 'ORD-123',
124
+ userName: 'John',
125
+ total: '$99.99',
126
+ items: [
127
+ { name: 'Product 1', price: '$49.99' },
128
+ { name: 'Product 2', price: '$50.00' },
129
+ ],
130
+ },
131
+ });
132
+ ```
133
+
134
+ ## Configuration Types
135
+
136
+ ```typescript
137
+ interface EmailConfig {
138
+ host: string;
139
+ port: number;
140
+ secure?: boolean; // true for 465, false for other ports
141
+ auth: {
142
+ user: string;
143
+ pass: string;
144
+ };
145
+ from: string;
146
+ }
147
+
148
+ interface EmailOptions {
149
+ to: string | string[];
150
+ subject: string;
151
+ text?: string;
152
+ html?: string;
153
+ template?: string;
154
+ data?: TemplateData;
155
+ replyTo?: string;
156
+ cc?: string | string[];
157
+ bcc?: string | string[];
158
+ attachments?: Attachment[];
159
+ }
160
+
161
+ interface EmailResult {
162
+ success: boolean;
163
+ messageId?: string;
164
+ error?: string;
165
+ }
166
+ ```
167
+
168
+ ## Built-in Template Variables
169
+
170
+ | Template | Variables |
171
+ |----------|-----------|
172
+ | `welcome` | `userName`, `userEmail`, `actionUrl`, `appName` |
173
+ | `verify-email` | `userName`, `userEmail`, `actionUrl`, `expiresIn` |
174
+ | `password-reset` | `userName`, `userEmail`, `actionUrl`, `expiresIn` |
175
+ | `password-changed` | `userName`, `ipAddress`, `userAgent`, `timestamp` |
176
+ | `login-alert` | `userName`, `ipAddress`, `userAgent`, `location`, `timestamp` |
177
+
178
+ ## Provider Examples
179
+
180
+ ### SendGrid SMTP
181
+
182
+ ```typescript
183
+ const emailService = createEmailService({
184
+ host: 'smtp.sendgrid.net',
185
+ port: 587,
186
+ auth: {
187
+ user: 'apikey',
188
+ pass: process.env.SENDGRID_API_KEY!,
189
+ },
190
+ from: 'noreply@myapp.com',
191
+ });
192
+ ```
193
+
194
+ ### Gmail SMTP
195
+
196
+ ```typescript
197
+ const emailService = createEmailService({
198
+ host: 'smtp.gmail.com',
199
+ port: 587,
200
+ auth: {
201
+ user: 'your-email@gmail.com',
202
+ pass: process.env.GMAIL_APP_PASSWORD!, // Use App Password
203
+ },
204
+ from: 'your-email@gmail.com',
205
+ });
206
+ ```
207
+
208
+ ### Amazon SES SMTP
209
+
210
+ ```typescript
211
+ const emailService = createEmailService({
212
+ host: 'email-smtp.us-east-1.amazonaws.com',
213
+ port: 587,
214
+ auth: {
215
+ user: process.env.AWS_SES_SMTP_USER!,
216
+ pass: process.env.AWS_SES_SMTP_PASS!,
217
+ },
218
+ from: 'noreply@myapp.com',
219
+ });
220
+ ```
221
+
222
+ ### Mailgun SMTP
223
+
224
+ ```typescript
225
+ const emailService = createEmailService({
226
+ host: 'smtp.mailgun.org',
227
+ port: 587,
228
+ auth: {
229
+ user: 'postmaster@mg.myapp.com',
230
+ pass: process.env.MAILGUN_SMTP_PASSWORD!,
231
+ },
232
+ from: 'noreply@myapp.com',
233
+ });
234
+ ```
235
+
236
+ ## Development Mode
237
+
238
+ If no SMTP configuration is provided, emails are logged instead of sent:
239
+
240
+ ```typescript
241
+ const emailService = createEmailService({}); // No config
242
+ await emailService.send({ to: 'test@example.com', subject: 'Test' });
243
+ // Logs: "Email would be sent (no transporter configured)"
244
+ // Returns: { success: true, messageId: 'dev-mode' }
245
+ ```
246
+
247
+ ## Best Practices
248
+
249
+ 1. **Use Templates** - Consistent branding and easier maintenance
250
+ 2. **Plain Text Fallback** - Always include plain text version
251
+ 3. **Verify Connection** - Check SMTP connection on startup
252
+ 4. **Handle Failures** - Implement retry logic for failed emails
253
+ 5. **Rate Limiting** - Respect provider rate limits
254
+ 6. **SPF/DKIM** - Configure DNS records for deliverability