@uniai-fe/util-functions 0.0.1
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 +64 -0
- package/src/form/checkbox.ts +41 -0
- package/src/functions/api.server.ts +114 -0
- package/src/functions/api.ts +515 -0
- package/src/functions/chart.ts +304 -0
- package/src/functions/convert.ts +229 -0
- package/src/functions/crypto.ts +44 -0
- package/src/functions/date.ts +386 -0
- package/src/functions/file.ts +57 -0
- package/src/functions/format.ts +318 -0
- package/src/functions/log.ts +9 -0
- package/src/functions/mask.ts +175 -0
- package/src/functions/reg-exp.ts +26 -0
- package/src/functions/route.ts +46 -0
- package/src/functions/sort.ts +71 -0
- package/src/functions/validation.ts +155 -0
- package/src/index.tsx +20 -0
- package/src/react/convert.tsx +129 -0
- package/src/react/match.tsx +41 -0
- package/src/style/size.ts +128 -0
|
@@ -0,0 +1,515 @@
|
|
|
1
|
+
import { dateFormat } from "./format";
|
|
2
|
+
import { convertObjectToSearchParams } from "./convert";
|
|
3
|
+
import type { CommonPostResponseType } from "@uniai/types";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* API; 인프라에 따른 도메인 추출
|
|
7
|
+
* @desc
|
|
8
|
+
* - 환경변수 값을 반환
|
|
9
|
+
* - PUBLIC_NEXT가 붙지 않았으므로 서버에서만 사용 가능
|
|
10
|
+
* - 별도의 도메인 지정시, URL을 그대로 입력
|
|
11
|
+
*/
|
|
12
|
+
const infraDomain = (infra: "ai" | "db" | "uniai" | string) => {
|
|
13
|
+
switch (infra) {
|
|
14
|
+
case "ai":
|
|
15
|
+
return process.env.AI_API_BASE;
|
|
16
|
+
case "db":
|
|
17
|
+
return process.env.DB_API_BASE;
|
|
18
|
+
case "uniai":
|
|
19
|
+
return process.env.UNIAI_API_BASE;
|
|
20
|
+
default:
|
|
21
|
+
return infra;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* API; 쿼리스트링 생성
|
|
27
|
+
* @util
|
|
28
|
+
* @param {unknown} [searchParams] 쿼리스트링으로 변환할 객체
|
|
29
|
+
* @return {string} 쿼리스트링
|
|
30
|
+
*/
|
|
31
|
+
export const getQueryString = (searchParams?: unknown): string =>
|
|
32
|
+
typeof searchParams !== "undefined" &&
|
|
33
|
+
convertObjectToSearchParams(searchParams).toString()
|
|
34
|
+
? `?${convertObjectToSearchParams(searchParams).toString()}`
|
|
35
|
+
: "";
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* API; POST/DELETE method option
|
|
39
|
+
*/
|
|
40
|
+
const getFetchOptions = ({
|
|
41
|
+
method,
|
|
42
|
+
headers,
|
|
43
|
+
body,
|
|
44
|
+
}: {
|
|
45
|
+
method: string;
|
|
46
|
+
} & Partial<{
|
|
47
|
+
headers: HeadersInit;
|
|
48
|
+
body: BodyInit | null;
|
|
49
|
+
}>): RequestInit => {
|
|
50
|
+
const option: RequestInit = { method };
|
|
51
|
+
// API fetch Headers
|
|
52
|
+
if (typeof headers !== "undefined") Object.assign(option, { headers });
|
|
53
|
+
// API fetch Body
|
|
54
|
+
if (typeof body !== "undefined") Object.assign(option, { body });
|
|
55
|
+
return option;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* API 요청 url 생성; GET 타입
|
|
60
|
+
* @util
|
|
61
|
+
* @param {object} props
|
|
62
|
+
* @param {"ai" | "db" | string} props.infra API 인프라
|
|
63
|
+
* @param {string} props.routeUrl Next.js /app/api 라우트 주소
|
|
64
|
+
* @param {string} props.queryUrl 백엔드 API url
|
|
65
|
+
* @param {URLSearchParams} [props.searchParams] 쿼리 스트링 추출
|
|
66
|
+
* @param {object} [props.log] 디버깅용 서버 로그 정보
|
|
67
|
+
* @param {boolean} [props.logDisabled] 로그 비활성화
|
|
68
|
+
* @return {string} GET API 요청 full url
|
|
69
|
+
*/
|
|
70
|
+
export const generateBackendQueryUrl_GET = ({
|
|
71
|
+
infra,
|
|
72
|
+
routeUrl,
|
|
73
|
+
queryUrl,
|
|
74
|
+
searchParams, // 가공이 완료된 파라미터
|
|
75
|
+
log,
|
|
76
|
+
logDisabled,
|
|
77
|
+
}: {
|
|
78
|
+
/**
|
|
79
|
+
* API 인프라
|
|
80
|
+
* - ai: AI API
|
|
81
|
+
* - db: DB API
|
|
82
|
+
* - uniai: UNIAI API
|
|
83
|
+
* - string: 직접 입력한 도메인
|
|
84
|
+
*/
|
|
85
|
+
infra: "ai" | "db" | "uniai" | string;
|
|
86
|
+
/**
|
|
87
|
+
* Next.js /app/api 라우트 주소
|
|
88
|
+
*/
|
|
89
|
+
routeUrl: string;
|
|
90
|
+
/**
|
|
91
|
+
* 백엔드 API url
|
|
92
|
+
*/
|
|
93
|
+
queryUrl: string;
|
|
94
|
+
} & Partial<{
|
|
95
|
+
/**
|
|
96
|
+
* 쿼리 스트링
|
|
97
|
+
* @desc
|
|
98
|
+
* - URLSearchParams 객체로 가공된 파라미터
|
|
99
|
+
*/
|
|
100
|
+
searchParams: URLSearchParams | object;
|
|
101
|
+
/**
|
|
102
|
+
* 디버깅용 서버 로그 정보
|
|
103
|
+
*/
|
|
104
|
+
log: object;
|
|
105
|
+
/**
|
|
106
|
+
* 로그 비활성화
|
|
107
|
+
* @default false
|
|
108
|
+
*/
|
|
109
|
+
logDisabled: boolean;
|
|
110
|
+
}>): string => {
|
|
111
|
+
// API 인프라에 따른 요청 도메인 추출
|
|
112
|
+
const DOMAIN = infraDomain(infra);
|
|
113
|
+
|
|
114
|
+
// url 생성
|
|
115
|
+
const url = `${DOMAIN}${queryUrl}${getQueryString(searchParams)}`;
|
|
116
|
+
|
|
117
|
+
// 서버 로그 출력
|
|
118
|
+
if (!logDisabled)
|
|
119
|
+
nextAPILog("get", routeUrl, url, {
|
|
120
|
+
...log,
|
|
121
|
+
...(searchParams ? searchParams : {}),
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
return url;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* API fetch 요청; POST/DELETE 타입
|
|
129
|
+
* @util
|
|
130
|
+
* @param {object} props
|
|
131
|
+
* @param {"ai" | "db" | string} props.infra API 인프라
|
|
132
|
+
* @param {"POST" | "DELETE"} props.method POST, DELETE
|
|
133
|
+
* @param {string} props.routeUrl Next.js /app/api 라우트 주소
|
|
134
|
+
* @param {string} props.queryUrl 백엔드 API url
|
|
135
|
+
* @param {HeadersInit} [props.headers] fetch Headers
|
|
136
|
+
* @param {BodyInit | null} [props.body] post/delete body (이대로 바로 전송됨)
|
|
137
|
+
* @param {object} [props.bodyData] body로 전송하기 위해 가공이 필요한 데이터 객체
|
|
138
|
+
* @param {object} [props.queryStringData] url에 쿼리스트링으로 요청하는 경우에 대한 데이터 객체
|
|
139
|
+
* @param {object} [props.log] 디버깅용 서버 로그 정보
|
|
140
|
+
* @param {boolean} [props.logDisabled] 로그 비활성화
|
|
141
|
+
* @param {boolean} [props.fetchDisabled] fetch 실행 비활성화
|
|
142
|
+
* @return {Promise<MutateAPICommonResponseType>} POST, DELETE 응답
|
|
143
|
+
*/
|
|
144
|
+
export const fetchBackendQuery = async <
|
|
145
|
+
FetchRequestType extends object,
|
|
146
|
+
FetchResponseType extends CommonPostResponseType,
|
|
147
|
+
>({
|
|
148
|
+
infra,
|
|
149
|
+
method,
|
|
150
|
+
routeUrl,
|
|
151
|
+
queryUrl,
|
|
152
|
+
headers,
|
|
153
|
+
body,
|
|
154
|
+
bodyOriginData,
|
|
155
|
+
queryStringData,
|
|
156
|
+
log,
|
|
157
|
+
logDisabled,
|
|
158
|
+
fetchDisabled,
|
|
159
|
+
}: {
|
|
160
|
+
/**
|
|
161
|
+
* API 인프라
|
|
162
|
+
* - ai: AI API
|
|
163
|
+
* - db: DB API
|
|
164
|
+
* - uniai: UNIAI API
|
|
165
|
+
* - string: 직접 입력한 도메인
|
|
166
|
+
*/
|
|
167
|
+
infra: "ai" | "db" | "uniai" | string;
|
|
168
|
+
/**
|
|
169
|
+
* 요청 방식
|
|
170
|
+
* POST, DELETE
|
|
171
|
+
*/
|
|
172
|
+
method: "POST" | "DELETE";
|
|
173
|
+
/**
|
|
174
|
+
* 프론트 API URL
|
|
175
|
+
*/
|
|
176
|
+
routeUrl: string;
|
|
177
|
+
/**
|
|
178
|
+
* 백엔드 API 요청 URL
|
|
179
|
+
*/
|
|
180
|
+
queryUrl: string;
|
|
181
|
+
} & Partial<{
|
|
182
|
+
/**
|
|
183
|
+
* fetch Headers
|
|
184
|
+
*/
|
|
185
|
+
headers: HeadersInit;
|
|
186
|
+
/**
|
|
187
|
+
* fetch Body
|
|
188
|
+
*/
|
|
189
|
+
body: BodyInit | null;
|
|
190
|
+
/**
|
|
191
|
+
* fetch Body 를 SearchParams 전환할 데이터
|
|
192
|
+
*/
|
|
193
|
+
bodyOriginData: FetchRequestType;
|
|
194
|
+
/**
|
|
195
|
+
* URL 쿼리 스트링
|
|
196
|
+
*/
|
|
197
|
+
queryStringData: FetchRequestType;
|
|
198
|
+
/**
|
|
199
|
+
* 디버그용 로그 객체
|
|
200
|
+
*/
|
|
201
|
+
log: object;
|
|
202
|
+
/**
|
|
203
|
+
* 로그 비활성화
|
|
204
|
+
*/
|
|
205
|
+
logDisabled: boolean;
|
|
206
|
+
/**
|
|
207
|
+
* fetch 비활성화
|
|
208
|
+
*/
|
|
209
|
+
fetchDisabled: boolean;
|
|
210
|
+
}>): Promise<FetchResponseType> => {
|
|
211
|
+
// API 인프라에 따른 요청 도메인 추출
|
|
212
|
+
const DOMAIN = infraDomain(infra);
|
|
213
|
+
|
|
214
|
+
// 쿼리 url 생성
|
|
215
|
+
const url = `${DOMAIN}${queryUrl}${getQueryString(queryStringData)}`;
|
|
216
|
+
|
|
217
|
+
// 에러 응답
|
|
218
|
+
const errRes: FetchResponseType = {
|
|
219
|
+
is_ok: false,
|
|
220
|
+
idx: "",
|
|
221
|
+
error: "",
|
|
222
|
+
} as FetchResponseType;
|
|
223
|
+
|
|
224
|
+
const bodyData = convertObjectToSearchParams(bodyOriginData);
|
|
225
|
+
|
|
226
|
+
// bodyOriginData가 undefined가 아닌데도, bodyOriginData의 데이터가 유효하지 않은 경우
|
|
227
|
+
if (typeof bodyOriginData !== "undefined" && bodyData.toString() === "") {
|
|
228
|
+
if (!logDisabled) {
|
|
229
|
+
nextAPILog(method.toLowerCase(), routeUrl, url, {
|
|
230
|
+
state: "ERROR (BODY - ORIGIN DATA)",
|
|
231
|
+
error: "데이터가 유효하지 않습니다.",
|
|
232
|
+
bodyOriginData,
|
|
233
|
+
...log,
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
errRes.error = "데이터가 유효하지 않습니다.";
|
|
237
|
+
return errRes;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// 쿼리 옵션 생성
|
|
241
|
+
const option: RequestInit = getFetchOptions({
|
|
242
|
+
method,
|
|
243
|
+
headers,
|
|
244
|
+
body,
|
|
245
|
+
});
|
|
246
|
+
if (!body && typeof bodyOriginData !== "undefined")
|
|
247
|
+
Object.assign(option, { body: bodyData });
|
|
248
|
+
|
|
249
|
+
// 로그 옵션
|
|
250
|
+
if (!logDisabled) {
|
|
251
|
+
// 쿼리 전 로그 출력
|
|
252
|
+
nextAPILog(method.toLowerCase(), routeUrl, url, {
|
|
253
|
+
state: "READY",
|
|
254
|
+
...option,
|
|
255
|
+
...log,
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// 디버깅을 위한 fetch 요청 제한
|
|
260
|
+
if (fetchDisabled) {
|
|
261
|
+
errRes.error = "API 요청제한 활성화됨.";
|
|
262
|
+
return errRes;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
try {
|
|
266
|
+
const res: FetchResponseType = await (await fetch(url, option)).json();
|
|
267
|
+
|
|
268
|
+
if (!logDisabled) {
|
|
269
|
+
// API 응답 성공 여부
|
|
270
|
+
const isSuccess =
|
|
271
|
+
"is_ok" in res && typeof res?.is_ok === "boolean" && res.is_ok === true;
|
|
272
|
+
|
|
273
|
+
nextAPILog(method.toLowerCase(), routeUrl, url, {
|
|
274
|
+
state: isSuccess ? "SUCCESS" : "FAIL",
|
|
275
|
+
...res,
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
return res;
|
|
280
|
+
} catch (error: unknown) {
|
|
281
|
+
errRes.error =
|
|
282
|
+
error instanceof Error
|
|
283
|
+
? error.message || "알 수 없는 오류가 발생하였습니다."
|
|
284
|
+
: String(error);
|
|
285
|
+
|
|
286
|
+
if (!logDisabled) {
|
|
287
|
+
nextAPILog(method.toLowerCase(), routeUrl, url, {
|
|
288
|
+
state: "ERROR (RESPONSE)",
|
|
289
|
+
error,
|
|
290
|
+
...log,
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return errRes;
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* 콘솔로그; Next.js API Route 디버깅용
|
|
300
|
+
* @util
|
|
301
|
+
* @param {string} method GET, POST, DELETE
|
|
302
|
+
* @param {string} routeUrl Next.js route API route URL
|
|
303
|
+
* @param {string} [queryUrl] DB API route URL
|
|
304
|
+
* @param {unknown[]} [messages] 로그 데이터
|
|
305
|
+
*/
|
|
306
|
+
export const nextAPILog = (
|
|
307
|
+
method: string,
|
|
308
|
+
routeUrl: string,
|
|
309
|
+
queryUrl?: string,
|
|
310
|
+
...messages: unknown[]
|
|
311
|
+
) => {
|
|
312
|
+
if (process.env.NODE_ENV === "production") return;
|
|
313
|
+
|
|
314
|
+
const DATE = dateFormat(new Date());
|
|
315
|
+
const TIME =
|
|
316
|
+
new Intl.DateTimeFormat("en-US", {
|
|
317
|
+
hour: "numeric",
|
|
318
|
+
minute: "numeric",
|
|
319
|
+
second: "numeric",
|
|
320
|
+
hour12: false,
|
|
321
|
+
}).format(new Date()) +
|
|
322
|
+
"." +
|
|
323
|
+
new Date().getMilliseconds();
|
|
324
|
+
|
|
325
|
+
const REQUEST_METHOD = method.split("-")[0]?.toUpperCase() || "-";
|
|
326
|
+
const RESPONSE_METHOD = method.split("-")[1]
|
|
327
|
+
? method.split("-")[1]?.toUpperCase() || "-"
|
|
328
|
+
: REQUEST_METHOD;
|
|
329
|
+
|
|
330
|
+
return console.log(
|
|
331
|
+
// `⚡️`,
|
|
332
|
+
`\n`,
|
|
333
|
+
`[Next Server API] ⏱ ${DATE} ( ${TIME} )`,
|
|
334
|
+
`\n λ [${REQUEST_METHOD}] FE route`,
|
|
335
|
+
`\n ${routeUrl}`,
|
|
336
|
+
...(queryUrl
|
|
337
|
+
? [`\n ═⏵ Ω [${RESPONSE_METHOD}] BE url`, `\n ${queryUrl}`, `\n`]
|
|
338
|
+
: []),
|
|
339
|
+
...(messages?.[0] ? [` ◇-`, ...messages] : []),
|
|
340
|
+
`\n`,
|
|
341
|
+
);
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* API; POST/DELETE method fetch
|
|
346
|
+
* @util
|
|
347
|
+
* @param {object} props
|
|
348
|
+
* @param {"ai" | "db" | string} props.infra API 인프라
|
|
349
|
+
* @param {"POST" | "DELETE"} props.method POST, DELETE
|
|
350
|
+
* @param {string} props.routeUrl Next.js /app/api 라우트 주소
|
|
351
|
+
* @param {string} props.queryUrl 백엔드 API url
|
|
352
|
+
* @param {HeadersInit} [props.headers] fetch Headers
|
|
353
|
+
* @param {BodyInit | null} [props.body] post/delete body (이대로 바로 전송됨)
|
|
354
|
+
* @param {object} [props.bodyData] body로 전송하기 위해 가공이 필요한 데이터 객체
|
|
355
|
+
* @param {object} [props.log] 디버깅용 서버 로그 정보
|
|
356
|
+
* @param {boolean} [props.logDisabled] 로그 비활성화
|
|
357
|
+
* @param {boolean} [props.fetchDisabled] fetch 실행 비활성화
|
|
358
|
+
* @param {object} [props.alternateResponse] fetch 실패 시 대체 응답
|
|
359
|
+
* @return {Promise<ResponseType>} POST, DELETE 응답
|
|
360
|
+
*/
|
|
361
|
+
export const fetchWithBody = async <
|
|
362
|
+
BodyDataType = object,
|
|
363
|
+
ResponseType extends object | Response = Response,
|
|
364
|
+
>({
|
|
365
|
+
infra,
|
|
366
|
+
method,
|
|
367
|
+
routeUrl,
|
|
368
|
+
queryUrl,
|
|
369
|
+
searchParams,
|
|
370
|
+
headers,
|
|
371
|
+
body,
|
|
372
|
+
bodyData,
|
|
373
|
+
isRawResponse,
|
|
374
|
+
alternateResponse,
|
|
375
|
+
debug,
|
|
376
|
+
disabled,
|
|
377
|
+
disabledLog,
|
|
378
|
+
}: {
|
|
379
|
+
/**
|
|
380
|
+
* API 인프라
|
|
381
|
+
* - ai: AI API
|
|
382
|
+
* - db: DB API
|
|
383
|
+
* - string: 직접 입력한 도메인
|
|
384
|
+
*/
|
|
385
|
+
infra: "ai" | "db" | "uniai" | string;
|
|
386
|
+
/**
|
|
387
|
+
* 요청 방식
|
|
388
|
+
* POST, DELETE
|
|
389
|
+
*/
|
|
390
|
+
method: string;
|
|
391
|
+
/**
|
|
392
|
+
* 프론트 API URL
|
|
393
|
+
*/
|
|
394
|
+
routeUrl: string;
|
|
395
|
+
/**
|
|
396
|
+
* 백엔드 API 요청 URL
|
|
397
|
+
*/
|
|
398
|
+
queryUrl: string;
|
|
399
|
+
/**
|
|
400
|
+
* fetch 실패 시 대체 응답
|
|
401
|
+
*/
|
|
402
|
+
alternateResponse: ResponseType;
|
|
403
|
+
} & Partial<{
|
|
404
|
+
searchParams: URLSearchParams | object;
|
|
405
|
+
/**
|
|
406
|
+
* fetch Headers
|
|
407
|
+
*/
|
|
408
|
+
headers: HeadersInit;
|
|
409
|
+
/**
|
|
410
|
+
* fetch Body
|
|
411
|
+
*/
|
|
412
|
+
body: BodyInit | null;
|
|
413
|
+
/**
|
|
414
|
+
* fetch Body Data
|
|
415
|
+
*/
|
|
416
|
+
bodyData: BodyDataType;
|
|
417
|
+
/**
|
|
418
|
+
* 응답값 원본으로 return
|
|
419
|
+
* const responseRaw = await fetch(api);
|
|
420
|
+
*/
|
|
421
|
+
isRawResponse: boolean;
|
|
422
|
+
/**
|
|
423
|
+
* 디버그용 로그 객체
|
|
424
|
+
*/
|
|
425
|
+
debug: object;
|
|
426
|
+
/**
|
|
427
|
+
* fetch 비활성화
|
|
428
|
+
*/
|
|
429
|
+
disabled: boolean;
|
|
430
|
+
/**
|
|
431
|
+
* 로그 비활성화
|
|
432
|
+
*/
|
|
433
|
+
disabledLog: boolean;
|
|
434
|
+
}>): Promise<ResponseType> => {
|
|
435
|
+
// ------------------------------------- API 요청 URL 생성
|
|
436
|
+
// API 인프라에 따른 요청 도메인 추출
|
|
437
|
+
const DOMAIN = infraDomain(infra);
|
|
438
|
+
|
|
439
|
+
// url 생성
|
|
440
|
+
const url = `${DOMAIN}${queryUrl}${getQueryString(searchParams)}`;
|
|
441
|
+
|
|
442
|
+
// ------------------------------------- 쿼리 옵션 생성
|
|
443
|
+
const option: RequestInit = getFetchOptions({
|
|
444
|
+
method,
|
|
445
|
+
headers,
|
|
446
|
+
body,
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
// ------------------------------------- body data 적용
|
|
450
|
+
// 완성된 body가 없고, body 데이터는 있는 경우
|
|
451
|
+
if (!body && typeof bodyData !== "undefined") {
|
|
452
|
+
// bodyData가 undefined가 아닌데도, bodyData의 데이터가 유효하지 않은 경우
|
|
453
|
+
if (typeof bodyData !== "undefined" && String(bodyData) === "") {
|
|
454
|
+
nextAPILog(method.toLowerCase(), routeUrl, url, {
|
|
455
|
+
state: "ERROR (BODY - DATA)",
|
|
456
|
+
error: "데이터가 유효하지 않습니다.",
|
|
457
|
+
bodyData,
|
|
458
|
+
...debug,
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
return alternateResponse;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// option에 bodyData 적용
|
|
465
|
+
Object.assign(option, { body: bodyData });
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// option 준비가 완료되면, READY 상태
|
|
469
|
+
if (!disabledLog)
|
|
470
|
+
nextAPILog(method.toLowerCase(), routeUrl, url, {
|
|
471
|
+
state: "READY",
|
|
472
|
+
...option,
|
|
473
|
+
...debug,
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
// ------------------------------------- fetch 요청
|
|
477
|
+
if (disabled) {
|
|
478
|
+
// fetch 요청 비활성화
|
|
479
|
+
nextAPILog(method.toLowerCase(), routeUrl, url, {
|
|
480
|
+
state: "FETCH DISABLED",
|
|
481
|
+
message: "API 요청제한 활성화됨.",
|
|
482
|
+
});
|
|
483
|
+
return alternateResponse;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
try {
|
|
487
|
+
const responseRaw = await fetch(url, option);
|
|
488
|
+
|
|
489
|
+
// API 응답 상태 코드
|
|
490
|
+
const resCode = responseRaw.status;
|
|
491
|
+
|
|
492
|
+
// API 응답 성공 여부
|
|
493
|
+
if (!disabledLog) {
|
|
494
|
+
nextAPILog(method.toLowerCase(), routeUrl, url, {
|
|
495
|
+
state: resCode === 200 ? "SUCCESS" : "FAIL",
|
|
496
|
+
code: resCode,
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
if (isRawResponse) return responseRaw as ResponseType;
|
|
501
|
+
|
|
502
|
+
const res = await responseRaw.json();
|
|
503
|
+
return res;
|
|
504
|
+
} catch (error: unknown) {
|
|
505
|
+
// 에러 응답
|
|
506
|
+
if (!disabledLog)
|
|
507
|
+
nextAPILog(method.toLowerCase(), routeUrl, url, {
|
|
508
|
+
state: "ERROR (RESPONSE)",
|
|
509
|
+
error,
|
|
510
|
+
...debug,
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
return alternateResponse;
|
|
514
|
+
}
|
|
515
|
+
};
|