@withwiz/toolkit 0.9.3 → 0.11.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 (99) hide show
  1. package/dist/{chunk-XDB3K74B.js → chunk-2QO7YXTF.js} +1 -1
  2. package/dist/{chunk-ISP4MDKW.js → chunk-5MPMPXIR.js} +1 -1
  3. package/dist/{chunk-KMUYO6YD.js → chunk-6E2Q27EN.js} +1 -1
  4. package/dist/chunk-6NFMRZWB.js +8 -0
  5. package/dist/{chunk-OXKVQGRH.js → chunk-7IOAGJMK.js} +13 -13
  6. package/dist/{chunk-ROMGYJFX.js → chunk-AWFP2KAU.js} +1 -1
  7. package/dist/chunk-BTNM5YSU.js +29 -0
  8. package/dist/chunk-CWS5RPRX.js +0 -0
  9. package/dist/{chunk-VQ47YRFC.js → chunk-DISEIUYD.js} +2 -2
  10. package/dist/{chunk-BOABYFJ7.js → chunk-DTRXWS7G.js} +22 -13
  11. package/dist/{chunk-NERL6VYQ.js → chunk-HNFYO5XV.js} +10 -6
  12. package/dist/{chunk-ZVGEGDYF.js → chunk-JRORMRVN.js} +1 -1
  13. package/dist/chunk-L2A6NGW7.js +21 -0
  14. package/dist/{chunk-CNXK3SLK.js → chunk-MJOXTFIC.js} +2 -2
  15. package/dist/chunk-MXWSG6ER.js +0 -0
  16. package/dist/chunk-NUHSUAXG.js +35 -0
  17. package/dist/{chunk-3P4TZM3O.js → chunk-QBXNL6QU.js} +1 -1
  18. package/dist/chunk-RWENSBNW.js +162 -0
  19. package/dist/{chunk-6SDUWMC3.js → chunk-RWN47K7J.js} +1 -1
  20. package/dist/chunk-TN5ZNYR2.js +0 -0
  21. package/dist/{chunk-N3TCQ5BF.js → chunk-TQMQ5XXG.js} +17 -2
  22. package/dist/chunk-XWHT53CZ.js +38 -0
  23. package/dist/{chunk-7S2PCYNT.js → chunk-YBVZ5UVC.js} +1 -1
  24. package/dist/chunk-Z4J452HD.js +24 -0
  25. package/dist/chunk-ZZTBIA57.js +18 -0
  26. package/dist/core/api-key/api-key.service.d.ts +28 -0
  27. package/dist/core/api-key/api-key.service.js +9 -0
  28. package/dist/core/api-key/index.d.ts +6 -0
  29. package/dist/core/api-key/index.js +28 -0
  30. package/dist/core/api-key/ip-whitelist.d.ts +4 -0
  31. package/dist/core/api-key/ip-whitelist.js +9 -0
  32. package/dist/core/api-key/key-generator.d.ts +6 -0
  33. package/dist/core/api-key/key-generator.js +11 -0
  34. package/dist/core/api-key/ports.d.ts +104 -0
  35. package/dist/core/api-key/ports.js +1 -0
  36. package/dist/core/api-key/types.d.ts +88 -0
  37. package/dist/core/api-key/types.js +1 -0
  38. package/dist/core/api-key/validate.d.ts +9 -0
  39. package/dist/core/api-key/validate.js +7 -0
  40. package/dist/core/auth/config.js +2 -1
  41. package/dist/core/auth/cookie-names.d.ts +3 -0
  42. package/dist/core/auth/cookie-names.js +9 -0
  43. package/dist/core/auth/index.js +13 -12
  44. package/dist/core/auth/jwt/cookie.js +3 -2
  45. package/dist/core/auth/jwt/index.js +3 -2
  46. package/dist/core/auth/oauth/index.js +7 -7
  47. package/dist/core/auth/oauth/providers/index.js +6 -6
  48. package/dist/core/auth/services/cache-token-stores.d.ts +45 -0
  49. package/dist/core/auth/services/cache-token-stores.js +59 -0
  50. package/dist/core/auth/services/index.js +7 -6
  51. package/dist/core/auth/services/login.service.js +3 -2
  52. package/dist/core/auth/services/oauth-callback.service.js +3 -2
  53. package/dist/core/auth/services/token-refresh.service.js +3 -2
  54. package/dist/core/auth/token-delivery.js +4 -3
  55. package/dist/core/cache/cache-factory.js +4 -4
  56. package/dist/core/cache/cache-invalidation.js +5 -5
  57. package/dist/core/cache/cache-redis.js +1 -1
  58. package/dist/core/cache/cache-wrapper.js +5 -5
  59. package/dist/core/cache/cache.js +10 -10
  60. package/dist/core/cache/hybrid-cache-manager.js +1 -1
  61. package/dist/core/cache/index.js +10 -10
  62. package/dist/core/cache/redis-cache-manager.js +1 -1
  63. package/dist/core/geolocation/index.js +7 -7
  64. package/dist/core/geolocation/providers/index.js +7 -7
  65. package/dist/core/system/environment.js +3 -2
  66. package/dist/core/system/health-check.js +1 -1
  67. package/dist/core/system/index.js +7 -6
  68. package/dist/initialize.js +6 -5
  69. package/dist/next/auth-handlers/index.js +20 -19
  70. package/dist/next/auth-handlers/login.handler.js +5 -4
  71. package/dist/next/auth-handlers/logout.handler.js +4 -3
  72. package/dist/next/auth-handlers/me.handler.js +5 -4
  73. package/dist/next/auth-handlers/oauth-authorize.handler.js +4 -4
  74. package/dist/next/auth-handlers/oauth-callback.handler.js +8 -7
  75. package/dist/next/auth-handlers/refresh.handler.js +5 -4
  76. package/dist/next/auth-types/handler-types.js +4 -3
  77. package/dist/next/auth-types/index.js +4 -3
  78. package/dist/next/error/error-handler.js +1 -1
  79. package/dist/next/error/index.js +1 -1
  80. package/dist/next/middleware/auth.js +6 -5
  81. package/dist/next/middleware/error-handler.js +1 -1
  82. package/dist/next/middleware/index.js +22 -21
  83. package/dist/next/middleware/wrappers.js +11 -10
  84. package/dist/next/oapi/api-key-auth.d.ts +27 -0
  85. package/dist/next/oapi/api-key-auth.js +14 -0
  86. package/dist/next/oapi/helpers.d.ts +19 -0
  87. package/dist/next/oapi/helpers.js +13 -0
  88. package/dist/next/oapi/index.d.ts +3 -0
  89. package/dist/next/oapi/index.js +28 -0
  90. package/dist/next/oapi/openapi-spec.d.ts +18 -0
  91. package/dist/next/oapi/openapi-spec.js +7 -0
  92. package/dist/next/proxy.d.ts +38 -0
  93. package/dist/next/proxy.js +53 -0
  94. package/dist/next/utils/index.js +14 -14
  95. package/package.json +21 -1
  96. package/dist/{chunk-BICSVLN7.js → chunk-NAFMJT62.js} +6 -6
  97. package/dist/{chunk-V3GEYUBG.js → chunk-UQ3Z3ZAF.js} +6 -6
  98. package/dist/{chunk-Q5RPNLET.js → chunk-VDRLJU6C.js} +6 -6
  99. /package/dist/{chunk-WU3V2AKE.js → chunk-WYA763JL.js} +0 -0
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  cache,
3
3
  geoCache
4
- } from "./chunk-BICSVLN7.js";
4
+ } from "./chunk-NAFMJT62.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-NERL6VYQ.js";
9
+ } from "./chunk-HNFYO5XV.js";
10
10
  import {
11
11
  JWT_DEFAULTS,
12
12
  ROLE_DEFAULTS
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  clearTokenCookies
3
- } from "./chunk-BOABYFJ7.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,15 +1,3 @@
1
- import {
2
- errorHandlerMiddleware
3
- } from "./chunk-4Y5MRUMX.js";
4
- import {
5
- initRequestMiddleware
6
- } from "./chunk-VC2E6KYQ.js";
7
- import {
8
- MiddlewareChain
9
- } from "./chunk-WXOWI7BJ.js";
10
- import {
11
- rateLimitMiddleware
12
- } from "./chunk-TRGFXIEF.js";
13
1
  import {
14
2
  responseLoggerMiddleware
15
3
  } from "./chunk-LCYDMYZS.js";
@@ -20,10 +8,22 @@ import {
20
8
  adminMiddleware,
21
9
  authMiddleware,
22
10
  optionalAuthMiddleware
23
- } from "./chunk-CNXK3SLK.js";
11
+ } from "./chunk-MJOXTFIC.js";
24
12
  import {
25
13
  corsMiddleware
26
14
  } from "./chunk-37VGD4VX.js";
15
+ import {
16
+ errorHandlerMiddleware
17
+ } from "./chunk-4Y5MRUMX.js";
18
+ import {
19
+ initRequestMiddleware
20
+ } from "./chunk-VC2E6KYQ.js";
21
+ import {
22
+ MiddlewareChain
23
+ } from "./chunk-WXOWI7BJ.js";
24
+ import {
25
+ rateLimitMiddleware
26
+ } from "./chunk-TRGFXIEF.js";
27
27
 
28
28
  // src/next/middleware/wrappers.ts
29
29
  function withPublicApi(handler) {
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-LWHLB2Y6.js";
4
4
  import {
5
5
  getTokenDeliveryStrategy
6
- } from "./chunk-NERL6VYQ.js";
6
+ } from "./chunk-HNFYO5XV.js";
7
7
  import {
8
8
  JWT_DEFAULTS
9
9
  } from "./chunk-7YWUKMZD.js";
@@ -0,0 +1,29 @@
1
+ // src/core/api-key/validate.ts
2
+ function validateApiKeyRecord(record, opts) {
3
+ var _a, _b;
4
+ if (!record) return { valid: false, error: "INVALID_API_KEY", message: "Invalid API key" };
5
+ if (!record.isActive) return { valid: false, error: "INACTIVE_API_KEY", message: "API key is inactive" };
6
+ if (record.expiresAt && record.expiresAt < /* @__PURE__ */ new Date())
7
+ return { valid: false, error: "EXPIRED_API_KEY", message: "API key has expired" };
8
+ if (!record.user.isActive) return { valid: false, error: "INACTIVE_USER", message: "User account is inactive" };
9
+ if (((_a = opts.freemiumPlans) != null ? _a : []).includes(record.user.plan))
10
+ return { valid: false, error: "PLAN_RESTRICTED", message: "API access is not available for this plan. Please upgrade." };
11
+ return {
12
+ valid: true,
13
+ apiKey: {
14
+ id: record.id,
15
+ userId: record.user.id,
16
+ permissions: record.permissions,
17
+ rateLimit: record.rateLimit,
18
+ endpointLimits: (_b = record.endpointLimits) != null ? _b : void 0,
19
+ ipWhitelist: record.ipWhitelist,
20
+ environment: record.environment,
21
+ expiresAt: record.expiresAt
22
+ },
23
+ user: { id: record.user.id, email: record.user.email, plan: record.user.plan }
24
+ };
25
+ }
26
+
27
+ export {
28
+ validateApiKeyRecord
29
+ };
File without changes
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-MTZXWVW3.js";
4
4
  import {
5
5
  OAuthManager
6
- } from "./chunk-V3GEYUBG.js";
6
+ } from "./chunk-UQ3Z3ZAF.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-BOABYFJ7.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,6 +1,6 @@
1
1
  import {
2
2
  getAuthConfig
3
- } from "./chunk-N3TCQ5BF.js";
3
+ } from "./chunk-TQMQ5XXG.js";
4
4
  import {
5
5
  JWT_DEFAULTS
6
6
  } from "./chunk-7YWUKMZD.js";
@@ -8,6 +8,11 @@ import {
8
8
  durationToSeconds
9
9
  } from "./chunk-OVOBSYR4.js";
10
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
 
@@ -1,9 +1,13 @@
1
1
  import {
2
2
  setTokenCookies
3
- } from "./chunk-BOABYFJ7.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,6 +1,6 @@
1
1
  import {
2
2
  OAuthManager
3
- } from "./chunk-V3GEYUBG.js";
3
+ } from "./chunk-UQ3Z3ZAF.js";
4
4
  import {
5
5
  generateOAuthState,
6
6
  setOAuthStateCookie
@@ -0,0 +1,21 @@
1
+ // src/next/oapi/openapi-spec.ts
2
+ function buildOpenApiSpec(input) {
3
+ var _a, _b;
4
+ return {
5
+ openapi: "3.0.3",
6
+ info: input.info,
7
+ servers: (_a = input.servers) != null ? _a : [],
8
+ paths: input.paths,
9
+ components: {
10
+ securitySchemes: {
11
+ ApiKeyAuth: { type: "apiKey", in: "header", name: "X-API-Key" }
12
+ },
13
+ schemas: (_b = input.schemas) != null ? _b : {}
14
+ },
15
+ security: [{ ApiKeyAuth: [] }]
16
+ };
17
+ }
18
+
19
+ export {
20
+ buildOpenApiSpec
21
+ };
@@ -12,10 +12,10 @@ import {
12
12
  } from "./chunk-LWHLB2Y6.js";
13
13
  import {
14
14
  getTokenDeliveryStrategy
15
- } from "./chunk-NERL6VYQ.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";
File without changes
@@ -0,0 +1,35 @@
1
+ // src/core/api-key/ip-whitelist.ts
2
+ function isIpInCidr(ip, cidr) {
3
+ try {
4
+ const [range, bits] = cidr.split("/");
5
+ const mask = parseInt(bits, 10);
6
+ if (Number.isNaN(mask) || mask < 0 || mask > 32) return false;
7
+ const ipParts = ip.split(".").map(Number);
8
+ const rangeParts = range.split(".").map(Number);
9
+ if (ipParts.length !== 4 || rangeParts.length !== 4) return false;
10
+ if (![...ipParts, ...rangeParts].every((o) => Number.isInteger(o) && o >= 0 && o <= 255)) return false;
11
+ const ipNum = ipParts[0] << 24 | ipParts[1] << 16 | ipParts[2] << 8 | ipParts[3];
12
+ const rangeNum = rangeParts[0] << 24 | rangeParts[1] << 16 | rangeParts[2] << 8 | rangeParts[3];
13
+ const maskNum = mask === 0 ? 0 : ~0 << 32 - mask >>> 0;
14
+ return (ipNum & maskNum) === (rangeNum & maskNum);
15
+ } catch (e) {
16
+ return false;
17
+ }
18
+ }
19
+ function isIpAllowed(clientIp, whitelist) {
20
+ if (!whitelist || whitelist.length === 0) return true;
21
+ const normalizedIp = clientIp.replace(/^::ffff:/, "");
22
+ for (const allowed of whitelist) {
23
+ if (allowed.includes("/")) {
24
+ if (isIpInCidr(normalizedIp, allowed)) return true;
25
+ } else if (normalizedIp === allowed.replace(/^::ffff:/, "")) {
26
+ return true;
27
+ }
28
+ }
29
+ return false;
30
+ }
31
+
32
+ export {
33
+ isIpInCidr,
34
+ isIpAllowed
35
+ };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  getCacheManager,
3
3
  getEffectiveCacheBackend
4
- } from "./chunk-BICSVLN7.js";
4
+ } from "./chunk-NAFMJT62.js";
5
5
  import {
6
6
  logger
7
7
  } from "./chunk-QAIN3WNN.js";
@@ -0,0 +1,162 @@
1
+ import {
2
+ validateApiKeyRecord
3
+ } from "./chunk-BTNM5YSU.js";
4
+ import {
5
+ generateRawKey,
6
+ hashKey,
7
+ keyPreview
8
+ } from "./chunk-ZZTBIA57.js";
9
+ import {
10
+ __spreadProps,
11
+ __spreadValues
12
+ } from "./chunk-N3ETBM74.js";
13
+
14
+ // src/core/api-key/api-key.service.ts
15
+ var ApiKeyService = class {
16
+ constructor(deps) {
17
+ this.deps = deps;
18
+ }
19
+ prefix(env) {
20
+ return env === "production" ? this.deps.env.prefixProd : this.deps.env.prefixDev;
21
+ }
22
+ toInfo(r) {
23
+ var _a, _b, _c, _d, _e;
24
+ return {
25
+ id: r.id,
26
+ name: r.name,
27
+ description: (_a = r.description) != null ? _a : void 0,
28
+ keyPreview: keyPreview(r.key),
29
+ permissions: r.permissions,
30
+ environment: r.environment,
31
+ rateLimit: r.rateLimit,
32
+ endpointLimits: (_b = r.endpointLimits) != null ? _b : void 0,
33
+ ipWhitelist: r.ipWhitelist,
34
+ lastUsedAt: (_c = r.lastUsedAt) != null ? _c : void 0,
35
+ lastUsedIp: (_d = r.lastUsedIp) != null ? _d : void 0,
36
+ usageCount: r.usageCount,
37
+ isActive: r.isActive,
38
+ expiresAt: (_e = r.expiresAt) != null ? _e : void 0,
39
+ createdAt: r.createdAt,
40
+ updatedAt: r.updatedAt
41
+ };
42
+ }
43
+ async requireOwned(id, userId, isAdmin) {
44
+ 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");
47
+ return rec;
48
+ }
49
+ async generateApiKey(userId, options, plan) {
50
+ var _a, _b, _c, _d, _e, _f, _g;
51
+ 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
+ }
55
+ const maxKeys = await planConfig.getApiKeyLimit(plan);
56
+ const active = await repo.countActive(userId);
57
+ if (active >= maxKeys) throw new Error(`API key limit reached. Max ${maxKeys} keys.`);
58
+ const rawKey = generateRawKey(this.prefix(options.environment));
59
+ const planRate = await planConfig.getRateLimit(plan);
60
+ const rateLimit = options.customRateLimit ? Math.min(options.customRateLimit, planRate) : planRate;
61
+ const expiresAt = (_a = options.expiresAt) != null ? _a : new Date(Date.now() + env.defaultExpiryDays * 864e5);
62
+ const created = await repo.create({
63
+ userId,
64
+ key: hashKey(rawKey),
65
+ name: options.name,
66
+ description: (_b = options.description) != null ? _b : null,
67
+ permissions: options.permissions,
68
+ rateLimit,
69
+ endpointLimits: (_c = options.endpointLimits) != null ? _c : null,
70
+ environment: options.environment,
71
+ ipWhitelist: (_d = options.ipWhitelist) != null ? _d : [],
72
+ expiresAt
73
+ });
74
+ return {
75
+ id: created.id,
76
+ key: rawKey,
77
+ name: created.name,
78
+ description: (_e = created.description) != null ? _e : void 0,
79
+ permissions: created.permissions,
80
+ environment: created.environment,
81
+ rateLimit: created.rateLimit,
82
+ endpointLimits: (_f = created.endpointLimits) != null ? _f : void 0,
83
+ expiresAt: (_g = created.expiresAt) != null ? _g : void 0,
84
+ createdAt: created.createdAt
85
+ };
86
+ }
87
+ async validateApiKey(rawKey) {
88
+ var _a;
89
+ const { repo, cache, env } = this.deps;
90
+ const keyHash = hashKey(rawKey);
91
+ const cached = await cache.getValidation(keyHash);
92
+ if (cached) {
93
+ const exp = (_a = cached.apiKey) == null ? void 0 : _a.expiresAt;
94
+ if (!(exp && new Date(exp) < /* @__PURE__ */ new Date())) return cached;
95
+ await cache.invalidate(keyHash);
96
+ }
97
+ const record = await repo.findByHash(keyHash);
98
+ const result = validateApiKeyRecord(record, { freemiumPlans: env.restrictedPlans });
99
+ if (result.valid) await cache.setValidation(keyHash, result);
100
+ return result;
101
+ }
102
+ async getApiKey(id, userId, isAdmin = false) {
103
+ const rec = await this.requireOwned(id, userId, isAdmin);
104
+ return this.toInfo(rec);
105
+ }
106
+ async getApiKeys(filters, requesterId, isAdmin = false) {
107
+ var _a, _b;
108
+ const scoped = isAdmin ? filters : __spreadProps(__spreadValues({}, filters), { userId: requesterId });
109
+ const page = (_a = scoped.page) != null ? _a : 1, pageSize = (_b = scoped.pageSize) != null ? _b : 10;
110
+ const { items, total } = await this.deps.repo.findMany(__spreadProps(__spreadValues({}, scoped), { page, pageSize }));
111
+ return { keys: items.map((r) => this.toInfo(r)), total, page, pageSize, hasMore: total > page * pageSize };
112
+ }
113
+ async updateApiKey(id, userId, data, isAdmin = false) {
114
+ const rec = await this.requireOwned(id, userId, isAdmin);
115
+ const updated = await this.deps.repo.update(id, {
116
+ name: data.name,
117
+ description: data.description,
118
+ isActive: data.isActive,
119
+ permissions: data.permissions,
120
+ ipWhitelist: data.ipWhitelist,
121
+ rateLimit: data.customRateLimit,
122
+ endpointLimits: data.endpointLimits
123
+ });
124
+ await this.deps.cache.invalidate(rec.key);
125
+ return this.toInfo(updated);
126
+ }
127
+ async deleteApiKey(id, userId, isAdmin = false) {
128
+ const rec = await this.requireOwned(id, userId, isAdmin);
129
+ await this.deps.repo.delete(id);
130
+ await this.deps.cache.invalidate(rec.key);
131
+ }
132
+ async trackUsage(apiKeyId, ip) {
133
+ try {
134
+ await this.deps.repo.incrementUsage(apiKeyId, ip);
135
+ } catch (e) {
136
+ }
137
+ }
138
+ async regenerateApiKey(userId, apiKeyId, plan, options = {}) {
139
+ var _a, _b, _c, _d, _e;
140
+ const old = await this.requireOwned(apiKeyId, userId, false);
141
+ if (!options.keepOldKeyActive) {
142
+ 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.`);
144
+ await this.deps.repo.deactivate(apiKeyId);
145
+ await this.deps.cache.invalidate(old.key);
146
+ }
147
+ return this.generateApiKey(userId, {
148
+ name: (_a = options.name) != null ? _a : old.name,
149
+ description: (_c = (_b = options.description) != null ? _b : old.description) != null ? _c : void 0,
150
+ permissions: old.permissions,
151
+ environment: old.environment,
152
+ customRateLimit: old.rateLimit,
153
+ ipWhitelist: old.ipWhitelist,
154
+ endpointLimits: (_d = old.endpointLimits) != null ? _d : void 0,
155
+ expiresAt: (_e = old.expiresAt) != null ? _e : void 0
156
+ }, plan);
157
+ }
158
+ };
159
+
160
+ export {
161
+ ApiKeyService
162
+ };
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-5GWGARXI.js";
7
7
  import {
8
8
  getTokenDeliveryStrategy
9
- } from "./chunk-NERL6VYQ.js";
9
+ } from "./chunk-HNFYO5XV.js";
10
10
 
11
11
  // src/next/auth-handlers/refresh.handler.ts
12
12
  import { NextResponse } from "next/server";
File without changes
@@ -1,6 +1,9 @@
1
1
  import {
2
2
  JWT_DEFAULTS
3
3
  } from "./chunk-7YWUKMZD.js";
4
+ import {
5
+ durationToSeconds
6
+ } from "./chunk-OVOBSYR4.js";
4
7
  import {
5
8
  configWarn
6
9
  } from "./chunk-6J2EJVND.js";
@@ -9,6 +12,7 @@ import {
9
12
  } from "./chunk-F3R3UYBF.js";
10
13
 
11
14
  // src/core/auth/config.ts
15
+ var LONG_ACCESS_WARN_THRESHOLD_SEC = 24 * 3600;
12
16
  function initializeAuth(config) {
13
17
  var _a, _b, _c, _d, _e;
14
18
  (_a = globalThis.__withwiz_config) != null ? _a : globalThis.__withwiz_config = {};
@@ -22,10 +26,21 @@ function initializeAuth(config) {
22
26
  if (!config.refreshTokenExpiry) {
23
27
  configWarn("Auth", `refreshTokenExpiry not provided, using default: ${JWT_DEFAULTS.DEFAULT_REFRESH_TOKEN_EXPIRES}`);
24
28
  }
29
+ const accessTokenExpiry = (_b = config.accessTokenExpiry) != null ? _b : JWT_DEFAULTS.DEFAULT_ACCESS_TOKEN_EXPIRES;
30
+ const refreshTokenExpiry = (_c = config.refreshTokenExpiry) != null ? _c : JWT_DEFAULTS.DEFAULT_REFRESH_TOKEN_EXPIRES;
31
+ try {
32
+ if (durationToSeconds(accessTokenExpiry) > LONG_ACCESS_WARN_THRESHOLD_SEC) {
33
+ configWarn(
34
+ "Auth",
35
+ `accessTokenExpiry(${accessTokenExpiry})\uAC00 24h\uB97C \uCD08\uACFC\uD569\uB2C8\uB2E4. refresh \uD1A0\uD070\uC774 \uC788\uB2E4\uBA74 \uC9E7\uC740 access(\uC608: 15m)\uB97C \uAD8C\uC7A5\uD569\uB2C8\uB2E4 \u2014 revoke/\uB9CC\uB8CC \uD6A8\uACFC \uADF9\uB300\uD654.`
36
+ );
37
+ }
38
+ } catch (e) {
39
+ }
25
40
  globalThis.__withwiz_config.auth = {
26
41
  jwtSecret: config.jwtSecret,
27
- accessTokenExpiry: (_b = config.accessTokenExpiry) != null ? _b : JWT_DEFAULTS.DEFAULT_ACCESS_TOKEN_EXPIRES,
28
- refreshTokenExpiry: (_c = config.refreshTokenExpiry) != null ? _c : JWT_DEFAULTS.DEFAULT_REFRESH_TOKEN_EXPIRES,
42
+ accessTokenExpiry,
43
+ refreshTokenExpiry,
29
44
  cookieSecure: (_d = config.cookieSecure) != null ? _d : false,
30
45
  tokenDelivery: (_e = config.tokenDelivery) != null ? _e : "hybrid"
31
46
  };
@@ -0,0 +1,38 @@
1
+ import {
2
+ isIpAllowed
3
+ } from "./chunk-NUHSUAXG.js";
4
+
5
+ // src/next/oapi/api-key-auth.ts
6
+ import { NextResponse } from "next/server";
7
+ var err = (code, status, message) => ({ response: NextResponse.json({ success: false, error: { code, message } }, { status }) });
8
+ function createApiKeyAuth(options) {
9
+ return async (req) => {
10
+ var _a;
11
+ try {
12
+ const apiKey = req.headers.get("x-api-key");
13
+ if (!apiKey) return err(40101, 401, "X-API-Key header is required");
14
+ const v = await options.service.validateApiKey(apiKey);
15
+ if (!v.valid || !v.apiKey || !v.user) return err(40101, 401, v.message || "Invalid API key");
16
+ const ip = options.extractClientIp(req.headers);
17
+ if (!isIpAllowed(ip, (_a = v.apiKey.ipWhitelist) != null ? _a : null)) return err(40301, 403, "Access denied: IP not in whitelist");
18
+ try {
19
+ const usage = await options.usage.canMakeApiCall(v.user.id, v.user.plan);
20
+ if (!usage.allowed) {
21
+ const t = usage.reason === "DAILY_LIMIT" ? "daily" : "monthly";
22
+ return err(40301, 403, `API ${t} usage limit exceeded. Please upgrade your plan or wait until reset.`);
23
+ }
24
+ } catch (e) {
25
+ }
26
+ options.service.trackUsage(v.apiKey.id, ip).catch(() => {
27
+ });
28
+ const role = await options.resolveRole(v.user.id);
29
+ return { user: { id: v.user.id, email: v.user.email, role, plan: v.user.plan, apiKeyId: v.apiKey.id } };
30
+ } catch (e) {
31
+ return err(50001, 500, "Internal authentication error");
32
+ }
33
+ };
34
+ }
35
+
36
+ export {
37
+ createApiKeyAuth
38
+ };
@@ -6,7 +6,7 @@ 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";
@@ -0,0 +1,24 @@
1
+ // src/next/oapi/helpers.ts
2
+ import { NextResponse } from "next/server";
3
+ function parsePaginationParams(sp) {
4
+ const page = Math.max(1, parseInt(sp.get("page") || "1", 10) || 1);
5
+ const pageSize = Math.min(100, Math.max(1, parseInt(sp.get("pageSize") || "10", 10) || 10));
6
+ return { page, pageSize };
7
+ }
8
+ function createPaginationMeta(total, page, pageSize) {
9
+ return { total, page, pageSize, hasMore: total > page * pageSize };
10
+ }
11
+ function parseSearchParams(sp) {
12
+ return { search: sp.get("search") || void 0 };
13
+ }
14
+ function requireParam(value, label) {
15
+ if (!value) return NextResponse.json({ success: false, error: { code: 40001, message: `${label} is required` } }, { status: 400 });
16
+ return null;
17
+ }
18
+
19
+ export {
20
+ parsePaginationParams,
21
+ createPaginationMeta,
22
+ parseSearchParams,
23
+ requireParam
24
+ };
@@ -0,0 +1,18 @@
1
+ // src/core/api-key/key-generator.ts
2
+ import crypto from "crypto";
3
+ function generateRawKey(prefix) {
4
+ return `${prefix}${crypto.randomBytes(32).toString("hex")}`;
5
+ }
6
+ function hashKey(rawKey) {
7
+ return crypto.createHash("sha256").update(rawKey).digest("hex");
8
+ }
9
+ function keyPreview(keyHash) {
10
+ if (keyHash.length < 14) return keyHash;
11
+ return `${keyHash.substring(0, 10)}...${keyHash.substring(keyHash.length - 4)}`;
12
+ }
13
+
14
+ export {
15
+ generateRawKey,
16
+ hashKey,
17
+ keyPreview
18
+ };