feat: 项目初始化

This commit is contained in:
JiaJun
2026-04-23 16:41:39 +08:00
parent be4669a9f1
commit bd92f10b83
42 changed files with 6047 additions and 2 deletions

4
.env.development Normal file
View File

@@ -0,0 +1,4 @@
VITE_APP_ENV=development
VITE_API_BASE_URL=http://localhost:3000
VITE_ENABLE_QUERY_DEVTOOLS=true
VITE_ENABLE_REQUEST_LOG=true

4
.env.example Normal file
View File

@@ -0,0 +1,4 @@
VITE_APP_ENV=development
VITE_API_BASE_URL=http://localhost:3000
VITE_ENABLE_QUERY_DEVTOOLS=true
VITE_ENABLE_REQUEST_LOG=true

4
.env.production Normal file
View File

@@ -0,0 +1,4 @@
VITE_APP_ENV=production
VITE_API_BASE_URL=https://api.example.com
VITE_ENABLE_QUERY_DEVTOOLS=false
VITE_ENABLE_REQUEST_LOG=false

27
.gitignore vendored Normal file
View File

@@ -0,0 +1,27 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
coverage
*.local
.env.local
.env.*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

1
.husky/commit-msg Executable file
View File

@@ -0,0 +1 @@
pnpm exec commitlint --edit "$1"

1
.husky/pre-commit Executable file
View File

@@ -0,0 +1 @@
pnpm exec lint-staged

421
README.md
View File

@@ -1,3 +1,420 @@
# 36-character-flower
# React SPA Template
36字花
这是一个用于后台系统或通用 SPA 项目的前端基础脚手架。它已经接好了以下底座能力:
- `Vite + React 19 + TypeScript`
- `TanStack Router` 文件路由
- `TanStack Query + ky` 请求与缓存
- `Zustand` 会话状态基座
- `Tailwind CSS` 原子化样式
- `i18next` 多语言
- `Head / Metadata` 动态标题与元信息
- `Biome + Husky + commitlint` 代码规范与提交规范
这个模板现在已经被“净化”为一个空白 scaffold。
你拿到它之后,应该在这个基础上替换成自己的页面、接口、登录逻辑和测试,而不是继续沿用示例业务。
## 1. 快速开始
```bash
pnpm install
pnpm dev
```
常用命令:
```bash
pnpm dev
pnpm build
pnpm lint
pnpm lint:fix
pnpm generate-routes
pnpm commit
```
## 2. 目录结构
核心目录说明:
- `src/routes`
TanStack Router 文件路由目录。你新增页面,优先在这里建文件。
- `src/lib/api`
通用请求层。`api-client.ts` 是所有接口调用的基础入口。
- `src/lib/auth`
会话初始化、401 清理、refresh token、受保护路由 helper。
- `src/lib/head`
页面标题、description、Open Graph、Twitter metadata。
- `src/lib/query`
TanStack Query 全局默认配置。
- `src/store`
全局状态。目前主要是认证状态。
- `src/styles.css`
全局 Tailwind 入口。当前项目只保留这一份样式文件。
- `src/locales`
多语言文案。
## 3. 新项目落地后先改哪里
如果你要基于这个模板开一个新项目,建议按这个顺序改:
### 第一步:改首页
先改这个文件:
- `src/routes/$lang/index.tsx`
这是当前默认首页。通常你会:
- 改成你的项目欢迎页
- 或直接改成 dashboard / 工作台入口
- 或拆成自己的页面布局
同时对应修改多语言文案:
- `src/locales/zh-CN/common.ts`
- `src/locales/en-US/common.ts`
### 第二步:改接口基础地址
先看这些文件:
- `.env.development`
- `.env.production`
- `src/vite-env.d.ts`
至少确认这些变量:
- `VITE_APP_ENV`
- `VITE_API_BASE_URL`
- `VITE_ENABLE_QUERY_DEVTOOLS`
- `VITE_ENABLE_REQUEST_LOG`
### 第三步:改全局样式入口
当前模板已经切到 Tailwind CSS并移除了旧的 `App.css` / `index.css`
你主要会改:
- `src/styles.css`
这里通常只放:
- `@import "tailwindcss";`
- 少量全局 base 样式
- 你的主题变量
### 第四步:接你的业务模块
建议按“功能模块”建目录,而不是把所有请求、类型和 hooks 混在一起。
例如:
```text
src/features/user/api/user-api.ts
src/features/user/hooks/use-current-user.ts
src/features/user/types/user.ts
src/routes/$lang/users/index.tsx
```
### 第五步:接你的登录体系
优先改这些文件:
- `src/store/auth-store.ts`
- `src/lib/auth/auth-session.ts`
- `src/lib/api/api-client.ts`
## 4. Head / Metadata 怎么用
模板已经提供了一个通用 hook
- `src/lib/head/document-metadata.ts`
在页面组件里直接调用:
```tsx
import { useDocumentMetadata } from '@/lib/head/document-metadata'
function UserPage() {
useDocumentMetadata({
title: '用户管理',
description: '用户管理页面',
})
return <div>User Page</div>
}
```
它会自动更新:
- `document.title`
- `meta[name="description"]`
- `meta[name="robots"]`
- `og:title`
- `og:description`
- `twitter:title`
- `twitter:description`
适用场景:
- 列表页标题
- 详情页标题
- 登录页 / 404 页
- 分享卡片基础描述
## 5. 登录怎么接
这个模板的认证层不是“现成登录系统”,而是“认证骨架”。
它已经有:
- `accessToken`
- `refreshToken`
- `currentUser`
- `status`
- `401` 后清会话
- refresh token 的可插拔入口
核心文件:
- `src/store/auth-store.ts`
- `src/lib/auth/auth-session.ts`
- `src/lib/api/api-client.ts`
### 5.1 登录成功后怎么写入会话
假设你的登录接口返回:
```ts
{
accessToken: string
refreshToken: string
user: {
id: string
name: string
}
}
```
那么登录成功后可以这样写:
```ts
import { useAuthStore } from '@/store/auth-store'
useAuthStore.getState().startSession({
accessToken: response.accessToken,
refreshToken: response.refreshToken,
currentUser: response.user,
})
```
### 5.2 刷新 token 怎么接
模板里预留了 refresh 的注册入口:
```ts
import { registerRefreshSessionHandler } from '@/lib/auth/auth-session'
registerRefreshSessionHandler(async (refreshToken) => {
const response = await fetch('/auth/refresh', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ refreshToken }),
}).then((result) => result.json())
return {
accessToken: response.accessToken,
refreshToken: response.refreshToken,
currentUser: response.user ?? null,
}
})
```
当请求返回 `401` 时,请求层会:
1. 尝试执行这个 refresh handler
2. 如果 refresh 成功,则自动重试原请求一次
3. 如果 refresh 失败,则清空本地会话
### 5.3 当前用户初始化怎么接
如果你的项目在刷新页面后,需要根据已有 token 主动请求一次“当前用户信息”,可以注册:
```ts
import { registerCurrentUserInitializer } from '@/lib/auth/auth-session'
registerCurrentUserInitializer(async () => {
const response = await fetch('/auth/me').then((result) => result.json())
return response.user
})
```
这样在应用启动时,模板会在已有 token 且尚未拿到 `currentUser` 的情况下,自动初始化一次用户信息。
## 6. 怎么加受保护路由
模板已经提供了路由保护 helper
- `src/lib/auth/require-auth.ts`
用法是,在路由的 `beforeLoad` 里调用它。
示例:
```tsx
import { createFileRoute } from '@tanstack/react-router'
import { requireAuthenticatedSession } from '@/lib/auth/require-auth'
export const Route = createFileRoute('/$lang/dashboard')({
beforeLoad: async () => {
await requireAuthenticatedSession()
},
component: DashboardPage,
})
function DashboardPage() {
return <div>Dashboard</div>
}
```
它的行为是:
- 如果当前已经登录,正常进入页面
- 如果当前未登录,重定向到 `/$lang`
如果你想把未登录用户导向专门的登录页,可以直接修改:
- `src/lib/auth/require-auth.ts`
把重定向目标从 `/$lang` 改成你的登录页路由,例如 `/$lang/login`
## 7. 怎么写第一个接口模块
推荐模式是:
1.`src/features/.../types` 定义类型
2.`src/features/.../api` 写请求函数
3.`src/features/.../hooks` 写 query / mutation hook
4.`src/routes/...` 页面里消费
示例:
```ts
// src/features/user/api/user-api.ts
import { api } from '@/lib/api/api-client'
export interface CurrentUser {
id: string
name: string
}
export function getCurrentUser() {
return api.get<CurrentUser>('users/me').then((response) => response.data)
}
```
```ts
// src/features/user/hooks/use-current-user.ts
import { useQuery } from '@tanstack/react-query'
import { getCurrentUser } from '@/features/user/api/user-api'
import type { ApiError } from '@/lib/api/api-error'
export function useCurrentUserQuery() {
return useQuery<Awaited<ReturnType<typeof getCurrentUser>>, ApiError>({
queryKey: ['current-user'],
queryFn: getCurrentUser,
})
}
```
## 8. 路由相关说明
这个模板使用 TanStack Router 文件路由。
路由目录:
- `src/routes`
生成文件:
- `src/routeTree.gen.ts`
你通常不需要手改 `src/routeTree.gen.ts`
新增、删除、修改路由文件后,执行:
```bash
pnpm generate-routes
```
`pnpm dev``pnpm build` 也都会自动先生成一次路由树。
## 9. 代码规范和提交流程
## 9.1 Tailwind 说明
当前模板使用的是官方 Vite 接法:
- `tailwindcss`
- `@tailwindcss/vite`
核心文件:
- `vite.config.ts`
- `src/styles.css`
新增页面时,优先直接写 Tailwind utility class而不是再恢复成多个分散的 CSS 文件。
格式化与 lint
```bash
pnpm lint
pnpm lint:fix
pnpm format
```
提交规范:
```bash
pnpm commit
```
仓库已经包含:
- `Biome`
- `Husky`
- `lint-staged`
- `commitlint`
- `Commitizen`
## 10. 你后续最可能改动的文件
如果你刚接手这个模板,优先关注这几个文件:
- `src/routes/$lang/index.tsx`
- `src/routes/$lang/route.tsx`
- `src/lib/api/api-client.ts`
- `src/lib/auth/auth-session.ts`
- `src/lib/auth/require-auth.ts`
- `src/store/auth-store.ts`
- `src/lib/head/document-metadata.ts`
- `src/locales/zh-CN/common.ts`
- `src/locales/en-US/common.ts`
## 11. 当前状态
当前模板已经验证通过:
- `pnpm lint`
- `pnpm build`
如果你继续往前整理,下一步通常就是:
1. 接入真实登录接口
2. 增加 `login``dashboard``403` 等实际页面
3. 按业务模块拆分 `features`
4. 按项目实际需要补充测试方案

65
biome.json Normal file
View File

@@ -0,0 +1,65 @@
{
"$schema": "https://biomejs.dev/schemas/2.4.12/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"ignoreUnknown": true,
"includes": ["**", "!coverage", "!src/routeTree.gen.ts"]
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2
},
"assist": {
"enabled": true,
"actions": {
"source": {
"organizeImports": "on"
}
}
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"complexity": {
"noUselessTypeConstraint": "error"
},
"correctness": {
"useExhaustiveDependencies": "warn",
"useHookAtTopLevel": "error"
},
"style": {
"noNamespace": "error",
"useArrayLiterals": "error",
"useAsConstAssertion": "error",
"useComponentExportOnlyModules": {
"level": "error",
"options": {
"allowConstantExport": true
}
},
"useConst": "error"
},
"suspicious": {
"noExplicitAny": "error"
}
}
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"jsxQuoteStyle": "double",
"semicolons": "asNeeded"
}
},
"css": {
"parser": {
"tailwindDirectives": true
}
}
}

3
commitlint.config.mjs Normal file
View File

@@ -0,0 +1,3 @@
export default {
extends: ['@commitlint/config-conventional'],
}

View File

@@ -0,0 +1,439 @@
# 《36字花》前端开发基线需求文档
## 1. 文档目的
本文件基于以下两份前期文档整理:
- `docs/《_36字花_ 前端开发对接与交互逻辑说明书》.docx`
- `docs/《36字花》用户前端 (User Portal) UI_UX .docx`
目标是移除营销型表述和非关键修辞,只保留后续 UI 设计、前端开发、联调和验收所需的核心设计要求、交互逻辑和技术栈建议。
## 2. 核心结论
### 2.1 产品形态
- 产品为实时开奖类游戏前端,主场景是移动端 H5同时要求兼容桌面端响应式布局。
- 页面核心是围绕单局倒计时循环运行的 36 宫格下注界面。
- 前端必须以服务器状态为准,不能依赖客户端本地时间做开奖判断。
### 2.2 设计方向
- 视觉风格保留为深色背景、高对比强调色的娱乐场风格。
- 颜色建议以深海蓝/黑为底,青色和金色作为强调色。
- 视觉参考中的“神鼎、宝箱、卷轴、巨龙、赛博朋克”等描述,只作为美术方向参考,不作为开发阻塞项。
- 所有文案容器必须支持多语言伸缩,禁止固定宽度写死。
### 2.3 交付优先级
后续设计与开发应按以下优先级执行:
1. 玩法状态正确
2. 倒计时与服务端同步正确
3. 下单、封盘、开奖、派彩状态切换正确
4. 移动端可用性与性能达标
5. 动效和视觉强化
## 3. 推荐技术栈
## 3.1 前端框架
- `React + TypeScript + Vite`
- 原因:移动 H5 交互复杂、状态密集、联调频繁Vite 启动快React 生态成熟TypeScript 适合管理复杂状态和接口约束。
## 3.2 路由与页面组织
- `React Router`
- 页面结构建议按大厅主界面、公告弹窗、规则面板、用户侧滑面板拆分。
## 3.3 状态管理
- `Zustand` 作为全局业务状态容器
- `XState` 或等价状态机方案用于维护单局生命周期状态
- 原因:本项目存在明确的 4 段式回合状态机、局内局外状态切换、自动托管覆盖态、网络重连恢复,单纯依赖局部状态容易错乱。
建议状态拆分:
- `roundStore`:期号、阶段、倒计时、开奖数据
- `betStore`:选中格子、锁定格子、筹码、总注额、按钮状态
- `userStore`:余额、连赢状态、下注上限、公告状态
- `uiStore`弹窗、抽屉、Toast、动画开关、自动托管蒙层
## 3.4 数据请求与实时通信
- `TanStack Query`:管理普通 HTTP 请求、缓存与重拉
- `WebSocket`:接收当前局状态、开奖、余额变动、派彩、自动托管进度
- 如果后端使用 Socket.IO则前端改用 `socket.io-client`
## 3.5 样式与动画
- 页面布局:`Tailwind CSS`
- 复杂状态样式:`CSS Modules` 或同级方案
- 盘面高频动画:优先 `CSS Animation / Transition / SVG`
- 全屏粒子特效:`PixiJS``tsParticles`
约束:
- 禁止用 JS 逐帧操作 DOM 做 36 宫格边框动画
- 动效必须优先使用合成层友好的属性,如 `transform``opacity``filter`
## 3.6 国际化与时间处理
- `react-i18next`
- `dayjs`
说明:
- `dayjs` 只用于显示格式化,不用于决定回合状态。
- 回合倒计时必须基于服务端时间戳推导。
## 3.7 测试与质量保障
- 单元测试:按项目需要自行接入
- 组件测试:按项目需要自行接入
- 端到端测试:`Playwright`
- 线上监控:建议接入 `Sentry`
## 4. 页面与模块范围
## 4.1 主游戏界面
必须包含以下区域:
- 顶部导航栏
- 开奖展示区
- 中控信息区
- 36 宫格下注区
- 筹码与操作栏
- 右侧历史区
- 底部单双走势区
## 4.2 次级界面
必须包含以下弹层或侧栏:
- 强制公告弹窗
- 自动托管运行浮层
- 玩法与规则面板
- 用户 Dashboard 侧滑面板
## 5. 单局生命周期状态机
后台可配置单局时长,前端默认按 30 秒一局建模,并支持服务端参数覆盖。
### 5.1 游戏阶段枚举
- `BETTING`:下注期
- `LOCKED`:封盘锁定
- `DRAWING`:算票与开奖
- `PAYOUT`:派彩与收尾
### 5.2 各阶段规则
`BETTING`
- 允许选格子、换筹码、清除未确认、重复上一注、确认下注、开启自动托管。
- 显示倒计时。
- 跑马灯处于常规速度。
`LOCKED`
- 到达封盘时间点后,前端必须立即锁盘,不等待后端响应。
- 所有点击事件、按钮、输入行为全部禁用。
- 所有 `PRE_SELECTED` 未确认格子必须清空。
- 显示“停止下注”提示。
`DRAWING`
- 等待 WebSocket 推送开奖结果。
- 收到开奖后,盘面跑马灯加速。
- 最终定格中奖格子,进入中奖态。
`PAYOUT`
- 接收余额和连赢状态更新。
- 播放中奖特效。
- 更新历史和走势。
- 为下一局做状态重置。
## 6. 36 宫格下注区需求
## 6.1 网格结构
- 固定为 `6 x 6`
- 每个格子包含:编号、动物名、动物图
- 格子需要支持轻量分组提示,用于区分业务分类,但不影响下注逻辑
## 6.2 单格状态枚举
建议统一实现 `CellStatus`
- `IDLE`:默认闲置
- `MARQUEE`:跑马灯焦点
- `HOVER`PC 悬浮
- `PRE_SELECTED`:已选未确认
- `LOCKED`:已确认下注
- `DISABLED`:不可操作
- `ERROR`:错误反馈
- `WINNING`:中奖高亮
- `LOSER`:未中奖弱化
- `AUTO_ACTIVE`:自动托管执行态
## 6.3 单格交互规则
- 玩家单局最多选择 5 个格子。
- `PRE_SELECTED + LOCKED` 的总数不得超过 5。
- 达到 5 个后,其余可选格子全部置为 `DISABLED`
- 点击第 6 个格子时,不得选中,必须触发错误反馈。
- 余额不足或超限点击时,必须触发错误反馈。
- 已确认格子在本局内不可取消。
- 若本局尚未封盘且未满 5 个,允许继续追加下注并再次确认。
## 7. 筹码与下注逻辑
## 7.1 筹码区
标准筹码档位:
- `1`
- `5`
- `10`
- `25`
- `50`
- `100`
## 7.2 统一下注金额同步
- 全局维护 `currentChipValue`
- 已处于 `PRE_SELECTED` 的所有格子,其显示筹码必须跟随 `currentChipValue` 实时同步
- 筹码切换后,总下注金额必须同步刷新
## 7.3 连赢上限与余额限制
需要实时校验:
- `selectedCount * currentChipValue <= streakMaxBetLimit`
- `totalBetAmount <= balance`
当不满足时:
- 对应不可选的大额筹码必须禁用
- 确认下注按钮进入错误态或禁用态
- 格子点击需给出明确错误反馈
## 8. 确认下注主按钮状态机
按钮需要独立维护以下 4 个状态:
- `DISABLED`:未选任何格子
- `READY`:已选格子且余额足够,可点击提交
- `ERROR`:总下注金额大于余额,文案显示“余额不足”
- `SUCCESS`:下注成功后维持成功态直到本局结束
约束:
- 禁止自动提交
- 必须由用户手动点击确认
- 成功后已确认格子不可撤销
## 9. 自动托管需求
## 9.1 功能行为
- 调用自动托管接口提交:下注格子、金额、局数
- 前端进入 `AUTO_MODE`
- 主键盘和筹码区整体进入不可编辑状态
- 自动托管中的目标格子显示 `AUTO_ACTIVE`
- 前端展示当前进度,例如 `12 / 50`
- 必须提供显式“停止托管”操作
## 9.2 视觉与交互约束
- 使用全局玻璃遮罩阻断手动操作
- 自动托管目标格子需要穿透遮罩高亮显示
- 自动托管态必须与手动锁定态有视觉区分
## 10. 中控信息区需求
必须展示以下信息:
- 当前余额
- 当前赔率
- 当前连赢次数
- 连赢限额提示
- 当前倒计时
- 当前期号
- 当前阶段状态,如 `OPEN` / `CLOSED`
倒计时要求:
- 最后 5 秒需要强化提示
- 倒计时只展示服务器推导结果
## 11. 历史与走势需求
## 11.1 右侧历史区
- 显示最近开奖记录
- 每条至少包含时间、号码、动物名
- 最新一条高亮
- 需要支持滚动
## 11.2 底部单双走势
- 保留最近 30 局
- 奇数显示红色圆点
- 偶数显示蓝色圆点
- 新增一条数据时,最后一个点需要入场动画
## 12. 弹窗与侧栏需求
## 12.1 强制公告弹窗
功能要求:
- 首屏进入时请求公告接口
- 若存在未读公告,必须强制弹出
- 不允许点击遮罩关闭
- 不允许提供右上角关闭按钮
- 勾选“已阅读并同意”前,进入游戏按钮必须禁用
- 关闭后要记录已读状态
- 无新公告时,不重复弹出
布局要求:
- 支持图文内容
- 内容超长时支持滚动
- 移动端建议复选框和主按钮上下排列,避免多语言挤压
## 12.2 规则面板
- 提供玩法规则、赔率说明、连胜机制、大奖说明
- 允许分页或滚动
- 结构化展示,不得纯长文堆叠
## 12.3 用户 Dashboard 侧滑面板
至少包含:
- 资产信息
- 充值入口
- 提现入口与手续费说明
- 最近 1 个月投注历史
- 站内信列表
- 公告信箱入口
## 13. 异常与容错要求
## 13.1 本地锁盘优先
- 到达封盘时间点时,前端必须立刻锁盘
- 即使网络延迟,也不能继续允许下注交互
## 13.2 压秒点击失败处理
场景:
- 用户在接近封盘时点击确认
- 请求发出,但服务器实际已封盘
前端处理:
- 先进入锁盘和加载态
- 若稍后收到失败响应,必须撤销未成功下注的本地状态
- 明确提示“网络延迟,下注失败,未扣款”
- 严禁误显示为下注成功
## 13.3 断线重连恢复
触发条件:
- 页面重新可见
- WebSocket 断开后重连
前端处理:
- 立即调用全量状态接口重新同步
- 重置倒计时、期号、余额、连赢、走势、当前盘面状态
- 禁止依赖本地累计时间继续运行
## 13.4 余额不足场景
- 确认按钮进入错误态
- 充值入口需要有明显引导
- 相关格子或筹码点击时给出即时反馈
## 14. 接口与事件依赖
以下为前端开发所需的最小接口能力,命名可与后端协商,但能力不可缺失。
## 14.1 HTTP 接口
- `GET /api/user/announcement`
- `GET /api/game/current_status`
- `POST /api/bet/place`
- `POST /api/auto_spin`
- `POST /api/announcement/read`
## 14.2 WebSocket 事件
- `round_status`:当前阶段、期号、服务器时间、剩余时间
- `draw_result`:开奖结果、中奖格子
- `balance_changed`:余额变化
- `streak_changed`:连赢状态与限额变化
- `trend_updated`:最新走势数据
- `auto_spin_progress`:自动托管局数进度
## 15. 性能与实现约束
- 移动端目标帧率:`60 FPS`
- 36 宫格状态切换不得出现明显掉帧
- 高亮、缩放、呼吸、闪烁等动画优先使用 GPU 友好属性
- 避免大面积重排和重绘
- 长列表区域应考虑虚拟化或分段渲染
- 全局状态更新必须避免引起整盘 36 格不必要重渲染
## 16. 多语言与响应式要求
- 所有按钮、标签、提示文案必须支持长度扩展
- 不允许固定像素宽度导致文案截断
- 文本区域需预留至少 40% 的横向伸缩空间
- 设计需优先保证移动端单手操作
- PC 端可补充 Hover 态,移动端不依赖 Hover 完成交互
## 17. 开发验收基线
满足以下条件才可进入测试或交付:
- 单局状态机完整跑通
- 封盘时前端能本地立即锁盘
- 服务端时间同步准确
- 下注数量限制与统一筹码机制无误
- 余额与连赢上限限制生效
- 自动托管可启动、运行、停止
- 公告弹窗强阻断逻辑正确
- 断线重连后状态可恢复
- 走势与历史区数据更新正确
- 移动端核心流程可稳定使用
## 18. 建议的开发顺序
1. 搭建项目骨架、路由、状态层、接口层
2. 先实现 30 秒回合状态机和服务端时间同步
3. 完成 36 宫格、筹码区、确认按钮的核心下注流程
4. 接入开奖、派彩、历史、走势
5. 实现公告弹窗、规则面板、用户侧栏
6. 实现自动托管
7. 最后补齐粒子特效、强化动画和视觉细节
## 19. 明确降级为“视觉参考”的内容
以下内容不应阻塞前端逻辑开发,可在视觉设计阶段再细化:
- 神坛主体到底是神鼎、宝箱还是法槌
- 是否采用卷轴、金属边框或全息科技框
- Jackpot 动画具体表现形式
- 动物头像是否 3D、半写实或插画风
- 特效音、粒子素材、品牌化图标样式
以上内容只影响视觉表现,不影响本文件定义的交互和功能边界。

31
index.html Normal file
View File

@@ -0,0 +1,31 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="description"
content="A frontend scaffold with Vite, React, TanStack Router, TanStack Query, Zustand, and Biome."
/>
<meta name="robots" content="index,follow" />
<meta property="og:type" content="website" />
<meta property="og:site_name" content="React SPA Template" />
<meta property="og:title" content="React SPA Template" />
<meta
property="og:description"
content="A frontend scaffold with Vite, React, TanStack Router, TanStack Query, Zustand, and Biome."
/>
<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="React SPA Template" />
<meta
name="twitter:description"
content="A frontend scaffold with Vite, React, TanStack Router, TanStack Query, Zustand, and Biome."
/>
<title>React SPA Template</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

61
package.json Normal file
View File

@@ -0,0 +1,61 @@
{
"name": "react-spa-template",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"commit": "cz",
"dev": "pnpm generate-routes && vite",
"build": "pnpm generate-routes && tsc -b && vite build",
"generate-routes": "tsr generate",
"lint": "biome check .",
"lint:fix": "biome check --write .",
"format": "biome format --write .",
"prepare": "husky",
"preview": "vite preview"
},
"lint-staged": {
"*.{js,jsx,ts,tsx,json,jsonc,css,md,html}": [
"biome check --write"
]
},
"config": {
"commitizen": {
"path": "cz-conventional-changelog"
}
},
"dependencies": {
"@tanstack/react-query": "^5.99.0",
"@tanstack/react-query-devtools": "^5.99.0",
"@tanstack/react-router": "^1.168.22",
"i18next": "^26.0.5",
"ky": "^2.0.1",
"react": "^19.2.4",
"react-dom": "^19.2.4",
"react-i18next": "^17.0.3",
"zustand": "^5.0.12"
},
"devDependencies": {
"@babel/core": "^7.29.0",
"@biomejs/biome": "2.4.12",
"@commitlint/cli": "20.5.0",
"@commitlint/config-conventional": "20.5.0",
"@rolldown/plugin-babel": "^0.2.2",
"@tailwindcss/vite": "^4.2.2",
"@tanstack/router-cli": "^1.166.33",
"@tanstack/router-plugin": "^1.167.22",
"@types/babel__core": "^7.20.5",
"@types/node": "^24.12.2",
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^6.0.1",
"babel-plugin-react-compiler": "^1.0.0",
"commitizen": "4.3.1",
"cz-conventional-changelog": "3.3.0",
"husky": "9.1.7",
"lint-staged": "16.4.0",
"tailwindcss": "^4.2.2",
"typescript": "~6.0.2",
"vite": "^8.0.4"
}
}

3687
pnpm-lock.yaml generated Normal file
View File

@@ -0,0 +1,3687 @@
lockfileVersion: '9.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
importers:
.:
dependencies:
'@tanstack/react-query':
specifier: ^5.99.0
version: 5.99.0(react@19.2.5)
'@tanstack/react-query-devtools':
specifier: ^5.99.0
version: 5.99.0(@tanstack/react-query@5.99.0(react@19.2.5))(react@19.2.5)
'@tanstack/react-router':
specifier: ^1.168.22
version: 1.168.22(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
i18next:
specifier: ^26.0.5
version: 26.0.5(typescript@6.0.2)
ky:
specifier: ^2.0.1
version: 2.0.1
react:
specifier: ^19.2.4
version: 19.2.5
react-dom:
specifier: ^19.2.4
version: 19.2.5(react@19.2.5)
react-i18next:
specifier: ^17.0.3
version: 17.0.3(i18next@26.0.5(typescript@6.0.2))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(typescript@6.0.2)
zustand:
specifier: ^5.0.12
version: 5.0.12(@types/react@19.2.14)(react@19.2.5)(use-sync-external-store@1.6.0(react@19.2.5))
devDependencies:
'@babel/core':
specifier: ^7.29.0
version: 7.29.0
'@biomejs/biome':
specifier: 2.4.12
version: 2.4.12
'@commitlint/cli':
specifier: 20.5.0
version: 20.5.0(@types/node@24.12.2)(conventional-commits-parser@6.4.0)(typescript@6.0.2)
'@commitlint/config-conventional':
specifier: 20.5.0
version: 20.5.0
'@rolldown/plugin-babel':
specifier: ^0.2.2
version: 0.2.3(@babel/core@7.29.0)(@babel/runtime@7.29.2)(rolldown@1.0.0-rc.15)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))
'@tailwindcss/vite':
specifier: ^4.2.2
version: 4.2.2(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))
'@tanstack/router-cli':
specifier: ^1.166.33
version: 1.166.33
'@tanstack/router-plugin':
specifier: ^1.167.22
version: 1.167.22(@tanstack/react-router@1.168.22(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))
'@types/babel__core':
specifier: ^7.20.5
version: 7.20.5
'@types/node':
specifier: ^24.12.2
version: 24.12.2
'@types/react':
specifier: ^19.2.14
version: 19.2.14
'@types/react-dom':
specifier: ^19.2.3
version: 19.2.3(@types/react@19.2.14)
'@vitejs/plugin-react':
specifier: ^6.0.1
version: 6.0.1(@rolldown/plugin-babel@0.2.3(@babel/core@7.29.0)(@babel/runtime@7.29.2)(rolldown@1.0.0-rc.15)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)))(babel-plugin-react-compiler@1.0.0)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))
babel-plugin-react-compiler:
specifier: ^1.0.0
version: 1.0.0
commitizen:
specifier: 4.3.1
version: 4.3.1(@types/node@24.12.2)(typescript@6.0.2)
cz-conventional-changelog:
specifier: 3.3.0
version: 3.3.0(@types/node@24.12.2)(typescript@6.0.2)
husky:
specifier: 9.1.7
version: 9.1.7
lint-staged:
specifier: 16.4.0
version: 16.4.0
tailwindcss:
specifier: ^4.2.2
version: 4.2.2
typescript:
specifier: ~6.0.2
version: 6.0.2
vite:
specifier: ^8.0.4
version: 8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)
packages:
'@babel/code-frame@7.29.0':
resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==}
engines: {node: '>=6.9.0'}
'@babel/compat-data@7.29.0':
resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==}
engines: {node: '>=6.9.0'}
'@babel/core@7.29.0':
resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==}
engines: {node: '>=6.9.0'}
'@babel/generator@7.29.1':
resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==}
engines: {node: '>=6.9.0'}
'@babel/helper-compilation-targets@7.28.6':
resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==}
engines: {node: '>=6.9.0'}
'@babel/helper-globals@7.28.0':
resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==}
engines: {node: '>=6.9.0'}
'@babel/helper-module-imports@7.28.6':
resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==}
engines: {node: '>=6.9.0'}
'@babel/helper-module-transforms@7.28.6':
resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
'@babel/helper-plugin-utils@7.28.6':
resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==}
engines: {node: '>=6.9.0'}
'@babel/helper-string-parser@7.27.1':
resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==}
engines: {node: '>=6.9.0'}
'@babel/helper-validator-identifier@7.28.5':
resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==}
engines: {node: '>=6.9.0'}
'@babel/helper-validator-option@7.27.1':
resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==}
engines: {node: '>=6.9.0'}
'@babel/helpers@7.29.2':
resolution: {integrity: sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==}
engines: {node: '>=6.9.0'}
'@babel/parser@7.29.2':
resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==}
engines: {node: '>=6.0.0'}
hasBin: true
'@babel/plugin-syntax-jsx@7.28.6':
resolution: {integrity: sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
'@babel/plugin-syntax-typescript@7.28.6':
resolution: {integrity: sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
'@babel/runtime@7.29.2':
resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==}
engines: {node: '>=6.9.0'}
'@babel/template@7.28.6':
resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==}
engines: {node: '>=6.9.0'}
'@babel/traverse@7.29.0':
resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==}
engines: {node: '>=6.9.0'}
'@babel/types@7.29.0':
resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==}
engines: {node: '>=6.9.0'}
'@biomejs/biome@2.4.12':
resolution: {integrity: sha512-Rro7adQl3NLq/zJCIL98eElXKI8eEiBtoeu5TbXF/U3qbjuSc7Jb5rjUbeHHcquDWeSf3HnGP7XI5qGrlRk/pA==}
engines: {node: '>=14.21.3'}
hasBin: true
'@biomejs/cli-darwin-arm64@2.4.12':
resolution: {integrity: sha512-BnMU4Pc3ciEVteVpZ0BK33MLr7X57F5w1dwDLDn+/iy/yTrA4Q/N2yftidFtsA4vrDh0FMXDpacNV/Tl3fbmng==}
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [darwin]
'@biomejs/cli-darwin-x64@2.4.12':
resolution: {integrity: sha512-x9uJ0bI1rJsWICp3VH8w/5PnAVD3A7SqzDpbrfoUQX1QyWrK5jSU4fRLo/wSgGeplCivbxBRKmt5Xq4/nWvq8A==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [darwin]
'@biomejs/cli-linux-arm64-musl@2.4.12':
resolution: {integrity: sha512-FhfpkAAlKL6kwvcVap0Hgp4AhZmtd3YImg0kK1jd7C/aSoh4SfsB2f++yG1rU0lr8Y5MCFJrcSkmssiL9Xnnig==}
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [linux]
libc: [musl]
'@biomejs/cli-linux-arm64@2.4.12':
resolution: {integrity: sha512-tOwuCuZZtKi1jVzbk/5nXmIsziOB6yqN8c9r9QM0EJYPU6DpQWf11uBOSCfFKKM4H3d9ZoarvlgMfbcuD051Pw==}
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@biomejs/cli-linux-x64-musl@2.4.12':
resolution: {integrity: sha512-dwTIgZrGutzhkQCuvHynCkyW6hJxUuyZqKKO0YNfaS2GUoRO+tOvxXZqZB6SkWAOdfZTzwaw8IEdUnIkHKHoew==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [linux]
libc: [musl]
'@biomejs/cli-linux-x64@2.4.12':
resolution: {integrity: sha512-8pFeAnLU9QdW9jCIslB/v82bI0lhBmz2ZAKc8pVMFPO0t0wAHsoEkrUQUbMkIorTRIjbqyNZHA3lEXavsPWYSw==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [linux]
libc: [glibc]
'@biomejs/cli-win32-arm64@2.4.12':
resolution: {integrity: sha512-B0DLnx0vA9ya/3v7XyCaP+/lCpnbWbMOfUFFve+xb5OxyYvdHaS55YsSddr228Y+JAFk58agCuZTsqNiw2a6ig==}
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [win32]
'@biomejs/cli-win32-x64@2.4.12':
resolution: {integrity: sha512-yMckRzTyZ83hkk8iDFWswqSdU8tvZxspJKnYNh7JZr/zhZNOlzH13k4ecboU6MurKExCe2HUkH75pGI/O2JwGA==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [win32]
'@commitlint/cli@20.5.0':
resolution: {integrity: sha512-yNkyN/tuKTJS3wdVfsZ2tXDM4G4Gi7z+jW54Cki8N8tZqwKBltbIvUUrSbT4hz1bhW/h0CdR+5sCSpXD+wMKaQ==}
engines: {node: '>=v18'}
hasBin: true
'@commitlint/config-conventional@20.5.0':
resolution: {integrity: sha512-t3Ni88rFw1XMa4nZHgOKJ8fIAT9M2j5TnKyTqJzsxea7FUetlNdYFus9dz+MhIRZmc16P0PPyEfh6X2d/qw8SA==}
engines: {node: '>=v18'}
'@commitlint/config-validator@20.5.0':
resolution: {integrity: sha512-T/Uh6iJUzyx7j35GmHWdIiGRQB+ouZDk0pwAaYq4SXgB54KZhFdJ0vYmxiW6AMYICTIWuyMxDBl1jK74oFp/Gw==}
engines: {node: '>=v18'}
'@commitlint/ensure@20.5.0':
resolution: {integrity: sha512-IpHqAUesBeW1EDDdjzJeaOxU9tnogLAyXLRBn03SHlj1SGENn2JGZqSWGkFvBJkJzfXAuCNtsoYzax+ZPS+puw==}
engines: {node: '>=v18'}
'@commitlint/execute-rule@20.0.0':
resolution: {integrity: sha512-xyCoOShoPuPL44gVa+5EdZsBVao/pNzpQhkzq3RdtlFdKZtjWcLlUFQHSWBuhk5utKYykeJPSz2i8ABHQA+ZZw==}
engines: {node: '>=v18'}
'@commitlint/format@20.5.0':
resolution: {integrity: sha512-TI9EwFU/qZWSK7a5qyXMpKPPv3qta7FO4tKW+Wt2al7sgMbLWTsAcDpX1cU8k16TRdsiiet9aOw0zpvRXNJu7Q==}
engines: {node: '>=v18'}
'@commitlint/is-ignored@20.5.0':
resolution: {integrity: sha512-JWLarAsurHJhPozbuAH6GbP4p/hdOCoqS9zJMfqwswne+/GPs5V0+rrsfOkP68Y8PSLphwtFXV0EzJ+GTXTTGg==}
engines: {node: '>=v18'}
'@commitlint/lint@20.5.0':
resolution: {integrity: sha512-jiM3hNUdu04jFBf1VgPdjtIPvbuVfDTBAc6L98AWcoLjF5sYqkulBHBzlVWll4rMF1T5zeQFB6r//a+s+BBKlA==}
engines: {node: '>=v18'}
'@commitlint/load@20.5.0':
resolution: {integrity: sha512-sLhhYTL/KxeOTZjjabKDhwidGZan84XKK1+XFkwDYL/4883kIajcz/dZFAhBJmZPtL8+nBx6bnkzA95YxPeDPw==}
engines: {node: '>=v18'}
'@commitlint/message@20.4.3':
resolution: {integrity: sha512-6akwCYrzcrFcTYz9GyUaWlhisY4lmQ3KvrnabmhoeAV8nRH4dXJAh4+EUQ3uArtxxKQkvxJS78hNX2EU3USgxQ==}
engines: {node: '>=v18'}
'@commitlint/parse@20.5.0':
resolution: {integrity: sha512-SeKWHBMk7YOTnnEWUhx+d1a9vHsjjuo6Uo1xRfPNfeY4bdYFasCH1dDpAv13Lyn+dDPOels+jP6D2GRZqzc5fA==}
engines: {node: '>=v18'}
'@commitlint/read@20.5.0':
resolution: {integrity: sha512-JDEIJ2+GnWpK8QqwfmW7O42h0aycJEWNqcdkJnyzLD11nf9dW2dWLTVEa8Wtlo4IZFGLPATjR5neA5QlOvIH1w==}
engines: {node: '>=v18'}
'@commitlint/resolve-extends@20.5.0':
resolution: {integrity: sha512-3SHPWUW2v0tyspCTcfSsYml0gses92l6TlogwzvM2cbxDgmhSRc+fldDjvGkCXJrjSM87BBaWYTPWwwyASZRrg==}
engines: {node: '>=v18'}
'@commitlint/rules@20.5.0':
resolution: {integrity: sha512-5NdQXQEdnDPT5pK8O39ZA7HohzPRHEsDGU23cyVCNPQy4WegAbAwrQk3nIu7p2sl3dutPk8RZd91yKTrMTnRkQ==}
engines: {node: '>=v18'}
'@commitlint/to-lines@20.0.0':
resolution: {integrity: sha512-2l9gmwiCRqZNWgV+pX1X7z4yP0b3ex/86UmUFgoRt672Ez6cAM2lOQeHFRUTuE6sPpi8XBCGnd8Kh3bMoyHwJw==}
engines: {node: '>=v18'}
'@commitlint/top-level@20.4.3':
resolution: {integrity: sha512-qD9xfP6dFg5jQ3NMrOhG0/w5y3bBUsVGyJvXxdWEwBm8hyx4WOk3kKXw28T5czBYvyeCVJgJJ6aoJZUWDpaacQ==}
engines: {node: '>=v18'}
'@commitlint/types@20.5.0':
resolution: {integrity: sha512-ZJoS8oSq2CAZEpc/YI9SulLrdiIyXeHb/OGqGrkUP6Q7YV+0ouNAa7GjqRdXeQPncHQIDz/jbCTlHScvYvO/gA==}
engines: {node: '>=v18'}
'@conventional-changelog/git-client@2.7.0':
resolution: {integrity: sha512-j7A8/LBEQ+3rugMzPXoKYzyUPpw/0CBQCyvtTR7Lmu4olG4yRC/Tfkq79Mr3yuPs0SUitlO2HwGP3gitMJnRFw==}
engines: {node: '>=18'}
peerDependencies:
conventional-commits-filter: ^5.0.0
conventional-commits-parser: ^6.4.0
peerDependenciesMeta:
conventional-commits-filter:
optional: true
conventional-commits-parser:
optional: true
'@emnapi/core@1.9.2':
resolution: {integrity: sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==}
'@emnapi/runtime@1.9.2':
resolution: {integrity: sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==}
'@emnapi/wasi-threads@1.2.1':
resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==}
'@esbuild/aix-ppc64@0.27.7':
resolution: {integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [aix]
'@esbuild/android-arm64@0.27.7':
resolution: {integrity: sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==}
engines: {node: '>=18'}
cpu: [arm64]
os: [android]
'@esbuild/android-arm@0.27.7':
resolution: {integrity: sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==}
engines: {node: '>=18'}
cpu: [arm]
os: [android]
'@esbuild/android-x64@0.27.7':
resolution: {integrity: sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==}
engines: {node: '>=18'}
cpu: [x64]
os: [android]
'@esbuild/darwin-arm64@0.27.7':
resolution: {integrity: sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==}
engines: {node: '>=18'}
cpu: [arm64]
os: [darwin]
'@esbuild/darwin-x64@0.27.7':
resolution: {integrity: sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [darwin]
'@esbuild/freebsd-arm64@0.27.7':
resolution: {integrity: sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==}
engines: {node: '>=18'}
cpu: [arm64]
os: [freebsd]
'@esbuild/freebsd-x64@0.27.7':
resolution: {integrity: sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [freebsd]
'@esbuild/linux-arm64@0.27.7':
resolution: {integrity: sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==}
engines: {node: '>=18'}
cpu: [arm64]
os: [linux]
'@esbuild/linux-arm@0.27.7':
resolution: {integrity: sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==}
engines: {node: '>=18'}
cpu: [arm]
os: [linux]
'@esbuild/linux-ia32@0.27.7':
resolution: {integrity: sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==}
engines: {node: '>=18'}
cpu: [ia32]
os: [linux]
'@esbuild/linux-loong64@0.27.7':
resolution: {integrity: sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==}
engines: {node: '>=18'}
cpu: [loong64]
os: [linux]
'@esbuild/linux-mips64el@0.27.7':
resolution: {integrity: sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==}
engines: {node: '>=18'}
cpu: [mips64el]
os: [linux]
'@esbuild/linux-ppc64@0.27.7':
resolution: {integrity: sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [linux]
'@esbuild/linux-riscv64@0.27.7':
resolution: {integrity: sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==}
engines: {node: '>=18'}
cpu: [riscv64]
os: [linux]
'@esbuild/linux-s390x@0.27.7':
resolution: {integrity: sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==}
engines: {node: '>=18'}
cpu: [s390x]
os: [linux]
'@esbuild/linux-x64@0.27.7':
resolution: {integrity: sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==}
engines: {node: '>=18'}
cpu: [x64]
os: [linux]
'@esbuild/netbsd-arm64@0.27.7':
resolution: {integrity: sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==}
engines: {node: '>=18'}
cpu: [arm64]
os: [netbsd]
'@esbuild/netbsd-x64@0.27.7':
resolution: {integrity: sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==}
engines: {node: '>=18'}
cpu: [x64]
os: [netbsd]
'@esbuild/openbsd-arm64@0.27.7':
resolution: {integrity: sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openbsd]
'@esbuild/openbsd-x64@0.27.7':
resolution: {integrity: sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==}
engines: {node: '>=18'}
cpu: [x64]
os: [openbsd]
'@esbuild/openharmony-arm64@0.27.7':
resolution: {integrity: sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openharmony]
'@esbuild/sunos-x64@0.27.7':
resolution: {integrity: sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==}
engines: {node: '>=18'}
cpu: [x64]
os: [sunos]
'@esbuild/win32-arm64@0.27.7':
resolution: {integrity: sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==}
engines: {node: '>=18'}
cpu: [arm64]
os: [win32]
'@esbuild/win32-ia32@0.27.7':
resolution: {integrity: sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==}
engines: {node: '>=18'}
cpu: [ia32]
os: [win32]
'@esbuild/win32-x64@0.27.7':
resolution: {integrity: sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==}
engines: {node: '>=18'}
cpu: [x64]
os: [win32]
'@jridgewell/gen-mapping@0.3.13':
resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
'@jridgewell/remapping@2.3.5':
resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==}
'@jridgewell/resolve-uri@3.1.2':
resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
engines: {node: '>=6.0.0'}
'@jridgewell/sourcemap-codec@1.5.5':
resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
'@jridgewell/trace-mapping@0.3.31':
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
'@napi-rs/wasm-runtime@1.1.4':
resolution: {integrity: sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==}
peerDependencies:
'@emnapi/core': ^1.7.1
'@emnapi/runtime': ^1.7.1
'@oxc-project/types@0.124.0':
resolution: {integrity: sha512-VBFWMTBvHxS11Z5Lvlr3IWgrwhMTXV+Md+EQF0Xf60+wAdsGFTBx7X7K/hP4pi8N7dcm1RvcHwDxZ16Qx8keUg==}
'@rolldown/binding-android-arm64@1.0.0-rc.15':
resolution: {integrity: sha512-YYe6aWruPZDtHNpwu7+qAHEMbQ/yRl6atqb/AhznLTnD3UY99Q1jE7ihLSahNWkF4EqRPVC4SiR4O0UkLK02tA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [android]
'@rolldown/binding-darwin-arm64@1.0.0-rc.15':
resolution: {integrity: sha512-oArR/ig8wNTPYsXL+Mzhs0oxhxfuHRfG7Ikw7jXsw8mYOtk71W0OkF2VEVh699pdmzjPQsTjlD1JIOoHkLP1Fg==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [darwin]
'@rolldown/binding-darwin-x64@1.0.0-rc.15':
resolution: {integrity: sha512-YzeVqOqjPYvUbJSWJ4EDL8ahbmsIXQpgL3JVipmN+MX0XnXMeWomLN3Fb+nwCmP/jfyqte5I3XRSm7OfQrbyxw==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [darwin]
'@rolldown/binding-freebsd-x64@1.0.0-rc.15':
resolution: {integrity: sha512-9Erhx956jeQ0nNTyif1+QWAXDRD38ZNjr//bSHrt6wDwB+QkAfl2q6Mn1k6OBPerznjRmbM10lgRb1Pli4xZPw==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [freebsd]
'@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.15':
resolution: {integrity: sha512-cVwk0w8QbZJGTnP/AHQBs5yNwmpgGYStL88t4UIaqcvYJWBfS0s3oqVLZPwsPU6M0zlW4GqjP0Zq5MnAGwFeGA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm]
os: [linux]
'@rolldown/binding-linux-arm64-gnu@1.0.0-rc.15':
resolution: {integrity: sha512-eBZ/u8iAK9SoHGanqe/jrPnY0JvBN6iXbVOsbO38mbz+ZJsaobExAm1Iu+rxa4S1l2FjG0qEZn4Rc6X8n+9M+w==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@rolldown/binding-linux-arm64-musl@1.0.0-rc.15':
resolution: {integrity: sha512-ZvRYMGrAklV9PEkgt4LQM6MjQX2P58HPAuecwYObY2DhS2t35R0I810bKi0wmaYORt6m/2Sm+Z+nFgb0WhXNcQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [linux]
libc: [musl]
'@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.15':
resolution: {integrity: sha512-VDpgGBzgfg5hLg+uBpCLoFG5kVvEyafmfxGUV0UHLcL5irxAK7PKNeC2MwClgk6ZAiNhmo9FLhRYgvMmedLtnQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [ppc64]
os: [linux]
libc: [glibc]
'@rolldown/binding-linux-s390x-gnu@1.0.0-rc.15':
resolution: {integrity: sha512-y1uXY3qQWCzcPgRJATPSOUP4tCemh4uBdY7e3EZbVwCJTY3gLJWnQABgeUetvED+bt1FQ01OeZwvhLS2bpNrAQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [s390x]
os: [linux]
libc: [glibc]
'@rolldown/binding-linux-x64-gnu@1.0.0-rc.15':
resolution: {integrity: sha512-023bTPBod7J3Y/4fzAN6QtpkSABR0rigtrwaP+qSEabUh5zf6ELr9Nc7GujaROuPY3uwdSIXWrvhn1KxOvurWA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [linux]
libc: [glibc]
'@rolldown/binding-linux-x64-musl@1.0.0-rc.15':
resolution: {integrity: sha512-witB2O0/hU4CgfOOKUoeFgQ4GktPi1eEbAhaLAIpgD6+ZnhcPkUtPsoKKHRzmOoWPZue46IThdSgdo4XneOLYw==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [linux]
libc: [musl]
'@rolldown/binding-openharmony-arm64@1.0.0-rc.15':
resolution: {integrity: sha512-UCL68NJ0Ud5zRipXZE9dF5PmirzJE4E4BCIOOssEnM7wLDsxjc6Qb0sGDxTNRTP53I6MZpygyCpY8Aa8sPfKPg==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [openharmony]
'@rolldown/binding-wasm32-wasi@1.0.0-rc.15':
resolution: {integrity: sha512-ApLruZq/ig+nhaE7OJm4lDjayUnOHVUa77zGeqnqZ9pn0ovdVbbNPerVibLXDmWeUZXjIYIT8V3xkT58Rm9u5Q==}
engines: {node: '>=14.0.0'}
cpu: [wasm32]
'@rolldown/binding-win32-arm64-msvc@1.0.0-rc.15':
resolution: {integrity: sha512-KmoUoU7HnN+Si5YWJigfTws1jz1bKBYDQKdbLspz0UaqjjFkddHsqorgiW1mxcAj88lYUE6NC/zJNwT+SloqtA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [win32]
'@rolldown/binding-win32-x64-msvc@1.0.0-rc.15':
resolution: {integrity: sha512-3P2A8L+x75qavWLe/Dll3EYBJLQmtkJN8rfh+U/eR3MqMgL/h98PhYI+JFfXuDPgPeCB7iZAKiqii5vqOvnA0g==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [win32]
'@rolldown/plugin-babel@0.2.3':
resolution: {integrity: sha512-+zEk16yGlz1F9STiRr6uG9hmIXb6nprjLczV/htGptYuLoCuxb+itZ03RKCEeOhBpDDd1NU7qF6x1VLMUp62bw==}
engines: {node: '>=22.12.0 || ^24.0.0'}
peerDependencies:
'@babel/core': ^7.29.0 || ^8.0.0-rc.1
'@babel/plugin-transform-runtime': ^7.29.0 || ^8.0.0-rc.1
'@babel/runtime': ^7.27.0 || ^8.0.0-rc.1
rolldown: ^1.0.0-rc.5
vite: ^8.0.0
peerDependenciesMeta:
'@babel/plugin-transform-runtime':
optional: true
'@babel/runtime':
optional: true
vite:
optional: true
'@rolldown/pluginutils@1.0.0-rc.15':
resolution: {integrity: sha512-UromN0peaE53IaBRe9W7CjrZgXl90fqGpK+mIZbA3qSTeYqg3pqpROBdIPvOG3F5ereDHNwoHBI2e50n1BDr1g==}
'@rolldown/pluginutils@1.0.0-rc.7':
resolution: {integrity: sha512-qujRfC8sFVInYSPPMLQByRh7zhwkGFS4+tyMQ83srV1qrxL4g8E2tyxVVyxd0+8QeBM1mIk9KbWxkegRr76XzA==}
'@simple-libs/child-process-utils@1.0.2':
resolution: {integrity: sha512-/4R8QKnd/8agJynkNdJmNw2MBxuFTRcNFnE5Sg/G+jkSsV8/UBgULMzhizWWW42p8L5H7flImV2ATi79Ove2Tw==}
engines: {node: '>=18'}
'@simple-libs/stream-utils@1.2.0':
resolution: {integrity: sha512-KxXvfapcixpz6rVEB6HPjOUZT22yN6v0vI0urQSk1L8MlEWPDFCZkhw2xmkyoTGYeFw7tWTZd7e3lVzRZRN/EA==}
engines: {node: '>=18'}
'@tailwindcss/node@4.2.2':
resolution: {integrity: sha512-pXS+wJ2gZpVXqFaUEjojq7jzMpTGf8rU6ipJz5ovJV6PUGmlJ+jvIwGrzdHdQ80Sg+wmQxUFuoW1UAAwHNEdFA==}
'@tailwindcss/oxide-android-arm64@4.2.2':
resolution: {integrity: sha512-dXGR1n+P3B6748jZO/SvHZq7qBOqqzQ+yFrXpoOWWALWndF9MoSKAT3Q0fYgAzYzGhxNYOoysRvYlpixRBBoDg==}
engines: {node: '>= 20'}
cpu: [arm64]
os: [android]
'@tailwindcss/oxide-darwin-arm64@4.2.2':
resolution: {integrity: sha512-iq9Qjr6knfMpZHj55/37ouZeykwbDqF21gPFtfnhCCKGDcPI/21FKC9XdMO/XyBM7qKORx6UIhGgg6jLl7BZlg==}
engines: {node: '>= 20'}
cpu: [arm64]
os: [darwin]
'@tailwindcss/oxide-darwin-x64@4.2.2':
resolution: {integrity: sha512-BlR+2c3nzc8f2G639LpL89YY4bdcIdUmiOOkv2GQv4/4M0vJlpXEa0JXNHhCHU7VWOKWT/CjqHdTP8aUuDJkuw==}
engines: {node: '>= 20'}
cpu: [x64]
os: [darwin]
'@tailwindcss/oxide-freebsd-x64@4.2.2':
resolution: {integrity: sha512-YUqUgrGMSu2CDO82hzlQ5qSb5xmx3RUrke/QgnoEx7KvmRJHQuZHZmZTLSuuHwFf0DJPybFMXMYf+WJdxHy/nQ==}
engines: {node: '>= 20'}
cpu: [x64]
os: [freebsd]
'@tailwindcss/oxide-linux-arm-gnueabihf@4.2.2':
resolution: {integrity: sha512-FPdhvsW6g06T9BWT0qTwiVZYE2WIFo2dY5aCSpjG/S/u1tby+wXoslXS0kl3/KXnULlLr1E3NPRRw0g7t2kgaQ==}
engines: {node: '>= 20'}
cpu: [arm]
os: [linux]
'@tailwindcss/oxide-linux-arm64-gnu@4.2.2':
resolution: {integrity: sha512-4og1V+ftEPXGttOO7eCmW7VICmzzJWgMx+QXAJRAhjrSjumCwWqMfkDrNu1LXEQzNAwz28NCUpucgQPrR4S2yw==}
engines: {node: '>= 20'}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@tailwindcss/oxide-linux-arm64-musl@4.2.2':
resolution: {integrity: sha512-oCfG/mS+/+XRlwNjnsNLVwnMWYH7tn/kYPsNPh+JSOMlnt93mYNCKHYzylRhI51X+TbR+ufNhhKKzm6QkqX8ag==}
engines: {node: '>= 20'}
cpu: [arm64]
os: [linux]
libc: [musl]
'@tailwindcss/oxide-linux-x64-gnu@4.2.2':
resolution: {integrity: sha512-rTAGAkDgqbXHNp/xW0iugLVmX62wOp2PoE39BTCGKjv3Iocf6AFbRP/wZT/kuCxC9QBh9Pu8XPkv/zCZB2mcMg==}
engines: {node: '>= 20'}
cpu: [x64]
os: [linux]
libc: [glibc]
'@tailwindcss/oxide-linux-x64-musl@4.2.2':
resolution: {integrity: sha512-XW3t3qwbIwiSyRCggeO2zxe3KWaEbM0/kW9e8+0XpBgyKU4ATYzcVSMKteZJ1iukJ3HgHBjbg9P5YPRCVUxlnQ==}
engines: {node: '>= 20'}
cpu: [x64]
os: [linux]
libc: [musl]
'@tailwindcss/oxide-wasm32-wasi@4.2.2':
resolution: {integrity: sha512-eKSztKsmEsn1O5lJ4ZAfyn41NfG7vzCg496YiGtMDV86jz1q/irhms5O0VrY6ZwTUkFy/EKG3RfWgxSI3VbZ8Q==}
engines: {node: '>=14.0.0'}
cpu: [wasm32]
bundledDependencies:
- '@napi-rs/wasm-runtime'
- '@emnapi/core'
- '@emnapi/runtime'
- '@tybys/wasm-util'
- '@emnapi/wasi-threads'
- tslib
'@tailwindcss/oxide-win32-arm64-msvc@4.2.2':
resolution: {integrity: sha512-qPmaQM4iKu5mxpsrWZMOZRgZv1tOZpUm+zdhhQP0VhJfyGGO3aUKdbh3gDZc/dPLQwW4eSqWGrrcWNBZWUWaXQ==}
engines: {node: '>= 20'}
cpu: [arm64]
os: [win32]
'@tailwindcss/oxide-win32-x64-msvc@4.2.2':
resolution: {integrity: sha512-1T/37VvI7WyH66b+vqHj/cLwnCxt7Qt3WFu5Q8hk65aOvlwAhs7rAp1VkulBJw/N4tMirXjVnylTR72uI0HGcA==}
engines: {node: '>= 20'}
cpu: [x64]
os: [win32]
'@tailwindcss/oxide@4.2.2':
resolution: {integrity: sha512-qEUA07+E5kehxYp9BVMpq9E8vnJuBHfJEC0vPC5e7iL/hw7HR61aDKoVoKzrG+QKp56vhNZe4qwkRmMC0zDLvg==}
engines: {node: '>= 20'}
'@tailwindcss/vite@4.2.2':
resolution: {integrity: sha512-mEiF5HO1QqCLXoNEfXVA1Tzo+cYsrqV7w9Juj2wdUFyW07JRenqMG225MvPwr3ZD9N1bFQj46X7r33iHxLUW0w==}
peerDependencies:
vite: ^5.2.0 || ^6 || ^7 || ^8
'@tanstack/history@1.161.6':
resolution: {integrity: sha512-NaOGLRrddszbQj9upGat6HG/4TKvXLvu+osAIgfxPYA+eIvYKv8GKDJOrY2D3/U9MRnKfMWD7bU4jeD4xmqyIg==}
engines: {node: '>=20.19'}
'@tanstack/query-core@5.99.0':
resolution: {integrity: sha512-3Jv3WQG0BCcH7G+7lf/bP8QyBfJOXeY+T08Rin3GZ1bshvwlbPt7NrDHMEzGdKIOmOzvIQmxjk28YEQX60k7pQ==}
'@tanstack/query-devtools@5.99.0':
resolution: {integrity: sha512-m4ufXaJ8FjWXw7xDtyzE/6fkZAyQFg9WrbMrUpt8ZecRJx58jiFOZ2lxZMphZdIpAnIeto/S8stbwLKLusyckQ==}
'@tanstack/react-query-devtools@5.99.0':
resolution: {integrity: sha512-CqqX7LCU9yOfCY/vBURSx2YSD83ryfX+QkfkaKionTfg1s2Hdm572Ro99gW3QPoJjzvsj1HM4pnN4nbDy3MXKA==}
peerDependencies:
'@tanstack/react-query': ^5.99.0
react: ^18 || ^19
'@tanstack/react-query@5.99.0':
resolution: {integrity: sha512-OY2bCqPemT1LlqJ8Y2CUau4KELnIhhG9Ol3ZndPbdnB095pRbPo1cHuXTndg8iIwtoHTgwZjyaDnQ0xD0mYwAw==}
peerDependencies:
react: ^18 || ^19
'@tanstack/react-router@1.168.22':
resolution: {integrity: sha512-W2LyfkfJtDCf//jOjZeUBWwOVl8iDRVTECpGHa2M28MT3T5/VVnjgicYNHR/ax0Filk1iU67MRjcjHheTYvK1Q==}
engines: {node: '>=20.19'}
peerDependencies:
react: '>=18.0.0 || >=19.0.0'
react-dom: '>=18.0.0 || >=19.0.0'
'@tanstack/react-store@0.9.3':
resolution: {integrity: sha512-y2iHd/N9OkoQbFJLUX1T9vbc2O9tjH0pQRgTcx1/Nz4IlwLvkgpuglXUx+mXt0g5ZDFrEeDnONPqkbfxXJKwRg==}
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
'@tanstack/router-cli@1.166.33':
resolution: {integrity: sha512-gCWBbCVkfT2OzgxQVV275BjRYKvfh7SEKD73ATHWyLE8ifm8/O2700roObVHUy+Y0jJT91Am0UkjsES0O2jqzw==}
engines: {node: '>=20.19'}
hasBin: true
'@tanstack/router-core@1.168.15':
resolution: {integrity: sha512-Wr0424NDtD8fT/uALobMZ9DdcfsTyXtW5IPR++7zvW8/7RaIOeaqXpVDId8ywaGtqPWLWOfaUg2zUtYtukoXYA==}
engines: {node: '>=20.19'}
hasBin: true
'@tanstack/router-generator@1.166.32':
resolution: {integrity: sha512-VuusKwEXcgKq+myq1JQfZogY8scTXIIeFls50dJ/UXgCXWp5n14iFreYNlg41wURcak2oA3M+t2TVfD0xUUD6g==}
engines: {node: '>=20.19'}
'@tanstack/router-plugin@1.167.22':
resolution: {integrity: sha512-wYPzIvBK8bcmXVUpZfSgGBXOrfBAdF4odKevz6rejio5rEd947NtKDF5R7eYdwlAOmRqYpLJnJ1QHkc5t8bY4w==}
engines: {node: '>=20.19'}
hasBin: true
peerDependencies:
'@rsbuild/core': '>=1.0.2'
'@tanstack/react-router': ^1.168.21
vite: '>=5.0.0 || >=6.0.0 || >=7.0.0 || >=8.0.0'
vite-plugin-solid: ^2.11.10 || ^3.0.0-0
webpack: '>=5.92.0'
peerDependenciesMeta:
'@rsbuild/core':
optional: true
'@tanstack/react-router':
optional: true
vite:
optional: true
vite-plugin-solid:
optional: true
webpack:
optional: true
'@tanstack/router-utils@1.161.6':
resolution: {integrity: sha512-nRcYw+w2OEgK6VfjirYvGyPLOK+tZQz1jkYcmH5AjMamQ9PycnlxZF2aEZtPpNoUsaceX2bHptn6Ub5hGXqNvw==}
engines: {node: '>=20.19'}
'@tanstack/store@0.9.3':
resolution: {integrity: sha512-8reSzl/qGWGGVKhBoxXPMWzATSbZLZFWhwBAFO9NAyp0TxzfBP0mIrGb8CP8KrQTmvzXlR/vFPPUrHTLBGyFyw==}
'@tanstack/virtual-file-routes@1.161.7':
resolution: {integrity: sha512-olW33+Cn+bsCsZKPwEGhlkqS6w3M2slFv11JIobdnCFKMLG97oAI2kWKdx5/zsywTL8flpnoIgaZZPlQTFYhdQ==}
engines: {node: '>=20.19'}
hasBin: true
'@tybys/wasm-util@0.10.1':
resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==}
'@types/babel__core@7.20.5':
resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
'@types/babel__generator@7.27.0':
resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==}
'@types/babel__template@7.4.4':
resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==}
'@types/babel__traverse@7.28.0':
resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==}
'@types/node@24.12.2':
resolution: {integrity: sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==}
'@types/react-dom@19.2.3':
resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==}
peerDependencies:
'@types/react': ^19.2.0
'@types/react@19.2.14':
resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==}
'@vitejs/plugin-react@6.0.1':
resolution: {integrity: sha512-l9X/E3cDb+xY3SWzlG1MOGt2usfEHGMNIaegaUGFsLkb3RCn/k8/TOXBcab+OndDI4TBtktT8/9BwwW8Vi9KUQ==}
engines: {node: ^20.19.0 || >=22.12.0}
peerDependencies:
'@rolldown/plugin-babel': ^0.1.7 || ^0.2.0
babel-plugin-react-compiler: ^1.0.0
vite: ^8.0.0
peerDependenciesMeta:
'@rolldown/plugin-babel':
optional: true
babel-plugin-react-compiler:
optional: true
acorn@8.16.0:
resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==}
engines: {node: '>=0.4.0'}
hasBin: true
ajv@8.18.0:
resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==}
ansi-escapes@4.3.2:
resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==}
engines: {node: '>=8'}
ansi-escapes@7.3.0:
resolution: {integrity: sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==}
engines: {node: '>=18'}
ansi-regex@5.0.1:
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
engines: {node: '>=8'}
ansi-regex@6.2.2:
resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==}
engines: {node: '>=12'}
ansi-styles@3.2.1:
resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
engines: {node: '>=4'}
ansi-styles@4.3.0:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
engines: {node: '>=8'}
ansi-styles@6.2.3:
resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==}
engines: {node: '>=12'}
ansis@4.2.0:
resolution: {integrity: sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==}
engines: {node: '>=14'}
anymatch@3.1.3:
resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
engines: {node: '>= 8'}
argparse@2.0.1:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
array-ify@1.0.0:
resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==}
at-least-node@1.0.0:
resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==}
engines: {node: '>= 4.0.0'}
babel-dead-code-elimination@1.0.12:
resolution: {integrity: sha512-GERT7L2TiYcYDtYk1IpD+ASAYXjKbLTDPhBtYj7X1NuRMDTMtAx9kyBenub1Ev41lo91OHCKdmP+egTDmfQ7Ig==}
babel-plugin-react-compiler@1.0.0:
resolution: {integrity: sha512-Ixm8tFfoKKIPYdCCKYTsqv+Fd4IJ0DQqMyEimo+pxUOMUR9cVPlwTrFt9Avu+3cb6Zp3mAzl+t1MrG2fxxKsxw==}
balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
baseline-browser-mapping@2.10.19:
resolution: {integrity: sha512-qCkNLi2sfBOn8XhZQ0FXsT1Ki/Yo5P90hrkRamVFRS7/KV9hpfA4HkoWNU152+8w0zPjnxo5psx5NL3PSGgv5g==}
engines: {node: '>=6.0.0'}
hasBin: true
binary-extensions@2.3.0:
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
engines: {node: '>=8'}
bl@4.1.0:
resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==}
brace-expansion@1.1.14:
resolution: {integrity: sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==}
braces@3.0.3:
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
engines: {node: '>=8'}
browserslist@4.28.2:
resolution: {integrity: sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==}
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
buffer@5.7.1:
resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
cachedir@2.3.0:
resolution: {integrity: sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==}
engines: {node: '>=6'}
callsites@3.1.0:
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
engines: {node: '>=6'}
caniuse-lite@1.0.30001788:
resolution: {integrity: sha512-6q8HFp+lOQtcf7wBK+uEenxymVWkGKkjFpCvw5W25cmMwEDU45p1xQFBQv8JDlMMry7eNxyBaR+qxgmTUZkIRQ==}
chalk@2.4.2:
resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
engines: {node: '>=4'}
chalk@4.1.2:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'}
chardet@0.7.0:
resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==}
chokidar@3.6.0:
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
engines: {node: '>= 8.10.0'}
cli-cursor@3.1.0:
resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==}
engines: {node: '>=8'}
cli-cursor@5.0.0:
resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==}
engines: {node: '>=18'}
cli-spinners@2.9.2:
resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==}
engines: {node: '>=6'}
cli-truncate@5.2.0:
resolution: {integrity: sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==}
engines: {node: '>=20'}
cli-width@3.0.0:
resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==}
engines: {node: '>= 10'}
cliui@8.0.1:
resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
engines: {node: '>=12'}
clone@1.0.4:
resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==}
engines: {node: '>=0.8'}
color-convert@1.9.3:
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
color-convert@2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
engines: {node: '>=7.0.0'}
color-name@1.1.3:
resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
colorette@2.0.20:
resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==}
commander@14.0.3:
resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==}
engines: {node: '>=20'}
commitizen@4.3.1:
resolution: {integrity: sha512-gwAPAVTy/j5YcOOebcCRIijn+mSjWJC+IYKivTu6aG8Ei/scoXgfsMRnuAk6b0GRste2J4NGxVdMN3ZpfNaVaw==}
engines: {node: '>= 12'}
hasBin: true
compare-func@2.0.0:
resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==}
concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
conventional-changelog-angular@8.3.1:
resolution: {integrity: sha512-6gfI3otXK5Ph5DfCOI1dblr+kN3FAm5a97hYoQkqNZxOaYa5WKfXH+AnpsmS+iUH2mgVC2Cg2Qw9m5OKcmNrIg==}
engines: {node: '>=18'}
conventional-changelog-conventionalcommits@9.3.1:
resolution: {integrity: sha512-dTYtpIacRpcZgrvBYvBfArMmK2xvIpv2TaxM0/ZI5CBtNUzvF2x0t15HsbRABWprS6UPmvj+PzHVjSx4qAVKyw==}
engines: {node: '>=18'}
conventional-commit-types@3.0.0:
resolution: {integrity: sha512-SmmCYnOniSsAa9GqWOeLqc179lfr5TRu5b4QFDkbsrJ5TZjPJx85wtOr3zn+1dbeNiXDKGPbZ72IKbPhLXh/Lg==}
conventional-commits-parser@6.4.0:
resolution: {integrity: sha512-tvRg7FIBNlyPzjdG8wWRlPHQJJHI7DylhtRGeU9Lq+JuoPh5BKpPRX83ZdLrvXuOSu5Eo/e7SzOQhU4Hd2Miuw==}
engines: {node: '>=18'}
hasBin: true
convert-source-map@2.0.0:
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
cookie-es@3.1.1:
resolution: {integrity: sha512-UaXxwISYJPTr9hwQxMFYZ7kNhSXboMXP+Z3TRX6f1/NyaGPfuNUZOWP1pUEb75B2HjfklIYLVRfWiFZJyC6Npg==}
cosmiconfig-typescript-loader@6.3.0:
resolution: {integrity: sha512-Akr82WH1Wfqatyiqpj8HDkO2o2KmJRu1FhKfSNJP3K4IdXwHfEyL7MOb62i1AGQVLtIQM+iCE9CGOtrfhR+mmA==}
engines: {node: '>=v18'}
peerDependencies:
'@types/node': '*'
cosmiconfig: '>=9'
typescript: '>=5'
cosmiconfig@9.0.1:
resolution: {integrity: sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==}
engines: {node: '>=14'}
peerDependencies:
typescript: '>=4.9.5'
peerDependenciesMeta:
typescript:
optional: true
csstype@3.2.3:
resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
cz-conventional-changelog@3.3.0:
resolution: {integrity: sha512-U466fIzU5U22eES5lTNiNbZ+d8dfcHcssH4o7QsdWaCcRs/feIPCxKYSWkYBNs5mny7MvEfwpTLWjvbm94hecw==}
engines: {node: '>= 10'}
debug@4.4.3:
resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
engines: {node: '>=6.0'}
peerDependencies:
supports-color: '*'
peerDependenciesMeta:
supports-color:
optional: true
dedent@0.7.0:
resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==}
defaults@1.0.4:
resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==}
detect-file@1.0.0:
resolution: {integrity: sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==}
engines: {node: '>=0.10.0'}
detect-indent@6.1.0:
resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==}
engines: {node: '>=8'}
detect-libc@2.1.2:
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
engines: {node: '>=8'}
diff@8.0.4:
resolution: {integrity: sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==}
engines: {node: '>=0.3.1'}
dot-prop@5.3.0:
resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==}
engines: {node: '>=8'}
electron-to-chromium@1.5.338:
resolution: {integrity: sha512-KVQQ3xko9/coDX3qXLUEEbqkKT8L+1DyAovrtu0Khtrt9wjSZ+7CZV4GVzxFy9Oe1NbrIU1oVXCwHJruIA1PNg==}
emoji-regex@10.6.0:
resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==}
emoji-regex@8.0.0:
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
enhanced-resolve@5.20.1:
resolution: {integrity: sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA==}
engines: {node: '>=10.13.0'}
env-paths@2.2.1:
resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==}
engines: {node: '>=6'}
environment@1.1.0:
resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==}
engines: {node: '>=18'}
error-ex@1.3.4:
resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==}
esbuild@0.27.7:
resolution: {integrity: sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==}
engines: {node: '>=18'}
hasBin: true
escalade@3.2.0:
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
engines: {node: '>=6'}
escape-string-regexp@1.0.5:
resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
engines: {node: '>=0.8.0'}
eventemitter3@5.0.4:
resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==}
expand-tilde@2.0.2:
resolution: {integrity: sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==}
engines: {node: '>=0.10.0'}
external-editor@3.1.0:
resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==}
engines: {node: '>=4'}
fast-deep-equal@3.1.3:
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
fast-uri@3.1.0:
resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==}
fdir@6.5.0:
resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
engines: {node: '>=12.0.0'}
peerDependencies:
picomatch: ^3 || ^4
peerDependenciesMeta:
picomatch:
optional: true
figures@3.2.0:
resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==}
engines: {node: '>=8'}
fill-range@7.1.1:
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
engines: {node: '>=8'}
find-node-modules@2.1.3:
resolution: {integrity: sha512-UC2I2+nx1ZuOBclWVNdcnbDR5dlrOdVb7xNjmT/lHE+LsgztWks3dG7boJ37yTS/venXw84B/mAW9uHVoC5QRg==}
find-root@1.1.0:
resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==}
findup-sync@4.0.0:
resolution: {integrity: sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ==}
engines: {node: '>= 8'}
fs-extra@9.1.0:
resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==}
engines: {node: '>=10'}
fs.realpath@1.0.0:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
fsevents@2.3.3:
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
os: [darwin]
gensync@1.0.0-beta.2:
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
engines: {node: '>=6.9.0'}
get-caller-file@2.0.5:
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
engines: {node: 6.* || 8.* || >= 10.*}
get-east-asian-width@1.5.0:
resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==}
engines: {node: '>=18'}
get-tsconfig@4.14.0:
resolution: {integrity: sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==}
git-raw-commits@5.0.1:
resolution: {integrity: sha512-Y+csSm2GD/PCSh6Isd/WiMjNAydu0VBiG9J7EdQsNA5P9uXvLayqjmTsNlK5Gs9IhblFZqOU0yid5Il5JPoLiQ==}
engines: {node: '>=18'}
hasBin: true
glob-parent@5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'}
glob@7.2.3:
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
deprecated: Glob versions prior to v9 are no longer supported
global-directory@4.0.1:
resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==}
engines: {node: '>=18'}
global-modules@1.0.0:
resolution: {integrity: sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==}
engines: {node: '>=0.10.0'}
global-prefix@1.0.2:
resolution: {integrity: sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==}
engines: {node: '>=0.10.0'}
graceful-fs@4.2.11:
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
has-flag@3.0.0:
resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
engines: {node: '>=4'}
has-flag@4.0.0:
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
engines: {node: '>=8'}
homedir-polyfill@1.0.3:
resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==}
engines: {node: '>=0.10.0'}
html-parse-stringify@3.0.1:
resolution: {integrity: sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==}
husky@9.1.7:
resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==}
engines: {node: '>=18'}
hasBin: true
i18next@26.0.5:
resolution: {integrity: sha512-9uHb4T27TdV36phJXcbpnRPt5yzAfqHXVrdASvmHZyPuZJtrLythd+GyXhiaHV5LlpuuskbAqhwPjmfTbKbi8w==}
peerDependencies:
typescript: ^5 || ^6
peerDependenciesMeta:
typescript:
optional: true
iconv-lite@0.4.24:
resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
engines: {node: '>=0.10.0'}
ieee754@1.2.1:
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
import-fresh@3.3.1:
resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
engines: {node: '>=6'}
import-meta-resolve@4.2.0:
resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==}
inflight@1.0.6:
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
inherits@2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
ini@1.3.8:
resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
ini@4.1.1:
resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==}
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
inquirer@8.2.5:
resolution: {integrity: sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ==}
engines: {node: '>=12.0.0'}
is-arrayish@0.2.1:
resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
is-binary-path@2.1.0:
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
engines: {node: '>=8'}
is-extglob@2.1.1:
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
engines: {node: '>=0.10.0'}
is-fullwidth-code-point@3.0.0:
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
engines: {node: '>=8'}
is-fullwidth-code-point@5.1.0:
resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==}
engines: {node: '>=18'}
is-glob@4.0.3:
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
engines: {node: '>=0.10.0'}
is-interactive@1.0.0:
resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==}
engines: {node: '>=8'}
is-number@7.0.0:
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
engines: {node: '>=0.12.0'}
is-obj@2.0.0:
resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==}
engines: {node: '>=8'}
is-plain-obj@4.1.0:
resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==}
engines: {node: '>=12'}
is-unicode-supported@0.1.0:
resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==}
engines: {node: '>=10'}
is-utf8@0.2.1:
resolution: {integrity: sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==}
is-windows@1.0.2:
resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==}
engines: {node: '>=0.10.0'}
isbot@5.1.39:
resolution: {integrity: sha512-obH0yYahGXdzNxo+djmHhBYThUKDkz565cxkIlt2L9hXfv1NlaLKoDBHo6KxXsYrIXx2RK3x5vY36CfZcobxEw==}
engines: {node: '>=18'}
isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
jiti@2.6.1:
resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==}
hasBin: true
js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
js-yaml@4.1.1:
resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==}
hasBin: true
jsesc@3.1.0:
resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==}
engines: {node: '>=6'}
hasBin: true
json-parse-even-better-errors@2.3.1:
resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
json-schema-traverse@1.0.0:
resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==}
json5@2.2.3:
resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
engines: {node: '>=6'}
hasBin: true
jsonfile@6.2.0:
resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==}
ky@2.0.1:
resolution: {integrity: sha512-HJPEjEpQPZQ5M3G5eu90/LWZDwysCnvqcfbLvq9FUvfizBZRi58WEixswyyI32LOLcFQd43w7kcfgkCPFxDt/Q==}
engines: {node: '>=22'}
lightningcss-android-arm64@1.32.0:
resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [android]
lightningcss-darwin-arm64@1.32.0:
resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [darwin]
lightningcss-darwin-x64@1.32.0:
resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [darwin]
lightningcss-freebsd-x64@1.32.0:
resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [freebsd]
lightningcss-linux-arm-gnueabihf@1.32.0:
resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==}
engines: {node: '>= 12.0.0'}
cpu: [arm]
os: [linux]
lightningcss-linux-arm64-gnu@1.32.0:
resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
libc: [glibc]
lightningcss-linux-arm64-musl@1.32.0:
resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
libc: [musl]
lightningcss-linux-x64-gnu@1.32.0:
resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
libc: [glibc]
lightningcss-linux-x64-musl@1.32.0:
resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
libc: [musl]
lightningcss-win32-arm64-msvc@1.32.0:
resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [win32]
lightningcss-win32-x64-msvc@1.32.0:
resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [win32]
lightningcss@1.32.0:
resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==}
engines: {node: '>= 12.0.0'}
lines-and-columns@1.2.4:
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
lint-staged@16.4.0:
resolution: {integrity: sha512-lBWt8hujh/Cjysw5GYVmZpFHXDCgZzhrOm8vbcUdobADZNOK/bRshr2kM3DfgrrtR1DQhfupW9gnIXOfiFi+bw==}
engines: {node: '>=20.17'}
hasBin: true
listr2@9.0.5:
resolution: {integrity: sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==}
engines: {node: '>=20.0.0'}
lodash.camelcase@4.3.0:
resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==}
lodash.kebabcase@4.1.1:
resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==}
lodash.map@4.6.0:
resolution: {integrity: sha512-worNHGKLDetmcEYDvh2stPCrrQRkP20E4l0iIS7F8EvzMqBBi7ltvFN5m1HvTf1P7Jk1txKhvFcmYsCr8O2F1Q==}
lodash.mergewith@4.6.2:
resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==}
lodash.snakecase@4.1.1:
resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==}
lodash.startcase@4.4.0:
resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==}
lodash.upperfirst@4.3.1:
resolution: {integrity: sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==}
lodash@4.17.21:
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
log-symbols@4.1.0:
resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==}
engines: {node: '>=10'}
log-update@6.1.0:
resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==}
engines: {node: '>=18'}
longest@2.0.1:
resolution: {integrity: sha512-Ajzxb8CM6WAnFjgiloPsI3bF+WCxcvhdIG3KNA2KN962+tdBsHcuQ4k4qX/EcS/2CRkcc0iAkR956Nib6aXU/Q==}
engines: {node: '>=0.10.0'}
lru-cache@5.1.1:
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
magic-string@0.30.21:
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
meow@13.2.0:
resolution: {integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==}
engines: {node: '>=18'}
merge@2.1.1:
resolution: {integrity: sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w==}
micromatch@4.0.8:
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
engines: {node: '>=8.6'}
mimic-fn@2.1.0:
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
engines: {node: '>=6'}
mimic-function@5.0.1:
resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==}
engines: {node: '>=18'}
minimatch@3.1.5:
resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==}
minimist@1.2.7:
resolution: {integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==}
minimist@1.2.8:
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
mute-stream@0.0.8:
resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==}
nanoid@3.3.11:
resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
node-releases@2.0.37:
resolution: {integrity: sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==}
normalize-path@3.0.0:
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
engines: {node: '>=0.10.0'}
once@1.4.0:
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
onetime@5.1.2:
resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
engines: {node: '>=6'}
onetime@7.0.0:
resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==}
engines: {node: '>=18'}
ora@5.4.1:
resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==}
engines: {node: '>=10'}
os-tmpdir@1.0.2:
resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==}
engines: {node: '>=0.10.0'}
parent-module@1.0.1:
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
engines: {node: '>=6'}
parse-json@5.2.0:
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
engines: {node: '>=8'}
parse-passwd@1.0.0:
resolution: {integrity: sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==}
engines: {node: '>=0.10.0'}
path-is-absolute@1.0.1:
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
engines: {node: '>=0.10.0'}
pathe@2.0.3:
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
picomatch@2.3.2:
resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==}
engines: {node: '>=8.6'}
picomatch@4.0.4:
resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==}
engines: {node: '>=12'}
postcss@8.5.10:
resolution: {integrity: sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==}
engines: {node: ^10 || ^12 || >=14}
prettier@3.8.3:
resolution: {integrity: sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==}
engines: {node: '>=14'}
hasBin: true
react-dom@19.2.5:
resolution: {integrity: sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag==}
peerDependencies:
react: ^19.2.5
react-i18next@17.0.3:
resolution: {integrity: sha512-x4xjvUNZ56T+zfXWNedNnCET9Xq1IBYWX7IsWo5cCQ/RT+Rm7GWqt0h9PShFi4IhyMnsdiu1C6Jc4DE+/S3PFQ==}
peerDependencies:
i18next: '>= 26.0.1'
react: '>= 16.8.0'
react-dom: '*'
react-native: '*'
typescript: ^5 || ^6
peerDependenciesMeta:
react-dom:
optional: true
react-native:
optional: true
typescript:
optional: true
react@19.2.5:
resolution: {integrity: sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA==}
engines: {node: '>=0.10.0'}
readable-stream@3.6.2:
resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
engines: {node: '>= 6'}
readdirp@3.6.0:
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
engines: {node: '>=8.10.0'}
require-directory@2.1.1:
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
engines: {node: '>=0.10.0'}
require-from-string@2.0.2:
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
engines: {node: '>=0.10.0'}
resolve-dir@1.0.1:
resolution: {integrity: sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==}
engines: {node: '>=0.10.0'}
resolve-from@4.0.0:
resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
engines: {node: '>=4'}
resolve-from@5.0.0:
resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==}
engines: {node: '>=8'}
resolve-pkg-maps@1.0.0:
resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
restore-cursor@3.1.0:
resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==}
engines: {node: '>=8'}
restore-cursor@5.1.0:
resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==}
engines: {node: '>=18'}
rfdc@1.4.1:
resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==}
rolldown@1.0.0-rc.15:
resolution: {integrity: sha512-Ff31guA5zT6WjnGp0SXw76X6hzGRk/OQq2hE+1lcDe+lJdHSgnSX6nK3erbONHyCbpSj9a9E+uX/OvytZoWp2g==}
engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true
run-async@2.4.1:
resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==}
engines: {node: '>=0.12.0'}
rxjs@7.8.2:
resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==}
safe-buffer@5.2.1:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
safer-buffer@2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
scheduler@0.27.0:
resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
semver@6.3.1:
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
hasBin: true
semver@7.7.4:
resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==}
engines: {node: '>=10'}
hasBin: true
seroval-plugins@1.5.2:
resolution: {integrity: sha512-qpY0Cl+fKYFn4GOf3cMiq6l72CpuVaawb6ILjubOQ+diJ54LfOWaSSPsaswN8DRPIPW4Yq+tE1k5aKd7ILyaFg==}
engines: {node: '>=10'}
peerDependencies:
seroval: ^1.0
seroval@1.5.2:
resolution: {integrity: sha512-xcRN39BdsnO9Tf+VzsE7b3JyTJASItIV1FVFewJKCFcW4s4haIKS3e6vj8PGB9qBwC7tnuOywQMdv5N4qkzi7Q==}
engines: {node: '>=10'}
signal-exit@3.0.7:
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
signal-exit@4.1.0:
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
engines: {node: '>=14'}
slice-ansi@7.1.2:
resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==}
engines: {node: '>=18'}
slice-ansi@8.0.0:
resolution: {integrity: sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==}
engines: {node: '>=20'}
source-map-js@1.2.1:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'}
string-argv@0.3.2:
resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==}
engines: {node: '>=0.6.19'}
string-width@4.2.3:
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
engines: {node: '>=8'}
string-width@7.2.0:
resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==}
engines: {node: '>=18'}
string-width@8.2.0:
resolution: {integrity: sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw==}
engines: {node: '>=20'}
string_decoder@1.3.0:
resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
strip-ansi@6.0.1:
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
engines: {node: '>=8'}
strip-ansi@7.2.0:
resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==}
engines: {node: '>=12'}
strip-bom@4.0.0:
resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==}
engines: {node: '>=8'}
strip-json-comments@3.1.1:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'}
supports-color@5.5.0:
resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
engines: {node: '>=4'}
supports-color@7.2.0:
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
engines: {node: '>=8'}
tailwindcss@4.2.2:
resolution: {integrity: sha512-KWBIxs1Xb6NoLdMVqhbhgwZf2PGBpPEiwOqgI4pFIYbNTfBXiKYyWoTsXgBQ9WFg/OlhnvHaY+AEpW7wSmFo2Q==}
tapable@2.3.2:
resolution: {integrity: sha512-1MOpMXuhGzGL5TTCZFItxCc0AARf1EZFQkGqMm7ERKj8+Hgr5oLvJOVFcC+lRmR8hCe2S3jC4T5D7Vg/d7/fhA==}
engines: {node: '>=6'}
through@2.3.8:
resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==}
tinyexec@1.1.1:
resolution: {integrity: sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==}
engines: {node: '>=18'}
tinyglobby@0.2.16:
resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==}
engines: {node: '>=12.0.0'}
tmp@0.0.33:
resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==}
engines: {node: '>=0.6.0'}
to-regex-range@5.0.1:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
engines: {node: '>=8.0'}
tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
tsx@4.21.0:
resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==}
engines: {node: '>=18.0.0'}
hasBin: true
type-fest@0.21.3:
resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==}
engines: {node: '>=10'}
typescript@6.0.2:
resolution: {integrity: sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ==}
engines: {node: '>=14.17'}
hasBin: true
undici-types@7.16.0:
resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==}
universalify@2.0.1:
resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
engines: {node: '>= 10.0.0'}
unplugin@2.3.11:
resolution: {integrity: sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==}
engines: {node: '>=18.12.0'}
update-browserslist-db@1.2.3:
resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==}
hasBin: true
peerDependencies:
browserslist: '>= 4.21.0'
use-sync-external-store@1.6.0:
resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==}
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
vite@8.0.8:
resolution: {integrity: sha512-dbU7/iLVa8KZALJyLOBOQ88nOXtNG8vxKuOT4I2mD+Ya70KPceF4IAmDsmU0h1Qsn5bPrvsY9HJstCRh3hG6Uw==}
engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true
peerDependencies:
'@types/node': ^20.19.0 || >=22.12.0
'@vitejs/devtools': ^0.1.0
esbuild: ^0.27.0 || ^0.28.0
jiti: '>=1.21.0'
less: ^4.0.0
sass: ^1.70.0
sass-embedded: ^1.70.0
stylus: '>=0.54.8'
sugarss: ^5.0.0
terser: ^5.16.0
tsx: ^4.8.1
yaml: ^2.4.2
peerDependenciesMeta:
'@types/node':
optional: true
'@vitejs/devtools':
optional: true
esbuild:
optional: true
jiti:
optional: true
less:
optional: true
sass:
optional: true
sass-embedded:
optional: true
stylus:
optional: true
sugarss:
optional: true
terser:
optional: true
tsx:
optional: true
yaml:
optional: true
void-elements@3.1.0:
resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==}
engines: {node: '>=0.10.0'}
wcwidth@1.0.1:
resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==}
webpack-virtual-modules@0.6.2:
resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==}
which@1.3.1:
resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==}
hasBin: true
word-wrap@1.2.5:
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
engines: {node: '>=0.10.0'}
wrap-ansi@7.0.0:
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
engines: {node: '>=10'}
wrap-ansi@9.0.2:
resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==}
engines: {node: '>=18'}
wrappy@1.0.2:
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
y18n@5.0.8:
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
engines: {node: '>=10'}
yallist@3.1.1:
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
yaml@2.8.3:
resolution: {integrity: sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==}
engines: {node: '>= 14.6'}
hasBin: true
yargs-parser@21.1.1:
resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
engines: {node: '>=12'}
yargs@17.7.2:
resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
engines: {node: '>=12'}
zod@3.25.76:
resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==}
zustand@5.0.12:
resolution: {integrity: sha512-i77ae3aZq4dhMlRhJVCYgMLKuSiZAaUPAct2AksxQ+gOtimhGMdXljRT21P5BNpeT4kXlLIckvkPM029OljD7g==}
engines: {node: '>=12.20.0'}
peerDependencies:
'@types/react': '>=18.0.0'
immer: '>=9.0.6'
react: '>=18.0.0'
use-sync-external-store: '>=1.2.0'
peerDependenciesMeta:
'@types/react':
optional: true
immer:
optional: true
react:
optional: true
use-sync-external-store:
optional: true
snapshots:
'@babel/code-frame@7.29.0':
dependencies:
'@babel/helper-validator-identifier': 7.28.5
js-tokens: 4.0.0
picocolors: 1.1.1
'@babel/compat-data@7.29.0': {}
'@babel/core@7.29.0':
dependencies:
'@babel/code-frame': 7.29.0
'@babel/generator': 7.29.1
'@babel/helper-compilation-targets': 7.28.6
'@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0)
'@babel/helpers': 7.29.2
'@babel/parser': 7.29.2
'@babel/template': 7.28.6
'@babel/traverse': 7.29.0
'@babel/types': 7.29.0
'@jridgewell/remapping': 2.3.5
convert-source-map: 2.0.0
debug: 4.4.3
gensync: 1.0.0-beta.2
json5: 2.2.3
semver: 6.3.1
transitivePeerDependencies:
- supports-color
'@babel/generator@7.29.1':
dependencies:
'@babel/parser': 7.29.2
'@babel/types': 7.29.0
'@jridgewell/gen-mapping': 0.3.13
'@jridgewell/trace-mapping': 0.3.31
jsesc: 3.1.0
'@babel/helper-compilation-targets@7.28.6':
dependencies:
'@babel/compat-data': 7.29.0
'@babel/helper-validator-option': 7.27.1
browserslist: 4.28.2
lru-cache: 5.1.1
semver: 6.3.1
'@babel/helper-globals@7.28.0': {}
'@babel/helper-module-imports@7.28.6':
dependencies:
'@babel/traverse': 7.29.0
'@babel/types': 7.29.0
transitivePeerDependencies:
- supports-color
'@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)':
dependencies:
'@babel/core': 7.29.0
'@babel/helper-module-imports': 7.28.6
'@babel/helper-validator-identifier': 7.28.5
'@babel/traverse': 7.29.0
transitivePeerDependencies:
- supports-color
'@babel/helper-plugin-utils@7.28.6': {}
'@babel/helper-string-parser@7.27.1': {}
'@babel/helper-validator-identifier@7.28.5': {}
'@babel/helper-validator-option@7.27.1': {}
'@babel/helpers@7.29.2':
dependencies:
'@babel/template': 7.28.6
'@babel/types': 7.29.0
'@babel/parser@7.29.2':
dependencies:
'@babel/types': 7.29.0
'@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0)':
dependencies:
'@babel/core': 7.29.0
'@babel/helper-plugin-utils': 7.28.6
'@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.29.0)':
dependencies:
'@babel/core': 7.29.0
'@babel/helper-plugin-utils': 7.28.6
'@babel/runtime@7.29.2': {}
'@babel/template@7.28.6':
dependencies:
'@babel/code-frame': 7.29.0
'@babel/parser': 7.29.2
'@babel/types': 7.29.0
'@babel/traverse@7.29.0':
dependencies:
'@babel/code-frame': 7.29.0
'@babel/generator': 7.29.1
'@babel/helper-globals': 7.28.0
'@babel/parser': 7.29.2
'@babel/template': 7.28.6
'@babel/types': 7.29.0
debug: 4.4.3
transitivePeerDependencies:
- supports-color
'@babel/types@7.29.0':
dependencies:
'@babel/helper-string-parser': 7.27.1
'@babel/helper-validator-identifier': 7.28.5
'@biomejs/biome@2.4.12':
optionalDependencies:
'@biomejs/cli-darwin-arm64': 2.4.12
'@biomejs/cli-darwin-x64': 2.4.12
'@biomejs/cli-linux-arm64': 2.4.12
'@biomejs/cli-linux-arm64-musl': 2.4.12
'@biomejs/cli-linux-x64': 2.4.12
'@biomejs/cli-linux-x64-musl': 2.4.12
'@biomejs/cli-win32-arm64': 2.4.12
'@biomejs/cli-win32-x64': 2.4.12
'@biomejs/cli-darwin-arm64@2.4.12':
optional: true
'@biomejs/cli-darwin-x64@2.4.12':
optional: true
'@biomejs/cli-linux-arm64-musl@2.4.12':
optional: true
'@biomejs/cli-linux-arm64@2.4.12':
optional: true
'@biomejs/cli-linux-x64-musl@2.4.12':
optional: true
'@biomejs/cli-linux-x64@2.4.12':
optional: true
'@biomejs/cli-win32-arm64@2.4.12':
optional: true
'@biomejs/cli-win32-x64@2.4.12':
optional: true
'@commitlint/cli@20.5.0(@types/node@24.12.2)(conventional-commits-parser@6.4.0)(typescript@6.0.2)':
dependencies:
'@commitlint/format': 20.5.0
'@commitlint/lint': 20.5.0
'@commitlint/load': 20.5.0(@types/node@24.12.2)(typescript@6.0.2)
'@commitlint/read': 20.5.0(conventional-commits-parser@6.4.0)
'@commitlint/types': 20.5.0
tinyexec: 1.1.1
yargs: 17.7.2
transitivePeerDependencies:
- '@types/node'
- conventional-commits-filter
- conventional-commits-parser
- typescript
'@commitlint/config-conventional@20.5.0':
dependencies:
'@commitlint/types': 20.5.0
conventional-changelog-conventionalcommits: 9.3.1
'@commitlint/config-validator@20.5.0':
dependencies:
'@commitlint/types': 20.5.0
ajv: 8.18.0
'@commitlint/ensure@20.5.0':
dependencies:
'@commitlint/types': 20.5.0
lodash.camelcase: 4.3.0
lodash.kebabcase: 4.1.1
lodash.snakecase: 4.1.1
lodash.startcase: 4.4.0
lodash.upperfirst: 4.3.1
'@commitlint/execute-rule@20.0.0': {}
'@commitlint/format@20.5.0':
dependencies:
'@commitlint/types': 20.5.0
picocolors: 1.1.1
'@commitlint/is-ignored@20.5.0':
dependencies:
'@commitlint/types': 20.5.0
semver: 7.7.4
'@commitlint/lint@20.5.0':
dependencies:
'@commitlint/is-ignored': 20.5.0
'@commitlint/parse': 20.5.0
'@commitlint/rules': 20.5.0
'@commitlint/types': 20.5.0
'@commitlint/load@20.5.0(@types/node@24.12.2)(typescript@6.0.2)':
dependencies:
'@commitlint/config-validator': 20.5.0
'@commitlint/execute-rule': 20.0.0
'@commitlint/resolve-extends': 20.5.0
'@commitlint/types': 20.5.0
cosmiconfig: 9.0.1(typescript@6.0.2)
cosmiconfig-typescript-loader: 6.3.0(@types/node@24.12.2)(cosmiconfig@9.0.1(typescript@6.0.2))(typescript@6.0.2)
is-plain-obj: 4.1.0
lodash.mergewith: 4.6.2
picocolors: 1.1.1
transitivePeerDependencies:
- '@types/node'
- typescript
'@commitlint/message@20.4.3': {}
'@commitlint/parse@20.5.0':
dependencies:
'@commitlint/types': 20.5.0
conventional-changelog-angular: 8.3.1
conventional-commits-parser: 6.4.0
'@commitlint/read@20.5.0(conventional-commits-parser@6.4.0)':
dependencies:
'@commitlint/top-level': 20.4.3
'@commitlint/types': 20.5.0
git-raw-commits: 5.0.1(conventional-commits-parser@6.4.0)
minimist: 1.2.8
tinyexec: 1.1.1
transitivePeerDependencies:
- conventional-commits-filter
- conventional-commits-parser
'@commitlint/resolve-extends@20.5.0':
dependencies:
'@commitlint/config-validator': 20.5.0
'@commitlint/types': 20.5.0
global-directory: 4.0.1
import-meta-resolve: 4.2.0
lodash.mergewith: 4.6.2
resolve-from: 5.0.0
'@commitlint/rules@20.5.0':
dependencies:
'@commitlint/ensure': 20.5.0
'@commitlint/message': 20.4.3
'@commitlint/to-lines': 20.0.0
'@commitlint/types': 20.5.0
'@commitlint/to-lines@20.0.0': {}
'@commitlint/top-level@20.4.3':
dependencies:
escalade: 3.2.0
'@commitlint/types@20.5.0':
dependencies:
conventional-commits-parser: 6.4.0
picocolors: 1.1.1
'@conventional-changelog/git-client@2.7.0(conventional-commits-parser@6.4.0)':
dependencies:
'@simple-libs/child-process-utils': 1.0.2
'@simple-libs/stream-utils': 1.2.0
semver: 7.7.4
optionalDependencies:
conventional-commits-parser: 6.4.0
'@emnapi/core@1.9.2':
dependencies:
'@emnapi/wasi-threads': 1.2.1
tslib: 2.8.1
optional: true
'@emnapi/runtime@1.9.2':
dependencies:
tslib: 2.8.1
optional: true
'@emnapi/wasi-threads@1.2.1':
dependencies:
tslib: 2.8.1
optional: true
'@esbuild/aix-ppc64@0.27.7':
optional: true
'@esbuild/android-arm64@0.27.7':
optional: true
'@esbuild/android-arm@0.27.7':
optional: true
'@esbuild/android-x64@0.27.7':
optional: true
'@esbuild/darwin-arm64@0.27.7':
optional: true
'@esbuild/darwin-x64@0.27.7':
optional: true
'@esbuild/freebsd-arm64@0.27.7':
optional: true
'@esbuild/freebsd-x64@0.27.7':
optional: true
'@esbuild/linux-arm64@0.27.7':
optional: true
'@esbuild/linux-arm@0.27.7':
optional: true
'@esbuild/linux-ia32@0.27.7':
optional: true
'@esbuild/linux-loong64@0.27.7':
optional: true
'@esbuild/linux-mips64el@0.27.7':
optional: true
'@esbuild/linux-ppc64@0.27.7':
optional: true
'@esbuild/linux-riscv64@0.27.7':
optional: true
'@esbuild/linux-s390x@0.27.7':
optional: true
'@esbuild/linux-x64@0.27.7':
optional: true
'@esbuild/netbsd-arm64@0.27.7':
optional: true
'@esbuild/netbsd-x64@0.27.7':
optional: true
'@esbuild/openbsd-arm64@0.27.7':
optional: true
'@esbuild/openbsd-x64@0.27.7':
optional: true
'@esbuild/openharmony-arm64@0.27.7':
optional: true
'@esbuild/sunos-x64@0.27.7':
optional: true
'@esbuild/win32-arm64@0.27.7':
optional: true
'@esbuild/win32-ia32@0.27.7':
optional: true
'@esbuild/win32-x64@0.27.7':
optional: true
'@jridgewell/gen-mapping@0.3.13':
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
'@jridgewell/trace-mapping': 0.3.31
'@jridgewell/remapping@2.3.5':
dependencies:
'@jridgewell/gen-mapping': 0.3.13
'@jridgewell/trace-mapping': 0.3.31
'@jridgewell/resolve-uri@3.1.2': {}
'@jridgewell/sourcemap-codec@1.5.5': {}
'@jridgewell/trace-mapping@0.3.31':
dependencies:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.5
'@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)':
dependencies:
'@emnapi/core': 1.9.2
'@emnapi/runtime': 1.9.2
'@tybys/wasm-util': 0.10.1
optional: true
'@oxc-project/types@0.124.0': {}
'@rolldown/binding-android-arm64@1.0.0-rc.15':
optional: true
'@rolldown/binding-darwin-arm64@1.0.0-rc.15':
optional: true
'@rolldown/binding-darwin-x64@1.0.0-rc.15':
optional: true
'@rolldown/binding-freebsd-x64@1.0.0-rc.15':
optional: true
'@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.15':
optional: true
'@rolldown/binding-linux-arm64-gnu@1.0.0-rc.15':
optional: true
'@rolldown/binding-linux-arm64-musl@1.0.0-rc.15':
optional: true
'@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.15':
optional: true
'@rolldown/binding-linux-s390x-gnu@1.0.0-rc.15':
optional: true
'@rolldown/binding-linux-x64-gnu@1.0.0-rc.15':
optional: true
'@rolldown/binding-linux-x64-musl@1.0.0-rc.15':
optional: true
'@rolldown/binding-openharmony-arm64@1.0.0-rc.15':
optional: true
'@rolldown/binding-wasm32-wasi@1.0.0-rc.15':
dependencies:
'@emnapi/core': 1.9.2
'@emnapi/runtime': 1.9.2
'@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)
optional: true
'@rolldown/binding-win32-arm64-msvc@1.0.0-rc.15':
optional: true
'@rolldown/binding-win32-x64-msvc@1.0.0-rc.15':
optional: true
'@rolldown/plugin-babel@0.2.3(@babel/core@7.29.0)(@babel/runtime@7.29.2)(rolldown@1.0.0-rc.15)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))':
dependencies:
'@babel/core': 7.29.0
picomatch: 4.0.4
rolldown: 1.0.0-rc.15
optionalDependencies:
'@babel/runtime': 7.29.2
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)
'@rolldown/pluginutils@1.0.0-rc.15': {}
'@rolldown/pluginutils@1.0.0-rc.7': {}
'@simple-libs/child-process-utils@1.0.2':
dependencies:
'@simple-libs/stream-utils': 1.2.0
'@simple-libs/stream-utils@1.2.0': {}
'@tailwindcss/node@4.2.2':
dependencies:
'@jridgewell/remapping': 2.3.5
enhanced-resolve: 5.20.1
jiti: 2.6.1
lightningcss: 1.32.0
magic-string: 0.30.21
source-map-js: 1.2.1
tailwindcss: 4.2.2
'@tailwindcss/oxide-android-arm64@4.2.2':
optional: true
'@tailwindcss/oxide-darwin-arm64@4.2.2':
optional: true
'@tailwindcss/oxide-darwin-x64@4.2.2':
optional: true
'@tailwindcss/oxide-freebsd-x64@4.2.2':
optional: true
'@tailwindcss/oxide-linux-arm-gnueabihf@4.2.2':
optional: true
'@tailwindcss/oxide-linux-arm64-gnu@4.2.2':
optional: true
'@tailwindcss/oxide-linux-arm64-musl@4.2.2':
optional: true
'@tailwindcss/oxide-linux-x64-gnu@4.2.2':
optional: true
'@tailwindcss/oxide-linux-x64-musl@4.2.2':
optional: true
'@tailwindcss/oxide-wasm32-wasi@4.2.2':
optional: true
'@tailwindcss/oxide-win32-arm64-msvc@4.2.2':
optional: true
'@tailwindcss/oxide-win32-x64-msvc@4.2.2':
optional: true
'@tailwindcss/oxide@4.2.2':
optionalDependencies:
'@tailwindcss/oxide-android-arm64': 4.2.2
'@tailwindcss/oxide-darwin-arm64': 4.2.2
'@tailwindcss/oxide-darwin-x64': 4.2.2
'@tailwindcss/oxide-freebsd-x64': 4.2.2
'@tailwindcss/oxide-linux-arm-gnueabihf': 4.2.2
'@tailwindcss/oxide-linux-arm64-gnu': 4.2.2
'@tailwindcss/oxide-linux-arm64-musl': 4.2.2
'@tailwindcss/oxide-linux-x64-gnu': 4.2.2
'@tailwindcss/oxide-linux-x64-musl': 4.2.2
'@tailwindcss/oxide-wasm32-wasi': 4.2.2
'@tailwindcss/oxide-win32-arm64-msvc': 4.2.2
'@tailwindcss/oxide-win32-x64-msvc': 4.2.2
'@tailwindcss/vite@4.2.2(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))':
dependencies:
'@tailwindcss/node': 4.2.2
'@tailwindcss/oxide': 4.2.2
tailwindcss: 4.2.2
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)
'@tanstack/history@1.161.6': {}
'@tanstack/query-core@5.99.0': {}
'@tanstack/query-devtools@5.99.0': {}
'@tanstack/react-query-devtools@5.99.0(@tanstack/react-query@5.99.0(react@19.2.5))(react@19.2.5)':
dependencies:
'@tanstack/query-devtools': 5.99.0
'@tanstack/react-query': 5.99.0(react@19.2.5)
react: 19.2.5
'@tanstack/react-query@5.99.0(react@19.2.5)':
dependencies:
'@tanstack/query-core': 5.99.0
react: 19.2.5
'@tanstack/react-router@1.168.22(react-dom@19.2.5(react@19.2.5))(react@19.2.5)':
dependencies:
'@tanstack/history': 1.161.6
'@tanstack/react-store': 0.9.3(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
'@tanstack/router-core': 1.168.15
isbot: 5.1.39
react: 19.2.5
react-dom: 19.2.5(react@19.2.5)
'@tanstack/react-store@0.9.3(react-dom@19.2.5(react@19.2.5))(react@19.2.5)':
dependencies:
'@tanstack/store': 0.9.3
react: 19.2.5
react-dom: 19.2.5(react@19.2.5)
use-sync-external-store: 1.6.0(react@19.2.5)
'@tanstack/router-cli@1.166.33':
dependencies:
'@tanstack/router-generator': 1.166.32
chokidar: 3.6.0
yargs: 17.7.2
transitivePeerDependencies:
- supports-color
'@tanstack/router-core@1.168.15':
dependencies:
'@tanstack/history': 1.161.6
cookie-es: 3.1.1
seroval: 1.5.2
seroval-plugins: 1.5.2(seroval@1.5.2)
'@tanstack/router-generator@1.166.32':
dependencies:
'@babel/types': 7.29.0
'@tanstack/router-core': 1.168.15
'@tanstack/router-utils': 1.161.6
'@tanstack/virtual-file-routes': 1.161.7
magic-string: 0.30.21
prettier: 3.8.3
tsx: 4.21.0
zod: 3.25.76
transitivePeerDependencies:
- supports-color
'@tanstack/router-plugin@1.167.22(@tanstack/react-router@1.168.22(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))':
dependencies:
'@babel/core': 7.29.0
'@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0)
'@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.0)
'@babel/template': 7.28.6
'@babel/traverse': 7.29.0
'@babel/types': 7.29.0
'@tanstack/router-core': 1.168.15
'@tanstack/router-generator': 1.166.32
'@tanstack/router-utils': 1.161.6
'@tanstack/virtual-file-routes': 1.161.7
chokidar: 3.6.0
unplugin: 2.3.11
zod: 3.25.76
optionalDependencies:
'@tanstack/react-router': 1.168.22(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)
transitivePeerDependencies:
- supports-color
'@tanstack/router-utils@1.161.6':
dependencies:
'@babel/core': 7.29.0
'@babel/generator': 7.29.1
'@babel/parser': 7.29.2
'@babel/types': 7.29.0
ansis: 4.2.0
babel-dead-code-elimination: 1.0.12
diff: 8.0.4
pathe: 2.0.3
tinyglobby: 0.2.16
transitivePeerDependencies:
- supports-color
'@tanstack/store@0.9.3': {}
'@tanstack/virtual-file-routes@1.161.7': {}
'@tybys/wasm-util@0.10.1':
dependencies:
tslib: 2.8.1
optional: true
'@types/babel__core@7.20.5':
dependencies:
'@babel/parser': 7.29.2
'@babel/types': 7.29.0
'@types/babel__generator': 7.27.0
'@types/babel__template': 7.4.4
'@types/babel__traverse': 7.28.0
'@types/babel__generator@7.27.0':
dependencies:
'@babel/types': 7.29.0
'@types/babel__template@7.4.4':
dependencies:
'@babel/parser': 7.29.2
'@babel/types': 7.29.0
'@types/babel__traverse@7.28.0':
dependencies:
'@babel/types': 7.29.0
'@types/node@24.12.2':
dependencies:
undici-types: 7.16.0
'@types/react-dom@19.2.3(@types/react@19.2.14)':
dependencies:
'@types/react': 19.2.14
'@types/react@19.2.14':
dependencies:
csstype: 3.2.3
'@vitejs/plugin-react@6.0.1(@rolldown/plugin-babel@0.2.3(@babel/core@7.29.0)(@babel/runtime@7.29.2)(rolldown@1.0.0-rc.15)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)))(babel-plugin-react-compiler@1.0.0)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))':
dependencies:
'@rolldown/pluginutils': 1.0.0-rc.7
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)
optionalDependencies:
'@rolldown/plugin-babel': 0.2.3(@babel/core@7.29.0)(@babel/runtime@7.29.2)(rolldown@1.0.0-rc.15)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))
babel-plugin-react-compiler: 1.0.0
acorn@8.16.0: {}
ajv@8.18.0:
dependencies:
fast-deep-equal: 3.1.3
fast-uri: 3.1.0
json-schema-traverse: 1.0.0
require-from-string: 2.0.2
ansi-escapes@4.3.2:
dependencies:
type-fest: 0.21.3
ansi-escapes@7.3.0:
dependencies:
environment: 1.1.0
ansi-regex@5.0.1: {}
ansi-regex@6.2.2: {}
ansi-styles@3.2.1:
dependencies:
color-convert: 1.9.3
ansi-styles@4.3.0:
dependencies:
color-convert: 2.0.1
ansi-styles@6.2.3: {}
ansis@4.2.0: {}
anymatch@3.1.3:
dependencies:
normalize-path: 3.0.0
picomatch: 2.3.2
argparse@2.0.1: {}
array-ify@1.0.0: {}
at-least-node@1.0.0: {}
babel-dead-code-elimination@1.0.12:
dependencies:
'@babel/core': 7.29.0
'@babel/parser': 7.29.2
'@babel/traverse': 7.29.0
'@babel/types': 7.29.0
transitivePeerDependencies:
- supports-color
babel-plugin-react-compiler@1.0.0:
dependencies:
'@babel/types': 7.29.0
balanced-match@1.0.2: {}
base64-js@1.5.1: {}
baseline-browser-mapping@2.10.19: {}
binary-extensions@2.3.0: {}
bl@4.1.0:
dependencies:
buffer: 5.7.1
inherits: 2.0.4
readable-stream: 3.6.2
brace-expansion@1.1.14:
dependencies:
balanced-match: 1.0.2
concat-map: 0.0.1
braces@3.0.3:
dependencies:
fill-range: 7.1.1
browserslist@4.28.2:
dependencies:
baseline-browser-mapping: 2.10.19
caniuse-lite: 1.0.30001788
electron-to-chromium: 1.5.338
node-releases: 2.0.37
update-browserslist-db: 1.2.3(browserslist@4.28.2)
buffer@5.7.1:
dependencies:
base64-js: 1.5.1
ieee754: 1.2.1
cachedir@2.3.0: {}
callsites@3.1.0: {}
caniuse-lite@1.0.30001788: {}
chalk@2.4.2:
dependencies:
ansi-styles: 3.2.1
escape-string-regexp: 1.0.5
supports-color: 5.5.0
chalk@4.1.2:
dependencies:
ansi-styles: 4.3.0
supports-color: 7.2.0
chardet@0.7.0: {}
chokidar@3.6.0:
dependencies:
anymatch: 3.1.3
braces: 3.0.3
glob-parent: 5.1.2
is-binary-path: 2.1.0
is-glob: 4.0.3
normalize-path: 3.0.0
readdirp: 3.6.0
optionalDependencies:
fsevents: 2.3.3
cli-cursor@3.1.0:
dependencies:
restore-cursor: 3.1.0
cli-cursor@5.0.0:
dependencies:
restore-cursor: 5.1.0
cli-spinners@2.9.2: {}
cli-truncate@5.2.0:
dependencies:
slice-ansi: 8.0.0
string-width: 8.2.0
cli-width@3.0.0: {}
cliui@8.0.1:
dependencies:
string-width: 4.2.3
strip-ansi: 6.0.1
wrap-ansi: 7.0.0
clone@1.0.4: {}
color-convert@1.9.3:
dependencies:
color-name: 1.1.3
color-convert@2.0.1:
dependencies:
color-name: 1.1.4
color-name@1.1.3: {}
color-name@1.1.4: {}
colorette@2.0.20: {}
commander@14.0.3: {}
commitizen@4.3.1(@types/node@24.12.2)(typescript@6.0.2):
dependencies:
cachedir: 2.3.0
cz-conventional-changelog: 3.3.0(@types/node@24.12.2)(typescript@6.0.2)
dedent: 0.7.0
detect-indent: 6.1.0
find-node-modules: 2.1.3
find-root: 1.1.0
fs-extra: 9.1.0
glob: 7.2.3
inquirer: 8.2.5
is-utf8: 0.2.1
lodash: 4.17.21
minimist: 1.2.7
strip-bom: 4.0.0
strip-json-comments: 3.1.1
transitivePeerDependencies:
- '@types/node'
- typescript
compare-func@2.0.0:
dependencies:
array-ify: 1.0.0
dot-prop: 5.3.0
concat-map@0.0.1: {}
conventional-changelog-angular@8.3.1:
dependencies:
compare-func: 2.0.0
conventional-changelog-conventionalcommits@9.3.1:
dependencies:
compare-func: 2.0.0
conventional-commit-types@3.0.0: {}
conventional-commits-parser@6.4.0:
dependencies:
'@simple-libs/stream-utils': 1.2.0
meow: 13.2.0
convert-source-map@2.0.0: {}
cookie-es@3.1.1: {}
cosmiconfig-typescript-loader@6.3.0(@types/node@24.12.2)(cosmiconfig@9.0.1(typescript@6.0.2))(typescript@6.0.2):
dependencies:
'@types/node': 24.12.2
cosmiconfig: 9.0.1(typescript@6.0.2)
jiti: 2.6.1
typescript: 6.0.2
cosmiconfig@9.0.1(typescript@6.0.2):
dependencies:
env-paths: 2.2.1
import-fresh: 3.3.1
js-yaml: 4.1.1
parse-json: 5.2.0
optionalDependencies:
typescript: 6.0.2
csstype@3.2.3: {}
cz-conventional-changelog@3.3.0(@types/node@24.12.2)(typescript@6.0.2):
dependencies:
chalk: 2.4.2
commitizen: 4.3.1(@types/node@24.12.2)(typescript@6.0.2)
conventional-commit-types: 3.0.0
lodash.map: 4.6.0
longest: 2.0.1
word-wrap: 1.2.5
optionalDependencies:
'@commitlint/load': 20.5.0(@types/node@24.12.2)(typescript@6.0.2)
transitivePeerDependencies:
- '@types/node'
- typescript
debug@4.4.3:
dependencies:
ms: 2.1.3
dedent@0.7.0: {}
defaults@1.0.4:
dependencies:
clone: 1.0.4
detect-file@1.0.0: {}
detect-indent@6.1.0: {}
detect-libc@2.1.2: {}
diff@8.0.4: {}
dot-prop@5.3.0:
dependencies:
is-obj: 2.0.0
electron-to-chromium@1.5.338: {}
emoji-regex@10.6.0: {}
emoji-regex@8.0.0: {}
enhanced-resolve@5.20.1:
dependencies:
graceful-fs: 4.2.11
tapable: 2.3.2
env-paths@2.2.1: {}
environment@1.1.0: {}
error-ex@1.3.4:
dependencies:
is-arrayish: 0.2.1
esbuild@0.27.7:
optionalDependencies:
'@esbuild/aix-ppc64': 0.27.7
'@esbuild/android-arm': 0.27.7
'@esbuild/android-arm64': 0.27.7
'@esbuild/android-x64': 0.27.7
'@esbuild/darwin-arm64': 0.27.7
'@esbuild/darwin-x64': 0.27.7
'@esbuild/freebsd-arm64': 0.27.7
'@esbuild/freebsd-x64': 0.27.7
'@esbuild/linux-arm': 0.27.7
'@esbuild/linux-arm64': 0.27.7
'@esbuild/linux-ia32': 0.27.7
'@esbuild/linux-loong64': 0.27.7
'@esbuild/linux-mips64el': 0.27.7
'@esbuild/linux-ppc64': 0.27.7
'@esbuild/linux-riscv64': 0.27.7
'@esbuild/linux-s390x': 0.27.7
'@esbuild/linux-x64': 0.27.7
'@esbuild/netbsd-arm64': 0.27.7
'@esbuild/netbsd-x64': 0.27.7
'@esbuild/openbsd-arm64': 0.27.7
'@esbuild/openbsd-x64': 0.27.7
'@esbuild/openharmony-arm64': 0.27.7
'@esbuild/sunos-x64': 0.27.7
'@esbuild/win32-arm64': 0.27.7
'@esbuild/win32-ia32': 0.27.7
'@esbuild/win32-x64': 0.27.7
escalade@3.2.0: {}
escape-string-regexp@1.0.5: {}
eventemitter3@5.0.4: {}
expand-tilde@2.0.2:
dependencies:
homedir-polyfill: 1.0.3
external-editor@3.1.0:
dependencies:
chardet: 0.7.0
iconv-lite: 0.4.24
tmp: 0.0.33
fast-deep-equal@3.1.3: {}
fast-uri@3.1.0: {}
fdir@6.5.0(picomatch@4.0.4):
optionalDependencies:
picomatch: 4.0.4
figures@3.2.0:
dependencies:
escape-string-regexp: 1.0.5
fill-range@7.1.1:
dependencies:
to-regex-range: 5.0.1
find-node-modules@2.1.3:
dependencies:
findup-sync: 4.0.0
merge: 2.1.1
find-root@1.1.0: {}
findup-sync@4.0.0:
dependencies:
detect-file: 1.0.0
is-glob: 4.0.3
micromatch: 4.0.8
resolve-dir: 1.0.1
fs-extra@9.1.0:
dependencies:
at-least-node: 1.0.0
graceful-fs: 4.2.11
jsonfile: 6.2.0
universalify: 2.0.1
fs.realpath@1.0.0: {}
fsevents@2.3.3:
optional: true
gensync@1.0.0-beta.2: {}
get-caller-file@2.0.5: {}
get-east-asian-width@1.5.0: {}
get-tsconfig@4.14.0:
dependencies:
resolve-pkg-maps: 1.0.0
git-raw-commits@5.0.1(conventional-commits-parser@6.4.0):
dependencies:
'@conventional-changelog/git-client': 2.7.0(conventional-commits-parser@6.4.0)
meow: 13.2.0
transitivePeerDependencies:
- conventional-commits-filter
- conventional-commits-parser
glob-parent@5.1.2:
dependencies:
is-glob: 4.0.3
glob@7.2.3:
dependencies:
fs.realpath: 1.0.0
inflight: 1.0.6
inherits: 2.0.4
minimatch: 3.1.5
once: 1.4.0
path-is-absolute: 1.0.1
global-directory@4.0.1:
dependencies:
ini: 4.1.1
global-modules@1.0.0:
dependencies:
global-prefix: 1.0.2
is-windows: 1.0.2
resolve-dir: 1.0.1
global-prefix@1.0.2:
dependencies:
expand-tilde: 2.0.2
homedir-polyfill: 1.0.3
ini: 1.3.8
is-windows: 1.0.2
which: 1.3.1
graceful-fs@4.2.11: {}
has-flag@3.0.0: {}
has-flag@4.0.0: {}
homedir-polyfill@1.0.3:
dependencies:
parse-passwd: 1.0.0
html-parse-stringify@3.0.1:
dependencies:
void-elements: 3.1.0
husky@9.1.7: {}
i18next@26.0.5(typescript@6.0.2):
dependencies:
'@babel/runtime': 7.29.2
optionalDependencies:
typescript: 6.0.2
iconv-lite@0.4.24:
dependencies:
safer-buffer: 2.1.2
ieee754@1.2.1: {}
import-fresh@3.3.1:
dependencies:
parent-module: 1.0.1
resolve-from: 4.0.0
import-meta-resolve@4.2.0: {}
inflight@1.0.6:
dependencies:
once: 1.4.0
wrappy: 1.0.2
inherits@2.0.4: {}
ini@1.3.8: {}
ini@4.1.1: {}
inquirer@8.2.5:
dependencies:
ansi-escapes: 4.3.2
chalk: 4.1.2
cli-cursor: 3.1.0
cli-width: 3.0.0
external-editor: 3.1.0
figures: 3.2.0
lodash: 4.17.21
mute-stream: 0.0.8
ora: 5.4.1
run-async: 2.4.1
rxjs: 7.8.2
string-width: 4.2.3
strip-ansi: 6.0.1
through: 2.3.8
wrap-ansi: 7.0.0
is-arrayish@0.2.1: {}
is-binary-path@2.1.0:
dependencies:
binary-extensions: 2.3.0
is-extglob@2.1.1: {}
is-fullwidth-code-point@3.0.0: {}
is-fullwidth-code-point@5.1.0:
dependencies:
get-east-asian-width: 1.5.0
is-glob@4.0.3:
dependencies:
is-extglob: 2.1.1
is-interactive@1.0.0: {}
is-number@7.0.0: {}
is-obj@2.0.0: {}
is-plain-obj@4.1.0: {}
is-unicode-supported@0.1.0: {}
is-utf8@0.2.1: {}
is-windows@1.0.2: {}
isbot@5.1.39: {}
isexe@2.0.0: {}
jiti@2.6.1: {}
js-tokens@4.0.0: {}
js-yaml@4.1.1:
dependencies:
argparse: 2.0.1
jsesc@3.1.0: {}
json-parse-even-better-errors@2.3.1: {}
json-schema-traverse@1.0.0: {}
json5@2.2.3: {}
jsonfile@6.2.0:
dependencies:
universalify: 2.0.1
optionalDependencies:
graceful-fs: 4.2.11
ky@2.0.1: {}
lightningcss-android-arm64@1.32.0:
optional: true
lightningcss-darwin-arm64@1.32.0:
optional: true
lightningcss-darwin-x64@1.32.0:
optional: true
lightningcss-freebsd-x64@1.32.0:
optional: true
lightningcss-linux-arm-gnueabihf@1.32.0:
optional: true
lightningcss-linux-arm64-gnu@1.32.0:
optional: true
lightningcss-linux-arm64-musl@1.32.0:
optional: true
lightningcss-linux-x64-gnu@1.32.0:
optional: true
lightningcss-linux-x64-musl@1.32.0:
optional: true
lightningcss-win32-arm64-msvc@1.32.0:
optional: true
lightningcss-win32-x64-msvc@1.32.0:
optional: true
lightningcss@1.32.0:
dependencies:
detect-libc: 2.1.2
optionalDependencies:
lightningcss-android-arm64: 1.32.0
lightningcss-darwin-arm64: 1.32.0
lightningcss-darwin-x64: 1.32.0
lightningcss-freebsd-x64: 1.32.0
lightningcss-linux-arm-gnueabihf: 1.32.0
lightningcss-linux-arm64-gnu: 1.32.0
lightningcss-linux-arm64-musl: 1.32.0
lightningcss-linux-x64-gnu: 1.32.0
lightningcss-linux-x64-musl: 1.32.0
lightningcss-win32-arm64-msvc: 1.32.0
lightningcss-win32-x64-msvc: 1.32.0
lines-and-columns@1.2.4: {}
lint-staged@16.4.0:
dependencies:
commander: 14.0.3
listr2: 9.0.5
picomatch: 4.0.4
string-argv: 0.3.2
tinyexec: 1.1.1
yaml: 2.8.3
listr2@9.0.5:
dependencies:
cli-truncate: 5.2.0
colorette: 2.0.20
eventemitter3: 5.0.4
log-update: 6.1.0
rfdc: 1.4.1
wrap-ansi: 9.0.2
lodash.camelcase@4.3.0: {}
lodash.kebabcase@4.1.1: {}
lodash.map@4.6.0: {}
lodash.mergewith@4.6.2: {}
lodash.snakecase@4.1.1: {}
lodash.startcase@4.4.0: {}
lodash.upperfirst@4.3.1: {}
lodash@4.17.21: {}
log-symbols@4.1.0:
dependencies:
chalk: 4.1.2
is-unicode-supported: 0.1.0
log-update@6.1.0:
dependencies:
ansi-escapes: 7.3.0
cli-cursor: 5.0.0
slice-ansi: 7.1.2
strip-ansi: 7.2.0
wrap-ansi: 9.0.2
longest@2.0.1: {}
lru-cache@5.1.1:
dependencies:
yallist: 3.1.1
magic-string@0.30.21:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
meow@13.2.0: {}
merge@2.1.1: {}
micromatch@4.0.8:
dependencies:
braces: 3.0.3
picomatch: 2.3.2
mimic-fn@2.1.0: {}
mimic-function@5.0.1: {}
minimatch@3.1.5:
dependencies:
brace-expansion: 1.1.14
minimist@1.2.7: {}
minimist@1.2.8: {}
ms@2.1.3: {}
mute-stream@0.0.8: {}
nanoid@3.3.11: {}
node-releases@2.0.37: {}
normalize-path@3.0.0: {}
once@1.4.0:
dependencies:
wrappy: 1.0.2
onetime@5.1.2:
dependencies:
mimic-fn: 2.1.0
onetime@7.0.0:
dependencies:
mimic-function: 5.0.1
ora@5.4.1:
dependencies:
bl: 4.1.0
chalk: 4.1.2
cli-cursor: 3.1.0
cli-spinners: 2.9.2
is-interactive: 1.0.0
is-unicode-supported: 0.1.0
log-symbols: 4.1.0
strip-ansi: 6.0.1
wcwidth: 1.0.1
os-tmpdir@1.0.2: {}
parent-module@1.0.1:
dependencies:
callsites: 3.1.0
parse-json@5.2.0:
dependencies:
'@babel/code-frame': 7.29.0
error-ex: 1.3.4
json-parse-even-better-errors: 2.3.1
lines-and-columns: 1.2.4
parse-passwd@1.0.0: {}
path-is-absolute@1.0.1: {}
pathe@2.0.3: {}
picocolors@1.1.1: {}
picomatch@2.3.2: {}
picomatch@4.0.4: {}
postcss@8.5.10:
dependencies:
nanoid: 3.3.11
picocolors: 1.1.1
source-map-js: 1.2.1
prettier@3.8.3: {}
react-dom@19.2.5(react@19.2.5):
dependencies:
react: 19.2.5
scheduler: 0.27.0
react-i18next@17.0.3(i18next@26.0.5(typescript@6.0.2))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(typescript@6.0.2):
dependencies:
'@babel/runtime': 7.29.2
html-parse-stringify: 3.0.1
i18next: 26.0.5(typescript@6.0.2)
react: 19.2.5
use-sync-external-store: 1.6.0(react@19.2.5)
optionalDependencies:
react-dom: 19.2.5(react@19.2.5)
typescript: 6.0.2
react@19.2.5: {}
readable-stream@3.6.2:
dependencies:
inherits: 2.0.4
string_decoder: 1.3.0
util-deprecate: 1.0.2
readdirp@3.6.0:
dependencies:
picomatch: 2.3.2
require-directory@2.1.1: {}
require-from-string@2.0.2: {}
resolve-dir@1.0.1:
dependencies:
expand-tilde: 2.0.2
global-modules: 1.0.0
resolve-from@4.0.0: {}
resolve-from@5.0.0: {}
resolve-pkg-maps@1.0.0: {}
restore-cursor@3.1.0:
dependencies:
onetime: 5.1.2
signal-exit: 3.0.7
restore-cursor@5.1.0:
dependencies:
onetime: 7.0.0
signal-exit: 4.1.0
rfdc@1.4.1: {}
rolldown@1.0.0-rc.15:
dependencies:
'@oxc-project/types': 0.124.0
'@rolldown/pluginutils': 1.0.0-rc.15
optionalDependencies:
'@rolldown/binding-android-arm64': 1.0.0-rc.15
'@rolldown/binding-darwin-arm64': 1.0.0-rc.15
'@rolldown/binding-darwin-x64': 1.0.0-rc.15
'@rolldown/binding-freebsd-x64': 1.0.0-rc.15
'@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.15
'@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.15
'@rolldown/binding-linux-arm64-musl': 1.0.0-rc.15
'@rolldown/binding-linux-ppc64-gnu': 1.0.0-rc.15
'@rolldown/binding-linux-s390x-gnu': 1.0.0-rc.15
'@rolldown/binding-linux-x64-gnu': 1.0.0-rc.15
'@rolldown/binding-linux-x64-musl': 1.0.0-rc.15
'@rolldown/binding-openharmony-arm64': 1.0.0-rc.15
'@rolldown/binding-wasm32-wasi': 1.0.0-rc.15
'@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.15
'@rolldown/binding-win32-x64-msvc': 1.0.0-rc.15
run-async@2.4.1: {}
rxjs@7.8.2:
dependencies:
tslib: 2.8.1
safe-buffer@5.2.1: {}
safer-buffer@2.1.2: {}
scheduler@0.27.0: {}
semver@6.3.1: {}
semver@7.7.4: {}
seroval-plugins@1.5.2(seroval@1.5.2):
dependencies:
seroval: 1.5.2
seroval@1.5.2: {}
signal-exit@3.0.7: {}
signal-exit@4.1.0: {}
slice-ansi@7.1.2:
dependencies:
ansi-styles: 6.2.3
is-fullwidth-code-point: 5.1.0
slice-ansi@8.0.0:
dependencies:
ansi-styles: 6.2.3
is-fullwidth-code-point: 5.1.0
source-map-js@1.2.1: {}
string-argv@0.3.2: {}
string-width@4.2.3:
dependencies:
emoji-regex: 8.0.0
is-fullwidth-code-point: 3.0.0
strip-ansi: 6.0.1
string-width@7.2.0:
dependencies:
emoji-regex: 10.6.0
get-east-asian-width: 1.5.0
strip-ansi: 7.2.0
string-width@8.2.0:
dependencies:
get-east-asian-width: 1.5.0
strip-ansi: 7.2.0
string_decoder@1.3.0:
dependencies:
safe-buffer: 5.2.1
strip-ansi@6.0.1:
dependencies:
ansi-regex: 5.0.1
strip-ansi@7.2.0:
dependencies:
ansi-regex: 6.2.2
strip-bom@4.0.0: {}
strip-json-comments@3.1.1: {}
supports-color@5.5.0:
dependencies:
has-flag: 3.0.0
supports-color@7.2.0:
dependencies:
has-flag: 4.0.0
tailwindcss@4.2.2: {}
tapable@2.3.2: {}
through@2.3.8: {}
tinyexec@1.1.1: {}
tinyglobby@0.2.16:
dependencies:
fdir: 6.5.0(picomatch@4.0.4)
picomatch: 4.0.4
tmp@0.0.33:
dependencies:
os-tmpdir: 1.0.2
to-regex-range@5.0.1:
dependencies:
is-number: 7.0.0
tslib@2.8.1: {}
tsx@4.21.0:
dependencies:
esbuild: 0.27.7
get-tsconfig: 4.14.0
optionalDependencies:
fsevents: 2.3.3
type-fest@0.21.3: {}
typescript@6.0.2: {}
undici-types@7.16.0: {}
universalify@2.0.1: {}
unplugin@2.3.11:
dependencies:
'@jridgewell/remapping': 2.3.5
acorn: 8.16.0
picomatch: 4.0.4
webpack-virtual-modules: 0.6.2
update-browserslist-db@1.2.3(browserslist@4.28.2):
dependencies:
browserslist: 4.28.2
escalade: 3.2.0
picocolors: 1.1.1
use-sync-external-store@1.6.0(react@19.2.5):
dependencies:
react: 19.2.5
util-deprecate@1.0.2: {}
vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3):
dependencies:
lightningcss: 1.32.0
picomatch: 4.0.4
postcss: 8.5.10
rolldown: 1.0.0-rc.15
tinyglobby: 0.2.16
optionalDependencies:
'@types/node': 24.12.2
esbuild: 0.27.7
fsevents: 2.3.3
jiti: 2.6.1
tsx: 4.21.0
yaml: 2.8.3
void-elements@3.1.0: {}
wcwidth@1.0.1:
dependencies:
defaults: 1.0.4
webpack-virtual-modules@0.6.2: {}
which@1.3.1:
dependencies:
isexe: 2.0.0
word-wrap@1.2.5: {}
wrap-ansi@7.0.0:
dependencies:
ansi-styles: 4.3.0
string-width: 4.2.3
strip-ansi: 6.0.1
wrap-ansi@9.0.2:
dependencies:
ansi-styles: 6.2.3
string-width: 7.2.0
strip-ansi: 7.2.0
wrappy@1.0.2: {}
y18n@5.0.8: {}
yallist@3.1.1: {}
yaml@2.8.3: {}
yargs-parser@21.1.1: {}
yargs@17.7.2:
dependencies:
cliui: 8.0.1
escalade: 3.2.0
get-caller-file: 2.0.5
require-directory: 2.1.1
string-width: 4.2.3
y18n: 5.0.8
yargs-parser: 21.1.1
zod@3.25.76: {}
zustand@5.0.12(@types/react@19.2.14)(react@19.2.5)(use-sync-external-store@1.6.0(react@19.2.5)):
optionalDependencies:
'@types/react': 19.2.14
react: 19.2.5
use-sync-external-store: 1.6.0(react@19.2.5)

1
public/favicon.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 9.3 KiB

41
src/constants/index.ts Normal file
View File

@@ -0,0 +1,41 @@
/** @description 应用启动阶段使用的根节点常量。 */
export const APP_ROOT_ELEMENT_ID = 'root'
/** @description 应用名称,用于文档标题和分享元信息。 */
export const APP_NAME = 'React SPA Template'
/** @description 应用默认的页面描述,用于 SEO 和分享卡片。 */
export const APP_DEFAULT_DESCRIPTION =
'A frontend scaffold with Vite, React, TanStack Router, TanStack Query, Zustand, and Biome.'
/** @description 认证状态持久化到浏览器时使用的存储键。 */
export const AUTH_STORAGE_KEY = 'auth-session'
/** @description 接口请求的默认超时时间,单位为毫秒。 */
export const DEFAULT_REQUEST_TIMEOUT_MS = 15_000
/** @description 请求默认声明可接收的响应内容类型。 */
export const DEFAULT_REQUEST_ACCEPT_HEADER = 'application/json'
/** @description 请求层统一使用的错误提示文案。 */
export const API_ERROR_MESSAGES = {
timeout: 'Request timed out',
unexpected: 'Unexpected request error',
} as const
/** @description TanStack Query 默认的缓存新鲜时间。 */
export const QUERY_DEFAULT_STALE_TIME_MS = 30_000
/** @description TanStack Query 默认的缓存回收时间。 */
export const QUERY_DEFAULT_GC_TIME_MS = 5 * 60_000
/** @description 查询请求默认允许的最大重试次数。 */
export const QUERY_RETRY_LIMIT = 2
/** @description 可被视为瞬时失败并允许重试的状态码集合。 */
export const QUERY_RETRYABLE_STATUS_CODES = [
408, 429, 500, 502, 503, 504,
] as const
/** @description 国际化语言设置持久化到浏览器时使用的存储键。 */
export const I18N_LANGUAGE_STORAGE_KEY = 'app-language'

112
src/i18n/index.ts Normal file
View File

@@ -0,0 +1,112 @@
import i18n from 'i18next'
import { initReactI18next } from 'react-i18next'
import { I18N_LANGUAGE_STORAGE_KEY } from '@/constants'
import enUSCommon from '@/locales/en-US/common'
import zhCNCommon from '@/locales/zh-CN/common'
export const supportedLanguages = ['zh-CN', 'en-US'] as const
export type AppLanguage = (typeof supportedLanguages)[number]
const defaultLanguage: AppLanguage = 'zh-CN'
/** @description 判断给定语言是否在当前应用支持列表中。 */
export function isSupportedLanguage(
value: string | null | undefined,
): value is AppLanguage {
return supportedLanguages.includes(value as AppLanguage)
}
/** @description 从浏览器设置中推断最匹配的语言。 */
function detectBrowserLanguage() {
if (typeof navigator === 'undefined') {
return defaultLanguage
}
const browserLanguages = [...navigator.languages, navigator.language]
for (const language of browserLanguages) {
if (isSupportedLanguage(language)) {
return language
}
const normalizedLanguage = language.toLowerCase()
if (normalizedLanguage.startsWith('zh')) {
return 'zh-CN'
}
if (normalizedLanguage.startsWith('en')) {
return 'en-US'
}
}
return defaultLanguage
}
/** @description 获取应用启动时应使用的初始语言。 */
function getInitialLanguage() {
if (typeof window === 'undefined') {
return defaultLanguage
}
const persistedLanguage = window.localStorage.getItem(
I18N_LANGUAGE_STORAGE_KEY,
)
if (isSupportedLanguage(persistedLanguage)) {
return persistedLanguage
}
return detectBrowserLanguage()
}
/** @description 暴露当前应用应优先使用的语言。 */
export function getPreferredLanguage() {
return getInitialLanguage()
}
/** @description 从路由路径中解析语言前缀。 */
export function getLanguageFromPathname(pathname: string) {
const [, firstSegment] = pathname.split('/')
if (isSupportedLanguage(firstSegment)) {
return firstSegment
}
return null
}
void i18n.use(initReactI18next).init({
lng: getInitialLanguage(),
fallbackLng: defaultLanguage,
debug: false,
interpolation: {
escapeValue: false,
},
resources: {
'zh-CN': {
common: zhCNCommon,
},
'en-US': {
common: enUSCommon,
},
},
defaultNS: 'common',
})
/** @description 同步当前语言到 html 标签并持久化到浏览器。 */
function syncLanguageState(language: string) {
if (typeof document !== 'undefined') {
document.documentElement.lang = language
}
if (typeof window !== 'undefined' && isSupportedLanguage(language)) {
window.localStorage.setItem(I18N_LANGUAGE_STORAGE_KEY, language)
}
}
syncLanguageState(i18n.resolvedLanguage ?? defaultLanguage)
i18n.on('languageChanged', syncLanguageState)
export default i18n

212
src/lib/api/api-client.ts Normal file
View File

@@ -0,0 +1,212 @@
import ky, { HTTPError, type Options, TimeoutError } from 'ky'
import {
API_ERROR_MESSAGES,
DEFAULT_REQUEST_ACCEPT_HEADER,
DEFAULT_REQUEST_TIMEOUT_MS,
} from '@/constants'
import {
handleUnauthorizedSession,
tryRefreshAuthSession,
} from '@/lib/auth/auth-session'
import { useAuthStore } from '@/store/auth-store'
import { ApiError } from './api-error'
import type { ApiResponse } from './types'
type RequestOptions = Omit<Options, 'json'>
type JsonRequestOptions<TBody> = RequestOptions & {
json?: TBody
}
const AUTH_REFRESH_ATTEMPTED_CONTEXT_KEY = 'authRefreshAttempted'
const AUTH_SKIP_REFRESH_CONTEXT_KEY = 'skipAuthRefresh'
const appEnv = import.meta.env.VITE_APP_ENV
const shouldLogRequests = import.meta.env.VITE_ENABLE_REQUEST_LOG === 'true'
function normalizeApiBaseUrl(baseUrl: string | undefined) {
const candidate = baseUrl?.trim()
if (!candidate) {
throw new Error('VITE_API_BASE_URL 未配置')
}
if (/^https?:\/\//.test(candidate)) {
return candidate.replace(/\/+$/, '')
}
return candidate.replace(/^\/+/, '').replace(/\/+$/, '')
}
async function parseResponseBody(response: Response) {
if (response.status === 204) {
return null
}
const contentType = response.headers.get('content-type') ?? ''
if (contentType.includes('application/json')) {
return response.json()
}
return response.text()
}
function getErrorMessage(response: Response, data: unknown) {
if (data && typeof data === 'object') {
const message =
'message' in data ? data.message : 'msg' in data ? data.msg : null
if (typeof message === 'string' && message.length > 0) {
return message
}
}
return `Request failed with status ${response.status}`
}
async function toApiError(error: unknown) {
if (error instanceof HTTPError) {
const data = error.data
return new ApiError({
message: getErrorMessage(error.response, data),
status: error.response.status,
data,
url: error.response.url,
})
}
if (error instanceof TimeoutError) {
return new ApiError({
message: API_ERROR_MESSAGES.timeout,
status: 408,
})
}
if (error instanceof Error) {
return new ApiError({
message: error.message,
})
}
return new ApiError({
message: API_ERROR_MESSAGES.unexpected,
})
}
export const apiBaseUrl = normalizeApiBaseUrl(import.meta.env.VITE_API_BASE_URL)
const apiClient = ky.create({
prefix: apiBaseUrl,
retry: 0,
timeout: DEFAULT_REQUEST_TIMEOUT_MS,
hooks: {
beforeRequest: [
({ request }) => {
request.headers.set('Accept', DEFAULT_REQUEST_ACCEPT_HEADER)
const token = useAuthStore.getState().accessToken
if (token) {
request.headers.set('Authorization', `Bearer ${token}`)
}
if (shouldLogRequests) {
console.info(`[api:${appEnv}] ${request.method} ${request.url}`)
}
},
],
afterResponse: [
({ request, response }) => {
if (shouldLogRequests) {
console.info(
`[api:${appEnv}] ${request.method} ${response.url} -> ${response.status}`,
)
}
},
],
},
})
async function request<TResponse>(input: string, options?: Options) {
try {
const response = await apiClient(input, options)
const data = await parseResponseBody(response)
return data as TResponse
} catch (error) {
if (
error instanceof HTTPError &&
error.response.status === 401 &&
options?.context?.[AUTH_SKIP_REFRESH_CONTEXT_KEY] !== true &&
options?.context?.[AUTH_REFRESH_ATTEMPTED_CONTEXT_KEY] !== true
) {
const refreshed = await tryRefreshAuthSession()
if (refreshed) {
return request<TResponse>(input, {
...options,
context: {
...options?.context,
[AUTH_REFRESH_ATTEMPTED_CONTEXT_KEY]: true,
},
})
}
}
if (error instanceof HTTPError && error.response.status === 401) {
handleUnauthorizedSession()
}
throw await toApiError(error)
}
}
async function requestRest<TData>(input: string, options?: Options) {
return request<ApiResponse<TData>>(input, options)
}
export const api = {
get<TData>(input: string, options?: RequestOptions) {
return requestRest<TData>(input, {
...options,
method: 'get',
})
},
post<TData, TBody = unknown>(
input: string,
{ json, ...options }: JsonRequestOptions<TBody> = {},
) {
return requestRest<TData>(input, {
...options,
json,
method: 'post',
})
},
put<TData, TBody = unknown>(
input: string,
{ json, ...options }: JsonRequestOptions<TBody> = {},
) {
return requestRest<TData>(input, {
...options,
json,
method: 'put',
})
},
patch<TData, TBody = unknown>(
input: string,
{ json, ...options }: JsonRequestOptions<TBody> = {},
) {
return requestRest<TData>(input, {
...options,
json,
method: 'patch',
})
},
delete<TData>(input: string, options?: RequestOptions) {
return requestRest<TData>(input, {
...options,
method: 'delete',
})
},
}

20
src/lib/api/api-error.ts Normal file
View File

@@ -0,0 +1,20 @@
interface ApiErrorOptions {
message: string
status?: number
data?: unknown
url?: string
}
export class ApiError extends Error {
status: number | null
data: unknown
url: string | null
constructor({ message, status, data, url }: ApiErrorOptions) {
super(message)
this.name = 'ApiError'
this.status = status ?? null
this.data = data ?? null
this.url = url ?? null
}
}

6
src/lib/api/types.ts Normal file
View File

@@ -0,0 +1,6 @@
/** @description 后端统一响应体结构。 */
export interface ApiResponse<T> {
code: number
msg: string
data: T
}

View File

@@ -0,0 +1,104 @@
import type { AuthSessionInput, AuthUser } from '@/store/auth-store'
import { useAuthStore } from '@/store/auth-store'
export type CurrentUserInitializer = () => Promise<AuthUser | null>
export type RefreshSessionHandler = (
refreshToken: string,
) => Promise<AuthSessionInput | null>
let currentUserInitializer: CurrentUserInitializer | null = null
let refreshSessionHandler: RefreshSessionHandler | null = null
let authInitializationPromise: Promise<void> | null = null
let refreshSessionPromise: Promise<boolean> | null = null
export function registerCurrentUserInitializer(
initializer: CurrentUserInitializer | null,
) {
currentUserInitializer = initializer
}
export function registerRefreshSessionHandler(
handler: RefreshSessionHandler | null,
) {
refreshSessionHandler = handler
}
export function isAuthenticated() {
const snapshot = useAuthStore.getState()
return snapshot.status === 'authenticated' && Boolean(snapshot.accessToken)
}
export function handleUnauthorizedSession() {
useAuthStore.getState().markUnauthorized()
}
export async function initializeAuthSession() {
if (authInitializationPromise) {
return authInitializationPromise
}
authInitializationPromise = (async () => {
await useAuthStore.persist.rehydrate()
const snapshot = useAuthStore.getState()
if (
!snapshot.accessToken ||
snapshot.currentUser ||
!currentUserInitializer
) {
return
}
const currentUser = await currentUserInitializer()
useAuthStore.getState().setCurrentUser(currentUser)
})().finally(() => {
authInitializationPromise = null
})
return authInitializationPromise
}
export async function tryRefreshAuthSession() {
if (refreshSessionPromise) {
return refreshSessionPromise
}
const snapshot = useAuthStore.getState()
if (!snapshot.refreshToken || !refreshSessionHandler) {
return false
}
const refreshToken = snapshot.refreshToken
refreshSessionPromise = (async () => {
try {
const nextSession = await refreshSessionHandler(refreshToken)
if (!nextSession?.accessToken) {
handleUnauthorizedSession()
return false
}
useAuthStore.getState().startSession({
accessToken: nextSession.accessToken,
currentUser: nextSession.currentUser ?? snapshot.currentUser,
refreshToken: nextSession.refreshToken ?? snapshot.refreshToken,
})
return true
} catch {
handleUnauthorizedSession()
return false
} finally {
refreshSessionPromise = null
}
})()
return refreshSessionPromise
}

View File

@@ -0,0 +1,29 @@
import { redirect } from '@tanstack/react-router'
import type { AppLanguage } from '@/i18n'
import { getPreferredLanguage } from '@/i18n'
import { useAuthStore } from '@/store/auth-store'
import { initializeAuthSession, isAuthenticated } from './auth-session'
interface RequireAuthenticatedSessionOptions {
fallbackLanguage?: AppLanguage
}
export async function requireAuthenticatedSession(
options: RequireAuthenticatedSessionOptions = {},
) {
await initializeAuthSession()
if (isAuthenticated()) {
return useAuthStore.getState()
}
throw redirect({
to: '/$lang',
params: {
lang: options.fallbackLanguage ?? getPreferredLanguage(),
},
replace: true,
})
}

View File

@@ -0,0 +1,95 @@
import { useEffect } from 'react'
import { APP_DEFAULT_DESCRIPTION, APP_NAME } from '@/constants'
interface DocumentMetadata {
description?: string
robots?: string
title?: string
}
function upsertMetaTag(
selector: string,
attributes: Record<string, string>,
content: string,
) {
let tag = document.head.querySelector<HTMLMetaElement>(selector)
if (!tag) {
tag = document.createElement('meta')
for (const [attribute, value] of Object.entries(attributes)) {
tag.setAttribute(attribute, value)
}
document.head.append(tag)
}
tag.setAttribute('content', content)
}
export function buildDocumentTitle(title?: string) {
if (!title) {
return APP_NAME
}
return `${title} | ${APP_NAME}`
}
export function applyDocumentMetadata({
description = APP_DEFAULT_DESCRIPTION,
robots = 'index,follow',
title,
}: DocumentMetadata) {
if (typeof document === 'undefined') {
return
}
const resolvedTitle = buildDocumentTitle(title)
document.title = resolvedTitle
upsertMetaTag(
'meta[name="description"]',
{ name: 'description' },
description,
)
upsertMetaTag('meta[name="robots"]', { name: 'robots' }, robots)
upsertMetaTag(
'meta[property="og:title"]',
{ property: 'og:title' },
resolvedTitle,
)
upsertMetaTag(
'meta[property="og:description"]',
{ property: 'og:description' },
description,
)
upsertMetaTag(
'meta[property="og:site_name"]',
{ property: 'og:site_name' },
APP_NAME,
)
upsertMetaTag(
'meta[name="twitter:title"]',
{ name: 'twitter:title' },
resolvedTitle,
)
upsertMetaTag(
'meta[name="twitter:description"]',
{ name: 'twitter:description' },
description,
)
}
export function useDocumentMetadata(metadata: DocumentMetadata) {
const { description, robots, title } = metadata
useEffect(() => {
applyDocumentMetadata({
description,
robots,
title,
})
}, [description, robots, title])
}

View File

@@ -0,0 +1,43 @@
import { QueryClient } from '@tanstack/react-query'
import {
QUERY_DEFAULT_GC_TIME_MS,
QUERY_DEFAULT_STALE_TIME_MS,
QUERY_RETRY_LIMIT,
QUERY_RETRYABLE_STATUS_CODES,
} from '@/constants'
import { ApiError } from '../api/api-error'
const retryableStatusCodes = new Set<number>(QUERY_RETRYABLE_STATUS_CODES)
function shouldRetryRequest(error: unknown) {
if (!(error instanceof ApiError)) {
return true
}
if (error.status === null) {
return true
}
return retryableStatusCodes.has(error.status) || error.status >= 500
}
export function createQueryClient() {
return new QueryClient({
defaultOptions: {
queries: {
staleTime: QUERY_DEFAULT_STALE_TIME_MS,
gcTime: QUERY_DEFAULT_GC_TIME_MS,
refetchOnWindowFocus: false,
retry(failureCount, error) {
return failureCount < QUERY_RETRY_LIMIT && shouldRetryRequest(error)
},
},
mutations: {
retry: false,
},
},
})
}
export const queryClient = createQueryClient()

View File

@@ -0,0 +1,42 @@
export default {
nav: {
home: 'Home',
},
shell: {
eyebrow: 'React SPA scaffold',
subtitle: 'TanStack Router + Query + Auth + i18n',
},
notFound: {
eyebrow: '404',
title: 'The page you requested could not be found.',
description: 'This route does not exist. Return to the scaffold home page.',
home: 'Back home',
},
home: {
eyebrow: 'Blank scaffold ready',
title: 'Start building your frontend project from here.',
description:
'The template already includes routing, data fetching, session state, head metadata, and i18n. After removing the examples, this page becomes your clean starting point.',
cards: {
routingMode: 'Routing mode',
dataLayer: 'Data layer',
transport: 'Transport',
auth: 'Auth layer',
metadata: 'Page metadata',
},
values: {
routingMode: 'SPA + file routes',
dataLayer: 'TanStack Query',
transport: 'ky',
auth: 'Zustand session scaffold',
metadata: 'Dynamic title / meta',
},
footnote:
'A practical place to start is replacing src/routes/$lang/index.tsx, src/lib/api/api-client.ts, and src/store/auth-store.ts with your project-specific structure.',
},
language: {
label: 'Language',
zhCN: '中文',
enUS: 'English',
},
} as const

View File

@@ -0,0 +1,42 @@
export default {
nav: {
home: '首页',
},
shell: {
eyebrow: 'React SPA 脚手架',
subtitle: 'TanStack Router + Query + Auth + i18n',
},
notFound: {
eyebrow: '404',
title: '找不到你访问的页面。',
description: '当前路由不存在,你可以返回脚手架首页继续开始开发。',
home: '返回首页',
},
home: {
eyebrow: '空白脚手架已就绪',
title: '从这里开始搭建你的前端项目。',
description:
'模板已经接好路由、请求层、会话状态、head metadata 和多语言。删除示例后,这一页就是你的干净起点。',
cards: {
routingMode: '路由模式',
dataLayer: '数据层',
transport: '请求层',
auth: '认证层',
metadata: '页面元信息',
},
values: {
routingMode: 'SPA + 文件路由',
dataLayer: 'TanStack Query',
transport: 'ky',
auth: 'Zustand 会话基座',
metadata: '动态 title / meta',
},
footnote:
'建议先从 src/routes/$lang/index.tsx、src/lib/api/api-client.ts 和 src/store/auth-store.ts 开始替换成你的项目结构。',
},
language: {
label: '语言',
zhCN: '中文',
enUS: 'English',
},
} as const

31
src/main.tsx Normal file
View File

@@ -0,0 +1,31 @@
import { QueryClientProvider } from '@tanstack/react-query'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
import { RouterProvider } from '@tanstack/react-router'
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { APP_ROOT_ELEMENT_ID } from '@/constants'
import '@/i18n'
import { initializeAuthSession } from '@/lib/auth/auth-session'
import { queryClient } from '@/lib/query/query-client'
import { router } from '@/router'
import './styles.css'
const rootElement = document.getElementById(APP_ROOT_ELEMENT_ID)
const shouldShowQueryDevtools =
import.meta.env.VITE_APP_ENV === 'development' &&
import.meta.env.VITE_ENABLE_QUERY_DEVTOOLS === 'true'
if (!rootElement) {
throw new Error('Root element not found')
}
void initializeAuthSession()
createRoot(rootElement).render(
<StrictMode>
<QueryClientProvider client={queryClient}>
<RouterProvider router={router} />
{shouldShowQueryDevtools && <ReactQueryDevtools initialIsOpen={false} />}
</QueryClientProvider>
</StrictMode>,
)

104
src/routeTree.gen.ts Normal file
View File

@@ -0,0 +1,104 @@
/* eslint-disable */
// @ts-nocheck
// noinspection JSUnusedGlobalSymbols
// This file was automatically generated by TanStack Router.
// You should NOT make any changes in this file as it will be overwritten.
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
import { Route as rootRouteImport } from './routes/__root'
import { Route as LangRouteRouteImport } from './routes/$lang/route'
import { Route as IndexRouteImport } from './routes/index'
import { Route as LangIndexRouteImport } from './routes/$lang/index'
const LangRouteRoute = LangRouteRouteImport.update({
id: '/$lang',
path: '/$lang',
getParentRoute: () => rootRouteImport,
} as any)
const IndexRoute = IndexRouteImport.update({
id: '/',
path: '/',
getParentRoute: () => rootRouteImport,
} as any)
const LangIndexRoute = LangIndexRouteImport.update({
id: '/',
path: '/',
getParentRoute: () => LangRouteRoute,
} as any)
export interface FileRoutesByFullPath {
'/': typeof IndexRoute
'/$lang': typeof LangRouteRouteWithChildren
'/$lang/': typeof LangIndexRoute
}
export interface FileRoutesByTo {
'/': typeof IndexRoute
'/$lang': typeof LangIndexRoute
}
export interface FileRoutesById {
__root__: typeof rootRouteImport
'/': typeof IndexRoute
'/$lang': typeof LangRouteRouteWithChildren
'/$lang/': typeof LangIndexRoute
}
export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath
fullPaths: '/' | '/$lang' | '/$lang/'
fileRoutesByTo: FileRoutesByTo
to: '/' | '/$lang'
id: '__root__' | '/' | '/$lang' | '/$lang/'
fileRoutesById: FileRoutesById
}
export interface RootRouteChildren {
IndexRoute: typeof IndexRoute
LangRouteRoute: typeof LangRouteRouteWithChildren
}
declare module '@tanstack/react-router' {
interface FileRoutesByPath {
'/$lang': {
id: '/$lang'
path: '/$lang'
fullPath: '/$lang'
preLoaderRoute: typeof LangRouteRouteImport
parentRoute: typeof rootRouteImport
}
'/': {
id: '/'
path: '/'
fullPath: '/'
preLoaderRoute: typeof IndexRouteImport
parentRoute: typeof rootRouteImport
}
'/$lang/': {
id: '/$lang/'
path: '/'
fullPath: '/$lang/'
preLoaderRoute: typeof LangIndexRouteImport
parentRoute: typeof LangRouteRoute
}
}
}
interface LangRouteRouteChildren {
LangIndexRoute: typeof LangIndexRoute
}
const LangRouteRouteChildren: LangRouteRouteChildren = {
LangIndexRoute: LangIndexRoute,
}
const LangRouteRouteWithChildren = LangRouteRoute._addFileChildren(
LangRouteRouteChildren,
)
const rootRouteChildren: RootRouteChildren = {
IndexRoute: IndexRoute,
LangRouteRoute: LangRouteRouteWithChildren,
}
export const routeTree = rootRouteImport
._addFileChildren(rootRouteChildren)
._addFileTypes<FileRouteTypes>()

14
src/router.tsx Normal file
View File

@@ -0,0 +1,14 @@
import { createRouter } from '@tanstack/react-router'
import { routeTree } from './routeTree.gen'
export const router = createRouter({
routeTree,
defaultPreload: 'intent',
})
declare module '@tanstack/react-router' {
interface Register {
router: typeof router
}
}

View File

@@ -0,0 +1,19 @@
import { createFileRoute } from '@tanstack/react-router'
import { useTranslation } from 'react-i18next'
import { useDocumentMetadata } from '@/lib/head/document-metadata'
export const Route = createFileRoute('/$lang/')({
component: HomePage,
})
function HomePage() {
const { t } = useTranslation()
useDocumentMetadata({
title: t('home.title'),
description: t('home.description'),
})
return <div>111</div>
}

View File

@@ -0,0 +1,46 @@
import { createFileRoute, Navigate, Outlet } from '@tanstack/react-router'
import { useEffect } from 'react'
import { useTranslation } from 'react-i18next'
import { getPreferredLanguage, isSupportedLanguage } from '@/i18n'
export const Route = createFileRoute('/$lang')({
component: LanguageLayout,
})
function LanguageLayout() {
const { lang } = Route.useParams()
const { i18n } = useTranslation()
const preferredLanguage = getPreferredLanguage()
const isValidLanguage = isSupportedLanguage(lang)
useEffect(() => {
if (isValidLanguage && i18n.resolvedLanguage !== lang) {
void i18n.changeLanguage(lang)
}
}, [i18n, isValidLanguage, lang])
if (!isValidLanguage) {
return <Navigate to="/$lang" params={{ lang: preferredLanguage }} replace />
}
// function changeLanguage(nextLanguage: AppLanguage) {
// const nextPathname = location.pathname.replace(
// /^\/(zh-CN|en-US)(?=\/|$)/,
// `/${nextLanguage}`,
// )
// void i18n.changeLanguage(nextLanguage)
// void navigate({
// to: nextPathname,
// search: location.search,
// hash: location.hash,
// replace: true,
// })
// }
return (
<>
<Outlet />
</>
)
}

64
src/routes/__root.tsx Normal file
View File

@@ -0,0 +1,64 @@
import {
createRootRoute,
Link,
Outlet,
useLocation,
} from '@tanstack/react-router'
import { useEffect } from 'react'
import { useTranslation } from 'react-i18next'
import { getLanguageFromPathname, getPreferredLanguage } from '@/i18n'
import { useDocumentMetadata } from '@/lib/head/document-metadata'
function NotFoundPage() {
const { i18n, t } = useTranslation()
const location = useLocation()
const routeLanguage =
getLanguageFromPathname(location.pathname) ??
(i18n.resolvedLanguage || getPreferredLanguage())
const homePath = `/${routeLanguage}`
useEffect(() => {
if (
getLanguageFromPathname(location.pathname) &&
i18n.resolvedLanguage !== routeLanguage
) {
void i18n.changeLanguage(routeLanguage)
}
}, [i18n, location.pathname, routeLanguage])
useDocumentMetadata({
title: t('notFound.title'),
description: t('notFound.description'),
robots: 'noindex,nofollow',
})
return (
<section className="flex flex-1 flex-col justify-center gap-6 px-6 py-14 md:px-10">
<span className="inline-flex w-fit rounded-full border border-rose-400/25 bg-rose-400/10 px-3 py-1 text-xs font-semibold tracking-[0.22em] text-rose-200 uppercase">
{t('notFound.eyebrow')}
</span>
<div className="max-w-2xl space-y-4">
<h1 className="text-4xl font-semibold tracking-tight text-white md:text-5xl">
{t('notFound.title')}
</h1>
<p className="text-base leading-7 text-neutral-300 md:text-lg">
{t('notFound.description')}
</p>
</div>
<div className="flex flex-wrap gap-3">
<Link
to={homePath}
className="inline-flex min-h-11 items-center rounded-full border border-rose-300/40 bg-rose-300/12 px-5 text-sm font-medium text-rose-100 transition hover:border-rose-200/60 hover:bg-rose-300/18"
>
{t('notFound.home')}
</Link>
</div>
</section>
)
}
export const Route = createRootRoute({
component: Outlet,
notFoundComponent: NotFoundPage,
})

13
src/routes/index.tsx Normal file
View File

@@ -0,0 +1,13 @@
import { createFileRoute, Navigate } from '@tanstack/react-router'
import { getPreferredLanguage } from '@/i18n'
export const Route = createFileRoute('/')({
component: RootRedirectPage,
})
function RootRedirectPage() {
return (
<Navigate to="/$lang" params={{ lang: getPreferredLanguage() }} replace />
)
}

143
src/store/auth-store.ts Normal file
View File

@@ -0,0 +1,143 @@
import { create } from 'zustand'
import { createJSONStorage, persist } from 'zustand/middleware'
import { AUTH_STORAGE_KEY } from '@/constants'
export type AuthStatus = 'anonymous' | 'authenticated' | 'restoring'
export interface AuthUser {
email?: string
id: string
name?: string
roles?: string[]
}
export interface AuthSessionInput {
accessToken: string
currentUser?: AuthUser | null
refreshToken?: string | null
}
interface PersistedAuthState {
accessToken: string | null
currentUser: AuthUser | null
refreshToken: string | null
}
interface AuthState extends PersistedAuthState {
clearAccessToken: () => void
clearSession: () => void
finishHydration: () => void
isHydrated: boolean
lastUnauthorizedAt: string | null
markUnauthorized: () => void
setAccessToken: (token: string) => void
setCurrentUser: (user: AuthUser | null) => void
startSession: (session: AuthSessionInput) => void
status: AuthStatus
updateTokens: (tokens: {
accessToken: string
refreshToken?: string | null
}) => void
}
function resolveAuthStatus(accessToken: string | null): AuthStatus {
return accessToken ? 'authenticated' : 'anonymous'
}
const initialPersistedState: PersistedAuthState = {
accessToken: null,
refreshToken: null,
currentUser: null,
}
export const useAuthStore = create<AuthState>()(
persist(
(set) => ({
...initialPersistedState,
status: 'restoring',
isHydrated: false,
lastUnauthorizedAt: null,
setAccessToken: (token) => {
set({
accessToken: token,
status: 'authenticated',
isHydrated: true,
})
},
setCurrentUser: (currentUser) => {
set((state) => ({
currentUser,
status: resolveAuthStatus(state.accessToken),
}))
},
startSession: ({
accessToken,
currentUser = null,
refreshToken = null,
}) => {
set({
accessToken,
currentUser,
refreshToken,
status: 'authenticated',
isHydrated: true,
})
},
updateTokens: ({ accessToken, refreshToken }) => {
set((state) => ({
accessToken,
refreshToken: refreshToken ?? state.refreshToken,
status: 'authenticated',
isHydrated: true,
}))
},
finishHydration: () => {
set((state) => ({
isHydrated: true,
status: resolveAuthStatus(state.accessToken),
}))
},
clearAccessToken: () => {
set({
accessToken: null,
status: 'anonymous',
isHydrated: true,
})
},
clearSession: () => {
set({
...initialPersistedState,
status: 'anonymous',
isHydrated: true,
})
},
markUnauthorized: () => {
set({
...initialPersistedState,
status: 'anonymous',
isHydrated: true,
lastUnauthorizedAt: new Date().toISOString(),
})
},
}),
{
name: AUTH_STORAGE_KEY,
storage: createJSONStorage(() => sessionStorage),
partialize: (state) => ({
accessToken: state.accessToken,
currentUser: state.currentUser,
refreshToken: state.refreshToken,
}),
onRehydrateStorage: () => (state, error) => {
if (error) {
state?.clearSession()
return
}
state?.finishHydration()
},
},
),
)

22
src/styles.css Normal file
View File

@@ -0,0 +1,22 @@
@import "tailwindcss";
@theme {
--font-sans:
"Inter", "SF Pro Display", "Segoe UI", "Helvetica Neue", sans-serif;
--font-mono:
"JetBrains Mono", "SFMono-Regular", "SF Mono", Consolas, monospace;
}
@layer base {
html {
@apply h-full w-full;
}
body {
@apply m-0 h-full w-full;
}
#root {
@apply h-full w-full;
}
}

12
src/vite-env.d.ts vendored Normal file
View File

@@ -0,0 +1,12 @@
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_APP_ENV: 'development' | 'production' | 'test'
readonly VITE_API_BASE_URL: string
readonly VITE_ENABLE_QUERY_DEVTOOLS: 'true' | 'false'
readonly VITE_ENABLE_REQUEST_LOG: 'true' | 'false'
}
interface ImportMeta {
readonly env: ImportMetaEnv
}

28
tsconfig.app.json Normal file
View File

@@ -0,0 +1,28 @@
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"target": "es2023",
"lib": ["ES2023", "DOM", "DOM.Iterable"],
"module": "esnext",
"types": ["vite/client"],
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",
"paths": {
"@/*": ["./src/*"]
},
/* Linting */
"noUnusedLocals": true,
"noUnusedParameters": true,
"erasableSyntaxOnly": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"]
}

7
tsconfig.json Normal file
View File

@@ -0,0 +1,7 @@
{
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
]
}

27
tsconfig.node.json Normal file
View File

@@ -0,0 +1,27 @@
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"target": "es2023",
"lib": ["ES2023"],
"module": "esnext",
"types": ["node"],
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"moduleDetection": "force",
"noEmit": true,
"paths": {
"@/*": ["./src/*"]
},
/* Linting */
"noUnusedLocals": true,
"noUnusedParameters": true,
"erasableSyntaxOnly": true,
"noFallthroughCasesInSwitch": true
},
"include": ["vite.config.ts"]
}

24
vite.config.ts Normal file
View File

@@ -0,0 +1,24 @@
import { fileURLToPath, URL } from 'node:url'
import babel from '@rolldown/plugin-babel'
import tailwindcss from '@tailwindcss/vite'
import { tanstackRouter } from '@tanstack/router-plugin/vite'
import react, { reactCompilerPreset } from '@vitejs/plugin-react'
import { defineConfig } from 'vite'
// https://vite.dev/config/
export default defineConfig({
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
},
},
plugins: [
tanstackRouter({
target: 'react',
autoCodeSplitting: true,
}),
tailwindcss(),
react(),
babel({ presets: [reactCompilerPreset()] }),
],
})