@spfn/core 0.2.0-beta.52 → 0.2.0-beta.54
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/dist/{boss-Cxqc-Oiw.d.ts → boss-CEik0yq-.d.ts} +7 -0
- package/dist/cache/index.js +10 -1
- package/dist/cache/index.js.map +1 -1
- package/dist/config/index.d.ts +285 -0
- package/dist/config/index.js +60 -1
- package/dist/config/index.js.map +1 -1
- package/dist/db/index.d.ts +57 -0
- package/dist/db/index.js +55 -8
- package/dist/db/index.js.map +1 -1
- package/dist/define-middleware-DuXD8Hvu.d.ts +167 -0
- package/dist/env/index.js +4 -3
- package/dist/env/index.js.map +1 -1
- package/dist/errors/index.d.ts +10 -0
- package/dist/errors/index.js +20 -2
- package/dist/errors/index.js.map +1 -1
- package/dist/event/index.d.ts +3 -3
- package/dist/event/index.js.map +1 -1
- package/dist/event/sse/client.d.ts +2 -2
- package/dist/event/sse/index.d.ts +4 -4
- package/dist/event/sse/index.js +41 -16
- package/dist/event/sse/index.js.map +1 -1
- package/dist/event/ws/client.d.ts +2 -2
- package/dist/event/ws/index.d.ts +3 -3
- package/dist/event/ws/index.js +75 -16
- package/dist/event/ws/index.js.map +1 -1
- package/dist/job/index.d.ts +2 -2
- package/dist/job/index.js +4 -4
- package/dist/job/index.js.map +1 -1
- package/dist/middleware/index.d.ts +171 -2
- package/dist/middleware/index.js +1186 -10
- package/dist/middleware/index.js.map +1 -1
- package/dist/nextjs/server.d.ts +10 -0
- package/dist/nextjs/server.js +115 -1
- package/dist/nextjs/server.js.map +1 -1
- package/dist/route/index.d.ts +3 -165
- package/dist/server/index.d.ts +31 -5
- package/dist/server/index.js +172 -36
- package/dist/server/index.js.map +1 -1
- package/dist/{token-manager-C2Ag5-s8.d.ts → token-manager-jKD_EsSE.d.ts} +0 -1
- package/dist/{types-VpVQIsyB.d.ts → types-BFB72jbM.d.ts} +1 -1
- package/dist/{types-CKsmzaB8.d.ts → types-DVjf37yO.d.ts} +37 -1
- package/package.json +6 -6
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { MiddlewareHandler } from 'hono';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Middleware Definition Helper
|
|
5
|
+
*
|
|
6
|
+
* Provides type-safe middleware definition with name inference
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Named middleware with type inference
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* export const authMiddleware = defineMiddleware('auth', async (c, next) => {
|
|
15
|
+
* // auth logic
|
|
16
|
+
* c.set('user', { id: 1 });
|
|
17
|
+
* await next();
|
|
18
|
+
* });
|
|
19
|
+
*
|
|
20
|
+
* export const rateLimitMiddleware = defineMiddleware('rateLimit', async (c, next) => {
|
|
21
|
+
* // rate limit logic
|
|
22
|
+
* await next();
|
|
23
|
+
* });
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
type NamedMiddleware<TName extends string = string> = {
|
|
27
|
+
name: TName;
|
|
28
|
+
handler: MiddlewareHandler;
|
|
29
|
+
_name: TName;
|
|
30
|
+
skips?: string[];
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Named middleware factory with type inference
|
|
34
|
+
*
|
|
35
|
+
* Factory function that creates middleware instances with parameters
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```ts
|
|
39
|
+
* export const requirePermissions = defineMiddleware('permission',
|
|
40
|
+
* (...permissions: string[]) => async (c, next) => {
|
|
41
|
+
* // permission check logic
|
|
42
|
+
* await next();
|
|
43
|
+
* }
|
|
44
|
+
* );
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
type NamedMiddlewareFactory<TName extends string = string, TArgs extends any[] = any[]> = {
|
|
48
|
+
name: TName;
|
|
49
|
+
_name: TName;
|
|
50
|
+
} & ((...args: TArgs) => MiddlewareHandler);
|
|
51
|
+
/**
|
|
52
|
+
* Define a named middleware
|
|
53
|
+
*
|
|
54
|
+
* Creates a middleware with a unique name that can be referenced
|
|
55
|
+
* in route-level skip() calls with full type safety.
|
|
56
|
+
*
|
|
57
|
+
* Supports two patterns:
|
|
58
|
+
* 1. Regular middleware: Direct middleware handler
|
|
59
|
+
* 2. Factory middleware: Function that creates middleware with parameters
|
|
60
|
+
*
|
|
61
|
+
* @param name - Unique middleware name
|
|
62
|
+
* @param handler - Middleware handler function
|
|
63
|
+
* @returns Named middleware with type inference
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```ts
|
|
67
|
+
* // Regular middleware
|
|
68
|
+
* export const authMiddleware = defineMiddleware('auth', async (c, next) => {
|
|
69
|
+
* const token = c.req.header('authorization');
|
|
70
|
+
* if (!token) {
|
|
71
|
+
* return c.json({ error: 'Unauthorized' }, 401);
|
|
72
|
+
* }
|
|
73
|
+
* c.set('user', await verifyToken(token));
|
|
74
|
+
* await next();
|
|
75
|
+
* });
|
|
76
|
+
*
|
|
77
|
+
* // Factory middleware
|
|
78
|
+
* export const requirePermissions = defineMiddleware('permission',
|
|
79
|
+
* (...permissions: string[]) => async (c, next) => {
|
|
80
|
+
* const user = c.get('user');
|
|
81
|
+
* if (!hasPermissions(user, permissions)) {
|
|
82
|
+
* return c.json({ error: 'Forbidden' }, 403);
|
|
83
|
+
* }
|
|
84
|
+
* await next();
|
|
85
|
+
* }
|
|
86
|
+
* );
|
|
87
|
+
*
|
|
88
|
+
* // server.config.ts
|
|
89
|
+
* export default defineServerConfig()
|
|
90
|
+
* .middlewares([authMiddleware])
|
|
91
|
+
* .routes(appRouter)
|
|
92
|
+
* .build();
|
|
93
|
+
*
|
|
94
|
+
* // routes.ts - skip by name
|
|
95
|
+
* export const publicRoute = route.get('/health')
|
|
96
|
+
* .skip(['auth']) // ✅ Type-safe! Autocomplete!
|
|
97
|
+
* .handler(async (c) => c.success({ status: 'ok' }));
|
|
98
|
+
*
|
|
99
|
+
* // Use factory middleware inline
|
|
100
|
+
* export const protectedRoute = route.get('/admin')
|
|
101
|
+
* .use([requirePermissions('admin:write')])
|
|
102
|
+
* .handler(async (c) => { ... });
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
/**
|
|
106
|
+
* Options for defineMiddleware
|
|
107
|
+
*/
|
|
108
|
+
interface DefineMiddlewareOptions {
|
|
109
|
+
/**
|
|
110
|
+
* Server-level middleware names to auto-skip when this middleware is used at route level.
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* ```ts
|
|
114
|
+
* // optionalAuth auto-skips the global 'auth' middleware
|
|
115
|
+
* export const optionalAuth = defineMiddleware('optionalAuth', handler, {
|
|
116
|
+
* skips: ['auth']
|
|
117
|
+
* });
|
|
118
|
+
*
|
|
119
|
+
* // Usage: .use([optionalAuth]) — no need for .skip(['auth'])
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
skips?: string[];
|
|
123
|
+
}
|
|
124
|
+
declare function defineMiddleware<TName extends string>(name: TName, handler: MiddlewareHandler, options?: DefineMiddlewareOptions): NamedMiddleware<TName>;
|
|
125
|
+
declare function defineMiddleware<TName extends string, TArgs extends any[]>(name: TName, factory: (...args: TArgs) => MiddlewareHandler, options?: DefineMiddlewareOptions): NamedMiddlewareFactory<TName, TArgs>;
|
|
126
|
+
/**
|
|
127
|
+
* Define a middleware factory explicitly
|
|
128
|
+
*
|
|
129
|
+
* Use this when your factory function has exactly 2 parameters,
|
|
130
|
+
* which would be incorrectly detected as a regular middleware handler.
|
|
131
|
+
*
|
|
132
|
+
* @param name - Unique middleware name
|
|
133
|
+
* @param factory - Factory function that returns a middleware handler
|
|
134
|
+
* @returns Named middleware factory with type inference
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```ts
|
|
138
|
+
* // Factory with 2 params (would be misdetected by defineMiddleware)
|
|
139
|
+
* export const rateLimiter = defineMiddlewareFactory('rateLimit',
|
|
140
|
+
* (limit: number, window: number) => async (c, next) => {
|
|
141
|
+
* // rate limit logic using limit and window
|
|
142
|
+
* await next();
|
|
143
|
+
* }
|
|
144
|
+
* );
|
|
145
|
+
*
|
|
146
|
+
* // Usage
|
|
147
|
+
* route.get('/api')
|
|
148
|
+
* .use([rateLimiter(100, 60000)]) // 100 requests per minute
|
|
149
|
+
* .handler(...)
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
declare function defineMiddlewareFactory<TName extends string, TArgs extends unknown[]>(name: TName, factory: (...args: TArgs) => MiddlewareHandler): NamedMiddlewareFactory<TName, TArgs>;
|
|
153
|
+
/**
|
|
154
|
+
* Extract middleware names from an array of named middlewares
|
|
155
|
+
*
|
|
156
|
+
* @example
|
|
157
|
+
* ```ts
|
|
158
|
+
* type Middlewares = [
|
|
159
|
+
* NamedMiddleware<'auth'>,
|
|
160
|
+
* NamedMiddleware<'rateLimit'>
|
|
161
|
+
* ];
|
|
162
|
+
* type Names = ExtractMiddlewareNames<Middlewares>; // 'auth' | 'rateLimit'
|
|
163
|
+
* ```
|
|
164
|
+
*/
|
|
165
|
+
type ExtractMiddlewareNames<T extends readonly NamedMiddleware<string>[]> = T[number]['_name'];
|
|
166
|
+
|
|
167
|
+
export { type ExtractMiddlewareNames as E, type NamedMiddleware as N, defineMiddlewareFactory as a, type NamedMiddlewareFactory as b, defineMiddleware as d };
|
package/dist/env/index.js
CHANGED
|
@@ -96,7 +96,7 @@ function parsePostgresUrl(value) {
|
|
|
96
96
|
url = new URL(value);
|
|
97
97
|
} catch (error) {
|
|
98
98
|
if (error instanceof TypeError) {
|
|
99
|
-
throw new Error(
|
|
99
|
+
throw new Error("Invalid PostgreSQL URL");
|
|
100
100
|
}
|
|
101
101
|
throw error;
|
|
102
102
|
}
|
|
@@ -113,7 +113,7 @@ function parseRedisUrl(value) {
|
|
|
113
113
|
url = new URL(value);
|
|
114
114
|
} catch (error) {
|
|
115
115
|
if (error instanceof TypeError) {
|
|
116
|
-
throw new Error(
|
|
116
|
+
throw new Error("Invalid Redis URL");
|
|
117
117
|
}
|
|
118
118
|
throw error;
|
|
119
119
|
}
|
|
@@ -477,7 +477,8 @@ var EnvRegistry = class {
|
|
|
477
477
|
try {
|
|
478
478
|
return this.applyValidator(value, schema);
|
|
479
479
|
} catch (error) {
|
|
480
|
-
const
|
|
480
|
+
const detail = schema.sensitive ? "(value hidden \u2014 sensitive key)" : error instanceof Error ? error.message : String(error);
|
|
481
|
+
const errorMsg = `${key} validation failed: ${detail}`;
|
|
481
482
|
envLogger.error(`Environment validation failed:
|
|
482
483
|
- ${errorMsg}`);
|
|
483
484
|
throw new Error("Environment validation failed");
|
package/dist/env/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/env/validator.ts","../../src/env/schema.ts","../../src/env/registry.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Environment Variable Management - Parsers\n *\n * Parser functions that transform and validate environment variable strings.\n * All parsers follow the pattern: (value: string) => T or throw Error\n */\n\n// ============================================================================\n// Core Types\n// ============================================================================\n\n/**\n * Parser function that transforms and validates a string value\n * @throws Error if validation fails\n */\nexport type Parser<T> = (value: string) => T;\n\n// ============================================================================\n// String Parsers\n// ============================================================================\n\n/**\n * Parse a non-empty string\n *\n * @param value - Value to parse\n * @returns Trimmed string\n * @throws Error if string is empty after trimming\n *\n * @example\n * ```typescript\n * const name = getEnvVar('APP_NAME', {\n * validator: parseString,\n * });\n * ```\n */\nexport function parseString(value: string): string\n{\n const trimmed = value.trim();\n\n if (trimmed.length === 0)\n {\n throw new Error('Value cannot be empty');\n }\n\n return trimmed;\n}\n\n/**\n * Create a string parser with validation rules\n *\n * @param options - Validation options\n * @returns Parser function\n *\n * @example\n * ```typescript\n * const apiKey = getEnvVar('API_KEY', {\n * validator: createStringParser({\n * minLength: 32,\n * pattern: /^[A-Za-z0-9_-]+$/,\n * }),\n * });\n * ```\n */\nexport function createStringParser(\n options: {\n minLength?: number;\n maxLength?: number;\n pattern?: RegExp;\n trim?: boolean;\n } = {},\n): Parser<string>\n{\n return (value: string): string =>\n {\n const { minLength, maxLength, pattern, trim = true } = options;\n\n let result = trim ? value.trim() : value;\n\n // Empty check\n if (result.length === 0)\n {\n throw new Error('Value cannot be empty');\n }\n\n // Length validation\n if (minLength !== undefined && result.length < minLength)\n {\n throw new Error(`Must be at least ${minLength} characters long (current: ${result.length})`);\n }\n\n if (maxLength !== undefined && result.length > maxLength)\n {\n throw new Error(`Must be at most ${maxLength} characters long (current: ${result.length})`);\n }\n\n // Pattern validation\n if (pattern && !pattern.test(result))\n {\n throw new Error(`Must match pattern ${pattern}`);\n }\n\n return result;\n };\n}\n\n// ============================================================================\n// Boolean Parser\n// ============================================================================\n\n/**\n * Parse a boolean environment variable\n *\n * Accepts: 'true', '1', 'yes' (case-insensitive) → true\n * 'false', '0', 'no' (case-insensitive) → false\n *\n * @param value - Value to parse\n * @returns Boolean value\n * @throws Error if value is not a valid boolean string\n *\n * @example\n * ```typescript\n * const debug = getEnvVar('DEBUG', {\n * default: 'false',\n * validator: parseBoolean,\n * });\n * ```\n */\nexport function parseBoolean(value: string): boolean\n{\n const normalized = value.toLowerCase().trim();\n\n if (['true', '1', 'yes'].includes(normalized))\n {\n return true;\n }\n\n if (['false', '0', 'no'].includes(normalized))\n {\n return false;\n }\n\n throw new Error(\n `Must be a boolean value (true/false, 1/0, yes/no), got: ${value}`,\n );\n}\n\n// ============================================================================\n// Number Parsers\n// ============================================================================\n\n/**\n * Parse and validate number\n *\n * @param value - Value to parse\n * @param options - Validation options\n * @returns Parsed number\n * @throws Error if invalid number or constraint violation\n *\n * @example\n * ```typescript\n * const port = getEnvVar('PORT', {\n * default: '3000',\n * validator: (val) => parseNumber(val, { min: 1, max: 65535, integer: true }),\n * });\n * ```\n */\nexport function parseNumber(\n value: string,\n options: { min?: number; max?: number; integer?: boolean } = {},\n): number\n{\n const { min, max, integer = false } = options;\n\n // Reject empty strings\n if (value.trim() === '')\n {\n throw new Error('Value cannot be empty');\n }\n\n const num = Number(value);\n\n if (isNaN(num))\n {\n throw new Error(`Must be a valid number, got: ${value}`);\n }\n\n if (integer && !Number.isInteger(num))\n {\n throw new Error(`Must be an integer, got: ${value}`);\n }\n\n if (min !== undefined && num < min)\n {\n throw new Error(`Must be at least ${min}, got: ${num}`);\n }\n\n if (max !== undefined && num > max)\n {\n throw new Error(`Must be at most ${max}, got: ${num}`);\n }\n\n return num;\n}\n\n/**\n * Create a number parser with specific constraints\n *\n * @param options - Validation constraints\n * @returns Parser function\n *\n * @example\n * ```typescript\n * const port = getEnvVar('PORT', {\n * default: '3000',\n * validator: createNumberParser({ min: 1, max: 65535, integer: true }),\n * });\n * ```\n */\nexport function createNumberParser(\n options: { min?: number; max?: number; integer?: boolean } = {},\n): Parser<number>\n{\n return (value: string) => parseNumber(value, options);\n}\n\n/**\n * Parse integer with optional constraints\n *\n * @param value - Value to parse\n * @param options - Min/max constraints\n * @returns Parsed integer\n * @throws Error if invalid or out of range\n *\n * @example\n * ```typescript\n * const retries = getEnvVar('MAX_RETRIES', {\n * default: '3',\n * validator: (val) => parseInteger(val, { min: 1, max: 10 }),\n * });\n * ```\n */\nexport function parseInteger(\n value: string,\n options: { min?: number; max?: number } = {},\n): number\n{\n return parseNumber(value, { ...options, integer: true });\n}\n\n/**\n * Parse float/decimal number with optional constraints\n *\n * @param value - Value to parse\n * @param options - Min/max constraints\n * @returns Parsed decimal number\n * @throws Error if invalid or out of range\n *\n * @example\n * ```typescript\n * const ratio = getEnvVar('CACHE_RATIO', {\n * default: '0.75',\n * validator: (val) => parseDecimal(val, { min: 0, max: 1 }),\n * });\n * ```\n */\nexport function parseDecimal(\n value: string,\n options: { min?: number; max?: number } = {},\n): number\n{\n return parseNumber(value, { ...options, integer: false });\n}\n\n// ============================================================================\n// URL Parsers\n// ============================================================================\n\n/**\n * Parse and validate URL\n *\n * @param value - Value to parse\n * @param options - Validation options\n * @returns Validated URL string\n * @throws Error if invalid URL or protocol mismatch\n *\n * @example\n * ```typescript\n * const apiUrl = getEnvVar('API_URL', {\n * validator: (val) => parseUrl(val, { protocol: 'https' }),\n * });\n * ```\n */\nexport function parseUrl(\n value: string,\n options: { protocol?: 'http' | 'https' | 'any' } = {},\n): string\n{\n const { protocol = 'any' } = options;\n\n // Parse URL (may throw TypeError)\n let url: URL;\n try\n {\n url = new URL(value);\n }\n catch (error)\n {\n if (error instanceof TypeError)\n {\n throw new Error(`Invalid URL: ${value}`);\n }\n throw error;\n }\n\n // Validate protocol\n if (protocol === 'http' && url.protocol !== 'http:')\n {\n throw new Error(`URL must use HTTP protocol, got ${url.protocol}`);\n }\n\n if (protocol === 'https' && url.protocol !== 'https:')\n {\n throw new Error(`URL must use HTTPS protocol, got ${url.protocol}`);\n }\n\n return value;\n}\n\n/**\n * Create a URL parser with specific protocol requirement\n *\n * @param protocol - Required protocol ('http', 'https', or 'any')\n * @returns Parser function\n *\n * @example\n * ```typescript\n * const apiUrl = getEnvVar('API_URL', {\n * validator: createUrlParser('https'),\n * });\n * ```\n */\nexport function createUrlParser(protocol: 'http' | 'https' | 'any' = 'any'): Parser<string>\n{\n return (value: string) => parseUrl(value, { protocol });\n}\n\n/**\n * Parse PostgreSQL connection string\n *\n * @param value - Value to parse\n * @returns Validated PostgreSQL URL string\n * @throws Error if invalid PostgreSQL URL\n *\n * @example\n * ```typescript\n * const dbUrl = getEnvVar('DATABASE_URL', {\n * required: true,\n * validator: parsePostgresUrl,\n * });\n * ```\n */\nexport function parsePostgresUrl(value: string): string\n{\n // Parse URL (may throw TypeError)\n let url: URL;\n try\n {\n url = new URL(value);\n }\n catch (error)\n {\n if (error instanceof TypeError)\n {\n throw new Error(`Invalid PostgreSQL URL: ${value}`);\n }\n throw error;\n }\n\n // Validate protocol\n if (url.protocol !== 'postgres:' && url.protocol !== 'postgresql:')\n {\n throw new Error(\n `Must be a PostgreSQL URL (postgres:// or postgresql://), got ${url.protocol}`,\n );\n }\n\n return value;\n}\n\n/**\n * Parse Redis connection string\n *\n * @param value - Value to parse\n * @returns Validated Redis URL string\n * @throws Error if invalid Redis URL\n *\n * @example\n * ```typescript\n * const redisUrl = getEnvVar('REDIS_URL', {\n * required: true,\n * validator: parseRedisUrl,\n * });\n * ```\n */\nexport function parseRedisUrl(value: string): string\n{\n // Parse URL (may throw TypeError)\n let url: URL;\n try\n {\n url = new URL(value);\n }\n catch (error)\n {\n if (error instanceof TypeError)\n {\n throw new Error(`Invalid Redis URL: ${value}`);\n }\n throw error;\n }\n\n // Validate protocol\n if (url.protocol !== 'redis:' && url.protocol !== 'rediss:')\n {\n throw new Error(\n `Must be a Redis URL (redis:// or rediss://), got ${url.protocol}`,\n );\n }\n\n return value;\n}\n\n// ============================================================================\n// Enum Parser\n// ============================================================================\n\n/**\n * Parse and validate enum value\n *\n * @param value - Value to parse\n * @param allowed - Array of allowed values\n * @param caseInsensitive - Whether to perform case-insensitive comparison\n * @returns Validated enum value\n * @throws Error if value not in allowed list\n *\n * @example\n * ```typescript\n * const env = getEnvVar('NODE_ENV', {\n * validator: (val) => parseEnum(val, ['development', 'production', 'test']),\n * });\n * ```\n */\nexport function parseEnum(\n value: string,\n allowed: string[],\n caseInsensitive = false,\n): string\n{\n if (caseInsensitive)\n {\n const normalizedValue = value.toLowerCase();\n const normalizedAllowed = allowed.map((v) => v.toLowerCase());\n const index = normalizedAllowed.indexOf(normalizedValue);\n\n if (index === -1)\n {\n throw new Error(\n `Must be one of [${allowed.join(', ')}], got: ${value}`,\n );\n }\n\n return allowed[index]; // Return original case from allowed list\n }\n\n if (!allowed.includes(value))\n {\n throw new Error(\n `Must be one of [${allowed.join(', ')}], got: ${value}`,\n );\n }\n\n return value;\n}\n\n/**\n * Create an enum parser with specific allowed values\n *\n * @param allowed - Array of allowed values\n * @param caseInsensitive - Whether to perform case-insensitive comparison\n * @returns Parser function\n *\n * @example\n * ```typescript\n * const logLevel = getEnvVar('LOG_LEVEL', {\n * default: 'info',\n * validator: createEnumParser(['debug', 'info', 'warn', 'error']),\n * });\n * ```\n */\nexport function createEnumParser(allowed: string[], caseInsensitive = false): Parser<string>\n{\n return (value: string) => parseEnum(value, allowed, caseInsensitive);\n}\n\n// ============================================================================\n// JSON Parser\n// ============================================================================\n\n/**\n * Parse JSON string\n *\n * @param value - JSON string to parse\n * @returns Parsed JSON value\n * @throws Error if invalid JSON\n *\n * @example\n * ```typescript\n * const config = getEnvVar('CONFIG_JSON', {\n * validator: parseJson,\n * });\n * ```\n */\nexport function parseJson<T = any>(value: string): T\n{\n try\n {\n return JSON.parse(value) as T;\n }\n catch (error)\n {\n throw new Error(\n `Invalid JSON: ${error instanceof Error ? error.message : 'Unknown error'}`,\n );\n }\n}\n\n/**\n * Create a typed JSON parser\n *\n * @returns Parser function\n *\n * @example\n * ```typescript\n * interface Config {\n * host: string;\n * port: number;\n * }\n *\n * const config = getEnvVar('CONFIG_JSON', {\n * validator: createJsonParser<Config>(),\n * });\n * ```\n */\nexport function createJsonParser<T>(): Parser<T>\n{\n return (value: string) => parseJson<T>(value);\n}\n\n// ============================================================================\n// Array Parser\n// ============================================================================\n\n/**\n * Parse comma-separated values into array\n *\n * @param value - Comma-separated string\n * @param options - Parser options\n * @returns Array of strings\n *\n * @example\n * ```typescript\n * const hosts = getEnvVar('ALLOWED_HOSTS', {\n * validator: parseArray,\n * });\n * // \"localhost,example.com,api.example.com\" → ['localhost', 'example.com', 'api.example.com']\n * ```\n */\nexport function parseArray(\n value: string,\n options: {\n separator?: string;\n trim?: boolean;\n filter?: (item: string) => boolean;\n } = {},\n): string[]\n{\n const { separator = ',', trim = true, filter } = options;\n\n if (value.trim() === '')\n {\n return [];\n }\n\n let items = value.split(separator);\n\n if (trim)\n {\n items = items.map((item) => item.trim());\n }\n\n if (filter)\n {\n items = items.filter(filter);\n }\n\n return items;\n}\n\n/**\n * Create an array parser with item parser\n *\n * @param itemParser - Parser to apply to each array item\n * @param options - Array parsing options\n * @returns Parser function\n *\n * @example\n * ```typescript\n * // Parse comma-separated ports\n * const ports = getEnvVar('PORTS', {\n * validator: createArrayParser(\n * createNumberParser({ min: 1, max: 65535, integer: true })\n * ),\n * });\n * // \"3000,4000,5000\" → [3000, 4000, 5000]\n * ```\n */\nexport function createArrayParser<T>(\n itemParser: Parser<T>,\n options: { separator?: string } = {},\n): Parser<T[]>\n{\n return (value: string): T[] =>\n {\n const items = parseArray(value, options);\n\n return items.map((item, index) =>\n {\n try\n {\n return itemParser(item);\n }\n catch (error)\n {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Invalid item at index ${index}: ${message}`);\n }\n });\n };\n}\n\n// ============================================================================\n// Secure Secret Parser\n// ============================================================================\n\n/**\n * Calculate Shannon entropy of a string\n * Returns entropy in bits per character\n *\n * @param str - String to calculate entropy for\n * @returns Entropy value (0 to ~6.6 bits for printable ASCII)\n *\n * @example\n * ```typescript\n * const entropy = calculateEntropy('my-secret-key');\n * // Higher entropy = more random\n * // - Random lowercase: ~4.7 bits/char\n * // - Random alphanumeric: ~5.2 bits/char\n * // - Random printable ASCII: ~6.6 bits/char\n * // - \"aaaaaaa...\": ~0 bits/char\n * ```\n */\nfunction calculateEntropy(str: string): number\n{\n const len = str.length;\n const frequencies = new Map<string, number>();\n\n // Count character frequencies\n for (const char of str)\n {\n frequencies.set(char, (frequencies.get(char) || 0) + 1);\n }\n\n // Calculate Shannon entropy\n let entropy = 0;\n for (const count of frequencies.values())\n {\n const probability = count / len;\n entropy -= probability * Math.log2(probability);\n }\n\n return entropy;\n}\n\n/**\n * Create a secure secret parser with entropy validation\n *\n * Validates cryptographic secrets for sufficient length, character diversity, and randomness.\n * Uses Shannon entropy to measure randomness quality.\n *\n * @param options - Validation options\n * @returns Parser function\n *\n * @example\n * ```typescript\n * const sessionSecret = getEnvVar('SESSION_SECRET', {\n * validator: createSecureSecretParser({\n * minLength: 32, // Minimum 256-bit\n * minUniqueChars: 16, // Character diversity\n * minEntropy: 3.5, // Shannon entropy (bits/char)\n * }),\n * });\n * ```\n */\nexport function createSecureSecretParser(\n options: {\n minLength?: number;\n minUniqueChars?: number;\n minEntropy?: number;\n } = {},\n): Parser<string>\n{\n const {\n minLength = 32,\n minUniqueChars = 16,\n minEntropy = 3.5,\n } = options;\n\n return (value: string): string =>\n {\n const length = value.length;\n const uniqueChars = new Set(value).size;\n const entropy = calculateEntropy(value);\n\n // Check length (minimum for cryptographic strength)\n if (length < minLength)\n {\n throw new Error(\n `Secret too short: ${length} characters (minimum: ${minLength})`,\n );\n }\n\n // Check unique character diversity\n if (uniqueChars < minUniqueChars)\n {\n throw new Error(\n `Secret has low diversity: ${uniqueChars} unique characters (minimum: ${minUniqueChars})`,\n );\n }\n\n // Check Shannon entropy (randomness quality)\n // Reference values:\n // - Random lowercase: ~4.7 bits/char\n // - Random alphanumeric: ~5.2 bits/char\n // - Random printable ASCII: ~6.6 bits/char\n // - \"aaaaaaa...\": ~0 bits/char\n // - \"abcabcabc...\": ~1.58 bits/char\n if (entropy < minEntropy)\n {\n throw new Error(\n `Secret has low entropy: ${entropy.toFixed(2)} bits/char (minimum: ${minEntropy}). Use a more random secret.`,\n );\n }\n\n return value;\n };\n}\n\n// ============================================================================\n// Password Parser\n// ============================================================================\n\n/**\n * Create a password strength parser\n *\n * Validates password strength based on configurable requirements.\n * Useful for enforcing password policies in environment variables or user input.\n *\n * @param options - Validation options\n * @returns Parser function\n *\n * @example\n * ```typescript\n * const adminPassword = getEnvVar('ADMIN_PASSWORD', {\n * validator: createPasswordParser({\n * minLength: 12,\n * requireUppercase: true,\n * requireLowercase: true,\n * requireNumber: true,\n * requireSpecial: true,\n * }),\n * });\n * ```\n */\nexport function createPasswordParser(\n options: {\n minLength?: number;\n requireUppercase?: boolean;\n requireLowercase?: boolean;\n requireNumber?: boolean;\n requireSpecial?: boolean;\n } = {},\n): Parser<string>\n{\n const {\n minLength = 8,\n requireUppercase = true,\n requireLowercase = true,\n requireNumber = true,\n requireSpecial = true,\n } = options;\n\n return (value: string): string =>\n {\n const errors: string[] = [];\n\n // Length check\n if (value.length < minLength)\n {\n errors.push(`Must be at least ${minLength} characters`);\n }\n\n // Uppercase check\n if (requireUppercase && !/[A-Z]/.test(value))\n {\n errors.push('Must contain at least one uppercase letter');\n }\n\n // Lowercase check\n if (requireLowercase && !/[a-z]/.test(value))\n {\n errors.push('Must contain at least one lowercase letter');\n }\n\n // Number check\n if (requireNumber && !/[0-9]/.test(value))\n {\n errors.push('Must contain at least one number');\n }\n\n // Special character check\n if (requireSpecial && !/[^A-Za-z0-9]/.test(value))\n {\n errors.push('Must contain at least one special character');\n }\n\n if (errors.length > 0)\n {\n throw new Error(`Password validation failed: ${errors.join(', ')}`);\n }\n\n return value;\n };\n}\n\n// ============================================================================\n// Parser Composition\n// ============================================================================\n\n/**\n * Chain multiple parsers sequentially\n *\n * Each parser receives the output of the previous parser.\n * Useful for multi-step validation/transformation.\n *\n * @param parsers - Array of parser functions\n * @returns Combined parser function\n *\n * @example\n * ```typescript\n * const apiKey = getEnvVar('API_KEY', {\n * validator: chain(\n * parseString,\n * createStringParser({ minLength: 32, pattern: /^[A-Za-z0-9_-]+$/ }),\n * ),\n * });\n * ```\n */\nexport function chain<T>(...parsers: Array<Parser<T>>): Parser<T>\n{\n return (value: string): T =>\n {\n let result = value as any;\n\n for (const parser of parsers)\n {\n result = parser(result);\n }\n\n return result;\n };\n}\n\n/**\n * Apply parser with fallback value\n *\n * If parser throws, returns fallback instead.\n * Useful for optional environment variables with complex parsing.\n *\n * @param parser - Parser to attempt\n * @param fallback - Fallback value if parsing fails\n * @returns Parser function\n *\n * @example\n * ```typescript\n * const config = getEnvVar('CONFIG_JSON', {\n * validator: withFallback(parseJson, { host: 'localhost', port: 3000 }),\n * });\n * ```\n */\nexport function withFallback<T>(parser: Parser<T>, fallback: T): Parser<T>\n{\n return (value: string): T =>\n {\n try\n {\n return parser(value);\n }\n catch\n {\n return fallback;\n }\n };\n}\n\n/**\n * Make parser optional\n *\n * Returns undefined for empty strings instead of throwing.\n *\n * @param parser - Parser to make optional\n * @returns Parser function that returns T | undefined\n *\n * @example\n * ```typescript\n * const redisUrl = getEnvVar('REDIS_URL', {\n * validator: optional(parseRedisUrl),\n * });\n * // Empty string → undefined\n * // Valid URL → parsed URL\n * // Invalid URL → throws\n * ```\n */\nexport function optional<T>(parser: Parser<T>): Parser<T | undefined>\n{\n return (value: string): T | undefined =>\n {\n if (value.trim() === '')\n {\n return undefined;\n }\n\n return parser(value);\n };\n}\n","/**\n * Environment Variable Schema Definition System\n *\n * 환경변수에 메타데이터를 정의하여 중앙 관리, 문서화, 검증을 지원합니다.\n *\n * @example\n * ```typescript\n * const schema = defineEnvSchema({\n * DATABASE_URL: envUrl({\n * description: 'Database connection',\n * required: true,\n * validator: parsePostgresUrl,\n * sensitive: true,\n * })\n * });\n * ```\n *\n * @module env/schema\n */\n\nimport { parseBoolean, parseNumber, parseJson } from './validator';\n\n/**\n * 환경변수 스키마 정의\n */\nexport interface EnvVarSchema<T = string>\n{\n /** 환경변수 키 */\n key: string;\n\n /** 설명 (목적, 사용처) */\n description: string;\n\n /** 타입 */\n type: 'string' | 'number' | 'boolean' | 'url' | 'enum' | 'json';\n\n /** 필수 여부 */\n required?: boolean;\n\n /** 기본값 */\n default?: T;\n\n /** 검증/변환 함수 */\n validator?: (value: string) => T;\n\n // === 검증 옵션 ===\n\n /** Fallback 환경변수 키들 (backward compatibility) */\n fallbackKeys?: string[];\n\n /** 최소 길이 (문자열 타입) */\n minLength?: number;\n\n // === 메타데이터 ===\n\n /** 민감정보 여부 (로깅 시 마스킹) */\n sensitive?: boolean;\n\n /**\n * 자동 생성 방식 — 값이 미지정이면 프로비저닝(secrets 관리 CLI)이 이 방식으로 생성한다.\n * 외부에서 받아야 하는 시크릿(API 키 등)은 generate를 비워 사용자 입력으로 둔다.\n */\n generate?: 'hex32' | 'hex64' | 'uuid' | 'base64url32';\n\n /** 예시 값들 (타입과 일치해야 함) */\n examples?: T[];\n\n // === 파일 분리 ===\n\n /**\n * Next.js 프로세스에서 사용 여부\n *\n * - true: .env.local에 존재해야 함 (Next.js 서버 컴포넌트에서 접근 가능)\n * - false: .env.server에만 존재해야 함 (SPFN 서버에서만 접근)\n *\n * @default NEXT_PUBLIC_* 이면 true, 아니면 false\n */\n nextjs?: boolean;\n}\n\n/**\n * 스키마 컬렉션 타입\n */\nexport type EnvSchemaCollection = Record<string, EnvVarSchema<any>>;\n\n/**\n * Helper type: Check if field has default value\n */\ntype HasDefault<T> = T extends { default: any } ? true : false;\n\n/**\n * Helper type: Check if field is explicitly required\n */\ntype IsRequired<T> = T extends { required: true } ? true : false;\n\n/**\n * Helper type: Check if field should be required (has default OR required: true)\n */\ntype ShouldBeRequired<T> = HasDefault<T> extends true ? true : IsRequired<T>;\n\n/**\n * 스키마로부터 타입 추출\n *\n * required: true 또는 default가 있는 필드 → 필수\n * required: false 또는 미지정 → optional (| undefined)\n */\nexport type InferEnvType<T extends EnvSchemaCollection> = {\n // Required fields (required: true OR has default)\n [K in keyof T as ShouldBeRequired<T[K]> extends true ? K : never]:\n T[K] extends EnvVarSchema<infer U> ? U : string;\n} & {\n // Optional fields (required: false OR not specified)\n [K in keyof T as ShouldBeRequired<T[K]> extends true ? never : K]?:\n T[K] extends EnvVarSchema<infer U> ? U | undefined : string | undefined;\n};\n\n/**\n * 스키마 정의 헬퍼 (타입 추론 지원)\n *\n * Automatically fills in the `key` property from object keys.\n *\n * @example\n * ```typescript\n * const schema = defineEnvSchema({\n * DATABASE_URL: envString({ description: 'Database URL', required: true })\n * });\n * // Automatically adds key: 'DATABASE_URL'\n * ```\n */\nexport function defineEnvSchema<T extends Record<string, any>>(\n schema: T,\n): { [K in keyof T]: T[K] & { key: K } }\n{\n const result: any = {};\n\n for (const key in schema)\n {\n result[key] = {\n ...schema[key],\n key,\n };\n }\n\n return result;\n}\n\n/**\n * 문자열 스키마 헬퍼\n *\n * @example\n * ```typescript\n * const schema = {\n * API_KEY: {\n * ...envString({\n * description: 'API authentication key',\n * required: true,\n * sensitive: true,\n * }),\n * key: 'API_KEY',\n * }\n * };\n * ```\n */\nexport function envString<T extends Omit<EnvVarSchema, 'key' | 'type'>>(\n options: T,\n): T & { type: 'string'; validator: (value: string) => string }\n{\n return {\n ...options,\n type: 'string',\n validator: options.validator || ((value: string) => value),\n };\n}\n\n/**\n * 시크릿 스키마 헬퍼 — sensitive:true 자동.\n *\n * generate 지정 시 프로비저닝(secrets CLI)이 값을 자동 생성, 미지정이면 외부 입력(사용자가 붙여넣음).\n * 이로써 env.config.ts가 \"설정(envString) vs 외부 시크릿(envSecret) vs 자동 시크릿(envSecret+generate)\"을\n * 선언적으로 가른다 — CLI·프레임워크·프로비저닝이 한 원천을 읽는다.\n *\n * @example\n * ```typescript\n * SPFN_AUTH_SESSION_SECRET: envSecret({ description: '세션 서명 키', generate: 'base64url32' }),\n * OPENAI_API_KEY: envSecret({ description: 'OpenAI API 키' }), // generate 없음 → 외부 입력\n * ```\n */\nexport function envSecret<T extends Omit<EnvVarSchema, 'key' | 'type' | 'sensitive'>>(\n options: T,\n): T & { type: 'string'; sensitive: true; validator: (value: string) => string }\n{\n return {\n ...options,\n type: 'string',\n sensitive: true,\n validator: options.validator || ((value: string) => value),\n };\n}\n\n/**\n * 숫자 스키마 헬퍼\n *\n * @example\n * ```typescript\n * const schema = {\n * PORT: {\n * ...envNumber({\n * description: 'Server port',\n * default: 3000,\n * validator: createNumberParser({ min: 1, max: 65535 }),\n * }),\n * key: 'PORT',\n * }\n * };\n * ```\n */\nexport function envNumber<T extends Omit<EnvVarSchema<number>, 'key' | 'type'>>(\n options: T,\n): T & { type: 'number'; validator: (value: string) => number }\n{\n return {\n ...options,\n type: 'number',\n validator: options.validator || parseNumber,\n };\n}\n\n/**\n * Boolean 스키마 헬퍼\n *\n * @example\n * ```typescript\n * const schema = {\n * DEBUG: {\n * ...envBoolean({\n * description: 'Enable debug mode',\n * default: false,\n * }),\n * key: 'DEBUG',\n * }\n * };\n * ```\n */\nexport function envBoolean<T extends Omit<EnvVarSchema<boolean>, 'key' | 'type'>>(\n options: T,\n): T & { type: 'boolean'; validator: (value: string) => boolean }\n{\n return {\n ...options,\n type: 'boolean',\n validator: options.validator || parseBoolean,\n };\n}\n\n/**\n * URL 스키마 헬퍼\n *\n * @example\n * ```typescript\n * const schema = {\n * DATABASE_URL: {\n * ...envUrl({\n * description: 'Database connection URL',\n * required: true,\n * validator: parsePostgresUrl,\n * }),\n * key: 'DATABASE_URL',\n * }\n * };\n * ```\n */\nexport function envUrl<T extends Omit<EnvVarSchema, 'key' | 'type'>>(\n options: T,\n): T & { type: 'url' }\n{\n return {\n ...options,\n type: 'url',\n };\n}\n\n/**\n * Enum 스키마 헬퍼\n *\n * @example\n * ```typescript\n * const schema = {\n * LOG_LEVEL: {\n * ...envEnum(['debug', 'info', 'warn', 'error'] as const, {\n * description: 'Logging level',\n * default: 'info',\n * }),\n * key: 'LOG_LEVEL',\n * }\n * };\n * ```\n */\nexport function envEnum<\n T extends string,\n O extends Omit<EnvVarSchema<T>, 'key' | 'type' | 'validator'>,\n>(\n allowed: readonly T[],\n options: O,\n): O & { type: 'enum'; validator: (val: string) => T }\n{\n return {\n ...options,\n type: 'enum',\n validator: (val: string): T =>\n {\n if (!allowed.includes(val as T))\n {\n throw new Error(`Must be one of: ${allowed.join(', ')}, got: ${val}`);\n }\n\n return val as T;\n },\n };\n}\n\n/**\n * JSON 스키마 헬퍼\n *\n * @example\n * ```typescript\n * const schema = {\n * CONFIG_JSON: {\n * ...envJson<{ host: string; port: number }>({\n * description: 'JSON configuration object',\n * required: true,\n * }),\n * key: 'CONFIG_JSON',\n * }\n * };\n * ```\n */\nexport function envJson<\n T = any,\n O extends Omit<EnvVarSchema<T>, 'key' | 'type' | 'validator'> = Omit<EnvVarSchema<T>, 'key' | 'type' | 'validator'>,\n>(\n options: O,\n): O & { type: 'json'; validator: (val: string) => T }\n{\n return {\n ...options,\n type: 'json',\n validator: (val: string) => parseJson<T>(val),\n };\n}\n\n/**\n * 환경변수가 클라이언트에서 접근 가능한지 확인\n * (NEXT_PUBLIC_ 접두사로 판단)\n *\n * @param key - 환경변수 키\n * @returns 클라이언트에서 접근 가능하면 true\n *\n * @example\n * ```typescript\n * isClientAccessible('NEXT_PUBLIC_API_URL'); // true\n * isClientAccessible('DATABASE_URL'); // false\n * ```\n */\nexport function isClientAccessible(key: string): boolean\n{\n return key.startsWith('NEXT_PUBLIC_');\n}\n\n/**\n * 환경변수가 서버 전용인지 확인\n * (NEXT_PUBLIC_ 접두사가 없으면 서버 전용)\n *\n * @param key - 환경변수 키\n * @returns 서버 전용이면 true\n *\n * @example\n * ```typescript\n * isServerOnly('DATABASE_URL'); // true\n * isServerOnly('NEXT_PUBLIC_API_URL'); // false\n * ```\n */\nexport function isServerOnly(key: string): boolean\n{\n return !isClientAccessible(key);\n}\n\n/**\n * 스키마의 nextjs 옵션 값 결정\n *\n * 명시적으로 지정되지 않은 경우:\n * - NEXT_PUBLIC_* → true\n * - 그 외 → false\n *\n * @param schema - 환경변수 스키마\n * @returns Next.js 프로세스에서 사용 가능 여부\n */\nexport function isNextjsAccessible(schema: EnvVarSchema): boolean\n{\n if (schema.nextjs !== undefined)\n {\n return schema.nextjs;\n }\n\n return isClientAccessible(schema.key);\n}\n\n/**\n * 스키마가 SPFN 서버 전용인지 확인\n *\n * @param schema - 환경변수 스키마\n * @returns SPFN 서버에서만 사용되면 true\n */\nexport function isSpfnServerOnly(schema: EnvVarSchema): boolean\n{\n return !isNextjsAccessible(schema);\n}\n","/**\n * Environment Variable Registry\n *\n * 환경변수 스키마를 등록하고 타입 안전하게 접근할 수 있는 레지스트리\n *\n * @example\n * ```typescript\n * const schema = defineEnvSchema({\n * DATABASE_URL: envString({ description: 'Database URL', required: true })\n * });\n *\n * const registry = createEnvRegistry(schema);\n * const env = registry.validate(); // 검증 + env 반환\n * console.log(env.DATABASE_URL);\n * ```\n *\n * @module env/registry\n */\nimport type { EnvVarSchema, EnvSchemaCollection, InferEnvType } from './schema';\nimport { isClientAccessible } from './schema';\nimport { logger } from '@spfn/core/logger';\n\nconst envLogger = logger.child('@spfn/core:env-registry');\n\n/**\n * 환경변수 레지스트리\n *\n * 스키마 기반 환경변수 관리 및 검증\n */\nexport class EnvRegistry<T extends EnvSchemaCollection = EnvSchemaCollection>\n{\n private schemas = new Map<string, EnvVarSchema>();\n private hasValidated = false;\n\n constructor(schemas?: T)\n {\n if (schemas)\n {\n this.registerMultiple(schemas);\n }\n }\n\n /**\n * 스키마 등록\n */\n register(schema: EnvVarSchema): void\n {\n this.schemas.set(schema.key, schema);\n }\n\n /**\n * 여러 스키마 등록\n */\n registerMultiple(schemas: EnvSchemaCollection): void\n {\n for (const [key, schema] of Object.entries(schemas))\n {\n this.register({ ...schema, key });\n }\n }\n\n /**\n * 검증 상태 리셋 (테스트용)\n */\n reset(): void\n {\n this.hasValidated = false;\n }\n\n /**\n * 환경변수 원시값 가져오기 (fallback 지원)\n */\n private getRawValue(key: string, fallbackKeys?: string[]): string | undefined\n {\n let value = process.env[key];\n\n if (!value && fallbackKeys)\n {\n for (const fallbackKey of fallbackKeys)\n {\n value = process.env[fallbackKey];\n if (value)\n {\n break;\n }\n }\n }\n\n return value;\n }\n\n /**\n * 값에 validator 적용\n */\n private applyValidator<U>(\n value: string,\n schema: EnvVarSchema<U>,\n ): U\n {\n if (schema.validator)\n {\n return schema.validator(value) as U;\n }\n\n return value as U;\n }\n\n /**\n * 스키마 검증 수행 (값 읽기 없이)\n *\n * @internal\n */\n private validateSchemas(): void\n {\n // Skip if already validated\n if (this.hasValidated)\n {\n return;\n }\n\n const warnings: string[] = [];\n\n // 클라이언트 변수 중 민감정보 경고\n for (const [key, schema] of this.schemas)\n {\n if (isClientAccessible(key) && schema.sensitive)\n {\n warnings.push(\n `${key} is marked as sensitive but accessible from client (NEXT_PUBLIC_*). Remove NEXT_PUBLIC_ prefix or unmark as sensitive.`,\n );\n }\n }\n\n // Log warnings\n if (warnings.length > 0)\n {\n envLogger.warn('Environment validation warnings:');\n warnings.forEach(w => envLogger.warn(` - ${w}`));\n }\n\n this.hasValidated = true;\n }\n\n /**\n * SKIP_ENV_VALIDATION 환경변수 확인\n */\n private shouldSkipValidation(): boolean\n {\n const skip = process.env.SKIP_ENV_VALIDATION;\n\n return skip === 'true' || skip === '1';\n }\n\n /**\n * 실제 접근 시점에 환경변수 값 가져오기 및 검증\n *\n * @internal\n */\n private getAndValidate(key: string): any\n {\n const schema = this.schemas.get(key);\n if (!schema)\n {\n return undefined;\n }\n\n // Get raw value using common helper\n const value = this.getRawValue(key, schema.fallbackKeys);\n\n // Check if required (skip if SKIP_ENV_VALIDATION is set)\n if (schema.required && !value && !this.shouldSkipValidation())\n {\n const fallbackHint = schema.fallbackKeys\n ? ` (or ${schema.fallbackKeys.join(', ')})`\n : '';\n\n const errorMsg = `${key}${fallbackHint} is required but not set. ${schema.description || ''}`;\n envLogger.error(`Environment validation failed:\\n - ${errorMsg}`);\n throw new Error('Environment validation failed');\n }\n\n // If no value and not required, use default\n if (!value)\n {\n return schema.default;\n }\n\n // Check minLength\n if (schema.minLength !== undefined && value.length < schema.minLength)\n {\n const errorMsg = `${key} must be at least ${schema.minLength} characters long (current: ${value.length})`;\n envLogger.error(`Environment validation failed:\\n - ${errorMsg}`);\n throw new Error('Environment validation failed');\n }\n\n // Apply validator\n try\n {\n return this.applyValidator(value, schema);\n }\n catch (error)\n {\n const errorMsg = `${key} validation failed: ${error instanceof Error ? error.message : String(error)}`;\n envLogger.error(`Environment validation failed:\\n - ${errorMsg}`);\n throw new Error('Environment validation failed');\n }\n }\n\n /**\n * 모든 환경변수를 명시적으로 검증 (SKIP_ENV_VALIDATION 무시)\n *\n * CLI에서 사용하기 위한 메서드로, 모든 required 환경변수를 강제 검증합니다.\n *\n * @returns 검증 결과 (errors, warnings)\n */\n validateAll(): { errors: Array<{ key: string; message: string }>; warnings: Array<{ key: string; message: string }> }\n {\n const errors: Array<{ key: string; message: string }> = [];\n const warnings: Array<{ key: string; message: string }> = [];\n\n for (const [key, schema] of this.schemas)\n {\n // 클라이언트 변수 중 민감정보 경고\n if (isClientAccessible(key) && schema.sensitive)\n {\n warnings.push({\n key,\n message: `${key} is marked as sensitive but accessible from client (NEXT_PUBLIC_*).`,\n });\n }\n\n const value = this.getRawValue(key, schema.fallbackKeys);\n\n // Check required\n if (schema.required && !value)\n {\n const fallbackHint = schema.fallbackKeys\n ? ` (or ${schema.fallbackKeys.join(', ')})`\n : '';\n errors.push({\n key,\n message: `${key}${fallbackHint} is required but not set. ${schema.description || ''}`,\n });\n continue;\n }\n\n // Check minLength\n if (value && schema.minLength !== undefined && value.length < schema.minLength)\n {\n errors.push({\n key,\n message: `${key} must be at least ${schema.minLength} characters long (current: ${value.length})`,\n });\n continue;\n }\n\n // Check validator\n if (value && schema.validator)\n {\n try\n {\n schema.validator(value);\n }\n catch (error)\n {\n errors.push({\n key,\n message: `${key} validation failed: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n }\n }\n\n return { errors, warnings };\n }\n\n /**\n * 환경변수 검증 및 타입 안전한 env 객체 반환\n *\n * Proxy 기반으로 구현되어 실제 환경변수 접근 시점에 값을 읽고 검증합니다.\n * 이를 통해 dotenv 로딩 타이밍과 무관하게 최신 환경변수 값을 가져올 수 있습니다.\n *\n * @returns 검증된 환경변수 객체 (Proxy)\n * @throws {Error} 필수 변수 누락 또는 검증 실패 시\n *\n * @example\n * ```typescript\n * const registry = createEnvRegistry(schema);\n * const env = registry.validate(); // 스키마만 검증\n * // ... dotenv 로딩 ...\n * console.log(env.DATABASE_URL); // 이 시점에 실제 값 읽기\n * ```\n */\n validate(): InferEnvType<T>\n {\n // Perform schema-level validation (without reading values)\n this.validateSchemas();\n\n // Return Proxy that lazily reads and validates on access\n return new Proxy({} as InferEnvType<T>, {\n get: (_target, prop: string) =>\n {\n return this.getAndValidate(prop);\n },\n\n ownKeys: () =>\n {\n return Array.from(this.schemas.keys());\n },\n\n getOwnPropertyDescriptor: (_target, prop: string) =>\n {\n if (this.schemas.has(prop))\n {\n return {\n enumerable: true,\n configurable: true,\n get: () => this.getAndValidate(prop),\n };\n }\n\n return undefined;\n },\n\n has: (_target, prop: string) =>\n {\n return this.schemas.has(prop);\n },\n });\n }\n}\n\n/**\n * 환경변수 검증 결과\n */\nexport interface EnvValidationResult\n{\n valid: boolean;\n errors: Array<{ key: string; message: string }>;\n warnings: Array<{ key: string; message: string }>;\n}\n\n/**\n * 레지스트리 생성 헬퍼\n *\n * @example\n * ```typescript\n * const schema = defineEnvSchema({\n * DATABASE_URL: envString({ description: 'Database URL', required: true })\n * });\n *\n * const registry = createEnvRegistry(schema);\n * const env = registry.validate();\n * ```\n */\nexport function createEnvRegistry<T extends EnvSchemaCollection>(\n schemas: T,\n): EnvRegistry<T>\n{\n return new EnvRegistry(schemas);\n}\n\n/**\n * 모든 환경변수를 명시적으로 검증 (SKIP_ENV_VALIDATION 무시)\n *\n * CLI `spfn env validate` 명령어에서 사용\n *\n * @param registries - 검증할 레지스트리 배열\n * @returns 검증 결과\n *\n * @example\n * ```typescript\n * const result = validateAllEnv([coreRegistry, authRegistry]);\n * if (!result.valid) {\n * console.error('Missing env vars:', result.errors);\n * process.exit(1);\n * }\n * ```\n */\nexport function validateAllEnv(\n registries: EnvRegistry<any>[],\n): EnvValidationResult\n{\n const errors: Array<{ key: string; message: string }> = [];\n const warnings: Array<{ key: string; message: string }> = [];\n\n for (const registry of registries)\n {\n const result = registry.validateAll();\n errors.push(...result.errors);\n warnings.push(...result.warnings);\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/env/validator.ts","../../src/env/schema.ts","../../src/env/registry.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Environment Variable Management - Parsers\n *\n * Parser functions that transform and validate environment variable strings.\n * All parsers follow the pattern: (value: string) => T or throw Error\n */\n\n// ============================================================================\n// Core Types\n// ============================================================================\n\n/**\n * Parser function that transforms and validates a string value\n * @throws Error if validation fails\n */\nexport type Parser<T> = (value: string) => T;\n\n// ============================================================================\n// String Parsers\n// ============================================================================\n\n/**\n * Parse a non-empty string\n *\n * @param value - Value to parse\n * @returns Trimmed string\n * @throws Error if string is empty after trimming\n *\n * @example\n * ```typescript\n * const name = getEnvVar('APP_NAME', {\n * validator: parseString,\n * });\n * ```\n */\nexport function parseString(value: string): string\n{\n const trimmed = value.trim();\n\n if (trimmed.length === 0)\n {\n throw new Error('Value cannot be empty');\n }\n\n return trimmed;\n}\n\n/**\n * Create a string parser with validation rules\n *\n * @param options - Validation options\n * @returns Parser function\n *\n * @example\n * ```typescript\n * const apiKey = getEnvVar('API_KEY', {\n * validator: createStringParser({\n * minLength: 32,\n * pattern: /^[A-Za-z0-9_-]+$/,\n * }),\n * });\n * ```\n */\nexport function createStringParser(\n options: {\n minLength?: number;\n maxLength?: number;\n pattern?: RegExp;\n trim?: boolean;\n } = {},\n): Parser<string>\n{\n return (value: string): string =>\n {\n const { minLength, maxLength, pattern, trim = true } = options;\n\n let result = trim ? value.trim() : value;\n\n // Empty check\n if (result.length === 0)\n {\n throw new Error('Value cannot be empty');\n }\n\n // Length validation\n if (minLength !== undefined && result.length < minLength)\n {\n throw new Error(`Must be at least ${minLength} characters long (current: ${result.length})`);\n }\n\n if (maxLength !== undefined && result.length > maxLength)\n {\n throw new Error(`Must be at most ${maxLength} characters long (current: ${result.length})`);\n }\n\n // Pattern validation\n if (pattern && !pattern.test(result))\n {\n throw new Error(`Must match pattern ${pattern}`);\n }\n\n return result;\n };\n}\n\n// ============================================================================\n// Boolean Parser\n// ============================================================================\n\n/**\n * Parse a boolean environment variable\n *\n * Accepts: 'true', '1', 'yes' (case-insensitive) → true\n * 'false', '0', 'no' (case-insensitive) → false\n *\n * @param value - Value to parse\n * @returns Boolean value\n * @throws Error if value is not a valid boolean string\n *\n * @example\n * ```typescript\n * const debug = getEnvVar('DEBUG', {\n * default: 'false',\n * validator: parseBoolean,\n * });\n * ```\n */\nexport function parseBoolean(value: string): boolean\n{\n const normalized = value.toLowerCase().trim();\n\n if (['true', '1', 'yes'].includes(normalized))\n {\n return true;\n }\n\n if (['false', '0', 'no'].includes(normalized))\n {\n return false;\n }\n\n throw new Error(\n `Must be a boolean value (true/false, 1/0, yes/no), got: ${value}`,\n );\n}\n\n// ============================================================================\n// Number Parsers\n// ============================================================================\n\n/**\n * Parse and validate number\n *\n * @param value - Value to parse\n * @param options - Validation options\n * @returns Parsed number\n * @throws Error if invalid number or constraint violation\n *\n * @example\n * ```typescript\n * const port = getEnvVar('PORT', {\n * default: '3000',\n * validator: (val) => parseNumber(val, { min: 1, max: 65535, integer: true }),\n * });\n * ```\n */\nexport function parseNumber(\n value: string,\n options: { min?: number; max?: number; integer?: boolean } = {},\n): number\n{\n const { min, max, integer = false } = options;\n\n // Reject empty strings\n if (value.trim() === '')\n {\n throw new Error('Value cannot be empty');\n }\n\n const num = Number(value);\n\n if (isNaN(num))\n {\n throw new Error(`Must be a valid number, got: ${value}`);\n }\n\n if (integer && !Number.isInteger(num))\n {\n throw new Error(`Must be an integer, got: ${value}`);\n }\n\n if (min !== undefined && num < min)\n {\n throw new Error(`Must be at least ${min}, got: ${num}`);\n }\n\n if (max !== undefined && num > max)\n {\n throw new Error(`Must be at most ${max}, got: ${num}`);\n }\n\n return num;\n}\n\n/**\n * Create a number parser with specific constraints\n *\n * @param options - Validation constraints\n * @returns Parser function\n *\n * @example\n * ```typescript\n * const port = getEnvVar('PORT', {\n * default: '3000',\n * validator: createNumberParser({ min: 1, max: 65535, integer: true }),\n * });\n * ```\n */\nexport function createNumberParser(\n options: { min?: number; max?: number; integer?: boolean } = {},\n): Parser<number>\n{\n return (value: string) => parseNumber(value, options);\n}\n\n/**\n * Parse integer with optional constraints\n *\n * @param value - Value to parse\n * @param options - Min/max constraints\n * @returns Parsed integer\n * @throws Error if invalid or out of range\n *\n * @example\n * ```typescript\n * const retries = getEnvVar('MAX_RETRIES', {\n * default: '3',\n * validator: (val) => parseInteger(val, { min: 1, max: 10 }),\n * });\n * ```\n */\nexport function parseInteger(\n value: string,\n options: { min?: number; max?: number } = {},\n): number\n{\n return parseNumber(value, { ...options, integer: true });\n}\n\n/**\n * Parse float/decimal number with optional constraints\n *\n * @param value - Value to parse\n * @param options - Min/max constraints\n * @returns Parsed decimal number\n * @throws Error if invalid or out of range\n *\n * @example\n * ```typescript\n * const ratio = getEnvVar('CACHE_RATIO', {\n * default: '0.75',\n * validator: (val) => parseDecimal(val, { min: 0, max: 1 }),\n * });\n * ```\n */\nexport function parseDecimal(\n value: string,\n options: { min?: number; max?: number } = {},\n): number\n{\n return parseNumber(value, { ...options, integer: false });\n}\n\n// ============================================================================\n// URL Parsers\n// ============================================================================\n\n/**\n * Parse and validate URL\n *\n * @param value - Value to parse\n * @param options - Validation options\n * @returns Validated URL string\n * @throws Error if invalid URL or protocol mismatch\n *\n * @example\n * ```typescript\n * const apiUrl = getEnvVar('API_URL', {\n * validator: (val) => parseUrl(val, { protocol: 'https' }),\n * });\n * ```\n */\nexport function parseUrl(\n value: string,\n options: { protocol?: 'http' | 'https' | 'any' } = {},\n): string\n{\n const { protocol = 'any' } = options;\n\n // Parse URL (may throw TypeError)\n let url: URL;\n try\n {\n url = new URL(value);\n }\n catch (error)\n {\n if (error instanceof TypeError)\n {\n throw new Error(`Invalid URL: ${value}`);\n }\n throw error;\n }\n\n // Validate protocol\n if (protocol === 'http' && url.protocol !== 'http:')\n {\n throw new Error(`URL must use HTTP protocol, got ${url.protocol}`);\n }\n\n if (protocol === 'https' && url.protocol !== 'https:')\n {\n throw new Error(`URL must use HTTPS protocol, got ${url.protocol}`);\n }\n\n return value;\n}\n\n/**\n * Create a URL parser with specific protocol requirement\n *\n * @param protocol - Required protocol ('http', 'https', or 'any')\n * @returns Parser function\n *\n * @example\n * ```typescript\n * const apiUrl = getEnvVar('API_URL', {\n * validator: createUrlParser('https'),\n * });\n * ```\n */\nexport function createUrlParser(protocol: 'http' | 'https' | 'any' = 'any'): Parser<string>\n{\n return (value: string) => parseUrl(value, { protocol });\n}\n\n/**\n * Parse PostgreSQL connection string\n *\n * @param value - Value to parse\n * @returns Validated PostgreSQL URL string\n * @throws Error if invalid PostgreSQL URL\n *\n * @example\n * ```typescript\n * const dbUrl = getEnvVar('DATABASE_URL', {\n * required: true,\n * validator: parsePostgresUrl,\n * });\n * ```\n */\nexport function parsePostgresUrl(value: string): string\n{\n // Parse URL (may throw TypeError)\n let url: URL;\n try\n {\n url = new URL(value);\n }\n catch (error)\n {\n if (error instanceof TypeError)\n {\n // Never echo the value — these URLs carry embedded credentials\n throw new Error('Invalid PostgreSQL URL');\n }\n throw error;\n }\n\n // Validate protocol\n if (url.protocol !== 'postgres:' && url.protocol !== 'postgresql:')\n {\n throw new Error(\n `Must be a PostgreSQL URL (postgres:// or postgresql://), got ${url.protocol}`,\n );\n }\n\n return value;\n}\n\n/**\n * Parse Redis connection string\n *\n * @param value - Value to parse\n * @returns Validated Redis URL string\n * @throws Error if invalid Redis URL\n *\n * @example\n * ```typescript\n * const redisUrl = getEnvVar('REDIS_URL', {\n * required: true,\n * validator: parseRedisUrl,\n * });\n * ```\n */\nexport function parseRedisUrl(value: string): string\n{\n // Parse URL (may throw TypeError)\n let url: URL;\n try\n {\n url = new URL(value);\n }\n catch (error)\n {\n if (error instanceof TypeError)\n {\n // Never echo the value — these URLs carry embedded credentials\n throw new Error('Invalid Redis URL');\n }\n throw error;\n }\n\n // Validate protocol\n if (url.protocol !== 'redis:' && url.protocol !== 'rediss:')\n {\n throw new Error(\n `Must be a Redis URL (redis:// or rediss://), got ${url.protocol}`,\n );\n }\n\n return value;\n}\n\n// ============================================================================\n// Enum Parser\n// ============================================================================\n\n/**\n * Parse and validate enum value\n *\n * @param value - Value to parse\n * @param allowed - Array of allowed values\n * @param caseInsensitive - Whether to perform case-insensitive comparison\n * @returns Validated enum value\n * @throws Error if value not in allowed list\n *\n * @example\n * ```typescript\n * const env = getEnvVar('NODE_ENV', {\n * validator: (val) => parseEnum(val, ['development', 'production', 'test']),\n * });\n * ```\n */\nexport function parseEnum(\n value: string,\n allowed: string[],\n caseInsensitive = false,\n): string\n{\n if (caseInsensitive)\n {\n const normalizedValue = value.toLowerCase();\n const normalizedAllowed = allowed.map((v) => v.toLowerCase());\n const index = normalizedAllowed.indexOf(normalizedValue);\n\n if (index === -1)\n {\n throw new Error(\n `Must be one of [${allowed.join(', ')}], got: ${value}`,\n );\n }\n\n return allowed[index]; // Return original case from allowed list\n }\n\n if (!allowed.includes(value))\n {\n throw new Error(\n `Must be one of [${allowed.join(', ')}], got: ${value}`,\n );\n }\n\n return value;\n}\n\n/**\n * Create an enum parser with specific allowed values\n *\n * @param allowed - Array of allowed values\n * @param caseInsensitive - Whether to perform case-insensitive comparison\n * @returns Parser function\n *\n * @example\n * ```typescript\n * const logLevel = getEnvVar('LOG_LEVEL', {\n * default: 'info',\n * validator: createEnumParser(['debug', 'info', 'warn', 'error']),\n * });\n * ```\n */\nexport function createEnumParser(allowed: string[], caseInsensitive = false): Parser<string>\n{\n return (value: string) => parseEnum(value, allowed, caseInsensitive);\n}\n\n// ============================================================================\n// JSON Parser\n// ============================================================================\n\n/**\n * Parse JSON string\n *\n * @param value - JSON string to parse\n * @returns Parsed JSON value\n * @throws Error if invalid JSON\n *\n * @example\n * ```typescript\n * const config = getEnvVar('CONFIG_JSON', {\n * validator: parseJson,\n * });\n * ```\n */\nexport function parseJson<T = any>(value: string): T\n{\n try\n {\n return JSON.parse(value) as T;\n }\n catch (error)\n {\n throw new Error(\n `Invalid JSON: ${error instanceof Error ? error.message : 'Unknown error'}`,\n );\n }\n}\n\n/**\n * Create a typed JSON parser\n *\n * @returns Parser function\n *\n * @example\n * ```typescript\n * interface Config {\n * host: string;\n * port: number;\n * }\n *\n * const config = getEnvVar('CONFIG_JSON', {\n * validator: createJsonParser<Config>(),\n * });\n * ```\n */\nexport function createJsonParser<T>(): Parser<T>\n{\n return (value: string) => parseJson<T>(value);\n}\n\n// ============================================================================\n// Array Parser\n// ============================================================================\n\n/**\n * Parse comma-separated values into array\n *\n * @param value - Comma-separated string\n * @param options - Parser options\n * @returns Array of strings\n *\n * @example\n * ```typescript\n * const hosts = getEnvVar('ALLOWED_HOSTS', {\n * validator: parseArray,\n * });\n * // \"localhost,example.com,api.example.com\" → ['localhost', 'example.com', 'api.example.com']\n * ```\n */\nexport function parseArray(\n value: string,\n options: {\n separator?: string;\n trim?: boolean;\n filter?: (item: string) => boolean;\n } = {},\n): string[]\n{\n const { separator = ',', trim = true, filter } = options;\n\n if (value.trim() === '')\n {\n return [];\n }\n\n let items = value.split(separator);\n\n if (trim)\n {\n items = items.map((item) => item.trim());\n }\n\n if (filter)\n {\n items = items.filter(filter);\n }\n\n return items;\n}\n\n/**\n * Create an array parser with item parser\n *\n * @param itemParser - Parser to apply to each array item\n * @param options - Array parsing options\n * @returns Parser function\n *\n * @example\n * ```typescript\n * // Parse comma-separated ports\n * const ports = getEnvVar('PORTS', {\n * validator: createArrayParser(\n * createNumberParser({ min: 1, max: 65535, integer: true })\n * ),\n * });\n * // \"3000,4000,5000\" → [3000, 4000, 5000]\n * ```\n */\nexport function createArrayParser<T>(\n itemParser: Parser<T>,\n options: { separator?: string } = {},\n): Parser<T[]>\n{\n return (value: string): T[] =>\n {\n const items = parseArray(value, options);\n\n return items.map((item, index) =>\n {\n try\n {\n return itemParser(item);\n }\n catch (error)\n {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Invalid item at index ${index}: ${message}`);\n }\n });\n };\n}\n\n// ============================================================================\n// Secure Secret Parser\n// ============================================================================\n\n/**\n * Calculate Shannon entropy of a string\n * Returns entropy in bits per character\n *\n * @param str - String to calculate entropy for\n * @returns Entropy value (0 to ~6.6 bits for printable ASCII)\n *\n * @example\n * ```typescript\n * const entropy = calculateEntropy('my-secret-key');\n * // Higher entropy = more random\n * // - Random lowercase: ~4.7 bits/char\n * // - Random alphanumeric: ~5.2 bits/char\n * // - Random printable ASCII: ~6.6 bits/char\n * // - \"aaaaaaa...\": ~0 bits/char\n * ```\n */\nfunction calculateEntropy(str: string): number\n{\n const len = str.length;\n const frequencies = new Map<string, number>();\n\n // Count character frequencies\n for (const char of str)\n {\n frequencies.set(char, (frequencies.get(char) || 0) + 1);\n }\n\n // Calculate Shannon entropy\n let entropy = 0;\n for (const count of frequencies.values())\n {\n const probability = count / len;\n entropy -= probability * Math.log2(probability);\n }\n\n return entropy;\n}\n\n/**\n * Create a secure secret parser with entropy validation\n *\n * Validates cryptographic secrets for sufficient length, character diversity, and randomness.\n * Uses Shannon entropy to measure randomness quality.\n *\n * @param options - Validation options\n * @returns Parser function\n *\n * @example\n * ```typescript\n * const sessionSecret = getEnvVar('SESSION_SECRET', {\n * validator: createSecureSecretParser({\n * minLength: 32, // Minimum 256-bit\n * minUniqueChars: 16, // Character diversity\n * minEntropy: 3.5, // Shannon entropy (bits/char)\n * }),\n * });\n * ```\n */\nexport function createSecureSecretParser(\n options: {\n minLength?: number;\n minUniqueChars?: number;\n minEntropy?: number;\n } = {},\n): Parser<string>\n{\n const {\n minLength = 32,\n minUniqueChars = 16,\n minEntropy = 3.5,\n } = options;\n\n return (value: string): string =>\n {\n const length = value.length;\n const uniqueChars = new Set(value).size;\n const entropy = calculateEntropy(value);\n\n // Check length (minimum for cryptographic strength)\n if (length < minLength)\n {\n throw new Error(\n `Secret too short: ${length} characters (minimum: ${minLength})`,\n );\n }\n\n // Check unique character diversity\n if (uniqueChars < minUniqueChars)\n {\n throw new Error(\n `Secret has low diversity: ${uniqueChars} unique characters (minimum: ${minUniqueChars})`,\n );\n }\n\n // Check Shannon entropy (randomness quality)\n // Reference values:\n // - Random lowercase: ~4.7 bits/char\n // - Random alphanumeric: ~5.2 bits/char\n // - Random printable ASCII: ~6.6 bits/char\n // - \"aaaaaaa...\": ~0 bits/char\n // - \"abcabcabc...\": ~1.58 bits/char\n if (entropy < minEntropy)\n {\n throw new Error(\n `Secret has low entropy: ${entropy.toFixed(2)} bits/char (minimum: ${minEntropy}). Use a more random secret.`,\n );\n }\n\n return value;\n };\n}\n\n// ============================================================================\n// Password Parser\n// ============================================================================\n\n/**\n * Create a password strength parser\n *\n * Validates password strength based on configurable requirements.\n * Useful for enforcing password policies in environment variables or user input.\n *\n * @param options - Validation options\n * @returns Parser function\n *\n * @example\n * ```typescript\n * const adminPassword = getEnvVar('ADMIN_PASSWORD', {\n * validator: createPasswordParser({\n * minLength: 12,\n * requireUppercase: true,\n * requireLowercase: true,\n * requireNumber: true,\n * requireSpecial: true,\n * }),\n * });\n * ```\n */\nexport function createPasswordParser(\n options: {\n minLength?: number;\n requireUppercase?: boolean;\n requireLowercase?: boolean;\n requireNumber?: boolean;\n requireSpecial?: boolean;\n } = {},\n): Parser<string>\n{\n const {\n minLength = 8,\n requireUppercase = true,\n requireLowercase = true,\n requireNumber = true,\n requireSpecial = true,\n } = options;\n\n return (value: string): string =>\n {\n const errors: string[] = [];\n\n // Length check\n if (value.length < minLength)\n {\n errors.push(`Must be at least ${minLength} characters`);\n }\n\n // Uppercase check\n if (requireUppercase && !/[A-Z]/.test(value))\n {\n errors.push('Must contain at least one uppercase letter');\n }\n\n // Lowercase check\n if (requireLowercase && !/[a-z]/.test(value))\n {\n errors.push('Must contain at least one lowercase letter');\n }\n\n // Number check\n if (requireNumber && !/[0-9]/.test(value))\n {\n errors.push('Must contain at least one number');\n }\n\n // Special character check\n if (requireSpecial && !/[^A-Za-z0-9]/.test(value))\n {\n errors.push('Must contain at least one special character');\n }\n\n if (errors.length > 0)\n {\n throw new Error(`Password validation failed: ${errors.join(', ')}`);\n }\n\n return value;\n };\n}\n\n// ============================================================================\n// Parser Composition\n// ============================================================================\n\n/**\n * Chain multiple parsers sequentially\n *\n * Each parser receives the output of the previous parser.\n * Useful for multi-step validation/transformation.\n *\n * @param parsers - Array of parser functions\n * @returns Combined parser function\n *\n * @example\n * ```typescript\n * const apiKey = getEnvVar('API_KEY', {\n * validator: chain(\n * parseString,\n * createStringParser({ minLength: 32, pattern: /^[A-Za-z0-9_-]+$/ }),\n * ),\n * });\n * ```\n */\nexport function chain<T>(...parsers: Array<Parser<T>>): Parser<T>\n{\n return (value: string): T =>\n {\n let result = value as any;\n\n for (const parser of parsers)\n {\n result = parser(result);\n }\n\n return result;\n };\n}\n\n/**\n * Apply parser with fallback value\n *\n * If parser throws, returns fallback instead.\n * Useful for optional environment variables with complex parsing.\n *\n * @param parser - Parser to attempt\n * @param fallback - Fallback value if parsing fails\n * @returns Parser function\n *\n * @example\n * ```typescript\n * const config = getEnvVar('CONFIG_JSON', {\n * validator: withFallback(parseJson, { host: 'localhost', port: 3000 }),\n * });\n * ```\n */\nexport function withFallback<T>(parser: Parser<T>, fallback: T): Parser<T>\n{\n return (value: string): T =>\n {\n try\n {\n return parser(value);\n }\n catch\n {\n return fallback;\n }\n };\n}\n\n/**\n * Make parser optional\n *\n * Returns undefined for empty strings instead of throwing.\n *\n * @param parser - Parser to make optional\n * @returns Parser function that returns T | undefined\n *\n * @example\n * ```typescript\n * const redisUrl = getEnvVar('REDIS_URL', {\n * validator: optional(parseRedisUrl),\n * });\n * // Empty string → undefined\n * // Valid URL → parsed URL\n * // Invalid URL → throws\n * ```\n */\nexport function optional<T>(parser: Parser<T>): Parser<T | undefined>\n{\n return (value: string): T | undefined =>\n {\n if (value.trim() === '')\n {\n return undefined;\n }\n\n return parser(value);\n };\n}\n","/**\n * Environment Variable Schema Definition System\n *\n * 환경변수에 메타데이터를 정의하여 중앙 관리, 문서화, 검증을 지원합니다.\n *\n * @example\n * ```typescript\n * const schema = defineEnvSchema({\n * DATABASE_URL: envUrl({\n * description: 'Database connection',\n * required: true,\n * validator: parsePostgresUrl,\n * sensitive: true,\n * })\n * });\n * ```\n *\n * @module env/schema\n */\n\nimport { parseBoolean, parseNumber, parseJson } from './validator';\n\n/**\n * 환경변수 스키마 정의\n */\nexport interface EnvVarSchema<T = string>\n{\n /** 환경변수 키 */\n key: string;\n\n /** 설명 (목적, 사용처) */\n description: string;\n\n /** 타입 */\n type: 'string' | 'number' | 'boolean' | 'url' | 'enum' | 'json';\n\n /** 필수 여부 */\n required?: boolean;\n\n /** 기본값 */\n default?: T;\n\n /** 검증/변환 함수 */\n validator?: (value: string) => T;\n\n // === 검증 옵션 ===\n\n /** Fallback 환경변수 키들 (backward compatibility) */\n fallbackKeys?: string[];\n\n /** 최소 길이 (문자열 타입) */\n minLength?: number;\n\n // === 메타데이터 ===\n\n /** 민감정보 여부 (로깅 시 마스킹) */\n sensitive?: boolean;\n\n /**\n * 자동 생성 방식 — 값이 미지정이면 프로비저닝(secrets 관리 CLI)이 이 방식으로 생성한다.\n * 외부에서 받아야 하는 시크릿(API 키 등)은 generate를 비워 사용자 입력으로 둔다.\n */\n generate?: 'hex32' | 'hex64' | 'uuid' | 'base64url32';\n\n /** 예시 값들 (타입과 일치해야 함) */\n examples?: T[];\n\n // === 파일 분리 ===\n\n /**\n * Next.js 프로세스에서 사용 여부\n *\n * - true: .env.local에 존재해야 함 (Next.js 서버 컴포넌트에서 접근 가능)\n * - false: .env.server에만 존재해야 함 (SPFN 서버에서만 접근)\n *\n * @default NEXT_PUBLIC_* 이면 true, 아니면 false\n */\n nextjs?: boolean;\n}\n\n/**\n * 스키마 컬렉션 타입\n */\nexport type EnvSchemaCollection = Record<string, EnvVarSchema<any>>;\n\n/**\n * Helper type: Check if field has default value\n */\ntype HasDefault<T> = T extends { default: any } ? true : false;\n\n/**\n * Helper type: Check if field is explicitly required\n */\ntype IsRequired<T> = T extends { required: true } ? true : false;\n\n/**\n * Helper type: Check if field should be required (has default OR required: true)\n */\ntype ShouldBeRequired<T> = HasDefault<T> extends true ? true : IsRequired<T>;\n\n/**\n * 스키마로부터 타입 추출\n *\n * required: true 또는 default가 있는 필드 → 필수\n * required: false 또는 미지정 → optional (| undefined)\n */\nexport type InferEnvType<T extends EnvSchemaCollection> = {\n // Required fields (required: true OR has default)\n [K in keyof T as ShouldBeRequired<T[K]> extends true ? K : never]:\n T[K] extends EnvVarSchema<infer U> ? U : string;\n} & {\n // Optional fields (required: false OR not specified)\n [K in keyof T as ShouldBeRequired<T[K]> extends true ? never : K]?:\n T[K] extends EnvVarSchema<infer U> ? U | undefined : string | undefined;\n};\n\n/**\n * 스키마 정의 헬퍼 (타입 추론 지원)\n *\n * Automatically fills in the `key` property from object keys.\n *\n * @example\n * ```typescript\n * const schema = defineEnvSchema({\n * DATABASE_URL: envString({ description: 'Database URL', required: true })\n * });\n * // Automatically adds key: 'DATABASE_URL'\n * ```\n */\nexport function defineEnvSchema<T extends Record<string, any>>(\n schema: T,\n): { [K in keyof T]: T[K] & { key: K } }\n{\n const result: any = {};\n\n for (const key in schema)\n {\n result[key] = {\n ...schema[key],\n key,\n };\n }\n\n return result;\n}\n\n/**\n * 문자열 스키마 헬퍼\n *\n * @example\n * ```typescript\n * const schema = {\n * API_KEY: {\n * ...envString({\n * description: 'API authentication key',\n * required: true,\n * sensitive: true,\n * }),\n * key: 'API_KEY',\n * }\n * };\n * ```\n */\nexport function envString<T extends Omit<EnvVarSchema, 'key' | 'type'>>(\n options: T,\n): T & { type: 'string'; validator: (value: string) => string }\n{\n return {\n ...options,\n type: 'string',\n validator: options.validator || ((value: string) => value),\n };\n}\n\n/**\n * 시크릿 스키마 헬퍼 — sensitive:true 자동.\n *\n * generate 지정 시 프로비저닝(secrets CLI)이 값을 자동 생성, 미지정이면 외부 입력(사용자가 붙여넣음).\n * 이로써 env.config.ts가 \"설정(envString) vs 외부 시크릿(envSecret) vs 자동 시크릿(envSecret+generate)\"을\n * 선언적으로 가른다 — CLI·프레임워크·프로비저닝이 한 원천을 읽는다.\n *\n * @example\n * ```typescript\n * SPFN_AUTH_SESSION_SECRET: envSecret({ description: '세션 서명 키', generate: 'base64url32' }),\n * OPENAI_API_KEY: envSecret({ description: 'OpenAI API 키' }), // generate 없음 → 외부 입력\n * ```\n */\nexport function envSecret<T extends Omit<EnvVarSchema, 'key' | 'type' | 'sensitive'>>(\n options: T,\n): T & { type: 'string'; sensitive: true; validator: (value: string) => string }\n{\n return {\n ...options,\n type: 'string',\n sensitive: true,\n validator: options.validator || ((value: string) => value),\n };\n}\n\n/**\n * 숫자 스키마 헬퍼\n *\n * @example\n * ```typescript\n * const schema = {\n * PORT: {\n * ...envNumber({\n * description: 'Server port',\n * default: 3000,\n * validator: createNumberParser({ min: 1, max: 65535 }),\n * }),\n * key: 'PORT',\n * }\n * };\n * ```\n */\nexport function envNumber<T extends Omit<EnvVarSchema<number>, 'key' | 'type'>>(\n options: T,\n): T & { type: 'number'; validator: (value: string) => number }\n{\n return {\n ...options,\n type: 'number',\n validator: options.validator || parseNumber,\n };\n}\n\n/**\n * Boolean 스키마 헬퍼\n *\n * @example\n * ```typescript\n * const schema = {\n * DEBUG: {\n * ...envBoolean({\n * description: 'Enable debug mode',\n * default: false,\n * }),\n * key: 'DEBUG',\n * }\n * };\n * ```\n */\nexport function envBoolean<T extends Omit<EnvVarSchema<boolean>, 'key' | 'type'>>(\n options: T,\n): T & { type: 'boolean'; validator: (value: string) => boolean }\n{\n return {\n ...options,\n type: 'boolean',\n validator: options.validator || parseBoolean,\n };\n}\n\n/**\n * URL 스키마 헬퍼\n *\n * @example\n * ```typescript\n * const schema = {\n * DATABASE_URL: {\n * ...envUrl({\n * description: 'Database connection URL',\n * required: true,\n * validator: parsePostgresUrl,\n * }),\n * key: 'DATABASE_URL',\n * }\n * };\n * ```\n */\nexport function envUrl<T extends Omit<EnvVarSchema, 'key' | 'type'>>(\n options: T,\n): T & { type: 'url' }\n{\n return {\n ...options,\n type: 'url',\n };\n}\n\n/**\n * Enum 스키마 헬퍼\n *\n * @example\n * ```typescript\n * const schema = {\n * LOG_LEVEL: {\n * ...envEnum(['debug', 'info', 'warn', 'error'] as const, {\n * description: 'Logging level',\n * default: 'info',\n * }),\n * key: 'LOG_LEVEL',\n * }\n * };\n * ```\n */\nexport function envEnum<\n T extends string,\n O extends Omit<EnvVarSchema<T>, 'key' | 'type' | 'validator'>,\n>(\n allowed: readonly T[],\n options: O,\n): O & { type: 'enum'; validator: (val: string) => T }\n{\n return {\n ...options,\n type: 'enum',\n validator: (val: string): T =>\n {\n if (!allowed.includes(val as T))\n {\n throw new Error(`Must be one of: ${allowed.join(', ')}, got: ${val}`);\n }\n\n return val as T;\n },\n };\n}\n\n/**\n * JSON 스키마 헬퍼\n *\n * @example\n * ```typescript\n * const schema = {\n * CONFIG_JSON: {\n * ...envJson<{ host: string; port: number }>({\n * description: 'JSON configuration object',\n * required: true,\n * }),\n * key: 'CONFIG_JSON',\n * }\n * };\n * ```\n */\nexport function envJson<\n T = any,\n O extends Omit<EnvVarSchema<T>, 'key' | 'type' | 'validator'> = Omit<EnvVarSchema<T>, 'key' | 'type' | 'validator'>,\n>(\n options: O,\n): O & { type: 'json'; validator: (val: string) => T }\n{\n return {\n ...options,\n type: 'json',\n validator: (val: string) => parseJson<T>(val),\n };\n}\n\n/**\n * 환경변수가 클라이언트에서 접근 가능한지 확인\n * (NEXT_PUBLIC_ 접두사로 판단)\n *\n * @param key - 환경변수 키\n * @returns 클라이언트에서 접근 가능하면 true\n *\n * @example\n * ```typescript\n * isClientAccessible('NEXT_PUBLIC_API_URL'); // true\n * isClientAccessible('DATABASE_URL'); // false\n * ```\n */\nexport function isClientAccessible(key: string): boolean\n{\n return key.startsWith('NEXT_PUBLIC_');\n}\n\n/**\n * 환경변수가 서버 전용인지 확인\n * (NEXT_PUBLIC_ 접두사가 없으면 서버 전용)\n *\n * @param key - 환경변수 키\n * @returns 서버 전용이면 true\n *\n * @example\n * ```typescript\n * isServerOnly('DATABASE_URL'); // true\n * isServerOnly('NEXT_PUBLIC_API_URL'); // false\n * ```\n */\nexport function isServerOnly(key: string): boolean\n{\n return !isClientAccessible(key);\n}\n\n/**\n * 스키마의 nextjs 옵션 값 결정\n *\n * 명시적으로 지정되지 않은 경우:\n * - NEXT_PUBLIC_* → true\n * - 그 외 → false\n *\n * @param schema - 환경변수 스키마\n * @returns Next.js 프로세스에서 사용 가능 여부\n */\nexport function isNextjsAccessible(schema: EnvVarSchema): boolean\n{\n if (schema.nextjs !== undefined)\n {\n return schema.nextjs;\n }\n\n return isClientAccessible(schema.key);\n}\n\n/**\n * 스키마가 SPFN 서버 전용인지 확인\n *\n * @param schema - 환경변수 스키마\n * @returns SPFN 서버에서만 사용되면 true\n */\nexport function isSpfnServerOnly(schema: EnvVarSchema): boolean\n{\n return !isNextjsAccessible(schema);\n}\n","/**\n * Environment Variable Registry\n *\n * 환경변수 스키마를 등록하고 타입 안전하게 접근할 수 있는 레지스트리\n *\n * @example\n * ```typescript\n * const schema = defineEnvSchema({\n * DATABASE_URL: envString({ description: 'Database URL', required: true })\n * });\n *\n * const registry = createEnvRegistry(schema);\n * const env = registry.validate(); // 검증 + env 반환\n * console.log(env.DATABASE_URL);\n * ```\n *\n * @module env/registry\n */\nimport type { EnvVarSchema, EnvSchemaCollection, InferEnvType } from './schema';\nimport { isClientAccessible } from './schema';\nimport { logger } from '@spfn/core/logger';\n\nconst envLogger = logger.child('@spfn/core:env-registry');\n\n/**\n * 환경변수 레지스트리\n *\n * 스키마 기반 환경변수 관리 및 검증\n */\nexport class EnvRegistry<T extends EnvSchemaCollection = EnvSchemaCollection>\n{\n private schemas = new Map<string, EnvVarSchema>();\n private hasValidated = false;\n\n constructor(schemas?: T)\n {\n if (schemas)\n {\n this.registerMultiple(schemas);\n }\n }\n\n /**\n * 스키마 등록\n */\n register(schema: EnvVarSchema): void\n {\n this.schemas.set(schema.key, schema);\n }\n\n /**\n * 여러 스키마 등록\n */\n registerMultiple(schemas: EnvSchemaCollection): void\n {\n for (const [key, schema] of Object.entries(schemas))\n {\n this.register({ ...schema, key });\n }\n }\n\n /**\n * 검증 상태 리셋 (테스트용)\n */\n reset(): void\n {\n this.hasValidated = false;\n }\n\n /**\n * 환경변수 원시값 가져오기 (fallback 지원)\n */\n private getRawValue(key: string, fallbackKeys?: string[]): string | undefined\n {\n let value = process.env[key];\n\n if (!value && fallbackKeys)\n {\n for (const fallbackKey of fallbackKeys)\n {\n value = process.env[fallbackKey];\n if (value)\n {\n break;\n }\n }\n }\n\n return value;\n }\n\n /**\n * 값에 validator 적용\n */\n private applyValidator<U>(\n value: string,\n schema: EnvVarSchema<U>,\n ): U\n {\n if (schema.validator)\n {\n return schema.validator(value) as U;\n }\n\n return value as U;\n }\n\n /**\n * 스키마 검증 수행 (값 읽기 없이)\n *\n * @internal\n */\n private validateSchemas(): void\n {\n // Skip if already validated\n if (this.hasValidated)\n {\n return;\n }\n\n const warnings: string[] = [];\n\n // 클라이언트 변수 중 민감정보 경고\n for (const [key, schema] of this.schemas)\n {\n if (isClientAccessible(key) && schema.sensitive)\n {\n warnings.push(\n `${key} is marked as sensitive but accessible from client (NEXT_PUBLIC_*). Remove NEXT_PUBLIC_ prefix or unmark as sensitive.`,\n );\n }\n }\n\n // Log warnings\n if (warnings.length > 0)\n {\n envLogger.warn('Environment validation warnings:');\n warnings.forEach(w => envLogger.warn(` - ${w}`));\n }\n\n this.hasValidated = true;\n }\n\n /**\n * SKIP_ENV_VALIDATION 환경변수 확인\n */\n private shouldSkipValidation(): boolean\n {\n const skip = process.env.SKIP_ENV_VALIDATION;\n\n return skip === 'true' || skip === '1';\n }\n\n /**\n * 실제 접근 시점에 환경변수 값 가져오기 및 검증\n *\n * @internal\n */\n private getAndValidate(key: string): any\n {\n const schema = this.schemas.get(key);\n if (!schema)\n {\n return undefined;\n }\n\n // Get raw value using common helper\n const value = this.getRawValue(key, schema.fallbackKeys);\n\n // Check if required (skip if SKIP_ENV_VALIDATION is set)\n if (schema.required && !value && !this.shouldSkipValidation())\n {\n const fallbackHint = schema.fallbackKeys\n ? ` (or ${schema.fallbackKeys.join(', ')})`\n : '';\n\n const errorMsg = `${key}${fallbackHint} is required but not set. ${schema.description || ''}`;\n envLogger.error(`Environment validation failed:\\n - ${errorMsg}`);\n throw new Error('Environment validation failed');\n }\n\n // If no value and not required, use default\n if (!value)\n {\n return schema.default;\n }\n\n // Check minLength\n if (schema.minLength !== undefined && value.length < schema.minLength)\n {\n const errorMsg = `${key} must be at least ${schema.minLength} characters long (current: ${value.length})`;\n envLogger.error(`Environment validation failed:\\n - ${errorMsg}`);\n throw new Error('Environment validation failed');\n }\n\n // Apply validator\n try\n {\n return this.applyValidator(value, schema);\n }\n catch (error)\n {\n // For sensitive keys, never log the validator's message — it may have\n // interpolated the secret value (e.g. a DB/Redis URL with credentials).\n const detail = schema.sensitive\n ? '(value hidden — sensitive key)'\n : (error instanceof Error ? error.message : String(error));\n const errorMsg = `${key} validation failed: ${detail}`;\n envLogger.error(`Environment validation failed:\\n - ${errorMsg}`);\n throw new Error('Environment validation failed');\n }\n }\n\n /**\n * 모든 환경변수를 명시적으로 검증 (SKIP_ENV_VALIDATION 무시)\n *\n * CLI에서 사용하기 위한 메서드로, 모든 required 환경변수를 강제 검증합니다.\n *\n * @returns 검증 결과 (errors, warnings)\n */\n validateAll(): { errors: Array<{ key: string; message: string }>; warnings: Array<{ key: string; message: string }> }\n {\n const errors: Array<{ key: string; message: string }> = [];\n const warnings: Array<{ key: string; message: string }> = [];\n\n for (const [key, schema] of this.schemas)\n {\n // 클라이언트 변수 중 민감정보 경고\n if (isClientAccessible(key) && schema.sensitive)\n {\n warnings.push({\n key,\n message: `${key} is marked as sensitive but accessible from client (NEXT_PUBLIC_*).`,\n });\n }\n\n const value = this.getRawValue(key, schema.fallbackKeys);\n\n // Check required\n if (schema.required && !value)\n {\n const fallbackHint = schema.fallbackKeys\n ? ` (or ${schema.fallbackKeys.join(', ')})`\n : '';\n errors.push({\n key,\n message: `${key}${fallbackHint} is required but not set. ${schema.description || ''}`,\n });\n continue;\n }\n\n // Check minLength\n if (value && schema.minLength !== undefined && value.length < schema.minLength)\n {\n errors.push({\n key,\n message: `${key} must be at least ${schema.minLength} characters long (current: ${value.length})`,\n });\n continue;\n }\n\n // Check validator\n if (value && schema.validator)\n {\n try\n {\n schema.validator(value);\n }\n catch (error)\n {\n errors.push({\n key,\n message: `${key} validation failed: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n }\n }\n\n return { errors, warnings };\n }\n\n /**\n * 환경변수 검증 및 타입 안전한 env 객체 반환\n *\n * Proxy 기반으로 구현되어 실제 환경변수 접근 시점에 값을 읽고 검증합니다.\n * 이를 통해 dotenv 로딩 타이밍과 무관하게 최신 환경변수 값을 가져올 수 있습니다.\n *\n * @returns 검증된 환경변수 객체 (Proxy)\n * @throws {Error} 필수 변수 누락 또는 검증 실패 시\n *\n * @example\n * ```typescript\n * const registry = createEnvRegistry(schema);\n * const env = registry.validate(); // 스키마만 검증\n * // ... dotenv 로딩 ...\n * console.log(env.DATABASE_URL); // 이 시점에 실제 값 읽기\n * ```\n */\n validate(): InferEnvType<T>\n {\n // Perform schema-level validation (without reading values)\n this.validateSchemas();\n\n // Return Proxy that lazily reads and validates on access\n return new Proxy({} as InferEnvType<T>, {\n get: (_target, prop: string) =>\n {\n return this.getAndValidate(prop);\n },\n\n ownKeys: () =>\n {\n return Array.from(this.schemas.keys());\n },\n\n getOwnPropertyDescriptor: (_target, prop: string) =>\n {\n if (this.schemas.has(prop))\n {\n return {\n enumerable: true,\n configurable: true,\n get: () => this.getAndValidate(prop),\n };\n }\n\n return undefined;\n },\n\n has: (_target, prop: string) =>\n {\n return this.schemas.has(prop);\n },\n });\n }\n}\n\n/**\n * 환경변수 검증 결과\n */\nexport interface EnvValidationResult\n{\n valid: boolean;\n errors: Array<{ key: string; message: string }>;\n warnings: Array<{ key: string; message: string }>;\n}\n\n/**\n * 레지스트리 생성 헬퍼\n *\n * @example\n * ```typescript\n * const schema = defineEnvSchema({\n * DATABASE_URL: envString({ description: 'Database URL', required: true })\n * });\n *\n * const registry = createEnvRegistry(schema);\n * const env = registry.validate();\n * ```\n */\nexport function createEnvRegistry<T extends EnvSchemaCollection>(\n schemas: T,\n): EnvRegistry<T>\n{\n return new EnvRegistry(schemas);\n}\n\n/**\n * 모든 환경변수를 명시적으로 검증 (SKIP_ENV_VALIDATION 무시)\n *\n * CLI `spfn env validate` 명령어에서 사용\n *\n * @param registries - 검증할 레지스트리 배열\n * @returns 검증 결과\n *\n * @example\n * ```typescript\n * const result = validateAllEnv([coreRegistry, authRegistry]);\n * if (!result.valid) {\n * console.error('Missing env vars:', result.errors);\n * process.exit(1);\n * }\n * ```\n */\nexport function validateAllEnv(\n registries: EnvRegistry<any>[],\n): EnvValidationResult\n{\n const errors: Array<{ key: string; message: string }> = [];\n const warnings: Array<{ key: string; message: string }> = [];\n\n for (const registry of registries)\n {\n const result = registry.validateAll();\n errors.push(...result.errors);\n warnings.push(...result.warnings);\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n"]}
|
package/dist/errors/index.d.ts
CHANGED
|
@@ -179,6 +179,14 @@ declare class DatabaseError<TDetails extends Record<string, unknown> = Record<st
|
|
|
179
179
|
statusCode?: number;
|
|
180
180
|
details?: TDetails;
|
|
181
181
|
});
|
|
182
|
+
/**
|
|
183
|
+
* Whether this error's message/details are derived from the raw database
|
|
184
|
+
* driver (SQL text, table/column/constraint names, parameter values) and
|
|
185
|
+
* therefore must NOT be exposed to clients in production. Defined as a
|
|
186
|
+
* prototype getter so it is never serialized into the response by toJSON().
|
|
187
|
+
* Subclasses with a safe, constructed message override this to `false`.
|
|
188
|
+
*/
|
|
189
|
+
get internal(): boolean;
|
|
182
190
|
}
|
|
183
191
|
/**
|
|
184
192
|
* Connection Error (503 Service Unavailable)
|
|
@@ -215,6 +223,7 @@ declare class EntityNotFoundError extends QueryError {
|
|
|
215
223
|
resource: string;
|
|
216
224
|
id: string | number;
|
|
217
225
|
});
|
|
226
|
+
get internal(): boolean;
|
|
218
227
|
}
|
|
219
228
|
/**
|
|
220
229
|
* Constraint Violation Error (400 Bad Request)
|
|
@@ -263,6 +272,7 @@ declare class DuplicateEntryError extends QueryError {
|
|
|
263
272
|
field: string;
|
|
264
273
|
value: string | number;
|
|
265
274
|
});
|
|
275
|
+
get internal(): boolean;
|
|
266
276
|
}
|
|
267
277
|
|
|
268
278
|
type databaseErrors_ConnectionError = ConnectionError;
|
package/dist/errors/index.js
CHANGED
|
@@ -321,6 +321,16 @@ var DatabaseError = class extends SerializableError {
|
|
|
321
321
|
this.details = data.details;
|
|
322
322
|
Error.captureStackTrace(this, this.constructor);
|
|
323
323
|
}
|
|
324
|
+
/**
|
|
325
|
+
* Whether this error's message/details are derived from the raw database
|
|
326
|
+
* driver (SQL text, table/column/constraint names, parameter values) and
|
|
327
|
+
* therefore must NOT be exposed to clients in production. Defined as a
|
|
328
|
+
* prototype getter so it is never serialized into the response by toJSON().
|
|
329
|
+
* Subclasses with a safe, constructed message override this to `false`.
|
|
330
|
+
*/
|
|
331
|
+
get internal() {
|
|
332
|
+
return true;
|
|
333
|
+
}
|
|
324
334
|
};
|
|
325
335
|
var ConnectionError = class extends DatabaseError {
|
|
326
336
|
constructor(data) {
|
|
@@ -351,6 +361,10 @@ var EntityNotFoundError = class extends QueryError {
|
|
|
351
361
|
this.resource = data.resource;
|
|
352
362
|
this.id = data.id;
|
|
353
363
|
}
|
|
364
|
+
// Message/details are constructed from the resource + id, not driver text
|
|
365
|
+
get internal() {
|
|
366
|
+
return false;
|
|
367
|
+
}
|
|
354
368
|
};
|
|
355
369
|
var ConstraintViolationError = class extends QueryError {
|
|
356
370
|
constructor(data) {
|
|
@@ -379,14 +393,18 @@ var DuplicateEntryError = class extends QueryError {
|
|
|
379
393
|
value;
|
|
380
394
|
constructor(data) {
|
|
381
395
|
super({
|
|
382
|
-
message: `${data.field}
|
|
396
|
+
message: `${data.field} already exists`,
|
|
383
397
|
statusCode: 409,
|
|
384
|
-
details: { field: data.field
|
|
398
|
+
details: { field: data.field }
|
|
385
399
|
});
|
|
386
400
|
this.name = "DuplicateEntryError";
|
|
387
401
|
this.field = data.field;
|
|
388
402
|
this.value = data.value;
|
|
389
403
|
}
|
|
404
|
+
// Field-only message/details — safe to surface to the client (not internal)
|
|
405
|
+
get internal() {
|
|
406
|
+
return false;
|
|
407
|
+
}
|
|
390
408
|
};
|
|
391
409
|
|
|
392
410
|
// src/errors/error-utils.ts
|