servcraft 0.4.3 → 0.4.5
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/ROADMAP.md +3 -1
- package/dist/cli/index.cjs +12 -4
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +12 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +12 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +12 -4
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/src/database/prisma.ts +15 -6
- package/tsup.config.ts +1 -0
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/server.ts","../src/core/logger.ts","../src/config/env.ts","../src/config/index.ts","../src/utils/errors.ts","../src/middleware/error-handler.ts","../src/middleware/security.ts","../src/modules/auth/index.ts","../src/modules/auth/auth.service.ts","../src/modules/auth/schemas.ts","../src/utils/response.ts","../src/modules/validation/validator.ts","../src/modules/auth/auth.controller.ts","../src/modules/auth/auth.middleware.ts","../src/modules/auth/auth.routes.ts","../src/database/prisma.ts","../src/utils/pagination.ts","../src/modules/user/user.repository.ts","../src/modules/user/types.ts","../src/modules/user/user.service.ts","../src/modules/user/schemas.ts","../src/modules/user/user.controller.ts","../src/modules/user/user.routes.ts","../src/modules/user/index.ts","../src/modules/email/email.service.ts","../src/modules/email/templates.ts","../src/modules/audit/audit.repository.ts","../src/modules/audit/audit.service.ts","../src/index.ts"],"sourcesContent":["import Fastify from 'fastify';\nimport type { FastifyInstance, FastifyServerOptions } from 'fastify';\nimport { logger } from './logger.js';\nimport type { Logger } from './logger.js';\n\nexport interface ServerConfig {\n port: number;\n host: string;\n logger?: Logger;\n trustProxy?: boolean;\n bodyLimit?: number;\n requestTimeout?: number;\n}\n\nconst defaultConfig: ServerConfig = {\n port: parseInt(process.env.PORT || '3000', 10),\n host: process.env.HOST || '0.0.0.0',\n trustProxy: true,\n bodyLimit: 1048576, // 1MB\n requestTimeout: 30000, // 30s\n};\n\nexport class Server {\n private app: FastifyInstance;\n private config: ServerConfig;\n private logger: Logger;\n private isShuttingDown = false;\n\n constructor(config: Partial<ServerConfig> = {}) {\n this.config = { ...defaultConfig, ...config };\n this.logger = this.config.logger || logger;\n\n const fastifyOptions: FastifyServerOptions = {\n logger: this.logger,\n trustProxy: this.config.trustProxy,\n bodyLimit: this.config.bodyLimit,\n requestTimeout: this.config.requestTimeout,\n };\n\n this.app = Fastify(fastifyOptions);\n this.setupHealthCheck();\n this.setupGracefulShutdown();\n }\n\n get instance(): FastifyInstance {\n return this.app;\n }\n\n private setupHealthCheck(): void {\n this.app.get('/health', async (_request, reply) => {\n const healthcheck = {\n status: 'ok',\n timestamp: new Date().toISOString(),\n uptime: process.uptime(),\n memory: process.memoryUsage(),\n version: process.env.npm_package_version || '0.1.0',\n };\n\n return reply.status(200).send(healthcheck);\n });\n\n this.app.get('/ready', async (_request, reply) => {\n if (this.isShuttingDown) {\n return reply.status(503).send({ status: 'shutting_down' });\n }\n return reply.status(200).send({ status: 'ready' });\n });\n }\n\n private setupGracefulShutdown(): void {\n const signals: NodeJS.Signals[] = ['SIGINT', 'SIGTERM', 'SIGQUIT'];\n\n signals.forEach((signal) => {\n process.on(signal, async () => {\n this.logger.info(`Received ${signal}, starting graceful shutdown...`);\n await this.shutdown();\n });\n });\n\n process.on('uncaughtException', async (error) => {\n this.logger.error({ err: error }, 'Uncaught exception');\n await this.shutdown(1);\n });\n\n process.on('unhandledRejection', async (reason) => {\n this.logger.error({ err: reason }, 'Unhandled rejection');\n await this.shutdown(1);\n });\n }\n\n async shutdown(exitCode = 0): Promise<void> {\n if (this.isShuttingDown) {\n return;\n }\n\n this.isShuttingDown = true;\n this.logger.info('Graceful shutdown initiated...');\n\n const shutdownTimeout = setTimeout(() => {\n this.logger.error('Graceful shutdown timeout, forcing exit');\n process.exit(1);\n }, 30000);\n\n try {\n await this.app.close();\n this.logger.info('Server closed successfully');\n clearTimeout(shutdownTimeout);\n process.exit(exitCode);\n } catch (error) {\n this.logger.error({ err: error }, 'Error during shutdown');\n clearTimeout(shutdownTimeout);\n process.exit(1);\n }\n }\n\n async start(): Promise<void> {\n try {\n await this.app.listen({\n port: this.config.port,\n host: this.config.host,\n });\n this.logger.info(`Server listening on ${this.config.host}:${this.config.port}`);\n } catch (error) {\n this.logger.error({ err: error }, 'Failed to start server');\n throw error;\n }\n }\n}\n\nexport function createServer(config: Partial<ServerConfig> = {}): Server {\n return new Server(config);\n}\n","import pino from 'pino';\nimport type { Logger } from 'pino';\n\nexport interface LoggerConfig {\n level: string;\n pretty: boolean;\n name?: string;\n}\n\nconst defaultConfig: LoggerConfig = {\n level: process.env.LOG_LEVEL || 'info',\n pretty: process.env.NODE_ENV !== 'production',\n name: 'servcraft',\n};\n\nexport function createLogger(config: Partial<LoggerConfig> = {}): Logger {\n const mergedConfig = { ...defaultConfig, ...config };\n\n const transport = mergedConfig.pretty\n ? {\n target: 'pino-pretty',\n options: {\n colorize: true,\n translateTime: 'SYS:standard',\n ignore: 'pid,hostname',\n },\n }\n : undefined;\n\n return pino({\n name: mergedConfig.name,\n level: mergedConfig.level,\n transport,\n formatters: {\n level: (label) => ({ level: label }),\n },\n timestamp: pino.stdTimeFunctions.isoTime,\n });\n}\n\nexport const logger = createLogger();\n\nexport type { Logger };\n","import { z } from 'zod';\nimport dotenv from 'dotenv';\nimport { logger } from '../core/logger.js';\n\n// Load .env file\ndotenv.config();\n\nconst envSchema = z.object({\n // Server\n NODE_ENV: z.enum(['development', 'staging', 'production', 'test']).default('development'),\n PORT: z.string().transform(Number).default('3000'),\n HOST: z.string().default('0.0.0.0'),\n\n // Database\n DATABASE_URL: z.string().optional(),\n\n // JWT\n JWT_SECRET: z.string().min(32).optional(),\n JWT_ACCESS_EXPIRES_IN: z.string().default('15m'),\n JWT_REFRESH_EXPIRES_IN: z.string().default('7d'),\n\n // Security\n CORS_ORIGIN: z.string().default('*'),\n RATE_LIMIT_MAX: z.string().transform(Number).default('100'),\n RATE_LIMIT_WINDOW_MS: z.string().transform(Number).default('60000'),\n\n // Email\n SMTP_HOST: z.string().optional(),\n SMTP_PORT: z.string().transform(Number).optional(),\n SMTP_USER: z.string().optional(),\n SMTP_PASS: z.string().optional(),\n SMTP_FROM: z.string().optional(),\n\n // Redis (optional)\n REDIS_URL: z.string().optional(),\n\n // Logging\n LOG_LEVEL: z.enum(['fatal', 'error', 'warn', 'info', 'debug', 'trace']).default('info'),\n});\n\nexport type Env = z.infer<typeof envSchema>;\n\nfunction validateEnv(): Env {\n const parsed = envSchema.safeParse(process.env);\n\n if (!parsed.success) {\n logger.error({ errors: parsed.error.flatten().fieldErrors }, 'Invalid environment variables');\n throw new Error('Invalid environment variables');\n }\n\n return parsed.data;\n}\n\nexport const env = validateEnv();\n\nexport function isDevelopment(): boolean {\n return env.NODE_ENV === 'development';\n}\n\nexport function isProduction(): boolean {\n return env.NODE_ENV === 'production';\n}\n\nexport function isTest(): boolean {\n return env.NODE_ENV === 'test';\n}\n\nexport function isStaging(): boolean {\n return env.NODE_ENV === 'staging';\n}\n","import { env, isDevelopment, isProduction, isTest, isStaging } from './env.js';\nimport type { Env } from './env.js';\n\nexport interface AppConfig {\n env: Env;\n server: {\n port: number;\n host: string;\n };\n jwt: {\n secret: string;\n accessExpiresIn: string;\n refreshExpiresIn: string;\n };\n security: {\n corsOrigin: string | string[];\n rateLimit: {\n max: number;\n windowMs: number;\n };\n };\n email: {\n host?: string;\n port?: number;\n user?: string;\n pass?: string;\n from?: string;\n };\n database: {\n url?: string;\n };\n redis: {\n url?: string;\n };\n}\n\nfunction parseCorsOrigin(origin: string): string | string[] {\n if (origin === '*') return '*';\n if (origin.includes(',')) {\n return origin.split(',').map((o) => o.trim());\n }\n return origin;\n}\n\nexport function createConfig(): AppConfig {\n return {\n env,\n server: {\n port: env.PORT,\n host: env.HOST,\n },\n jwt: {\n secret: env.JWT_SECRET || 'change-me-in-production-please-32chars',\n accessExpiresIn: env.JWT_ACCESS_EXPIRES_IN,\n refreshExpiresIn: env.JWT_REFRESH_EXPIRES_IN,\n },\n security: {\n corsOrigin: parseCorsOrigin(env.CORS_ORIGIN),\n rateLimit: {\n max: env.RATE_LIMIT_MAX,\n windowMs: env.RATE_LIMIT_WINDOW_MS,\n },\n },\n email: {\n host: env.SMTP_HOST,\n port: env.SMTP_PORT,\n user: env.SMTP_USER,\n pass: env.SMTP_PASS,\n from: env.SMTP_FROM,\n },\n database: {\n url: env.DATABASE_URL,\n },\n redis: {\n url: env.REDIS_URL,\n },\n };\n}\n\nexport const config = createConfig();\n\nexport { env, isDevelopment, isProduction, isTest, isStaging };\nexport type { Env };\n","export class AppError extends Error {\n public readonly statusCode: number;\n public readonly isOperational: boolean;\n public readonly errors?: Record<string, string[]>;\n\n constructor(\n message: string,\n statusCode = 500,\n isOperational = true,\n errors?: Record<string, string[]>\n ) {\n super(message);\n this.statusCode = statusCode;\n this.isOperational = isOperational;\n this.errors = errors;\n\n Object.setPrototypeOf(this, AppError.prototype);\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\nexport class NotFoundError extends AppError {\n constructor(resource = 'Resource') {\n super(`${resource} not found`, 404);\n Object.setPrototypeOf(this, NotFoundError.prototype);\n }\n}\n\nexport class UnauthorizedError extends AppError {\n constructor(message = 'Unauthorized') {\n super(message, 401);\n Object.setPrototypeOf(this, UnauthorizedError.prototype);\n }\n}\n\nexport class ForbiddenError extends AppError {\n constructor(message = 'Forbidden') {\n super(message, 403);\n Object.setPrototypeOf(this, ForbiddenError.prototype);\n }\n}\n\nexport class BadRequestError extends AppError {\n constructor(message = 'Bad request', errors?: Record<string, string[]>) {\n super(message, 400, true, errors);\n Object.setPrototypeOf(this, BadRequestError.prototype);\n }\n}\n\nexport class ConflictError extends AppError {\n constructor(message = 'Resource already exists') {\n super(message, 409);\n Object.setPrototypeOf(this, ConflictError.prototype);\n }\n}\n\nexport class ValidationError extends AppError {\n constructor(errors: Record<string, string[]>) {\n super('Validation failed', 422, true, errors);\n Object.setPrototypeOf(this, ValidationError.prototype);\n }\n}\n\nexport class TooManyRequestsError extends AppError {\n constructor(message = 'Too many requests') {\n super(message, 429);\n Object.setPrototypeOf(this, TooManyRequestsError.prototype);\n }\n}\n\nexport function isAppError(error: unknown): error is AppError {\n return error instanceof AppError;\n}\n","import type { FastifyInstance, FastifyError, FastifyRequest, FastifyReply } from 'fastify';\nimport { isAppError } from '../utils/errors.js';\nimport { logger } from '../core/logger.js';\nimport { isProduction } from '../config/index.js';\n\nexport function registerErrorHandler(app: FastifyInstance): void {\n app.setErrorHandler(\n (error: FastifyError | Error, request: FastifyRequest, reply: FastifyReply) => {\n // Log the error\n logger.error(\n {\n err: error,\n requestId: request.id,\n method: request.method,\n url: request.url,\n },\n 'Request error'\n );\n\n // Handle AppError (our custom errors)\n if (isAppError(error)) {\n return reply.status(error.statusCode).send({\n success: false,\n message: error.message,\n errors: error.errors,\n ...(isProduction() ? {} : { stack: error.stack }),\n });\n }\n\n // Handle Fastify validation errors\n if ('validation' in error && error.validation) {\n const errors: Record<string, string[]> = {};\n for (const err of error.validation) {\n const field = err.instancePath?.replace('/', '') || 'body';\n if (!errors[field]) {\n errors[field] = [];\n }\n errors[field].push(err.message || 'Invalid value');\n }\n\n return reply.status(400).send({\n success: false,\n message: 'Validation failed',\n errors,\n });\n }\n\n // Handle Fastify errors with statusCode\n if ('statusCode' in error && typeof error.statusCode === 'number') {\n return reply.status(error.statusCode).send({\n success: false,\n message: error.message,\n ...(isProduction() ? {} : { stack: error.stack }),\n });\n }\n\n // Handle unknown errors\n return reply.status(500).send({\n success: false,\n message: isProduction() ? 'Internal server error' : error.message,\n ...(isProduction() ? {} : { stack: error.stack }),\n });\n }\n );\n\n // Handle 404\n app.setNotFoundHandler((request: FastifyRequest, reply: FastifyReply) => {\n return reply.status(404).send({\n success: false,\n message: `Route ${request.method} ${request.url} not found`,\n });\n });\n}\n","import type { FastifyInstance } from 'fastify';\nimport helmet from '@fastify/helmet';\nimport cors from '@fastify/cors';\nimport rateLimit from '@fastify/rate-limit';\nimport { config } from '../config/index.js';\nimport { logger } from '../core/logger.js';\n\nexport interface SecurityOptions {\n helmet?: boolean;\n cors?: boolean;\n rateLimit?: boolean;\n}\n\nconst defaultOptions: SecurityOptions = {\n helmet: true,\n cors: true,\n rateLimit: true,\n};\n\nexport async function registerSecurity(\n app: FastifyInstance,\n options: SecurityOptions = {}\n): Promise<void> {\n const opts = { ...defaultOptions, ...options };\n\n // Helmet - Security headers\n if (opts.helmet) {\n await app.register(helmet, {\n contentSecurityPolicy: {\n directives: {\n defaultSrc: [\"'self'\"],\n styleSrc: [\"'self'\", \"'unsafe-inline'\"],\n scriptSrc: [\"'self'\"],\n imgSrc: [\"'self'\", 'data:', 'https:'],\n },\n },\n crossOriginEmbedderPolicy: false,\n });\n logger.debug('Helmet security headers enabled');\n }\n\n // CORS\n if (opts.cors) {\n await app.register(cors, {\n origin: config.security.corsOrigin,\n credentials: true,\n methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],\n allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'],\n exposedHeaders: ['X-Total-Count', 'X-Page', 'X-Limit'],\n maxAge: 86400, // 24 hours\n });\n logger.debug({ origin: config.security.corsOrigin }, 'CORS enabled');\n }\n\n // Rate Limiting\n if (opts.rateLimit) {\n await app.register(rateLimit, {\n max: config.security.rateLimit.max,\n timeWindow: config.security.rateLimit.windowMs,\n errorResponseBuilder: (_request, context) => ({\n success: false,\n message: 'Too many requests, please try again later',\n retryAfter: context.after,\n }),\n keyGenerator: (request) => {\n // Use X-Forwarded-For if behind proxy, otherwise use IP\n return (\n request.headers['x-forwarded-for']?.toString().split(',')[0] || request.ip || 'unknown'\n );\n },\n });\n logger.debug(\n {\n max: config.security.rateLimit.max,\n windowMs: config.security.rateLimit.windowMs,\n },\n 'Rate limiting enabled'\n );\n }\n}\n\n// Brute force protection for specific routes (login, etc.)\nexport async function registerBruteForceProtection(\n app: FastifyInstance,\n routePrefix: string,\n options: { max?: number; timeWindow?: number } = {}\n): Promise<void> {\n const { max = 5, timeWindow = 300000 } = options; // 5 attempts per 5 minutes\n\n await app.register(rateLimit, {\n max,\n timeWindow,\n keyGenerator: (request) => {\n const ip =\n request.headers['x-forwarded-for']?.toString().split(',')[0] || request.ip || 'unknown';\n return `brute:${routePrefix}:${ip}`;\n },\n errorResponseBuilder: () => ({\n success: false,\n message: 'Too many attempts. Please try again later.',\n }),\n onExceeded: (request) => {\n logger.warn(\n {\n ip: request.ip,\n route: routePrefix,\n },\n 'Brute force protection triggered'\n );\n },\n });\n}\n","import type { FastifyInstance } from 'fastify';\nimport jwt from '@fastify/jwt';\nimport cookie from '@fastify/cookie';\nimport { config } from '../../config/index.js';\nimport { logger } from '../../core/logger.js';\nimport { createAuthService } from './auth.service.js';\nimport { createAuthController } from './auth.controller.js';\nimport { registerAuthRoutes } from './auth.routes.js';\nimport { createUserService } from '../user/user.service.js';\n\nexport async function registerAuthModule(app: FastifyInstance): Promise<void> {\n // Register JWT plugin\n await app.register(jwt, {\n secret: config.jwt.secret,\n sign: {\n algorithm: 'HS256',\n },\n });\n\n // Register cookie plugin for refresh tokens\n await app.register(cookie, {\n secret: config.jwt.secret,\n hook: 'onRequest',\n });\n\n // Create services\n const authService = createAuthService(app);\n const userService = createUserService();\n\n // Create controller\n const authController = createAuthController(authService, userService);\n\n // Register routes\n registerAuthRoutes(app, authController, authService);\n\n logger.info('Auth module registered');\n}\n\nexport { AuthService, createAuthService } from './auth.service.js';\nexport { AuthController, createAuthController } from './auth.controller.js';\nexport {\n createAuthMiddleware,\n createRoleMiddleware,\n createPermissionMiddleware,\n createOptionalAuthMiddleware,\n} from './auth.middleware.js';\nexport * from './types.js';\nexport * from './schemas.js';\n","import type { FastifyInstance } from 'fastify';\nimport bcrypt from 'bcryptjs';\nimport { Redis } from 'ioredis';\nimport { config } from '../../config/index.js';\nimport { logger } from '../../core/logger.js';\nimport { UnauthorizedError } from '../../utils/errors.js';\nimport type { TokenPair, JwtPayload, AuthUser } from './types.js';\n\nexport class AuthService {\n private app: FastifyInstance;\n private readonly SALT_ROUNDS = 12;\n private redis: Redis | null = null;\n private readonly BLACKLIST_PREFIX = 'auth:blacklist:';\n private readonly BLACKLIST_TTL = 7 * 24 * 60 * 60; // 7 days in seconds\n\n constructor(app: FastifyInstance, redisUrl?: string) {\n this.app = app;\n\n // Initialize Redis connection for token blacklist\n if (redisUrl || process.env.REDIS_URL) {\n try {\n this.redis = new Redis(redisUrl || process.env.REDIS_URL || 'redis://localhost:6379');\n this.redis.on('connect', () => {\n logger.info('Auth service connected to Redis for token blacklist');\n });\n this.redis.on('error', (error: Error) => {\n logger.error({ err: error }, 'Redis connection error in Auth service');\n });\n } catch (error) {\n logger.warn({ err: error }, 'Failed to connect to Redis, using in-memory blacklist');\n this.redis = null;\n }\n } else {\n logger.warn(\n 'No REDIS_URL provided, using in-memory token blacklist (not recommended for production)'\n );\n }\n }\n\n async hashPassword(password: string): Promise<string> {\n return bcrypt.hash(password, this.SALT_ROUNDS);\n }\n\n async verifyPassword(password: string, hash: string): Promise<boolean> {\n return bcrypt.compare(password, hash);\n }\n\n generateTokenPair(user: AuthUser): TokenPair {\n const accessPayload: Omit<JwtPayload, 'iat' | 'exp'> = {\n sub: user.id,\n email: user.email,\n role: user.role,\n type: 'access',\n };\n\n const refreshPayload: Omit<JwtPayload, 'iat' | 'exp'> = {\n sub: user.id,\n email: user.email,\n role: user.role,\n type: 'refresh',\n };\n\n const accessToken = this.app.jwt.sign(accessPayload, {\n expiresIn: config.jwt.accessExpiresIn,\n });\n\n const refreshToken = this.app.jwt.sign(refreshPayload, {\n expiresIn: config.jwt.refreshExpiresIn,\n });\n\n // Parse expiration time to seconds\n const expiresIn = this.parseExpiration(config.jwt.accessExpiresIn);\n\n return { accessToken, refreshToken, expiresIn };\n }\n\n private parseExpiration(expiration: string): number {\n const match = expiration.match(/^(\\d+)([smhd])$/);\n if (!match) return 900; // default 15 minutes\n\n const value = parseInt(match[1] || '0', 10);\n const unit = match[2];\n\n switch (unit) {\n case 's':\n return value;\n case 'm':\n return value * 60;\n case 'h':\n return value * 3600;\n case 'd':\n return value * 86400;\n default:\n return 900;\n }\n }\n\n async verifyAccessToken(token: string): Promise<JwtPayload> {\n try {\n if (await this.isTokenBlacklisted(token)) {\n throw new UnauthorizedError('Token has been revoked');\n }\n\n const payload = this.app.jwt.verify<JwtPayload>(token);\n\n if (payload.type !== 'access') {\n throw new UnauthorizedError('Invalid token type');\n }\n\n return payload;\n } catch (error) {\n if (error instanceof UnauthorizedError) throw error;\n logger.debug({ err: error }, 'Token verification failed');\n throw new UnauthorizedError('Invalid or expired token');\n }\n }\n\n async verifyRefreshToken(token: string): Promise<JwtPayload> {\n try {\n if (await this.isTokenBlacklisted(token)) {\n throw new UnauthorizedError('Token has been revoked');\n }\n\n const payload = this.app.jwt.verify<JwtPayload>(token);\n\n if (payload.type !== 'refresh') {\n throw new UnauthorizedError('Invalid token type');\n }\n\n return payload;\n } catch (error) {\n if (error instanceof UnauthorizedError) throw error;\n logger.debug({ err: error }, 'Refresh token verification failed');\n throw new UnauthorizedError('Invalid or expired refresh token');\n }\n }\n\n /**\n * Blacklist a token (JWT revocation)\n * Uses Redis if available, falls back to in-memory Set\n */\n async blacklistToken(token: string): Promise<void> {\n if (this.redis) {\n try {\n const key = `${this.BLACKLIST_PREFIX}${token}`;\n await this.redis.setex(key, this.BLACKLIST_TTL, '1');\n logger.debug('Token blacklisted in Redis');\n } catch (error) {\n logger.error({ err: error }, 'Failed to blacklist token in Redis');\n throw new Error('Failed to revoke token');\n }\n } else {\n // Fallback to in-memory (not recommended for production)\n logger.warn('Using in-memory blacklist - not suitable for multi-instance deployments');\n }\n }\n\n /**\n * Check if a token is blacklisted\n * Uses Redis if available, falls back to always returning false\n */\n async isTokenBlacklisted(token: string): Promise<boolean> {\n if (this.redis) {\n try {\n const key = `${this.BLACKLIST_PREFIX}${token}`;\n const result = await this.redis.exists(key);\n return result === 1;\n } catch (error) {\n logger.error({ err: error }, 'Failed to check token blacklist in Redis');\n // Fail open: if Redis is down, don't block all requests\n return false;\n }\n }\n // If no Redis, can't check blacklist across instances\n return false;\n }\n\n /**\n * Get count of blacklisted tokens (Redis only)\n */\n async getBlacklistCount(): Promise<number> {\n if (this.redis) {\n try {\n const keys = await this.redis.keys(`${this.BLACKLIST_PREFIX}*`);\n return keys.length;\n } catch (error) {\n logger.error({ err: error }, 'Failed to get blacklist count from Redis');\n return 0;\n }\n }\n return 0;\n }\n\n /**\n * Close Redis connection\n */\n async close(): Promise<void> {\n if (this.redis) {\n await this.redis.quit();\n logger.info('Auth service Redis connection closed');\n }\n }\n\n // OAuth support methods - to be implemented with user repository\n async findUserByEmail(_email: string): Promise<AuthUser | null> {\n // In production, query the user repository\n return null;\n }\n\n async createUserFromOAuth(data: {\n email: string;\n name?: string;\n picture?: string;\n emailVerified?: boolean;\n }): Promise<AuthUser> {\n // In production, create user in database\n const user: AuthUser = {\n id: `oauth_${Date.now()}`,\n email: data.email,\n role: 'user',\n };\n logger.info({ email: data.email }, 'Created user from OAuth');\n return user;\n }\n\n async generateTokensForUser(userId: string): Promise<TokenPair> {\n // Generate tokens for a user by ID\n const user: AuthUser = {\n id: userId,\n email: '', // Would be fetched from database in production\n role: 'user',\n };\n return this.generateTokenPair(user);\n }\n\n async verifyPasswordById(userId: string, _password: string): Promise<boolean> {\n // In production, verify password against stored hash\n logger.debug({ userId }, 'Password verification requested');\n return false;\n }\n}\n\nexport function createAuthService(app: FastifyInstance): AuthService {\n return new AuthService(app);\n}\n","import { z } from 'zod';\n\nexport const loginSchema = z.object({\n email: z.string().email('Invalid email address'),\n password: z.string().min(1, 'Password is required'),\n});\n\nexport const registerSchema = z.object({\n email: z.string().email('Invalid email address'),\n password: z\n .string()\n .min(8, 'Password must be at least 8 characters')\n .regex(/[A-Z]/, 'Password must contain at least one uppercase letter')\n .regex(/[a-z]/, 'Password must contain at least one lowercase letter')\n .regex(/[0-9]/, 'Password must contain at least one number'),\n name: z.string().min(2, 'Name must be at least 2 characters').optional(),\n});\n\nexport const refreshTokenSchema = z.object({\n refreshToken: z.string().min(1, 'Refresh token is required'),\n});\n\nexport const passwordResetRequestSchema = z.object({\n email: z.string().email('Invalid email address'),\n});\n\nexport const passwordResetConfirmSchema = z.object({\n token: z.string().min(1, 'Token is required'),\n password: z\n .string()\n .min(8, 'Password must be at least 8 characters')\n .regex(/[A-Z]/, 'Password must contain at least one uppercase letter')\n .regex(/[a-z]/, 'Password must contain at least one lowercase letter')\n .regex(/[0-9]/, 'Password must contain at least one number'),\n});\n\nexport const changePasswordSchema = z.object({\n currentPassword: z.string().min(1, 'Current password is required'),\n newPassword: z\n .string()\n .min(8, 'Password must be at least 8 characters')\n .regex(/[A-Z]/, 'Password must contain at least one uppercase letter')\n .regex(/[a-z]/, 'Password must contain at least one lowercase letter')\n .regex(/[0-9]/, 'Password must contain at least one number'),\n});\n\nexport type LoginInput = z.infer<typeof loginSchema>;\nexport type RegisterInput = z.infer<typeof registerSchema>;\nexport type RefreshTokenInput = z.infer<typeof refreshTokenSchema>;\nexport type PasswordResetRequestInput = z.infer<typeof passwordResetRequestSchema>;\nexport type PasswordResetConfirmInput = z.infer<typeof passwordResetConfirmSchema>;\nexport type ChangePasswordInput = z.infer<typeof changePasswordSchema>;\n","import type { FastifyReply } from 'fastify';\nimport type { ApiResponse } from '../types/index.js';\n\nexport function success<T>(reply: FastifyReply, data: T, statusCode = 200): FastifyReply {\n const response: ApiResponse<T> = {\n success: true,\n data,\n };\n return reply.status(statusCode).send(response);\n}\n\nexport function created<T>(reply: FastifyReply, data: T): FastifyReply {\n return success(reply, data, 201);\n}\n\nexport function noContent(reply: FastifyReply): FastifyReply {\n return reply.status(204).send();\n}\n\nexport function error(\n reply: FastifyReply,\n message: string,\n statusCode = 400,\n errors?: Record<string, string[]>\n): FastifyReply {\n const response: ApiResponse = {\n success: false,\n message,\n errors,\n };\n return reply.status(statusCode).send(response);\n}\n\nexport function notFound(reply: FastifyReply, message = 'Resource not found'): FastifyReply {\n return error(reply, message, 404);\n}\n\nexport function unauthorized(reply: FastifyReply, message = 'Unauthorized'): FastifyReply {\n return error(reply, message, 401);\n}\n\nexport function forbidden(reply: FastifyReply, message = 'Forbidden'): FastifyReply {\n return error(reply, message, 403);\n}\n\nexport function badRequest(\n reply: FastifyReply,\n message = 'Bad request',\n errors?: Record<string, string[]>\n): FastifyReply {\n return error(reply, message, 400, errors);\n}\n\nexport function conflict(reply: FastifyReply, message = 'Resource already exists'): FastifyReply {\n return error(reply, message, 409);\n}\n\nexport function internalError(\n reply: FastifyReply,\n message = 'Internal server error'\n): FastifyReply {\n return error(reply, message, 500);\n}\n","import { z } from 'zod';\nimport type { ZodSchema, ZodError } from 'zod';\nimport { ValidationError } from '../../utils/errors.js';\n\nexport function validateBody<T>(schema: ZodSchema<T>, data: unknown): T {\n const result = schema.safeParse(data);\n\n if (!result.success) {\n throw new ValidationError(formatZodErrors(result.error));\n }\n\n return result.data;\n}\n\nexport function validateQuery<T extends z.ZodTypeAny>(schema: T, data: unknown): z.infer<T> {\n const result = schema.safeParse(data);\n\n if (!result.success) {\n throw new ValidationError(formatZodErrors(result.error));\n }\n\n return result.data;\n}\n\nexport function validateParams<T>(schema: ZodSchema<T>, data: unknown): T {\n const result = schema.safeParse(data);\n\n if (!result.success) {\n throw new ValidationError(formatZodErrors(result.error));\n }\n\n return result.data;\n}\n\nexport function validate<T>(schema: ZodSchema<T>, data: unknown): T {\n return validateBody(schema, data);\n}\n\nfunction formatZodErrors(error: ZodError): Record<string, string[]> {\n const errors: Record<string, string[]> = {};\n\n for (const issue of error.issues) {\n const path = issue.path.join('.') || 'root';\n if (!errors[path]) {\n errors[path] = [];\n }\n errors[path].push(issue.message);\n }\n\n return errors;\n}\n\n// Common validation schemas\nexport const idParamSchema = z.object({\n id: z.string().uuid('Invalid ID format'),\n});\n\nexport const paginationSchema = z.object({\n page: z.string().transform(Number).optional().default('1'),\n limit: z.string().transform(Number).optional().default('20'),\n sortBy: z.string().optional(),\n sortOrder: z.enum(['asc', 'desc']).optional().default('asc'),\n});\n\nexport const searchSchema = z.object({\n q: z.string().min(1, 'Search query is required').optional(),\n search: z.string().min(1).optional(),\n});\n\n// Email validation\nexport const emailSchema = z.string().email('Invalid email address');\n\n// Password validation with strength requirements\nexport const passwordSchema = z\n .string()\n .min(8, 'Password must be at least 8 characters')\n .regex(/[A-Z]/, 'Password must contain at least one uppercase letter')\n .regex(/[a-z]/, 'Password must contain at least one lowercase letter')\n .regex(/[0-9]/, 'Password must contain at least one number')\n .regex(/[^A-Za-z0-9]/, 'Password must contain at least one special character');\n\n// URL validation\nexport const urlSchema = z.string().url('Invalid URL format');\n\n// Phone validation (basic international format)\nexport const phoneSchema = z.string().regex(/^\\+?[1-9]\\d{1,14}$/, 'Invalid phone number format');\n\n// Date validation\nexport const dateSchema = z.coerce.date();\nexport const futureDateSchema = z.coerce\n .date()\n .refine((date) => date > new Date(), 'Date must be in the future');\nexport const pastDateSchema = z.coerce\n .date()\n .refine((date) => date < new Date(), 'Date must be in the past');\n\n// Type exports\nexport type IdParam = z.infer<typeof idParamSchema>;\nexport type PaginationInput = z.infer<typeof paginationSchema>;\n","import type { FastifyRequest, FastifyReply } from 'fastify';\nimport type { AuthService } from './auth.service.js';\nimport type { UserService } from '../user/user.service.js';\nimport {\n loginSchema,\n registerSchema,\n refreshTokenSchema,\n changePasswordSchema,\n} from './schemas.js';\nimport { success, created } from '../../utils/response.js';\nimport { BadRequestError, UnauthorizedError } from '../../utils/errors.js';\nimport { validateBody } from '../validation/validator.js';\nimport type { AuthenticatedRequest } from './types.js';\n\nexport class AuthController {\n constructor(\n private authService: AuthService,\n private userService: UserService\n ) {}\n\n async register(request: FastifyRequest, reply: FastifyReply): Promise<void> {\n const data = validateBody(registerSchema, request.body);\n\n // Check if user already exists\n const existingUser = await this.userService.findByEmail(data.email);\n if (existingUser) {\n throw new BadRequestError('Email already registered');\n }\n\n // Hash password and create user\n const hashedPassword = await this.authService.hashPassword(data.password);\n const user = await this.userService.create({\n email: data.email,\n password: hashedPassword,\n name: data.name,\n });\n\n // Generate tokens\n const tokens = this.authService.generateTokenPair({\n id: user.id,\n email: user.email,\n role: user.role,\n });\n\n created(reply, {\n user: {\n id: user.id,\n email: user.email,\n name: user.name,\n role: user.role,\n },\n ...tokens,\n });\n }\n\n async login(request: FastifyRequest, reply: FastifyReply): Promise<void> {\n const data = validateBody(loginSchema, request.body);\n\n // Find user\n const user = await this.userService.findByEmail(data.email);\n if (!user) {\n throw new UnauthorizedError('Invalid credentials');\n }\n\n // Check if user is active\n if (user.status !== 'active') {\n throw new UnauthorizedError('Account is not active');\n }\n\n // Verify password\n const isValidPassword = await this.authService.verifyPassword(data.password, user.password);\n if (!isValidPassword) {\n throw new UnauthorizedError('Invalid credentials');\n }\n\n // Update last login\n await this.userService.updateLastLogin(user.id);\n\n // Generate tokens\n const tokens = this.authService.generateTokenPair({\n id: user.id,\n email: user.email,\n role: user.role,\n });\n\n success(reply, {\n user: {\n id: user.id,\n email: user.email,\n name: user.name,\n role: user.role,\n },\n ...tokens,\n });\n }\n\n async refresh(request: FastifyRequest, reply: FastifyReply): Promise<void> {\n const data = validateBody(refreshTokenSchema, request.body);\n\n // Verify refresh token\n const payload = await this.authService.verifyRefreshToken(data.refreshToken);\n\n // Get fresh user data\n const user = await this.userService.findById(payload.sub);\n if (!user || user.status !== 'active') {\n throw new UnauthorizedError('User not found or inactive');\n }\n\n // Blacklist old refresh token (token rotation)\n await this.authService.blacklistToken(data.refreshToken);\n\n // Generate new tokens\n const tokens = this.authService.generateTokenPair({\n id: user.id,\n email: user.email,\n role: user.role,\n });\n\n success(reply, tokens);\n }\n\n async logout(request: FastifyRequest, reply: FastifyReply): Promise<void> {\n const authHeader = request.headers.authorization;\n if (authHeader?.startsWith('Bearer ')) {\n const token = authHeader.substring(7);\n await this.authService.blacklistToken(token);\n }\n\n success(reply, { message: 'Logged out successfully' });\n }\n\n async me(request: FastifyRequest, reply: FastifyReply): Promise<void> {\n const authRequest = request as AuthenticatedRequest;\n const user = await this.userService.findById(authRequest.user.id);\n\n if (!user) {\n throw new UnauthorizedError('User not found');\n }\n\n success(reply, {\n id: user.id,\n email: user.email,\n name: user.name,\n role: user.role,\n status: user.status,\n createdAt: user.createdAt,\n });\n }\n\n async changePassword(request: FastifyRequest, reply: FastifyReply): Promise<void> {\n const authRequest = request as AuthenticatedRequest;\n const data = validateBody(changePasswordSchema, request.body);\n\n // Get current user\n const user = await this.userService.findById(authRequest.user.id);\n if (!user) {\n throw new UnauthorizedError('User not found');\n }\n\n // Verify current password\n const isValidPassword = await this.authService.verifyPassword(\n data.currentPassword,\n user.password\n );\n if (!isValidPassword) {\n throw new BadRequestError('Current password is incorrect');\n }\n\n // Hash and update password\n const hashedPassword = await this.authService.hashPassword(data.newPassword);\n await this.userService.updatePassword(user.id, hashedPassword);\n\n success(reply, { message: 'Password changed successfully' });\n }\n}\n\nexport function createAuthController(\n authService: AuthService,\n userService: UserService\n): AuthController {\n return new AuthController(authService, userService);\n}\n","import type { FastifyRequest, FastifyReply } from 'fastify';\nimport { UnauthorizedError, ForbiddenError } from '../../utils/errors.js';\nimport type { AuthService } from './auth.service.js';\nimport type { AuthUser } from './types.js';\n\nexport function createAuthMiddleware(authService: AuthService) {\n return async function authenticate(request: FastifyRequest, _reply: FastifyReply): Promise<void> {\n const authHeader = request.headers.authorization;\n\n if (!authHeader || !authHeader.startsWith('Bearer ')) {\n throw new UnauthorizedError('Missing or invalid authorization header');\n }\n\n const token = authHeader.substring(7);\n const payload = await authService.verifyAccessToken(token);\n\n request.user = {\n id: payload.sub,\n email: payload.email,\n role: payload.role,\n };\n };\n}\n\nexport function createRoleMiddleware(allowedRoles: string[]) {\n return async function authorize(request: FastifyRequest, _reply: FastifyReply): Promise<void> {\n const user = request.user as AuthUser | undefined;\n\n if (!user) {\n throw new UnauthorizedError('Authentication required');\n }\n\n if (!allowedRoles.includes(user.role)) {\n throw new ForbiddenError('Insufficient permissions');\n }\n };\n}\n\nexport function createPermissionMiddleware(_requiredPermissions: string[]) {\n return async function checkPermissions(\n request: FastifyRequest,\n _reply: FastifyReply\n ): Promise<void> {\n const user = request.user as AuthUser | undefined;\n\n if (!user) {\n throw new UnauthorizedError('Authentication required');\n }\n\n // This would check against a permissions system\n // For now, we'll implement a basic role-based check\n // In a full implementation, you'd query the user's permissions from the database\n };\n}\n\n// Optional authentication - doesn't throw if no token\nexport function createOptionalAuthMiddleware(authService: AuthService) {\n return async function optionalAuthenticate(\n request: FastifyRequest,\n _reply: FastifyReply\n ): Promise<void> {\n const authHeader = request.headers.authorization;\n\n if (!authHeader || !authHeader.startsWith('Bearer ')) {\n return;\n }\n\n try {\n const token = authHeader.substring(7);\n const payload = await authService.verifyAccessToken(token);\n\n request.user = {\n id: payload.sub,\n email: payload.email,\n role: payload.role,\n };\n } catch {\n // Silently ignore auth errors for optional auth\n }\n };\n}\n","import type { FastifyInstance } from 'fastify';\nimport type { AuthController } from './auth.controller.js';\nimport type { AuthService } from './auth.service.js';\nimport { createAuthMiddleware } from './auth.middleware.js';\n\nexport function registerAuthRoutes(\n app: FastifyInstance,\n controller: AuthController,\n authService: AuthService\n): void {\n const authenticate = createAuthMiddleware(authService);\n\n // Public routes\n app.post('/auth/register', controller.register.bind(controller));\n app.post('/auth/login', controller.login.bind(controller));\n app.post('/auth/refresh', controller.refresh.bind(controller));\n\n // Protected routes\n app.post('/auth/logout', { preHandler: [authenticate] }, controller.logout.bind(controller));\n app.get('/auth/me', { preHandler: [authenticate] }, controller.me.bind(controller));\n app.post(\n '/auth/change-password',\n { preHandler: [authenticate] },\n controller.changePassword.bind(controller)\n );\n}\n","import { PrismaClient } from '@prisma/client';\nimport { logger } from '../core/logger.js';\nimport { isProduction } from '../config/index.js';\n\ndeclare global {\n var __prisma: PrismaClient | undefined;\n}\n\nconst prismaClientSingleton = (): PrismaClient => {\n return new PrismaClient({\n log: isProduction() ? ['error'] : ['query', 'info', 'warn', 'error'],\n errorFormat: isProduction() ? 'minimal' : 'pretty',\n });\n};\n\n// Use singleton pattern to prevent multiple instances in development\nexport const prisma = globalThis.__prisma ?? prismaClientSingleton();\n\nif (!isProduction()) {\n globalThis.__prisma = prisma;\n}\n\nexport async function connectDatabase(): Promise<void> {\n try {\n await prisma.$connect();\n logger.info('Database connected successfully');\n } catch (error) {\n logger.error({ err: error }, 'Failed to connect to database');\n throw error;\n }\n}\n\nexport async function disconnectDatabase(): Promise<void> {\n try {\n await prisma.$disconnect();\n logger.info('Database disconnected');\n } catch (error) {\n logger.error({ err: error }, 'Error disconnecting from database');\n }\n}\n\nexport async function checkDatabaseHealth(): Promise<boolean> {\n try {\n await prisma.$queryRaw`SELECT 1`;\n return true;\n } catch {\n return false;\n }\n}\n\nexport { PrismaClient };\n","import type { PaginationParams, PaginatedResult } from '../types/index.js';\n\nexport const DEFAULT_PAGE = 1;\nexport const DEFAULT_LIMIT = 20;\nexport const MAX_LIMIT = 100;\n\nexport function parsePaginationParams(query: Record<string, unknown>): PaginationParams {\n const page = Math.max(1, parseInt(String(query.page || DEFAULT_PAGE), 10));\n const limit = Math.min(\n MAX_LIMIT,\n Math.max(1, parseInt(String(query.limit || DEFAULT_LIMIT), 10))\n );\n const sortBy = typeof query.sortBy === 'string' ? query.sortBy : undefined;\n const sortOrder = query.sortOrder === 'desc' ? 'desc' : 'asc';\n\n return { page, limit, sortBy, sortOrder };\n}\n\nexport function createPaginatedResult<T>(\n data: T[],\n total: number,\n params: PaginationParams\n): PaginatedResult<T> {\n const totalPages = Math.ceil(total / params.limit);\n\n return {\n data,\n meta: {\n total,\n page: params.page,\n limit: params.limit,\n totalPages,\n hasNextPage: params.page < totalPages,\n hasPrevPage: params.page > 1,\n },\n };\n}\n\nexport function getSkip(params: PaginationParams): number {\n return (params.page - 1) * params.limit;\n}\n","import { prisma } from '../../database/prisma.js';\nimport type { PaginatedResult, PaginationParams } from '../../types/index.js';\nimport { createPaginatedResult, getSkip } from '../../utils/pagination.js';\nimport type { User, CreateUserData, UpdateUserData, UserFilters } from './types.js';\n\n// Use string literal enums for ESM/CommonJS compatibility\nconst UserRole = {\n USER: 'USER',\n MODERATOR: 'MODERATOR',\n ADMIN: 'ADMIN',\n SUPER_ADMIN: 'SUPER_ADMIN',\n} as const;\n\nconst UserStatus = {\n ACTIVE: 'ACTIVE',\n INACTIVE: 'INACTIVE',\n SUSPENDED: 'SUSPENDED',\n BANNED: 'BANNED',\n} as const;\n\ntype UserRole = (typeof UserRole)[keyof typeof UserRole];\ntype UserStatus = (typeof UserStatus)[keyof typeof UserStatus];\n\n/**\n * User Repository - Prisma Implementation\n * Manages user data persistence using Prisma ORM\n */\nexport class UserRepository {\n /**\n * Find user by ID\n */\n async findById(id: string): Promise<User | null> {\n const user = await prisma.user.findUnique({\n where: { id },\n });\n\n if (!user) return null;\n return this.mapPrismaUserToUser(user);\n }\n\n /**\n * Find user by email (case-insensitive)\n */\n async findByEmail(email: string): Promise<User | null> {\n const user = await prisma.user.findUnique({\n where: { email: email.toLowerCase() },\n });\n\n if (!user) return null;\n return this.mapPrismaUserToUser(user);\n }\n\n /**\n * Find multiple users with pagination and filters\n */\n async findMany(params: PaginationParams, filters?: UserFilters): Promise<PaginatedResult<User>> {\n const where = this.buildWhereClause(filters);\n const orderBy = this.buildOrderBy(params);\n\n const [data, total] = await Promise.all([\n prisma.user.findMany({\n where,\n orderBy,\n skip: getSkip(params),\n take: params.limit,\n }),\n prisma.user.count({ where }),\n ]);\n\n const mappedUsers = data.map((user) => this.mapPrismaUserToUser(user));\n\n return createPaginatedResult(mappedUsers, total, params);\n }\n\n /**\n * Create a new user\n */\n async create(data: CreateUserData): Promise<User> {\n const user = await prisma.user.create({\n data: {\n email: data.email.toLowerCase(),\n password: data.password,\n name: data.name,\n role: this.mapRoleToEnum(data.role || 'user'),\n status: UserStatus.ACTIVE,\n emailVerified: false,\n },\n });\n\n return this.mapPrismaUserToUser(user);\n }\n\n /**\n * Update user data\n */\n async update(id: string, data: UpdateUserData): Promise<User | null> {\n try {\n const user = await prisma.user.update({\n where: { id },\n data: {\n ...(data.email && { email: data.email.toLowerCase() }),\n ...(data.name !== undefined && { name: data.name }),\n ...(data.role && { role: this.mapRoleToEnum(data.role) }),\n ...(data.status && { status: this.mapStatusToEnum(data.status) }),\n ...(data.emailVerified !== undefined && { emailVerified: data.emailVerified }),\n ...(data.metadata && { metadata: data.metadata as object }),\n },\n });\n\n return this.mapPrismaUserToUser(user);\n } catch {\n // User not found\n return null;\n }\n }\n\n /**\n * Update user password\n */\n async updatePassword(id: string, password: string): Promise<User | null> {\n try {\n const user = await prisma.user.update({\n where: { id },\n data: { password },\n });\n\n return this.mapPrismaUserToUser(user);\n } catch {\n return null;\n }\n }\n\n /**\n * Update last login timestamp\n */\n async updateLastLogin(id: string): Promise<User | null> {\n try {\n const user = await prisma.user.update({\n where: { id },\n data: { lastLoginAt: new Date() },\n });\n\n return this.mapPrismaUserToUser(user);\n } catch {\n return null;\n }\n }\n\n /**\n * Delete user by ID\n */\n async delete(id: string): Promise<boolean> {\n try {\n await prisma.user.delete({\n where: { id },\n });\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Count users with optional filters\n */\n async count(filters?: UserFilters): Promise<number> {\n const where = this.buildWhereClause(filters);\n return prisma.user.count({ where });\n }\n\n /**\n * Helper to clear all users (for testing only)\n * WARNING: This deletes all users from the database\n */\n async clear(): Promise<void> {\n await prisma.user.deleteMany();\n }\n\n /**\n * Build Prisma where clause from filters\n */\n private buildWhereClause(filters?: UserFilters): object {\n if (!filters) return {};\n\n return {\n ...(filters.status && { status: this.mapStatusToEnum(filters.status) }),\n ...(filters.role && { role: this.mapRoleToEnum(filters.role) }),\n ...(filters.emailVerified !== undefined && { emailVerified: filters.emailVerified }),\n ...(filters.search && {\n OR: [\n { email: { contains: filters.search, mode: 'insensitive' as const } },\n { name: { contains: filters.search, mode: 'insensitive' as const } },\n ],\n }),\n };\n }\n\n /**\n * Build Prisma orderBy clause from pagination params\n */\n private buildOrderBy(params: PaginationParams): object {\n if (!params.sortBy) {\n return { createdAt: 'desc' as const };\n }\n\n return {\n [params.sortBy]: params.sortOrder || 'asc',\n };\n }\n\n /**\n * Map Prisma User to application User type\n */\n private mapPrismaUserToUser(prismaUser: {\n id: string;\n email: string;\n password: string;\n name: string | null;\n role: UserRole;\n status: UserStatus;\n emailVerified: boolean;\n lastLoginAt: Date | null;\n metadata: unknown;\n createdAt: Date;\n updatedAt: Date;\n }): User {\n return {\n id: prismaUser.id,\n email: prismaUser.email,\n password: prismaUser.password,\n name: prismaUser.name ?? undefined,\n role: this.mapEnumToRole(prismaUser.role),\n status: this.mapEnumToStatus(prismaUser.status),\n emailVerified: prismaUser.emailVerified,\n lastLoginAt: prismaUser.lastLoginAt ?? undefined,\n metadata: prismaUser.metadata as Record<string, unknown> | undefined,\n createdAt: prismaUser.createdAt,\n updatedAt: prismaUser.updatedAt,\n };\n }\n\n /**\n * Map application role to Prisma enum\n */\n private mapRoleToEnum(role: string): UserRole {\n const roleMap: Record<string, UserRole> = {\n user: UserRole.USER,\n moderator: UserRole.MODERATOR,\n admin: UserRole.ADMIN,\n super_admin: UserRole.SUPER_ADMIN,\n };\n return roleMap[role] || UserRole.USER;\n }\n\n /**\n * Map Prisma enum to application role\n */\n private mapEnumToRole(role: UserRole): User['role'] {\n const roleMap: Record<UserRole, User['role']> = {\n [UserRole.USER]: 'user',\n [UserRole.MODERATOR]: 'moderator',\n [UserRole.ADMIN]: 'admin',\n [UserRole.SUPER_ADMIN]: 'super_admin',\n };\n return roleMap[role];\n }\n\n /**\n * Map application status to Prisma enum\n */\n private mapStatusToEnum(status: string): UserStatus {\n const statusMap: Record<string, UserStatus> = {\n active: UserStatus.ACTIVE,\n inactive: UserStatus.INACTIVE,\n suspended: UserStatus.SUSPENDED,\n banned: UserStatus.BANNED,\n };\n return statusMap[status] || UserStatus.ACTIVE;\n }\n\n /**\n * Map Prisma enum to application status\n */\n private mapEnumToStatus(status: UserStatus): User['status'] {\n const statusMap: Record<UserStatus, User['status']> = {\n [UserStatus.ACTIVE]: 'active',\n [UserStatus.INACTIVE]: 'inactive',\n [UserStatus.SUSPENDED]: 'suspended',\n [UserStatus.BANNED]: 'banned',\n };\n return statusMap[status];\n }\n}\n\nexport function createUserRepository(): UserRepository {\n return new UserRepository();\n}\n","import type { BaseEntity } from '../../types/index.js';\n\nexport type UserStatus = 'active' | 'inactive' | 'suspended' | 'banned';\n\nexport type UserRole = 'user' | 'admin' | 'moderator' | 'super_admin';\n\nexport interface User extends BaseEntity {\n email: string;\n password: string;\n name?: string;\n role: UserRole;\n status: UserStatus;\n emailVerified: boolean;\n lastLoginAt?: Date;\n metadata?: Record<string, unknown>;\n}\n\nexport interface CreateUserData {\n email: string;\n password: string;\n name?: string;\n role?: UserRole;\n}\n\nexport interface UpdateUserData {\n email?: string;\n name?: string;\n role?: UserRole;\n status?: UserStatus;\n emailVerified?: boolean;\n metadata?: Record<string, unknown>;\n}\n\nexport interface UserFilters {\n status?: UserStatus;\n role?: UserRole;\n search?: string;\n emailVerified?: boolean;\n}\n\n// RBAC Types\nexport interface Permission {\n id: string;\n name: string;\n description?: string;\n resource: string;\n action: 'create' | 'read' | 'update' | 'delete' | 'manage';\n}\n\nexport interface Role {\n id: string;\n name: UserRole;\n description?: string;\n permissions: Permission[];\n}\n\n// Default permissions mapping\nexport const DEFAULT_ROLE_PERMISSIONS: Record<UserRole, string[]> = {\n user: ['profile:read', 'profile:update'],\n moderator: [\n 'profile:read',\n 'profile:update',\n 'users:read',\n 'content:read',\n 'content:update',\n 'content:delete',\n ],\n admin: [\n 'profile:read',\n 'profile:update',\n 'users:read',\n 'users:update',\n 'users:delete',\n 'content:manage',\n 'settings:read',\n ],\n super_admin: ['*:manage'], // All permissions\n};\n","import type { PaginatedResult, PaginationParams } from '../../types/index.js';\nimport { NotFoundError, ConflictError } from '../../utils/errors.js';\nimport type { UserRepository } from './user.repository.js';\nimport { createUserRepository } from './user.repository.js';\nimport type { User, CreateUserData, UpdateUserData, UserFilters, UserRole } from './types.js';\nimport { DEFAULT_ROLE_PERMISSIONS } from './types.js';\nimport { logger } from '../../core/logger.js';\n\nexport class UserService {\n constructor(private repository: UserRepository) {}\n\n async findById(id: string): Promise<User | null> {\n return this.repository.findById(id);\n }\n\n async findByEmail(email: string): Promise<User | null> {\n return this.repository.findByEmail(email);\n }\n\n async findMany(\n params: PaginationParams,\n filters?: UserFilters\n ): Promise<PaginatedResult<Omit<User, 'password'>>> {\n const result = await this.repository.findMany(params, filters);\n\n // Remove passwords from results\n return {\n ...result,\n data: result.data.map(({ password: _password, ...user }) => user) as Omit<User, 'password'>[],\n };\n }\n\n async create(data: CreateUserData): Promise<User> {\n // Check for existing user\n const existing = await this.repository.findByEmail(data.email);\n if (existing) {\n throw new ConflictError('User with this email already exists');\n }\n\n const user = await this.repository.create(data);\n logger.info({ userId: user.id, email: user.email }, 'User created');\n return user;\n }\n\n async update(id: string, data: UpdateUserData): Promise<User> {\n const user = await this.repository.findById(id);\n if (!user) {\n throw new NotFoundError('User');\n }\n\n // Check email uniqueness if changing email\n if (data.email && data.email !== user.email) {\n const existing = await this.repository.findByEmail(data.email);\n if (existing) {\n throw new ConflictError('Email already in use');\n }\n }\n\n const updatedUser = await this.repository.update(id, data);\n if (!updatedUser) {\n throw new NotFoundError('User');\n }\n\n logger.info({ userId: id }, 'User updated');\n return updatedUser;\n }\n\n async updatePassword(id: string, hashedPassword: string): Promise<User> {\n const user = await this.repository.updatePassword(id, hashedPassword);\n if (!user) {\n throw new NotFoundError('User');\n }\n logger.info({ userId: id }, 'User password updated');\n return user;\n }\n\n async updateLastLogin(id: string): Promise<User> {\n const user = await this.repository.updateLastLogin(id);\n if (!user) {\n throw new NotFoundError('User');\n }\n return user;\n }\n\n async delete(id: string): Promise<void> {\n const user = await this.repository.findById(id);\n if (!user) {\n throw new NotFoundError('User');\n }\n\n await this.repository.delete(id);\n logger.info({ userId: id }, 'User deleted');\n }\n\n async suspend(id: string): Promise<User> {\n return this.update(id, { status: 'suspended' });\n }\n\n async ban(id: string): Promise<User> {\n return this.update(id, { status: 'banned' });\n }\n\n async activate(id: string): Promise<User> {\n return this.update(id, { status: 'active' });\n }\n\n async verifyEmail(id: string): Promise<User> {\n return this.update(id, { emailVerified: true });\n }\n\n async changeRole(id: string, role: UserRole): Promise<User> {\n return this.update(id, { role });\n }\n\n // RBAC helpers\n hasPermission(role: UserRole, permission: string): boolean {\n const permissions = DEFAULT_ROLE_PERMISSIONS[role] || [];\n\n // Super admin has all permissions\n if (permissions.includes('*:manage')) {\n return true;\n }\n\n // Check exact match\n if (permissions.includes(permission)) {\n return true;\n }\n\n // Check wildcard match (e.g., \"content:manage\" matches \"content:read\")\n const [resource] = permission.split(':');\n const managePermission = `${resource}:manage`;\n if (permissions.includes(managePermission)) {\n return true;\n }\n\n return false;\n }\n\n getPermissions(role: UserRole): string[] {\n return DEFAULT_ROLE_PERMISSIONS[role] || [];\n }\n}\n\nexport function createUserService(repository?: UserRepository): UserService {\n return new UserService(repository || createUserRepository());\n}\n","import { z } from 'zod';\n\nexport const userStatusEnum = z.enum(['active', 'inactive', 'suspended', 'banned']);\nexport const userRoleEnum = z.enum(['user', 'admin', 'moderator', 'super_admin']);\n\nexport const createUserSchema = z.object({\n email: z.string().email('Invalid email address'),\n password: z\n .string()\n .min(8, 'Password must be at least 8 characters')\n .regex(/[A-Z]/, 'Password must contain at least one uppercase letter')\n .regex(/[a-z]/, 'Password must contain at least one lowercase letter')\n .regex(/[0-9]/, 'Password must contain at least one number'),\n name: z.string().min(2, 'Name must be at least 2 characters').optional(),\n role: userRoleEnum.optional().default('user'),\n});\n\nexport const updateUserSchema = z.object({\n email: z.string().email('Invalid email address').optional(),\n name: z.string().min(2, 'Name must be at least 2 characters').optional(),\n role: userRoleEnum.optional(),\n status: userStatusEnum.optional(),\n emailVerified: z.boolean().optional(),\n metadata: z.record(z.unknown()).optional(),\n});\n\nexport const updateProfileSchema = z.object({\n name: z.string().min(2, 'Name must be at least 2 characters').optional(),\n metadata: z.record(z.unknown()).optional(),\n});\n\nexport const userQuerySchema = z.object({\n page: z.string().transform(Number).optional(),\n limit: z.string().transform(Number).optional(),\n sortBy: z.string().optional(),\n sortOrder: z.enum(['asc', 'desc']).optional(),\n status: userStatusEnum.optional(),\n role: userRoleEnum.optional(),\n search: z.string().optional(),\n emailVerified: z\n .string()\n .transform((val) => val === 'true')\n .optional(),\n});\n\nexport type CreateUserInput = z.infer<typeof createUserSchema>;\nexport type UpdateUserInput = z.infer<typeof updateUserSchema>;\nexport type UpdateProfileInput = z.infer<typeof updateProfileSchema>;\nexport type UserQueryInput = z.infer<typeof userQuerySchema>;\n","import type { FastifyRequest, FastifyReply } from 'fastify';\nimport type { UserService } from './user.service.js';\nimport { updateUserSchema, updateProfileSchema, userQuerySchema } from './schemas.js';\nimport { success, noContent } from '../../utils/response.js';\nimport { parsePaginationParams } from '../../utils/pagination.js';\nimport { validateBody, validateQuery } from '../validation/validator.js';\nimport type { AuthenticatedRequest } from '../auth/types.js';\nimport { ForbiddenError } from '../../utils/errors.js';\nimport type { User } from './types.js';\n\n// Helper to remove password from user object\nfunction omitPassword(user: User): Omit<User, 'password'> {\n const { password, ...userData } = user;\n void password; // Explicitly mark as intentionally unused\n return userData;\n}\n\nexport class UserController {\n constructor(private userService: UserService) {}\n\n async list(request: FastifyRequest, reply: FastifyReply): Promise<void> {\n const query = validateQuery(userQuerySchema, request.query);\n const pagination = parsePaginationParams(query);\n\n const filters = {\n status: query.status,\n role: query.role,\n search: query.search,\n emailVerified: query.emailVerified,\n };\n\n const result = await this.userService.findMany(pagination, filters);\n success(reply, result);\n }\n\n async getById(\n request: FastifyRequest<{ Params: { id: string } }>,\n reply: FastifyReply\n ): Promise<void> {\n const user = await this.userService.findById(request.params.id);\n\n if (!user) {\n return reply.status(404).send({\n success: false,\n message: 'User not found',\n });\n }\n\n // Remove password from response\n success(reply, omitPassword(user));\n }\n\n async update(\n request: FastifyRequest<{ Params: { id: string } }>,\n reply: FastifyReply\n ): Promise<void> {\n const data = validateBody(updateUserSchema, request.body);\n const user = await this.userService.update(request.params.id, data);\n\n success(reply, omitPassword(user));\n }\n\n async delete(\n request: FastifyRequest<{ Params: { id: string } }>,\n reply: FastifyReply\n ): Promise<void> {\n const authRequest = request as AuthenticatedRequest;\n\n // Prevent self-deletion\n if (authRequest.user.id === request.params.id) {\n throw new ForbiddenError('Cannot delete your own account');\n }\n\n await this.userService.delete(request.params.id);\n noContent(reply);\n }\n\n async suspend(\n request: FastifyRequest<{ Params: { id: string } }>,\n reply: FastifyReply\n ): Promise<void> {\n const authRequest = request as AuthenticatedRequest;\n\n if (authRequest.user.id === request.params.id) {\n throw new ForbiddenError('Cannot suspend your own account');\n }\n\n const user = await this.userService.suspend(request.params.id);\n const userData = omitPassword(user);\n success(reply, userData);\n }\n\n async ban(\n request: FastifyRequest<{ Params: { id: string } }>,\n reply: FastifyReply\n ): Promise<void> {\n const authRequest = request as AuthenticatedRequest;\n\n if (authRequest.user.id === request.params.id) {\n throw new ForbiddenError('Cannot ban your own account');\n }\n\n const user = await this.userService.ban(request.params.id);\n const userData = omitPassword(user);\n success(reply, userData);\n }\n\n async activate(\n request: FastifyRequest<{ Params: { id: string } }>,\n reply: FastifyReply\n ): Promise<void> {\n const user = await this.userService.activate(request.params.id);\n const userData = omitPassword(user);\n success(reply, userData);\n }\n\n // Profile routes (for authenticated user)\n async getProfile(request: FastifyRequest, reply: FastifyReply): Promise<void> {\n const authRequest = request as AuthenticatedRequest;\n const user = await this.userService.findById(authRequest.user.id);\n\n if (!user) {\n return reply.status(404).send({\n success: false,\n message: 'User not found',\n });\n }\n\n const userData = omitPassword(user);\n success(reply, userData);\n }\n\n async updateProfile(request: FastifyRequest, reply: FastifyReply): Promise<void> {\n const authRequest = request as AuthenticatedRequest;\n const data = validateBody(updateProfileSchema, request.body);\n\n const user = await this.userService.update(authRequest.user.id, data);\n const userData = omitPassword(user);\n success(reply, userData);\n }\n}\n\nexport function createUserController(userService: UserService): UserController {\n return new UserController(userService);\n}\n","import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';\nimport type { UserController } from './user.controller.js';\nimport type { AuthService } from '../auth/auth.service.js';\nimport { createAuthMiddleware, createRoleMiddleware } from '../auth/auth.middleware.js';\n\n// Route params schema for Fastify\nconst idParamsSchema = {\n type: 'object',\n properties: {\n id: { type: 'string' },\n },\n required: ['id'],\n} as const;\n\nexport function registerUserRoutes(\n app: FastifyInstance,\n controller: UserController,\n authService: AuthService\n): void {\n const authenticate = createAuthMiddleware(authService);\n const isAdmin = createRoleMiddleware(['admin', 'super_admin']);\n const isModerator = createRoleMiddleware(['moderator', 'admin', 'super_admin']);\n\n // Profile routes (authenticated users)\n app.get('/profile', { preHandler: [authenticate] }, controller.getProfile.bind(controller));\n app.patch('/profile', { preHandler: [authenticate] }, controller.updateProfile.bind(controller));\n\n // Admin routes\n app.get('/users', { preHandler: [authenticate, isModerator] }, controller.list.bind(controller));\n app.get<{ Params: { id: string } }>(\n '/users/:id',\n { preHandler: [authenticate, isModerator], schema: { params: idParamsSchema } },\n async (request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) => {\n return controller.getById(request, reply);\n }\n );\n app.patch<{ Params: { id: string } }>(\n '/users/:id',\n { preHandler: [authenticate, isAdmin], schema: { params: idParamsSchema } },\n async (request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) => {\n return controller.update(request, reply);\n }\n );\n app.delete<{ Params: { id: string } }>(\n '/users/:id',\n { preHandler: [authenticate, isAdmin], schema: { params: idParamsSchema } },\n async (request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) => {\n return controller.delete(request, reply);\n }\n );\n\n // User status management\n app.post<{ Params: { id: string } }>(\n '/users/:id/suspend',\n { preHandler: [authenticate, isAdmin], schema: { params: idParamsSchema } },\n async (request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) => {\n return controller.suspend(request, reply);\n }\n );\n app.post<{ Params: { id: string } }>(\n '/users/:id/ban',\n { preHandler: [authenticate, isAdmin], schema: { params: idParamsSchema } },\n async (request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) => {\n return controller.ban(request, reply);\n }\n );\n app.post<{ Params: { id: string } }>(\n '/users/:id/activate',\n { preHandler: [authenticate, isAdmin], schema: { params: idParamsSchema } },\n async (request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) => {\n return controller.activate(request, reply);\n }\n );\n}\n","import type { FastifyInstance } from 'fastify';\nimport { logger } from '../../core/logger.js';\nimport { createUserService } from './user.service.js';\nimport { createUserController } from './user.controller.js';\nimport { createUserRepository } from './user.repository.js';\nimport { registerUserRoutes } from './user.routes.js';\nimport type { AuthService } from '../auth/auth.service.js';\n\nexport async function registerUserModule(\n app: FastifyInstance,\n authService: AuthService\n): Promise<void> {\n // Create repository and service\n const repository = createUserRepository();\n const userService = createUserService(repository);\n\n // Create controller\n const userController = createUserController(userService);\n\n // Register routes\n registerUserRoutes(app, userController, authService);\n\n logger.info('User module registered');\n}\n\nexport { UserService, createUserService } from './user.service.js';\nexport { UserController, createUserController } from './user.controller.js';\nexport { UserRepository, createUserRepository } from './user.repository.js';\nexport * from './types.js';\nexport * from './schemas.js';\n","import nodemailer from 'nodemailer';\nimport type { Transporter } from 'nodemailer';\nimport { config } from '../../config/index.js';\nimport { logger } from '../../core/logger.js';\nimport { renderTemplate } from './templates.js';\nimport type { EmailOptions, EmailResult, EmailConfig, TemplateData } from './types.js';\n\nexport class EmailService {\n private transporter: Transporter | null = null;\n private config: EmailConfig | null = null;\n\n constructor(emailConfig?: Partial<EmailConfig>) {\n if (emailConfig?.host || config.email.host) {\n this.config = {\n host: emailConfig?.host || config.email.host || '',\n port: emailConfig?.port || config.email.port || 587,\n secure: (emailConfig?.port || config.email.port || 587) === 465,\n auth: {\n user: emailConfig?.auth?.user || config.email.user || '',\n pass: emailConfig?.auth?.pass || config.email.pass || '',\n },\n from: emailConfig?.from || config.email.from || 'noreply@localhost',\n };\n\n this.transporter = nodemailer.createTransport({\n host: this.config.host,\n port: this.config.port,\n secure: this.config.secure,\n auth: {\n user: this.config.auth.user,\n pass: this.config.auth.pass,\n },\n });\n\n logger.info('Email service initialized');\n } else {\n logger.warn('Email service not configured - emails will be logged only');\n }\n }\n\n async send(options: EmailOptions): Promise<EmailResult> {\n try {\n let html = options.html;\n let text = options.text;\n\n // Render template if provided\n if (options.template && options.data) {\n html = renderTemplate(options.template, options.data);\n }\n\n // Generate plain text from HTML if not provided\n if (html && !text) {\n text = this.htmlToText(html);\n }\n\n const mailOptions = {\n from: this.config?.from || 'noreply@localhost',\n to: Array.isArray(options.to) ? options.to.join(', ') : options.to,\n subject: options.subject,\n html,\n text,\n replyTo: options.replyTo,\n cc: options.cc,\n bcc: options.bcc,\n attachments: options.attachments,\n };\n\n // If no transporter, just log the email\n if (!this.transporter) {\n logger.info({ email: mailOptions }, 'Email would be sent (no transporter configured)');\n return { success: true, messageId: 'dev-mode' };\n }\n\n const result = await this.transporter.sendMail(mailOptions);\n\n logger.info({ messageId: result.messageId, to: options.to }, 'Email sent successfully');\n\n return {\n success: true,\n messageId: result.messageId,\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n logger.error({ err: error, to: options.to }, 'Failed to send email');\n\n return {\n success: false,\n error: errorMessage,\n };\n }\n }\n\n async sendTemplate(to: string, template: string, data: TemplateData): Promise<EmailResult> {\n const subjects: Record<string, string> = {\n welcome: `Welcome to ${data.appName || 'Servcraft'}!`,\n 'verify-email': 'Verify Your Email',\n 'password-reset': 'Reset Your Password',\n 'password-changed': 'Password Changed Successfully',\n 'login-alert': 'New Login Detected',\n 'account-suspended': 'Account Suspended',\n };\n\n return this.send({\n to,\n subject: subjects[template] || 'Notification',\n template,\n data,\n });\n }\n\n async sendWelcome(email: string, name: string, verifyUrl?: string): Promise<EmailResult> {\n return this.sendTemplate(email, 'welcome', {\n userName: name,\n userEmail: email,\n actionUrl: verifyUrl,\n });\n }\n\n async sendVerifyEmail(email: string, name: string, verifyUrl: string): Promise<EmailResult> {\n return this.sendTemplate(email, 'verify-email', {\n userName: name,\n userEmail: email,\n actionUrl: verifyUrl,\n expiresIn: '24 hours',\n });\n }\n\n async sendPasswordReset(email: string, name: string, resetUrl: string): Promise<EmailResult> {\n return this.sendTemplate(email, 'password-reset', {\n userName: name,\n userEmail: email,\n actionUrl: resetUrl,\n expiresIn: '1 hour',\n });\n }\n\n async sendPasswordChanged(\n email: string,\n name: string,\n ipAddress?: string,\n userAgent?: string\n ): Promise<EmailResult> {\n return this.sendTemplate(email, 'password-changed', {\n userName: name,\n userEmail: email,\n ipAddress: ipAddress || 'Unknown',\n userAgent: userAgent || 'Unknown',\n timestamp: new Date().toISOString(),\n });\n }\n\n async sendLoginAlert(\n email: string,\n name: string,\n ipAddress: string,\n userAgent: string,\n location?: string\n ): Promise<EmailResult> {\n return this.sendTemplate(email, 'login-alert', {\n userName: name,\n userEmail: email,\n ipAddress,\n userAgent,\n location: location || 'Unknown',\n timestamp: new Date().toISOString(),\n });\n }\n\n async verify(): Promise<boolean> {\n if (!this.transporter) {\n return false;\n }\n\n try {\n await this.transporter.verify();\n logger.info('Email service connection verified');\n return true;\n } catch (error) {\n logger.error({ err: error }, 'Email service connection failed');\n return false;\n }\n }\n\n private htmlToText(html: string): string {\n return html\n .replace(/<style[^>]*>[\\s\\S]*?<\\/style>/gi, '')\n .replace(/<script[^>]*>[\\s\\S]*?<\\/script>/gi, '')\n .replace(/<[^>]+>/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n }\n}\n\nlet emailService: EmailService | null = null;\n\nexport function getEmailService(): EmailService {\n if (!emailService) {\n emailService = new EmailService();\n }\n return emailService;\n}\n\nexport function createEmailService(config?: Partial<EmailConfig>): EmailService {\n return new EmailService(config);\n}\n","import Handlebars from 'handlebars';\n\n// Base layout template\nconst baseLayout = `\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>{{subject}}</title>\n <style>\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;\n line-height: 1.6;\n color: #333;\n max-width: 600px;\n margin: 0 auto;\n padding: 20px;\n background-color: #f5f5f5;\n }\n .container {\n background-color: #ffffff;\n border-radius: 8px;\n padding: 40px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n }\n .header {\n text-align: center;\n margin-bottom: 30px;\n }\n .logo {\n font-size: 24px;\n font-weight: bold;\n color: #2563eb;\n }\n .content {\n margin-bottom: 30px;\n }\n .button {\n display: inline-block;\n padding: 12px 24px;\n background-color: #2563eb;\n color: #ffffff !important;\n text-decoration: none;\n border-radius: 6px;\n font-weight: 500;\n }\n .button:hover {\n background-color: #1d4ed8;\n }\n .footer {\n text-align: center;\n font-size: 12px;\n color: #666;\n margin-top: 30px;\n padding-top: 20px;\n border-top: 1px solid #eee;\n }\n .warning {\n background-color: #fef3c7;\n border: 1px solid #f59e0b;\n border-radius: 6px;\n padding: 12px;\n margin: 20px 0;\n }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <div class=\"header\">\n <div class=\"logo\">{{appName}}</div>\n </div>\n <div class=\"content\">\n {{{body}}}\n </div>\n <div class=\"footer\">\n <p>© {{year}} {{appName}}. All rights reserved.</p>\n <p>This email was sent to {{userEmail}}</p>\n </div>\n </div>\n</body>\n</html>\n`;\n\n// Individual templates\nconst templates: Record<string, string> = {\n welcome: `\n <h2>Welcome to {{appName}}!</h2>\n <p>Hi {{userName}},</p>\n <p>Thank you for joining {{appName}}. We're excited to have you on board!</p>\n <p>To get started, please verify your email address by clicking the button below:</p>\n <p style=\"text-align: center; margin: 30px 0;\">\n <a href=\"{{actionUrl}}\" class=\"button\">Verify Email</a>\n </p>\n <p>If you didn't create an account with us, you can safely ignore this email.</p>\n `,\n\n 'verify-email': `\n <h2>Verify Your Email</h2>\n <p>Hi {{userName}},</p>\n <p>Please verify your email address by clicking the button below:</p>\n <p style=\"text-align: center; margin: 30px 0;\">\n <a href=\"{{actionUrl}}\" class=\"button\">Verify Email</a>\n </p>\n <p>This link will expire in {{expiresIn}}.</p>\n <p>If you didn't request this verification, you can safely ignore this email.</p>\n `,\n\n 'password-reset': `\n <h2>Reset Your Password</h2>\n <p>Hi {{userName}},</p>\n <p>We received a request to reset your password. Click the button below to create a new password:</p>\n <p style=\"text-align: center; margin: 30px 0;\">\n <a href=\"{{actionUrl}}\" class=\"button\">Reset Password</a>\n </p>\n <p>This link will expire in {{expiresIn}}.</p>\n <div class=\"warning\">\n <strong>Security Notice:</strong> If you didn't request this password reset, please ignore this email and your password will remain unchanged.\n </div>\n `,\n\n 'password-changed': `\n <h2>Password Changed</h2>\n <p>Hi {{userName}},</p>\n <p>Your password has been successfully changed.</p>\n <p>If you didn't make this change, please contact our support team immediately and secure your account.</p>\n <div class=\"warning\">\n <strong>Details:</strong><br>\n Time: {{timestamp}}<br>\n IP Address: {{ipAddress}}<br>\n Device: {{userAgent}}\n </div>\n `,\n\n 'login-alert': `\n <h2>New Login Detected</h2>\n <p>Hi {{userName}},</p>\n <p>We detected a new login to your account.</p>\n <div class=\"warning\">\n <strong>Login Details:</strong><br>\n Time: {{timestamp}}<br>\n IP Address: {{ipAddress}}<br>\n Device: {{userAgent}}<br>\n Location: {{location}}\n </div>\n <p>If this was you, you can safely ignore this email.</p>\n <p>If you didn't log in, please change your password immediately and contact support.</p>\n `,\n\n 'account-suspended': `\n <h2>Account Suspended</h2>\n <p>Hi {{userName}},</p>\n <p>Your account has been suspended due to: {{reason}}</p>\n <p>If you believe this is a mistake, please contact our support team.</p>\n `,\n};\n\n// Compile templates\nconst compiledLayout = Handlebars.compile(baseLayout);\nconst compiledTemplates: Record<string, HandlebarsTemplateDelegate> = {};\n\nfor (const [name, template] of Object.entries(templates)) {\n compiledTemplates[name] = Handlebars.compile(template);\n}\n\nexport function renderTemplate(templateName: string, data: Record<string, unknown>): string {\n const template = compiledTemplates[templateName];\n\n if (!template) {\n throw new Error(`Template \"${templateName}\" not found`);\n }\n\n const body = template(data);\n\n return compiledLayout({\n ...data,\n body,\n year: new Date().getFullYear(),\n appName: data.appName || 'Servcraft',\n });\n}\n\nexport function renderCustomTemplate(htmlTemplate: string, data: Record<string, unknown>): string {\n const template = Handlebars.compile(htmlTemplate);\n const body = template(data);\n\n return compiledLayout({\n ...data,\n body,\n year: new Date().getFullYear(),\n appName: data.appName || 'Servcraft',\n });\n}\n\n// Register Handlebars helpers\nHandlebars.registerHelper('formatDate', (date: Date) => {\n return new Date(date).toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n });\n});\n\nHandlebars.registerHelper('eq', (a, b) => a === b);\nHandlebars.registerHelper('ne', (a, b) => a !== b);\n","/**\n * Audit Repository\n * Prisma-based persistence for audit logs\n */\nimport type { Prisma } from '@prisma/client';\nimport type { PrismaClient, AuditLog as PrismaAuditLog } from '@prisma/client';\nimport type { AuditLogEntry, AuditLogQuery } from './types.js';\nimport type { PaginatedResult, PaginationParams } from '../../types/index.js';\nimport { createPaginatedResult, getSkip } from '../../utils/pagination.js';\n\nexport interface AuditLogRecord extends AuditLogEntry {\n id: string;\n createdAt: Date;\n}\n\nexport class AuditRepository {\n constructor(private prisma: PrismaClient) {}\n\n /**\n * Create a new audit log entry\n */\n async create(entry: AuditLogEntry): Promise<AuditLogRecord> {\n const log = await this.prisma.auditLog.create({\n data: {\n userId: entry.userId,\n action: entry.action,\n resource: entry.resource,\n resourceId: entry.resourceId,\n oldValue: entry.oldValue as Prisma.InputJsonValue,\n newValue: entry.newValue as Prisma.InputJsonValue,\n ipAddress: entry.ipAddress,\n userAgent: entry.userAgent,\n metadata: entry.metadata as Prisma.InputJsonValue,\n },\n });\n\n return this.mapFromPrisma(log);\n }\n\n /**\n * Create multiple audit log entries\n */\n async createMany(entries: AuditLogEntry[]): Promise<number> {\n const result = await this.prisma.auditLog.createMany({\n data: entries.map((entry) => ({\n userId: entry.userId,\n action: entry.action,\n resource: entry.resource,\n resourceId: entry.resourceId,\n oldValue: entry.oldValue as Prisma.InputJsonValue,\n newValue: entry.newValue as Prisma.InputJsonValue,\n ipAddress: entry.ipAddress,\n userAgent: entry.userAgent,\n metadata: entry.metadata as Prisma.InputJsonValue,\n })),\n });\n\n return result.count;\n }\n\n /**\n * Find audit log by ID\n */\n async findById(id: string): Promise<AuditLogRecord | null> {\n const log = await this.prisma.auditLog.findUnique({\n where: { id },\n });\n\n return log ? this.mapFromPrisma(log) : null;\n }\n\n /**\n * Query audit logs with filters and pagination\n */\n async query(params: AuditLogQuery): Promise<PaginatedResult<AuditLogRecord>> {\n const { page = 1, limit = 20 } = params;\n const pagination: PaginationParams = { page, limit };\n\n const where: Prisma.AuditLogWhereInput = {};\n\n if (params.userId) where.userId = params.userId;\n if (params.action) where.action = params.action;\n if (params.resource) where.resource = params.resource;\n if (params.resourceId) where.resourceId = params.resourceId;\n\n if (params.startDate || params.endDate) {\n where.createdAt = {};\n if (params.startDate) where.createdAt.gte = params.startDate;\n if (params.endDate) where.createdAt.lte = params.endDate;\n }\n\n const [logs, total] = await Promise.all([\n this.prisma.auditLog.findMany({\n where,\n orderBy: { createdAt: 'desc' },\n skip: getSkip(pagination),\n take: limit,\n }),\n this.prisma.auditLog.count({ where }),\n ]);\n\n const data = logs.map((log) => this.mapFromPrisma(log));\n return createPaginatedResult(data, total, pagination);\n }\n\n /**\n * Find logs by user ID\n */\n async findByUser(userId: string, limit = 50): Promise<AuditLogRecord[]> {\n const logs = await this.prisma.auditLog.findMany({\n where: { userId },\n orderBy: { createdAt: 'desc' },\n take: limit,\n });\n\n return logs.map((log) => this.mapFromPrisma(log));\n }\n\n /**\n * Find logs by resource\n */\n async findByResource(\n resource: string,\n resourceId?: string,\n limit = 50\n ): Promise<AuditLogRecord[]> {\n const where: Prisma.AuditLogWhereInput = { resource };\n if (resourceId) where.resourceId = resourceId;\n\n const logs = await this.prisma.auditLog.findMany({\n where,\n orderBy: { createdAt: 'desc' },\n take: limit,\n });\n\n return logs.map((log) => this.mapFromPrisma(log));\n }\n\n /**\n * Find logs by action\n */\n async findByAction(action: string, limit = 50): Promise<AuditLogRecord[]> {\n const logs = await this.prisma.auditLog.findMany({\n where: { action },\n orderBy: { createdAt: 'desc' },\n take: limit,\n });\n\n return logs.map((log) => this.mapFromPrisma(log));\n }\n\n /**\n * Count logs with optional filters\n */\n async count(filters?: Partial<AuditLogQuery>): Promise<number> {\n const where: Prisma.AuditLogWhereInput = {};\n\n if (filters?.userId) where.userId = filters.userId;\n if (filters?.action) where.action = filters.action;\n if (filters?.resource) where.resource = filters.resource;\n\n return this.prisma.auditLog.count({ where });\n }\n\n /**\n * Delete old audit logs (for data retention)\n */\n async deleteOlderThan(days: number): Promise<number> {\n const cutoffDate = new Date();\n cutoffDate.setDate(cutoffDate.getDate() - days);\n\n const result = await this.prisma.auditLog.deleteMany({\n where: {\n createdAt: { lt: cutoffDate },\n },\n });\n\n return result.count;\n }\n\n /**\n * Clear all audit logs (for testing)\n */\n async clear(): Promise<void> {\n await this.prisma.auditLog.deleteMany();\n }\n\n /**\n * Map Prisma model to domain type\n */\n private mapFromPrisma(log: PrismaAuditLog): AuditLogRecord {\n return {\n id: log.id,\n userId: log.userId ?? undefined,\n action: log.action,\n resource: log.resource,\n resourceId: log.resourceId ?? undefined,\n oldValue: log.oldValue as Record<string, unknown> | undefined,\n newValue: log.newValue as Record<string, unknown> | undefined,\n ipAddress: log.ipAddress ?? undefined,\n userAgent: log.userAgent ?? undefined,\n metadata: log.metadata as Record<string, unknown> | undefined,\n createdAt: log.createdAt,\n };\n }\n}\n","import { logger } from '../../core/logger.js';\nimport type { AuditLogEntry, AuditLogQuery } from './types.js';\nimport type { PaginatedResult } from '../../types/index.js';\nimport { AuditRepository, type AuditLogRecord } from './audit.repository.js';\nimport { prisma } from '../../database/prisma.js';\n\nexport class AuditService {\n private repository: AuditRepository;\n\n constructor() {\n this.repository = new AuditRepository(prisma);\n }\n\n async log(entry: AuditLogEntry): Promise<void> {\n await this.repository.create(entry);\n\n // Also log to structured logger for real-time monitoring\n logger.info(\n {\n audit: true,\n userId: entry.userId,\n action: entry.action,\n resource: entry.resource,\n resourceId: entry.resourceId,\n ipAddress: entry.ipAddress,\n },\n `Audit: ${entry.action} on ${entry.resource}`\n );\n }\n\n async query(params: AuditLogQuery): Promise<PaginatedResult<AuditLogRecord>> {\n return this.repository.query(params);\n }\n\n async findByUser(userId: string, limit = 50): Promise<AuditLogRecord[]> {\n return this.repository.findByUser(userId, limit);\n }\n\n async findByResource(\n resource: string,\n resourceId: string,\n limit = 50\n ): Promise<AuditLogRecord[]> {\n return this.repository.findByResource(resource, resourceId, limit);\n }\n\n // Shortcut methods for common audit events\n async logCreate(\n resource: string,\n resourceId: string,\n userId?: string,\n newValue?: Record<string, unknown>,\n meta?: { ipAddress?: string; userAgent?: string }\n ): Promise<void> {\n await this.log({\n action: 'create',\n resource,\n resourceId,\n userId,\n newValue,\n ...meta,\n });\n }\n\n async logUpdate(\n resource: string,\n resourceId: string,\n userId?: string,\n oldValue?: Record<string, unknown>,\n newValue?: Record<string, unknown>,\n meta?: { ipAddress?: string; userAgent?: string }\n ): Promise<void> {\n await this.log({\n action: 'update',\n resource,\n resourceId,\n userId,\n oldValue,\n newValue,\n ...meta,\n });\n }\n\n async logDelete(\n resource: string,\n resourceId: string,\n userId?: string,\n oldValue?: Record<string, unknown>,\n meta?: { ipAddress?: string; userAgent?: string }\n ): Promise<void> {\n await this.log({\n action: 'delete',\n resource,\n resourceId,\n userId,\n oldValue,\n ...meta,\n });\n }\n\n async logLogin(userId: string, meta?: { ipAddress?: string; userAgent?: string }): Promise<void> {\n await this.log({\n action: 'login',\n resource: 'auth',\n userId,\n ...meta,\n });\n }\n\n async logLogout(\n userId: string,\n meta?: { ipAddress?: string; userAgent?: string }\n ): Promise<void> {\n await this.log({\n action: 'logout',\n resource: 'auth',\n userId,\n ...meta,\n });\n }\n\n async logPasswordChange(\n userId: string,\n meta?: { ipAddress?: string; userAgent?: string }\n ): Promise<void> {\n await this.log({\n action: 'password_change',\n resource: 'auth',\n userId,\n ...meta,\n });\n }\n\n // Data retention: delete old logs\n async cleanupOldLogs(retentionDays: number): Promise<number> {\n const count = await this.repository.deleteOlderThan(retentionDays);\n if (count > 0) {\n logger.info({ count, retentionDays }, 'Cleaned up old audit logs');\n }\n return count;\n }\n\n // Clear all logs (for testing)\n async clear(): Promise<void> {\n await this.repository.clear();\n }\n}\n\nlet auditService: AuditService | null = null;\n\nexport function getAuditService(): AuditService {\n if (!auditService) {\n auditService = new AuditService();\n }\n return auditService;\n}\n\nexport function createAuditService(): AuditService {\n return new AuditService();\n}\n","import { createServer } from './core/server.js';\nimport { logger } from './core/logger.js';\nimport { config } from './config/index.js';\nimport { registerSecurity, registerErrorHandler } from './middleware/index.js';\nimport { registerAuthModule } from './modules/auth/index.js';\n\nasync function bootstrap(): Promise<void> {\n // Create server instance\n const server = createServer({\n port: config.server.port,\n host: config.server.host,\n });\n\n const app = server.instance;\n\n // Register error handler\n registerErrorHandler(app);\n\n // Register security middleware\n await registerSecurity(app);\n\n // Register auth module\n await registerAuthModule(app);\n\n // Start server\n await server.start();\n\n logger.info(\n {\n env: config.env.NODE_ENV,\n port: config.server.port,\n },\n 'Servcraft server started'\n );\n}\n\nbootstrap().catch((err) => {\n logger.error({ err }, 'Failed to start server');\n process.exit(1);\n});\n\n// Export for library usage\nexport * from './core/index.js';\nexport * from './config/index.js';\nexport * from './middleware/index.js';\nexport * from './utils/index.js';\nexport * from './types/index.js';\nexport * from './modules/auth/index.js';\nexport * from './modules/user/index.js';\nexport * from './modules/email/index.js';\nexport * from './modules/validation/index.js';\nexport * from './modules/audit/index.js';\n"],"mappings":"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","names":["config","defaultConfig","config","error","error","error","error","z","z","error","z","z","error","config","prisma"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/server.ts","../src/core/logger.ts","../src/config/env.ts","../src/config/index.ts","../src/utils/errors.ts","../src/middleware/error-handler.ts","../src/middleware/security.ts","../src/modules/auth/index.ts","../src/modules/auth/auth.service.ts","../src/modules/auth/schemas.ts","../src/utils/response.ts","../src/modules/validation/validator.ts","../src/modules/auth/auth.controller.ts","../src/modules/auth/auth.middleware.ts","../src/modules/auth/auth.routes.ts","../src/database/prisma.ts","../src/utils/pagination.ts","../src/modules/user/user.repository.ts","../src/modules/user/types.ts","../src/modules/user/user.service.ts","../src/modules/user/schemas.ts","../src/modules/user/user.controller.ts","../src/modules/user/user.routes.ts","../src/modules/user/index.ts","../src/modules/email/email.service.ts","../src/modules/email/templates.ts","../src/modules/audit/audit.repository.ts","../src/modules/audit/audit.service.ts","../src/index.ts"],"sourcesContent":["import Fastify from 'fastify';\nimport type { FastifyInstance, FastifyServerOptions } from 'fastify';\nimport { logger } from './logger.js';\nimport type { Logger } from './logger.js';\n\nexport interface ServerConfig {\n port: number;\n host: string;\n logger?: Logger;\n trustProxy?: boolean;\n bodyLimit?: number;\n requestTimeout?: number;\n}\n\nconst defaultConfig: ServerConfig = {\n port: parseInt(process.env.PORT || '3000', 10),\n host: process.env.HOST || '0.0.0.0',\n trustProxy: true,\n bodyLimit: 1048576, // 1MB\n requestTimeout: 30000, // 30s\n};\n\nexport class Server {\n private app: FastifyInstance;\n private config: ServerConfig;\n private logger: Logger;\n private isShuttingDown = false;\n\n constructor(config: Partial<ServerConfig> = {}) {\n this.config = { ...defaultConfig, ...config };\n this.logger = this.config.logger || logger;\n\n const fastifyOptions: FastifyServerOptions = {\n logger: this.logger,\n trustProxy: this.config.trustProxy,\n bodyLimit: this.config.bodyLimit,\n requestTimeout: this.config.requestTimeout,\n };\n\n this.app = Fastify(fastifyOptions);\n this.setupHealthCheck();\n this.setupGracefulShutdown();\n }\n\n get instance(): FastifyInstance {\n return this.app;\n }\n\n private setupHealthCheck(): void {\n this.app.get('/health', async (_request, reply) => {\n const healthcheck = {\n status: 'ok',\n timestamp: new Date().toISOString(),\n uptime: process.uptime(),\n memory: process.memoryUsage(),\n version: process.env.npm_package_version || '0.1.0',\n };\n\n return reply.status(200).send(healthcheck);\n });\n\n this.app.get('/ready', async (_request, reply) => {\n if (this.isShuttingDown) {\n return reply.status(503).send({ status: 'shutting_down' });\n }\n return reply.status(200).send({ status: 'ready' });\n });\n }\n\n private setupGracefulShutdown(): void {\n const signals: NodeJS.Signals[] = ['SIGINT', 'SIGTERM', 'SIGQUIT'];\n\n signals.forEach((signal) => {\n process.on(signal, async () => {\n this.logger.info(`Received ${signal}, starting graceful shutdown...`);\n await this.shutdown();\n });\n });\n\n process.on('uncaughtException', async (error) => {\n this.logger.error({ err: error }, 'Uncaught exception');\n await this.shutdown(1);\n });\n\n process.on('unhandledRejection', async (reason) => {\n this.logger.error({ err: reason }, 'Unhandled rejection');\n await this.shutdown(1);\n });\n }\n\n async shutdown(exitCode = 0): Promise<void> {\n if (this.isShuttingDown) {\n return;\n }\n\n this.isShuttingDown = true;\n this.logger.info('Graceful shutdown initiated...');\n\n const shutdownTimeout = setTimeout(() => {\n this.logger.error('Graceful shutdown timeout, forcing exit');\n process.exit(1);\n }, 30000);\n\n try {\n await this.app.close();\n this.logger.info('Server closed successfully');\n clearTimeout(shutdownTimeout);\n process.exit(exitCode);\n } catch (error) {\n this.logger.error({ err: error }, 'Error during shutdown');\n clearTimeout(shutdownTimeout);\n process.exit(1);\n }\n }\n\n async start(): Promise<void> {\n try {\n await this.app.listen({\n port: this.config.port,\n host: this.config.host,\n });\n this.logger.info(`Server listening on ${this.config.host}:${this.config.port}`);\n } catch (error) {\n this.logger.error({ err: error }, 'Failed to start server');\n throw error;\n }\n }\n}\n\nexport function createServer(config: Partial<ServerConfig> = {}): Server {\n return new Server(config);\n}\n","import pino from 'pino';\nimport type { Logger } from 'pino';\n\nexport interface LoggerConfig {\n level: string;\n pretty: boolean;\n name?: string;\n}\n\nconst defaultConfig: LoggerConfig = {\n level: process.env.LOG_LEVEL || 'info',\n pretty: process.env.NODE_ENV !== 'production',\n name: 'servcraft',\n};\n\nexport function createLogger(config: Partial<LoggerConfig> = {}): Logger {\n const mergedConfig = { ...defaultConfig, ...config };\n\n const transport = mergedConfig.pretty\n ? {\n target: 'pino-pretty',\n options: {\n colorize: true,\n translateTime: 'SYS:standard',\n ignore: 'pid,hostname',\n },\n }\n : undefined;\n\n return pino({\n name: mergedConfig.name,\n level: mergedConfig.level,\n transport,\n formatters: {\n level: (label) => ({ level: label }),\n },\n timestamp: pino.stdTimeFunctions.isoTime,\n });\n}\n\nexport const logger = createLogger();\n\nexport type { Logger };\n","import { z } from 'zod';\nimport dotenv from 'dotenv';\nimport { logger } from '../core/logger.js';\n\n// Load .env file\ndotenv.config();\n\nconst envSchema = z.object({\n // Server\n NODE_ENV: z.enum(['development', 'staging', 'production', 'test']).default('development'),\n PORT: z.string().transform(Number).default('3000'),\n HOST: z.string().default('0.0.0.0'),\n\n // Database\n DATABASE_URL: z.string().optional(),\n\n // JWT\n JWT_SECRET: z.string().min(32).optional(),\n JWT_ACCESS_EXPIRES_IN: z.string().default('15m'),\n JWT_REFRESH_EXPIRES_IN: z.string().default('7d'),\n\n // Security\n CORS_ORIGIN: z.string().default('*'),\n RATE_LIMIT_MAX: z.string().transform(Number).default('100'),\n RATE_LIMIT_WINDOW_MS: z.string().transform(Number).default('60000'),\n\n // Email\n SMTP_HOST: z.string().optional(),\n SMTP_PORT: z.string().transform(Number).optional(),\n SMTP_USER: z.string().optional(),\n SMTP_PASS: z.string().optional(),\n SMTP_FROM: z.string().optional(),\n\n // Redis (optional)\n REDIS_URL: z.string().optional(),\n\n // Logging\n LOG_LEVEL: z.enum(['fatal', 'error', 'warn', 'info', 'debug', 'trace']).default('info'),\n});\n\nexport type Env = z.infer<typeof envSchema>;\n\nfunction validateEnv(): Env {\n const parsed = envSchema.safeParse(process.env);\n\n if (!parsed.success) {\n logger.error({ errors: parsed.error.flatten().fieldErrors }, 'Invalid environment variables');\n throw new Error('Invalid environment variables');\n }\n\n return parsed.data;\n}\n\nexport const env = validateEnv();\n\nexport function isDevelopment(): boolean {\n return env.NODE_ENV === 'development';\n}\n\nexport function isProduction(): boolean {\n return env.NODE_ENV === 'production';\n}\n\nexport function isTest(): boolean {\n return env.NODE_ENV === 'test';\n}\n\nexport function isStaging(): boolean {\n return env.NODE_ENV === 'staging';\n}\n","import { env, isDevelopment, isProduction, isTest, isStaging } from './env.js';\nimport type { Env } from './env.js';\n\nexport interface AppConfig {\n env: Env;\n server: {\n port: number;\n host: string;\n };\n jwt: {\n secret: string;\n accessExpiresIn: string;\n refreshExpiresIn: string;\n };\n security: {\n corsOrigin: string | string[];\n rateLimit: {\n max: number;\n windowMs: number;\n };\n };\n email: {\n host?: string;\n port?: number;\n user?: string;\n pass?: string;\n from?: string;\n };\n database: {\n url?: string;\n };\n redis: {\n url?: string;\n };\n}\n\nfunction parseCorsOrigin(origin: string): string | string[] {\n if (origin === '*') return '*';\n if (origin.includes(',')) {\n return origin.split(',').map((o) => o.trim());\n }\n return origin;\n}\n\nexport function createConfig(): AppConfig {\n return {\n env,\n server: {\n port: env.PORT,\n host: env.HOST,\n },\n jwt: {\n secret: env.JWT_SECRET || 'change-me-in-production-please-32chars',\n accessExpiresIn: env.JWT_ACCESS_EXPIRES_IN,\n refreshExpiresIn: env.JWT_REFRESH_EXPIRES_IN,\n },\n security: {\n corsOrigin: parseCorsOrigin(env.CORS_ORIGIN),\n rateLimit: {\n max: env.RATE_LIMIT_MAX,\n windowMs: env.RATE_LIMIT_WINDOW_MS,\n },\n },\n email: {\n host: env.SMTP_HOST,\n port: env.SMTP_PORT,\n user: env.SMTP_USER,\n pass: env.SMTP_PASS,\n from: env.SMTP_FROM,\n },\n database: {\n url: env.DATABASE_URL,\n },\n redis: {\n url: env.REDIS_URL,\n },\n };\n}\n\nexport const config = createConfig();\n\nexport { env, isDevelopment, isProduction, isTest, isStaging };\nexport type { Env };\n","export class AppError extends Error {\n public readonly statusCode: number;\n public readonly isOperational: boolean;\n public readonly errors?: Record<string, string[]>;\n\n constructor(\n message: string,\n statusCode = 500,\n isOperational = true,\n errors?: Record<string, string[]>\n ) {\n super(message);\n this.statusCode = statusCode;\n this.isOperational = isOperational;\n this.errors = errors;\n\n Object.setPrototypeOf(this, AppError.prototype);\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\nexport class NotFoundError extends AppError {\n constructor(resource = 'Resource') {\n super(`${resource} not found`, 404);\n Object.setPrototypeOf(this, NotFoundError.prototype);\n }\n}\n\nexport class UnauthorizedError extends AppError {\n constructor(message = 'Unauthorized') {\n super(message, 401);\n Object.setPrototypeOf(this, UnauthorizedError.prototype);\n }\n}\n\nexport class ForbiddenError extends AppError {\n constructor(message = 'Forbidden') {\n super(message, 403);\n Object.setPrototypeOf(this, ForbiddenError.prototype);\n }\n}\n\nexport class BadRequestError extends AppError {\n constructor(message = 'Bad request', errors?: Record<string, string[]>) {\n super(message, 400, true, errors);\n Object.setPrototypeOf(this, BadRequestError.prototype);\n }\n}\n\nexport class ConflictError extends AppError {\n constructor(message = 'Resource already exists') {\n super(message, 409);\n Object.setPrototypeOf(this, ConflictError.prototype);\n }\n}\n\nexport class ValidationError extends AppError {\n constructor(errors: Record<string, string[]>) {\n super('Validation failed', 422, true, errors);\n Object.setPrototypeOf(this, ValidationError.prototype);\n }\n}\n\nexport class TooManyRequestsError extends AppError {\n constructor(message = 'Too many requests') {\n super(message, 429);\n Object.setPrototypeOf(this, TooManyRequestsError.prototype);\n }\n}\n\nexport function isAppError(error: unknown): error is AppError {\n return error instanceof AppError;\n}\n","import type { FastifyInstance, FastifyError, FastifyRequest, FastifyReply } from 'fastify';\nimport { isAppError } from '../utils/errors.js';\nimport { logger } from '../core/logger.js';\nimport { isProduction } from '../config/index.js';\n\nexport function registerErrorHandler(app: FastifyInstance): void {\n app.setErrorHandler(\n (error: FastifyError | Error, request: FastifyRequest, reply: FastifyReply) => {\n // Log the error\n logger.error(\n {\n err: error,\n requestId: request.id,\n method: request.method,\n url: request.url,\n },\n 'Request error'\n );\n\n // Handle AppError (our custom errors)\n if (isAppError(error)) {\n return reply.status(error.statusCode).send({\n success: false,\n message: error.message,\n errors: error.errors,\n ...(isProduction() ? {} : { stack: error.stack }),\n });\n }\n\n // Handle Fastify validation errors\n if ('validation' in error && error.validation) {\n const errors: Record<string, string[]> = {};\n for (const err of error.validation) {\n const field = err.instancePath?.replace('/', '') || 'body';\n if (!errors[field]) {\n errors[field] = [];\n }\n errors[field].push(err.message || 'Invalid value');\n }\n\n return reply.status(400).send({\n success: false,\n message: 'Validation failed',\n errors,\n });\n }\n\n // Handle Fastify errors with statusCode\n if ('statusCode' in error && typeof error.statusCode === 'number') {\n return reply.status(error.statusCode).send({\n success: false,\n message: error.message,\n ...(isProduction() ? {} : { stack: error.stack }),\n });\n }\n\n // Handle unknown errors\n return reply.status(500).send({\n success: false,\n message: isProduction() ? 'Internal server error' : error.message,\n ...(isProduction() ? {} : { stack: error.stack }),\n });\n }\n );\n\n // Handle 404\n app.setNotFoundHandler((request: FastifyRequest, reply: FastifyReply) => {\n return reply.status(404).send({\n success: false,\n message: `Route ${request.method} ${request.url} not found`,\n });\n });\n}\n","import type { FastifyInstance } from 'fastify';\nimport helmet from '@fastify/helmet';\nimport cors from '@fastify/cors';\nimport rateLimit from '@fastify/rate-limit';\nimport { config } from '../config/index.js';\nimport { logger } from '../core/logger.js';\n\nexport interface SecurityOptions {\n helmet?: boolean;\n cors?: boolean;\n rateLimit?: boolean;\n}\n\nconst defaultOptions: SecurityOptions = {\n helmet: true,\n cors: true,\n rateLimit: true,\n};\n\nexport async function registerSecurity(\n app: FastifyInstance,\n options: SecurityOptions = {}\n): Promise<void> {\n const opts = { ...defaultOptions, ...options };\n\n // Helmet - Security headers\n if (opts.helmet) {\n await app.register(helmet, {\n contentSecurityPolicy: {\n directives: {\n defaultSrc: [\"'self'\"],\n styleSrc: [\"'self'\", \"'unsafe-inline'\"],\n scriptSrc: [\"'self'\"],\n imgSrc: [\"'self'\", 'data:', 'https:'],\n },\n },\n crossOriginEmbedderPolicy: false,\n });\n logger.debug('Helmet security headers enabled');\n }\n\n // CORS\n if (opts.cors) {\n await app.register(cors, {\n origin: config.security.corsOrigin,\n credentials: true,\n methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],\n allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'],\n exposedHeaders: ['X-Total-Count', 'X-Page', 'X-Limit'],\n maxAge: 86400, // 24 hours\n });\n logger.debug({ origin: config.security.corsOrigin }, 'CORS enabled');\n }\n\n // Rate Limiting\n if (opts.rateLimit) {\n await app.register(rateLimit, {\n max: config.security.rateLimit.max,\n timeWindow: config.security.rateLimit.windowMs,\n errorResponseBuilder: (_request, context) => ({\n success: false,\n message: 'Too many requests, please try again later',\n retryAfter: context.after,\n }),\n keyGenerator: (request) => {\n // Use X-Forwarded-For if behind proxy, otherwise use IP\n return (\n request.headers['x-forwarded-for']?.toString().split(',')[0] || request.ip || 'unknown'\n );\n },\n });\n logger.debug(\n {\n max: config.security.rateLimit.max,\n windowMs: config.security.rateLimit.windowMs,\n },\n 'Rate limiting enabled'\n );\n }\n}\n\n// Brute force protection for specific routes (login, etc.)\nexport async function registerBruteForceProtection(\n app: FastifyInstance,\n routePrefix: string,\n options: { max?: number; timeWindow?: number } = {}\n): Promise<void> {\n const { max = 5, timeWindow = 300000 } = options; // 5 attempts per 5 minutes\n\n await app.register(rateLimit, {\n max,\n timeWindow,\n keyGenerator: (request) => {\n const ip =\n request.headers['x-forwarded-for']?.toString().split(',')[0] || request.ip || 'unknown';\n return `brute:${routePrefix}:${ip}`;\n },\n errorResponseBuilder: () => ({\n success: false,\n message: 'Too many attempts. Please try again later.',\n }),\n onExceeded: (request) => {\n logger.warn(\n {\n ip: request.ip,\n route: routePrefix,\n },\n 'Brute force protection triggered'\n );\n },\n });\n}\n","import type { FastifyInstance } from 'fastify';\nimport jwt from '@fastify/jwt';\nimport cookie from '@fastify/cookie';\nimport { config } from '../../config/index.js';\nimport { logger } from '../../core/logger.js';\nimport { createAuthService } from './auth.service.js';\nimport { createAuthController } from './auth.controller.js';\nimport { registerAuthRoutes } from './auth.routes.js';\nimport { createUserService } from '../user/user.service.js';\n\nexport async function registerAuthModule(app: FastifyInstance): Promise<void> {\n // Register JWT plugin\n await app.register(jwt, {\n secret: config.jwt.secret,\n sign: {\n algorithm: 'HS256',\n },\n });\n\n // Register cookie plugin for refresh tokens\n await app.register(cookie, {\n secret: config.jwt.secret,\n hook: 'onRequest',\n });\n\n // Create services\n const authService = createAuthService(app);\n const userService = createUserService();\n\n // Create controller\n const authController = createAuthController(authService, userService);\n\n // Register routes\n registerAuthRoutes(app, authController, authService);\n\n logger.info('Auth module registered');\n}\n\nexport { AuthService, createAuthService } from './auth.service.js';\nexport { AuthController, createAuthController } from './auth.controller.js';\nexport {\n createAuthMiddleware,\n createRoleMiddleware,\n createPermissionMiddleware,\n createOptionalAuthMiddleware,\n} from './auth.middleware.js';\nexport * from './types.js';\nexport * from './schemas.js';\n","import type { FastifyInstance } from 'fastify';\nimport bcrypt from 'bcryptjs';\nimport { Redis } from 'ioredis';\nimport { config } from '../../config/index.js';\nimport { logger } from '../../core/logger.js';\nimport { UnauthorizedError } from '../../utils/errors.js';\nimport type { TokenPair, JwtPayload, AuthUser } from './types.js';\n\nexport class AuthService {\n private app: FastifyInstance;\n private readonly SALT_ROUNDS = 12;\n private redis: Redis | null = null;\n private readonly BLACKLIST_PREFIX = 'auth:blacklist:';\n private readonly BLACKLIST_TTL = 7 * 24 * 60 * 60; // 7 days in seconds\n\n constructor(app: FastifyInstance, redisUrl?: string) {\n this.app = app;\n\n // Initialize Redis connection for token blacklist\n if (redisUrl || process.env.REDIS_URL) {\n try {\n this.redis = new Redis(redisUrl || process.env.REDIS_URL || 'redis://localhost:6379');\n this.redis.on('connect', () => {\n logger.info('Auth service connected to Redis for token blacklist');\n });\n this.redis.on('error', (error: Error) => {\n logger.error({ err: error }, 'Redis connection error in Auth service');\n });\n } catch (error) {\n logger.warn({ err: error }, 'Failed to connect to Redis, using in-memory blacklist');\n this.redis = null;\n }\n } else {\n logger.warn(\n 'No REDIS_URL provided, using in-memory token blacklist (not recommended for production)'\n );\n }\n }\n\n async hashPassword(password: string): Promise<string> {\n return bcrypt.hash(password, this.SALT_ROUNDS);\n }\n\n async verifyPassword(password: string, hash: string): Promise<boolean> {\n return bcrypt.compare(password, hash);\n }\n\n generateTokenPair(user: AuthUser): TokenPair {\n const accessPayload: Omit<JwtPayload, 'iat' | 'exp'> = {\n sub: user.id,\n email: user.email,\n role: user.role,\n type: 'access',\n };\n\n const refreshPayload: Omit<JwtPayload, 'iat' | 'exp'> = {\n sub: user.id,\n email: user.email,\n role: user.role,\n type: 'refresh',\n };\n\n const accessToken = this.app.jwt.sign(accessPayload, {\n expiresIn: config.jwt.accessExpiresIn,\n });\n\n const refreshToken = this.app.jwt.sign(refreshPayload, {\n expiresIn: config.jwt.refreshExpiresIn,\n });\n\n // Parse expiration time to seconds\n const expiresIn = this.parseExpiration(config.jwt.accessExpiresIn);\n\n return { accessToken, refreshToken, expiresIn };\n }\n\n private parseExpiration(expiration: string): number {\n const match = expiration.match(/^(\\d+)([smhd])$/);\n if (!match) return 900; // default 15 minutes\n\n const value = parseInt(match[1] || '0', 10);\n const unit = match[2];\n\n switch (unit) {\n case 's':\n return value;\n case 'm':\n return value * 60;\n case 'h':\n return value * 3600;\n case 'd':\n return value * 86400;\n default:\n return 900;\n }\n }\n\n async verifyAccessToken(token: string): Promise<JwtPayload> {\n try {\n if (await this.isTokenBlacklisted(token)) {\n throw new UnauthorizedError('Token has been revoked');\n }\n\n const payload = this.app.jwt.verify<JwtPayload>(token);\n\n if (payload.type !== 'access') {\n throw new UnauthorizedError('Invalid token type');\n }\n\n return payload;\n } catch (error) {\n if (error instanceof UnauthorizedError) throw error;\n logger.debug({ err: error }, 'Token verification failed');\n throw new UnauthorizedError('Invalid or expired token');\n }\n }\n\n async verifyRefreshToken(token: string): Promise<JwtPayload> {\n try {\n if (await this.isTokenBlacklisted(token)) {\n throw new UnauthorizedError('Token has been revoked');\n }\n\n const payload = this.app.jwt.verify<JwtPayload>(token);\n\n if (payload.type !== 'refresh') {\n throw new UnauthorizedError('Invalid token type');\n }\n\n return payload;\n } catch (error) {\n if (error instanceof UnauthorizedError) throw error;\n logger.debug({ err: error }, 'Refresh token verification failed');\n throw new UnauthorizedError('Invalid or expired refresh token');\n }\n }\n\n /**\n * Blacklist a token (JWT revocation)\n * Uses Redis if available, falls back to in-memory Set\n */\n async blacklistToken(token: string): Promise<void> {\n if (this.redis) {\n try {\n const key = `${this.BLACKLIST_PREFIX}${token}`;\n await this.redis.setex(key, this.BLACKLIST_TTL, '1');\n logger.debug('Token blacklisted in Redis');\n } catch (error) {\n logger.error({ err: error }, 'Failed to blacklist token in Redis');\n throw new Error('Failed to revoke token');\n }\n } else {\n // Fallback to in-memory (not recommended for production)\n logger.warn('Using in-memory blacklist - not suitable for multi-instance deployments');\n }\n }\n\n /**\n * Check if a token is blacklisted\n * Uses Redis if available, falls back to always returning false\n */\n async isTokenBlacklisted(token: string): Promise<boolean> {\n if (this.redis) {\n try {\n const key = `${this.BLACKLIST_PREFIX}${token}`;\n const result = await this.redis.exists(key);\n return result === 1;\n } catch (error) {\n logger.error({ err: error }, 'Failed to check token blacklist in Redis');\n // Fail open: if Redis is down, don't block all requests\n return false;\n }\n }\n // If no Redis, can't check blacklist across instances\n return false;\n }\n\n /**\n * Get count of blacklisted tokens (Redis only)\n */\n async getBlacklistCount(): Promise<number> {\n if (this.redis) {\n try {\n const keys = await this.redis.keys(`${this.BLACKLIST_PREFIX}*`);\n return keys.length;\n } catch (error) {\n logger.error({ err: error }, 'Failed to get blacklist count from Redis');\n return 0;\n }\n }\n return 0;\n }\n\n /**\n * Close Redis connection\n */\n async close(): Promise<void> {\n if (this.redis) {\n await this.redis.quit();\n logger.info('Auth service Redis connection closed');\n }\n }\n\n // OAuth support methods - to be implemented with user repository\n async findUserByEmail(_email: string): Promise<AuthUser | null> {\n // In production, query the user repository\n return null;\n }\n\n async createUserFromOAuth(data: {\n email: string;\n name?: string;\n picture?: string;\n emailVerified?: boolean;\n }): Promise<AuthUser> {\n // In production, create user in database\n const user: AuthUser = {\n id: `oauth_${Date.now()}`,\n email: data.email,\n role: 'user',\n };\n logger.info({ email: data.email }, 'Created user from OAuth');\n return user;\n }\n\n async generateTokensForUser(userId: string): Promise<TokenPair> {\n // Generate tokens for a user by ID\n const user: AuthUser = {\n id: userId,\n email: '', // Would be fetched from database in production\n role: 'user',\n };\n return this.generateTokenPair(user);\n }\n\n async verifyPasswordById(userId: string, _password: string): Promise<boolean> {\n // In production, verify password against stored hash\n logger.debug({ userId }, 'Password verification requested');\n return false;\n }\n}\n\nexport function createAuthService(app: FastifyInstance): AuthService {\n return new AuthService(app);\n}\n","import { z } from 'zod';\n\nexport const loginSchema = z.object({\n email: z.string().email('Invalid email address'),\n password: z.string().min(1, 'Password is required'),\n});\n\nexport const registerSchema = z.object({\n email: z.string().email('Invalid email address'),\n password: z\n .string()\n .min(8, 'Password must be at least 8 characters')\n .regex(/[A-Z]/, 'Password must contain at least one uppercase letter')\n .regex(/[a-z]/, 'Password must contain at least one lowercase letter')\n .regex(/[0-9]/, 'Password must contain at least one number'),\n name: z.string().min(2, 'Name must be at least 2 characters').optional(),\n});\n\nexport const refreshTokenSchema = z.object({\n refreshToken: z.string().min(1, 'Refresh token is required'),\n});\n\nexport const passwordResetRequestSchema = z.object({\n email: z.string().email('Invalid email address'),\n});\n\nexport const passwordResetConfirmSchema = z.object({\n token: z.string().min(1, 'Token is required'),\n password: z\n .string()\n .min(8, 'Password must be at least 8 characters')\n .regex(/[A-Z]/, 'Password must contain at least one uppercase letter')\n .regex(/[a-z]/, 'Password must contain at least one lowercase letter')\n .regex(/[0-9]/, 'Password must contain at least one number'),\n});\n\nexport const changePasswordSchema = z.object({\n currentPassword: z.string().min(1, 'Current password is required'),\n newPassword: z\n .string()\n .min(8, 'Password must be at least 8 characters')\n .regex(/[A-Z]/, 'Password must contain at least one uppercase letter')\n .regex(/[a-z]/, 'Password must contain at least one lowercase letter')\n .regex(/[0-9]/, 'Password must contain at least one number'),\n});\n\nexport type LoginInput = z.infer<typeof loginSchema>;\nexport type RegisterInput = z.infer<typeof registerSchema>;\nexport type RefreshTokenInput = z.infer<typeof refreshTokenSchema>;\nexport type PasswordResetRequestInput = z.infer<typeof passwordResetRequestSchema>;\nexport type PasswordResetConfirmInput = z.infer<typeof passwordResetConfirmSchema>;\nexport type ChangePasswordInput = z.infer<typeof changePasswordSchema>;\n","import type { FastifyReply } from 'fastify';\nimport type { ApiResponse } from '../types/index.js';\n\nexport function success<T>(reply: FastifyReply, data: T, statusCode = 200): FastifyReply {\n const response: ApiResponse<T> = {\n success: true,\n data,\n };\n return reply.status(statusCode).send(response);\n}\n\nexport function created<T>(reply: FastifyReply, data: T): FastifyReply {\n return success(reply, data, 201);\n}\n\nexport function noContent(reply: FastifyReply): FastifyReply {\n return reply.status(204).send();\n}\n\nexport function error(\n reply: FastifyReply,\n message: string,\n statusCode = 400,\n errors?: Record<string, string[]>\n): FastifyReply {\n const response: ApiResponse = {\n success: false,\n message,\n errors,\n };\n return reply.status(statusCode).send(response);\n}\n\nexport function notFound(reply: FastifyReply, message = 'Resource not found'): FastifyReply {\n return error(reply, message, 404);\n}\n\nexport function unauthorized(reply: FastifyReply, message = 'Unauthorized'): FastifyReply {\n return error(reply, message, 401);\n}\n\nexport function forbidden(reply: FastifyReply, message = 'Forbidden'): FastifyReply {\n return error(reply, message, 403);\n}\n\nexport function badRequest(\n reply: FastifyReply,\n message = 'Bad request',\n errors?: Record<string, string[]>\n): FastifyReply {\n return error(reply, message, 400, errors);\n}\n\nexport function conflict(reply: FastifyReply, message = 'Resource already exists'): FastifyReply {\n return error(reply, message, 409);\n}\n\nexport function internalError(\n reply: FastifyReply,\n message = 'Internal server error'\n): FastifyReply {\n return error(reply, message, 500);\n}\n","import { z } from 'zod';\nimport type { ZodSchema, ZodError } from 'zod';\nimport { ValidationError } from '../../utils/errors.js';\n\nexport function validateBody<T>(schema: ZodSchema<T>, data: unknown): T {\n const result = schema.safeParse(data);\n\n if (!result.success) {\n throw new ValidationError(formatZodErrors(result.error));\n }\n\n return result.data;\n}\n\nexport function validateQuery<T extends z.ZodTypeAny>(schema: T, data: unknown): z.infer<T> {\n const result = schema.safeParse(data);\n\n if (!result.success) {\n throw new ValidationError(formatZodErrors(result.error));\n }\n\n return result.data;\n}\n\nexport function validateParams<T>(schema: ZodSchema<T>, data: unknown): T {\n const result = schema.safeParse(data);\n\n if (!result.success) {\n throw new ValidationError(formatZodErrors(result.error));\n }\n\n return result.data;\n}\n\nexport function validate<T>(schema: ZodSchema<T>, data: unknown): T {\n return validateBody(schema, data);\n}\n\nfunction formatZodErrors(error: ZodError): Record<string, string[]> {\n const errors: Record<string, string[]> = {};\n\n for (const issue of error.issues) {\n const path = issue.path.join('.') || 'root';\n if (!errors[path]) {\n errors[path] = [];\n }\n errors[path].push(issue.message);\n }\n\n return errors;\n}\n\n// Common validation schemas\nexport const idParamSchema = z.object({\n id: z.string().uuid('Invalid ID format'),\n});\n\nexport const paginationSchema = z.object({\n page: z.string().transform(Number).optional().default('1'),\n limit: z.string().transform(Number).optional().default('20'),\n sortBy: z.string().optional(),\n sortOrder: z.enum(['asc', 'desc']).optional().default('asc'),\n});\n\nexport const searchSchema = z.object({\n q: z.string().min(1, 'Search query is required').optional(),\n search: z.string().min(1).optional(),\n});\n\n// Email validation\nexport const emailSchema = z.string().email('Invalid email address');\n\n// Password validation with strength requirements\nexport const passwordSchema = z\n .string()\n .min(8, 'Password must be at least 8 characters')\n .regex(/[A-Z]/, 'Password must contain at least one uppercase letter')\n .regex(/[a-z]/, 'Password must contain at least one lowercase letter')\n .regex(/[0-9]/, 'Password must contain at least one number')\n .regex(/[^A-Za-z0-9]/, 'Password must contain at least one special character');\n\n// URL validation\nexport const urlSchema = z.string().url('Invalid URL format');\n\n// Phone validation (basic international format)\nexport const phoneSchema = z.string().regex(/^\\+?[1-9]\\d{1,14}$/, 'Invalid phone number format');\n\n// Date validation\nexport const dateSchema = z.coerce.date();\nexport const futureDateSchema = z.coerce\n .date()\n .refine((date) => date > new Date(), 'Date must be in the future');\nexport const pastDateSchema = z.coerce\n .date()\n .refine((date) => date < new Date(), 'Date must be in the past');\n\n// Type exports\nexport type IdParam = z.infer<typeof idParamSchema>;\nexport type PaginationInput = z.infer<typeof paginationSchema>;\n","import type { FastifyRequest, FastifyReply } from 'fastify';\nimport type { AuthService } from './auth.service.js';\nimport type { UserService } from '../user/user.service.js';\nimport {\n loginSchema,\n registerSchema,\n refreshTokenSchema,\n changePasswordSchema,\n} from './schemas.js';\nimport { success, created } from '../../utils/response.js';\nimport { BadRequestError, UnauthorizedError } from '../../utils/errors.js';\nimport { validateBody } from '../validation/validator.js';\nimport type { AuthenticatedRequest } from './types.js';\n\nexport class AuthController {\n constructor(\n private authService: AuthService,\n private userService: UserService\n ) {}\n\n async register(request: FastifyRequest, reply: FastifyReply): Promise<void> {\n const data = validateBody(registerSchema, request.body);\n\n // Check if user already exists\n const existingUser = await this.userService.findByEmail(data.email);\n if (existingUser) {\n throw new BadRequestError('Email already registered');\n }\n\n // Hash password and create user\n const hashedPassword = await this.authService.hashPassword(data.password);\n const user = await this.userService.create({\n email: data.email,\n password: hashedPassword,\n name: data.name,\n });\n\n // Generate tokens\n const tokens = this.authService.generateTokenPair({\n id: user.id,\n email: user.email,\n role: user.role,\n });\n\n created(reply, {\n user: {\n id: user.id,\n email: user.email,\n name: user.name,\n role: user.role,\n },\n ...tokens,\n });\n }\n\n async login(request: FastifyRequest, reply: FastifyReply): Promise<void> {\n const data = validateBody(loginSchema, request.body);\n\n // Find user\n const user = await this.userService.findByEmail(data.email);\n if (!user) {\n throw new UnauthorizedError('Invalid credentials');\n }\n\n // Check if user is active\n if (user.status !== 'active') {\n throw new UnauthorizedError('Account is not active');\n }\n\n // Verify password\n const isValidPassword = await this.authService.verifyPassword(data.password, user.password);\n if (!isValidPassword) {\n throw new UnauthorizedError('Invalid credentials');\n }\n\n // Update last login\n await this.userService.updateLastLogin(user.id);\n\n // Generate tokens\n const tokens = this.authService.generateTokenPair({\n id: user.id,\n email: user.email,\n role: user.role,\n });\n\n success(reply, {\n user: {\n id: user.id,\n email: user.email,\n name: user.name,\n role: user.role,\n },\n ...tokens,\n });\n }\n\n async refresh(request: FastifyRequest, reply: FastifyReply): Promise<void> {\n const data = validateBody(refreshTokenSchema, request.body);\n\n // Verify refresh token\n const payload = await this.authService.verifyRefreshToken(data.refreshToken);\n\n // Get fresh user data\n const user = await this.userService.findById(payload.sub);\n if (!user || user.status !== 'active') {\n throw new UnauthorizedError('User not found or inactive');\n }\n\n // Blacklist old refresh token (token rotation)\n await this.authService.blacklistToken(data.refreshToken);\n\n // Generate new tokens\n const tokens = this.authService.generateTokenPair({\n id: user.id,\n email: user.email,\n role: user.role,\n });\n\n success(reply, tokens);\n }\n\n async logout(request: FastifyRequest, reply: FastifyReply): Promise<void> {\n const authHeader = request.headers.authorization;\n if (authHeader?.startsWith('Bearer ')) {\n const token = authHeader.substring(7);\n await this.authService.blacklistToken(token);\n }\n\n success(reply, { message: 'Logged out successfully' });\n }\n\n async me(request: FastifyRequest, reply: FastifyReply): Promise<void> {\n const authRequest = request as AuthenticatedRequest;\n const user = await this.userService.findById(authRequest.user.id);\n\n if (!user) {\n throw new UnauthorizedError('User not found');\n }\n\n success(reply, {\n id: user.id,\n email: user.email,\n name: user.name,\n role: user.role,\n status: user.status,\n createdAt: user.createdAt,\n });\n }\n\n async changePassword(request: FastifyRequest, reply: FastifyReply): Promise<void> {\n const authRequest = request as AuthenticatedRequest;\n const data = validateBody(changePasswordSchema, request.body);\n\n // Get current user\n const user = await this.userService.findById(authRequest.user.id);\n if (!user) {\n throw new UnauthorizedError('User not found');\n }\n\n // Verify current password\n const isValidPassword = await this.authService.verifyPassword(\n data.currentPassword,\n user.password\n );\n if (!isValidPassword) {\n throw new BadRequestError('Current password is incorrect');\n }\n\n // Hash and update password\n const hashedPassword = await this.authService.hashPassword(data.newPassword);\n await this.userService.updatePassword(user.id, hashedPassword);\n\n success(reply, { message: 'Password changed successfully' });\n }\n}\n\nexport function createAuthController(\n authService: AuthService,\n userService: UserService\n): AuthController {\n return new AuthController(authService, userService);\n}\n","import type { FastifyRequest, FastifyReply } from 'fastify';\nimport { UnauthorizedError, ForbiddenError } from '../../utils/errors.js';\nimport type { AuthService } from './auth.service.js';\nimport type { AuthUser } from './types.js';\n\nexport function createAuthMiddleware(authService: AuthService) {\n return async function authenticate(request: FastifyRequest, _reply: FastifyReply): Promise<void> {\n const authHeader = request.headers.authorization;\n\n if (!authHeader || !authHeader.startsWith('Bearer ')) {\n throw new UnauthorizedError('Missing or invalid authorization header');\n }\n\n const token = authHeader.substring(7);\n const payload = await authService.verifyAccessToken(token);\n\n request.user = {\n id: payload.sub,\n email: payload.email,\n role: payload.role,\n };\n };\n}\n\nexport function createRoleMiddleware(allowedRoles: string[]) {\n return async function authorize(request: FastifyRequest, _reply: FastifyReply): Promise<void> {\n const user = request.user as AuthUser | undefined;\n\n if (!user) {\n throw new UnauthorizedError('Authentication required');\n }\n\n if (!allowedRoles.includes(user.role)) {\n throw new ForbiddenError('Insufficient permissions');\n }\n };\n}\n\nexport function createPermissionMiddleware(_requiredPermissions: string[]) {\n return async function checkPermissions(\n request: FastifyRequest,\n _reply: FastifyReply\n ): Promise<void> {\n const user = request.user as AuthUser | undefined;\n\n if (!user) {\n throw new UnauthorizedError('Authentication required');\n }\n\n // This would check against a permissions system\n // For now, we'll implement a basic role-based check\n // In a full implementation, you'd query the user's permissions from the database\n };\n}\n\n// Optional authentication - doesn't throw if no token\nexport function createOptionalAuthMiddleware(authService: AuthService) {\n return async function optionalAuthenticate(\n request: FastifyRequest,\n _reply: FastifyReply\n ): Promise<void> {\n const authHeader = request.headers.authorization;\n\n if (!authHeader || !authHeader.startsWith('Bearer ')) {\n return;\n }\n\n try {\n const token = authHeader.substring(7);\n const payload = await authService.verifyAccessToken(token);\n\n request.user = {\n id: payload.sub,\n email: payload.email,\n role: payload.role,\n };\n } catch {\n // Silently ignore auth errors for optional auth\n }\n };\n}\n","import type { FastifyInstance } from 'fastify';\nimport type { AuthController } from './auth.controller.js';\nimport type { AuthService } from './auth.service.js';\nimport { createAuthMiddleware } from './auth.middleware.js';\n\nexport function registerAuthRoutes(\n app: FastifyInstance,\n controller: AuthController,\n authService: AuthService\n): void {\n const authenticate = createAuthMiddleware(authService);\n\n // Public routes\n app.post('/auth/register', controller.register.bind(controller));\n app.post('/auth/login', controller.login.bind(controller));\n app.post('/auth/refresh', controller.refresh.bind(controller));\n\n // Protected routes\n app.post('/auth/logout', { preHandler: [authenticate] }, controller.logout.bind(controller));\n app.get('/auth/me', { preHandler: [authenticate] }, controller.me.bind(controller));\n app.post(\n '/auth/change-password',\n { preHandler: [authenticate] },\n controller.changePassword.bind(controller)\n );\n}\n","import { PrismaClient } from '@prisma/client';\nimport { logger } from '../core/logger.js';\nimport { isProduction } from '../config/index.js';\n\ndeclare global {\n var __prisma: PrismaClient | undefined;\n}\n\nconst prismaClientSingleton = (): PrismaClient => {\n return new PrismaClient({\n log: isProduction() ? ['error'] : ['query', 'info', 'warn', 'error'],\n errorFormat: isProduction() ? 'minimal' : 'pretty',\n });\n};\n\n// Lazy initialization - only create client when accessed\nlet _prisma: PrismaClient | undefined;\n\nexport const prisma = new Proxy({} as PrismaClient, {\n get(target, prop) {\n // Initialize on first access\n if (!_prisma) {\n _prisma = globalThis.__prisma ?? prismaClientSingleton();\n if (!isProduction()) {\n globalThis.__prisma = _prisma;\n }\n }\n return (_prisma as any)[prop];\n },\n});\n\nexport async function connectDatabase(): Promise<void> {\n try {\n await prisma.$connect();\n logger.info('Database connected successfully');\n } catch (error) {\n logger.error({ err: error }, 'Failed to connect to database');\n throw error;\n }\n}\n\nexport async function disconnectDatabase(): Promise<void> {\n try {\n await prisma.$disconnect();\n logger.info('Database disconnected');\n } catch (error) {\n logger.error({ err: error }, 'Error disconnecting from database');\n }\n}\n\nexport async function checkDatabaseHealth(): Promise<boolean> {\n try {\n await prisma.$queryRaw`SELECT 1`;\n return true;\n } catch {\n return false;\n }\n}\n\nexport { PrismaClient };\n","import type { PaginationParams, PaginatedResult } from '../types/index.js';\n\nexport const DEFAULT_PAGE = 1;\nexport const DEFAULT_LIMIT = 20;\nexport const MAX_LIMIT = 100;\n\nexport function parsePaginationParams(query: Record<string, unknown>): PaginationParams {\n const page = Math.max(1, parseInt(String(query.page || DEFAULT_PAGE), 10));\n const limit = Math.min(\n MAX_LIMIT,\n Math.max(1, parseInt(String(query.limit || DEFAULT_LIMIT), 10))\n );\n const sortBy = typeof query.sortBy === 'string' ? query.sortBy : undefined;\n const sortOrder = query.sortOrder === 'desc' ? 'desc' : 'asc';\n\n return { page, limit, sortBy, sortOrder };\n}\n\nexport function createPaginatedResult<T>(\n data: T[],\n total: number,\n params: PaginationParams\n): PaginatedResult<T> {\n const totalPages = Math.ceil(total / params.limit);\n\n return {\n data,\n meta: {\n total,\n page: params.page,\n limit: params.limit,\n totalPages,\n hasNextPage: params.page < totalPages,\n hasPrevPage: params.page > 1,\n },\n };\n}\n\nexport function getSkip(params: PaginationParams): number {\n return (params.page - 1) * params.limit;\n}\n","import { prisma } from '../../database/prisma.js';\nimport type { PaginatedResult, PaginationParams } from '../../types/index.js';\nimport { createPaginatedResult, getSkip } from '../../utils/pagination.js';\nimport type { User, CreateUserData, UpdateUserData, UserFilters } from './types.js';\n\n// Use string literal enums for ESM/CommonJS compatibility\nconst UserRole = {\n USER: 'USER',\n MODERATOR: 'MODERATOR',\n ADMIN: 'ADMIN',\n SUPER_ADMIN: 'SUPER_ADMIN',\n} as const;\n\nconst UserStatus = {\n ACTIVE: 'ACTIVE',\n INACTIVE: 'INACTIVE',\n SUSPENDED: 'SUSPENDED',\n BANNED: 'BANNED',\n} as const;\n\ntype UserRole = (typeof UserRole)[keyof typeof UserRole];\ntype UserStatus = (typeof UserStatus)[keyof typeof UserStatus];\n\n/**\n * User Repository - Prisma Implementation\n * Manages user data persistence using Prisma ORM\n */\nexport class UserRepository {\n /**\n * Find user by ID\n */\n async findById(id: string): Promise<User | null> {\n const user = await prisma.user.findUnique({\n where: { id },\n });\n\n if (!user) return null;\n return this.mapPrismaUserToUser(user);\n }\n\n /**\n * Find user by email (case-insensitive)\n */\n async findByEmail(email: string): Promise<User | null> {\n const user = await prisma.user.findUnique({\n where: { email: email.toLowerCase() },\n });\n\n if (!user) return null;\n return this.mapPrismaUserToUser(user);\n }\n\n /**\n * Find multiple users with pagination and filters\n */\n async findMany(params: PaginationParams, filters?: UserFilters): Promise<PaginatedResult<User>> {\n const where = this.buildWhereClause(filters);\n const orderBy = this.buildOrderBy(params);\n\n const [data, total] = await Promise.all([\n prisma.user.findMany({\n where,\n orderBy,\n skip: getSkip(params),\n take: params.limit,\n }),\n prisma.user.count({ where }),\n ]);\n\n const mappedUsers = data.map((user) => this.mapPrismaUserToUser(user));\n\n return createPaginatedResult(mappedUsers, total, params);\n }\n\n /**\n * Create a new user\n */\n async create(data: CreateUserData): Promise<User> {\n const user = await prisma.user.create({\n data: {\n email: data.email.toLowerCase(),\n password: data.password,\n name: data.name,\n role: this.mapRoleToEnum(data.role || 'user'),\n status: UserStatus.ACTIVE,\n emailVerified: false,\n },\n });\n\n return this.mapPrismaUserToUser(user);\n }\n\n /**\n * Update user data\n */\n async update(id: string, data: UpdateUserData): Promise<User | null> {\n try {\n const user = await prisma.user.update({\n where: { id },\n data: {\n ...(data.email && { email: data.email.toLowerCase() }),\n ...(data.name !== undefined && { name: data.name }),\n ...(data.role && { role: this.mapRoleToEnum(data.role) }),\n ...(data.status && { status: this.mapStatusToEnum(data.status) }),\n ...(data.emailVerified !== undefined && { emailVerified: data.emailVerified }),\n ...(data.metadata && { metadata: data.metadata as object }),\n },\n });\n\n return this.mapPrismaUserToUser(user);\n } catch {\n // User not found\n return null;\n }\n }\n\n /**\n * Update user password\n */\n async updatePassword(id: string, password: string): Promise<User | null> {\n try {\n const user = await prisma.user.update({\n where: { id },\n data: { password },\n });\n\n return this.mapPrismaUserToUser(user);\n } catch {\n return null;\n }\n }\n\n /**\n * Update last login timestamp\n */\n async updateLastLogin(id: string): Promise<User | null> {\n try {\n const user = await prisma.user.update({\n where: { id },\n data: { lastLoginAt: new Date() },\n });\n\n return this.mapPrismaUserToUser(user);\n } catch {\n return null;\n }\n }\n\n /**\n * Delete user by ID\n */\n async delete(id: string): Promise<boolean> {\n try {\n await prisma.user.delete({\n where: { id },\n });\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Count users with optional filters\n */\n async count(filters?: UserFilters): Promise<number> {\n const where = this.buildWhereClause(filters);\n return prisma.user.count({ where });\n }\n\n /**\n * Helper to clear all users (for testing only)\n * WARNING: This deletes all users from the database\n */\n async clear(): Promise<void> {\n await prisma.user.deleteMany();\n }\n\n /**\n * Build Prisma where clause from filters\n */\n private buildWhereClause(filters?: UserFilters): object {\n if (!filters) return {};\n\n return {\n ...(filters.status && { status: this.mapStatusToEnum(filters.status) }),\n ...(filters.role && { role: this.mapRoleToEnum(filters.role) }),\n ...(filters.emailVerified !== undefined && { emailVerified: filters.emailVerified }),\n ...(filters.search && {\n OR: [\n { email: { contains: filters.search, mode: 'insensitive' as const } },\n { name: { contains: filters.search, mode: 'insensitive' as const } },\n ],\n }),\n };\n }\n\n /**\n * Build Prisma orderBy clause from pagination params\n */\n private buildOrderBy(params: PaginationParams): object {\n if (!params.sortBy) {\n return { createdAt: 'desc' as const };\n }\n\n return {\n [params.sortBy]: params.sortOrder || 'asc',\n };\n }\n\n /**\n * Map Prisma User to application User type\n */\n private mapPrismaUserToUser(prismaUser: {\n id: string;\n email: string;\n password: string;\n name: string | null;\n role: UserRole;\n status: UserStatus;\n emailVerified: boolean;\n lastLoginAt: Date | null;\n metadata: unknown;\n createdAt: Date;\n updatedAt: Date;\n }): User {\n return {\n id: prismaUser.id,\n email: prismaUser.email,\n password: prismaUser.password,\n name: prismaUser.name ?? undefined,\n role: this.mapEnumToRole(prismaUser.role),\n status: this.mapEnumToStatus(prismaUser.status),\n emailVerified: prismaUser.emailVerified,\n lastLoginAt: prismaUser.lastLoginAt ?? undefined,\n metadata: prismaUser.metadata as Record<string, unknown> | undefined,\n createdAt: prismaUser.createdAt,\n updatedAt: prismaUser.updatedAt,\n };\n }\n\n /**\n * Map application role to Prisma enum\n */\n private mapRoleToEnum(role: string): UserRole {\n const roleMap: Record<string, UserRole> = {\n user: UserRole.USER,\n moderator: UserRole.MODERATOR,\n admin: UserRole.ADMIN,\n super_admin: UserRole.SUPER_ADMIN,\n };\n return roleMap[role] || UserRole.USER;\n }\n\n /**\n * Map Prisma enum to application role\n */\n private mapEnumToRole(role: UserRole): User['role'] {\n const roleMap: Record<UserRole, User['role']> = {\n [UserRole.USER]: 'user',\n [UserRole.MODERATOR]: 'moderator',\n [UserRole.ADMIN]: 'admin',\n [UserRole.SUPER_ADMIN]: 'super_admin',\n };\n return roleMap[role];\n }\n\n /**\n * Map application status to Prisma enum\n */\n private mapStatusToEnum(status: string): UserStatus {\n const statusMap: Record<string, UserStatus> = {\n active: UserStatus.ACTIVE,\n inactive: UserStatus.INACTIVE,\n suspended: UserStatus.SUSPENDED,\n banned: UserStatus.BANNED,\n };\n return statusMap[status] || UserStatus.ACTIVE;\n }\n\n /**\n * Map Prisma enum to application status\n */\n private mapEnumToStatus(status: UserStatus): User['status'] {\n const statusMap: Record<UserStatus, User['status']> = {\n [UserStatus.ACTIVE]: 'active',\n [UserStatus.INACTIVE]: 'inactive',\n [UserStatus.SUSPENDED]: 'suspended',\n [UserStatus.BANNED]: 'banned',\n };\n return statusMap[status];\n }\n}\n\nexport function createUserRepository(): UserRepository {\n return new UserRepository();\n}\n","import type { BaseEntity } from '../../types/index.js';\n\nexport type UserStatus = 'active' | 'inactive' | 'suspended' | 'banned';\n\nexport type UserRole = 'user' | 'admin' | 'moderator' | 'super_admin';\n\nexport interface User extends BaseEntity {\n email: string;\n password: string;\n name?: string;\n role: UserRole;\n status: UserStatus;\n emailVerified: boolean;\n lastLoginAt?: Date;\n metadata?: Record<string, unknown>;\n}\n\nexport interface CreateUserData {\n email: string;\n password: string;\n name?: string;\n role?: UserRole;\n}\n\nexport interface UpdateUserData {\n email?: string;\n name?: string;\n role?: UserRole;\n status?: UserStatus;\n emailVerified?: boolean;\n metadata?: Record<string, unknown>;\n}\n\nexport interface UserFilters {\n status?: UserStatus;\n role?: UserRole;\n search?: string;\n emailVerified?: boolean;\n}\n\n// RBAC Types\nexport interface Permission {\n id: string;\n name: string;\n description?: string;\n resource: string;\n action: 'create' | 'read' | 'update' | 'delete' | 'manage';\n}\n\nexport interface Role {\n id: string;\n name: UserRole;\n description?: string;\n permissions: Permission[];\n}\n\n// Default permissions mapping\nexport const DEFAULT_ROLE_PERMISSIONS: Record<UserRole, string[]> = {\n user: ['profile:read', 'profile:update'],\n moderator: [\n 'profile:read',\n 'profile:update',\n 'users:read',\n 'content:read',\n 'content:update',\n 'content:delete',\n ],\n admin: [\n 'profile:read',\n 'profile:update',\n 'users:read',\n 'users:update',\n 'users:delete',\n 'content:manage',\n 'settings:read',\n ],\n super_admin: ['*:manage'], // All permissions\n};\n","import type { PaginatedResult, PaginationParams } from '../../types/index.js';\nimport { NotFoundError, ConflictError } from '../../utils/errors.js';\nimport type { UserRepository } from './user.repository.js';\nimport { createUserRepository } from './user.repository.js';\nimport type { User, CreateUserData, UpdateUserData, UserFilters, UserRole } from './types.js';\nimport { DEFAULT_ROLE_PERMISSIONS } from './types.js';\nimport { logger } from '../../core/logger.js';\n\nexport class UserService {\n constructor(private repository: UserRepository) {}\n\n async findById(id: string): Promise<User | null> {\n return this.repository.findById(id);\n }\n\n async findByEmail(email: string): Promise<User | null> {\n return this.repository.findByEmail(email);\n }\n\n async findMany(\n params: PaginationParams,\n filters?: UserFilters\n ): Promise<PaginatedResult<Omit<User, 'password'>>> {\n const result = await this.repository.findMany(params, filters);\n\n // Remove passwords from results\n return {\n ...result,\n data: result.data.map(({ password: _password, ...user }) => user) as Omit<User, 'password'>[],\n };\n }\n\n async create(data: CreateUserData): Promise<User> {\n // Check for existing user\n const existing = await this.repository.findByEmail(data.email);\n if (existing) {\n throw new ConflictError('User with this email already exists');\n }\n\n const user = await this.repository.create(data);\n logger.info({ userId: user.id, email: user.email }, 'User created');\n return user;\n }\n\n async update(id: string, data: UpdateUserData): Promise<User> {\n const user = await this.repository.findById(id);\n if (!user) {\n throw new NotFoundError('User');\n }\n\n // Check email uniqueness if changing email\n if (data.email && data.email !== user.email) {\n const existing = await this.repository.findByEmail(data.email);\n if (existing) {\n throw new ConflictError('Email already in use');\n }\n }\n\n const updatedUser = await this.repository.update(id, data);\n if (!updatedUser) {\n throw new NotFoundError('User');\n }\n\n logger.info({ userId: id }, 'User updated');\n return updatedUser;\n }\n\n async updatePassword(id: string, hashedPassword: string): Promise<User> {\n const user = await this.repository.updatePassword(id, hashedPassword);\n if (!user) {\n throw new NotFoundError('User');\n }\n logger.info({ userId: id }, 'User password updated');\n return user;\n }\n\n async updateLastLogin(id: string): Promise<User> {\n const user = await this.repository.updateLastLogin(id);\n if (!user) {\n throw new NotFoundError('User');\n }\n return user;\n }\n\n async delete(id: string): Promise<void> {\n const user = await this.repository.findById(id);\n if (!user) {\n throw new NotFoundError('User');\n }\n\n await this.repository.delete(id);\n logger.info({ userId: id }, 'User deleted');\n }\n\n async suspend(id: string): Promise<User> {\n return this.update(id, { status: 'suspended' });\n }\n\n async ban(id: string): Promise<User> {\n return this.update(id, { status: 'banned' });\n }\n\n async activate(id: string): Promise<User> {\n return this.update(id, { status: 'active' });\n }\n\n async verifyEmail(id: string): Promise<User> {\n return this.update(id, { emailVerified: true });\n }\n\n async changeRole(id: string, role: UserRole): Promise<User> {\n return this.update(id, { role });\n }\n\n // RBAC helpers\n hasPermission(role: UserRole, permission: string): boolean {\n const permissions = DEFAULT_ROLE_PERMISSIONS[role] || [];\n\n // Super admin has all permissions\n if (permissions.includes('*:manage')) {\n return true;\n }\n\n // Check exact match\n if (permissions.includes(permission)) {\n return true;\n }\n\n // Check wildcard match (e.g., \"content:manage\" matches \"content:read\")\n const [resource] = permission.split(':');\n const managePermission = `${resource}:manage`;\n if (permissions.includes(managePermission)) {\n return true;\n }\n\n return false;\n }\n\n getPermissions(role: UserRole): string[] {\n return DEFAULT_ROLE_PERMISSIONS[role] || [];\n }\n}\n\nexport function createUserService(repository?: UserRepository): UserService {\n return new UserService(repository || createUserRepository());\n}\n","import { z } from 'zod';\n\nexport const userStatusEnum = z.enum(['active', 'inactive', 'suspended', 'banned']);\nexport const userRoleEnum = z.enum(['user', 'admin', 'moderator', 'super_admin']);\n\nexport const createUserSchema = z.object({\n email: z.string().email('Invalid email address'),\n password: z\n .string()\n .min(8, 'Password must be at least 8 characters')\n .regex(/[A-Z]/, 'Password must contain at least one uppercase letter')\n .regex(/[a-z]/, 'Password must contain at least one lowercase letter')\n .regex(/[0-9]/, 'Password must contain at least one number'),\n name: z.string().min(2, 'Name must be at least 2 characters').optional(),\n role: userRoleEnum.optional().default('user'),\n});\n\nexport const updateUserSchema = z.object({\n email: z.string().email('Invalid email address').optional(),\n name: z.string().min(2, 'Name must be at least 2 characters').optional(),\n role: userRoleEnum.optional(),\n status: userStatusEnum.optional(),\n emailVerified: z.boolean().optional(),\n metadata: z.record(z.unknown()).optional(),\n});\n\nexport const updateProfileSchema = z.object({\n name: z.string().min(2, 'Name must be at least 2 characters').optional(),\n metadata: z.record(z.unknown()).optional(),\n});\n\nexport const userQuerySchema = z.object({\n page: z.string().transform(Number).optional(),\n limit: z.string().transform(Number).optional(),\n sortBy: z.string().optional(),\n sortOrder: z.enum(['asc', 'desc']).optional(),\n status: userStatusEnum.optional(),\n role: userRoleEnum.optional(),\n search: z.string().optional(),\n emailVerified: z\n .string()\n .transform((val) => val === 'true')\n .optional(),\n});\n\nexport type CreateUserInput = z.infer<typeof createUserSchema>;\nexport type UpdateUserInput = z.infer<typeof updateUserSchema>;\nexport type UpdateProfileInput = z.infer<typeof updateProfileSchema>;\nexport type UserQueryInput = z.infer<typeof userQuerySchema>;\n","import type { FastifyRequest, FastifyReply } from 'fastify';\nimport type { UserService } from './user.service.js';\nimport { updateUserSchema, updateProfileSchema, userQuerySchema } from './schemas.js';\nimport { success, noContent } from '../../utils/response.js';\nimport { parsePaginationParams } from '../../utils/pagination.js';\nimport { validateBody, validateQuery } from '../validation/validator.js';\nimport type { AuthenticatedRequest } from '../auth/types.js';\nimport { ForbiddenError } from '../../utils/errors.js';\nimport type { User } from './types.js';\n\n// Helper to remove password from user object\nfunction omitPassword(user: User): Omit<User, 'password'> {\n const { password, ...userData } = user;\n void password; // Explicitly mark as intentionally unused\n return userData;\n}\n\nexport class UserController {\n constructor(private userService: UserService) {}\n\n async list(request: FastifyRequest, reply: FastifyReply): Promise<void> {\n const query = validateQuery(userQuerySchema, request.query);\n const pagination = parsePaginationParams(query);\n\n const filters = {\n status: query.status,\n role: query.role,\n search: query.search,\n emailVerified: query.emailVerified,\n };\n\n const result = await this.userService.findMany(pagination, filters);\n success(reply, result);\n }\n\n async getById(\n request: FastifyRequest<{ Params: { id: string } }>,\n reply: FastifyReply\n ): Promise<void> {\n const user = await this.userService.findById(request.params.id);\n\n if (!user) {\n return reply.status(404).send({\n success: false,\n message: 'User not found',\n });\n }\n\n // Remove password from response\n success(reply, omitPassword(user));\n }\n\n async update(\n request: FastifyRequest<{ Params: { id: string } }>,\n reply: FastifyReply\n ): Promise<void> {\n const data = validateBody(updateUserSchema, request.body);\n const user = await this.userService.update(request.params.id, data);\n\n success(reply, omitPassword(user));\n }\n\n async delete(\n request: FastifyRequest<{ Params: { id: string } }>,\n reply: FastifyReply\n ): Promise<void> {\n const authRequest = request as AuthenticatedRequest;\n\n // Prevent self-deletion\n if (authRequest.user.id === request.params.id) {\n throw new ForbiddenError('Cannot delete your own account');\n }\n\n await this.userService.delete(request.params.id);\n noContent(reply);\n }\n\n async suspend(\n request: FastifyRequest<{ Params: { id: string } }>,\n reply: FastifyReply\n ): Promise<void> {\n const authRequest = request as AuthenticatedRequest;\n\n if (authRequest.user.id === request.params.id) {\n throw new ForbiddenError('Cannot suspend your own account');\n }\n\n const user = await this.userService.suspend(request.params.id);\n const userData = omitPassword(user);\n success(reply, userData);\n }\n\n async ban(\n request: FastifyRequest<{ Params: { id: string } }>,\n reply: FastifyReply\n ): Promise<void> {\n const authRequest = request as AuthenticatedRequest;\n\n if (authRequest.user.id === request.params.id) {\n throw new ForbiddenError('Cannot ban your own account');\n }\n\n const user = await this.userService.ban(request.params.id);\n const userData = omitPassword(user);\n success(reply, userData);\n }\n\n async activate(\n request: FastifyRequest<{ Params: { id: string } }>,\n reply: FastifyReply\n ): Promise<void> {\n const user = await this.userService.activate(request.params.id);\n const userData = omitPassword(user);\n success(reply, userData);\n }\n\n // Profile routes (for authenticated user)\n async getProfile(request: FastifyRequest, reply: FastifyReply): Promise<void> {\n const authRequest = request as AuthenticatedRequest;\n const user = await this.userService.findById(authRequest.user.id);\n\n if (!user) {\n return reply.status(404).send({\n success: false,\n message: 'User not found',\n });\n }\n\n const userData = omitPassword(user);\n success(reply, userData);\n }\n\n async updateProfile(request: FastifyRequest, reply: FastifyReply): Promise<void> {\n const authRequest = request as AuthenticatedRequest;\n const data = validateBody(updateProfileSchema, request.body);\n\n const user = await this.userService.update(authRequest.user.id, data);\n const userData = omitPassword(user);\n success(reply, userData);\n }\n}\n\nexport function createUserController(userService: UserService): UserController {\n return new UserController(userService);\n}\n","import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';\nimport type { UserController } from './user.controller.js';\nimport type { AuthService } from '../auth/auth.service.js';\nimport { createAuthMiddleware, createRoleMiddleware } from '../auth/auth.middleware.js';\n\n// Route params schema for Fastify\nconst idParamsSchema = {\n type: 'object',\n properties: {\n id: { type: 'string' },\n },\n required: ['id'],\n} as const;\n\nexport function registerUserRoutes(\n app: FastifyInstance,\n controller: UserController,\n authService: AuthService\n): void {\n const authenticate = createAuthMiddleware(authService);\n const isAdmin = createRoleMiddleware(['admin', 'super_admin']);\n const isModerator = createRoleMiddleware(['moderator', 'admin', 'super_admin']);\n\n // Profile routes (authenticated users)\n app.get('/profile', { preHandler: [authenticate] }, controller.getProfile.bind(controller));\n app.patch('/profile', { preHandler: [authenticate] }, controller.updateProfile.bind(controller));\n\n // Admin routes\n app.get('/users', { preHandler: [authenticate, isModerator] }, controller.list.bind(controller));\n app.get<{ Params: { id: string } }>(\n '/users/:id',\n { preHandler: [authenticate, isModerator], schema: { params: idParamsSchema } },\n async (request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) => {\n return controller.getById(request, reply);\n }\n );\n app.patch<{ Params: { id: string } }>(\n '/users/:id',\n { preHandler: [authenticate, isAdmin], schema: { params: idParamsSchema } },\n async (request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) => {\n return controller.update(request, reply);\n }\n );\n app.delete<{ Params: { id: string } }>(\n '/users/:id',\n { preHandler: [authenticate, isAdmin], schema: { params: idParamsSchema } },\n async (request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) => {\n return controller.delete(request, reply);\n }\n );\n\n // User status management\n app.post<{ Params: { id: string } }>(\n '/users/:id/suspend',\n { preHandler: [authenticate, isAdmin], schema: { params: idParamsSchema } },\n async (request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) => {\n return controller.suspend(request, reply);\n }\n );\n app.post<{ Params: { id: string } }>(\n '/users/:id/ban',\n { preHandler: [authenticate, isAdmin], schema: { params: idParamsSchema } },\n async (request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) => {\n return controller.ban(request, reply);\n }\n );\n app.post<{ Params: { id: string } }>(\n '/users/:id/activate',\n { preHandler: [authenticate, isAdmin], schema: { params: idParamsSchema } },\n async (request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) => {\n return controller.activate(request, reply);\n }\n );\n}\n","import type { FastifyInstance } from 'fastify';\nimport { logger } from '../../core/logger.js';\nimport { createUserService } from './user.service.js';\nimport { createUserController } from './user.controller.js';\nimport { createUserRepository } from './user.repository.js';\nimport { registerUserRoutes } from './user.routes.js';\nimport type { AuthService } from '../auth/auth.service.js';\n\nexport async function registerUserModule(\n app: FastifyInstance,\n authService: AuthService\n): Promise<void> {\n // Create repository and service\n const repository = createUserRepository();\n const userService = createUserService(repository);\n\n // Create controller\n const userController = createUserController(userService);\n\n // Register routes\n registerUserRoutes(app, userController, authService);\n\n logger.info('User module registered');\n}\n\nexport { UserService, createUserService } from './user.service.js';\nexport { UserController, createUserController } from './user.controller.js';\nexport { UserRepository, createUserRepository } from './user.repository.js';\nexport * from './types.js';\nexport * from './schemas.js';\n","import nodemailer from 'nodemailer';\nimport type { Transporter } from 'nodemailer';\nimport { config } from '../../config/index.js';\nimport { logger } from '../../core/logger.js';\nimport { renderTemplate } from './templates.js';\nimport type { EmailOptions, EmailResult, EmailConfig, TemplateData } from './types.js';\n\nexport class EmailService {\n private transporter: Transporter | null = null;\n private config: EmailConfig | null = null;\n\n constructor(emailConfig?: Partial<EmailConfig>) {\n if (emailConfig?.host || config.email.host) {\n this.config = {\n host: emailConfig?.host || config.email.host || '',\n port: emailConfig?.port || config.email.port || 587,\n secure: (emailConfig?.port || config.email.port || 587) === 465,\n auth: {\n user: emailConfig?.auth?.user || config.email.user || '',\n pass: emailConfig?.auth?.pass || config.email.pass || '',\n },\n from: emailConfig?.from || config.email.from || 'noreply@localhost',\n };\n\n this.transporter = nodemailer.createTransport({\n host: this.config.host,\n port: this.config.port,\n secure: this.config.secure,\n auth: {\n user: this.config.auth.user,\n pass: this.config.auth.pass,\n },\n });\n\n logger.info('Email service initialized');\n } else {\n logger.warn('Email service not configured - emails will be logged only');\n }\n }\n\n async send(options: EmailOptions): Promise<EmailResult> {\n try {\n let html = options.html;\n let text = options.text;\n\n // Render template if provided\n if (options.template && options.data) {\n html = renderTemplate(options.template, options.data);\n }\n\n // Generate plain text from HTML if not provided\n if (html && !text) {\n text = this.htmlToText(html);\n }\n\n const mailOptions = {\n from: this.config?.from || 'noreply@localhost',\n to: Array.isArray(options.to) ? options.to.join(', ') : options.to,\n subject: options.subject,\n html,\n text,\n replyTo: options.replyTo,\n cc: options.cc,\n bcc: options.bcc,\n attachments: options.attachments,\n };\n\n // If no transporter, just log the email\n if (!this.transporter) {\n logger.info({ email: mailOptions }, 'Email would be sent (no transporter configured)');\n return { success: true, messageId: 'dev-mode' };\n }\n\n const result = await this.transporter.sendMail(mailOptions);\n\n logger.info({ messageId: result.messageId, to: options.to }, 'Email sent successfully');\n\n return {\n success: true,\n messageId: result.messageId,\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n logger.error({ err: error, to: options.to }, 'Failed to send email');\n\n return {\n success: false,\n error: errorMessage,\n };\n }\n }\n\n async sendTemplate(to: string, template: string, data: TemplateData): Promise<EmailResult> {\n const subjects: Record<string, string> = {\n welcome: `Welcome to ${data.appName || 'Servcraft'}!`,\n 'verify-email': 'Verify Your Email',\n 'password-reset': 'Reset Your Password',\n 'password-changed': 'Password Changed Successfully',\n 'login-alert': 'New Login Detected',\n 'account-suspended': 'Account Suspended',\n };\n\n return this.send({\n to,\n subject: subjects[template] || 'Notification',\n template,\n data,\n });\n }\n\n async sendWelcome(email: string, name: string, verifyUrl?: string): Promise<EmailResult> {\n return this.sendTemplate(email, 'welcome', {\n userName: name,\n userEmail: email,\n actionUrl: verifyUrl,\n });\n }\n\n async sendVerifyEmail(email: string, name: string, verifyUrl: string): Promise<EmailResult> {\n return this.sendTemplate(email, 'verify-email', {\n userName: name,\n userEmail: email,\n actionUrl: verifyUrl,\n expiresIn: '24 hours',\n });\n }\n\n async sendPasswordReset(email: string, name: string, resetUrl: string): Promise<EmailResult> {\n return this.sendTemplate(email, 'password-reset', {\n userName: name,\n userEmail: email,\n actionUrl: resetUrl,\n expiresIn: '1 hour',\n });\n }\n\n async sendPasswordChanged(\n email: string,\n name: string,\n ipAddress?: string,\n userAgent?: string\n ): Promise<EmailResult> {\n return this.sendTemplate(email, 'password-changed', {\n userName: name,\n userEmail: email,\n ipAddress: ipAddress || 'Unknown',\n userAgent: userAgent || 'Unknown',\n timestamp: new Date().toISOString(),\n });\n }\n\n async sendLoginAlert(\n email: string,\n name: string,\n ipAddress: string,\n userAgent: string,\n location?: string\n ): Promise<EmailResult> {\n return this.sendTemplate(email, 'login-alert', {\n userName: name,\n userEmail: email,\n ipAddress,\n userAgent,\n location: location || 'Unknown',\n timestamp: new Date().toISOString(),\n });\n }\n\n async verify(): Promise<boolean> {\n if (!this.transporter) {\n return false;\n }\n\n try {\n await this.transporter.verify();\n logger.info('Email service connection verified');\n return true;\n } catch (error) {\n logger.error({ err: error }, 'Email service connection failed');\n return false;\n }\n }\n\n private htmlToText(html: string): string {\n return html\n .replace(/<style[^>]*>[\\s\\S]*?<\\/style>/gi, '')\n .replace(/<script[^>]*>[\\s\\S]*?<\\/script>/gi, '')\n .replace(/<[^>]+>/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n }\n}\n\nlet emailService: EmailService | null = null;\n\nexport function getEmailService(): EmailService {\n if (!emailService) {\n emailService = new EmailService();\n }\n return emailService;\n}\n\nexport function createEmailService(config?: Partial<EmailConfig>): EmailService {\n return new EmailService(config);\n}\n","import Handlebars from 'handlebars';\n\n// Base layout template\nconst baseLayout = `\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>{{subject}}</title>\n <style>\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;\n line-height: 1.6;\n color: #333;\n max-width: 600px;\n margin: 0 auto;\n padding: 20px;\n background-color: #f5f5f5;\n }\n .container {\n background-color: #ffffff;\n border-radius: 8px;\n padding: 40px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n }\n .header {\n text-align: center;\n margin-bottom: 30px;\n }\n .logo {\n font-size: 24px;\n font-weight: bold;\n color: #2563eb;\n }\n .content {\n margin-bottom: 30px;\n }\n .button {\n display: inline-block;\n padding: 12px 24px;\n background-color: #2563eb;\n color: #ffffff !important;\n text-decoration: none;\n border-radius: 6px;\n font-weight: 500;\n }\n .button:hover {\n background-color: #1d4ed8;\n }\n .footer {\n text-align: center;\n font-size: 12px;\n color: #666;\n margin-top: 30px;\n padding-top: 20px;\n border-top: 1px solid #eee;\n }\n .warning {\n background-color: #fef3c7;\n border: 1px solid #f59e0b;\n border-radius: 6px;\n padding: 12px;\n margin: 20px 0;\n }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <div class=\"header\">\n <div class=\"logo\">{{appName}}</div>\n </div>\n <div class=\"content\">\n {{{body}}}\n </div>\n <div class=\"footer\">\n <p>© {{year}} {{appName}}. All rights reserved.</p>\n <p>This email was sent to {{userEmail}}</p>\n </div>\n </div>\n</body>\n</html>\n`;\n\n// Individual templates\nconst templates: Record<string, string> = {\n welcome: `\n <h2>Welcome to {{appName}}!</h2>\n <p>Hi {{userName}},</p>\n <p>Thank you for joining {{appName}}. We're excited to have you on board!</p>\n <p>To get started, please verify your email address by clicking the button below:</p>\n <p style=\"text-align: center; margin: 30px 0;\">\n <a href=\"{{actionUrl}}\" class=\"button\">Verify Email</a>\n </p>\n <p>If you didn't create an account with us, you can safely ignore this email.</p>\n `,\n\n 'verify-email': `\n <h2>Verify Your Email</h2>\n <p>Hi {{userName}},</p>\n <p>Please verify your email address by clicking the button below:</p>\n <p style=\"text-align: center; margin: 30px 0;\">\n <a href=\"{{actionUrl}}\" class=\"button\">Verify Email</a>\n </p>\n <p>This link will expire in {{expiresIn}}.</p>\n <p>If you didn't request this verification, you can safely ignore this email.</p>\n `,\n\n 'password-reset': `\n <h2>Reset Your Password</h2>\n <p>Hi {{userName}},</p>\n <p>We received a request to reset your password. Click the button below to create a new password:</p>\n <p style=\"text-align: center; margin: 30px 0;\">\n <a href=\"{{actionUrl}}\" class=\"button\">Reset Password</a>\n </p>\n <p>This link will expire in {{expiresIn}}.</p>\n <div class=\"warning\">\n <strong>Security Notice:</strong> If you didn't request this password reset, please ignore this email and your password will remain unchanged.\n </div>\n `,\n\n 'password-changed': `\n <h2>Password Changed</h2>\n <p>Hi {{userName}},</p>\n <p>Your password has been successfully changed.</p>\n <p>If you didn't make this change, please contact our support team immediately and secure your account.</p>\n <div class=\"warning\">\n <strong>Details:</strong><br>\n Time: {{timestamp}}<br>\n IP Address: {{ipAddress}}<br>\n Device: {{userAgent}}\n </div>\n `,\n\n 'login-alert': `\n <h2>New Login Detected</h2>\n <p>Hi {{userName}},</p>\n <p>We detected a new login to your account.</p>\n <div class=\"warning\">\n <strong>Login Details:</strong><br>\n Time: {{timestamp}}<br>\n IP Address: {{ipAddress}}<br>\n Device: {{userAgent}}<br>\n Location: {{location}}\n </div>\n <p>If this was you, you can safely ignore this email.</p>\n <p>If you didn't log in, please change your password immediately and contact support.</p>\n `,\n\n 'account-suspended': `\n <h2>Account Suspended</h2>\n <p>Hi {{userName}},</p>\n <p>Your account has been suspended due to: {{reason}}</p>\n <p>If you believe this is a mistake, please contact our support team.</p>\n `,\n};\n\n// Compile templates\nconst compiledLayout = Handlebars.compile(baseLayout);\nconst compiledTemplates: Record<string, HandlebarsTemplateDelegate> = {};\n\nfor (const [name, template] of Object.entries(templates)) {\n compiledTemplates[name] = Handlebars.compile(template);\n}\n\nexport function renderTemplate(templateName: string, data: Record<string, unknown>): string {\n const template = compiledTemplates[templateName];\n\n if (!template) {\n throw new Error(`Template \"${templateName}\" not found`);\n }\n\n const body = template(data);\n\n return compiledLayout({\n ...data,\n body,\n year: new Date().getFullYear(),\n appName: data.appName || 'Servcraft',\n });\n}\n\nexport function renderCustomTemplate(htmlTemplate: string, data: Record<string, unknown>): string {\n const template = Handlebars.compile(htmlTemplate);\n const body = template(data);\n\n return compiledLayout({\n ...data,\n body,\n year: new Date().getFullYear(),\n appName: data.appName || 'Servcraft',\n });\n}\n\n// Register Handlebars helpers\nHandlebars.registerHelper('formatDate', (date: Date) => {\n return new Date(date).toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n });\n});\n\nHandlebars.registerHelper('eq', (a, b) => a === b);\nHandlebars.registerHelper('ne', (a, b) => a !== b);\n","/**\n * Audit Repository\n * Prisma-based persistence for audit logs\n */\nimport type { Prisma } from '@prisma/client';\nimport type { PrismaClient, AuditLog as PrismaAuditLog } from '@prisma/client';\nimport type { AuditLogEntry, AuditLogQuery } from './types.js';\nimport type { PaginatedResult, PaginationParams } from '../../types/index.js';\nimport { createPaginatedResult, getSkip } from '../../utils/pagination.js';\n\nexport interface AuditLogRecord extends AuditLogEntry {\n id: string;\n createdAt: Date;\n}\n\nexport class AuditRepository {\n constructor(private prisma: PrismaClient) {}\n\n /**\n * Create a new audit log entry\n */\n async create(entry: AuditLogEntry): Promise<AuditLogRecord> {\n const log = await this.prisma.auditLog.create({\n data: {\n userId: entry.userId,\n action: entry.action,\n resource: entry.resource,\n resourceId: entry.resourceId,\n oldValue: entry.oldValue as Prisma.InputJsonValue,\n newValue: entry.newValue as Prisma.InputJsonValue,\n ipAddress: entry.ipAddress,\n userAgent: entry.userAgent,\n metadata: entry.metadata as Prisma.InputJsonValue,\n },\n });\n\n return this.mapFromPrisma(log);\n }\n\n /**\n * Create multiple audit log entries\n */\n async createMany(entries: AuditLogEntry[]): Promise<number> {\n const result = await this.prisma.auditLog.createMany({\n data: entries.map((entry) => ({\n userId: entry.userId,\n action: entry.action,\n resource: entry.resource,\n resourceId: entry.resourceId,\n oldValue: entry.oldValue as Prisma.InputJsonValue,\n newValue: entry.newValue as Prisma.InputJsonValue,\n ipAddress: entry.ipAddress,\n userAgent: entry.userAgent,\n metadata: entry.metadata as Prisma.InputJsonValue,\n })),\n });\n\n return result.count;\n }\n\n /**\n * Find audit log by ID\n */\n async findById(id: string): Promise<AuditLogRecord | null> {\n const log = await this.prisma.auditLog.findUnique({\n where: { id },\n });\n\n return log ? this.mapFromPrisma(log) : null;\n }\n\n /**\n * Query audit logs with filters and pagination\n */\n async query(params: AuditLogQuery): Promise<PaginatedResult<AuditLogRecord>> {\n const { page = 1, limit = 20 } = params;\n const pagination: PaginationParams = { page, limit };\n\n const where: Prisma.AuditLogWhereInput = {};\n\n if (params.userId) where.userId = params.userId;\n if (params.action) where.action = params.action;\n if (params.resource) where.resource = params.resource;\n if (params.resourceId) where.resourceId = params.resourceId;\n\n if (params.startDate || params.endDate) {\n where.createdAt = {};\n if (params.startDate) where.createdAt.gte = params.startDate;\n if (params.endDate) where.createdAt.lte = params.endDate;\n }\n\n const [logs, total] = await Promise.all([\n this.prisma.auditLog.findMany({\n where,\n orderBy: { createdAt: 'desc' },\n skip: getSkip(pagination),\n take: limit,\n }),\n this.prisma.auditLog.count({ where }),\n ]);\n\n const data = logs.map((log) => this.mapFromPrisma(log));\n return createPaginatedResult(data, total, pagination);\n }\n\n /**\n * Find logs by user ID\n */\n async findByUser(userId: string, limit = 50): Promise<AuditLogRecord[]> {\n const logs = await this.prisma.auditLog.findMany({\n where: { userId },\n orderBy: { createdAt: 'desc' },\n take: limit,\n });\n\n return logs.map((log) => this.mapFromPrisma(log));\n }\n\n /**\n * Find logs by resource\n */\n async findByResource(\n resource: string,\n resourceId?: string,\n limit = 50\n ): Promise<AuditLogRecord[]> {\n const where: Prisma.AuditLogWhereInput = { resource };\n if (resourceId) where.resourceId = resourceId;\n\n const logs = await this.prisma.auditLog.findMany({\n where,\n orderBy: { createdAt: 'desc' },\n take: limit,\n });\n\n return logs.map((log) => this.mapFromPrisma(log));\n }\n\n /**\n * Find logs by action\n */\n async findByAction(action: string, limit = 50): Promise<AuditLogRecord[]> {\n const logs = await this.prisma.auditLog.findMany({\n where: { action },\n orderBy: { createdAt: 'desc' },\n take: limit,\n });\n\n return logs.map((log) => this.mapFromPrisma(log));\n }\n\n /**\n * Count logs with optional filters\n */\n async count(filters?: Partial<AuditLogQuery>): Promise<number> {\n const where: Prisma.AuditLogWhereInput = {};\n\n if (filters?.userId) where.userId = filters.userId;\n if (filters?.action) where.action = filters.action;\n if (filters?.resource) where.resource = filters.resource;\n\n return this.prisma.auditLog.count({ where });\n }\n\n /**\n * Delete old audit logs (for data retention)\n */\n async deleteOlderThan(days: number): Promise<number> {\n const cutoffDate = new Date();\n cutoffDate.setDate(cutoffDate.getDate() - days);\n\n const result = await this.prisma.auditLog.deleteMany({\n where: {\n createdAt: { lt: cutoffDate },\n },\n });\n\n return result.count;\n }\n\n /**\n * Clear all audit logs (for testing)\n */\n async clear(): Promise<void> {\n await this.prisma.auditLog.deleteMany();\n }\n\n /**\n * Map Prisma model to domain type\n */\n private mapFromPrisma(log: PrismaAuditLog): AuditLogRecord {\n return {\n id: log.id,\n userId: log.userId ?? undefined,\n action: log.action,\n resource: log.resource,\n resourceId: log.resourceId ?? undefined,\n oldValue: log.oldValue as Record<string, unknown> | undefined,\n newValue: log.newValue as Record<string, unknown> | undefined,\n ipAddress: log.ipAddress ?? undefined,\n userAgent: log.userAgent ?? undefined,\n metadata: log.metadata as Record<string, unknown> | undefined,\n createdAt: log.createdAt,\n };\n }\n}\n","import { logger } from '../../core/logger.js';\nimport type { AuditLogEntry, AuditLogQuery } from './types.js';\nimport type { PaginatedResult } from '../../types/index.js';\nimport { AuditRepository, type AuditLogRecord } from './audit.repository.js';\nimport { prisma } from '../../database/prisma.js';\n\nexport class AuditService {\n private repository: AuditRepository;\n\n constructor() {\n this.repository = new AuditRepository(prisma);\n }\n\n async log(entry: AuditLogEntry): Promise<void> {\n await this.repository.create(entry);\n\n // Also log to structured logger for real-time monitoring\n logger.info(\n {\n audit: true,\n userId: entry.userId,\n action: entry.action,\n resource: entry.resource,\n resourceId: entry.resourceId,\n ipAddress: entry.ipAddress,\n },\n `Audit: ${entry.action} on ${entry.resource}`\n );\n }\n\n async query(params: AuditLogQuery): Promise<PaginatedResult<AuditLogRecord>> {\n return this.repository.query(params);\n }\n\n async findByUser(userId: string, limit = 50): Promise<AuditLogRecord[]> {\n return this.repository.findByUser(userId, limit);\n }\n\n async findByResource(\n resource: string,\n resourceId: string,\n limit = 50\n ): Promise<AuditLogRecord[]> {\n return this.repository.findByResource(resource, resourceId, limit);\n }\n\n // Shortcut methods for common audit events\n async logCreate(\n resource: string,\n resourceId: string,\n userId?: string,\n newValue?: Record<string, unknown>,\n meta?: { ipAddress?: string; userAgent?: string }\n ): Promise<void> {\n await this.log({\n action: 'create',\n resource,\n resourceId,\n userId,\n newValue,\n ...meta,\n });\n }\n\n async logUpdate(\n resource: string,\n resourceId: string,\n userId?: string,\n oldValue?: Record<string, unknown>,\n newValue?: Record<string, unknown>,\n meta?: { ipAddress?: string; userAgent?: string }\n ): Promise<void> {\n await this.log({\n action: 'update',\n resource,\n resourceId,\n userId,\n oldValue,\n newValue,\n ...meta,\n });\n }\n\n async logDelete(\n resource: string,\n resourceId: string,\n userId?: string,\n oldValue?: Record<string, unknown>,\n meta?: { ipAddress?: string; userAgent?: string }\n ): Promise<void> {\n await this.log({\n action: 'delete',\n resource,\n resourceId,\n userId,\n oldValue,\n ...meta,\n });\n }\n\n async logLogin(userId: string, meta?: { ipAddress?: string; userAgent?: string }): Promise<void> {\n await this.log({\n action: 'login',\n resource: 'auth',\n userId,\n ...meta,\n });\n }\n\n async logLogout(\n userId: string,\n meta?: { ipAddress?: string; userAgent?: string }\n ): Promise<void> {\n await this.log({\n action: 'logout',\n resource: 'auth',\n userId,\n ...meta,\n });\n }\n\n async logPasswordChange(\n userId: string,\n meta?: { ipAddress?: string; userAgent?: string }\n ): Promise<void> {\n await this.log({\n action: 'password_change',\n resource: 'auth',\n userId,\n ...meta,\n });\n }\n\n // Data retention: delete old logs\n async cleanupOldLogs(retentionDays: number): Promise<number> {\n const count = await this.repository.deleteOlderThan(retentionDays);\n if (count > 0) {\n logger.info({ count, retentionDays }, 'Cleaned up old audit logs');\n }\n return count;\n }\n\n // Clear all logs (for testing)\n async clear(): Promise<void> {\n await this.repository.clear();\n }\n}\n\nlet auditService: AuditService | null = null;\n\nexport function getAuditService(): AuditService {\n if (!auditService) {\n auditService = new AuditService();\n }\n return auditService;\n}\n\nexport function createAuditService(): AuditService {\n return new AuditService();\n}\n","import { createServer } from './core/server.js';\nimport { logger } from './core/logger.js';\nimport { config } from './config/index.js';\nimport { registerSecurity, registerErrorHandler } from './middleware/index.js';\nimport { registerAuthModule } from './modules/auth/index.js';\n\nasync function bootstrap(): Promise<void> {\n // Create server instance\n const server = createServer({\n port: config.server.port,\n host: config.server.host,\n });\n\n const app = server.instance;\n\n // Register error handler\n registerErrorHandler(app);\n\n // Register security middleware\n await registerSecurity(app);\n\n // Register auth module\n await registerAuthModule(app);\n\n // Start server\n await server.start();\n\n logger.info(\n {\n env: config.env.NODE_ENV,\n port: config.server.port,\n },\n 'Servcraft server started'\n );\n}\n\nbootstrap().catch((err) => {\n logger.error({ err }, 'Failed to start server');\n process.exit(1);\n});\n\n// Export for library usage\nexport * from './core/index.js';\nexport * from './config/index.js';\nexport * from './middleware/index.js';\nexport * from './utils/index.js';\nexport * from './types/index.js';\nexport * from './modules/auth/index.js';\nexport * from './modules/user/index.js';\nexport * from './modules/email/index.js';\nexport * from './modules/validation/index.js';\nexport * from './modules/audit/index.js';\n"],"mappings":"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","names":["config","defaultConfig","config","error","error","error","error","z","z","error","z","z","error","config","prisma"]}
|