@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.
- package/README.md +6 -0
- package/dist/{chunk-Z64GNAB7.js → chunk-2SV6VZOC.js} +2 -2
- package/dist/{chunk-3P4TZM3O.js → chunk-3EEOZHIJ.js} +3 -3
- package/dist/chunk-4JZIIMAF.js +33 -0
- package/dist/{chunk-BICSVLN7.js → chunk-4OFL7KZ7.js} +11 -11
- package/dist/{chunk-XDB3K74B.js → chunk-4OKAMI6O.js} +1 -1
- package/dist/{chunk-W27FQNP6.js → chunk-5MPMPXIR.js} +1 -1
- package/dist/{chunk-XQIAXMRY.js → chunk-5VZIAXO2.js} +2 -1
- package/dist/{chunk-465MEI5K.js → chunk-6E2Q27EN.js} +1 -1
- package/dist/chunk-6NFMRZWB.js +8 -0
- package/dist/{chunk-HZN44RWL.js → chunk-7Q6SMNMN.js} +7 -7
- package/dist/{chunk-SROPI74N.js → chunk-AWFP2KAU.js} +1 -1
- package/dist/{chunk-7S2PCYNT.js → chunk-B2JZPUQ3.js} +2 -2
- package/dist/{chunk-HV6A6Z5R.js → chunk-BPDYEB37.js} +1 -1
- package/dist/{chunk-BRFW2LL2.js → chunk-D4QADM6T.js} +2 -2
- package/dist/{chunk-6NEGFM32.js → chunk-DTRXWS7G.js} +25 -16
- package/dist/{chunk-UIWR5MXM.js → chunk-ETXMWDXV.js} +1 -1
- package/dist/{chunk-4TGPAUJV.js → chunk-F2FTS6H4.js} +2 -2
- package/dist/{chunk-P4MGYRJM.js → chunk-G4IGD3AZ.js} +33 -13
- package/dist/{chunk-VHRBXD7U.js → chunk-HNFYO5XV.js} +10 -6
- package/dist/{chunk-23LQJYZN.js → chunk-KAS5ILUM.js} +1 -1
- package/dist/{chunk-KHXS4DGA.js → chunk-LFJ24NDO.js} +8 -8
- package/dist/{chunk-TRGFXIEF.js → chunk-M4ZVQFOH.js} +2 -2
- package/dist/{chunk-ATAQRXTH.js → chunk-MCPPJI3T.js} +1 -1
- package/dist/{chunk-ZEHNCHIV.js → chunk-MTRPUJ4B.js} +1 -1
- package/dist/{chunk-R7EFDSPZ.js → chunk-NHFIOK2D.js} +5 -5
- package/dist/{chunk-5Z5CZAZP.js → chunk-NT6URT4W.js} +14 -14
- package/dist/{chunk-Y6CPPBJI.js → chunk-OEZPVNSA.js} +1 -1
- package/dist/{chunk-KZ4PDS5K.js → chunk-RWN47K7J.js} +1 -1
- package/dist/{chunk-N3TCQ5BF.js → chunk-TQMQ5XXG.js} +17 -2
- package/dist/{chunk-OII5BXCZ.js → chunk-U2TGXJ3A.js} +1 -1
- package/dist/{chunk-5S7M2AJL.js → chunk-W2FBLCOR.js} +1 -1
- package/dist/{chunk-XF3WUF3F.js → chunk-ZFBY2FNS.js} +2 -2
- package/dist/{chunk-2GK4LDPV.js → chunk-ZLUID5BU.js} +2 -2
- package/dist/core/api-key/api-key.service.d.ts +1 -0
- package/dist/core/api-key/api-key.service.js +3 -2
- package/dist/core/api-key/errors.d.ts +21 -0
- package/dist/core/api-key/errors.js +11 -0
- package/dist/core/api-key/index.d.ts +1 -0
- package/dist/core/api-key/index.js +15 -7
- package/dist/core/auth/adapters/sql/email-token-repository.js +2 -2
- package/dist/core/auth/adapters/sql/index.js +8 -8
- package/dist/core/auth/adapters/sql/oauth-account-repository.js +2 -2
- package/dist/core/auth/adapters/sql/user-repository.js +2 -2
- package/dist/core/auth/config.js +2 -1
- package/dist/core/auth/cookie-names.d.ts +3 -0
- package/dist/core/auth/cookie-names.js +9 -0
- package/dist/core/auth/index.js +9 -8
- package/dist/core/auth/jwt/cookie.js +4 -3
- package/dist/core/auth/jwt/index.js +4 -3
- package/dist/core/auth/oauth/index.js +7 -7
- package/dist/core/auth/oauth/providers/index.js +6 -6
- package/dist/core/auth/services/cache-token-stores.d.ts +45 -0
- package/dist/core/auth/services/cache-token-stores.js +59 -0
- package/dist/core/auth/services/index.js +4 -3
- package/dist/core/auth/services/login.service.js +4 -3
- package/dist/core/auth/services/oauth-callback.service.js +4 -3
- package/dist/core/auth/services/token-refresh.service.js +4 -3
- package/dist/core/auth/token-delivery.js +5 -4
- package/dist/core/cache/cache-config.js +4 -4
- package/dist/core/cache/cache-env.js +3 -3
- package/dist/core/cache/cache-factory.js +9 -9
- package/dist/core/cache/cache-invalidation.js +10 -10
- package/dist/core/cache/cache-redis.js +4 -4
- package/dist/core/cache/cache-wrapper.js +10 -10
- package/dist/core/cache/cache.js +16 -16
- package/dist/core/cache/config.js +2 -2
- package/dist/core/cache/hybrid-cache-manager.js +5 -5
- package/dist/core/cache/index.js +16 -16
- package/dist/core/cache/noop-cache-manager.js +5 -5
- package/dist/core/cache/redis-cache-manager.js +5 -5
- package/dist/core/constants/error-codes.js +1 -1
- package/dist/core/constants/index.js +1 -1
- package/dist/core/error/app-error.js +2 -2
- package/dist/core/error/friendly-messages-v2.js +2 -2
- package/dist/core/error/friendly-messages.js +1 -1
- package/dist/core/error/index.js +5 -5
- package/dist/core/storage/r2-storage.js +2 -2
- package/dist/core/system/environment.js +6 -5
- package/dist/core/system/health-check.js +3 -3
- package/dist/core/system/index.js +10 -9
- package/dist/core/utils/optimistic-lock.js +2 -2
- package/dist/initialize.js +11 -10
- package/dist/next/auth-handlers/index.js +14 -13
- package/dist/next/auth-handlers/login.handler.js +6 -5
- package/dist/next/auth-handlers/logout.handler.js +5 -4
- package/dist/next/auth-handlers/me.handler.js +6 -5
- package/dist/next/auth-handlers/oauth-authorize.handler.js +4 -4
- package/dist/next/auth-handlers/oauth-callback.handler.js +8 -7
- package/dist/next/auth-handlers/refresh.handler.js +6 -5
- package/dist/next/auth-types/handler-types.js +5 -4
- package/dist/next/auth-types/index.js +5 -4
- package/dist/next/error/error-handler.js +4 -4
- package/dist/next/error/index.js +5 -5
- package/dist/next/middleware/auth.js +10 -9
- package/dist/next/middleware/error-handler.js +5 -5
- package/dist/next/middleware/index.js +27 -26
- package/dist/next/middleware/rate-limit.js +3 -3
- package/dist/next/middleware/wrappers.js +16 -15
- package/dist/next/oapi/api-key-auth.js +6 -5
- package/dist/next/oapi/index.js +6 -5
- package/dist/next/proxy.d.ts +38 -0
- package/dist/next/proxy.js +53 -0
- package/dist/next/utils/api-helpers.js +2 -2
- package/dist/next/utils/error-processor.js +3 -3
- package/dist/next/utils/index.js +27 -27
- package/package.json +13 -3
- package/dist/{chunk-GSRAIDD7.js → chunk-6A5JHOBB.js} +3 -3
- package/dist/{chunk-43XXILCX.js → chunk-BTYH4MHU.js} +3 -3
- package/dist/{chunk-MXWSG6ER.js → chunk-KYUJ6D65.js} +0 -0
- package/dist/{chunk-ER6LSA4M.js → chunk-P7WHMKN5.js} +6 -6
- package/dist/{chunk-7KIM5MHV.js → chunk-RHYETIUR.js} +3 -3
- 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-
|
|
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-
|
|
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-
|
|
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-
|
|
11
|
+
} from "./chunk-OEZPVNSA.js";
|
|
12
12
|
import {
|
|
13
13
|
isCacheEnabled
|
|
14
|
-
} from "./chunk-
|
|
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-
|
|
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-
|
|
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-
|
|
22
|
+
} from "./chunk-OEZPVNSA.js";
|
|
23
23
|
import {
|
|
24
24
|
getENV,
|
|
25
25
|
isCacheEnabled
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-BPDYEB37.js";
|
|
27
27
|
import {
|
|
28
28
|
isCacheConfigInitialized
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-RHYETIUR.js";
|
|
30
30
|
import {
|
|
31
31
|
configWarn
|
|
32
32
|
} from "./chunk-6J2EJVND.js";
|
|
@@ -94,7 +94,8 @@ var ERROR_CODES = {
|
|
|
94
94
|
},
|
|
95
95
|
// ============================================
|
|
96
96
|
// Permissions Related (403xx - 01~09)
|
|
97
|
-
//
|
|
97
|
+
// 40301: next/oapi api-key-auth wire 계약에서 사용 중 (IP 차단·사용량 초과) — 재배정 금지
|
|
98
|
+
// Reserved: 40302~40303 (미사용, 향후 세분화 확장용)
|
|
98
99
|
// ============================================
|
|
99
100
|
FORBIDDEN: {
|
|
100
101
|
code: 40304,
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AppError
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-MCPPJI3T.js";
|
|
4
4
|
import {
|
|
5
5
|
ERROR_CODES
|
|
6
|
-
} from "./chunk-
|
|
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-
|
|
13
|
-
import {
|
|
14
|
-
logger
|
|
15
|
-
} from "./chunk-QAIN3WNN.js";
|
|
15
|
+
} from "./chunk-HNFYO5XV.js";
|
|
16
16
|
import {
|
|
17
17
|
getAuthConfig
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-TQMQ5XXG.js";
|
|
19
19
|
import {
|
|
20
20
|
ROLE_DEFAULTS
|
|
21
21
|
} from "./chunk-7YWUKMZD.js";
|
|
@@ -6,13 +6,13 @@ import {
|
|
|
6
6
|
} from "./chunk-CRJUFA73.js";
|
|
7
7
|
import {
|
|
8
8
|
getAuthConfig
|
|
9
|
-
} from "./chunk-
|
|
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-
|
|
15
|
+
} from "./chunk-RHYETIUR.js";
|
|
16
16
|
|
|
17
17
|
// src/core/system/environment.ts
|
|
18
18
|
import os from "os";
|
|
@@ -1,13 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
durationToSeconds
|
|
3
|
-
} from "./chunk-OVOBSYR4.js";
|
|
4
1
|
import {
|
|
5
2
|
getAuthConfig
|
|
6
|
-
} from "./chunk-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
|
@@ -3,14 +3,14 @@ import {
|
|
|
3
3
|
isRedisGloballyDisabled,
|
|
4
4
|
notifyRedisError,
|
|
5
5
|
resetRedisGlobalState
|
|
6
|
-
} from "./chunk-
|
|
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-
|
|
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
|
|
46
|
-
if (!isAdmin && rec.userId !== userId) throw new
|
|
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
|
-
|
|
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)
|
|
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
|
-
|
|
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-
|
|
3
|
+
} from "./chunk-DTRXWS7G.js";
|
|
4
4
|
import {
|
|
5
5
|
getAuthConfig
|
|
6
|
-
} from "./chunk-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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,22 +1,22 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AUTH_ERROR_CODE_MAP
|
|
3
|
-
} from "./chunk-
|
|
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-
|
|
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,18 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AppError
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-MCPPJI3T.js";
|
|
4
4
|
import {
|
|
5
5
|
ERROR_CODES,
|
|
6
6
|
classifyError,
|
|
7
7
|
formatErrorMessage,
|
|
8
8
|
getHttpStatus
|
|
9
|
-
} from "./chunk-
|
|
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-
|
|
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-
|
|
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) {
|