@withwiz/toolkit 0.10.0 → 0.12.0

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 (113) hide show
  1. package/README.md +6 -0
  2. package/dist/{chunk-Z64GNAB7.js → chunk-2SV6VZOC.js} +2 -2
  3. package/dist/{chunk-3P4TZM3O.js → chunk-3EEOZHIJ.js} +3 -3
  4. package/dist/chunk-4JZIIMAF.js +33 -0
  5. package/dist/{chunk-BICSVLN7.js → chunk-4OFL7KZ7.js} +11 -11
  6. package/dist/{chunk-XDB3K74B.js → chunk-4OKAMI6O.js} +1 -1
  7. package/dist/{chunk-W27FQNP6.js → chunk-5MPMPXIR.js} +1 -1
  8. package/dist/{chunk-XQIAXMRY.js → chunk-5VZIAXO2.js} +2 -1
  9. package/dist/{chunk-465MEI5K.js → chunk-6E2Q27EN.js} +1 -1
  10. package/dist/chunk-6NFMRZWB.js +8 -0
  11. package/dist/{chunk-HZN44RWL.js → chunk-7Q6SMNMN.js} +7 -7
  12. package/dist/{chunk-SROPI74N.js → chunk-AWFP2KAU.js} +1 -1
  13. package/dist/{chunk-7S2PCYNT.js → chunk-B2JZPUQ3.js} +2 -2
  14. package/dist/{chunk-HV6A6Z5R.js → chunk-BPDYEB37.js} +1 -1
  15. package/dist/{chunk-BRFW2LL2.js → chunk-D4QADM6T.js} +2 -2
  16. package/dist/{chunk-6NEGFM32.js → chunk-DTRXWS7G.js} +25 -16
  17. package/dist/{chunk-UIWR5MXM.js → chunk-ETXMWDXV.js} +1 -1
  18. package/dist/{chunk-4TGPAUJV.js → chunk-F2FTS6H4.js} +2 -2
  19. package/dist/{chunk-P4MGYRJM.js → chunk-G4IGD3AZ.js} +33 -13
  20. package/dist/{chunk-VHRBXD7U.js → chunk-HNFYO5XV.js} +10 -6
  21. package/dist/{chunk-23LQJYZN.js → chunk-KAS5ILUM.js} +1 -1
  22. package/dist/{chunk-KHXS4DGA.js → chunk-LFJ24NDO.js} +8 -8
  23. package/dist/{chunk-TRGFXIEF.js → chunk-M4ZVQFOH.js} +2 -2
  24. package/dist/{chunk-ATAQRXTH.js → chunk-MCPPJI3T.js} +1 -1
  25. package/dist/{chunk-ZEHNCHIV.js → chunk-MTRPUJ4B.js} +1 -1
  26. package/dist/{chunk-R7EFDSPZ.js → chunk-NHFIOK2D.js} +5 -5
  27. package/dist/{chunk-5Z5CZAZP.js → chunk-NT6URT4W.js} +14 -14
  28. package/dist/{chunk-Y6CPPBJI.js → chunk-OEZPVNSA.js} +1 -1
  29. package/dist/{chunk-KZ4PDS5K.js → chunk-RWN47K7J.js} +1 -1
  30. package/dist/{chunk-N3TCQ5BF.js → chunk-TQMQ5XXG.js} +17 -2
  31. package/dist/{chunk-OII5BXCZ.js → chunk-U2TGXJ3A.js} +1 -1
  32. package/dist/{chunk-5S7M2AJL.js → chunk-W2FBLCOR.js} +1 -1
  33. package/dist/{chunk-XF3WUF3F.js → chunk-ZFBY2FNS.js} +2 -2
  34. package/dist/{chunk-2GK4LDPV.js → chunk-ZLUID5BU.js} +2 -2
  35. package/dist/core/api-key/api-key.service.d.ts +1 -0
  36. package/dist/core/api-key/api-key.service.js +3 -2
  37. package/dist/core/api-key/errors.d.ts +21 -0
  38. package/dist/core/api-key/errors.js +11 -0
  39. package/dist/core/api-key/index.d.ts +1 -0
  40. package/dist/core/api-key/index.js +15 -7
  41. package/dist/core/auth/adapters/sql/email-token-repository.js +2 -2
  42. package/dist/core/auth/adapters/sql/index.js +8 -8
  43. package/dist/core/auth/adapters/sql/oauth-account-repository.js +2 -2
  44. package/dist/core/auth/adapters/sql/user-repository.js +2 -2
  45. package/dist/core/auth/config.js +2 -1
  46. package/dist/core/auth/cookie-names.d.ts +3 -0
  47. package/dist/core/auth/cookie-names.js +9 -0
  48. package/dist/core/auth/index.js +9 -8
  49. package/dist/core/auth/jwt/cookie.js +4 -3
  50. package/dist/core/auth/jwt/index.js +4 -3
  51. package/dist/core/auth/oauth/index.js +7 -7
  52. package/dist/core/auth/oauth/providers/index.js +6 -6
  53. package/dist/core/auth/services/cache-token-stores.d.ts +45 -0
  54. package/dist/core/auth/services/cache-token-stores.js +59 -0
  55. package/dist/core/auth/services/index.js +4 -3
  56. package/dist/core/auth/services/login.service.js +4 -3
  57. package/dist/core/auth/services/oauth-callback.service.js +4 -3
  58. package/dist/core/auth/services/token-refresh.service.js +4 -3
  59. package/dist/core/auth/token-delivery.js +5 -4
  60. package/dist/core/cache/cache-config.js +4 -4
  61. package/dist/core/cache/cache-env.js +3 -3
  62. package/dist/core/cache/cache-factory.js +9 -9
  63. package/dist/core/cache/cache-invalidation.js +10 -10
  64. package/dist/core/cache/cache-redis.js +4 -4
  65. package/dist/core/cache/cache-wrapper.js +10 -10
  66. package/dist/core/cache/cache.js +16 -16
  67. package/dist/core/cache/config.js +2 -2
  68. package/dist/core/cache/hybrid-cache-manager.js +5 -5
  69. package/dist/core/cache/index.js +16 -16
  70. package/dist/core/cache/noop-cache-manager.js +5 -5
  71. package/dist/core/cache/redis-cache-manager.js +5 -5
  72. package/dist/core/constants/error-codes.js +1 -1
  73. package/dist/core/constants/index.js +1 -1
  74. package/dist/core/error/app-error.js +2 -2
  75. package/dist/core/error/friendly-messages-v2.js +2 -2
  76. package/dist/core/error/friendly-messages.js +1 -1
  77. package/dist/core/error/index.js +5 -5
  78. package/dist/core/storage/r2-storage.js +2 -2
  79. package/dist/core/system/environment.js +6 -5
  80. package/dist/core/system/health-check.js +3 -3
  81. package/dist/core/system/index.js +10 -9
  82. package/dist/core/utils/optimistic-lock.js +2 -2
  83. package/dist/initialize.js +11 -10
  84. package/dist/next/auth-handlers/index.js +14 -13
  85. package/dist/next/auth-handlers/login.handler.js +6 -5
  86. package/dist/next/auth-handlers/logout.handler.js +5 -4
  87. package/dist/next/auth-handlers/me.handler.js +6 -5
  88. package/dist/next/auth-handlers/oauth-authorize.handler.js +4 -4
  89. package/dist/next/auth-handlers/oauth-callback.handler.js +8 -7
  90. package/dist/next/auth-handlers/refresh.handler.js +6 -5
  91. package/dist/next/auth-types/handler-types.js +5 -4
  92. package/dist/next/auth-types/index.js +5 -4
  93. package/dist/next/error/error-handler.js +4 -4
  94. package/dist/next/error/index.js +5 -5
  95. package/dist/next/middleware/auth.js +10 -9
  96. package/dist/next/middleware/error-handler.js +5 -5
  97. package/dist/next/middleware/index.js +27 -26
  98. package/dist/next/middleware/rate-limit.js +3 -3
  99. package/dist/next/middleware/wrappers.js +16 -15
  100. package/dist/next/oapi/api-key-auth.js +6 -5
  101. package/dist/next/oapi/index.js +6 -5
  102. package/dist/next/proxy.d.ts +38 -0
  103. package/dist/next/proxy.js +53 -0
  104. package/dist/next/utils/api-helpers.js +2 -2
  105. package/dist/next/utils/error-processor.js +3 -3
  106. package/dist/next/utils/index.js +27 -27
  107. package/package.json +13 -3
  108. package/dist/{chunk-GSRAIDD7.js → chunk-6A5JHOBB.js} +3 -3
  109. package/dist/{chunk-43XXILCX.js → chunk-BTYH4MHU.js} +3 -3
  110. package/dist/{chunk-MXWSG6ER.js → chunk-KYUJ6D65.js} +0 -0
  111. package/dist/{chunk-ER6LSA4M.js → chunk-P7WHMKN5.js} +6 -6
  112. package/dist/{chunk-7KIM5MHV.js → chunk-RHYETIUR.js} +3 -3
  113. package/dist/{chunk-5VDT3ZB4.js → chunk-VQJY52YF.js} +3 -3
package/README.md CHANGED
@@ -8,6 +8,7 @@ Shared utility library for [withwiz](https://github.com/greeun) projects — a c
8
8
 
9
9
  - **Composition root** — assemble every tier's configuration at once with a single `initialize()`
10
10
  - **Framework tiers** — dependencies split across three tiers: `core` / `next` / `prisma` (0.8+)
11
+ - **API key** — framework/DB-agnostic API key core (generation with sha256-hashed storage, validation FSM, IP whitelist, plan limits, typed errors) over injectable ports, plus an x-api-key auth middleware and OpenAPI spec builder for Next.js (`next/oapi`)
11
12
  - **Auth** — JWT, password hashing, OAuth helpers (Google / GitHub / Kakao / Microsoft / Meta), state-cookie CSRF binding, Prisma adapter
12
13
  - **Cache** — Redis / in-memory / hybrid / noop backends, factory, invalidation, defaults
13
14
  - **Constants** — Error codes, messages, pagination, security constants
@@ -141,6 +142,10 @@ and the 0.7.0 / 0.8.0 entries in [`CHANGELOG.md`](CHANGELOG.md).
141
142
 
142
143
  | Subpath | Description |
143
144
  |---|---|
145
+ | `/core/api-key` | API key core barrel (service + generator + validate + ip-whitelist + errors) |
146
+ | `/core/api-key/api-key.service` | `ApiKeyService` — generate / validate / CRUD / regenerate over injected ports |
147
+ | `/core/api-key/errors` | `ApiKeyError`, `API_KEY_ERROR_CODES`, `isApiKeyError` structural guard |
148
+ | `/core/api-key/{types,ports,key-generator,ip-whitelist,validate}` | Pure types, DI ports, and helpers |
144
149
  | `/core/auth` | Full auth (JWT + password + OAuth + services + email + types) |
145
150
  | `/core/auth/jwt` | JWT sign / verify |
146
151
  | `/core/auth/password` | bcrypt helpers |
@@ -172,6 +177,7 @@ and the 0.7.0 / 0.8.0 entries in [`CHANGELOG.md`](CHANGELOG.md).
172
177
  | `/next/auth-handlers` | Route handlers (login / refresh / oauth callback / me) |
173
178
  | `/next/auth-types` | Handler types (`NextRequest` signatures) |
174
179
  | `/next/error` | `error-handler` (NextResponse), `LocaleDetector`, `ErrorBoundary` |
180
+ | `/next/oapi` | `createApiKeyAuth` (x-api-key auth middleware), OpenAPI 3.0.3 spec builder, pagination helpers |
175
181
  | `/next/utils` | `api-helpers`, `cors`, `csv-export`, `error-processor` |
176
182
 
177
183
  ### `react` — moved to `@withwiz/ui` (0.8)
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-MTZXWVW3.js";
4
4
  import {
5
5
  OAuthManager
6
- } from "./chunk-ER6LSA4M.js";
6
+ } from "./chunk-P7WHMKN5.js";
7
7
  import {
8
8
  OAUTH_STATE_COOKIE,
9
9
  clearOAuthStateCookie,
@@ -14,7 +14,7 @@ import {
14
14
  } from "./chunk-5GWGARXI.js";
15
15
  import {
16
16
  setTokenCookies
17
- } from "./chunk-6NEGFM32.js";
17
+ } from "./chunk-DTRXWS7G.js";
18
18
 
19
19
  // src/next/auth-handlers/oauth-callback.handler.ts
20
20
  import { NextResponse } from "next/server";
@@ -1,17 +1,17 @@
1
1
  import {
2
2
  getCacheManager,
3
3
  getEffectiveCacheBackend
4
- } from "./chunk-BICSVLN7.js";
4
+ } from "./chunk-4OFL7KZ7.js";
5
5
  import {
6
6
  logger
7
7
  } from "./chunk-QAIN3WNN.js";
8
8
  import {
9
9
  getCacheConfig,
10
10
  getCacheTTL
11
- } from "./chunk-Y6CPPBJI.js";
11
+ } from "./chunk-OEZPVNSA.js";
12
12
  import {
13
13
  isCacheEnabled
14
- } from "./chunk-HV6A6Z5R.js";
14
+ } from "./chunk-BPDYEB37.js";
15
15
 
16
16
  // src/core/cache/cache-wrapper.ts
17
17
  function getCacheBackendLabel() {
@@ -0,0 +1,33 @@
1
+ // src/core/api-key/errors.ts
2
+ var API_KEY_ERROR_CODES = {
3
+ /** 대상 API 키 미존재 */
4
+ NOT_FOUND: "API_KEY_NOT_FOUND",
5
+ /** 비소유자 접근 (admin 우회 제외) */
6
+ OWNERSHIP: "API_KEY_OWNERSHIP",
7
+ /** 제한 플랜(restrictedPlans)의 발급 시도 */
8
+ PLAN_RESTRICTED: "API_KEY_PLAN_RESTRICTED",
9
+ /** 플랜별 활성 키 한도 초과 */
10
+ LIMIT_REACHED: "API_KEY_LIMIT_REACHED"
11
+ };
12
+ var ApiKeyError = class _ApiKeyError extends Error {
13
+ constructor(message, code) {
14
+ super(message);
15
+ this.code = code;
16
+ this.name = "ApiKeyError";
17
+ if (Error.captureStackTrace) {
18
+ Error.captureStackTrace(this, _ApiKeyError);
19
+ }
20
+ }
21
+ };
22
+ function isApiKeyError(error, code) {
23
+ if (!(error instanceof Error) || error.name !== "ApiKeyError" || typeof error.code !== "string") {
24
+ return false;
25
+ }
26
+ return code === void 0 || error.code === code;
27
+ }
28
+
29
+ export {
30
+ API_KEY_ERROR_CODES,
31
+ ApiKeyError,
32
+ isApiKeyError
33
+ };
@@ -1,32 +1,32 @@
1
- import {
2
- NoopCacheManager
3
- } from "./chunk-XF3WUF3F.js";
4
- import {
5
- RedisCacheManager
6
- } from "./chunk-4TGPAUJV.js";
7
1
  import {
8
2
  HybridCacheManager
9
- } from "./chunk-2GK4LDPV.js";
3
+ } from "./chunk-ZLUID5BU.js";
10
4
  import {
11
5
  InMemoryCacheManager
12
6
  } from "./chunk-YYTA6ERS.js";
7
+ import {
8
+ NoopCacheManager
9
+ } from "./chunk-ZFBY2FNS.js";
10
+ import {
11
+ RedisCacheManager
12
+ } from "./chunk-F2FTS6H4.js";
13
13
  import {
14
14
  isRedisAvailableNow,
15
15
  isRedisGloballyDisabled
16
- } from "./chunk-ZEHNCHIV.js";
16
+ } from "./chunk-MTRPUJ4B.js";
17
17
  import {
18
18
  logger
19
19
  } from "./chunk-QAIN3WNN.js";
20
20
  import {
21
21
  getCacheConfig
22
- } from "./chunk-Y6CPPBJI.js";
22
+ } from "./chunk-OEZPVNSA.js";
23
23
  import {
24
24
  getENV,
25
25
  isCacheEnabled
26
- } from "./chunk-HV6A6Z5R.js";
26
+ } from "./chunk-BPDYEB37.js";
27
27
  import {
28
28
  isCacheConfigInitialized
29
- } from "./chunk-7KIM5MHV.js";
29
+ } from "./chunk-RHYETIUR.js";
30
30
  import {
31
31
  configWarn
32
32
  } from "./chunk-6J2EJVND.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  cache,
3
3
  geoCache
4
- } from "./chunk-BICSVLN7.js";
4
+ } from "./chunk-4OFL7KZ7.js";
5
5
 
6
6
  // src/core/cache/cache-invalidation.ts
7
7
  var invalidateCache = {
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-5GWGARXI.js";
7
7
  import {
8
8
  getTokenDeliveryStrategy
9
- } from "./chunk-VHRBXD7U.js";
9
+ } from "./chunk-HNFYO5XV.js";
10
10
  import {
11
11
  JWT_DEFAULTS,
12
12
  ROLE_DEFAULTS
@@ -94,7 +94,8 @@ var ERROR_CODES = {
94
94
  },
95
95
  // ============================================
96
96
  // Permissions Related (403xx - 01~09)
97
- // Reserved: 40301~40303 (미사용, 향후 세분화 확장용)
97
+ // 40301: next/oapi api-key-auth wire 계약에서 사용 중 (IP 차단·사용량 초과) — 재배정 금지
98
+ // Reserved: 40302~40303 (미사용, 향후 세분화 확장용)
98
99
  // ============================================
99
100
  FORBIDDEN: {
100
101
  code: 40304,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  clearTokenCookies
3
- } from "./chunk-6NEGFM32.js";
3
+ } from "./chunk-DTRXWS7G.js";
4
4
 
5
5
  // src/next/auth-handlers/logout.handler.ts
6
6
  import { NextResponse } from "next/server";
@@ -0,0 +1,8 @@
1
+ // src/core/auth/cookie-names.ts
2
+ var ACCESS_TOKEN_COOKIE = "access_token";
3
+ var REFRESH_TOKEN_COOKIE = "refresh_token";
4
+
5
+ export {
6
+ ACCESS_TOKEN_COOKIE,
7
+ REFRESH_TOKEN_COOKIE
8
+ };
@@ -1,21 +1,21 @@
1
1
  import {
2
2
  AppError
3
- } from "./chunk-ATAQRXTH.js";
3
+ } from "./chunk-MCPPJI3T.js";
4
4
  import {
5
5
  ERROR_CODES
6
- } from "./chunk-XQIAXMRY.js";
6
+ } from "./chunk-5VZIAXO2.js";
7
+ import {
8
+ logger
9
+ } from "./chunk-QAIN3WNN.js";
7
10
  import {
8
11
  JWTManager
9
12
  } from "./chunk-LWHLB2Y6.js";
10
13
  import {
11
14
  getTokenDeliveryStrategy
12
- } from "./chunk-VHRBXD7U.js";
13
- import {
14
- logger
15
- } from "./chunk-QAIN3WNN.js";
15
+ } from "./chunk-HNFYO5XV.js";
16
16
  import {
17
17
  getAuthConfig
18
- } from "./chunk-N3TCQ5BF.js";
18
+ } from "./chunk-TQMQ5XXG.js";
19
19
  import {
20
20
  ROLE_DEFAULTS
21
21
  } from "./chunk-7YWUKMZD.js";
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-LWHLB2Y6.js";
4
4
  import {
5
5
  getTokenDeliveryStrategy
6
- } from "./chunk-VHRBXD7U.js";
6
+ } from "./chunk-HNFYO5XV.js";
7
7
  import {
8
8
  JWT_DEFAULTS
9
9
  } from "./chunk-7YWUKMZD.js";
@@ -6,13 +6,13 @@ import {
6
6
  } from "./chunk-CRJUFA73.js";
7
7
  import {
8
8
  getAuthConfig
9
- } from "./chunk-N3TCQ5BF.js";
9
+ } from "./chunk-TQMQ5XXG.js";
10
10
  import {
11
11
  getCommonConfig
12
12
  } from "./chunk-PX535BHW.js";
13
13
  import {
14
14
  getResolvedCacheConfig
15
- } from "./chunk-7KIM5MHV.js";
15
+ } from "./chunk-RHYETIUR.js";
16
16
 
17
17
  // src/core/system/environment.ts
18
18
  import os from "os";
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-PX535BHW.js";
4
4
  import {
5
5
  getResolvedCacheConfig
6
- } from "./chunk-7KIM5MHV.js";
6
+ } from "./chunk-RHYETIUR.js";
7
7
 
8
8
  // src/core/cache/cache-env.ts
9
9
  function _getNodeEnv() {
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  AppError
3
- } from "./chunk-ATAQRXTH.js";
3
+ } from "./chunk-MCPPJI3T.js";
4
4
  import {
5
5
  ERROR_CODES,
6
6
  formatErrorMessage
7
- } from "./chunk-XQIAXMRY.js";
7
+ } from "./chunk-5VZIAXO2.js";
8
8
  import {
9
9
  logApiRequest,
10
10
  logApiResponse,
@@ -1,13 +1,18 @@
1
- import {
2
- durationToSeconds
3
- } from "./chunk-OVOBSYR4.js";
4
1
  import {
5
2
  getAuthConfig
6
- } from "./chunk-N3TCQ5BF.js";
3
+ } from "./chunk-TQMQ5XXG.js";
7
4
  import {
8
5
  JWT_DEFAULTS
9
6
  } from "./chunk-7YWUKMZD.js";
10
7
  import {
8
+ durationToSeconds
9
+ } from "./chunk-OVOBSYR4.js";
10
+ import {
11
+ ACCESS_TOKEN_COOKIE,
12
+ REFRESH_TOKEN_COOKIE
13
+ } from "./chunk-6NFMRZWB.js";
14
+ import {
15
+ __spreadProps,
11
16
  __spreadValues
12
17
  } from "./chunk-N3ETBM74.js";
13
18
 
@@ -38,39 +43,43 @@ function setTokenCookies(response, tokenPair, options = {}) {
38
43
  var _a, _b, _c;
39
44
  const opts = __spreadValues(__spreadValues({}, getDefaultOptions()), options);
40
45
  const maxAge = resolveMaxAge();
41
- response.cookies.set("access_token", tokenPair.accessToken, {
46
+ response.cookies.set(ACCESS_TOKEN_COOKIE, tokenPair.accessToken, __spreadProps(__spreadValues({
42
47
  httpOnly: true,
43
48
  secure: opts.secure,
44
49
  sameSite: opts.sameSite,
45
- path: "/",
50
+ path: "/"
51
+ }, opts.domain ? { domain: opts.domain } : {}), {
46
52
  maxAge: (_a = opts.accessTokenMaxAge) != null ? _a : maxAge.access
47
- });
48
- response.cookies.set("refresh_token", tokenPair.refreshToken, {
53
+ }));
54
+ response.cookies.set(REFRESH_TOKEN_COOKIE, tokenPair.refreshToken, __spreadProps(__spreadValues({
49
55
  httpOnly: true,
50
56
  secure: opts.secure,
51
57
  sameSite: opts.sameSite,
52
- path: (_b = opts.refreshTokenPath) != null ? _b : "/api/auth",
58
+ path: (_b = opts.refreshTokenPath) != null ? _b : "/api/auth"
59
+ }, opts.domain ? { domain: opts.domain } : {}), {
53
60
  maxAge: (_c = opts.refreshTokenMaxAge) != null ? _c : maxAge.refresh
54
- });
61
+ }));
55
62
  return response;
56
63
  }
57
64
  function clearTokenCookies(response, options = {}) {
58
65
  var _a;
59
66
  const opts = __spreadValues(__spreadValues({}, getDefaultOptions()), options);
60
- response.cookies.set("access_token", "", {
67
+ response.cookies.set(ACCESS_TOKEN_COOKIE, "", __spreadProps(__spreadValues({
61
68
  httpOnly: true,
62
69
  secure: opts.secure,
63
70
  sameSite: opts.sameSite,
64
- path: "/",
71
+ path: "/"
72
+ }, opts.domain ? { domain: opts.domain } : {}), {
65
73
  maxAge: 0
66
- });
67
- response.cookies.set("refresh_token", "", {
74
+ }));
75
+ response.cookies.set(REFRESH_TOKEN_COOKIE, "", __spreadProps(__spreadValues({
68
76
  httpOnly: true,
69
77
  secure: opts.secure,
70
78
  sameSite: opts.sameSite,
71
- path: (_a = opts.refreshTokenPath) != null ? _a : "/api/auth",
79
+ path: (_a = opts.refreshTokenPath) != null ? _a : "/api/auth"
80
+ }, opts.domain ? { domain: opts.domain } : {}), {
72
81
  maxAge: 0
73
- });
82
+ }));
74
83
  return response;
75
84
  }
76
85
 
@@ -10,7 +10,7 @@ import {
10
10
  } from "./chunk-QAIN3WNN.js";
11
11
  import {
12
12
  getResolvedCacheConfig
13
- } from "./chunk-7KIM5MHV.js";
13
+ } from "./chunk-RHYETIUR.js";
14
14
 
15
15
  // src/core/system/health-check.ts
16
16
  async function checkServiceHealth(prismaClient) {
@@ -3,14 +3,14 @@ import {
3
3
  isRedisGloballyDisabled,
4
4
  notifyRedisError,
5
5
  resetRedisGlobalState
6
- } from "./chunk-ZEHNCHIV.js";
6
+ } from "./chunk-MTRPUJ4B.js";
7
7
  import {
8
8
  logger
9
9
  } from "./chunk-QAIN3WNN.js";
10
10
  import {
11
11
  getENV,
12
12
  isCacheEnabled
13
- } from "./chunk-HV6A6Z5R.js";
13
+ } from "./chunk-BPDYEB37.js";
14
14
  import {
15
15
  __spreadValues
16
16
  } from "./chunk-N3ETBM74.js";
@@ -1,11 +1,15 @@
1
+ import {
2
+ validateApiKeyRecord
3
+ } from "./chunk-BTNM5YSU.js";
4
+ import {
5
+ API_KEY_ERROR_CODES,
6
+ ApiKeyError
7
+ } from "./chunk-4JZIIMAF.js";
1
8
  import {
2
9
  generateRawKey,
3
10
  hashKey,
4
11
  keyPreview
5
12
  } from "./chunk-ZZTBIA57.js";
6
- import {
7
- validateApiKeyRecord
8
- } from "./chunk-BTNM5YSU.js";
9
13
  import {
10
14
  __spreadProps,
11
15
  __spreadValues
@@ -42,19 +46,28 @@ var ApiKeyService = class {
42
46
  }
43
47
  async requireOwned(id, userId, isAdmin) {
44
48
  const rec = await this.deps.repo.findById(id);
45
- if (!rec) throw new Error("API key not found");
46
- if (!isAdmin && rec.userId !== userId) throw new Error("Unauthorized");
49
+ if (!rec) throw new ApiKeyError("API key not found", API_KEY_ERROR_CODES.NOT_FOUND);
50
+ if (!isAdmin && rec.userId !== userId) throw new ApiKeyError("Unauthorized", API_KEY_ERROR_CODES.OWNERSHIP);
47
51
  return rec;
48
52
  }
53
+ // FREEMIUM 등 제한 플랜은 한도(0) 의존이 아닌 명시 차단 — generate/validate 단일원천
54
+ assertPlanNotRestricted(plan) {
55
+ if (this.deps.env.restrictedPlans.includes(plan)) {
56
+ throw new ApiKeyError(
57
+ `API key is not available for the ${plan} plan. Please upgrade.`,
58
+ API_KEY_ERROR_CODES.PLAN_RESTRICTED
59
+ );
60
+ }
61
+ }
49
62
  async generateApiKey(userId, options, plan) {
50
63
  var _a, _b, _c, _d, _e, _f, _g;
51
64
  const { repo, planConfig, env } = this.deps;
52
- if (env.restrictedPlans.includes(plan)) {
53
- throw new Error(`API key is not available for the ${plan} plan. Please upgrade.`);
54
- }
65
+ this.assertPlanNotRestricted(plan);
55
66
  const maxKeys = await planConfig.getApiKeyLimit(plan);
56
67
  const active = await repo.countActive(userId);
57
- if (active >= maxKeys) throw new Error(`API key limit reached. Max ${maxKeys} keys.`);
68
+ if (active >= maxKeys) {
69
+ throw new ApiKeyError(`API key limit reached. Max ${maxKeys} keys.`, API_KEY_ERROR_CODES.LIMIT_REACHED);
70
+ }
58
71
  const rawKey = generateRawKey(this.prefix(options.environment));
59
72
  const planRate = await planConfig.getRateLimit(plan);
60
73
  const rateLimit = options.customRateLimit ? Math.min(options.customRateLimit, planRate) : planRate;
@@ -88,15 +101,17 @@ var ApiKeyService = class {
88
101
  var _a;
89
102
  const { repo, cache, env } = this.deps;
90
103
  const keyHash = hashKey(rawKey);
91
- const cached = await cache.getValidation(keyHash);
104
+ const cached = await cache.getValidation(keyHash).catch(() => null);
92
105
  if (cached) {
93
106
  const exp = (_a = cached.apiKey) == null ? void 0 : _a.expiresAt;
94
107
  if (!(exp && new Date(exp) < /* @__PURE__ */ new Date())) return cached;
95
- await cache.invalidate(keyHash);
108
+ await cache.invalidate(keyHash).catch(() => {
109
+ });
96
110
  }
97
111
  const record = await repo.findByHash(keyHash);
98
112
  const result = validateApiKeyRecord(record, { freemiumPlans: env.restrictedPlans });
99
- if (result.valid) await cache.setValidation(keyHash, result);
113
+ if (result.valid) await cache.setValidation(keyHash, result).catch(() => {
114
+ });
100
115
  return result;
101
116
  }
102
117
  async getApiKey(id, userId, isAdmin = false) {
@@ -138,9 +153,14 @@ var ApiKeyService = class {
138
153
  async regenerateApiKey(userId, apiKeyId, plan, options = {}) {
139
154
  var _a, _b, _c, _d, _e;
140
155
  const old = await this.requireOwned(apiKeyId, userId, false);
156
+ this.assertPlanNotRestricted(plan);
141
157
  if (!options.keepOldKeyActive) {
142
158
  const max = await this.deps.planConfig.getApiKeyLimit(plan);
143
- if (await this.deps.repo.countActive(userId) >= max) throw new Error(`API key limit reached. Max ${max} keys.`);
159
+ const active = await this.deps.repo.countActive(userId);
160
+ const effective = old.isActive ? active - 1 : active;
161
+ if (effective >= max) {
162
+ throw new ApiKeyError(`API key limit reached. Max ${max} keys.`, API_KEY_ERROR_CODES.LIMIT_REACHED);
163
+ }
144
164
  await this.deps.repo.deactivate(apiKeyId);
145
165
  await this.deps.cache.invalidate(old.key);
146
166
  }
@@ -1,9 +1,13 @@
1
1
  import {
2
2
  setTokenCookies
3
- } from "./chunk-6NEGFM32.js";
3
+ } from "./chunk-DTRXWS7G.js";
4
4
  import {
5
5
  getAuthConfig
6
- } from "./chunk-N3TCQ5BF.js";
6
+ } from "./chunk-TQMQ5XXG.js";
7
+ import {
8
+ ACCESS_TOKEN_COOKIE,
9
+ REFRESH_TOKEN_COOKIE
10
+ } from "./chunk-6NFMRZWB.js";
7
11
  import {
8
12
  __spreadValues
9
13
  } from "./chunk-N3ETBM74.js";
@@ -21,11 +25,11 @@ async function readBodyRefreshToken(source) {
21
25
  var cookieStrategy = {
22
26
  extractAccessToken: (source) => {
23
27
  var _a, _b;
24
- return (_b = (_a = source.cookies.get("access_token")) == null ? void 0 : _a.value) != null ? _b : null;
28
+ return (_b = (_a = source.cookies.get(ACCESS_TOKEN_COOKIE)) == null ? void 0 : _a.value) != null ? _b : null;
25
29
  },
26
30
  extractRefreshToken: async (source) => {
27
31
  var _a;
28
- return (_a = source.cookies.get("refresh_token")) == null ? void 0 : _a.value;
32
+ return (_a = source.cookies.get(REFRESH_TOKEN_COOKIE)) == null ? void 0 : _a.value;
29
33
  },
30
34
  buildTokenResponse: (body) => body,
31
35
  attachCookies: (response, tokens, options) => setTokenCookies(response, tokens, options)
@@ -39,12 +43,12 @@ var headerStrategy = {
39
43
  var hybridStrategy = {
40
44
  extractAccessToken: (source, parseHeader) => {
41
45
  var _a, _b;
42
- return (_b = (_a = source.cookies.get("access_token")) == null ? void 0 : _a.value) != null ? _b : parseHeader(source.headers.get("authorization"));
46
+ return (_b = (_a = source.cookies.get(ACCESS_TOKEN_COOKIE)) == null ? void 0 : _a.value) != null ? _b : parseHeader(source.headers.get("authorization"));
43
47
  },
44
48
  // 쿠키 우선 — 쿠키가 있으면 body 를 소비하지 않는다 (빈 body 요청 보호)
45
49
  extractRefreshToken: async (source) => {
46
50
  var _a, _b;
47
- return (_b = (_a = source.cookies.get("refresh_token")) == null ? void 0 : _a.value) != null ? _b : await readBodyRefreshToken(source);
51
+ return (_b = (_a = source.cookies.get(REFRESH_TOKEN_COOKIE)) == null ? void 0 : _a.value) != null ? _b : await readBodyRefreshToken(source);
48
52
  },
49
53
  buildTokenResponse: (body, fragment) => __spreadValues(__spreadValues({}, body), fragment),
50
54
  attachCookies: (response, tokens, options) => setTokenCookies(response, tokens, options)
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  ERROR_CODES,
3
3
  formatErrorMessage
4
- } from "./chunk-XQIAXMRY.js";
4
+ } from "./chunk-5VZIAXO2.js";
5
5
  import {
6
6
  ROLE_DEFAULTS
7
7
  } from "./chunk-7YWUKMZD.js";
@@ -1,22 +1,22 @@
1
1
  import {
2
2
  AUTH_ERROR_CODE_MAP
3
- } from "./chunk-R7EFDSPZ.js";
4
- import {
5
- AppError
6
- } from "./chunk-ATAQRXTH.js";
3
+ } from "./chunk-NHFIOK2D.js";
7
4
  import {
8
5
  getErrorMessage
9
6
  } from "./chunk-7WG7XPXC.js";
7
+ import {
8
+ AppError
9
+ } from "./chunk-MCPPJI3T.js";
10
10
  import {
11
11
  ERROR_CODES,
12
12
  classifyError
13
- } from "./chunk-XQIAXMRY.js";
14
- import {
15
- AuthError
16
- } from "./chunk-5GWGARXI.js";
13
+ } from "./chunk-5VZIAXO2.js";
17
14
  import {
18
15
  logger
19
16
  } from "./chunk-QAIN3WNN.js";
17
+ import {
18
+ AuthError
19
+ } from "./chunk-5GWGARXI.js";
20
20
  import {
21
21
  __spreadValues
22
22
  } from "./chunk-N3ETBM74.js";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  AppError
3
- } from "./chunk-ATAQRXTH.js";
3
+ } from "./chunk-MCPPJI3T.js";
4
4
  import {
5
5
  ERROR_CODES
6
- } from "./chunk-XQIAXMRY.js";
6
+ } from "./chunk-5VZIAXO2.js";
7
7
  import {
8
8
  logger
9
9
  } from "./chunk-QAIN3WNN.js";
@@ -4,7 +4,7 @@ import {
4
4
  formatErrorMessage,
5
5
  getErrorCategory,
6
6
  getHttpStatus
7
- } from "./chunk-XQIAXMRY.js";
7
+ } from "./chunk-5VZIAXO2.js";
8
8
 
9
9
  // src/core/error/app-error.ts
10
10
  var AppError = class _AppError extends Error {
@@ -7,7 +7,7 @@ import {
7
7
  getEnv,
8
8
  isCacheEnabled,
9
9
  validateRedisEnvironment
10
- } from "./chunk-HV6A6Z5R.js";
10
+ } from "./chunk-BPDYEB37.js";
11
11
 
12
12
  // src/core/cache/cache-redis.ts
13
13
  import { Redis } from "@upstash/redis";
@@ -1,18 +1,18 @@
1
1
  import {
2
2
  AppError
3
- } from "./chunk-ATAQRXTH.js";
3
+ } from "./chunk-MCPPJI3T.js";
4
4
  import {
5
5
  ERROR_CODES,
6
6
  classifyError,
7
7
  formatErrorMessage,
8
8
  getHttpStatus
9
- } from "./chunk-XQIAXMRY.js";
10
- import {
11
- AuthError
12
- } from "./chunk-5GWGARXI.js";
9
+ } from "./chunk-5VZIAXO2.js";
13
10
  import {
14
11
  logger
15
12
  } from "./chunk-QAIN3WNN.js";
13
+ import {
14
+ AuthError
15
+ } from "./chunk-5GWGARXI.js";
16
16
  import {
17
17
  __spreadProps,
18
18
  __spreadValues
@@ -1,18 +1,6 @@
1
- import {
2
- corsMiddleware
3
- } from "./chunk-37VGD4VX.js";
4
- import {
5
- errorHandlerMiddleware
6
- } from "./chunk-KHXS4DGA.js";
7
- import {
8
- initRequestMiddleware
9
- } from "./chunk-VC2E6KYQ.js";
10
- import {
11
- MiddlewareChain
12
- } from "./chunk-WXOWI7BJ.js";
13
1
  import {
14
2
  rateLimitMiddleware
15
- } from "./chunk-TRGFXIEF.js";
3
+ } from "./chunk-M4ZVQFOH.js";
16
4
  import {
17
5
  responseLoggerMiddleware
18
6
  } from "./chunk-LCYDMYZS.js";
@@ -23,7 +11,19 @@ import {
23
11
  adminMiddleware,
24
12
  authMiddleware,
25
13
  optionalAuthMiddleware
26
- } from "./chunk-HZN44RWL.js";
14
+ } from "./chunk-7Q6SMNMN.js";
15
+ import {
16
+ corsMiddleware
17
+ } from "./chunk-37VGD4VX.js";
18
+ import {
19
+ errorHandlerMiddleware
20
+ } from "./chunk-LFJ24NDO.js";
21
+ import {
22
+ initRequestMiddleware
23
+ } from "./chunk-VC2E6KYQ.js";
24
+ import {
25
+ MiddlewareChain
26
+ } from "./chunk-WXOWI7BJ.js";
27
27
 
28
28
  // src/next/middleware/wrappers.ts
29
29
  function withPublicApi(handler) {