sales-frontend-server-side-helper 0.0.9 → 0.0.11

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 (51) hide show
  1. package/dist/api-route/index.cjs +150 -4
  2. package/dist/api-route/index.cjs.map +1 -1
  3. package/dist/api-route/index.d.cts +39 -1
  4. package/dist/api-route/index.d.ts +39 -1
  5. package/dist/api-route/index.js +149 -4
  6. package/dist/api-route/index.js.map +1 -1
  7. package/dist/config/index.cjs +16 -0
  8. package/dist/config/index.cjs.map +1 -0
  9. package/dist/config/index.d.cts +5 -0
  10. package/dist/config/index.d.ts +5 -0
  11. package/dist/config/index.js +14 -0
  12. package/dist/config/index.js.map +1 -0
  13. package/dist/middleware/index.cjs +247 -4
  14. package/dist/middleware/index.cjs.map +1 -1
  15. package/dist/middleware/index.d.cts +61 -2
  16. package/dist/middleware/index.d.ts +61 -2
  17. package/dist/middleware/index.js +241 -4
  18. package/dist/middleware/index.js.map +1 -1
  19. package/dist/server-side-helper.types-Cp3VfyqT.d.cts +52 -0
  20. package/dist/server-side-helper.types-Cp3VfyqT.d.ts +52 -0
  21. package/dist/utils/index.cjs +144 -0
  22. package/dist/utils/index.cjs.map +1 -0
  23. package/dist/utils/index.d.cts +60 -0
  24. package/dist/utils/index.d.ts +60 -0
  25. package/dist/utils/index.js +135 -0
  26. package/dist/utils/index.js.map +1 -0
  27. package/package.json +20 -10
  28. package/dist/api-route/something.cjs +0 -10
  29. package/dist/api-route/something.cjs.map +0 -1
  30. package/dist/api-route/something.d.cts +0 -3
  31. package/dist/api-route/something.d.ts +0 -3
  32. package/dist/api-route/something.js +0 -8
  33. package/dist/api-route/something.js.map +0 -1
  34. package/dist/common/cookie.cjs +0 -11
  35. package/dist/common/cookie.cjs.map +0 -1
  36. package/dist/common/cookie.d.cts +0 -9
  37. package/dist/common/cookie.d.ts +0 -9
  38. package/dist/common/cookie.js +0 -9
  39. package/dist/common/cookie.js.map +0 -1
  40. package/dist/common/index.cjs +0 -11
  41. package/dist/common/index.cjs.map +0 -1
  42. package/dist/common/index.d.cts +0 -2
  43. package/dist/common/index.d.ts +0 -2
  44. package/dist/common/index.js +0 -9
  45. package/dist/common/index.js.map +0 -1
  46. package/dist/middleware/sample.cjs +0 -13
  47. package/dist/middleware/sample.cjs.map +0 -1
  48. package/dist/middleware/sample.d.cts +0 -5
  49. package/dist/middleware/sample.d.ts +0 -5
  50. package/dist/middleware/sample.js +0 -11
  51. package/dist/middleware/sample.js.map +0 -1
@@ -1,10 +1,156 @@
1
1
  'use strict';
2
2
 
3
- // src/api-route/something.ts
4
- var getSomething = () => {
5
- console.log("something");
3
+ var server = require('next/server');
4
+ var salesFrontendUtils = require('sales-frontend-utils');
5
+
6
+ // src/api-route/refresh-token.ts
7
+
8
+ // src/config/cookie-config.ts
9
+ var COOKIE_DEFAULT_CONFIG = {
10
+ httpOnly: true,
11
+ maxAge: 60 * 60 * 24,
12
+ sameSite: "strict",
13
+ secure: true
14
+ };
15
+
16
+ // src/utils/cookie-utils.ts
17
+ var createResponseWithCookies = (response, request, cookieData) => {
18
+ const { hostname } = new URL(request.url);
19
+ if (cookieData?.tokens?.tokenType) {
20
+ response.cookies.set({
21
+ name: "tokenType",
22
+ value: cookieData.tokens.tokenType,
23
+ ...getDefaultCookieConfig(hostname)
24
+ });
25
+ }
26
+ if (cookieData?.tokens?.expiresIn) {
27
+ response.cookies.set({
28
+ name: "expiresIn",
29
+ value: String(cookieData.tokens.expiresIn),
30
+ ...getDefaultCookieConfig(hostname)
31
+ });
32
+ }
33
+ if (cookieData?.tokens?.accessToken) {
34
+ response.cookies.set({
35
+ name: "accessToken",
36
+ value: cookieData.tokens.accessToken,
37
+ ...getDefaultCookieConfig(hostname)
38
+ });
39
+ }
40
+ if (cookieData?.tokens?.refreshToken) {
41
+ response.cookies.set({
42
+ name: "refreshToken",
43
+ value: cookieData.tokens.refreshToken,
44
+ ...getDefaultCookieConfig(hostname)
45
+ });
46
+ }
47
+ if (cookieData?.formFactor) {
48
+ response.cookies.set({
49
+ name: "formFactor",
50
+ value: cookieData.formFactor,
51
+ ...getDefaultCookieConfig(hostname),
52
+ maxAge: 0
53
+ });
54
+ }
55
+ return response;
56
+ };
57
+ var getDefaultCookieConfig = (hostname) => {
58
+ const environment = salesFrontendUtils.getEnvironmentFromHostname(hostname);
59
+ if (environment === "local" || environment === "dev") {
60
+ return {
61
+ ...COOKIE_DEFAULT_CONFIG,
62
+ httpOnly: false,
63
+ secure: false
64
+ };
65
+ }
66
+ return COOKIE_DEFAULT_CONFIG;
67
+ };
68
+
69
+ // src/api-route/refresh-token.ts
70
+ var refreshTokens = async (request, refreshTokensOptions) => {
71
+ const refreshToken = request.cookies.get("refreshToken")?.value;
72
+ if (!refreshToken) {
73
+ return server.NextResponse.json(
74
+ {
75
+ isSuccess: false,
76
+ code: "REFRESH_TOKEN_MISSING",
77
+ message: "[ServerSideHelper-Api-Route] Refresh Token\uC774 \uC874\uC7AC\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.)",
78
+ data: null
79
+ },
80
+ { status: 401 }
81
+ );
82
+ }
83
+ try {
84
+ const tokenResponse = await fetch(
85
+ `https://${salesFrontendUtils.getApiHostNameFromEnvironment(new URL(request.url).hostname, refreshTokensOptions?.forceApiHostName)}/api/dat/v1/post/token/refresh`,
86
+ {
87
+ method: "POST",
88
+ headers: {
89
+ "Content-Type": "application/json",
90
+ ...Object.fromEntries(
91
+ Array.from(request.headers.entries()).filter(([key]) => key.toLowerCase().startsWith("x-channel"))
92
+ )
93
+ },
94
+ body: JSON.stringify({
95
+ refreshToken
96
+ })
97
+ }
98
+ );
99
+ const tokenData = await tokenResponse.json();
100
+ console.log("[ServerSideHelper-Api-Route] tokenData", tokenData);
101
+ if (!tokenResponse.ok || !tokenData.isSuccess === false) {
102
+ return server.NextResponse.json(
103
+ {
104
+ isSuccess: false,
105
+ code: tokenData.code || "TOKEN_REFRESH_FAILED",
106
+ message: `[ServerSideHelper-Api-Route] ${tokenData.message || "\uD1A0\uD070 \uAC31\uC2E0\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4."}`,
107
+ data: null
108
+ },
109
+ { status: 401 }
110
+ );
111
+ }
112
+ if (!tokenData.data?.accessToken || !tokenData.data?.refreshToken) {
113
+ throw new Error("[ServerSideHelper-Api-Route] Invalid token data structure");
114
+ }
115
+ const { accessToken: newAccessToken, refreshToken: newRefreshToken, expiresIn, tokenType } = tokenData.data;
116
+ const response = server.NextResponse.json(
117
+ {
118
+ isSuccess: true,
119
+ code: "",
120
+ message: "[ServerSideHelper-Api-Route] Token \uAC31\uC2E0 \uC131\uACF5",
121
+ data: { accessToken: newAccessToken, refreshToken: newRefreshToken, expiresIn, tokenType }
122
+ },
123
+ { status: 200 }
124
+ );
125
+ createResponseWithCookies(response, request, {
126
+ tokens: { accessToken: newAccessToken, refreshToken: newRefreshToken, expiresIn, tokenType }
127
+ });
128
+ return response;
129
+ } catch (error) {
130
+ console.error("Token refresh error:", error);
131
+ return server.NextResponse.json(
132
+ {
133
+ isSuccess: false,
134
+ code: "REFRESH_TOKEN_MISSING",
135
+ message: "[ServerSideHelper-Api-Route] \uD1A0\uD070 \uC7AC\uBC1C\uAE09 \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.",
136
+ data: null
137
+ },
138
+ { status: 401 }
139
+ );
140
+ }
141
+ };
142
+ var getServerTime = () => {
143
+ const now = /* @__PURE__ */ new Date();
144
+ const serverTime = now.getTime();
145
+ return server.NextResponse.json({
146
+ isSuccess: true,
147
+ code: "",
148
+ message: "Current server time fetched successfully",
149
+ data: { serverTime }
150
+ });
6
151
  };
7
152
 
8
- exports.getSomething = getSomething;
153
+ exports.getServerTime = getServerTime;
154
+ exports.refreshTokens = refreshTokens;
9
155
  //# sourceMappingURL=index.cjs.map
10
156
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/api-route/something.ts"],"names":[],"mappings":";;;AAAO,IAAM,eAAe,MAAM;AAChC,EAAA,OAAA,CAAQ,IAAI,WAAW,CAAA;AACzB","file":"index.cjs","sourcesContent":["export const getSomething = () => {\n console.log('something');\n};\n"]}
1
+ {"version":3,"sources":["../../src/config/cookie-config.ts","../../src/utils/cookie-utils.ts","../../src/api-route/refresh-token.ts","../../src/api-route/server-time.ts"],"names":["getEnvironmentFromHostname","NextResponse","getApiHostNameFromEnvironment"],"mappings":"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","file":"index.cjs","sourcesContent":["export const COOKIE_DEFAULT_CONFIG = {\n httpOnly: true,\n maxAge: 60 * 60 * 24,\n sameSite: 'strict' as const,\n secure: true\n};\n","import { NextRequest, NextResponse } from 'next/server';\n\nimport { getEnvironmentFromHostname } from 'sales-frontend-utils';\n\nimport { COOKIE_DEFAULT_CONFIG } from '../config/cookie-config';\nimport { CookieData } from '../server-side-helper.types';\n\n/**\n * 쿠키 생성\n * @param response\n * @param cookieData\n * @returns\n */\nexport const createResponseWithCookies = (\n response: NextResponse,\n request: NextRequest,\n cookieData?: CookieData\n): NextResponse => {\n const { hostname } = new URL(request.url);\n\n // 토큰타입\n if (cookieData?.tokens?.tokenType) {\n response.cookies.set({\n name: 'tokenType',\n value: cookieData.tokens.tokenType,\n ...getDefaultCookieConfig(hostname)\n });\n }\n\n // expiresIn\n if (cookieData?.tokens?.expiresIn) {\n response.cookies.set({\n name: 'expiresIn',\n value: String(cookieData.tokens.expiresIn),\n ...getDefaultCookieConfig(hostname)\n });\n }\n\n // 액세스 토큰 쿠키\n if (cookieData?.tokens?.accessToken) {\n response.cookies.set({\n name: 'accessToken',\n value: cookieData.tokens.accessToken,\n ...getDefaultCookieConfig(hostname)\n });\n }\n\n // 리프레시 토큰 쿠키\n if (cookieData?.tokens?.refreshToken) {\n response.cookies.set({\n name: 'refreshToken',\n value: cookieData.tokens.refreshToken,\n ...getDefaultCookieConfig(hostname)\n });\n }\n\n // FormFactor 쿠키\n if (cookieData?.formFactor) {\n response.cookies.set({\n name: 'formFactor',\n value: cookieData.formFactor,\n ...getDefaultCookieConfig(hostname),\n maxAge: 0\n });\n }\n\n return response;\n};\n\n/**\n * 환경에 따른 기본 쿠키 설정값 반환\n * @param hostname\n * @returns\n */\nconst getDefaultCookieConfig = (hostname: string) => {\n const environment = getEnvironmentFromHostname(hostname);\n\n if (environment === 'local' || environment === 'dev') {\n return {\n ...COOKIE_DEFAULT_CONFIG,\n httpOnly: false,\n secure: false\n };\n }\n\n return COOKIE_DEFAULT_CONFIG;\n};\n","import { NextRequest, NextResponse } from 'next/server';\n\nimport { getApiHostNameFromEnvironment } from 'sales-frontend-utils';\n\nimport { DspResponseDspTokenResponseDto, ApiErrorResponse, RefreshTokensOptions } from '../server-side-helper.types';\nimport { createResponseWithCookies } from '../utils/cookie-utils';\n\n/**\n * 리프레시 토큰을 사용하여 새로운 액세스 토큰과 리프레시 토큰을 쿠키로 발급 받습니다.\n * API Route에서 사용될 수 있습니다.\n * 권장경로: /app/internal/api/auth/refresh/route.ts\n * Method: POST\n * @returns 새로운 AT, RT 발급 후 새 AT 반환\n */\nexport const refreshTokens = async (request: NextRequest, refreshTokensOptions?: RefreshTokensOptions) => {\n const refreshToken = request.cookies.get('refreshToken')?.value;\n\n // 기본 밸리데이션\n if (!refreshToken) {\n return NextResponse.json(\n {\n isSuccess: false,\n code: 'REFRESH_TOKEN_MISSING',\n message: '[ServerSideHelper-Api-Route] Refresh Token이 존재하지 않습니다.)',\n data: null\n } as ApiErrorResponse,\n { status: 401 }\n );\n }\n\n try {\n // TODO: 실제 토큰 재발급 API 주소로 변경 필요\n const tokenResponse = await fetch(\n `https://${getApiHostNameFromEnvironment(new URL(request.url).hostname, refreshTokensOptions?.forceApiHostName)}/api/dat/v1/post/token/refresh`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...Object.fromEntries(\n Array.from(request.headers.entries()).filter(([key]) => key.toLowerCase().startsWith('x-channel'))\n )\n },\n body: JSON.stringify({\n refreshToken\n })\n }\n );\n\n const tokenData: DspResponseDspTokenResponseDto = await tokenResponse.json();\n console.log('[ServerSideHelper-Api-Route] tokenData', tokenData);\n\n if (!tokenResponse.ok || !tokenData.isSuccess === false) {\n return NextResponse.json(\n {\n isSuccess: false,\n code: tokenData.code || 'TOKEN_REFRESH_FAILED',\n message: `[ServerSideHelper-Api-Route] ${tokenData.message || '토큰 갱신에 실패했습니다.'}`,\n data: null\n } as ApiErrorResponse,\n { status: 401 }\n );\n }\n\n // 응답 유효성 체크\n if (!tokenData.data?.accessToken || !tokenData.data?.refreshToken) {\n throw new Error('[ServerSideHelper-Api-Route] Invalid token data structure');\n }\n\n const { accessToken: newAccessToken, refreshToken: newRefreshToken, expiresIn, tokenType } = tokenData.data;\n\n // 응답 생성\n const response = NextResponse.json(\n {\n isSuccess: true,\n code: '',\n message: '[ServerSideHelper-Api-Route] Token 갱신 성공',\n data: { accessToken: newAccessToken, refreshToken: newRefreshToken, expiresIn, tokenType }\n },\n { status: 200 }\n );\n\n // 새 토큰들을 쿠키에 저장\n createResponseWithCookies(response, request, {\n tokens: { accessToken: newAccessToken, refreshToken: newRefreshToken, expiresIn, tokenType }\n });\n\n return response;\n } catch (error) {\n console.error('Token refresh error:', error);\n\n return NextResponse.json(\n {\n isSuccess: false,\n code: 'REFRESH_TOKEN_MISSING',\n message: '[ServerSideHelper-Api-Route] 토큰 재발급 중 오류가 발생했습니다.',\n data: null\n } as ApiErrorResponse,\n { status: 401 }\n );\n }\n};\n","import { NextResponse } from 'next/server';\n\n/**\n * 서버의 현재 시간을 밀리초 단위로 반환합니다.\n * API Route에서 사용될 수 있습니다.\n * 권장경로: /app/internal/api/time/route.ts\n * Method: GET\n * @returns\n */\nexport const getServerTime = () => {\n const now = new Date();\n const serverTime = now.getTime();\n\n return NextResponse.json({\n isSuccess: true,\n code: '',\n message: 'Current server time fetched successfully',\n data: { serverTime }\n });\n};\n"]}
@@ -1 +1,39 @@
1
- export { getSomething } from './something.cjs';
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+ import { R as RefreshTokensOptions, A as ApiErrorResponse } from '../server-side-helper.types-Cp3VfyqT.cjs';
3
+
4
+ /**
5
+ * 리프레시 토큰을 사용하여 새로운 액세스 토큰과 리프레시 토큰을 쿠키로 발급 받습니다.
6
+ * API Route에서 사용될 수 있습니다.
7
+ * 권장경로: /app/internal/api/auth/refresh/route.ts
8
+ * Method: POST
9
+ * @returns 새로운 AT, RT 발급 후 새 AT 반환
10
+ */
11
+ declare const refreshTokens: (request: NextRequest, refreshTokensOptions?: RefreshTokensOptions) => Promise<NextResponse<ApiErrorResponse> | NextResponse<{
12
+ isSuccess: boolean;
13
+ code: string;
14
+ message: string;
15
+ data: {
16
+ accessToken: string;
17
+ refreshToken: string;
18
+ expiresIn: number;
19
+ tokenType: string;
20
+ };
21
+ }>>;
22
+
23
+ /**
24
+ * 서버의 현재 시간을 밀리초 단위로 반환합니다.
25
+ * API Route에서 사용될 수 있습니다.
26
+ * 권장경로: /app/internal/api/time/route.ts
27
+ * Method: GET
28
+ * @returns
29
+ */
30
+ declare const getServerTime: () => NextResponse<{
31
+ isSuccess: boolean;
32
+ code: string;
33
+ message: string;
34
+ data: {
35
+ serverTime: number;
36
+ };
37
+ }>;
38
+
39
+ export { getServerTime, refreshTokens };
@@ -1 +1,39 @@
1
- export { getSomething } from './something.js';
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+ import { R as RefreshTokensOptions, A as ApiErrorResponse } from '../server-side-helper.types-Cp3VfyqT.js';
3
+
4
+ /**
5
+ * 리프레시 토큰을 사용하여 새로운 액세스 토큰과 리프레시 토큰을 쿠키로 발급 받습니다.
6
+ * API Route에서 사용될 수 있습니다.
7
+ * 권장경로: /app/internal/api/auth/refresh/route.ts
8
+ * Method: POST
9
+ * @returns 새로운 AT, RT 발급 후 새 AT 반환
10
+ */
11
+ declare const refreshTokens: (request: NextRequest, refreshTokensOptions?: RefreshTokensOptions) => Promise<NextResponse<ApiErrorResponse> | NextResponse<{
12
+ isSuccess: boolean;
13
+ code: string;
14
+ message: string;
15
+ data: {
16
+ accessToken: string;
17
+ refreshToken: string;
18
+ expiresIn: number;
19
+ tokenType: string;
20
+ };
21
+ }>>;
22
+
23
+ /**
24
+ * 서버의 현재 시간을 밀리초 단위로 반환합니다.
25
+ * API Route에서 사용될 수 있습니다.
26
+ * 권장경로: /app/internal/api/time/route.ts
27
+ * Method: GET
28
+ * @returns
29
+ */
30
+ declare const getServerTime: () => NextResponse<{
31
+ isSuccess: boolean;
32
+ code: string;
33
+ message: string;
34
+ data: {
35
+ serverTime: number;
36
+ };
37
+ }>;
38
+
39
+ export { getServerTime, refreshTokens };
@@ -1,8 +1,153 @@
1
- // src/api-route/something.ts
2
- var getSomething = () => {
3
- console.log("something");
1
+ import { NextResponse } from 'next/server';
2
+ import { getApiHostNameFromEnvironment, getEnvironmentFromHostname } from 'sales-frontend-utils';
3
+
4
+ // src/api-route/refresh-token.ts
5
+
6
+ // src/config/cookie-config.ts
7
+ var COOKIE_DEFAULT_CONFIG = {
8
+ httpOnly: true,
9
+ maxAge: 60 * 60 * 24,
10
+ sameSite: "strict",
11
+ secure: true
12
+ };
13
+
14
+ // src/utils/cookie-utils.ts
15
+ var createResponseWithCookies = (response, request, cookieData) => {
16
+ const { hostname } = new URL(request.url);
17
+ if (cookieData?.tokens?.tokenType) {
18
+ response.cookies.set({
19
+ name: "tokenType",
20
+ value: cookieData.tokens.tokenType,
21
+ ...getDefaultCookieConfig(hostname)
22
+ });
23
+ }
24
+ if (cookieData?.tokens?.expiresIn) {
25
+ response.cookies.set({
26
+ name: "expiresIn",
27
+ value: String(cookieData.tokens.expiresIn),
28
+ ...getDefaultCookieConfig(hostname)
29
+ });
30
+ }
31
+ if (cookieData?.tokens?.accessToken) {
32
+ response.cookies.set({
33
+ name: "accessToken",
34
+ value: cookieData.tokens.accessToken,
35
+ ...getDefaultCookieConfig(hostname)
36
+ });
37
+ }
38
+ if (cookieData?.tokens?.refreshToken) {
39
+ response.cookies.set({
40
+ name: "refreshToken",
41
+ value: cookieData.tokens.refreshToken,
42
+ ...getDefaultCookieConfig(hostname)
43
+ });
44
+ }
45
+ if (cookieData?.formFactor) {
46
+ response.cookies.set({
47
+ name: "formFactor",
48
+ value: cookieData.formFactor,
49
+ ...getDefaultCookieConfig(hostname),
50
+ maxAge: 0
51
+ });
52
+ }
53
+ return response;
54
+ };
55
+ var getDefaultCookieConfig = (hostname) => {
56
+ const environment = getEnvironmentFromHostname(hostname);
57
+ if (environment === "local" || environment === "dev") {
58
+ return {
59
+ ...COOKIE_DEFAULT_CONFIG,
60
+ httpOnly: false,
61
+ secure: false
62
+ };
63
+ }
64
+ return COOKIE_DEFAULT_CONFIG;
65
+ };
66
+
67
+ // src/api-route/refresh-token.ts
68
+ var refreshTokens = async (request, refreshTokensOptions) => {
69
+ const refreshToken = request.cookies.get("refreshToken")?.value;
70
+ if (!refreshToken) {
71
+ return NextResponse.json(
72
+ {
73
+ isSuccess: false,
74
+ code: "REFRESH_TOKEN_MISSING",
75
+ message: "[ServerSideHelper-Api-Route] Refresh Token\uC774 \uC874\uC7AC\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.)",
76
+ data: null
77
+ },
78
+ { status: 401 }
79
+ );
80
+ }
81
+ try {
82
+ const tokenResponse = await fetch(
83
+ `https://${getApiHostNameFromEnvironment(new URL(request.url).hostname, refreshTokensOptions?.forceApiHostName)}/api/dat/v1/post/token/refresh`,
84
+ {
85
+ method: "POST",
86
+ headers: {
87
+ "Content-Type": "application/json",
88
+ ...Object.fromEntries(
89
+ Array.from(request.headers.entries()).filter(([key]) => key.toLowerCase().startsWith("x-channel"))
90
+ )
91
+ },
92
+ body: JSON.stringify({
93
+ refreshToken
94
+ })
95
+ }
96
+ );
97
+ const tokenData = await tokenResponse.json();
98
+ console.log("[ServerSideHelper-Api-Route] tokenData", tokenData);
99
+ if (!tokenResponse.ok || !tokenData.isSuccess === false) {
100
+ return NextResponse.json(
101
+ {
102
+ isSuccess: false,
103
+ code: tokenData.code || "TOKEN_REFRESH_FAILED",
104
+ message: `[ServerSideHelper-Api-Route] ${tokenData.message || "\uD1A0\uD070 \uAC31\uC2E0\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4."}`,
105
+ data: null
106
+ },
107
+ { status: 401 }
108
+ );
109
+ }
110
+ if (!tokenData.data?.accessToken || !tokenData.data?.refreshToken) {
111
+ throw new Error("[ServerSideHelper-Api-Route] Invalid token data structure");
112
+ }
113
+ const { accessToken: newAccessToken, refreshToken: newRefreshToken, expiresIn, tokenType } = tokenData.data;
114
+ const response = NextResponse.json(
115
+ {
116
+ isSuccess: true,
117
+ code: "",
118
+ message: "[ServerSideHelper-Api-Route] Token \uAC31\uC2E0 \uC131\uACF5",
119
+ data: { accessToken: newAccessToken, refreshToken: newRefreshToken, expiresIn, tokenType }
120
+ },
121
+ { status: 200 }
122
+ );
123
+ createResponseWithCookies(response, request, {
124
+ tokens: { accessToken: newAccessToken, refreshToken: newRefreshToken, expiresIn, tokenType }
125
+ });
126
+ return response;
127
+ } catch (error) {
128
+ console.error("Token refresh error:", error);
129
+ return NextResponse.json(
130
+ {
131
+ isSuccess: false,
132
+ code: "REFRESH_TOKEN_MISSING",
133
+ message: "[ServerSideHelper-Api-Route] \uD1A0\uD070 \uC7AC\uBC1C\uAE09 \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.",
134
+ data: null
135
+ },
136
+ { status: 401 }
137
+ );
138
+ }
139
+ };
140
+ var getServerTime = () => {
141
+ const now = /* @__PURE__ */ new Date();
142
+ const serverTime = now.getTime();
143
+ return NextResponse.json({
144
+ isSuccess: true,
145
+ code: "",
146
+ message: "Current server time fetched successfully",
147
+ data: { serverTime }
148
+ });
4
149
  };
5
150
 
6
- export { getSomething };
151
+ export { getServerTime, refreshTokens };
7
152
  //# sourceMappingURL=index.js.map
8
153
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/api-route/something.ts"],"names":[],"mappings":";AAAO,IAAM,eAAe,MAAM;AAChC,EAAA,OAAA,CAAQ,IAAI,WAAW,CAAA;AACzB","file":"index.js","sourcesContent":["export const getSomething = () => {\n console.log('something');\n};\n"]}
1
+ {"version":3,"sources":["../../src/config/cookie-config.ts","../../src/utils/cookie-utils.ts","../../src/api-route/refresh-token.ts","../../src/api-route/server-time.ts"],"names":["NextResponse"],"mappings":"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","file":"index.js","sourcesContent":["export const COOKIE_DEFAULT_CONFIG = {\n httpOnly: true,\n maxAge: 60 * 60 * 24,\n sameSite: 'strict' as const,\n secure: true\n};\n","import { NextRequest, NextResponse } from 'next/server';\n\nimport { getEnvironmentFromHostname } from 'sales-frontend-utils';\n\nimport { COOKIE_DEFAULT_CONFIG } from '../config/cookie-config';\nimport { CookieData } from '../server-side-helper.types';\n\n/**\n * 쿠키 생성\n * @param response\n * @param cookieData\n * @returns\n */\nexport const createResponseWithCookies = (\n response: NextResponse,\n request: NextRequest,\n cookieData?: CookieData\n): NextResponse => {\n const { hostname } = new URL(request.url);\n\n // 토큰타입\n if (cookieData?.tokens?.tokenType) {\n response.cookies.set({\n name: 'tokenType',\n value: cookieData.tokens.tokenType,\n ...getDefaultCookieConfig(hostname)\n });\n }\n\n // expiresIn\n if (cookieData?.tokens?.expiresIn) {\n response.cookies.set({\n name: 'expiresIn',\n value: String(cookieData.tokens.expiresIn),\n ...getDefaultCookieConfig(hostname)\n });\n }\n\n // 액세스 토큰 쿠키\n if (cookieData?.tokens?.accessToken) {\n response.cookies.set({\n name: 'accessToken',\n value: cookieData.tokens.accessToken,\n ...getDefaultCookieConfig(hostname)\n });\n }\n\n // 리프레시 토큰 쿠키\n if (cookieData?.tokens?.refreshToken) {\n response.cookies.set({\n name: 'refreshToken',\n value: cookieData.tokens.refreshToken,\n ...getDefaultCookieConfig(hostname)\n });\n }\n\n // FormFactor 쿠키\n if (cookieData?.formFactor) {\n response.cookies.set({\n name: 'formFactor',\n value: cookieData.formFactor,\n ...getDefaultCookieConfig(hostname),\n maxAge: 0\n });\n }\n\n return response;\n};\n\n/**\n * 환경에 따른 기본 쿠키 설정값 반환\n * @param hostname\n * @returns\n */\nconst getDefaultCookieConfig = (hostname: string) => {\n const environment = getEnvironmentFromHostname(hostname);\n\n if (environment === 'local' || environment === 'dev') {\n return {\n ...COOKIE_DEFAULT_CONFIG,\n httpOnly: false,\n secure: false\n };\n }\n\n return COOKIE_DEFAULT_CONFIG;\n};\n","import { NextRequest, NextResponse } from 'next/server';\n\nimport { getApiHostNameFromEnvironment } from 'sales-frontend-utils';\n\nimport { DspResponseDspTokenResponseDto, ApiErrorResponse, RefreshTokensOptions } from '../server-side-helper.types';\nimport { createResponseWithCookies } from '../utils/cookie-utils';\n\n/**\n * 리프레시 토큰을 사용하여 새로운 액세스 토큰과 리프레시 토큰을 쿠키로 발급 받습니다.\n * API Route에서 사용될 수 있습니다.\n * 권장경로: /app/internal/api/auth/refresh/route.ts\n * Method: POST\n * @returns 새로운 AT, RT 발급 후 새 AT 반환\n */\nexport const refreshTokens = async (request: NextRequest, refreshTokensOptions?: RefreshTokensOptions) => {\n const refreshToken = request.cookies.get('refreshToken')?.value;\n\n // 기본 밸리데이션\n if (!refreshToken) {\n return NextResponse.json(\n {\n isSuccess: false,\n code: 'REFRESH_TOKEN_MISSING',\n message: '[ServerSideHelper-Api-Route] Refresh Token이 존재하지 않습니다.)',\n data: null\n } as ApiErrorResponse,\n { status: 401 }\n );\n }\n\n try {\n // TODO: 실제 토큰 재발급 API 주소로 변경 필요\n const tokenResponse = await fetch(\n `https://${getApiHostNameFromEnvironment(new URL(request.url).hostname, refreshTokensOptions?.forceApiHostName)}/api/dat/v1/post/token/refresh`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...Object.fromEntries(\n Array.from(request.headers.entries()).filter(([key]) => key.toLowerCase().startsWith('x-channel'))\n )\n },\n body: JSON.stringify({\n refreshToken\n })\n }\n );\n\n const tokenData: DspResponseDspTokenResponseDto = await tokenResponse.json();\n console.log('[ServerSideHelper-Api-Route] tokenData', tokenData);\n\n if (!tokenResponse.ok || !tokenData.isSuccess === false) {\n return NextResponse.json(\n {\n isSuccess: false,\n code: tokenData.code || 'TOKEN_REFRESH_FAILED',\n message: `[ServerSideHelper-Api-Route] ${tokenData.message || '토큰 갱신에 실패했습니다.'}`,\n data: null\n } as ApiErrorResponse,\n { status: 401 }\n );\n }\n\n // 응답 유효성 체크\n if (!tokenData.data?.accessToken || !tokenData.data?.refreshToken) {\n throw new Error('[ServerSideHelper-Api-Route] Invalid token data structure');\n }\n\n const { accessToken: newAccessToken, refreshToken: newRefreshToken, expiresIn, tokenType } = tokenData.data;\n\n // 응답 생성\n const response = NextResponse.json(\n {\n isSuccess: true,\n code: '',\n message: '[ServerSideHelper-Api-Route] Token 갱신 성공',\n data: { accessToken: newAccessToken, refreshToken: newRefreshToken, expiresIn, tokenType }\n },\n { status: 200 }\n );\n\n // 새 토큰들을 쿠키에 저장\n createResponseWithCookies(response, request, {\n tokens: { accessToken: newAccessToken, refreshToken: newRefreshToken, expiresIn, tokenType }\n });\n\n return response;\n } catch (error) {\n console.error('Token refresh error:', error);\n\n return NextResponse.json(\n {\n isSuccess: false,\n code: 'REFRESH_TOKEN_MISSING',\n message: '[ServerSideHelper-Api-Route] 토큰 재발급 중 오류가 발생했습니다.',\n data: null\n } as ApiErrorResponse,\n { status: 401 }\n );\n }\n};\n","import { NextResponse } from 'next/server';\n\n/**\n * 서버의 현재 시간을 밀리초 단위로 반환합니다.\n * API Route에서 사용될 수 있습니다.\n * 권장경로: /app/internal/api/time/route.ts\n * Method: GET\n * @returns\n */\nexport const getServerTime = () => {\n const now = new Date();\n const serverTime = now.getTime();\n\n return NextResponse.json({\n isSuccess: true,\n code: '',\n message: 'Current server time fetched successfully',\n data: { serverTime }\n });\n};\n"]}
@@ -0,0 +1,16 @@
1
+ 'use strict';
2
+
3
+ // src/config/middleware-config.ts
4
+ var middlewareConfig = {
5
+ matcher: [
6
+ "/",
7
+ "/api/:path*",
8
+ // API 경로
9
+ "/((?!_next/static|_next/image|favicon|.*\\.js|.*\\.css).*)"
10
+ // 정적 파일 제외
11
+ ]
12
+ };
13
+
14
+ exports.middlewareConfig = middlewareConfig;
15
+ //# sourceMappingURL=index.cjs.map
16
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/config/middleware-config.ts"],"names":[],"mappings":";;;AAAO,IAAM,gBAAmB,GAAA;AAAA,EAC9B,OAAS,EAAA;AAAA,IACP,GAAA;AAAA,IACA,aAAA;AAAA;AAAA,IACA;AAAA;AAAA;AAEJ","file":"index.cjs","sourcesContent":["export const middlewareConfig = {\n matcher: [\n '/',\n '/api/:path*', // API 경로\n '/((?!_next/static|_next/image|favicon|.*\\\\.js|.*\\\\.css).*)' // 정적 파일 제외\n ]\n};\n"]}
@@ -0,0 +1,5 @@
1
+ declare const middlewareConfig: {
2
+ matcher: string[];
3
+ };
4
+
5
+ export { middlewareConfig };
@@ -0,0 +1,5 @@
1
+ declare const middlewareConfig: {
2
+ matcher: string[];
3
+ };
4
+
5
+ export { middlewareConfig };
@@ -0,0 +1,14 @@
1
+ // src/config/middleware-config.ts
2
+ var middlewareConfig = {
3
+ matcher: [
4
+ "/",
5
+ "/api/:path*",
6
+ // API 경로
7
+ "/((?!_next/static|_next/image|favicon|.*\\.js|.*\\.css).*)"
8
+ // 정적 파일 제외
9
+ ]
10
+ };
11
+
12
+ export { middlewareConfig };
13
+ //# sourceMappingURL=index.js.map
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/config/middleware-config.ts"],"names":[],"mappings":";AAAO,IAAM,gBAAmB,GAAA;AAAA,EAC9B,OAAS,EAAA;AAAA,IACP,GAAA;AAAA,IACA,aAAA;AAAA;AAAA,IACA;AAAA;AAAA;AAEJ","file":"index.js","sourcesContent":["export const middlewareConfig = {\n matcher: [\n '/',\n '/api/:path*', // API 경로\n '/((?!_next/static|_next/image|favicon|.*\\\\.js|.*\\\\.css).*)' // 정적 파일 제외\n ]\n};\n"]}