diff --git a/apps/as/package.json b/apps/as/package.json index cebdf28ee..ed4016352 100644 --- a/apps/as/package.json +++ b/apps/as/package.json @@ -32,7 +32,6 @@ "next": "15.5.18", "react-hook-form": "^7.54.2", "tus-js-client": "^4.3.1", - "uuid": "^14.0.1", "zod": "^3.24.2" }, "devDependencies": { diff --git a/apps/as/src/entities/auth/api/auth-service.ts b/apps/as/src/entities/auth/api/auth-service.ts index b7158bf80..527d72e7a 100644 --- a/apps/as/src/entities/auth/api/auth-service.ts +++ b/apps/as/src/entities/auth/api/auth-service.ts @@ -1,7 +1,11 @@ import { ACCESS_TOKEN, AUTH_USER_ID, CLAIM_NAME, ENDPOINT } from "@/shared/config"; -import { type AuthPayload, type AuthService } from "@common/auth"; +import { + type AuthPayload, + type AuthService, + clearDeviceId, + getOrCreateDeviceId, +} from "@common/auth"; -import { clearDeviceId, getOrCreateDeviceId } from "../lib/device-id"; import { clearRefreshTimer, setToken, tokenManager } from "../lib/token-manager"; async function login(payload: AuthPayload): Promise { diff --git a/apps/as/src/entities/auth/lib/device-id.ts b/apps/as/src/entities/auth/lib/device-id.ts deleted file mode 100644 index ce173b141..000000000 --- a/apps/as/src/entities/auth/lib/device-id.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { v4 as uuidv4 } from "uuid"; - -const DEVICE_ID_KEY = "x-device-id"; - -export function getOrCreateDeviceId(): string { - if (typeof window === "undefined") return ""; - const existing = localStorage.getItem(DEVICE_ID_KEY); - if (existing) return existing; - const id = uuidv4(); - localStorage.setItem(DEVICE_ID_KEY, id); - return id; -} - -export function clearDeviceId(): void { - if (typeof window === "undefined") return; - localStorage.removeItem(DEVICE_ID_KEY); -} diff --git a/apps/cm/package.json b/apps/cm/package.json index 1f9f98815..0440c504c 100644 --- a/apps/cm/package.json +++ b/apps/cm/package.json @@ -47,7 +47,6 @@ "sonner": "^2.0.1", "tailwindcss-animate": "^1.0.7", "tus-js-client": "^4.3.1", - "uuid": "^14.0.1", "zod": "^3.24.2", "zustand": "^5.0.3" }, diff --git a/apps/cm/src/entities/auth/api/auth-service.ts b/apps/cm/src/entities/auth/api/auth-service.ts index 073f95fe2..79d99c1e8 100644 --- a/apps/cm/src/entities/auth/api/auth-service.ts +++ b/apps/cm/src/entities/auth/api/auth-service.ts @@ -5,18 +5,17 @@ import { ENDPOINT, } from "@/shared/config"; import { + clearDeviceId, + getOrCreateDeviceId, type AuthPayload, type AuthService, - getRemainingMs, } from "@common/auth"; import { clearRefreshTimer, setToken, - setupRefreshTimer, tokenManager, } from "../lib/token-manager"; -import { clearDeviceId, getOrCreateDeviceId } from "../lib/device-id"; function completeSession(accessToken: string, tokenId: string): void { setToken(CLAIM_NAME, accessToken); diff --git a/apps/cm/src/entities/auth/lib/device-id.ts b/apps/cm/src/entities/auth/lib/device-id.ts deleted file mode 100644 index 3683c7189..000000000 --- a/apps/cm/src/entities/auth/lib/device-id.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { v4 as uuidv4 } from "uuid"; - -const DEVICE_ID_KEY = "x-device-id"; - -export function getOrCreateDeviceId(): string { - if (typeof window === "undefined") return ""; - - const existing = localStorage.getItem(DEVICE_ID_KEY); - if (existing) return existing; - - const id = uuidv4(); - localStorage.setItem(DEVICE_ID_KEY, id); - return id; -} - -export function clearDeviceId(): void { - if (typeof window === "undefined") return; - - localStorage.removeItem(DEVICE_ID_KEY); -} diff --git a/apps/cs/package.json b/apps/cs/package.json index 710032627..d362d1178 100644 --- a/apps/cs/package.json +++ b/apps/cs/package.json @@ -45,7 +45,6 @@ "sonner": "^2.0.1", "tailwindcss-animate": "^1.0.7", "tus-js-client": "^4.3.1", - "uuid": "^14.0.1", "zod": "^3.24.2", "zustand": "^5.0.3" }, diff --git a/apps/cs/src/entities/auth/api/auth-service.ts b/apps/cs/src/entities/auth/api/auth-service.ts index 93c0bc0bb..ce148e37d 100644 --- a/apps/cs/src/entities/auth/api/auth-service.ts +++ b/apps/cs/src/entities/auth/api/auth-service.ts @@ -4,9 +4,13 @@ import { CLAIM_NAME, ENDPOINT, } from "@/shared/config"; -import { type AuthPayload, type AuthService } from "@common/auth"; +import { + type AuthPayload, + type AuthService, + clearDeviceId, + getOrCreateDeviceId, +} from "@common/auth"; -import { clearDeviceId, getOrCreateDeviceId } from "../lib/device-id"; import { clearRefreshTimer, setToken, diff --git a/apps/cs/src/entities/auth/lib/device-id.ts b/apps/cs/src/entities/auth/lib/device-id.ts deleted file mode 100644 index 3683c7189..000000000 --- a/apps/cs/src/entities/auth/lib/device-id.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { v4 as uuidv4 } from "uuid"; - -const DEVICE_ID_KEY = "x-device-id"; - -export function getOrCreateDeviceId(): string { - if (typeof window === "undefined") return ""; - - const existing = localStorage.getItem(DEVICE_ID_KEY); - if (existing) return existing; - - const id = uuidv4(); - localStorage.setItem(DEVICE_ID_KEY, id); - return id; -} - -export function clearDeviceId(): void { - if (typeof window === "undefined") return; - - localStorage.removeItem(DEVICE_ID_KEY); -} diff --git a/apps/fo/package.json b/apps/fo/package.json index 84b192049..8116359df 100644 --- a/apps/fo/package.json +++ b/apps/fo/package.json @@ -35,8 +35,7 @@ "react-hook-form": "^7.54.2", "zod": "^3.24.2", "axios": "^1.8.1", - "proj4": "^2.9.0", - "uuid": "^14.0.1" + "proj4": "^2.9.0" }, "devDependencies": { "@eslint/eslintrc": "^3", diff --git a/apps/fo/src/entities/auth/api/auth-service.ts b/apps/fo/src/entities/auth/api/auth-service.ts index 2ea6bab12..3985fca8c 100644 --- a/apps/fo/src/entities/auth/api/auth-service.ts +++ b/apps/fo/src/entities/auth/api/auth-service.ts @@ -1,47 +1,82 @@ import { - ACCESS_TOKEN, - AUTH_USER_ID, - CLAIM_NAME, - ENDPOINT, + ACCESS_TOKEN, + AUTH_USER_ID, + CLAIM_NAME, + ENDPOINT, } from "@/src/shared/config"; import { getCookie } from "@/src/shared/lib"; import { - type AuthPayload, - type AuthService, - getRemainingMs, + clearDeviceId, + getOrCreateDeviceId, + type AuthPayload, + type AuthService, + getRemainingMs, } from "@common/auth"; -import { clearDeviceId, getOrCreateDeviceId } from "../lib/device-id"; import { - clearRefreshTimer, - setToken, - setupRefreshTimer, - tokenManager, + clearRefreshTimer, + setToken, + setupRefreshTimer, + tokenManager, } from "../lib/token-manager"; - import { clearTabStorePersist } from "@/src/store/tab-store"; async function login(payload: AuthPayload): Promise { - const response = await fetch(`/api/proxy${ENDPOINT.USER_SERVICE.LOGIN}`, { - method: "POST", + const response = await fetch(`/api/proxy${ENDPOINT.USER_SERVICE.LOGIN}`, { + method: "POST", + headers: { + "Content-Type": "application/json", + "X-Device-Id": getOrCreateDeviceId(), + }, + body: JSON.stringify(payload), + }); + + const data = await response.json(); + + const accessToken = data[ACCESS_TOKEN]; + const tokenId = data[AUTH_USER_ID]; + + if (!accessToken || !tokenId) { + throw new Error("인증 토큰을 받지 못했습니다."); + } + + const prevTokenId = getCookie(AUTH_USER_ID); + if (prevTokenId !== undefined && prevTokenId !== tokenId) { + clearTabStorePersist(); + } + + setToken(CLAIM_NAME, accessToken); + setToken(AUTH_USER_ID, tokenId); + + const remainingMs = getRemainingMs(accessToken); + if (remainingMs > 0) { + setupRefreshTimer(silentRefresh, remainingMs); + } +} + +async function silentRefresh(): Promise { + console.log(`[silentRefresh] Called at ${new Date().toISOString()}`); + try { + const response = await fetch( + `/api/proxy${ENDPOINT.USER_SERVICE.SILENT_REFRESH}`, + { + method: "PUT", headers: { - "Content-Type": "application/json", - "X-Device-Id": getOrCreateDeviceId(), + "X-Device-Id": getOrCreateDeviceId(), }, - body: JSON.stringify(payload), - }); + }, + ); const data = await response.json(); + if (!response.ok) { + throw new Error(data?.message ?? "토큰 갱신에 실패했습니다."); + } + const accessToken = data[ACCESS_TOKEN]; const tokenId = data[AUTH_USER_ID]; if (!accessToken || !tokenId) { - throw new Error("인증 토큰을 받지 못했습니다."); - } - - const prevTokenId = getCookie(AUTH_USER_ID); - if (prevTokenId !== undefined && prevTokenId !== tokenId) { - clearTabStorePersist(); + throw new Error("갱신된 인증 토큰을 받지 못했습니다."); } setToken(CLAIM_NAME, accessToken); @@ -49,67 +84,32 @@ async function login(payload: AuthPayload): Promise { const remainingMs = getRemainingMs(accessToken); if (remainingMs > 0) { - setupRefreshTimer(silentRefresh, remainingMs); + setupRefreshTimer(silentRefresh, remainingMs); } -} - -async function silentRefresh(): Promise { - console.log(`[silentRefresh] Called at ${new Date().toISOString()}`); - try { - const response = await fetch( - `/api/proxy${ENDPOINT.USER_SERVICE.SILENT_REFRESH}`, - { - method: "PUT", - headers: { - "X-Device-Id": getOrCreateDeviceId(), - }, - }, - ); - - const data = await response.json(); - - if (!response.ok) { - throw new Error(data?.message ?? "토큰 갱신에 실패했습니다."); - } - - const accessToken = data[ACCESS_TOKEN]; - const tokenId = data[AUTH_USER_ID]; - - if (!accessToken || !tokenId) { - throw new Error("갱신된 인증 토큰을 받지 못했습니다."); - } - - setToken(CLAIM_NAME, accessToken); - setToken(AUTH_USER_ID, tokenId); - - const remainingMs = getRemainingMs(accessToken); - if (remainingMs > 0) { - setupRefreshTimer(silentRefresh, remainingMs); - } - } catch (error) { - console.error( - `[silentRefresh] Failed at ${new Date().toISOString()}`, - error, - ); - tokenManager.clearAuthToken(); - if (typeof window !== "undefined") { - window.dispatchEvent(new CustomEvent("auth:logout")); - } + } catch (error) { + console.error( + `[silentRefresh] Failed at ${new Date().toISOString()}`, + error, + ); + tokenManager.clearAuthToken(); + if (typeof window !== "undefined") { + window.dispatchEvent(new CustomEvent("auth:logout")); } + } } export async function logout(): Promise { - tokenManager.clearAuthToken(); - clearDeviceId(); + tokenManager.clearAuthToken(); + clearDeviceId(); - if (typeof window !== "undefined") { - window.dispatchEvent(new CustomEvent("auth:logout")); - } + if (typeof window !== "undefined") { + window.dispatchEvent(new CustomEvent("auth:logout")); + } } export const authService: AuthService = { - login, - silentRefresh, - declineSessionExtend: clearRefreshTimer, - logout, + login, + silentRefresh, + declineSessionExtend: clearRefreshTimer, + logout, }; diff --git a/apps/fo/src/entities/auth/lib/device-id.ts b/apps/fo/src/entities/auth/lib/device-id.ts deleted file mode 100644 index f844fcbef..000000000 --- a/apps/fo/src/entities/auth/lib/device-id.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { v4 as uuidv4 } from "uuid"; - -const DEVICE_ID_KEY = "x-device-id"; - -export function getOrCreateDeviceId(): string { - if (typeof window === "undefined") return ""; - - const existing = localStorage.getItem(DEVICE_ID_KEY); - if (existing) return existing; - - const id = uuidv4(); - localStorage.setItem(DEVICE_ID_KEY, id); - return id; -} - -export function clearDeviceId(): void { - if (typeof window === "undefined") return; - - localStorage.removeItem(DEVICE_ID_KEY); -} diff --git a/apps/sn/package.json b/apps/sn/package.json index 8cfd172aa..cc7c4e17f 100644 --- a/apps/sn/package.json +++ b/apps/sn/package.json @@ -37,7 +37,6 @@ "react-hook-form": "^7.54.2", "tailwindcss-animate": "^1.0.7", "tus-js-client": "^4.3.1", - "uuid": "^14.0.1", "xlsx": "^0.18.5", "xlsx-populate": "^1.21.0", "zod": "^3.24.2", diff --git a/apps/sn/src/entities/auth/api/auth-service.ts b/apps/sn/src/entities/auth/api/auth-service.ts index 93b158ef9..0320aa474 100644 --- a/apps/sn/src/entities/auth/api/auth-service.ts +++ b/apps/sn/src/entities/auth/api/auth-service.ts @@ -1,47 +1,83 @@ import { - ACCESS_TOKEN, - AUTH_USER_ID, - CLAIM_NAME, - ENDPOINT, + ACCESS_TOKEN, + AUTH_USER_ID, + CLAIM_NAME, + ENDPOINT, } from "@/shared/config"; import { getCookie } from "@/shared/lib"; import { - type AuthPayload, - type AuthService, - getRemainingMs, + clearDeviceId, + getOrCreateDeviceId, + type AuthPayload, + type AuthService, + getRemainingMs, } from "@common/auth"; -import { clearDeviceId, getOrCreateDeviceId } from "../lib/device-id"; import { - clearRefreshTimer, - setToken, - setupRefreshTimer, - tokenManager, + clearRefreshTimer, + setToken, + setupRefreshTimer, + tokenManager, } from "../lib/token-manager"; import { clearTabStorePersist } from "../../../store/tab-store"; async function login(payload: AuthPayload): Promise { - const response = await fetch(`/api/proxy${ENDPOINT.USER_SERVICE.LOGIN}`, { - method: "POST", + const response = await fetch(`/api/proxy${ENDPOINT.USER_SERVICE.LOGIN}`, { + method: "POST", + headers: { + "Content-Type": "application/json", + "X-Device-Id": getOrCreateDeviceId(), + }, + body: JSON.stringify(payload), + }); + + const data = await response.json(); + + const accessToken = data[ACCESS_TOKEN]; + const tokenId = data[AUTH_USER_ID]; + + if (!accessToken || !tokenId) { + throw new Error("인증 토큰을 받지 못했습니다."); + } + + const prevTokenId = getCookie(AUTH_USER_ID); + if (prevTokenId !== undefined && prevTokenId !== tokenId) { + clearTabStorePersist(); + } + + setToken(CLAIM_NAME, accessToken); + setToken(AUTH_USER_ID, tokenId); + + const remainingMs = getRemainingMs(accessToken); + if (remainingMs > 0) { + setupRefreshTimer(silentRefresh, remainingMs); + } +} + +async function silentRefresh(): Promise { + console.log(`[silentRefresh] Called at ${new Date().toISOString()}`); + try { + const response = await fetch( + `/api/proxy${ENDPOINT.USER_SERVICE.SILENT_REFRESH}`, + { + method: "PUT", headers: { - "Content-Type": "application/json", - "X-Device-Id": getOrCreateDeviceId(), + "X-Device-Id": getOrCreateDeviceId(), }, - body: JSON.stringify(payload), - }); + }, + ); const data = await response.json(); + if (!response.ok) { + throw new Error(data?.message ?? "토큰 갱신에 실패했습니다."); + } + const accessToken = data[ACCESS_TOKEN]; const tokenId = data[AUTH_USER_ID]; if (!accessToken || !tokenId) { - throw new Error("인증 토큰을 받지 못했습니다."); - } - - const prevTokenId = getCookie(AUTH_USER_ID); - if (prevTokenId !== undefined && prevTokenId !== tokenId) { - clearTabStorePersist(); + throw new Error("갱신된 인증 토큰을 받지 못했습니다."); } setToken(CLAIM_NAME, accessToken); @@ -49,67 +85,32 @@ async function login(payload: AuthPayload): Promise { const remainingMs = getRemainingMs(accessToken); if (remainingMs > 0) { - setupRefreshTimer(silentRefresh, remainingMs); + setupRefreshTimer(silentRefresh, remainingMs); } -} - -async function silentRefresh(): Promise { - console.log(`[silentRefresh] Called at ${new Date().toISOString()}`); - try { - const response = await fetch( - `/api/proxy${ENDPOINT.USER_SERVICE.SILENT_REFRESH}`, - { - method: "PUT", - headers: { - "X-Device-Id": getOrCreateDeviceId(), - }, - }, - ); - - const data = await response.json(); - - if (!response.ok) { - throw new Error(data?.message ?? "토큰 갱신에 실패했습니다."); - } - - const accessToken = data[ACCESS_TOKEN]; - const tokenId = data[AUTH_USER_ID]; - - if (!accessToken || !tokenId) { - throw new Error("갱신된 인증 토큰을 받지 못했습니다."); - } - - setToken(CLAIM_NAME, accessToken); - setToken(AUTH_USER_ID, tokenId); - - const remainingMs = getRemainingMs(accessToken); - if (remainingMs > 0) { - setupRefreshTimer(silentRefresh, remainingMs); - } - } catch (error) { - console.error( - `[silentRefresh] Failed at ${new Date().toISOString()}`, - error, - ); - tokenManager.clearAuthToken(); - if (typeof window !== "undefined") { - window.dispatchEvent(new CustomEvent("auth:logout")); - } + } catch (error) { + console.error( + `[silentRefresh] Failed at ${new Date().toISOString()}`, + error, + ); + tokenManager.clearAuthToken(); + if (typeof window !== "undefined") { + window.dispatchEvent(new CustomEvent("auth:logout")); } + } } export async function logout(): Promise { - tokenManager.clearAuthToken(); - clearDeviceId(); + tokenManager.clearAuthToken(); + clearDeviceId(); - if (typeof window !== "undefined") { - window.dispatchEvent(new CustomEvent("auth:logout")); - } + if (typeof window !== "undefined") { + window.dispatchEvent(new CustomEvent("auth:logout")); + } } export const authService: AuthService = { - login, - silentRefresh, - declineSessionExtend: clearRefreshTimer, - logout, + login, + silentRefresh, + declineSessionExtend: clearRefreshTimer, + logout, }; diff --git a/apps/sn/src/entities/auth/lib/device-id.ts b/apps/sn/src/entities/auth/lib/device-id.ts deleted file mode 100644 index f844fcbef..000000000 --- a/apps/sn/src/entities/auth/lib/device-id.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { v4 as uuidv4 } from "uuid"; - -const DEVICE_ID_KEY = "x-device-id"; - -export function getOrCreateDeviceId(): string { - if (typeof window === "undefined") return ""; - - const existing = localStorage.getItem(DEVICE_ID_KEY); - if (existing) return existing; - - const id = uuidv4(); - localStorage.setItem(DEVICE_ID_KEY, id); - return id; -} - -export function clearDeviceId(): void { - if (typeof window === "undefined") return; - - localStorage.removeItem(DEVICE_ID_KEY); -} diff --git a/apps/st/package.json b/apps/st/package.json index 08f5bde6b..7ae6c9f53 100644 --- a/apps/st/package.json +++ b/apps/st/package.json @@ -57,7 +57,6 @@ "swr": "^2.3.7", "tailwindcss-animate": "^1.0.7", "tus-js-client": "^4.3.1", - "uuid": "^14.0.1", "xlsx": "^0.18.5", "zod": "^3.24.2", "zustand": "^5.0.3" diff --git a/apps/st/src/entities/auth/api/auth-service.ts b/apps/st/src/entities/auth/api/auth-service.ts index c79034a70..0c3725d22 100644 --- a/apps/st/src/entities/auth/api/auth-service.ts +++ b/apps/st/src/entities/auth/api/auth-service.ts @@ -5,9 +5,13 @@ import { ENDPOINT, } from "@/shared/config"; import { getCookie } from "@/shared/lib"; -import { type AuthPayload, type AuthService } from "@common/auth"; +import { + type AuthPayload, + type AuthService, + clearDeviceId, + getOrCreateDeviceId, +} from "@common/auth"; -import { clearDeviceId, getOrCreateDeviceId } from "../lib/device-id"; import { clearRefreshTimer, setToken, diff --git a/apps/st/src/entities/auth/lib/device-id.ts b/apps/st/src/entities/auth/lib/device-id.ts deleted file mode 100644 index a3b1aa800..000000000 --- a/apps/st/src/entities/auth/lib/device-id.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { v4 as uuidv4 } from "uuid"; - -const DEVICE_ID_KEY = "x-device-id"; - -export function getOrCreateDeviceId(): string { - if (typeof window === "undefined") return ""; - - const existing = localStorage.getItem(DEVICE_ID_KEY); - if (existing) return existing; - - const id = uuidv4(); - localStorage.setItem(DEVICE_ID_KEY, id); - return id; -} - -export function clearDeviceId(): void { - if (typeof window === "undefined") return; - - localStorage.removeItem(DEVICE_ID_KEY); -} diff --git a/apps/wr/package.json b/apps/wr/package.json index 812bc6fa0..3ec9cecfb 100644 --- a/apps/wr/package.json +++ b/apps/wr/package.json @@ -49,7 +49,6 @@ "tailwind-merge": "^3.0.1", "tailwindcss-animate": "^1.0.7", "tus-js-client": "^4.3.1", - "uuid": "^14.0.1", "xlsx": "^0.18.5", "xlsx-populate": "^1.21.0", "zod": "^3.24.2", diff --git a/apps/wr/src/entities/auth/api/auth-service.ts b/apps/wr/src/entities/auth/api/auth-service.ts index 2ea6bab12..4a6ac5fc5 100644 --- a/apps/wr/src/entities/auth/api/auth-service.ts +++ b/apps/wr/src/entities/auth/api/auth-service.ts @@ -1,47 +1,83 @@ import { - ACCESS_TOKEN, - AUTH_USER_ID, - CLAIM_NAME, - ENDPOINT, + ACCESS_TOKEN, + AUTH_USER_ID, + CLAIM_NAME, + ENDPOINT, } from "@/src/shared/config"; import { getCookie } from "@/src/shared/lib"; import { - type AuthPayload, - type AuthService, - getRemainingMs, + clearDeviceId, + getOrCreateDeviceId, + type AuthPayload, + type AuthService, + getRemainingMs, } from "@common/auth"; -import { clearDeviceId, getOrCreateDeviceId } from "../lib/device-id"; import { - clearRefreshTimer, - setToken, - setupRefreshTimer, - tokenManager, + clearRefreshTimer, + setToken, + setupRefreshTimer, + tokenManager, } from "../lib/token-manager"; import { clearTabStorePersist } from "@/src/store/tab-store"; async function login(payload: AuthPayload): Promise { - const response = await fetch(`/api/proxy${ENDPOINT.USER_SERVICE.LOGIN}`, { - method: "POST", + const response = await fetch(`/api/proxy${ENDPOINT.USER_SERVICE.LOGIN}`, { + method: "POST", + headers: { + "Content-Type": "application/json", + "X-Device-Id": getOrCreateDeviceId(), + }, + body: JSON.stringify(payload), + }); + + const data = await response.json(); + + const accessToken = data[ACCESS_TOKEN]; + const tokenId = data[AUTH_USER_ID]; + + if (!accessToken || !tokenId) { + throw new Error("인증 토큰을 받지 못했습니다."); + } + + const prevTokenId = getCookie(AUTH_USER_ID); + if (prevTokenId !== undefined && prevTokenId !== tokenId) { + clearTabStorePersist(); + } + + setToken(CLAIM_NAME, accessToken); + setToken(AUTH_USER_ID, tokenId); + + const remainingMs = getRemainingMs(accessToken); + if (remainingMs > 0) { + setupRefreshTimer(silentRefresh, remainingMs); + } +} + +async function silentRefresh(): Promise { + console.log(`[silentRefresh] Called at ${new Date().toISOString()}`); + try { + const response = await fetch( + `/api/proxy${ENDPOINT.USER_SERVICE.SILENT_REFRESH}`, + { + method: "PUT", headers: { - "Content-Type": "application/json", - "X-Device-Id": getOrCreateDeviceId(), + "X-Device-Id": getOrCreateDeviceId(), }, - body: JSON.stringify(payload), - }); + }, + ); const data = await response.json(); + if (!response.ok) { + throw new Error(data?.message ?? "토큰 갱신에 실패했습니다."); + } + const accessToken = data[ACCESS_TOKEN]; const tokenId = data[AUTH_USER_ID]; if (!accessToken || !tokenId) { - throw new Error("인증 토큰을 받지 못했습니다."); - } - - const prevTokenId = getCookie(AUTH_USER_ID); - if (prevTokenId !== undefined && prevTokenId !== tokenId) { - clearTabStorePersist(); + throw new Error("갱신된 인증 토큰을 받지 못했습니다."); } setToken(CLAIM_NAME, accessToken); @@ -49,67 +85,32 @@ async function login(payload: AuthPayload): Promise { const remainingMs = getRemainingMs(accessToken); if (remainingMs > 0) { - setupRefreshTimer(silentRefresh, remainingMs); + setupRefreshTimer(silentRefresh, remainingMs); } -} - -async function silentRefresh(): Promise { - console.log(`[silentRefresh] Called at ${new Date().toISOString()}`); - try { - const response = await fetch( - `/api/proxy${ENDPOINT.USER_SERVICE.SILENT_REFRESH}`, - { - method: "PUT", - headers: { - "X-Device-Id": getOrCreateDeviceId(), - }, - }, - ); - - const data = await response.json(); - - if (!response.ok) { - throw new Error(data?.message ?? "토큰 갱신에 실패했습니다."); - } - - const accessToken = data[ACCESS_TOKEN]; - const tokenId = data[AUTH_USER_ID]; - - if (!accessToken || !tokenId) { - throw new Error("갱신된 인증 토큰을 받지 못했습니다."); - } - - setToken(CLAIM_NAME, accessToken); - setToken(AUTH_USER_ID, tokenId); - - const remainingMs = getRemainingMs(accessToken); - if (remainingMs > 0) { - setupRefreshTimer(silentRefresh, remainingMs); - } - } catch (error) { - console.error( - `[silentRefresh] Failed at ${new Date().toISOString()}`, - error, - ); - tokenManager.clearAuthToken(); - if (typeof window !== "undefined") { - window.dispatchEvent(new CustomEvent("auth:logout")); - } + } catch (error) { + console.error( + `[silentRefresh] Failed at ${new Date().toISOString()}`, + error, + ); + tokenManager.clearAuthToken(); + if (typeof window !== "undefined") { + window.dispatchEvent(new CustomEvent("auth:logout")); } + } } export async function logout(): Promise { - tokenManager.clearAuthToken(); - clearDeviceId(); + tokenManager.clearAuthToken(); + clearDeviceId(); - if (typeof window !== "undefined") { - window.dispatchEvent(new CustomEvent("auth:logout")); - } + if (typeof window !== "undefined") { + window.dispatchEvent(new CustomEvent("auth:logout")); + } } export const authService: AuthService = { - login, - silentRefresh, - declineSessionExtend: clearRefreshTimer, - logout, + login, + silentRefresh, + declineSessionExtend: clearRefreshTimer, + logout, }; diff --git a/apps/wr/src/entities/auth/lib/device-id.ts b/apps/wr/src/entities/auth/lib/device-id.ts deleted file mode 100644 index f844fcbef..000000000 --- a/apps/wr/src/entities/auth/lib/device-id.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { v4 as uuidv4 } from "uuid"; - -const DEVICE_ID_KEY = "x-device-id"; - -export function getOrCreateDeviceId(): string { - if (typeof window === "undefined") return ""; - - const existing = localStorage.getItem(DEVICE_ID_KEY); - if (existing) return existing; - - const id = uuidv4(); - localStorage.setItem(DEVICE_ID_KEY, id); - return id; -} - -export function clearDeviceId(): void { - if (typeof window === "undefined") return; - - localStorage.removeItem(DEVICE_ID_KEY); -} diff --git a/packages/common/auth/README.md b/packages/common/auth/README.md index fbc8742c5..fd0305dc7 100644 --- a/packages/common/auth/README.md +++ b/packages/common/auth/README.md @@ -19,6 +19,7 @@ packages/common/auth/ ├── types.ts # 타입 정의 ├── token-manager.ts # 토큰 관리 로직 ├── cookie.ts # 쿠키 유틸리티 +├── device-id.ts # 기기 ID (쿠키) ├── jwt-utils.ts # JWT 유틸리티 └── README.md # 문서 ``` diff --git a/packages/common/auth/device-id.ts b/packages/common/auth/device-id.ts new file mode 100644 index 000000000..ffdc1eead --- /dev/null +++ b/packages/common/auth/device-id.ts @@ -0,0 +1,27 @@ +import { v4 as uuidv4 } from "uuid"; +import { getCookie, removeCookie, setCookie } from "./cookie"; + +const DEVICE_ID_KEY = "x-device-id"; +const COOKIE_DOMAIN = process.env.NEXT_PUBLIC_COOKIE_DOMAIN; + +export function getOrCreateDeviceId(): string { + const existing = getCookie(DEVICE_ID_KEY); + if (existing) return existing; + + const id = uuidv4(); + const isHttps = + typeof window !== "undefined" && window.location.protocol === "https:"; + setCookie(DEVICE_ID_KEY, id, { + secure: isHttps, + sameSite: "lax", + domain: COOKIE_DOMAIN, + path: "/", + expires: 365, + }); + + return id; +} + +export function clearDeviceId(): void { + removeCookie(DEVICE_ID_KEY, { path: "/" }); +} diff --git a/packages/common/auth/index.ts b/packages/common/auth/index.ts index a3d7024da..ac5547ed5 100644 --- a/packages/common/auth/index.ts +++ b/packages/common/auth/index.ts @@ -2,6 +2,7 @@ export { createTokenManager } from "./token-manager"; export type { TokenManager } from "./token-manager"; export { getCookie, setCookie, removeCookie } from "./cookie"; +export { clearDeviceId, getOrCreateDeviceId } from "./device-id"; export { getJwtExpiry, getRemainingMs, diff --git a/packages/common/auth/package.json b/packages/common/auth/package.json index 4baa26d35..aa45f6a99 100644 --- a/packages/common/auth/package.json +++ b/packages/common/auth/package.json @@ -8,7 +8,8 @@ ".": "./index.ts" }, "dependencies": { - "js-cookie": "^3.0.5" + "js-cookie": "^3.0.5", + "uuid": "^14.0.1" }, "devDependencies": { "@types/js-cookie": "^3.0.6", diff --git a/packages/common/auth/tsconfig.json b/packages/common/auth/tsconfig.json index 04a0208c5..a46cfb4a7 100644 --- a/packages/common/auth/tsconfig.json +++ b/packages/common/auth/tsconfig.json @@ -3,6 +3,7 @@ "extends": "../../../tsconfig.base.json", "compilerOptions": { "target": "ES2017", + "types": ["node"], "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, diff --git a/packages/common/components/tsconfig.json b/packages/common/components/tsconfig.json index 9fa9e88ee..9ee9a8868 100644 --- a/packages/common/components/tsconfig.json +++ b/packages/common/components/tsconfig.json @@ -12,9 +12,8 @@ "noEmit": false, "incremental": true, "strict": true, - "baseUrl": ".", "paths": { - "@/*": ["src/*"] + "@/*": ["./src/*"] } }, "exclude": ["**/node_modules", "**/.*/*", "dist"], diff --git a/packages/common/network/client.ts b/packages/common/network/client.ts index 6b39a33fa..f222bff3f 100644 --- a/packages/common/network/client.ts +++ b/packages/common/network/client.ts @@ -9,6 +9,8 @@ interface ClientConfig { siteId: string; } +const DEVICE_ID_KEY = "x-device-id"; + class Client { private static instance: Client; private axiosInstance: AxiosInstance; @@ -26,6 +28,7 @@ class Client { this.axiosInstance.interceptors.request.use((config) => { const token = Cookies.get(CLAIM_NAME); const userId = Cookies.get(AUTH_USER_ID); + const deviceId = Cookies.get(DEVICE_ID_KEY); if (!token || !userId) { return config; @@ -33,6 +36,7 @@ class Client { config.headers[CLAIM_NAME] = token; config.headers[AUTH_USER_ID] = userId; + config.headers["X-Device-Id"] = deviceId; return config; }); diff --git a/packages/common/network/tsconfig.json b/packages/common/network/tsconfig.json index 7f4dcf889..12e1ce819 100644 --- a/packages/common/network/tsconfig.json +++ b/packages/common/network/tsconfig.json @@ -2,8 +2,8 @@ "$schema": "https://json.schemastore.org/tsconfig", "extends": "../../../tsconfig.base.json", "compilerOptions": { - "baseUrl": ".", - "module": "ESNext" + "module": "ESNext", + "types": ["node"] }, "include": ["."], "exclude": ["node_modules", "dist"] diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 214b99a21..c1c687666 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -104,10 +104,10 @@ importers: devDependencies: eslint: specifier: ^9.0.0 - version: 9.39.4(jiti@1.21.7) + version: 9.39.4(jiti@2.6.1) eslint-config-next: specifier: 15.3.8 - version: 15.3.8(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3) + version: 15.3.8(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) postcss: specifier: ^8.4.49 version: 8.5.8 @@ -195,9 +195,6 @@ importers: tus-js-client: specifier: ^4.3.1 version: 4.3.1 - uuid: - specifier: ^14.0.1 - version: 14.0.1 zod: specifier: ^3.24.2 version: 3.25.76 @@ -352,9 +349,6 @@ importers: tus-js-client: specifier: ^4.3.1 version: 4.3.1 - uuid: - specifier: ^14.0.1 - version: 14.0.1 zod: specifier: ^3.24.2 version: 3.25.76 @@ -639,9 +633,6 @@ importers: tus-js-client: specifier: ^4.3.1 version: 4.3.1 - uuid: - specifier: ^14.0.1 - version: 14.0.1 zod: specifier: ^3.24.2 version: 3.25.76 @@ -951,9 +942,6 @@ importers: select: specifier: ^1.1.2 version: 1.1.2 - uuid: - specifier: ^14.0.1 - version: 14.0.1 webpack: specifier: ^5.98.0 version: 5.105.4 @@ -1078,9 +1066,6 @@ importers: tus-js-client: specifier: ^4.3.1 version: 4.3.1 - uuid: - specifier: ^14.0.1 - version: 14.0.1 xlsx: specifier: ^0.18.5 version: 0.18.5 @@ -1280,9 +1265,6 @@ importers: tus-js-client: specifier: ^4.3.1 version: 4.3.1 - uuid: - specifier: ^14.0.1 - version: 14.0.1 xlsx: specifier: ^0.18.5 version: 0.18.5 @@ -1440,9 +1422,6 @@ importers: tus-js-client: specifier: ^4.3.1 version: 4.3.1 - uuid: - specifier: ^14.0.1 - version: 14.0.1 xlsx: specifier: ^0.18.5 version: 0.18.5 @@ -1495,6 +1474,9 @@ importers: js-cookie: specifier: ^3.0.5 version: 3.0.5 + uuid: + specifier: ^14.0.1 + version: 14.0.1 devDependencies: '@types/js-cookie': specifier: ^3.0.6 @@ -1848,7 +1830,7 @@ importers: version: 8.6.18(@storybook/test@8.6.15(storybook@8.6.18(prettier@3.8.1)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@8.6.18(prettier@3.8.1))(typescript@5.6.3) '@storybook/react-vite': specifier: ^8.5.3 - version: 8.6.18(@storybook/test@8.6.15(storybook@8.6.18(prettier@3.8.1)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rollup@4.60.0)(storybook@8.6.18(prettier@3.8.1))(typescript@5.6.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3)) + version: 8.6.18(@storybook/test@8.6.15(storybook@8.6.18(prettier@3.8.1)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rollup@4.60.0)(storybook@8.6.18(prettier@3.8.1))(typescript@5.6.3)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3)) '@storybook/test': specifier: ^8.5.3 version: 8.6.15(storybook@8.6.18(prettier@3.8.1)) @@ -1860,22 +1842,22 @@ importers: version: 22.19.15 '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3)) + version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3)) autoprefixer: specifier: ^10.4.20 version: 10.4.27(postcss@8.5.8) eslint: specifier: ^9.17.0 - version: 9.39.4(jiti@2.6.1) + version: 9.39.4(jiti@1.21.7) eslint-plugin-react-hooks: specifier: ^5.0.0 - version: 5.2.0(eslint@9.39.4(jiti@2.6.1)) + version: 5.2.0(eslint@9.39.4(jiti@1.21.7)) eslint-plugin-react-refresh: specifier: ^0.4.16 - version: 0.4.26(eslint@9.39.4(jiti@2.6.1)) + version: 0.4.26(eslint@9.39.4(jiti@1.21.7)) eslint-plugin-storybook: specifier: ^0.11.2 - version: 0.11.6(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3) + version: 0.11.6(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3) globals: specifier: ^15.14.0 version: 15.15.0 @@ -1896,19 +1878,19 @@ importers: version: 3.4.19(yaml@2.8.3) tsup: specifier: 8.3.6 - version: 8.3.6(jiti@2.6.1)(postcss@8.5.8)(typescript@5.6.3)(yaml@2.8.3) + version: 8.3.6(jiti@1.21.7)(postcss@8.5.8)(typescript@5.6.3)(yaml@2.8.3) typescript: specifier: ~5.6.2 version: 5.6.3 typescript-eslint: specifier: ^8.18.2 - version: 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3) + version: 8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3) vite: specifier: ^6.0.5 - version: 6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3) + version: 6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3) vite-tsconfig-paths: specifier: 5.1.4 - version: 5.1.4(typescript@5.6.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3)) + version: 5.1.4(typescript@5.6.3)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3)) packages/common/config: devDependencies: @@ -8384,6 +8366,15 @@ snapshots: wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 + '@joshwooding/vite-plugin-react-docgen-typescript@0.5.0(typescript@5.6.3)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))': + dependencies: + glob: 10.5.0 + magic-string: 0.27.0 + react-docgen-typescript: 2.4.0(typescript@5.6.3) + vite: 6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3) + optionalDependencies: + typescript: 5.6.3 + '@joshwooding/vite-plugin-react-docgen-typescript@0.5.0(typescript@5.6.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))': dependencies: glob: 10.5.0 @@ -9286,6 +9277,14 @@ snapshots: react: 19.2.4 react-dom: 19.2.4(react@19.2.4) + '@storybook/builder-vite@8.6.18(storybook@8.6.18(prettier@3.8.1))(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))': + dependencies: + '@storybook/csf-plugin': 8.6.18(storybook@8.6.18(prettier@3.8.1)) + browser-assert: 1.2.1 + storybook: 8.6.18(prettier@3.8.1) + ts-dedent: 2.2.0 + vite: 6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3) + '@storybook/builder-vite@8.6.18(storybook@8.6.18(prettier@3.8.1))(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))': dependencies: '@storybook/csf-plugin': 8.6.18(storybook@8.6.18(prettier@3.8.1)) @@ -9376,6 +9375,28 @@ snapshots: react-dom: 19.2.4(react@19.2.4) storybook: 8.6.18(prettier@3.8.1) + '@storybook/react-vite@8.6.18(@storybook/test@8.6.15(storybook@8.6.18(prettier@3.8.1)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rollup@4.60.0)(storybook@8.6.18(prettier@3.8.1))(typescript@5.6.3)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))': + dependencies: + '@joshwooding/vite-plugin-react-docgen-typescript': 0.5.0(typescript@5.6.3)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3)) + '@rollup/pluginutils': 5.3.0(rollup@4.60.0) + '@storybook/builder-vite': 8.6.18(storybook@8.6.18(prettier@3.8.1))(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3)) + '@storybook/react': 8.6.18(@storybook/test@8.6.15(storybook@8.6.18(prettier@3.8.1)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@8.6.18(prettier@3.8.1))(typescript@5.6.3) + find-up: 5.0.0 + magic-string: 0.30.21 + react: 19.2.4 + react-docgen: 7.1.1 + react-dom: 19.2.4(react@19.2.4) + resolve: 1.22.11 + storybook: 8.6.18(prettier@3.8.1) + tsconfig-paths: 4.2.0 + vite: 6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3) + optionalDependencies: + '@storybook/test': 8.6.15(storybook@8.6.18(prettier@3.8.1)) + transitivePeerDependencies: + - rollup + - supports-color + - typescript + '@storybook/react-vite@8.6.18(@storybook/test@8.6.15(storybook@8.6.18(prettier@3.8.1)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rollup@4.60.0)(storybook@8.6.18(prettier@3.8.1))(typescript@5.6.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))': dependencies: '@joshwooding/vite-plugin-react-docgen-typescript': 0.5.0(typescript@5.6.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3)) @@ -9683,26 +9704,26 @@ snapshots: dependencies: xlsx: 0.18.5 - '@typescript-eslint/eslint-plugin@8.57.2(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.57.2(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3))(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/parser': 8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3) '@typescript-eslint/scope-manager': 8.57.2 - '@typescript-eslint/type-utils': 8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3) - '@typescript-eslint/utils': 8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/type-utils': 8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3) + '@typescript-eslint/utils': 8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3) '@typescript-eslint/visitor-keys': 8.57.2 eslint: 9.39.4(jiti@1.21.7) ignore: 7.0.5 natural-compare: 1.4.0 - ts-api-utils: 2.5.0(typescript@5.9.3) - typescript: 5.9.3 + ts-api-utils: 2.5.0(typescript@5.6.3) + typescript: 5.6.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/eslint-plugin@8.57.2(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3)': + '@typescript-eslint/eslint-plugin@8.57.2(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3) + '@typescript-eslint/parser': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/scope-manager': 8.57.2 '@typescript-eslint/type-utils': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3) '@typescript-eslint/utils': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3) @@ -9731,15 +9752,15 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3)': + '@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3)': dependencies: '@typescript-eslint/scope-manager': 8.57.2 '@typescript-eslint/types': 8.57.2 - '@typescript-eslint/typescript-estree': 8.57.2(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.57.2(typescript@5.6.3) '@typescript-eslint/visitor-keys': 8.57.2 debug: 4.4.3 eslint: 9.39.4(jiti@1.21.7) - typescript: 5.9.3 + typescript: 5.6.3 transitivePeerDependencies: - supports-color @@ -9798,15 +9819,15 @@ snapshots: dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3)': dependencies: '@typescript-eslint/types': 8.57.2 - '@typescript-eslint/typescript-estree': 8.57.2(typescript@5.9.3) - '@typescript-eslint/utils': 8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.57.2(typescript@5.6.3) + '@typescript-eslint/utils': 8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3) debug: 4.4.3 eslint: 9.39.4(jiti@1.21.7) - ts-api-utils: 2.5.0(typescript@5.9.3) - typescript: 5.9.3 + ts-api-utils: 2.5.0(typescript@5.6.3) + typescript: 5.6.3 transitivePeerDependencies: - supports-color @@ -9866,14 +9887,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3)': + '@typescript-eslint/utils@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3)': dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@1.21.7)) '@typescript-eslint/scope-manager': 8.57.2 '@typescript-eslint/types': 8.57.2 - '@typescript-eslint/typescript-estree': 8.57.2(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.57.2(typescript@5.6.3) eslint: 9.39.4(jiti@1.21.7) - typescript: 5.9.3 + typescript: 5.6.3 transitivePeerDependencies: - supports-color @@ -9963,6 +9984,18 @@ snapshots: '@unrs/resolver-binding-win32-x64-msvc@1.11.1': optional: true + '@vitejs/plugin-react@4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))': + dependencies: + '@babel/core': 7.29.0 + '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.29.0) + '@rolldown/pluginutils': 1.0.0-beta.27 + '@types/babel__core': 7.20.5 + react-refresh: 0.17.0 + vite: 6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3) + transitivePeerDependencies: + - supports-color + '@vitejs/plugin-react@4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))': dependencies: '@babel/core': 7.29.0 @@ -10991,26 +11024,6 @@ snapshots: optionalDependencies: source-map: 0.7.6 - eslint-config-next@15.3.8(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3): - dependencies: - '@next/eslint-plugin-next': 15.3.8 - '@rushstack/eslint-patch': 1.16.1 - '@typescript-eslint/eslint-plugin': 8.57.2(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3) - '@typescript-eslint/parser': 8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3) - eslint: 9.39.4(jiti@1.21.7) - eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@1.21.7)) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.4(jiti@1.21.7)) - eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.4(jiti@1.21.7)) - eslint-plugin-react: 7.37.5(eslint@9.39.4(jiti@1.21.7)) - eslint-plugin-react-hooks: 5.2.0(eslint@9.39.4(jiti@1.21.7)) - optionalDependencies: - typescript: 5.9.3 - transitivePeerDependencies: - - eslint-import-resolver-webpack - - eslint-plugin-import-x - - supports-color - eslint-config-next@15.3.8(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3): dependencies: '@next/eslint-plugin-next': 15.3.8 @@ -11039,21 +11052,6 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@1.21.7)): - dependencies: - '@nolyfill/is-core-module': 1.0.39 - debug: 4.4.3 - eslint: 9.39.4(jiti@1.21.7) - get-tsconfig: 4.13.7 - is-bun-module: 2.0.0 - stable-hash: 0.0.5 - tinyglobby: 0.2.15 - unrs-resolver: 1.11.1 - optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.4(jiti@1.21.7)) - transitivePeerDependencies: - - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@2.6.1)): dependencies: '@nolyfill/is-core-module': 1.0.39 @@ -11069,17 +11067,6 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@1.21.7)): - dependencies: - debug: 3.2.7 - optionalDependencies: - '@typescript-eslint/parser': 8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3) - eslint: 9.39.4(jiti@1.21.7) - eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@1.21.7)) - transitivePeerDependencies: - - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.6.1)): dependencies: debug: 3.2.7 @@ -11091,35 +11078,6 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.4(jiti@1.21.7)): - dependencies: - '@rtsao/scc': 1.1.0 - array-includes: 3.1.9 - array.prototype.findlastindex: 1.2.6 - array.prototype.flat: 1.3.3 - array.prototype.flatmap: 1.3.3 - debug: 3.2.7 - doctrine: 2.1.0 - eslint: 9.39.4(jiti@1.21.7) - eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@1.21.7)) - hasown: 2.0.2 - is-core-module: 2.16.1 - is-glob: 4.0.3 - minimatch: 3.1.5 - object.fromentries: 2.0.8 - object.groupby: 1.0.3 - object.values: 1.2.1 - semver: 6.3.1 - string.prototype.trimend: 1.0.9 - tsconfig-paths: 3.15.0 - optionalDependencies: - '@typescript-eslint/parser': 8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3) - transitivePeerDependencies: - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.6.1)): dependencies: '@rtsao/scc': 1.1.0 @@ -11149,25 +11107,6 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.4(jiti@1.21.7)): - dependencies: - aria-query: 5.3.2 - array-includes: 3.1.9 - array.prototype.flatmap: 1.3.3 - ast-types-flow: 0.0.8 - axe-core: 4.11.1 - axobject-query: 4.1.0 - damerau-levenshtein: 1.0.8 - emoji-regex: 9.2.2 - eslint: 9.39.4(jiti@1.21.7) - hasown: 2.0.2 - jsx-ast-utils: 3.3.5 - language-tags: 1.0.9 - minimatch: 3.1.5 - object.fromentries: 2.0.8 - safe-regex-test: 1.1.0 - string.prototype.includes: 2.0.1 - eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.4(jiti@2.6.1)): dependencies: aria-query: 5.3.2 @@ -11195,32 +11134,14 @@ snapshots: dependencies: eslint: 9.39.4(jiti@2.6.1) + eslint-plugin-react-refresh@0.4.26(eslint@9.39.4(jiti@1.21.7)): + dependencies: + eslint: 9.39.4(jiti@1.21.7) + eslint-plugin-react-refresh@0.4.26(eslint@9.39.4(jiti@2.6.1)): dependencies: eslint: 9.39.4(jiti@2.6.1) - eslint-plugin-react@7.37.5(eslint@9.39.4(jiti@1.21.7)): - dependencies: - array-includes: 3.1.9 - array.prototype.findlast: 1.2.5 - array.prototype.flatmap: 1.3.3 - array.prototype.tosorted: 1.1.4 - doctrine: 2.1.0 - es-iterator-helpers: 1.3.1 - eslint: 9.39.4(jiti@1.21.7) - estraverse: 5.3.0 - hasown: 2.0.2 - jsx-ast-utils: 3.3.5 - minimatch: 3.1.5 - object.entries: 1.1.9 - object.fromentries: 2.0.8 - object.values: 1.2.1 - prop-types: 15.8.1 - resolve: 2.0.0-next.6 - semver: 6.3.1 - string.prototype.matchall: 4.0.12 - string.prototype.repeat: 1.0.0 - eslint-plugin-react@7.37.5(eslint@9.39.4(jiti@2.6.1)): dependencies: array-includes: 3.1.9 @@ -11247,6 +11168,16 @@ snapshots: dependencies: eslint: 9.39.4(jiti@2.6.1) + eslint-plugin-storybook@0.11.6(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3): + dependencies: + '@storybook/csf': 0.1.13 + '@typescript-eslint/utils': 8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3) + eslint: 9.39.4(jiti@1.21.7) + ts-dedent: 2.2.0 + transitivePeerDependencies: + - supports-color + - typescript + eslint-plugin-storybook@0.11.6(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3): dependencies: '@storybook/csf': 0.1.13 @@ -13341,6 +13272,33 @@ snapshots: tslib@2.8.1: {} + tsup@8.3.6(jiti@1.21.7)(postcss@8.5.8)(typescript@5.6.3)(yaml@2.8.3): + dependencies: + bundle-require: 5.1.0(esbuild@0.24.2) + cac: 6.7.14 + chokidar: 4.0.3 + consola: 3.4.2 + debug: 4.4.3 + esbuild: 0.24.2 + joycon: 3.1.1 + picocolors: 1.1.1 + postcss-load-config: 6.0.1(jiti@1.21.7)(postcss@8.5.8)(yaml@2.8.3) + resolve-from: 5.0.0 + rollup: 4.60.0 + source-map: 0.7.6 + sucrase: 3.35.1 + tinyexec: 0.3.2 + tinyglobby: 0.2.15 + tree-kill: 1.2.2 + optionalDependencies: + postcss: 8.5.8 + typescript: 5.6.3 + transitivePeerDependencies: + - jiti + - supports-color + - tsx + - yaml + tsup@8.3.6(jiti@2.6.1)(postcss@8.5.8)(typescript@5.6.3)(yaml@2.8.3): dependencies: bundle-require: 5.1.0(esbuild@0.24.2) @@ -13471,9 +13429,20 @@ snapshots: possible-typed-array-names: 1.1.0 reflect.getprototypeof: 1.0.10 + typescript-eslint@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3): + dependencies: + '@typescript-eslint/eslint-plugin': 8.57.2(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3))(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3) + '@typescript-eslint/parser': 8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3) + '@typescript-eslint/typescript-estree': 8.57.2(typescript@5.6.3) + '@typescript-eslint/utils': 8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3) + eslint: 9.39.4(jiti@1.21.7) + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color + typescript-eslint@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.57.2(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3) + '@typescript-eslint/eslint-plugin': 8.57.2(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3) '@typescript-eslint/parser': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3) '@typescript-eslint/typescript-estree': 8.57.2(typescript@5.6.3) '@typescript-eslint/utils': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3) @@ -13599,6 +13568,17 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 + vite-tsconfig-paths@5.1.4(typescript@5.6.3)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3)): + dependencies: + debug: 4.4.3 + globrex: 0.1.2 + tsconfck: 3.1.6(typescript@5.6.3) + optionalDependencies: + vite: 6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3) + transitivePeerDependencies: + - supports-color + - typescript + vite-tsconfig-paths@5.1.4(typescript@5.6.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3)): dependencies: debug: 4.4.3 @@ -13621,6 +13601,22 @@ snapshots: lightningcss: 1.32.0 terser: 5.46.1 + vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3): + dependencies: + esbuild: 0.25.12 + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + postcss: 8.5.8 + rollup: 4.60.0 + tinyglobby: 0.2.15 + optionalDependencies: + '@types/node': 22.19.15 + fsevents: 2.3.3 + jiti: 1.21.7 + lightningcss: 1.32.0 + terser: 5.46.1 + yaml: 2.8.3 + vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3): dependencies: esbuild: 0.25.12