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,111 @@
1
+ import { Router } from 'express';
2
+ import type { Request, Response } from 'express';
3
+ import type { MediaProcessingService } from './media-processing.service.js';
4
+ import type { ImageOperation, VideoOperation, MediaType, ThumbnailOptions } from './types.js';
5
+
6
+ /**
7
+ * Create media processing routes
8
+ */
9
+ export function createMediaProcessingRoutes(mediaService: MediaProcessingService): Router {
10
+ const router = Router();
11
+
12
+ /**
13
+ * Process image
14
+ * POST /image
15
+ */
16
+ router.post('/image', async (req: Request, res: Response) => {
17
+ const { source, output, operations } = req.body as {
18
+ source: string;
19
+ output: string;
20
+ operations: ImageOperation[];
21
+ };
22
+
23
+ const result = await mediaService.processImage(source, output, operations);
24
+ res.json(result);
25
+ });
26
+
27
+ /**
28
+ * Process video
29
+ * POST /video
30
+ */
31
+ router.post('/video', async (req: Request, res: Response) => {
32
+ const { source, output, operations } = req.body as {
33
+ source: string;
34
+ output: string;
35
+ operations: VideoOperation[];
36
+ };
37
+
38
+ const result = await mediaService.processVideo(source, output, operations);
39
+ res.json(result);
40
+ });
41
+
42
+ /**
43
+ * Create processing job
44
+ * POST /jobs
45
+ */
46
+ router.post('/jobs', async (req: Request, res: Response) => {
47
+ const { mediaType, source, output, operations } = req.body as {
48
+ mediaType: MediaType;
49
+ source: string;
50
+ output: string;
51
+ operations: (ImageOperation | VideoOperation)[];
52
+ };
53
+
54
+ const job = await mediaService.createJob(mediaType, source, output, operations);
55
+ res.status(201).json(job);
56
+ });
57
+
58
+ /**
59
+ * Get job status
60
+ * GET /jobs/:id
61
+ */
62
+ router.get('/jobs/:id', async (req: Request, res: Response) => {
63
+ const jobId = req.params.id;
64
+ if (!jobId) {
65
+ res.status(400).json({ error: 'Job ID is required' });
66
+ return;
67
+ }
68
+
69
+ const job = await mediaService.getJob(jobId);
70
+
71
+ if (!job) {
72
+ res.status(404).json({ error: 'Job not found' });
73
+ return;
74
+ }
75
+
76
+ res.json(job);
77
+ });
78
+
79
+ /**
80
+ * Get media info
81
+ * POST /info
82
+ */
83
+ router.post('/info', async (req: Request, res: Response) => {
84
+ const { filePath } = req.body as { filePath: string };
85
+
86
+ if (!filePath) {
87
+ res.status(400).json({ error: 'filePath is required' });
88
+ return;
89
+ }
90
+
91
+ const info = await mediaService.getMediaInfo(filePath);
92
+ res.json(info);
93
+ });
94
+
95
+ /**
96
+ * Generate thumbnail
97
+ * POST /thumbnail
98
+ */
99
+ router.post('/thumbnail', async (req: Request, res: Response) => {
100
+ const { source, output, options } = req.body as {
101
+ source: string;
102
+ output: string;
103
+ options?: ThumbnailOptions;
104
+ };
105
+
106
+ const result = await mediaService.generateThumbnail(source, output, options);
107
+ res.json(result);
108
+ });
109
+
110
+ return router;
111
+ }
@@ -0,0 +1,245 @@
1
+ import { logger } from '../../core/logger.js';
2
+ import { randomUUID } from 'crypto';
3
+ import type {
4
+ MediaProcessingConfig,
5
+ ProcessingJob,
6
+ ImageOperation,
7
+ VideoOperation,
8
+ MediaInfo,
9
+ ThumbnailOptions,
10
+ ProcessingResult,
11
+ MediaType,
12
+ } from './types.js';
13
+
14
+ /**
15
+ * Media Processing Service
16
+ * Image and video processing with FFmpeg
17
+ */
18
+ export class MediaProcessingService {
19
+ private config: MediaProcessingConfig;
20
+ private jobs = new Map<string, ProcessingJob>();
21
+ private queue: ProcessingJob[] = [];
22
+ private processing = 0;
23
+
24
+ constructor(config: MediaProcessingConfig = {}) {
25
+ this.config = {
26
+ ffmpegPath: 'ffmpeg',
27
+ ffprobePath: 'ffprobe',
28
+ tempDir: './temp',
29
+ maxConcurrent: 3,
30
+ gpuAcceleration: false,
31
+ ...config,
32
+ };
33
+
34
+ logger.info('Media processing service initialized');
35
+ }
36
+
37
+ /**
38
+ * Process image
39
+ */
40
+ async processImage(
41
+ source: string,
42
+ output: string,
43
+ operations: ImageOperation[]
44
+ ): Promise<ProcessingResult> {
45
+ const startTime = Date.now();
46
+
47
+ try {
48
+ // Note: In production, use Sharp library for image processing
49
+ // This is a placeholder implementation
50
+ logger.info({ source, output, operations }, 'Processing image');
51
+
52
+ // Simulate processing
53
+ await this.simulateProcessing();
54
+
55
+ return {
56
+ success: true,
57
+ outputPath: output,
58
+ processingTime: Date.now() - startTime,
59
+ };
60
+ } catch (error) {
61
+ logger.error({ source, error }, 'Image processing failed');
62
+ return {
63
+ success: false,
64
+ processingTime: Date.now() - startTime,
65
+ error: error instanceof Error ? error.message : 'Processing failed',
66
+ };
67
+ }
68
+ }
69
+
70
+ /**
71
+ * Process video
72
+ */
73
+ async processVideo(
74
+ source: string,
75
+ output: string,
76
+ operations: VideoOperation[]
77
+ ): Promise<ProcessingResult> {
78
+ const startTime = Date.now();
79
+
80
+ try {
81
+ // Note: In production, use fluent-ffmpeg or node-ffmpeg
82
+ logger.info({ source, output, operations }, 'Processing video');
83
+
84
+ // Simulate processing
85
+ await this.simulateProcessing();
86
+
87
+ return {
88
+ success: true,
89
+ outputPath: output,
90
+ processingTime: Date.now() - startTime,
91
+ };
92
+ } catch (error) {
93
+ logger.error({ source, error }, 'Video processing failed');
94
+ return {
95
+ success: false,
96
+ processingTime: Date.now() - startTime,
97
+ error: error instanceof Error ? error.message : 'Processing failed',
98
+ };
99
+ }
100
+ }
101
+
102
+ /**
103
+ * Create job
104
+ */
105
+ async createJob(
106
+ mediaType: MediaType,
107
+ source: string,
108
+ output: string,
109
+ operations: (ImageOperation | VideoOperation)[]
110
+ ): Promise<ProcessingJob> {
111
+ const job: ProcessingJob = {
112
+ id: randomUUID(),
113
+ mediaType,
114
+ source,
115
+ output,
116
+ operations,
117
+ status: 'pending',
118
+ progress: 0,
119
+ createdAt: new Date(),
120
+ };
121
+
122
+ this.jobs.set(job.id, job);
123
+ this.queue.push(job);
124
+
125
+ this.processQueue();
126
+
127
+ logger.info({ jobId: job.id }, 'Processing job created');
128
+
129
+ return job;
130
+ }
131
+
132
+ /**
133
+ * Get job status
134
+ */
135
+ async getJob(jobId: string): Promise<ProcessingJob | null> {
136
+ return this.jobs.get(jobId) || null;
137
+ }
138
+
139
+ /**
140
+ * Get media info
141
+ */
142
+ async getMediaInfo(filePath: string): Promise<MediaInfo> {
143
+ // Note: In production, use ffprobe
144
+ logger.info({ filePath }, 'Getting media info');
145
+
146
+ return {
147
+ path: filePath,
148
+ type: 'image',
149
+ format: 'jpeg',
150
+ size: 0,
151
+ width: 1920,
152
+ height: 1080,
153
+ };
154
+ }
155
+
156
+ /**
157
+ * Generate thumbnail
158
+ */
159
+ async generateThumbnail(
160
+ source: string,
161
+ output: string,
162
+ options: ThumbnailOptions = {}
163
+ ): Promise<ProcessingResult> {
164
+ const startTime = Date.now();
165
+
166
+ try {
167
+ logger.info({ source, output, options }, 'Generating thumbnail');
168
+
169
+ // Simulate processing
170
+ await this.simulateProcessing();
171
+
172
+ return {
173
+ success: true,
174
+ outputPath: output,
175
+ processingTime: Date.now() - startTime,
176
+ };
177
+ } catch (error) {
178
+ return {
179
+ success: false,
180
+ processingTime: Date.now() - startTime,
181
+ error: error instanceof Error ? error.message : 'Thumbnail generation failed',
182
+ };
183
+ }
184
+ }
185
+
186
+ /**
187
+ * Process queue
188
+ */
189
+ private async processQueue(): Promise<void> {
190
+ if (this.processing >= (this.config.maxConcurrent || 3)) {
191
+ return;
192
+ }
193
+
194
+ const job = this.queue.shift();
195
+ if (!job) {
196
+ return;
197
+ }
198
+
199
+ this.processing++;
200
+ job.status = 'processing';
201
+
202
+ try {
203
+ let result: ProcessingResult;
204
+
205
+ if (job.mediaType === 'image') {
206
+ result = await this.processImage(
207
+ job.source,
208
+ job.output,
209
+ job.operations as ImageOperation[]
210
+ );
211
+ } else if (job.mediaType === 'video') {
212
+ result = await this.processVideo(
213
+ job.source,
214
+ job.output,
215
+ job.operations as VideoOperation[]
216
+ );
217
+ } else {
218
+ throw new Error('Unsupported media type');
219
+ }
220
+
221
+ job.status = result.success ? 'completed' : 'failed';
222
+ job.progress = 100;
223
+ job.completedAt = new Date();
224
+ job.processingTime = result.processingTime;
225
+
226
+ if (!result.success) {
227
+ job.error = result.error;
228
+ }
229
+ } catch (error) {
230
+ job.status = 'failed';
231
+ job.error = error instanceof Error ? error.message : 'Processing failed';
232
+ job.completedAt = new Date();
233
+ }
234
+
235
+ this.processing--;
236
+ this.processQueue();
237
+ }
238
+
239
+ /**
240
+ * Simulate processing (placeholder)
241
+ */
242
+ private async simulateProcessing(): Promise<void> {
243
+ return new Promise((resolve) => setTimeout(resolve, 100));
244
+ }
245
+ }
@@ -0,0 +1,156 @@
1
+ export type MediaType = 'image' | 'video' | 'audio';
2
+ export type ImageFormat = 'jpeg' | 'png' | 'webp' | 'gif' | 'avif';
3
+ export type VideoFormat = 'mp4' | 'webm' | 'avi' | 'mov';
4
+ export type AudioFormat = 'mp3' | 'wav' | 'ogg' | 'aac';
5
+
6
+ export interface MediaProcessingConfig {
7
+ /** FFmpeg path */
8
+ ffmpegPath?: string;
9
+ /** FFprobe path */
10
+ ffprobePath?: string;
11
+ /** Temporary directory */
12
+ tempDir?: string;
13
+ /** Max concurrent jobs */
14
+ maxConcurrent?: number;
15
+ /** Enable GPU acceleration */
16
+ gpuAcceleration?: boolean;
17
+ }
18
+
19
+ export interface ImageOperation {
20
+ type: 'resize' | 'crop' | 'rotate' | 'flip' | 'watermark' | 'compress' | 'filter';
21
+ options: ImageOperationOptions;
22
+ }
23
+
24
+ export interface ImageOperationOptions {
25
+ // Resize
26
+ width?: number;
27
+ height?: number;
28
+ fit?: 'cover' | 'contain' | 'fill' | 'inside' | 'outside';
29
+
30
+ // Crop
31
+ x?: number;
32
+ y?: number;
33
+
34
+ // Rotate
35
+ angle?: number;
36
+
37
+ // Flip
38
+ direction?: 'horizontal' | 'vertical';
39
+
40
+ // Watermark
41
+ text?: string;
42
+ image?: string;
43
+ position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'center';
44
+ opacity?: number;
45
+
46
+ // Compress
47
+ quality?: number;
48
+
49
+ // Filter
50
+ filter?: 'grayscale' | 'blur' | 'sharpen' | 'sepia' | 'brightness' | 'contrast';
51
+ intensity?: number;
52
+ }
53
+
54
+ export interface VideoOperation {
55
+ type: 'trim' | 'resize' | 'compress' | 'extract-audio' | 'add-subtitle' | 'thumbnail';
56
+ options: VideoOperationOptions;
57
+ }
58
+
59
+ export interface VideoOperationOptions {
60
+ // Trim
61
+ startTime?: string;
62
+ endTime?: string;
63
+ duration?: string;
64
+
65
+ // Resize
66
+ width?: number;
67
+ height?: number;
68
+ scale?: string;
69
+
70
+ // Compress
71
+ bitrate?: string;
72
+ crf?: number;
73
+
74
+ // Thumbnail
75
+ timestamp?: string;
76
+ count?: number;
77
+
78
+ // Subtitle
79
+ subtitleFile?: string;
80
+ }
81
+
82
+ export interface ProcessingJob {
83
+ /** Job ID */
84
+ id: string;
85
+ /** Media type */
86
+ mediaType: MediaType;
87
+ /** Source file path */
88
+ source: string;
89
+ /** Output file path */
90
+ output: string;
91
+ /** Operations to perform */
92
+ operations: (ImageOperation | VideoOperation)[];
93
+ /** Job status */
94
+ status: 'pending' | 'processing' | 'completed' | 'failed';
95
+ /** Progress (0-100) */
96
+ progress: number;
97
+ /** Error message */
98
+ error?: string;
99
+ /** Created at */
100
+ createdAt: Date;
101
+ /** Completed at */
102
+ completedAt?: Date;
103
+ /** Processing time (ms) */
104
+ processingTime?: number;
105
+ }
106
+
107
+ export interface MediaInfo {
108
+ /** File path */
109
+ path: string;
110
+ /** Media type */
111
+ type: MediaType;
112
+ /** Format */
113
+ format: string;
114
+ /** Duration (for video/audio) */
115
+ duration?: number;
116
+ /** Width (for image/video) */
117
+ width?: number;
118
+ /** Height (for image/video) */
119
+ height?: number;
120
+ /** Bitrate */
121
+ bitrate?: number;
122
+ /** File size in bytes */
123
+ size: number;
124
+ /** Codec */
125
+ codec?: string;
126
+ /** Frame rate (for video) */
127
+ fps?: number;
128
+ /** Metadata */
129
+ metadata?: Record<string, unknown>;
130
+ }
131
+
132
+ export interface ThumbnailOptions {
133
+ /** Timestamp for video (e.g., '00:00:05') */
134
+ timestamp?: string;
135
+ /** Width */
136
+ width?: number;
137
+ /** Height */
138
+ height?: number;
139
+ /** Format */
140
+ format?: ImageFormat;
141
+ /** Quality (1-100) */
142
+ quality?: number;
143
+ }
144
+
145
+ export interface ProcessingResult {
146
+ /** Success status */
147
+ success: boolean;
148
+ /** Output file path */
149
+ outputPath?: string;
150
+ /** Processing time (ms) */
151
+ processingTime: number;
152
+ /** File size */
153
+ size?: number;
154
+ /** Error message */
155
+ error?: string;
156
+ }
@@ -0,0 +1,20 @@
1
+ export { MFAService, getMFAService, createMFAService } from './mfa.service.js';
2
+ export { registerMFARoutes } from './mfa.routes.js';
3
+ export {
4
+ generateSecret,
5
+ generateTOTP,
6
+ verifyTOTP,
7
+ generateTOTPUri,
8
+ generateQRCode,
9
+ formatSecretForDisplay,
10
+ getRemainingSeconds,
11
+ } from './totp.js';
12
+ export type {
13
+ MFAConfig,
14
+ MFAMethod,
15
+ UserMFA,
16
+ TOTPSetup,
17
+ MFAChallenge,
18
+ MFAVerifyResult,
19
+ BackupCodesResult,
20
+ } from './types.js';