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.
- package/.claude/settings.local.json +29 -0
- package/.github/CODEOWNERS +18 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +46 -0
- package/.github/dependabot.yml +59 -0
- package/.github/workflows/ci.yml +188 -0
- package/.github/workflows/release.yml +195 -0
- package/AUDIT.md +602 -0
- package/README.md +1070 -1
- package/dist/cli/index.cjs +2026 -2168
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +2026 -2168
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +595 -616
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +114 -52
- package/dist/index.d.ts +114 -52
- package/dist/index.js +595 -616
- package/dist/index.js.map +1 -1
- package/docs/CLI-001_MULTI_DB_PLAN.md +546 -0
- package/docs/DATABASE_MULTI_ORM.md +399 -0
- package/docs/PHASE1_BREAKDOWN.md +346 -0
- package/docs/PROGRESS.md +550 -0
- package/docs/modules/ANALYTICS.md +226 -0
- package/docs/modules/API-VERSIONING.md +252 -0
- package/docs/modules/AUDIT.md +192 -0
- package/docs/modules/AUTH.md +431 -0
- package/docs/modules/CACHE.md +346 -0
- package/docs/modules/EMAIL.md +254 -0
- package/docs/modules/FEATURE-FLAG.md +291 -0
- package/docs/modules/I18N.md +294 -0
- package/docs/modules/MEDIA-PROCESSING.md +281 -0
- package/docs/modules/MFA.md +266 -0
- package/docs/modules/NOTIFICATION.md +311 -0
- package/docs/modules/OAUTH.md +237 -0
- package/docs/modules/PAYMENT.md +804 -0
- package/docs/modules/QUEUE.md +540 -0
- package/docs/modules/RATE-LIMIT.md +339 -0
- package/docs/modules/SEARCH.md +288 -0
- package/docs/modules/SECURITY.md +327 -0
- package/docs/modules/SESSION.md +382 -0
- package/docs/modules/SWAGGER.md +305 -0
- package/docs/modules/UPLOAD.md +296 -0
- package/docs/modules/USER.md +505 -0
- package/docs/modules/VALIDATION.md +294 -0
- package/docs/modules/WEBHOOK.md +270 -0
- package/docs/modules/WEBSOCKET.md +691 -0
- package/package.json +53 -38
- package/prisma/schema.prisma +395 -1
- package/src/cli/commands/add-module.ts +520 -87
- package/src/cli/commands/db.ts +3 -4
- package/src/cli/commands/docs.ts +256 -6
- package/src/cli/commands/generate.ts +12 -19
- package/src/cli/commands/init.ts +384 -214
- package/src/cli/index.ts +0 -4
- package/src/cli/templates/repository.ts +6 -1
- package/src/cli/templates/routes.ts +6 -21
- package/src/cli/utils/docs-generator.ts +6 -7
- package/src/cli/utils/env-manager.ts +717 -0
- package/src/cli/utils/field-parser.ts +16 -7
- package/src/cli/utils/interactive-prompt.ts +223 -0
- package/src/cli/utils/template-manager.ts +346 -0
- package/src/config/database.config.ts +183 -0
- package/src/config/env.ts +0 -10
- package/src/config/index.ts +0 -14
- package/src/core/server.ts +1 -1
- package/src/database/adapters/mongoose.adapter.ts +132 -0
- package/src/database/adapters/prisma.adapter.ts +118 -0
- package/src/database/connection.ts +190 -0
- package/src/database/interfaces/database.interface.ts +85 -0
- package/src/database/interfaces/index.ts +7 -0
- package/src/database/interfaces/repository.interface.ts +129 -0
- package/src/database/models/mongoose/index.ts +7 -0
- package/src/database/models/mongoose/payment.schema.ts +347 -0
- package/src/database/models/mongoose/user.schema.ts +154 -0
- package/src/database/prisma.ts +1 -4
- package/src/database/redis.ts +101 -0
- package/src/database/repositories/mongoose/index.ts +7 -0
- package/src/database/repositories/mongoose/payment.repository.ts +380 -0
- package/src/database/repositories/mongoose/user.repository.ts +255 -0
- package/src/database/seed.ts +6 -1
- package/src/index.ts +9 -20
- package/src/middleware/security.ts +2 -6
- package/src/modules/analytics/analytics.routes.ts +80 -0
- package/src/modules/analytics/analytics.service.ts +364 -0
- package/src/modules/analytics/index.ts +18 -0
- package/src/modules/analytics/types.ts +180 -0
- package/src/modules/api-versioning/index.ts +15 -0
- package/src/modules/api-versioning/types.ts +86 -0
- package/src/modules/api-versioning/versioning.middleware.ts +120 -0
- package/src/modules/api-versioning/versioning.routes.ts +54 -0
- package/src/modules/api-versioning/versioning.service.ts +189 -0
- package/src/modules/audit/audit.repository.ts +206 -0
- package/src/modules/audit/audit.service.ts +27 -59
- package/src/modules/auth/auth.controller.ts +2 -2
- package/src/modules/auth/auth.middleware.ts +3 -9
- package/src/modules/auth/auth.routes.ts +10 -107
- package/src/modules/auth/auth.service.ts +126 -23
- package/src/modules/auth/index.ts +3 -4
- package/src/modules/cache/cache.service.ts +367 -0
- package/src/modules/cache/index.ts +10 -0
- package/src/modules/cache/types.ts +44 -0
- package/src/modules/email/email.service.ts +3 -10
- package/src/modules/email/templates.ts +2 -8
- package/src/modules/feature-flag/feature-flag.repository.ts +303 -0
- package/src/modules/feature-flag/feature-flag.routes.ts +247 -0
- package/src/modules/feature-flag/feature-flag.service.ts +566 -0
- package/src/modules/feature-flag/index.ts +20 -0
- package/src/modules/feature-flag/types.ts +192 -0
- package/src/modules/i18n/i18n.middleware.ts +186 -0
- package/src/modules/i18n/i18n.routes.ts +191 -0
- package/src/modules/i18n/i18n.service.ts +456 -0
- package/src/modules/i18n/index.ts +18 -0
- package/src/modules/i18n/types.ts +118 -0
- package/src/modules/media-processing/index.ts +17 -0
- package/src/modules/media-processing/media-processing.routes.ts +111 -0
- package/src/modules/media-processing/media-processing.service.ts +245 -0
- package/src/modules/media-processing/types.ts +156 -0
- package/src/modules/mfa/index.ts +20 -0
- package/src/modules/mfa/mfa.repository.ts +206 -0
- package/src/modules/mfa/mfa.routes.ts +595 -0
- package/src/modules/mfa/mfa.service.ts +572 -0
- package/src/modules/mfa/totp.ts +150 -0
- package/src/modules/mfa/types.ts +57 -0
- package/src/modules/notification/index.ts +20 -0
- package/src/modules/notification/notification.repository.ts +356 -0
- package/src/modules/notification/notification.service.ts +483 -0
- package/src/modules/notification/types.ts +119 -0
- package/src/modules/oauth/index.ts +20 -0
- package/src/modules/oauth/oauth.repository.ts +219 -0
- package/src/modules/oauth/oauth.routes.ts +446 -0
- package/src/modules/oauth/oauth.service.ts +293 -0
- package/src/modules/oauth/providers/apple.provider.ts +250 -0
- package/src/modules/oauth/providers/facebook.provider.ts +181 -0
- package/src/modules/oauth/providers/github.provider.ts +248 -0
- package/src/modules/oauth/providers/google.provider.ts +189 -0
- package/src/modules/oauth/providers/twitter.provider.ts +214 -0
- package/src/modules/oauth/types.ts +94 -0
- package/src/modules/payment/index.ts +19 -0
- package/src/modules/payment/payment.repository.ts +733 -0
- package/src/modules/payment/payment.routes.ts +390 -0
- package/src/modules/payment/payment.service.ts +354 -0
- package/src/modules/payment/providers/mobile-money.provider.ts +274 -0
- package/src/modules/payment/providers/paypal.provider.ts +190 -0
- package/src/modules/payment/providers/stripe.provider.ts +215 -0
- package/src/modules/payment/types.ts +140 -0
- package/src/modules/queue/cron.ts +438 -0
- package/src/modules/queue/index.ts +87 -0
- package/src/modules/queue/queue.routes.ts +600 -0
- package/src/modules/queue/queue.service.ts +842 -0
- package/src/modules/queue/types.ts +222 -0
- package/src/modules/queue/workers.ts +366 -0
- package/src/modules/rate-limit/index.ts +59 -0
- package/src/modules/rate-limit/rate-limit.middleware.ts +134 -0
- package/src/modules/rate-limit/rate-limit.routes.ts +269 -0
- package/src/modules/rate-limit/rate-limit.service.ts +348 -0
- package/src/modules/rate-limit/stores/memory.store.ts +165 -0
- package/src/modules/rate-limit/stores/redis.store.ts +322 -0
- package/src/modules/rate-limit/types.ts +153 -0
- package/src/modules/search/adapters/elasticsearch.adapter.ts +326 -0
- package/src/modules/search/adapters/meilisearch.adapter.ts +261 -0
- package/src/modules/search/adapters/memory.adapter.ts +278 -0
- package/src/modules/search/index.ts +21 -0
- package/src/modules/search/search.service.ts +234 -0
- package/src/modules/search/types.ts +214 -0
- package/src/modules/security/index.ts +40 -0
- package/src/modules/security/sanitize.ts +223 -0
- package/src/modules/security/security-audit.service.ts +388 -0
- package/src/modules/security/security.middleware.ts +398 -0
- package/src/modules/session/index.ts +3 -0
- package/src/modules/session/session.repository.ts +159 -0
- package/src/modules/session/session.service.ts +340 -0
- package/src/modules/session/types.ts +38 -0
- package/src/modules/swagger/index.ts +7 -1
- package/src/modules/swagger/schema-builder.ts +16 -4
- package/src/modules/swagger/swagger.service.ts +9 -10
- package/src/modules/swagger/types.ts +0 -2
- package/src/modules/upload/index.ts +14 -0
- package/src/modules/upload/types.ts +83 -0
- package/src/modules/upload/upload.repository.ts +199 -0
- package/src/modules/upload/upload.routes.ts +311 -0
- package/src/modules/upload/upload.service.ts +448 -0
- package/src/modules/user/index.ts +3 -3
- package/src/modules/user/user.controller.ts +15 -9
- package/src/modules/user/user.repository.ts +237 -113
- package/src/modules/user/user.routes.ts +39 -164
- package/src/modules/user/user.service.ts +4 -3
- package/src/modules/validation/validator.ts +12 -17
- package/src/modules/webhook/index.ts +91 -0
- package/src/modules/webhook/retry.ts +196 -0
- package/src/modules/webhook/signature.ts +135 -0
- package/src/modules/webhook/types.ts +181 -0
- package/src/modules/webhook/webhook.repository.ts +358 -0
- package/src/modules/webhook/webhook.routes.ts +442 -0
- package/src/modules/webhook/webhook.service.ts +457 -0
- package/src/modules/websocket/features.ts +504 -0
- package/src/modules/websocket/index.ts +106 -0
- package/src/modules/websocket/middlewares.ts +298 -0
- package/src/modules/websocket/types.ts +181 -0
- package/src/modules/websocket/websocket.service.ts +692 -0
- package/src/utils/errors.ts +7 -0
- package/src/utils/pagination.ts +4 -1
- package/tests/helpers/db-check.ts +79 -0
- package/tests/integration/auth-redis.test.ts +94 -0
- package/tests/integration/cache-redis.test.ts +387 -0
- package/tests/integration/mongoose-repositories.test.ts +410 -0
- package/tests/integration/payment-prisma.test.ts +637 -0
- package/tests/integration/queue-bullmq.test.ts +417 -0
- package/tests/integration/user-prisma.test.ts +441 -0
- package/tests/integration/websocket-socketio.test.ts +552 -0
- package/tests/setup.ts +11 -9
- package/vitest.config.ts +3 -8
- package/npm-cache/_cacache/content-v2/sha512/1c/d0/03440d500a0487621aad1d6402978340698976602046db8e24fa03c01ee6c022c69b0582f969042d9442ee876ac35c038e960dd427d1e622fa24b8eb7dba +0 -0
- package/npm-cache/_cacache/content-v2/sha512/42/55/28b493ca491833e5aab0e9c3108d29ab3f36c248ca88f45d4630674fce9130959e56ae308797ac2b6328fa7f09a610b9550ed09cb971d039876d293fc69d +0 -0
- package/npm-cache/_cacache/content-v2/sha512/e0/12/f360dc9315ee5f17844a0c8c233ee6bf7c30837c4a02ea0d56c61c7f7ab21c0e958e50ed2c57c59f983c762b93056778c9009b2398ffc26def0183999b13 +0 -0
- package/npm-cache/_cacache/content-v2/sha512/ed/b0/fae1161902898f4c913c67d7f6cdf6be0665aec3b389b9c4f4f0a101ca1da59badf1b59c4e0030f5223023b8d63cfe501c46a32c20c895d4fb3f11ca2232 +0 -0
- package/npm-cache/_cacache/index-v5/58/94/c2cba79e0f16b4c10e95a87e32255741149e8222cc314a476aab67c39cc0 +0 -5
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify';
|
|
2
2
|
import pino, { Logger } from 'pino';
|
|
3
3
|
export { Logger } from 'pino';
|
|
4
|
-
import { z,
|
|
4
|
+
import { z, ZodSchema } from 'zod';
|
|
5
5
|
|
|
6
6
|
interface LoggerConfig {
|
|
7
7
|
level: string;
|
|
@@ -50,11 +50,6 @@ declare const envSchema: z.ZodObject<{
|
|
|
50
50
|
SMTP_PASS: z.ZodOptional<z.ZodString>;
|
|
51
51
|
SMTP_FROM: z.ZodOptional<z.ZodString>;
|
|
52
52
|
REDIS_URL: z.ZodOptional<z.ZodString>;
|
|
53
|
-
SWAGGER_ENABLED: z.ZodEffects<z.ZodDefault<z.ZodUnion<[z.ZodLiteral<"true">, z.ZodLiteral<"false">]>>, boolean, "true" | "false" | undefined>;
|
|
54
|
-
SWAGGER_ROUTE: z.ZodDefault<z.ZodString>;
|
|
55
|
-
SWAGGER_TITLE: z.ZodDefault<z.ZodString>;
|
|
56
|
-
SWAGGER_DESCRIPTION: z.ZodDefault<z.ZodString>;
|
|
57
|
-
SWAGGER_VERSION: z.ZodDefault<z.ZodString>;
|
|
58
53
|
LOG_LEVEL: z.ZodDefault<z.ZodEnum<["fatal", "error", "warn", "info", "debug", "trace"]>>;
|
|
59
54
|
}, "strip", z.ZodTypeAny, {
|
|
60
55
|
NODE_ENV: "development" | "staging" | "production" | "test";
|
|
@@ -65,11 +60,6 @@ declare const envSchema: z.ZodObject<{
|
|
|
65
60
|
CORS_ORIGIN: string;
|
|
66
61
|
RATE_LIMIT_MAX: number;
|
|
67
62
|
RATE_LIMIT_WINDOW_MS: number;
|
|
68
|
-
SWAGGER_ENABLED: boolean;
|
|
69
|
-
SWAGGER_ROUTE: string;
|
|
70
|
-
SWAGGER_TITLE: string;
|
|
71
|
-
SWAGGER_DESCRIPTION: string;
|
|
72
|
-
SWAGGER_VERSION: string;
|
|
73
63
|
LOG_LEVEL: "fatal" | "error" | "warn" | "info" | "debug" | "trace";
|
|
74
64
|
DATABASE_URL?: string | undefined;
|
|
75
65
|
JWT_SECRET?: string | undefined;
|
|
@@ -96,11 +86,6 @@ declare const envSchema: z.ZodObject<{
|
|
|
96
86
|
SMTP_PASS?: string | undefined;
|
|
97
87
|
SMTP_FROM?: string | undefined;
|
|
98
88
|
REDIS_URL?: string | undefined;
|
|
99
|
-
SWAGGER_ENABLED?: "true" | "false" | undefined;
|
|
100
|
-
SWAGGER_ROUTE?: string | undefined;
|
|
101
|
-
SWAGGER_TITLE?: string | undefined;
|
|
102
|
-
SWAGGER_DESCRIPTION?: string | undefined;
|
|
103
|
-
SWAGGER_VERSION?: string | undefined;
|
|
104
89
|
LOG_LEVEL?: "fatal" | "error" | "warn" | "info" | "debug" | "trace" | undefined;
|
|
105
90
|
}>;
|
|
106
91
|
type Env = z.infer<typeof envSchema>;
|
|
@@ -113,11 +98,6 @@ declare const env: {
|
|
|
113
98
|
CORS_ORIGIN: string;
|
|
114
99
|
RATE_LIMIT_MAX: number;
|
|
115
100
|
RATE_LIMIT_WINDOW_MS: number;
|
|
116
|
-
SWAGGER_ENABLED: boolean;
|
|
117
|
-
SWAGGER_ROUTE: string;
|
|
118
|
-
SWAGGER_TITLE: string;
|
|
119
|
-
SWAGGER_DESCRIPTION: string;
|
|
120
|
-
SWAGGER_VERSION: string;
|
|
121
101
|
LOG_LEVEL: "fatal" | "error" | "warn" | "info" | "debug" | "trace";
|
|
122
102
|
DATABASE_URL?: string | undefined;
|
|
123
103
|
JWT_SECRET?: string | undefined;
|
|
@@ -164,13 +144,6 @@ interface AppConfig {
|
|
|
164
144
|
redis: {
|
|
165
145
|
url?: string;
|
|
166
146
|
};
|
|
167
|
-
swagger: {
|
|
168
|
-
enabled: boolean;
|
|
169
|
-
route: string;
|
|
170
|
-
title: string;
|
|
171
|
-
description: string;
|
|
172
|
-
version: string;
|
|
173
|
-
};
|
|
174
147
|
}
|
|
175
148
|
declare function createConfig(): AppConfig;
|
|
176
149
|
declare const config: AppConfig;
|
|
@@ -343,16 +316,43 @@ declare module '@fastify/jwt' {
|
|
|
343
316
|
declare class AuthService {
|
|
344
317
|
private app;
|
|
345
318
|
private readonly SALT_ROUNDS;
|
|
346
|
-
|
|
319
|
+
private redis;
|
|
320
|
+
private readonly BLACKLIST_PREFIX;
|
|
321
|
+
private readonly BLACKLIST_TTL;
|
|
322
|
+
constructor(app: FastifyInstance, redisUrl?: string);
|
|
347
323
|
hashPassword(password: string): Promise<string>;
|
|
348
324
|
verifyPassword(password: string, hash: string): Promise<boolean>;
|
|
349
325
|
generateTokenPair(user: AuthUser): TokenPair;
|
|
350
326
|
private parseExpiration;
|
|
351
327
|
verifyAccessToken(token: string): Promise<JwtPayload>;
|
|
352
328
|
verifyRefreshToken(token: string): Promise<JwtPayload>;
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
329
|
+
/**
|
|
330
|
+
* Blacklist a token (JWT revocation)
|
|
331
|
+
* Uses Redis if available, falls back to in-memory Set
|
|
332
|
+
*/
|
|
333
|
+
blacklistToken(token: string): Promise<void>;
|
|
334
|
+
/**
|
|
335
|
+
* Check if a token is blacklisted
|
|
336
|
+
* Uses Redis if available, falls back to always returning false
|
|
337
|
+
*/
|
|
338
|
+
isTokenBlacklisted(token: string): Promise<boolean>;
|
|
339
|
+
/**
|
|
340
|
+
* Get count of blacklisted tokens (Redis only)
|
|
341
|
+
*/
|
|
342
|
+
getBlacklistCount(): Promise<number>;
|
|
343
|
+
/**
|
|
344
|
+
* Close Redis connection
|
|
345
|
+
*/
|
|
346
|
+
close(): Promise<void>;
|
|
347
|
+
findUserByEmail(_email: string): Promise<AuthUser | null>;
|
|
348
|
+
createUserFromOAuth(data: {
|
|
349
|
+
email: string;
|
|
350
|
+
name?: string;
|
|
351
|
+
picture?: string;
|
|
352
|
+
emailVerified?: boolean;
|
|
353
|
+
}): Promise<AuthUser>;
|
|
354
|
+
generateTokensForUser(userId: string): Promise<TokenPair>;
|
|
355
|
+
verifyPasswordById(userId: string, _password: string): Promise<boolean>;
|
|
356
356
|
}
|
|
357
357
|
declare function createAuthService(app: FastifyInstance): AuthService;
|
|
358
358
|
|
|
@@ -403,17 +403,80 @@ interface Role {
|
|
|
403
403
|
}
|
|
404
404
|
declare const DEFAULT_ROLE_PERMISSIONS: Record<UserRole, string[]>;
|
|
405
405
|
|
|
406
|
+
/**
|
|
407
|
+
* User Repository - Prisma Implementation
|
|
408
|
+
* Manages user data persistence using Prisma ORM
|
|
409
|
+
*/
|
|
406
410
|
declare class UserRepository {
|
|
411
|
+
/**
|
|
412
|
+
* Find user by ID
|
|
413
|
+
*/
|
|
407
414
|
findById(id: string): Promise<User | null>;
|
|
415
|
+
/**
|
|
416
|
+
* Find user by email (case-insensitive)
|
|
417
|
+
*/
|
|
408
418
|
findByEmail(email: string): Promise<User | null>;
|
|
419
|
+
/**
|
|
420
|
+
* Find multiple users with pagination and filters
|
|
421
|
+
*/
|
|
409
422
|
findMany(params: PaginationParams, filters?: UserFilters): Promise<PaginatedResult<User>>;
|
|
423
|
+
/**
|
|
424
|
+
* Create a new user
|
|
425
|
+
*/
|
|
410
426
|
create(data: CreateUserData): Promise<User>;
|
|
427
|
+
/**
|
|
428
|
+
* Update user data
|
|
429
|
+
*/
|
|
411
430
|
update(id: string, data: UpdateUserData): Promise<User | null>;
|
|
431
|
+
/**
|
|
432
|
+
* Update user password
|
|
433
|
+
*/
|
|
412
434
|
updatePassword(id: string, password: string): Promise<User | null>;
|
|
435
|
+
/**
|
|
436
|
+
* Update last login timestamp
|
|
437
|
+
*/
|
|
413
438
|
updateLastLogin(id: string): Promise<User | null>;
|
|
439
|
+
/**
|
|
440
|
+
* Delete user by ID
|
|
441
|
+
*/
|
|
414
442
|
delete(id: string): Promise<boolean>;
|
|
443
|
+
/**
|
|
444
|
+
* Count users with optional filters
|
|
445
|
+
*/
|
|
415
446
|
count(filters?: UserFilters): Promise<number>;
|
|
447
|
+
/**
|
|
448
|
+
* Helper to clear all users (for testing only)
|
|
449
|
+
* WARNING: This deletes all users from the database
|
|
450
|
+
*/
|
|
416
451
|
clear(): Promise<void>;
|
|
452
|
+
/**
|
|
453
|
+
* Build Prisma where clause from filters
|
|
454
|
+
*/
|
|
455
|
+
private buildWhereClause;
|
|
456
|
+
/**
|
|
457
|
+
* Build Prisma orderBy clause from pagination params
|
|
458
|
+
*/
|
|
459
|
+
private buildOrderBy;
|
|
460
|
+
/**
|
|
461
|
+
* Map Prisma User to application User type
|
|
462
|
+
*/
|
|
463
|
+
private mapPrismaUserToUser;
|
|
464
|
+
/**
|
|
465
|
+
* Map application role to Prisma enum
|
|
466
|
+
*/
|
|
467
|
+
private mapRoleToEnum;
|
|
468
|
+
/**
|
|
469
|
+
* Map Prisma enum to application role
|
|
470
|
+
*/
|
|
471
|
+
private mapEnumToRole;
|
|
472
|
+
/**
|
|
473
|
+
* Map application status to Prisma enum
|
|
474
|
+
*/
|
|
475
|
+
private mapStatusToEnum;
|
|
476
|
+
/**
|
|
477
|
+
* Map Prisma enum to application status
|
|
478
|
+
*/
|
|
479
|
+
private mapEnumToStatus;
|
|
417
480
|
}
|
|
418
481
|
declare function createUserRepository(): UserRepository;
|
|
419
482
|
|
|
@@ -451,9 +514,9 @@ declare class AuthController {
|
|
|
451
514
|
}
|
|
452
515
|
declare function createAuthController(authService: AuthService, userService: UserService): AuthController;
|
|
453
516
|
|
|
454
|
-
declare function createAuthMiddleware(authService: AuthService): (request: FastifyRequest,
|
|
517
|
+
declare function createAuthMiddleware(authService: AuthService): (request: FastifyRequest, _reply: FastifyReply) => Promise<void>;
|
|
455
518
|
declare function createRoleMiddleware(allowedRoles: string[]): (request: FastifyRequest, _reply: FastifyReply) => Promise<void>;
|
|
456
|
-
declare function createPermissionMiddleware(
|
|
519
|
+
declare function createPermissionMiddleware(_requiredPermissions: string[]): (request: FastifyRequest, _reply: FastifyReply) => Promise<void>;
|
|
457
520
|
declare function createOptionalAuthMiddleware(authService: AuthService): (request: FastifyRequest, _reply: FastifyReply) => Promise<void>;
|
|
458
521
|
|
|
459
522
|
declare const loginSchema: z.ZodObject<{
|
|
@@ -520,7 +583,7 @@ type PasswordResetRequestInput = z.infer<typeof passwordResetRequestSchema>;
|
|
|
520
583
|
type PasswordResetConfirmInput = z.infer<typeof passwordResetConfirmSchema>;
|
|
521
584
|
type ChangePasswordInput = z.infer<typeof changePasswordSchema>;
|
|
522
585
|
|
|
523
|
-
declare function registerAuthModule(app: FastifyInstance): Promise<
|
|
586
|
+
declare function registerAuthModule(app: FastifyInstance): Promise<void>;
|
|
524
587
|
|
|
525
588
|
declare class UserController {
|
|
526
589
|
private userService;
|
|
@@ -570,8 +633,8 @@ declare const createUserSchema: z.ZodObject<{
|
|
|
570
633
|
role: z.ZodDefault<z.ZodOptional<z.ZodEnum<["user", "admin", "moderator", "super_admin"]>>>;
|
|
571
634
|
}, "strip", z.ZodTypeAny, {
|
|
572
635
|
email: string;
|
|
573
|
-
password: string;
|
|
574
636
|
role: "user" | "admin" | "moderator" | "super_admin";
|
|
637
|
+
password: string;
|
|
575
638
|
name?: string | undefined;
|
|
576
639
|
}, {
|
|
577
640
|
email: string;
|
|
@@ -712,10 +775,10 @@ declare function createEmailService(config?: Partial<EmailConfig>): EmailService
|
|
|
712
775
|
declare function renderTemplate(templateName: string, data: Record<string, unknown>): string;
|
|
713
776
|
declare function renderCustomTemplate(htmlTemplate: string, data: Record<string, unknown>): string;
|
|
714
777
|
|
|
715
|
-
declare function validateBody<T
|
|
716
|
-
declare function validateQuery<T extends ZodTypeAny>(schema: T, data: unknown): z.infer<T>;
|
|
717
|
-
declare function validateParams<T
|
|
718
|
-
declare function validate<T
|
|
778
|
+
declare function validateBody<T>(schema: ZodSchema<T>, data: unknown): T;
|
|
779
|
+
declare function validateQuery<T extends z.ZodTypeAny>(schema: T, data: unknown): z.infer<T>;
|
|
780
|
+
declare function validateParams<T>(schema: ZodSchema<T>, data: unknown): T;
|
|
781
|
+
declare function validate<T>(schema: ZodSchema<T>, data: unknown): T;
|
|
719
782
|
declare const idParamSchema: z.ZodObject<{
|
|
720
783
|
id: z.ZodString;
|
|
721
784
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -782,20 +845,18 @@ interface AuditLogQuery {
|
|
|
782
845
|
limit?: number;
|
|
783
846
|
}
|
|
784
847
|
|
|
848
|
+
interface AuditLogRecord extends AuditLogEntry {
|
|
849
|
+
id: string;
|
|
850
|
+
createdAt: Date;
|
|
851
|
+
}
|
|
852
|
+
|
|
785
853
|
declare class AuditService {
|
|
854
|
+
private repository;
|
|
855
|
+
constructor();
|
|
786
856
|
log(entry: AuditLogEntry): Promise<void>;
|
|
787
|
-
query(params: AuditLogQuery): Promise<PaginatedResult<
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
}>>;
|
|
791
|
-
findByUser(userId: string, limit?: number): Promise<(AuditLogEntry & {
|
|
792
|
-
id: string;
|
|
793
|
-
createdAt: Date;
|
|
794
|
-
})[]>;
|
|
795
|
-
findByResource(resource: string, resourceId: string, limit?: number): Promise<(AuditLogEntry & {
|
|
796
|
-
id: string;
|
|
797
|
-
createdAt: Date;
|
|
798
|
-
})[]>;
|
|
857
|
+
query(params: AuditLogQuery): Promise<PaginatedResult<AuditLogRecord>>;
|
|
858
|
+
findByUser(userId: string, limit?: number): Promise<AuditLogRecord[]>;
|
|
859
|
+
findByResource(resource: string, resourceId: string, limit?: number): Promise<AuditLogRecord[]>;
|
|
799
860
|
logCreate(resource: string, resourceId: string, userId?: string, newValue?: Record<string, unknown>, meta?: {
|
|
800
861
|
ipAddress?: string;
|
|
801
862
|
userAgent?: string;
|
|
@@ -820,6 +881,7 @@ declare class AuditService {
|
|
|
820
881
|
ipAddress?: string;
|
|
821
882
|
userAgent?: string;
|
|
822
883
|
}): Promise<void>;
|
|
884
|
+
cleanupOldLogs(retentionDays: number): Promise<number>;
|
|
823
885
|
clear(): Promise<void>;
|
|
824
886
|
}
|
|
825
887
|
declare function getAuditService(): AuditService;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify';
|
|
2
2
|
import pino, { Logger } from 'pino';
|
|
3
3
|
export { Logger } from 'pino';
|
|
4
|
-
import { z,
|
|
4
|
+
import { z, ZodSchema } from 'zod';
|
|
5
5
|
|
|
6
6
|
interface LoggerConfig {
|
|
7
7
|
level: string;
|
|
@@ -50,11 +50,6 @@ declare const envSchema: z.ZodObject<{
|
|
|
50
50
|
SMTP_PASS: z.ZodOptional<z.ZodString>;
|
|
51
51
|
SMTP_FROM: z.ZodOptional<z.ZodString>;
|
|
52
52
|
REDIS_URL: z.ZodOptional<z.ZodString>;
|
|
53
|
-
SWAGGER_ENABLED: z.ZodEffects<z.ZodDefault<z.ZodUnion<[z.ZodLiteral<"true">, z.ZodLiteral<"false">]>>, boolean, "true" | "false" | undefined>;
|
|
54
|
-
SWAGGER_ROUTE: z.ZodDefault<z.ZodString>;
|
|
55
|
-
SWAGGER_TITLE: z.ZodDefault<z.ZodString>;
|
|
56
|
-
SWAGGER_DESCRIPTION: z.ZodDefault<z.ZodString>;
|
|
57
|
-
SWAGGER_VERSION: z.ZodDefault<z.ZodString>;
|
|
58
53
|
LOG_LEVEL: z.ZodDefault<z.ZodEnum<["fatal", "error", "warn", "info", "debug", "trace"]>>;
|
|
59
54
|
}, "strip", z.ZodTypeAny, {
|
|
60
55
|
NODE_ENV: "development" | "staging" | "production" | "test";
|
|
@@ -65,11 +60,6 @@ declare const envSchema: z.ZodObject<{
|
|
|
65
60
|
CORS_ORIGIN: string;
|
|
66
61
|
RATE_LIMIT_MAX: number;
|
|
67
62
|
RATE_LIMIT_WINDOW_MS: number;
|
|
68
|
-
SWAGGER_ENABLED: boolean;
|
|
69
|
-
SWAGGER_ROUTE: string;
|
|
70
|
-
SWAGGER_TITLE: string;
|
|
71
|
-
SWAGGER_DESCRIPTION: string;
|
|
72
|
-
SWAGGER_VERSION: string;
|
|
73
63
|
LOG_LEVEL: "fatal" | "error" | "warn" | "info" | "debug" | "trace";
|
|
74
64
|
DATABASE_URL?: string | undefined;
|
|
75
65
|
JWT_SECRET?: string | undefined;
|
|
@@ -96,11 +86,6 @@ declare const envSchema: z.ZodObject<{
|
|
|
96
86
|
SMTP_PASS?: string | undefined;
|
|
97
87
|
SMTP_FROM?: string | undefined;
|
|
98
88
|
REDIS_URL?: string | undefined;
|
|
99
|
-
SWAGGER_ENABLED?: "true" | "false" | undefined;
|
|
100
|
-
SWAGGER_ROUTE?: string | undefined;
|
|
101
|
-
SWAGGER_TITLE?: string | undefined;
|
|
102
|
-
SWAGGER_DESCRIPTION?: string | undefined;
|
|
103
|
-
SWAGGER_VERSION?: string | undefined;
|
|
104
89
|
LOG_LEVEL?: "fatal" | "error" | "warn" | "info" | "debug" | "trace" | undefined;
|
|
105
90
|
}>;
|
|
106
91
|
type Env = z.infer<typeof envSchema>;
|
|
@@ -113,11 +98,6 @@ declare const env: {
|
|
|
113
98
|
CORS_ORIGIN: string;
|
|
114
99
|
RATE_LIMIT_MAX: number;
|
|
115
100
|
RATE_LIMIT_WINDOW_MS: number;
|
|
116
|
-
SWAGGER_ENABLED: boolean;
|
|
117
|
-
SWAGGER_ROUTE: string;
|
|
118
|
-
SWAGGER_TITLE: string;
|
|
119
|
-
SWAGGER_DESCRIPTION: string;
|
|
120
|
-
SWAGGER_VERSION: string;
|
|
121
101
|
LOG_LEVEL: "fatal" | "error" | "warn" | "info" | "debug" | "trace";
|
|
122
102
|
DATABASE_URL?: string | undefined;
|
|
123
103
|
JWT_SECRET?: string | undefined;
|
|
@@ -164,13 +144,6 @@ interface AppConfig {
|
|
|
164
144
|
redis: {
|
|
165
145
|
url?: string;
|
|
166
146
|
};
|
|
167
|
-
swagger: {
|
|
168
|
-
enabled: boolean;
|
|
169
|
-
route: string;
|
|
170
|
-
title: string;
|
|
171
|
-
description: string;
|
|
172
|
-
version: string;
|
|
173
|
-
};
|
|
174
147
|
}
|
|
175
148
|
declare function createConfig(): AppConfig;
|
|
176
149
|
declare const config: AppConfig;
|
|
@@ -343,16 +316,43 @@ declare module '@fastify/jwt' {
|
|
|
343
316
|
declare class AuthService {
|
|
344
317
|
private app;
|
|
345
318
|
private readonly SALT_ROUNDS;
|
|
346
|
-
|
|
319
|
+
private redis;
|
|
320
|
+
private readonly BLACKLIST_PREFIX;
|
|
321
|
+
private readonly BLACKLIST_TTL;
|
|
322
|
+
constructor(app: FastifyInstance, redisUrl?: string);
|
|
347
323
|
hashPassword(password: string): Promise<string>;
|
|
348
324
|
verifyPassword(password: string, hash: string): Promise<boolean>;
|
|
349
325
|
generateTokenPair(user: AuthUser): TokenPair;
|
|
350
326
|
private parseExpiration;
|
|
351
327
|
verifyAccessToken(token: string): Promise<JwtPayload>;
|
|
352
328
|
verifyRefreshToken(token: string): Promise<JwtPayload>;
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
329
|
+
/**
|
|
330
|
+
* Blacklist a token (JWT revocation)
|
|
331
|
+
* Uses Redis if available, falls back to in-memory Set
|
|
332
|
+
*/
|
|
333
|
+
blacklistToken(token: string): Promise<void>;
|
|
334
|
+
/**
|
|
335
|
+
* Check if a token is blacklisted
|
|
336
|
+
* Uses Redis if available, falls back to always returning false
|
|
337
|
+
*/
|
|
338
|
+
isTokenBlacklisted(token: string): Promise<boolean>;
|
|
339
|
+
/**
|
|
340
|
+
* Get count of blacklisted tokens (Redis only)
|
|
341
|
+
*/
|
|
342
|
+
getBlacklistCount(): Promise<number>;
|
|
343
|
+
/**
|
|
344
|
+
* Close Redis connection
|
|
345
|
+
*/
|
|
346
|
+
close(): Promise<void>;
|
|
347
|
+
findUserByEmail(_email: string): Promise<AuthUser | null>;
|
|
348
|
+
createUserFromOAuth(data: {
|
|
349
|
+
email: string;
|
|
350
|
+
name?: string;
|
|
351
|
+
picture?: string;
|
|
352
|
+
emailVerified?: boolean;
|
|
353
|
+
}): Promise<AuthUser>;
|
|
354
|
+
generateTokensForUser(userId: string): Promise<TokenPair>;
|
|
355
|
+
verifyPasswordById(userId: string, _password: string): Promise<boolean>;
|
|
356
356
|
}
|
|
357
357
|
declare function createAuthService(app: FastifyInstance): AuthService;
|
|
358
358
|
|
|
@@ -403,17 +403,80 @@ interface Role {
|
|
|
403
403
|
}
|
|
404
404
|
declare const DEFAULT_ROLE_PERMISSIONS: Record<UserRole, string[]>;
|
|
405
405
|
|
|
406
|
+
/**
|
|
407
|
+
* User Repository - Prisma Implementation
|
|
408
|
+
* Manages user data persistence using Prisma ORM
|
|
409
|
+
*/
|
|
406
410
|
declare class UserRepository {
|
|
411
|
+
/**
|
|
412
|
+
* Find user by ID
|
|
413
|
+
*/
|
|
407
414
|
findById(id: string): Promise<User | null>;
|
|
415
|
+
/**
|
|
416
|
+
* Find user by email (case-insensitive)
|
|
417
|
+
*/
|
|
408
418
|
findByEmail(email: string): Promise<User | null>;
|
|
419
|
+
/**
|
|
420
|
+
* Find multiple users with pagination and filters
|
|
421
|
+
*/
|
|
409
422
|
findMany(params: PaginationParams, filters?: UserFilters): Promise<PaginatedResult<User>>;
|
|
423
|
+
/**
|
|
424
|
+
* Create a new user
|
|
425
|
+
*/
|
|
410
426
|
create(data: CreateUserData): Promise<User>;
|
|
427
|
+
/**
|
|
428
|
+
* Update user data
|
|
429
|
+
*/
|
|
411
430
|
update(id: string, data: UpdateUserData): Promise<User | null>;
|
|
431
|
+
/**
|
|
432
|
+
* Update user password
|
|
433
|
+
*/
|
|
412
434
|
updatePassword(id: string, password: string): Promise<User | null>;
|
|
435
|
+
/**
|
|
436
|
+
* Update last login timestamp
|
|
437
|
+
*/
|
|
413
438
|
updateLastLogin(id: string): Promise<User | null>;
|
|
439
|
+
/**
|
|
440
|
+
* Delete user by ID
|
|
441
|
+
*/
|
|
414
442
|
delete(id: string): Promise<boolean>;
|
|
443
|
+
/**
|
|
444
|
+
* Count users with optional filters
|
|
445
|
+
*/
|
|
415
446
|
count(filters?: UserFilters): Promise<number>;
|
|
447
|
+
/**
|
|
448
|
+
* Helper to clear all users (for testing only)
|
|
449
|
+
* WARNING: This deletes all users from the database
|
|
450
|
+
*/
|
|
416
451
|
clear(): Promise<void>;
|
|
452
|
+
/**
|
|
453
|
+
* Build Prisma where clause from filters
|
|
454
|
+
*/
|
|
455
|
+
private buildWhereClause;
|
|
456
|
+
/**
|
|
457
|
+
* Build Prisma orderBy clause from pagination params
|
|
458
|
+
*/
|
|
459
|
+
private buildOrderBy;
|
|
460
|
+
/**
|
|
461
|
+
* Map Prisma User to application User type
|
|
462
|
+
*/
|
|
463
|
+
private mapPrismaUserToUser;
|
|
464
|
+
/**
|
|
465
|
+
* Map application role to Prisma enum
|
|
466
|
+
*/
|
|
467
|
+
private mapRoleToEnum;
|
|
468
|
+
/**
|
|
469
|
+
* Map Prisma enum to application role
|
|
470
|
+
*/
|
|
471
|
+
private mapEnumToRole;
|
|
472
|
+
/**
|
|
473
|
+
* Map application status to Prisma enum
|
|
474
|
+
*/
|
|
475
|
+
private mapStatusToEnum;
|
|
476
|
+
/**
|
|
477
|
+
* Map Prisma enum to application status
|
|
478
|
+
*/
|
|
479
|
+
private mapEnumToStatus;
|
|
417
480
|
}
|
|
418
481
|
declare function createUserRepository(): UserRepository;
|
|
419
482
|
|
|
@@ -451,9 +514,9 @@ declare class AuthController {
|
|
|
451
514
|
}
|
|
452
515
|
declare function createAuthController(authService: AuthService, userService: UserService): AuthController;
|
|
453
516
|
|
|
454
|
-
declare function createAuthMiddleware(authService: AuthService): (request: FastifyRequest,
|
|
517
|
+
declare function createAuthMiddleware(authService: AuthService): (request: FastifyRequest, _reply: FastifyReply) => Promise<void>;
|
|
455
518
|
declare function createRoleMiddleware(allowedRoles: string[]): (request: FastifyRequest, _reply: FastifyReply) => Promise<void>;
|
|
456
|
-
declare function createPermissionMiddleware(
|
|
519
|
+
declare function createPermissionMiddleware(_requiredPermissions: string[]): (request: FastifyRequest, _reply: FastifyReply) => Promise<void>;
|
|
457
520
|
declare function createOptionalAuthMiddleware(authService: AuthService): (request: FastifyRequest, _reply: FastifyReply) => Promise<void>;
|
|
458
521
|
|
|
459
522
|
declare const loginSchema: z.ZodObject<{
|
|
@@ -520,7 +583,7 @@ type PasswordResetRequestInput = z.infer<typeof passwordResetRequestSchema>;
|
|
|
520
583
|
type PasswordResetConfirmInput = z.infer<typeof passwordResetConfirmSchema>;
|
|
521
584
|
type ChangePasswordInput = z.infer<typeof changePasswordSchema>;
|
|
522
585
|
|
|
523
|
-
declare function registerAuthModule(app: FastifyInstance): Promise<
|
|
586
|
+
declare function registerAuthModule(app: FastifyInstance): Promise<void>;
|
|
524
587
|
|
|
525
588
|
declare class UserController {
|
|
526
589
|
private userService;
|
|
@@ -570,8 +633,8 @@ declare const createUserSchema: z.ZodObject<{
|
|
|
570
633
|
role: z.ZodDefault<z.ZodOptional<z.ZodEnum<["user", "admin", "moderator", "super_admin"]>>>;
|
|
571
634
|
}, "strip", z.ZodTypeAny, {
|
|
572
635
|
email: string;
|
|
573
|
-
password: string;
|
|
574
636
|
role: "user" | "admin" | "moderator" | "super_admin";
|
|
637
|
+
password: string;
|
|
575
638
|
name?: string | undefined;
|
|
576
639
|
}, {
|
|
577
640
|
email: string;
|
|
@@ -712,10 +775,10 @@ declare function createEmailService(config?: Partial<EmailConfig>): EmailService
|
|
|
712
775
|
declare function renderTemplate(templateName: string, data: Record<string, unknown>): string;
|
|
713
776
|
declare function renderCustomTemplate(htmlTemplate: string, data: Record<string, unknown>): string;
|
|
714
777
|
|
|
715
|
-
declare function validateBody<T
|
|
716
|
-
declare function validateQuery<T extends ZodTypeAny>(schema: T, data: unknown): z.infer<T>;
|
|
717
|
-
declare function validateParams<T
|
|
718
|
-
declare function validate<T
|
|
778
|
+
declare function validateBody<T>(schema: ZodSchema<T>, data: unknown): T;
|
|
779
|
+
declare function validateQuery<T extends z.ZodTypeAny>(schema: T, data: unknown): z.infer<T>;
|
|
780
|
+
declare function validateParams<T>(schema: ZodSchema<T>, data: unknown): T;
|
|
781
|
+
declare function validate<T>(schema: ZodSchema<T>, data: unknown): T;
|
|
719
782
|
declare const idParamSchema: z.ZodObject<{
|
|
720
783
|
id: z.ZodString;
|
|
721
784
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -782,20 +845,18 @@ interface AuditLogQuery {
|
|
|
782
845
|
limit?: number;
|
|
783
846
|
}
|
|
784
847
|
|
|
848
|
+
interface AuditLogRecord extends AuditLogEntry {
|
|
849
|
+
id: string;
|
|
850
|
+
createdAt: Date;
|
|
851
|
+
}
|
|
852
|
+
|
|
785
853
|
declare class AuditService {
|
|
854
|
+
private repository;
|
|
855
|
+
constructor();
|
|
786
856
|
log(entry: AuditLogEntry): Promise<void>;
|
|
787
|
-
query(params: AuditLogQuery): Promise<PaginatedResult<
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
}>>;
|
|
791
|
-
findByUser(userId: string, limit?: number): Promise<(AuditLogEntry & {
|
|
792
|
-
id: string;
|
|
793
|
-
createdAt: Date;
|
|
794
|
-
})[]>;
|
|
795
|
-
findByResource(resource: string, resourceId: string, limit?: number): Promise<(AuditLogEntry & {
|
|
796
|
-
id: string;
|
|
797
|
-
createdAt: Date;
|
|
798
|
-
})[]>;
|
|
857
|
+
query(params: AuditLogQuery): Promise<PaginatedResult<AuditLogRecord>>;
|
|
858
|
+
findByUser(userId: string, limit?: number): Promise<AuditLogRecord[]>;
|
|
859
|
+
findByResource(resource: string, resourceId: string, limit?: number): Promise<AuditLogRecord[]>;
|
|
799
860
|
logCreate(resource: string, resourceId: string, userId?: string, newValue?: Record<string, unknown>, meta?: {
|
|
800
861
|
ipAddress?: string;
|
|
801
862
|
userAgent?: string;
|
|
@@ -820,6 +881,7 @@ declare class AuditService {
|
|
|
820
881
|
ipAddress?: string;
|
|
821
882
|
userAgent?: string;
|
|
822
883
|
}): Promise<void>;
|
|
884
|
+
cleanupOldLogs(retentionDays: number): Promise<number>;
|
|
823
885
|
clear(): Promise<void>;
|
|
824
886
|
}
|
|
825
887
|
declare function getAuditService(): AuditService;
|