@scpxl/nodejs-framework 1.0.24 → 1.0.27
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 +65 -17
- package/dist/api-requester/api-requester.d.ts.map +1 -1
- package/dist/api-requester/api-requester.js +2 -1
- package/dist/api-requester/api-requester.js.map +2 -2
- package/dist/application/base-application.d.ts.map +1 -1
- package/dist/application/base-application.js +4 -3
- package/dist/application/base-application.js.map +2 -2
- package/dist/cache/manager.d.ts.map +1 -1
- package/dist/cache/manager.js +2 -1
- package/dist/cache/manager.js.map +2 -2
- package/dist/cli/index.js +7019 -83
- package/dist/cli/index.js.map +4 -4
- package/dist/cluster/cluster-manager.d.ts +3 -0
- package/dist/cluster/cluster-manager.d.ts.map +1 -1
- package/dist/cluster/cluster-manager.js +45 -8
- package/dist/cluster/cluster-manager.js.map +2 -2
- package/dist/database/dynamic-entity-form-decorators.d.ts +2 -2
- package/dist/database/dynamic-entity-form-decorators.d.ts.map +1 -1
- package/dist/database/dynamic-entity-form-decorators.js.map +1 -1
- package/dist/database/dynamic-entity.d.ts +21 -4
- package/dist/database/dynamic-entity.d.ts.map +1 -1
- package/dist/database/dynamic-entity.js +39 -10
- package/dist/database/dynamic-entity.js.map +2 -2
- package/dist/database/manager.d.ts.map +1 -1
- package/dist/database/manager.js +3 -2
- package/dist/database/manager.js.map +2 -2
- package/dist/error/error-reporter.d.ts +20 -7
- package/dist/error/error-reporter.d.ts.map +1 -1
- package/dist/error/error-reporter.js +32 -29
- package/dist/error/error-reporter.js.map +2 -2
- package/dist/error/index.d.ts +1 -1
- package/dist/error/index.d.ts.map +1 -1
- package/dist/error/index.js +3 -2
- package/dist/error/index.js.map +2 -2
- package/dist/event/controller/base.d.ts.map +1 -1
- package/dist/event/controller/base.js +2 -1
- package/dist/event/controller/base.js.map +2 -2
- package/dist/event/manager.d.ts.map +1 -1
- package/dist/event/manager.js +5 -4
- package/dist/event/manager.js.map +2 -2
- package/dist/lifecycle/exit.d.ts.map +1 -1
- package/dist/lifecycle/exit.js.map +2 -2
- package/dist/logger/logger.d.ts.map +1 -1
- package/dist/logger/logger.js +3 -2
- package/dist/logger/logger.js.map +2 -2
- package/dist/performance/performance-monitor.d.ts.map +1 -1
- package/dist/performance/performance-monitor.js +10 -3
- package/dist/performance/performance-monitor.js.map +2 -2
- package/dist/queue/processor/base.d.ts.map +1 -1
- package/dist/queue/processor/base.js +2 -1
- package/dist/queue/processor/base.js.map +2 -2
- package/dist/redis/manager.d.ts.map +1 -1
- package/dist/redis/manager.js +3 -2
- package/dist/redis/manager.js.map +2 -2
- package/dist/schemas/common.d.ts +197 -0
- package/dist/schemas/common.d.ts.map +1 -0
- package/dist/schemas/common.js +108 -0
- package/dist/schemas/common.js.map +7 -0
- package/dist/schemas/entity-builder.d.ts +35 -0
- package/dist/schemas/entity-builder.d.ts.map +1 -0
- package/dist/schemas/entity-builder.js +39 -0
- package/dist/schemas/entity-builder.js.map +7 -0
- package/dist/schemas/index.d.ts +6 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +2 -0
- package/dist/schemas/index.js.map +7 -0
- package/dist/util/loader.d.ts.map +1 -1
- package/dist/util/loader.js.map +2 -2
- package/dist/webserver/controller/base.d.ts.map +1 -1
- package/dist/webserver/controller/base.js +4 -4
- package/dist/webserver/controller/base.js.map +2 -2
- package/dist/webserver/controller/entity.js +2 -2
- package/dist/webserver/controller/entity.js.map +2 -2
- package/dist/webserver/controller/health.d.ts +0 -2
- package/dist/webserver/controller/health.d.ts.map +1 -1
- package/dist/webserver/controller/health.js +0 -14
- package/dist/webserver/controller/health.js.map +2 -2
- package/dist/webserver/webserver.d.ts.map +1 -1
- package/dist/webserver/webserver.interface.d.ts +2 -2
- package/dist/webserver/webserver.interface.d.ts.map +1 -1
- package/dist/webserver/webserver.interface.js.map +1 -1
- package/dist/webserver/webserver.js +2 -2
- package/dist/webserver/webserver.js.map +2 -2
- package/dist/websocket/index.d.ts +2 -0
- package/dist/websocket/index.d.ts.map +1 -1
- package/dist/websocket/index.js +2 -0
- package/dist/websocket/index.js.map +2 -2
- package/dist/websocket/websocket-auth.d.ts +17 -0
- package/dist/websocket/websocket-auth.d.ts.map +1 -0
- package/dist/websocket/websocket-auth.js +46 -0
- package/dist/websocket/websocket-auth.js.map +7 -0
- package/dist/websocket/websocket-client-manager.d.ts.map +1 -1
- package/dist/websocket/websocket-client-manager.js +6 -5
- package/dist/websocket/websocket-client-manager.js.map +2 -2
- package/dist/websocket/websocket-client.d.ts +29 -0
- package/dist/websocket/websocket-client.d.ts.map +1 -1
- package/dist/websocket/websocket-client.js +97 -3
- package/dist/websocket/websocket-client.js.map +2 -2
- package/dist/websocket/websocket-server.d.ts +10 -0
- package/dist/websocket/websocket-server.d.ts.map +1 -1
- package/dist/websocket/websocket-server.js +40 -52
- package/dist/websocket/websocket-server.js.map +2 -2
- package/dist/websocket/websocket.interface.d.ts +13 -0
- package/dist/websocket/websocket.interface.d.ts.map +1 -1
- package/dist/websocket/websocket.interface.js.map +2 -2
- package/package.json +9 -12
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/redis/manager.ts"],
|
|
4
|
-
"sourcesContent": ["import { Redis, type RedisOptions } from 'ioredis';\nimport { EventEmitter } from 'node:events';\nimport type { RedisManagerConfig as RedisManagerOptions } from './manager.interface.js';\nimport RedisInstance from './instance.js';\nimport { Logger } from '../logger/index.js';\nimport { CachePerformanceWrapper } from '../performance/index.js';\n\nconst truthyPattern = /^(1|true|yes|on)$/i;\nconst scheduleMicrotask =\n typeof (globalThis as any).queueMicrotask === 'function'\n ? (globalThis as any).queueMicrotask.bind(globalThis)\n : (callback: () => void) => {\n void Promise.resolve().then(callback);\n };\n\ntype RedisCallback = (error: Error | null, result?: string) => void;\n\ninterface InMemoryRedisSharedState {\n store: Map<string, string | Buffer>;\n expirations: Map<string, NodeJS.Timeout>;\n subscriptions: Map<string, Set<InMemoryRedisClient>>;\n}\n\n// Global singleton shared state for in-memory Redis\nlet globalInMemoryRedisState: InMemoryRedisSharedState | null = null;\n\nfunction getGlobalInMemoryRedisState(): InMemoryRedisSharedState {\n globalInMemoryRedisState ??= {\n store: new Map<string, string | Buffer>(),\n expirations: new Map<string, NodeJS.Timeout>(),\n subscriptions: new Map<string, Set<InMemoryRedisClient>>(),\n };\n return globalInMemoryRedisState;\n}\n\nclass InMemoryRedisClient extends EventEmitter {\n private shared: InMemoryRedisSharedState;\n\n constructor(shared: InMemoryRedisSharedState) {\n super();\n this.shared = shared;\n\n scheduleMicrotask(() => {\n this.emit('ready');\n });\n }\n\n private cleanupSubscriptions(): void {\n for (const subscribers of this.shared.subscriptions.values()) {\n subscribers.delete(this);\n }\n }\n\n private clearExpirationForKey(key: string): void {\n const timer = this.shared.expirations.get(key);\n if (timer) {\n clearTimeout(timer);\n this.shared.expirations.delete(key);\n }\n }\n\n public ping(callback?: RedisCallback): Promise<string> {\n if (callback) {\n callback(null, 'PONG');\n return Promise.resolve('PONG');\n }\n\n return Promise.resolve('PONG');\n }\n\n public async set(...args: any[]): Promise<'OK'> {\n const [key, value, mode, expiration] = args;\n const serializedValue: string | Buffer = value instanceof Buffer ? value : String(value);\n\n this.shared.store.set(key, serializedValue);\n this.clearExpirationForKey(key);\n\n if (typeof mode === 'string' && mode.toUpperCase() === 'EX' && typeof expiration === 'number') {\n const timer = setTimeout(() => {\n this.shared.store.delete(key);\n this.shared.expirations.delete(key);\n }, expiration * 1000);\n\n if (typeof timer.unref === 'function') {\n timer.unref();\n }\n\n this.shared.expirations.set(key, timer);\n }\n\n return 'OK';\n }\n\n public async get(key: string): Promise<string | null> {\n return (this.shared.store.get(key) as string | undefined) ?? null;\n }\n\n public async del(key: string): Promise<number> {\n const existed = this.shared.store.delete(key);\n this.clearExpirationForKey(key);\n return existed ? 1 : 0;\n }\n\n public async publish(channel: string, message: string): Promise<number> {\n const subscribers = this.shared.subscriptions.get(channel);\n\n if (!subscribers || subscribers.size === 0) {\n return 0;\n }\n\n for (const subscriber of subscribers) {\n scheduleMicrotask(() => {\n subscriber.emit('message', channel, message);\n });\n }\n\n return subscribers.size;\n }\n\n public async subscribe(channel: string): Promise<number> {\n let subscribers = this.shared.subscriptions.get(channel);\n if (!subscribers) {\n subscribers = new Set<InMemoryRedisClient>();\n this.shared.subscriptions.set(channel, subscribers);\n }\n subscribers.add(this);\n return subscribers.size;\n }\n\n public async unsubscribe(channel: string): Promise<number> {\n const subscribers = this.shared.subscriptions.get(channel);\n\n if (!subscribers) {\n return 0;\n }\n\n subscribers.delete(this);\n return subscribers.size;\n }\n\n public async quit(): Promise<'OK'> {\n this.cleanupSubscriptions();\n this.emit('end');\n this.removeAllListeners();\n return 'OK';\n }\n\n public disconnect(): void {\n this.cleanupSubscriptions();\n this.emit('end');\n this.removeAllListeners();\n }\n}\n\nexport default class RedisManager {\n private logger: typeof Logger = Logger;\n\n private options: RedisManagerOptions;\n\n public instances: RedisInstance[] = [];\n\n constructor(config: RedisManagerOptions) {\n this.options = config;\n }\n\n public async connect(): Promise<RedisInstance> {\n return CachePerformanceWrapper.monitorConnection(\n 'connect',\n async () => {\n const startTime = performance.now();\n\n const redisOptions: RedisOptions = {\n host: this.options.host,\n port: this.options.port,\n password: this.options.password,\n maxRetriesPerRequest: null, // Needed for bullmq\n };\n\n const useInMemoryRedis =\n truthyPattern.test(process.env.PXL_REDIS_IN_MEMORY ?? '') ||\n truthyPattern.test(process.env.REDIS_IN_MEMORY ?? '');\n\n const createClient = (): Redis => {\n if (useInMemoryRedis) {\n return new InMemoryRedisClient(getGlobalInMemoryRedisState()) as unknown as Redis;\n }\n\n return new Redis(redisOptions);\n };\n\n const client = createClient();\n const publisherClient = createClient();\n const subscriberClient = createClient();\n\n try {\n // Wait for all three clients to be ready\n await Promise.all([\n new Promise<void>((resolve, reject) => {\n client.once('ready', () => resolve());\n client.once('error', (error: Error) => reject(error));\n }),\n new Promise<void>((resolve, reject) => {\n publisherClient.once('ready', () => resolve());\n publisherClient.once('error', (error: Error) => reject(error));\n }),\n new Promise<void>((resolve, reject) => {\n subscriberClient.once('ready', () => resolve());\n subscriberClient.once('error', (error: Error) => reject(error));\n }),\n ]);\n\n const redisInstance = new RedisInstance({\n redisManager: this,\n client,\n publisherClient,\n subscriberClient,\n });\n\n this.instances.push(redisInstance);\n\n const duration = performance.now() - startTime;\n const meta = {\n Host: this.options.host,\n Port: this.options.port,\n Duration: `${duration.toFixed(2)}ms`,\n Mode: useInMemoryRedis ? 'in-memory' : 'network',\n };\n\n if (this.options.applicationConfig.log?.startUp) {\n this.log('Connected', meta);\n } else {\n this.logger.debug({ message: 'Redis connected', meta });\n }\n\n if (useInMemoryRedis) {\n this.logger.debug({ message: 'Using in-memory Redis stub' });\n }\n\n return redisInstance;\n } catch (error) {\n const duration = performance.now() - startTime;\n\n // Clean up clients on error\n await Promise.allSettled([client.quit(), publisherClient.quit(), subscriberClient.quit()]);\n\n this.logger.error({\n error: error instanceof Error ? error : new Error(
|
|
5
|
-
"mappings": ";;AAAA,SAAS,aAAgC;AACzC,SAAS,oBAAoB;AAE7B,OAAO,mBAAmB;AAC1B,SAAS,cAAc;AACvB,SAAS,+BAA+B;
|
|
4
|
+
"sourcesContent": ["import { Redis, type RedisOptions } from 'ioredis';\nimport { EventEmitter } from 'node:events';\nimport type { RedisManagerConfig as RedisManagerOptions } from './manager.interface.js';\nimport RedisInstance from './instance.js';\nimport { Logger } from '../logger/index.js';\nimport { CachePerformanceWrapper } from '../performance/index.js';\nimport { safeSerializeError } from '../error/error-reporter.js';\n\nconst truthyPattern = /^(1|true|yes|on)$/i;\nconst scheduleMicrotask =\n typeof (globalThis as any).queueMicrotask === 'function'\n ? (globalThis as any).queueMicrotask.bind(globalThis)\n : (callback: () => void) => {\n void Promise.resolve().then(callback);\n };\n\ntype RedisCallback = (error: Error | null, result?: string) => void;\n\ninterface InMemoryRedisSharedState {\n store: Map<string, string | Buffer>;\n expirations: Map<string, NodeJS.Timeout>;\n subscriptions: Map<string, Set<InMemoryRedisClient>>;\n}\n\n// Global singleton shared state for in-memory Redis\nlet globalInMemoryRedisState: InMemoryRedisSharedState | null = null;\n\nfunction getGlobalInMemoryRedisState(): InMemoryRedisSharedState {\n globalInMemoryRedisState ??= {\n store: new Map<string, string | Buffer>(),\n expirations: new Map<string, NodeJS.Timeout>(),\n subscriptions: new Map<string, Set<InMemoryRedisClient>>(),\n };\n return globalInMemoryRedisState;\n}\n\nclass InMemoryRedisClient extends EventEmitter {\n private shared: InMemoryRedisSharedState;\n\n constructor(shared: InMemoryRedisSharedState) {\n super();\n this.shared = shared;\n\n scheduleMicrotask(() => {\n this.emit('ready');\n });\n }\n\n private cleanupSubscriptions(): void {\n for (const subscribers of this.shared.subscriptions.values()) {\n subscribers.delete(this);\n }\n }\n\n private clearExpirationForKey(key: string): void {\n const timer = this.shared.expirations.get(key);\n if (timer) {\n clearTimeout(timer);\n this.shared.expirations.delete(key);\n }\n }\n\n public ping(callback?: RedisCallback): Promise<string> {\n if (callback) {\n callback(null, 'PONG');\n return Promise.resolve('PONG');\n }\n\n return Promise.resolve('PONG');\n }\n\n public async set(...args: any[]): Promise<'OK'> {\n const [key, value, mode, expiration] = args;\n const serializedValue: string | Buffer = value instanceof Buffer ? value : String(value);\n\n this.shared.store.set(key, serializedValue);\n this.clearExpirationForKey(key);\n\n if (typeof mode === 'string' && mode.toUpperCase() === 'EX' && typeof expiration === 'number') {\n const timer = setTimeout(() => {\n this.shared.store.delete(key);\n this.shared.expirations.delete(key);\n }, expiration * 1000);\n\n if (typeof timer.unref === 'function') {\n timer.unref();\n }\n\n this.shared.expirations.set(key, timer);\n }\n\n return 'OK';\n }\n\n public async get(key: string): Promise<string | null> {\n return (this.shared.store.get(key) as string | undefined) ?? null;\n }\n\n public async del(key: string): Promise<number> {\n const existed = this.shared.store.delete(key);\n this.clearExpirationForKey(key);\n return existed ? 1 : 0;\n }\n\n public async publish(channel: string, message: string): Promise<number> {\n const subscribers = this.shared.subscriptions.get(channel);\n\n if (!subscribers || subscribers.size === 0) {\n return 0;\n }\n\n for (const subscriber of subscribers) {\n scheduleMicrotask(() => {\n subscriber.emit('message', channel, message);\n });\n }\n\n return subscribers.size;\n }\n\n public async subscribe(channel: string): Promise<number> {\n let subscribers = this.shared.subscriptions.get(channel);\n if (!subscribers) {\n subscribers = new Set<InMemoryRedisClient>();\n this.shared.subscriptions.set(channel, subscribers);\n }\n subscribers.add(this);\n return subscribers.size;\n }\n\n public async unsubscribe(channel: string): Promise<number> {\n const subscribers = this.shared.subscriptions.get(channel);\n\n if (!subscribers) {\n return 0;\n }\n\n subscribers.delete(this);\n return subscribers.size;\n }\n\n public async quit(): Promise<'OK'> {\n this.cleanupSubscriptions();\n this.emit('end');\n this.removeAllListeners();\n return 'OK';\n }\n\n public disconnect(): void {\n this.cleanupSubscriptions();\n this.emit('end');\n this.removeAllListeners();\n }\n}\n\nexport default class RedisManager {\n private logger: typeof Logger = Logger;\n\n private options: RedisManagerOptions;\n\n public instances: RedisInstance[] = [];\n\n constructor(config: RedisManagerOptions) {\n this.options = config;\n }\n\n public async connect(): Promise<RedisInstance> {\n return CachePerformanceWrapper.monitorConnection(\n 'connect',\n async () => {\n const startTime = performance.now();\n\n const redisOptions: RedisOptions = {\n host: this.options.host,\n port: this.options.port,\n password: this.options.password,\n maxRetriesPerRequest: null, // Needed for bullmq\n };\n\n const useInMemoryRedis =\n truthyPattern.test(process.env.PXL_REDIS_IN_MEMORY ?? '') ||\n truthyPattern.test(process.env.REDIS_IN_MEMORY ?? '');\n\n const createClient = (): Redis => {\n if (useInMemoryRedis) {\n return new InMemoryRedisClient(getGlobalInMemoryRedisState()) as unknown as Redis;\n }\n\n return new Redis(redisOptions);\n };\n\n const client = createClient();\n const publisherClient = createClient();\n const subscriberClient = createClient();\n\n try {\n // Wait for all three clients to be ready\n await Promise.all([\n new Promise<void>((resolve, reject) => {\n client.once('ready', () => resolve());\n client.once('error', (error: Error) => reject(error));\n }),\n new Promise<void>((resolve, reject) => {\n publisherClient.once('ready', () => resolve());\n publisherClient.once('error', (error: Error) => reject(error));\n }),\n new Promise<void>((resolve, reject) => {\n subscriberClient.once('ready', () => resolve());\n subscriberClient.once('error', (error: Error) => reject(error));\n }),\n ]);\n\n const redisInstance = new RedisInstance({\n redisManager: this,\n client,\n publisherClient,\n subscriberClient,\n });\n\n this.instances.push(redisInstance);\n\n const duration = performance.now() - startTime;\n const meta = {\n Host: this.options.host,\n Port: this.options.port,\n Duration: `${duration.toFixed(2)}ms`,\n Mode: useInMemoryRedis ? 'in-memory' : 'network',\n };\n\n if (this.options.applicationConfig.log?.startUp) {\n this.log('Connected', meta);\n } else {\n this.logger.debug({ message: 'Redis connected', meta });\n }\n\n if (useInMemoryRedis) {\n this.logger.debug({ message: 'Using in-memory Redis stub' });\n }\n\n return redisInstance;\n } catch (error) {\n const duration = performance.now() - startTime;\n\n // Clean up clients on error\n await Promise.allSettled([client.quit(), publisherClient.quit(), subscriberClient.quit()]);\n\n this.logger.error({\n error: error instanceof Error ? error : new Error(safeSerializeError(error)),\n message: 'Redis connection failed',\n meta: {\n Host: this.options.host,\n Port: this.options.port,\n Duration: `${duration.toFixed(2)}ms`,\n Mode: useInMemoryRedis ? 'in-memory' : 'network',\n },\n });\n\n throw error;\n }\n },\n { host: this.options.host, port: this.options.port },\n );\n }\n\n public async disconnect(): Promise<void> {\n await CachePerformanceWrapper.monitorConnection(\n 'disconnect',\n async () => {\n const startTime = performance.now();\n const instanceCount = this.instances.length;\n\n try {\n await Promise.all(this.instances.map(instance => instance.disconnect()));\n\n const duration = performance.now() - startTime;\n\n if (instanceCount > 0) {\n const meta = {\n Instances: instanceCount,\n Host: this.options.host,\n Port: this.options.port,\n Duration: `${duration.toFixed(2)}ms`,\n };\n\n if (this.options.applicationConfig.log?.startUp) {\n this.log('Disconnected all Redis instances', meta);\n } else {\n this.logger.debug({ message: 'Redis instances disconnected', meta });\n }\n }\n\n this.instances = [];\n } catch (error) {\n const duration = performance.now() - startTime;\n\n this.logger.error({\n error: error instanceof Error ? error : new Error(safeSerializeError(error)),\n message: 'Redis disconnection failed',\n meta: {\n Host: this.options.host,\n Port: this.options.port,\n Instances: instanceCount,\n Duration: `${duration.toFixed(2)}ms`,\n },\n });\n\n throw error;\n }\n },\n { host: this.options.host, port: this.options.port },\n );\n }\n\n /**\n * Log Redis message\n */\n public log(message: string, meta?: Record<string, unknown>): void {\n this.logger.custom({ level: 'redis', message, meta });\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Common Zod schemas for reuse across the framework
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Numeric ID schema (positive integer)
|
|
7
|
+
*/
|
|
8
|
+
export declare const NumericIdSchema: z.ZodCoercedNumber<unknown>;
|
|
9
|
+
/**
|
|
10
|
+
* UUID v4 schema
|
|
11
|
+
*/
|
|
12
|
+
export declare const UuidSchema: z.ZodString;
|
|
13
|
+
/**
|
|
14
|
+
* Optional numeric ID (for updates where ID may not be required)
|
|
15
|
+
*/
|
|
16
|
+
export declare const OptionalNumericIdSchema: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
17
|
+
/**
|
|
18
|
+
* Pagination query parameters schema
|
|
19
|
+
*/
|
|
20
|
+
export declare const PaginationQuerySchema: z.ZodObject<{
|
|
21
|
+
page: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
22
|
+
limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
23
|
+
}, z.core.$strip>;
|
|
24
|
+
/**
|
|
25
|
+
* Inferred type for pagination query
|
|
26
|
+
*/
|
|
27
|
+
export type PaginationQuery = z.infer<typeof PaginationQuerySchema>;
|
|
28
|
+
/**
|
|
29
|
+
* Paginated response wrapper schema
|
|
30
|
+
*/
|
|
31
|
+
export declare const createPaginatedResponseSchema: <T extends z.ZodTypeAny>(itemSchema: T) => z.ZodObject<{
|
|
32
|
+
data: z.ZodArray<T>;
|
|
33
|
+
total_items: z.ZodNumber;
|
|
34
|
+
page: z.ZodNumber;
|
|
35
|
+
total_pages: z.ZodNumber;
|
|
36
|
+
limit: z.ZodNumber;
|
|
37
|
+
}, z.core.$strip>;
|
|
38
|
+
/**
|
|
39
|
+
* Helper type for paginated response
|
|
40
|
+
*/
|
|
41
|
+
export type PaginatedResponse<T> = {
|
|
42
|
+
data: T[];
|
|
43
|
+
total_items: number;
|
|
44
|
+
page: number;
|
|
45
|
+
total_pages: number;
|
|
46
|
+
limit: number;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Sort order schema
|
|
50
|
+
*/
|
|
51
|
+
export declare const SortOrderSchema: z.ZodDefault<z.ZodEnum<{
|
|
52
|
+
ASC: "ASC";
|
|
53
|
+
DESC: "DESC";
|
|
54
|
+
asc: "asc";
|
|
55
|
+
desc: "desc";
|
|
56
|
+
}>>;
|
|
57
|
+
/**
|
|
58
|
+
* Generic sort query schema
|
|
59
|
+
*/
|
|
60
|
+
export declare const SortQuerySchema: z.ZodObject<{
|
|
61
|
+
sort: z.ZodOptional<z.ZodString>;
|
|
62
|
+
'sort-order': z.ZodOptional<z.ZodDefault<z.ZodEnum<{
|
|
63
|
+
ASC: "ASC";
|
|
64
|
+
DESC: "DESC";
|
|
65
|
+
asc: "asc";
|
|
66
|
+
desc: "desc";
|
|
67
|
+
}>>>;
|
|
68
|
+
}, z.core.$strip>;
|
|
69
|
+
/**
|
|
70
|
+
* Search query schema
|
|
71
|
+
*/
|
|
72
|
+
export declare const SearchQuerySchema: z.ZodObject<{
|
|
73
|
+
search: z.ZodOptional<z.ZodString>;
|
|
74
|
+
}, z.core.$strip>;
|
|
75
|
+
/**
|
|
76
|
+
* Combined list query schema (pagination + sorting + search)
|
|
77
|
+
*/
|
|
78
|
+
export declare const ListQuerySchema: z.ZodObject<{
|
|
79
|
+
page: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
80
|
+
limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
81
|
+
sort: z.ZodOptional<z.ZodString>;
|
|
82
|
+
'sort-order': z.ZodOptional<z.ZodDefault<z.ZodEnum<{
|
|
83
|
+
ASC: "ASC";
|
|
84
|
+
DESC: "DESC";
|
|
85
|
+
asc: "asc";
|
|
86
|
+
desc: "desc";
|
|
87
|
+
}>>>;
|
|
88
|
+
search: z.ZodOptional<z.ZodString>;
|
|
89
|
+
}, z.core.$strip>;
|
|
90
|
+
/**
|
|
91
|
+
* Inferred type for list query
|
|
92
|
+
*/
|
|
93
|
+
export type ListQuery = z.infer<typeof ListQuerySchema>;
|
|
94
|
+
/**
|
|
95
|
+
* Success response wrapper schema
|
|
96
|
+
*/
|
|
97
|
+
export declare const createSuccessResponseSchema: <T extends z.ZodTypeAny>(dataSchema: T) => z.ZodObject<{
|
|
98
|
+
data: T;
|
|
99
|
+
}, z.core.$strip>;
|
|
100
|
+
/**
|
|
101
|
+
* Error response schema
|
|
102
|
+
*/
|
|
103
|
+
export declare const ErrorResponseSchema: z.ZodObject<{
|
|
104
|
+
error: z.ZodString;
|
|
105
|
+
message: z.ZodOptional<z.ZodString>;
|
|
106
|
+
statusCode: z.ZodOptional<z.ZodNumber>;
|
|
107
|
+
details: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
108
|
+
}, z.core.$strip>;
|
|
109
|
+
/**
|
|
110
|
+
* Inferred type for error response
|
|
111
|
+
*/
|
|
112
|
+
export type ErrorResponse = z.infer<typeof ErrorResponseSchema>;
|
|
113
|
+
/**
|
|
114
|
+
* Generic API response schema (success or error)
|
|
115
|
+
*/
|
|
116
|
+
export declare const createApiResponseSchema: <T extends z.ZodTypeAny>(dataSchema: T) => z.ZodUnion<readonly [z.ZodObject<{
|
|
117
|
+
data: T;
|
|
118
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
119
|
+
error: z.ZodString;
|
|
120
|
+
message: z.ZodOptional<z.ZodString>;
|
|
121
|
+
statusCode: z.ZodOptional<z.ZodNumber>;
|
|
122
|
+
details: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
123
|
+
}, z.core.$strip>]>;
|
|
124
|
+
/**
|
|
125
|
+
* Email schema
|
|
126
|
+
*/
|
|
127
|
+
export declare const EmailSchema: z.ZodString;
|
|
128
|
+
/**
|
|
129
|
+
* URL schema
|
|
130
|
+
*/
|
|
131
|
+
export declare const UrlSchema: z.ZodString;
|
|
132
|
+
/**
|
|
133
|
+
* Phone number schema (basic validation)
|
|
134
|
+
*/
|
|
135
|
+
export declare const PhoneSchema: z.ZodString;
|
|
136
|
+
/**
|
|
137
|
+
* Date string schema (ISO 8601)
|
|
138
|
+
*/
|
|
139
|
+
export declare const DateStringSchema: z.ZodString;
|
|
140
|
+
/**
|
|
141
|
+
* Non-empty string schema
|
|
142
|
+
*/
|
|
143
|
+
export declare const NonEmptyStringSchema: z.ZodString;
|
|
144
|
+
/**
|
|
145
|
+
* Trimmed non-empty string schema
|
|
146
|
+
*/
|
|
147
|
+
export declare const TrimmedStringSchema: z.ZodString;
|
|
148
|
+
/**
|
|
149
|
+
* Boolean schema with string coercion
|
|
150
|
+
*/
|
|
151
|
+
export declare const BooleanSchema: z.ZodPipe<z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>, z.ZodTransform<boolean, string | boolean>>;
|
|
152
|
+
/**
|
|
153
|
+
* Created/Updated timestamp schema
|
|
154
|
+
*/
|
|
155
|
+
export declare const TimestampSchema: z.ZodObject<{
|
|
156
|
+
createdAt: z.ZodDate;
|
|
157
|
+
updatedAt: z.ZodDate;
|
|
158
|
+
}, z.core.$strip>;
|
|
159
|
+
/**
|
|
160
|
+
* Optional timestamp schema
|
|
161
|
+
*/
|
|
162
|
+
export declare const OptionalTimestampSchema: z.ZodObject<{
|
|
163
|
+
createdAt: z.ZodOptional<z.ZodDate>;
|
|
164
|
+
updatedAt: z.ZodOptional<z.ZodDate>;
|
|
165
|
+
}, z.core.$strip>;
|
|
166
|
+
/**
|
|
167
|
+
* Comma-separated string to array transformer
|
|
168
|
+
*/
|
|
169
|
+
export declare const CommaSeparatedStringSchema: z.ZodPipe<z.ZodString, z.ZodTransform<string[], string>>;
|
|
170
|
+
/**
|
|
171
|
+
* JSON string schema (parses JSON string to object)
|
|
172
|
+
*/
|
|
173
|
+
export declare const JsonStringSchema: z.ZodPipe<z.ZodString, z.ZodTransform<any, string>>;
|
|
174
|
+
/**
|
|
175
|
+
* Health check response schema
|
|
176
|
+
*/
|
|
177
|
+
export declare const HealthCheckResponseSchema: z.ZodObject<{
|
|
178
|
+
status: z.ZodEnum<{
|
|
179
|
+
healthy: "healthy";
|
|
180
|
+
unhealthy: "unhealthy";
|
|
181
|
+
degraded: "degraded";
|
|
182
|
+
}>;
|
|
183
|
+
timestamp: z.ZodString;
|
|
184
|
+
services: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
185
|
+
status: z.ZodEnum<{
|
|
186
|
+
degraded: "degraded";
|
|
187
|
+
up: "up";
|
|
188
|
+
down: "down";
|
|
189
|
+
}>;
|
|
190
|
+
message: z.ZodOptional<z.ZodString>;
|
|
191
|
+
}, z.core.$strip>>>;
|
|
192
|
+
}, z.core.$strip>;
|
|
193
|
+
/**
|
|
194
|
+
* Inferred type for health check response
|
|
195
|
+
*/
|
|
196
|
+
export type HealthCheckResponse = z.infer<typeof HealthCheckResponseSchema>;
|
|
197
|
+
//# sourceMappingURL=common.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/schemas/common.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;GAEG;AAMH;;GAEG;AACH,eAAO,MAAM,eAAe,6BAAqC,CAAC;AAElE;;GAEG;AACH,eAAO,MAAM,UAAU,aAAoB,CAAC;AAE5C;;GAEG;AACH,eAAO,MAAM,uBAAuB,4CAA6B,CAAC;AAMlE;;GAEG;AACH,eAAO,MAAM,qBAAqB;;;iBAGhC,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;;GAEG;AACH,eAAO,MAAM,6BAA6B,GAAI,CAAC,SAAS,CAAC,CAAC,UAAU,EAAE,YAAY,CAAC;;;;;;iBAQlF,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,iBAAiB,CAAC,CAAC,IAAI;IACjC,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAMF;;GAEG;AACH,eAAO,MAAM,eAAe;;;;;GAAwD,CAAC;AAErF;;GAEG;AACH,eAAO,MAAM,eAAe;;;;;;;;iBAG1B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,iBAAiB;;iBAE5B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;iBAAwE,CAAC;AAErG;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAMxD;;GAEG;AACH,eAAO,MAAM,2BAA2B,GAAI,CAAC,SAAS,CAAC,CAAC,UAAU,EAAE,YAAY,CAAC;;iBAIhF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;;iBAK9B,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE;;GAEG;AACH,eAAO,MAAM,uBAAuB,GAAI,CAAC,SAAS,CAAC,CAAC,UAAU,EAAE,YAAY,CAAC;;;;;;;mBAE5E,CAAC;AAMF;;GAEG;AACH,eAAO,MAAM,WAAW,aAAqB,CAAC;AAE9C;;GAEG;AACH,eAAO,MAAM,SAAS,aAAmB,CAAC;AAE1C;;GAEG;AACH,eAAO,MAAM,WAAW,aAAyC,CAAC;AAElE;;GAEG;AACH,eAAO,MAAM,gBAAgB,aAAwB,CAAC;AAEtD;;GAEG;AACH,eAAO,MAAM,oBAAoB,aAAoB,CAAC;AAEtD;;GAEG;AACH,eAAO,MAAM,mBAAmB,aAA2B,CAAC;AAE5D;;GAEG;AACH,eAAO,MAAM,aAAa,wGAExB,CAAC;AAMH;;GAEG;AACH,eAAO,MAAM,eAAe;;;iBAG1B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;iBAGlC,CAAC;AAMH;;GAEG;AACH,eAAO,MAAM,0BAA0B,0DAErC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,gBAAgB,qDAO3B,CAAC;AAMH;;GAEG;AACH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;iBAYpC,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
const NumericIdSchema = z.coerce.number().int().positive();
|
|
5
|
+
const UuidSchema = z.string().uuid();
|
|
6
|
+
const OptionalNumericIdSchema = NumericIdSchema.optional();
|
|
7
|
+
const PaginationQuerySchema = z.object({
|
|
8
|
+
page: z.coerce.number().int().positive().default(1),
|
|
9
|
+
limit: z.coerce.number().int().positive().max(100).default(20)
|
|
10
|
+
});
|
|
11
|
+
const createPaginatedResponseSchema = /* @__PURE__ */ __name((itemSchema) => {
|
|
12
|
+
return z.object({
|
|
13
|
+
data: z.array(itemSchema),
|
|
14
|
+
total_items: z.number().int().nonnegative(),
|
|
15
|
+
page: z.number().int().positive(),
|
|
16
|
+
total_pages: z.number().int().nonnegative(),
|
|
17
|
+
limit: z.number().int().positive()
|
|
18
|
+
});
|
|
19
|
+
}, "createPaginatedResponseSchema");
|
|
20
|
+
const SortOrderSchema = z.enum(["ASC", "DESC", "asc", "desc"]).default("ASC");
|
|
21
|
+
const SortQuerySchema = z.object({
|
|
22
|
+
sort: z.string().optional(),
|
|
23
|
+
"sort-order": SortOrderSchema.optional()
|
|
24
|
+
});
|
|
25
|
+
const SearchQuerySchema = z.object({
|
|
26
|
+
search: z.string().min(1).optional()
|
|
27
|
+
});
|
|
28
|
+
const ListQuerySchema = PaginationQuerySchema.merge(SortQuerySchema).merge(SearchQuerySchema);
|
|
29
|
+
const createSuccessResponseSchema = /* @__PURE__ */ __name((dataSchema) => {
|
|
30
|
+
return z.object({
|
|
31
|
+
data: dataSchema
|
|
32
|
+
});
|
|
33
|
+
}, "createSuccessResponseSchema");
|
|
34
|
+
const ErrorResponseSchema = z.object({
|
|
35
|
+
error: z.string(),
|
|
36
|
+
message: z.string().optional(),
|
|
37
|
+
statusCode: z.number().int().optional(),
|
|
38
|
+
details: z.record(z.string(), z.unknown()).optional()
|
|
39
|
+
});
|
|
40
|
+
const createApiResponseSchema = /* @__PURE__ */ __name((dataSchema) => {
|
|
41
|
+
return z.union([createSuccessResponseSchema(dataSchema), ErrorResponseSchema]);
|
|
42
|
+
}, "createApiResponseSchema");
|
|
43
|
+
const EmailSchema = z.string().email();
|
|
44
|
+
const UrlSchema = z.string().url();
|
|
45
|
+
const PhoneSchema = z.string().regex(/^\+?[1-9]\d{1,14}$/);
|
|
46
|
+
const DateStringSchema = z.string().datetime();
|
|
47
|
+
const NonEmptyStringSchema = z.string().min(1);
|
|
48
|
+
const TrimmedStringSchema = z.string().trim().min(1);
|
|
49
|
+
const BooleanSchema = z.union([z.boolean(), z.string()]).transform((val) => {
|
|
50
|
+
return typeof val === "string" ? val === "true" : val;
|
|
51
|
+
});
|
|
52
|
+
const TimestampSchema = z.object({
|
|
53
|
+
createdAt: z.date(),
|
|
54
|
+
updatedAt: z.date()
|
|
55
|
+
});
|
|
56
|
+
const OptionalTimestampSchema = z.object({
|
|
57
|
+
createdAt: z.date().optional(),
|
|
58
|
+
updatedAt: z.date().optional()
|
|
59
|
+
});
|
|
60
|
+
const CommaSeparatedStringSchema = z.string().transform((val) => {
|
|
61
|
+
return val.split(",").map((item) => item.trim());
|
|
62
|
+
});
|
|
63
|
+
const JsonStringSchema = z.string().transform((str, _ctx) => {
|
|
64
|
+
try {
|
|
65
|
+
return JSON.parse(str);
|
|
66
|
+
} catch {
|
|
67
|
+
_ctx.addIssue({ code: "custom", message: "Invalid JSON string" });
|
|
68
|
+
return z.NEVER;
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
const HealthCheckResponseSchema = z.object({
|
|
72
|
+
status: z.enum(["healthy", "unhealthy", "degraded"]),
|
|
73
|
+
timestamp: z.string().datetime(),
|
|
74
|
+
services: z.record(
|
|
75
|
+
z.string(),
|
|
76
|
+
z.object({
|
|
77
|
+
status: z.enum(["up", "down", "degraded"]),
|
|
78
|
+
message: z.string().optional()
|
|
79
|
+
})
|
|
80
|
+
).optional()
|
|
81
|
+
});
|
|
82
|
+
export {
|
|
83
|
+
BooleanSchema,
|
|
84
|
+
CommaSeparatedStringSchema,
|
|
85
|
+
DateStringSchema,
|
|
86
|
+
EmailSchema,
|
|
87
|
+
ErrorResponseSchema,
|
|
88
|
+
HealthCheckResponseSchema,
|
|
89
|
+
JsonStringSchema,
|
|
90
|
+
ListQuerySchema,
|
|
91
|
+
NonEmptyStringSchema,
|
|
92
|
+
NumericIdSchema,
|
|
93
|
+
OptionalNumericIdSchema,
|
|
94
|
+
OptionalTimestampSchema,
|
|
95
|
+
PaginationQuerySchema,
|
|
96
|
+
PhoneSchema,
|
|
97
|
+
SearchQuerySchema,
|
|
98
|
+
SortOrderSchema,
|
|
99
|
+
SortQuerySchema,
|
|
100
|
+
TimestampSchema,
|
|
101
|
+
TrimmedStringSchema,
|
|
102
|
+
UrlSchema,
|
|
103
|
+
UuidSchema,
|
|
104
|
+
createApiResponseSchema,
|
|
105
|
+
createPaginatedResponseSchema,
|
|
106
|
+
createSuccessResponseSchema
|
|
107
|
+
};
|
|
108
|
+
//# sourceMappingURL=common.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/schemas/common.ts"],
|
|
4
|
+
"sourcesContent": ["import { z } from 'zod';\n\n/**\n * Common Zod schemas for reuse across the framework\n */\n\n// ============================================================================\n// ID Schemas\n// ============================================================================\n\n/**\n * Numeric ID schema (positive integer)\n */\nexport const NumericIdSchema = z.coerce.number().int().positive();\n\n/**\n * UUID v4 schema\n */\nexport const UuidSchema = z.string().uuid();\n\n/**\n * Optional numeric ID (for updates where ID may not be required)\n */\nexport const OptionalNumericIdSchema = NumericIdSchema.optional();\n\n// ============================================================================\n// Pagination Schemas\n// ============================================================================\n\n/**\n * Pagination query parameters schema\n */\nexport const PaginationQuerySchema = z.object({\n page: z.coerce.number().int().positive().default(1),\n limit: z.coerce.number().int().positive().max(100).default(20),\n});\n\n/**\n * Inferred type for pagination query\n */\nexport type PaginationQuery = z.infer<typeof PaginationQuerySchema>;\n\n/**\n * Paginated response wrapper schema\n */\nexport const createPaginatedResponseSchema = <T extends z.ZodTypeAny>(itemSchema: T) => {\n return z.object({\n data: z.array(itemSchema),\n total_items: z.number().int().nonnegative(),\n page: z.number().int().positive(),\n total_pages: z.number().int().nonnegative(),\n limit: z.number().int().positive(),\n });\n};\n\n/**\n * Helper type for paginated response\n */\nexport type PaginatedResponse<T> = {\n data: T[];\n total_items: number;\n page: number;\n total_pages: number;\n limit: number;\n};\n\n// ============================================================================\n// Sorting & Filtering Schemas\n// ============================================================================\n\n/**\n * Sort order schema\n */\nexport const SortOrderSchema = z.enum(['ASC', 'DESC', 'asc', 'desc']).default('ASC');\n\n/**\n * Generic sort query schema\n */\nexport const SortQuerySchema = z.object({\n sort: z.string().optional(),\n 'sort-order': SortOrderSchema.optional(),\n});\n\n/**\n * Search query schema\n */\nexport const SearchQuerySchema = z.object({\n search: z.string().min(1).optional(),\n});\n\n/**\n * Combined list query schema (pagination + sorting + search)\n */\nexport const ListQuerySchema = PaginationQuerySchema.merge(SortQuerySchema).merge(SearchQuerySchema);\n\n/**\n * Inferred type for list query\n */\nexport type ListQuery = z.infer<typeof ListQuerySchema>;\n\n// ============================================================================\n// Response Schemas\n// ============================================================================\n\n/**\n * Success response wrapper schema\n */\nexport const createSuccessResponseSchema = <T extends z.ZodTypeAny>(dataSchema: T) => {\n return z.object({\n data: dataSchema,\n });\n};\n\n/**\n * Error response schema\n */\nexport const ErrorResponseSchema = z.object({\n error: z.string(),\n message: z.string().optional(),\n statusCode: z.number().int().optional(),\n details: z.record(z.string(), z.unknown()).optional(),\n});\n\n/**\n * Inferred type for error response\n */\nexport type ErrorResponse = z.infer<typeof ErrorResponseSchema>;\n\n/**\n * Generic API response schema (success or error)\n */\nexport const createApiResponseSchema = <T extends z.ZodTypeAny>(dataSchema: T) => {\n return z.union([createSuccessResponseSchema(dataSchema), ErrorResponseSchema]);\n};\n\n// ============================================================================\n// Common Field Schemas\n// ============================================================================\n\n/**\n * Email schema\n */\nexport const EmailSchema = z.string().email();\n\n/**\n * URL schema\n */\nexport const UrlSchema = z.string().url();\n\n/**\n * Phone number schema (basic validation)\n */\nexport const PhoneSchema = z.string().regex(/^\\+?[1-9]\\d{1,14}$/);\n\n/**\n * Date string schema (ISO 8601)\n */\nexport const DateStringSchema = z.string().datetime();\n\n/**\n * Non-empty string schema\n */\nexport const NonEmptyStringSchema = z.string().min(1);\n\n/**\n * Trimmed non-empty string schema\n */\nexport const TrimmedStringSchema = z.string().trim().min(1);\n\n/**\n * Boolean schema with string coercion\n */\nexport const BooleanSchema = z.union([z.boolean(), z.string()]).transform(val => {\n return typeof val === 'string' ? val === 'true' : val;\n});\n\n// ============================================================================\n// Timestamp Schemas\n// ============================================================================\n\n/**\n * Created/Updated timestamp schema\n */\nexport const TimestampSchema = z.object({\n createdAt: z.date(),\n updatedAt: z.date(),\n});\n\n/**\n * Optional timestamp schema\n */\nexport const OptionalTimestampSchema = z.object({\n createdAt: z.date().optional(),\n updatedAt: z.date().optional(),\n});\n\n// ============================================================================\n// Utility Schemas\n// ============================================================================\n\n/**\n * Comma-separated string to array transformer\n */\nexport const CommaSeparatedStringSchema = z.string().transform(val => {\n return val.split(',').map(item => item.trim());\n});\n\n/**\n * JSON string schema (parses JSON string to object)\n */\nexport const JsonStringSchema = z.string().transform((str, _ctx) => {\n try {\n return JSON.parse(str);\n } catch {\n _ctx.addIssue({ code: 'custom', message: 'Invalid JSON string' });\n return z.NEVER;\n }\n});\n\n// ============================================================================\n// Health Check Schemas\n// ============================================================================\n\n/**\n * Health check response schema\n */\nexport const HealthCheckResponseSchema = z.object({\n status: z.enum(['healthy', 'unhealthy', 'degraded']),\n timestamp: z.string().datetime(),\n services: z\n .record(\n z.string(),\n z.object({\n status: z.enum(['up', 'down', 'degraded']),\n message: z.string().optional(),\n }),\n )\n .optional(),\n});\n\n/**\n * Inferred type for health check response\n */\nexport type HealthCheckResponse = z.infer<typeof HealthCheckResponseSchema>;\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Options for building standardized entity schemas.
|
|
4
|
+
* - shape: base create shape (required fields for creation)
|
|
5
|
+
* - updatableFields: subset of keys allowed in updates (defaults to all keys of shape)
|
|
6
|
+
* - readAugment: additional fields present on the persisted/read model (e.g. id, timestamps)
|
|
7
|
+
* - strict: apply .strict() to objects (defaults true)
|
|
8
|
+
*/
|
|
9
|
+
export interface BuildEntitySchemasOptions<Shape extends z.ZodRawShape, Updatable extends keyof Shape = keyof Shape, ReadAugment extends z.ZodRawShape = {}> {
|
|
10
|
+
shape: Shape;
|
|
11
|
+
updatableFields?: readonly Updatable[];
|
|
12
|
+
readAugment?: ReadAugment;
|
|
13
|
+
strict?: boolean;
|
|
14
|
+
requireAtLeastOneOnUpdate?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface BuiltEntitySchemas<Shape extends z.ZodRawShape, Updatable extends keyof Shape, ReadAugment extends z.ZodRawShape> {
|
|
17
|
+
create: z.ZodObject<Shape>;
|
|
18
|
+
/** Update schema is a partial over selected updatable keys. */
|
|
19
|
+
update: z.ZodTypeAny;
|
|
20
|
+
read: z.ZodObject<Shape & ReadAugment>;
|
|
21
|
+
keys: (keyof Shape)[];
|
|
22
|
+
updatableKeys: Updatable[];
|
|
23
|
+
}
|
|
24
|
+
export declare function buildEntitySchemas<Shape extends z.ZodRawShape, Updatable extends keyof Shape = keyof Shape, ReadAugment extends z.ZodRawShape = {}>(options: BuildEntitySchemasOptions<Shape, Updatable, ReadAugment>): BuiltEntitySchemas<Shape, Updatable, ReadAugment>;
|
|
25
|
+
export declare const HttpMethodSchema: z.ZodEnum<{
|
|
26
|
+
GET: "GET";
|
|
27
|
+
POST: "POST";
|
|
28
|
+
PUT: "PUT";
|
|
29
|
+
DELETE: "DELETE";
|
|
30
|
+
HEAD: "HEAD";
|
|
31
|
+
PATCH: "PATCH";
|
|
32
|
+
OPTIONS: "OPTIONS";
|
|
33
|
+
}>;
|
|
34
|
+
export declare const HttpStatusCodeSchema: z.core.$ZodBranded<z.ZodNumber, "HttpStatusCode">;
|
|
35
|
+
//# sourceMappingURL=entity-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entity-builder.d.ts","sourceRoot":"","sources":["../../src/schemas/entity-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;GAMG;AACH,MAAM,WAAW,yBAAyB,CACxC,KAAK,SAAS,CAAC,CAAC,WAAW,EAC3B,SAAS,SAAS,MAAM,KAAK,GAAG,MAAM,KAAK,EAC3C,WAAW,SAAS,CAAC,CAAC,WAAW,GAAG,EAAE;IAEtC,KAAK,EAAE,KAAK,CAAC;IACb,eAAe,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;IACvC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,yBAAyB,CAAC,EAAE,OAAO,CAAC;CACrC;AAED,MAAM,WAAW,kBAAkB,CACjC,KAAK,SAAS,CAAC,CAAC,WAAW,EAC3B,SAAS,SAAS,MAAM,KAAK,EAC7B,WAAW,SAAS,CAAC,CAAC,WAAW;IAEjC,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC3B,+DAA+D;IAC/D,MAAM,EAAE,CAAC,CAAC,UAAU,CAAC;IACrB,IAAI,EAAE,CAAC,CAAC,SAAS,CAAC,KAAK,GAAG,WAAW,CAAC,CAAC;IACvC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;IACtB,aAAa,EAAE,SAAS,EAAE,CAAC;CAC5B;AAED,wBAAgB,kBAAkB,CAChC,KAAK,SAAS,CAAC,CAAC,WAAW,EAC3B,SAAS,SAAS,MAAM,KAAK,GAAG,MAAM,KAAK,EAC3C,WAAW,SAAS,CAAC,CAAC,WAAW,GAAG,EAAE,EAEtC,OAAO,EAAE,yBAAyB,CAAC,KAAK,EAAE,SAAS,EAAE,WAAW,CAAC,GAChE,kBAAkB,CAAC,KAAK,EAAE,SAAS,EAAE,WAAW,CAAC,CAoCnD;AAGD,eAAO,MAAM,gBAAgB;;;;;;;;EAAuE,CAAC;AACrG,eAAO,MAAM,oBAAoB,mDAA+D,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
function buildEntitySchemas(options) {
|
|
5
|
+
const { shape, updatableFields, readAugment, strict = true, requireAtLeastOneOnUpdate = true } = options;
|
|
6
|
+
Object.freeze(shape);
|
|
7
|
+
const create = strict ? z.object(shape).strict() : z.object(shape);
|
|
8
|
+
const updatableKeys = updatableFields ? [...updatableFields] : Object.keys(shape);
|
|
9
|
+
const pickMask = updatableKeys.reduce((acc, key) => {
|
|
10
|
+
acc[String(key)] = true;
|
|
11
|
+
return acc;
|
|
12
|
+
}, {});
|
|
13
|
+
const updateBase = updatableFields ? create.pick(pickMask) : create;
|
|
14
|
+
let updateObject = updateBase.partial();
|
|
15
|
+
if (requireAtLeastOneOnUpdate) {
|
|
16
|
+
updateObject = updateObject.refine(
|
|
17
|
+
(value) => !!value && typeof value === "object" && Object.keys(value).length > 0,
|
|
18
|
+
"At least one field must be provided for update"
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
const readShape = { ...shape, ...readAugment ?? {} };
|
|
22
|
+
const read = strict ? z.object(readShape).strict() : z.object(readShape);
|
|
23
|
+
return {
|
|
24
|
+
create,
|
|
25
|
+
update: updateObject,
|
|
26
|
+
read,
|
|
27
|
+
keys: Object.keys(shape),
|
|
28
|
+
updatableKeys
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
__name(buildEntitySchemas, "buildEntitySchemas");
|
|
32
|
+
const HttpMethodSchema = z.enum(["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"]);
|
|
33
|
+
const HttpStatusCodeSchema = z.number().int().min(100).max(599).brand();
|
|
34
|
+
export {
|
|
35
|
+
HttpMethodSchema,
|
|
36
|
+
HttpStatusCodeSchema,
|
|
37
|
+
buildEntitySchemas
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=entity-builder.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/schemas/entity-builder.ts"],
|
|
4
|
+
"sourcesContent": ["import { z } from 'zod';\n\n/**\n * Options for building standardized entity schemas.\n * - shape: base create shape (required fields for creation)\n * - updatableFields: subset of keys allowed in updates (defaults to all keys of shape)\n * - readAugment: additional fields present on the persisted/read model (e.g. id, timestamps)\n * - strict: apply .strict() to objects (defaults true)\n */\nexport interface BuildEntitySchemasOptions<\n Shape extends z.ZodRawShape,\n Updatable extends keyof Shape = keyof Shape,\n ReadAugment extends z.ZodRawShape = {},\n> {\n shape: Shape;\n updatableFields?: readonly Updatable[];\n readAugment?: ReadAugment; // fields that exist after persistence (e.g. id, createdAt)\n strict?: boolean;\n requireAtLeastOneOnUpdate?: boolean; // default true\n}\n\nexport interface BuiltEntitySchemas<\n Shape extends z.ZodRawShape,\n Updatable extends keyof Shape,\n ReadAugment extends z.ZodRawShape,\n> {\n create: z.ZodObject<Shape>;\n /** Update schema is a partial over selected updatable keys. */\n update: z.ZodTypeAny;\n read: z.ZodObject<Shape & ReadAugment>;\n keys: (keyof Shape)[];\n updatableKeys: Updatable[];\n}\n\nexport function buildEntitySchemas<\n Shape extends z.ZodRawShape,\n Updatable extends keyof Shape = keyof Shape,\n ReadAugment extends z.ZodRawShape = {},\n>(\n options: BuildEntitySchemasOptions<Shape, Updatable, ReadAugment>,\n): BuiltEntitySchemas<Shape, Updatable, ReadAugment> {\n const { shape, updatableFields, readAugment, strict = true, requireAtLeastOneOnUpdate = true } = options;\n\n // Freeze to avoid accidental mutation\n Object.freeze(shape);\n\n const create = strict ? z.object(shape).strict() : z.object(shape);\n\n const updatableKeys = updatableFields ? [...updatableFields] : (Object.keys(shape) as Updatable[]);\n // Build pick mask for updatable keys\n const pickMask = updatableKeys.reduce<Record<string, true>>((acc, key) => {\n acc[String(key)] = true;\n return acc;\n }, {});\n\n const updateBase = updatableFields ? (create as z.ZodObject<any>).pick(pickMask) : (create as z.ZodObject<any>);\n let updateObject: z.ZodTypeAny = updateBase.partial();\n\n if (requireAtLeastOneOnUpdate) {\n updateObject = updateObject.refine(\n (value: unknown) =>\n !!value && typeof value === 'object' && Object.keys(value as Record<string, unknown>).length > 0,\n 'At least one field must be provided for update',\n );\n }\n\n const readShape = { ...shape, ...(readAugment ?? {}) } as Shape & ReadAugment;\n const read = strict ? z.object(readShape).strict() : z.object(readShape);\n\n return {\n create,\n update: updateObject,\n read: read as z.ZodObject<Shape & ReadAugment>,\n keys: Object.keys(shape) as (keyof Shape)[],\n updatableKeys,\n };\n}\n\n// Common atoms for reuse in entity schemas\nexport const HttpMethodSchema = z.enum(['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS']);\nexport const HttpStatusCodeSchema = z.number().int().min(100).max(599).brand<'HttpStatusCode'>();\n"],
|
|
5
|
+
"mappings": ";;AAAA,SAAS,SAAS;AAkCX,SAAS,mBAKd,SACmD;AACnD,QAAM,EAAE,OAAO,iBAAiB,aAAa,SAAS,MAAM,4BAA4B,KAAK,IAAI;AAGjG,SAAO,OAAO,KAAK;AAEnB,QAAM,SAAS,SAAS,EAAE,OAAO,KAAK,EAAE,OAAO,IAAI,EAAE,OAAO,KAAK;AAEjE,QAAM,gBAAgB,kBAAkB,CAAC,GAAG,eAAe,IAAK,OAAO,KAAK,KAAK;AAEjF,QAAM,WAAW,cAAc,OAA6B,CAAC,KAAK,QAAQ;AACxE,QAAI,OAAO,GAAG,CAAC,IAAI;AACnB,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AAEL,QAAM,aAAa,kBAAmB,OAA4B,KAAK,QAAQ,IAAK;AACpF,MAAI,eAA6B,WAAW,QAAQ;AAEpD,MAAI,2BAA2B;AAC7B,mBAAe,aAAa;AAAA,MAC1B,CAAC,UACC,CAAC,CAAC,SAAS,OAAO,UAAU,YAAY,OAAO,KAAK,KAAgC,EAAE,SAAS;AAAA,MACjG;AAAA,IACF;AAAA,EACF;AAEA,QAAM,YAAY,EAAE,GAAG,OAAO,GAAI,eAAe,CAAC,EAAG;AACrD,QAAM,OAAO,SAAS,EAAE,OAAO,SAAS,EAAE,OAAO,IAAI,EAAE,OAAO,SAAS;AAEvE,SAAO;AAAA,IACL;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA,MAAM,OAAO,KAAK,KAAK;AAAA,IACvB;AAAA,EACF;AACF;AA1CgB;AA6CT,MAAM,mBAAmB,EAAE,KAAK,CAAC,OAAO,QAAQ,OAAO,UAAU,SAAS,QAAQ,SAAS,CAAC;AAC5F,MAAM,uBAAuB,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,GAAG,EAAE,IAAI,GAAG,EAAE,MAAwB;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/schemas/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,aAAa,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/util/loader.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,SAAS,CAAC,CAAC,GAAG,OAAO;IACpC,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,CAAC;CAClB;
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/util/loader.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,SAAS,CAAC,CAAC,GAAG,OAAO;IACpC,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,CAAC;CAClB;AAiFD,MAAM,MAAM,WAAW,CAAC,CAAC,GAAG,OAAO,IAAI,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;;6BAnE/B,CAAC,wCAGpC;QACD,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;KACvB,KAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;uBA+DO,CAAC,gDAG9B;QACD,iBAAiB,EAAE,MAAM,CAAC;QAC1B,UAAU,EAAE,MAAM,CAAC;KACpB,KAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;4BAkCE,IAAI;yBAKP;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE;;AAO3E,wBAKE"}
|
package/dist/util/loader.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/util/loader.ts"],
|
|
4
|
-
"sourcesContent": ["import fs from 'fs';\nimport path from 'path';\nimport { LRUCache } from 'lru-cache';\nimport { Helper } from './index.js';\n\n// Type for a map of loaded modules\nexport interface ModuleMap<T = unknown> {\n [key: string]: T;\n}\n\n// Cache for loaded modules to avoid repeated imports\n// Using LRU cache to prevent unbounded memory growth in long-running processes\nconst moduleCache = new LRUCache<string, ModuleMap>({\n max: 100, // Max 100 directories cached\n ttl: 1000 * 60 * 10, // 10 minutes\n});\n\nconst entityCache = new LRUCache<string, EntityClass>({\n max: 500, // Max 500 entities cached (accessed more frequently than modules)\n ttl: 1000 * 60 * 10, // 10 minutes\n});\n\nconst loadModulesInDirectory = async <T = unknown>({\n directory,\n extensions,\n}: {\n directory: string;\n extensions?: string[];\n}): Promise<ModuleMap<T>> => {\n // Create cache key based on directory and extensions\n const cacheKey = `${directory}:${extensions?.join(',') ?? 'all'}`;\n\n // Check cache first\n if (moduleCache.has(cacheKey)) {\n const cachedModule = moduleCache.get(cacheKey);\n if (cachedModule) {\n return cachedModule as ModuleMap<T>;\n }\n }\n\n const loadedModules: ModuleMap<T> = {};\n\n // Use readdir with withFileTypes option to avoid separate stat calls\n const dirents = await fs.promises.readdir(directory, { withFileTypes: true });\n\n for (const dirent of dirents) {\n // Skip directories without needing stat call\n if (dirent.isDirectory()) {\n continue;\n }\n\n const file = dirent.name;\n const ext = path.extname(file);\n const isDeclarationFile = file.endsWith('.d.ts');\n\n // Skip files that are not in the specified extensions or are .d.ts files\n if ((extensions && extensions.length > 0 && !extensions.includes(ext)) || isDeclarationFile) {\n continue;\n }\n\n const moduleName = path.basename(file, ext);\n const filePath = path.join(directory, file);\n // Convert to absolute path for ESM import\n const absolutePath = path.isAbsolute(filePath) ? filePath : path.resolve(filePath);\n // Use file:// URL for Windows compatibility\n const fileUrl = `file://${absolutePath.replace(/\\\\/g, '/')}`;\n\n try {\n const importedModule = await import(fileUrl);\n\n // Use safe property assignment to prevent prototype pollution\n if (moduleName !== '__proto__' && moduleName !== 'constructor' && moduleName !== 'prototype') {\n // Prefer default export, but fall back to the entire module if no default\n const moduleExport = importedModule.default ?? importedModule;\n Reflect.set(loadedModules, moduleName, moduleExport);\n }\n } catch (error) {\n console.error(`Failed to import module ${filePath}:`, error);\n }\n }\n\n // Cache the results for future use\n moduleCache.set(cacheKey, loadedModules);\n\n return loadedModules;\n};\n\n// Type constraint for entity classes (must be constructable)\nexport type EntityClass<T = unknown> = new (...args: unknown[]) => T;\n\nconst loadEntityModule = async <T = unknown>({\n entitiesDirectory,\n entityName,\n}: {\n entitiesDirectory: string;\n entityName: string;\n}): Promise<EntityClass<T>> => {\n // Create cache key based on directory and entity name\n const cacheKey = `${entitiesDirectory}:${entityName}`;\n\n // Check cache first\n if (entityCache.has(cacheKey)) {\n return entityCache.get(cacheKey) as EntityClass<T>;\n }\n\n // Define entity module path\n const entityModulePath = path.join(entitiesDirectory, `${entityName}.${Helper.getScriptFileExtension()}`);\n\n // Import entity module\n const entityModule = await import(entityModulePath);\n\n // Safe property access to prevent prototype pollution\n if (entityName === '__proto__' || entityName === 'constructor' || entityName === 'prototype') {\n throw new Error(`Invalid entity name (Entity: ${entityName})`);\n }\n\n if (!entityModule || !Object.prototype.hasOwnProperty.call(entityModule, entityName)) {\n throw new Error(`Entity not found (Entity: ${entityName})`);\n }\n\n // Get entity class\n const EntityClass = Reflect.get(entityModule, entityName);\n\n // Cache the entity for future use\n entityCache.set(cacheKey, EntityClass);\n\n return EntityClass;\n};\n\n// Cache management functions for development/testing\nconst clearModuleCache = (): void => {\n moduleCache.clear();\n entityCache.clear();\n};\n\nconst getCacheStats = (): { modulesCached: number; entitiesCached: number } => {\n return {\n modulesCached: moduleCache.size,\n entitiesCached: entityCache.size,\n };\n};\n\nexport default {\n loadModulesInDirectory,\n loadEntityModule,\n clearModuleCache,\n getCacheStats,\n};\n"],
|
|
5
|
-
"mappings": ";;AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,gBAAgB;AACzB,SAAS,cAAc;AASvB,MAAM,cAAc,IAAI,SAA4B;AAAA,EAClD,KAAK;AAAA;AAAA,EACL,KAAK,MAAO,KAAK;AAAA;AACnB,CAAC;AAED,MAAM,cAAc,IAAI,SAA8B;AAAA,EACpD,KAAK;AAAA;AAAA,EACL,KAAK,MAAO,KAAK;AAAA;AACnB,CAAC;AAED,MAAM,yBAAyB,8BAAoB;AAAA,EACjD;AAAA,EACA;AACF,MAG6B;AAE3B,QAAM,WAAW,GAAG,SAAS,IAAI,YAAY,KAAK,GAAG,KAAK,KAAK;AAG/D,MAAI,YAAY,IAAI,QAAQ,GAAG;AAC7B,UAAM,eAAe,YAAY,IAAI,QAAQ;AAC7C,QAAI,cAAc;AAChB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,gBAA8B,CAAC;AAGrC,QAAM,UAAU,MAAM,GAAG,SAAS,QAAQ,WAAW,EAAE,eAAe,KAAK,CAAC;AAE5E,aAAW,UAAU,SAAS;AAE5B,QAAI,OAAO,YAAY,GAAG;AACxB;AAAA,IACF;AAEA,UAAM,OAAO,OAAO;AACpB,UAAM,MAAM,KAAK,QAAQ,IAAI;AAC7B,UAAM,oBAAoB,KAAK,SAAS,OAAO;AAG/C,QAAK,cAAc,WAAW,SAAS,KAAK,CAAC,WAAW,SAAS,GAAG,KAAM,mBAAmB;AAC3F;AAAA,IACF;AAEA,UAAM,aAAa,KAAK,SAAS,MAAM,GAAG;AAC1C,UAAM,WAAW,KAAK,KAAK,WAAW,IAAI;AAE1C,UAAM,eAAe,KAAK,WAAW,QAAQ,IAAI,WAAW,KAAK,QAAQ,QAAQ;AAEjF,UAAM,UAAU,UAAU,aAAa,QAAQ,OAAO,GAAG,CAAC;AAE1D,QAAI;AACF,YAAM,iBAAiB,MAAM,OAAO;AAGpC,UAAI,eAAe,eAAe,eAAe,iBAAiB,eAAe,aAAa;AAE5F,cAAM,eAAe,eAAe,WAAW;AAC/C,gBAAQ,IAAI,eAAe,YAAY,YAAY;AAAA,MACrD;AAAA,IACF,SAAS,OAAO;
|
|
4
|
+
"sourcesContent": ["import fs from 'fs';\nimport path from 'path';\nimport { LRUCache } from 'lru-cache';\nimport { Helper } from './index.js';\n\n// Type for a map of loaded modules\nexport interface ModuleMap<T = unknown> {\n [key: string]: T;\n}\n\n// Cache for loaded modules to avoid repeated imports\n// Using LRU cache to prevent unbounded memory growth in long-running processes\nconst moduleCache = new LRUCache<string, ModuleMap>({\n max: 100, // Max 100 directories cached\n ttl: 1000 * 60 * 10, // 10 minutes\n});\n\nconst entityCache = new LRUCache<string, EntityClass>({\n max: 500, // Max 500 entities cached (accessed more frequently than modules)\n ttl: 1000 * 60 * 10, // 10 minutes\n});\n\nconst loadModulesInDirectory = async <T = unknown>({\n directory,\n extensions,\n}: {\n directory: string;\n extensions?: string[];\n}): Promise<ModuleMap<T>> => {\n // Create cache key based on directory and extensions\n const cacheKey = `${directory}:${extensions?.join(',') ?? 'all'}`;\n\n // Check cache first\n if (moduleCache.has(cacheKey)) {\n const cachedModule = moduleCache.get(cacheKey);\n if (cachedModule) {\n return cachedModule as ModuleMap<T>;\n }\n }\n\n const loadedModules: ModuleMap<T> = {};\n\n // Use readdir with withFileTypes option to avoid separate stat calls\n const dirents = await fs.promises.readdir(directory, { withFileTypes: true });\n\n for (const dirent of dirents) {\n // Skip directories without needing stat call\n if (dirent.isDirectory()) {\n continue;\n }\n\n const file = dirent.name;\n const ext = path.extname(file);\n const isDeclarationFile = file.endsWith('.d.ts');\n\n // Skip files that are not in the specified extensions or are .d.ts files\n if ((extensions && extensions.length > 0 && !extensions.includes(ext)) || isDeclarationFile) {\n continue;\n }\n\n const moduleName = path.basename(file, ext);\n const filePath = path.join(directory, file);\n // Convert to absolute path for ESM import\n const absolutePath = path.isAbsolute(filePath) ? filePath : path.resolve(filePath);\n // Use file:// URL for Windows compatibility\n const fileUrl = `file://${absolutePath.replace(/\\\\/g, '/')}`;\n\n try {\n const importedModule = await import(fileUrl);\n\n // Use safe property assignment to prevent prototype pollution\n if (moduleName !== '__proto__' && moduleName !== 'constructor' && moduleName !== 'prototype') {\n // Prefer default export, but fall back to the entire module if no default\n const moduleExport = importedModule.default ?? importedModule;\n Reflect.set(loadedModules, moduleName, moduleExport);\n }\n } catch (error) {\n // Note: console.error used here as Logger may not be initialized during early bootstrap\n console.error(`Failed to import module ${filePath}:`, error);\n }\n }\n\n // Cache the results for future use\n moduleCache.set(cacheKey, loadedModules);\n\n return loadedModules;\n};\n\n// Type constraint for entity classes (must be constructable)\nexport type EntityClass<T = unknown> = new (...args: unknown[]) => T;\n\nconst loadEntityModule = async <T = unknown>({\n entitiesDirectory,\n entityName,\n}: {\n entitiesDirectory: string;\n entityName: string;\n}): Promise<EntityClass<T>> => {\n // Create cache key based on directory and entity name\n const cacheKey = `${entitiesDirectory}:${entityName}`;\n\n // Check cache first\n if (entityCache.has(cacheKey)) {\n return entityCache.get(cacheKey) as EntityClass<T>;\n }\n\n // Define entity module path\n const entityModulePath = path.join(entitiesDirectory, `${entityName}.${Helper.getScriptFileExtension()}`);\n\n // Import entity module\n const entityModule = await import(entityModulePath);\n\n // Safe property access to prevent prototype pollution\n if (entityName === '__proto__' || entityName === 'constructor' || entityName === 'prototype') {\n throw new Error(`Invalid entity name (Entity: ${entityName})`);\n }\n\n if (!entityModule || !Object.prototype.hasOwnProperty.call(entityModule, entityName)) {\n throw new Error(`Entity not found (Entity: ${entityName})`);\n }\n\n // Get entity class\n const EntityClass = Reflect.get(entityModule, entityName);\n\n // Cache the entity for future use\n entityCache.set(cacheKey, EntityClass);\n\n return EntityClass;\n};\n\n// Cache management functions for development/testing\nconst clearModuleCache = (): void => {\n moduleCache.clear();\n entityCache.clear();\n};\n\nconst getCacheStats = (): { modulesCached: number; entitiesCached: number } => {\n return {\n modulesCached: moduleCache.size,\n entitiesCached: entityCache.size,\n };\n};\n\nexport default {\n loadModulesInDirectory,\n loadEntityModule,\n clearModuleCache,\n getCacheStats,\n};\n"],
|
|
5
|
+
"mappings": ";;AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,gBAAgB;AACzB,SAAS,cAAc;AASvB,MAAM,cAAc,IAAI,SAA4B;AAAA,EAClD,KAAK;AAAA;AAAA,EACL,KAAK,MAAO,KAAK;AAAA;AACnB,CAAC;AAED,MAAM,cAAc,IAAI,SAA8B;AAAA,EACpD,KAAK;AAAA;AAAA,EACL,KAAK,MAAO,KAAK;AAAA;AACnB,CAAC;AAED,MAAM,yBAAyB,8BAAoB;AAAA,EACjD;AAAA,EACA;AACF,MAG6B;AAE3B,QAAM,WAAW,GAAG,SAAS,IAAI,YAAY,KAAK,GAAG,KAAK,KAAK;AAG/D,MAAI,YAAY,IAAI,QAAQ,GAAG;AAC7B,UAAM,eAAe,YAAY,IAAI,QAAQ;AAC7C,QAAI,cAAc;AAChB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,gBAA8B,CAAC;AAGrC,QAAM,UAAU,MAAM,GAAG,SAAS,QAAQ,WAAW,EAAE,eAAe,KAAK,CAAC;AAE5E,aAAW,UAAU,SAAS;AAE5B,QAAI,OAAO,YAAY,GAAG;AACxB;AAAA,IACF;AAEA,UAAM,OAAO,OAAO;AACpB,UAAM,MAAM,KAAK,QAAQ,IAAI;AAC7B,UAAM,oBAAoB,KAAK,SAAS,OAAO;AAG/C,QAAK,cAAc,WAAW,SAAS,KAAK,CAAC,WAAW,SAAS,GAAG,KAAM,mBAAmB;AAC3F;AAAA,IACF;AAEA,UAAM,aAAa,KAAK,SAAS,MAAM,GAAG;AAC1C,UAAM,WAAW,KAAK,KAAK,WAAW,IAAI;AAE1C,UAAM,eAAe,KAAK,WAAW,QAAQ,IAAI,WAAW,KAAK,QAAQ,QAAQ;AAEjF,UAAM,UAAU,UAAU,aAAa,QAAQ,OAAO,GAAG,CAAC;AAE1D,QAAI;AACF,YAAM,iBAAiB,MAAM,OAAO;AAGpC,UAAI,eAAe,eAAe,eAAe,iBAAiB,eAAe,aAAa;AAE5F,cAAM,eAAe,eAAe,WAAW;AAC/C,gBAAQ,IAAI,eAAe,YAAY,YAAY;AAAA,MACrD;AAAA,IACF,SAAS,OAAO;AAEd,cAAQ,MAAM,2BAA2B,QAAQ,KAAK,KAAK;AAAA,IAC7D;AAAA,EACF;AAGA,cAAY,IAAI,UAAU,aAAa;AAEvC,SAAO;AACT,GAhE+B;AAqE/B,MAAM,mBAAmB,8BAAoB;AAAA,EAC3C;AAAA,EACA;AACF,MAG+B;AAE7B,QAAM,WAAW,GAAG,iBAAiB,IAAI,UAAU;AAGnD,MAAI,YAAY,IAAI,QAAQ,GAAG;AAC7B,WAAO,YAAY,IAAI,QAAQ;AAAA,EACjC;AAGA,QAAM,mBAAmB,KAAK,KAAK,mBAAmB,GAAG,UAAU,IAAI,OAAO,uBAAuB,CAAC,EAAE;AAGxG,QAAM,eAAe,MAAM,OAAO;AAGlC,MAAI,eAAe,eAAe,eAAe,iBAAiB,eAAe,aAAa;AAC5F,UAAM,IAAI,MAAM,gCAAgC,UAAU,GAAG;AAAA,EAC/D;AAEA,MAAI,CAAC,gBAAgB,CAAC,OAAO,UAAU,eAAe,KAAK,cAAc,UAAU,GAAG;AACpF,UAAM,IAAI,MAAM,6BAA6B,UAAU,GAAG;AAAA,EAC5D;AAGA,QAAM,cAAc,QAAQ,IAAI,cAAc,UAAU;AAGxD,cAAY,IAAI,UAAU,WAAW;AAErC,SAAO;AACT,GArCyB;AAwCzB,MAAM,mBAAmB,6BAAY;AACnC,cAAY,MAAM;AAClB,cAAY,MAAM;AACpB,GAHyB;AAKzB,MAAM,gBAAgB,6BAAyD;AAC7E,SAAO;AAAA,IACL,eAAe,YAAY;AAAA,IAC3B,gBAAgB,YAAY;AAAA,EAC9B;AACF,GALsB;AAOtB,IAAO,iBAAQ;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/webserver/controller/base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,wCAAwC,EAAE,MAAM,qBAAqB,CAAC;AAE3G,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iDAAiD,CAAC;AACzF,OAAO,KAAK,YAAY,MAAM,wBAAwB,CAAC;AAEvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/webserver/controller/base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,wCAAwC,EAAE,MAAM,qBAAqB,CAAC;AAE3G,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iDAAiD,CAAC;AACzF,OAAO,KAAK,YAAY,MAAM,wBAAwB,CAAC;AAEvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAI7E,MAAM,WAAW,iBAAiB,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACnE,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,QAAQ,CAAC;CACnB;AAED,MAAM,CAAC,OAAO,CAAC,QAAQ,OAAO,cAAc,CAC1C,aAAa,SAAS,YAAY,GAAG,YAAY,EACjD,cAAc,SAAS,aAAa,GAAG,aAAa,EACpD,aAAa,SAAS,YAAY,GAAG,YAAY,EACjD,iBAAiB,SAAS,gBAAgB,GAAG,gBAAgB;IAE7D,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAEvC,SAAS,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAC/C,SAAS,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAE7C,SAAS,CAAC,aAAa,EAAE,cAAc,CAAC;IACxC,SAAS,CAAC,YAAY,EAAE,aAAa,CAAC;IACtC,SAAS,CAAC,YAAY,EAAE,aAAa,CAAC;IACtC,SAAS,CAAC,gBAAgB,EAAE,iBAAiB,CAAC;IAC9C,SAAS,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;gBAEjC,EACV,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,GACjB,EAAE,wCAAwC,CAAC,aAAa,EAAE,cAAc,EAAE,aAAa,EAAE,iBAAiB,CAAC;IAa5G,SAAS,CAAC,mBAAmB,CAAC,CAAC,GAAG,OAAO,EAAE,EACzC,KAAK,EACL,IAAI,EACJ,UAA2B,EAC3B,IAAI,GACL,EAAE;QACD,KAAK,EAAE,YAAY,CAAC;QACpB,IAAI,EAAE,CAAC,CAAC;QACR,UAAU,CAAC,EAAE,WAAW,CAAC;QACzB,IAAI,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;KAC/B;IAYD,SAAS,CAAC,oBAAoB,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,GAAE,MAA6B;IAW1F,SAAS,CAAC,iBAAiB,CAAC,EAC1B,KAAK,EACL,KAAK,EACL,UAAoC,EACpC,SAAS,GACV,EAAE;QACD,KAAK,EAAE,YAAY,CAAC;QACpB,KAAK,EAAE,OAAO,CAAC;QACf,UAAU,CAAC,EAAE,WAAW,CAAC;QACzB,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;KAC9B;IA4CD,OAAO,CAAC,YAAY;cAoBJ,mBAAmB,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;CAwErH"}
|
|
@@ -4,6 +4,7 @@ import { StatusCodes } from "http-status-codes";
|
|
|
4
4
|
import { Logger } from "../../logger/index.js";
|
|
5
5
|
import cluster from "cluster";
|
|
6
6
|
import Jwt from "../../auth/jwt.js";
|
|
7
|
+
import { safeSerializeError } from "../../error/error-reporter.js";
|
|
7
8
|
class BaseController {
|
|
8
9
|
static {
|
|
9
10
|
__name(this, "BaseController");
|
|
@@ -73,7 +74,7 @@ class BaseController {
|
|
|
73
74
|
publicErrorMessage = error.stack ?? error.message;
|
|
74
75
|
errorDetails = { stack: error.stack, name: error.name };
|
|
75
76
|
} else {
|
|
76
|
-
publicErrorMessage =
|
|
77
|
+
publicErrorMessage = safeSerializeError(error);
|
|
77
78
|
}
|
|
78
79
|
} else {
|
|
79
80
|
if (process.env.NODE_ENV === "production") {
|
|
@@ -89,12 +90,11 @@ class BaseController {
|
|
|
89
90
|
publicErrorMessage = error.stack ?? error.message;
|
|
90
91
|
errorDetails = { stack: error.stack, name: error.name };
|
|
91
92
|
} else {
|
|
92
|
-
publicErrorMessage =
|
|
93
|
+
publicErrorMessage = safeSerializeError(error);
|
|
93
94
|
}
|
|
94
95
|
}
|
|
95
96
|
}
|
|
96
|
-
Logger.
|
|
97
|
-
console.error(error);
|
|
97
|
+
Logger.error({ error });
|
|
98
98
|
const apiError = {
|
|
99
99
|
message: publicErrorMessage,
|
|
100
100
|
type: errorType ?? this.getErrorType(statusCode),
|