diff --git a/.gitignore b/.gitignore
index a0f0e53..82da4af 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,39 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# Dependencies
+node_modules
+.pnp
+.pnp.js
+
+# Local env files
+.env
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+
+# Testing
+coverage
+
+# Turbo
+.turbo
+
+# Vercel
+.vercel
+
+# Build Outputs
+.next/
+out/
+build
+dist
+
+
+# Debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Misc
.vscode
.DS_Store
+*.pem
diff --git a/.husky/pre-commit b/.husky/pre-commit
new file mode 100644
index 0000000..d4b4a3b
--- /dev/null
+++ b/.husky/pre-commit
@@ -0,0 +1 @@
+pnpm nano-staged
\ No newline at end of file
diff --git a/.nanostagedrc b/.nanostagedrc
new file mode 100644
index 0000000..af87dd4
--- /dev/null
+++ b/.nanostagedrc
@@ -0,0 +1,6 @@
+{
+ "*.{ts,tsx,json,jsonc}": [
+ "biome format --write",
+ "biome lint"
+ ]
+}
diff --git a/.nvmrc b/.nvmrc
new file mode 100644
index 0000000..d79a9a2
--- /dev/null
+++ b/.nvmrc
@@ -0,0 +1 @@
+v20.13.0
\ No newline at end of file
diff --git a/README.md b/README.md
index b994bf7..7ac0fd6 100644
--- a/README.md
+++ b/README.md
@@ -1,24 +1,28 @@
# functional-javascript-programming
+
함수형 자바스크립트 프로그래밍

# 시간 및 장소
+
- 시간: 매주 일요일 16시
- 장소: 디스코드
# 방식
+
- 주 1회 온라인 환경인 디스코드에서 진행합니다.
- 최대한 해당 책을 기반으로 코드를 많이 짜보는 것을 목표로 합니다.
- 스터디 진행 전에 주 차별 챕터를 읽고 정리합니다. 마크 다운 기반으로 정리를 하고 형식은 자유입니다. 논의하고 싶은 사항이 있다면 포함합니다.
- 정리가 완료되면 스터디 전까지 Github 레포의 해당되는 주차의 폴더에 업로드를 합니다. ([참고](https://github.com/FEBookStudy/Grokking-Simplicity))
- - 파일 이름 형식: 이름.md
- - 커밋 형식: `docs: 업데이트 내용`
+ - 파일 이름 형식: 이름.md
+ - 커밋 형식: `docs: 업데이트 내용`
- 온라인으로 스터디 진행 전에 발표자 1명을 무작위로 선정해 발표를 진행합니다.
- 발표 후에 궁금한 점, 논의가 필요한 점을 이야기합니다.
- - 해당 내용은 질문, 논의별 [Issue](https://github.com/FEBookStudy/Grokking-Simplicity/issues)를 생성해 기록합니다.
+ - 해당 내용은 질문, 논의별 [Issue](https://github.com/FEBookStudy/Grokking-Simplicity/issues)를 생성해 기록합니다.
# 발표 방식
+
- 주차 별 브랜치에 정리한 내용을 commit합니다. (`week-1` 브랜치에 `/docs/1주차/이름.md`)
- 발표 당일에 `main` 브랜치로 PR을 합니다.
- CODEOWNERS와 팀 설정으로 reviewer가 1명 자동 선정됩니다. (Load balance)
@@ -27,17 +31,17 @@
# 스터디 상세 일정표
-| **주차** | **날짜** | **학습 내용** |
-|---------|-------------|--------------------------------------------|
-| **0주차** | 11/25 (20시) | OT 및 스터디 방식 상세 논의 |
-| **1주차** | 12/8 | 1장 함수형 자바스크립트 소개 |
-| **2주차** | 12/15 | 2장 함수형 자바스크립트를 위한 문법 다시 보기 |
-| **3주차** | 12/22 | 3장 Underscore.js를 직접 만들며 함수형 자바스크립트의 뼈대 익히기 |
-| **4주차** | 12/29 | 4장 함수 조립하기 |
-| **5주차** | 1/5 | 5장 Partial.js와 함수 조립 |
-| **6주차** | 1/12 | 6장 값에 대해 & 7장 실전에서 함수형 자바스크립트 더 많이 사용하기 |
-| **7주차** | 1/19 | 8장 함수형으로 만드는 할 일 앱 & 9장 메모이제이션 & 회고 |
-
+| **주차** | **날짜** | **학습 내용** |
+| --------- | ------------ | ----------------------------------------------------------------- |
+| **0주차** | 11/25 (20시) | OT 및 스터디 방식 상세 논의 |
+| **1주차** | 12/8 | 1장 함수형 자바스크립트 소개 |
+| **2주차** | 12/15 | 2장 함수형 자바스크립트를 위한 문법 다시 보기 |
+| **3주차** | 12/22 | 3장 Underscore.js를 직접 만들며 함수형 자바스크립트의 뼈대 익히기 |
+| **4주차** | 12/29 | 4장 함수 조립하기 |
+| **5주차** | 1/5 | 5장 Partial.js와 함수 조립 |
+| **6주차** | 1/12 | 6장 값에 대해 & 7장 실전에서 함수형 자바스크립트 더 많이 사용하기 |
+| **7주차** | 1/19 | 8장 함수형으로 만드는 할 일 앱 & 9장 메모이제이션 & 회고 |
# 함수형 자바스크립트 서적 깃허브 참고
+
https://github.com/indongyoo/functional-javascript
diff --git a/biome.json b/biome.json
new file mode 100644
index 0000000..448be1d
--- /dev/null
+++ b/biome.json
@@ -0,0 +1,42 @@
+{
+ "$schema": "https://biomejs.dev/schemas/1.7.0/schema.json",
+ "organizeImports": {
+ "enabled": true
+ },
+ "linter": {
+ "enabled": true,
+ "ignore": ["node_modules", "dist", ".next"],
+ "rules": {
+ "recommended": true,
+ "style": {
+ "useBlockStatements": "error"
+ }
+ }
+ },
+ "formatter": {
+ "enabled": true,
+ "indentWidth": 2,
+ "indentStyle": "space",
+ "lineWidth": 100,
+ "ignore": ["node_modules", "dist", ".next"]
+ },
+ "json": {
+ "parser": {
+ "allowTrailingCommas": true
+ },
+ "formatter": {
+ "enabled": true
+ }
+ },
+ "javascript": {
+ "formatter": {
+ "enabled": true,
+ "quoteStyle": "single",
+ "jsxQuoteStyle": "double",
+ "trailingComma": "all",
+ "semicolons": "asNeeded",
+ "arrowParentheses": "always",
+ "quoteProperties": "asNeeded"
+ }
+ }
+}
diff --git a/cspell.json b/cspell.json
new file mode 100644
index 0000000..40b1379
--- /dev/null
+++ b/cspell.json
@@ -0,0 +1,3 @@
+{
+ "words": ["functional-javascript-programming", "hyobum"]
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..6563744
--- /dev/null
+++ b/package.json
@@ -0,0 +1,26 @@
+{
+ "name": "functional-javascript-programming",
+ "private": true,
+ "scripts": {
+ "clean:branch": "git fetch --prune && git branch | grep -v '^*' | xargs git branch -D",
+ "clean:cache": "turbo clean",
+ "build:all": "turbo build",
+ "start": "turbo start",
+ "lint": "turbo lint",
+ "format": "turbo format",
+ "prepare": "husky",
+ "preinstall": "corepack enable"
+ },
+ "devDependencies": {
+ "@biomejs/biome": "1.7.3",
+ "husky": "^9.0.11",
+ "nano-staged": "^0.8.0",
+ "turbo": "^2.0.7",
+ "typescript": "^5.4.5",
+ "@types/node": "20.13.0"
+ },
+ "packageManager": "pnpm@9.1.0",
+ "engines": {
+ "node": "20.13.0"
+ }
+}
diff --git a/playground/README.md b/playground/README.md
index 74872fd..7c8d451 100644
--- a/playground/README.md
+++ b/playground/README.md
@@ -1,50 +1 @@
-# React + TypeScript + Vite
-
-This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
-
-Currently, two official plugins are available:
-
-- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
-- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
-
-## Expanding the ESLint configuration
-
-If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
-
-- Configure the top-level `parserOptions` property like this:
-
-```js
-export default tseslint.config({
- languageOptions: {
- // other options...
- parserOptions: {
- project: ['./tsconfig.node.json', './tsconfig.app.json'],
- tsconfigRootDir: import.meta.dirname,
- },
- },
-})
-```
-
-- Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked`
-- Optionally add `...tseslint.configs.stylisticTypeChecked`
-- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and update the config:
-
-```js
-// eslint.config.js
-import react from 'eslint-plugin-react'
-
-export default tseslint.config({
- // Set the react version
- settings: { react: { version: '18.3' } },
- plugins: {
- // Add the react plugin
- react,
- },
- rules: {
- // other rules...
- // Enable its recommended rules
- ...react.configs.recommended.rules,
- ...react.configs['jsx-runtime'].rules,
- },
-})
-```
+# functional-javascript-programming playground
diff --git a/playground/.gitignore b/playground/apps/home/.gitignore
similarity index 100%
rename from playground/.gitignore
rename to playground/apps/home/.gitignore
diff --git a/playground/apps/home/README.md b/playground/apps/home/README.md
new file mode 100644
index 0000000..780c92d
--- /dev/null
+++ b/playground/apps/home/README.md
@@ -0,0 +1,50 @@
+# React + TypeScript + Vite
+
+This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
+
+Currently, two official plugins are available:
+
+- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
+- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
+
+## Expanding the ESLint configuration
+
+If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
+
+- Configure the top-level `parserOptions` property like this:
+
+```js
+export default tseslint.config({
+ languageOptions: {
+ // other options...
+ parserOptions: {
+ project: ["./tsconfig.node.json", "./tsconfig.app.json"],
+ tsconfigRootDir: import.meta.dirname,
+ },
+ },
+});
+```
+
+- Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked`
+- Optionally add `...tseslint.configs.stylisticTypeChecked`
+- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and update the config:
+
+```js
+// eslint.config.js
+import react from "eslint-plugin-react";
+
+export default tseslint.config({
+ // Set the react version
+ settings: { react: { version: "18.3" } },
+ plugins: {
+ // Add the react plugin
+ react,
+ },
+ rules: {
+ // other rules...
+ // Enable its recommended rules
+ ...react.configs.recommended.rules,
+ ...react.configs["jsx-runtime"].rules,
+ },
+});
+```
diff --git a/playground/apps/home/eslint.config.js b/playground/apps/home/eslint.config.js
new file mode 100644
index 0000000..0bbf074
--- /dev/null
+++ b/playground/apps/home/eslint.config.js
@@ -0,0 +1,28 @@
+import js from "@eslint/js";
+import globals from "globals";
+import reactHooks from "eslint-plugin-react-hooks";
+import reactRefresh from "eslint-plugin-react-refresh";
+import tseslint from "typescript-eslint";
+
+export default tseslint.config(
+ { ignores: ["dist"] },
+ {
+ extends: [js.configs.recommended, ...tseslint.configs.recommended],
+ files: ["**/*.{ts,tsx}"],
+ languageOptions: {
+ ecmaVersion: 2020,
+ globals: globals.browser,
+ },
+ plugins: {
+ "react-hooks": reactHooks,
+ "react-refresh": reactRefresh,
+ },
+ rules: {
+ ...reactHooks.configs.recommended.rules,
+ "react-refresh/only-export-components": [
+ "warn",
+ { allowConstantExport: true },
+ ],
+ },
+ }
+);
diff --git a/playground/index.html b/playground/apps/home/index.html
similarity index 95%
rename from playground/index.html
rename to playground/apps/home/index.html
index e4b78ea..e0d1c84 100644
--- a/playground/index.html
+++ b/playground/apps/home/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/playground/apps/home/package.json b/playground/apps/home/package.json
new file mode 100644
index 0000000..0d26381
--- /dev/null
+++ b/playground/apps/home/package.json
@@ -0,0 +1,36 @@
+{
+ "name": "home",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "lint": "biome lint ./src",
+ "format": "biome format ./src --write",
+ "dev": "vite",
+ "build": "tsc -b && vite build",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@functional-javascript-programming/utils": "workspace:*",
+ "axios": "^1.7.9",
+ "js-cookie": "^3.0.5",
+ "react": "^18.3.1",
+ "react-dom": "^18.3.1",
+ "react-router-dom": "^7.0.2"
+ },
+ "devDependencies": {
+ "@eslint/js": "^9.15.0",
+ "@originjs/vite-plugin-federation": "^1.3.6",
+ "@types/js-cookie": "^3.0.6",
+ "@types/react": "^18.3.12",
+ "@types/react-dom": "^18.3.1",
+ "@vitejs/plugin-react-swc": "^3.5.0",
+ "eslint": "^9.15.0",
+ "eslint-plugin-react-hooks": "^5.0.0",
+ "eslint-plugin-react-refresh": "^0.4.14",
+ "globals": "^15.12.0",
+ "typescript": "~5.6.2",
+ "typescript-eslint": "^8.15.0",
+ "vite": "^6.0.1"
+ }
+}
diff --git a/playground/public/vite.svg b/playground/apps/home/public/vite.svg
similarity index 100%
rename from playground/public/vite.svg
rename to playground/apps/home/public/vite.svg
diff --git a/playground/src/App.css b/playground/apps/home/src/App.css
similarity index 80%
rename from playground/src/App.css
rename to playground/apps/home/src/App.css
index b9d355d..172761c 100644
--- a/playground/src/App.css
+++ b/playground/apps/home/src/App.css
@@ -1,10 +1,3 @@
-#root {
- max-width: 1280px;
- margin: 0 auto;
- padding: 2rem;
- text-align: center;
-}
-
.logo {
height: 6em;
padding: 1.5em;
@@ -34,9 +27,14 @@
}
.card {
- padding: 2em;
+ width: 400px;
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ margin: 0 auto;
+ padding: 0;
}
.read-the-docs {
- color: #888;
+ color: var(--blue-300);
}
diff --git a/playground/apps/home/src/App.tsx b/playground/apps/home/src/App.tsx
new file mode 100644
index 0000000..7156f85
--- /dev/null
+++ b/playground/apps/home/src/App.tsx
@@ -0,0 +1,20 @@
+import { BrowserRouter } from 'react-router-dom'
+
+import './App.css'
+import Router from './router'
+
+interface Props {
+ hello?: string
+}
+
+function App({ hello }: Props) {
+ console.log('hello:', hello)
+
+ return (
+
+
+
+ )
+}
+
+export default App
diff --git a/playground/apps/home/src/apis/index.ts b/playground/apps/home/src/apis/index.ts
new file mode 100644
index 0000000..6e7898a
--- /dev/null
+++ b/playground/apps/home/src/apis/index.ts
@@ -0,0 +1,10 @@
+import axios, { type AxiosInstance } from 'axios'
+
+export const axiosInstance: AxiosInstance = axios.create({
+ withCredentials: true,
+ baseURL: '/common',
+ headers: {
+ dataType: 'json',
+ contentType: 'application/x-www-form-urlencoded',
+ },
+})
diff --git a/playground/src/assets/react.svg b/playground/apps/home/src/assets/react.svg
similarity index 100%
rename from playground/src/assets/react.svg
rename to playground/apps/home/src/assets/react.svg
diff --git a/playground/src/main.tsx b/playground/apps/home/src/main.tsx
similarity index 77%
rename from playground/src/main.tsx
rename to playground/apps/home/src/main.tsx
index bef5202..79f5105 100644
--- a/playground/src/main.tsx
+++ b/playground/apps/home/src/main.tsx
@@ -1,8 +1,8 @@
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
-import './index.css'
import App from './App.tsx'
+// biome-ignore lint/style/noNonNullAssertion:
createRoot(document.getElementById('root')!).render(
diff --git a/playground/apps/home/src/pages/dashboard/index.tsx b/playground/apps/home/src/pages/dashboard/index.tsx
new file mode 100644
index 0000000..62f4cfa
--- /dev/null
+++ b/playground/apps/home/src/pages/dashboard/index.tsx
@@ -0,0 +1,5 @@
+const DashboardPage = () => {
+ return 함수형 프로그래밍 소개팅에 오신걸 환영합니다.
+}
+
+export default DashboardPage
diff --git a/playground/apps/home/src/pages/entrance/index.tsx b/playground/apps/home/src/pages/entrance/index.tsx
new file mode 100644
index 0000000..0aeee18
--- /dev/null
+++ b/playground/apps/home/src/pages/entrance/index.tsx
@@ -0,0 +1,26 @@
+import viteLogo from '/vite.svg'
+import { useNavigate } from 'react-router-dom'
+
+const EntrancePage = () => {
+ const navigate = useNavigate()
+ const goDashboardPage = () => navigate('/home/dashboard')
+
+ return (
+ <>
+
+ 홈
+
+ 함수형 자바스크립트 프로그래밍 스터디의 멤버들을 소개해드릴까요?
+
+
+ >
+ )
+}
+
+export default EntrancePage
diff --git a/playground/apps/home/src/pages/index.ts b/playground/apps/home/src/pages/index.ts
new file mode 100644
index 0000000..d604612
--- /dev/null
+++ b/playground/apps/home/src/pages/index.ts
@@ -0,0 +1,2 @@
+export { default as EntrancePage } from './entrance'
+export { default as DashboardPage } from './dashboard'
diff --git a/playground/apps/home/src/router/index.tsx b/playground/apps/home/src/router/index.tsx
new file mode 100644
index 0000000..32e2e4d
--- /dev/null
+++ b/playground/apps/home/src/router/index.tsx
@@ -0,0 +1,14 @@
+import { Routes, Route } from 'react-router-dom'
+import { EntrancePage, DashboardPage } from '@/pages'
+
+function Router() {
+ return (
+
+ } />
+ } />
+ Other...>} />
+
+ )
+}
+
+export default Router
diff --git a/playground/src/vite-env.d.ts b/playground/apps/home/src/vite-env.d.ts
similarity index 100%
rename from playground/src/vite-env.d.ts
rename to playground/apps/home/src/vite-env.d.ts
diff --git a/playground/tsconfig.app.json b/playground/apps/home/tsconfig.app.json
similarity index 79%
rename from playground/tsconfig.app.json
rename to playground/apps/home/tsconfig.app.json
index f867de0..b416f44 100644
--- a/playground/tsconfig.app.json
+++ b/playground/apps/home/tsconfig.app.json
@@ -7,20 +7,23 @@
"module": "ESNext",
"skipLibCheck": true,
- /* Bundler mode */
- "moduleResolution": "Bundler",
+ "moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",
- /* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
- "noUncheckedSideEffectImports": true
+ "noUncheckedSideEffectImports": true,
+
+ "baseUrl": "./",
+ "paths": {
+ "@/*": ["./src/*"]
+ }
},
"include": ["src"]
}
diff --git a/playground/apps/home/tsconfig.json b/playground/apps/home/tsconfig.json
new file mode 100644
index 0000000..d32ff68
--- /dev/null
+++ b/playground/apps/home/tsconfig.json
@@ -0,0 +1,4 @@
+{
+ "files": [],
+ "references": [{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" }]
+}
diff --git a/playground/tsconfig.node.json b/playground/apps/home/tsconfig.node.json
similarity index 87%
rename from playground/tsconfig.node.json
rename to playground/apps/home/tsconfig.node.json
index abcd7f0..c921d97 100644
--- a/playground/tsconfig.node.json
+++ b/playground/apps/home/tsconfig.node.json
@@ -6,14 +6,12 @@
"module": "ESNext",
"skipLibCheck": true,
- /* Bundler mode */
- "moduleResolution": "Bundler",
+ "moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
- /* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
diff --git a/playground/apps/home/vite.config.ts b/playground/apps/home/vite.config.ts
new file mode 100644
index 0000000..15a122d
--- /dev/null
+++ b/playground/apps/home/vite.config.ts
@@ -0,0 +1,40 @@
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react-swc'
+import federation from '@originjs/vite-plugin-federation'
+import * as path from 'node:path'
+
+// https://vite.dev/config/
+export default defineConfig({
+ plugins: [
+ react(),
+ federation({
+ name: 'remote-app',
+ filename: 'home.js',
+ // Modules to expose
+ exposes: {
+ './HomeRoutes': './src/router/index.tsx',
+ },
+ shared: ['react', 'react-dom', 'react-router-dom'],
+ }),
+ ],
+ server: {
+ port: 3001,
+ },
+ preview: {
+ port: 3001,
+ },
+ resolve: {
+ alias: [
+ {
+ find: '@',
+ replacement: path.resolve(__dirname, 'src'),
+ },
+ ],
+ },
+ build: {
+ modulePreload: false,
+ target: 'esnext',
+ minify: false,
+ cssCodeSplit: false,
+ },
+})
diff --git a/playground/apps/members/.gitignore b/playground/apps/members/.gitignore
new file mode 100644
index 0000000..a547bf3
--- /dev/null
+++ b/playground/apps/members/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/playground/apps/members/README.md b/playground/apps/members/README.md
new file mode 100644
index 0000000..780c92d
--- /dev/null
+++ b/playground/apps/members/README.md
@@ -0,0 +1,50 @@
+# React + TypeScript + Vite
+
+This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
+
+Currently, two official plugins are available:
+
+- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
+- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
+
+## Expanding the ESLint configuration
+
+If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
+
+- Configure the top-level `parserOptions` property like this:
+
+```js
+export default tseslint.config({
+ languageOptions: {
+ // other options...
+ parserOptions: {
+ project: ["./tsconfig.node.json", "./tsconfig.app.json"],
+ tsconfigRootDir: import.meta.dirname,
+ },
+ },
+});
+```
+
+- Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked`
+- Optionally add `...tseslint.configs.stylisticTypeChecked`
+- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and update the config:
+
+```js
+// eslint.config.js
+import react from "eslint-plugin-react";
+
+export default tseslint.config({
+ // Set the react version
+ settings: { react: { version: "18.3" } },
+ plugins: {
+ // Add the react plugin
+ react,
+ },
+ rules: {
+ // other rules...
+ // Enable its recommended rules
+ ...react.configs.recommended.rules,
+ ...react.configs["jsx-runtime"].rules,
+ },
+});
+```
diff --git a/playground/apps/members/eslint.config.js b/playground/apps/members/eslint.config.js
new file mode 100644
index 0000000..0bbf074
--- /dev/null
+++ b/playground/apps/members/eslint.config.js
@@ -0,0 +1,28 @@
+import js from "@eslint/js";
+import globals from "globals";
+import reactHooks from "eslint-plugin-react-hooks";
+import reactRefresh from "eslint-plugin-react-refresh";
+import tseslint from "typescript-eslint";
+
+export default tseslint.config(
+ { ignores: ["dist"] },
+ {
+ extends: [js.configs.recommended, ...tseslint.configs.recommended],
+ files: ["**/*.{ts,tsx}"],
+ languageOptions: {
+ ecmaVersion: 2020,
+ globals: globals.browser,
+ },
+ plugins: {
+ "react-hooks": reactHooks,
+ "react-refresh": reactRefresh,
+ },
+ rules: {
+ ...reactHooks.configs.recommended.rules,
+ "react-refresh/only-export-components": [
+ "warn",
+ { allowConstantExport: true },
+ ],
+ },
+ }
+);
diff --git a/playground/apps/members/index.html b/playground/apps/members/index.html
new file mode 100644
index 0000000..e0d1c84
--- /dev/null
+++ b/playground/apps/members/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ Vite + React + TS
+
+
+
+
+
+
diff --git a/playground/apps/members/package.json b/playground/apps/members/package.json
new file mode 100644
index 0000000..77c9f94
--- /dev/null
+++ b/playground/apps/members/package.json
@@ -0,0 +1,36 @@
+{
+ "name": "members",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "lint": "biome lint ./src",
+ "format": "biome format ./src --write",
+ "dev": "vite",
+ "build": "tsc -b && vite build",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@functional-javascript-programming/utils": "workspace:*",
+ "axios": "^1.7.9",
+ "js-cookie": "^3.0.5",
+ "react": "^18.3.1",
+ "react-dom": "^18.3.1",
+ "react-router-dom": "^7.0.2"
+ },
+ "devDependencies": {
+ "@eslint/js": "^9.15.0",
+ "@originjs/vite-plugin-federation": "^1.3.6",
+ "@types/js-cookie": "^3.0.6",
+ "@types/react": "^18.3.12",
+ "@types/react-dom": "^18.3.1",
+ "@vitejs/plugin-react-swc": "^3.5.0",
+ "eslint": "^9.15.0",
+ "eslint-plugin-react-hooks": "^5.0.0",
+ "eslint-plugin-react-refresh": "^0.4.14",
+ "globals": "^15.12.0",
+ "typescript": "~5.6.2",
+ "typescript-eslint": "^8.15.0",
+ "vite": "^6.0.1"
+ }
+}
diff --git a/playground/apps/members/public/vite.svg b/playground/apps/members/public/vite.svg
new file mode 100644
index 0000000..e7b8dfb
--- /dev/null
+++ b/playground/apps/members/public/vite.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/playground/apps/members/src/App.css b/playground/apps/members/src/App.css
new file mode 100644
index 0000000..172761c
--- /dev/null
+++ b/playground/apps/members/src/App.css
@@ -0,0 +1,40 @@
+.logo {
+ height: 6em;
+ padding: 1.5em;
+ will-change: filter;
+ transition: filter 300ms;
+}
+.logo:hover {
+ filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+ filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+ a:nth-of-type(2) .logo {
+ animation: logo-spin infinite 20s linear;
+ }
+}
+
+.card {
+ width: 400px;
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ margin: 0 auto;
+ padding: 0;
+}
+
+.read-the-docs {
+ color: var(--blue-300);
+}
diff --git a/playground/apps/members/src/App.tsx b/playground/apps/members/src/App.tsx
new file mode 100644
index 0000000..7156f85
--- /dev/null
+++ b/playground/apps/members/src/App.tsx
@@ -0,0 +1,20 @@
+import { BrowserRouter } from 'react-router-dom'
+
+import './App.css'
+import Router from './router'
+
+interface Props {
+ hello?: string
+}
+
+function App({ hello }: Props) {
+ console.log('hello:', hello)
+
+ return (
+
+
+
+ )
+}
+
+export default App
diff --git a/playground/apps/members/src/apis/index.ts b/playground/apps/members/src/apis/index.ts
new file mode 100644
index 0000000..6e7898a
--- /dev/null
+++ b/playground/apps/members/src/apis/index.ts
@@ -0,0 +1,10 @@
+import axios, { type AxiosInstance } from 'axios'
+
+export const axiosInstance: AxiosInstance = axios.create({
+ withCredentials: true,
+ baseURL: '/common',
+ headers: {
+ dataType: 'json',
+ contentType: 'application/x-www-form-urlencoded',
+ },
+})
diff --git a/playground/apps/members/src/assets/react.svg b/playground/apps/members/src/assets/react.svg
new file mode 100644
index 0000000..6c87de9
--- /dev/null
+++ b/playground/apps/members/src/assets/react.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/playground/apps/members/src/main.tsx b/playground/apps/members/src/main.tsx
new file mode 100644
index 0000000..79f5105
--- /dev/null
+++ b/playground/apps/members/src/main.tsx
@@ -0,0 +1,10 @@
+import { StrictMode } from 'react'
+import { createRoot } from 'react-dom/client'
+import App from './App.tsx'
+
+// biome-ignore lint/style/noNonNullAssertion:
+createRoot(document.getElementById('root')!).render(
+
+
+ ,
+)
diff --git a/playground/apps/members/src/pages/dashboard/index.tsx b/playground/apps/members/src/pages/dashboard/index.tsx
new file mode 100644
index 0000000..1bda9a4
--- /dev/null
+++ b/playground/apps/members/src/pages/dashboard/index.tsx
@@ -0,0 +1,15 @@
+const DashboardPage = () => {
+ return (
+
+
+ - 안녕하세요 저는 holim0!
+ - 안녕하세요 저는 wo-o29!
+ - 안녕하세요 저는 wontory!
+ - 안녕하세요 저는 onlyoon!
+ - 안녕하세요 저는 createhb21!
+
+
+ )
+}
+
+export default DashboardPage
diff --git a/playground/apps/members/src/pages/entrance/index.tsx b/playground/apps/members/src/pages/entrance/index.tsx
new file mode 100644
index 0000000..144a0be
--- /dev/null
+++ b/playground/apps/members/src/pages/entrance/index.tsx
@@ -0,0 +1,23 @@
+import viteLogo from '/vite.svg'
+import { useNavigate } from 'react-router-dom'
+
+const EntrancePage = () => {
+ const navigate = useNavigate()
+ const goDashboardPage = () => navigate('/members/dashboard')
+
+ return (
+ <>
+
+ 함수형 자바스크립트 프로그래밍 스터디의 멤버들을 소개할게요!
+
+ >
+ )
+}
+
+export default EntrancePage
diff --git a/playground/apps/members/src/pages/index.ts b/playground/apps/members/src/pages/index.ts
new file mode 100644
index 0000000..d604612
--- /dev/null
+++ b/playground/apps/members/src/pages/index.ts
@@ -0,0 +1,2 @@
+export { default as EntrancePage } from './entrance'
+export { default as DashboardPage } from './dashboard'
diff --git a/playground/apps/members/src/router/index.tsx b/playground/apps/members/src/router/index.tsx
new file mode 100644
index 0000000..32e2e4d
--- /dev/null
+++ b/playground/apps/members/src/router/index.tsx
@@ -0,0 +1,14 @@
+import { Routes, Route } from 'react-router-dom'
+import { EntrancePage, DashboardPage } from '@/pages'
+
+function Router() {
+ return (
+
+ } />
+ } />
+ Other...>} />
+
+ )
+}
+
+export default Router
diff --git a/playground/apps/members/src/vite-env.d.ts b/playground/apps/members/src/vite-env.d.ts
new file mode 100644
index 0000000..11f02fe
--- /dev/null
+++ b/playground/apps/members/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/playground/apps/members/tsconfig.app.json b/playground/apps/members/tsconfig.app.json
new file mode 100644
index 0000000..b416f44
--- /dev/null
+++ b/playground/apps/members/tsconfig.app.json
@@ -0,0 +1,29 @@
+{
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "isolatedModules": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+ "jsx": "react-jsx",
+
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true,
+
+ "baseUrl": "./",
+ "paths": {
+ "@/*": ["./src/*"]
+ }
+ },
+ "include": ["src"]
+}
diff --git a/playground/apps/members/tsconfig.json b/playground/apps/members/tsconfig.json
new file mode 100644
index 0000000..d32ff68
--- /dev/null
+++ b/playground/apps/members/tsconfig.json
@@ -0,0 +1,4 @@
+{
+ "files": [],
+ "references": [{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" }]
+}
diff --git a/playground/apps/members/tsconfig.node.json b/playground/apps/members/tsconfig.node.json
new file mode 100644
index 0000000..c921d97
--- /dev/null
+++ b/playground/apps/members/tsconfig.node.json
@@ -0,0 +1,22 @@
+{
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
+ "target": "ES2022",
+ "lib": ["ES2023"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "isolatedModules": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/playground/apps/members/vite.config.ts b/playground/apps/members/vite.config.ts
new file mode 100644
index 0000000..eb32d26
--- /dev/null
+++ b/playground/apps/members/vite.config.ts
@@ -0,0 +1,40 @@
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react-swc'
+import federation from '@originjs/vite-plugin-federation'
+import * as path from 'node:path'
+
+// https://vite.dev/config/
+export default defineConfig({
+ plugins: [
+ react(),
+ federation({
+ name: 'remote-app',
+ filename: 'members.js',
+ // Modules to expose
+ exposes: {
+ './MembersRoutes': './src/router/index.tsx',
+ },
+ shared: ['react', 'react-dom', 'react-router-dom'],
+ }),
+ ],
+ server: {
+ port: 3003,
+ },
+ preview: {
+ port: 3003,
+ },
+ resolve: {
+ alias: [
+ {
+ find: '@',
+ replacement: path.resolve(__dirname, 'src'),
+ },
+ ],
+ },
+ build: {
+ modulePreload: false,
+ target: 'esnext',
+ minify: false,
+ cssCodeSplit: false,
+ },
+})
diff --git a/playground/apps/projects/.gitignore b/playground/apps/projects/.gitignore
new file mode 100644
index 0000000..a547bf3
--- /dev/null
+++ b/playground/apps/projects/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/playground/apps/projects/README.md b/playground/apps/projects/README.md
new file mode 100644
index 0000000..780c92d
--- /dev/null
+++ b/playground/apps/projects/README.md
@@ -0,0 +1,50 @@
+# React + TypeScript + Vite
+
+This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
+
+Currently, two official plugins are available:
+
+- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
+- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
+
+## Expanding the ESLint configuration
+
+If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
+
+- Configure the top-level `parserOptions` property like this:
+
+```js
+export default tseslint.config({
+ languageOptions: {
+ // other options...
+ parserOptions: {
+ project: ["./tsconfig.node.json", "./tsconfig.app.json"],
+ tsconfigRootDir: import.meta.dirname,
+ },
+ },
+});
+```
+
+- Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked`
+- Optionally add `...tseslint.configs.stylisticTypeChecked`
+- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and update the config:
+
+```js
+// eslint.config.js
+import react from "eslint-plugin-react";
+
+export default tseslint.config({
+ // Set the react version
+ settings: { react: { version: "18.3" } },
+ plugins: {
+ // Add the react plugin
+ react,
+ },
+ rules: {
+ // other rules...
+ // Enable its recommended rules
+ ...react.configs.recommended.rules,
+ ...react.configs["jsx-runtime"].rules,
+ },
+});
+```
diff --git a/playground/apps/projects/eslint.config.js b/playground/apps/projects/eslint.config.js
new file mode 100644
index 0000000..0bbf074
--- /dev/null
+++ b/playground/apps/projects/eslint.config.js
@@ -0,0 +1,28 @@
+import js from "@eslint/js";
+import globals from "globals";
+import reactHooks from "eslint-plugin-react-hooks";
+import reactRefresh from "eslint-plugin-react-refresh";
+import tseslint from "typescript-eslint";
+
+export default tseslint.config(
+ { ignores: ["dist"] },
+ {
+ extends: [js.configs.recommended, ...tseslint.configs.recommended],
+ files: ["**/*.{ts,tsx}"],
+ languageOptions: {
+ ecmaVersion: 2020,
+ globals: globals.browser,
+ },
+ plugins: {
+ "react-hooks": reactHooks,
+ "react-refresh": reactRefresh,
+ },
+ rules: {
+ ...reactHooks.configs.recommended.rules,
+ "react-refresh/only-export-components": [
+ "warn",
+ { allowConstantExport: true },
+ ],
+ },
+ }
+);
diff --git a/playground/apps/projects/index.html b/playground/apps/projects/index.html
new file mode 100644
index 0000000..e0d1c84
--- /dev/null
+++ b/playground/apps/projects/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ Vite + React + TS
+
+
+
+
+
+
diff --git a/playground/apps/projects/package.json b/playground/apps/projects/package.json
new file mode 100644
index 0000000..f00ea1d
--- /dev/null
+++ b/playground/apps/projects/package.json
@@ -0,0 +1,36 @@
+{
+ "name": "projects",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "lint": "biome lint ./src",
+ "format": "biome format ./src --write",
+ "dev": "vite",
+ "build": "tsc -b && vite build",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@functional-javascript-programming/utils": "workspace:*",
+ "axios": "^1.7.9",
+ "js-cookie": "^3.0.5",
+ "react": "^18.3.1",
+ "react-dom": "^18.3.1",
+ "react-router-dom": "^7.0.2"
+ },
+ "devDependencies": {
+ "@eslint/js": "^9.15.0",
+ "@originjs/vite-plugin-federation": "^1.3.6",
+ "@types/js-cookie": "^3.0.6",
+ "@types/react": "^18.3.12",
+ "@types/react-dom": "^18.3.1",
+ "@vitejs/plugin-react-swc": "^3.5.0",
+ "eslint": "^9.15.0",
+ "eslint-plugin-react-hooks": "^5.0.0",
+ "eslint-plugin-react-refresh": "^0.4.14",
+ "globals": "^15.12.0",
+ "typescript": "~5.6.2",
+ "typescript-eslint": "^8.15.0",
+ "vite": "^6.0.1"
+ }
+}
diff --git a/playground/apps/projects/public/vite.svg b/playground/apps/projects/public/vite.svg
new file mode 100644
index 0000000..e7b8dfb
--- /dev/null
+++ b/playground/apps/projects/public/vite.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/playground/apps/projects/src/App.css b/playground/apps/projects/src/App.css
new file mode 100644
index 0000000..172761c
--- /dev/null
+++ b/playground/apps/projects/src/App.css
@@ -0,0 +1,40 @@
+.logo {
+ height: 6em;
+ padding: 1.5em;
+ will-change: filter;
+ transition: filter 300ms;
+}
+.logo:hover {
+ filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+ filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+ a:nth-of-type(2) .logo {
+ animation: logo-spin infinite 20s linear;
+ }
+}
+
+.card {
+ width: 400px;
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ margin: 0 auto;
+ padding: 0;
+}
+
+.read-the-docs {
+ color: var(--blue-300);
+}
diff --git a/playground/apps/projects/src/App.tsx b/playground/apps/projects/src/App.tsx
new file mode 100644
index 0000000..7156f85
--- /dev/null
+++ b/playground/apps/projects/src/App.tsx
@@ -0,0 +1,20 @@
+import { BrowserRouter } from 'react-router-dom'
+
+import './App.css'
+import Router from './router'
+
+interface Props {
+ hello?: string
+}
+
+function App({ hello }: Props) {
+ console.log('hello:', hello)
+
+ return (
+
+
+
+ )
+}
+
+export default App
diff --git a/playground/apps/projects/src/apis/index.ts b/playground/apps/projects/src/apis/index.ts
new file mode 100644
index 0000000..6e7898a
--- /dev/null
+++ b/playground/apps/projects/src/apis/index.ts
@@ -0,0 +1,10 @@
+import axios, { type AxiosInstance } from 'axios'
+
+export const axiosInstance: AxiosInstance = axios.create({
+ withCredentials: true,
+ baseURL: '/common',
+ headers: {
+ dataType: 'json',
+ contentType: 'application/x-www-form-urlencoded',
+ },
+})
diff --git a/playground/apps/projects/src/assets/react.svg b/playground/apps/projects/src/assets/react.svg
new file mode 100644
index 0000000..6c87de9
--- /dev/null
+++ b/playground/apps/projects/src/assets/react.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/playground/apps/projects/src/main.tsx b/playground/apps/projects/src/main.tsx
new file mode 100644
index 0000000..79f5105
--- /dev/null
+++ b/playground/apps/projects/src/main.tsx
@@ -0,0 +1,10 @@
+import { StrictMode } from 'react'
+import { createRoot } from 'react-dom/client'
+import App from './App.tsx'
+
+// biome-ignore lint/style/noNonNullAssertion:
+createRoot(document.getElementById('root')!).render(
+
+
+ ,
+)
diff --git a/playground/apps/projects/src/pages/dashboard/index.tsx b/playground/apps/projects/src/pages/dashboard/index.tsx
new file mode 100644
index 0000000..1c0ac55
--- /dev/null
+++ b/playground/apps/projects/src/pages/dashboard/index.tsx
@@ -0,0 +1,5 @@
+const DashboardPage = () => {
+ return 함산기 - 함수형 프로그래밍을 활용해서 계산기를 만들었어요.
+}
+
+export default DashboardPage
diff --git a/playground/apps/projects/src/pages/entrance/index.tsx b/playground/apps/projects/src/pages/entrance/index.tsx
new file mode 100644
index 0000000..8c57251
--- /dev/null
+++ b/playground/apps/projects/src/pages/entrance/index.tsx
@@ -0,0 +1,35 @@
+import { useReducer } from 'react'
+import Cookies from 'js-cookie'
+
+import viteLogo from '/vite.svg'
+import { useNavigate } from 'react-router-dom'
+
+const EntrancePage = () => {
+ const [showCookie, toggleCookie] = useReducer((show) => !show, false)
+
+ const getCookieString = () => Cookies.get('hi') ?? '안녕하세요'
+
+ const navigate = useNavigate()
+ const goDashboardPage = () => navigate('/projects/dashboard')
+
+ return (
+ <>
+
+ 다음과 같은 프로젝트를 만들고 있어요
+
+ {showCookie && {getCookieString()}
}
+
+
+ >
+ )
+}
+
+export default EntrancePage
diff --git a/playground/apps/projects/src/pages/index.ts b/playground/apps/projects/src/pages/index.ts
new file mode 100644
index 0000000..d604612
--- /dev/null
+++ b/playground/apps/projects/src/pages/index.ts
@@ -0,0 +1,2 @@
+export { default as EntrancePage } from './entrance'
+export { default as DashboardPage } from './dashboard'
diff --git a/playground/apps/projects/src/router/index.tsx b/playground/apps/projects/src/router/index.tsx
new file mode 100644
index 0000000..32e2e4d
--- /dev/null
+++ b/playground/apps/projects/src/router/index.tsx
@@ -0,0 +1,14 @@
+import { Routes, Route } from 'react-router-dom'
+import { EntrancePage, DashboardPage } from '@/pages'
+
+function Router() {
+ return (
+
+ } />
+ } />
+ Other...>} />
+
+ )
+}
+
+export default Router
diff --git a/playground/apps/projects/src/vite-env.d.ts b/playground/apps/projects/src/vite-env.d.ts
new file mode 100644
index 0000000..11f02fe
--- /dev/null
+++ b/playground/apps/projects/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/playground/apps/projects/tsconfig.app.json b/playground/apps/projects/tsconfig.app.json
new file mode 100644
index 0000000..b416f44
--- /dev/null
+++ b/playground/apps/projects/tsconfig.app.json
@@ -0,0 +1,29 @@
+{
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "isolatedModules": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+ "jsx": "react-jsx",
+
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true,
+
+ "baseUrl": "./",
+ "paths": {
+ "@/*": ["./src/*"]
+ }
+ },
+ "include": ["src"]
+}
diff --git a/playground/apps/projects/tsconfig.json b/playground/apps/projects/tsconfig.json
new file mode 100644
index 0000000..d32ff68
--- /dev/null
+++ b/playground/apps/projects/tsconfig.json
@@ -0,0 +1,4 @@
+{
+ "files": [],
+ "references": [{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" }]
+}
diff --git a/playground/apps/projects/tsconfig.node.json b/playground/apps/projects/tsconfig.node.json
new file mode 100644
index 0000000..c921d97
--- /dev/null
+++ b/playground/apps/projects/tsconfig.node.json
@@ -0,0 +1,22 @@
+{
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
+ "target": "ES2022",
+ "lib": ["ES2023"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "isolatedModules": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/playground/apps/projects/vite.config.ts b/playground/apps/projects/vite.config.ts
new file mode 100644
index 0000000..6d6cc01
--- /dev/null
+++ b/playground/apps/projects/vite.config.ts
@@ -0,0 +1,40 @@
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react-swc'
+import federation from '@originjs/vite-plugin-federation'
+import * as path from 'node:path'
+
+// https://vite.dev/config/
+export default defineConfig({
+ plugins: [
+ react(),
+ federation({
+ name: 'remote-app',
+ filename: 'projects.js',
+ // Modules to expose
+ exposes: {
+ './ProjectsRoutes': './src/router/index.tsx',
+ },
+ shared: ['react', 'react-dom', 'react-router-dom'],
+ }),
+ ],
+ server: {
+ port: 3002,
+ },
+ preview: {
+ port: 3002,
+ },
+ resolve: {
+ alias: [
+ {
+ find: '@',
+ replacement: path.resolve(__dirname, 'src'),
+ },
+ ],
+ },
+ build: {
+ modulePreload: false,
+ target: 'esnext',
+ minify: false,
+ cssCodeSplit: false,
+ },
+})
diff --git a/playground/eslint.config.js b/playground/eslint.config.js
deleted file mode 100644
index 092408a..0000000
--- a/playground/eslint.config.js
+++ /dev/null
@@ -1,28 +0,0 @@
-import js from '@eslint/js'
-import globals from 'globals'
-import reactHooks from 'eslint-plugin-react-hooks'
-import reactRefresh from 'eslint-plugin-react-refresh'
-import tseslint from 'typescript-eslint'
-
-export default tseslint.config(
- { ignores: ['dist'] },
- {
- extends: [js.configs.recommended, ...tseslint.configs.recommended],
- files: ['**/*.{ts,tsx}'],
- languageOptions: {
- ecmaVersion: 2020,
- globals: globals.browser,
- },
- plugins: {
- 'react-hooks': reactHooks,
- 'react-refresh': reactRefresh,
- },
- rules: {
- ...reactHooks.configs.recommended.rules,
- 'react-refresh/only-export-components': [
- 'warn',
- { allowConstantExport: true },
- ],
- },
- },
-)
diff --git a/playground/packages/esbuild/index.js b/playground/packages/esbuild/index.js
new file mode 100644
index 0000000..8d37302
--- /dev/null
+++ b/playground/packages/esbuild/index.js
@@ -0,0 +1,64 @@
+const { build, context } = require("esbuild");
+
+const run = async ({ entryPoints = ["src/index.ts"], pkg, config = {} }) => {
+ const dev = process.argv.includes("--dev");
+ const minify = !dev;
+ const shouldWatch = process.argv.includes("--watch");
+
+ const external = Object.keys({
+ ...pkg.dependencies,
+ ...pkg.peerDependencies,
+ });
+
+ const baseConfig = {
+ entryPoints,
+ bundle: true,
+ minify,
+ sourcemap: true,
+ outdir: "dist",
+ target: "es2019",
+ external,
+ ...config,
+ };
+
+ try {
+ if (shouldWatch) {
+ // watch 모드일 때는 context를 사용
+ const [esmContext, cjsContext] = await Promise.all([
+ context({
+ ...baseConfig,
+ format: "esm",
+ }),
+ context({
+ ...baseConfig,
+ format: "cjs",
+ outExtension: {
+ ".js": ".cjs",
+ },
+ }),
+ ]);
+
+ await Promise.all([esmContext.watch(), cjsContext.watch()]);
+ } else {
+ // 일반 빌드
+ await Promise.all([
+ build({
+ ...baseConfig,
+ format: "esm",
+ }),
+ build({
+ ...baseConfig,
+ format: "cjs",
+ outExtension: {
+ ".js": ".cjs",
+ },
+ }),
+ ]);
+ }
+ } catch (error) {
+ console.error("Build failed:", error);
+ process.exit(1);
+ }
+};
+
+module.exports = run;
diff --git a/playground/packages/esbuild/package.json b/playground/packages/esbuild/package.json
new file mode 100644
index 0000000..8a226a6
--- /dev/null
+++ b/playground/packages/esbuild/package.json
@@ -0,0 +1,9 @@
+{
+ "name": "@functional-javascript-programming/esbuild-config",
+ "version": "0.0.2",
+ "main": "index.js",
+ "files": ["index.js"],
+ "dependencies": {
+ "esbuild": "^0.24.0"
+ }
+}
diff --git a/playground/packages/tsconfig/base.json b/playground/packages/tsconfig/base.json
new file mode 100644
index 0000000..0f80cfd
--- /dev/null
+++ b/playground/packages/tsconfig/base.json
@@ -0,0 +1,20 @@
+{
+ "$schema": "https://json.schemastore.org/tsconfig",
+ "display": "Default",
+ "compilerOptions": {
+ "declaration": true,
+ "declarationMap": true,
+ "esModuleInterop": true,
+ "incremental": false,
+ "isolatedModules": true,
+ "lib": ["es2022", "DOM", "DOM.Iterable"],
+ "module": "NodeNext",
+ "moduleDetection": "force",
+ "moduleResolution": "NodeNext",
+ "noUncheckedIndexedAccess": true,
+ "resolveJsonModule": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "target": "ES2022"
+ }
+}
diff --git a/playground/packages/tsconfig/nextjs.json b/playground/packages/tsconfig/nextjs.json
new file mode 100644
index 0000000..44f4289
--- /dev/null
+++ b/playground/packages/tsconfig/nextjs.json
@@ -0,0 +1,13 @@
+{
+ "$schema": "https://json.schemastore.org/tsconfig",
+ "display": "Next.js",
+ "extends": "./base.json",
+ "compilerOptions": {
+ "plugins": [{ "name": "next" }],
+ "module": "ESNext",
+ "moduleResolution": "Bundler",
+ "allowJs": true,
+ "jsx": "preserve",
+ "noEmit": true
+ }
+}
diff --git a/playground/packages/tsconfig/package.json b/playground/packages/tsconfig/package.json
new file mode 100644
index 0000000..344d3f0
--- /dev/null
+++ b/playground/packages/tsconfig/package.json
@@ -0,0 +1,4 @@
+{
+ "name": "@functional-javascript-programming/typescript-config",
+ "version": "0.0.1"
+}
diff --git a/playground/packages/tsconfig/react-library.json b/playground/packages/tsconfig/react-library.json
new file mode 100644
index 0000000..44924d9
--- /dev/null
+++ b/playground/packages/tsconfig/react-library.json
@@ -0,0 +1,8 @@
+{
+ "$schema": "https://json.schemastore.org/tsconfig",
+ "display": "React Library",
+ "extends": "./base.json",
+ "compilerOptions": {
+ "jsx": "react-jsx"
+ }
+}
diff --git a/playground/packages/utils/package.json b/playground/packages/utils/package.json
new file mode 100644
index 0000000..391109b
--- /dev/null
+++ b/playground/packages/utils/package.json
@@ -0,0 +1,15 @@
+{
+ "name": "@functional-javascript-programming/utils",
+ "version": "0.0.0",
+ "private": true,
+ "exports": {
+ ".": "./src/index.ts"
+ },
+ "scripts": {
+ "lint": "biome lint ./src",
+ "format": "biome format ./src --write"
+ },
+ "devDependencies": {
+ "@functional-javascript-programming/typescript-config": "workspace:*"
+ }
+}
diff --git a/playground/packages/utils/src/add/add.ts b/playground/packages/utils/src/add/add.ts
new file mode 100644
index 0000000..c39ee17
--- /dev/null
+++ b/playground/packages/utils/src/add/add.ts
@@ -0,0 +1,3 @@
+export const addNumbers = (a: number, b: number) => {
+ return a + b
+}
diff --git a/playground/packages/utils/src/add/index.ts b/playground/packages/utils/src/add/index.ts
new file mode 100644
index 0000000..2bed2c4
--- /dev/null
+++ b/playground/packages/utils/src/add/index.ts
@@ -0,0 +1 @@
+export * from './add'
diff --git a/playground/packages/utils/src/index.ts b/playground/packages/utils/src/index.ts
new file mode 100644
index 0000000..2bed2c4
--- /dev/null
+++ b/playground/packages/utils/src/index.ts
@@ -0,0 +1 @@
+export * from './add'
diff --git a/playground/packages/utils/tsconfig.json b/playground/packages/utils/tsconfig.json
new file mode 100644
index 0000000..1911fb6
--- /dev/null
+++ b/playground/packages/utils/tsconfig.json
@@ -0,0 +1,7 @@
+{
+ "extends": "@functional-javascript-programming/typescript-config/react-library.json",
+ "compilerOptions": {
+ "outDir": "dist"
+ },
+ "include": ["src"]
+}
diff --git a/playground/src/App.tsx b/playground/src/App.tsx
deleted file mode 100644
index 3d7ded3..0000000
--- a/playground/src/App.tsx
+++ /dev/null
@@ -1,35 +0,0 @@
-import { useState } from 'react'
-import reactLogo from './assets/react.svg'
-import viteLogo from '/vite.svg'
-import './App.css'
-
-function App() {
- const [count, setCount] = useState(0)
-
- return (
- <>
-
- Vite + React
-
-
-
- Edit src/App.tsx
and save to test HMR
-
-
-
- Click on the Vite and React logos to learn more
-
- >
- )
-}
-
-export default App
diff --git a/playground/src/index.css b/playground/src/index.css
deleted file mode 100644
index 6119ad9..0000000
--- a/playground/src/index.css
+++ /dev/null
@@ -1,68 +0,0 @@
-:root {
- font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
- line-height: 1.5;
- font-weight: 400;
-
- color-scheme: light dark;
- color: rgba(255, 255, 255, 0.87);
- background-color: #242424;
-
- font-synthesis: none;
- text-rendering: optimizeLegibility;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-}
-
-a {
- font-weight: 500;
- color: #646cff;
- text-decoration: inherit;
-}
-a:hover {
- color: #535bf2;
-}
-
-body {
- margin: 0;
- display: flex;
- place-items: center;
- min-width: 320px;
- min-height: 100vh;
-}
-
-h1 {
- font-size: 3.2em;
- line-height: 1.1;
-}
-
-button {
- border-radius: 8px;
- border: 1px solid transparent;
- padding: 0.6em 1.2em;
- font-size: 1em;
- font-weight: 500;
- font-family: inherit;
- background-color: #1a1a1a;
- cursor: pointer;
- transition: border-color 0.25s;
-}
-button:hover {
- border-color: #646cff;
-}
-button:focus,
-button:focus-visible {
- outline: 4px auto -webkit-focus-ring-color;
-}
-
-@media (prefers-color-scheme: light) {
- :root {
- color: #213547;
- background-color: #ffffff;
- }
- a:hover {
- color: #747bff;
- }
- button {
- background-color: #f9f9f9;
- }
-}
diff --git a/playground/tsconfig.json b/playground/tsconfig.json
deleted file mode 100644
index 1ffef60..0000000
--- a/playground/tsconfig.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "files": [],
- "references": [
- { "path": "./tsconfig.app.json" },
- { "path": "./tsconfig.node.json" }
- ]
-}
diff --git a/playground/vite.config.ts b/playground/vite.config.ts
deleted file mode 100644
index 2328e17..0000000
--- a/playground/vite.config.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { defineConfig } from 'vite'
-import react from '@vitejs/plugin-react-swc'
-
-// https://vite.dev/config/
-export default defineConfig({
- plugins: [react()],
-})
diff --git a/playground/web/.gitignore b/playground/web/.gitignore
new file mode 100644
index 0000000..a547bf3
--- /dev/null
+++ b/playground/web/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/playground/web/README.md b/playground/web/README.md
new file mode 100644
index 0000000..780c92d
--- /dev/null
+++ b/playground/web/README.md
@@ -0,0 +1,50 @@
+# React + TypeScript + Vite
+
+This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
+
+Currently, two official plugins are available:
+
+- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
+- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
+
+## Expanding the ESLint configuration
+
+If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
+
+- Configure the top-level `parserOptions` property like this:
+
+```js
+export default tseslint.config({
+ languageOptions: {
+ // other options...
+ parserOptions: {
+ project: ["./tsconfig.node.json", "./tsconfig.app.json"],
+ tsconfigRootDir: import.meta.dirname,
+ },
+ },
+});
+```
+
+- Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked`
+- Optionally add `...tseslint.configs.stylisticTypeChecked`
+- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and update the config:
+
+```js
+// eslint.config.js
+import react from "eslint-plugin-react";
+
+export default tseslint.config({
+ // Set the react version
+ settings: { react: { version: "18.3" } },
+ plugins: {
+ // Add the react plugin
+ react,
+ },
+ rules: {
+ // other rules...
+ // Enable its recommended rules
+ ...react.configs.recommended.rules,
+ ...react.configs["jsx-runtime"].rules,
+ },
+});
+```
diff --git a/playground/web/eslint.config.js b/playground/web/eslint.config.js
new file mode 100644
index 0000000..0bbf074
--- /dev/null
+++ b/playground/web/eslint.config.js
@@ -0,0 +1,28 @@
+import js from "@eslint/js";
+import globals from "globals";
+import reactHooks from "eslint-plugin-react-hooks";
+import reactRefresh from "eslint-plugin-react-refresh";
+import tseslint from "typescript-eslint";
+
+export default tseslint.config(
+ { ignores: ["dist"] },
+ {
+ extends: [js.configs.recommended, ...tseslint.configs.recommended],
+ files: ["**/*.{ts,tsx}"],
+ languageOptions: {
+ ecmaVersion: 2020,
+ globals: globals.browser,
+ },
+ plugins: {
+ "react-hooks": reactHooks,
+ "react-refresh": reactRefresh,
+ },
+ rules: {
+ ...reactHooks.configs.recommended.rules,
+ "react-refresh/only-export-components": [
+ "warn",
+ { allowConstantExport: true },
+ ],
+ },
+ }
+);
diff --git a/playground/web/index.html b/playground/web/index.html
new file mode 100644
index 0000000..e0d1c84
--- /dev/null
+++ b/playground/web/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ Vite + React + TS
+
+
+
+
+
+
diff --git a/playground/package.json b/playground/web/package.json
similarity index 58%
rename from playground/package.json
rename to playground/web/package.json
index 2851f67..45a6942 100644
--- a/playground/package.json
+++ b/playground/web/package.json
@@ -1,5 +1,5 @@
{
- "name": "playground",
+ "name": "web",
"private": true,
"version": "0.0.0",
"type": "module",
@@ -10,20 +10,25 @@
"preview": "vite preview"
},
"dependencies": {
+ "axios": "^1.7.9",
+ "js-cookie": "^3.0.5",
"react": "^18.3.1",
- "react-dom": "^18.3.1"
+ "react-dom": "^18.3.1",
+ "react-router-dom": "^7.0.2"
},
"devDependencies": {
- "@eslint/js": "^9.13.0",
+ "@eslint/js": "^9.15.0",
+ "@originjs/vite-plugin-federation": "^1.3.6",
+ "@types/js-cookie": "^3.0.6",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"@vitejs/plugin-react-swc": "^3.5.0",
- "eslint": "^9.13.0",
+ "eslint": "^9.15.0",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.14",
- "globals": "^15.11.0",
+ "globals": "^15.12.0",
"typescript": "~5.6.2",
- "typescript-eslint": "^8.11.0",
- "vite": "^5.4.10"
+ "typescript-eslint": "^8.15.0",
+ "vite": "^6.0.1"
}
}
diff --git a/playground/web/public/vite.svg b/playground/web/public/vite.svg
new file mode 100644
index 0000000..e7b8dfb
--- /dev/null
+++ b/playground/web/public/vite.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/playground/web/src/App.tsx b/playground/web/src/App.tsx
new file mode 100644
index 0000000..1d79560
--- /dev/null
+++ b/playground/web/src/App.tsx
@@ -0,0 +1,16 @@
+import React from 'react'
+import { BrowserRouter } from 'react-router-dom'
+
+import Router from './router'
+
+function App() {
+ return (
+
+
+
+
+
+ )
+}
+
+export default App
diff --git a/playground/web/src/apis/index.ts b/playground/web/src/apis/index.ts
new file mode 100644
index 0000000..1e36302
--- /dev/null
+++ b/playground/web/src/apis/index.ts
@@ -0,0 +1,7 @@
+import axios, { type AxiosInstance } from 'axios'
+
+const axiosInstance: AxiosInstance = axios.create({
+ baseURL: '/api',
+})
+
+export { axiosInstance }
diff --git a/playground/web/src/assets/icons/keyboard-icon.tsx b/playground/web/src/assets/icons/keyboard-icon.tsx
new file mode 100644
index 0000000..dd910a3
--- /dev/null
+++ b/playground/web/src/assets/icons/keyboard-icon.tsx
@@ -0,0 +1,17 @@
+export function KeyboardIcon() {
+ return (
+
+ )
+}
diff --git a/playground/web/src/components/index.ts b/playground/web/src/components/index.ts
new file mode 100644
index 0000000..8405297
--- /dev/null
+++ b/playground/web/src/components/index.ts
@@ -0,0 +1,2 @@
+export * as LayoutComponent from './layout'
+export * as UiComponent from './ui'
diff --git a/playground/web/src/components/layout/Base.tsx b/playground/web/src/components/layout/Base.tsx
new file mode 100644
index 0000000..9d5ad0c
--- /dev/null
+++ b/playground/web/src/components/layout/Base.tsx
@@ -0,0 +1,17 @@
+import { Outlet } from 'react-router-dom'
+import { UiComponent } from '..'
+
+function Base() {
+ return (
+ <>
+
+
+
+
+
+ {/* {enabledGlobalLoading && } */}
+ >
+ )
+}
+
+export default Base
diff --git a/playground/web/src/components/layout/index.ts b/playground/web/src/components/layout/index.ts
new file mode 100644
index 0000000..75486f4
--- /dev/null
+++ b/playground/web/src/components/layout/index.ts
@@ -0,0 +1 @@
+export { default as Base } from './Base'
diff --git a/playground/web/src/components/ui/Header/Header.tsx b/playground/web/src/components/ui/Header/Header.tsx
new file mode 100644
index 0000000..cdaed13
--- /dev/null
+++ b/playground/web/src/components/ui/Header/Header.tsx
@@ -0,0 +1,17 @@
+import { useNavigate } from 'react-router-dom'
+
+function Header() {
+ const navigate = useNavigate()
+ const onClickLogoItem = () => {
+ navigate('/landing')
+ }
+ return (
+
+ )
+}
+
+export default Header
diff --git a/playground/web/src/components/ui/Header/index.ts b/playground/web/src/components/ui/Header/index.ts
new file mode 100644
index 0000000..6f8c579
--- /dev/null
+++ b/playground/web/src/components/ui/Header/index.ts
@@ -0,0 +1 @@
+export { default } from './Header'
diff --git a/playground/web/src/components/ui/Navigation/Navigation.tsx b/playground/web/src/components/ui/Navigation/Navigation.tsx
new file mode 100644
index 0000000..716effe
--- /dev/null
+++ b/playground/web/src/components/ui/Navigation/Navigation.tsx
@@ -0,0 +1,47 @@
+import { useNavigate, useLocation } from 'react-router-dom'
+
+const NAV_LIST = [
+ {
+ name: '홈',
+ path: '/home',
+ },
+ {
+ name: '멤버 소개',
+ path: '/members',
+ },
+ {
+ name: '프로젝트',
+ path: '/projects',
+ },
+]
+
+function Navigation() {
+ const navigate = useNavigate()
+ const { pathname } = useLocation()
+
+ const onClickNavItem = (path: string) => {
+ navigate(path)
+ }
+
+ return (
+
+ )
+}
+
+export default Navigation
diff --git a/playground/web/src/components/ui/Navigation/index.ts b/playground/web/src/components/ui/Navigation/index.ts
new file mode 100644
index 0000000..e09ebad
--- /dev/null
+++ b/playground/web/src/components/ui/Navigation/index.ts
@@ -0,0 +1 @@
+export { default } from './Navigation'
diff --git a/playground/web/src/components/ui/index.ts b/playground/web/src/components/ui/index.ts
new file mode 100644
index 0000000..8c65e82
--- /dev/null
+++ b/playground/web/src/components/ui/index.ts
@@ -0,0 +1,2 @@
+export { default as Header } from './Header'
+export { default as Navigation } from './Navigation'
diff --git a/playground/web/src/data/path.ts b/playground/web/src/data/path.ts
new file mode 100644
index 0000000..c492342
--- /dev/null
+++ b/playground/web/src/data/path.ts
@@ -0,0 +1,8 @@
+const PATH = {
+ landing: '/landing',
+ home: '/home/*',
+ projects: '/projects/*',
+ members: '/members/*',
+} as const
+
+export { PATH }
diff --git a/playground/web/src/globals.d.ts b/playground/web/src/globals.d.ts
new file mode 100644
index 0000000..c53a449
--- /dev/null
+++ b/playground/web/src/globals.d.ts
@@ -0,0 +1,5 @@
+declare module '*.module.css'
+
+declare module 'home/HomeRoutes'
+declare module 'projects/ProjectsRoutes'
+declare module 'members/MembersRoutes'
diff --git a/playground/web/src/hooks/index.ts b/playground/web/src/hooks/index.ts
new file mode 100644
index 0000000..0380b3a
--- /dev/null
+++ b/playground/web/src/hooks/index.ts
@@ -0,0 +1 @@
+export * from './useQueryParams'
diff --git a/playground/web/src/hooks/useQueryParams.ts b/playground/web/src/hooks/useQueryParams.ts
new file mode 100644
index 0000000..021176c
--- /dev/null
+++ b/playground/web/src/hooks/useQueryParams.ts
@@ -0,0 +1,62 @@
+import { useState, useEffect, useCallback } from 'react'
+
+export const useQueryParams = () => {
+ const [queryParams, setQueryParams] = useState>({})
+
+ const parseQueryParams = useCallback(() => {
+ const params = new URLSearchParams(window.location.search)
+ const parsedParams: Record = {}
+ params.forEach((value, key) => {
+ parsedParams[key] = value
+ })
+ setQueryParams(parsedParams)
+ }, [])
+
+ useEffect(() => {
+ parseQueryParams()
+
+ const handlePopState = () => {
+ parseQueryParams()
+ }
+
+ window.addEventListener('popstate', handlePopState)
+
+ return () => {
+ window.removeEventListener('popstate', handlePopState)
+ }
+ }, [parseQueryParams])
+
+ const getQueryParam = useCallback(
+ (key: string): string | null => {
+ return queryParams[key] || null
+ },
+ [queryParams],
+ )
+
+ const setQueryParam = useCallback(
+ (key: string, value: string) => {
+ const params = new URLSearchParams(window.location.search)
+ params.set(key, value)
+ window.history.pushState({}, '', `${window.location.pathname}?${params.toString()}`)
+ parseQueryParams()
+ },
+ [parseQueryParams],
+ )
+
+ const removeQueryParam = useCallback(
+ (key: string) => {
+ const params = new URLSearchParams(window.location.search)
+ params.delete(key)
+ window.history.pushState({}, '', `${window.location.pathname}?${params.toString()}`)
+ parseQueryParams()
+ },
+ [parseQueryParams],
+ )
+
+ return {
+ queryParams,
+ getQueryParam,
+ setQueryParam,
+ removeQueryParam,
+ }
+}
diff --git a/playground/web/src/index.css b/playground/web/src/index.css
new file mode 100644
index 0000000..b3016d3
--- /dev/null
+++ b/playground/web/src/index.css
@@ -0,0 +1,89 @@
+:root {
+ font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
+ line-height: 1.5;
+ font-weight: 400;
+
+ color-scheme: light dark;
+ color: rgba(255, 255, 255, 0.87);
+ background-color: #242424;
+
+ font-synthesis: none;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+}
+
+body {
+ margin: 0;
+ display: flex;
+ place-items: center;
+}
+
+h1 {
+ font-size: 3.2em;
+ line-height: 1.1;
+}
+
+ul {
+ list-style: none;
+}
+
+header {
+ position: fixed;
+ height: 60px;
+ width: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ background-color: cadetblue;
+ padding: 0 2rem;
+}
+
+aside {
+ position: fixed;
+ top: 60px;
+ left: 0;
+ height: 100%;
+ width: 20%;
+ color: black;
+ background-color: antiquewhite;
+ font-size: 18px;
+ font-weight: 700;
+}
+
+aside ul {
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+ padding-top: 100px;
+}
+
+aside ul li {
+ cursor: pointer;
+}
+
+main {
+ position: absolute;
+ top: 60px;
+ left: 20%;
+ max-height: calc(100% - 60px);
+ max-width: calc(100% - 20%);
+ padding: 2rem;
+}
+
+button {
+ border: none;
+ outline: none;
+ background-color: aquamarine;
+ cursor: pointer;
+}
+
+.active {
+ color: darkorange;
+}
diff --git a/playground/web/src/main.tsx b/playground/web/src/main.tsx
new file mode 100644
index 0000000..44ed599
--- /dev/null
+++ b/playground/web/src/main.tsx
@@ -0,0 +1,12 @@
+import { StrictMode } from 'react'
+import { createRoot } from 'react-dom/client'
+import App from './App'
+
+import './index.css'
+
+// biome-ignore lint/style/noNonNullAssertion:
+createRoot(document.getElementById('root')!).render(
+
+
+ ,
+)
diff --git a/playground/web/src/pages/index.ts b/playground/web/src/pages/index.ts
new file mode 100644
index 0000000..a25780d
--- /dev/null
+++ b/playground/web/src/pages/index.ts
@@ -0,0 +1 @@
+export { default } from './landing'
diff --git a/playground/web/src/pages/landing/index.tsx b/playground/web/src/pages/landing/index.tsx
new file mode 100644
index 0000000..86f9cc7
--- /dev/null
+++ b/playground/web/src/pages/landing/index.tsx
@@ -0,0 +1,21 @@
+import Cookies from 'js-cookie'
+import { useNavigate } from 'react-router-dom'
+
+function LandingContent() {
+ const navigate = useNavigate()
+ const requestLogin = () => {
+ Cookies.set('hi', 'Hola!')
+ navigate('/projects')
+ }
+
+ return (
+
+
안녕하세요 함수형 프로그래밍 스터디입니다.
+
+
+ )
+}
+
+export default LandingContent
diff --git a/playground/web/src/router/index.tsx b/playground/web/src/router/index.tsx
new file mode 100644
index 0000000..5ad7080
--- /dev/null
+++ b/playground/web/src/router/index.tsx
@@ -0,0 +1,11 @@
+import { useRoutes } from 'react-router-dom'
+
+import { publicRoutes } from './routes/public'
+
+function Router() {
+ const routes = useRoutes([publicRoutes])
+
+ return routes
+}
+
+export default Router
diff --git a/playground/web/src/router/routes/public.tsx b/playground/web/src/router/routes/public.tsx
new file mode 100644
index 0000000..3699e90
--- /dev/null
+++ b/playground/web/src/router/routes/public.tsx
@@ -0,0 +1,39 @@
+import { type RouteObject, Navigate } from 'react-router-dom'
+
+import HomeRoutes from 'home/HomeRoutes'
+import ProjectsRoutes from 'projects/ProjectsRoutes'
+import MembersRoutes from 'members/MembersRoutes'
+
+import LandingContent from '@/pages'
+import { LayoutComponent } from '@/components'
+import { PATH } from '@/data/path'
+
+export const publicRoutes: RouteObject = {
+ element: ,
+ children: [
+ {
+ children: [
+ {
+ path: PATH.landing,
+ element: ,
+ },
+ {
+ path: PATH.home,
+ element: ,
+ },
+ {
+ path: PATH.members,
+ element: ,
+ },
+ {
+ path: PATH.projects,
+ element: ,
+ },
+ {
+ path: '/',
+ element: ,
+ },
+ ],
+ },
+ ],
+}
diff --git a/playground/web/src/types/auth.ts b/playground/web/src/types/auth.ts
new file mode 100644
index 0000000..3fabe44
--- /dev/null
+++ b/playground/web/src/types/auth.ts
@@ -0,0 +1,4 @@
+export interface IToken {
+ accessToken: string
+ refreshToken: string
+}
diff --git a/playground/web/src/types/index.ts b/playground/web/src/types/index.ts
new file mode 100644
index 0000000..f140b2e
--- /dev/null
+++ b/playground/web/src/types/index.ts
@@ -0,0 +1 @@
+export * from './auth'
diff --git a/playground/web/src/vite-env.d.ts b/playground/web/src/vite-env.d.ts
new file mode 100644
index 0000000..11f02fe
--- /dev/null
+++ b/playground/web/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/playground/web/tsconfig.app.json b/playground/web/tsconfig.app.json
new file mode 100644
index 0000000..b416f44
--- /dev/null
+++ b/playground/web/tsconfig.app.json
@@ -0,0 +1,29 @@
+{
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "isolatedModules": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+ "jsx": "react-jsx",
+
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true,
+
+ "baseUrl": "./",
+ "paths": {
+ "@/*": ["./src/*"]
+ }
+ },
+ "include": ["src"]
+}
diff --git a/playground/web/tsconfig.json b/playground/web/tsconfig.json
new file mode 100644
index 0000000..d32ff68
--- /dev/null
+++ b/playground/web/tsconfig.json
@@ -0,0 +1,4 @@
+{
+ "files": [],
+ "references": [{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" }]
+}
diff --git a/playground/web/tsconfig.node.json b/playground/web/tsconfig.node.json
new file mode 100644
index 0000000..c921d97
--- /dev/null
+++ b/playground/web/tsconfig.node.json
@@ -0,0 +1,22 @@
+{
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
+ "target": "ES2022",
+ "lib": ["ES2023"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "isolatedModules": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/playground/web/vite.config.ts b/playground/web/vite.config.ts
new file mode 100644
index 0000000..8592d34
--- /dev/null
+++ b/playground/web/vite.config.ts
@@ -0,0 +1,40 @@
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react-swc'
+import federation from '@originjs/vite-plugin-federation'
+import * as path from 'node:path'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [
+ react(),
+ federation({
+ name: 'host-app',
+ remotes: {
+ home: 'http://localhost:3001/assets/home.js',
+ projects: 'http://localhost:3002/assets/projects.js',
+ members: 'http://localhost:3003/assets/members.js',
+ },
+ shared: ['react', 'react-dom', 'react-router-dom'],
+ }),
+ ],
+ server: {
+ port: 3000,
+ },
+ preview: {
+ port: 3000,
+ },
+ resolve: {
+ alias: [
+ {
+ find: '@',
+ replacement: path.resolve(__dirname, 'src'),
+ },
+ ],
+ },
+ build: {
+ modulePreload: false,
+ target: 'esnext',
+ minify: false,
+ cssCodeSplit: false,
+ },
+})
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
new file mode 100644
index 0000000..d7a4766
--- /dev/null
+++ b/pnpm-lock.yaml
@@ -0,0 +1,2329 @@
+lockfileVersion: '9.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+importers:
+
+ .:
+ devDependencies:
+ '@biomejs/biome':
+ specifier: 1.7.3
+ version: 1.7.3
+ '@types/node':
+ specifier: 20.13.0
+ version: 20.13.0
+ husky:
+ specifier: ^9.0.11
+ version: 9.1.7
+ nano-staged:
+ specifier: ^0.8.0
+ version: 0.8.0
+ turbo:
+ specifier: ^2.0.7
+ version: 2.3.3
+ typescript:
+ specifier: ^5.4.5
+ version: 5.6.3
+
+ playground/apps/home:
+ dependencies:
+ '@functional-javascript-programming/utils':
+ specifier: workspace:*
+ version: link:../../packages/utils
+ axios:
+ specifier: ^1.7.9
+ version: 1.7.9
+ js-cookie:
+ specifier: ^3.0.5
+ version: 3.0.5
+ react:
+ specifier: ^18.3.1
+ version: 18.3.1
+ react-dom:
+ specifier: ^18.3.1
+ version: 18.3.1(react@18.3.1)
+ react-router-dom:
+ specifier: ^7.0.2
+ version: 7.0.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ devDependencies:
+ '@eslint/js':
+ specifier: ^9.15.0
+ version: 9.17.0
+ '@originjs/vite-plugin-federation':
+ specifier: ^1.3.6
+ version: 1.3.6
+ '@types/js-cookie':
+ specifier: ^3.0.6
+ version: 3.0.6
+ '@types/react':
+ specifier: ^18.3.12
+ version: 18.3.17
+ '@types/react-dom':
+ specifier: ^18.3.1
+ version: 18.3.5(@types/react@18.3.17)
+ '@vitejs/plugin-react-swc':
+ specifier: ^3.5.0
+ version: 3.7.2(vite@6.0.3(@types/node@20.13.0))
+ eslint:
+ specifier: ^9.15.0
+ version: 9.17.0
+ eslint-plugin-react-hooks:
+ specifier: ^5.0.0
+ version: 5.1.0(eslint@9.17.0)
+ eslint-plugin-react-refresh:
+ specifier: ^0.4.14
+ version: 0.4.16(eslint@9.17.0)
+ globals:
+ specifier: ^15.12.0
+ version: 15.13.0
+ typescript:
+ specifier: ~5.6.2
+ version: 5.6.3
+ typescript-eslint:
+ specifier: ^8.15.0
+ version: 8.18.1(eslint@9.17.0)(typescript@5.6.3)
+ vite:
+ specifier: ^6.0.1
+ version: 6.0.3(@types/node@20.13.0)
+
+ playground/apps/members:
+ dependencies:
+ '@functional-javascript-programming/utils':
+ specifier: workspace:*
+ version: link:../../packages/utils
+ axios:
+ specifier: ^1.7.9
+ version: 1.7.9
+ js-cookie:
+ specifier: ^3.0.5
+ version: 3.0.5
+ react:
+ specifier: ^18.3.1
+ version: 18.3.1
+ react-dom:
+ specifier: ^18.3.1
+ version: 18.3.1(react@18.3.1)
+ react-router-dom:
+ specifier: ^7.0.2
+ version: 7.0.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ devDependencies:
+ '@eslint/js':
+ specifier: ^9.15.0
+ version: 9.17.0
+ '@originjs/vite-plugin-federation':
+ specifier: ^1.3.6
+ version: 1.3.6
+ '@types/js-cookie':
+ specifier: ^3.0.6
+ version: 3.0.6
+ '@types/react':
+ specifier: ^18.3.12
+ version: 18.3.17
+ '@types/react-dom':
+ specifier: ^18.3.1
+ version: 18.3.5(@types/react@18.3.17)
+ '@vitejs/plugin-react-swc':
+ specifier: ^3.5.0
+ version: 3.7.2(vite@6.0.3(@types/node@20.13.0))
+ eslint:
+ specifier: ^9.15.0
+ version: 9.17.0
+ eslint-plugin-react-hooks:
+ specifier: ^5.0.0
+ version: 5.1.0(eslint@9.17.0)
+ eslint-plugin-react-refresh:
+ specifier: ^0.4.14
+ version: 0.4.16(eslint@9.17.0)
+ globals:
+ specifier: ^15.12.0
+ version: 15.13.0
+ typescript:
+ specifier: ~5.6.2
+ version: 5.6.3
+ typescript-eslint:
+ specifier: ^8.15.0
+ version: 8.18.1(eslint@9.17.0)(typescript@5.6.3)
+ vite:
+ specifier: ^6.0.1
+ version: 6.0.3(@types/node@20.13.0)
+
+ playground/apps/projects:
+ dependencies:
+ '@functional-javascript-programming/utils':
+ specifier: workspace:*
+ version: link:../../packages/utils
+ axios:
+ specifier: ^1.7.9
+ version: 1.7.9
+ js-cookie:
+ specifier: ^3.0.5
+ version: 3.0.5
+ react:
+ specifier: ^18.3.1
+ version: 18.3.1
+ react-dom:
+ specifier: ^18.3.1
+ version: 18.3.1(react@18.3.1)
+ react-router-dom:
+ specifier: ^7.0.2
+ version: 7.0.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ devDependencies:
+ '@eslint/js':
+ specifier: ^9.15.0
+ version: 9.17.0
+ '@originjs/vite-plugin-federation':
+ specifier: ^1.3.6
+ version: 1.3.6
+ '@types/js-cookie':
+ specifier: ^3.0.6
+ version: 3.0.6
+ '@types/react':
+ specifier: ^18.3.12
+ version: 18.3.17
+ '@types/react-dom':
+ specifier: ^18.3.1
+ version: 18.3.5(@types/react@18.3.17)
+ '@vitejs/plugin-react-swc':
+ specifier: ^3.5.0
+ version: 3.7.2(vite@6.0.3(@types/node@20.13.0))
+ eslint:
+ specifier: ^9.15.0
+ version: 9.17.0
+ eslint-plugin-react-hooks:
+ specifier: ^5.0.0
+ version: 5.1.0(eslint@9.17.0)
+ eslint-plugin-react-refresh:
+ specifier: ^0.4.14
+ version: 0.4.16(eslint@9.17.0)
+ globals:
+ specifier: ^15.12.0
+ version: 15.13.0
+ typescript:
+ specifier: ~5.6.2
+ version: 5.6.3
+ typescript-eslint:
+ specifier: ^8.15.0
+ version: 8.18.1(eslint@9.17.0)(typescript@5.6.3)
+ vite:
+ specifier: ^6.0.1
+ version: 6.0.3(@types/node@20.13.0)
+
+ playground/packages/esbuild:
+ dependencies:
+ esbuild:
+ specifier: ^0.24.0
+ version: 0.24.0
+
+ playground/packages/tsconfig: {}
+
+ playground/packages/utils:
+ devDependencies:
+ '@functional-javascript-programming/typescript-config':
+ specifier: workspace:*
+ version: link:../tsconfig
+
+ playground/web:
+ dependencies:
+ axios:
+ specifier: ^1.7.9
+ version: 1.7.9
+ js-cookie:
+ specifier: ^3.0.5
+ version: 3.0.5
+ react:
+ specifier: ^18.3.1
+ version: 18.3.1
+ react-dom:
+ specifier: ^18.3.1
+ version: 18.3.1(react@18.3.1)
+ react-router-dom:
+ specifier: ^7.0.2
+ version: 7.0.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ devDependencies:
+ '@eslint/js':
+ specifier: ^9.15.0
+ version: 9.17.0
+ '@originjs/vite-plugin-federation':
+ specifier: ^1.3.6
+ version: 1.3.6
+ '@types/js-cookie':
+ specifier: ^3.0.6
+ version: 3.0.6
+ '@types/react':
+ specifier: ^18.3.12
+ version: 18.3.17
+ '@types/react-dom':
+ specifier: ^18.3.1
+ version: 18.3.5(@types/react@18.3.17)
+ '@vitejs/plugin-react-swc':
+ specifier: ^3.5.0
+ version: 3.7.2(vite@6.0.3(@types/node@20.13.0))
+ eslint:
+ specifier: ^9.15.0
+ version: 9.17.0
+ eslint-plugin-react-hooks:
+ specifier: ^5.0.0
+ version: 5.1.0(eslint@9.17.0)
+ eslint-plugin-react-refresh:
+ specifier: ^0.4.14
+ version: 0.4.16(eslint@9.17.0)
+ globals:
+ specifier: ^15.12.0
+ version: 15.13.0
+ typescript:
+ specifier: ~5.6.2
+ version: 5.6.3
+ typescript-eslint:
+ specifier: ^8.15.0
+ version: 8.18.1(eslint@9.17.0)(typescript@5.6.3)
+ vite:
+ specifier: ^6.0.1
+ version: 6.0.3(@types/node@20.13.0)
+
+packages:
+
+ '@biomejs/biome@1.7.3':
+ resolution: {integrity: sha512-ogFQI+fpXftr+tiahA6bIXwZ7CSikygASdqMtH07J2cUzrpjyTMVc9Y97v23c7/tL1xCZhM+W9k4hYIBm7Q6cQ==}
+ engines: {node: '>=14.21.3'}
+ hasBin: true
+
+ '@biomejs/cli-darwin-arm64@1.7.3':
+ resolution: {integrity: sha512-eDvLQWmGRqrPIRY7AIrkPHkQ3visEItJKkPYSHCscSDdGvKzYjmBJwG1Gu8+QC5ed6R7eiU63LEC0APFBobmfQ==}
+ engines: {node: '>=14.21.3'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@biomejs/cli-darwin-x64@1.7.3':
+ resolution: {integrity: sha512-JXCaIseKRER7dIURsVlAJacnm8SG5I0RpxZ4ya3dudASYUc68WGl4+FEN03ABY3KMIq7hcK1tzsJiWlmXyosZg==}
+ engines: {node: '>=14.21.3'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@biomejs/cli-linux-arm64-musl@1.7.3':
+ resolution: {integrity: sha512-c8AlO45PNFZ1BYcwaKzdt46kYbuP6xPGuGQ6h4j3XiEDpyseRRUy/h+6gxj07XovmyxKnSX9GSZ6nVbZvcVUAw==}
+ engines: {node: '>=14.21.3'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@biomejs/cli-linux-arm64@1.7.3':
+ resolution: {integrity: sha512-phNTBpo7joDFastnmZsFjYcDYobLTx4qR4oPvc9tJ486Bd1SfEVPHEvJdNJrMwUQK56T+TRClOQd/8X1nnjA9w==}
+ engines: {node: '>=14.21.3'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@biomejs/cli-linux-x64-musl@1.7.3':
+ resolution: {integrity: sha512-UdEHKtYGWEX3eDmVWvQeT+z05T9/Sdt2+F/7zmMOFQ7boANeX8pcO6EkJPK3wxMudrApsNEKT26rzqK6sZRTRA==}
+ engines: {node: '>=14.21.3'}
+ cpu: [x64]
+ os: [linux]
+
+ '@biomejs/cli-linux-x64@1.7.3':
+ resolution: {integrity: sha512-vnedYcd5p4keT3iD48oSKjOIRPYcjSNNbd8MO1bKo9ajg3GwQXZLAH+0Cvlr+eMsO67/HddWmscSQwTFrC/uPA==}
+ engines: {node: '>=14.21.3'}
+ cpu: [x64]
+ os: [linux]
+
+ '@biomejs/cli-win32-arm64@1.7.3':
+ resolution: {integrity: sha512-unNCDqUKjujYkkSxs7gFIfdasttbDC4+z0kYmcqzRk6yWVoQBL4dNLcCbdnJS+qvVDNdI9rHp2NwpQ0WAdla4Q==}
+ engines: {node: '>=14.21.3'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@biomejs/cli-win32-x64@1.7.3':
+ resolution: {integrity: sha512-ZmByhbrnmz/UUFYB622CECwhKIPjJLLPr5zr3edhu04LzbfcOrz16VYeNq5dpO1ADG70FORhAJkaIGdaVBG00w==}
+ engines: {node: '>=14.21.3'}
+ cpu: [x64]
+ os: [win32]
+
+ '@esbuild/aix-ppc64@0.24.0':
+ resolution: {integrity: sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [aix]
+
+ '@esbuild/android-arm64@0.24.0':
+ resolution: {integrity: sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [android]
+
+ '@esbuild/android-arm@0.24.0':
+ resolution: {integrity: sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [android]
+
+ '@esbuild/android-x64@0.24.0':
+ resolution: {integrity: sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [android]
+
+ '@esbuild/darwin-arm64@0.24.0':
+ resolution: {integrity: sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@esbuild/darwin-x64@0.24.0':
+ resolution: {integrity: sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@esbuild/freebsd-arm64@0.24.0':
+ resolution: {integrity: sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@esbuild/freebsd-x64@0.24.0':
+ resolution: {integrity: sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@esbuild/linux-arm64@0.24.0':
+ resolution: {integrity: sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@esbuild/linux-arm@0.24.0':
+ resolution: {integrity: sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [linux]
+
+ '@esbuild/linux-ia32@0.24.0':
+ resolution: {integrity: sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [linux]
+
+ '@esbuild/linux-loong64@0.24.0':
+ resolution: {integrity: sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==}
+ engines: {node: '>=18'}
+ cpu: [loong64]
+ os: [linux]
+
+ '@esbuild/linux-mips64el@0.24.0':
+ resolution: {integrity: sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==}
+ engines: {node: '>=18'}
+ cpu: [mips64el]
+ os: [linux]
+
+ '@esbuild/linux-ppc64@0.24.0':
+ resolution: {integrity: sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@esbuild/linux-riscv64@0.24.0':
+ resolution: {integrity: sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==}
+ engines: {node: '>=18'}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@esbuild/linux-s390x@0.24.0':
+ resolution: {integrity: sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==}
+ engines: {node: '>=18'}
+ cpu: [s390x]
+ os: [linux]
+
+ '@esbuild/linux-x64@0.24.0':
+ resolution: {integrity: sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [linux]
+
+ '@esbuild/netbsd-x64@0.24.0':
+ resolution: {integrity: sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [netbsd]
+
+ '@esbuild/openbsd-arm64@0.24.0':
+ resolution: {integrity: sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openbsd]
+
+ '@esbuild/openbsd-x64@0.24.0':
+ resolution: {integrity: sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@esbuild/sunos-x64@0.24.0':
+ resolution: {integrity: sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [sunos]
+
+ '@esbuild/win32-arm64@0.24.0':
+ resolution: {integrity: sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@esbuild/win32-ia32@0.24.0':
+ resolution: {integrity: sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [win32]
+
+ '@esbuild/win32-x64@0.24.0':
+ resolution: {integrity: sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [win32]
+
+ '@eslint-community/eslint-utils@4.4.1':
+ resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
+
+ '@eslint-community/regexpp@4.12.1':
+ resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==}
+ engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
+
+ '@eslint/config-array@0.19.1':
+ resolution: {integrity: sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@eslint/core@0.9.1':
+ resolution: {integrity: sha512-GuUdqkyyzQI5RMIWkHhvTWLCyLo1jNK3vzkSyaExH5kHPDHcuL2VOpHjmMY+y3+NC69qAKToBqldTBgYeLSr9Q==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@eslint/eslintrc@3.2.0':
+ resolution: {integrity: sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@eslint/js@9.17.0':
+ resolution: {integrity: sha512-Sxc4hqcs1kTu0iID3kcZDW3JHq2a77HO9P8CP6YEA/FpH3Ll8UXE2r/86Rz9YJLKme39S9vU5OWNjC6Xl0Cr3w==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@eslint/object-schema@2.1.5':
+ resolution: {integrity: sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@eslint/plugin-kit@0.2.4':
+ resolution: {integrity: sha512-zSkKow6H5Kdm0ZUQUB2kV5JIXqoG0+uH5YADhaEHswm664N9Db8dXSi0nMJpacpMf+MyyglF1vnZohpEg5yUtg==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@humanfs/core@0.19.1':
+ resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
+ engines: {node: '>=18.18.0'}
+
+ '@humanfs/node@0.16.6':
+ resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==}
+ engines: {node: '>=18.18.0'}
+
+ '@humanwhocodes/module-importer@1.0.1':
+ resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
+ engines: {node: '>=12.22'}
+
+ '@humanwhocodes/retry@0.3.1':
+ resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==}
+ engines: {node: '>=18.18'}
+
+ '@humanwhocodes/retry@0.4.1':
+ resolution: {integrity: sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==}
+ engines: {node: '>=18.18'}
+
+ '@jridgewell/sourcemap-codec@1.5.0':
+ resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
+
+ '@nodelib/fs.scandir@2.1.5':
+ resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
+ engines: {node: '>= 8'}
+
+ '@nodelib/fs.stat@2.0.5':
+ resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
+ engines: {node: '>= 8'}
+
+ '@nodelib/fs.walk@1.2.8':
+ resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
+ engines: {node: '>= 8'}
+
+ '@originjs/vite-plugin-federation@1.3.6':
+ resolution: {integrity: sha512-tHLMjdMJFPFMSJrUuJJiv8l7OFRvM19E9O1B9dhbk+04i3RnYwE9A6oNtSUM1dnvkalzCLwZIuMpti28/tnh8g==}
+ engines: {node: '>=14.0.0', pnpm: '>=7.0.1'}
+
+ '@rollup/rollup-android-arm-eabi@4.28.1':
+ resolution: {integrity: sha512-2aZp8AES04KI2dy3Ss6/MDjXbwBzj+i0GqKtWXgw2/Ma6E4jJvujryO6gJAghIRVz7Vwr9Gtl/8na3nDUKpraQ==}
+ cpu: [arm]
+ os: [android]
+
+ '@rollup/rollup-android-arm64@4.28.1':
+ resolution: {integrity: sha512-EbkK285O+1YMrg57xVA+Dp0tDBRB93/BZKph9XhMjezf6F4TpYjaUSuPt5J0fZXlSag0LmZAsTmdGGqPp4pQFA==}
+ cpu: [arm64]
+ os: [android]
+
+ '@rollup/rollup-darwin-arm64@4.28.1':
+ resolution: {integrity: sha512-prduvrMKU6NzMq6nxzQw445zXgaDBbMQvmKSJaxpaZ5R1QDM8w+eGxo6Y/jhT/cLoCvnZI42oEqf9KQNYz1fqQ==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@rollup/rollup-darwin-x64@4.28.1':
+ resolution: {integrity: sha512-WsvbOunsUk0wccO/TV4o7IKgloJ942hVFK1CLatwv6TJspcCZb9umQkPdvB7FihmdxgaKR5JyxDjWpCOp4uZlQ==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@rollup/rollup-freebsd-arm64@4.28.1':
+ resolution: {integrity: sha512-HTDPdY1caUcU4qK23FeeGxCdJF64cKkqajU0iBnTVxS8F7H/7BewvYoG+va1KPSL63kQ1PGNyiwKOfReavzvNA==}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@rollup/rollup-freebsd-x64@4.28.1':
+ resolution: {integrity: sha512-m/uYasxkUevcFTeRSM9TeLyPe2QDuqtjkeoTpP9SW0XxUWfcYrGDMkO/m2tTw+4NMAF9P2fU3Mw4ahNvo7QmsQ==}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.28.1':
+ resolution: {integrity: sha512-QAg11ZIt6mcmzpNE6JZBpKfJaKkqTm1A9+y9O+frdZJEuhQxiugM05gnCWiANHj4RmbgeVJpTdmKRmH/a+0QbA==}
+ cpu: [arm]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm-musleabihf@4.28.1':
+ resolution: {integrity: sha512-dRP9PEBfolq1dmMcFqbEPSd9VlRuVWEGSmbxVEfiq2cs2jlZAl0YNxFzAQS2OrQmsLBLAATDMb3Z6MFv5vOcXg==}
+ cpu: [arm]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm64-gnu@4.28.1':
+ resolution: {integrity: sha512-uGr8khxO+CKT4XU8ZUH1TTEUtlktK6Kgtv0+6bIFSeiSlnGJHG1tSFSjm41uQ9sAO/5ULx9mWOz70jYLyv1QkA==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm64-musl@4.28.1':
+ resolution: {integrity: sha512-QF54q8MYGAqMLrX2t7tNpi01nvq5RI59UBNx+3+37zoKX5KViPo/gk2QLhsuqok05sSCRluj0D00LzCwBikb0A==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rollup/rollup-linux-loongarch64-gnu@4.28.1':
+ resolution: {integrity: sha512-vPul4uodvWvLhRco2w0GcyZcdyBfpfDRgNKU+p35AWEbJ/HPs1tOUrkSueVbBS0RQHAf/A+nNtDpvw95PeVKOA==}
+ cpu: [loong64]
+ os: [linux]
+
+ '@rollup/rollup-linux-powerpc64le-gnu@4.28.1':
+ resolution: {integrity: sha512-pTnTdBuC2+pt1Rmm2SV7JWRqzhYpEILML4PKODqLz+C7Ou2apEV52h19CR7es+u04KlqplggmN9sqZlekg3R1A==}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@rollup/rollup-linux-riscv64-gnu@4.28.1':
+ resolution: {integrity: sha512-vWXy1Nfg7TPBSuAncfInmAI/WZDd5vOklyLJDdIRKABcZWojNDY0NJwruY2AcnCLnRJKSaBgf/GiJfauu8cQZA==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@rollup/rollup-linux-s390x-gnu@4.28.1':
+ resolution: {integrity: sha512-/yqC2Y53oZjb0yz8PVuGOQQNOTwxcizudunl/tFs1aLvObTclTwZ0JhXF2XcPT/zuaymemCDSuuUPXJJyqeDOg==}
+ cpu: [s390x]
+ os: [linux]
+
+ '@rollup/rollup-linux-x64-gnu@4.28.1':
+ resolution: {integrity: sha512-fzgeABz7rrAlKYB0y2kSEiURrI0691CSL0+KXwKwhxvj92VULEDQLpBYLHpF49MSiPG4sq5CK3qHMnb9tlCjBw==}
+ cpu: [x64]
+ os: [linux]
+
+ '@rollup/rollup-linux-x64-musl@4.28.1':
+ resolution: {integrity: sha512-xQTDVzSGiMlSshpJCtudbWyRfLaNiVPXt1WgdWTwWz9n0U12cI2ZVtWe/Jgwyv/6wjL7b66uu61Vg0POWVfz4g==}
+ cpu: [x64]
+ os: [linux]
+
+ '@rollup/rollup-win32-arm64-msvc@4.28.1':
+ resolution: {integrity: sha512-wSXmDRVupJstFP7elGMgv+2HqXelQhuNf+IS4V+nUpNVi/GUiBgDmfwD0UGN3pcAnWsgKG3I52wMOBnk1VHr/A==}
+ cpu: [arm64]
+ os: [win32]
+
+ '@rollup/rollup-win32-ia32-msvc@4.28.1':
+ resolution: {integrity: sha512-ZkyTJ/9vkgrE/Rk9vhMXhf8l9D+eAhbAVbsGsXKy2ohmJaWg0LPQLnIxRdRp/bKyr8tXuPlXhIoGlEB5XpJnGA==}
+ cpu: [ia32]
+ os: [win32]
+
+ '@rollup/rollup-win32-x64-msvc@4.28.1':
+ resolution: {integrity: sha512-ZvK2jBafvttJjoIdKm/Q/Bh7IJ1Ose9IBOwpOXcOvW3ikGTQGmKDgxTC6oCAzW6PynbkKP8+um1du81XJHZ0JA==}
+ cpu: [x64]
+ os: [win32]
+
+ '@swc/core-darwin-arm64@1.10.1':
+ resolution: {integrity: sha512-NyELPp8EsVZtxH/mEqvzSyWpfPJ1lugpTQcSlMduZLj1EASLO4sC8wt8hmL1aizRlsbjCX+r0PyL+l0xQ64/6Q==}
+ engines: {node: '>=10'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@swc/core-darwin-x64@1.10.1':
+ resolution: {integrity: sha512-L4BNt1fdQ5ZZhAk5qoDfUnXRabDOXKnXBxMDJ+PWLSxOGBbWE6aJTnu4zbGjJvtot0KM46m2LPAPY8ttknqaZA==}
+ engines: {node: '>=10'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@swc/core-linux-arm-gnueabihf@1.10.1':
+ resolution: {integrity: sha512-Y1u9OqCHgvVp2tYQAJ7hcU9qO5brDMIrA5R31rwWQIAKDkJKtv3IlTHF0hrbWk1wPR0ZdngkQSJZple7G+Grvw==}
+ engines: {node: '>=10'}
+ cpu: [arm]
+ os: [linux]
+
+ '@swc/core-linux-arm64-gnu@1.10.1':
+ resolution: {integrity: sha512-tNQHO/UKdtnqjc7o04iRXng1wTUXPgVd8Y6LI4qIbHVoVPwksZydISjMcilKNLKIwOoUQAkxyJ16SlOAeADzhQ==}
+ engines: {node: '>=10'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@swc/core-linux-arm64-musl@1.10.1':
+ resolution: {integrity: sha512-x0L2Pd9weQ6n8dI1z1Isq00VHFvpBClwQJvrt3NHzmR+1wCT/gcYl1tp9P5xHh3ldM8Cn4UjWCw+7PaUgg8FcQ==}
+ engines: {node: '>=10'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@swc/core-linux-x64-gnu@1.10.1':
+ resolution: {integrity: sha512-yyYEwQcObV3AUsC79rSzN9z6kiWxKAVJ6Ntwq2N9YoZqSPYph+4/Am5fM1xEQYf/kb99csj0FgOelomJSobxQA==}
+ engines: {node: '>=10'}
+ cpu: [x64]
+ os: [linux]
+
+ '@swc/core-linux-x64-musl@1.10.1':
+ resolution: {integrity: sha512-tcaS43Ydd7Fk7sW5ROpaf2Kq1zR+sI5K0RM+0qYLYYurvsJruj3GhBCaiN3gkzd8m/8wkqNqtVklWaQYSDsyqA==}
+ engines: {node: '>=10'}
+ cpu: [x64]
+ os: [linux]
+
+ '@swc/core-win32-arm64-msvc@1.10.1':
+ resolution: {integrity: sha512-D3Qo1voA7AkbOzQ2UGuKNHfYGKL6eejN8VWOoQYtGHHQi1p5KK/Q7V1ku55oxXBsj79Ny5FRMqiRJpVGad7bjQ==}
+ engines: {node: '>=10'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@swc/core-win32-ia32-msvc@1.10.1':
+ resolution: {integrity: sha512-WalYdFoU3454Og+sDKHM1MrjvxUGwA2oralknXkXL8S0I/8RkWZOB++p3pLaGbTvOO++T+6znFbQdR8KRaa7DA==}
+ engines: {node: '>=10'}
+ cpu: [ia32]
+ os: [win32]
+
+ '@swc/core-win32-x64-msvc@1.10.1':
+ resolution: {integrity: sha512-JWobfQDbTnoqaIwPKQ3DVSywihVXlQMbDuwik/dDWlj33A8oEHcjPOGs4OqcA3RHv24i+lfCQpM3Mn4FAMfacA==}
+ engines: {node: '>=10'}
+ cpu: [x64]
+ os: [win32]
+
+ '@swc/core@1.10.1':
+ resolution: {integrity: sha512-rQ4dS6GAdmtzKiCRt3LFVxl37FaY1cgL9kSUTnhQ2xc3fmHOd7jdJK/V4pSZMG1ruGTd0bsi34O2R0Olg9Zo/w==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ '@swc/helpers': '*'
+ peerDependenciesMeta:
+ '@swc/helpers':
+ optional: true
+
+ '@swc/counter@0.1.3':
+ resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==}
+
+ '@swc/types@0.1.17':
+ resolution: {integrity: sha512-V5gRru+aD8YVyCOMAjMpWR1Ui577DD5KSJsHP8RAxopAH22jFz6GZd/qxqjO6MJHQhcsjvjOFXyDhyLQUnMveQ==}
+
+ '@types/cookie@0.6.0':
+ resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==}
+
+ '@types/estree@1.0.6':
+ resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
+
+ '@types/js-cookie@3.0.6':
+ resolution: {integrity: sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==}
+
+ '@types/json-schema@7.0.15':
+ resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
+
+ '@types/node@20.13.0':
+ resolution: {integrity: sha512-FM6AOb3khNkNIXPnHFDYaHerSv8uN22C91z098AnGccVu+Pcdhi+pNUFDi0iLmPIsVE0JBD0KVS7mzUYt4nRzQ==}
+
+ '@types/prop-types@15.7.14':
+ resolution: {integrity: sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==}
+
+ '@types/react-dom@18.3.5':
+ resolution: {integrity: sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q==}
+ peerDependencies:
+ '@types/react': ^18.0.0
+
+ '@types/react@18.3.17':
+ resolution: {integrity: sha512-opAQ5no6LqJNo9TqnxBKsgnkIYHozW9KSTlFVoSUJYh1Fl/sswkEoqIugRSm7tbh6pABtYjGAjW+GOS23j8qbw==}
+
+ '@typescript-eslint/eslint-plugin@8.18.1':
+ resolution: {integrity: sha512-Ncvsq5CT3Gvh+uJG0Lwlho6suwDfUXH0HztslDf5I+F2wAFAZMRwYLEorumpKLzmO2suAXZ/td1tBg4NZIi9CQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <5.8.0'
+
+ '@typescript-eslint/parser@8.18.1':
+ resolution: {integrity: sha512-rBnTWHCdbYM2lh7hjyXqxk70wvon3p2FyaniZuey5TrcGBpfhVp0OxOa6gxr9Q9YhZFKyfbEnxc24ZnVbbUkCA==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <5.8.0'
+
+ '@typescript-eslint/scope-manager@8.18.1':
+ resolution: {integrity: sha512-HxfHo2b090M5s2+/9Z3gkBhI6xBH8OJCFjH9MhQ+nnoZqxU3wNxkLT+VWXWSFWc3UF3Z+CfPAyqdCTdoXtDPCQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@typescript-eslint/type-utils@8.18.1':
+ resolution: {integrity: sha512-jAhTdK/Qx2NJPNOTxXpMwlOiSymtR2j283TtPqXkKBdH8OAMmhiUfP0kJjc/qSE51Xrq02Gj9NY7MwK+UxVwHQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <5.8.0'
+
+ '@typescript-eslint/types@8.18.1':
+ resolution: {integrity: sha512-7uoAUsCj66qdNQNpH2G8MyTFlgerum8ubf21s3TSM3XmKXuIn+H2Sifh/ES2nPOPiYSRJWAk0fDkW0APBWcpfw==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@typescript-eslint/typescript-estree@8.18.1':
+ resolution: {integrity: sha512-z8U21WI5txzl2XYOW7i9hJhxoKKNG1kcU4RzyNvKrdZDmbjkmLBo8bgeiOJmA06kizLI76/CCBAAGlTlEeUfyg==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ typescript: '>=4.8.4 <5.8.0'
+
+ '@typescript-eslint/utils@8.18.1':
+ resolution: {integrity: sha512-8vikiIj2ebrC4WRdcAdDcmnu9Q/MXXwg+STf40BVfT8exDqBCUPdypvzcUPxEqRGKg9ALagZ0UWcYCtn+4W2iQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <5.8.0'
+
+ '@typescript-eslint/visitor-keys@8.18.1':
+ resolution: {integrity: sha512-Vj0WLm5/ZsD013YeUKn+K0y8p1M0jPpxOkKdbD1wB0ns53a5piVY02zjf072TblEweAbcYiFiPoSMF3kp+VhhQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@vitejs/plugin-react-swc@3.7.2':
+ resolution: {integrity: sha512-y0byko2b2tSVVf5Gpng1eEhX1OvPC7x8yns1Fx8jDzlJp4LS6CMkCPfLw47cjyoMrshQDoQw4qcgjsU9VvlCew==}
+ peerDependencies:
+ vite: ^4 || ^5 || ^6
+
+ acorn-jsx@5.3.2:
+ resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
+ peerDependencies:
+ acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
+
+ acorn@8.14.0:
+ resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==}
+ engines: {node: '>=0.4.0'}
+ hasBin: true
+
+ ajv@6.12.6:
+ resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
+
+ ansi-styles@4.3.0:
+ resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
+ engines: {node: '>=8'}
+
+ argparse@2.0.1:
+ resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
+
+ asynckit@0.4.0:
+ resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
+
+ axios@1.7.9:
+ resolution: {integrity: sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==}
+
+ balanced-match@1.0.2:
+ resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+
+ brace-expansion@1.1.11:
+ resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
+
+ brace-expansion@2.0.1:
+ resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
+
+ braces@3.0.3:
+ resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
+ engines: {node: '>=8'}
+
+ callsites@3.1.0:
+ resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
+ engines: {node: '>=6'}
+
+ chalk@4.1.2:
+ resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
+ engines: {node: '>=10'}
+
+ color-convert@2.0.1:
+ resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
+ engines: {node: '>=7.0.0'}
+
+ color-name@1.1.4:
+ resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+
+ combined-stream@1.0.8:
+ resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
+ engines: {node: '>= 0.8'}
+
+ concat-map@0.0.1:
+ resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
+
+ cookie@1.0.2:
+ resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==}
+ engines: {node: '>=18'}
+
+ cross-spawn@7.0.6:
+ resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
+ engines: {node: '>= 8'}
+
+ csstype@3.1.3:
+ resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
+
+ debug@4.4.0:
+ resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
+ deep-is@0.1.4:
+ resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
+
+ delayed-stream@1.0.0:
+ resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
+ engines: {node: '>=0.4.0'}
+
+ esbuild@0.24.0:
+ resolution: {integrity: sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==}
+ engines: {node: '>=18'}
+ hasBin: true
+
+ escape-string-regexp@4.0.0:
+ resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
+ engines: {node: '>=10'}
+
+ eslint-plugin-react-hooks@5.1.0:
+ resolution: {integrity: sha512-mpJRtPgHN2tNAvZ35AMfqeB3Xqeo273QxrHJsbBEPWODRM4r0yB6jfoROqKEYrOn27UtRPpcpHc2UqyBSuUNTw==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0
+
+ eslint-plugin-react-refresh@0.4.16:
+ resolution: {integrity: sha512-slterMlxAhov/DZO8NScf6mEeMBBXodFUolijDvrtTxyezyLoTQaa73FyYus/VbTdftd8wBgBxPMRk3poleXNQ==}
+ peerDependencies:
+ eslint: '>=8.40'
+
+ eslint-scope@8.2.0:
+ resolution: {integrity: sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ eslint-visitor-keys@3.4.3:
+ resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+
+ eslint-visitor-keys@4.2.0:
+ resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ eslint@9.17.0:
+ resolution: {integrity: sha512-evtlNcpJg+cZLcnVKwsai8fExnqjGPicK7gnUtlNuzu+Fv9bI0aLpND5T44VLQtoMEnI57LoXO9XAkIXwohKrA==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ hasBin: true
+ peerDependencies:
+ jiti: '*'
+ peerDependenciesMeta:
+ jiti:
+ optional: true
+
+ espree@10.3.0:
+ resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ esquery@1.6.0:
+ resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==}
+ engines: {node: '>=0.10'}
+
+ esrecurse@4.3.0:
+ resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
+ engines: {node: '>=4.0'}
+
+ estraverse@5.3.0:
+ resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
+ engines: {node: '>=4.0'}
+
+ estree-walker@3.0.3:
+ resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
+
+ esutils@2.0.3:
+ resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
+ engines: {node: '>=0.10.0'}
+
+ fast-deep-equal@3.1.3:
+ resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
+
+ fast-glob@3.3.2:
+ resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==}
+ engines: {node: '>=8.6.0'}
+
+ fast-json-stable-stringify@2.1.0:
+ resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
+
+ fast-levenshtein@2.0.6:
+ resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
+
+ fastq@1.17.1:
+ resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==}
+
+ file-entry-cache@8.0.0:
+ resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
+ engines: {node: '>=16.0.0'}
+
+ fill-range@7.1.1:
+ resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
+ engines: {node: '>=8'}
+
+ find-up@5.0.0:
+ resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
+ engines: {node: '>=10'}
+
+ flat-cache@4.0.1:
+ resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
+ engines: {node: '>=16'}
+
+ flatted@3.3.2:
+ resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==}
+
+ follow-redirects@1.15.9:
+ resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==}
+ engines: {node: '>=4.0'}
+ peerDependencies:
+ debug: '*'
+ peerDependenciesMeta:
+ debug:
+ optional: true
+
+ form-data@4.0.1:
+ resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==}
+ engines: {node: '>= 6'}
+
+ fsevents@2.3.3:
+ resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+
+ glob-parent@5.1.2:
+ resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
+ engines: {node: '>= 6'}
+
+ glob-parent@6.0.2:
+ resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
+ engines: {node: '>=10.13.0'}
+
+ globals@14.0.0:
+ resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
+ engines: {node: '>=18'}
+
+ globals@15.13.0:
+ resolution: {integrity: sha512-49TewVEz0UxZjr1WYYsWpPrhyC/B/pA8Bq0fUmet2n+eR7yn0IvNzNaoBwnK6mdkzcN+se7Ez9zUgULTz2QH4g==}
+ engines: {node: '>=18'}
+
+ graphemer@1.4.0:
+ resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
+
+ has-flag@4.0.0:
+ resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
+ engines: {node: '>=8'}
+
+ husky@9.1.7:
+ resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==}
+ engines: {node: '>=18'}
+ hasBin: true
+
+ ignore@5.3.2:
+ resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
+ engines: {node: '>= 4'}
+
+ import-fresh@3.3.0:
+ resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
+ engines: {node: '>=6'}
+
+ imurmurhash@0.1.4:
+ resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
+ engines: {node: '>=0.8.19'}
+
+ is-extglob@2.1.1:
+ resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+ engines: {node: '>=0.10.0'}
+
+ is-glob@4.0.3:
+ resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+ engines: {node: '>=0.10.0'}
+
+ is-number@7.0.0:
+ resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
+ engines: {node: '>=0.12.0'}
+
+ isexe@2.0.0:
+ resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+
+ js-cookie@3.0.5:
+ resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==}
+ engines: {node: '>=14'}
+
+ js-tokens@4.0.0:
+ resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+
+ js-yaml@4.1.0:
+ resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
+ hasBin: true
+
+ json-buffer@3.0.1:
+ resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
+
+ json-schema-traverse@0.4.1:
+ resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
+
+ json-stable-stringify-without-jsonify@1.0.1:
+ resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
+
+ keyv@4.5.4:
+ resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
+
+ levn@0.4.1:
+ resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
+ engines: {node: '>= 0.8.0'}
+
+ locate-path@6.0.0:
+ resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
+ engines: {node: '>=10'}
+
+ lodash.merge@4.6.2:
+ resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
+
+ loose-envify@1.4.0:
+ resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
+ hasBin: true
+
+ magic-string@0.27.0:
+ resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==}
+ engines: {node: '>=12'}
+
+ merge2@1.4.1:
+ resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
+ engines: {node: '>= 8'}
+
+ micromatch@4.0.8:
+ resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
+ engines: {node: '>=8.6'}
+
+ mime-db@1.52.0:
+ resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
+ engines: {node: '>= 0.6'}
+
+ mime-types@2.1.35:
+ resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
+ engines: {node: '>= 0.6'}
+
+ minimatch@3.1.2:
+ resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
+
+ minimatch@9.0.5:
+ resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
+ engines: {node: '>=16 || 14 >=14.17'}
+
+ ms@2.1.3:
+ resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+
+ nano-staged@0.8.0:
+ resolution: {integrity: sha512-QSEqPGTCJbkHU2yLvfY6huqYPjdBrOaTMKatO1F8nCSrkQGXeKwtCiCnsdxnuMhbg3DTVywKaeWLGCE5oJpq0g==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ hasBin: true
+
+ nanoid@3.3.8:
+ resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+
+ natural-compare@1.4.0:
+ resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
+
+ optionator@0.9.4:
+ resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
+ engines: {node: '>= 0.8.0'}
+
+ p-limit@3.1.0:
+ resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
+ engines: {node: '>=10'}
+
+ p-locate@5.0.0:
+ resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
+ engines: {node: '>=10'}
+
+ parent-module@1.0.1:
+ resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
+ engines: {node: '>=6'}
+
+ path-exists@4.0.0:
+ resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
+ engines: {node: '>=8'}
+
+ path-key@3.1.1:
+ resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
+ engines: {node: '>=8'}
+
+ picocolors@1.1.1:
+ resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
+
+ picomatch@2.3.1:
+ resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
+ engines: {node: '>=8.6'}
+
+ postcss@8.4.49:
+ resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==}
+ engines: {node: ^10 || ^12 || >=14}
+
+ prelude-ls@1.2.1:
+ resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
+ engines: {node: '>= 0.8.0'}
+
+ proxy-from-env@1.1.0:
+ resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
+
+ punycode@2.3.1:
+ resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
+ engines: {node: '>=6'}
+
+ queue-microtask@1.2.3:
+ resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+
+ react-dom@18.3.1:
+ resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==}
+ peerDependencies:
+ react: ^18.3.1
+
+ react-router-dom@7.0.2:
+ resolution: {integrity: sha512-VJOQ+CDWFDGaWdrG12Nl+d7yHtLaurNgAQZVgaIy7/Xd+DojgmYLosFfZdGz1wpxmjJIAkAMVTKWcvkx1oggAw==}
+ engines: {node: '>=20.0.0'}
+ peerDependencies:
+ react: '>=18'
+ react-dom: '>=18'
+
+ react-router@7.0.2:
+ resolution: {integrity: sha512-m5AcPfTRUcjwmhBzOJGEl6Y7+Crqyju0+TgTQxoS4SO+BkWbhOrcfZNq6wSWdl2BBbJbsAoBUb8ZacOFT+/JlA==}
+ engines: {node: '>=20.0.0'}
+ peerDependencies:
+ react: '>=18'
+ react-dom: '>=18'
+ peerDependenciesMeta:
+ react-dom:
+ optional: true
+
+ react@18.3.1:
+ resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
+ engines: {node: '>=0.10.0'}
+
+ resolve-from@4.0.0:
+ resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
+ engines: {node: '>=4'}
+
+ reusify@1.0.4:
+ resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
+ engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+
+ rollup@4.28.1:
+ resolution: {integrity: sha512-61fXYl/qNVinKmGSTHAZ6Yy8I3YIJC/r2m9feHo6SwVAVcLT5MPwOUFe7EuURA/4m0NR8lXG4BBXuo/IZEsjMg==}
+ engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+ hasBin: true
+
+ run-parallel@1.2.0:
+ resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+
+ scheduler@0.23.2:
+ resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==}
+
+ semver@7.6.3:
+ resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==}
+ engines: {node: '>=10'}
+ hasBin: true
+
+ set-cookie-parser@2.7.1:
+ resolution: {integrity: sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==}
+
+ shebang-command@2.0.0:
+ resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
+ engines: {node: '>=8'}
+
+ shebang-regex@3.0.0:
+ resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
+ engines: {node: '>=8'}
+
+ source-map-js@1.2.1:
+ resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
+ engines: {node: '>=0.10.0'}
+
+ strip-json-comments@3.1.1:
+ resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
+ engines: {node: '>=8'}
+
+ supports-color@7.2.0:
+ resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
+ engines: {node: '>=8'}
+
+ to-regex-range@5.0.1:
+ resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
+ engines: {node: '>=8.0'}
+
+ ts-api-utils@1.4.3:
+ resolution: {integrity: sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==}
+ engines: {node: '>=16'}
+ peerDependencies:
+ typescript: '>=4.2.0'
+
+ turbo-darwin-64@2.3.3:
+ resolution: {integrity: sha512-bxX82xe6du/3rPmm4aCC5RdEilIN99VUld4HkFQuw+mvFg6darNBuQxyWSHZTtc25XgYjQrjsV05888w1grpaA==}
+ cpu: [x64]
+ os: [darwin]
+
+ turbo-darwin-arm64@2.3.3:
+ resolution: {integrity: sha512-DYbQwa3NsAuWkCUYVzfOUBbSUBVQzH5HWUFy2Kgi3fGjIWVZOFk86ss+xsWu//rlEAfYwEmopigsPYSmW4X15A==}
+ cpu: [arm64]
+ os: [darwin]
+
+ turbo-linux-64@2.3.3:
+ resolution: {integrity: sha512-eHj9OIB0dFaP6BxB88jSuaCLsOQSYWBgmhy2ErCu6D2GG6xW3b6e2UWHl/1Ho9FsTg4uVgo4DB9wGsKa5erjUA==}
+ cpu: [x64]
+ os: [linux]
+
+ turbo-linux-arm64@2.3.3:
+ resolution: {integrity: sha512-NmDE/NjZoDj1UWBhMtOPmqFLEBKhzGS61KObfrDEbXvU3lekwHeoPvAMfcovzswzch+kN2DrtbNIlz+/rp8OCg==}
+ cpu: [arm64]
+ os: [linux]
+
+ turbo-stream@2.4.0:
+ resolution: {integrity: sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==}
+
+ turbo-windows-64@2.3.3:
+ resolution: {integrity: sha512-O2+BS4QqjK3dOERscXqv7N2GXNcqHr9hXumkMxDj/oGx9oCatIwnnwx34UmzodloSnJpgSqjl8iRWiY65SmYoQ==}
+ cpu: [x64]
+ os: [win32]
+
+ turbo-windows-arm64@2.3.3:
+ resolution: {integrity: sha512-dW4ZK1r6XLPNYLIKjC4o87HxYidtRRcBeo/hZ9Wng2XM/MqqYkAyzJXJGgRMsc0MMEN9z4+ZIfnSNBrA0b08ag==}
+ cpu: [arm64]
+ os: [win32]
+
+ turbo@2.3.3:
+ resolution: {integrity: sha512-DUHWQAcC8BTiUZDRzAYGvpSpGLiaOQPfYXlCieQbwUvmml/LRGIe3raKdrOPOoiX0DYlzxs2nH6BoWJoZrj8hA==}
+ hasBin: true
+
+ type-check@0.4.0:
+ resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
+ engines: {node: '>= 0.8.0'}
+
+ typescript-eslint@8.18.1:
+ resolution: {integrity: sha512-Mlaw6yxuaDEPQvb/2Qwu3/TfgeBHy9iTJ3mTwe7OvpPmF6KPQjVOfGyEJpPv6Ez2C34OODChhXrzYw/9phI0MQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <5.8.0'
+
+ typescript@5.6.3:
+ resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==}
+ engines: {node: '>=14.17'}
+ hasBin: true
+
+ undici-types@5.26.5:
+ resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
+
+ uri-js@4.4.1:
+ resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
+
+ vite@6.0.3:
+ resolution: {integrity: sha512-Cmuo5P0ENTN6HxLSo6IHsjCLn/81Vgrp81oaiFFMRa8gGDj5xEjIcEpf2ZymZtZR8oU0P2JX5WuUp/rlXcHkAw==}
+ engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
+ jiti: '>=1.21.0'
+ less: '*'
+ lightningcss: ^1.21.0
+ sass: '*'
+ sass-embedded: '*'
+ stylus: '*'
+ sugarss: '*'
+ terser: ^5.16.0
+ tsx: ^4.8.1
+ yaml: ^2.4.2
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ jiti:
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ sass-embedded:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ tsx:
+ optional: true
+ yaml:
+ optional: true
+
+ which@2.0.2:
+ resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
+ engines: {node: '>= 8'}
+ hasBin: true
+
+ word-wrap@1.2.5:
+ resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
+ engines: {node: '>=0.10.0'}
+
+ yocto-queue@0.1.0:
+ resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
+ engines: {node: '>=10'}
+
+snapshots:
+
+ '@biomejs/biome@1.7.3':
+ optionalDependencies:
+ '@biomejs/cli-darwin-arm64': 1.7.3
+ '@biomejs/cli-darwin-x64': 1.7.3
+ '@biomejs/cli-linux-arm64': 1.7.3
+ '@biomejs/cli-linux-arm64-musl': 1.7.3
+ '@biomejs/cli-linux-x64': 1.7.3
+ '@biomejs/cli-linux-x64-musl': 1.7.3
+ '@biomejs/cli-win32-arm64': 1.7.3
+ '@biomejs/cli-win32-x64': 1.7.3
+
+ '@biomejs/cli-darwin-arm64@1.7.3':
+ optional: true
+
+ '@biomejs/cli-darwin-x64@1.7.3':
+ optional: true
+
+ '@biomejs/cli-linux-arm64-musl@1.7.3':
+ optional: true
+
+ '@biomejs/cli-linux-arm64@1.7.3':
+ optional: true
+
+ '@biomejs/cli-linux-x64-musl@1.7.3':
+ optional: true
+
+ '@biomejs/cli-linux-x64@1.7.3':
+ optional: true
+
+ '@biomejs/cli-win32-arm64@1.7.3':
+ optional: true
+
+ '@biomejs/cli-win32-x64@1.7.3':
+ optional: true
+
+ '@esbuild/aix-ppc64@0.24.0':
+ optional: true
+
+ '@esbuild/android-arm64@0.24.0':
+ optional: true
+
+ '@esbuild/android-arm@0.24.0':
+ optional: true
+
+ '@esbuild/android-x64@0.24.0':
+ optional: true
+
+ '@esbuild/darwin-arm64@0.24.0':
+ optional: true
+
+ '@esbuild/darwin-x64@0.24.0':
+ optional: true
+
+ '@esbuild/freebsd-arm64@0.24.0':
+ optional: true
+
+ '@esbuild/freebsd-x64@0.24.0':
+ optional: true
+
+ '@esbuild/linux-arm64@0.24.0':
+ optional: true
+
+ '@esbuild/linux-arm@0.24.0':
+ optional: true
+
+ '@esbuild/linux-ia32@0.24.0':
+ optional: true
+
+ '@esbuild/linux-loong64@0.24.0':
+ optional: true
+
+ '@esbuild/linux-mips64el@0.24.0':
+ optional: true
+
+ '@esbuild/linux-ppc64@0.24.0':
+ optional: true
+
+ '@esbuild/linux-riscv64@0.24.0':
+ optional: true
+
+ '@esbuild/linux-s390x@0.24.0':
+ optional: true
+
+ '@esbuild/linux-x64@0.24.0':
+ optional: true
+
+ '@esbuild/netbsd-x64@0.24.0':
+ optional: true
+
+ '@esbuild/openbsd-arm64@0.24.0':
+ optional: true
+
+ '@esbuild/openbsd-x64@0.24.0':
+ optional: true
+
+ '@esbuild/sunos-x64@0.24.0':
+ optional: true
+
+ '@esbuild/win32-arm64@0.24.0':
+ optional: true
+
+ '@esbuild/win32-ia32@0.24.0':
+ optional: true
+
+ '@esbuild/win32-x64@0.24.0':
+ optional: true
+
+ '@eslint-community/eslint-utils@4.4.1(eslint@9.17.0)':
+ dependencies:
+ eslint: 9.17.0
+ eslint-visitor-keys: 3.4.3
+
+ '@eslint-community/regexpp@4.12.1': {}
+
+ '@eslint/config-array@0.19.1':
+ dependencies:
+ '@eslint/object-schema': 2.1.5
+ debug: 4.4.0
+ minimatch: 3.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@eslint/core@0.9.1':
+ dependencies:
+ '@types/json-schema': 7.0.15
+
+ '@eslint/eslintrc@3.2.0':
+ dependencies:
+ ajv: 6.12.6
+ debug: 4.4.0
+ espree: 10.3.0
+ globals: 14.0.0
+ ignore: 5.3.2
+ import-fresh: 3.3.0
+ js-yaml: 4.1.0
+ minimatch: 3.1.2
+ strip-json-comments: 3.1.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@eslint/js@9.17.0': {}
+
+ '@eslint/object-schema@2.1.5': {}
+
+ '@eslint/plugin-kit@0.2.4':
+ dependencies:
+ levn: 0.4.1
+
+ '@humanfs/core@0.19.1': {}
+
+ '@humanfs/node@0.16.6':
+ dependencies:
+ '@humanfs/core': 0.19.1
+ '@humanwhocodes/retry': 0.3.1
+
+ '@humanwhocodes/module-importer@1.0.1': {}
+
+ '@humanwhocodes/retry@0.3.1': {}
+
+ '@humanwhocodes/retry@0.4.1': {}
+
+ '@jridgewell/sourcemap-codec@1.5.0': {}
+
+ '@nodelib/fs.scandir@2.1.5':
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ run-parallel: 1.2.0
+
+ '@nodelib/fs.stat@2.0.5': {}
+
+ '@nodelib/fs.walk@1.2.8':
+ dependencies:
+ '@nodelib/fs.scandir': 2.1.5
+ fastq: 1.17.1
+
+ '@originjs/vite-plugin-federation@1.3.6':
+ dependencies:
+ estree-walker: 3.0.3
+ magic-string: 0.27.0
+
+ '@rollup/rollup-android-arm-eabi@4.28.1':
+ optional: true
+
+ '@rollup/rollup-android-arm64@4.28.1':
+ optional: true
+
+ '@rollup/rollup-darwin-arm64@4.28.1':
+ optional: true
+
+ '@rollup/rollup-darwin-x64@4.28.1':
+ optional: true
+
+ '@rollup/rollup-freebsd-arm64@4.28.1':
+ optional: true
+
+ '@rollup/rollup-freebsd-x64@4.28.1':
+ optional: true
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.28.1':
+ optional: true
+
+ '@rollup/rollup-linux-arm-musleabihf@4.28.1':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-gnu@4.28.1':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-musl@4.28.1':
+ optional: true
+
+ '@rollup/rollup-linux-loongarch64-gnu@4.28.1':
+ optional: true
+
+ '@rollup/rollup-linux-powerpc64le-gnu@4.28.1':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-gnu@4.28.1':
+ optional: true
+
+ '@rollup/rollup-linux-s390x-gnu@4.28.1':
+ optional: true
+
+ '@rollup/rollup-linux-x64-gnu@4.28.1':
+ optional: true
+
+ '@rollup/rollup-linux-x64-musl@4.28.1':
+ optional: true
+
+ '@rollup/rollup-win32-arm64-msvc@4.28.1':
+ optional: true
+
+ '@rollup/rollup-win32-ia32-msvc@4.28.1':
+ optional: true
+
+ '@rollup/rollup-win32-x64-msvc@4.28.1':
+ optional: true
+
+ '@swc/core-darwin-arm64@1.10.1':
+ optional: true
+
+ '@swc/core-darwin-x64@1.10.1':
+ optional: true
+
+ '@swc/core-linux-arm-gnueabihf@1.10.1':
+ optional: true
+
+ '@swc/core-linux-arm64-gnu@1.10.1':
+ optional: true
+
+ '@swc/core-linux-arm64-musl@1.10.1':
+ optional: true
+
+ '@swc/core-linux-x64-gnu@1.10.1':
+ optional: true
+
+ '@swc/core-linux-x64-musl@1.10.1':
+ optional: true
+
+ '@swc/core-win32-arm64-msvc@1.10.1':
+ optional: true
+
+ '@swc/core-win32-ia32-msvc@1.10.1':
+ optional: true
+
+ '@swc/core-win32-x64-msvc@1.10.1':
+ optional: true
+
+ '@swc/core@1.10.1':
+ dependencies:
+ '@swc/counter': 0.1.3
+ '@swc/types': 0.1.17
+ optionalDependencies:
+ '@swc/core-darwin-arm64': 1.10.1
+ '@swc/core-darwin-x64': 1.10.1
+ '@swc/core-linux-arm-gnueabihf': 1.10.1
+ '@swc/core-linux-arm64-gnu': 1.10.1
+ '@swc/core-linux-arm64-musl': 1.10.1
+ '@swc/core-linux-x64-gnu': 1.10.1
+ '@swc/core-linux-x64-musl': 1.10.1
+ '@swc/core-win32-arm64-msvc': 1.10.1
+ '@swc/core-win32-ia32-msvc': 1.10.1
+ '@swc/core-win32-x64-msvc': 1.10.1
+
+ '@swc/counter@0.1.3': {}
+
+ '@swc/types@0.1.17':
+ dependencies:
+ '@swc/counter': 0.1.3
+
+ '@types/cookie@0.6.0': {}
+
+ '@types/estree@1.0.6': {}
+
+ '@types/js-cookie@3.0.6': {}
+
+ '@types/json-schema@7.0.15': {}
+
+ '@types/node@20.13.0':
+ dependencies:
+ undici-types: 5.26.5
+
+ '@types/prop-types@15.7.14': {}
+
+ '@types/react-dom@18.3.5(@types/react@18.3.17)':
+ dependencies:
+ '@types/react': 18.3.17
+
+ '@types/react@18.3.17':
+ dependencies:
+ '@types/prop-types': 15.7.14
+ csstype: 3.1.3
+
+ '@typescript-eslint/eslint-plugin@8.18.1(@typescript-eslint/parser@8.18.1(eslint@9.17.0)(typescript@5.6.3))(eslint@9.17.0)(typescript@5.6.3)':
+ dependencies:
+ '@eslint-community/regexpp': 4.12.1
+ '@typescript-eslint/parser': 8.18.1(eslint@9.17.0)(typescript@5.6.3)
+ '@typescript-eslint/scope-manager': 8.18.1
+ '@typescript-eslint/type-utils': 8.18.1(eslint@9.17.0)(typescript@5.6.3)
+ '@typescript-eslint/utils': 8.18.1(eslint@9.17.0)(typescript@5.6.3)
+ '@typescript-eslint/visitor-keys': 8.18.1
+ eslint: 9.17.0
+ graphemer: 1.4.0
+ ignore: 5.3.2
+ natural-compare: 1.4.0
+ ts-api-utils: 1.4.3(typescript@5.6.3)
+ typescript: 5.6.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/parser@8.18.1(eslint@9.17.0)(typescript@5.6.3)':
+ dependencies:
+ '@typescript-eslint/scope-manager': 8.18.1
+ '@typescript-eslint/types': 8.18.1
+ '@typescript-eslint/typescript-estree': 8.18.1(typescript@5.6.3)
+ '@typescript-eslint/visitor-keys': 8.18.1
+ debug: 4.4.0
+ eslint: 9.17.0
+ typescript: 5.6.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/scope-manager@8.18.1':
+ dependencies:
+ '@typescript-eslint/types': 8.18.1
+ '@typescript-eslint/visitor-keys': 8.18.1
+
+ '@typescript-eslint/type-utils@8.18.1(eslint@9.17.0)(typescript@5.6.3)':
+ dependencies:
+ '@typescript-eslint/typescript-estree': 8.18.1(typescript@5.6.3)
+ '@typescript-eslint/utils': 8.18.1(eslint@9.17.0)(typescript@5.6.3)
+ debug: 4.4.0
+ eslint: 9.17.0
+ ts-api-utils: 1.4.3(typescript@5.6.3)
+ typescript: 5.6.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/types@8.18.1': {}
+
+ '@typescript-eslint/typescript-estree@8.18.1(typescript@5.6.3)':
+ dependencies:
+ '@typescript-eslint/types': 8.18.1
+ '@typescript-eslint/visitor-keys': 8.18.1
+ debug: 4.4.0
+ fast-glob: 3.3.2
+ is-glob: 4.0.3
+ minimatch: 9.0.5
+ semver: 7.6.3
+ ts-api-utils: 1.4.3(typescript@5.6.3)
+ typescript: 5.6.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/utils@8.18.1(eslint@9.17.0)(typescript@5.6.3)':
+ dependencies:
+ '@eslint-community/eslint-utils': 4.4.1(eslint@9.17.0)
+ '@typescript-eslint/scope-manager': 8.18.1
+ '@typescript-eslint/types': 8.18.1
+ '@typescript-eslint/typescript-estree': 8.18.1(typescript@5.6.3)
+ eslint: 9.17.0
+ typescript: 5.6.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/visitor-keys@8.18.1':
+ dependencies:
+ '@typescript-eslint/types': 8.18.1
+ eslint-visitor-keys: 4.2.0
+
+ '@vitejs/plugin-react-swc@3.7.2(vite@6.0.3(@types/node@20.13.0))':
+ dependencies:
+ '@swc/core': 1.10.1
+ vite: 6.0.3(@types/node@20.13.0)
+ transitivePeerDependencies:
+ - '@swc/helpers'
+
+ acorn-jsx@5.3.2(acorn@8.14.0):
+ dependencies:
+ acorn: 8.14.0
+
+ acorn@8.14.0: {}
+
+ ajv@6.12.6:
+ dependencies:
+ fast-deep-equal: 3.1.3
+ fast-json-stable-stringify: 2.1.0
+ json-schema-traverse: 0.4.1
+ uri-js: 4.4.1
+
+ ansi-styles@4.3.0:
+ dependencies:
+ color-convert: 2.0.1
+
+ argparse@2.0.1: {}
+
+ asynckit@0.4.0: {}
+
+ axios@1.7.9:
+ dependencies:
+ follow-redirects: 1.15.9
+ form-data: 4.0.1
+ proxy-from-env: 1.1.0
+ transitivePeerDependencies:
+ - debug
+
+ balanced-match@1.0.2: {}
+
+ brace-expansion@1.1.11:
+ dependencies:
+ balanced-match: 1.0.2
+ concat-map: 0.0.1
+
+ brace-expansion@2.0.1:
+ dependencies:
+ balanced-match: 1.0.2
+
+ braces@3.0.3:
+ dependencies:
+ fill-range: 7.1.1
+
+ callsites@3.1.0: {}
+
+ chalk@4.1.2:
+ dependencies:
+ ansi-styles: 4.3.0
+ supports-color: 7.2.0
+
+ color-convert@2.0.1:
+ dependencies:
+ color-name: 1.1.4
+
+ color-name@1.1.4: {}
+
+ combined-stream@1.0.8:
+ dependencies:
+ delayed-stream: 1.0.0
+
+ concat-map@0.0.1: {}
+
+ cookie@1.0.2: {}
+
+ cross-spawn@7.0.6:
+ dependencies:
+ path-key: 3.1.1
+ shebang-command: 2.0.0
+ which: 2.0.2
+
+ csstype@3.1.3: {}
+
+ debug@4.4.0:
+ dependencies:
+ ms: 2.1.3
+
+ deep-is@0.1.4: {}
+
+ delayed-stream@1.0.0: {}
+
+ esbuild@0.24.0:
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.24.0
+ '@esbuild/android-arm': 0.24.0
+ '@esbuild/android-arm64': 0.24.0
+ '@esbuild/android-x64': 0.24.0
+ '@esbuild/darwin-arm64': 0.24.0
+ '@esbuild/darwin-x64': 0.24.0
+ '@esbuild/freebsd-arm64': 0.24.0
+ '@esbuild/freebsd-x64': 0.24.0
+ '@esbuild/linux-arm': 0.24.0
+ '@esbuild/linux-arm64': 0.24.0
+ '@esbuild/linux-ia32': 0.24.0
+ '@esbuild/linux-loong64': 0.24.0
+ '@esbuild/linux-mips64el': 0.24.0
+ '@esbuild/linux-ppc64': 0.24.0
+ '@esbuild/linux-riscv64': 0.24.0
+ '@esbuild/linux-s390x': 0.24.0
+ '@esbuild/linux-x64': 0.24.0
+ '@esbuild/netbsd-x64': 0.24.0
+ '@esbuild/openbsd-arm64': 0.24.0
+ '@esbuild/openbsd-x64': 0.24.0
+ '@esbuild/sunos-x64': 0.24.0
+ '@esbuild/win32-arm64': 0.24.0
+ '@esbuild/win32-ia32': 0.24.0
+ '@esbuild/win32-x64': 0.24.0
+
+ escape-string-regexp@4.0.0: {}
+
+ eslint-plugin-react-hooks@5.1.0(eslint@9.17.0):
+ dependencies:
+ eslint: 9.17.0
+
+ eslint-plugin-react-refresh@0.4.16(eslint@9.17.0):
+ dependencies:
+ eslint: 9.17.0
+
+ eslint-scope@8.2.0:
+ dependencies:
+ esrecurse: 4.3.0
+ estraverse: 5.3.0
+
+ eslint-visitor-keys@3.4.3: {}
+
+ eslint-visitor-keys@4.2.0: {}
+
+ eslint@9.17.0:
+ dependencies:
+ '@eslint-community/eslint-utils': 4.4.1(eslint@9.17.0)
+ '@eslint-community/regexpp': 4.12.1
+ '@eslint/config-array': 0.19.1
+ '@eslint/core': 0.9.1
+ '@eslint/eslintrc': 3.2.0
+ '@eslint/js': 9.17.0
+ '@eslint/plugin-kit': 0.2.4
+ '@humanfs/node': 0.16.6
+ '@humanwhocodes/module-importer': 1.0.1
+ '@humanwhocodes/retry': 0.4.1
+ '@types/estree': 1.0.6
+ '@types/json-schema': 7.0.15
+ ajv: 6.12.6
+ chalk: 4.1.2
+ cross-spawn: 7.0.6
+ debug: 4.4.0
+ escape-string-regexp: 4.0.0
+ eslint-scope: 8.2.0
+ eslint-visitor-keys: 4.2.0
+ espree: 10.3.0
+ esquery: 1.6.0
+ esutils: 2.0.3
+ fast-deep-equal: 3.1.3
+ file-entry-cache: 8.0.0
+ find-up: 5.0.0
+ glob-parent: 6.0.2
+ ignore: 5.3.2
+ imurmurhash: 0.1.4
+ is-glob: 4.0.3
+ json-stable-stringify-without-jsonify: 1.0.1
+ lodash.merge: 4.6.2
+ minimatch: 3.1.2
+ natural-compare: 1.4.0
+ optionator: 0.9.4
+ transitivePeerDependencies:
+ - supports-color
+
+ espree@10.3.0:
+ dependencies:
+ acorn: 8.14.0
+ acorn-jsx: 5.3.2(acorn@8.14.0)
+ eslint-visitor-keys: 4.2.0
+
+ esquery@1.6.0:
+ dependencies:
+ estraverse: 5.3.0
+
+ esrecurse@4.3.0:
+ dependencies:
+ estraverse: 5.3.0
+
+ estraverse@5.3.0: {}
+
+ estree-walker@3.0.3:
+ dependencies:
+ '@types/estree': 1.0.6
+
+ esutils@2.0.3: {}
+
+ fast-deep-equal@3.1.3: {}
+
+ fast-glob@3.3.2:
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ '@nodelib/fs.walk': 1.2.8
+ glob-parent: 5.1.2
+ merge2: 1.4.1
+ micromatch: 4.0.8
+
+ fast-json-stable-stringify@2.1.0: {}
+
+ fast-levenshtein@2.0.6: {}
+
+ fastq@1.17.1:
+ dependencies:
+ reusify: 1.0.4
+
+ file-entry-cache@8.0.0:
+ dependencies:
+ flat-cache: 4.0.1
+
+ fill-range@7.1.1:
+ dependencies:
+ to-regex-range: 5.0.1
+
+ find-up@5.0.0:
+ dependencies:
+ locate-path: 6.0.0
+ path-exists: 4.0.0
+
+ flat-cache@4.0.1:
+ dependencies:
+ flatted: 3.3.2
+ keyv: 4.5.4
+
+ flatted@3.3.2: {}
+
+ follow-redirects@1.15.9: {}
+
+ form-data@4.0.1:
+ dependencies:
+ asynckit: 0.4.0
+ combined-stream: 1.0.8
+ mime-types: 2.1.35
+
+ fsevents@2.3.3:
+ optional: true
+
+ glob-parent@5.1.2:
+ dependencies:
+ is-glob: 4.0.3
+
+ glob-parent@6.0.2:
+ dependencies:
+ is-glob: 4.0.3
+
+ globals@14.0.0: {}
+
+ globals@15.13.0: {}
+
+ graphemer@1.4.0: {}
+
+ has-flag@4.0.0: {}
+
+ husky@9.1.7: {}
+
+ ignore@5.3.2: {}
+
+ import-fresh@3.3.0:
+ dependencies:
+ parent-module: 1.0.1
+ resolve-from: 4.0.0
+
+ imurmurhash@0.1.4: {}
+
+ is-extglob@2.1.1: {}
+
+ is-glob@4.0.3:
+ dependencies:
+ is-extglob: 2.1.1
+
+ is-number@7.0.0: {}
+
+ isexe@2.0.0: {}
+
+ js-cookie@3.0.5: {}
+
+ js-tokens@4.0.0: {}
+
+ js-yaml@4.1.0:
+ dependencies:
+ argparse: 2.0.1
+
+ json-buffer@3.0.1: {}
+
+ json-schema-traverse@0.4.1: {}
+
+ json-stable-stringify-without-jsonify@1.0.1: {}
+
+ keyv@4.5.4:
+ dependencies:
+ json-buffer: 3.0.1
+
+ levn@0.4.1:
+ dependencies:
+ prelude-ls: 1.2.1
+ type-check: 0.4.0
+
+ locate-path@6.0.0:
+ dependencies:
+ p-locate: 5.0.0
+
+ lodash.merge@4.6.2: {}
+
+ loose-envify@1.4.0:
+ dependencies:
+ js-tokens: 4.0.0
+
+ magic-string@0.27.0:
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.5.0
+
+ merge2@1.4.1: {}
+
+ micromatch@4.0.8:
+ dependencies:
+ braces: 3.0.3
+ picomatch: 2.3.1
+
+ mime-db@1.52.0: {}
+
+ mime-types@2.1.35:
+ dependencies:
+ mime-db: 1.52.0
+
+ minimatch@3.1.2:
+ dependencies:
+ brace-expansion: 1.1.11
+
+ minimatch@9.0.5:
+ dependencies:
+ brace-expansion: 2.0.1
+
+ ms@2.1.3: {}
+
+ nano-staged@0.8.0:
+ dependencies:
+ picocolors: 1.1.1
+
+ nanoid@3.3.8: {}
+
+ natural-compare@1.4.0: {}
+
+ optionator@0.9.4:
+ dependencies:
+ deep-is: 0.1.4
+ fast-levenshtein: 2.0.6
+ levn: 0.4.1
+ prelude-ls: 1.2.1
+ type-check: 0.4.0
+ word-wrap: 1.2.5
+
+ p-limit@3.1.0:
+ dependencies:
+ yocto-queue: 0.1.0
+
+ p-locate@5.0.0:
+ dependencies:
+ p-limit: 3.1.0
+
+ parent-module@1.0.1:
+ dependencies:
+ callsites: 3.1.0
+
+ path-exists@4.0.0: {}
+
+ path-key@3.1.1: {}
+
+ picocolors@1.1.1: {}
+
+ picomatch@2.3.1: {}
+
+ postcss@8.4.49:
+ dependencies:
+ nanoid: 3.3.8
+ picocolors: 1.1.1
+ source-map-js: 1.2.1
+
+ prelude-ls@1.2.1: {}
+
+ proxy-from-env@1.1.0: {}
+
+ punycode@2.3.1: {}
+
+ queue-microtask@1.2.3: {}
+
+ react-dom@18.3.1(react@18.3.1):
+ dependencies:
+ loose-envify: 1.4.0
+ react: 18.3.1
+ scheduler: 0.23.2
+
+ react-router-dom@7.0.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+ dependencies:
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ react-router: 7.0.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+
+ react-router@7.0.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+ dependencies:
+ '@types/cookie': 0.6.0
+ cookie: 1.0.2
+ react: 18.3.1
+ set-cookie-parser: 2.7.1
+ turbo-stream: 2.4.0
+ optionalDependencies:
+ react-dom: 18.3.1(react@18.3.1)
+
+ react@18.3.1:
+ dependencies:
+ loose-envify: 1.4.0
+
+ resolve-from@4.0.0: {}
+
+ reusify@1.0.4: {}
+
+ rollup@4.28.1:
+ dependencies:
+ '@types/estree': 1.0.6
+ optionalDependencies:
+ '@rollup/rollup-android-arm-eabi': 4.28.1
+ '@rollup/rollup-android-arm64': 4.28.1
+ '@rollup/rollup-darwin-arm64': 4.28.1
+ '@rollup/rollup-darwin-x64': 4.28.1
+ '@rollup/rollup-freebsd-arm64': 4.28.1
+ '@rollup/rollup-freebsd-x64': 4.28.1
+ '@rollup/rollup-linux-arm-gnueabihf': 4.28.1
+ '@rollup/rollup-linux-arm-musleabihf': 4.28.1
+ '@rollup/rollup-linux-arm64-gnu': 4.28.1
+ '@rollup/rollup-linux-arm64-musl': 4.28.1
+ '@rollup/rollup-linux-loongarch64-gnu': 4.28.1
+ '@rollup/rollup-linux-powerpc64le-gnu': 4.28.1
+ '@rollup/rollup-linux-riscv64-gnu': 4.28.1
+ '@rollup/rollup-linux-s390x-gnu': 4.28.1
+ '@rollup/rollup-linux-x64-gnu': 4.28.1
+ '@rollup/rollup-linux-x64-musl': 4.28.1
+ '@rollup/rollup-win32-arm64-msvc': 4.28.1
+ '@rollup/rollup-win32-ia32-msvc': 4.28.1
+ '@rollup/rollup-win32-x64-msvc': 4.28.1
+ fsevents: 2.3.3
+
+ run-parallel@1.2.0:
+ dependencies:
+ queue-microtask: 1.2.3
+
+ scheduler@0.23.2:
+ dependencies:
+ loose-envify: 1.4.0
+
+ semver@7.6.3: {}
+
+ set-cookie-parser@2.7.1: {}
+
+ shebang-command@2.0.0:
+ dependencies:
+ shebang-regex: 3.0.0
+
+ shebang-regex@3.0.0: {}
+
+ source-map-js@1.2.1: {}
+
+ strip-json-comments@3.1.1: {}
+
+ supports-color@7.2.0:
+ dependencies:
+ has-flag: 4.0.0
+
+ to-regex-range@5.0.1:
+ dependencies:
+ is-number: 7.0.0
+
+ ts-api-utils@1.4.3(typescript@5.6.3):
+ dependencies:
+ typescript: 5.6.3
+
+ turbo-darwin-64@2.3.3:
+ optional: true
+
+ turbo-darwin-arm64@2.3.3:
+ optional: true
+
+ turbo-linux-64@2.3.3:
+ optional: true
+
+ turbo-linux-arm64@2.3.3:
+ optional: true
+
+ turbo-stream@2.4.0: {}
+
+ turbo-windows-64@2.3.3:
+ optional: true
+
+ turbo-windows-arm64@2.3.3:
+ optional: true
+
+ turbo@2.3.3:
+ optionalDependencies:
+ turbo-darwin-64: 2.3.3
+ turbo-darwin-arm64: 2.3.3
+ turbo-linux-64: 2.3.3
+ turbo-linux-arm64: 2.3.3
+ turbo-windows-64: 2.3.3
+ turbo-windows-arm64: 2.3.3
+
+ type-check@0.4.0:
+ dependencies:
+ prelude-ls: 1.2.1
+
+ typescript-eslint@8.18.1(eslint@9.17.0)(typescript@5.6.3):
+ dependencies:
+ '@typescript-eslint/eslint-plugin': 8.18.1(@typescript-eslint/parser@8.18.1(eslint@9.17.0)(typescript@5.6.3))(eslint@9.17.0)(typescript@5.6.3)
+ '@typescript-eslint/parser': 8.18.1(eslint@9.17.0)(typescript@5.6.3)
+ '@typescript-eslint/utils': 8.18.1(eslint@9.17.0)(typescript@5.6.3)
+ eslint: 9.17.0
+ typescript: 5.6.3
+ transitivePeerDependencies:
+ - supports-color
+
+ typescript@5.6.3: {}
+
+ undici-types@5.26.5: {}
+
+ uri-js@4.4.1:
+ dependencies:
+ punycode: 2.3.1
+
+ vite@6.0.3(@types/node@20.13.0):
+ dependencies:
+ esbuild: 0.24.0
+ postcss: 8.4.49
+ rollup: 4.28.1
+ optionalDependencies:
+ '@types/node': 20.13.0
+ fsevents: 2.3.3
+
+ which@2.0.2:
+ dependencies:
+ isexe: 2.0.0
+
+ word-wrap@1.2.5: {}
+
+ yocto-queue@0.1.0: {}
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
new file mode 100644
index 0000000..ab333b1
--- /dev/null
+++ b/pnpm-workspace.yaml
@@ -0,0 +1,4 @@
+packages:
+ - "playground/web"
+ - "playground/apps/*"
+ - "playground/packages/*"
diff --git a/turbo.json b/turbo.json
new file mode 100644
index 0000000..4083c9b
--- /dev/null
+++ b/turbo.json
@@ -0,0 +1,26 @@
+{
+ "$schema": "https://turbo.build/schema.json",
+ "ui": "tui",
+ "globalDependencies": ["**/.env.*local"],
+ "tasks": {
+ "build": {
+ "dependsOn": ["^build"],
+ "outputs": [".next/**", "!.next/cache/**"]
+ },
+ "lint": {
+ "dependsOn": ["^lint"]
+ },
+ "format": {
+ "dependsOn": ["^format"]
+ },
+ "dev": {
+ "cache": false,
+ "persistent": true
+ },
+ "start": {
+ "dependsOn": ["build"],
+ "cache": false,
+ "persistent": true
+ }
+ }
+}