@withwiz/toolkit 0.11.0 → 0.13.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-4JZIIMAF.js +33 -0
- package/dist/{chunk-XQIAXMRY.js → chunk-5VZIAXO2.js} +2 -1
- package/dist/{chunk-MJOXTFIC.js → chunk-7Q6SMNMN.js} +2 -2
- package/dist/{chunk-4Y5MRUMX.js → chunk-A6NIKJX5.js} +3 -3
- package/dist/{chunk-DISEIUYD.js → chunk-AQQ7JSS5.js} +1 -1
- package/dist/{chunk-BRFW2LL2.js → chunk-D4QADM6T.js} +2 -2
- package/dist/{chunk-RWENSBNW.js → chunk-G4IGD3AZ.js} +30 -10
- package/dist/{chunk-4TGPAUJV.js → chunk-K7OZWWIS.js} +2 -2
- package/dist/{chunk-23LQJYZN.js → chunk-KAS5ILUM.js} +1 -1
- package/dist/{chunk-YBVZ5UVC.js → chunk-L4WQRYMR.js} +3 -3
- package/dist/{chunk-QBXNL6QU.js → chunk-LYO2HV5F.js} +3 -3
- package/dist/{chunk-TRGFXIEF.js → chunk-M4ZVQFOH.js} +2 -2
- package/dist/{chunk-ATAQRXTH.js → chunk-MCPPJI3T.js} +1 -1
- package/dist/{chunk-AYCXN6QJ.js → chunk-NHFIOK2D.js} +2 -2
- package/dist/{chunk-ZEHNCHIV.js → chunk-NKZPMRVF.js} +1 -1
- package/dist/{chunk-Y6CPPBJI.js → chunk-QVPGBTCL.js} +1 -1
- package/dist/{chunk-2QO7YXTF.js → chunk-QVU4BHMC.js} +1 -1
- package/dist/{chunk-XF3WUF3F.js → chunk-ROJJJXRL.js} +2 -2
- package/dist/{chunk-NAFMJT62.js → chunk-TDRB5BIM.js} +7 -7
- package/dist/{chunk-WYA763JL.js → chunk-TGEKWTFZ.js} +1 -1
- package/dist/{chunk-HV6A6Z5R.js → chunk-UGLEAXTY.js} +3 -3
- package/dist/{chunk-5S7M2AJL.js → chunk-W2FBLCOR.js} +1 -1
- package/dist/{chunk-7IOAGJMK.js → chunk-YOIZUVRD.js} +3 -3
- package/dist/{chunk-2GK4LDPV.js → chunk-Z3OLZKTN.js} +2 -2
- package/dist/{chunk-JRORMRVN.js → chunk-ZVGEGDYF.js} +1 -1
- package/dist/core/api-key/api-key.service.d.ts +1 -0
- package/dist/core/api-key/api-key.service.js +2 -1
- 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 +11 -3
- package/dist/core/auth/index.js +29 -29
- package/dist/core/auth/oauth/index.js +7 -7
- package/dist/core/auth/oauth/providers/index.js +6 -6
- package/dist/core/auth/services/index.js +7 -7
- 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 +13 -13
- package/dist/core/cache/config.js +2 -2
- package/dist/core/cache/hybrid-cache-manager.js +5 -5
- package/dist/core/cache/index.js +13 -13
- 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 +3 -3
- package/dist/core/geolocation/index.js +7 -7
- package/dist/core/geolocation/providers/index.js +7 -7
- package/dist/core/storage/r2-storage.js +2 -2
- package/dist/core/system/environment.js +3 -3
- package/dist/core/system/health-check.js +3 -3
- package/dist/core/system/index.js +7 -7
- package/dist/core/utils/optimistic-lock.js +2 -2
- package/dist/core/utils/startup-banner.d.ts +56 -0
- package/dist/core/utils/startup-banner.js +78 -0
- package/dist/initialize.js +10 -10
- package/dist/next/auth-handlers/index.js +18 -18
- package/dist/next/auth-handlers/oauth-authorize.handler.js +4 -4
- package/dist/next/auth-handlers/oauth-callback.handler.js +5 -5
- package/dist/next/error/error-handler.js +3 -3
- package/dist/next/error/index.js +4 -4
- package/dist/next/middleware/auth.js +3 -3
- package/dist/next/middleware/error-handler.js +4 -4
- package/dist/next/middleware/index.js +7 -7
- package/dist/next/middleware/rate-limit.js +3 -3
- package/dist/next/middleware/wrappers.js +7 -7
- package/dist/next/oapi/api-key-auth.js +4 -3
- package/dist/next/oapi/index.js +4 -3
- package/dist/next/utils/api-helpers.js +2 -2
- package/dist/next/utils/error-processor.js +3 -3
- package/dist/next/utils/index.js +17 -17
- package/package.json +3 -1
- package/dist/{chunk-MXWSG6ER.js → chunk-KYUJ6D65.js} +0 -0
- package/dist/{chunk-VDRLJU6C.js → chunk-Q5RPNLET.js} +6 -6
- package/dist/{chunk-7KIM5MHV.js → chunk-RHYETIUR.js} +3 -3
- package/dist/{chunk-UQ3Z3ZAF.js → chunk-V3GEYUBG.js} +6 -6
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)
|
|
@@ -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
|
+
};
|
|
@@ -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,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AUTH_ERROR_CODE_MAP
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-NHFIOK2D.js";
|
|
4
4
|
import {
|
|
5
5
|
AppError
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-MCPPJI3T.js";
|
|
7
7
|
import {
|
|
8
8
|
getErrorMessage
|
|
9
9
|
} from "./chunk-7WG7XPXC.js";
|
|
10
10
|
import {
|
|
11
11
|
ERROR_CODES,
|
|
12
12
|
classifyError
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-5VZIAXO2.js";
|
|
14
14
|
import {
|
|
15
15
|
logger
|
|
16
16
|
} from "./chunk-QAIN3WNN.js";
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
validateApiKeyRecord
|
|
3
3
|
} from "./chunk-BTNM5YSU.js";
|
|
4
|
+
import {
|
|
5
|
+
API_KEY_ERROR_CODES,
|
|
6
|
+
ApiKeyError
|
|
7
|
+
} from "./chunk-4JZIIMAF.js";
|
|
4
8
|
import {
|
|
5
9
|
generateRawKey,
|
|
6
10
|
hashKey,
|
|
@@ -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
|
}
|
|
@@ -3,14 +3,14 @@ import {
|
|
|
3
3
|
isRedisGloballyDisabled,
|
|
4
4
|
notifyRedisError,
|
|
5
5
|
resetRedisGlobalState
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-NKZPMRVF.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-UGLEAXTY.js";
|
|
14
14
|
import {
|
|
15
15
|
__spreadValues
|
|
16
16
|
} from "./chunk-N3ETBM74.js";
|
|
@@ -7,12 +7,12 @@ import {
|
|
|
7
7
|
import {
|
|
8
8
|
getAuthConfig
|
|
9
9
|
} from "./chunk-TQMQ5XXG.js";
|
|
10
|
+
import {
|
|
11
|
+
getResolvedCacheConfig
|
|
12
|
+
} from "./chunk-RHYETIUR.js";
|
|
10
13
|
import {
|
|
11
14
|
getCommonConfig
|
|
12
15
|
} from "./chunk-PX535BHW.js";
|
|
13
|
-
import {
|
|
14
|
-
getResolvedCacheConfig
|
|
15
|
-
} from "./chunk-7KIM5MHV.js";
|
|
16
16
|
|
|
17
17
|
// src/core/system/environment.ts
|
|
18
18
|
import os from "os";
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getCacheManager,
|
|
3
3
|
getEffectiveCacheBackend
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-TDRB5BIM.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-QVPGBTCL.js";
|
|
12
12
|
import {
|
|
13
13
|
isCacheEnabled
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-UGLEAXTY.js";
|
|
15
15
|
|
|
16
16
|
// src/core/cache/cache-wrapper.ts
|
|
17
17
|
function getCacheBackendLabel() {
|
|
@@ -1,12 +1,12 @@
|
|
|
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-
|
|
9
|
+
} from "./chunk-5VZIAXO2.js";
|
|
10
10
|
import {
|
|
11
11
|
logger
|
|
12
12
|
} from "./chunk-QAIN3WNN.js";
|
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
import {
|
|
2
2
|
HybridCacheManager
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-Z3OLZKTN.js";
|
|
4
4
|
import {
|
|
5
5
|
InMemoryCacheManager
|
|
6
6
|
} from "./chunk-YYTA6ERS.js";
|
|
7
7
|
import {
|
|
8
8
|
NoopCacheManager
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-ROJJJXRL.js";
|
|
10
10
|
import {
|
|
11
11
|
RedisCacheManager
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-K7OZWWIS.js";
|
|
13
13
|
import {
|
|
14
14
|
isRedisAvailableNow,
|
|
15
15
|
isRedisGloballyDisabled
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-NKZPMRVF.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-QVPGBTCL.js";
|
|
23
23
|
import {
|
|
24
24
|
getENV,
|
|
25
25
|
isCacheEnabled
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-UGLEAXTY.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";
|
|
@@ -8,13 +8,13 @@ import {
|
|
|
8
8
|
adminMiddleware,
|
|
9
9
|
authMiddleware,
|
|
10
10
|
optionalAuthMiddleware
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-7Q6SMNMN.js";
|
|
12
12
|
import {
|
|
13
13
|
corsMiddleware
|
|
14
14
|
} from "./chunk-37VGD4VX.js";
|
|
15
15
|
import {
|
|
16
16
|
errorHandlerMiddleware
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-A6NIKJX5.js";
|
|
18
18
|
import {
|
|
19
19
|
initRequestMiddleware
|
|
20
20
|
} from "./chunk-VC2E6KYQ.js";
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
} from "./chunk-WXOWI7BJ.js";
|
|
24
24
|
import {
|
|
25
25
|
rateLimitMiddleware
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-M4ZVQFOH.js";
|
|
27
27
|
|
|
28
28
|
// src/next/middleware/wrappers.ts
|
|
29
29
|
function withPublicApi(handler) {
|
|
@@ -4,13 +4,13 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
isRedisGloballyDisabled,
|
|
6
6
|
notifyRedisError
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-NKZPMRVF.js";
|
|
8
8
|
import {
|
|
9
9
|
logger
|
|
10
10
|
} from "./chunk-QAIN3WNN.js";
|
|
11
11
|
import {
|
|
12
12
|
getCacheFallbackConfig
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-UGLEAXTY.js";
|
|
14
14
|
import {
|
|
15
15
|
__spreadValues
|
|
16
16
|
} from "./chunk-N3ETBM74.js";
|
|
@@ -13,6 +13,7 @@ export declare class ApiKeyService {
|
|
|
13
13
|
private prefix;
|
|
14
14
|
private toInfo;
|
|
15
15
|
private requireOwned;
|
|
16
|
+
private assertPlanNotRestricted;
|
|
16
17
|
generateApiKey(userId: string, options: CreateApiKeyOptions, plan: string): Promise<ApiKeyResult>;
|
|
17
18
|
validateApiKey(rawKey: string): Promise<ApiKeyValidationResult>;
|
|
18
19
|
getApiKey(id: string, userId: string, isAdmin?: boolean): Promise<ApiKeyInfo>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare const API_KEY_ERROR_CODES: {
|
|
2
|
+
/** 대상 API 키 미존재 */
|
|
3
|
+
readonly NOT_FOUND: "API_KEY_NOT_FOUND";
|
|
4
|
+
/** 비소유자 접근 (admin 우회 제외) */
|
|
5
|
+
readonly OWNERSHIP: "API_KEY_OWNERSHIP";
|
|
6
|
+
/** 제한 플랜(restrictedPlans)의 발급 시도 */
|
|
7
|
+
readonly PLAN_RESTRICTED: "API_KEY_PLAN_RESTRICTED";
|
|
8
|
+
/** 플랜별 활성 키 한도 초과 */
|
|
9
|
+
readonly LIMIT_REACHED: "API_KEY_LIMIT_REACHED";
|
|
10
|
+
};
|
|
11
|
+
export type ApiKeyErrorCode = (typeof API_KEY_ERROR_CODES)[keyof typeof API_KEY_ERROR_CODES];
|
|
12
|
+
export declare class ApiKeyError extends Error {
|
|
13
|
+
readonly code: ApiKeyErrorCode;
|
|
14
|
+
constructor(message: string, code: ApiKeyErrorCode);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* ApiKeyError 판별 가드. instanceof 대신 name+code 구조 검사를 사용해
|
|
18
|
+
* 패키지 중복 설치(모듈 인스턴스 분리) 환경에서도 판별이 깨지지 않는다.
|
|
19
|
+
* code를 지정하면 해당 코드까지 일치해야 true.
|
|
20
|
+
*/
|
|
21
|
+
export declare function isApiKeyError(error: unknown, code?: ApiKeyErrorCode): error is ApiKeyError;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from '@withwiz/toolkit/core/api-key/types';
|
|
2
|
+
export * from '@withwiz/toolkit/core/api-key/errors';
|
|
2
3
|
export * from '@withwiz/toolkit/core/api-key/ports';
|
|
3
4
|
export * from '@withwiz/toolkit/core/api-key/key-generator';
|
|
4
5
|
export * from '@withwiz/toolkit/core/api-key/ip-whitelist';
|
|
@@ -1,10 +1,16 @@
|
|
|
1
|
-
import "../../chunk-
|
|
1
|
+
import "../../chunk-KYUJ6D65.js";
|
|
2
|
+
import "../../chunk-TN5ZNYR2.js";
|
|
2
3
|
import {
|
|
3
4
|
ApiKeyService
|
|
4
|
-
} from "../../chunk-
|
|
5
|
+
} from "../../chunk-G4IGD3AZ.js";
|
|
5
6
|
import {
|
|
6
7
|
validateApiKeyRecord
|
|
7
8
|
} from "../../chunk-BTNM5YSU.js";
|
|
9
|
+
import {
|
|
10
|
+
API_KEY_ERROR_CODES,
|
|
11
|
+
ApiKeyError,
|
|
12
|
+
isApiKeyError
|
|
13
|
+
} from "../../chunk-4JZIIMAF.js";
|
|
8
14
|
import {
|
|
9
15
|
isIpAllowed,
|
|
10
16
|
isIpInCidr
|
|
@@ -16,11 +22,13 @@ import {
|
|
|
16
22
|
} from "../../chunk-ZZTBIA57.js";
|
|
17
23
|
import "../../chunk-N3ETBM74.js";
|
|
18
24
|
import "../../chunk-CWS5RPRX.js";
|
|
19
|
-
import "../../chunk-TN5ZNYR2.js";
|
|
20
25
|
export {
|
|
26
|
+
API_KEY_ERROR_CODES,
|
|
27
|
+
ApiKeyError,
|
|
21
28
|
ApiKeyService,
|
|
22
29
|
generateRawKey,
|
|
23
30
|
hashKey,
|
|
31
|
+
isApiKeyError,
|
|
24
32
|
isIpAllowed,
|
|
25
33
|
isIpInCidr,
|
|
26
34
|
keyPreview,
|