@spfn/core 0.2.0-beta.6 → 0.2.0-beta.64

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.
Files changed (73) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +181 -1281
  3. package/dist/authz/index.d.ts +34 -0
  4. package/dist/authz/index.js +415 -0
  5. package/dist/authz/index.js.map +1 -0
  6. package/dist/{boss-DI1r4kTS.d.ts → boss-gXhgctn6.d.ts} +40 -0
  7. package/dist/cache/index.js +42 -30
  8. package/dist/cache/index.js.map +1 -1
  9. package/dist/codegen/index.d.ts +55 -8
  10. package/dist/codegen/index.js +183 -7
  11. package/dist/codegen/index.js.map +1 -1
  12. package/dist/config/index.d.ts +585 -6
  13. package/dist/config/index.js +116 -5
  14. package/dist/config/index.js.map +1 -1
  15. package/dist/db/index.d.ts +270 -4
  16. package/dist/db/index.js +404 -60
  17. package/dist/db/index.js.map +1 -1
  18. package/dist/define-middleware-DuXD8Hvu.d.ts +167 -0
  19. package/dist/env/index.d.ts +26 -2
  20. package/dist/env/index.js +15 -5
  21. package/dist/env/index.js.map +1 -1
  22. package/dist/env/loader.d.ts +26 -19
  23. package/dist/env/loader.js +32 -25
  24. package/dist/env/loader.js.map +1 -1
  25. package/dist/errors/index.d.ts +10 -0
  26. package/dist/errors/index.js +20 -2
  27. package/dist/errors/index.js.map +1 -1
  28. package/dist/event/index.d.ts +33 -3
  29. package/dist/event/index.js +24 -3
  30. package/dist/event/index.js.map +1 -1
  31. package/dist/event/sse/client.d.ts +42 -3
  32. package/dist/event/sse/client.js +128 -45
  33. package/dist/event/sse/client.js.map +1 -1
  34. package/dist/event/sse/index.d.ts +12 -5
  35. package/dist/event/sse/index.js +271 -32
  36. package/dist/event/sse/index.js.map +1 -1
  37. package/dist/event/ws/client.d.ts +59 -0
  38. package/dist/event/ws/client.js +273 -0
  39. package/dist/event/ws/client.js.map +1 -0
  40. package/dist/event/ws/index.d.ts +94 -0
  41. package/dist/event/ws/index.js +272 -0
  42. package/dist/event/ws/index.js.map +1 -0
  43. package/dist/job/index.d.ts +2 -2
  44. package/dist/job/index.js +155 -42
  45. package/dist/job/index.js.map +1 -1
  46. package/dist/logger/index.d.ts +5 -0
  47. package/dist/logger/index.js +14 -0
  48. package/dist/logger/index.js.map +1 -1
  49. package/dist/middleware/index.d.ts +243 -2
  50. package/dist/middleware/index.js +1323 -13
  51. package/dist/middleware/index.js.map +1 -1
  52. package/dist/nextjs/index.d.ts +2 -2
  53. package/dist/nextjs/index.js +77 -31
  54. package/dist/nextjs/index.js.map +1 -1
  55. package/dist/nextjs/server.d.ts +53 -23
  56. package/dist/nextjs/server.js +197 -66
  57. package/dist/nextjs/server.js.map +1 -1
  58. package/dist/route/index.d.ts +138 -146
  59. package/dist/route/index.js +238 -22
  60. package/dist/route/index.js.map +1 -1
  61. package/dist/security/index.d.ts +83 -0
  62. package/dist/security/index.js +173 -0
  63. package/dist/security/index.js.map +1 -0
  64. package/dist/server/index.d.ts +450 -17
  65. package/dist/server/index.js +1756 -277
  66. package/dist/server/index.js.map +1 -1
  67. package/dist/{router-Di7ENoah.d.ts → token-manager-jKD_EsSE.d.ts} +121 -1
  68. package/dist/{types-D_N_U-Py.d.ts → types-7Mhoxnnt.d.ts} +21 -1
  69. package/dist/types-BFB72jbM.d.ts +282 -0
  70. package/dist/types-DVjf37yO.d.ts +205 -0
  71. package/docs/file-upload.md +717 -0
  72. package/package.json +235 -208
  73. package/dist/types-B-e_f2dQ.d.ts +0 -121
@@ -1,17 +1,27 @@
1
1
  /**
2
2
  * Environment Variable Loader
3
3
  *
4
- * Next.js 스타일의 환경변수 파일 로딩
4
+ * Next.js 스타일의 환경변수 파일 로딩 (환경별 분리 지원)
5
+ *
6
+ * 로딩 우선순위 (낮음 -> 높음, 나중 파일이 덮어씀):
7
+ * 1. .env - 기본값 (committed)
8
+ * 2. .env.{NODE_ENV} - 환경별 오버라이드 (committed)
9
+ * 3. .env.local - 로컬 오버라이드 (gitignored, test에서 스킵)
10
+ * 4. .env.{NODE_ENV}.local - 환경별 시크릿 (gitignored)
11
+ * 5. .env.server - 서버 전용 (gitignored, Next.js 미로드)
5
12
  *
6
13
  * @example
7
14
  * ```typescript
8
15
  * import { loadEnv } from '@spfn/core/env/loader';
9
16
  *
10
- * // SPFN 서버 진입점에서 호출
17
+ * // 기본 사용 (NODE_ENV 자동 감지)
11
18
  * loadEnv();
12
19
  *
13
- * // 이후 스키마 검증
14
- * const env = createEnvRegistry(envSchema).validate();
20
+ * // 특정 환경 지정
21
+ * loadEnv({ nodeEnv: 'production' });
22
+ *
23
+ * // 서버 레이어 제외 (Next.js 클라이언트용)
24
+ * loadEnv({ server: false });
15
25
  * ```
16
26
  *
17
27
  * @module env/loader
@@ -25,6 +35,16 @@ interface LoadEnvOptions {
25
35
  * @default process.cwd()
26
36
  */
27
37
  cwd?: string;
38
+ /**
39
+ * NODE_ENV 값 (환경별 .env 파일 결정)
40
+ * @default process.env.NODE_ENV || 'local'
41
+ */
42
+ nodeEnv?: string;
43
+ /**
44
+ * 서버 전용 파일 포함 여부 (.env.server)
45
+ * @default true
46
+ */
47
+ server?: boolean;
28
48
  /**
29
49
  * 디버그 모드 (로드된 파일 로깅)
30
50
  * @default false
@@ -52,24 +72,11 @@ interface LoadEnvResult {
52
72
  /**
53
73
  * 프로젝트 루트의 환경변수 파일들을 규칙에 따라 로드
54
74
  *
55
- * Next.js 스타일의 우선순위를 따름:
56
- * - .env .env.local .env.server .env.server.local
57
- * - 나중에 로드된 값이 이전 값을 덮어씀
75
+ * 모든 파일을 파싱 후 머지한 뒤 process.env에 한번에 적용.
76
+ * 이미 process.env 존재하는 키는 덮어쓰지 않음 (플랫폼 주입 보호).
58
77
  *
59
78
  * @param options - 로드 옵션
60
79
  * @returns 로드 결과 (로드된 파일, 키 목록)
61
- *
62
- * @example
63
- * ```typescript
64
- * // 기본 사용
65
- * loadEnv();
66
- *
67
- * // 커스텀 경로
68
- * loadEnv({ cwd: '/path/to/project' });
69
- *
70
- * // 디버그 모드
71
- * loadEnv({ debug: true });
72
- * ```
73
80
  */
74
81
  declare function loadEnv(options?: LoadEnvOptions): LoadEnvResult;
75
82
  /**
@@ -5,58 +5,65 @@ import { logger } from '@spfn/core/logger';
5
5
 
6
6
  // src/env/loader.ts
7
7
  var envLogger = logger.child("@spfn/core:env-loader");
8
- var ENV_FILES = [
9
- ".env",
10
- ".env.local",
11
- ".env.server",
12
- ".env.server.local"
13
- ];
8
+ function getEnvFiles(nodeEnv, server) {
9
+ const files = [
10
+ ".env",
11
+ `.env.${nodeEnv}`
12
+ ];
13
+ if (nodeEnv !== "test") {
14
+ files.push(".env.local");
15
+ }
16
+ files.push(`.env.${nodeEnv}.local`);
17
+ if (server) {
18
+ files.push(".env.server");
19
+ }
20
+ return files;
21
+ }
14
22
  function parseEnvFile(filePath) {
15
23
  if (!existsSync(filePath)) {
16
24
  return null;
17
25
  }
18
- const content = readFileSync(filePath, "utf-8");
19
- return parse(content);
26
+ return parse(readFileSync(filePath, "utf-8"));
20
27
  }
21
28
  function loadEnv(options = {}) {
22
29
  const {
23
30
  cwd = process.cwd(),
31
+ nodeEnv = process.env.NODE_ENV || "local",
32
+ server = true,
24
33
  debug = false,
25
34
  override = false
26
35
  } = options;
36
+ const envFiles = getEnvFiles(nodeEnv, server);
27
37
  const loadedFiles = [];
28
- const loadedKeys = /* @__PURE__ */ new Set();
29
- for (const fileName of ENV_FILES) {
38
+ const existingKeys = new Set(Object.keys(process.env));
39
+ const merged = {};
40
+ for (const fileName of envFiles) {
30
41
  const filePath = resolve(cwd, fileName);
31
42
  const parsed = parseEnvFile(filePath);
32
43
  if (parsed === null) {
33
44
  continue;
34
45
  }
35
46
  loadedFiles.push(fileName);
36
- for (const [key, value] of Object.entries(parsed)) {
37
- if (!override && process.env[key] !== void 0) {
38
- continue;
39
- }
40
- process.env[key] = value;
41
- loadedKeys.add(key);
47
+ Object.assign(merged, parsed);
48
+ }
49
+ const loadedKeys = [];
50
+ for (const [key, value] of Object.entries(merged)) {
51
+ if (!override && existingKeys.has(key)) {
52
+ continue;
42
53
  }
54
+ process.env[key] = value;
55
+ loadedKeys.push(key);
43
56
  }
44
57
  if (debug && loadedFiles.length > 0) {
45
58
  envLogger.debug(`Loaded env files: ${loadedFiles.join(", ")}`);
46
- envLogger.debug(`Loaded ${loadedKeys.size} environment variables`);
59
+ envLogger.debug(`Loaded ${loadedKeys.length} environment variables`);
47
60
  }
48
- return {
49
- loadedFiles,
50
- loadedKeys: Array.from(loadedKeys)
51
- };
61
+ return { loadedFiles, loadedKeys };
52
62
  }
53
63
  var isEnvLoaded = false;
54
64
  function loadEnvOnce(options = {}) {
55
65
  if (isEnvLoaded) {
56
- return {
57
- loadedFiles: [],
58
- loadedKeys: []
59
- };
66
+ return { loadedFiles: [], loadedKeys: [] };
60
67
  }
61
68
  isEnvLoaded = true;
62
69
  return loadEnv(options);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/env/loader.ts"],"names":[],"mappings":";;;;;;AAwBA,IAAM,SAAA,GAAY,MAAA,CAAO,KAAA,CAAM,uBAAuB,CAAA;AAkCtD,IAAM,SAAA,GAAY;AAAA,EACd,MAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA;AACJ,CAAA;AAKA,SAAS,aAAa,QAAA,EACtB;AACI,EAAA,IAAI,CAAC,UAAA,CAAW,QAAQ,CAAA,EACxB;AACI,IAAA,OAAO,IAAA;AAAA,EACX;AAEA,EAAA,MAAM,OAAA,GAAU,YAAA,CAAa,QAAA,EAAU,OAAO,CAAA;AAC9C,EAAA,OAAO,MAAM,OAAO,CAAA;AACxB;AAwCO,SAAS,OAAA,CAAQ,OAAA,GAA0B,EAAC,EACnD;AACI,EAAA,MAAM;AAAA,IACF,GAAA,GAAM,QAAQ,GAAA,EAAI;AAAA,IAClB,KAAA,GAAQ,KAAA;AAAA,IACR,QAAA,GAAW;AAAA,GACf,GAAI,OAAA;AAEJ,EAAA,MAAM,cAAwB,EAAC;AAC/B,EAAA,MAAM,UAAA,uBAAiB,GAAA,EAAY;AAEnC,EAAA,KAAA,MAAW,YAAY,SAAA,EACvB;AACI,IAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,GAAA,EAAK,QAAQ,CAAA;AACtC,IAAA,MAAM,MAAA,GAAS,aAAa,QAAQ,CAAA;AAEpC,IAAA,IAAI,WAAW,IAAA,EACf;AACI,MAAA;AAAA,IACJ;AAEA,IAAA,WAAA,CAAY,KAAK,QAAQ,CAAA;AAEzB,IAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,EAChD;AAEI,MAAA,IAAI,CAAC,QAAA,IAAY,OAAA,CAAQ,GAAA,CAAI,GAAG,MAAM,MAAA,EACtC;AACI,QAAA;AAAA,MACJ;AAEA,MAAA,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA,GAAI,KAAA;AACnB,MAAA,UAAA,CAAW,IAAI,GAAG,CAAA;AAAA,IACtB;AAAA,EACJ;AAEA,EAAA,IAAI,KAAA,IAAS,WAAA,CAAY,MAAA,GAAS,CAAA,EAClC;AACI,IAAA,SAAA,CAAU,MAAM,CAAA,kBAAA,EAAqB,WAAA,CAAY,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AAC7D,IAAA,SAAA,CAAU,KAAA,CAAM,CAAA,OAAA,EAAU,UAAA,CAAW,IAAI,CAAA,sBAAA,CAAwB,CAAA;AAAA,EACrE;AAEA,EAAA,OAAO;AAAA,IACH,WAAA;AAAA,IACA,UAAA,EAAY,KAAA,CAAM,IAAA,CAAK,UAAU;AAAA,GACrC;AACJ;AAKA,IAAI,WAAA,GAAc,KAAA;AAQX,SAAS,WAAA,CAAY,OAAA,GAA0B,EAAC,EACvD;AACI,EAAA,IAAI,WAAA,EACJ;AACI,IAAA,OAAO;AAAA,MACH,aAAa,EAAC;AAAA,MACd,YAAY;AAAC,KACjB;AAAA,EACJ;AAEA,EAAA,WAAA,GAAc,IAAA;AACd,EAAA,OAAO,QAAQ,OAAO,CAAA;AAC1B;AAKO,SAAS,iBAAA,GAChB;AACI,EAAA,WAAA,GAAc,KAAA;AAClB","file":"loader.js","sourcesContent":["/**\n * Environment Variable Loader\n *\n * Next.js 스타일의 환경변수 파일 로딩\n *\n * @example\n * ```typescript\n * import { loadEnv } from '@spfn/core/env/loader';\n *\n * // SPFN 서버 진입점에서 호출\n * loadEnv();\n *\n * // 이후 스키마 검증\n * const env = createEnvRegistry(envSchema).validate();\n * ```\n *\n * @module env/loader\n */\n\nimport { existsSync, readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { parse } from 'dotenv';\nimport { logger } from '@spfn/core/logger';\n\nconst envLogger = logger.child('@spfn/core:env-loader');\n\n/**\n * loadEnv 옵션\n */\nexport interface LoadEnvOptions\n{\n /**\n * 프로젝트 루트 경로\n * @default process.cwd()\n */\n cwd?: string;\n\n /**\n * 디버그 모드 (로드된 파일 로깅)\n * @default false\n */\n debug?: boolean;\n\n /**\n * 기존 process.env 값 덮어쓰기 허용\n * @default false\n */\n override?: boolean;\n}\n\n/**\n * 환경변수 파일 로딩 순서 (우선순위 낮음 높음)\n *\n * 1. .env - 기본값 (커밋 O)\n * 2. .env.local - 로컬 오버라이드 (커밋 X)\n * 3. .env.server - 서버 전용 기본값 (커밋 O)\n * 4. .env.server.local - 서버 전용 민감정보 (커밋 X)\n */\nconst ENV_FILES = [\n '.env',\n '.env.local',\n '.env.server',\n '.env.server.local',\n] as const;\n\n/**\n * 단일 .env 파일 파싱\n */\nfunction parseEnvFile(filePath: string): Record<string, string> | null\n{\n if (!existsSync(filePath))\n {\n return null;\n }\n\n const content = readFileSync(filePath, 'utf-8');\n return parse(content);\n}\n\n/**\n * 환경변수 로드 결과\n */\nexport interface LoadEnvResult\n{\n /**\n * 로드된 파일 목록\n */\n loadedFiles: string[];\n\n /**\n * 로드된 환경변수 키 목록\n */\n loadedKeys: string[];\n}\n\n/**\n * 프로젝트 루트의 환경변수 파일들을 규칙에 따라 로드\n *\n * Next.js 스타일의 우선순위를 따름:\n * - .env .env.local .env.server .env.server.local\n * - 나중에 로드된 값이 이전 값을 덮어씀\n *\n * @param options - 로드 옵션\n * @returns 로드 결과 (로드된 파일, 키 목록)\n *\n * @example\n * ```typescript\n * // 기본 사용\n * loadEnv();\n *\n * // 커스텀 경로\n * loadEnv({ cwd: '/path/to/project' });\n *\n * // 디버그 모드\n * loadEnv({ debug: true });\n * ```\n */\nexport function loadEnv(options: LoadEnvOptions = {}): LoadEnvResult\n{\n const {\n cwd = process.cwd(),\n debug = false,\n override = false,\n } = options;\n\n const loadedFiles: string[] = [];\n const loadedKeys = new Set<string>();\n\n for (const fileName of ENV_FILES)\n {\n const filePath = resolve(cwd, fileName);\n const parsed = parseEnvFile(filePath);\n\n if (parsed === null)\n {\n continue;\n }\n\n loadedFiles.push(fileName);\n\n for (const [key, value] of Object.entries(parsed))\n {\n // 기존 값이 있고 override가 false 스킵\n if (!override && process.env[key] !== undefined)\n {\n continue;\n }\n\n process.env[key] = value;\n loadedKeys.add(key);\n }\n }\n\n if (debug && loadedFiles.length > 0)\n {\n envLogger.debug(`Loaded env files: ${loadedFiles.join(', ')}`);\n envLogger.debug(`Loaded ${loadedKeys.size} environment variables`);\n }\n\n return {\n loadedFiles,\n loadedKeys: Array.from(loadedKeys),\n };\n}\n\n/**\n * 환경변수가 이미 로드되었는지 확인하는 플래그\n */\nlet isEnvLoaded = false;\n\n/**\n * 환경변수를 한 번만 로드 (중복 호출 방지)\n *\n * @param options - 로드 옵션\n * @returns 로드 결과 (이미 로드된 경우 빈 결과)\n */\nexport function loadEnvOnce(options: LoadEnvOptions = {}): LoadEnvResult\n{\n if (isEnvLoaded)\n {\n return {\n loadedFiles: [],\n loadedKeys: [],\n };\n }\n\n isEnvLoaded = true;\n return loadEnv(options);\n}\n\n/**\n * 환경변수 로드 상태 리셋 (테스트용)\n */\nexport function resetEnvLoadState(): void\n{\n isEnvLoaded = false;\n}\n"]}
1
+ {"version":3,"sources":["../../src/env/loader.ts"],"names":[],"mappings":"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","file":"loader.js","sourcesContent":["/**\n * Environment Variable Loader\n *\n * Next.js 스타일의 환경변수 파일 로딩 (환경별 분리 지원)\n *\n * 로딩 우선순위 (낮음 -> 높음, 나중 파일이 덮어씀):\n * 1. .env - 기본값 (committed)\n * 2. .env.{NODE_ENV} - 환경별 오버라이드 (committed)\n * 3. .env.local - 로컬 오버라이드 (gitignored, test에서 스킵)\n * 4. .env.{NODE_ENV}.local - 환경별 시크릿 (gitignored)\n * 5. .env.server - 서버 전용 (gitignored, Next.js 미로드)\n *\n * @example\n * ```typescript\n * import { loadEnv } from '@spfn/core/env/loader';\n *\n * // 기본 사용 (NODE_ENV 자동 감지)\n * loadEnv();\n *\n * // 특정 환경 지정\n * loadEnv({ nodeEnv: 'production' });\n *\n * // 서버 레이어 제외 (Next.js 클라이언트용)\n * loadEnv({ server: false });\n * ```\n *\n * @module env/loader\n */\n\nimport { existsSync, readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { parse } from 'dotenv';\nimport { logger } from '@spfn/core/logger';\n\nconst envLogger = logger.child('@spfn/core:env-loader');\n\n/**\n * loadEnv 옵션\n */\nexport interface LoadEnvOptions\n{\n /**\n * 프로젝트 루트 경로\n * @default process.cwd()\n */\n cwd?: string;\n\n /**\n * NODE_ENV 값 (환경별 .env 파일 결정)\n * @default process.env.NODE_ENV || 'local'\n */\n nodeEnv?: string;\n\n /**\n * 서버 전용 파일 포함 여부 (.env.server)\n * @default true\n */\n server?: boolean;\n\n /**\n * 디버그 모드 (로드된 파일 로깅)\n * @default false\n */\n debug?: boolean;\n\n /**\n * 기존 process.env 값 덮어쓰기 허용\n * @default false\n */\n override?: boolean;\n}\n\n/**\n * 환경변수 로드 결과\n */\nexport interface LoadEnvResult\n{\n /**\n * 로드된 파일 목록\n */\n loadedFiles: string[];\n\n /**\n * 로드된 환경변수 목록\n */\n loadedKeys: string[];\n}\n\n/**\n * NODE_ENV에 따른 .env 파일 목록 생성 (우선순위 낮음 -> 높음)\n *\n * 구체적인 파일이 승리:\n * - environment > base\n * - server > shared\n * - local > committed\n */\nfunction getEnvFiles(nodeEnv: string, server: boolean): string[]\n{\n const files: string[] = [\n '.env',\n `.env.${nodeEnv}`,\n ];\n\n // test 환경에서는 .env.local 스킵 (테스트 결정론성 보장)\n if (nodeEnv !== 'test')\n {\n files.push('.env.local');\n }\n\n files.push(`.env.${nodeEnv}.local`);\n\n if (server)\n {\n files.push('.env.server');\n }\n\n return files;\n}\n\n/**\n * 단일 .env 파일 파싱\n */\nfunction parseEnvFile(filePath: string): Record<string, string> | null\n{\n if (!existsSync(filePath))\n {\n return null;\n }\n\n return parse(readFileSync(filePath, 'utf-8'));\n}\n\n/**\n * 프로젝트 루트의 환경변수 파일들을 규칙에 따라 로드\n *\n * 모든 파일을 파싱 머지한 process.env 한번에 적용.\n * 이미 process.env 존재하는 키는 덮어쓰지 않음 (플랫폼 주입 보호).\n *\n * @param options - 로드 옵션\n * @returns 로드 결과 (로드된 파일, 키 목록)\n */\nexport function loadEnv(options: LoadEnvOptions = {}): LoadEnvResult\n{\n const {\n cwd = process.cwd(),\n nodeEnv = process.env.NODE_ENV || 'local',\n server = true,\n debug = false,\n override = false,\n } = options;\n\n const envFiles = getEnvFiles(nodeEnv, server);\n const loadedFiles: string[] = [];\n\n // 1) 기존 process.env 키 스냅샷 저장\n const existingKeys = new Set(Object.keys(process.env));\n\n // 2) 모든 .env 파일 파싱 후 머지 (나중 파일이 승리)\n const merged: Record<string, string> = {};\n\n for (const fileName of envFiles)\n {\n const filePath = resolve(cwd, fileName);\n const parsed = parseEnvFile(filePath);\n\n if (parsed === null)\n {\n continue;\n }\n\n loadedFiles.push(fileName);\n Object.assign(merged, parsed);\n }\n\n // 3) 머지된 결과를 process.env에 적용\n const loadedKeys: string[] = [];\n\n for (const [key, value] of Object.entries(merged))\n {\n // 기존 process.env에 이미 있는 키는 스킵 (override가 false 때)\n if (!override && existingKeys.has(key))\n {\n continue;\n }\n\n process.env[key] = value;\n loadedKeys.push(key);\n }\n\n if (debug && loadedFiles.length > 0)\n {\n envLogger.debug(`Loaded env files: ${loadedFiles.join(', ')}`);\n envLogger.debug(`Loaded ${loadedKeys.length} environment variables`);\n }\n\n return { loadedFiles, loadedKeys };\n}\n\n/**\n * 환경변수가 이미 로드되었는지 확인하는 플래그\n */\nlet isEnvLoaded = false;\n\n/**\n * 환경변수를 한 번만 로드 (중복 호출 방지)\n *\n * @param options - 로드 옵션\n * @returns 로드 결과 (이미 로드된 경우 빈 결과)\n */\nexport function loadEnvOnce(options: LoadEnvOptions = {}): LoadEnvResult\n{\n if (isEnvLoaded)\n {\n return { loadedFiles: [], loadedKeys: [] };\n }\n\n isEnvLoaded = true;\n\n return loadEnv(options);\n}\n\n/**\n * 환경변수 로드 상태 리셋 (테스트용)\n */\nexport function resetEnvLoadState(): void\n{\n isEnvLoaded = false;\n}\n"]}
@@ -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;
@@ -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} '${data.value}' already exists`,
396
+ message: `${data.field} already exists`,
383
397
  statusCode: 409,
384
- details: { field: data.field, value: data.value }
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
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/errors/error-registry.ts","../../src/errors/http-errors.ts","../../src/errors/serializable-error.ts","../../src/errors/database-errors.ts","../../src/errors/error-utils.ts","../../src/errors/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Error Registry\n *\n * Central registry for serializable error types.\n * Enables automatic error deserialization on the client side.\n */\n\nimport type { SerializableError } from './serializable-error';\n\n/**\n * Error constructor type\n */\nexport type SerializableErrorConstructor = new (data: any) => SerializableError;\n\n/**\n * Input type for ErrorRegistry constructor\n */\nexport type ErrorRegistryInput =\n | SerializableErrorConstructor\n | SerializableErrorConstructor[]\n | ErrorRegistry;\n\n/**\n * Error registry for serialization/deserialization\n *\n * @example\n * ```typescript\n * // Create registry with initial errors\n * const registry = new ErrorRegistry([\n * errorRegistry, // Another ErrorRegistry\n * PaymentFailedError, // Single error class\n * [RefundError, OrderError], // Array of error classes\n * ]);\n *\n * // Or create empty and append\n * const registry = new ErrorRegistry();\n * registry\n * .append(ValidationError)\n * .append([PaymentFailedError, RefundError]);\n *\n * // Deserialize from JSON\n * const error = registry.deserialize({\n * __type: 'PaymentFailedError',\n * message: 'Payment failed',\n * transactionId: 'tx_123',\n * reason: 'insufficient_funds'\n * });\n *\n * // error instanceof PaymentFailedError === true\n * ```\n */\nexport class ErrorRegistry\n{\n private errors = new Map<string, SerializableErrorConstructor>();\n\n constructor(initialErrors?: ErrorRegistryInput[])\n {\n if (initialErrors)\n {\n for (const input of initialErrors)\n {\n if (input instanceof ErrorRegistry)\n {\n this.concat(input);\n }\n else if (Array.isArray(input))\n {\n this.append(input);\n }\n else\n {\n this.append(input);\n }\n }\n }\n }\n\n /**\n * Append error class(es) to the registry\n *\n * @param ErrorClass - Single error constructor\n * @returns This registry for chaining\n */\n append(ErrorClass: SerializableErrorConstructor): this;\n\n /**\n * Append error class(es) to the registry\n *\n * @param ErrorClasses - Array of error constructors\n * @returns This registry for chaining\n */\n append(ErrorClasses: SerializableErrorConstructor[]): this;\n\n /**\n * Append error class(es) to the registry\n *\n * @param input - Error constructor or array of constructors\n * @returns This registry for chaining\n */\n append(input: SerializableErrorConstructor | SerializableErrorConstructor[]): this\n {\n if (Array.isArray(input))\n {\n for (const ErrorClass of input)\n {\n this.errors.set(ErrorClass.name, ErrorClass);\n }\n }\n else\n {\n this.errors.set(input.name, input);\n }\n\n return this;\n }\n\n /**\n * Concatenate another ErrorRegistry into this one\n *\n * @param registry - Another ErrorRegistry to merge\n * @returns This registry for chaining\n */\n concat(registry: ErrorRegistry): this\n {\n for (const [name, ErrorClass] of registry.errors)\n {\n this.errors.set(name, ErrorClass);\n }\n\n return this;\n }\n\n /**\n * Check if error type is registered\n *\n * @param name - Error class name\n */\n has(name: string): boolean\n {\n return this.errors.has(name);\n }\n\n /**\n * Deserialize error from JSON data\n *\n * @param data - Serialized error data with __type field\n * @returns Deserialized error instance\n * @throws Error if error type is not registered\n */\n deserialize(data: { __type: string; [key: string]: any }): SerializableError\n {\n const ErrorClass = this.errors.get(data.__type);\n\n if (!ErrorClass)\n {\n throw new Error(`Unknown error type: ${data.__type}`);\n }\n\n // Pass entire data object to constructor\n return new ErrorClass(data);\n }\n\n /**\n * Try to deserialize error, return null if type unknown\n *\n * @param data - Serialized error data\n * @returns Deserialized error or null\n */\n tryDeserialize(data: { __type?: string; [key: string]: any }): SerializableError | null\n {\n if (!data.__type || !this.has(data.__type))\n {\n return null;\n }\n\n try\n {\n return this.deserialize(data as any);\n }\n catch\n {\n return null;\n }\n }\n\n /**\n * Get all registered error types\n */\n getRegisteredTypes(): string[]\n {\n return Array.from(this.errors.keys());\n }\n}","/**\n * HTTP Error Classes\n *\n * Standard HTTP error classes for API responses\n * All errors are serializable for type-safe client-side error handling\n */\n\nimport { SerializableError } from './serializable-error';\n\n/**\n * Base HTTP Error\n *\n * Base class for all HTTP-related errors\n */\nexport class HttpError extends SerializableError\n{\n public readonly statusCode: number;\n public details?: Record<string, unknown>;\n\n constructor(data: {\n message: string;\n statusCode: number;\n details?: Record<string, unknown>;\n })\n {\n super(data.message);\n\n this.name = 'HttpError';\n this.statusCode = data.statusCode;\n\n if (data.details)\n {\n this.details = data.details;\n }\n\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\n/**\n * Bad Request Error (400)\n *\n * Generic bad request - malformed syntax, invalid parameters, etc.\n */\nexport class BadRequestError extends HttpError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Bad request',\n statusCode: 400,\n details: data.details,\n });\n\n this.name = 'BadRequestError';\n }\n}\n\n/**\n * Validation Error (400)\n *\n * Input validation failure (request params, query, body)\n * Used by define-route system for automatic validation\n */\nexport class ValidationError extends HttpError\n{\n fields?: Array<{ path: string; message: string; value?: any }>;\n\n constructor(data: {\n message: string;\n fields?: Array<{ path: string; message: string; value?: any }>;\n details?: Record<string, any>;\n })\n {\n super({\n message: data.message,\n statusCode: 400,\n details: data.details,\n });\n\n this.name = 'ValidationError';\n\n if (data.fields)\n {\n this.fields = data.fields;\n }\n }\n}\n\n/**\n * Unauthorized Error (401)\n *\n * Authentication required or authentication failed\n */\nexport class UnauthorizedError extends HttpError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Authentication required',\n statusCode: 401,\n details: data.details,\n });\n\n this.name = 'UnauthorizedError';\n }\n}\n\n/**\n * Forbidden Error (403)\n *\n * Authenticated but lacks permission to access resource\n */\nexport class ForbiddenError extends HttpError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Access forbidden',\n statusCode: 403,\n details: data.details,\n });\n\n this.name = 'ForbiddenError';\n }\n}\n\n/**\n * Not Found Error (404)\n *\n * Requested resource does not exist\n */\nexport class NotFoundError extends HttpError\n{\n resource?: string;\n\n constructor(data: { message?: string; resource?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Resource not found',\n statusCode: 404,\n details: data.details,\n });\n\n this.name = 'NotFoundError';\n\n if (data.resource)\n {\n this.resource = data.resource;\n }\n }\n}\n\n/**\n * Conflict Error (409)\n *\n * Generic conflict - resource state conflict, concurrent modification, etc.\n */\nexport class ConflictError extends HttpError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Resource conflict',\n statusCode: 409,\n details: data.details,\n });\n\n this.name = 'ConflictError';\n }\n}\n\n/**\n * Gone Error (410)\n *\n * Resource permanently deleted and no longer available\n */\nexport class GoneError extends HttpError\n{\n resource?: string;\n\n constructor(data: { message?: string; resource?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Resource permanently deleted',\n statusCode: 410,\n details: data.details,\n });\n\n this.name = 'GoneError';\n\n if (data.resource)\n {\n this.resource = data.resource;\n }\n }\n}\n\n/**\n * Too Many Requests Error (429)\n *\n * Rate limit exceeded\n */\nexport class TooManyRequestsError extends HttpError\n{\n retryAfter?: number;\n\n constructor(data: {\n message?: string;\n retryAfter?: number;\n details?: Record<string, any>;\n } = {})\n {\n super({\n message: data.message || 'Too many requests',\n statusCode: 429,\n details: data.details,\n });\n\n this.name = 'TooManyRequestsError';\n\n if (data.retryAfter)\n {\n this.retryAfter = data.retryAfter;\n }\n }\n}\n\n/**\n * Internal Server Error (500)\n *\n * Generic server error when no specific error type applies\n */\nexport class InternalServerError extends HttpError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Internal server error',\n statusCode: 500,\n details: data.details,\n });\n\n this.name = 'InternalServerError';\n }\n}\n\n/**\n * Unsupported Media Type Error (415)\n *\n * Media type not supported - invalid file type, content type, etc.\n */\nexport class UnsupportedMediaTypeError extends HttpError\n{\n mediaType?: string;\n supportedTypes?: string[];\n\n constructor(data: {\n message?: string;\n mediaType?: string;\n supportedTypes?: string[];\n details?: Record<string, any>;\n } = {})\n {\n super({\n message: data.message || 'Unsupported media type',\n statusCode: 415,\n details: data.details,\n });\n\n this.name = 'UnsupportedMediaTypeError';\n\n if (data.mediaType)\n {\n this.mediaType = data.mediaType;\n }\n\n if (data.supportedTypes)\n {\n this.supportedTypes = data.supportedTypes;\n }\n }\n}\n\n/**\n * Unprocessable Entity Error (422)\n *\n * Request is well-formed but contains semantic errors\n */\nexport class UnprocessableEntityError extends HttpError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Unprocessable entity',\n statusCode: 422,\n details: data.details,\n });\n\n this.name = 'UnprocessableEntityError';\n }\n}\n\n/**\n * Service Unavailable Error (503)\n *\n * Service temporarily unavailable (maintenance, overload, etc.)\n */\nexport class ServiceUnavailableError extends HttpError\n{\n retryAfter?: number;\n\n constructor(data: {\n message?: string;\n retryAfter?: number;\n details?: Record<string, any>;\n } = {})\n {\n super({\n message: data.message || 'Service unavailable',\n statusCode: 503,\n details: data.details,\n });\n\n this.name = 'ServiceUnavailableError';\n\n if (data.retryAfter)\n {\n this.retryAfter = data.retryAfter;\n }\n }\n}","/**\n * Serializable Error Base Class\n *\n * Base class for errors that can be serialized/deserialized across HTTP boundary.\n * Automatically serializes public fields for transmission to client.\n */\n\n/**\n * Serialized error format for JSON transmission\n */\nexport interface SerializedError\n{\n __type: string;\n message: string;\n [key: string]: unknown;\n}\n\n/**\n * Base class for all serializable errors\n *\n * Features:\n * - Auto-serialization of public fields via toJSON()\n * - Constructor accepts object with all fields\n * - Type-safe error handling with instanceof\n *\n * @example\n * ```typescript\n * class PaymentFailedError extends SerializableError\n * {\n * readonly statusCode = 402;\n * transactionId!: string;\n * reason!: 'insufficient_funds' | 'card_declined';\n *\n * constructor(data: {\n * message: string;\n * transactionId: string;\n * reason: 'insufficient_funds' | 'card_declined';\n * })\n * {\n * super(data.message);\n * this.name = 'PaymentFailedError';\n * Object.assign(this, data);\n * }\n * }\n * ```\n */\nexport abstract class SerializableError extends Error\n{\n /**\n * HTTP status code for this error type\n */\n abstract readonly statusCode: number;\n\n /**\n * Serialize error to JSON-compatible object\n *\n * Automatically includes:\n * - __type: Constructor name for deserialization\n * - message: Error message\n * - All public instance properties (except name, stack)\n */\n toJSON(): SerializedError\n {\n const json: SerializedError = {\n __type: this.constructor.name,\n message: this.message,\n };\n\n // Extract all public instance properties\n for (const key of Object.keys(this))\n {\n // Skip Error built-ins and statusCode (inferred from type)\n if (key !== 'name' && key !== 'message' && key !== 'stack' && key !== 'statusCode')\n {\n json[key] = (this as unknown as Record<string, unknown>)[key];\n }\n }\n\n return json;\n }\n}\n","/**\n * Database Error Classes\n *\n * Type-safe error handling with custom error class hierarchy\n * Mapped to HTTP status codes for API responses\n * All errors extend SerializableError for consistent JSON serialization\n */\n\nimport { SerializableError } from './serializable-error';\n\n/**\n * Base Database Error\n *\n * Base class for all database-related errors\n */\nexport class DatabaseError<TDetails extends Record<string, unknown> = Record<string, unknown>>\n extends SerializableError\n{\n public readonly statusCode: number;\n public readonly details?: TDetails;\n\n constructor(data: {\n message: string;\n statusCode?: number;\n details?: TDetails;\n })\n {\n super(data.message);\n this.name = 'DatabaseError';\n this.statusCode = data.statusCode ?? 500;\n this.details = data.details;\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\n/**\n * Connection Error (503 Service Unavailable)\n *\n * Database connection failure, connection pool exhaustion, etc.\n */\nexport class ConnectionError extends DatabaseError\n{\n constructor(data: { message: string; details?: Record<string, unknown> })\n {\n super({ message: data.message, statusCode: 503, details: data.details });\n this.name = 'ConnectionError';\n }\n}\n\n/**\n * Query Error (500 Internal Server Error)\n *\n * SQL query execution failure, syntax errors, etc.\n */\nexport class QueryError extends DatabaseError\n{\n constructor(data: {\n message: string;\n statusCode?: number;\n details?: Record<string, unknown>;\n })\n {\n super({\n message: data.message,\n statusCode: data.statusCode ?? 500,\n details: data.details,\n });\n this.name = 'QueryError';\n }\n}\n\n/**\n * Entity Not Found Error (404 Not Found)\n *\n * Database entity does not exist\n */\nexport class EntityNotFoundError extends QueryError\n{\n public readonly resource: string;\n public readonly id: string | number;\n\n constructor(data: { resource: string; id: string | number })\n {\n super({\n message: `${data.resource} with id ${data.id} not found`,\n statusCode: 404,\n details: { resource: data.resource, id: data.id },\n });\n this.name = 'EntityNotFoundError';\n this.resource = data.resource;\n this.id = data.id;\n }\n}\n\n/**\n * Constraint Violation Error (400 Bad Request)\n *\n * Database constraint violation (NOT NULL, CHECK, FOREIGN KEY, etc.)\n * This is different from HTTP ValidationError which validates request input\n */\nexport class ConstraintViolationError extends QueryError\n{\n constructor(data: { message: string; details?: Record<string, unknown> })\n {\n super({ message: data.message, statusCode: 400, details: data.details });\n this.name = 'ConstraintViolationError';\n }\n}\n\n/**\n * Transaction Error (500 Internal Server Error)\n *\n * Transaction start/commit/rollback failure\n */\nexport class TransactionError extends DatabaseError\n{\n constructor(data: {\n message: string;\n statusCode?: number;\n details?: Record<string, unknown>;\n })\n {\n super({\n message: data.message,\n statusCode: data.statusCode ?? 500,\n details: data.details,\n });\n this.name = 'TransactionError';\n }\n}\n\n/**\n * Deadlock Error (409 Conflict)\n *\n * Database deadlock detected\n */\nexport class DeadlockError extends TransactionError\n{\n constructor(data: { message: string; details?: Record<string, unknown> })\n {\n super({ message: data.message, statusCode: 409, details: data.details });\n this.name = 'DeadlockError';\n }\n}\n\n/**\n * Duplicate Entry Error (409 Conflict)\n *\n * Unique constraint violation (e.g., duplicate email)\n */\nexport class DuplicateEntryError extends QueryError\n{\n public readonly field: string;\n public readonly value: string | number;\n\n constructor(data: { field: string; value: string | number })\n {\n super({\n message: `${data.field} '${data.value}' already exists`,\n statusCode: 409,\n details: { field: data.field, value: data.value },\n });\n this.name = 'DuplicateEntryError';\n this.field = data.field;\n this.value = data.value;\n }\n}\n","/**\n * Error Utility Functions\n *\n * Generic error type checking utilities\n */\n\nimport { DatabaseError } from './database-errors';\nimport { HttpError } from './http-errors';\n\n/**\n * Check if error is a DatabaseError\n */\nexport function isDatabaseError(error: unknown): error is DatabaseError\n{\n return error instanceof DatabaseError;\n}\n\n/**\n * Check if error is an HttpError\n */\nexport function isHttpError(error: unknown): error is HttpError\n{\n return error instanceof HttpError;\n}\n\n/**\n * Check if error has a statusCode property\n */\nexport function hasStatusCode(error: unknown): error is { statusCode: number }\n{\n return (\n typeof error === 'object' &&\n error !== null &&\n 'statusCode' in error &&\n typeof (error as any).statusCode === 'number'\n );\n}\n","/**\n * Error Module Exports\n *\n * Entry point for error handling module with serialization support\n */\n\n// Core Error Registry\n// Pre-configured registry with all built-in HTTP and Database errors\nimport { ErrorRegistry } from './error-registry';\nimport {\n HttpError,\n BadRequestError,\n ValidationError,\n UnauthorizedError,\n ForbiddenError,\n NotFoundError,\n ConflictError,\n GoneError,\n TooManyRequestsError,\n UnsupportedMediaTypeError,\n UnprocessableEntityError,\n InternalServerError,\n ServiceUnavailableError,\n} from './http-errors';\nimport {\n DatabaseError,\n ConnectionError,\n QueryError,\n EntityNotFoundError,\n ConstraintViolationError,\n TransactionError,\n DeadlockError,\n DuplicateEntryError,\n} from './database-errors';\n\n// Base Classes\nexport { SerializableError } from './serializable-error';\nexport type { SerializedError } from './serializable-error';\nexport { ErrorRegistry } from './error-registry';\nexport type { SerializableErrorConstructor, ErrorRegistryInput } from './error-registry';\n\n// Database Error Classes\nexport {\n DatabaseError,\n ConnectionError,\n QueryError,\n EntityNotFoundError,\n ConstraintViolationError,\n TransactionError,\n DeadlockError,\n DuplicateEntryError,\n} from './database-errors';\n\n// HTTP Error Classes\nexport {\n HttpError,\n BadRequestError,\n ValidationError,\n UnauthorizedError,\n ForbiddenError,\n NotFoundError,\n ConflictError,\n GoneError,\n TooManyRequestsError,\n UnsupportedMediaTypeError,\n UnprocessableEntityError,\n InternalServerError,\n ServiceUnavailableError,\n} from './http-errors';\n\n// Error Utilities\nexport {\n isDatabaseError,\n isHttpError,\n hasStatusCode,\n} from './error-utils';\n\nexport const errorRegistry = new ErrorRegistry();\n\n// HTTP Errors\nerrorRegistry.append([\n HttpError,\n BadRequestError,\n ValidationError,\n UnauthorizedError,\n ForbiddenError,\n NotFoundError,\n ConflictError,\n GoneError,\n TooManyRequestsError,\n UnsupportedMediaTypeError,\n UnprocessableEntityError,\n InternalServerError,\n ServiceUnavailableError,\n]);\n\n// Database Errors\nerrorRegistry.append([\n DatabaseError,\n ConnectionError,\n QueryError,\n EntityNotFoundError,\n ConstraintViolationError,\n TransactionError,\n DeadlockError,\n DuplicateEntryError,\n]);\n\nexport * as HttpErrors from './http-errors';\nexport * as DatabaseErrors from './database-errors';"]}
1
+ {"version":3,"sources":["../../src/errors/error-registry.ts","../../src/errors/http-errors.ts","../../src/errors/serializable-error.ts","../../src/errors/database-errors.ts","../../src/errors/error-utils.ts","../../src/errors/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Error Registry\n *\n * Central registry for serializable error types.\n * Enables automatic error deserialization on the client side.\n */\n\nimport type { SerializableError } from './serializable-error';\n\n/**\n * Error constructor type\n */\nexport type SerializableErrorConstructor = new (data: any) => SerializableError;\n\n/**\n * Input type for ErrorRegistry constructor\n */\nexport type ErrorRegistryInput =\n | SerializableErrorConstructor\n | SerializableErrorConstructor[]\n | ErrorRegistry;\n\n/**\n * Error registry for serialization/deserialization\n *\n * @example\n * ```typescript\n * // Create registry with initial errors\n * const registry = new ErrorRegistry([\n * errorRegistry, // Another ErrorRegistry\n * PaymentFailedError, // Single error class\n * [RefundError, OrderError], // Array of error classes\n * ]);\n *\n * // Or create empty and append\n * const registry = new ErrorRegistry();\n * registry\n * .append(ValidationError)\n * .append([PaymentFailedError, RefundError]);\n *\n * // Deserialize from JSON\n * const error = registry.deserialize({\n * __type: 'PaymentFailedError',\n * message: 'Payment failed',\n * transactionId: 'tx_123',\n * reason: 'insufficient_funds'\n * });\n *\n * // error instanceof PaymentFailedError === true\n * ```\n */\nexport class ErrorRegistry\n{\n private errors = new Map<string, SerializableErrorConstructor>();\n\n constructor(initialErrors?: ErrorRegistryInput[])\n {\n if (initialErrors)\n {\n for (const input of initialErrors)\n {\n if (input instanceof ErrorRegistry)\n {\n this.concat(input);\n }\n else if (Array.isArray(input))\n {\n this.append(input);\n }\n else\n {\n this.append(input);\n }\n }\n }\n }\n\n /**\n * Append error class(es) to the registry\n *\n * @param ErrorClass - Single error constructor\n * @returns This registry for chaining\n */\n append(ErrorClass: SerializableErrorConstructor): this;\n\n /**\n * Append error class(es) to the registry\n *\n * @param ErrorClasses - Array of error constructors\n * @returns This registry for chaining\n */\n append(ErrorClasses: SerializableErrorConstructor[]): this;\n\n /**\n * Append error class(es) to the registry\n *\n * @param input - Error constructor or array of constructors\n * @returns This registry for chaining\n */\n append(input: SerializableErrorConstructor | SerializableErrorConstructor[]): this\n {\n if (Array.isArray(input))\n {\n for (const ErrorClass of input)\n {\n this.errors.set(ErrorClass.name, ErrorClass);\n }\n }\n else\n {\n this.errors.set(input.name, input);\n }\n\n return this;\n }\n\n /**\n * Concatenate another ErrorRegistry into this one\n *\n * @param registry - Another ErrorRegistry to merge\n * @returns This registry for chaining\n */\n concat(registry: ErrorRegistry): this\n {\n for (const [name, ErrorClass] of registry.errors)\n {\n this.errors.set(name, ErrorClass);\n }\n\n return this;\n }\n\n /**\n * Check if error type is registered\n *\n * @param name - Error class name\n */\n has(name: string): boolean\n {\n return this.errors.has(name);\n }\n\n /**\n * Deserialize error from JSON data\n *\n * @param data - Serialized error data with __type field\n * @returns Deserialized error instance\n * @throws Error if error type is not registered\n */\n deserialize(data: { __type: string; [key: string]: any }): SerializableError\n {\n const ErrorClass = this.errors.get(data.__type);\n\n if (!ErrorClass)\n {\n throw new Error(`Unknown error type: ${data.__type}`);\n }\n\n // Pass entire data object to constructor\n return new ErrorClass(data);\n }\n\n /**\n * Try to deserialize error, return null if type unknown\n *\n * @param data - Serialized error data\n * @returns Deserialized error or null\n */\n tryDeserialize(data: { __type?: string; [key: string]: any }): SerializableError | null\n {\n if (!data.__type || !this.has(data.__type))\n {\n return null;\n }\n\n try\n {\n return this.deserialize(data as any);\n }\n catch\n {\n return null;\n }\n }\n\n /**\n * Get all registered error types\n */\n getRegisteredTypes(): string[]\n {\n return Array.from(this.errors.keys());\n }\n}\n","/**\n * HTTP Error Classes\n *\n * Standard HTTP error classes for API responses\n * All errors are serializable for type-safe client-side error handling\n */\n\nimport { SerializableError } from './serializable-error';\n\n/**\n * Base HTTP Error\n *\n * Base class for all HTTP-related errors\n */\nexport class HttpError extends SerializableError\n{\n public readonly statusCode: number;\n public details?: Record<string, unknown>;\n\n constructor(data: {\n message: string;\n statusCode: number;\n details?: Record<string, unknown>;\n })\n {\n super(data.message);\n\n this.name = 'HttpError';\n this.statusCode = data.statusCode;\n\n if (data.details)\n {\n this.details = data.details;\n }\n\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\n/**\n * Bad Request Error (400)\n *\n * Generic bad request - malformed syntax, invalid parameters, etc.\n */\nexport class BadRequestError extends HttpError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Bad request',\n statusCode: 400,\n details: data.details,\n });\n\n this.name = 'BadRequestError';\n }\n}\n\n/**\n * Validation Error (400)\n *\n * Input validation failure (request params, query, body)\n * Used by define-route system for automatic validation\n */\nexport class ValidationError extends HttpError\n{\n fields?: Array<{ path: string; message: string; value?: any }>;\n\n constructor(data: {\n message: string;\n fields?: Array<{ path: string; message: string; value?: any }>;\n details?: Record<string, any>;\n })\n {\n super({\n message: data.message,\n statusCode: 400,\n details: data.details,\n });\n\n this.name = 'ValidationError';\n\n if (data.fields)\n {\n this.fields = data.fields;\n }\n }\n}\n\n/**\n * Unauthorized Error (401)\n *\n * Authentication required or authentication failed\n */\nexport class UnauthorizedError extends HttpError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Authentication required',\n statusCode: 401,\n details: data.details,\n });\n\n this.name = 'UnauthorizedError';\n }\n}\n\n/**\n * Forbidden Error (403)\n *\n * Authenticated but lacks permission to access resource\n */\nexport class ForbiddenError extends HttpError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Access forbidden',\n statusCode: 403,\n details: data.details,\n });\n\n this.name = 'ForbiddenError';\n }\n}\n\n/**\n * Not Found Error (404)\n *\n * Requested resource does not exist\n */\nexport class NotFoundError extends HttpError\n{\n resource?: string;\n\n constructor(data: { message?: string; resource?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Resource not found',\n statusCode: 404,\n details: data.details,\n });\n\n this.name = 'NotFoundError';\n\n if (data.resource)\n {\n this.resource = data.resource;\n }\n }\n}\n\n/**\n * Conflict Error (409)\n *\n * Generic conflict - resource state conflict, concurrent modification, etc.\n */\nexport class ConflictError extends HttpError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Resource conflict',\n statusCode: 409,\n details: data.details,\n });\n\n this.name = 'ConflictError';\n }\n}\n\n/**\n * Gone Error (410)\n *\n * Resource permanently deleted and no longer available\n */\nexport class GoneError extends HttpError\n{\n resource?: string;\n\n constructor(data: { message?: string; resource?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Resource permanently deleted',\n statusCode: 410,\n details: data.details,\n });\n\n this.name = 'GoneError';\n\n if (data.resource)\n {\n this.resource = data.resource;\n }\n }\n}\n\n/**\n * Too Many Requests Error (429)\n *\n * Rate limit exceeded\n */\nexport class TooManyRequestsError extends HttpError\n{\n retryAfter?: number;\n\n constructor(data: {\n message?: string;\n retryAfter?: number;\n details?: Record<string, any>;\n } = {})\n {\n super({\n message: data.message || 'Too many requests',\n statusCode: 429,\n details: data.details,\n });\n\n this.name = 'TooManyRequestsError';\n\n if (data.retryAfter)\n {\n this.retryAfter = data.retryAfter;\n }\n }\n}\n\n/**\n * Internal Server Error (500)\n *\n * Generic server error when no specific error type applies\n */\nexport class InternalServerError extends HttpError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Internal server error',\n statusCode: 500,\n details: data.details,\n });\n\n this.name = 'InternalServerError';\n }\n}\n\n/**\n * Unsupported Media Type Error (415)\n *\n * Media type not supported - invalid file type, content type, etc.\n */\nexport class UnsupportedMediaTypeError extends HttpError\n{\n mediaType?: string;\n supportedTypes?: string[];\n\n constructor(data: {\n message?: string;\n mediaType?: string;\n supportedTypes?: string[];\n details?: Record<string, any>;\n } = {})\n {\n super({\n message: data.message || 'Unsupported media type',\n statusCode: 415,\n details: data.details,\n });\n\n this.name = 'UnsupportedMediaTypeError';\n\n if (data.mediaType)\n {\n this.mediaType = data.mediaType;\n }\n\n if (data.supportedTypes)\n {\n this.supportedTypes = data.supportedTypes;\n }\n }\n}\n\n/**\n * Unprocessable Entity Error (422)\n *\n * Request is well-formed but contains semantic errors\n */\nexport class UnprocessableEntityError extends HttpError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Unprocessable entity',\n statusCode: 422,\n details: data.details,\n });\n\n this.name = 'UnprocessableEntityError';\n }\n}\n\n/**\n * Service Unavailable Error (503)\n *\n * Service temporarily unavailable (maintenance, overload, etc.)\n */\nexport class ServiceUnavailableError extends HttpError\n{\n retryAfter?: number;\n\n constructor(data: {\n message?: string;\n retryAfter?: number;\n details?: Record<string, any>;\n } = {})\n {\n super({\n message: data.message || 'Service unavailable',\n statusCode: 503,\n details: data.details,\n });\n\n this.name = 'ServiceUnavailableError';\n\n if (data.retryAfter)\n {\n this.retryAfter = data.retryAfter;\n }\n }\n}\n","/**\n * Serializable Error Base Class\n *\n * Base class for errors that can be serialized/deserialized across HTTP boundary.\n * Automatically serializes public fields for transmission to client.\n */\n\n/**\n * Serialized error format for JSON transmission\n */\nexport interface SerializedError\n{\n __type: string;\n message: string;\n [key: string]: unknown;\n}\n\n/**\n * Base class for all serializable errors\n *\n * Features:\n * - Auto-serialization of public fields via toJSON()\n * - Constructor accepts object with all fields\n * - Type-safe error handling with instanceof\n *\n * @example\n * ```typescript\n * class PaymentFailedError extends SerializableError\n * {\n * readonly statusCode = 402;\n * transactionId!: string;\n * reason!: 'insufficient_funds' | 'card_declined';\n *\n * constructor(data: {\n * message: string;\n * transactionId: string;\n * reason: 'insufficient_funds' | 'card_declined';\n * })\n * {\n * super(data.message);\n * this.name = 'PaymentFailedError';\n * Object.assign(this, data);\n * }\n * }\n * ```\n */\nexport abstract class SerializableError extends Error\n{\n /**\n * HTTP status code for this error type\n */\n abstract readonly statusCode: number;\n\n /**\n * Serialize error to JSON-compatible object\n *\n * Automatically includes:\n * - __type: Constructor name for deserialization\n * - message: Error message\n * - All public instance properties (except name, stack)\n */\n toJSON(): SerializedError\n {\n const json: SerializedError = {\n __type: this.constructor.name,\n message: this.message,\n };\n\n // Extract all public instance properties\n for (const key of Object.keys(this))\n {\n // Skip Error built-ins and statusCode (inferred from type)\n if (key !== 'name' && key !== 'message' && key !== 'stack' && key !== 'statusCode')\n {\n json[key] = (this as unknown as Record<string, unknown>)[key];\n }\n }\n\n return json;\n }\n}\n","/**\n * Database Error Classes\n *\n * Type-safe error handling with custom error class hierarchy\n * Mapped to HTTP status codes for API responses\n * All errors extend SerializableError for consistent JSON serialization\n */\n\nimport { SerializableError } from './serializable-error';\n\n/**\n * Base Database Error\n *\n * Base class for all database-related errors\n */\nexport class DatabaseError<TDetails extends Record<string, unknown> = Record<string, unknown>>\n extends SerializableError\n{\n public readonly statusCode: number;\n public readonly details?: TDetails;\n\n constructor(data: {\n message: string;\n statusCode?: number;\n details?: TDetails;\n })\n {\n super(data.message);\n this.name = 'DatabaseError';\n this.statusCode = data.statusCode ?? 500;\n this.details = data.details;\n Error.captureStackTrace(this, this.constructor);\n }\n\n /**\n * Whether this error's message/details are derived from the raw database\n * driver (SQL text, table/column/constraint names, parameter values) and\n * therefore must NOT be exposed to clients in production. Defined as a\n * prototype getter so it is never serialized into the response by toJSON().\n * Subclasses with a safe, constructed message override this to `false`.\n */\n get internal(): boolean\n {\n return true;\n }\n}\n\n/**\n * Connection Error (503 Service Unavailable)\n *\n * Database connection failure, connection pool exhaustion, etc.\n */\nexport class ConnectionError extends DatabaseError\n{\n constructor(data: { message: string; details?: Record<string, unknown> })\n {\n super({ message: data.message, statusCode: 503, details: data.details });\n this.name = 'ConnectionError';\n }\n}\n\n/**\n * Query Error (500 Internal Server Error)\n *\n * SQL query execution failure, syntax errors, etc.\n */\nexport class QueryError extends DatabaseError\n{\n constructor(data: {\n message: string;\n statusCode?: number;\n details?: Record<string, unknown>;\n })\n {\n super({\n message: data.message,\n statusCode: data.statusCode ?? 500,\n details: data.details,\n });\n this.name = 'QueryError';\n }\n}\n\n/**\n * Entity Not Found Error (404 Not Found)\n *\n * Database entity does not exist\n */\nexport class EntityNotFoundError extends QueryError\n{\n public readonly resource: string;\n public readonly id: string | number;\n\n constructor(data: { resource: string; id: string | number })\n {\n super({\n message: `${data.resource} with id ${data.id} not found`,\n statusCode: 404,\n details: { resource: data.resource, id: data.id },\n });\n this.name = 'EntityNotFoundError';\n this.resource = data.resource;\n this.id = data.id;\n }\n\n // Message/details are constructed from the resource + id, not driver text\n override get internal(): boolean\n {\n return false;\n }\n}\n\n/**\n * Constraint Violation Error (400 Bad Request)\n *\n * Database constraint violation (NOT NULL, CHECK, FOREIGN KEY, etc.)\n * This is different from HTTP ValidationError which validates request input\n */\nexport class ConstraintViolationError extends QueryError\n{\n constructor(data: { message: string; details?: Record<string, unknown> })\n {\n super({ message: data.message, statusCode: 400, details: data.details });\n this.name = 'ConstraintViolationError';\n }\n}\n\n/**\n * Transaction Error (500 Internal Server Error)\n *\n * Transaction start/commit/rollback failure\n */\nexport class TransactionError extends DatabaseError\n{\n constructor(data: {\n message: string;\n statusCode?: number;\n details?: Record<string, unknown>;\n })\n {\n super({\n message: data.message,\n statusCode: data.statusCode ?? 500,\n details: data.details,\n });\n this.name = 'TransactionError';\n }\n}\n\n/**\n * Deadlock Error (409 Conflict)\n *\n * Database deadlock detected\n */\nexport class DeadlockError extends TransactionError\n{\n constructor(data: { message: string; details?: Record<string, unknown> })\n {\n super({ message: data.message, statusCode: 409, details: data.details });\n this.name = 'DeadlockError';\n }\n}\n\n/**\n * Duplicate Entry Error (409 Conflict)\n *\n * Unique constraint violation (e.g., duplicate email)\n */\nexport class DuplicateEntryError extends QueryError\n{\n public readonly field: string;\n public readonly value: string | number;\n\n constructor(data: { field: string; value: string | number })\n {\n // The client-facing message/details name the field but NOT the value: echoing\n // the value back (e.g. an email) confirms it exists, an enumeration aid. The\n // raw value stays on the instance for server-side handling/logging.\n super({\n message: `${data.field} already exists`,\n statusCode: 409,\n details: { field: data.field },\n });\n this.name = 'DuplicateEntryError';\n this.field = data.field;\n this.value = data.value;\n }\n\n // Field-only message/details — safe to surface to the client (not internal)\n override get internal(): boolean\n {\n return false;\n }\n}\n","/**\n * Error Utility Functions\n *\n * Generic error type checking utilities\n */\n\nimport { DatabaseError } from './database-errors';\nimport { HttpError } from './http-errors';\n\n/**\n * Check if error is a DatabaseError\n */\nexport function isDatabaseError(error: unknown): error is DatabaseError\n{\n return error instanceof DatabaseError;\n}\n\n/**\n * Check if error is an HttpError\n */\nexport function isHttpError(error: unknown): error is HttpError\n{\n return error instanceof HttpError;\n}\n\n/**\n * Check if error has a statusCode property\n */\nexport function hasStatusCode(error: unknown): error is { statusCode: number }\n{\n return (\n typeof error === 'object' &&\n error !== null &&\n 'statusCode' in error &&\n typeof (error as any).statusCode === 'number'\n );\n}\n","/**\n * Error Module Exports\n *\n * Entry point for error handling module with serialization support\n */\n\n// Core Error Registry\n// Pre-configured registry with all built-in HTTP and Database errors\nimport { ErrorRegistry } from './error-registry';\nimport {\n HttpError,\n BadRequestError,\n ValidationError,\n UnauthorizedError,\n ForbiddenError,\n NotFoundError,\n ConflictError,\n GoneError,\n TooManyRequestsError,\n UnsupportedMediaTypeError,\n UnprocessableEntityError,\n InternalServerError,\n ServiceUnavailableError,\n} from './http-errors';\nimport {\n DatabaseError,\n ConnectionError,\n QueryError,\n EntityNotFoundError,\n ConstraintViolationError,\n TransactionError,\n DeadlockError,\n DuplicateEntryError,\n} from './database-errors';\n\n// Base Classes\nexport { SerializableError } from './serializable-error';\nexport type { SerializedError } from './serializable-error';\nexport { ErrorRegistry } from './error-registry';\nexport type { SerializableErrorConstructor, ErrorRegistryInput } from './error-registry';\n\n// Database Error Classes\nexport {\n DatabaseError,\n ConnectionError,\n QueryError,\n EntityNotFoundError,\n ConstraintViolationError,\n TransactionError,\n DeadlockError,\n DuplicateEntryError,\n} from './database-errors';\n\n// HTTP Error Classes\nexport {\n HttpError,\n BadRequestError,\n ValidationError,\n UnauthorizedError,\n ForbiddenError,\n NotFoundError,\n ConflictError,\n GoneError,\n TooManyRequestsError,\n UnsupportedMediaTypeError,\n UnprocessableEntityError,\n InternalServerError,\n ServiceUnavailableError,\n} from './http-errors';\n\n// Error Utilities\nexport {\n isDatabaseError,\n isHttpError,\n hasStatusCode,\n} from './error-utils';\n\nexport const errorRegistry = new ErrorRegistry();\n\n// HTTP Errors\nerrorRegistry.append([\n HttpError,\n BadRequestError,\n ValidationError,\n UnauthorizedError,\n ForbiddenError,\n NotFoundError,\n ConflictError,\n GoneError,\n TooManyRequestsError,\n UnsupportedMediaTypeError,\n UnprocessableEntityError,\n InternalServerError,\n ServiceUnavailableError,\n]);\n\n// Database Errors\nerrorRegistry.append([\n DatabaseError,\n ConnectionError,\n QueryError,\n EntityNotFoundError,\n ConstraintViolationError,\n TransactionError,\n DeadlockError,\n DuplicateEntryError,\n]);\n\nexport * as HttpErrors from './http-errors';\nexport * as DatabaseErrors from './database-errors';\n"]}
@@ -1,6 +1,10 @@
1
1
  import { TSchema, Static } from '@sinclair/typebox';
2
- import { a as EventDef } from '../router-Di7ENoah.js';
3
- export { e as EventHandler, E as EventRouterDef, I as InferEventNames, f as InferEventPayload, c as InferEventPayloads, b as InferRouterEventPayload, J as JobQueueSender, P as PubSubCache, d as defineEventRouter } from '../router-Di7ENoah.js';
2
+ import { a as EventDef } from '../token-manager-jKD_EsSE.js';
3
+ export { e as EventHandler, E as EventRouterDef, I as InferEventNames, f as InferEventPayload, c as InferEventPayloads, b as InferRouterEventPayload, J as JobQueueSender, P as PubSubCache, d as defineEventRouter } from '../token-manager-jKD_EsSE.js';
4
+ export { defineWSRouter } from './ws/index.js';
5
+ import '../types-DVjf37yO.js';
6
+ import 'hono';
7
+ import 'node:http';
4
8
 
5
9
  /**
6
10
  * Event System
@@ -38,4 +42,30 @@ declare function defineEvent(name: string): EventDef<void>;
38
42
  */
39
43
  declare function defineEvent<T extends TSchema>(name: string, schema: T): EventDef<Static<T>>;
40
44
 
41
- export { EventDef, defineEvent };
45
+ /**
46
+ * SSE Event Route Map
47
+ *
48
+ * Static route map for SSE token endpoint.
49
+ * Merge into RPC proxy routeMap so `eventsToken` resolves to `POST /events/token`.
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * // app/api/rpc/[routeName]/route.ts
54
+ * import { createRpcProxy } from '@spfn/core/nextjs/server';
55
+ * import { eventRouteMap } from '@spfn/core/event';
56
+ * import { authRouteMap } from '@spfn/auth';
57
+ * import { routeMap } from '@/generated/route-map';
58
+ *
59
+ * export const { GET, POST } = createRpcProxy({
60
+ * routeMap: { ...routeMap, ...authRouteMap, ...eventRouteMap },
61
+ * });
62
+ * ```
63
+ */
64
+ declare const eventRouteMap: {
65
+ eventsToken: {
66
+ method: "POST";
67
+ path: string;
68
+ };
69
+ };
70
+
71
+ export { EventDef, defineEvent, eventRouteMap };
@@ -89,15 +89,19 @@ function createEventImpl(name, schema) {
89
89
  eventLogger.warn(`Cache already configured for event: ${name}`);
90
90
  return self;
91
91
  }
92
- cache = newCache;
93
- cacheSubscribed = true;
94
92
  await newCache.subscribe(name, async (message) => {
95
93
  eventLogger.debug(`Received event from cache: ${name}`);
96
94
  await handlerManager.trigger(message);
97
95
  });
96
+ cache = newCache;
97
+ cacheSubscribed = true;
98
98
  eventLogger.debug(`Cache subscription ready for event: ${name}`);
99
99
  return self;
100
100
  };
101
+ const resetCache = () => {
102
+ cache = void 0;
103
+ cacheSubscribed = false;
104
+ };
101
105
  const self = {
102
106
  name,
103
107
  schema,
@@ -106,6 +110,7 @@ function createEventImpl(name, schema) {
106
110
  emit,
107
111
  useCache,
108
112
  _registerJobQueue: jobQueueManager.register,
113
+ _resetCache: resetCache,
109
114
  _payload: void 0
110
115
  };
111
116
  return self;
@@ -117,6 +122,11 @@ function defineEvent(name, schema) {
117
122
  return createEventImpl(name);
118
123
  }
119
124
 
125
+ // src/event/sse/route-map.ts
126
+ var eventRouteMap = {
127
+ eventsToken: { method: "POST", path: "/events/token" }
128
+ };
129
+
120
130
  // src/event/router.ts
121
131
  function defineEventRouter(events) {
122
132
  return {
@@ -125,7 +135,18 @@ function defineEventRouter(events) {
125
135
  _types: {}
126
136
  };
127
137
  }
138
+ logger.child("@spfn/core:ws");
139
+
140
+ // src/event/ws/index.ts
141
+ function defineWSRouter(def) {
142
+ return {
143
+ events: def.events,
144
+ eventNames: Object.keys(def.events),
145
+ messages: def.messages ?? {},
146
+ _types: {}
147
+ };
148
+ }
128
149
 
129
- export { defineEvent, defineEventRouter };
150
+ export { defineEvent, defineEventRouter, defineWSRouter, eventRouteMap };
130
151
  //# sourceMappingURL=index.js.map
131
152
  //# sourceMappingURL=index.js.map