@farmzone/fz-template-react 1.0.5 → 1.0.7
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 +102 -102
- package/bin/create.js +108 -108
- package/package.json +24 -24
- package/template/.env.example +5 -5
- package/template/.prettierrc +9 -9
- package/template/eslint.config.js +26 -26
- package/template/index.css +32 -32
- package/template/index.html +19 -19
- package/template/package.json +54 -55
- package/template/pnpm-lock.yaml +4214 -4214
- package/template/public/mockServiceWorker.js +349 -349
- package/template/src/app/App.tsx +26 -26
- package/template/src/app/api/api.ts +178 -178
- package/template/src/app/api/queries.ts +335 -326
- package/template/src/app/api/queryKey.ts +7 -7
- package/template/src/app/api/token.ts +8 -7
- package/template/src/app/layout/Layout.tsx +33 -33
- package/template/src/app/layout/ListContents.tsx +9 -9
- package/template/src/app/layout/ListHeader.tsx +41 -41
- package/template/src/app/layout/MultiTabNav.tsx +106 -101
- package/template/src/app/layout/Sidebar.tsx +33 -33
- package/template/src/app/layout/UserInfo.tsx +95 -94
- package/template/src/app/layout/menu.ts +79 -55
- package/template/src/app/layout/tabSwitchStore.ts +11 -11
- package/template/src/app/router/Router.tsx +56 -56
- package/template/src/app/store/index.ts +26 -26
- package/template/src/index.tsx +21 -21
- package/template/src/mocks/browser.ts +17 -17
- package/template/src/mocks/handlers.ts +43 -43
- package/template/src/mocks/scenarios.ts +57 -57
- package/template/src/pages/dashboard/index.tsx +541 -541
- package/template/src/pages/error/Error.tsx +29 -29
- package/template/src/pages/error/NotFound.tsx +27 -27
- package/template/src/pages/login/index.tsx +317 -317
- package/template/src/pages/post/PostFormModal.tsx +128 -128
- package/template/src/pages/post/detail/index.tsx +545 -548
- package/template/src/pages/post/index.tsx +266 -266
- package/template/src/pages/sample/SampleFormModal.tsx +188 -115
- package/template/src/pages/sample/detail/index.tsx +551 -400
- package/template/src/pages/sample/index.tsx +298 -278
- package/template/src/pages/sample/modal/index.tsx +308 -300
- package/template/src/pages/system/log/index.tsx +173 -173
- package/template/src/pages/user/config/columns.tsx +102 -102
- package/template/src/pages/user/config/schema.ts +54 -54
- package/template/src/pages/user/index.tsx +704 -641
- package/template/src/shared/components/CommentInput.tsx +243 -243
- package/template/src/shared/components/FilePreviewCard.tsx +71 -70
- package/template/src/shared/config/text.ts +27 -27
- package/template/src/shared/config/type.ts +40 -40
- package/template/src/shared/utils/format.ts +11 -11
- package/template/src/types/auth.ts +10 -10
- package/template/src/types/comment.ts +33 -33
- package/template/src/types/common.ts +19 -19
- package/template/src/types/dashboard.ts +53 -53
- package/template/src/types/index.ts +16 -16
- package/template/src/types/log.ts +21 -21
- package/template/src/types/post.ts +32 -32
- package/template/src/types/sample.ts +33 -29
- package/template/src/types/user.ts +51 -51
- package/template/src/vite-env.d.ts +10 -10
- package/template/tsconfig.app.json +32 -32
- package/template/tsconfig.json +7 -7
- package/template/tsconfig.node.json +26 -26
- package/template/vite.config.ts +13 -13
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
import { HttpResponse, delay, http, passthrough } from "msw";
|
|
2
|
-
|
|
3
|
-
import { getScenario, getTargetPath } from "./scenarios";
|
|
4
|
-
|
|
5
|
-
const BASE_URL = `${import.meta.env.VITE_APP_API_HOST}/api/${import.meta.env.VITE_APP_API_VERSION}`;
|
|
6
|
-
|
|
7
|
-
const ERROR_RESPONSES: Record<string, () => Response> = {
|
|
8
|
-
"500": () => HttpResponse.json({ message: "Internal Server Error" }, { status: 500 }),
|
|
9
|
-
"503": () => HttpResponse.json({ message: "Service Unavailable" }, { status: 503 }),
|
|
10
|
-
"408": () => HttpResponse.json({ message: "Request Timeout" }, { status: 408 }),
|
|
11
|
-
"401": () => HttpResponse.json({ message: "Unauthorized" }, { status: 401 }),
|
|
12
|
-
"403": () => HttpResponse.json({ message: "Forbidden" }, { status: 403 }),
|
|
13
|
-
"404": () => HttpResponse.json({ message: "Not Found" }, { status: 404 }),
|
|
14
|
-
"400": () => HttpResponse.json({ message: "Bad Request" }, { status: 400 }),
|
|
15
|
-
network: () => HttpResponse.error(),
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const timeoutInterceptor = async () => {
|
|
19
|
-
await delay(3_000); // 3초 지연 후 408 반환 (타임아웃 시뮬레이션)
|
|
20
|
-
return HttpResponse.json({ message: "Request Timeout" }, { status: 408 });
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const errorInterceptor = async ({ request }: { request: Request }) => {
|
|
24
|
-
const scenario = getScenario();
|
|
25
|
-
|
|
26
|
-
if (scenario === "none") return passthrough();
|
|
27
|
-
|
|
28
|
-
const targetPath = getTargetPath();
|
|
29
|
-
if (targetPath && !request.url.includes(targetPath)) return passthrough();
|
|
30
|
-
|
|
31
|
-
if (scenario === "timeout") return timeoutInterceptor();
|
|
32
|
-
|
|
33
|
-
const handler = ERROR_RESPONSES[scenario];
|
|
34
|
-
return handler ? handler() : passthrough();
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export const handlers = [
|
|
38
|
-
http.get(`${BASE_URL}/*`, errorInterceptor),
|
|
39
|
-
http.post(`${BASE_URL}/*`, errorInterceptor),
|
|
40
|
-
http.put(`${BASE_URL}/*`, errorInterceptor),
|
|
41
|
-
http.patch(`${BASE_URL}/*`, errorInterceptor),
|
|
42
|
-
http.delete(`${BASE_URL}/*`, errorInterceptor),
|
|
43
|
-
];
|
|
1
|
+
import { HttpResponse, delay, http, passthrough } from "msw";
|
|
2
|
+
|
|
3
|
+
import { getScenario, getTargetPath } from "./scenarios";
|
|
4
|
+
|
|
5
|
+
const BASE_URL = `${import.meta.env.VITE_APP_API_HOST}/api/${import.meta.env.VITE_APP_API_VERSION}`;
|
|
6
|
+
|
|
7
|
+
const ERROR_RESPONSES: Record<string, () => Response> = {
|
|
8
|
+
"500": () => HttpResponse.json({ message: "Internal Server Error" }, { status: 500 }),
|
|
9
|
+
"503": () => HttpResponse.json({ message: "Service Unavailable" }, { status: 503 }),
|
|
10
|
+
"408": () => HttpResponse.json({ message: "Request Timeout" }, { status: 408 }),
|
|
11
|
+
"401": () => HttpResponse.json({ message: "Unauthorized" }, { status: 401 }),
|
|
12
|
+
"403": () => HttpResponse.json({ message: "Forbidden" }, { status: 403 }),
|
|
13
|
+
"404": () => HttpResponse.json({ message: "Not Found" }, { status: 404 }),
|
|
14
|
+
"400": () => HttpResponse.json({ message: "Bad Request" }, { status: 400 }),
|
|
15
|
+
network: () => HttpResponse.error(),
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const timeoutInterceptor = async () => {
|
|
19
|
+
await delay(3_000); // 3초 지연 후 408 반환 (타임아웃 시뮬레이션)
|
|
20
|
+
return HttpResponse.json({ message: "Request Timeout" }, { status: 408 });
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const errorInterceptor = async ({ request }: { request: Request }) => {
|
|
24
|
+
const scenario = getScenario();
|
|
25
|
+
|
|
26
|
+
if (scenario === "none") return passthrough();
|
|
27
|
+
|
|
28
|
+
const targetPath = getTargetPath();
|
|
29
|
+
if (targetPath && !request.url.includes(targetPath)) return passthrough();
|
|
30
|
+
|
|
31
|
+
if (scenario === "timeout") return timeoutInterceptor();
|
|
32
|
+
|
|
33
|
+
const handler = ERROR_RESPONSES[scenario];
|
|
34
|
+
return handler ? handler() : passthrough();
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const handlers = [
|
|
38
|
+
http.get(`${BASE_URL}/*`, errorInterceptor),
|
|
39
|
+
http.post(`${BASE_URL}/*`, errorInterceptor),
|
|
40
|
+
http.put(`${BASE_URL}/*`, errorInterceptor),
|
|
41
|
+
http.patch(`${BASE_URL}/*`, errorInterceptor),
|
|
42
|
+
http.delete(`${BASE_URL}/*`, errorInterceptor),
|
|
43
|
+
];
|
|
@@ -1,57 +1,57 @@
|
|
|
1
|
-
// 브라우저 콘솔에서 에러 시나리오 변경:
|
|
2
|
-
// window.__setMswErrorScenario('500') → 모든 API 서버 내부 오류
|
|
3
|
-
// window.__setMswErrorScenario('500', 'users') → /users 포함 URL만 500, 나머지 정상
|
|
4
|
-
// window.__setMswErrorScenario('503') → 서비스 일시 불능 (1회 재시도)
|
|
5
|
-
// window.__setMswErrorScenario('408') → 타임아웃 (1회 재시도)
|
|
6
|
-
// window.__setMswErrorScenario('401') → 인증 오류
|
|
7
|
-
// window.__setMswErrorScenario('403') → 권한 오류
|
|
8
|
-
// window.__setMswErrorScenario('404') → 존재하지 않는 리소스
|
|
9
|
-
// window.__setMswErrorScenario('400') → 잘못된 요청
|
|
10
|
-
// window.__setMswErrorScenario('timeout') → 타임아웃 (3초 지연 후 408 반환 → 1회 재시도)
|
|
11
|
-
// window.__setMswErrorScenario('network') → 네트워크 장애 (1회 재시도)
|
|
12
|
-
// window.__setMswErrorScenario('none') → 모킹 해제
|
|
13
|
-
|
|
14
|
-
export type MswScenario =
|
|
15
|
-
| "500"
|
|
16
|
-
| "503"
|
|
17
|
-
| "408"
|
|
18
|
-
| "401"
|
|
19
|
-
| "403"
|
|
20
|
-
| "404"
|
|
21
|
-
| "400"
|
|
22
|
-
| "network"
|
|
23
|
-
| "timeout"
|
|
24
|
-
| "none";
|
|
25
|
-
|
|
26
|
-
const SCENARIO_KEY = "msw-scenario";
|
|
27
|
-
const TARGET_KEY = "msw-target-path";
|
|
28
|
-
|
|
29
|
-
export const getScenario = (): MswScenario => (localStorage.getItem(SCENARIO_KEY) as MswScenario) ?? "none";
|
|
30
|
-
|
|
31
|
-
export const getTargetPath = (): string | null => localStorage.getItem(TARGET_KEY);
|
|
32
|
-
|
|
33
|
-
export const setErrorScenario = (scenario: MswScenario, targetPath?: string) => {
|
|
34
|
-
localStorage.setItem(SCENARIO_KEY, scenario);
|
|
35
|
-
|
|
36
|
-
if (targetPath) {
|
|
37
|
-
localStorage.setItem(TARGET_KEY, targetPath);
|
|
38
|
-
} else {
|
|
39
|
-
localStorage.removeItem(TARGET_KEY);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const flags = [targetPath ? `대상: *${targetPath}*` : null].filter(Boolean).join(", ");
|
|
43
|
-
|
|
44
|
-
console.log(`[MSW] 시나리오 변경: ${scenario}${flags ? ` (${flags})` : ""} (새로고침 후 적용)`);
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
export const getScenarioGuide = () => {
|
|
48
|
-
console.log(`
|
|
49
|
-
[브라우저 콘솔에서 에러 시나리오 변경 Guide]
|
|
50
|
-
|
|
51
|
-
(1) API 500 에러
|
|
52
|
-
window.__setMswErrorScenario('500')
|
|
53
|
-
|
|
54
|
-
(2) users API만 500 에러
|
|
55
|
-
window.__setMswErrorScenario('500', 'users')
|
|
56
|
-
`);
|
|
57
|
-
};
|
|
1
|
+
// 브라우저 콘솔에서 에러 시나리오 변경:
|
|
2
|
+
// window.__setMswErrorScenario('500') → 모든 API 서버 내부 오류
|
|
3
|
+
// window.__setMswErrorScenario('500', 'users') → /users 포함 URL만 500, 나머지 정상
|
|
4
|
+
// window.__setMswErrorScenario('503') → 서비스 일시 불능 (1회 재시도)
|
|
5
|
+
// window.__setMswErrorScenario('408') → 타임아웃 (1회 재시도)
|
|
6
|
+
// window.__setMswErrorScenario('401') → 인증 오류
|
|
7
|
+
// window.__setMswErrorScenario('403') → 권한 오류
|
|
8
|
+
// window.__setMswErrorScenario('404') → 존재하지 않는 리소스
|
|
9
|
+
// window.__setMswErrorScenario('400') → 잘못된 요청
|
|
10
|
+
// window.__setMswErrorScenario('timeout') → 타임아웃 (3초 지연 후 408 반환 → 1회 재시도)
|
|
11
|
+
// window.__setMswErrorScenario('network') → 네트워크 장애 (1회 재시도)
|
|
12
|
+
// window.__setMswErrorScenario('none') → 모킹 해제
|
|
13
|
+
|
|
14
|
+
export type MswScenario =
|
|
15
|
+
| "500"
|
|
16
|
+
| "503"
|
|
17
|
+
| "408"
|
|
18
|
+
| "401"
|
|
19
|
+
| "403"
|
|
20
|
+
| "404"
|
|
21
|
+
| "400"
|
|
22
|
+
| "network"
|
|
23
|
+
| "timeout"
|
|
24
|
+
| "none";
|
|
25
|
+
|
|
26
|
+
const SCENARIO_KEY = "msw-scenario";
|
|
27
|
+
const TARGET_KEY = "msw-target-path";
|
|
28
|
+
|
|
29
|
+
export const getScenario = (): MswScenario => (localStorage.getItem(SCENARIO_KEY) as MswScenario) ?? "none";
|
|
30
|
+
|
|
31
|
+
export const getTargetPath = (): string | null => localStorage.getItem(TARGET_KEY);
|
|
32
|
+
|
|
33
|
+
export const setErrorScenario = (scenario: MswScenario, targetPath?: string) => {
|
|
34
|
+
localStorage.setItem(SCENARIO_KEY, scenario);
|
|
35
|
+
|
|
36
|
+
if (targetPath) {
|
|
37
|
+
localStorage.setItem(TARGET_KEY, targetPath);
|
|
38
|
+
} else {
|
|
39
|
+
localStorage.removeItem(TARGET_KEY);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const flags = [targetPath ? `대상: *${targetPath}*` : null].filter(Boolean).join(", ");
|
|
43
|
+
|
|
44
|
+
console.log(`[MSW] 시나리오 변경: ${scenario}${flags ? ` (${flags})` : ""} (새로고침 후 적용)`);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const getScenarioGuide = () => {
|
|
48
|
+
console.log(`
|
|
49
|
+
[브라우저 콘솔에서 에러 시나리오 변경 Guide]
|
|
50
|
+
|
|
51
|
+
(1) API 500 에러
|
|
52
|
+
window.__setMswErrorScenario('500')
|
|
53
|
+
|
|
54
|
+
(2) users API만 500 에러
|
|
55
|
+
window.__setMswErrorScenario('500', 'users')
|
|
56
|
+
`);
|
|
57
|
+
};
|