@uniai-fe/uds-templates 0.4.8 → 0.4.10
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/package.json
CHANGED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path d="M12 15C12.5523 15 13 15.4477 13 16C13 16.5523 12.5523 17 12 17C11.4477 17 11 16.5523 11 16C11 15.4477 11.4477 15 12 15Z" fill="#313235"/>
|
|
3
|
+
<path d="M11.998 7.2002C13.2476 7.2002 14.3376 8.05045 14.6406 9.2627C14.7662 9.76506 14.7458 10.2929 14.582 10.7842L14.5293 10.9414C14.2978 11.6359 13.8415 12.2335 13.2324 12.6396L12.7998 12.9277V13.5C12.7998 13.9418 12.4418 14.2998 12 14.2998C11.5582 14.2998 11.2002 13.9418 11.2002 13.5V12.5889C11.2003 12.2658 11.362 11.9644 11.6309 11.7852L12.3447 11.3086C12.6578 11.0998 12.8927 10.7926 13.0117 10.4355L13.0635 10.2783C13.131 10.0757 13.1397 9.85761 13.0879 9.65039C12.9628 9.1506 12.5133 8.79981 11.998 8.7998H11.9404C11.4248 8.7998 10.9668 9.12998 10.8037 9.61914L10.7588 9.75293C10.6191 10.1721 10.1662 10.3985 9.74707 10.2588C9.32792 10.1191 9.10149 9.66622 9.24121 9.24707L9.28613 9.11328C9.66698 7.97078 10.7361 7.2002 11.9404 7.2002H11.998Z" fill="#313235"/>
|
|
4
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 2.2002C17.4124 2.2002 21.7998 6.58761 21.7998 12C21.7998 17.4124 17.4124 21.7998 12 21.7998C10.1462 21.7998 8.41115 21.2835 6.93164 20.3877L4.3125 21.3643C3.26584 21.7545 2.2468 20.7301 2.64258 19.6855L3.625 17.0898C2.72126 15.6057 2.2002 13.8627 2.2002 12C2.2002 6.58761 6.58761 2.2002 12 2.2002ZM12 3.7998C7.47126 3.7998 3.7998 7.47126 3.7998 12C3.7998 13.6028 4.25928 15.0964 5.05273 16.3584C5.26539 16.6969 5.3223 17.1274 5.17188 17.5244L4.37207 19.6338L6.50488 18.8398L6.6543 18.7939C6.95446 18.7215 7.2638 18.7605 7.53125 18.8887L7.66211 18.96L7.90039 19.1035C9.10585 19.8009 10.5053 20.2002 12 20.2002C16.5287 20.2002 20.2002 16.5287 20.2002 12C20.2002 7.47126 16.5287 3.7998 12 3.7998Z" fill="#313235"/>
|
|
5
|
+
</svg>
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
+
import { usePathname, useSearchParams } from "next/navigation";
|
|
3
4
|
import { useAtom, useAtomValue } from "jotai";
|
|
5
|
+
import { useMemo } from "react";
|
|
4
6
|
import type {
|
|
5
7
|
ServiceInquiryUserContext,
|
|
6
8
|
UseServiceInquiryUserContextReturn,
|
|
@@ -20,9 +22,22 @@ import {
|
|
|
20
22
|
export function useServiceInquiryUserContext(): UseServiceInquiryUserContextReturn {
|
|
21
23
|
/** 1) form init — request context snapshot과 trigger 추가 context를 atom 기반으로 읽는다. */
|
|
22
24
|
const requestContext = useAtomValue(serviceInquiryRequestContextAtom);
|
|
25
|
+
const pathname = usePathname();
|
|
26
|
+
const searchParams = useSearchParams();
|
|
23
27
|
const [additionalUserContext, setAdditionalUserContext] = useAtom(
|
|
24
28
|
serviceInquiryAdditionalUserContextAtom,
|
|
25
29
|
);
|
|
30
|
+
const resolvedRequestContext = useMemo(
|
|
31
|
+
() => ({
|
|
32
|
+
...requestContext,
|
|
33
|
+
// 변경 설명: route 이동 후에도 문의 submit 시점의 현재 URL이 page_path로 반영되도록 route 변화에 맞춰 snapshot을 새로 만든다.
|
|
34
|
+
page_path:
|
|
35
|
+
typeof window === "undefined"
|
|
36
|
+
? requestContext.page_path
|
|
37
|
+
: window.location.href,
|
|
38
|
+
}),
|
|
39
|
+
[pathname, requestContext, searchParams],
|
|
40
|
+
);
|
|
26
41
|
|
|
27
42
|
/** 2) submit/액션 — trigger별 추가 context를 append/reset 할 수 있게 연다. */
|
|
28
43
|
const setNextAdditionalUserContext: UseServiceInquiryUserContextReturn["setAdditionalUserContext"] =
|
|
@@ -48,7 +63,7 @@ export function useServiceInquiryUserContext(): UseServiceInquiryUserContextRetu
|
|
|
48
63
|
};
|
|
49
64
|
|
|
50
65
|
return {
|
|
51
|
-
requestContext,
|
|
66
|
+
requestContext: resolvedRequestContext,
|
|
52
67
|
additionalUserContext,
|
|
53
68
|
setAdditionalUserContext: setNextAdditionalUserContext,
|
|
54
69
|
appendUserContext,
|
|
@@ -8,6 +8,10 @@ import {
|
|
|
8
8
|
useServiceInquiryUserContext,
|
|
9
9
|
} from "./hooks";
|
|
10
10
|
import { createServiceInquiryModal } from "./utils/modal-option";
|
|
11
|
+
import {
|
|
12
|
+
getServiceInquiryDebugHeaders,
|
|
13
|
+
parseResponseWithServiceInquiryDebug,
|
|
14
|
+
} from "./utils/network-debug";
|
|
11
15
|
|
|
12
16
|
/**
|
|
13
17
|
* Service Inquiry; 문의 form + modal option 엔트리
|
|
@@ -21,6 +25,8 @@ export const ServiceInquiry = {
|
|
|
21
25
|
useProvideContext: useProvideServiceInquiryContext,
|
|
22
26
|
useUserContext: useServiceInquiryUserContext,
|
|
23
27
|
createModal: createServiceInquiryModal,
|
|
28
|
+
getNetworkDebugHeaders: getServiceInquiryDebugHeaders,
|
|
29
|
+
parseResponseDebug: parseResponseWithServiceInquiryDebug,
|
|
24
30
|
};
|
|
25
31
|
|
|
26
32
|
export {
|
|
@@ -31,5 +37,7 @@ export {
|
|
|
31
37
|
useProvideServiceInquiryContext,
|
|
32
38
|
useServiceInquiryUserContext,
|
|
33
39
|
createServiceInquiryModal,
|
|
40
|
+
getServiceInquiryDebugHeaders,
|
|
41
|
+
parseResponseWithServiceInquiryDebug,
|
|
34
42
|
};
|
|
35
43
|
export type * from "./types";
|
|
@@ -19,12 +19,44 @@ export interface ServiceInquiryProvidedContext {
|
|
|
19
19
|
userContext?: ServiceInquiryUserContext | null;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Service Inquiry Hook; 네트워크 오류 헤더 요약
|
|
24
|
+
* @property {string} [uniai_native_domain] 응답 헤더 `Uniai-Native-Domain`
|
|
25
|
+
* @property {string} [uniai_native_path] 응답 헤더 `Uniai-Native-Path`
|
|
26
|
+
* @property {string} [uniai_native_url] 응답 헤더 `Uniai-Native-URL`
|
|
27
|
+
* @property {string} [content_type] 응답 헤더 `content-type`
|
|
28
|
+
* @property {boolean} [has_authorization] 요청 헤더에 Authorization 존재 여부
|
|
29
|
+
*/
|
|
30
|
+
export interface ServiceInquiryNetworkErrorHeaders {
|
|
31
|
+
/**
|
|
32
|
+
* 응답 헤더 `Uniai-Native-Domain`
|
|
33
|
+
*/
|
|
34
|
+
uniai_native_domain?: string;
|
|
35
|
+
/**
|
|
36
|
+
* 응답 헤더 `Uniai-Native-Path`
|
|
37
|
+
*/
|
|
38
|
+
uniai_native_path?: string;
|
|
39
|
+
/**
|
|
40
|
+
* 응답 헤더 `Uniai-Native-URL`
|
|
41
|
+
*/
|
|
42
|
+
uniai_native_url?: string;
|
|
43
|
+
/**
|
|
44
|
+
* 응답 헤더 `content-type`
|
|
45
|
+
*/
|
|
46
|
+
content_type?: string;
|
|
47
|
+
/**
|
|
48
|
+
* 요청 헤더에 Authorization 존재 여부
|
|
49
|
+
*/
|
|
50
|
+
has_authorization?: boolean;
|
|
51
|
+
}
|
|
52
|
+
|
|
22
53
|
/**
|
|
23
54
|
* Service Inquiry Hook; 네트워크 오류 기록
|
|
24
55
|
* @property {string} [route] 요청 route 또는 endpoint
|
|
25
56
|
* @property {number} [code] HTTP status code
|
|
26
57
|
* @property {string} [state] 서비스 레이어 상태 문자열
|
|
27
58
|
* @property {string} [message] 사용자/운영 확인용 오류 메시지
|
|
59
|
+
* @property {ServiceInquiryNetworkErrorHeaders} [headers] 선택 수집된 request/response 헤더 정보
|
|
28
60
|
* @property {string} [timestamp] 오류 기록 시각
|
|
29
61
|
*/
|
|
30
62
|
export interface ServiceInquiryNetworkError {
|
|
@@ -44,6 +76,10 @@ export interface ServiceInquiryNetworkError {
|
|
|
44
76
|
* 사용자/운영 확인용 오류 메시지
|
|
45
77
|
*/
|
|
46
78
|
message?: string;
|
|
79
|
+
/**
|
|
80
|
+
* 선택 수집된 request/response 헤더 정보
|
|
81
|
+
*/
|
|
82
|
+
headers?: ServiceInquiryNetworkErrorHeaders;
|
|
47
83
|
/**
|
|
48
84
|
* 오류 기록 시각
|
|
49
85
|
*/
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import type { ServiceInquiryNetworkErrorHeaders } from "../types";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Service Inquiry Utility; Authorization 헤더 존재 여부 판별
|
|
5
|
+
* @param {HeadersInit} [requestHeaders] 요청 헤더
|
|
6
|
+
* @returns {boolean} Authorization 헤더 존재 여부
|
|
7
|
+
* @example
|
|
8
|
+
* const hasAuthorization = resolveServiceInquiryHasAuthorization({
|
|
9
|
+
* Authorization: "Bearer token",
|
|
10
|
+
* });
|
|
11
|
+
*/
|
|
12
|
+
const resolveServiceInquiryHasAuthorization = (
|
|
13
|
+
requestHeaders?: HeadersInit,
|
|
14
|
+
): boolean => {
|
|
15
|
+
if (!requestHeaders) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return new Headers(requestHeaders).has("Authorization");
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Service Inquiry Utility; 선택 디버그 헤더 추출
|
|
24
|
+
* @param {Headers} responseHeaders 응답 헤더
|
|
25
|
+
* @param {HeadersInit} [requestHeaders] 요청 헤더
|
|
26
|
+
* @returns {ServiceInquiryNetworkErrorHeaders | undefined} service-inquiry에 기록할 최소 헤더 정보
|
|
27
|
+
* @example
|
|
28
|
+
* const headers = pickServiceInquiryDebugHeaders(response.headers, {
|
|
29
|
+
* Authorization: "Bearer token",
|
|
30
|
+
* });
|
|
31
|
+
*/
|
|
32
|
+
const pickServiceInquiryDebugHeaders = (
|
|
33
|
+
responseHeaders: Headers,
|
|
34
|
+
requestHeaders?: HeadersInit,
|
|
35
|
+
): ServiceInquiryNetworkErrorHeaders | undefined => {
|
|
36
|
+
const headers: ServiceInquiryNetworkErrorHeaders = {
|
|
37
|
+
uniai_native_domain:
|
|
38
|
+
responseHeaders.get("Uniai-Native-Domain") ?? undefined,
|
|
39
|
+
uniai_native_path: responseHeaders.get("Uniai-Native-Path") ?? undefined,
|
|
40
|
+
uniai_native_url: responseHeaders.get("Uniai-Native-URL") ?? undefined,
|
|
41
|
+
content_type: responseHeaders.get("content-type") ?? undefined,
|
|
42
|
+
has_authorization: resolveServiceInquiryHasAuthorization(requestHeaders),
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
if (
|
|
46
|
+
!headers.uniai_native_domain &&
|
|
47
|
+
!headers.uniai_native_path &&
|
|
48
|
+
!headers.uniai_native_url &&
|
|
49
|
+
!headers.content_type &&
|
|
50
|
+
!headers.has_authorization
|
|
51
|
+
) {
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return headers;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Service Inquiry Utility; 응답 payload에 디버그 헤더 주입
|
|
60
|
+
* @param {Response} response fetch 응답 객체
|
|
61
|
+
* @param {HeadersInit} [requestHeaders] 요청 헤더
|
|
62
|
+
* @returns {Promise<ResponseData>} 선택 디버그 헤더가 포함된 응답 payload
|
|
63
|
+
* @example
|
|
64
|
+
* const payload = await parseResponseWithServiceInquiryDebug(response, {
|
|
65
|
+
* Authorization: "Bearer token",
|
|
66
|
+
* });
|
|
67
|
+
*/
|
|
68
|
+
export async function parseResponseWithServiceInquiryDebug<
|
|
69
|
+
ResponseData extends object,
|
|
70
|
+
>(response: Response, requestHeaders?: HeadersInit): Promise<ResponseData> {
|
|
71
|
+
const payload = (await response.json()) as ResponseData;
|
|
72
|
+
const headers = pickServiceInquiryDebugHeaders(
|
|
73
|
+
response.headers,
|
|
74
|
+
requestHeaders,
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
if (!headers) {
|
|
78
|
+
return payload;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// 변경 설명: service-inquiry 네트워크 기록에 필요한 최소 header 정보만 응답 payload에 숨겨서 전달한다.
|
|
82
|
+
return Object.assign(payload, {
|
|
83
|
+
_service_inquiry_debug: {
|
|
84
|
+
headers,
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Service Inquiry Utility; 응답 payload에서 디버그 헤더 읽기
|
|
91
|
+
* @param {unknown} response service 응답 payload
|
|
92
|
+
* @returns {ServiceInquiryNetworkErrorHeaders | undefined} 숨겨서 실은 디버그 헤더
|
|
93
|
+
* @example
|
|
94
|
+
* const headers = getServiceInquiryDebugHeaders(response);
|
|
95
|
+
*/
|
|
96
|
+
export function getServiceInquiryDebugHeaders(
|
|
97
|
+
response: unknown,
|
|
98
|
+
): ServiceInquiryNetworkErrorHeaders | undefined {
|
|
99
|
+
if (!response || typeof response !== "object") {
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const debugData = (
|
|
104
|
+
response as {
|
|
105
|
+
_service_inquiry_debug?: {
|
|
106
|
+
headers?: ServiceInquiryNetworkErrorHeaders;
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
)._service_inquiry_debug;
|
|
110
|
+
|
|
111
|
+
return debugData?.headers;
|
|
112
|
+
}
|