saas-backend-kit 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +205 -6
- package/dist/auth/index.js +2 -1
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/index.mjs +2 -1
- package/dist/auth/index.mjs.map +1 -1
- package/dist/config/index.js +1 -0
- package/dist/config/index.js.map +1 -1
- package/dist/config/index.mjs +1 -0
- package/dist/config/index.mjs.map +1 -1
- package/dist/index.js +124 -41
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +122 -42
- package/dist/index.mjs.map +1 -1
- package/dist/logger/index.js +1 -0
- package/dist/logger/index.js.map +1 -1
- package/dist/logger/index.mjs +1 -0
- package/dist/logger/index.mjs.map +1 -1
- package/dist/notifications/index.js +1 -0
- package/dist/notifications/index.js.map +1 -1
- package/dist/notifications/index.mjs +1 -0
- package/dist/notifications/index.mjs.map +1 -1
- package/dist/queue/index.js +1 -0
- package/dist/queue/index.js.map +1 -1
- package/dist/queue/index.mjs +1 -0
- package/dist/queue/index.mjs.map +1 -1
- package/dist/rate-limit/index.js +2 -0
- package/dist/rate-limit/index.js.map +1 -1
- package/dist/rate-limit/index.mjs +2 -0
- package/dist/rate-limit/index.mjs.map +1 -1
- package/dist/response/index.js +51 -40
- package/dist/response/index.js.map +1 -1
- package/dist/response/index.mjs +51 -40
- package/dist/response/index.mjs.map +1 -1
- package/dist/upload/index.js +1 -0
- package/dist/upload/index.js.map +1 -1
- package/dist/upload/index.mjs +1 -0
- package/dist/upload/index.mjs.map +1 -1
- package/examples/express/.env.example +4 -1
- package/jest-output.json +72 -0
- package/jest.config.js +19 -0
- package/package.json +10 -7
- package/src/auth/jwt.ts +1 -1
- package/src/config/index.ts +1 -0
- package/src/database/index.ts +102 -0
- package/src/index.ts +1 -0
- package/src/rate-limit/express.ts +1 -0
- package/src/response/index.ts +49 -40
- package/tests/auth.test.ts +134 -0
- package/tests/config.test.ts +36 -0
- package/tests/logger.test.ts +47 -0
- package/tests/notifications.test.ts +19 -0
- package/tests/rate-limit.test.ts +50 -0
- package/tests/upload.test.ts +33 -0
- package/tsconfig.test.json +14 -0
- package/tsup.config.ts +2 -1
package/dist/queue/index.mjs
CHANGED
|
@@ -7,6 +7,7 @@ var envSchema = z.object({
|
|
|
7
7
|
NODE_ENV: z.enum(["development", "production", "test"]).default("development"),
|
|
8
8
|
PORT: z.string().default("3000"),
|
|
9
9
|
DATABASE_URL: z.string().optional(),
|
|
10
|
+
MONGODB_URL: z.string().optional(),
|
|
10
11
|
REDIS_URL: z.string().default("redis://localhost:6379"),
|
|
11
12
|
JWT_SECRET: z.string().min(32).optional(),
|
|
12
13
|
JWT_EXPIRES_IN: z.string().default("7d"),
|
package/dist/queue/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/config/index.ts","../../src/logger/index.ts","../../src/queue/index.ts"],"names":["logger","queue"],"mappings":"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","file":"index.mjs","sourcesContent":["import { z } from 'zod';\n\nexport const envSchema = z.object({\n NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),\n PORT: z.string().default('3000'),\n DATABASE_URL: z.string().optional(),\n REDIS_URL: z.string().default('redis://localhost:6379'),\n JWT_SECRET: z.string().min(32).optional(),\n JWT_EXPIRES_IN: z.string().default('7d'),\n JWT_REFRESH_SECRET: z.string().min(32).optional(),\n JWT_REFRESH_EXPIRES_IN: z.string().default('30d'),\n GOOGLE_CLIENT_ID: z.string().optional(),\n GOOGLE_CLIENT_SECRET: z.string().optional(),\n GOOGLE_REDIRECT_URI: z.string().optional(),\n SMTP_HOST: z.string().optional(),\n SMTP_PORT: z.string().default('587'),\n SMTP_USER: z.string().optional(),\n SMTP_PASS: z.string().optional(),\n SMTP_FROM: z.string().optional(),\n TWILIO_ACCOUNT_SID: z.string().optional(),\n TWILIO_AUTH_TOKEN: z.string().optional(),\n TWILIO_PHONE_NUMBER: z.string().optional(),\n SLACK_WEBHOOK_URL: z.string().optional(),\n RATE_LIMIT_WINDOW: z.string().default('1m'),\n RATE_LIMIT_LIMIT: z.string().default('100'),\n LOG_LEVEL: z.enum(['fatal', 'error', 'warn', 'info', 'debug', 'trace']).default('info'),\n AWS_REGION: z.string().default('us-east-1'),\n AWS_ACCESS_KEY_ID: z.string().optional(),\n AWS_SECRET_ACCESS_KEY: z.string().optional(),\n AWS_S3_BUCKET: z.string().optional(),\n AWS_ENDPOINT: z.string().optional(),\n});\n\nexport type EnvConfig = z.infer<typeof envSchema>;\n\nexport interface ConfigOptions {\n schema?: z.ZodSchema;\n envPath?: string;\n validate?: boolean;\n}\n\nclass ConfigManager {\n private config: EnvConfig | null = null;\n private schema: z.ZodSchema;\n private validate: boolean;\n\n constructor(options: ConfigOptions = {}) {\n this.schema = options.schema || envSchema;\n this.validate = options.validate ?? true;\n }\n\n load(): EnvConfig {\n if (this.config) return this.config;\n\n const env: Record<string, string | undefined> = {};\n \n for (const key of Object.keys(this.schema.shape)) {\n env[key] = process.env[key];\n }\n\n if (this.validate) {\n const result = this.schema.safeParse(env);\n if (!result.success) {\n const errors = result.error.errors.map(e => `${e.path.join('.')}: ${e.message}`).join(', ');\n throw new Error(`Config validation failed: ${errors}`);\n }\n this.config = result.data;\n } else {\n this.config = env as EnvConfig;\n }\n\n return this.config;\n }\n\n get<K extends keyof EnvConfig>(key: K): EnvConfig[K] {\n if (!this.config) this.load();\n return this.config![key];\n }\n\n int(key: keyof EnvConfig): number {\n const value = this.get(key);\n if (typeof value === 'string') return parseInt(value, 10);\n return Number(value);\n }\n\n bool(key: keyof EnvConfig): boolean {\n const value = this.get(key);\n if (typeof value === 'boolean') return value;\n if (typeof value === 'string') return value.toLowerCase() === 'true';\n return Boolean(value);\n }\n\n isProduction(): boolean {\n return this.get('NODE_ENV') === 'production';\n }\n\n isDevelopment(): boolean {\n return this.get('NODE_ENV') === 'development';\n }\n\n isTest(): boolean {\n return this.get('NODE_ENV') === 'test';\n }\n\n getAll(): EnvConfig {\n if (!this.config) this.load();\n return this.config!;\n }\n}\n\nconst globalConfig = new ConfigManager();\n\nexport const config = {\n load: () => globalConfig.load(),\n get: <K extends keyof EnvConfig>(key: K) => globalConfig.get(key),\n int: (key: keyof EnvConfig) => globalConfig.int(key),\n bool: (key: keyof EnvConfig) => globalConfig.bool(key),\n isProduction: () => globalConfig.isProduction(),\n isDevelopment: () => globalConfig.isDevelopment(),\n isTest: () => globalConfig.isTest(),\n getAll: () => globalConfig.getAll(),\n create: (options?: ConfigOptions) => new ConfigManager(options),\n};\n\nexport default config;\n","import pino, { Logger, LoggerOptions, Bindings } from 'pino';\nimport { config } from '../config';\n\nexport type LogLevel = 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace';\n\nexport interface LoggerConfig extends Partial<LoggerOptions> {\n level?: LogLevel;\n name?: string;\n prettyPrint?: boolean;\n}\n\nexport interface RequestLoggerOptions {\n logLevel?: LogLevel;\n autoLogging?: boolean;\n}\n\nclass LoggerManager {\n private loggers: Map<string, Logger> = new Map();\n private defaultLogger: Logger;\n\n constructor() {\n const level = (config.get('LOG_LEVEL') as LogLevel) || 'info';\n this.defaultLogger = pino({\n level,\n name: 'saas-backend-kit',\n formatters: {\n bindings: (bindings: Bindings) => ({\n ...bindings,\n service: 'saas-backend-kit',\n }),\n },\n });\n }\n\n createLogger(options: LoggerConfig = {}): Logger {\n const name = options.name || 'default';\n \n if (this.loggers.has(name)) {\n return this.loggers.get(name)!;\n }\n\n const level = options.level || (config.get('LOG_LEVEL') as LogLevel) || 'info';\n \n const logger = pino({\n level,\n name: options.name,\n ...options,\n });\n\n this.loggers.set(name, logger);\n return logger;\n }\n\n getLogger(name?: string): Logger {\n if (name) {\n return this.loggers.get(name) || this.defaultLogger;\n }\n return this.defaultLogger;\n }\n\n child(bindings: Bindings, options?: { name?: string }): Logger {\n const name = options?.name || 'child';\n const parent = options?.name ? this.getLogger(name) : this.defaultLogger;\n return parent.child(bindings);\n }\n}\n\nconst loggerManager = new LoggerManager();\n\nexport const logger = {\n info: (message: string, ...args: unknown[]) => loggerManager.getLogger().info(message, ...args),\n warn: (message: string, ...args: unknown[]) => loggerManager.getLogger().warn(message, ...args),\n error: (message: string, ...args: unknown[]) => loggerManager.getLogger().error(message, ...args),\n debug: (message: string, ...args: unknown[]) => loggerManager.getLogger().debug(message, ...args),\n trace: (message: string, ...args: unknown[]) => loggerManager.getLogger().trace(message, ...args),\n fatal: (message: string, ...args: unknown[]) => loggerManager.getLogger().fatal(message, ...args),\n child: (bindings: Bindings, options?: { name?: string }) => loggerManager.child(bindings, options),\n create: (options?: LoggerConfig) => loggerManager.createLogger(options),\n get: (name?: string) => loggerManager.getLogger(name),\n};\n\nexport function createRequestLogger(options: RequestLoggerOptions = {}) {\n const logLevel = options.logLevel || 'info';\n const logger = loggerManager.getLogger('http');\n\n return function requestLogger(\n req: { method: string; url: string; headers: Record<string, string | string[] | undefined> },\n res: { statusCode: number; statusMessage?: string },\n elapsed: number\n ) {\n const log = logger.child({\n method: req.method,\n url: req.url,\n status: res.statusCode,\n responseTime: elapsed,\n ip: req.headers['x-forwarded-for'] || req.headers['x-real-ip'] || 'unknown',\n userAgent: req.headers['user-agent'],\n });\n\n if (res.statusCode >= 500) {\n log.error(`Request completed`);\n } else if (res.statusCode >= 400) {\n log.warn(`Request completed`);\n } else {\n log.info(`Request completed`);\n }\n };\n}\n\nexport default logger;\n","import { Queue, Worker, Job, JobsOptions, WorkerOptions } from 'bullmq';\nimport { config } from '../config';\nimport { logger } from '../logger';\n\nexport interface QueueOptions {\n name: string;\n defaultJobOptions?: JobsOptions;\n}\n\nexport interface RedisOptions {\n host?: string;\n port?: number;\n password?: string;\n db?: number;\n url?: string;\n}\n\nexport interface JobData {\n [key: string]: unknown;\n}\n\nexport type JobProcessor = (job: Job<JobData>) => Promise<unknown>;\n\nclass QueueManager {\n private queues: Map<string, Queue> = new Map();\n private workers: Map<string, Worker> = new Map();\n private redisOptions: RedisOptions;\n\n constructor() {\n const redisUrl = config.get('REDIS_URL');\n if (redisUrl) {\n this.redisOptions = { url: redisUrl };\n } else {\n this.redisOptions = {\n host: 'localhost',\n port: 6379,\n };\n }\n }\n\n setRedisOptions(options: RedisOptions): void {\n this.redisOptions = options;\n }\n\n createQueue(name: string, options?: Partial<QueueOptions>): Queue {\n if (this.queues.has(name)) {\n return this.queues.get(name)!;\n }\n\n const queue = new Queue(name, {\n connection: this.redisOptions as any,\n defaultJobOptions: options?.defaultJobOptions || {\n removeOnComplete: 100,\n removeOnFail: 100,\n },\n });\n\n this.queues.set(name, queue);\n logger.info(`Queue \"${name}\" created`);\n\n return queue;\n }\n\n getQueue(name: string): Queue | undefined {\n return this.queues.get(name);\n }\n\n async addJob(\n queueName: string,\n jobName: string,\n data: JobData,\n options?: JobsOptions\n ): Promise<Job> {\n const queue = this.getQueue(queueName) || this.createQueue(queueName);\n const job = await queue.add(jobName, data, options);\n logger.debug(`Job \"${jobName}\" added to queue \"${queueName}\"`, { jobId: job.id });\n return job;\n }\n\n async addBulkJobs(\n queueName: string,\n jobs: Array<{ name: string; data: JobData; options?: JobsOptions }>\n ): Promise<Job[]> {\n const queue = this.getQueue(queueName) || this.createQueue(queueName);\n const bulkJobs = jobs.map(job => ({\n name: job.name,\n data: job.data,\n ...job.options,\n }));\n const result = await queue.addBulk(bulkJobs);\n logger.debug(`${jobs.length} jobs added to queue \"${queueName}\"`);\n return result;\n }\n\n processJob(\n queueName: string,\n processor: JobProcessor,\n options?: WorkerOptions\n ): Worker {\n const queue = this.getQueue(queueName) || this.createQueue(queueName);\n \n const worker = new Worker(queueName, async (job) => {\n logger.debug(`Processing job \"${job.name}\"`, { jobId: job.id, queue: queueName });\n return await processor(job);\n }, {\n connection: this.redisOptions as any,\n concurrency: options?.concurrency || 1,\n ...options,\n });\n\n worker.on('completed', (job) => {\n logger.debug(`Job completed`, { jobId: job.id, queue: queueName });\n });\n\n worker.on('failed', (job, err) => {\n logger.error(`Job failed`, { jobId: job?.id, queue: queueName, error: err.message });\n });\n\n worker.on('error', (err) => {\n logger.error(`Worker error`, { queue: queueName, error: err.message });\n });\n\n this.workers.set(queueName, worker);\n logger.info(`Worker started for queue \"${queueName}\"`);\n\n return worker;\n }\n\n async getJobCounts(queueName: string): Promise<Record<string, number>> {\n const queue = this.getQueue(queueName);\n if (!queue) {\n return { waiting: 0, active: 0, completed: 0, failed: 0, delayed: 0 };\n }\n return await queue.getJobCounts();\n }\n\n async getJobs(queueName: string, start: number = 0, end: number = 10): Promise<Job[]> {\n const queue = this.getQueue(queueName);\n if (!queue) return [];\n return await queue.getJobs(['waiting', 'active', 'completed', 'failed'], start, end);\n }\n\n async closeQueue(name: string): Promise<void> {\n const queue = this.queues.get(name);\n if (queue) {\n await queue.close();\n this.queues.delete(name);\n logger.info(`Queue \"${name}\" closed`);\n }\n }\n\n async closeWorker(name: string): Promise<void> {\n const worker = this.workers.get(name);\n if (worker) {\n await worker.close();\n this.workers.delete(name);\n logger.info(`Worker for queue \"${name}\" closed`);\n }\n }\n\n async closeAll(): Promise<void> {\n await Promise.all([\n ...Array.from(this.queues.values()).map(q => q.close()),\n ...Array.from(this.workers.values()).map(w => w.close()),\n ]);\n this.queues.clear();\n this.workers.clear();\n logger.info('All queues and workers closed');\n }\n}\n\nconst queueManager = new QueueManager();\n\nexport const createQueue = (name: string, options?: Partial<QueueOptions>): Queue => {\n return queueManager.createQueue(name, options);\n};\n\nexport const addJob = (\n queueName: string,\n jobName: string,\n data: JobData,\n options?: JobsOptions\n): Promise<Job> => {\n return queueManager.addJob(queueName, jobName, data, options);\n};\n\nexport const processJob = (\n queueName: string,\n processor: JobProcessor,\n options?: WorkerOptions\n): Worker => {\n return queueManager.processJob(queueName, processor, options);\n};\n\nexport const queue = {\n create: createQueue,\n add: addJob,\n process: processJob,\n get: (name: string) => queueManager.getQueue(name),\n getJobCounts: (name: string) => queueManager.getJobCounts(name),\n getJobs: (name: string, start?: number, end?: number) => queueManager.getJobs(name, start, end),\n close: (name: string) => queueManager.closeQueue(name),\n closeAll: () => queueManager.closeAll(),\n setRedisOptions: (options: RedisOptions) => queueManager.setRedisOptions(options),\n};\n\nexport { QueueManager };\nexport default queue;\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/config/index.ts","../../src/logger/index.ts","../../src/queue/index.ts"],"names":["logger","queue"],"mappings":";;;;;AAEO,IAAM,SAAA,GAAY,EAAE,MAAA,CAAO;AAAA,EAChC,QAAA,EAAU,CAAA,CAAE,IAAA,CAAK,CAAC,aAAA,EAAe,cAAc,MAAM,CAAC,CAAA,CAAE,OAAA,CAAQ,aAAa,CAAA;AAAA,EAC7E,IAAA,EAAM,CAAA,CAAE,MAAA,EAAO,CAAE,QAAQ,MAAM,CAAA;AAAA,EAC/B,YAAA,EAAc,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAClC,WAAA,EAAa,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EACjC,SAAA,EAAW,CAAA,CAAE,MAAA,EAAO,CAAE,QAAQ,wBAAwB,CAAA;AAAA,EACtD,YAAY,CAAA,CAAE,MAAA,GAAS,GAAA,CAAI,EAAE,EAAE,QAAA,EAAS;AAAA,EACxC,cAAA,EAAgB,CAAA,CAAE,MAAA,EAAO,CAAE,QAAQ,IAAI,CAAA;AAAA,EACvC,oBAAoB,CAAA,CAAE,MAAA,GAAS,GAAA,CAAI,EAAE,EAAE,QAAA,EAAS;AAAA,EAChD,sBAAA,EAAwB,CAAA,CAAE,MAAA,EAAO,CAAE,QAAQ,KAAK,CAAA;AAAA,EAChD,gBAAA,EAAkB,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EACtC,oBAAA,EAAsB,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC1C,mBAAA,EAAqB,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EACzC,SAAA,EAAW,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC/B,SAAA,EAAW,CAAA,CAAE,MAAA,EAAO,CAAE,QAAQ,KAAK,CAAA;AAAA,EACnC,SAAA,EAAW,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC/B,SAAA,EAAW,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC/B,SAAA,EAAW,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC/B,kBAAA,EAAoB,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EACxC,iBAAA,EAAmB,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EACvC,mBAAA,EAAqB,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EACzC,iBAAA,EAAmB,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EACvC,iBAAA,EAAmB,CAAA,CAAE,MAAA,EAAO,CAAE,QAAQ,IAAI,CAAA;AAAA,EAC1C,gBAAA,EAAkB,CAAA,CAAE,MAAA,EAAO,CAAE,QAAQ,KAAK,CAAA;AAAA,EAC1C,SAAA,EAAW,CAAA,CAAE,IAAA,CAAK,CAAC,OAAA,EAAS,OAAA,EAAS,MAAA,EAAQ,MAAA,EAAQ,OAAA,EAAS,OAAO,CAAC,CAAA,CAAE,QAAQ,MAAM,CAAA;AAAA,EACtF,UAAA,EAAY,CAAA,CAAE,MAAA,EAAO,CAAE,QAAQ,WAAW,CAAA;AAAA,EAC1C,iBAAA,EAAmB,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EACvC,qBAAA,EAAuB,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC3C,aAAA,EAAe,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EACnC,YAAA,EAAc,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA;AAC3B,CAAC,CAAA;AAUD,IAAM,gBAAN,MAAoB;AAAA,EACV,MAAA,GAA2B,IAAA;AAAA,EAC3B,MAAA;AAAA,EACA,QAAA;AAAA,EAER,WAAA,CAAY,OAAA,GAAyB,EAAC,EAAG;AACvC,IAAA,IAAA,CAAK,MAAA,GAAS,QAAQ,MAAA,IAAU,SAAA;AAChC,IAAA,IAAA,CAAK,QAAA,GAAW,QAAQ,QAAA,IAAY,IAAA;AAAA,EACtC;AAAA,EAEA,IAAA,GAAkB;AAChB,IAAA,IAAI,IAAA,CAAK,MAAA,EAAQ,OAAO,IAAA,CAAK,MAAA;AAE7B,IAAA,MAAM,MAA0C,EAAC;AAEjD,IAAA,KAAA,MAAW,OAAO,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,KAAK,CAAA,EAAG;AAChD,MAAA,GAAA,CAAI,GAAG,CAAA,GAAI,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA;AAAA,IAC5B;AAEA,IAAA,IAAI,KAAK,QAAA,EAAU;AACjB,MAAA,MAAM,MAAA,GAAS,IAAA,CAAK,MAAA,CAAO,SAAA,CAAU,GAAG,CAAA;AACxC,MAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,QAAA,MAAM,SAAS,MAAA,CAAO,KAAA,CAAM,OAAO,GAAA,CAAI,CAAA,CAAA,KAAK,GAAG,CAAA,CAAE,IAAA,CAAK,IAAA,CAAK,GAAG,CAAC,CAAA,EAAA,EAAK,CAAA,CAAE,OAAO,CAAA,CAAE,CAAA,CAAE,KAAK,IAAI,CAAA;AAC1F,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,0BAAA,EAA6B,MAAM,CAAA,CAAE,CAAA;AAAA,MACvD;AACA,MAAA,IAAA,CAAK,SAAS,MAAA,CAAO,IAAA;AAAA,IACvB,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,MAAA,GAAS,GAAA;AAAA,IAChB;AAEA,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AAAA,EAEA,IAA+B,GAAA,EAAsB;AACnD,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,EAAQ,IAAA,CAAK,IAAA,EAAK;AAC5B,IAAA,OAAO,IAAA,CAAK,OAAQ,GAAG,CAAA;AAAA,EACzB;AAAA,EAEA,IAAI,GAAA,EAA8B;AAChC,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,GAAG,CAAA;AAC1B,IAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,QAAA,CAAS,OAAO,EAAE,CAAA;AACxD,IAAA,OAAO,OAAO,KAAK,CAAA;AAAA,EACrB;AAAA,EAEA,KAAK,GAAA,EAA+B;AAClC,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,GAAG,CAAA;AAC1B,IAAA,IAAI,OAAO,KAAA,KAAU,SAAA,EAAW,OAAO,KAAA;AACvC,IAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,KAAA,CAAM,aAAY,KAAM,MAAA;AAC9D,IAAA,OAAO,QAAQ,KAAK,CAAA;AAAA,EACtB;AAAA,EAEA,YAAA,GAAwB;AACtB,IAAA,OAAO,IAAA,CAAK,GAAA,CAAI,UAAU,CAAA,KAAM,YAAA;AAAA,EAClC;AAAA,EAEA,aAAA,GAAyB;AACvB,IAAA,OAAO,IAAA,CAAK,GAAA,CAAI,UAAU,CAAA,KAAM,aAAA;AAAA,EAClC;AAAA,EAEA,MAAA,GAAkB;AAChB,IAAA,OAAO,IAAA,CAAK,GAAA,CAAI,UAAU,CAAA,KAAM,MAAA;AAAA,EAClC;AAAA,EAEA,MAAA,GAAoB;AAClB,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,EAAQ,IAAA,CAAK,IAAA,EAAK;AAC5B,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AACF,CAAA;AAEA,IAAM,YAAA,GAAe,IAAI,aAAA,EAAc;AAEhC,IAAM,MAAA,GAAS;AAAA,EACpB,IAAA,EAAM,MAAM,YAAA,CAAa,IAAA,EAAK;AAAA,EAC9B,GAAA,EAAK,CAA4B,GAAA,KAAW,YAAA,CAAa,IAAI,GAAG,CAAA;AAAA,EAChE,GAAA,EAAK,CAAC,GAAA,KAAyB,YAAA,CAAa,IAAI,GAAG,CAAA;AAAA,EACnD,IAAA,EAAM,CAAC,GAAA,KAAyB,YAAA,CAAa,KAAK,GAAG,CAAA;AAAA,EACrD,YAAA,EAAc,MAAM,YAAA,CAAa,YAAA,EAAa;AAAA,EAC9C,aAAA,EAAe,MAAM,YAAA,CAAa,aAAA,EAAc;AAAA,EAChD,MAAA,EAAQ,MAAM,YAAA,CAAa,MAAA,EAAO;AAAA,EAClC,MAAA,EAAQ,MAAM,YAAA,CAAa,MAAA,EAAO;AAAA,EAClC,MAAA,EAAQ,CAAC,OAAA,KAA4B,IAAI,cAAc,OAAO;AAChE,CAAA;AC3GA,IAAM,gBAAN,MAAoB;AAAA,EACV,OAAA,uBAAmC,GAAA,EAAI;AAAA,EACvC,aAAA;AAAA,EAER,WAAA,GAAc;AACZ,IAAA,MAAM,KAAA,GAAS,MAAA,CAAO,GAAA,CAAI,WAAW,CAAA,IAAkB,MAAA;AACvD,IAAA,IAAA,CAAK,gBAAgB,IAAA,CAAK;AAAA,MACxB,KAAA;AAAA,MACA,IAAA,EAAM,kBAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,QAAA,EAAU,CAAC,QAAA,MAAwB;AAAA,UACjC,GAAG,QAAA;AAAA,UACH,OAAA,EAAS;AAAA,SACX;AAAA;AACF,KACD,CAAA;AAAA,EACH;AAAA,EAEA,YAAA,CAAa,OAAA,GAAwB,EAAC,EAAW;AAC/C,IAAA,MAAM,IAAA,GAAO,QAAQ,IAAA,IAAQ,SAAA;AAE7B,IAAA,IAAI,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,IAAI,CAAA,EAAG;AAC1B,MAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,IAAI,CAAA;AAAA,IAC9B;AAEA,IAAA,MAAM,QAAQ,OAAA,CAAQ,KAAA,IAAU,MAAA,CAAO,GAAA,CAAI,WAAW,CAAA,IAAkB,MAAA;AAExE,IAAA,MAAMA,UAAS,IAAA,CAAK;AAAA,MAClB,KAAA;AAAA,MACA,MAAM,OAAA,CAAQ,IAAA;AAAA,MACd,GAAG;AAAA,KACJ,CAAA;AAED,IAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,IAAA,EAAMA,OAAM,CAAA;AAC7B,IAAA,OAAOA,OAAAA;AAAA,EACT;AAAA,EAEA,UAAU,IAAA,EAAuB;AAC/B,IAAA,IAAI,IAAA,EAAM;AACR,MAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,IAAI,KAAK,IAAA,CAAK,aAAA;AAAA,IACxC;AACA,IAAA,OAAO,IAAA,CAAK,aAAA;AAAA,EACd;AAAA,EAEA,KAAA,CAAM,UAAoB,OAAA,EAAqC;AAC7D,IAAA,MAAM,IAAA,GAAO,SAAS,IAAA,IAAQ,OAAA;AAC9B,IAAA,MAAM,SAAS,OAAA,EAAS,IAAA,GAAO,KAAK,SAAA,CAAU,IAAI,IAAI,IAAA,CAAK,aAAA;AAC3D,IAAA,OAAO,MAAA,CAAO,MAAM,QAAQ,CAAA;AAAA,EAC9B;AACF,CAAA;AAEA,IAAM,aAAA,GAAgB,IAAI,aAAA,EAAc;AAEjC,IAAM,MAAA,GAAS;AAAA,EACpB,IAAA,EAAM,CAAC,OAAA,EAAA,GAAoB,IAAA,KAAoB,aAAA,CAAc,WAAU,CAAE,IAAA,CAAK,OAAA,EAAS,GAAG,IAAI,CAAA;AAAA,EAC9F,IAAA,EAAM,CAAC,OAAA,EAAA,GAAoB,IAAA,KAAoB,aAAA,CAAc,WAAU,CAAE,IAAA,CAAK,OAAA,EAAS,GAAG,IAAI,CAAA;AAAA,EAC9F,KAAA,EAAO,CAAC,OAAA,EAAA,GAAoB,IAAA,KAAoB,aAAA,CAAc,WAAU,CAAE,KAAA,CAAM,OAAA,EAAS,GAAG,IAAI,CAAA;AAAA,EAChG,KAAA,EAAO,CAAC,OAAA,EAAA,GAAoB,IAAA,KAAoB,aAAA,CAAc,WAAU,CAAE,KAAA,CAAM,OAAA,EAAS,GAAG,IAAI,CAAA;AAAA,EAChG,KAAA,EAAO,CAAC,OAAA,EAAA,GAAoB,IAAA,KAAoB,aAAA,CAAc,WAAU,CAAE,KAAA,CAAM,OAAA,EAAS,GAAG,IAAI,CAAA;AAAA,EAChG,KAAA,EAAO,CAAC,OAAA,EAAA,GAAoB,IAAA,KAAoB,aAAA,CAAc,WAAU,CAAE,KAAA,CAAM,OAAA,EAAS,GAAG,IAAI,CAAA;AAAA,EAChG,OAAO,CAAC,QAAA,EAAoB,YAAgC,aAAA,CAAc,KAAA,CAAM,UAAU,OAAO,CAAA;AAAA,EACjG,MAAA,EAAQ,CAAC,OAAA,KAA2B,aAAA,CAAc,aAAa,OAAO,CAAA;AAAA,EACtE,GAAA,EAAK,CAAC,IAAA,KAAkB,aAAA,CAAc,UAAU,IAAI;AACtD,CAAA;;;ACxDA,IAAM,eAAN,MAAmB;AAAA,EACT,MAAA,uBAAiC,GAAA,EAAI;AAAA,EACrC,OAAA,uBAAmC,GAAA,EAAI;AAAA,EACvC,YAAA;AAAA,EAER,WAAA,GAAc;AACZ,IAAA,MAAM,QAAA,GAAW,MAAA,CAAO,GAAA,CAAI,WAAW,CAAA;AACvC,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,IAAA,CAAK,YAAA,GAAe,EAAE,GAAA,EAAK,QAAA,EAAS;AAAA,IACtC,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,YAAA,GAAe;AAAA,QAClB,IAAA,EAAM,WAAA;AAAA,QACN,IAAA,EAAM;AAAA,OACR;AAAA,IACF;AAAA,EACF;AAAA,EAEA,gBAAgB,OAAA,EAA6B;AAC3C,IAAA,IAAA,CAAK,YAAA,GAAe,OAAA;AAAA,EACtB;AAAA,EAEA,WAAA,CAAY,MAAc,OAAA,EAAwC;AAChE,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,IAAI,CAAA,EAAG;AACzB,MAAA,OAAO,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,IAAI,CAAA;AAAA,IAC7B;AAEA,IAAA,MAAMC,MAAAA,GAAQ,IAAI,KAAA,CAAM,IAAA,EAAM;AAAA,MAC5B,YAAY,IAAA,CAAK,YAAA;AAAA,MACjB,iBAAA,EAAmB,SAAS,iBAAA,IAAqB;AAAA,QAC/C,gBAAA,EAAkB,GAAA;AAAA,QAClB,YAAA,EAAc;AAAA;AAChB,KACD,CAAA;AAED,IAAA,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,IAAA,EAAMA,MAAK,CAAA;AAC3B,IAAA,MAAA,CAAO,IAAA,CAAK,CAAA,OAAA,EAAU,IAAI,CAAA,SAAA,CAAW,CAAA;AAErC,IAAA,OAAOA,MAAAA;AAAA,EACT;AAAA,EAEA,SAAS,IAAA,EAAiC;AACxC,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,IAAI,CAAA;AAAA,EAC7B;AAAA,EAEA,MAAM,MAAA,CACJ,SAAA,EACA,OAAA,EACA,MACA,OAAA,EACc;AACd,IAAA,MAAMA,SAAQ,IAAA,CAAK,QAAA,CAAS,SAAS,CAAA,IAAK,IAAA,CAAK,YAAY,SAAS,CAAA;AACpE,IAAA,MAAM,MAAM,MAAMA,MAAAA,CAAM,GAAA,CAAI,OAAA,EAAS,MAAM,OAAO,CAAA;AAClD,IAAA,MAAA,CAAO,KAAA,CAAM,CAAA,KAAA,EAAQ,OAAO,CAAA,kBAAA,EAAqB,SAAS,KAAK,EAAE,KAAA,EAAO,GAAA,CAAI,EAAA,EAAI,CAAA;AAChF,IAAA,OAAO,GAAA;AAAA,EACT;AAAA,EAEA,MAAM,WAAA,CACJ,SAAA,EACA,IAAA,EACgB;AAChB,IAAA,MAAMA,SAAQ,IAAA,CAAK,QAAA,CAAS,SAAS,CAAA,IAAK,IAAA,CAAK,YAAY,SAAS,CAAA;AACpE,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,GAAA,CAAI,CAAA,GAAA,MAAQ;AAAA,MAChC,MAAM,GAAA,CAAI,IAAA;AAAA,MACV,MAAM,GAAA,CAAI,IAAA;AAAA,MACV,GAAG,GAAA,CAAI;AAAA,KACT,CAAE,CAAA;AACF,IAAA,MAAM,MAAA,GAAS,MAAMA,MAAAA,CAAM,OAAA,CAAQ,QAAQ,CAAA;AAC3C,IAAA,MAAA,CAAO,MAAM,CAAA,EAAG,IAAA,CAAK,MAAM,CAAA,sBAAA,EAAyB,SAAS,CAAA,CAAA,CAAG,CAAA;AAChE,IAAA,OAAO,MAAA;AAAA,EACT;AAAA,EAEA,UAAA,CACE,SAAA,EACA,SAAA,EACA,OAAA,EACQ;AACR,IAAc,IAAA,CAAK,QAAA,CAAS,SAAS,CAAA,IAAK,IAAA,CAAK,YAAY,SAAS;AAEpE,IAAA,MAAM,MAAA,GAAS,IAAI,MAAA,CAAO,SAAA,EAAW,OAAO,GAAA,KAAQ;AAClD,MAAA,MAAA,CAAO,KAAA,CAAM,CAAA,gBAAA,EAAmB,GAAA,CAAI,IAAI,CAAA,CAAA,CAAA,EAAK,EAAE,KAAA,EAAO,GAAA,CAAI,EAAA,EAAI,KAAA,EAAO,SAAA,EAAW,CAAA;AAChF,MAAA,OAAO,MAAM,UAAU,GAAG,CAAA;AAAA,IAC5B,CAAA,EAAG;AAAA,MACD,YAAY,IAAA,CAAK,YAAA;AAAA,MACjB,WAAA,EAAa,SAAS,WAAA,IAAe,CAAA;AAAA,MACrC,GAAG;AAAA,KACJ,CAAA;AAED,IAAA,MAAA,CAAO,EAAA,CAAG,WAAA,EAAa,CAAC,GAAA,KAAQ;AAC9B,MAAA,MAAA,CAAO,KAAA,CAAM,iBAAiB,EAAE,KAAA,EAAO,IAAI,EAAA,EAAI,KAAA,EAAO,WAAW,CAAA;AAAA,IACnE,CAAC,CAAA;AAED,IAAA,MAAA,CAAO,EAAA,CAAG,QAAA,EAAU,CAAC,GAAA,EAAK,GAAA,KAAQ;AAChC,MAAA,MAAA,CAAO,KAAA,CAAM,CAAA,UAAA,CAAA,EAAc,EAAE,KAAA,EAAO,GAAA,EAAK,EAAA,EAAI,KAAA,EAAO,SAAA,EAAW,KAAA,EAAO,GAAA,CAAI,OAAA,EAAS,CAAA;AAAA,IACrF,CAAC,CAAA;AAED,IAAA,MAAA,CAAO,EAAA,CAAG,OAAA,EAAS,CAAC,GAAA,KAAQ;AAC1B,MAAA,MAAA,CAAO,KAAA,CAAM,gBAAgB,EAAE,KAAA,EAAO,WAAW,KAAA,EAAO,GAAA,CAAI,SAAS,CAAA;AAAA,IACvE,CAAC,CAAA;AAED,IAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,SAAA,EAAW,MAAM,CAAA;AAClC,IAAA,MAAA,CAAO,IAAA,CAAK,CAAA,0BAAA,EAA6B,SAAS,CAAA,CAAA,CAAG,CAAA;AAErD,IAAA,OAAO,MAAA;AAAA,EACT;AAAA,EAEA,MAAM,aAAa,SAAA,EAAoD;AACrE,IAAA,MAAMA,MAAAA,GAAQ,IAAA,CAAK,QAAA,CAAS,SAAS,CAAA;AACrC,IAAA,IAAI,CAACA,MAAAA,EAAO;AACV,MAAA,OAAO,EAAE,OAAA,EAAS,CAAA,EAAG,MAAA,EAAQ,CAAA,EAAG,WAAW,CAAA,EAAG,MAAA,EAAQ,CAAA,EAAG,OAAA,EAAS,CAAA,EAAE;AAAA,IACtE;AACA,IAAA,OAAO,MAAMA,OAAM,YAAA,EAAa;AAAA,EAClC;AAAA,EAEA,MAAM,OAAA,CAAQ,SAAA,EAAmB,KAAA,GAAgB,CAAA,EAAG,MAAc,EAAA,EAAoB;AACpF,IAAA,MAAMA,MAAAA,GAAQ,IAAA,CAAK,QAAA,CAAS,SAAS,CAAA;AACrC,IAAA,IAAI,CAACA,MAAAA,EAAO,OAAO,EAAC;AACpB,IAAA,OAAO,MAAMA,MAAAA,CAAM,OAAA,CAAQ,CAAC,SAAA,EAAW,UAAU,WAAA,EAAa,QAAQ,CAAA,EAAG,KAAA,EAAO,GAAG,CAAA;AAAA,EACrF;AAAA,EAEA,MAAM,WAAW,IAAA,EAA6B;AAC5C,IAAA,MAAMA,MAAAA,GAAQ,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,IAAI,CAAA;AAClC,IAAA,IAAIA,MAAAA,EAAO;AACT,MAAA,MAAMA,OAAM,KAAA,EAAM;AAClB,MAAA,IAAA,CAAK,MAAA,CAAO,OAAO,IAAI,CAAA;AACvB,MAAA,MAAA,CAAO,IAAA,CAAK,CAAA,OAAA,EAAU,IAAI,CAAA,QAAA,CAAU,CAAA;AAAA,IACtC;AAAA,EACF;AAAA,EAEA,MAAM,YAAY,IAAA,EAA6B;AAC7C,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,IAAI,CAAA;AACpC,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,MAAM,OAAO,KAAA,EAAM;AACnB,MAAA,IAAA,CAAK,OAAA,CAAQ,OAAO,IAAI,CAAA;AACxB,MAAA,MAAA,CAAO,IAAA,CAAK,CAAA,kBAAA,EAAqB,IAAI,CAAA,QAAA,CAAU,CAAA;AAAA,IACjD;AAAA,EACF;AAAA,EAEA,MAAM,QAAA,GAA0B;AAC9B,IAAA,MAAM,QAAQ,GAAA,CAAI;AAAA,MAChB,GAAG,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,MAAA,EAAQ,CAAA,CAAE,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,KAAA,EAAO,CAAA;AAAA,MACtD,GAAG,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,CAAA,CAAE,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,KAAA,EAAO;AAAA,KACxD,CAAA;AACD,IAAA,IAAA,CAAK,OAAO,KAAA,EAAM;AAClB,IAAA,IAAA,CAAK,QAAQ,KAAA,EAAM;AACnB,IAAA,MAAA,CAAO,KAAK,+BAA+B,CAAA;AAAA,EAC7C;AACF;AAEA,IAAM,YAAA,GAAe,IAAI,YAAA,EAAa;AAE/B,IAAM,WAAA,GAAc,CAAC,IAAA,EAAc,OAAA,KAA2C;AACnF,EAAA,OAAO,YAAA,CAAa,WAAA,CAAY,IAAA,EAAM,OAAO,CAAA;AAC/C;AAEO,IAAM,MAAA,GAAS,CACpB,SAAA,EACA,OAAA,EACA,MACA,OAAA,KACiB;AACjB,EAAA,OAAO,YAAA,CAAa,MAAA,CAAO,SAAA,EAAW,OAAA,EAAS,MAAM,OAAO,CAAA;AAC9D;AAEO,IAAM,UAAA,GAAa,CACxB,SAAA,EACA,SAAA,EACA,OAAA,KACW;AACX,EAAA,OAAO,YAAA,CAAa,UAAA,CAAW,SAAA,EAAW,SAAA,EAAW,OAAO,CAAA;AAC9D;AAEO,IAAM,KAAA,GAAQ;AAAA,EACnB,MAAA,EAAQ,WAAA;AAAA,EACR,GAAA,EAAK,MAAA;AAAA,EACL,OAAA,EAAS,UAAA;AAAA,EACT,GAAA,EAAK,CAAC,IAAA,KAAiB,YAAA,CAAa,SAAS,IAAI,CAAA;AAAA,EACjD,YAAA,EAAc,CAAC,IAAA,KAAiB,YAAA,CAAa,aAAa,IAAI,CAAA;AAAA,EAC9D,OAAA,EAAS,CAAC,IAAA,EAAc,KAAA,EAAgB,QAAiB,YAAA,CAAa,OAAA,CAAQ,IAAA,EAAM,KAAA,EAAO,GAAG,CAAA;AAAA,EAC9F,KAAA,EAAO,CAAC,IAAA,KAAiB,YAAA,CAAa,WAAW,IAAI,CAAA;AAAA,EACrD,QAAA,EAAU,MAAM,YAAA,CAAa,QAAA,EAAS;AAAA,EACtC,eAAA,EAAiB,CAAC,OAAA,KAA0B,YAAA,CAAa,gBAAgB,OAAO;AAClF;AAGA,IAAO,aAAA,GAAQ","file":"index.mjs","sourcesContent":["import { z } from 'zod';\n\nexport const envSchema = z.object({\n NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),\n PORT: z.string().default('3000'),\n DATABASE_URL: z.string().optional(),\n MONGODB_URL: z.string().optional(),\n REDIS_URL: z.string().default('redis://localhost:6379'),\n JWT_SECRET: z.string().min(32).optional(),\n JWT_EXPIRES_IN: z.string().default('7d'),\n JWT_REFRESH_SECRET: z.string().min(32).optional(),\n JWT_REFRESH_EXPIRES_IN: z.string().default('30d'),\n GOOGLE_CLIENT_ID: z.string().optional(),\n GOOGLE_CLIENT_SECRET: z.string().optional(),\n GOOGLE_REDIRECT_URI: z.string().optional(),\n SMTP_HOST: z.string().optional(),\n SMTP_PORT: z.string().default('587'),\n SMTP_USER: z.string().optional(),\n SMTP_PASS: z.string().optional(),\n SMTP_FROM: z.string().optional(),\n TWILIO_ACCOUNT_SID: z.string().optional(),\n TWILIO_AUTH_TOKEN: z.string().optional(),\n TWILIO_PHONE_NUMBER: z.string().optional(),\n SLACK_WEBHOOK_URL: z.string().optional(),\n RATE_LIMIT_WINDOW: z.string().default('1m'),\n RATE_LIMIT_LIMIT: z.string().default('100'),\n LOG_LEVEL: z.enum(['fatal', 'error', 'warn', 'info', 'debug', 'trace']).default('info'),\n AWS_REGION: z.string().default('us-east-1'),\n AWS_ACCESS_KEY_ID: z.string().optional(),\n AWS_SECRET_ACCESS_KEY: z.string().optional(),\n AWS_S3_BUCKET: z.string().optional(),\n AWS_ENDPOINT: z.string().optional(),\n});\n\nexport type EnvConfig = z.infer<typeof envSchema>;\n\nexport interface ConfigOptions {\n schema?: z.ZodSchema;\n envPath?: string;\n validate?: boolean;\n}\n\nclass ConfigManager {\n private config: EnvConfig | null = null;\n private schema: z.ZodSchema;\n private validate: boolean;\n\n constructor(options: ConfigOptions = {}) {\n this.schema = options.schema || envSchema;\n this.validate = options.validate ?? true;\n }\n\n load(): EnvConfig {\n if (this.config) return this.config;\n\n const env: Record<string, string | undefined> = {};\n \n for (const key of Object.keys(this.schema.shape)) {\n env[key] = process.env[key];\n }\n\n if (this.validate) {\n const result = this.schema.safeParse(env);\n if (!result.success) {\n const errors = result.error.errors.map(e => `${e.path.join('.')}: ${e.message}`).join(', ');\n throw new Error(`Config validation failed: ${errors}`);\n }\n this.config = result.data;\n } else {\n this.config = env as EnvConfig;\n }\n\n return this.config;\n }\n\n get<K extends keyof EnvConfig>(key: K): EnvConfig[K] {\n if (!this.config) this.load();\n return this.config![key];\n }\n\n int(key: keyof EnvConfig): number {\n const value = this.get(key);\n if (typeof value === 'string') return parseInt(value, 10);\n return Number(value);\n }\n\n bool(key: keyof EnvConfig): boolean {\n const value = this.get(key);\n if (typeof value === 'boolean') return value;\n if (typeof value === 'string') return value.toLowerCase() === 'true';\n return Boolean(value);\n }\n\n isProduction(): boolean {\n return this.get('NODE_ENV') === 'production';\n }\n\n isDevelopment(): boolean {\n return this.get('NODE_ENV') === 'development';\n }\n\n isTest(): boolean {\n return this.get('NODE_ENV') === 'test';\n }\n\n getAll(): EnvConfig {\n if (!this.config) this.load();\n return this.config!;\n }\n}\n\nconst globalConfig = new ConfigManager();\n\nexport const config = {\n load: () => globalConfig.load(),\n get: <K extends keyof EnvConfig>(key: K) => globalConfig.get(key),\n int: (key: keyof EnvConfig) => globalConfig.int(key),\n bool: (key: keyof EnvConfig) => globalConfig.bool(key),\n isProduction: () => globalConfig.isProduction(),\n isDevelopment: () => globalConfig.isDevelopment(),\n isTest: () => globalConfig.isTest(),\n getAll: () => globalConfig.getAll(),\n create: (options?: ConfigOptions) => new ConfigManager(options),\n};\n\nexport default config;\n","import pino, { Logger, LoggerOptions, Bindings } from 'pino';\nimport { config } from '../config';\n\nexport type LogLevel = 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace';\n\nexport interface LoggerConfig extends Partial<LoggerOptions> {\n level?: LogLevel;\n name?: string;\n prettyPrint?: boolean;\n}\n\nexport interface RequestLoggerOptions {\n logLevel?: LogLevel;\n autoLogging?: boolean;\n}\n\nclass LoggerManager {\n private loggers: Map<string, Logger> = new Map();\n private defaultLogger: Logger;\n\n constructor() {\n const level = (config.get('LOG_LEVEL') as LogLevel) || 'info';\n this.defaultLogger = pino({\n level,\n name: 'saas-backend-kit',\n formatters: {\n bindings: (bindings: Bindings) => ({\n ...bindings,\n service: 'saas-backend-kit',\n }),\n },\n });\n }\n\n createLogger(options: LoggerConfig = {}): Logger {\n const name = options.name || 'default';\n \n if (this.loggers.has(name)) {\n return this.loggers.get(name)!;\n }\n\n const level = options.level || (config.get('LOG_LEVEL') as LogLevel) || 'info';\n \n const logger = pino({\n level,\n name: options.name,\n ...options,\n });\n\n this.loggers.set(name, logger);\n return logger;\n }\n\n getLogger(name?: string): Logger {\n if (name) {\n return this.loggers.get(name) || this.defaultLogger;\n }\n return this.defaultLogger;\n }\n\n child(bindings: Bindings, options?: { name?: string }): Logger {\n const name = options?.name || 'child';\n const parent = options?.name ? this.getLogger(name) : this.defaultLogger;\n return parent.child(bindings);\n }\n}\n\nconst loggerManager = new LoggerManager();\n\nexport const logger = {\n info: (message: string, ...args: unknown[]) => loggerManager.getLogger().info(message, ...args),\n warn: (message: string, ...args: unknown[]) => loggerManager.getLogger().warn(message, ...args),\n error: (message: string, ...args: unknown[]) => loggerManager.getLogger().error(message, ...args),\n debug: (message: string, ...args: unknown[]) => loggerManager.getLogger().debug(message, ...args),\n trace: (message: string, ...args: unknown[]) => loggerManager.getLogger().trace(message, ...args),\n fatal: (message: string, ...args: unknown[]) => loggerManager.getLogger().fatal(message, ...args),\n child: (bindings: Bindings, options?: { name?: string }) => loggerManager.child(bindings, options),\n create: (options?: LoggerConfig) => loggerManager.createLogger(options),\n get: (name?: string) => loggerManager.getLogger(name),\n};\n\nexport function createRequestLogger(options: RequestLoggerOptions = {}) {\n const logLevel = options.logLevel || 'info';\n const logger = loggerManager.getLogger('http');\n\n return function requestLogger(\n req: { method: string; url: string; headers: Record<string, string | string[] | undefined> },\n res: { statusCode: number; statusMessage?: string },\n elapsed: number\n ) {\n const log = logger.child({\n method: req.method,\n url: req.url,\n status: res.statusCode,\n responseTime: elapsed,\n ip: req.headers['x-forwarded-for'] || req.headers['x-real-ip'] || 'unknown',\n userAgent: req.headers['user-agent'],\n });\n\n if (res.statusCode >= 500) {\n log.error(`Request completed`);\n } else if (res.statusCode >= 400) {\n log.warn(`Request completed`);\n } else {\n log.info(`Request completed`);\n }\n };\n}\n\nexport default logger;\n","import { Queue, Worker, Job, JobsOptions, WorkerOptions } from 'bullmq';\nimport { config } from '../config';\nimport { logger } from '../logger';\n\nexport interface QueueOptions {\n name: string;\n defaultJobOptions?: JobsOptions;\n}\n\nexport interface RedisOptions {\n host?: string;\n port?: number;\n password?: string;\n db?: number;\n url?: string;\n}\n\nexport interface JobData {\n [key: string]: unknown;\n}\n\nexport type JobProcessor = (job: Job<JobData>) => Promise<unknown>;\n\nclass QueueManager {\n private queues: Map<string, Queue> = new Map();\n private workers: Map<string, Worker> = new Map();\n private redisOptions: RedisOptions;\n\n constructor() {\n const redisUrl = config.get('REDIS_URL');\n if (redisUrl) {\n this.redisOptions = { url: redisUrl };\n } else {\n this.redisOptions = {\n host: 'localhost',\n port: 6379,\n };\n }\n }\n\n setRedisOptions(options: RedisOptions): void {\n this.redisOptions = options;\n }\n\n createQueue(name: string, options?: Partial<QueueOptions>): Queue {\n if (this.queues.has(name)) {\n return this.queues.get(name)!;\n }\n\n const queue = new Queue(name, {\n connection: this.redisOptions as any,\n defaultJobOptions: options?.defaultJobOptions || {\n removeOnComplete: 100,\n removeOnFail: 100,\n },\n });\n\n this.queues.set(name, queue);\n logger.info(`Queue \"${name}\" created`);\n\n return queue;\n }\n\n getQueue(name: string): Queue | undefined {\n return this.queues.get(name);\n }\n\n async addJob(\n queueName: string,\n jobName: string,\n data: JobData,\n options?: JobsOptions\n ): Promise<Job> {\n const queue = this.getQueue(queueName) || this.createQueue(queueName);\n const job = await queue.add(jobName, data, options);\n logger.debug(`Job \"${jobName}\" added to queue \"${queueName}\"`, { jobId: job.id });\n return job;\n }\n\n async addBulkJobs(\n queueName: string,\n jobs: Array<{ name: string; data: JobData; options?: JobsOptions }>\n ): Promise<Job[]> {\n const queue = this.getQueue(queueName) || this.createQueue(queueName);\n const bulkJobs = jobs.map(job => ({\n name: job.name,\n data: job.data,\n ...job.options,\n }));\n const result = await queue.addBulk(bulkJobs);\n logger.debug(`${jobs.length} jobs added to queue \"${queueName}\"`);\n return result;\n }\n\n processJob(\n queueName: string,\n processor: JobProcessor,\n options?: WorkerOptions\n ): Worker {\n const queue = this.getQueue(queueName) || this.createQueue(queueName);\n \n const worker = new Worker(queueName, async (job) => {\n logger.debug(`Processing job \"${job.name}\"`, { jobId: job.id, queue: queueName });\n return await processor(job);\n }, {\n connection: this.redisOptions as any,\n concurrency: options?.concurrency || 1,\n ...options,\n });\n\n worker.on('completed', (job) => {\n logger.debug(`Job completed`, { jobId: job.id, queue: queueName });\n });\n\n worker.on('failed', (job, err) => {\n logger.error(`Job failed`, { jobId: job?.id, queue: queueName, error: err.message });\n });\n\n worker.on('error', (err) => {\n logger.error(`Worker error`, { queue: queueName, error: err.message });\n });\n\n this.workers.set(queueName, worker);\n logger.info(`Worker started for queue \"${queueName}\"`);\n\n return worker;\n }\n\n async getJobCounts(queueName: string): Promise<Record<string, number>> {\n const queue = this.getQueue(queueName);\n if (!queue) {\n return { waiting: 0, active: 0, completed: 0, failed: 0, delayed: 0 };\n }\n return await queue.getJobCounts();\n }\n\n async getJobs(queueName: string, start: number = 0, end: number = 10): Promise<Job[]> {\n const queue = this.getQueue(queueName);\n if (!queue) return [];\n return await queue.getJobs(['waiting', 'active', 'completed', 'failed'], start, end);\n }\n\n async closeQueue(name: string): Promise<void> {\n const queue = this.queues.get(name);\n if (queue) {\n await queue.close();\n this.queues.delete(name);\n logger.info(`Queue \"${name}\" closed`);\n }\n }\n\n async closeWorker(name: string): Promise<void> {\n const worker = this.workers.get(name);\n if (worker) {\n await worker.close();\n this.workers.delete(name);\n logger.info(`Worker for queue \"${name}\" closed`);\n }\n }\n\n async closeAll(): Promise<void> {\n await Promise.all([\n ...Array.from(this.queues.values()).map(q => q.close()),\n ...Array.from(this.workers.values()).map(w => w.close()),\n ]);\n this.queues.clear();\n this.workers.clear();\n logger.info('All queues and workers closed');\n }\n}\n\nconst queueManager = new QueueManager();\n\nexport const createQueue = (name: string, options?: Partial<QueueOptions>): Queue => {\n return queueManager.createQueue(name, options);\n};\n\nexport const addJob = (\n queueName: string,\n jobName: string,\n data: JobData,\n options?: JobsOptions\n): Promise<Job> => {\n return queueManager.addJob(queueName, jobName, data, options);\n};\n\nexport const processJob = (\n queueName: string,\n processor: JobProcessor,\n options?: WorkerOptions\n): Worker => {\n return queueManager.processJob(queueName, processor, options);\n};\n\nexport const queue = {\n create: createQueue,\n add: addJob,\n process: processJob,\n get: (name: string) => queueManager.getQueue(name),\n getJobCounts: (name: string) => queueManager.getJobCounts(name),\n getJobs: (name: string, start?: number, end?: number) => queueManager.getJobs(name, start, end),\n close: (name: string) => queueManager.closeQueue(name),\n closeAll: () => queueManager.closeAll(),\n setRedisOptions: (options: RedisOptions) => queueManager.setRedisOptions(options),\n};\n\nexport { QueueManager };\nexport default queue;\n"]}
|
package/dist/rate-limit/index.js
CHANGED
|
@@ -29,6 +29,7 @@ var init_config = __esm({
|
|
|
29
29
|
NODE_ENV: zod.z.enum(["development", "production", "test"]).default("development"),
|
|
30
30
|
PORT: zod.z.string().default("3000"),
|
|
31
31
|
DATABASE_URL: zod.z.string().optional(),
|
|
32
|
+
MONGODB_URL: zod.z.string().optional(),
|
|
32
33
|
REDIS_URL: zod.z.string().default("redis://localhost:6379"),
|
|
33
34
|
JWT_SECRET: zod.z.string().min(32).optional(),
|
|
34
35
|
JWT_EXPIRES_IN: zod.z.string().default("7d"),
|
|
@@ -148,6 +149,7 @@ var init_express = __esm({
|
|
|
148
149
|
cleanupInterval;
|
|
149
150
|
constructor() {
|
|
150
151
|
this.cleanupInterval = setInterval(() => this.cleanup(), 6e4);
|
|
152
|
+
this.cleanupInterval.unref();
|
|
151
153
|
}
|
|
152
154
|
cleanup() {
|
|
153
155
|
const now = Date.now();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/config/index.ts","../../src/rate-limit/express.ts","../../src/rate-limit/index.ts","../../src/rate-limit/fastify.ts"],"names":["z"],"mappings":"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","file":"index.js","sourcesContent":["import { z } from 'zod';\n\nexport const envSchema = z.object({\n NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),\n PORT: z.string().default('3000'),\n DATABASE_URL: z.string().optional(),\n REDIS_URL: z.string().default('redis://localhost:6379'),\n JWT_SECRET: z.string().min(32).optional(),\n JWT_EXPIRES_IN: z.string().default('7d'),\n JWT_REFRESH_SECRET: z.string().min(32).optional(),\n JWT_REFRESH_EXPIRES_IN: z.string().default('30d'),\n GOOGLE_CLIENT_ID: z.string().optional(),\n GOOGLE_CLIENT_SECRET: z.string().optional(),\n GOOGLE_REDIRECT_URI: z.string().optional(),\n SMTP_HOST: z.string().optional(),\n SMTP_PORT: z.string().default('587'),\n SMTP_USER: z.string().optional(),\n SMTP_PASS: z.string().optional(),\n SMTP_FROM: z.string().optional(),\n TWILIO_ACCOUNT_SID: z.string().optional(),\n TWILIO_AUTH_TOKEN: z.string().optional(),\n TWILIO_PHONE_NUMBER: z.string().optional(),\n SLACK_WEBHOOK_URL: z.string().optional(),\n RATE_LIMIT_WINDOW: z.string().default('1m'),\n RATE_LIMIT_LIMIT: z.string().default('100'),\n LOG_LEVEL: z.enum(['fatal', 'error', 'warn', 'info', 'debug', 'trace']).default('info'),\n AWS_REGION: z.string().default('us-east-1'),\n AWS_ACCESS_KEY_ID: z.string().optional(),\n AWS_SECRET_ACCESS_KEY: z.string().optional(),\n AWS_S3_BUCKET: z.string().optional(),\n AWS_ENDPOINT: z.string().optional(),\n});\n\nexport type EnvConfig = z.infer<typeof envSchema>;\n\nexport interface ConfigOptions {\n schema?: z.ZodSchema;\n envPath?: string;\n validate?: boolean;\n}\n\nclass ConfigManager {\n private config: EnvConfig | null = null;\n private schema: z.ZodSchema;\n private validate: boolean;\n\n constructor(options: ConfigOptions = {}) {\n this.schema = options.schema || envSchema;\n this.validate = options.validate ?? true;\n }\n\n load(): EnvConfig {\n if (this.config) return this.config;\n\n const env: Record<string, string | undefined> = {};\n \n for (const key of Object.keys(this.schema.shape)) {\n env[key] = process.env[key];\n }\n\n if (this.validate) {\n const result = this.schema.safeParse(env);\n if (!result.success) {\n const errors = result.error.errors.map(e => `${e.path.join('.')}: ${e.message}`).join(', ');\n throw new Error(`Config validation failed: ${errors}`);\n }\n this.config = result.data;\n } else {\n this.config = env as EnvConfig;\n }\n\n return this.config;\n }\n\n get<K extends keyof EnvConfig>(key: K): EnvConfig[K] {\n if (!this.config) this.load();\n return this.config![key];\n }\n\n int(key: keyof EnvConfig): number {\n const value = this.get(key);\n if (typeof value === 'string') return parseInt(value, 10);\n return Number(value);\n }\n\n bool(key: keyof EnvConfig): boolean {\n const value = this.get(key);\n if (typeof value === 'boolean') return value;\n if (typeof value === 'string') return value.toLowerCase() === 'true';\n return Boolean(value);\n }\n\n isProduction(): boolean {\n return this.get('NODE_ENV') === 'production';\n }\n\n isDevelopment(): boolean {\n return this.get('NODE_ENV') === 'development';\n }\n\n isTest(): boolean {\n return this.get('NODE_ENV') === 'test';\n }\n\n getAll(): EnvConfig {\n if (!this.config) this.load();\n return this.config!;\n }\n}\n\nconst globalConfig = new ConfigManager();\n\nexport const config = {\n load: () => globalConfig.load(),\n get: <K extends keyof EnvConfig>(key: K) => globalConfig.get(key),\n int: (key: keyof EnvConfig) => globalConfig.int(key),\n bool: (key: keyof EnvConfig) => globalConfig.bool(key),\n isProduction: () => globalConfig.isProduction(),\n isDevelopment: () => globalConfig.isDevelopment(),\n isTest: () => globalConfig.isTest(),\n getAll: () => globalConfig.getAll(),\n create: (options?: ConfigOptions) => new ConfigManager(options),\n};\n\nexport default config;\n","import { Request, Response, NextFunction, RequestHandler } from 'express';\nimport { config } from '../config';\n\nexport interface RateLimitOptions {\n window?: string;\n limit?: number;\n keyGenerator?: (req: Request) => string;\n handler?: (req: Request, res: Response) => void;\n skipSuccessfulRequests?: boolean;\n skipFailedRequests?: boolean;\n skip?: (req: Request) => boolean;\n}\n\ninterface RateLimitRecord {\n count: number;\n resetTime: number;\n}\n\nclass InMemoryRateLimiter {\n private store: Map<string, RateLimitRecord> = new Map();\n private cleanupInterval: NodeJS.Timeout;\n\n constructor() {\n this.cleanupInterval = setInterval(() => this.cleanup(), 60000);\n }\n\n private cleanup(): void {\n const now = Date.now();\n for (const [key, record] of this.store.entries()) {\n if (record.resetTime < now) {\n this.store.delete(key);\n }\n }\n }\n\n increment(key: string, windowMs: number): RateLimitRecord {\n const now = Date.now();\n const record = this.store.get(key);\n\n if (!record || record.resetTime < now) {\n const resetTime = now + windowMs;\n this.store.set(key, { count: 1, resetTime });\n return { count: 1, resetTime };\n }\n\n record.count++;\n return record;\n }\n\n get(key: string): RateLimitRecord | undefined {\n return this.store.get(key);\n }\n\n destroy(): void {\n clearInterval(this.cleanupInterval);\n }\n}\n\nclass RateLimiter {\n private options: Required<RateLimitOptions>;\n private store: InMemoryRateLimiter;\n\n constructor(options: RateLimitOptions = {}) {\n const defaultWindow = config.get('RATE_LIMIT_WINDOW') || '1m';\n const defaultLimit = parseInt(config.get('RATE_LIMIT_LIMIT') || '100', 10);\n\n this.options = {\n window: options.window || defaultWindow,\n limit: options.limit || defaultLimit,\n keyGenerator: options.keyGenerator || ((req: Request) => req.ip || 'unknown'),\n handler: options.handler || this.defaultHandler,\n skipSuccessfulRequests: options.skipSuccessfulRequests || false,\n skipFailedRequests: options.skipFailedRequests || false,\n skip: options.skip || (() => false),\n };\n\n this.store = new InMemoryRateLimiter();\n }\n\n private getWindowMs(): number {\n const window = this.options.window;\n const match = window.match(/^(\\d+)(s|m|h|d)$/);\n if (!match) return 60000;\n\n const value = parseInt(match[1], 10);\n const unit = match[2];\n\n switch (unit) {\n case 's': return value * 1000;\n case 'm': return value * 60 * 1000;\n case 'h': return value * 60 * 60 * 1000;\n case 'd': return value * 24 * 60 * 60 * 1000;\n default: return 60000;\n }\n }\n\n private defaultHandler(req: Request, res: Response): void {\n res.status(429).json({\n error: 'Too many requests',\n message: `Rate limit exceeded. Please try again later.`,\n });\n }\n\n middleware(): RequestHandler {\n const windowMs = this.getWindowMs();\n\n return (req: Request, res: Response, next: NextFunction) => {\n if (this.options.skip(req)) {\n return next();\n }\n\n const key = this.options.keyGenerator(req);\n const record = this.store.increment(key, windowMs);\n\n const remaining = Math.max(0, this.options.limit - record.count);\n const resetTime = new Date(record.resetTime);\n\n res.setHeader('X-RateLimit-Limit', this.options.limit);\n res.setHeader('X-RateLimit-Remaining', remaining);\n res.setHeader('X-RateLimit-Reset', Math.ceil(record.resetTime / 1000));\n\n if (record.count > this.options.limit) {\n return this.options.handler(req, res);\n }\n\n next();\n };\n }\n\n destroy(): void {\n this.store.destroy();\n }\n}\n\nexport function rateLimit(options: RateLimitOptions = {}): RequestHandler {\n const limiter = new RateLimiter(options);\n return limiter.middleware();\n}\n\nexport function createRateLimiter(options: RateLimitOptions): RateLimiter {\n return new RateLimiter(options);\n}\n\nexport default rateLimit;\n","export * from './express';\nexport * from './fastify';\n","import { FastifyInstance, FastifyRequest, FastifyReply, HookHandlerDoneFunction } from 'fastify';\nimport { RateLimitOptions, InMemoryRateLimiter } from './express';\n\nexport function registerRateLimitPlugin(fastify: FastifyInstance, options: RateLimitOptions = {}, done: HookHandlerDoneFunction) {\n const limiter = new (require('./express').createRateLimiter.constructor)(options);\n \n fastify.addHook('onRequest', async (request: FastifyRequest, reply: FastifyReply) => {\n const key = options.keyGenerator \n ? options.keyGenerator(request.raw as any)\n : request.ip || 'unknown';\n \n const windowMs = parseWindowMs(options.window || '1m');\n const record = (limiter as any).store.increment(key, windowMs);\n const limit = options.limit || 100;\n const remaining = Math.max(0, limit - record.count);\n\n reply.header('X-RateLimit-Limit', limit);\n reply.header('X-RateLimit-Remaining', remaining);\n reply.header('X-RateLimit-Reset', Math.ceil(record.resetTime / 1000));\n\n if (record.count > limit) {\n reply.status(429).send({\n error: 'Too many requests',\n message: 'Rate limit exceeded. Please try again later.',\n });\n return reply;\n }\n });\n\n done();\n}\n\nfunction parseWindowMs(window: string): number {\n const match = window.match(/^(\\d+)(s|m|h|d)$/);\n if (!match) return 60000;\n\n const value = parseInt(match[1], 10);\n const unit = match[2];\n\n switch (unit) {\n case 's': return value * 1000;\n case 'm': return value * 60 * 1000;\n case 'h': return value * 60 * 60 * 1000;\n case 'd': return value * 24 * 60 * 60 * 1000;\n default: return 60000;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/config/index.ts","../../src/rate-limit/express.ts","../../src/rate-limit/index.ts","../../src/rate-limit/fastify.ts"],"names":["z"],"mappings":"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","file":"index.js","sourcesContent":["import { z } from 'zod';\n\nexport const envSchema = z.object({\n NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),\n PORT: z.string().default('3000'),\n DATABASE_URL: z.string().optional(),\n MONGODB_URL: z.string().optional(),\n REDIS_URL: z.string().default('redis://localhost:6379'),\n JWT_SECRET: z.string().min(32).optional(),\n JWT_EXPIRES_IN: z.string().default('7d'),\n JWT_REFRESH_SECRET: z.string().min(32).optional(),\n JWT_REFRESH_EXPIRES_IN: z.string().default('30d'),\n GOOGLE_CLIENT_ID: z.string().optional(),\n GOOGLE_CLIENT_SECRET: z.string().optional(),\n GOOGLE_REDIRECT_URI: z.string().optional(),\n SMTP_HOST: z.string().optional(),\n SMTP_PORT: z.string().default('587'),\n SMTP_USER: z.string().optional(),\n SMTP_PASS: z.string().optional(),\n SMTP_FROM: z.string().optional(),\n TWILIO_ACCOUNT_SID: z.string().optional(),\n TWILIO_AUTH_TOKEN: z.string().optional(),\n TWILIO_PHONE_NUMBER: z.string().optional(),\n SLACK_WEBHOOK_URL: z.string().optional(),\n RATE_LIMIT_WINDOW: z.string().default('1m'),\n RATE_LIMIT_LIMIT: z.string().default('100'),\n LOG_LEVEL: z.enum(['fatal', 'error', 'warn', 'info', 'debug', 'trace']).default('info'),\n AWS_REGION: z.string().default('us-east-1'),\n AWS_ACCESS_KEY_ID: z.string().optional(),\n AWS_SECRET_ACCESS_KEY: z.string().optional(),\n AWS_S3_BUCKET: z.string().optional(),\n AWS_ENDPOINT: z.string().optional(),\n});\n\nexport type EnvConfig = z.infer<typeof envSchema>;\n\nexport interface ConfigOptions {\n schema?: z.ZodSchema;\n envPath?: string;\n validate?: boolean;\n}\n\nclass ConfigManager {\n private config: EnvConfig | null = null;\n private schema: z.ZodSchema;\n private validate: boolean;\n\n constructor(options: ConfigOptions = {}) {\n this.schema = options.schema || envSchema;\n this.validate = options.validate ?? true;\n }\n\n load(): EnvConfig {\n if (this.config) return this.config;\n\n const env: Record<string, string | undefined> = {};\n \n for (const key of Object.keys(this.schema.shape)) {\n env[key] = process.env[key];\n }\n\n if (this.validate) {\n const result = this.schema.safeParse(env);\n if (!result.success) {\n const errors = result.error.errors.map(e => `${e.path.join('.')}: ${e.message}`).join(', ');\n throw new Error(`Config validation failed: ${errors}`);\n }\n this.config = result.data;\n } else {\n this.config = env as EnvConfig;\n }\n\n return this.config;\n }\n\n get<K extends keyof EnvConfig>(key: K): EnvConfig[K] {\n if (!this.config) this.load();\n return this.config![key];\n }\n\n int(key: keyof EnvConfig): number {\n const value = this.get(key);\n if (typeof value === 'string') return parseInt(value, 10);\n return Number(value);\n }\n\n bool(key: keyof EnvConfig): boolean {\n const value = this.get(key);\n if (typeof value === 'boolean') return value;\n if (typeof value === 'string') return value.toLowerCase() === 'true';\n return Boolean(value);\n }\n\n isProduction(): boolean {\n return this.get('NODE_ENV') === 'production';\n }\n\n isDevelopment(): boolean {\n return this.get('NODE_ENV') === 'development';\n }\n\n isTest(): boolean {\n return this.get('NODE_ENV') === 'test';\n }\n\n getAll(): EnvConfig {\n if (!this.config) this.load();\n return this.config!;\n }\n}\n\nconst globalConfig = new ConfigManager();\n\nexport const config = {\n load: () => globalConfig.load(),\n get: <K extends keyof EnvConfig>(key: K) => globalConfig.get(key),\n int: (key: keyof EnvConfig) => globalConfig.int(key),\n bool: (key: keyof EnvConfig) => globalConfig.bool(key),\n isProduction: () => globalConfig.isProduction(),\n isDevelopment: () => globalConfig.isDevelopment(),\n isTest: () => globalConfig.isTest(),\n getAll: () => globalConfig.getAll(),\n create: (options?: ConfigOptions) => new ConfigManager(options),\n};\n\nexport default config;\n","import { Request, Response, NextFunction, RequestHandler } from 'express';\nimport { config } from '../config';\n\nexport interface RateLimitOptions {\n window?: string;\n limit?: number;\n keyGenerator?: (req: Request) => string;\n handler?: (req: Request, res: Response) => void;\n skipSuccessfulRequests?: boolean;\n skipFailedRequests?: boolean;\n skip?: (req: Request) => boolean;\n}\n\ninterface RateLimitRecord {\n count: number;\n resetTime: number;\n}\n\nclass InMemoryRateLimiter {\n private store: Map<string, RateLimitRecord> = new Map();\n private cleanupInterval: NodeJS.Timeout;\n\n constructor() {\n this.cleanupInterval = setInterval(() => this.cleanup(), 60000);\n this.cleanupInterval.unref();\n }\n\n private cleanup(): void {\n const now = Date.now();\n for (const [key, record] of this.store.entries()) {\n if (record.resetTime < now) {\n this.store.delete(key);\n }\n }\n }\n\n increment(key: string, windowMs: number): RateLimitRecord {\n const now = Date.now();\n const record = this.store.get(key);\n\n if (!record || record.resetTime < now) {\n const resetTime = now + windowMs;\n this.store.set(key, { count: 1, resetTime });\n return { count: 1, resetTime };\n }\n\n record.count++;\n return record;\n }\n\n get(key: string): RateLimitRecord | undefined {\n return this.store.get(key);\n }\n\n destroy(): void {\n clearInterval(this.cleanupInterval);\n }\n}\n\nclass RateLimiter {\n private options: Required<RateLimitOptions>;\n private store: InMemoryRateLimiter;\n\n constructor(options: RateLimitOptions = {}) {\n const defaultWindow = config.get('RATE_LIMIT_WINDOW') || '1m';\n const defaultLimit = parseInt(config.get('RATE_LIMIT_LIMIT') || '100', 10);\n\n this.options = {\n window: options.window || defaultWindow,\n limit: options.limit || defaultLimit,\n keyGenerator: options.keyGenerator || ((req: Request) => req.ip || 'unknown'),\n handler: options.handler || this.defaultHandler,\n skipSuccessfulRequests: options.skipSuccessfulRequests || false,\n skipFailedRequests: options.skipFailedRequests || false,\n skip: options.skip || (() => false),\n };\n\n this.store = new InMemoryRateLimiter();\n }\n\n private getWindowMs(): number {\n const window = this.options.window;\n const match = window.match(/^(\\d+)(s|m|h|d)$/);\n if (!match) return 60000;\n\n const value = parseInt(match[1], 10);\n const unit = match[2];\n\n switch (unit) {\n case 's': return value * 1000;\n case 'm': return value * 60 * 1000;\n case 'h': return value * 60 * 60 * 1000;\n case 'd': return value * 24 * 60 * 60 * 1000;\n default: return 60000;\n }\n }\n\n private defaultHandler(req: Request, res: Response): void {\n res.status(429).json({\n error: 'Too many requests',\n message: `Rate limit exceeded. Please try again later.`,\n });\n }\n\n middleware(): RequestHandler {\n const windowMs = this.getWindowMs();\n\n return (req: Request, res: Response, next: NextFunction) => {\n if (this.options.skip(req)) {\n return next();\n }\n\n const key = this.options.keyGenerator(req);\n const record = this.store.increment(key, windowMs);\n\n const remaining = Math.max(0, this.options.limit - record.count);\n const resetTime = new Date(record.resetTime);\n\n res.setHeader('X-RateLimit-Limit', this.options.limit);\n res.setHeader('X-RateLimit-Remaining', remaining);\n res.setHeader('X-RateLimit-Reset', Math.ceil(record.resetTime / 1000));\n\n if (record.count > this.options.limit) {\n return this.options.handler(req, res);\n }\n\n next();\n };\n }\n\n destroy(): void {\n this.store.destroy();\n }\n}\n\nexport function rateLimit(options: RateLimitOptions = {}): RequestHandler {\n const limiter = new RateLimiter(options);\n return limiter.middleware();\n}\n\nexport function createRateLimiter(options: RateLimitOptions): RateLimiter {\n return new RateLimiter(options);\n}\n\nexport default rateLimit;\n","export * from './express';\nexport * from './fastify';\n","import { FastifyInstance, FastifyRequest, FastifyReply, HookHandlerDoneFunction } from 'fastify';\nimport { RateLimitOptions, InMemoryRateLimiter } from './express';\n\nexport function registerRateLimitPlugin(fastify: FastifyInstance, options: RateLimitOptions = {}, done: HookHandlerDoneFunction) {\n const limiter = new (require('./express').createRateLimiter.constructor)(options);\n \n fastify.addHook('onRequest', async (request: FastifyRequest, reply: FastifyReply) => {\n const key = options.keyGenerator \n ? options.keyGenerator(request.raw as any)\n : request.ip || 'unknown';\n \n const windowMs = parseWindowMs(options.window || '1m');\n const record = (limiter as any).store.increment(key, windowMs);\n const limit = options.limit || 100;\n const remaining = Math.max(0, limit - record.count);\n\n reply.header('X-RateLimit-Limit', limit);\n reply.header('X-RateLimit-Remaining', remaining);\n reply.header('X-RateLimit-Reset', Math.ceil(record.resetTime / 1000));\n\n if (record.count > limit) {\n reply.status(429).send({\n error: 'Too many requests',\n message: 'Rate limit exceeded. Please try again later.',\n });\n return reply;\n }\n });\n\n done();\n}\n\nfunction parseWindowMs(window: string): number {\n const match = window.match(/^(\\d+)(s|m|h|d)$/);\n if (!match) return 60000;\n\n const value = parseInt(match[1], 10);\n const unit = match[2];\n\n switch (unit) {\n case 's': return value * 1000;\n case 'm': return value * 60 * 1000;\n case 'h': return value * 60 * 60 * 1000;\n case 'd': return value * 24 * 60 * 60 * 1000;\n default: return 60000;\n }\n}\n"]}
|
|
@@ -27,6 +27,7 @@ var init_config = __esm({
|
|
|
27
27
|
NODE_ENV: z.enum(["development", "production", "test"]).default("development"),
|
|
28
28
|
PORT: z.string().default("3000"),
|
|
29
29
|
DATABASE_URL: z.string().optional(),
|
|
30
|
+
MONGODB_URL: z.string().optional(),
|
|
30
31
|
REDIS_URL: z.string().default("redis://localhost:6379"),
|
|
31
32
|
JWT_SECRET: z.string().min(32).optional(),
|
|
32
33
|
JWT_EXPIRES_IN: z.string().default("7d"),
|
|
@@ -146,6 +147,7 @@ var init_express = __esm({
|
|
|
146
147
|
cleanupInterval;
|
|
147
148
|
constructor() {
|
|
148
149
|
this.cleanupInterval = setInterval(() => this.cleanup(), 6e4);
|
|
150
|
+
this.cleanupInterval.unref();
|
|
149
151
|
}
|
|
150
152
|
cleanup() {
|
|
151
153
|
const now = Date.now();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/config/index.ts","../../src/rate-limit/express.ts","../../src/rate-limit/index.ts","../../src/rate-limit/fastify.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import { z } from 'zod';\n\nexport const envSchema = z.object({\n NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),\n PORT: z.string().default('3000'),\n DATABASE_URL: z.string().optional(),\n REDIS_URL: z.string().default('redis://localhost:6379'),\n JWT_SECRET: z.string().min(32).optional(),\n JWT_EXPIRES_IN: z.string().default('7d'),\n JWT_REFRESH_SECRET: z.string().min(32).optional(),\n JWT_REFRESH_EXPIRES_IN: z.string().default('30d'),\n GOOGLE_CLIENT_ID: z.string().optional(),\n GOOGLE_CLIENT_SECRET: z.string().optional(),\n GOOGLE_REDIRECT_URI: z.string().optional(),\n SMTP_HOST: z.string().optional(),\n SMTP_PORT: z.string().default('587'),\n SMTP_USER: z.string().optional(),\n SMTP_PASS: z.string().optional(),\n SMTP_FROM: z.string().optional(),\n TWILIO_ACCOUNT_SID: z.string().optional(),\n TWILIO_AUTH_TOKEN: z.string().optional(),\n TWILIO_PHONE_NUMBER: z.string().optional(),\n SLACK_WEBHOOK_URL: z.string().optional(),\n RATE_LIMIT_WINDOW: z.string().default('1m'),\n RATE_LIMIT_LIMIT: z.string().default('100'),\n LOG_LEVEL: z.enum(['fatal', 'error', 'warn', 'info', 'debug', 'trace']).default('info'),\n AWS_REGION: z.string().default('us-east-1'),\n AWS_ACCESS_KEY_ID: z.string().optional(),\n AWS_SECRET_ACCESS_KEY: z.string().optional(),\n AWS_S3_BUCKET: z.string().optional(),\n AWS_ENDPOINT: z.string().optional(),\n});\n\nexport type EnvConfig = z.infer<typeof envSchema>;\n\nexport interface ConfigOptions {\n schema?: z.ZodSchema;\n envPath?: string;\n validate?: boolean;\n}\n\nclass ConfigManager {\n private config: EnvConfig | null = null;\n private schema: z.ZodSchema;\n private validate: boolean;\n\n constructor(options: ConfigOptions = {}) {\n this.schema = options.schema || envSchema;\n this.validate = options.validate ?? true;\n }\n\n load(): EnvConfig {\n if (this.config) return this.config;\n\n const env: Record<string, string | undefined> = {};\n \n for (const key of Object.keys(this.schema.shape)) {\n env[key] = process.env[key];\n }\n\n if (this.validate) {\n const result = this.schema.safeParse(env);\n if (!result.success) {\n const errors = result.error.errors.map(e => `${e.path.join('.')}: ${e.message}`).join(', ');\n throw new Error(`Config validation failed: ${errors}`);\n }\n this.config = result.data;\n } else {\n this.config = env as EnvConfig;\n }\n\n return this.config;\n }\n\n get<K extends keyof EnvConfig>(key: K): EnvConfig[K] {\n if (!this.config) this.load();\n return this.config![key];\n }\n\n int(key: keyof EnvConfig): number {\n const value = this.get(key);\n if (typeof value === 'string') return parseInt(value, 10);\n return Number(value);\n }\n\n bool(key: keyof EnvConfig): boolean {\n const value = this.get(key);\n if (typeof value === 'boolean') return value;\n if (typeof value === 'string') return value.toLowerCase() === 'true';\n return Boolean(value);\n }\n\n isProduction(): boolean {\n return this.get('NODE_ENV') === 'production';\n }\n\n isDevelopment(): boolean {\n return this.get('NODE_ENV') === 'development';\n }\n\n isTest(): boolean {\n return this.get('NODE_ENV') === 'test';\n }\n\n getAll(): EnvConfig {\n if (!this.config) this.load();\n return this.config!;\n }\n}\n\nconst globalConfig = new ConfigManager();\n\nexport const config = {\n load: () => globalConfig.load(),\n get: <K extends keyof EnvConfig>(key: K) => globalConfig.get(key),\n int: (key: keyof EnvConfig) => globalConfig.int(key),\n bool: (key: keyof EnvConfig) => globalConfig.bool(key),\n isProduction: () => globalConfig.isProduction(),\n isDevelopment: () => globalConfig.isDevelopment(),\n isTest: () => globalConfig.isTest(),\n getAll: () => globalConfig.getAll(),\n create: (options?: ConfigOptions) => new ConfigManager(options),\n};\n\nexport default config;\n","import { Request, Response, NextFunction, RequestHandler } from 'express';\nimport { config } from '../config';\n\nexport interface RateLimitOptions {\n window?: string;\n limit?: number;\n keyGenerator?: (req: Request) => string;\n handler?: (req: Request, res: Response) => void;\n skipSuccessfulRequests?: boolean;\n skipFailedRequests?: boolean;\n skip?: (req: Request) => boolean;\n}\n\ninterface RateLimitRecord {\n count: number;\n resetTime: number;\n}\n\nclass InMemoryRateLimiter {\n private store: Map<string, RateLimitRecord> = new Map();\n private cleanupInterval: NodeJS.Timeout;\n\n constructor() {\n this.cleanupInterval = setInterval(() => this.cleanup(), 60000);\n }\n\n private cleanup(): void {\n const now = Date.now();\n for (const [key, record] of this.store.entries()) {\n if (record.resetTime < now) {\n this.store.delete(key);\n }\n }\n }\n\n increment(key: string, windowMs: number): RateLimitRecord {\n const now = Date.now();\n const record = this.store.get(key);\n\n if (!record || record.resetTime < now) {\n const resetTime = now + windowMs;\n this.store.set(key, { count: 1, resetTime });\n return { count: 1, resetTime };\n }\n\n record.count++;\n return record;\n }\n\n get(key: string): RateLimitRecord | undefined {\n return this.store.get(key);\n }\n\n destroy(): void {\n clearInterval(this.cleanupInterval);\n }\n}\n\nclass RateLimiter {\n private options: Required<RateLimitOptions>;\n private store: InMemoryRateLimiter;\n\n constructor(options: RateLimitOptions = {}) {\n const defaultWindow = config.get('RATE_LIMIT_WINDOW') || '1m';\n const defaultLimit = parseInt(config.get('RATE_LIMIT_LIMIT') || '100', 10);\n\n this.options = {\n window: options.window || defaultWindow,\n limit: options.limit || defaultLimit,\n keyGenerator: options.keyGenerator || ((req: Request) => req.ip || 'unknown'),\n handler: options.handler || this.defaultHandler,\n skipSuccessfulRequests: options.skipSuccessfulRequests || false,\n skipFailedRequests: options.skipFailedRequests || false,\n skip: options.skip || (() => false),\n };\n\n this.store = new InMemoryRateLimiter();\n }\n\n private getWindowMs(): number {\n const window = this.options.window;\n const match = window.match(/^(\\d+)(s|m|h|d)$/);\n if (!match) return 60000;\n\n const value = parseInt(match[1], 10);\n const unit = match[2];\n\n switch (unit) {\n case 's': return value * 1000;\n case 'm': return value * 60 * 1000;\n case 'h': return value * 60 * 60 * 1000;\n case 'd': return value * 24 * 60 * 60 * 1000;\n default: return 60000;\n }\n }\n\n private defaultHandler(req: Request, res: Response): void {\n res.status(429).json({\n error: 'Too many requests',\n message: `Rate limit exceeded. Please try again later.`,\n });\n }\n\n middleware(): RequestHandler {\n const windowMs = this.getWindowMs();\n\n return (req: Request, res: Response, next: NextFunction) => {\n if (this.options.skip(req)) {\n return next();\n }\n\n const key = this.options.keyGenerator(req);\n const record = this.store.increment(key, windowMs);\n\n const remaining = Math.max(0, this.options.limit - record.count);\n const resetTime = new Date(record.resetTime);\n\n res.setHeader('X-RateLimit-Limit', this.options.limit);\n res.setHeader('X-RateLimit-Remaining', remaining);\n res.setHeader('X-RateLimit-Reset', Math.ceil(record.resetTime / 1000));\n\n if (record.count > this.options.limit) {\n return this.options.handler(req, res);\n }\n\n next();\n };\n }\n\n destroy(): void {\n this.store.destroy();\n }\n}\n\nexport function rateLimit(options: RateLimitOptions = {}): RequestHandler {\n const limiter = new RateLimiter(options);\n return limiter.middleware();\n}\n\nexport function createRateLimiter(options: RateLimitOptions): RateLimiter {\n return new RateLimiter(options);\n}\n\nexport default rateLimit;\n","export * from './express';\nexport * from './fastify';\n","import { FastifyInstance, FastifyRequest, FastifyReply, HookHandlerDoneFunction } from 'fastify';\nimport { RateLimitOptions, InMemoryRateLimiter } from './express';\n\nexport function registerRateLimitPlugin(fastify: FastifyInstance, options: RateLimitOptions = {}, done: HookHandlerDoneFunction) {\n const limiter = new (require('./express').createRateLimiter.constructor)(options);\n \n fastify.addHook('onRequest', async (request: FastifyRequest, reply: FastifyReply) => {\n const key = options.keyGenerator \n ? options.keyGenerator(request.raw as any)\n : request.ip || 'unknown';\n \n const windowMs = parseWindowMs(options.window || '1m');\n const record = (limiter as any).store.increment(key, windowMs);\n const limit = options.limit || 100;\n const remaining = Math.max(0, limit - record.count);\n\n reply.header('X-RateLimit-Limit', limit);\n reply.header('X-RateLimit-Remaining', remaining);\n reply.header('X-RateLimit-Reset', Math.ceil(record.resetTime / 1000));\n\n if (record.count > limit) {\n reply.status(429).send({\n error: 'Too many requests',\n message: 'Rate limit exceeded. Please try again later.',\n });\n return reply;\n }\n });\n\n done();\n}\n\nfunction parseWindowMs(window: string): number {\n const match = window.match(/^(\\d+)(s|m|h|d)$/);\n if (!match) return 60000;\n\n const value = parseInt(match[1], 10);\n const unit = match[2];\n\n switch (unit) {\n case 's': return value * 1000;\n case 'm': return value * 60 * 1000;\n case 'h': return value * 60 * 60 * 1000;\n case 'd': return value * 24 * 60 * 60 * 1000;\n default: return 60000;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/config/index.ts","../../src/rate-limit/express.ts","../../src/rate-limit/index.ts","../../src/rate-limit/fastify.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import { z } from 'zod';\n\nexport const envSchema = z.object({\n NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),\n PORT: z.string().default('3000'),\n DATABASE_URL: z.string().optional(),\n MONGODB_URL: z.string().optional(),\n REDIS_URL: z.string().default('redis://localhost:6379'),\n JWT_SECRET: z.string().min(32).optional(),\n JWT_EXPIRES_IN: z.string().default('7d'),\n JWT_REFRESH_SECRET: z.string().min(32).optional(),\n JWT_REFRESH_EXPIRES_IN: z.string().default('30d'),\n GOOGLE_CLIENT_ID: z.string().optional(),\n GOOGLE_CLIENT_SECRET: z.string().optional(),\n GOOGLE_REDIRECT_URI: z.string().optional(),\n SMTP_HOST: z.string().optional(),\n SMTP_PORT: z.string().default('587'),\n SMTP_USER: z.string().optional(),\n SMTP_PASS: z.string().optional(),\n SMTP_FROM: z.string().optional(),\n TWILIO_ACCOUNT_SID: z.string().optional(),\n TWILIO_AUTH_TOKEN: z.string().optional(),\n TWILIO_PHONE_NUMBER: z.string().optional(),\n SLACK_WEBHOOK_URL: z.string().optional(),\n RATE_LIMIT_WINDOW: z.string().default('1m'),\n RATE_LIMIT_LIMIT: z.string().default('100'),\n LOG_LEVEL: z.enum(['fatal', 'error', 'warn', 'info', 'debug', 'trace']).default('info'),\n AWS_REGION: z.string().default('us-east-1'),\n AWS_ACCESS_KEY_ID: z.string().optional(),\n AWS_SECRET_ACCESS_KEY: z.string().optional(),\n AWS_S3_BUCKET: z.string().optional(),\n AWS_ENDPOINT: z.string().optional(),\n});\n\nexport type EnvConfig = z.infer<typeof envSchema>;\n\nexport interface ConfigOptions {\n schema?: z.ZodSchema;\n envPath?: string;\n validate?: boolean;\n}\n\nclass ConfigManager {\n private config: EnvConfig | null = null;\n private schema: z.ZodSchema;\n private validate: boolean;\n\n constructor(options: ConfigOptions = {}) {\n this.schema = options.schema || envSchema;\n this.validate = options.validate ?? true;\n }\n\n load(): EnvConfig {\n if (this.config) return this.config;\n\n const env: Record<string, string | undefined> = {};\n \n for (const key of Object.keys(this.schema.shape)) {\n env[key] = process.env[key];\n }\n\n if (this.validate) {\n const result = this.schema.safeParse(env);\n if (!result.success) {\n const errors = result.error.errors.map(e => `${e.path.join('.')}: ${e.message}`).join(', ');\n throw new Error(`Config validation failed: ${errors}`);\n }\n this.config = result.data;\n } else {\n this.config = env as EnvConfig;\n }\n\n return this.config;\n }\n\n get<K extends keyof EnvConfig>(key: K): EnvConfig[K] {\n if (!this.config) this.load();\n return this.config![key];\n }\n\n int(key: keyof EnvConfig): number {\n const value = this.get(key);\n if (typeof value === 'string') return parseInt(value, 10);\n return Number(value);\n }\n\n bool(key: keyof EnvConfig): boolean {\n const value = this.get(key);\n if (typeof value === 'boolean') return value;\n if (typeof value === 'string') return value.toLowerCase() === 'true';\n return Boolean(value);\n }\n\n isProduction(): boolean {\n return this.get('NODE_ENV') === 'production';\n }\n\n isDevelopment(): boolean {\n return this.get('NODE_ENV') === 'development';\n }\n\n isTest(): boolean {\n return this.get('NODE_ENV') === 'test';\n }\n\n getAll(): EnvConfig {\n if (!this.config) this.load();\n return this.config!;\n }\n}\n\nconst globalConfig = new ConfigManager();\n\nexport const config = {\n load: () => globalConfig.load(),\n get: <K extends keyof EnvConfig>(key: K) => globalConfig.get(key),\n int: (key: keyof EnvConfig) => globalConfig.int(key),\n bool: (key: keyof EnvConfig) => globalConfig.bool(key),\n isProduction: () => globalConfig.isProduction(),\n isDevelopment: () => globalConfig.isDevelopment(),\n isTest: () => globalConfig.isTest(),\n getAll: () => globalConfig.getAll(),\n create: (options?: ConfigOptions) => new ConfigManager(options),\n};\n\nexport default config;\n","import { Request, Response, NextFunction, RequestHandler } from 'express';\nimport { config } from '../config';\n\nexport interface RateLimitOptions {\n window?: string;\n limit?: number;\n keyGenerator?: (req: Request) => string;\n handler?: (req: Request, res: Response) => void;\n skipSuccessfulRequests?: boolean;\n skipFailedRequests?: boolean;\n skip?: (req: Request) => boolean;\n}\n\ninterface RateLimitRecord {\n count: number;\n resetTime: number;\n}\n\nclass InMemoryRateLimiter {\n private store: Map<string, RateLimitRecord> = new Map();\n private cleanupInterval: NodeJS.Timeout;\n\n constructor() {\n this.cleanupInterval = setInterval(() => this.cleanup(), 60000);\n this.cleanupInterval.unref();\n }\n\n private cleanup(): void {\n const now = Date.now();\n for (const [key, record] of this.store.entries()) {\n if (record.resetTime < now) {\n this.store.delete(key);\n }\n }\n }\n\n increment(key: string, windowMs: number): RateLimitRecord {\n const now = Date.now();\n const record = this.store.get(key);\n\n if (!record || record.resetTime < now) {\n const resetTime = now + windowMs;\n this.store.set(key, { count: 1, resetTime });\n return { count: 1, resetTime };\n }\n\n record.count++;\n return record;\n }\n\n get(key: string): RateLimitRecord | undefined {\n return this.store.get(key);\n }\n\n destroy(): void {\n clearInterval(this.cleanupInterval);\n }\n}\n\nclass RateLimiter {\n private options: Required<RateLimitOptions>;\n private store: InMemoryRateLimiter;\n\n constructor(options: RateLimitOptions = {}) {\n const defaultWindow = config.get('RATE_LIMIT_WINDOW') || '1m';\n const defaultLimit = parseInt(config.get('RATE_LIMIT_LIMIT') || '100', 10);\n\n this.options = {\n window: options.window || defaultWindow,\n limit: options.limit || defaultLimit,\n keyGenerator: options.keyGenerator || ((req: Request) => req.ip || 'unknown'),\n handler: options.handler || this.defaultHandler,\n skipSuccessfulRequests: options.skipSuccessfulRequests || false,\n skipFailedRequests: options.skipFailedRequests || false,\n skip: options.skip || (() => false),\n };\n\n this.store = new InMemoryRateLimiter();\n }\n\n private getWindowMs(): number {\n const window = this.options.window;\n const match = window.match(/^(\\d+)(s|m|h|d)$/);\n if (!match) return 60000;\n\n const value = parseInt(match[1], 10);\n const unit = match[2];\n\n switch (unit) {\n case 's': return value * 1000;\n case 'm': return value * 60 * 1000;\n case 'h': return value * 60 * 60 * 1000;\n case 'd': return value * 24 * 60 * 60 * 1000;\n default: return 60000;\n }\n }\n\n private defaultHandler(req: Request, res: Response): void {\n res.status(429).json({\n error: 'Too many requests',\n message: `Rate limit exceeded. Please try again later.`,\n });\n }\n\n middleware(): RequestHandler {\n const windowMs = this.getWindowMs();\n\n return (req: Request, res: Response, next: NextFunction) => {\n if (this.options.skip(req)) {\n return next();\n }\n\n const key = this.options.keyGenerator(req);\n const record = this.store.increment(key, windowMs);\n\n const remaining = Math.max(0, this.options.limit - record.count);\n const resetTime = new Date(record.resetTime);\n\n res.setHeader('X-RateLimit-Limit', this.options.limit);\n res.setHeader('X-RateLimit-Remaining', remaining);\n res.setHeader('X-RateLimit-Reset', Math.ceil(record.resetTime / 1000));\n\n if (record.count > this.options.limit) {\n return this.options.handler(req, res);\n }\n\n next();\n };\n }\n\n destroy(): void {\n this.store.destroy();\n }\n}\n\nexport function rateLimit(options: RateLimitOptions = {}): RequestHandler {\n const limiter = new RateLimiter(options);\n return limiter.middleware();\n}\n\nexport function createRateLimiter(options: RateLimitOptions): RateLimiter {\n return new RateLimiter(options);\n}\n\nexport default rateLimit;\n","export * from './express';\nexport * from './fastify';\n","import { FastifyInstance, FastifyRequest, FastifyReply, HookHandlerDoneFunction } from 'fastify';\nimport { RateLimitOptions, InMemoryRateLimiter } from './express';\n\nexport function registerRateLimitPlugin(fastify: FastifyInstance, options: RateLimitOptions = {}, done: HookHandlerDoneFunction) {\n const limiter = new (require('./express').createRateLimiter.constructor)(options);\n \n fastify.addHook('onRequest', async (request: FastifyRequest, reply: FastifyReply) => {\n const key = options.keyGenerator \n ? options.keyGenerator(request.raw as any)\n : request.ip || 'unknown';\n \n const windowMs = parseWindowMs(options.window || '1m');\n const record = (limiter as any).store.increment(key, windowMs);\n const limit = options.limit || 100;\n const remaining = Math.max(0, limit - record.count);\n\n reply.header('X-RateLimit-Limit', limit);\n reply.header('X-RateLimit-Remaining', remaining);\n reply.header('X-RateLimit-Reset', Math.ceil(record.resetTime / 1000));\n\n if (record.count > limit) {\n reply.status(429).send({\n error: 'Too many requests',\n message: 'Rate limit exceeded. Please try again later.',\n });\n return reply;\n }\n });\n\n done();\n}\n\nfunction parseWindowMs(window: string): number {\n const match = window.match(/^(\\d+)(s|m|h|d)$/);\n if (!match) return 60000;\n\n const value = parseInt(match[1], 10);\n const unit = match[2];\n\n switch (unit) {\n case 's': return value * 1000;\n case 'm': return value * 60 * 1000;\n case 'h': return value * 60 * 60 * 1000;\n case 'd': return value * 24 * 60 * 60 * 1000;\n default: return 60000;\n }\n}\n"]}
|
package/dist/response/index.js
CHANGED
|
@@ -2,7 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var
|
|
5
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
6
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
7
|
+
}) : x)(function(x) {
|
|
8
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
9
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
10
|
+
});
|
|
6
11
|
|
|
7
12
|
// src/response/index.ts
|
|
8
13
|
var ResponseHelper = class {
|
|
@@ -71,45 +76,51 @@ var ResponseHelper = class {
|
|
|
71
76
|
return res.status(204).send();
|
|
72
77
|
}
|
|
73
78
|
};
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
};
|
|
79
|
+
try {
|
|
80
|
+
const proto = __require("express").response;
|
|
81
|
+
if (proto) {
|
|
82
|
+
proto.success = function(data, message, statusCode = 200) {
|
|
83
|
+
return ResponseHelper.success(this, data, message, statusCode);
|
|
84
|
+
};
|
|
85
|
+
proto.created = function(data, message) {
|
|
86
|
+
return ResponseHelper.created(this, data, message);
|
|
87
|
+
};
|
|
88
|
+
proto.updated = function(data, message) {
|
|
89
|
+
return ResponseHelper.updated(this, data, message);
|
|
90
|
+
};
|
|
91
|
+
proto.deleted = function(message) {
|
|
92
|
+
return ResponseHelper.deleted(this, message);
|
|
93
|
+
};
|
|
94
|
+
proto.error = function(error, statusCode = 400, code, details) {
|
|
95
|
+
return ResponseHelper.error(this, error, statusCode, code, details);
|
|
96
|
+
};
|
|
97
|
+
proto.badRequest = function(error, code) {
|
|
98
|
+
return ResponseHelper.badRequest(this, error, code);
|
|
99
|
+
};
|
|
100
|
+
proto.unauthorized = function(error, code) {
|
|
101
|
+
return ResponseHelper.unauthorized(this, error, code);
|
|
102
|
+
};
|
|
103
|
+
proto.forbidden = function(error, code) {
|
|
104
|
+
return ResponseHelper.forbidden(this, error, code);
|
|
105
|
+
};
|
|
106
|
+
proto.notFound = function(error, code) {
|
|
107
|
+
return ResponseHelper.notFound(this, error, code);
|
|
108
|
+
};
|
|
109
|
+
proto.conflict = function(error, code) {
|
|
110
|
+
return ResponseHelper.conflict(this, error, code);
|
|
111
|
+
};
|
|
112
|
+
proto.validationError = function(error, details) {
|
|
113
|
+
return ResponseHelper.validationError(this, error, details);
|
|
114
|
+
};
|
|
115
|
+
proto.internalError = function(error) {
|
|
116
|
+
return ResponseHelper.internalError(this, error);
|
|
117
|
+
};
|
|
118
|
+
proto.paginated = function(data, page, limit, total) {
|
|
119
|
+
return ResponseHelper.paginated(this, data, page, limit, total);
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
} catch {
|
|
123
|
+
}
|
|
113
124
|
var response = ResponseHelper;
|
|
114
125
|
var response_default = ResponseHelper;
|
|
115
126
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/response/index.ts"],"names":["response","Response"],"mappings":"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","file":"index.js","sourcesContent":["import { Response } from 'express';\n\nexport interface ApiResponse<T = unknown> {\n success: boolean;\n data?: T;\n error?: string;\n message?: string;\n meta?: {\n page?: number;\n limit?: number;\n total?: number;\n totalPages?: number;\n };\n}\n\nexport interface PaginatedResponse<T> extends ApiResponse<T> {\n meta: {\n page: number;\n limit: number;\n total: number;\n totalPages: number;\n };\n}\n\nexport interface ErrorResponse {\n success: false;\n error: string;\n code?: string;\n details?: Record<string, unknown>;\n}\n\nexport class ResponseHelper {\n static success<T>(res: Response, data?: T, message?: string, statusCode: number = 200): Response {\n const response: ApiResponse<T> = {\n success: true,\n data,\n message,\n };\n return res.status(statusCode).json(response);\n }\n\n static created<T>(res: Response, data?: T, message: string = 'Resource created'): Response {\n return this.success(res, data, message, 201);\n }\n\n static updated<T>(res: Response, data?: T, message: string = 'Resource updated'): Response {\n return this.success(res, data, message, 200);\n }\n\n static deleted(res: Response, message: string = 'Resource deleted'): Response {\n return this.success(res, null, message, 200);\n }\n\n static error(\n res: Response,\n error: string,\n statusCode: number = 400,\n code?: string,\n details?: Record<string, unknown>\n ): Response {\n const response: ErrorResponse = {\n success: false,\n error,\n code,\n ...(details && { details }),\n };\n return res.status(statusCode).json(response);\n }\n\n static badRequest(res: Response, error: string = 'Bad request', code?: string): Response {\n return this.error(res, error, 400, code);\n }\n\n static unauthorized(res: Response, error: string = 'Unauthorized', code?: string): Response {\n return this.error(res, error, 401, code);\n }\n\n static forbidden(res: Response, error: string = 'Forbidden', code?: string): Response {\n return this.error(res, error, 403, code);\n }\n\n static notFound(res: Response, error: string = 'Resource not found', code?: string): Response {\n return this.error(res, error, 404, code);\n }\n\n static conflict(res: Response, error: string = 'Conflict', code?: string): Response {\n return this.error(res, error, 409, code);\n }\n\n static validationError(res: Response, error: string, details?: Record<string, unknown>): Response {\n return this.error(res, error, 422, 'VALIDATION_ERROR', details);\n }\n\n static internalError(res: Response, error: string = 'Internal server error'): Response {\n return this.error(res, error, 500, 'INTERNAL_ERROR');\n }\n\n static paginated<T>(\n res: Response,\n data: T[],\n page: number,\n limit: number,\n total: number\n ): Response<PaginatedResponse<T>> {\n const totalPages = Math.ceil(total / limit);\n const response: PaginatedResponse<T> = {\n success: true,\n data,\n meta: {\n page,\n limit,\n total,\n totalPages,\n },\n };\n return res.status(200).json(response);\n }\n\n static noContent(res: Response): Response {\n return res.status(204).send();\n }\n}\n\ndeclare global {\n namespace Express {\n interface Response {\n success<T>(data?: T, message?: string, statusCode?: number): Response;\n created<T>(data?: T, message?: string): Response;\n updated<T>(data?: T, message?: string): Response;\n deleted(message?: string): Response;\n error(error: string, statusCode?: number, code?: string, details?: Record<string, unknown>): Response;\n badRequest(error?: string, code?: string): Response;\n unauthorized(error?: string, code?: string): Response;\n forbidden(error?: string, code?: string): Response;\n notFound(error?: string, code?: string): Response;\n conflict(error?: string, code?: string): Response;\n validationError(error: string, details?: Record<string, unknown>): Response;\n internalError(error?: string): Response;\n paginated<T>(data: T[], page: number, limit: number, total: number): Response;\n }\n }\n}\n\nResponse.prototype.success = function <T>(data?: T, message?: string, statusCode: number = 200) {\n return ResponseHelper.success(this, data, message, statusCode);\n};\n\nResponse.prototype.created = function <T>(data?: T, message?: string) {\n return ResponseHelper.created(this, data, message);\n};\n\nResponse.prototype.updated = function <T>(data?: T, message?: string) {\n return ResponseHelper.updated(this, data, message);\n};\n\nResponse.prototype.deleted = function (message?: string) {\n return ResponseHelper.deleted(this, message);\n};\n\nResponse.prototype.error = function (error: string, statusCode: number = 400, code?: string, details?: Record<string, unknown>) {\n return ResponseHelper.error(this, error, statusCode, code, details);\n};\n\nResponse.prototype.badRequest = function (error?: string, code?: string) {\n return ResponseHelper.badRequest(this, error, code);\n};\n\nResponse.prototype.unauthorized = function (error?: string, code?: string) {\n return ResponseHelper.unauthorized(this, error, code);\n};\n\nResponse.prototype.forbidden = function (error?: string, code?: string) {\n return ResponseHelper.forbidden(this, error, code);\n};\n\nResponse.prototype.notFound = function (error?: string, code?: string) {\n return ResponseHelper.notFound(this, error, code);\n};\n\nResponse.prototype.conflict = function (error?: string, code?: string) {\n return ResponseHelper.conflict(this, error, code);\n};\n\nResponse.prototype.validationError = function (error: string, details?: Record<string, unknown>) {\n return ResponseHelper.validationError(this, error, details);\n};\n\nResponse.prototype.internalError = function (error?: string) {\n return ResponseHelper.internalError(this, error);\n};\n\nResponse.prototype.paginated = function <T>(data: T[], page: number, limit: number, total: number) {\n return ResponseHelper.paginated(this, data, page, limit, total);\n};\n\nexport const response = ResponseHelper;\nexport default ResponseHelper;\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/response/index.ts"],"names":["response"],"mappings":"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","file":"index.js","sourcesContent":["import { Response } from 'express';\n\nexport interface ApiResponse<T = unknown> {\n success: boolean;\n data?: T;\n error?: string;\n message?: string;\n meta?: {\n page?: number;\n limit?: number;\n total?: number;\n totalPages?: number;\n };\n}\n\nexport interface PaginatedResponse<T> extends Omit<ApiResponse<T[]>, 'data'> {\n data: T[];\n meta: {\n page: number;\n limit: number;\n total: number;\n totalPages: number;\n };\n}\n\nexport interface ErrorResponse {\n success: false;\n error: string;\n code?: string;\n details?: Record<string, unknown>;\n}\n\nexport class ResponseHelper {\n static success<T>(res: Response, data?: T, message?: string, statusCode: number = 200): Response {\n const response: ApiResponse<T> = {\n success: true,\n data,\n message,\n };\n return res.status(statusCode).json(response);\n }\n\n static created<T>(res: Response, data?: T, message: string = 'Resource created'): Response {\n return this.success(res, data, message, 201);\n }\n\n static updated<T>(res: Response, data?: T, message: string = 'Resource updated'): Response {\n return this.success(res, data, message, 200);\n }\n\n static deleted(res: Response, message: string = 'Resource deleted'): Response {\n return this.success(res, null, message, 200);\n }\n\n static error(\n res: Response,\n error: string,\n statusCode: number = 400,\n code?: string,\n details?: Record<string, unknown>\n ): Response {\n const response: ErrorResponse = {\n success: false,\n error,\n code,\n ...(details && { details }),\n };\n return res.status(statusCode).json(response);\n }\n\n static badRequest(res: Response, error: string = 'Bad request', code?: string): Response {\n return this.error(res, error, 400, code);\n }\n\n static unauthorized(res: Response, error: string = 'Unauthorized', code?: string): Response {\n return this.error(res, error, 401, code);\n }\n\n static forbidden(res: Response, error: string = 'Forbidden', code?: string): Response {\n return this.error(res, error, 403, code);\n }\n\n static notFound(res: Response, error: string = 'Resource not found', code?: string): Response {\n return this.error(res, error, 404, code);\n }\n\n static conflict(res: Response, error: string = 'Conflict', code?: string): Response {\n return this.error(res, error, 409, code);\n }\n\n static validationError(res: Response, error: string, details?: Record<string, unknown>): Response {\n return this.error(res, error, 422, 'VALIDATION_ERROR', details);\n }\n\n static internalError(res: Response, error: string = 'Internal server error'): Response {\n return this.error(res, error, 500, 'INTERNAL_ERROR');\n }\n\n static paginated<T>(\n res: Response,\n data: T[],\n page: number,\n limit: number,\n total: number\n ): Response<PaginatedResponse<T>> {\n const totalPages = Math.ceil(total / limit);\n const response: PaginatedResponse<T> = {\n success: true,\n data,\n meta: {\n page,\n limit,\n total,\n totalPages,\n },\n };\n return res.status(200).json(response);\n }\n\n static noContent(res: Response): Response {\n return res.status(204).send();\n }\n}\n\ndeclare global {\n namespace Express {\n interface Response {\n success<T>(data?: T, message?: string, statusCode?: number): Response;\n created<T>(data?: T, message?: string): Response;\n updated<T>(data?: T, message?: string): Response;\n deleted(message?: string): Response;\n error(error: string, statusCode?: number, code?: string, details?: Record<string, unknown>): Response;\n badRequest(error?: string, code?: string): Response;\n unauthorized(error?: string, code?: string): Response;\n forbidden(error?: string, code?: string): Response;\n notFound(error?: string, code?: string): Response;\n conflict(error?: string, code?: string): Response;\n validationError(error: string, details?: Record<string, unknown>): Response;\n internalError(error?: string): Response;\n paginated<T>(data: T[], page: number, limit: number, total: number): Response;\n }\n }\n}\n\ntry {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const proto = require('express').response;\n if (proto) {\n proto.success = function <T>(this: Response, data?: T, message?: string, statusCode: number = 200) {\n return ResponseHelper.success(this, data, message, statusCode);\n };\n\n proto.created = function <T>(this: Response, data?: T, message?: string) {\n return ResponseHelper.created(this, data, message);\n };\n\n proto.updated = function <T>(this: Response, data?: T, message?: string) {\n return ResponseHelper.updated(this, data, message);\n };\n\n proto.deleted = function (this: Response, message?: string) {\n return ResponseHelper.deleted(this, message);\n };\n\n proto.error = function (this: Response, error: string, statusCode: number = 400, code?: string, details?: Record<string, unknown>) {\n return ResponseHelper.error(this, error, statusCode, code, details);\n };\n\n proto.badRequest = function (this: Response, error?: string, code?: string) {\n return ResponseHelper.badRequest(this, error, code);\n };\n\n proto.unauthorized = function (this: Response, error?: string, code?: string) {\n return ResponseHelper.unauthorized(this, error, code);\n };\n\n proto.forbidden = function (this: Response, error?: string, code?: string) {\n return ResponseHelper.forbidden(this, error, code);\n };\n\n proto.notFound = function (this: Response, error?: string, code?: string) {\n return ResponseHelper.notFound(this, error, code);\n };\n\n proto.conflict = function (this: Response, error?: string, code?: string) {\n return ResponseHelper.conflict(this, error, code);\n };\n\n proto.validationError = function (this: Response, error: string, details?: Record<string, unknown>) {\n return ResponseHelper.validationError(this, error, details);\n };\n\n proto.internalError = function (this: Response, error?: string) {\n return ResponseHelper.internalError(this, error);\n };\n\n proto.paginated = function <T>(this: Response, data: T[], page: number, limit: number, total: number) {\n return ResponseHelper.paginated(this, data, page, limit, total);\n };\n }\n} catch {\n // express not available at runtime\n}\n\nexport const response = ResponseHelper;\nexport default ResponseHelper;\n"]}
|