diff --git a/.dockerignore b/.dockerignore
index 2d1feac..4d26d5f 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1,2 +1,7 @@
.env
-.env*.local
\ No newline at end of file
+.env*.local
+.git
+dist
+node_modules
+npm-debug.log*
+pnpm-debug.log*
diff --git a/.eslintrc.js b/.eslintrc.js
index 241cdcb..43015d5 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -4,21 +4,44 @@ module.exports = {
es2021: true,
node: true,
},
- plugins: ['@typescript-eslint', 'simple-import-sort', 'unused-imports'],
+ plugins: [
+ '@typescript-eslint',
+ 'react',
+ 'react-hooks',
+ 'simple-import-sort',
+ 'unused-imports',
+ ],
extends: [
'eslint:recommended',
- 'next',
- 'next/core-web-vitals',
+ 'plugin:react/recommended',
+ 'plugin:react-hooks/recommended',
'plugin:@typescript-eslint/recommended',
'prettier',
],
+ settings: {
+ react: {
+ version: 'detect',
+ },
+ },
rules: {
'no-unused-vars': 'off',
'no-console': 'warn',
'@typescript-eslint/explicit-module-boundary-types': 'off',
+ '@typescript-eslint/no-empty-function': 'off',
+ '@typescript-eslint/no-inferrable-types': 'off',
+ '@typescript-eslint/no-var-requires': 'off',
+ 'no-case-declarations': 'off',
'react/no-unescaped-entities': 'off',
+ 'no-empty': 'off',
+ 'no-useless-escape': 'off',
+ 'prefer-const': 'off',
'react/display-name': 'off',
+ 'react/prop-types': 'off',
+ 'react-hooks/immutability': 'off',
+ 'react-hooks/purity': 'off',
+ 'react-hooks/refs': 'off',
+ 'react-hooks/set-state-in-effect': 'off',
'react/jsx-curly-brace-presence': [
'warn',
{ props: 'never', children: 'never' },
diff --git a/.gitignore b/.gitignore
index d2a80c9..512e368 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,12 +8,12 @@
# testing
/coverage
-# next.js
-/.next/
+# static export
/out/
# production
/build
+/dist
# misc
.DS_Store
@@ -34,12 +34,11 @@ yarn-error.log*
# typescript
*.tsbuildinfo
-next-env.d.ts
-# next-sitemap
+# generated sitemap
sitemap.xml
sitemap-*.xml
# generated files
src/lib/runtime.ts
-public/manifest.json
\ No newline at end of file
+public/manifest.json
diff --git a/.npmrc b/.npmrc
index e69de29..b6f27f1 100644
--- a/.npmrc
+++ b/.npmrc
@@ -0,0 +1 @@
+engine-strict=true
diff --git a/.nvmrc b/.nvmrc
index 790e110..a3b7a31 100644
--- a/.nvmrc
+++ b/.nvmrc
@@ -1 +1 @@
-v20.10.0
+v24.14.1
diff --git a/Dockerfile b/Dockerfile
index ad88675..8fa4ff7 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,143 +1,82 @@
-# 多架构构建 Dockerfile
-# 使用 Docker Buildx 进行多架构构建:
-# docker buildx build --platform linux/amd64,linux/arm64 -t your-image:tag --push .
-# 或单一架构构建:
-# docker buildx build --platform linux/amd64 -t your-image:tag --load .
-
-# 声明构建参数,用于多架构构建
ARG BUILDPLATFORM
ARG TARGETPLATFORM
+ARG NODE_VERSION=24
+ARG PNPM_VERSION=10.14.0
-# ---- 第 1 阶段:安装依赖 ----
-FROM --platform=$BUILDPLATFORM node:20-alpine AS deps
+FROM --platform=$BUILDPLATFORM node:${NODE_VERSION}-alpine AS deps
-# 启用 corepack 并激活 pnpm
-RUN corepack enable && corepack prepare pnpm@latest --activate
+ARG PNPM_VERSION
+RUN corepack enable && corepack prepare pnpm@${PNPM_VERSION} --activate
WORKDIR /app
-# 先复制所有文件
-COPY . .
-
-# 然后检查文件
-RUN echo "文件列表:" && ls -la && \
- echo "检查 tsconfig.json:" && \
- if [ -f "tsconfig.json" ]; then \
- echo "tsconfig.json 存在"; \
- else \
- echo "tsconfig.json 不存在"; \
- echo "查找所有文件:"; \
- find . -type f -name "*tsconfig*"; \
- exit 1; \
- fi
-
-
-# 安装所有依赖
+COPY package.json pnpm-lock.yaml ./
+ENV HUSKY=0
RUN pnpm install --frozen-lockfile
-# ---- 第 2 阶段:构建项目 ----
-FROM --platform=$BUILDPLATFORM node:20-alpine AS builder
-RUN corepack enable && corepack prepare pnpm@latest --activate
+FROM --platform=$BUILDPLATFORM node:${NODE_VERSION}-alpine AS builder
+
+ARG PNPM_VERSION
+RUN corepack enable && corepack prepare pnpm@${PNPM_VERSION} --activate
+
WORKDIR /app
-# 复制依赖
COPY --from=deps /app/node_modules ./node_modules
-# 复制全部源代码
COPY . .
ENV DOCKER_ENV=true
+RUN pnpm build
-# 生成生产构建
-RUN pnpm run build
+FROM node:${NODE_VERSION}-alpine AS runner
-# ---- 第 3 阶段:生成运行时镜像 ----
-FROM node:20-alpine AS runner
-
-# 创建非 root 用户
-RUN addgroup -g 1001 -S nodejs && adduser -u 1001 -S nextjs -G nodejs
+ARG PNPM_VERSION
+RUN corepack enable && corepack prepare pnpm@${PNPM_VERSION} --activate
+RUN addgroup -g 1001 -S nodejs && adduser -u 1001 -S orangetv -G nodejs
WORKDIR /app
+
ENV NODE_ENV=production
ENV HOSTNAME=0.0.0.0
ENV PORT=3000
ENV DOCKER_ENV=true
-# 从构建器中复制 standalone 输出
-COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
-# 从构建器中复制 scripts 目录
-COPY --from=builder --chown=nextjs:nodejs /app/scripts ./scripts
-# 从构建器中复制启动脚本和WebSocket相关文件
-COPY --from=builder --chown=nextjs:nodejs /app/start.js ./start.js
-COPY --from=builder --chown=nextjs:nodejs /app/websocket.js ./websocket.js
-COPY --from=builder --chown=nextjs:nodejs /app/production.js ./production.js
-COPY --from=builder --chown=nextjs:nodejs /app/production-final.js ./production-final.js
-COPY --from=builder --chown=nextjs:nodejs /app/standalone-websocket.js ./standalone-websocket.js
-# 从构建器中复制 public 和 .next/static 目录
-COPY --from=builder --chown=nextjs:nodejs /app/public ./public
-COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
-# 从构建器中复制 package.json 和 package-lock.json,用于安装额外依赖
-COPY --from=builder --chown=nextjs:nodejs /app/package.json ./package.json
-COPY --from=builder --chown=nextjs:nodejs /app/pnpm-lock.yaml ./pnpm-lock.yaml
-# 复制 tsconfig.json 以确保路径解析正确
-COPY --from=builder --chown=nextjs:nodejs /app/tsconfig.json ./tsconfig.json
+COPY package.json pnpm-lock.yaml ./
+RUN pnpm install --prod --frozen-lockfile --ignore-scripts && pnpm store prune
-# 安装必要的WebSocket依赖(兼容多架构)
-USER root
-RUN corepack enable && corepack prepare pnpm@latest --activate && \
- # 使用 --no-optional 避免某些架构下的可选依赖问题
- pnpm install --prod --no-optional ws && \
- # 清理安装缓存减小镜像大小
- pnpm store prune
+COPY --from=builder --chown=orangetv:nodejs /app/dist ./dist
+COPY --from=builder --chown=orangetv:nodejs /app/public ./public
-# 创建健康检查脚本(在切换用户之前以root权限创建)
-RUN echo '#!/usr/bin/env node\n\
-const http = require("http");\n\
-const options = {\n\
- hostname: "localhost",\n\
- port: 3000,\n\
- path: "/api/health",\n\
- method: "GET",\n\
- timeout: 5000\n\
-};\n\
-\n\
-const req = http.request(options, (res) => {\n\
- if (res.statusCode === 200) {\n\
- console.log("Health check passed");\n\
- process.exit(0);\n\
- } else {\n\
- console.log(`Health check failed with status: ${res.statusCode}`);\n\
- process.exit(1);\n\
- }\n\
-});\n\
-\n\
-req.on("error", (err) => {\n\
- console.log(`Health check error: ${err.message}`);\n\
- process.exit(1);\n\
-});\n\
-\n\
-req.on("timeout", () => {\n\
- console.log("Health check timeout");\n\
- req.destroy();\n\
- process.exit(1);\n\
-});\n\
-\n\
-req.setTimeout(5000);\n\
-req.end();' > /app/healthcheck.js && \
- chmod +x /app/healthcheck.js && \
- chown nextjs:nodejs /app/healthcheck.js
+RUN cat > /app/healthcheck.js <<'EOF'
+const http = require('http');
-# 切回非特权用户
-USER nextjs
+const req = http.request(
+ {
+ hostname: 'localhost',
+ port: Number(process.env.PORT || 3000),
+ path: '/api/health',
+ method: 'GET',
+ timeout: 5000,
+ },
+ (res) => {
+ process.exit(res.statusCode === 200 ? 0 : 1);
+ }
+);
-# 暴露HTTP和WebSocket端口
-EXPOSE 3000 3001
+req.on('error', () => process.exit(1));
+req.on('timeout', () => {
+ req.destroy();
+ process.exit(1);
+});
+req.end();
+EOF
-# 添加健康检查
-HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
+RUN chown orangetv:nodejs /app/healthcheck.js
+
+USER orangetv
+
+EXPOSE 3000
+
+HEALTHCHECK --interval=30s --timeout=10s --start-period=20s --retries=3 \
CMD node /app/healthcheck.js
-# 设置WebSocket端口环境变量
-ENV WS_PORT=3001
-
-# 使用最终的生产环境脚本,分离WebSocket服务
-CMD ["node", "production-final.js"]
\ No newline at end of file
+CMD ["node", "dist/server/index.js"]
diff --git a/README.md b/README.md
index 84e4596..e77bc3b 100644
--- a/README.md
+++ b/README.md
@@ -4,13 +4,14 @@
-> 🎬 **OrangeTV** 是一个开箱即用的、跨平台的影视聚合播放器。它基于 **Next.js 14** + **Tailwind CSS** + **TypeScript** 构建,支持多资源搜索、在线播放、收藏同步、播放记录、云端存储,让你可以随时随地畅享海量免费影视内容。
+> 🎬 **OrangeTV** 是一个开箱即用的、跨平台的影视聚合播放器。它基于 **Vite + React**、**Fastify**、**Tailwind CSS** 和 **TypeScript** 构建,支持多资源搜索、在线播放、收藏同步、播放记录、云端存储,让你可以随时随地畅享海量免费影视内容。
-
-
-
+
+
+
+


@@ -42,6 +43,7 @@
## 🗺 目录
- [技术栈](#技术栈)
+- [本地开发环境](#本地开发环境)
- [部署](#部署)
- [配置文件](#配置文件)
- [自动更新](#自动更新)
@@ -56,13 +58,20 @@
| 分类 | 主要依赖 |
| --------- | ----------------------------------------------------------------------------------------------------- |
-| 前端框架 | [Next.js 14](https://nextjs.org/) · App Router |
-| UI & 样式 | [Tailwind CSS 3](https://tailwindcss.com/) |
-| 语言 | TypeScript 4 |
+| 前端框架 | [Vite](https://vite.dev/) · [React Router](https://reactrouter.com/) |
+| 后端 | [Fastify](https://fastify.dev/) |
+| UI & 样式 | [Tailwind CSS 4](https://tailwindcss.com/) |
+| 语言 | TypeScript 5 |
| 播放器 | [ArtPlayer](https://github.com/zhw2590582/ArtPlayer) · [HLS.js](https://github.com/video-dev/hls.js/) |
| 代码质量 | ESLint · Prettier · Jest |
| 部署 | Docker |
+## 本地开发环境
+
+- Node.js:`v24.14.1`,仓库通过 `.nvmrc` 固定,并只支持 Node 24.x。
+- pnpm:`10.14.0`,通过 `packageManager`、`engines` 和 `.npmrc` 校验。
+- 建议先运行 `nvm use`,再运行 `corepack enable && corepack prepare pnpm@10.14.0 --activate`,然后执行 `pnpm install`。
+
## 部署
本项目**仅支持 Docker 或其他基于 Docker 的平台** 部署。
@@ -77,11 +86,10 @@ services:
restart: on-failure
ports:
- '3000:3000'
- - '3001:3001'
environment:
- USERNAME=admin
- PASSWORD=orange
- - NEXT_PUBLIC_STORAGE_TYPE=kvrocks
+ - VITE_STORAGE_TYPE=kvrocks
- KVROCKS_URL=redis://OrangeTV-kvrocks:6666
networks:
- OrangeTV-network
@@ -112,11 +120,10 @@ services:
restart: on-failure
ports:
- '3000:3000'
- - '3001:3001'
environment:
- USERNAME=admin
- PASSWORD=orange
- - NEXT_PUBLIC_STORAGE_TYPE=redis
+ - VITE_STORAGE_TYPE=redis
- REDIS_URL=redis://OrangeTV-redis:6379
networks:
- OrangeTV-network
@@ -149,11 +156,10 @@ services:
restart: on-failure
ports:
- '3000:3000'
- - '3001:3001'
environment:
- USERNAME=admin
- PASSWORD=orange
- - NEXT_PUBLIC_STORAGE_TYPE=upstash
+ - VITE_STORAGE_TYPE=upstash
- UPSTASH_URL=上面 https 开头的 HTTPS ENDPOINT
- UPSTASH_TOKEN=上面的 TOKEN
```
@@ -218,37 +224,37 @@ dockge/komodo 等 docker compose UI 也有自动更新功能
| USERNAME | 站长账号 | 任意字符串 | 无默认,必填字段 |
| PASSWORD | 站长密码 | 任意字符串 | 无默认,必填字段 |
| SITE_BASE | 站点 url | 形如 https://example.com | 空 |
-| NEXT_PUBLIC_SITE_NAME | 站点名称 | 任意字符串 | OrangeTV |
+| VITE_SITE_NAME | 站点名称 | 任意字符串 | OrangeTV |
| ANNOUNCEMENT | 站点公告 | 任意字符串 | 本网站仅提供影视信息搜索服务,所有内容均来自第三方网站。本站不存储任何视频资源,不对任何内容的准确性、合法性、完整性负责。 |
-| NEXT_PUBLIC_STORAGE_TYPE | 播放记录/收藏的存储方式 | redis、kvrocks、upstash | 无默认,必填字段 |
+| VITE_STORAGE_TYPE | 播放记录/收藏的存储方式 | redis、kvrocks、upstash | 无默认,必填字段 |
| KVROCKS_URL | kvrocks 连接 url | 连接 url | 空 |
| REDIS_URL | redis 连接 url | 连接 url | 空 |
| UPSTASH_URL | upstash redis 连接 url | 连接 url | 空 |
| UPSTASH_TOKEN | upstash redis 连接 token | 连接 token | 空 |
-| NEXT_PUBLIC_SEARCH_MAX_PAGE | 搜索接口可拉取的最大页数 | 1-50 | 5 |
-| NEXT_PUBLIC_DOUBAN_PROXY_TYPE | 豆瓣数据源请求方式 | 见下方 | direct |
-| NEXT_PUBLIC_DOUBAN_PROXY | 自定义豆瓣数据代理 URL | url prefix | (空) |
-| NEXT_PUBLIC_DOUBAN_IMAGE_PROXY_TYPE | 豆瓣图片代理类型 | 见下方 | direct |
-| NEXT_PUBLIC_DOUBAN_IMAGE_PROXY | 自定义豆瓣图片代理 URL | url prefix | (空) |
-| NEXT_PUBLIC_DISABLE_YELLOW_FILTER | 关闭色情内容过滤 | true/false | false |
-| NEXT_PUBLIC_FLUID_SEARCH | 是否开启搜索接口流式输出 | true/ false | true |
+| VITE_SEARCH_MAX_PAGE | 搜索接口可拉取的最大页数 | 1-50 | 5 |
+| VITE_DOUBAN_PROXY_TYPE | 豆瓣数据源请求方式 | 见下方 | direct |
+| VITE_DOUBAN_PROXY | 自定义豆瓣数据代理 URL | url prefix | (空) |
+| VITE_DOUBAN_IMAGE_PROXY_TYPE | 豆瓣图片代理类型 | 见下方 | direct |
+| VITE_DOUBAN_IMAGE_PROXY | 自定义豆瓣图片代理 URL | url prefix | (空) |
+| VITE_DISABLE_YELLOW_FILTER | 关闭色情内容过滤 | true/false | false |
+| VITE_FLUID_SEARCH | 是否开启搜索接口流式输出 | true/ false | true |
-NEXT_PUBLIC_DOUBAN_PROXY_TYPE 选项解释:
+VITE_DOUBAN_PROXY_TYPE 选项解释:
- direct: 由服务器直接请求豆瓣源站
- cors-proxy-zwei: 浏览器向 cors proxy 请求豆瓣数据,该 cors proxy 由 [Zwei](https://github.com/bestzwei) 搭建
- cmliussss-cdn-tencent: 浏览器向豆瓣 CDN 请求数据,该 CDN 由 [CMLiussss](https://github.com/cmliu) 搭建,并由腾讯云 cdn 提供加速
- cmliussss-cdn-ali: 浏览器向豆瓣 CDN 请求数据,该 CDN 由 [CMLiussss](https://github.com/cmliu) 搭建,并由阿里云 cdn 提供加速
-- custom: 用户自定义 proxy,由 NEXT_PUBLIC_DOUBAN_PROXY 定义
+- custom: 用户自定义 proxy,由 VITE_DOUBAN_PROXY 定义
-NEXT_PUBLIC_DOUBAN_IMAGE_PROXY_TYPE 选项解释:
+VITE_DOUBAN_IMAGE_PROXY_TYPE 选项解释:
- direct:由浏览器直接请求豆瓣分配的默认图片域名
- server:由服务器代理请求豆瓣分配的默认图片域名
- img3:由浏览器请求豆瓣官方的精品 cdn(阿里云)
- cmliussss-cdn-tencent:由浏览器请求豆瓣 CDN,该 CDN 由 [CMLiussss](https://github.com/cmliu) 搭建,并由腾讯云 cdn 提供加速
- cmliussss-cdn-ali:由浏览器请求豆瓣 CDN,该 CDN 由 [CMLiussss](https://github.com/cmliu) 搭建,并由阿里云 cdn 提供加速
-- custom: 用户自定义 proxy,由 NEXT_PUBLIC_DOUBAN_IMAGE_PROXY 定义
+- custom: 用户自定义 proxy,由 VITE_DOUBAN_IMAGE_PROXY 定义
## AndroidTV 使用
@@ -282,7 +288,7 @@ NEXT_PUBLIC_DOUBAN_IMAGE_PROXY_TYPE 选项解释:
## 致谢
-- [ts-nextjs-tailwind-starter](https://github.com/theodorusclarence/ts-nextjs-tailwind-starter) — 项目最初基于该脚手架。
+- OrangeTV has moved to a pure Vite/Fastify runtime while preserving the original product flows.
- [LibreTV](https://github.com/LibreSpark/LibreTV) — 由此启发,站在巨人的肩膀上。
- [MoonTV](https://github.com/MoonTechLab/LunaTV) — 由此启发,第二次站在巨人的肩膀上。
- [艾福森昵] - 感谢论坛佬友提供的短剧API
diff --git a/docs/superpowers/specs/2026-04-09-orangetv-a2-design.md b/docs/superpowers/specs/2026-04-09-orangetv-a2-design.md
index 412c13e..db93a68 100644
--- a/docs/superpowers/specs/2026-04-09-orangetv-a2-design.md
+++ b/docs/superpowers/specs/2026-04-09-orangetv-a2-design.md
@@ -8,7 +8,7 @@ Chosen direction: `A2` cinematic lounge
OrangeTV will be redesigned around the `A2` direction: a sharper, warmer, projection-inspired interface that treats the app like a screening room rather than a generic streaming dashboard.
-The redesign will not introduce a new information architecture or a new framework. It will keep the current Next.js 14 + Tailwind CSS v3 stack, preserve existing product flows, and refactor the visual system through a new design token layer and updated component styling.
+The redesign will not introduce a new information architecture or a new framework. It will keep the current React + Tailwind CSS stack, preserve existing product flows, and refactor the visual system through a new design token layer and updated component styling.
The visual reset is defined by these decisions:
diff --git a/docs/vite-fastify-refactor-handoff.md b/docs/vite-fastify-refactor-handoff.md
new file mode 100644
index 0000000..9af4a58
--- /dev/null
+++ b/docs/vite-fastify-refactor-handoff.md
@@ -0,0 +1,251 @@
+# Vite/Fastify Refactor Handoff
+
+Last updated: 2026-06-04
+
+## Current State
+
+The repo has been refactored from a Next.js compatibility migration into a Vite React + TypeScript SPA served by a Fastify runtime.
+
+The intended architecture is now:
+
+- Client: Vite, React 19, TypeScript, React Router, Tailwind CSS 4.
+- Server: Fastify on port `3000`, serving both API routes and the SPA on the same origin.
+- Dev: Fastify starts the app and mounts Vite middleware for client assets/HMR.
+- Production: `pnpm build` writes `dist/client` and `dist/server`, then `pnpm start` runs `dist/server/index.js`.
+- Toolchain: Node `v24.14.1` and pnpm `10.14.0`.
+- Docker: official `node:24-alpine` image family with pnpm activated through Corepack.
+
+The repo is still dirty and not committed. Treat this as a handoff snapshot before creating the first refactor commit.
+
+## What Is Good
+
+- Next.js runtime/build dependencies have been removed from production code.
+- Client Next imports have been replaced with app-native React/Vite equivalents:
+ - Router behavior uses `react-router-dom` wrappers.
+ - Image usage no longer depends on `next/image`.
+ - Theme behavior no longer depends on `next-themes`.
+- API routes have been moved to Fastify route modules under `src/server/routes`.
+- The generated Next route adapter path has been removed from the runtime direction.
+- Fastify handles SPA serving, API registration, auth guards, cookies, static assets, and runtime config.
+- React Compiler is configured through the Vite React plugin path using `@vitejs/plugin-react`, `@rolldown/plugin-babel`, and `babel-plugin-react-compiler`.
+- Node tooling is now pinned consistently:
+ - `.nvmrc` is `v24.14.1`.
+ - `package.json` enforces `node >=24 <25` and `pnpm 10.14.0`.
+ - `.npmrc` has `engine-strict=true`.
+ - Docker uses `node:24-alpine`.
+ - Server bundling targets `node24`.
+- Search SSE completion was fixed:
+ - Shortdrama is included as an invoked async source.
+ - Completion reaches the expected source count.
+ - The header text clarifies source progress instead of implying visible card count.
+ - Aggregated search can still show fewer cards than source count by design.
+- Search result cover badges and search-history pill close button were adjusted visually.
+- The exact player URL that previously failed was manually confirmed working during the session:
+ - `http://localhost:3000/play?title=%E6%9C%A8%E4%B9%83%E4%BC%8A&year=2026&stype=movie&source=maotaizy&id=129378`
+
+## Verified
+
+These checks were run with Node `v24.14.1` and pnpm `10.14.0` unless noted.
+
+```bash
+node -v
+# v24.14.1
+
+pnpm -v
+# 10.14.0
+```
+
+```bash
+pnpm typecheck
+# passed
+```
+
+```bash
+pnpm lint
+# passed with warnings
+# 0 errors, 287 warnings
+```
+
+```bash
+pnpm test --runInBand
+# passed
+# 13 test suites, 30 tests
+```
+
+Important: with pnpm `10.14.0`, use `pnpm test --runInBand`. The older-looking form `pnpm test -- --runInBand` forwarded `--` into Jest and caused Jest to treat `--runInBand` as a test pattern.
+
+```bash
+pnpm build
+# passed
+```
+
+```bash
+rg "v20|node20|Node 20|node:20|apk add --no-cache nodejs" . \
+ --glob '!node_modules/**' \
+ --glob '!dist/**'
+# no matches
+```
+
+```bash
+docker build -t orangetv-refactor-smoke:local .
+# passed
+```
+
+Docker build details:
+
+- Pulled and used `node:24-alpine`.
+- Activated `pnpm@10.14.0` in Docker stages.
+- Installed dependencies with the lockfile.
+- Ran in-container `pnpm build`.
+- Exported image as `orangetv-refactor-smoke:local`.
+
+## Verified Earlier In The Refactor
+
+These checks were done before the final Node 24 pin and are still useful context:
+
+- API route parity check found 63 old app API routes and 63 new Fastify route paths.
+- No missing route paths were identified in that comparison.
+- No method mismatches were identified in that comparison.
+- Static Next production-reference scans found no remaining production `next/*` imports.
+- Local dev with Redis was used during debugging.
+- Search route and player route issues were reproduced and fixed against the running dev server.
+
+## Known Warnings
+
+`pnpm lint` currently passes but reports 287 warnings. The warning categories are mostly:
+
+- import sorting
+- `no-console`
+- explicit `any`
+- React hook dependency warnings
+- unused imports/vars
+- non-null assertions
+
+`pnpm test --runInBand` passes but Jest prints an open-handle warning after completion:
+
+- `Jest did not exit one second after the test run has completed.`
+
+`pnpm build` and Docker build pass but include expected build warnings:
+
+- `/runtime-config.js` script in `index.html` cannot be bundled without `type="module"`.
+- `tailwind.config.ts` is reparsed as ESM because `package.json` does not declare `"type": "module"`.
+- `artplayer-plugin-danmuku` uses CommonJS `module` inside an ESM bundle.
+- Some chunks are larger than 500 kB.
+- `hls.js` and `artplayer` dynamic imports are ineffective because they are also imported statically elsewhere.
+- `@rolldown/plugin-babel` dominates build plugin time.
+- Browserslist data is stale.
+
+These warnings existed as non-blocking issues during verification. They should not block the first refactor commit unless release standards require warning cleanup.
+
+## Remaining Gaps
+
+These are the main gaps to address before calling the refactor fully production-ready.
+
+1. Docker runtime smoke was not completed.
+ - The image builds.
+ - The container has not yet been run and checked via `/api/health`, login, player page, and admin page.
+
+2. Production runtime smoke is still limited.
+ - `pnpm build` passes.
+ - A fresh `pnpm start` smoke with HTTP checks was not run after the final Node 24 pin.
+
+3. Chat/WebSocket parity needs focused review.
+ - HTTP chat routes exist in the Fastify route tree.
+ - Full WebSocket behavior should be compared against the old deployment expectations before claiming chat parity.
+
+4. Lint warning debt remains large.
+ - Lint exits successfully, but the warning count is high.
+ - A follow-up cleanup pass should decide which warnings are acceptable and which should become errors.
+
+5. Jest open-handle warning remains.
+ - Tests pass, but async cleanup should be investigated before tightening CI.
+
+6. Bundle-size and import-splitting warnings remain.
+ - Player-related libraries are large and currently defeat some dynamic imports.
+ - This is not a correctness blocker, but it is relevant for performance.
+
+7. Browser smoke should be repeated after the final commit candidate.
+ - Prior manual checks were useful, but a final pass should cover search, detail, play, favorites, play records, admin config, and theme save/load.
+
+8. Git hygiene needs review before commit.
+ - The worktree includes broad refactor changes plus Node 24 pinning.
+ - `docs/superpowers/specs/2026-04-09-orangetv-a2-design.md` was already modified outside this handoff task and should be reviewed before staging.
+
+## Important Commands
+
+Local dev:
+
+```bash
+pnpm dev
+```
+
+Local dev with Redis:
+
+```bash
+pnpm dev:redis
+```
+
+Production build:
+
+```bash
+pnpm build
+```
+
+Production start:
+
+```bash
+pnpm start
+```
+
+Full local verification set:
+
+```bash
+node -v
+pnpm -v
+pnpm typecheck
+pnpm lint
+pnpm test --runInBand
+pnpm build
+docker build -t orangetv-refactor-smoke:local .
+```
+
+Static checks worth keeping:
+
+```bash
+rg "next/|NextRequest|NextResponse|next-env|next.config|eslint-config-next|next-themes|next-pwa" . \
+ --glob '!node_modules/**' \
+ --glob '!dist/**'
+
+rg "v20|node20|Node 20|node:20|apk add --no-cache nodejs" . \
+ --glob '!node_modules/**' \
+ --glob '!dist/**'
+```
+
+## Suggested Next Steps
+
+1. Run the Docker image and smoke it:
+
+```bash
+docker run --rm -p 3000:3000 \
+ -e USERNAME=admin \
+ -e PASSWORD=orange \
+ -e VITE_STORAGE_TYPE=redis \
+ -e REDIS_URL=redis://host.docker.internal:6379 \
+ orangetv-refactor-smoke:local
+```
+
+Then check:
+
+- `GET http://localhost:3000/api/health`
+- login as `admin` / `orange` if those env vars are used
+- `/search?q=%E6%AD%8C%E6%89%8B2026`
+- the known player URL
+- `/admin`
+
+2. Run a final browser smoke on `pnpm dev:redis`.
+
+3. Review chat/WebSocket behavior explicitly.
+
+4. Decide whether to clean warnings now or track them as follow-up issues.
+
+5. Stage only the intended refactor files, then create the first refactor commit.
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..7b76c2d
--- /dev/null
+++ b/index.html
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
OrangeTV
+
+
+
+
+
+
diff --git a/jest.config.js b/jest.config.js
index 8132cc3..41743fd 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -1,32 +1,25 @@
-// eslint-disable-next-line @typescript-eslint/no-var-requires
-const nextJest = require('next/jest');
-
-const createJestConfig = nextJest({
- // Provide the path to your Next.js app to load next.config.js and .env files in your test environment
- dir: './',
-});
-
-// Add any custom config to be passed to Jest
-const customJestConfig = {
- // Add more setup options before each test is run
+module.exports = {
setupFilesAfterEnv: ['
/jest.setup.js'],
-
- // if using TypeScript with a baseUrl set to the root directory then you need the below for alias' to work
moduleDirectories: ['node_modules', '/'],
-
testEnvironment: 'jest-environment-jsdom',
-
- /**
- * Absolute imports and Module Path Aliases
- */
+ transform: {
+ '^.+\\.(ts|tsx)$': [
+ 'babel-jest',
+ {
+ presets: [
+ ['@babel/preset-env', { targets: { node: 'current' } }],
+ ['@babel/preset-react', { runtime: 'automatic' }],
+ '@babel/preset-typescript',
+ ],
+ },
+ ],
+ },
+ testPathIgnorePatterns: ['/node_modules/', '/dist/'],
+ modulePathIgnorePatterns: ['/dist/'],
moduleNameMapper: {
'^@heroui/react$': '/src/__mocks__/heroui-react.tsx',
'^@/(.*)$': '/src/$1',
'^~/(.*)$': '/public/$1',
'^.+\\.(svg)$': '/src/__mocks__/svg.tsx',
},
- modulePathIgnorePatterns: ['/.next/'],
};
-
-// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
-module.exports = createJestConfig(customJestConfig);
diff --git a/jest.setup.js b/jest.setup.js
index 3f1e9e1..1d6ae19 100644
--- a/jest.setup.js
+++ b/jest.setup.js
@@ -1,5 +1 @@
-import '@testing-library/jest-dom/extend-expect';
-
-// Allow router mocks.
-// eslint-disable-next-line no-undef
-jest.mock('next/router', () => require('next-router-mock'));
+require('@testing-library/jest-dom/extend-expect');
diff --git a/next.config.js b/next.config.js
deleted file mode 100644
index 2423566..0000000
--- a/next.config.js
+++ /dev/null
@@ -1,91 +0,0 @@
-/** @type {import('next').NextConfig} */
-/* eslint-disable @typescript-eslint/no-var-requires */
-
-const nextConfig = {
- output: 'standalone',
- eslint: {
- dirs: ['src'],
- ignoreDuringBuilds: true, // 始终在构建时忽略 ESLint 错误
- },
-
- reactStrictMode: false,
- // Uncoment to add domain whitelist
- images: {
- unoptimized: true,
- remotePatterns: [
- {
- protocol: 'https',
- hostname: '**',
- },
- {
- protocol: 'http',
- hostname: '**',
- },
- ],
- },
-
- webpack(config) {
- // Grab the existing rule that handles SVG imports
- const fileLoaderRule = config.module.rules.find((rule) =>
- rule.test?.test?.('.svg')
- );
-
- config.module.rules.push(
- // Reapply the existing rule, but only for svg imports ending in ?url
- {
- ...fileLoaderRule,
- test: /\.svg$/i,
- resourceQuery: /url/, // *.svg?url
- },
- // Convert all other *.svg imports to React components
- {
- test: /\.svg$/i,
- issuer: { not: /\.(css|scss|sass)$/ },
- resourceQuery: { not: /url/ }, // exclude if *.svg?url
- loader: '@svgr/webpack',
- options: {
- dimensions: false,
- titleProp: true,
- },
- }
- );
-
- // Modify the file loader rule to ignore *.svg, since we have it handled now.
- fileLoaderRule.exclude = /\.svg$/i;
-
- // Add alias configuration to ensure proper path resolution in Docker builds
- const path = require('path');
- config.resolve.alias = {
- ...config.resolve.alias,
- '@': path.resolve(__dirname, 'src'),
- '~': path.resolve(__dirname, 'public'),
- };
-
- // Ensure proper file extension resolution
- config.resolve.extensions = ['.ts', '.tsx', '.js', '.jsx', '.json'];
-
- // Add TypeScript module resolution support
- config.resolve.modules = [
- path.resolve(__dirname, 'src'),
- 'node_modules'
- ];
-
- config.resolve.fallback = {
- ...config.resolve.fallback,
- net: false,
- tls: false,
- crypto: false,
- };
-
- return config;
- },
-};
-
-const withPWA = require('next-pwa')({
- dest: 'public',
- disable: process.env.NODE_ENV === 'development',
- register: true,
- skipWaiting: true,
-});
-
-module.exports = withPWA(nextConfig);
diff --git a/nginx.conf b/nginx.conf
index 262f447..e45fb8a 100644
--- a/nginx.conf
+++ b/nginx.conf
@@ -1,46 +1,26 @@
server {
- listen 443 ssl;
- server_name domain.com;
- charset utf-8;
-
- ssl_certificate /home/cert/tvcertificate.crt;
- ssl_certificate_key /home/cert/tvprivate.pem;
-
- location / {
- proxy_pass http://ip:3003;
+ listen 443 ssl;
+ server_name domain.com;
+ charset utf-8;
- # 重要的代理头信息,让 Next.js 服务器知道原始请求的来源
- proxy_set_header Host $host; # 原始主机名
- proxy_set_header X-Real-IP $remote_addr; # 客户端真实 IP
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 代理链
- proxy_set_header X-Forwarded-Proto $scheme; # 原始协议 (http/https)
- proxy_set_header X-Forwarded-Host $host;
- proxy_set_header X-Forwarded-Server $host;
- }
- location /ws-api {
- proxy_pass http://ip:3001;
+ ssl_certificate /home/cert/tvcertificate.crt;
+ ssl_certificate_key /home/cert/tvprivate.pem;
+
+ location / {
+ proxy_pass http://ip:3000;
proxy_http_version 1.1;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
-
- # WebSocket 特定的超时设置(长连接)
- proxy_connect_timeout 7d;
- proxy_send_timeout 7d;
- proxy_read_timeout 7d;
-
- # 禁用缓冲以减少延迟
- proxy_buffering off;
+ proxy_set_header X-Forwarded-Host $host;
+ proxy_set_header X-Forwarded-Server $host;
}
}
server {
- listen 80;
+ listen 80;
+ server_name domain.com;
- server_name domain.com;
-
- return 301 https://domain.com$request_uri;
-}
\ No newline at end of file
+ return 301 https://domain.com$request_uri;
+}
diff --git a/nginx.conf.example b/nginx.conf.example
index 3acb460..65fe113 100644
--- a/nginx.conf.example
+++ b/nginx.conf.example
@@ -1,72 +1,27 @@
-# Nginx配置示例,用于生产环境反向代理
-# 将此文件放置在 /etc/nginx/sites-available/ 并创建符号链接到 sites-enabled/
+# Nginx production reverse proxy example.
-upstream nextjs_app {
+upstream orangetv_app {
server localhost:3000;
}
-upstream websocket_app {
- server localhost:3001;
-}
-
server {
listen 80;
server_name your-domain.com;
-
- # 如果使用HTTPS,取消下面的注释并配置SSL证书
+
+ # If using HTTPS, uncomment and configure certificates.
# listen 443 ssl;
# ssl_certificate /path/to/ssl/cert.pem;
# ssl_certificate_key /path/to/ssl/key.pem;
-
- # 增加请求体大小限制
+
client_max_body_size 100M;
-
- # Next.js应用的主要路由
+
location / {
- proxy_pass http://nextjs_app;
+ proxy_pass http://orangetv_app;
proxy_http_version 1.1;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection 'upgrade';
- proxy_set_header Host $host;
- proxy_cache_bypass $http_upgrade;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Proto $scheme;
- }
-
- # WebSocket专用路由
- location /ws-api {
- proxy_pass http://websocket_app;
- proxy_http_version 1.1;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
-
- # WebSocket特定的超时设置
- proxy_connect_timeout 7d;
- proxy_send_timeout 7d;
- proxy_read_timeout 7d;
- }
-
- # 静态资源缓存
- location /_next/static {
- proxy_pass http://nextjs_app;
- proxy_cache_valid 60m;
- add_header Cache-Control "public, immutable";
- }
-
- location /public {
- proxy_pass http://nextjs_app;
- proxy_cache_valid 60m;
- add_header Cache-Control "public, max-age=3600";
+ proxy_set_header X-Forwarded-Host $host;
}
}
-
-
-
-
-
-
diff --git a/package.json b/package.json
index 692bedc..00b7549 100644
--- a/package.json
+++ b/package.json
@@ -3,17 +3,13 @@
"version": "0.1.0",
"private": true,
"scripts": {
- "dev": "pnpm gen:manifest && node simple-dev.js",
+ "dev": "pnpm gen:manifest && tsx watch src/server/index.ts",
"dev:redis": "node scripts/dev-with-redis.js",
- "dev:complex": "pnpm gen:manifest && node dev-server.js",
- "dev:ws": "node standalone-websocket.js",
- "test:ws": "node test-websocket-connection.js",
+ "dev:complex": "pnpm dev",
"debug:api": "node debug-api.js",
- "build": "pnpm gen:manifest && next build",
- "start": "NODE_ENV=production node server.js",
- "prod": "NODE_ENV=production node production.js",
- "prod:final": "NODE_ENV=production node production-final.js",
- "lint": "next lint",
+ "build": "pnpm gen:manifest && vite build && node scripts/build-server.js",
+ "start": "NODE_ENV=production node dist/server/index.js",
+ "lint": "eslint src --ext .ts,.tsx",
"lint:fix": "eslint src --fix && pnpm format",
"lint:strict": "eslint --max-warnings=0 src",
"typecheck": "tsc --noEmit --incremental false",
@@ -30,6 +26,9 @@
"@dnd-kit/modifiers": "^9.0.0",
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
+ "@fastify/cookie": "^11.0.2",
+ "@fastify/middie": "^9.3.2",
+ "@fastify/static": "^9.1.3",
"@heroui/react": "3.0.5",
"@heroui/styles": "3.0.5",
"@types/crypto-js": "^4.2.2",
@@ -41,30 +40,34 @@
"bs58": "^6.0.0",
"clsx": "^2.0.0",
"crypto-js": "^4.2.0",
+ "fastify": "^5.8.5",
"framer-motion": "^12.18.1",
"he": "^1.2.0",
"hls.js": "^1.6.10",
"lucide-react": "^0.438.0",
"media-icons": "^1.1.5",
- "next": "^15.5.18",
- "next-pwa": "^5.6.0",
- "next-themes": "^0.4.6",
"react": "^19.2.3",
"react-dom": "^19.2.3",
"react-icons": "^5.4.0",
"react-image-crop": "^11.0.10",
+ "react-router-dom": "^7.15.1",
"redis": "^4.6.7",
"swiper": "^11.2.8",
"tailwind-merge": "^3.4.0",
"tailwind-variants": "3.2.2",
"vidstack": "^0.6.15",
+ "vite-plugin-pwa": "^1.3.0",
"ws": "^8.18.3",
"zod": "^3.24.1"
},
"devDependencies": {
+ "@babel/core": "^7.29.7",
+ "@babel/preset-env": "^7.29.7",
+ "@babel/preset-react": "^7.29.7",
+ "@babel/preset-typescript": "^7.29.7",
"@commitlint/cli": "^16.3.0",
"@commitlint/config-conventional": "^16.2.4",
- "@svgr/webpack": "^8.1.0",
+ "@rolldown/plugin-babel": "^0.2.3",
"@tailwindcss/forms": "^0.5.10",
"@tailwindcss/postcss": "^4.3.0",
"@testing-library/dom": "^10.4.1",
@@ -72,28 +75,36 @@
"@testing-library/react": "^16.3.2",
"@types/bs58": "^5.0.0",
"@types/he": "^1.2.3",
+ "@types/jest": "27.5.2",
"@types/node": "24.0.3",
"@types/react": "^19.2.15",
"@types/react-dom": "^19.2.3",
"@types/testing-library__jest-dom": "^5.14.9",
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0",
+ "@vitejs/plugin-react": "^6.0.2",
"autoprefixer": "^10.4.20",
+ "babel-jest": "27.5.1",
+ "babel-plugin-react-compiler": "^1.0.0",
+ "esbuild": "^0.28.0",
"eslint": "^8.57.1",
- "eslint-config-next": "^15.5.18",
"eslint-config-prettier": "^8.10.0",
+ "eslint-plugin-react": "^7.37.5",
+ "eslint-plugin-react-hooks": "^7.1.1",
"eslint-plugin-simple-import-sort": "^7.0.0",
"eslint-plugin-unused-imports": "^2.0.0",
"husky": "^7.0.4",
"jest": "^27.5.1",
"lint-staged": "^12.5.0",
- "next-router-mock": "^0.9.0",
"playwright": "^1.60.0",
"postcss": "^8.5.1",
"prettier": "^2.8.8",
"prettier-plugin-tailwindcss": "^0.5.0",
"tailwindcss": "^4.3.0",
+ "tsx": "^4.22.3",
"typescript": "^5.9.3",
+ "undici": "^8.3.0",
+ "vite": "^8.0.14",
"webpack-obfuscator": "^3.5.1"
},
"lint-staged": {
@@ -105,5 +116,9 @@
"prettier -w"
]
},
- "packageManager": "pnpm@10.14.0"
+ "packageManager": "pnpm@10.14.0",
+ "engines": {
+ "node": ">=24 <25",
+ "pnpm": "10.14.0"
+ }
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 94985cd..cc6099f 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -20,6 +20,15 @@ importers:
'@dnd-kit/utilities':
specifier: ^3.2.2
version: 3.2.2(react@19.2.3)
+ '@fastify/cookie':
+ specifier: ^11.0.2
+ version: 11.0.2
+ '@fastify/middie':
+ specifier: ^9.3.2
+ version: 9.3.2
+ '@fastify/static':
+ specifier: ^9.1.3
+ version: 9.1.3
'@heroui/react':
specifier: 3.0.5
version: 3.0.5(@react-spectrum/provider@3.11.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@types/react-dom@19.2.3(@types/react@19.2.15))(@types/react@19.2.15)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.3.0)
@@ -53,6 +62,9 @@ importers:
crypto-js:
specifier: ^4.2.0
version: 4.2.0
+ fastify:
+ specifier: ^5.8.5
+ version: 5.8.5
framer-motion:
specifier: ^12.18.1
version: 12.18.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
@@ -68,15 +80,6 @@ importers:
media-icons:
specifier: ^1.1.5
version: 1.1.5
- next:
- specifier: ^15.5.18
- version: 15.5.18(@babel/core@7.27.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- next-pwa:
- specifier: ^5.6.0
- version: 5.6.0(@babel/core@7.27.4)(@types/babel__core@7.20.5)(next@15.5.18(@babel/core@7.27.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(webpack@5.99.9)
- next-themes:
- specifier: ^0.4.6
- version: 0.4.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
react:
specifier: ^19.2.3
version: 19.2.3
@@ -89,6 +92,9 @@ importers:
react-image-crop:
specifier: ^11.0.10
version: 11.0.10(react@19.2.3)
+ react-router-dom:
+ specifier: ^7.15.1
+ version: 7.15.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
redis:
specifier: ^4.6.7
version: 4.7.1
@@ -104,6 +110,9 @@ importers:
vidstack:
specifier: ^0.6.15
version: 0.6.15
+ vite-plugin-pwa:
+ specifier: ^1.3.0
+ version: 1.3.0(vite@8.0.14(@types/node@24.0.3)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.43.1)(tsx@4.22.3))(workbox-build@6.6.0(@types/babel__core@7.20.5))(workbox-window@6.6.0)
ws:
specifier: ^8.18.3
version: 8.18.3
@@ -111,15 +120,27 @@ importers:
specifier: ^3.24.1
version: 3.25.67
devDependencies:
+ '@babel/core':
+ specifier: ^7.29.7
+ version: 7.29.7
+ '@babel/preset-env':
+ specifier: ^7.29.7
+ version: 7.29.7(@babel/core@7.29.7)
+ '@babel/preset-react':
+ specifier: ^7.29.7
+ version: 7.29.7(@babel/core@7.29.7)
+ '@babel/preset-typescript':
+ specifier: ^7.29.7
+ version: 7.29.7(@babel/core@7.29.7)
'@commitlint/cli':
specifier: ^16.3.0
version: 16.3.0
'@commitlint/config-conventional':
specifier: ^16.2.4
version: 16.2.4
- '@svgr/webpack':
- specifier: ^8.1.0
- version: 8.1.0(typescript@5.9.3)
+ '@rolldown/plugin-babel':
+ specifier: ^0.2.3
+ version: 0.2.3(@babel/core@7.29.7)(@babel/runtime@7.27.6)(rolldown@1.0.2)(vite@8.0.14(@types/node@24.0.3)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.43.1)(tsx@4.22.3))
'@tailwindcss/forms':
specifier: ^0.5.10
version: 0.5.10(tailwindcss@4.3.0)
@@ -141,6 +162,9 @@ importers:
'@types/he':
specifier: ^1.2.3
version: 1.2.3
+ '@types/jest':
+ specifier: 27.5.2
+ version: 27.5.2
'@types/node':
specifier: 24.0.3
version: 24.0.3
@@ -159,18 +183,33 @@ importers:
'@typescript-eslint/parser':
specifier: ^5.62.0
version: 5.62.0(eslint@8.57.1)(typescript@5.9.3)
+ '@vitejs/plugin-react':
+ specifier: ^6.0.2
+ version: 6.0.2(@rolldown/plugin-babel@0.2.3(@babel/core@7.29.7)(@babel/runtime@7.27.6)(rolldown@1.0.2)(vite@8.0.14(@types/node@24.0.3)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.43.1)(tsx@4.22.3)))(babel-plugin-react-compiler@1.0.0)(vite@8.0.14(@types/node@24.0.3)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.43.1)(tsx@4.22.3))
autoprefixer:
specifier: ^10.4.20
version: 10.4.21(postcss@8.5.6)
+ babel-jest:
+ specifier: 27.5.1
+ version: 27.5.1(@babel/core@7.29.7)
+ babel-plugin-react-compiler:
+ specifier: ^1.0.0
+ version: 1.0.0
+ esbuild:
+ specifier: ^0.28.0
+ version: 0.28.0
eslint:
specifier: ^8.57.1
version: 8.57.1
- eslint-config-next:
- specifier: ^15.5.18
- version: 15.5.18(eslint@8.57.1)(typescript@5.9.3)
eslint-config-prettier:
specifier: ^8.10.0
version: 8.10.0(eslint@8.57.1)
+ eslint-plugin-react:
+ specifier: ^7.37.5
+ version: 7.37.5(eslint@8.57.1)
+ eslint-plugin-react-hooks:
+ specifier: ^7.1.1
+ version: 7.1.1(eslint@8.57.1)
eslint-plugin-simple-import-sort:
specifier: ^7.0.0
version: 7.0.0(eslint@8.57.1)
@@ -186,9 +225,6 @@ importers:
lint-staged:
specifier: ^12.5.0
version: 12.5.0
- next-router-mock:
- specifier: ^0.9.0
- version: 0.9.13(next@15.5.18(@babel/core@7.27.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)
playwright:
specifier: ^1.60.0
version: 1.60.0
@@ -204,12 +240,21 @@ importers:
tailwindcss:
specifier: ^4.3.0
version: 4.3.0
+ tsx:
+ specifier: ^4.22.3
+ version: 4.22.3
typescript:
specifier: ^5.9.3
version: 5.9.3
+ undici:
+ specifier: ^8.3.0
+ version: 8.3.0
+ vite:
+ specifier: ^8.0.14
+ version: 8.0.14(@types/node@24.0.3)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.43.1)(tsx@4.22.3)
webpack-obfuscator:
specifier: ^3.5.1
- version: 3.5.1(javascript-obfuscator@4.1.1)(webpack@5.99.9)
+ version: 3.5.1(javascript-obfuscator@4.1.1)(webpack@5.99.9(esbuild@0.28.0))
packages:
@@ -238,10 +283,6 @@ packages:
resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
engines: {node: '>=10'}
- '@ampproject/remapping@2.3.0':
- resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
- engines: {node: '>=6.0.0'}
-
'@apideck/better-ajv-errors@0.3.6':
resolution: {integrity: sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==}
engines: {node: '>=10'}
@@ -252,24 +293,36 @@ packages:
resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==}
engines: {node: '>=6.9.0'}
- '@babel/compat-data@7.27.5':
- resolution: {integrity: sha512-KiRAp/VoJaWkkte84TvUd9qjdbZAdiqyvMxrGl1N6vzFogKmaLgoM3L1kgtLicp2HP5fBJS8JrZKLVIZGVJAVg==}
+ '@babel/code-frame@7.29.7':
+ resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==}
engines: {node: '>=6.9.0'}
- '@babel/core@7.27.4':
- resolution: {integrity: sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==}
+ '@babel/compat-data@7.29.7':
+ resolution: {integrity: sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/core@7.29.7':
+ resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==}
engines: {node: '>=6.9.0'}
'@babel/generator@7.27.5':
resolution: {integrity: sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==}
engines: {node: '>=6.9.0'}
+ '@babel/generator@7.29.7':
+ resolution: {integrity: sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==}
+ engines: {node: '>=6.9.0'}
+
'@babel/helper-annotate-as-pure@7.27.3':
resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==}
engines: {node: '>=6.9.0'}
- '@babel/helper-compilation-targets@7.27.2':
- resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==}
+ '@babel/helper-annotate-as-pure@7.29.7':
+ resolution: {integrity: sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-compilation-targets@7.29.7':
+ resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==}
engines: {node: '>=6.9.0'}
'@babel/helper-create-class-features-plugin@7.27.1':
@@ -278,27 +331,52 @@ packages:
peerDependencies:
'@babel/core': ^7.0.0
+ '@babel/helper-create-class-features-plugin@7.29.7':
+ resolution: {integrity: sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
'@babel/helper-create-regexp-features-plugin@7.27.1':
resolution: {integrity: sha512-uVDC72XVf8UbrH5qQTc18Agb8emwjTiZrQE11Nv3CuBEZmVvTwwE9CBUEvHku06gQCAyYf8Nv6ja1IN+6LMbxQ==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
+ '@babel/helper-create-regexp-features-plugin@7.29.7':
+ resolution: {integrity: sha512-907Uymvqgg1dwUA+7IGwFAOSYzQOuzPXKNJ1yxzwPffzkYFg2q2eHi1fIOs6sXkG9NbIUMunnUlkYsfRFNvomg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
'@babel/helper-define-polyfill-provider@0.6.4':
resolution: {integrity: sha512-jljfR1rGnXXNWnmQg2K3+bvhkxB51Rl32QRaOTuwwjviGrHzIbSc8+x9CpraDtbT7mfyjXObULP4w/adunNwAw==}
peerDependencies:
'@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0
+ '@babel/helper-define-polyfill-provider@0.6.8':
+ resolution: {integrity: sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==}
+ peerDependencies:
+ '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0
+
+ '@babel/helper-globals@7.29.7':
+ resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==}
+ engines: {node: '>=6.9.0'}
+
'@babel/helper-member-expression-to-functions@7.27.1':
resolution: {integrity: sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==}
engines: {node: '>=6.9.0'}
- '@babel/helper-module-imports@7.27.1':
- resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==}
+ '@babel/helper-member-expression-to-functions@7.29.7':
+ resolution: {integrity: sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg==}
engines: {node: '>=6.9.0'}
- '@babel/helper-module-transforms@7.27.3':
- resolution: {integrity: sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==}
+ '@babel/helper-module-imports@7.29.7':
+ resolution: {integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-module-transforms@7.29.7':
+ resolution: {integrity: sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
@@ -307,44 +385,80 @@ packages:
resolution: {integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==}
engines: {node: '>=6.9.0'}
+ '@babel/helper-optimise-call-expression@7.29.7':
+ resolution: {integrity: sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong==}
+ engines: {node: '>=6.9.0'}
+
'@babel/helper-plugin-utils@7.27.1':
resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==}
engines: {node: '>=6.9.0'}
+ '@babel/helper-plugin-utils@7.29.7':
+ resolution: {integrity: sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==}
+ engines: {node: '>=6.9.0'}
+
'@babel/helper-remap-async-to-generator@7.27.1':
resolution: {integrity: sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
+ '@babel/helper-remap-async-to-generator@7.29.7':
+ resolution: {integrity: sha512-16AMiW26DbXWBbr3B8wNozKM0ydMLB892vaOaJW/fPJdnT8vJk5sdkQcU/isqUxyCE0cEoa8wZOcbgDuC4b6Og==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
'@babel/helper-replace-supers@7.27.1':
resolution: {integrity: sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
+ '@babel/helper-replace-supers@7.29.7':
+ resolution: {integrity: sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
'@babel/helper-skip-transparent-expression-wrappers@7.27.1':
resolution: {integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==}
engines: {node: '>=6.9.0'}
+ '@babel/helper-skip-transparent-expression-wrappers@7.29.7':
+ resolution: {integrity: sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==}
+ engines: {node: '>=6.9.0'}
+
'@babel/helper-string-parser@7.27.1':
resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==}
engines: {node: '>=6.9.0'}
+ '@babel/helper-string-parser@7.29.7':
+ resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==}
+ engines: {node: '>=6.9.0'}
+
'@babel/helper-validator-identifier@7.27.1':
resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==}
engines: {node: '>=6.9.0'}
- '@babel/helper-validator-option@7.27.1':
- resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==}
+ '@babel/helper-validator-identifier@7.29.7':
+ resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-validator-option@7.29.7':
+ resolution: {integrity: sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==}
engines: {node: '>=6.9.0'}
'@babel/helper-wrap-function@7.27.1':
resolution: {integrity: sha512-NFJK2sHUvrjo8wAU/nQTWU890/zB2jj0qBcCbZbbf+005cAsv6tMjXz31fBign6M5ov1o0Bllu+9nbqkfsjjJQ==}
engines: {node: '>=6.9.0'}
- '@babel/helpers@7.27.6':
- resolution: {integrity: sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==}
+ '@babel/helper-wrap-function@7.29.7':
+ resolution: {integrity: sha512-iES0Skag9ERIF68aXadpO6dbXa03mNWK3sEqJaMnLNs/eC3l0lkImdfoy6Y09/SfkpawdAB4RjQ7PVA7TcVGdw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helpers@7.29.7':
+ resolution: {integrity: sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==}
engines: {node: '>=6.9.0'}
'@babel/parser@7.27.5':
@@ -352,36 +466,77 @@ packages:
engines: {node: '>=6.0.0'}
hasBin: true
+ '@babel/parser@7.29.7':
+ resolution: {integrity: sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+
'@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.27.1':
resolution: {integrity: sha512-QPG3C9cCVRQLxAVwmefEmwdTanECuUBMQZ/ym5kiw3XKCGA7qkuQLcjWWHcrD/GKbn/WmJwaezfuuAOcyKlRPA==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
+ '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.29.7':
+ resolution: {integrity: sha512-j8SrR0zLZrRsC09DlszEx8FpMiwukKffYXMK0d5LmOglO7vGG6sz/BR/20yHqWH+Lnn31JTt2PE3hIWNgM2J6w==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
'@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1':
resolution: {integrity: sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
+ '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.29.7':
+ resolution: {integrity: sha512-r8j8escF+U2FUHo0KOhPUdMzUO+jp9fInva6+ACVAF3Y97Ev+5iNZwiqTghmzNeWwDkOPlYuTcfb1vDaoZKmAQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
'@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1':
resolution: {integrity: sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
+ '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.29.7':
+ resolution: {integrity: sha512-GE1TFSiuFeGsCxmYXZl8HwoPrVlwe4rHPFE8weieGKZqnDORK+Ar3vgWMgW+AOxQ6/2TgLSKx9p6W7O4rC6qgQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/plugin-bugfix-safari-rest-destructuring-rhs-array@7.29.7':
+ resolution: {integrity: sha512-oBNVCvnO5tND+xSopWvV8WNGfpTfgP4Zr/YXXSj8zfmcPktp5Ku/aZlsIowgSD4fjmgHn6sGmB9APVsU5zOdhA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
'@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1':
resolution: {integrity: sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.13.0
+ '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.29.7':
+ resolution: {integrity: sha512-QQt9qKHZ2sg/kivaLr7lnQr8HVrQDdBNSfCsTjiDxRuX/K5ORyKq+Bu8Xr0cDE3Dfkv0cw28Ve0EKyKMvulkOw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.13.0
+
'@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.27.1':
resolution: {integrity: sha512-6BpaYGDavZqkI6yT+KSPdpZFfpnd68UKXbcjI9pJ13pvHhPrCKWOOLp+ysvMeA+DxnhuPpgIaRpxRxo5A9t5jw==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
+ '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.29.7':
+ resolution: {integrity: sha512-pn6QacGLgvCcwc+syUhKE/qSjV2D1IHDB84RNxWYSt1mW3K/SCtjinZ2p0cETJxAWBjPy3K/1lHwG5BjjPxNlw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
'@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2':
resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==}
engines: {node: '>=6.9.0'}
@@ -415,12 +570,24 @@ packages:
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-syntax-import-assertions@7.29.7':
+ resolution: {integrity: sha512-/An1OCBN93thpBAGyfsK2pcf0jvju1SAtKkL2Ny++B5Sy6sqgzXDQH1cZxWbF96Wuk+bn41MDA9bLd4VVAw6rw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-syntax-import-attributes@7.27.1':
resolution: {integrity: sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-syntax-import-attributes@7.29.7':
+ resolution: {integrity: sha512-zGYcYfq/WmZ4V+kBIXQon9dSSc8ircGZqw9ZaNhhGj9nZkeBu1jHLBDQqYYi5WA9uawvA2sIMbry2nCFhf5Djg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-syntax-import-meta@7.10.4':
resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==}
peerDependencies:
@@ -431,8 +598,8 @@ packages:
peerDependencies:
'@babel/core': ^7.0.0-0
- '@babel/plugin-syntax-jsx@7.27.1':
- resolution: {integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==}
+ '@babel/plugin-syntax-jsx@7.29.7':
+ resolution: {integrity: sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
@@ -485,6 +652,12 @@ packages:
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-syntax-typescript@7.29.7':
+ resolution: {integrity: sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-syntax-unicode-sets-regex@7.18.6':
resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==}
engines: {node: '>=6.9.0'}
@@ -497,254 +670,482 @@ packages:
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-arrow-functions@7.29.7':
+ resolution: {integrity: sha512-N7zArUXWzAMzm+/N0uPBeVB3Fam5lMxtUwMmDK5f/IBBS7a7p1qeUoxd/6CckXoxUdgsntq1Dh8xNW06maZbDQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-async-generator-functions@7.27.1':
resolution: {integrity: sha512-eST9RrwlpaoJBDHShc+DS2SG4ATTi2MYNb4OxYkf3n+7eb49LWpnS+HSpVfW4x927qQwgk8A2hGNVaajAEw0EA==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-async-generator-functions@7.29.7':
+ resolution: {integrity: sha512-d98gXZkgswvkyohMBABkhm3GeXhYj8psWfwQ2C7gtfrKGTykQa/iOIi+JJhwMjPlZ6Vm2XN+DCf3Es1EoG4ZLA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-async-to-generator@7.27.1':
resolution: {integrity: sha512-NREkZsZVJS4xmTr8qzE5y8AfIPqsdQfRuUiLRTEzb7Qii8iFWCyDKaUV2c0rCuh4ljDZ98ALHP/PetiBV2nddA==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-async-to-generator@7.29.7':
+ resolution: {integrity: sha512-pcUb2SS+RMo9TWVBwKGI5ShtoG7R+zBsFmCKDa6fe8c+hPr3XJlZgoE5j6i8W7gDjhyvy+85vmYexanvXh3d1w==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-block-scoped-functions@7.27.1':
resolution: {integrity: sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-block-scoped-functions@7.29.7':
+ resolution: {integrity: sha512-cUSmjh72N+rN4PrkFlN1dJwNCwjVp5d38/CQrEsFggkD10UiFlBFgdH3tv5dNsLuHY+3S8db2xCHjhZcv5WgvA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-block-scoping@7.27.5':
resolution: {integrity: sha512-JF6uE2s67f0y2RZcm2kpAUEbD50vH62TyWVebxwHAlbSdM49VqPz8t4a1uIjp4NIOIZ4xzLfjY5emt/RCyC7TQ==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-block-scoping@7.29.7':
+ resolution: {integrity: sha512-ONyr4+AZhKh8yKWInVxU9AXA9EbsyeLcL6V0dJy6M2/62vuvpGm29zzuymbTpdc451GEpDIdAyPLP3r+P61yKQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-class-properties@7.27.1':
resolution: {integrity: sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-class-properties@7.29.7':
+ resolution: {integrity: sha512-GtcpjFvanPfzNQi3eTitsCqtRRmmqzpy/A+yhTR1HaZo1Ly3EA8ZXxlPyHdR8/IuRMYc3E4wdGBewB2QKQjAaA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-class-static-block@7.27.1':
resolution: {integrity: sha512-s734HmYU78MVzZ++joYM+NkJusItbdRcbm+AGRgJCt3iA+yux0QpD9cBVdz3tKyrjVYWRl7j0mHSmv4lhV0aoA==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.12.0
+ '@babel/plugin-transform-class-static-block@7.29.7':
+ resolution: {integrity: sha512-kibJgmEdX2iMwsHY2tSZNDgj8PwIlCQz7FK9KuGKO8zsuoUwSEhoNnNVp/emKWrbY4HeO6kkXfdMqRKKKXBm2A==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.12.0
+
'@babel/plugin-transform-classes@7.27.1':
resolution: {integrity: sha512-7iLhfFAubmpeJe/Wo2TVuDrykh/zlWXLzPNdL0Jqn/Xu8R3QQ8h9ff8FQoISZOsw74/HFqFI7NX63HN7QFIHKA==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-classes@7.29.7':
+ resolution: {integrity: sha512-qV0OGGBVacduzQHE649JyCneOFI/maT+YKsO+K4Yi3xv2wTPNjM/W2o2gdzMwEAZz7fXNTHAe0NcSg30bIN69g==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-computed-properties@7.27.1':
resolution: {integrity: sha512-lj9PGWvMTVksbWiDT2tW68zGS/cyo4AkZ/QTp0sQT0mjPopCmrSkzxeXkznjqBxzDI6TclZhOJbBmbBLjuOZUw==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-computed-properties@7.29.7':
+ resolution: {integrity: sha512-RK7/IyU5phpuCdBAuig5VkzG/EnbDaui5SQGdU9BFrHdV+mV4cUjLMQ9lJDjLNtWHsqtiefpGZUXQP2BiTYMsA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-destructuring@7.27.3':
resolution: {integrity: sha512-s4Jrok82JpiaIprtY2nHsYmrThKvvwgHwjgd7UMiYhZaN0asdXNLr0y+NjTfkA7SyQE5i2Fb7eawUOZmLvyqOA==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-destructuring@7.29.7':
+ resolution: {integrity: sha512-iPX8aD6H9zV5s7ZsqTdNocPN/MGQ5sSMnElKrktxjJRMnB2jN/1p2+R7GkfD6CAYoVFqy5A4XnSIUeGgJzIWpg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-dotall-regex@7.27.1':
resolution: {integrity: sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-dotall-regex@7.29.7':
+ resolution: {integrity: sha512-3qc18hsD2RdZiyJNDNc7HQpv6xbncwh8FYtxNFFzclSyh/trPD9KkVR9BDECUjDLvb7yJVF15GfYUuC+LMkkiQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-duplicate-keys@7.27.1':
resolution: {integrity: sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-duplicate-keys@7.29.7':
+ resolution: {integrity: sha512-6IvRRriEMqnBwD6chtxdLpMYCHWEzN+oL5cyQtjykya19UgzbmKhxmhZgKC/LHxS2nYr9Q/qYPZ5Lr6jOL9+yQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.27.1':
resolution: {integrity: sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
+ '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.7':
+ resolution: {integrity: sha512-2wiIyo2BjtgU7HufSeDnL9L2O7zr8jmhFKuSr65VpRkUiRKRNpb0mdlk56+XPPKoIrfHqzbMuglDvZun0RISsA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
'@babel/plugin-transform-dynamic-import@7.27.1':
resolution: {integrity: sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-dynamic-import@7.29.7':
+ resolution: {integrity: sha512-giOlEm/EFjfjr+te9NsdjkUo2v4f8rS/SXPumRVHAtbNcyNlvtREkU1dZzaIDclNpnaVhlCqRdFKhJBjBikzLg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-explicit-resource-management@7.29.7':
+ resolution: {integrity: sha512-Rstj7coNz8sE+7Ju7ihpHLI564lsK5pUpNNlvptCIC/16E/S5hbl6n3kESPKdNRmqEWlpn5xpS5Q2dvXBsySLw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-exponentiation-operator@7.27.1':
resolution: {integrity: sha512-uspvXnhHvGKf2r4VVtBpeFnuDWsJLQ6MF6lGJLC89jBR1uoVeqM416AZtTuhTezOfgHicpJQmoD5YUakO/YmXQ==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-exponentiation-operator@7.29.7':
+ resolution: {integrity: sha512-zFpMOTLZBdW5LfObqcSbL6kefg4R4eLdmvS0wbN9M6D5Mym/sKm9toOoWyVOa+xDjvCnuWcHls2YonXwHvH3CQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-export-namespace-from@7.27.1':
resolution: {integrity: sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-export-namespace-from@7.29.7':
+ resolution: {integrity: sha512-24B2nOy2TeJSMheqwPD4DDQOV/elLSIlKxjZt4i05H5AgdPdWR3n18HnNrcJ+j76WJd9gbwb9jPjNYUy6RautA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-for-of@7.27.1':
resolution: {integrity: sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-for-of@7.29.7':
+ resolution: {integrity: sha512-zeSIHh0+E1Um1WJRXCFlHQYu2ieJNdivLLjlBEp+dIBu3S51n+SZZmIXjxnItw6pz56Cn+KvK68BIBVsxq2JiQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-function-name@7.27.1':
resolution: {integrity: sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-function-name@7.29.7':
+ resolution: {integrity: sha512-otRWaHXE6fbAGkePvaj/kvs3HsqXfPhlnzwSOlnFgbqCPMd975dW+4wZ00WFBt+/YlBGcJwNrARQTOJOb4ZrIg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-json-strings@7.27.1':
resolution: {integrity: sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-json-strings@7.29.7':
+ resolution: {integrity: sha512-RRnE2+eon1rJAq8MnoF1b5kTpY1vU88twHcvcKMrsqP/jxIRqDVs9iJB5fqPuqyeFAW0wJo4MlUIPpQCq/aRsg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-literals@7.27.1':
resolution: {integrity: sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-literals@7.29.7':
+ resolution: {integrity: sha512-DZ/oLP21ZuWx1vKqnoNv6/tvEK48AQOBRai40CX9dTjGluvT/YZCyY3rryDtyUqCEoyNroy5KKPwX2iQCiRvyw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-logical-assignment-operators@7.27.1':
resolution: {integrity: sha512-SJvDs5dXxiae4FbSL1aBJlG4wvl594N6YEVVn9e3JGulwioy6z3oPjx/sQBO3Y4NwUu5HNix6KJ3wBZoewcdbw==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-logical-assignment-operators@7.29.7':
+ resolution: {integrity: sha512-A0H91hh6W8MFRkp5TqJmMr39jzGD1A1E1Ysiv2O06Sfbhkapm+XyIzxWCEh5kqwOZ1/8QZ0dY3SeQ7XBqfJd5Q==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-member-expression-literals@7.27.1':
resolution: {integrity: sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-member-expression-literals@7.29.7':
+ resolution: {integrity: sha512-hl1kwFZCCiDyfH25Xmco9jTrkPgnS9pmOzSG7W5I4SaGbLeqKv417hcU2RKmaxoPEgsoJh7ZPOrnPGq99bHoUg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-modules-amd@7.27.1':
resolution: {integrity: sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-modules-amd@7.29.7':
+ resolution: {integrity: sha512-fxtQoH3m5ywUSIfaH0FGCzWu4McsYon5bD3K4XnskC7f+OyQMj7rsOMi4NvvmJ83WwBAg4UCe+ov4VZlqEvyew==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-modules-commonjs@7.27.1':
resolution: {integrity: sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-modules-commonjs@7.29.7':
+ resolution: {integrity: sha512-j0vCldybPC5b5dwCQOJ21uKtHzt7hxLygJTg9eF1ScfaikEDNfzn94XoW5Fi+seBR0nCyL23xaBFFkq7dTM8XQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-modules-systemjs@7.27.1':
resolution: {integrity: sha512-w5N1XzsRbc0PQStASMksmUeqECuzKuTJer7kFagK8AXgpCMkeDMO5S+aaFb7A51ZYDF7XI34qsTX+fkHiIm5yA==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-modules-systemjs@7.29.7':
+ resolution: {integrity: sha512-TM2ZcQLoG2/y4HODiStCo10DibYhWhGWAwVv+EQKmG/7GFl0N+AAmUiXOMKM+aiJ9XBJ9AHVZBvTzMnJ2sM3cQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-modules-umd@7.27.1':
resolution: {integrity: sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-modules-umd@7.29.7':
+ resolution: {integrity: sha512-B4UkaTK3QpgCwJnrxKfMPKdo92CN7OKXAlpAAnM3UPu0Q0lCCk57ylA9AJbRy2v8dDKOPAAWcoR6CMyeoHwRCA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-named-capturing-groups-regex@7.27.1':
resolution: {integrity: sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
+ '@babel/plugin-transform-named-capturing-groups-regex@7.29.7':
+ resolution: {integrity: sha512-vuFoLwr4qnv2xbZ16SQd6uPcH5FNrLHhk/Jzo++0XJFcaDsr4gjJVg6j398oMHiC+83k/GiBzviwF5KBJkPUtQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
'@babel/plugin-transform-new-target@7.27.1':
resolution: {integrity: sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-new-target@7.29.7':
+ resolution: {integrity: sha512-fEo41GmsOUhOBlw8ioo6zvjX5Xc2Lqkzlyfqbpsk3eB6TReV18uhxZ0esfEokVbY2+PVJAQHNKxER6lGrzNd3A==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-nullish-coalescing-operator@7.27.1':
resolution: {integrity: sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-nullish-coalescing-operator@7.29.7':
+ resolution: {integrity: sha512-idmp1dFaekP9GbcMvG24Kvw2BfhFZjHnNJCkV4WuIY4PskJzwI3f1N5OdgYke38T7rftO6ERulFRn2cFeZwRkg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-numeric-separator@7.27.1':
resolution: {integrity: sha512-fdPKAcujuvEChxDBJ5c+0BTaS6revLV7CJL08e4m3de8qJfNIuCc2nc7XJYOjBoTMJeqSmwXJ0ypE14RCjLwaw==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-numeric-separator@7.29.7':
+ resolution: {integrity: sha512-zR7fv/z14OjgHl4AgRtkDBvBMhIzCxqV/qN/2BCRC7LjFwvuzjYe7gDWxC4Wl/SNsLM6SE1IWvRPYMgSJaUvNw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-object-rest-spread@7.27.3':
resolution: {integrity: sha512-7ZZtznF9g4l2JCImCo5LNKFHB5eXnN39lLtLY5Tg+VkR0jwOt7TBciMckuiQIOIW7L5tkQOCh3bVGYeXgMx52Q==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-object-rest-spread@7.29.7':
+ resolution: {integrity: sha512-Ld98jn4c0smUywL57m7SgsHq3OpThOa6LqZJif3G6jYOovPleoFhVrBJ1WegRApSFB2wu4+RelAj9AC9G08Z4A==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-object-super@7.27.1':
resolution: {integrity: sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-object-super@7.29.7':
+ resolution: {integrity: sha512-Ea/diGcw0twB5IlZPO5sgET6fJsLJqPABqTuFWIR+iMPGPZJkATEIWx0wa+aEQ5UY1CBQyP/gkAiLEqn1vBiQA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-optional-catch-binding@7.27.1':
resolution: {integrity: sha512-txEAEKzYrHEX4xSZN4kJ+OfKXFVSWKB2ZxM9dpcE3wT7smwkNmXo5ORRlVzMVdJbD+Q8ILTgSD7959uj+3Dm3Q==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-optional-catch-binding@7.29.7':
+ resolution: {integrity: sha512-sLsyndxK2VwX6yNUOakMb7Sh553ZTe/vVM1XJ+9Z5aW1ytsc8xOIwmyk05NNjN60vkc5/KqoTH6hB4V41LJhng==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-optional-chaining@7.27.1':
resolution: {integrity: sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-optional-chaining@7.29.7':
+ resolution: {integrity: sha512-6GM1dhvK3gNODkXcEcMCOLEDCLSoZ/sBbro2Ax8HURyasQ4NshagQixkRFdh5niI6E4gmA/jYI/4aT7rRos3ZQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-parameters@7.27.1':
resolution: {integrity: sha512-018KRk76HWKeZ5l4oTj2zPpSh+NbGdt0st5S6x0pga6HgrjBOJb24mMDHorFopOOd6YHkLgOZ+zaCjZGPO4aKg==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-parameters@7.29.7':
+ resolution: {integrity: sha512-ZDOBqV/qLYJI0YElr8DcENEyARsFQeESqWXH6gZlghYXuPPjvweuDhP4VyEi4BlUBlLRFZVjxoZDMjxhLW766g==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-private-methods@7.27.1':
resolution: {integrity: sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-private-methods@7.29.7':
+ resolution: {integrity: sha512-/6Rz4DK1ETDEM/bWHsPHcaEe7ZaT1EqSXjtSP/L0DijOYuaUhiRiOKcwpZ8P7zR4xXEHc2ITdiCgBm9Tpyv9ug==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-private-property-in-object@7.27.1':
resolution: {integrity: sha512-5J+IhqTi1XPa0DXF83jYOaARrX+41gOewWbkPyjMNRDqgOCqdffGh8L3f/Ek5utaEBZExjSAzcyjmV9SSAWObQ==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-private-property-in-object@7.29.7':
+ resolution: {integrity: sha512-+BNo06dnrzdNNqCm1X6YUaVv0DKk8Q+JYcoZfOkLhYWNCXzlwTSRq8zGWayT1csjcpNXV9CQTBRRbmTLZac5cA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-property-literals@7.27.1':
resolution: {integrity: sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
- '@babel/plugin-transform-react-constant-elements@7.27.1':
- resolution: {integrity: sha512-edoidOjl/ZxvYo4lSBOQGDSyToYVkTAwyVoa2tkuYTSmjrB1+uAedoL5iROVLXkxH+vRgA7uP4tMg2pUJpZ3Ug==}
+ '@babel/plugin-transform-property-literals@7.29.7':
+ resolution: {integrity: sha512-bOMRLQuI0A5ZqHq3OWJ89/rXpJ/NJrbVhXiP4zwPGMs6kpcVsuTUNjwoE30K0Qm3mf48a/TnRYYD6vPNqcg6jA==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
- '@babel/plugin-transform-react-display-name@7.27.1':
- resolution: {integrity: sha512-p9+Vl3yuHPmkirRrg021XiP+EETmPMQTLr6Ayjj85RLNEbb3Eya/4VI0vAdzQG9SEAl2Lnt7fy5lZyMzjYoZQQ==}
+ '@babel/plugin-transform-react-display-name@7.29.7':
+ resolution: {integrity: sha512-+1wdDMGNb4UPeY3Q4L5yLiYe6TXPXubs4NjrgRFw13hPRLJfEMw2Q5OXkee6/IfdqePIeW4Jjwe3aBh7SdKz4Q==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
- '@babel/plugin-transform-react-jsx-development@7.27.1':
- resolution: {integrity: sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==}
+ '@babel/plugin-transform-react-jsx-development@7.29.7':
+ resolution: {integrity: sha512-Xfy3UVMF04+ypnFbkhvfqtmvwfe92qwQdbGZVonhE+6v35GzlofmOnA1szaZqzb9xYWr0nl1e5EMmzi0DNON1g==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
- '@babel/plugin-transform-react-jsx@7.27.1':
- resolution: {integrity: sha512-2KH4LWGSrJIkVf5tSiBFYuXDAoWRq2MMwgivCf+93dd0GQi8RXLjKA/0EvRnVV5G0hrHczsquXuD01L8s6dmBw==}
+ '@babel/plugin-transform-react-jsx@7.29.7':
+ resolution: {integrity: sha512-WsZulLVBUHXVj2cUcPVx6UE21TpalB6bHbSFErKT0Ib++ax24jjXe73FqlWvdylFOjiuPHYi6VCcgRad1ItN+A==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
- '@babel/plugin-transform-react-pure-annotations@7.27.1':
- resolution: {integrity: sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA==}
+ '@babel/plugin-transform-react-pure-annotations@7.29.7':
+ resolution: {integrity: sha512-H5E+HBgDpr6Q5t+Aj11tL7XkIui1jhbIoArVQnqjgXo5/3YxkN7ZEBcWF4RQlB0T4rrxJQbXS6kiFV6B7XTqUA==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
@@ -755,50 +1156,98 @@ packages:
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-regenerator@7.29.7':
+ resolution: {integrity: sha512-rNNFV0DBAJp988xW2DOntfDoYn1eR8GGF5AT5vYc+rjyfaQkM242c9tZUHHPe7KYaiJizXPWhQTzzdbXySyhBw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-regexp-modifiers@7.27.1':
resolution: {integrity: sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
+ '@babel/plugin-transform-regexp-modifiers@7.29.7':
+ resolution: {integrity: sha512-mB5Fs0VWrJ42ZCmc8114v60qetdaUVNkj9PmSZRmanCZM3S9hm0CFRLjRmYIsuXav14l2jvZ+4T8iiCGnhj3nQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
'@babel/plugin-transform-reserved-words@7.27.1':
resolution: {integrity: sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-reserved-words@7.29.7':
+ resolution: {integrity: sha512-5+YhdpVgmfSmwZyLMftfaiffLRMHjzIRHFHHLdibcSyJm2pasMrKHrO3Ptrt2DRshjvpgjEJJ1zVW14WPq/6QA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-shorthand-properties@7.27.1':
resolution: {integrity: sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-shorthand-properties@7.29.7':
+ resolution: {integrity: sha512-I+WYbGBAiCn7nA6xBrlgPH+MB7HWb4u8pv5S0Pv7OtwNvIFvCCb24YlttKEeUFVurfBCEaOTnuhlqsb7f0Z5Dg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-spread@7.27.1':
resolution: {integrity: sha512-kpb3HUqaILBJcRFVhFUs6Trdd4mkrzcGXss+6/mxUd273PfbWqSDHRzMT2234gIg2QYfAjvXLSquP1xECSg09Q==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-spread@7.29.7':
+ resolution: {integrity: sha512-/u5K1QWada7tbYNqTjMh96718g9NTwh9tfPJMsSmVsQwGT447FskV+KcfeXkXq2GWki4EM/MuTdmBec+hOuVTQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-sticky-regex@7.27.1':
resolution: {integrity: sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-sticky-regex@7.29.7':
+ resolution: {integrity: sha512-BCHzNYJGe9l7EpwwDBN/ztlL2NYFFq8hp9ddjtUEM9f2O7S7kKV/lL6Fwo7IF7NSkYhPK2vO+86nIGltA90MsA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-template-literals@7.27.1':
resolution: {integrity: sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-template-literals@7.29.7':
+ resolution: {integrity: sha512-NCSEJ4sLFU2gqAub45HYh4fus2yQ36rr6ei6vpU7NdoJqCpxvEG8E6eJpscGyXP3VHD2Ny+fSXr04k1hoUrFqA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-typeof-symbol@7.27.1':
resolution: {integrity: sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
- '@babel/plugin-transform-typescript@7.27.1':
- resolution: {integrity: sha512-Q5sT5+O4QUebHdbwKedFBEwRLb02zJ7r4A5Gg2hUoLuU3FjdMcyqcywqUrLCaDsFCxzokf7u9kuy7qz51YUuAg==}
+ '@babel/plugin-transform-typeof-symbol@7.29.7':
+ resolution: {integrity: sha512-223mNGoTkBiTEWFoK+Q6Go3tueMRclO8vxxxxquNCYuNI4jWOofFKJRRDu6SDrB8Sgo1UEGW9T4GAQ8ZyRso1A==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-typescript@7.29.7':
+ resolution: {integrity: sha512-jK52h8LaLc7JarhQV2ofeFMts4H7vnOXnqZNA6fYglBTZewRBE51KWt3BUltW1P+KoPsYkHoJeXePuz4zo2LMw==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
@@ -809,43 +1258,73 @@ packages:
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-unicode-escapes@7.29.7':
+ resolution: {integrity: sha512-jCfXxSjf94lf4E0hKE0AByxF6F3/pVFqRdUUNkDJhsY0m1ZKjnN6ZYyMeHNpzflxb/0q5b7t3p+BE+SLF1WOtA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-unicode-property-regex@7.27.1':
resolution: {integrity: sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-unicode-property-regex@7.29.7':
+ resolution: {integrity: sha512-OgZ+zoAJgZLUCunsTRQ5LAjOywDv5zzZ2/hQ5aMw1pGXyY2rtE8/chXYUmu3AlVHKpm10KEdG9aMwbI/K76ZGw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-unicode-regex@7.27.1':
resolution: {integrity: sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-unicode-regex@7.29.7':
+ resolution: {integrity: sha512-7D/x/23/d/3VqZ0QA+LGbZMlGwZjztBygSWWWsfTPoQ1oQ6Q1P6Mr3d0kk42XabyUVw+fha3LqdRsFqeKqvCyA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-unicode-sets-regex@7.27.1':
resolution: {integrity: sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
+ '@babel/plugin-transform-unicode-sets-regex@7.29.7':
+ resolution: {integrity: sha512-BLOhLht9DOJwIxlmp91wHvkXv1lguuHS3/FwUO8HL1H0u8s4hR1gASVFyilu9iGtcTRYqjTZmlsFFeQletntEg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
'@babel/preset-env@7.27.2':
resolution: {integrity: sha512-Ma4zSuYSlGNRlCLO+EAzLnCmJK2vdstgv+n7aUP+/IKZrOfWHOJVdSJtuub8RzHTj3ahD37k5OKJWvzf16TQyQ==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/preset-env@7.29.7':
+ resolution: {integrity: sha512-GYzX36n1nsciIb0uyH0GHwxwtNwPQIcpxSeiVLDtG/B7jB5xXgchnmL1f/jCX5o+pwnaDBtO60ONSJhEBJfxYA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/preset-modules@0.1.6-no-external-plugins':
resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==}
peerDependencies:
'@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0
- '@babel/preset-react@7.27.1':
- resolution: {integrity: sha512-oJHWh2gLhU9dW9HHr42q0cI0/iHHXTLGe39qvpAZZzagHy0MzYLCnCVV0symeRvzmjHyVU7mw2K06E6u/JwbhA==}
+ '@babel/preset-react@7.29.7':
+ resolution: {integrity: sha512-C+PV1TFUPTmBQGoPBL8j2QmLpZ117YTCwxIZeJOM96GbYMFSc7/pOXU5lVykwnZxyTqQxRsvoRk6f2FktZgGHA==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
- '@babel/preset-typescript@7.27.1':
- resolution: {integrity: sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ==}
+ '@babel/preset-typescript@7.29.7':
+ resolution: {integrity: sha512-/Foi8vKY2EVbed/1eZx0gJEEwHAIxogrySI7rULcRIvhZzbvoE/b5qG5Ghc0WKAFKOHA9SD1x7RsFlOYdutIiQ==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
@@ -858,14 +1337,26 @@ packages:
resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==}
engines: {node: '>=6.9.0'}
+ '@babel/template@7.29.7':
+ resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==}
+ engines: {node: '>=6.9.0'}
+
'@babel/traverse@7.27.4':
resolution: {integrity: sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==}
engines: {node: '>=6.9.0'}
+ '@babel/traverse@7.29.7':
+ resolution: {integrity: sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==}
+ engines: {node: '>=6.9.0'}
+
'@babel/types@7.27.6':
resolution: {integrity: sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==}
engines: {node: '>=6.9.0'}
+ '@babel/types@7.29.7':
+ resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==}
+ engines: {node: '>=6.9.0'}
+
'@bcoe/v8-coverage@0.2.3':
resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
@@ -970,14 +1461,170 @@ packages:
peerDependencies:
react: '>=16.8.0'
- '@emnapi/core@1.4.3':
- resolution: {integrity: sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==}
+ '@emnapi/core@1.10.0':
+ resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==}
'@emnapi/runtime@1.10.0':
resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==}
- '@emnapi/wasi-threads@1.0.2':
- resolution: {integrity: sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==}
+ '@emnapi/wasi-threads@1.2.1':
+ resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==}
+
+ '@esbuild/aix-ppc64@0.28.0':
+ resolution: {integrity: sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [aix]
+
+ '@esbuild/android-arm64@0.28.0':
+ resolution: {integrity: sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [android]
+
+ '@esbuild/android-arm@0.28.0':
+ resolution: {integrity: sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [android]
+
+ '@esbuild/android-x64@0.28.0':
+ resolution: {integrity: sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [android]
+
+ '@esbuild/darwin-arm64@0.28.0':
+ resolution: {integrity: sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@esbuild/darwin-x64@0.28.0':
+ resolution: {integrity: sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@esbuild/freebsd-arm64@0.28.0':
+ resolution: {integrity: sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@esbuild/freebsd-x64@0.28.0':
+ resolution: {integrity: sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@esbuild/linux-arm64@0.28.0':
+ resolution: {integrity: sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@esbuild/linux-arm@0.28.0':
+ resolution: {integrity: sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [linux]
+
+ '@esbuild/linux-ia32@0.28.0':
+ resolution: {integrity: sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [linux]
+
+ '@esbuild/linux-loong64@0.28.0':
+ resolution: {integrity: sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==}
+ engines: {node: '>=18'}
+ cpu: [loong64]
+ os: [linux]
+
+ '@esbuild/linux-mips64el@0.28.0':
+ resolution: {integrity: sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==}
+ engines: {node: '>=18'}
+ cpu: [mips64el]
+ os: [linux]
+
+ '@esbuild/linux-ppc64@0.28.0':
+ resolution: {integrity: sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@esbuild/linux-riscv64@0.28.0':
+ resolution: {integrity: sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==}
+ engines: {node: '>=18'}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@esbuild/linux-s390x@0.28.0':
+ resolution: {integrity: sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==}
+ engines: {node: '>=18'}
+ cpu: [s390x]
+ os: [linux]
+
+ '@esbuild/linux-x64@0.28.0':
+ resolution: {integrity: sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [linux]
+
+ '@esbuild/netbsd-arm64@0.28.0':
+ resolution: {integrity: sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [netbsd]
+
+ '@esbuild/netbsd-x64@0.28.0':
+ resolution: {integrity: sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [netbsd]
+
+ '@esbuild/openbsd-arm64@0.28.0':
+ resolution: {integrity: sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openbsd]
+
+ '@esbuild/openbsd-x64@0.28.0':
+ resolution: {integrity: sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@esbuild/openharmony-arm64@0.28.0':
+ resolution: {integrity: sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@esbuild/sunos-x64@0.28.0':
+ resolution: {integrity: sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [sunos]
+
+ '@esbuild/win32-arm64@0.28.0':
+ resolution: {integrity: sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@esbuild/win32-ia32@0.28.0':
+ resolution: {integrity: sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [win32]
+
+ '@esbuild/win32-x64@0.28.0':
+ resolution: {integrity: sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [win32]
'@eslint-community/eslint-utils@4.7.0':
resolution: {integrity: sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==}
@@ -997,6 +1644,39 @@ packages:
resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ '@fastify/accept-negotiator@2.0.1':
+ resolution: {integrity: sha512-/c/TW2bO/v9JeEgoD/g1G5GxGeCF1Hafdf79WPmUlgYiBXummY0oX3VVq4yFkKKVBKDNlaDUYoab7g38RpPqCQ==}
+
+ '@fastify/ajv-compiler@4.0.5':
+ resolution: {integrity: sha512-KoWKW+MhvfTRWL4qrhUwAAZoaChluo0m0vbiJlGMt2GXvL4LVPQEjt8kSpHI3IBq5Rez8fg+XeH3cneztq+C7A==}
+
+ '@fastify/cookie@11.0.2':
+ resolution: {integrity: sha512-GWdwdGlgJxyvNv+QcKiGNevSspMQXncjMZ1J8IvuDQk0jvkzgWWZFNC2En3s+nHndZBGV8IbLwOI/sxCZw/mzA==}
+
+ '@fastify/error@4.2.0':
+ resolution: {integrity: sha512-RSo3sVDXfHskiBZKBPRgnQTtIqpi/7zhJOEmAxCiBcM7d0uwdGdxLlsCaLzGs8v8NnxIRlfG0N51p5yFaOentQ==}
+
+ '@fastify/fast-json-stringify-compiler@5.0.3':
+ resolution: {integrity: sha512-uik7yYHkLr6fxd8hJSZ8c+xF4WafPK+XzneQDPU+D10r5X19GW8lJcom2YijX2+qtFF1ENJlHXKFM9ouXNJYgQ==}
+
+ '@fastify/forwarded@3.0.1':
+ resolution: {integrity: sha512-JqDochHFqXs3C3Ml3gOY58zM7OqO9ENqPo0UqAjAjH8L01fRZqwX9iLeX34//kiJubF7r2ZQHtBRU36vONbLlw==}
+
+ '@fastify/merge-json-schemas@0.2.1':
+ resolution: {integrity: sha512-OA3KGBCy6KtIvLf8DINC5880o5iBlDX4SxzLQS8HorJAbqluzLRn80UXU0bxZn7UOFhFgpRJDasfwn9nG4FG4A==}
+
+ '@fastify/middie@9.3.2':
+ resolution: {integrity: sha512-5C3xMHJxpfqoHd+xZSHPBI71fpzkoF6wMsYtgzXRyQUNvsIAxJm2yY4r2fUjF0h3rS9MXlo/aXLaXv3s4TL+JQ==}
+
+ '@fastify/proxy-addr@5.1.0':
+ resolution: {integrity: sha512-INS+6gh91cLUjB+PVHfu1UqcB76Sqtpyp7bnL+FYojhjygvOPA9ctiD/JDKsyD9Xgu4hUhCSJBPig/w7duNajw==}
+
+ '@fastify/send@4.1.0':
+ resolution: {integrity: sha512-TMYeQLCBSy2TOFmV95hQWkiTYgC/SEx7vMdV+wnZVX4tt8VBLKzmH8vV9OzJehV0+XBfg+WxPMt5wp+JBUKsVw==}
+
+ '@fastify/static@9.1.3':
+ resolution: {integrity: sha512-aXrYtsiryLhRxRNaxNqsn7FUISeb7rB9q4eHUPIot5aeQBLNahnz1m6thzm7JWC1poSGXS9XrX8DvuMivp2hkQ==}
+
'@floating-ui/core@1.7.1':
resolution: {integrity: sha512-azI0DrjMMfIug/ExbBaeDVJXcY0a7EPvPjb2xAJPa4HeimBX+Z18HK8QQR3jb6356SnDDdxx+hinMLcJEDdOjw==}
@@ -1046,143 +1726,6 @@ packages:
resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==}
deprecated: Use @eslint/object-schema instead
- '@img/colour@1.1.0':
- resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==}
- engines: {node: '>=18'}
-
- '@img/sharp-darwin-arm64@0.34.5':
- resolution: {integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==}
- engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
- cpu: [arm64]
- os: [darwin]
-
- '@img/sharp-darwin-x64@0.34.5':
- resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==}
- engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
- cpu: [x64]
- os: [darwin]
-
- '@img/sharp-libvips-darwin-arm64@1.2.4':
- resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==}
- cpu: [arm64]
- os: [darwin]
-
- '@img/sharp-libvips-darwin-x64@1.2.4':
- resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==}
- cpu: [x64]
- os: [darwin]
-
- '@img/sharp-libvips-linux-arm64@1.2.4':
- resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==}
- cpu: [arm64]
- os: [linux]
-
- '@img/sharp-libvips-linux-arm@1.2.4':
- resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==}
- cpu: [arm]
- os: [linux]
-
- '@img/sharp-libvips-linux-ppc64@1.2.4':
- resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==}
- cpu: [ppc64]
- os: [linux]
-
- '@img/sharp-libvips-linux-riscv64@1.2.4':
- resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==}
- cpu: [riscv64]
- os: [linux]
-
- '@img/sharp-libvips-linux-s390x@1.2.4':
- resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==}
- cpu: [s390x]
- os: [linux]
-
- '@img/sharp-libvips-linux-x64@1.2.4':
- resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==}
- cpu: [x64]
- os: [linux]
-
- '@img/sharp-libvips-linuxmusl-arm64@1.2.4':
- resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==}
- cpu: [arm64]
- os: [linux]
-
- '@img/sharp-libvips-linuxmusl-x64@1.2.4':
- resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==}
- cpu: [x64]
- os: [linux]
-
- '@img/sharp-linux-arm64@0.34.5':
- resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==}
- engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
- cpu: [arm64]
- os: [linux]
-
- '@img/sharp-linux-arm@0.34.5':
- resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==}
- engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
- cpu: [arm]
- os: [linux]
-
- '@img/sharp-linux-ppc64@0.34.5':
- resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==}
- engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
- cpu: [ppc64]
- os: [linux]
-
- '@img/sharp-linux-riscv64@0.34.5':
- resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==}
- engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
- cpu: [riscv64]
- os: [linux]
-
- '@img/sharp-linux-s390x@0.34.5':
- resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==}
- engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
- cpu: [s390x]
- os: [linux]
-
- '@img/sharp-linux-x64@0.34.5':
- resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==}
- engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
- cpu: [x64]
- os: [linux]
-
- '@img/sharp-linuxmusl-arm64@0.34.5':
- resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==}
- engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
- cpu: [arm64]
- os: [linux]
-
- '@img/sharp-linuxmusl-x64@0.34.5':
- resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==}
- engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
- cpu: [x64]
- os: [linux]
-
- '@img/sharp-wasm32@0.34.5':
- resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==}
- engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
- cpu: [wasm32]
-
- '@img/sharp-win32-arm64@0.34.5':
- resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==}
- engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
- cpu: [arm64]
- os: [win32]
-
- '@img/sharp-win32-ia32@0.34.5':
- resolution: {integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==}
- engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
- cpu: [ia32]
- os: [win32]
-
- '@img/sharp-win32-x64@0.34.5':
- resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==}
- engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
- cpu: [x64]
- os: [win32]
-
'@internationalized/date@3.12.1':
resolution: {integrity: sha512-6IedsVWXyq4P9Tj+TxuU8WGWM70hYLl12nbYU8jkikVpa6WXapFazPUcHUMDMoWftIDE2ILDkFFte6W2nFCkRQ==}
@@ -1224,34 +1767,18 @@ packages:
node-notifier:
optional: true
- '@jest/diff-sequences@30.0.0':
- resolution: {integrity: sha512-xMbtoCeKJDto86GW6AiwVv7M4QAuI56R7dVBr1RNGYbOT44M2TIzOiske2RxopBqkumDY+A1H55pGvuribRY9A==}
- engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
-
'@jest/environment@27.5.1':
resolution: {integrity: sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
- '@jest/expect-utils@30.0.0':
- resolution: {integrity: sha512-UiWfsqNi/+d7xepfOv8KDcbbzcYtkWBe3a3kVDtg6M1kuN6CJ7b4HzIp5e1YHrSaQaVS8sdCoyCMCZClTLNKFQ==}
- engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
-
'@jest/fake-timers@27.5.1':
resolution: {integrity: sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
- '@jest/get-type@30.0.0':
- resolution: {integrity: sha512-VZWMjrBzqfDKngQ7sUctKeLxanAbsBFoZnPxNIG6CmxK7Gv6K44yqd0nzveNIBfuhGZMmk1n5PGbvdSTOu0yTg==}
- engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
-
'@jest/globals@27.5.1':
resolution: {integrity: sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
- '@jest/pattern@30.0.0':
- resolution: {integrity: sha512-k+TpEThzLVXMkbdxf8KHjZ83Wl+G54ytVJoDIGWwS96Ql4xyASRjc6SU1hs5jHVql+hpyK9G8N7WuFhLpGHRpQ==}
- engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
-
'@jest/reporters@27.5.1':
resolution: {integrity: sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
@@ -1261,10 +1788,6 @@ packages:
node-notifier:
optional: true
- '@jest/schemas@30.0.0':
- resolution: {integrity: sha512-NID2VRyaEkevCRz6badhfqYwri/RvMbiHY81rk3AkK/LaiB0LSxi1RdVZ7MpZdTjNugtZeGfpL0mLs9Kp3MrQw==}
- engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
-
'@jest/source-map@27.5.1':
resolution: {integrity: sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
@@ -1285,9 +1808,8 @@ packages:
resolution: {integrity: sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
- '@jest/types@30.0.0':
- resolution: {integrity: sha512-1Nox8mAL52PKPfEnUQWBvKU/bp8FTT6AiDu76bFDEJj/qsRFSAVSldfCH3XYMqialti2zHXKvD5gN0AaHc0yKA==}
- engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+ '@jridgewell/gen-mapping@0.3.13':
+ resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
'@jridgewell/gen-mapping@0.3.8':
resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==}
@@ -1316,68 +1838,24 @@ packages:
'@jridgewell/trace-mapping@0.3.25':
resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
+ '@jridgewell/trace-mapping@0.3.31':
+ resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
+
'@jridgewell/trace-mapping@0.3.9':
resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
+ '@lukeed/ms@2.0.2':
+ resolution: {integrity: sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==}
+ engines: {node: '>=8'}
+
'@maverick-js/signals@5.11.5':
resolution: {integrity: sha512-/GO94awrwN9ROYZDMTeByordjvbhcm3CMvB/2aL/sEUy9Va8nM/2GmNgOOe+rrooTGnz8/DzO73xomuBRrnYWw==}
- '@napi-rs/wasm-runtime@0.2.11':
- resolution: {integrity: sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA==}
-
- '@next/env@15.5.18':
- resolution: {integrity: sha512-hAV85Ckd9QR6RvH04MEKwsfLTksvFpO47j9xwtoIuvuPnlwecpSi+uZTtm8HirVbtlI2Fnz//xpcSTjFdyJk+g==}
-
- '@next/eslint-plugin-next@15.5.18':
- resolution: {integrity: sha512-w4MYq8M26a8PNrfto0JosLf5/3ssln1rsyP96g2DkC8uFVymStM5DLSz5ElxxrPRg2XnTMnFo3kREFlhYvxhWw==}
-
- '@next/swc-darwin-arm64@15.5.18':
- resolution: {integrity: sha512-w0WvQf1n+txiwns/9pwIQteCJpZTbxzO2SE0FLcwuD4v0WEh1JPOjdyxWL21XwJsdpx8cFRjyzxzCS/siP7HcQ==}
- engines: {node: '>= 10'}
- cpu: [arm64]
- os: [darwin]
-
- '@next/swc-darwin-x64@15.5.18':
- resolution: {integrity: sha512-znn71QmDuxm+BOaglihMZfvyySMnNljkVIY5Z2TCssBmm+WqL6c19VhtH5ktFkHa8EZ2bnTUpcNcmNSQsg67og==}
- engines: {node: '>= 10'}
- cpu: [x64]
- os: [darwin]
-
- '@next/swc-linux-arm64-gnu@15.5.18':
- resolution: {integrity: sha512-yPPe5MNL+igZUa+OsqQJisqSfh6oarIuA1Q0BDxljGJhRQyZeP+WRHh7rs/jZUGMh5aY0YdIjXZG0VohkKkUdw==}
- engines: {node: '>= 10'}
- cpu: [arm64]
- os: [linux]
-
- '@next/swc-linux-arm64-musl@15.5.18':
- resolution: {integrity: sha512-glaCczEWIrHsokFZ3pP08U4BpKxwIdnT+txdOM32OBgpL9Yw4aqx8NejmgtZQZOdstQ5f0L3CasIZudzCuD+nw==}
- engines: {node: '>= 10'}
- cpu: [arm64]
- os: [linux]
-
- '@next/swc-linux-x64-gnu@15.5.18':
- resolution: {integrity: sha512-oUfg2EgJmU3R0OCOWiokGFUTvZiPfXtriXiuF3YNxRoROCdgvTedHIzYoeKH34gsZxS/V7mHbfq2hpAHwhH1/A==}
- engines: {node: '>= 10'}
- cpu: [x64]
- os: [linux]
-
- '@next/swc-linux-x64-musl@15.5.18':
- resolution: {integrity: sha512-JLxSP3KTd9iu/bvUMQxH7RJo9xKSHf55/6RPE4a6FTSZygGn7uvZbCej0AHXydwkggQGSD9UddSjwv6Xz5ESfA==}
- engines: {node: '>= 10'}
- cpu: [x64]
- os: [linux]
-
- '@next/swc-win32-arm64-msvc@15.5.18':
- resolution: {integrity: sha512-ir1v7enP52K2HNz3tQQvwF+x7VNxBk1ciiZ18WBPvxf4C59IqdfmHPJYK3vH7rSxpuCVw/8C712wTXNAtEp+NA==}
- engines: {node: '>= 10'}
- cpu: [arm64]
- os: [win32]
-
- '@next/swc-win32-x64-msvc@15.5.18':
- resolution: {integrity: sha512-LIu5me6QTANCd25E7I5uIEfvgQ06RK7tvHAbYo3zCb3VpxQEPvMcSpd87NwUABDT6MbGPdEGR5VRiK4PPTJhQg==}
- engines: {node: '>= 10'}
- cpu: [x64]
- os: [win32]
+ '@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
'@nodelib/fs.scandir@2.1.5':
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
@@ -1391,9 +1869,11 @@ packages:
resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
engines: {node: '>= 8'}
- '@nolyfill/is-core-module@1.0.39':
- resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==}
- engines: {node: '>=12.4.0'}
+ '@oxc-project/types@0.132.0':
+ resolution: {integrity: sha512-FESMOxil5Se014ui/Eq8fT5uHJo6nIRwH0PfJrZJXs6Gek3ZVFOrpUv3YIZT20m+extU98Hg1Ym72U58rlsxUQ==}
+
+ '@pinojs/redact@0.4.0':
+ resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==}
'@radix-ui/react-avatar@1.1.11':
resolution: {integrity: sha512-0Qk603AHGV28BOBO34p7IgD5m+V5Sg/YovfayABkoDDBM5d3NCx0Mp4gGrjzLGes1jV5eNOE1r3itqOR33VC6Q==}
@@ -1565,6 +2045,115 @@ packages:
peerDependencies:
'@redis/client': ^1.0.0
+ '@rolldown/binding-android-arm64@1.0.2':
+ resolution: {integrity: sha512-ZS4D1JPGn/MYQN/SYDWftIE/nVsM8j/AFOYEzAoOE2O3NktQOZru+/vYXGbR/qtdLdIfGCP0lcoJiYVzsEz+iQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [android]
+
+ '@rolldown/binding-darwin-arm64@1.0.2':
+ resolution: {integrity: sha512-vdFA9+C/rekyGce7WqHs/xoT0ioZEWaOFyZLIV1mEeNFaFDUQrPIo8Vs2GvJ6eetb3rzDUtUBgzto3ExpXJB3w==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@rolldown/binding-darwin-x64@1.0.2':
+ resolution: {integrity: sha512-BewSOwTHazv77DTYiAZXSqqKZ4KP/KonFisDMVU7PImxoWfB2aepnPhd2E4SWz3zDzYgDNbs6jBmTdgNnF02GA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [darwin]
+
+ '@rolldown/binding-freebsd-x64@1.0.2':
+ resolution: {integrity: sha512-m41o7M0YWtUdqk61Tb+jnKb2rN++iRdIASlExkUoKfIAH30DOHCB8fVLzSUpbWHHU8esmEioY62PxzexE8MBuA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@rolldown/binding-linux-arm-gnueabihf@1.0.2':
+ resolution: {integrity: sha512-jcojB9H7W/jS29pMKWAK1N+fU99vXodHDTatS3b3y/XSOCiHo0kkA74pL3jJmkoQtYpOCxDvaKs1fo2Ij/1X5w==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm]
+ os: [linux]
+
+ '@rolldown/binding-linux-arm64-gnu@1.0.2':
+ resolution: {integrity: sha512-1jn6qDU5iiOgFgygDzKUuKP0maTi0/f1+sBLgvij/76C77Nm3ts6ufz9Bjg5q5dduxiUIxtq86JIoBvo1xQ4Ig==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rolldown/binding-linux-arm64-musl@1.0.2':
+ resolution: {integrity: sha512-QVLO/czFMdoMFSqlX3bcswcJNm/23r+qoa/jgtmFc/qEp6/jXmIkDjF/XIo8dPfGaiwy1xfQn8o77L79GeXFgw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rolldown/binding-linux-ppc64-gnu@1.0.2':
+ resolution: {integrity: sha512-hgO5Abm0w5UL6FEa2iFnZqo2KlK7TQ5QhV5x09hujBf7t5KzHQ1VmfPuTpqRy/rNlSxua3eWH374xxiVrP+lcA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@rolldown/binding-linux-s390x-gnu@1.0.2':
+ resolution: {integrity: sha512-fy8rXxuYEu602abC8MUNaPjYLIFzReOaEIEMKMUa0rFEUxNpVXhs15KSSQ4qlqSaM7B6rcj9rDZgADh/IGDzLQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [s390x]
+ os: [linux]
+
+ '@rolldown/binding-linux-x64-gnu@1.0.2':
+ resolution: {integrity: sha512-0+bOkiQ779+r1WpoHOWHqncvyySci0vKph+myNDYb+im6meJAzHQXay6oEgnkHuUGouM1LKTZwqKpBow6Kj7CQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [linux]
+
+ '@rolldown/binding-linux-x64-musl@1.0.2':
+ resolution: {integrity: sha512-mjSkrzZK5Qsl0a9d1JgILOiuZOSDTVdKENcSXBoqbzSrspLR/4/IRVDo5wd2GgZjNss/viBFJdeq+j7qH2nypw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [linux]
+
+ '@rolldown/binding-openharmony-arm64@1.0.2':
+ resolution: {integrity: sha512-1v5vHasdfQAZoEHakBV72LIFAC9JjnymsiKxp+GEr/ma3+NJCPSaYK+qavInOovJkgwFrs7GccX2d6IgDA3Z5w==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@rolldown/binding-wasm32-wasi@1.0.2':
+ resolution: {integrity: sha512-mb1VobWn6NheziTk5/WEaR6AKVbrwT5sOi6C7zk3gy/pD1qtJfU1j4PgTo2NJnOtbL9Dl3Aeei8w9jJ7qC2jZQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [wasm32]
+
+ '@rolldown/binding-win32-arm64-msvc@1.0.2':
+ resolution: {integrity: sha512-SqKonF56vA/L2yHwHYcEp2P34URpOZ7d1fS635cTkpDnUtEGdUbhI6NzsPdqeSWvAAeGDrxjWjNmibDIdFf9/A==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [win32]
+
+ '@rolldown/binding-win32-x64-msvc@1.0.2':
+ resolution: {integrity: sha512-v7qRI7gXLRINcOGXt+7YmAZ6iFuyZVMIoXAxhd8oP+DR9dLfL9GfNIx7PLMxmhZdvq8waUJBQiWN9EKNy+TRBQ==}
+ 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.1':
+ resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==}
+
'@rollup/plugin-babel@5.3.1':
resolution: {integrity: sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==}
engines: {node: '>= 10.0.0'}
@@ -1593,15 +2182,6 @@ packages:
peerDependencies:
rollup: ^1.20.0||^2.0.0
- '@rtsao/scc@1.1.0':
- resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==}
-
- '@rushstack/eslint-patch@1.11.0':
- resolution: {integrity: sha512-zxnHvoMQVqewTJr/W4pKjF0bMGiKJv1WX7bSrkl46Hg0QjESbzBROWK0Wg4RphzSOS5Jiy7eFimmM3UgMrMZbQ==}
-
- '@sinclair/typebox@0.34.35':
- resolution: {integrity: sha512-C6ypdODf2VZkgRT6sFM8E1F8vR+HcffniX0Kp8MsU8PIfrlXbNCBz0jzj17GjdmjTx1OtZzdH8+iALL21UjF5A==}
-
'@sinonjs/commons@1.8.6':
resolution: {integrity: sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==}
@@ -1625,84 +2205,6 @@ packages:
'@surma/rollup-plugin-off-main-thread@2.2.3':
resolution: {integrity: sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==}
- '@svgr/babel-plugin-add-jsx-attribute@8.0.0':
- resolution: {integrity: sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==}
- engines: {node: '>=14'}
- peerDependencies:
- '@babel/core': ^7.0.0-0
-
- '@svgr/babel-plugin-remove-jsx-attribute@8.0.0':
- resolution: {integrity: sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==}
- engines: {node: '>=14'}
- peerDependencies:
- '@babel/core': ^7.0.0-0
-
- '@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0':
- resolution: {integrity: sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==}
- engines: {node: '>=14'}
- peerDependencies:
- '@babel/core': ^7.0.0-0
-
- '@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0':
- resolution: {integrity: sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==}
- engines: {node: '>=14'}
- peerDependencies:
- '@babel/core': ^7.0.0-0
-
- '@svgr/babel-plugin-svg-dynamic-title@8.0.0':
- resolution: {integrity: sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==}
- engines: {node: '>=14'}
- peerDependencies:
- '@babel/core': ^7.0.0-0
-
- '@svgr/babel-plugin-svg-em-dimensions@8.0.0':
- resolution: {integrity: sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==}
- engines: {node: '>=14'}
- peerDependencies:
- '@babel/core': ^7.0.0-0
-
- '@svgr/babel-plugin-transform-react-native-svg@8.1.0':
- resolution: {integrity: sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==}
- engines: {node: '>=14'}
- peerDependencies:
- '@babel/core': ^7.0.0-0
-
- '@svgr/babel-plugin-transform-svg-component@8.0.0':
- resolution: {integrity: sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==}
- engines: {node: '>=12'}
- peerDependencies:
- '@babel/core': ^7.0.0-0
-
- '@svgr/babel-preset@8.1.0':
- resolution: {integrity: sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==}
- engines: {node: '>=14'}
- peerDependencies:
- '@babel/core': ^7.0.0-0
-
- '@svgr/core@8.1.0':
- resolution: {integrity: sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==}
- engines: {node: '>=14'}
-
- '@svgr/hast-util-to-babel-ast@8.0.0':
- resolution: {integrity: sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==}
- engines: {node: '>=14'}
-
- '@svgr/plugin-jsx@8.1.0':
- resolution: {integrity: sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==}
- engines: {node: '>=14'}
- peerDependencies:
- '@svgr/core': '*'
-
- '@svgr/plugin-svgo@8.1.0':
- resolution: {integrity: sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA==}
- engines: {node: '>=14'}
- peerDependencies:
- '@svgr/core': '*'
-
- '@svgr/webpack@8.1.0':
- resolution: {integrity: sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==}
- engines: {node: '>=14'}
-
'@swc/counter@0.1.3':
resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==}
@@ -1832,10 +2334,6 @@ packages:
resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==}
engines: {node: '>= 6'}
- '@trysound/sax@0.2.0':
- resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==}
- engines: {node: '>=10.13.0'}
-
'@tsconfig/node10@1.0.11':
resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==}
@@ -1848,8 +2346,8 @@ packages:
'@tsconfig/node16@1.0.4':
resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==}
- '@tybys/wasm-util@0.9.0':
- resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==}
+ '@tybys/wasm-util@0.10.2':
+ resolution: {integrity: sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==}
'@types/aria-query@5.0.4':
resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==}
@@ -1885,9 +2383,6 @@ packages:
'@types/estree@1.0.8':
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
- '@types/glob@7.2.0':
- resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==}
-
'@types/graceful-fs@4.1.9':
resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==}
@@ -1903,21 +2398,15 @@ packages:
'@types/istanbul-reports@3.0.4':
resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==}
- '@types/jest@30.0.0':
- resolution: {integrity: sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==}
+ '@types/jest@27.5.2':
+ resolution: {integrity: sha512-mpT8LJJ4CMeeahobofYWIjFo0xonRS/HfxnVEPMPFSQdGUt1uHCnoPT7Zhb+sjDU2wz0oKV0OLUR0WzrHNgfeA==}
'@types/json-schema@7.0.15':
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
- '@types/json5@0.0.29':
- resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
-
'@types/minimatch@3.0.5':
resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==}
- '@types/minimatch@5.1.2':
- resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==}
-
'@types/minimist@1.2.5':
resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==}
@@ -1968,9 +2457,6 @@ packages:
'@types/yargs@16.0.9':
resolution: {integrity: sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==}
- '@types/yargs@17.0.33':
- resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==}
-
'@typescript-eslint/eslint-plugin@5.62.0':
resolution: {integrity: sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -2032,101 +2518,6 @@ packages:
'@ungap/structured-clone@1.3.0':
resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
- '@unrs/resolver-binding-android-arm-eabi@1.9.0':
- resolution: {integrity: sha512-h1T2c2Di49ekF2TE8ZCoJkb+jwETKUIPDJ/nO3tJBKlLFPu+fyd93f0rGP/BvArKx2k2HlRM4kqkNarj3dvZlg==}
- cpu: [arm]
- os: [android]
-
- '@unrs/resolver-binding-android-arm64@1.9.0':
- resolution: {integrity: sha512-sG1NHtgXtX8owEkJ11yn34vt0Xqzi3k9TJ8zppDmyG8GZV4kVWw44FHwKwHeEFl07uKPeC4ZoyuQaGh5ruJYPA==}
- cpu: [arm64]
- os: [android]
-
- '@unrs/resolver-binding-darwin-arm64@1.9.0':
- resolution: {integrity: sha512-nJ9z47kfFnCxN1z/oYZS7HSNsFh43y2asePzTEZpEvK7kGyuShSl3RRXnm/1QaqFL+iP+BjMwuB+DYUymOkA5A==}
- cpu: [arm64]
- os: [darwin]
-
- '@unrs/resolver-binding-darwin-x64@1.9.0':
- resolution: {integrity: sha512-TK+UA1TTa0qS53rjWn7cVlEKVGz2B6JYe0C++TdQjvWYIyx83ruwh0wd4LRxYBM5HeuAzXcylA9BH2trARXJTw==}
- cpu: [x64]
- os: [darwin]
-
- '@unrs/resolver-binding-freebsd-x64@1.9.0':
- resolution: {integrity: sha512-6uZwzMRFcD7CcCd0vz3Hp+9qIL2jseE/bx3ZjaLwn8t714nYGwiE84WpaMCYjU+IQET8Vu/+BNAGtYD7BG/0yA==}
- cpu: [x64]
- os: [freebsd]
-
- '@unrs/resolver-binding-linux-arm-gnueabihf@1.9.0':
- resolution: {integrity: sha512-bPUBksQfrgcfv2+mm+AZinaKq8LCFvt5PThYqRotqSuuZK1TVKkhbVMS/jvSRfYl7jr3AoZLYbDkItxgqMKRkg==}
- cpu: [arm]
- os: [linux]
-
- '@unrs/resolver-binding-linux-arm-musleabihf@1.9.0':
- resolution: {integrity: sha512-uT6E7UBIrTdCsFQ+y0tQd3g5oudmrS/hds5pbU3h4s2t/1vsGWbbSKhBSCD9mcqaqkBwoqlECpUrRJCmldl8PA==}
- cpu: [arm]
- os: [linux]
-
- '@unrs/resolver-binding-linux-arm64-gnu@1.9.0':
- resolution: {integrity: sha512-vdqBh911wc5awE2bX2zx3eflbyv8U9xbE/jVKAm425eRoOVv/VseGZsqi3A3SykckSpF4wSROkbQPvbQFn8EsA==}
- cpu: [arm64]
- os: [linux]
-
- '@unrs/resolver-binding-linux-arm64-musl@1.9.0':
- resolution: {integrity: sha512-/8JFZ/SnuDr1lLEVsxsuVwrsGquTvT51RZGvyDB/dOK3oYK2UqeXzgeyq6Otp8FZXQcEYqJwxb9v+gtdXn03eQ==}
- cpu: [arm64]
- os: [linux]
-
- '@unrs/resolver-binding-linux-ppc64-gnu@1.9.0':
- resolution: {integrity: sha512-FkJjybtrl+rajTw4loI3L6YqSOpeZfDls4SstL/5lsP2bka9TiHUjgMBjygeZEis1oC8LfJTS8FSgpKPaQx2tQ==}
- cpu: [ppc64]
- os: [linux]
-
- '@unrs/resolver-binding-linux-riscv64-gnu@1.9.0':
- resolution: {integrity: sha512-w/NZfHNeDusbqSZ8r/hp8iL4S39h4+vQMc9/vvzuIKMWKppyUGKm3IST0Qv0aOZ1rzIbl9SrDeIqK86ZpUK37w==}
- cpu: [riscv64]
- os: [linux]
-
- '@unrs/resolver-binding-linux-riscv64-musl@1.9.0':
- resolution: {integrity: sha512-bEPBosut8/8KQbUixPry8zg/fOzVOWyvwzOfz0C0Rw6dp+wIBseyiHKjkcSyZKv/98edrbMknBaMNJfA/UEdqw==}
- cpu: [riscv64]
- os: [linux]
-
- '@unrs/resolver-binding-linux-s390x-gnu@1.9.0':
- resolution: {integrity: sha512-LDtMT7moE3gK753gG4pc31AAqGUC86j3AplaFusc717EUGF9ZFJ356sdQzzZzkBk1XzMdxFyZ4f/i35NKM/lFA==}
- cpu: [s390x]
- os: [linux]
-
- '@unrs/resolver-binding-linux-x64-gnu@1.9.0':
- resolution: {integrity: sha512-WmFd5KINHIXj8o1mPaT8QRjA9HgSXhN1gl9Da4IZihARihEnOylu4co7i/yeaIpcfsI6sYs33cNZKyHYDh0lrA==}
- cpu: [x64]
- os: [linux]
-
- '@unrs/resolver-binding-linux-x64-musl@1.9.0':
- resolution: {integrity: sha512-CYuXbANW+WgzVRIl8/QvZmDaZxrqvOldOwlbUjIM4pQ46FJ0W5cinJ/Ghwa/Ng1ZPMJMk1VFdsD/XwmCGIXBWg==}
- cpu: [x64]
- os: [linux]
-
- '@unrs/resolver-binding-wasm32-wasi@1.9.0':
- resolution: {integrity: sha512-6Rp2WH0OoitMYR57Z6VE8Y6corX8C6QEMWLgOV6qXiJIeZ1F9WGXY/yQ8yDC4iTraotyLOeJ2Asea0urWj2fKQ==}
- engines: {node: '>=14.0.0'}
- cpu: [wasm32]
-
- '@unrs/resolver-binding-win32-arm64-msvc@1.9.0':
- resolution: {integrity: sha512-rknkrTRuvujprrbPmGeHi8wYWxmNVlBoNW8+4XF2hXUnASOjmuC9FNF1tGbDiRQWn264q9U/oGtixyO3BT8adQ==}
- cpu: [arm64]
- os: [win32]
-
- '@unrs/resolver-binding-win32-ia32-msvc@1.9.0':
- resolution: {integrity: sha512-Ceymm+iBl+bgAICtgiHyMLz6hjxmLJKqBim8tDzpX61wpZOx2bPK6Gjuor7I2RiUynVjvvkoRIkrPyMwzBzF3A==}
- cpu: [ia32]
- os: [win32]
-
- '@unrs/resolver-binding-win32-x64-msvc@1.9.0':
- resolution: {integrity: sha512-k59o9ZyeyS0hAlcaKFezYSH2agQeRFEB7KoQLXl3Nb3rgkqT1NY9Vwy+SqODiLmYnEjxWJVRE/yq2jFVqdIxZw==}
- cpu: [x64]
- os: [win32]
-
'@upstash/redis@1.35.1':
resolution: {integrity: sha512-sIMuAMU9IYbE2bkgDby8KLoQKRiBMXn0moXxqLvUmQ7VUu2CvulZLtK8O0x3WQZFvvZhU5sRC2/lOVZdGfudkA==}
@@ -2137,6 +2528,19 @@ packages:
'@types/react': ^18.0.0 || ^19.0.0
react: ^18.0.0 || ^19.0.0
+ '@vitejs/plugin-react@6.0.2':
+ resolution: {integrity: sha512-DlSMqo4WhThw4vB8Mpn0Woe9J+Jfq1geJ61AKW0QEgLzGMNwtIMdxbDUzLxcun8W7NbJO0e2Jg/Nxm3cCSVzzg==}
+ 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
+
'@webassemblyjs/ast@1.14.1':
resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==}
@@ -2196,6 +2600,9 @@ packages:
resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==}
deprecated: Use your platform's native atob() and btoa() methods instead
+ abstract-logging@2.0.1:
+ resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==}
+
acorn-globals@6.0.0:
resolution: {integrity: sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==}
@@ -2243,10 +2650,13 @@ packages:
ajv:
optional: true
- ajv-keywords@3.5.2:
- resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==}
+ ajv-formats@3.0.1:
+ resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==}
peerDependencies:
- ajv: ^6.9.1
+ ajv: ^8.0.0
+ peerDependenciesMeta:
+ ajv:
+ optional: true
ajv-keywords@5.1.0:
resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==}
@@ -2326,26 +2736,14 @@ packages:
resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==}
engines: {node: '>= 0.4'}
- array-union@1.0.2:
- resolution: {integrity: sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==}
- engines: {node: '>=0.10.0'}
-
array-union@2.1.0:
resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
engines: {node: '>=8'}
- array-uniq@1.0.3:
- resolution: {integrity: sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==}
- engines: {node: '>=0.10.0'}
-
array.prototype.findlast@1.2.5:
resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==}
engines: {node: '>= 0.4'}
- array.prototype.findlastindex@1.2.6:
- resolution: {integrity: sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==}
- engines: {node: '>= 0.4'}
-
array.prototype.flat@1.3.3:
resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==}
engines: {node: '>= 0.4'}
@@ -2379,9 +2777,6 @@ packages:
assert@2.0.0:
resolution: {integrity: sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==}
- ast-types-flow@0.0.8:
- resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==}
-
astral-regex@2.0.0:
resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==}
engines: {node: '>=8'}
@@ -2400,6 +2795,10 @@ packages:
resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==}
engines: {node: '>= 4.0.0'}
+ atomic-sleep@1.0.0:
+ resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==}
+ engines: {node: '>=8.0.0'}
+
autoprefixer@10.4.21:
resolution: {integrity: sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==}
engines: {node: ^10 || ^12 || >=14}
@@ -2411,13 +2810,8 @@ packages:
resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
engines: {node: '>= 0.4'}
- axe-core@4.10.3:
- resolution: {integrity: sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==}
- engines: {node: '>=4'}
-
- axobject-query@4.1.0:
- resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==}
- engines: {node: '>= 0.4'}
+ avvio@9.2.0:
+ resolution: {integrity: sha512-2t/sy01ArdHHE0vRH5Hsay+RtCZt3dLPji7W7/MMOCEgze5b7SNDC4j5H6FnVgPkI1MTNFGzHdHrVXDDl7QSSQ==}
babel-jest@27.5.1:
resolution: {integrity: sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==}
@@ -2425,13 +2819,6 @@ packages:
peerDependencies:
'@babel/core': ^7.8.0
- babel-loader@8.4.1:
- resolution: {integrity: sha512-nXzRChX+Z1GoE6yWavBQg6jDslyFF3SDjl2paADuoQtQW10JqShJt62R6eJQ5m/pjJFDT8xgKIWSP85OY8eXeA==}
- engines: {node: '>= 8.9'}
- peerDependencies:
- '@babel/core': ^7.0.0
- webpack: '>=2'
-
babel-plugin-istanbul@6.1.1:
resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==}
engines: {node: '>=8'}
@@ -2445,16 +2832,34 @@ packages:
peerDependencies:
'@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0
+ babel-plugin-polyfill-corejs2@0.4.17:
+ resolution: {integrity: sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==}
+ peerDependencies:
+ '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0
+
babel-plugin-polyfill-corejs3@0.11.1:
resolution: {integrity: sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==}
peerDependencies:
'@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0
+ babel-plugin-polyfill-corejs3@0.14.2:
+ resolution: {integrity: sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g==}
+ peerDependencies:
+ '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0
+
babel-plugin-polyfill-regenerator@0.6.4:
resolution: {integrity: sha512-7gD3pRadPrbjhjLyxebmx/WrFYcuSjZ0XbdUujQMZ/fcE9oeewk2U/7PCvez84UeuK3oSjmPZ0Ch0dlupQvGzw==}
peerDependencies:
'@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0
+ babel-plugin-polyfill-regenerator@0.6.8:
+ resolution: {integrity: sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==}
+ peerDependencies:
+ '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0
+
+ babel-plugin-react-compiler@1.0.0:
+ resolution: {integrity: sha512-Ixm8tFfoKKIPYdCCKYTsqv+Fd4IJ0DQqMyEimo+pxUOMUR9cVPlwTrFt9Avu+3cb6Zp3mAzl+t1MrG2fxxKsxw==}
+
babel-preset-current-node-syntax@1.1.0:
resolution: {integrity: sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==}
peerDependencies:
@@ -2469,21 +2874,31 @@ packages:
balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+ balanced-match@4.0.4:
+ resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==}
+ engines: {node: 18 || 20 || >=22}
+
base-x@5.0.1:
resolution: {integrity: sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg==}
+ baseline-browser-mapping@2.10.32:
+ resolution: {integrity: sha512-wbPvpyjJPC0zdfdKXxqEL3Ea+bOMD/87X4lftiJkkaBiuG6ALQy1SLmEd7BSmVCuwCQsBrCamgBoLyfFDD1EPg==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+
big.js@5.2.2:
resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==}
- boolbase@1.0.0:
- resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
-
brace-expansion@1.1.12:
resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==}
brace-expansion@2.0.2:
resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==}
+ brace-expansion@5.0.6:
+ resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==}
+ engines: {node: 18 || 20 || >=22}
+
braces@3.0.3:
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
engines: {node: '>=8'}
@@ -2501,6 +2916,11 @@ packages:
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
+ 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
+
bs58@6.0.0:
resolution: {integrity: sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==}
@@ -2522,6 +2942,10 @@ packages:
resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==}
engines: {node: '>= 0.4'}
+ call-bind@1.0.9:
+ resolution: {integrity: sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==}
+ engines: {node: '>= 0.4'}
+
call-bound@1.0.4:
resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==}
engines: {node: '>= 0.4'}
@@ -2548,6 +2972,9 @@ packages:
caniuse-lite@1.0.30001741:
resolution: {integrity: sha512-QGUGitqsc8ARjLdgAfxETDhRbJ0REsP6O3I96TAth/mVjh2cYzN2u+3AzPP3aVSm2FehEItaJw1xd+IGBXWeSw==}
+ caniuse-lite@1.0.30001793:
+ resolution: {integrity: sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==}
+
chalk@3.0.0:
resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==}
engines: {node: '>=8'}
@@ -2574,10 +3001,6 @@ packages:
resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==}
engines: {node: '>=8'}
- ci-info@4.2.0:
- resolution: {integrity: sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg==}
- engines: {node: '>=8'}
-
cjs-module-lexer@1.4.3:
resolution: {integrity: sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==}
@@ -2588,12 +3011,6 @@ packages:
resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==}
engines: {node: '>=6'}
- clean-webpack-plugin@4.0.0:
- resolution: {integrity: sha512-WuWE1nyTNAyW5T7oNyys2EN0cfP2fdRxhxnIQWiAp0bMabPdHhoGxM8A6YL2GhqwgrPnnaemVE7nv5XJ2Fhh2w==}
- engines: {node: '>=10.0.0'}
- peerDependencies:
- webpack: '>=4.0.0 <6.0.0'
-
cli-cursor@3.1.0:
resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==}
engines: {node: '>=8'}
@@ -2652,10 +3069,6 @@ packages:
commander@2.20.3:
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
- commander@7.2.0:
- resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==}
- engines: {node: '>= 10'}
-
commander@9.5.0:
resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==}
engines: {node: ^12.20.0 || >=14}
@@ -2664,15 +3077,16 @@ packages:
resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==}
engines: {node: '>=4.0.0'}
- commondir@1.0.1:
- resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==}
-
compare-func@2.0.0:
resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==}
concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
+ content-disposition@1.1.0:
+ resolution: {integrity: sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==}
+ engines: {node: '>=18'}
+
conventional-changelog-angular@5.0.13:
resolution: {integrity: sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==}
engines: {node: '>=10'}
@@ -2692,9 +3106,16 @@ packages:
convert-source-map@2.0.0:
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+ cookie@1.1.1:
+ resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==}
+ engines: {node: '>=18'}
+
core-js-compat@3.43.0:
resolution: {integrity: sha512-2GML2ZsCc5LR7hZYz4AXmjQw8zuy2T//2QntwdnpuYI7jteT6GVYJL7F6C2C57R7gSYrcqVW3lAALefdbhBLDA==}
+ core-js-compat@3.49.0:
+ resolution: {integrity: sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==}
+
cosmiconfig-typescript-loader@2.0.2:
resolution: {integrity: sha512-KmE+bMjWMXJbkWCeY4FJX/npHuZPNr9XF9q9CIQ/bpFwi1qHfCmSiKarrCcRa0LO4fWjk93pVoeRtJAkTGcYNw==}
engines: {node: '>=12', npm: '>=6'}
@@ -2707,15 +3128,6 @@ packages:
resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==}
engines: {node: '>=10'}
- cosmiconfig@8.3.6:
- resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==}
- engines: {node: '>=14'}
- peerDependencies:
- typescript: '>=4.9.5'
- peerDependenciesMeta:
- typescript:
- optional: true
-
create-require@1.1.1:
resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
@@ -2733,28 +3145,9 @@ packages:
resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==}
engines: {node: '>=8'}
- css-select@5.1.0:
- resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==}
-
- css-tree@2.2.1:
- resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==}
- engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'}
-
- css-tree@2.3.1:
- resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==}
- engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0}
-
- css-what@6.1.0:
- resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==}
- engines: {node: '>= 6'}
-
css.escape@1.5.1:
resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==}
- csso@5.0.5:
- resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==}
- engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'}
-
cssom@0.3.8:
resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==}
@@ -2771,9 +3164,6 @@ packages:
csstype@3.2.3:
resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
- damerau-levenshtein@1.0.8:
- resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==}
-
dargs@7.0.0:
resolution: {integrity: sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==}
engines: {node: '>=8'}
@@ -2794,16 +3184,17 @@ packages:
resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==}
engines: {node: '>= 0.4'}
- debug@3.2.7:
- resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
+ debug@4.4.1:
+ resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==}
+ engines: {node: '>=6.0'}
peerDependencies:
supports-color: '*'
peerDependenciesMeta:
supports-color:
optional: true
- debug@4.4.1:
- resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==}
+ debug@4.4.3:
+ resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
engines: {node: '>=6.0'}
peerDependencies:
supports-color: '*'
@@ -2840,14 +3231,14 @@ packages:
resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
engines: {node: '>= 0.4'}
- del@4.1.1:
- resolution: {integrity: sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==}
- engines: {node: '>=6'}
-
delayed-stream@1.0.0:
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
engines: {node: '>=0.4.0'}
+ depd@2.0.0:
+ resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
+ engines: {node: '>= 0.8'}
+
dequal@2.0.3:
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
engines: {node: '>=6'}
@@ -2886,27 +3277,11 @@ packages:
dom-helpers@5.2.1:
resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==}
- dom-serializer@2.0.0:
- resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==}
-
- domelementtype@2.3.0:
- resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==}
-
domexception@2.0.1:
resolution: {integrity: sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==}
engines: {node: '>=8'}
deprecated: Use your platform's native DOMException instead
- domhandler@5.0.3:
- resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==}
- engines: {node: '>= 4'}
-
- domutils@3.2.2:
- resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==}
-
- dot-case@3.0.4:
- resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==}
-
dot-prop@5.3.0:
resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==}
engines: {node: '>=8'}
@@ -2929,6 +3304,9 @@ packages:
electron-to-chromium@1.5.215:
resolution: {integrity: sha512-TIvGp57UpeNetj/wV/xpFNpWGb0b/ROw372lHPx5Aafx02gjTBtWnEEcaSX3W2dLM3OSdGGyHX/cHl01JQsLaQ==}
+ electron-to-chromium@1.5.361:
+ resolution: {integrity: sha512-Q6Hts7N9FnJc5LeGRINFvLhCI9xZmNtTDe5ZbcVezQz7cU4a8Aua3GH1b8J2XY8Al9PF+OCwYqhgsOOheMdvkA==}
+
emittery@0.8.1:
resolution: {integrity: sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==}
engines: {node: '>=10'}
@@ -2947,10 +3325,6 @@ packages:
resolution: {integrity: sha512-aNnGCvbJ/RIyWo1IuhNdVjnNF+EjH9wpzpNHt+ci/m9He9LJvUN8wrCcXjp9cWsGNAuvSpVFTx/vraAFQ8qGjQ==}
engines: {node: '>=10.13.0'}
- entities@4.5.0:
- resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
- engines: {node: '>=0.12'}
-
error-ex@1.3.2:
resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
@@ -2958,6 +3332,10 @@ packages:
resolution: {integrity: sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==}
engines: {node: '>= 0.4'}
+ es-abstract@1.24.2:
+ resolution: {integrity: sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==}
+ engines: {node: '>= 0.4'}
+
es-define-property@1.0.1:
resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
engines: {node: '>= 0.4'}
@@ -2966,8 +3344,8 @@ packages:
resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
engines: {node: '>= 0.4'}
- es-iterator-helpers@1.2.1:
- resolution: {integrity: sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==}
+ es-iterator-helpers@1.3.2:
+ resolution: {integrity: sha512-HVLACW1TppGYjJ8H6/jqH/pqOtKRw6wMlrB23xfExmFWxFquAIWCmwoLsOyN96K4a5KbmOf5At9ZUO3GZbetAw==}
engines: {node: '>= 0.4'}
es-module-lexer@1.7.0:
@@ -2992,10 +3370,18 @@ packages:
es6-object-assign@1.1.0:
resolution: {integrity: sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw==}
+ esbuild@0.28.0:
+ resolution: {integrity: sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==}
+ engines: {node: '>=18'}
+ hasBin: true
+
escalade@3.2.0:
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
engines: {node: '>=6'}
+ escape-html@1.0.3:
+ resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
+
escape-string-regexp@2.0.0:
resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==}
engines: {node: '>=8'}
@@ -3009,79 +3395,17 @@ packages:
engines: {node: '>=6.0'}
hasBin: true
- eslint-config-next@15.5.18:
- resolution: {integrity: sha512-HuoJU6uUPD00eyiud78IBnT4HLhztFj2V+ild2Uon5ZUrYZKe0Olu2QRD99e9IgL4/H1eg5Onka3BsfRW2U0Xw==}
- peerDependencies:
- eslint: ^7.23.0 || ^8.0.0 || ^9.0.0
- typescript: '>=3.3.1'
- peerDependenciesMeta:
- typescript:
- optional: true
-
eslint-config-prettier@8.10.0:
resolution: {integrity: sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==}
hasBin: true
peerDependencies:
eslint: '>=7.0.0'
- eslint-import-resolver-node@0.3.9:
- resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==}
-
- eslint-import-resolver-typescript@3.10.1:
- resolution: {integrity: sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==}
- engines: {node: ^14.18.0 || >=16.0.0}
+ eslint-plugin-react-hooks@7.1.1:
+ resolution: {integrity: sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==}
+ engines: {node: '>=18'}
peerDependencies:
- eslint: '*'
- eslint-plugin-import: '*'
- eslint-plugin-import-x: '*'
- peerDependenciesMeta:
- eslint-plugin-import:
- optional: true
- eslint-plugin-import-x:
- optional: true
-
- eslint-module-utils@2.12.0:
- resolution: {integrity: sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==}
- engines: {node: '>=4'}
- peerDependencies:
- '@typescript-eslint/parser': '*'
- eslint: '*'
- eslint-import-resolver-node: '*'
- eslint-import-resolver-typescript: '*'
- eslint-import-resolver-webpack: '*'
- peerDependenciesMeta:
- '@typescript-eslint/parser':
- optional: true
- eslint:
- optional: true
- eslint-import-resolver-node:
- optional: true
- eslint-import-resolver-typescript:
- optional: true
- eslint-import-resolver-webpack:
- optional: true
-
- eslint-plugin-import@2.31.0:
- resolution: {integrity: sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==}
- engines: {node: '>=4'}
- peerDependencies:
- '@typescript-eslint/parser': '*'
- eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9
- peerDependenciesMeta:
- '@typescript-eslint/parser':
- optional: true
-
- eslint-plugin-jsx-a11y@6.10.2:
- resolution: {integrity: sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==}
- engines: {node: '>=4.0'}
- peerDependencies:
- eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9
-
- eslint-plugin-react-hooks@5.2.0:
- resolution: {integrity: sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==}
- engines: {node: '>=10'}
- peerDependencies:
- eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0
+ eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0
eslint-plugin-react@7.37.5:
resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==}
@@ -3182,17 +3506,12 @@ packages:
resolution: {integrity: sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
- expect@30.0.0:
- resolution: {integrity: sha512-xCdPp6gwiR9q9lsPCHANarIkFTN/IMZso6Kkq03sOm9IIGtzK/UJqml0dkhHibGh8HKOj8BIDIpZ0BZuU7QK6w==}
- engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+ fast-decode-uri-component@1.0.1:
+ resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==}
fast-deep-equal@3.1.3:
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
- fast-glob@3.3.1:
- resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==}
- engines: {node: '>=8.6.0'}
-
fast-glob@3.3.3:
resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==}
engines: {node: '>=8.6.0'}
@@ -3200,12 +3519,24 @@ packages:
fast-json-stable-stringify@2.1.0:
resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
+ fast-json-stringify@6.4.0:
+ resolution: {integrity: sha512-ibRCQ0GZKJIQ+P3Et1h0LhPgp3PMTYk0MH8O+kW3lNYsvmaQww5Nn3f1jf73Q0jR1Yz3a1CDP4/NZD3vOajWJQ==}
+
fast-levenshtein@2.0.6:
resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
+ fast-querystring@1.1.2:
+ resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==}
+
fast-uri@3.0.6:
resolution: {integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==}
+ fastify-plugin@5.1.0:
+ resolution: {integrity: sha512-FAIDA8eovSt5qcDgcBvDuX/v0Cjz0ohGhENZ/wpc3y+oZCY2afZ9Baqql3g/lC+OHRnciQol4ww7tuthOb9idw==}
+
+ fastify@5.8.5:
+ resolution: {integrity: sha512-Yqptv59pQzPgQUSIm87hMqHJmdkb1+GPxdE6vW6FRyVE9G86mt7rOghitiU4JHRaTyDUk9pfeKmDeu70lAwM4Q==}
+
fastq@1.19.1:
resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==}
@@ -3220,6 +3551,15 @@ packages:
picomatch:
optional: true
+ fdir@6.5.0:
+ resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
+ engines: {node: '>=12.0.0'}
+ peerDependencies:
+ picomatch: ^3 || ^4
+ peerDependenciesMeta:
+ picomatch:
+ optional: true
+
file-entry-cache@6.0.1:
resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
engines: {node: ^10.12.0 || >=12.0.0}
@@ -3231,9 +3571,9 @@ packages:
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
engines: {node: '>=8'}
- find-cache-dir@3.3.2:
- resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==}
- engines: {node: '>=8'}
+ find-my-way@9.6.0:
+ resolution: {integrity: sha512-Zf4Xve4RymLl7NgaavNebZ01joJ8MfVerOG43wy7SHLO+r+K0C6d/SE0BiR7AV5V1VOCFlOP7ecdo+I4qmiHrQ==}
+ engines: {node: '>=20'}
find-up@4.1.0:
resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
@@ -3341,9 +3681,6 @@ packages:
resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==}
engines: {node: '>= 0.4'}
- get-tsconfig@4.10.1:
- resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==}
-
git-raw-commits@2.0.11:
resolution: {integrity: sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==}
engines: {node: '>=10'}
@@ -3360,6 +3697,10 @@ packages:
glob-to-regexp@0.4.1:
resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==}
+ glob@13.0.6:
+ resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==}
+ engines: {node: 18 || 20 || >=22}
+
glob@7.2.3:
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
deprecated: Glob versions prior to v9 are no longer supported
@@ -3384,10 +3725,6 @@ packages:
resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
engines: {node: '>=10'}
- globby@6.1.0:
- resolution: {integrity: sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==}
- engines: {node: '>=0.10.0'}
-
gopd@1.2.0:
resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
engines: {node: '>= 0.4'}
@@ -3429,10 +3766,20 @@ packages:
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
engines: {node: '>= 0.4'}
+ hasown@2.0.3:
+ resolution: {integrity: sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==}
+ engines: {node: '>= 0.4'}
+
he@1.2.0:
resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
hasBin: true
+ hermes-estree@0.25.1:
+ resolution: {integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==}
+
+ hermes-parser@0.25.1:
+ resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==}
+
hls.js@1.6.10:
resolution: {integrity: sha512-16XHorwFNh+hYazYxDNXBLEm5aRoU+oxMX6qVnkbGH3hJil4xLav3/M6NH92VkD1qSOGKXeSm+5unuawPXK6OQ==}
@@ -3450,6 +3797,10 @@ packages:
html-escaper@2.0.2:
resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
+ http-errors@2.0.1:
+ resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==}
+ engines: {node: '>= 0.8'}
+
http-proxy-agent@4.0.1:
resolution: {integrity: sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==}
engines: {node: '>= 6'}
@@ -3521,6 +3872,10 @@ packages:
inversify@6.0.1:
resolution: {integrity: sha512-B3ex30927698TJENHR++8FfEaJGqoWOgI6ZY5Ht/nLUsFCwHn6akbwtnUAPCgUepAnTpe2qHxhDNjoKLyz6rgQ==}
+ ipaddr.js@2.4.0:
+ resolution: {integrity: sha512-9VGk3HGanVE6JoZXHiCpnGy5X0jYDnN4EA4lntFPj+1vIWlFhIylq2CrrCOJH9EAhc5CYhq18F2Av2tgoAPsYQ==}
+ engines: {node: '>= 10'}
+
is-arguments@1.2.0:
resolution: {integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==}
engines: {node: '>= 0.4'}
@@ -3547,9 +3902,6 @@ packages:
is-buffer@1.1.6:
resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==}
- is-bun-module@2.0.0:
- resolution: {integrity: sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==}
-
is-callable@1.2.7:
resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
engines: {node: '>= 0.4'}
@@ -3558,6 +3910,10 @@ packages:
resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==}
engines: {node: '>= 0.4'}
+ is-core-module@2.16.2:
+ resolution: {integrity: sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==}
+ engines: {node: '>= 0.4'}
+
is-data-view@1.0.2:
resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==}
engines: {node: '>= 0.4'}
@@ -3625,18 +3981,6 @@ packages:
resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==}
engines: {node: '>=8'}
- is-path-cwd@2.2.0:
- resolution: {integrity: sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==}
- engines: {node: '>=6'}
-
- is-path-in-cwd@2.1.0:
- resolution: {integrity: sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==}
- engines: {node: '>=6'}
-
- is-path-inside@2.1.0:
- resolution: {integrity: sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==}
- engines: {node: '>=6'}
-
is-path-inside@3.0.3:
resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==}
engines: {node: '>=8'}
@@ -3770,10 +4114,6 @@ packages:
resolution: {integrity: sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
- jest-diff@30.0.0:
- resolution: {integrity: sha512-TgT1+KipV8JTLXXeFX0qSvIJR/UXiNNojjxb/awh3vYlBZyChU/NEmyKmq+wijKjWEztyrGJFL790nqMqNjTHA==}
- engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
-
jest-docblock@27.5.1:
resolution: {integrity: sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
@@ -3810,26 +4150,14 @@ packages:
resolution: {integrity: sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
- jest-matcher-utils@30.0.0:
- resolution: {integrity: sha512-m5mrunqopkrqwG1mMdJxe1J4uGmS9AHHKYUmoxeQOxBcLjEvirIrIDwuKmUYrecPHVB/PUBpXs2gPoeA2FSSLQ==}
- engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
-
jest-message-util@27.5.1:
resolution: {integrity: sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
- jest-message-util@30.0.0:
- resolution: {integrity: sha512-pV3qcrb4utEsa/U7UI2VayNzSDQcmCllBZLSoIucrESRu0geKThFZOjjh0kACDJFJRAQwsK7GVsmS6SpEceD8w==}
- engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
-
jest-mock@27.5.1:
resolution: {integrity: sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
- jest-mock@30.0.0:
- resolution: {integrity: sha512-W2sRA4ALXILrEetEOh2ooZG6fZ01iwVs0OWMKSSWRcUlaLr4ESHuiKXDNTg+ZVgOq8Ei5445i/Yxrv59VT+XkA==}
- engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
-
jest-pnp-resolver@1.2.3:
resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==}
engines: {node: '>=6'}
@@ -3843,10 +4171,6 @@ packages:
resolution: {integrity: sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
- jest-regex-util@30.0.0:
- resolution: {integrity: sha512-rT84010qRu/5OOU7a9TeidC2Tp3Qgt9Sty4pOZ/VSDuEmRupIjKZAb53gU3jr4ooMlhwScrgC9UixJxWzVu9oQ==}
- engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
-
jest-resolve-dependencies@27.5.1:
resolution: {integrity: sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
@@ -3875,10 +4199,6 @@ packages:
resolution: {integrity: sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
- jest-util@30.0.0:
- resolution: {integrity: sha512-fhNBBM9uSUbd4Lzsf8l/kcAdaHD/4SgoI48en3HXcBEMwKwoleKFMZ6cYEYs21SB779PRuRCyNLmymApAm8tZw==}
- engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
-
jest-validate@27.5.1:
resolution: {integrity: sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
@@ -3949,6 +4269,9 @@ packages:
json-parse-even-better-errors@2.3.1:
resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
+ json-schema-ref-resolver@3.0.0:
+ resolution: {integrity: sha512-hOrZIVL5jyYFjzk7+y7n5JDzGlU8rfWDuYyHwGa2WA8/pcmMHezp2xsVwxrebD/Q9t8Nc5DboieySDpCp4WG4A==}
+
json-schema-traverse@0.4.1:
resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
@@ -3961,10 +4284,6 @@ packages:
json-stable-stringify-without-jsonify@1.0.1:
resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
- json5@1.0.2:
- resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==}
- hasBin: true
-
json5@2.2.3:
resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
engines: {node: '>=6'}
@@ -3996,13 +4315,6 @@ packages:
resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==}
engines: {node: '>=6'}
- language-subtag-registry@0.3.23:
- resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==}
-
- language-tags@1.0.9:
- resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==}
- engines: {node: '>=0.10'}
-
leven@3.1.0:
resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==}
engines: {node: '>=6'}
@@ -4018,6 +4330,9 @@ packages:
libphonenumber-js@1.12.15:
resolution: {integrity: sha512-TMDCtIhWUDHh91wRC+wFuGlIzKdPzaTUHHVrIZ3vPUEoNaXFLrsIQ1ZpAeZeXApIF6rvDksMTvjrIQlLKaYxqQ==}
+ light-my-request@6.6.0:
+ resolution: {integrity: sha512-CHYbu8RtboSIoVsHZ6Ye4cj4Aw/yg2oAFimlF7mNvfDV192LR7nDiKtSIfCuLT7KokPSTn/9kfVLm5OGN0A28A==}
+
lightningcss-android-arm64@1.32.0:
resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==}
engines: {node: '>= 12.0.0'}
@@ -4145,8 +4460,9 @@ packages:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
hasBin: true
- lower-case@2.0.2:
- resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==}
+ lru-cache@11.5.0:
+ resolution: {integrity: sha512-5YgH9UJd7wVb9hIouI2adWpgqrrICkt070Dnj8EUY1+B4B2P9eRLPAkAAo6NICA7CEhOIeBHl46u9zSNpNu7zA==}
+ engines: {node: 20 || >=22}
lru-cache@5.1.1:
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
@@ -4170,10 +4486,6 @@ packages:
magic-string@0.30.21:
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
- make-dir@3.1.0:
- resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==}
- engines: {node: '>=8'}
-
make-dir@4.0.0:
resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==}
engines: {node: '>=10'}
@@ -4203,12 +4515,6 @@ packages:
md5@2.3.0:
resolution: {integrity: sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==}
- mdn-data@2.0.28:
- resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==}
-
- mdn-data@2.0.30:
- resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==}
-
media-captions@0.0.18:
resolution: {integrity: sha512-JW18P6FuHdyLSGwC4TQ0kF3WdNj/+wMw2cKOb8BnmY6vSJGtnwJ+vkYj+IjHOV34j3XMc70HDeB/QYKR7E7fuQ==}
engines: {node: '>=16'}
@@ -4244,6 +4550,11 @@ packages:
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
engines: {node: '>= 0.6'}
+ mime@3.0.0:
+ resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==}
+ engines: {node: '>=10.0.0'}
+ hasBin: true
+
mimic-fn@2.1.0:
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
engines: {node: '>=6'}
@@ -4256,6 +4567,10 @@ packages:
resolution: {integrity: sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==}
hasBin: true
+ minimatch@10.2.5:
+ resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==}
+ engines: {node: 18 || 20 || >=22}
+
minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
@@ -4267,8 +4582,9 @@ packages:
resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==}
engines: {node: '>= 6'}
- minimist@1.2.8:
- resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
+ minipass@7.1.3:
+ resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==}
+ engines: {node: '>=16 || 14 >=14.17'}
mkdirp@2.1.3:
resolution: {integrity: sha512-sjAkg21peAG9HS+Dkx7hlG9Ztx7HLeKnvB3NQRcu/mltCVmvkF0pisbiTSfDVYTT86XEfZrTUosLdZLStquZUw==}
@@ -4301,11 +4617,6 @@ packages:
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
- napi-postinstall@0.2.4:
- resolution: {integrity: sha512-ZEzHJwBhZ8qQSbknHqYcdtQVr8zUgGyM/q6h6qAyhtyVMNrSgDhrC4disf03dYW0e+czXyLnZINnCTEkWy0eJg==}
- engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
- hasBin: true
-
natural-compare-lite@1.4.0:
resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==}
@@ -4315,46 +4626,9 @@ packages:
neo-async@2.6.2:
resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
- next-pwa@5.6.0:
- resolution: {integrity: sha512-XV8g8C6B7UmViXU8askMEYhWwQ4qc/XqJGnexbLV68hzKaGHZDMtHsm2TNxFcbR7+ypVuth/wwpiIlMwpRJJ5A==}
- peerDependencies:
- next: '>=9.0.0'
-
- next-router-mock@0.9.13:
- resolution: {integrity: sha512-906n2RRaE6Y28PfYJbaz5XZeJ6Tw8Xz1S6E31GGwZ0sXB6/XjldD1/2azn1ZmBmRk5PQRkzjg+n+RHZe5xQzWA==}
- peerDependencies:
- next: '>=10.0.0'
- react: '>=17.0.0'
-
- next-themes@0.4.6:
- resolution: {integrity: sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==}
- peerDependencies:
- react: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc
- react-dom: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc
-
- next@15.5.18:
- resolution: {integrity: sha512-eKL8zUJkX9Y5lE+RX/2YJoItVdGlIscyVyboeD9wSpp0PaGqjoA4tTpT2qPqz9ax+5IzGESyLSeZ/RCwbSZ2uQ==}
- engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0}
- hasBin: true
- peerDependencies:
- '@opentelemetry/api': ^1.1.0
- '@playwright/test': ^1.51.1
- babel-plugin-react-compiler: '*'
- react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0
- react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0
- sass: ^1.3.0
- peerDependenciesMeta:
- '@opentelemetry/api':
- optional: true
- '@playwright/test':
- optional: true
- babel-plugin-react-compiler:
- optional: true
- sass:
- optional: true
-
- no-case@3.0.4:
- resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==}
+ node-exports-info@1.6.0:
+ resolution: {integrity: sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==}
+ engines: {node: '>= 0.4'}
node-int64@0.4.0:
resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==}
@@ -4365,6 +4639,10 @@ packages:
node-releases@2.0.20:
resolution: {integrity: sha512-7gK6zSXEH6neM212JgfYFXe+GmZQM+fia5SsusuBIUgnPheLFBmIPhtFoAQRj8/7wASYQnbDlHPVwY0BefoFgA==}
+ node-releases@2.0.46:
+ resolution: {integrity: sha512-GYVXHE2KnrzAfsAjl4uP++evGFCrAU1jta4ubEjIG7YWt/64Gqv66a30yKwWczVjA6j3bM4nBwH7Pk1JmDHaxQ==}
+ engines: {node: '>=18'}
+
normalize-package-data@2.5.0:
resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==}
@@ -4384,9 +4662,6 @@ packages:
resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
engines: {node: '>=8'}
- nth-check@2.1.1:
- resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
-
nwsapi@2.2.20:
resolution: {integrity: sha512-/ieB+mDe4MrrKMT8z+mQL8klXydZWGR5Dowt4RAGKbJ3kIGEx3X4ljUo+6V73IXtUPWgfOlU5B9MlGxFO5T+cA==}
@@ -4418,14 +4693,14 @@ packages:
resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==}
engines: {node: '>= 0.4'}
- object.groupby@1.0.3:
- resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==}
- engines: {node: '>= 0.4'}
-
object.values@1.2.1:
resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==}
engines: {node: '>= 0.4'}
+ on-exit-leak-free@2.1.2:
+ resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==}
+ engines: {node: '>=14.0.0'}
+
once@1.4.0:
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
@@ -4468,10 +4743,6 @@ packages:
resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
engines: {node: '>=10'}
- p-map@2.1.0:
- resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==}
- engines: {node: '>=6'}
-
p-map@4.0.0:
resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==}
engines: {node: '>=10'}
@@ -4499,9 +4770,6 @@ packages:
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
engines: {node: '>=0.10.0'}
- path-is-inside@1.0.2:
- resolution: {integrity: sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==}
-
path-key@3.1.1:
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
engines: {node: '>=8'}
@@ -4509,6 +4777,13 @@ packages:
path-parse@1.0.7:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+ path-scurry@2.0.2:
+ resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==}
+ engines: {node: 18 || 20 || >=22}
+
+ path-to-regexp@8.4.2:
+ resolution: {integrity: sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==}
+
path-type@4.0.0:
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
engines: {node: '>=8'}
@@ -4524,26 +4799,24 @@ packages:
resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==}
engines: {node: '>=12'}
+ picomatch@4.0.4:
+ resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==}
+ engines: {node: '>=12'}
+
pidtree@0.5.0:
resolution: {integrity: sha512-9nxspIM7OpZuhBxPg73Zvyq7j1QMPMPsGKTqRc2XOaFQauDvoNz9fM1Wdkjmeo7l9GXOZiRs97sPkuayl39wjA==}
engines: {node: '>=0.10'}
hasBin: true
- pify@2.3.0:
- resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
- engines: {node: '>=0.10.0'}
+ pino-abstract-transport@3.0.0:
+ resolution: {integrity: sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==}
- pify@4.0.1:
- resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==}
- engines: {node: '>=6'}
+ pino-std-serializers@7.1.0:
+ resolution: {integrity: sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==}
- pinkie-promise@2.0.1:
- resolution: {integrity: sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==}
- engines: {node: '>=0.10.0'}
-
- pinkie@2.0.4:
- resolution: {integrity: sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==}
- engines: {node: '>=0.10.0'}
+ pino@10.3.1:
+ resolution: {integrity: sha512-r34yH/GlQpKZbU1BvFFqOjhISRo1MNx1tWYsYvmj6KIRHSPMT2+yHOEb1SG6NMvRoHRF0a07kCOox/9yakl1vg==}
+ hasBin: true
pirates@4.0.7:
resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==}
@@ -4570,10 +4843,6 @@ packages:
postcss-value-parser@4.2.0:
resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
- postcss@8.4.31:
- resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==}
- engines: {node: ^10 || ^12 || >=14}
-
postcss@8.5.15:
resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==}
engines: {node: ^10 || ^12 || >=14}
@@ -4651,13 +4920,19 @@ packages:
resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==}
engines: {node: '>=6'}
+ pretty-bytes@6.1.1:
+ resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==}
+ engines: {node: ^14.13.1 || >=16.0.0}
+
pretty-format@27.5.1:
resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
- pretty-format@30.0.0:
- resolution: {integrity: sha512-18NAOUr4ZOQiIR+BgI5NhQE7uREdx4ZyV0dyay5izh4yfQ+1T7BSvggxvRGoXocrRyevqW5OhScUjbi9GB8R8Q==}
- engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+ process-warning@4.0.1:
+ resolution: {integrity: sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==}
+
+ process-warning@5.0.0:
+ resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==}
process@0.11.10:
resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==}
@@ -4691,6 +4966,9 @@ packages:
queue-microtask@1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+ quick-format-unescaped@4.0.4:
+ resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==}
+
quick-lru@4.0.1:
resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==}
engines: {node: '>=8'}
@@ -4731,8 +5009,22 @@ packages:
react-is@17.0.2:
resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
- react-is@18.3.1:
- resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==}
+ react-router-dom@7.15.1:
+ resolution: {integrity: sha512-AzF62gjY6U9rkMq4RfP/r2EVtQ7DMfNMjyOp/flLTCrtRylLiK4wT4pSq6O8rOXZ2eXdZYJPEYe+ifomiv+Igg==}
+ engines: {node: '>=20.0.0'}
+ peerDependencies:
+ react: '>=18'
+ react-dom: '>=18'
+
+ react-router@7.15.1:
+ resolution: {integrity: sha512-R8rl9HhgikFYoPJymnUtPXWbnDb3oget6lQnfIoupbt61aT9aOhRkDsY2XRhZRyX1Z/8a5sL74fXmFNm3NRK5A==}
+ engines: {node: '>=20.0.0'}
+ peerDependencies:
+ react: '>=18'
+ react-dom: '>=18'
+ peerDependenciesMeta:
+ react-dom:
+ optional: true
react-stately@3.46.0:
resolution: {integrity: sha512-OdxhWvHgs2L4OJGIs7hnuTr5WjjMM6enhNEAMRqiekhF8+ITvA2LRwNftOZwcogaoCslGYq5S2VQTQwnm0GbCA==}
@@ -4761,6 +5053,13 @@ packages:
resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
engines: {node: '>= 6'}
+ real-require@0.2.0:
+ resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==}
+ engines: {node: '>= 12.13.0'}
+
+ real-require@1.0.0:
+ resolution: {integrity: sha512-P4nbQYQfePJxRSmY+v/KINxVucm4NF3p3s7pJveMTtom52FR4YGltUQLB8idDXwDDWW+eYrWDFbuzUnjoWHF7g==}
+
redent@3.0.0:
resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==}
engines: {node: '>=8'}
@@ -4779,6 +5078,10 @@ packages:
resolution: {integrity: sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==}
engines: {node: '>=4'}
+ regenerate-unicode-properties@10.2.2:
+ resolution: {integrity: sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==}
+ engines: {node: '>=4'}
+
regenerate@1.4.2:
resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==}
@@ -4790,6 +5093,10 @@ packages:
resolution: {integrity: sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==}
engines: {node: '>=4'}
+ regexpu-core@6.4.0:
+ resolution: {integrity: sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==}
+ engines: {node: '>=4'}
+
regjsgen@0.8.0:
resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==}
@@ -4797,6 +5104,10 @@ packages:
resolution: {integrity: sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==}
hasBin: true
+ regjsparser@0.13.1:
+ resolution: {integrity: sha512-dLsljMd9sqwRkby8zhO1gSg3PnJIBFid8f4CQj/sXx+7cKx+E7u0PKhZ+U4wmhx7EfmtvnA318oVaIkAB1lRJw==}
+ hasBin: true
+
require-directory@2.1.1:
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
engines: {node: '>=0.10.0'}
@@ -4824,9 +5135,6 @@ packages:
resolution: {integrity: sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==}
engines: {node: '>=8'}
- resolve-pkg-maps@1.0.0:
- resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
-
resolve.exports@1.1.1:
resolution: {integrity: sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==}
engines: {node: '>=10'}
@@ -4836,14 +5144,24 @@ packages:
engines: {node: '>= 0.4'}
hasBin: true
- resolve@2.0.0-next.5:
- resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==}
+ resolve@1.22.12:
+ resolution: {integrity: sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==}
+ engines: {node: '>= 0.4'}
+ hasBin: true
+
+ resolve@2.0.0-next.7:
+ resolution: {integrity: sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==}
+ engines: {node: '>= 0.4'}
hasBin: true
restore-cursor@3.1.0:
resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==}
engines: {node: '>=8'}
+ ret@0.5.0:
+ resolution: {integrity: sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw==}
+ engines: {node: '>=10'}
+
reusify@1.1.0:
resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
@@ -4851,16 +5169,16 @@ packages:
rfdc@1.4.1:
resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==}
- rimraf@2.7.1:
- resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==}
- deprecated: Rimraf versions prior to v4 are no longer supported
- hasBin: true
-
rimraf@3.0.2:
resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
deprecated: Rimraf versions prior to v4 are no longer supported
hasBin: true
+ rolldown@1.0.2:
+ resolution: {integrity: sha512-oZx5zVDtVB44AW3eaifgDml1gWRDZGvjcfdxonE4swNPG98PrrXjaO/KrnUjzlMnztCCRVlUueA1kCXhARGk6g==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ hasBin: true
+
rollup-plugin-terser@7.0.2:
resolution: {integrity: sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==}
deprecated: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser
@@ -4893,6 +5211,14 @@ packages:
resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==}
engines: {node: '>= 0.4'}
+ safe-regex2@5.1.1:
+ resolution: {integrity: sha512-mOSBvHGDZMuIEZMdOz/aCEYDCv0E7nfcNsIhUF+/P+xC7Hyf3FkvymqgPbg9D1EdSGu+uKbJgy09K/RKKc7kJA==}
+ hasBin: true
+
+ safe-stable-stringify@2.5.0:
+ resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==}
+ engines: {node: '>=10'}
+
safer-buffer@2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
@@ -4903,14 +5229,13 @@ packages:
scheduler@0.27.0:
resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
- schema-utils@2.7.1:
- resolution: {integrity: sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==}
- engines: {node: '>= 8.9.0'}
-
schema-utils@4.3.2:
resolution: {integrity: sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==}
engines: {node: '>= 10.13.0'}
+ secure-json-parse@4.1.0:
+ resolution: {integrity: sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==}
+
semver@5.7.2:
resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==}
hasBin: true
@@ -4940,6 +5265,9 @@ packages:
serialize-javascript@6.0.2:
resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==}
+ set-cookie-parser@2.7.2:
+ resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==}
+
set-function-length@1.2.2:
resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
engines: {node: '>= 0.4'}
@@ -4952,9 +5280,8 @@ packages:
resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==}
engines: {node: '>= 0.4'}
- sharp@0.34.5:
- resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==}
- engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ setprototypeof@1.2.0:
+ resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
shebang-command@2.0.0:
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
@@ -5002,8 +5329,8 @@ packages:
resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==}
engines: {node: '>=12'}
- snake-case@3.0.4:
- resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==}
+ sonic-boom@4.2.1:
+ resolution: {integrity: sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==}
source-list-map@2.0.1:
resolution: {integrity: sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==}
@@ -5030,6 +5357,7 @@ packages:
source-map@0.8.0-beta.0:
resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==}
engines: {node: '>= 8'}
+ deprecated: The work that was done in this beta branch won't be included in future versions
sourcemap-codec@1.4.8:
resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==}
@@ -5050,16 +5378,21 @@ packages:
split2@3.2.2:
resolution: {integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==}
+ split2@4.2.0:
+ resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
+ engines: {node: '>= 10.x'}
+
sprintf-js@1.0.3:
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
- stable-hash@0.0.5:
- resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==}
-
stack-utils@2.0.6:
resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==}
engines: {node: '>=10'}
+ statuses@2.0.2:
+ resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
+ engines: {node: '>= 0.8'}
+
stop-iteration-iterator@1.1.0:
resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
engines: {node: '>= 0.4'}
@@ -5083,10 +5416,6 @@ packages:
resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
engines: {node: '>=12'}
- string.prototype.includes@2.0.1:
- resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==}
- engines: {node: '>= 0.4'}
-
string.prototype.matchall@4.0.12:
resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==}
engines: {node: '>= 0.4'}
@@ -5124,10 +5453,6 @@ packages:
resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
engines: {node: '>=12'}
- strip-bom@3.0.0:
- resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
- engines: {node: '>=4'}
-
strip-bom@4.0.0:
resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==}
engines: {node: '>=8'}
@@ -5148,19 +5473,6 @@ packages:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'}
- styled-jsx@5.1.6:
- resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==}
- engines: {node: '>= 12.0.0'}
- peerDependencies:
- '@babel/core': '*'
- babel-plugin-macros: '*'
- react: '>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0'
- peerDependenciesMeta:
- '@babel/core':
- optional: true
- babel-plugin-macros:
- optional: true
-
supports-color@7.2.0:
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
engines: {node: '>=8'}
@@ -5181,14 +5493,6 @@ packages:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
- svg-parser@2.0.4:
- resolution: {integrity: sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==}
-
- svgo@3.3.2:
- resolution: {integrity: sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==}
- engines: {node: '>=14.0.0'}
- hasBin: true
-
swiper@11.2.8:
resolution: {integrity: sha512-S5FVf6zWynPWooi7pJ7lZhSUe2snTzqLuUzbd5h5PHUOhzgvW0bLKBd2wv0ixn6/5o9vwc/IkQT74CRcLJQzeg==}
engines: {node: '>= 4.7.0'}
@@ -5260,6 +5564,10 @@ packages:
text-table@0.2.0:
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
+ thread-stream@4.2.0:
+ resolution: {integrity: sha512-e2zZ96wSChazBsbENf/Pcm/4swHt2cEKQ92rhUjkL9GCKiTDJIaTBenjE/m9DXi0QBmTMDkFDdOomUy20A1tDQ==}
+ engines: {node: '>=20'}
+
throat@6.0.2:
resolution: {integrity: sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==}
@@ -5273,6 +5581,10 @@ packages:
resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==}
engines: {node: '>=12.0.0'}
+ tinyglobby@0.2.16:
+ resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==}
+ engines: {node: '>=12.0.0'}
+
tmpl@1.0.5:
resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==}
@@ -5280,6 +5592,14 @@ packages:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
engines: {node: '>=8.0'}
+ toad-cache@3.7.1:
+ resolution: {integrity: sha512-5DXWzE4Vz7xNHsv+xQ+MGfJYyC78Aok3tEr0MNwHoRf7vZnga1mQXZ4/Nsodld4VR6Wd+VhfmqnNrsRJyYPfrQ==}
+ engines: {node: '>=20'}
+
+ toidentifier@1.0.1:
+ resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
+ engines: {node: '>=0.6'}
+
tough-cookie@4.1.4:
resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==}
engines: {node: '>=6'}
@@ -5309,9 +5629,6 @@ packages:
'@swc/wasm':
optional: true
- tsconfig-paths@3.15.0:
- resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==}
-
tslib@1.14.1:
resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
@@ -5327,6 +5644,11 @@ packages:
peerDependencies:
typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta'
+ tsx@4.22.3:
+ resolution: {integrity: sha512-mdoNxBC/cSQObGGVQ5Bpn5i+yv7j68gk3Nfm3wFjcJg3Z0Mix9jzAFfP12prmm5eVGmDKtp0yyArrs0Q+8gZHg==}
+ engines: {node: '>=18.0.0'}
+ hasBin: true
+
tw-animate-css@1.4.0:
resolution: {integrity: sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==}
@@ -5409,6 +5731,10 @@ packages:
undici-types@7.8.0:
resolution: {integrity: sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==}
+ undici@8.3.0:
+ resolution: {integrity: sha512-TkUDgb6tl7KOGZ+7e8E3d2FYgUQgF6z5YypqjWmixVQSQERFcVrVg0ySADm2LVLRh5ljAaHTCR5Fmz3Q34rB7Q==}
+ engines: {node: '>=22.19.0'}
+
unicode-canonical-property-names-ecmascript@2.0.1:
resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==}
engines: {node: '>=4'}
@@ -5421,6 +5747,10 @@ packages:
resolution: {integrity: sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==}
engines: {node: '>=4'}
+ unicode-match-property-value-ecmascript@2.2.1:
+ resolution: {integrity: sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==}
+ engines: {node: '>=4'}
+
unicode-property-aliases-ecmascript@2.1.0:
resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==}
engines: {node: '>=4'}
@@ -5437,9 +5767,6 @@ packages:
resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
engines: {node: '>= 10.0.0'}
- unrs-resolver@1.9.0:
- resolution: {integrity: sha512-wqaRu4UnzBD2ABTC1kLfBjAqIDZ5YUTr/MLGa7By47JV1bJDSW7jq/ZSLigB7enLe7ubNaJhtnBXgrc/50cEhg==}
-
upath@1.2.0:
resolution: {integrity: sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==}
engines: {node: '>=4'}
@@ -5450,6 +5777,12 @@ packages:
peerDependencies:
browserslist: '>= 4.21.0'
+ update-browserslist-db@1.2.3:
+ resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==}
+ hasBin: true
+ peerDependencies:
+ browserslist: '>= 4.21.0'
+
uri-js@4.4.1:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
@@ -5490,6 +5823,61 @@ packages:
resolution: {integrity: sha512-pI2aixBuOpu/LSnRgNJ40tU/KFW+x1X+O2bW1hz946ZZShDM5oqRXF9pavDOuckHAHPgUN9HYUr9vUNTBUPF1Q==}
engines: {node: '>=16'}
+ vite-plugin-pwa@1.3.0:
+ resolution: {integrity: sha512-c5kMgN+ITrOtHXp8PAtk2uOIEea6XjP/unCGxOWWBzQ6qa65qj/awHg0wf+QF9E/2u9vh86LqxPwzEPNbM2r5A==}
+ engines: {node: '>=16.0.0'}
+ peerDependencies:
+ '@vite-pwa/assets-generator': ^1.0.0
+ vite: ^3.1.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0
+ workbox-build: ^7.4.1
+ workbox-window: ^7.4.1
+ peerDependenciesMeta:
+ '@vite-pwa/assets-generator':
+ optional: true
+
+ vite@8.0.14:
+ resolution: {integrity: sha512-s4BJJ+5y1pYL6Otw51FHhVJQhPnuRinKig64g/1+EUNaJsd3gCKdD31IPFvswUgW9/60QT9oFHbZHbQK5imcxw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^20.19.0 || >=22.12.0
+ '@vitejs/devtools': ^0.1.18
+ 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
+
w3c-hr-time@1.0.2:
resolution: {integrity: sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==}
deprecated: Use your platform's native performance.now() and performance.timeOrigin.
@@ -5522,9 +5910,6 @@ packages:
javascript-obfuscator: ^2.8.0 || ^3.0.0 || ^4.0.0
webpack: ^5.1.0
- webpack-sources@1.4.3:
- resolution: {integrity: sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==}
-
webpack-sources@2.3.1:
resolution: {integrity: sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==}
engines: {node: '>=10.13.0'}
@@ -5629,12 +6014,6 @@ packages:
workbox-sw@6.6.0:
resolution: {integrity: sha512-R2IkwDokbtHUE4Kus8pKO5+VkPHD2oqTgl+XJwh4zbF1HyjAbgNmK/FneZHVU7p03XUt9ICfuGDYISWG9qV/CQ==}
- workbox-webpack-plugin@6.6.0:
- resolution: {integrity: sha512-xNZIZHalboZU66Wa7x1YkjIqEy1gTR+zPM+kjrYJzqN7iurYZBctBLISyScjhkJKYuRrZUP0iqViZTh8rS0+3A==}
- engines: {node: '>=10.0.0'}
- peerDependencies:
- webpack: ^4.4.0 || ^5.9.0
-
workbox-window@6.6.0:
resolution: {integrity: sha512-L4N9+vka17d16geaJXXRjENLFldvkWy7JyGxElRD0JvBxvFEd8LOhr+uXCcar/NzAmIBRv9EZ+M+Qr4mOoBITw==}
@@ -5720,6 +6099,12 @@ packages:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'}
+ zod-validation-error@4.0.2:
+ resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==}
+ engines: {node: '>=18.0.0'}
+ peerDependencies:
+ zod: ^3.25.0 || ^4.0.0
+
zod@3.25.67:
resolution: {integrity: sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==}
@@ -5756,11 +6141,6 @@ snapshots:
'@alloc/quick-lru@5.2.0': {}
- '@ampproject/remapping@2.3.0':
- dependencies:
- '@jridgewell/gen-mapping': 0.3.8
- '@jridgewell/trace-mapping': 0.3.25
-
'@apideck/better-ajv-errors@0.3.6(ajv@8.17.1)':
dependencies:
ajv: 8.17.1
@@ -5774,20 +6154,26 @@ snapshots:
js-tokens: 4.0.0
picocolors: 1.1.1
- '@babel/compat-data@7.27.5': {}
-
- '@babel/core@7.27.4':
+ '@babel/code-frame@7.29.7':
dependencies:
- '@ampproject/remapping': 2.3.0
- '@babel/code-frame': 7.27.1
- '@babel/generator': 7.27.5
- '@babel/helper-compilation-targets': 7.27.2
- '@babel/helper-module-transforms': 7.27.3(@babel/core@7.27.4)
- '@babel/helpers': 7.27.6
- '@babel/parser': 7.27.5
- '@babel/template': 7.27.2
- '@babel/traverse': 7.27.4
- '@babel/types': 7.27.6
+ '@babel/helper-validator-identifier': 7.29.7
+ js-tokens: 4.0.0
+ picocolors: 1.1.1
+
+ '@babel/compat-data@7.29.7': {}
+
+ '@babel/core@7.29.7':
+ dependencies:
+ '@babel/code-frame': 7.29.7
+ '@babel/generator': 7.29.7
+ '@babel/helper-compilation-targets': 7.29.7
+ '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7)
+ '@babel/helpers': 7.29.7
+ '@babel/parser': 7.29.7
+ '@babel/template': 7.29.7
+ '@babel/traverse': 7.29.7
+ '@babel/types': 7.29.7
+ '@jridgewell/remapping': 2.3.5
convert-source-map: 2.0.0
debug: 4.4.1(supports-color@9.4.0)
gensync: 1.0.0-beta.2
@@ -5804,42 +6190,74 @@ snapshots:
'@jridgewell/trace-mapping': 0.3.25
jsesc: 3.1.0
+ '@babel/generator@7.29.7':
+ dependencies:
+ '@babel/parser': 7.29.7
+ '@babel/types': 7.29.7
+ '@jridgewell/gen-mapping': 0.3.13
+ '@jridgewell/trace-mapping': 0.3.31
+ jsesc: 3.1.0
+
'@babel/helper-annotate-as-pure@7.27.3':
dependencies:
- '@babel/types': 7.27.6
+ '@babel/types': 7.29.7
- '@babel/helper-compilation-targets@7.27.2':
+ '@babel/helper-annotate-as-pure@7.29.7':
dependencies:
- '@babel/compat-data': 7.27.5
- '@babel/helper-validator-option': 7.27.1
- browserslist: 4.25.0
+ '@babel/types': 7.29.7
+
+ '@babel/helper-compilation-targets@7.29.7':
+ dependencies:
+ '@babel/compat-data': 7.29.7
+ '@babel/helper-validator-option': 7.29.7
+ browserslist: 4.25.4
lru-cache: 5.1.1
semver: 6.3.1
- '@babel/helper-create-class-features-plugin@7.27.1(@babel/core@7.27.4)':
+ '@babel/helper-create-class-features-plugin@7.27.1(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
'@babel/helper-annotate-as-pure': 7.27.3
'@babel/helper-member-expression-to-functions': 7.27.1
'@babel/helper-optimise-call-expression': 7.27.1
- '@babel/helper-replace-supers': 7.27.1(@babel/core@7.27.4)
+ '@babel/helper-replace-supers': 7.27.1(@babel/core@7.29.7)
'@babel/helper-skip-transparent-expression-wrappers': 7.27.1
- '@babel/traverse': 7.27.4
+ '@babel/traverse': 7.29.7
semver: 6.3.1
transitivePeerDependencies:
- supports-color
- '@babel/helper-create-regexp-features-plugin@7.27.1(@babel/core@7.27.4)':
+ '@babel/helper-create-class-features-plugin@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
+ '@babel/helper-annotate-as-pure': 7.29.7
+ '@babel/helper-member-expression-to-functions': 7.29.7
+ '@babel/helper-optimise-call-expression': 7.29.7
+ '@babel/helper-replace-supers': 7.29.7(@babel/core@7.29.7)
+ '@babel/helper-skip-transparent-expression-wrappers': 7.29.7
+ '@babel/traverse': 7.29.7
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-create-regexp-features-plugin@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
'@babel/helper-annotate-as-pure': 7.27.3
regexpu-core: 6.2.0
semver: 6.3.1
- '@babel/helper-define-polyfill-provider@0.6.4(@babel/core@7.27.4)':
+ '@babel/helper-create-regexp-features-plugin@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-compilation-targets': 7.27.2
+ '@babel/core': 7.29.7
+ '@babel/helper-annotate-as-pure': 7.29.7
+ regexpu-core: 6.4.0
+ semver: 6.3.1
+
+ '@babel/helper-define-polyfill-provider@0.6.4(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-compilation-targets': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
debug: 4.4.1(supports-color@9.4.0)
lodash.debounce: 4.0.8
@@ -5847,684 +6265,1214 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@babel/helper-define-polyfill-provider@0.6.8(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-compilation-targets': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+ debug: 4.4.3
+ lodash.debounce: 4.0.8
+ resolve: 1.22.12
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-globals@7.29.7': {}
+
'@babel/helper-member-expression-to-functions@7.27.1':
dependencies:
- '@babel/traverse': 7.27.4
- '@babel/types': 7.27.6
+ '@babel/traverse': 7.29.7
+ '@babel/types': 7.29.7
transitivePeerDependencies:
- supports-color
- '@babel/helper-module-imports@7.27.1':
+ '@babel/helper-member-expression-to-functions@7.29.7':
dependencies:
- '@babel/traverse': 7.27.4
- '@babel/types': 7.27.6
+ '@babel/traverse': 7.29.7
+ '@babel/types': 7.29.7
transitivePeerDependencies:
- supports-color
- '@babel/helper-module-transforms@7.27.3(@babel/core@7.27.4)':
+ '@babel/helper-module-imports@7.29.7':
dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-module-imports': 7.27.1
- '@babel/helper-validator-identifier': 7.27.1
- '@babel/traverse': 7.27.4
+ '@babel/traverse': 7.29.7
+ '@babel/types': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-module-imports': 7.29.7
+ '@babel/helper-validator-identifier': 7.29.7
+ '@babel/traverse': 7.29.7
transitivePeerDependencies:
- supports-color
'@babel/helper-optimise-call-expression@7.27.1':
dependencies:
- '@babel/types': 7.27.6
+ '@babel/types': 7.29.7
+
+ '@babel/helper-optimise-call-expression@7.29.7':
+ dependencies:
+ '@babel/types': 7.29.7
'@babel/helper-plugin-utils@7.27.1': {}
- '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.27.4)':
+ '@babel/helper-plugin-utils@7.29.7': {}
+
+ '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
'@babel/helper-annotate-as-pure': 7.27.3
'@babel/helper-wrap-function': 7.27.1
- '@babel/traverse': 7.27.4
+ '@babel/traverse': 7.29.7
transitivePeerDependencies:
- supports-color
- '@babel/helper-replace-supers@7.27.1(@babel/core@7.27.4)':
+ '@babel/helper-remap-async-to-generator@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
+ '@babel/helper-annotate-as-pure': 7.29.7
+ '@babel/helper-wrap-function': 7.29.7
+ '@babel/traverse': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-replace-supers@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
'@babel/helper-member-expression-to-functions': 7.27.1
'@babel/helper-optimise-call-expression': 7.27.1
- '@babel/traverse': 7.27.4
+ '@babel/traverse': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-replace-supers@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-member-expression-to-functions': 7.29.7
+ '@babel/helper-optimise-call-expression': 7.29.7
+ '@babel/traverse': 7.29.7
transitivePeerDependencies:
- supports-color
'@babel/helper-skip-transparent-expression-wrappers@7.27.1':
dependencies:
- '@babel/traverse': 7.27.4
- '@babel/types': 7.27.6
+ '@babel/traverse': 7.29.7
+ '@babel/types': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-skip-transparent-expression-wrappers@7.29.7':
+ dependencies:
+ '@babel/traverse': 7.29.7
+ '@babel/types': 7.29.7
transitivePeerDependencies:
- supports-color
'@babel/helper-string-parser@7.27.1': {}
+ '@babel/helper-string-parser@7.29.7': {}
+
'@babel/helper-validator-identifier@7.27.1': {}
- '@babel/helper-validator-option@7.27.1': {}
+ '@babel/helper-validator-identifier@7.29.7': {}
+
+ '@babel/helper-validator-option@7.29.7': {}
'@babel/helper-wrap-function@7.27.1':
dependencies:
- '@babel/template': 7.27.2
- '@babel/traverse': 7.27.4
- '@babel/types': 7.27.6
+ '@babel/template': 7.29.7
+ '@babel/traverse': 7.29.7
+ '@babel/types': 7.29.7
transitivePeerDependencies:
- supports-color
- '@babel/helpers@7.27.6':
+ '@babel/helper-wrap-function@7.29.7':
dependencies:
- '@babel/template': 7.27.2
- '@babel/types': 7.27.6
+ '@babel/template': 7.29.7
+ '@babel/traverse': 7.29.7
+ '@babel/types': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helpers@7.29.7':
+ dependencies:
+ '@babel/template': 7.29.7
+ '@babel/types': 7.29.7
'@babel/parser@7.27.5':
dependencies:
'@babel/types': 7.27.6
- '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.27.1(@babel/core@7.27.4)':
+ '@babel/parser@7.29.7':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/types': 7.29.7
+
+ '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
- '@babel/traverse': 7.27.4
+ '@babel/traverse': 7.29.7
transitivePeerDependencies:
- supports-color
- '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+ '@babel/traverse': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-bugfix-safari-rest-destructuring-rhs-array@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+ '@babel/helper-skip-transparent-expression-wrappers': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
'@babel/helper-skip-transparent-expression-wrappers': 7.27.1
- '@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.27.4)
+ '@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.29.7)
transitivePeerDependencies:
- supports-color
- '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
- '@babel/traverse': 7.27.4
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+ '@babel/helper-skip-transparent-expression-wrappers': 7.29.7
+ '@babel/plugin-transform-optional-chaining': 7.29.7(@babel/core@7.29.7)
transitivePeerDependencies:
- supports-color
- '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.27.4)':
+ '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.27.1(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
-
- '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-syntax-import-assertions@7.27.1(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.27.4)
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-transform-async-generator-functions@7.27.1(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
- '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.27.4)
- '@babel/traverse': 7.27.4
+ '@babel/traverse': 7.29.7
transitivePeerDependencies:
- supports-color
- '@babel/plugin-transform-async-to-generator@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-module-imports': 7.27.1
- '@babel/helper-plugin-utils': 7.27.1
- '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.27.4)
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+ '@babel/traverse': 7.29.7
transitivePeerDependencies:
- supports-color
- '@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
+
+ '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-block-scoping@7.27.5(@babel/core@7.27.4)':
+ '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-class-properties@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.27.4)
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-import-assertions@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-import-assertions@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-import-attributes@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-jsx@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-typescript@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.29.7)
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-transform-arrow-functions@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-async-generator-functions@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.27.1
+ '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.29.7)
+ '@babel/traverse': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-async-generator-functions@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+ '@babel/helper-remap-async-to-generator': 7.29.7(@babel/core@7.29.7)
+ '@babel/traverse': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-async-to-generator@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-module-imports': 7.29.7
+ '@babel/helper-plugin-utils': 7.27.1
+ '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.29.7)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-async-to-generator@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-module-imports': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+ '@babel/helper-remap-async-to-generator': 7.29.7(@babel/core@7.29.7)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-transform-block-scoped-functions@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-block-scoping@7.27.5(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-transform-block-scoping@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-class-properties@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.29.7)
'@babel/helper-plugin-utils': 7.27.1
transitivePeerDependencies:
- supports-color
- '@babel/plugin-transform-class-static-block@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-class-properties@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.27.4)
+ '@babel/core': 7.29.7
+ '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7)
+ '@babel/helper-plugin-utils': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-class-static-block@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.29.7)
'@babel/helper-plugin-utils': 7.27.1
transitivePeerDependencies:
- supports-color
- '@babel/plugin-transform-classes@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-class-static-block@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
+ '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7)
+ '@babel/helper-plugin-utils': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-classes@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
'@babel/helper-annotate-as-pure': 7.27.3
- '@babel/helper-compilation-targets': 7.27.2
+ '@babel/helper-compilation-targets': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
- '@babel/helper-replace-supers': 7.27.1(@babel/core@7.27.4)
- '@babel/traverse': 7.27.4
+ '@babel/helper-replace-supers': 7.27.1(@babel/core@7.29.7)
+ '@babel/traverse': 7.29.7
globals: 11.12.0
transitivePeerDependencies:
- supports-color
- '@babel/plugin-transform-computed-properties@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-classes@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
- '@babel/template': 7.27.2
+ '@babel/core': 7.29.7
+ '@babel/helper-annotate-as-pure': 7.29.7
+ '@babel/helper-compilation-targets': 7.29.7
+ '@babel/helper-globals': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+ '@babel/helper-replace-supers': 7.29.7(@babel/core@7.29.7)
+ '@babel/traverse': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
- '@babel/plugin-transform-destructuring@7.27.3(@babel/core@7.27.4)':
+ '@babel/plugin-transform-computed-properties@7.27.1(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.27.1
+ '@babel/template': 7.29.7
+
+ '@babel/plugin-transform-computed-properties@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+ '@babel/template': 7.29.7
+
+ '@babel/plugin-transform-destructuring@7.27.3(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-dotall-regex@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-destructuring@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.27.4)
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+ '@babel/traverse': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-dotall-regex@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.29.7)
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-duplicate-keys@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-dotall-regex@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
+ '@babel/helper-create-regexp-features-plugin': 7.29.7(@babel/core@7.29.7)
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-duplicate-keys@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-duplicate-keys@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.27.4)
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.29.7)
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-dynamic-import@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
+ '@babel/helper-create-regexp-features-plugin': 7.29.7(@babel/core@7.29.7)
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-dynamic-import@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-exponentiation-operator@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-dynamic-import@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-explicit-resource-management@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+ '@babel/plugin-transform-destructuring': 7.29.7(@babel/core@7.29.7)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-exponentiation-operator@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-exponentiation-operator@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-export-namespace-from@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
'@babel/helper-skip-transparent-expression-wrappers': 7.27.1
transitivePeerDependencies:
- supports-color
- '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-for-of@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-compilation-targets': 7.27.2
- '@babel/helper-plugin-utils': 7.27.1
- '@babel/traverse': 7.27.4
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+ '@babel/helper-skip-transparent-expression-wrappers': 7.29.7
transitivePeerDependencies:
- supports-color
- '@babel/plugin-transform-json-strings@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
+ '@babel/helper-compilation-targets': 7.29.7
+ '@babel/helper-plugin-utils': 7.27.1
+ '@babel/traverse': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-function-name@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-compilation-targets': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+ '@babel/traverse': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-json-strings@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-literals@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-json-strings@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-literals@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-logical-assignment-operators@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-literals@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-logical-assignment-operators@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-member-expression-literals@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-logical-assignment-operators@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-member-expression-literals@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-member-expression-literals@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-module-transforms': 7.27.3(@babel/core@7.27.4)
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7)
'@babel/helper-plugin-utils': 7.27.1
transitivePeerDependencies:
- supports-color
- '@babel/plugin-transform-modules-commonjs@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-modules-amd@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-module-transforms': 7.27.3(@babel/core@7.27.4)
+ '@babel/core': 7.29.7
+ '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7)
+ '@babel/helper-plugin-utils': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-modules-commonjs@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7)
'@babel/helper-plugin-utils': 7.27.1
transitivePeerDependencies:
- supports-color
- '@babel/plugin-transform-modules-systemjs@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-modules-commonjs@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-module-transforms': 7.27.3(@babel/core@7.27.4)
- '@babel/helper-plugin-utils': 7.27.1
- '@babel/helper-validator-identifier': 7.27.1
- '@babel/traverse': 7.27.4
+ '@babel/core': 7.29.7
+ '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7)
+ '@babel/helper-plugin-utils': 7.29.7
transitivePeerDependencies:
- supports-color
- '@babel/plugin-transform-modules-umd@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-modules-systemjs@7.27.1(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-module-transforms': 7.27.3(@babel/core@7.27.4)
+ '@babel/core': 7.29.7
+ '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7)
+ '@babel/helper-plugin-utils': 7.27.1
+ '@babel/helper-validator-identifier': 7.29.7
+ '@babel/traverse': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-modules-systemjs@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7)
+ '@babel/helper-plugin-utils': 7.29.7
+ '@babel/helper-validator-identifier': 7.29.7
+ '@babel/traverse': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-modules-umd@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7)
'@babel/helper-plugin-utils': 7.27.1
transitivePeerDependencies:
- supports-color
- '@babel/plugin-transform-named-capturing-groups-regex@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-modules-umd@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.27.4)
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-transform-new-target@7.27.1(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-transform-nullish-coalescing-operator@7.27.1(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-transform-numeric-separator@7.27.1(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-transform-object-rest-spread@7.27.3(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-compilation-targets': 7.27.2
- '@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-destructuring': 7.27.3(@babel/core@7.27.4)
- '@babel/plugin-transform-parameters': 7.27.1(@babel/core@7.27.4)
-
- '@babel/plugin-transform-object-super@7.27.1(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
- '@babel/helper-replace-supers': 7.27.1(@babel/core@7.27.4)
+ '@babel/core': 7.29.7
+ '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7)
+ '@babel/helper-plugin-utils': 7.29.7
transitivePeerDependencies:
- supports-color
- '@babel/plugin-transform-optional-catch-binding@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-named-capturing-groups-regex@7.27.1(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
+ '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.29.7)
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-optional-chaining@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-named-capturing-groups-regex@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
+ '@babel/helper-create-regexp-features-plugin': 7.29.7(@babel/core@7.29.7)
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-new-target@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-transform-new-target@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-nullish-coalescing-operator@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-transform-nullish-coalescing-operator@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-numeric-separator@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-transform-numeric-separator@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-object-rest-spread@7.27.3(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-compilation-targets': 7.29.7
+ '@babel/helper-plugin-utils': 7.27.1
+ '@babel/plugin-transform-destructuring': 7.27.3(@babel/core@7.29.7)
+ '@babel/plugin-transform-parameters': 7.27.1(@babel/core@7.29.7)
+
+ '@babel/plugin-transform-object-rest-spread@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-compilation-targets': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+ '@babel/plugin-transform-destructuring': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-parameters': 7.29.7(@babel/core@7.29.7)
+ '@babel/traverse': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-object-super@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.27.1
+ '@babel/helper-replace-supers': 7.27.1(@babel/core@7.29.7)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-object-super@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+ '@babel/helper-replace-supers': 7.29.7(@babel/core@7.29.7)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-optional-catch-binding@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-transform-optional-catch-binding@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-optional-chaining@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
'@babel/helper-skip-transparent-expression-wrappers': 7.27.1
transitivePeerDependencies:
- supports-color
- '@babel/plugin-transform-parameters@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-optional-chaining@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+ '@babel/helper-skip-transparent-expression-wrappers': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-parameters@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-private-methods@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-parameters@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.27.4)
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-private-methods@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.29.7)
'@babel/helper-plugin-utils': 7.27.1
transitivePeerDependencies:
- supports-color
- '@babel/plugin-transform-private-property-in-object@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-private-methods@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
+ '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7)
+ '@babel/helper-plugin-utils': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-private-property-in-object@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
'@babel/helper-annotate-as-pure': 7.27.3
- '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.27.4)
+ '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.29.7)
'@babel/helper-plugin-utils': 7.27.1
transitivePeerDependencies:
- supports-color
- '@babel/plugin-transform-property-literals@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-private-property-in-object@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-transform-react-constant-elements@7.27.1(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-transform-react-display-name@7.27.1(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-transform-react-jsx-development@7.27.1(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.27.4)
+ '@babel/core': 7.29.7
+ '@babel/helper-annotate-as-pure': 7.29.7
+ '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7)
+ '@babel/helper-plugin-utils': 7.29.7
transitivePeerDependencies:
- supports-color
- '@babel/plugin-transform-react-jsx@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-property-literals@7.27.1(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-annotate-as-pure': 7.27.3
- '@babel/helper-module-imports': 7.27.1
+ '@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.27.4)
- '@babel/types': 7.27.6
+
+ '@babel/plugin-transform-property-literals@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-react-display-name@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-react-jsx-development@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/plugin-transform-react-jsx': 7.29.7(@babel/core@7.29.7)
transitivePeerDependencies:
- supports-color
- '@babel/plugin-transform-react-pure-annotations@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-react-jsx@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-annotate-as-pure': 7.27.3
+ '@babel/core': 7.29.7
+ '@babel/helper-annotate-as-pure': 7.29.7
+ '@babel/helper-module-imports': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+ '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7)
+ '@babel/types': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-react-pure-annotations@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-annotate-as-pure': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-regenerator@7.27.5(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-regenerator@7.27.5(@babel/core@7.27.4)':
+ '@babel/plugin-transform-regenerator@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-regexp-modifiers@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.29.7)
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-regexp-modifiers@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-regexp-modifiers@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.27.4)
+ '@babel/core': 7.29.7
+ '@babel/helper-create-regexp-features-plugin': 7.29.7(@babel/core@7.29.7)
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-reserved-words@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-reserved-words@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-reserved-words@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-shorthand-properties@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
- '@babel/plugin-transform-spread@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-spread@7.27.1(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
'@babel/helper-skip-transparent-expression-wrappers': 7.27.1
transitivePeerDependencies:
- supports-color
- '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-spread@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-transform-typeof-symbol@7.27.1(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-transform-typescript@7.27.1(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-annotate-as-pure': 7.27.3
- '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.27.4)
- '@babel/helper-plugin-utils': 7.27.1
- '@babel/helper-skip-transparent-expression-wrappers': 7.27.1
- '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.27.4)
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+ '@babel/helper-skip-transparent-expression-wrappers': 7.29.7
transitivePeerDependencies:
- supports-color
- '@babel/plugin-transform-unicode-escapes@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-unicode-property-regex@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-sticky-regex@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.27.4)
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-template-literals@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.27.4)
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-typeof-symbol@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-unicode-sets-regex@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-typeof-symbol@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.27.4)
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-typescript@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-annotate-as-pure': 7.29.7
+ '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7)
+ '@babel/helper-plugin-utils': 7.29.7
+ '@babel/helper-skip-transparent-expression-wrappers': 7.29.7
+ '@babel/plugin-syntax-typescript': 7.29.7(@babel/core@7.29.7)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-unicode-escapes@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
- '@babel/preset-env@7.27.2(@babel/core@7.27.4)':
+ '@babel/plugin-transform-unicode-escapes@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/compat-data': 7.27.5
- '@babel/core': 7.27.4
- '@babel/helper-compilation-targets': 7.27.2
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-unicode-property-regex@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.29.7)
'@babel/helper-plugin-utils': 7.27.1
- '@babel/helper-validator-option': 7.27.1
- '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.27.4)
- '@babel/plugin-syntax-import-assertions': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.27.4)
- '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-async-generator-functions': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-async-to-generator': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-block-scoped-functions': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-block-scoping': 7.27.5(@babel/core@7.27.4)
- '@babel/plugin-transform-class-properties': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-class-static-block': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-classes': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-computed-properties': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-destructuring': 7.27.3(@babel/core@7.27.4)
- '@babel/plugin-transform-dotall-regex': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-duplicate-keys': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-dynamic-import': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-exponentiation-operator': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-json-strings': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-logical-assignment-operators': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-member-expression-literals': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-modules-amd': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-modules-systemjs': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-modules-umd': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-named-capturing-groups-regex': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-new-target': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-nullish-coalescing-operator': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-numeric-separator': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-object-rest-spread': 7.27.3(@babel/core@7.27.4)
- '@babel/plugin-transform-object-super': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-optional-catch-binding': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-parameters': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-private-methods': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-private-property-in-object': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-property-literals': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-regenerator': 7.27.5(@babel/core@7.27.4)
- '@babel/plugin-transform-regexp-modifiers': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-reserved-words': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-spread': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-template-literals': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-typeof-symbol': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-unicode-escapes': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-unicode-property-regex': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-unicode-sets-regex': 7.27.1(@babel/core@7.27.4)
- '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.27.4)
- babel-plugin-polyfill-corejs2: 0.4.13(@babel/core@7.27.4)
- babel-plugin-polyfill-corejs3: 0.11.1(@babel/core@7.27.4)
- babel-plugin-polyfill-regenerator: 0.6.4(@babel/core@7.27.4)
+
+ '@babel/plugin-transform-unicode-property-regex@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-create-regexp-features-plugin': 7.29.7(@babel/core@7.29.7)
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.29.7)
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-transform-unicode-regex@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-create-regexp-features-plugin': 7.29.7(@babel/core@7.29.7)
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-unicode-sets-regex@7.27.1(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.29.7)
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-transform-unicode-sets-regex@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-create-regexp-features-plugin': 7.29.7(@babel/core@7.29.7)
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/preset-env@7.27.2(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/compat-data': 7.29.7
+ '@babel/core': 7.29.7
+ '@babel/helper-compilation-targets': 7.29.7
+ '@babel/helper-plugin-utils': 7.27.1
+ '@babel/helper-validator-option': 7.29.7
+ '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.29.7)
+ '@babel/plugin-syntax-import-assertions': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.29.7)
+ '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-async-generator-functions': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-async-to-generator': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-block-scoped-functions': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-block-scoping': 7.27.5(@babel/core@7.29.7)
+ '@babel/plugin-transform-class-properties': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-class-static-block': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-classes': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-computed-properties': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-destructuring': 7.27.3(@babel/core@7.29.7)
+ '@babel/plugin-transform-dotall-regex': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-duplicate-keys': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-dynamic-import': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-exponentiation-operator': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-json-strings': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-logical-assignment-operators': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-member-expression-literals': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-modules-amd': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-modules-systemjs': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-modules-umd': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-named-capturing-groups-regex': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-new-target': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-nullish-coalescing-operator': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-numeric-separator': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-object-rest-spread': 7.27.3(@babel/core@7.29.7)
+ '@babel/plugin-transform-object-super': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-optional-catch-binding': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-parameters': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-private-methods': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-private-property-in-object': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-property-literals': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-regenerator': 7.27.5(@babel/core@7.29.7)
+ '@babel/plugin-transform-regexp-modifiers': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-reserved-words': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-spread': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-template-literals': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-typeof-symbol': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-unicode-escapes': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-unicode-property-regex': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-transform-unicode-sets-regex': 7.27.1(@babel/core@7.29.7)
+ '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.29.7)
+ babel-plugin-polyfill-corejs2: 0.4.13(@babel/core@7.29.7)
+ babel-plugin-polyfill-corejs3: 0.11.1(@babel/core@7.29.7)
+ babel-plugin-polyfill-regenerator: 0.6.4(@babel/core@7.29.7)
core-js-compat: 3.43.0
semver: 6.3.1
transitivePeerDependencies:
- supports-color
- '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.27.4)':
+ '@babel/preset-env@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
- '@babel/types': 7.27.6
- esutils: 2.0.3
-
- '@babel/preset-react@7.27.1(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
- '@babel/helper-validator-option': 7.27.1
- '@babel/plugin-transform-react-display-name': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-react-jsx-development': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-react-pure-annotations': 7.27.1(@babel/core@7.27.4)
+ '@babel/compat-data': 7.29.7
+ '@babel/core': 7.29.7
+ '@babel/helper-compilation-targets': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+ '@babel/helper-validator-option': 7.29.7
+ '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-bugfix-safari-rest-destructuring-rhs-array': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.29.7)
+ '@babel/plugin-syntax-import-assertions': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-syntax-import-attributes': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.29.7)
+ '@babel/plugin-transform-arrow-functions': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-async-generator-functions': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-async-to-generator': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-block-scoped-functions': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-block-scoping': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-class-properties': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-class-static-block': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-classes': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-computed-properties': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-destructuring': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-dotall-regex': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-duplicate-keys': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-dynamic-import': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-explicit-resource-management': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-exponentiation-operator': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-export-namespace-from': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-for-of': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-function-name': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-json-strings': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-literals': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-logical-assignment-operators': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-member-expression-literals': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-modules-amd': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-modules-commonjs': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-modules-systemjs': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-modules-umd': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-named-capturing-groups-regex': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-new-target': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-nullish-coalescing-operator': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-numeric-separator': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-object-rest-spread': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-object-super': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-optional-catch-binding': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-optional-chaining': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-parameters': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-private-methods': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-private-property-in-object': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-property-literals': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-regenerator': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-regexp-modifiers': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-reserved-words': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-shorthand-properties': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-spread': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-sticky-regex': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-template-literals': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-typeof-symbol': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-unicode-escapes': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-unicode-property-regex': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-unicode-regex': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-unicode-sets-regex': 7.29.7(@babel/core@7.29.7)
+ '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.29.7)
+ babel-plugin-polyfill-corejs2: 0.4.17(@babel/core@7.29.7)
+ babel-plugin-polyfill-corejs3: 0.14.2(@babel/core@7.29.7)
+ babel-plugin-polyfill-regenerator: 0.6.8(@babel/core@7.29.7)
+ core-js-compat: 3.49.0
+ semver: 6.3.1
transitivePeerDependencies:
- supports-color
- '@babel/preset-typescript@7.27.1(@babel/core@7.27.4)':
+ '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.29.7)':
dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-plugin-utils': 7.27.1
- '@babel/helper-validator-option': 7.27.1
- '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-typescript': 7.27.1(@babel/core@7.27.4)
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+ '@babel/types': 7.29.7
+ esutils: 2.0.3
+
+ '@babel/preset-react@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+ '@babel/helper-validator-option': 7.29.7
+ '@babel/plugin-transform-react-display-name': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-react-jsx': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-react-jsx-development': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-react-pure-annotations': 7.29.7(@babel/core@7.29.7)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/preset-typescript@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+ '@babel/helper-validator-option': 7.29.7
+ '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-modules-commonjs': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-typescript': 7.29.7(@babel/core@7.29.7)
transitivePeerDependencies:
- supports-color
@@ -6536,6 +7484,12 @@ snapshots:
'@babel/parser': 7.27.5
'@babel/types': 7.27.6
+ '@babel/template@7.29.7':
+ dependencies:
+ '@babel/code-frame': 7.29.7
+ '@babel/parser': 7.29.7
+ '@babel/types': 7.29.7
+
'@babel/traverse@7.27.4':
dependencies:
'@babel/code-frame': 7.27.1
@@ -6548,11 +7502,28 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@babel/traverse@7.29.7':
+ dependencies:
+ '@babel/code-frame': 7.29.7
+ '@babel/generator': 7.29.7
+ '@babel/helper-globals': 7.29.7
+ '@babel/parser': 7.29.7
+ '@babel/template': 7.29.7
+ '@babel/types': 7.29.7
+ debug: 4.4.1(supports-color@9.4.0)
+ transitivePeerDependencies:
+ - supports-color
+
'@babel/types@7.27.6':
dependencies:
'@babel/helper-string-parser': 7.27.1
'@babel/helper-validator-identifier': 7.27.1
+ '@babel/types@7.29.7':
+ dependencies:
+ '@babel/helper-string-parser': 7.29.7
+ '@babel/helper-validator-identifier': 7.29.7
+
'@bcoe/v8-coverage@0.2.3': {}
'@commitlint/cli@16.3.0':
@@ -6698,9 +7669,9 @@ snapshots:
react: 19.2.3
tslib: 2.8.1
- '@emnapi/core@1.4.3':
+ '@emnapi/core@1.10.0':
dependencies:
- '@emnapi/wasi-threads': 1.0.2
+ '@emnapi/wasi-threads': 1.2.1
tslib: 2.8.1
optional: true
@@ -6709,11 +7680,89 @@ snapshots:
tslib: 2.8.1
optional: true
- '@emnapi/wasi-threads@1.0.2':
+ '@emnapi/wasi-threads@1.2.1':
dependencies:
tslib: 2.8.1
optional: true
+ '@esbuild/aix-ppc64@0.28.0':
+ optional: true
+
+ '@esbuild/android-arm64@0.28.0':
+ optional: true
+
+ '@esbuild/android-arm@0.28.0':
+ optional: true
+
+ '@esbuild/android-x64@0.28.0':
+ optional: true
+
+ '@esbuild/darwin-arm64@0.28.0':
+ optional: true
+
+ '@esbuild/darwin-x64@0.28.0':
+ optional: true
+
+ '@esbuild/freebsd-arm64@0.28.0':
+ optional: true
+
+ '@esbuild/freebsd-x64@0.28.0':
+ optional: true
+
+ '@esbuild/linux-arm64@0.28.0':
+ optional: true
+
+ '@esbuild/linux-arm@0.28.0':
+ optional: true
+
+ '@esbuild/linux-ia32@0.28.0':
+ optional: true
+
+ '@esbuild/linux-loong64@0.28.0':
+ optional: true
+
+ '@esbuild/linux-mips64el@0.28.0':
+ optional: true
+
+ '@esbuild/linux-ppc64@0.28.0':
+ optional: true
+
+ '@esbuild/linux-riscv64@0.28.0':
+ optional: true
+
+ '@esbuild/linux-s390x@0.28.0':
+ optional: true
+
+ '@esbuild/linux-x64@0.28.0':
+ optional: true
+
+ '@esbuild/netbsd-arm64@0.28.0':
+ optional: true
+
+ '@esbuild/netbsd-x64@0.28.0':
+ optional: true
+
+ '@esbuild/openbsd-arm64@0.28.0':
+ optional: true
+
+ '@esbuild/openbsd-x64@0.28.0':
+ optional: true
+
+ '@esbuild/openharmony-arm64@0.28.0':
+ optional: true
+
+ '@esbuild/sunos-x64@0.28.0':
+ optional: true
+
+ '@esbuild/win32-arm64@0.28.0':
+ optional: true
+
+ '@esbuild/win32-ia32@0.28.0':
+ optional: true
+
+ '@esbuild/win32-x64@0.28.0':
+ optional: true
+
'@eslint-community/eslint-utils@4.7.0(eslint@8.57.1)':
dependencies:
eslint: 8.57.1
@@ -6737,6 +7786,61 @@ snapshots:
'@eslint/js@8.57.1': {}
+ '@fastify/accept-negotiator@2.0.1': {}
+
+ '@fastify/ajv-compiler@4.0.5':
+ dependencies:
+ ajv: 8.17.1
+ ajv-formats: 3.0.1(ajv@8.17.1)
+ fast-uri: 3.0.6
+
+ '@fastify/cookie@11.0.2':
+ dependencies:
+ cookie: 1.1.1
+ fastify-plugin: 5.1.0
+
+ '@fastify/error@4.2.0': {}
+
+ '@fastify/fast-json-stringify-compiler@5.0.3':
+ dependencies:
+ fast-json-stringify: 6.4.0
+
+ '@fastify/forwarded@3.0.1': {}
+
+ '@fastify/merge-json-schemas@0.2.1':
+ dependencies:
+ dequal: 2.0.3
+
+ '@fastify/middie@9.3.2':
+ dependencies:
+ '@fastify/error': 4.2.0
+ fastify-plugin: 5.1.0
+ find-my-way: 9.6.0
+ path-to-regexp: 8.4.2
+ reusify: 1.1.0
+
+ '@fastify/proxy-addr@5.1.0':
+ dependencies:
+ '@fastify/forwarded': 3.0.1
+ ipaddr.js: 2.4.0
+
+ '@fastify/send@4.1.0':
+ dependencies:
+ '@lukeed/ms': 2.0.2
+ escape-html: 1.0.3
+ fast-decode-uri-component: 1.0.1
+ http-errors: 2.0.1
+ mime: 3.0.0
+
+ '@fastify/static@9.1.3':
+ dependencies:
+ '@fastify/accept-negotiator': 2.0.1
+ '@fastify/send': 4.1.0
+ content-disposition: 1.1.0
+ fastify-plugin: 5.1.0
+ fastq: 1.19.1
+ glob: 13.0.6
+
'@floating-ui/core@1.7.1':
dependencies:
'@floating-ui/utils': 0.2.9
@@ -6816,103 +7920,6 @@ snapshots:
'@humanwhocodes/object-schema@2.0.3': {}
- '@img/colour@1.1.0':
- optional: true
-
- '@img/sharp-darwin-arm64@0.34.5':
- optionalDependencies:
- '@img/sharp-libvips-darwin-arm64': 1.2.4
- optional: true
-
- '@img/sharp-darwin-x64@0.34.5':
- optionalDependencies:
- '@img/sharp-libvips-darwin-x64': 1.2.4
- optional: true
-
- '@img/sharp-libvips-darwin-arm64@1.2.4':
- optional: true
-
- '@img/sharp-libvips-darwin-x64@1.2.4':
- optional: true
-
- '@img/sharp-libvips-linux-arm64@1.2.4':
- optional: true
-
- '@img/sharp-libvips-linux-arm@1.2.4':
- optional: true
-
- '@img/sharp-libvips-linux-ppc64@1.2.4':
- optional: true
-
- '@img/sharp-libvips-linux-riscv64@1.2.4':
- optional: true
-
- '@img/sharp-libvips-linux-s390x@1.2.4':
- optional: true
-
- '@img/sharp-libvips-linux-x64@1.2.4':
- optional: true
-
- '@img/sharp-libvips-linuxmusl-arm64@1.2.4':
- optional: true
-
- '@img/sharp-libvips-linuxmusl-x64@1.2.4':
- optional: true
-
- '@img/sharp-linux-arm64@0.34.5':
- optionalDependencies:
- '@img/sharp-libvips-linux-arm64': 1.2.4
- optional: true
-
- '@img/sharp-linux-arm@0.34.5':
- optionalDependencies:
- '@img/sharp-libvips-linux-arm': 1.2.4
- optional: true
-
- '@img/sharp-linux-ppc64@0.34.5':
- optionalDependencies:
- '@img/sharp-libvips-linux-ppc64': 1.2.4
- optional: true
-
- '@img/sharp-linux-riscv64@0.34.5':
- optionalDependencies:
- '@img/sharp-libvips-linux-riscv64': 1.2.4
- optional: true
-
- '@img/sharp-linux-s390x@0.34.5':
- optionalDependencies:
- '@img/sharp-libvips-linux-s390x': 1.2.4
- optional: true
-
- '@img/sharp-linux-x64@0.34.5':
- optionalDependencies:
- '@img/sharp-libvips-linux-x64': 1.2.4
- optional: true
-
- '@img/sharp-linuxmusl-arm64@0.34.5':
- optionalDependencies:
- '@img/sharp-libvips-linuxmusl-arm64': 1.2.4
- optional: true
-
- '@img/sharp-linuxmusl-x64@0.34.5':
- optionalDependencies:
- '@img/sharp-libvips-linuxmusl-x64': 1.2.4
- optional: true
-
- '@img/sharp-wasm32@0.34.5':
- dependencies:
- '@emnapi/runtime': 1.10.0
- optional: true
-
- '@img/sharp-win32-arm64@0.34.5':
- optional: true
-
- '@img/sharp-win32-ia32@0.34.5':
- optional: true
-
- '@img/sharp-win32-x64@0.34.5':
- optional: true
-
'@internationalized/date@3.12.1':
dependencies:
'@swc/helpers': 0.5.5
@@ -6997,8 +8004,6 @@ snapshots:
- ts-node
- utf-8-validate
- '@jest/diff-sequences@30.0.0': {}
-
'@jest/environment@27.5.1':
dependencies:
'@jest/fake-timers': 27.5.1
@@ -7006,10 +8011,6 @@ snapshots:
'@types/node': 24.0.3
jest-mock: 27.5.1
- '@jest/expect-utils@30.0.0':
- dependencies:
- '@jest/get-type': 30.0.0
-
'@jest/fake-timers@27.5.1':
dependencies:
'@jest/types': 27.5.1
@@ -7019,19 +8020,12 @@ snapshots:
jest-mock: 27.5.1
jest-util: 27.5.1
- '@jest/get-type@30.0.0': {}
-
'@jest/globals@27.5.1':
dependencies:
'@jest/environment': 27.5.1
'@jest/types': 27.5.1
expect: 27.5.1
- '@jest/pattern@30.0.0':
- dependencies:
- '@types/node': 24.0.3
- jest-regex-util: 30.0.0
-
'@jest/reporters@27.5.1':
dependencies:
'@bcoe/v8-coverage': 0.2.3
@@ -7062,10 +8056,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@jest/schemas@30.0.0':
- dependencies:
- '@sinclair/typebox': 0.34.35
-
'@jest/source-map@27.5.1':
dependencies:
callsites: 3.1.0
@@ -7090,7 +8080,7 @@ snapshots:
'@jest/transform@27.5.1':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
'@jest/types': 27.5.1
babel-plugin-istanbul: 6.1.1
chalk: 4.1.2
@@ -7116,15 +8106,10 @@ snapshots:
'@types/yargs': 16.0.9
chalk: 4.1.2
- '@jest/types@30.0.0':
+ '@jridgewell/gen-mapping@0.3.13':
dependencies:
- '@jest/pattern': 30.0.0
- '@jest/schemas': 30.0.0
- '@types/istanbul-lib-coverage': 2.0.6
- '@types/istanbul-reports': 3.0.4
- '@types/node': 24.0.3
- '@types/yargs': 17.0.33
- chalk: 4.1.2
+ '@jridgewell/sourcemap-codec': 1.5.5
+ '@jridgewell/trace-mapping': 0.3.31
'@jridgewell/gen-mapping@0.3.8':
dependencies:
@@ -7143,8 +8128,8 @@ snapshots:
'@jridgewell/source-map@0.3.6':
dependencies:
- '@jridgewell/gen-mapping': 0.3.8
- '@jridgewell/trace-mapping': 0.3.25
+ '@jridgewell/gen-mapping': 0.3.13
+ '@jridgewell/trace-mapping': 0.3.31
'@jridgewell/sourcemap-codec@1.5.0': {}
@@ -7155,48 +8140,25 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.0
+ '@jridgewell/trace-mapping@0.3.31':
+ dependencies:
+ '@jridgewell/resolve-uri': 3.1.2
+ '@jridgewell/sourcemap-codec': 1.5.5
+
'@jridgewell/trace-mapping@0.3.9':
dependencies:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.0
+ '@lukeed/ms@2.0.2': {}
+
'@maverick-js/signals@5.11.5': {}
- '@napi-rs/wasm-runtime@0.2.11':
+ '@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)':
dependencies:
- '@emnapi/core': 1.4.3
+ '@emnapi/core': 1.10.0
'@emnapi/runtime': 1.10.0
- '@tybys/wasm-util': 0.9.0
- optional: true
-
- '@next/env@15.5.18': {}
-
- '@next/eslint-plugin-next@15.5.18':
- dependencies:
- fast-glob: 3.3.1
-
- '@next/swc-darwin-arm64@15.5.18':
- optional: true
-
- '@next/swc-darwin-x64@15.5.18':
- optional: true
-
- '@next/swc-linux-arm64-gnu@15.5.18':
- optional: true
-
- '@next/swc-linux-arm64-musl@15.5.18':
- optional: true
-
- '@next/swc-linux-x64-gnu@15.5.18':
- optional: true
-
- '@next/swc-linux-x64-musl@15.5.18':
- optional: true
-
- '@next/swc-win32-arm64-msvc@15.5.18':
- optional: true
-
- '@next/swc-win32-x64-msvc@15.5.18':
+ '@tybys/wasm-util': 0.10.2
optional: true
'@nodelib/fs.scandir@2.1.5':
@@ -7211,7 +8173,9 @@ snapshots:
'@nodelib/fs.scandir': 2.1.5
fastq: 1.19.1
- '@nolyfill/is-core-module@1.0.39': {}
+ '@oxc-project/types@0.132.0': {}
+
+ '@pinojs/redact@0.4.0': {}
'@radix-ui/react-avatar@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.15))(@types/react@19.2.15)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
dependencies:
@@ -7373,10 +8337,70 @@ snapshots:
dependencies:
'@redis/client': 1.6.1
- '@rollup/plugin-babel@5.3.1(@babel/core@7.27.4)(@types/babel__core@7.20.5)(rollup@2.79.2)':
+ '@rolldown/binding-android-arm64@1.0.2':
+ optional: true
+
+ '@rolldown/binding-darwin-arm64@1.0.2':
+ optional: true
+
+ '@rolldown/binding-darwin-x64@1.0.2':
+ optional: true
+
+ '@rolldown/binding-freebsd-x64@1.0.2':
+ optional: true
+
+ '@rolldown/binding-linux-arm-gnueabihf@1.0.2':
+ optional: true
+
+ '@rolldown/binding-linux-arm64-gnu@1.0.2':
+ optional: true
+
+ '@rolldown/binding-linux-arm64-musl@1.0.2':
+ optional: true
+
+ '@rolldown/binding-linux-ppc64-gnu@1.0.2':
+ optional: true
+
+ '@rolldown/binding-linux-s390x-gnu@1.0.2':
+ optional: true
+
+ '@rolldown/binding-linux-x64-gnu@1.0.2':
+ optional: true
+
+ '@rolldown/binding-linux-x64-musl@1.0.2':
+ optional: true
+
+ '@rolldown/binding-openharmony-arm64@1.0.2':
+ optional: true
+
+ '@rolldown/binding-wasm32-wasi@1.0.2':
dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-module-imports': 7.27.1
+ '@emnapi/core': 1.10.0
+ '@emnapi/runtime': 1.10.0
+ '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)
+ optional: true
+
+ '@rolldown/binding-win32-arm64-msvc@1.0.2':
+ optional: true
+
+ '@rolldown/binding-win32-x64-msvc@1.0.2':
+ optional: true
+
+ '@rolldown/plugin-babel@0.2.3(@babel/core@7.29.7)(@babel/runtime@7.27.6)(rolldown@1.0.2)(vite@8.0.14(@types/node@24.0.3)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.43.1)(tsx@4.22.3))':
+ dependencies:
+ '@babel/core': 7.29.7
+ picomatch: 4.0.4
+ rolldown: 1.0.2
+ optionalDependencies:
+ '@babel/runtime': 7.27.6
+ vite: 8.0.14(@types/node@24.0.3)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.43.1)(tsx@4.22.3)
+
+ '@rolldown/pluginutils@1.0.1': {}
+
+ '@rollup/plugin-babel@5.3.1(@babel/core@7.29.7)(@types/babel__core@7.20.5)(rollup@2.79.2)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-module-imports': 7.29.7
'@rollup/pluginutils': 3.1.0(rollup@2.79.2)
rollup: 2.79.2
optionalDependencies:
@@ -7407,12 +8431,6 @@ snapshots:
picomatch: 2.3.1
rollup: 2.79.2
- '@rtsao/scc@1.1.0': {}
-
- '@rushstack/eslint-patch@1.11.0': {}
-
- '@sinclair/typebox@0.34.35': {}
-
'@sinonjs/commons@1.8.6':
dependencies:
type-detect: 4.0.8
@@ -7445,99 +8463,6 @@ snapshots:
magic-string: 0.25.9
string.prototype.matchall: 4.0.12
- '@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
-
- '@svgr/babel-plugin-remove-jsx-attribute@8.0.0(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
-
- '@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
-
- '@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
-
- '@svgr/babel-plugin-svg-dynamic-title@8.0.0(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
-
- '@svgr/babel-plugin-svg-em-dimensions@8.0.0(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
-
- '@svgr/babel-plugin-transform-react-native-svg@8.1.0(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
-
- '@svgr/babel-plugin-transform-svg-component@8.0.0(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
-
- '@svgr/babel-preset@8.1.0(@babel/core@7.27.4)':
- dependencies:
- '@babel/core': 7.27.4
- '@svgr/babel-plugin-add-jsx-attribute': 8.0.0(@babel/core@7.27.4)
- '@svgr/babel-plugin-remove-jsx-attribute': 8.0.0(@babel/core@7.27.4)
- '@svgr/babel-plugin-remove-jsx-empty-expression': 8.0.0(@babel/core@7.27.4)
- '@svgr/babel-plugin-replace-jsx-attribute-value': 8.0.0(@babel/core@7.27.4)
- '@svgr/babel-plugin-svg-dynamic-title': 8.0.0(@babel/core@7.27.4)
- '@svgr/babel-plugin-svg-em-dimensions': 8.0.0(@babel/core@7.27.4)
- '@svgr/babel-plugin-transform-react-native-svg': 8.1.0(@babel/core@7.27.4)
- '@svgr/babel-plugin-transform-svg-component': 8.0.0(@babel/core@7.27.4)
-
- '@svgr/core@8.1.0(typescript@5.9.3)':
- dependencies:
- '@babel/core': 7.27.4
- '@svgr/babel-preset': 8.1.0(@babel/core@7.27.4)
- camelcase: 6.3.0
- cosmiconfig: 8.3.6(typescript@5.9.3)
- snake-case: 3.0.4
- transitivePeerDependencies:
- - supports-color
- - typescript
-
- '@svgr/hast-util-to-babel-ast@8.0.0':
- dependencies:
- '@babel/types': 7.27.6
- entities: 4.5.0
-
- '@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(typescript@5.9.3))':
- dependencies:
- '@babel/core': 7.27.4
- '@svgr/babel-preset': 8.1.0(@babel/core@7.27.4)
- '@svgr/core': 8.1.0(typescript@5.9.3)
- '@svgr/hast-util-to-babel-ast': 8.0.0
- svg-parser: 2.0.4
- transitivePeerDependencies:
- - supports-color
-
- '@svgr/plugin-svgo@8.1.0(@svgr/core@8.1.0(typescript@5.9.3))(typescript@5.9.3)':
- dependencies:
- '@svgr/core': 8.1.0(typescript@5.9.3)
- cosmiconfig: 8.3.6(typescript@5.9.3)
- deepmerge: 4.3.1
- svgo: 3.3.2
- transitivePeerDependencies:
- - typescript
-
- '@svgr/webpack@8.1.0(typescript@5.9.3)':
- dependencies:
- '@babel/core': 7.27.4
- '@babel/plugin-transform-react-constant-elements': 7.27.1(@babel/core@7.27.4)
- '@babel/preset-env': 7.27.2(@babel/core@7.27.4)
- '@babel/preset-react': 7.27.1(@babel/core@7.27.4)
- '@babel/preset-typescript': 7.27.1(@babel/core@7.27.4)
- '@svgr/core': 8.1.0(typescript@5.9.3)
- '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.9.3))
- '@svgr/plugin-svgo': 8.1.0(@svgr/core@8.1.0(typescript@5.9.3))(typescript@5.9.3)
- transitivePeerDependencies:
- - supports-color
- - typescript
-
'@swc/counter@0.1.3': {}
'@swc/helpers@0.5.15':
@@ -7658,8 +8583,6 @@ snapshots:
'@tootallnate/once@1.1.2': {}
- '@trysound/sax@0.2.0': {}
-
'@tsconfig/node10@1.0.11': {}
'@tsconfig/node12@1.0.11': {}
@@ -7668,7 +8591,7 @@ snapshots:
'@tsconfig/node16@1.0.4': {}
- '@tybys/wasm-util@0.9.0':
+ '@tybys/wasm-util@0.10.2':
dependencies:
tslib: 2.8.1
optional: true
@@ -7677,20 +8600,20 @@ snapshots:
'@types/babel__core@7.20.5':
dependencies:
- '@babel/parser': 7.27.5
- '@babel/types': 7.27.6
+ '@babel/parser': 7.29.7
+ '@babel/types': 7.29.7
'@types/babel__generator': 7.27.0
'@types/babel__template': 7.4.4
'@types/babel__traverse': 7.20.7
'@types/babel__generator@7.27.0':
dependencies:
- '@babel/types': 7.27.6
+ '@babel/types': 7.29.7
'@types/babel__template@7.4.4':
dependencies:
- '@babel/parser': 7.27.5
- '@babel/types': 7.27.6
+ '@babel/parser': 7.29.7
+ '@babel/types': 7.29.7
'@types/babel__traverse@7.20.7':
dependencies:
@@ -7716,11 +8639,6 @@ snapshots:
'@types/estree@1.0.8': {}
- '@types/glob@7.2.0':
- dependencies:
- '@types/minimatch': 5.1.2
- '@types/node': 24.0.3
-
'@types/graceful-fs@4.1.9':
dependencies:
'@types/node': 24.0.3
@@ -7737,19 +8655,15 @@ snapshots:
dependencies:
'@types/istanbul-lib-report': 3.0.3
- '@types/jest@30.0.0':
+ '@types/jest@27.5.2':
dependencies:
- expect: 30.0.0
- pretty-format: 30.0.0
+ jest-matcher-utils: 27.5.1
+ pretty-format: 27.5.1
'@types/json-schema@7.0.15': {}
- '@types/json5@0.0.29': {}
-
'@types/minimatch@3.0.5': {}
- '@types/minimatch@5.1.2': {}
-
'@types/minimist@1.2.5': {}
'@types/node@24.0.3':
@@ -7780,7 +8694,7 @@ snapshots:
'@types/testing-library__jest-dom@5.14.9':
dependencies:
- '@types/jest': 30.0.0
+ '@types/jest': 27.5.2
'@types/trusted-types@2.0.7': {}
@@ -7796,10 +8710,6 @@ snapshots:
dependencies:
'@types/yargs-parser': 21.0.3
- '@types/yargs@17.0.33':
- dependencies:
- '@types/yargs-parser': 21.0.3
-
'@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3)':
dependencies:
'@eslint-community/regexpp': 4.12.1
@@ -7886,65 +8796,6 @@ snapshots:
'@ungap/structured-clone@1.3.0': {}
- '@unrs/resolver-binding-android-arm-eabi@1.9.0':
- optional: true
-
- '@unrs/resolver-binding-android-arm64@1.9.0':
- optional: true
-
- '@unrs/resolver-binding-darwin-arm64@1.9.0':
- optional: true
-
- '@unrs/resolver-binding-darwin-x64@1.9.0':
- optional: true
-
- '@unrs/resolver-binding-freebsd-x64@1.9.0':
- optional: true
-
- '@unrs/resolver-binding-linux-arm-gnueabihf@1.9.0':
- optional: true
-
- '@unrs/resolver-binding-linux-arm-musleabihf@1.9.0':
- optional: true
-
- '@unrs/resolver-binding-linux-arm64-gnu@1.9.0':
- optional: true
-
- '@unrs/resolver-binding-linux-arm64-musl@1.9.0':
- optional: true
-
- '@unrs/resolver-binding-linux-ppc64-gnu@1.9.0':
- optional: true
-
- '@unrs/resolver-binding-linux-riscv64-gnu@1.9.0':
- optional: true
-
- '@unrs/resolver-binding-linux-riscv64-musl@1.9.0':
- optional: true
-
- '@unrs/resolver-binding-linux-s390x-gnu@1.9.0':
- optional: true
-
- '@unrs/resolver-binding-linux-x64-gnu@1.9.0':
- optional: true
-
- '@unrs/resolver-binding-linux-x64-musl@1.9.0':
- optional: true
-
- '@unrs/resolver-binding-wasm32-wasi@1.9.0':
- dependencies:
- '@napi-rs/wasm-runtime': 0.2.11
- optional: true
-
- '@unrs/resolver-binding-win32-arm64-msvc@1.9.0':
- optional: true
-
- '@unrs/resolver-binding-win32-ia32-msvc@1.9.0':
- optional: true
-
- '@unrs/resolver-binding-win32-x64-msvc@1.9.0':
- optional: true
-
'@upstash/redis@1.35.1':
dependencies:
uncrypto: 0.1.3
@@ -7956,6 +8807,14 @@ snapshots:
media-captions: 1.0.4
react: 19.2.3
+ '@vitejs/plugin-react@6.0.2(@rolldown/plugin-babel@0.2.3(@babel/core@7.29.7)(@babel/runtime@7.27.6)(rolldown@1.0.2)(vite@8.0.14(@types/node@24.0.3)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.43.1)(tsx@4.22.3)))(babel-plugin-react-compiler@1.0.0)(vite@8.0.14(@types/node@24.0.3)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.43.1)(tsx@4.22.3))':
+ dependencies:
+ '@rolldown/pluginutils': 1.0.1
+ vite: 8.0.14(@types/node@24.0.3)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.43.1)(tsx@4.22.3)
+ optionalDependencies:
+ '@rolldown/plugin-babel': 0.2.3(@babel/core@7.29.7)(@babel/runtime@7.27.6)(rolldown@1.0.2)(vite@8.0.14(@types/node@24.0.3)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.43.1)(tsx@4.22.3))
+ babel-plugin-react-compiler: 1.0.0
+
'@webassemblyjs/ast@1.14.1':
dependencies:
'@webassemblyjs/helper-numbers': 1.13.2
@@ -8043,6 +8902,8 @@ snapshots:
abab@2.0.6: {}
+ abstract-logging@2.0.1: {}
+
acorn-globals@6.0.0:
dependencies:
acorn: 7.4.1
@@ -8079,9 +8940,9 @@ snapshots:
optionalDependencies:
ajv: 8.17.1
- ajv-keywords@3.5.2(ajv@6.12.6):
- dependencies:
- ajv: 6.12.6
+ ajv-formats@3.0.1(ajv@8.17.1):
+ optionalDependencies:
+ ajv: 8.17.1
ajv-keywords@5.1.0(ajv@8.17.1):
dependencies:
@@ -8163,14 +9024,8 @@ snapshots:
is-string: 1.1.1
math-intrinsics: 1.1.0
- array-union@1.0.2:
- dependencies:
- array-uniq: 1.0.3
-
array-union@2.1.0: {}
- array-uniq@1.0.3: {}
-
array.prototype.findlast@1.2.5:
dependencies:
call-bind: 1.0.8
@@ -8180,16 +9035,6 @@ snapshots:
es-object-atoms: 1.1.1
es-shim-unscopables: 1.1.0
- array.prototype.findlastindex@1.2.6:
- dependencies:
- call-bind: 1.0.8
- call-bound: 1.0.4
- define-properties: 1.2.1
- es-abstract: 1.24.0
- es-errors: 1.3.0
- es-object-atoms: 1.1.1
- es-shim-unscopables: 1.1.0
-
array.prototype.flat@1.3.3:
dependencies:
call-bind: 1.0.8
@@ -8239,8 +9084,6 @@ snapshots:
object-is: 1.1.6
util: 0.12.5
- ast-types-flow@0.0.8: {}
-
astral-regex@2.0.0: {}
async-function@1.0.0: {}
@@ -8251,6 +9094,8 @@ snapshots:
at-least-node@1.0.0: {}
+ atomic-sleep@1.0.0: {}
+
autoprefixer@10.4.21(postcss@8.5.6):
dependencies:
browserslist: 4.25.0
@@ -8265,33 +9110,25 @@ snapshots:
dependencies:
possible-typed-array-names: 1.1.0
- axe-core@4.10.3: {}
-
- axobject-query@4.1.0: {}
-
- babel-jest@27.5.1(@babel/core@7.27.4):
+ avvio@9.2.0:
dependencies:
- '@babel/core': 7.27.4
+ '@fastify/error': 4.2.0
+ fastq: 1.19.1
+
+ babel-jest@27.5.1(@babel/core@7.29.7):
+ dependencies:
+ '@babel/core': 7.29.7
'@jest/transform': 27.5.1
'@jest/types': 27.5.1
'@types/babel__core': 7.20.5
babel-plugin-istanbul: 6.1.1
- babel-preset-jest: 27.5.1(@babel/core@7.27.4)
+ babel-preset-jest: 27.5.1(@babel/core@7.29.7)
chalk: 4.1.2
graceful-fs: 4.2.11
slash: 3.0.0
transitivePeerDependencies:
- supports-color
- babel-loader@8.4.1(@babel/core@7.27.4)(webpack@5.99.9):
- dependencies:
- '@babel/core': 7.27.4
- find-cache-dir: 3.3.2
- loader-utils: 2.0.4
- make-dir: 3.1.0
- schema-utils: 2.7.1
- webpack: 5.99.9
-
babel-plugin-istanbul@6.1.1:
dependencies:
'@babel/helper-plugin-utils': 7.27.1
@@ -8304,67 +9141,97 @@ snapshots:
babel-plugin-jest-hoist@27.5.1:
dependencies:
- '@babel/template': 7.27.2
- '@babel/types': 7.27.6
+ '@babel/template': 7.29.7
+ '@babel/types': 7.29.7
'@types/babel__core': 7.20.5
'@types/babel__traverse': 7.20.7
- babel-plugin-polyfill-corejs2@0.4.13(@babel/core@7.27.4):
+ babel-plugin-polyfill-corejs2@0.4.13(@babel/core@7.29.7):
dependencies:
- '@babel/compat-data': 7.27.5
- '@babel/core': 7.27.4
- '@babel/helper-define-polyfill-provider': 0.6.4(@babel/core@7.27.4)
+ '@babel/compat-data': 7.29.7
+ '@babel/core': 7.29.7
+ '@babel/helper-define-polyfill-provider': 0.6.4(@babel/core@7.29.7)
semver: 6.3.1
transitivePeerDependencies:
- supports-color
- babel-plugin-polyfill-corejs3@0.11.1(@babel/core@7.27.4):
+ babel-plugin-polyfill-corejs2@0.4.17(@babel/core@7.29.7):
dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-define-polyfill-provider': 0.6.4(@babel/core@7.27.4)
+ '@babel/compat-data': 7.29.7
+ '@babel/core': 7.29.7
+ '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.29.7)
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+
+ babel-plugin-polyfill-corejs3@0.11.1(@babel/core@7.29.7):
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-define-polyfill-provider': 0.6.4(@babel/core@7.29.7)
core-js-compat: 3.43.0
transitivePeerDependencies:
- supports-color
- babel-plugin-polyfill-regenerator@0.6.4(@babel/core@7.27.4):
+ babel-plugin-polyfill-corejs3@0.14.2(@babel/core@7.29.7):
dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-define-polyfill-provider': 0.6.4(@babel/core@7.27.4)
+ '@babel/core': 7.29.7
+ '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.29.7)
+ core-js-compat: 3.49.0
transitivePeerDependencies:
- supports-color
- babel-preset-current-node-syntax@1.1.0(@babel/core@7.27.4):
+ babel-plugin-polyfill-regenerator@0.6.4(@babel/core@7.29.7):
dependencies:
- '@babel/core': 7.27.4
- '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.27.4)
- '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.27.4)
- '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.27.4)
- '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.27.4)
- '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.27.4)
- '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.27.4)
- '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.27.4)
- '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.27.4)
- '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.27.4)
- '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.27.4)
- '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.27.4)
- '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.27.4)
- '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.27.4)
- '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.27.4)
+ '@babel/core': 7.29.7
+ '@babel/helper-define-polyfill-provider': 0.6.4(@babel/core@7.29.7)
+ transitivePeerDependencies:
+ - supports-color
- babel-preset-jest@27.5.1(@babel/core@7.27.4):
+ babel-plugin-polyfill-regenerator@0.6.8(@babel/core@7.29.7):
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
+ '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.29.7)
+ transitivePeerDependencies:
+ - supports-color
+
+ babel-plugin-react-compiler@1.0.0:
+ dependencies:
+ '@babel/types': 7.27.6
+
+ babel-preset-current-node-syntax@1.1.0(@babel/core@7.29.7):
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.29.7)
+ '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.29.7)
+ '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.29.7)
+ '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.29.7)
+ '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.29.7)
+ '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.29.7)
+ '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.29.7)
+ '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.29.7)
+ '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.29.7)
+ '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.29.7)
+ '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.29.7)
+ '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.29.7)
+ '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.29.7)
+ '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.29.7)
+ '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.29.7)
+
+ babel-preset-jest@27.5.1(@babel/core@7.29.7):
+ dependencies:
+ '@babel/core': 7.29.7
babel-plugin-jest-hoist: 27.5.1
- babel-preset-current-node-syntax: 1.1.0(@babel/core@7.27.4)
+ babel-preset-current-node-syntax: 1.1.0(@babel/core@7.29.7)
balanced-match@1.0.2: {}
+ balanced-match@4.0.4: {}
+
base-x@5.0.1: {}
- big.js@5.2.2: {}
+ baseline-browser-mapping@2.10.32: {}
- boolbase@1.0.0: {}
+ big.js@5.2.2: {}
brace-expansion@1.1.12:
dependencies:
@@ -8375,6 +9242,10 @@ snapshots:
dependencies:
balanced-match: 1.0.2
+ brace-expansion@5.0.6:
+ dependencies:
+ balanced-match: 4.0.4
+
braces@3.0.3:
dependencies:
fill-range: 7.1.1
@@ -8395,6 +9266,14 @@ snapshots:
node-releases: 2.0.20
update-browserslist-db: 1.1.3(browserslist@4.25.4)
+ browserslist@4.28.2:
+ dependencies:
+ baseline-browser-mapping: 2.10.32
+ caniuse-lite: 1.0.30001793
+ electron-to-chromium: 1.5.361
+ node-releases: 2.0.46
+ update-browserslist-db: 1.2.3(browserslist@4.28.2)
+
bs58@6.0.0:
dependencies:
base-x: 5.0.1
@@ -8419,6 +9298,13 @@ snapshots:
get-intrinsic: 1.3.0
set-function-length: 1.2.2
+ call-bind@1.0.9:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ es-define-property: 1.0.1
+ get-intrinsic: 1.3.0
+ set-function-length: 1.2.2
+
call-bound@1.0.4:
dependencies:
call-bind-apply-helpers: 1.0.2
@@ -8440,6 +9326,8 @@ snapshots:
caniuse-lite@1.0.30001741: {}
+ caniuse-lite@1.0.30001793: {}
+
chalk@3.0.0:
dependencies:
ansi-styles: 4.3.0
@@ -8460,8 +9348,6 @@ snapshots:
ci-info@3.9.0: {}
- ci-info@4.2.0: {}
-
cjs-module-lexer@1.4.3: {}
class-validator@0.14.1:
@@ -8472,11 +9358,6 @@ snapshots:
clean-stack@2.2.0: {}
- clean-webpack-plugin@4.0.0(webpack@5.99.9):
- dependencies:
- del: 4.1.1
- webpack: 5.99.9
-
cli-cursor@3.1.0:
dependencies:
restore-cursor: 3.1.0
@@ -8529,14 +9410,10 @@ snapshots:
commander@2.20.3: {}
- commander@7.2.0: {}
-
commander@9.5.0: {}
common-tags@1.8.2: {}
- commondir@1.0.1: {}
-
compare-func@2.0.0:
dependencies:
array-ify: 1.0.0
@@ -8544,6 +9421,8 @@ snapshots:
concat-map@0.0.1: {}
+ content-disposition@1.1.0: {}
+
conventional-changelog-angular@5.0.13:
dependencies:
compare-func: 2.0.0
@@ -8568,9 +9447,15 @@ snapshots:
convert-source-map@2.0.0: {}
+ cookie@1.1.1: {}
+
core-js-compat@3.43.0:
dependencies:
- browserslist: 4.25.0
+ browserslist: 4.25.4
+
+ core-js-compat@3.49.0:
+ dependencies:
+ browserslist: 4.28.2
cosmiconfig-typescript-loader@2.0.2(@types/node@24.0.3)(cosmiconfig@7.1.0)(typescript@4.9.5):
dependencies:
@@ -8590,15 +9475,6 @@ snapshots:
path-type: 4.0.0
yaml: 1.10.2
- cosmiconfig@8.3.6(typescript@5.9.3):
- dependencies:
- import-fresh: 3.3.1
- js-yaml: 4.1.0
- parse-json: 5.2.0
- path-type: 4.0.0
- optionalDependencies:
- typescript: 5.9.3
-
create-require@1.1.1: {}
cross-spawn@7.0.6:
@@ -8613,32 +9489,8 @@ snapshots:
crypto-random-string@2.0.0: {}
- css-select@5.1.0:
- dependencies:
- boolbase: 1.0.0
- css-what: 6.1.0
- domhandler: 5.0.3
- domutils: 3.2.2
- nth-check: 2.1.1
-
- css-tree@2.2.1:
- dependencies:
- mdn-data: 2.0.28
- source-map-js: 1.2.1
-
- css-tree@2.3.1:
- dependencies:
- mdn-data: 2.0.30
- source-map-js: 1.2.1
-
- css-what@6.1.0: {}
-
css.escape@1.5.1: {}
- csso@5.0.5:
- dependencies:
- css-tree: 2.2.1
-
cssom@0.3.8: {}
cssom@0.4.4: {}
@@ -8651,8 +9503,6 @@ snapshots:
csstype@3.2.3: {}
- damerau-levenshtein@1.0.8: {}
-
dargs@7.0.0: {}
data-urls@2.0.0:
@@ -8679,16 +9529,16 @@ snapshots:
es-errors: 1.3.0
is-data-view: 1.0.2
- debug@3.2.7:
- dependencies:
- ms: 2.1.3
-
debug@4.4.1(supports-color@9.4.0):
dependencies:
ms: 2.1.3
optionalDependencies:
supports-color: 9.4.0
+ debug@4.4.3:
+ dependencies:
+ ms: 2.1.3
+
decamelize-keys@1.1.1:
dependencies:
decamelize: 1.2.0
@@ -8716,18 +9566,10 @@ snapshots:
has-property-descriptors: 1.0.2
object-keys: 1.1.1
- del@4.1.1:
- dependencies:
- '@types/glob': 7.2.0
- globby: 6.1.0
- is-path-cwd: 2.2.0
- is-path-in-cwd: 2.1.0
- p-map: 2.1.0
- pify: 4.0.1
- rimraf: 2.7.1
-
delayed-stream@1.0.0: {}
+ depd@2.0.0: {}
+
dequal@2.0.3: {}
detect-libc@2.1.2: {}
@@ -8757,33 +9599,10 @@ snapshots:
'@babel/runtime': 7.27.6
csstype: 3.1.3
- dom-serializer@2.0.0:
- dependencies:
- domelementtype: 2.3.0
- domhandler: 5.0.3
- entities: 4.5.0
-
- domelementtype@2.3.0: {}
-
domexception@2.0.1:
dependencies:
webidl-conversions: 5.0.0
- domhandler@5.0.3:
- dependencies:
- domelementtype: 2.3.0
-
- domutils@3.2.2:
- dependencies:
- dom-serializer: 2.0.0
- domelementtype: 2.3.0
- domhandler: 5.0.3
-
- dot-case@3.0.4:
- dependencies:
- no-case: 3.0.4
- tslib: 2.8.1
-
dot-prop@5.3.0:
dependencies:
is-obj: 2.0.0
@@ -8804,6 +9623,8 @@ snapshots:
electron-to-chromium@1.5.215: {}
+ electron-to-chromium@1.5.361: {}
+
emittery@0.8.1: {}
emoji-regex@8.0.0: {}
@@ -8817,8 +9638,6 @@ snapshots:
graceful-fs: 4.2.11
tapable: 2.3.3
- entities@4.5.0: {}
-
error-ex@1.3.2:
dependencies:
is-arrayish: 0.2.1
@@ -8880,16 +9699,73 @@ snapshots:
unbox-primitive: 1.1.0
which-typed-array: 1.1.19
+ es-abstract@1.24.2:
+ dependencies:
+ array-buffer-byte-length: 1.0.2
+ arraybuffer.prototype.slice: 1.0.4
+ available-typed-arrays: 1.0.7
+ call-bind: 1.0.9
+ call-bound: 1.0.4
+ data-view-buffer: 1.0.2
+ data-view-byte-length: 1.0.2
+ data-view-byte-offset: 1.0.1
+ es-define-property: 1.0.1
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+ es-set-tostringtag: 2.1.0
+ es-to-primitive: 1.3.0
+ function.prototype.name: 1.1.8
+ get-intrinsic: 1.3.0
+ get-proto: 1.0.1
+ get-symbol-description: 1.1.0
+ globalthis: 1.0.4
+ gopd: 1.2.0
+ has-property-descriptors: 1.0.2
+ has-proto: 1.2.0
+ has-symbols: 1.1.0
+ hasown: 2.0.2
+ internal-slot: 1.1.0
+ is-array-buffer: 3.0.5
+ is-callable: 1.2.7
+ is-data-view: 1.0.2
+ is-negative-zero: 2.0.3
+ is-regex: 1.2.1
+ is-set: 2.0.3
+ is-shared-array-buffer: 1.0.4
+ is-string: 1.1.1
+ is-typed-array: 1.1.15
+ is-weakref: 1.1.1
+ math-intrinsics: 1.1.0
+ object-inspect: 1.13.4
+ object-keys: 1.1.1
+ object.assign: 4.1.7
+ own-keys: 1.0.1
+ regexp.prototype.flags: 1.5.4
+ safe-array-concat: 1.1.3
+ safe-push-apply: 1.0.0
+ safe-regex-test: 1.1.0
+ set-proto: 1.0.0
+ stop-iteration-iterator: 1.1.0
+ string.prototype.trim: 1.2.10
+ string.prototype.trimend: 1.0.9
+ string.prototype.trimstart: 1.0.8
+ typed-array-buffer: 1.0.3
+ typed-array-byte-length: 1.0.3
+ typed-array-byte-offset: 1.0.4
+ typed-array-length: 1.0.7
+ unbox-primitive: 1.1.0
+ which-typed-array: 1.1.19
+
es-define-property@1.0.1: {}
es-errors@1.3.0: {}
- es-iterator-helpers@1.2.1:
+ es-iterator-helpers@1.3.2:
dependencies:
- call-bind: 1.0.8
+ call-bind: 1.0.9
call-bound: 1.0.4
define-properties: 1.2.1
- es-abstract: 1.24.0
+ es-abstract: 1.24.2
es-errors: 1.3.0
es-set-tostringtag: 2.1.0
function-bind: 1.1.2
@@ -8901,7 +9777,7 @@ snapshots:
has-symbols: 1.1.0
internal-slot: 1.1.0
iterator.prototype: 1.1.5
- safe-array-concat: 1.1.3
+ math-intrinsics: 1.1.0
es-module-lexer@1.7.0: {}
@@ -8928,8 +9804,39 @@ snapshots:
es6-object-assign@1.1.0: {}
+ esbuild@0.28.0:
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.28.0
+ '@esbuild/android-arm': 0.28.0
+ '@esbuild/android-arm64': 0.28.0
+ '@esbuild/android-x64': 0.28.0
+ '@esbuild/darwin-arm64': 0.28.0
+ '@esbuild/darwin-x64': 0.28.0
+ '@esbuild/freebsd-arm64': 0.28.0
+ '@esbuild/freebsd-x64': 0.28.0
+ '@esbuild/linux-arm': 0.28.0
+ '@esbuild/linux-arm64': 0.28.0
+ '@esbuild/linux-ia32': 0.28.0
+ '@esbuild/linux-loong64': 0.28.0
+ '@esbuild/linux-mips64el': 0.28.0
+ '@esbuild/linux-ppc64': 0.28.0
+ '@esbuild/linux-riscv64': 0.28.0
+ '@esbuild/linux-s390x': 0.28.0
+ '@esbuild/linux-x64': 0.28.0
+ '@esbuild/netbsd-arm64': 0.28.0
+ '@esbuild/netbsd-x64': 0.28.0
+ '@esbuild/openbsd-arm64': 0.28.0
+ '@esbuild/openbsd-x64': 0.28.0
+ '@esbuild/openharmony-arm64': 0.28.0
+ '@esbuild/sunos-x64': 0.28.0
+ '@esbuild/win32-arm64': 0.28.0
+ '@esbuild/win32-ia32': 0.28.0
+ '@esbuild/win32-x64': 0.28.0
+
escalade@3.2.0: {}
+ escape-html@1.0.3: {}
+
escape-string-regexp@2.0.0: {}
escape-string-regexp@4.0.0: {}
@@ -8942,116 +9849,21 @@ snapshots:
optionalDependencies:
source-map: 0.6.1
- eslint-config-next@15.5.18(eslint@8.57.1)(typescript@5.9.3):
- dependencies:
- '@next/eslint-plugin-next': 15.5.18
- '@rushstack/eslint-patch': 1.11.0
- '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3)
- '@typescript-eslint/parser': 5.62.0(eslint@8.57.1)(typescript@5.9.3)
- eslint: 8.57.1
- eslint-import-resolver-node: 0.3.9
- eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.31.0)(eslint@8.57.1)
- eslint-plugin-import: 2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1)
- eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.1)
- eslint-plugin-react: 7.37.5(eslint@8.57.1)
- eslint-plugin-react-hooks: 5.2.0(eslint@8.57.1)
- optionalDependencies:
- typescript: 5.9.3
- transitivePeerDependencies:
- - eslint-import-resolver-webpack
- - eslint-plugin-import-x
- - supports-color
-
eslint-config-prettier@8.10.0(eslint@8.57.1):
dependencies:
eslint: 8.57.1
- eslint-import-resolver-node@0.3.9:
+ eslint-plugin-react-hooks@7.1.1(eslint@8.57.1):
dependencies:
- debug: 3.2.7
- is-core-module: 2.16.1
- resolve: 1.22.10
+ '@babel/core': 7.29.7
+ '@babel/parser': 7.27.5
+ eslint: 8.57.1
+ hermes-parser: 0.25.1
+ zod: 3.25.67
+ zod-validation-error: 4.0.2(zod@3.25.67)
transitivePeerDependencies:
- supports-color
- eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.31.0)(eslint@8.57.1):
- dependencies:
- '@nolyfill/is-core-module': 1.0.39
- debug: 4.4.1(supports-color@9.4.0)
- eslint: 8.57.1
- get-tsconfig: 4.10.1
- is-bun-module: 2.0.0
- stable-hash: 0.0.5
- tinyglobby: 0.2.14
- unrs-resolver: 1.9.0
- optionalDependencies:
- eslint-plugin-import: 2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1)
- transitivePeerDependencies:
- - supports-color
-
- eslint-module-utils@2.12.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1):
- dependencies:
- debug: 3.2.7
- optionalDependencies:
- '@typescript-eslint/parser': 5.62.0(eslint@8.57.1)(typescript@5.9.3)
- eslint: 8.57.1
- eslint-import-resolver-node: 0.3.9
- eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.31.0)(eslint@8.57.1)
- transitivePeerDependencies:
- - supports-color
-
- eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1):
- dependencies:
- '@rtsao/scc': 1.1.0
- array-includes: 3.1.9
- array.prototype.findlastindex: 1.2.6
- array.prototype.flat: 1.3.3
- array.prototype.flatmap: 1.3.3
- debug: 3.2.7
- doctrine: 2.1.0
- eslint: 8.57.1
- eslint-import-resolver-node: 0.3.9
- eslint-module-utils: 2.12.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1)
- hasown: 2.0.2
- is-core-module: 2.16.1
- is-glob: 4.0.3
- minimatch: 3.1.2
- object.fromentries: 2.0.8
- object.groupby: 1.0.3
- object.values: 1.2.1
- semver: 6.3.1
- string.prototype.trimend: 1.0.9
- tsconfig-paths: 3.15.0
- optionalDependencies:
- '@typescript-eslint/parser': 5.62.0(eslint@8.57.1)(typescript@5.9.3)
- transitivePeerDependencies:
- - eslint-import-resolver-typescript
- - eslint-import-resolver-webpack
- - supports-color
-
- eslint-plugin-jsx-a11y@6.10.2(eslint@8.57.1):
- dependencies:
- aria-query: 5.3.2
- array-includes: 3.1.9
- array.prototype.flatmap: 1.3.3
- ast-types-flow: 0.0.8
- axe-core: 4.10.3
- axobject-query: 4.1.0
- damerau-levenshtein: 1.0.8
- emoji-regex: 9.2.2
- eslint: 8.57.1
- hasown: 2.0.2
- jsx-ast-utils: 3.3.5
- language-tags: 1.0.9
- minimatch: 3.1.2
- object.fromentries: 2.0.8
- safe-regex-test: 1.1.0
- string.prototype.includes: 2.0.1
-
- eslint-plugin-react-hooks@5.2.0(eslint@8.57.1):
- dependencies:
- eslint: 8.57.1
-
eslint-plugin-react@7.37.5(eslint@8.57.1):
dependencies:
array-includes: 3.1.9
@@ -9059,7 +9871,7 @@ snapshots:
array.prototype.flatmap: 1.3.3
array.prototype.tosorted: 1.1.4
doctrine: 2.1.0
- es-iterator-helpers: 1.2.1
+ es-iterator-helpers: 1.3.2
eslint: 8.57.1
estraverse: 5.3.0
hasown: 2.0.2
@@ -9069,7 +9881,7 @@ snapshots:
object.fromentries: 2.0.8
object.values: 1.2.1
prop-types: 15.8.1
- resolve: 2.0.0-next.5
+ resolve: 2.0.0-next.7
semver: 6.3.1
string.prototype.matchall: 4.0.12
string.prototype.repeat: 1.0.0
@@ -9196,25 +10008,10 @@ snapshots:
jest-matcher-utils: 27.5.1
jest-message-util: 27.5.1
- expect@30.0.0:
- dependencies:
- '@jest/expect-utils': 30.0.0
- '@jest/get-type': 30.0.0
- jest-matcher-utils: 30.0.0
- jest-message-util: 30.0.0
- jest-mock: 30.0.0
- jest-util: 30.0.0
+ fast-decode-uri-component@1.0.1: {}
fast-deep-equal@3.1.3: {}
- fast-glob@3.3.1:
- dependencies:
- '@nodelib/fs.stat': 2.0.5
- '@nodelib/fs.walk': 1.2.8
- glob-parent: 5.1.2
- merge2: 1.4.1
- micromatch: 4.0.8
-
fast-glob@3.3.3:
dependencies:
'@nodelib/fs.stat': 2.0.5
@@ -9225,10 +10022,43 @@ snapshots:
fast-json-stable-stringify@2.1.0: {}
+ fast-json-stringify@6.4.0:
+ dependencies:
+ '@fastify/merge-json-schemas': 0.2.1
+ ajv: 8.17.1
+ ajv-formats: 3.0.1(ajv@8.17.1)
+ fast-uri: 3.0.6
+ json-schema-ref-resolver: 3.0.0
+ rfdc: 1.4.1
+
fast-levenshtein@2.0.6: {}
+ fast-querystring@1.1.2:
+ dependencies:
+ fast-decode-uri-component: 1.0.1
+
fast-uri@3.0.6: {}
+ fastify-plugin@5.1.0: {}
+
+ fastify@5.8.5:
+ dependencies:
+ '@fastify/ajv-compiler': 4.0.5
+ '@fastify/error': 4.2.0
+ '@fastify/fast-json-stringify-compiler': 5.0.3
+ '@fastify/proxy-addr': 5.1.0
+ abstract-logging: 2.0.1
+ avvio: 9.2.0
+ fast-json-stringify: 6.4.0
+ find-my-way: 9.6.0
+ light-my-request: 6.6.0
+ pino: 10.3.1
+ process-warning: 5.0.0
+ rfdc: 1.4.1
+ secure-json-parse: 4.1.0
+ semver: 7.8.0
+ toad-cache: 3.7.1
+
fastq@1.19.1:
dependencies:
reusify: 1.1.0
@@ -9241,6 +10071,10 @@ snapshots:
optionalDependencies:
picomatch: 4.0.2
+ fdir@6.5.0(picomatch@4.0.4):
+ optionalDependencies:
+ picomatch: 4.0.4
+
file-entry-cache@6.0.1:
dependencies:
flat-cache: 3.2.0
@@ -9253,11 +10087,11 @@ snapshots:
dependencies:
to-regex-range: 5.0.1
- find-cache-dir@3.3.2:
+ find-my-way@9.6.0:
dependencies:
- commondir: 1.0.1
- make-dir: 3.1.0
- pkg-dir: 4.2.0
+ fast-deep-equal: 3.1.3
+ fast-querystring: 1.1.2
+ safe-regex2: 5.1.1
find-up@4.1.0:
dependencies:
@@ -9369,10 +10203,6 @@ snapshots:
es-errors: 1.3.0
get-intrinsic: 1.3.0
- get-tsconfig@4.10.1:
- dependencies:
- resolve-pkg-maps: 1.0.0
-
git-raw-commits@2.0.11:
dependencies:
dargs: 7.0.0
@@ -9391,6 +10221,12 @@ snapshots:
glob-to-regexp@0.4.1: {}
+ glob@13.0.6:
+ dependencies:
+ minimatch: 10.2.5
+ minipass: 7.1.3
+ path-scurry: 2.0.2
+
glob@7.2.3:
dependencies:
fs.realpath: 1.0.0
@@ -9424,14 +10260,6 @@ snapshots:
merge2: 1.4.1
slash: 3.0.0
- globby@6.1.0:
- dependencies:
- array-union: 1.0.2
- glob: 7.2.3
- object-assign: 4.1.1
- pify: 2.3.0
- pinkie-promise: 2.0.1
-
gopd@1.2.0: {}
graceful-fs@4.2.11: {}
@@ -9462,8 +10290,18 @@ snapshots:
dependencies:
function-bind: 1.1.2
+ hasown@2.0.3:
+ dependencies:
+ function-bind: 1.1.2
+
he@1.2.0: {}
+ hermes-estree@0.25.1: {}
+
+ hermes-parser@0.25.1:
+ dependencies:
+ hermes-estree: 0.25.1
+
hls.js@1.6.10: {}
hosted-git-info@2.8.9: {}
@@ -9478,6 +10316,14 @@ snapshots:
html-escaper@2.0.2: {}
+ http-errors@2.0.1:
+ dependencies:
+ depd: 2.0.0
+ inherits: 2.0.4
+ setprototypeof: 1.2.0
+ statuses: 2.0.2
+ toidentifier: 1.0.1
+
http-proxy-agent@4.0.1:
dependencies:
'@tootallnate/once': 1.1.2
@@ -9548,6 +10394,8 @@ snapshots:
inversify@6.0.1: {}
+ ipaddr.js@2.4.0: {}
+
is-arguments@1.2.0:
dependencies:
call-bound: 1.0.4
@@ -9580,16 +10428,16 @@ snapshots:
is-buffer@1.1.6: {}
- is-bun-module@2.0.0:
- dependencies:
- semver: 7.8.0
-
is-callable@1.2.7: {}
is-core-module@2.16.1:
dependencies:
hasown: 2.0.2
+ is-core-module@2.16.2:
+ dependencies:
+ hasown: 2.0.3
+
is-data-view@1.0.2:
dependencies:
call-bound: 1.0.4
@@ -9630,7 +10478,7 @@ snapshots:
is-nan@1.3.2:
dependencies:
- call-bind: 1.0.8
+ call-bind: 1.0.9
define-properties: 1.2.1
is-negative-zero@2.0.3: {}
@@ -9646,16 +10494,6 @@ snapshots:
is-obj@2.0.0: {}
- is-path-cwd@2.2.0: {}
-
- is-path-in-cwd@2.1.0:
- dependencies:
- is-path-inside: 2.1.0
-
- is-path-inside@2.1.0:
- dependencies:
- path-is-inside: 1.0.2
-
is-path-inside@3.0.3: {}
is-plain-obj@1.1.0: {}
@@ -9719,7 +10557,7 @@ snapshots:
istanbul-lib-instrument@5.2.1:
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
'@babel/parser': 7.27.5
'@istanbuljs/schema': 0.1.3
istanbul-lib-coverage: 3.2.2
@@ -9841,10 +10679,10 @@ snapshots:
jest-config@27.5.1(ts-node@10.9.2(@types/node@24.0.3)(typescript@5.9.3)):
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
'@jest/test-sequencer': 27.5.1
'@jest/types': 27.5.1
- babel-jest: 27.5.1(@babel/core@7.27.4)
+ babel-jest: 27.5.1(@babel/core@7.29.7)
chalk: 4.1.2
ci-info: 3.9.0
deepmerge: 4.3.1
@@ -9880,13 +10718,6 @@ snapshots:
jest-get-type: 27.5.1
pretty-format: 27.5.1
- jest-diff@30.0.0:
- dependencies:
- '@jest/diff-sequences': 30.0.0
- '@jest/get-type': 30.0.0
- chalk: 4.1.2
- pretty-format: 30.0.0
-
jest-docblock@27.5.1:
dependencies:
detect-newline: 3.1.0
@@ -9976,13 +10807,6 @@ snapshots:
jest-get-type: 27.5.1
pretty-format: 27.5.1
- jest-matcher-utils@30.0.0:
- dependencies:
- '@jest/get-type': 30.0.0
- chalk: 4.1.2
- jest-diff: 30.0.0
- pretty-format: 30.0.0
-
jest-message-util@27.5.1:
dependencies:
'@babel/code-frame': 7.27.1
@@ -9995,37 +10819,17 @@ snapshots:
slash: 3.0.0
stack-utils: 2.0.6
- jest-message-util@30.0.0:
- dependencies:
- '@babel/code-frame': 7.27.1
- '@jest/types': 30.0.0
- '@types/stack-utils': 2.0.3
- chalk: 4.1.2
- graceful-fs: 4.2.11
- micromatch: 4.0.8
- pretty-format: 30.0.0
- slash: 3.0.0
- stack-utils: 2.0.6
-
jest-mock@27.5.1:
dependencies:
'@jest/types': 27.5.1
'@types/node': 24.0.3
- jest-mock@30.0.0:
- dependencies:
- '@jest/types': 30.0.0
- '@types/node': 24.0.3
- jest-util: 30.0.0
-
jest-pnp-resolver@1.2.3(jest-resolve@27.5.1):
optionalDependencies:
jest-resolve: 27.5.1
jest-regex-util@27.5.1: {}
- jest-regex-util@30.0.0: {}
-
jest-resolve-dependencies@27.5.1:
dependencies:
'@jest/types': 27.5.1
@@ -10110,16 +10914,16 @@ snapshots:
jest-snapshot@27.5.1:
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.29.7
'@babel/generator': 7.27.5
- '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.27.4)
+ '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.29.7)
'@babel/traverse': 7.27.4
'@babel/types': 7.27.6
'@jest/transform': 27.5.1
'@jest/types': 27.5.1
'@types/babel__traverse': 7.20.7
'@types/prettier': 2.7.3
- babel-preset-current-node-syntax: 1.1.0(@babel/core@7.27.4)
+ babel-preset-current-node-syntax: 1.1.0(@babel/core@7.29.7)
chalk: 4.1.2
expect: 27.5.1
graceful-fs: 4.2.11
@@ -10144,15 +10948,6 @@ snapshots:
graceful-fs: 4.2.11
picomatch: 2.3.1
- jest-util@30.0.0:
- dependencies:
- '@jest/types': 30.0.0
- '@types/node': 24.0.3
- chalk: 4.1.2
- ci-info: 4.2.0
- graceful-fs: 4.2.11
- picomatch: 4.0.2
-
jest-validate@27.5.1:
dependencies:
'@jest/types': 27.5.1
@@ -10253,6 +11048,10 @@ snapshots:
json-parse-even-better-errors@2.3.1: {}
+ json-schema-ref-resolver@3.0.0:
+ dependencies:
+ dequal: 2.0.3
+
json-schema-traverse@0.4.1: {}
json-schema-traverse@1.0.0: {}
@@ -10261,10 +11060,6 @@ snapshots:
json-stable-stringify-without-jsonify@1.0.1: {}
- json5@1.0.2:
- dependencies:
- minimist: 1.2.8
-
json5@2.2.3: {}
jsonfile@6.1.0:
@@ -10292,12 +11087,6 @@ snapshots:
kleur@3.0.3: {}
- language-subtag-registry@0.3.23: {}
-
- language-tags@1.0.9:
- dependencies:
- language-subtag-registry: 0.3.23
-
leven@3.1.0: {}
levn@0.3.0:
@@ -10312,6 +11101,12 @@ snapshots:
libphonenumber-js@1.12.15: {}
+ light-my-request@6.6.0:
+ dependencies:
+ cookie: 1.1.1
+ process-warning: 4.0.1
+ set-cookie-parser: 2.7.2
+
lightningcss-android-arm64@1.32.0:
optional: true
@@ -10430,9 +11225,7 @@ snapshots:
dependencies:
js-tokens: 4.0.0
- lower-case@2.0.2:
- dependencies:
- tslib: 2.8.1
+ lru-cache@11.5.0: {}
lru-cache@5.1.1:
dependencies:
@@ -10456,10 +11249,6 @@ snapshots:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
- make-dir@3.1.0:
- dependencies:
- semver: 6.3.1
-
make-dir@4.0.0:
dependencies:
semver: 7.7.2
@@ -10487,10 +11276,6 @@ snapshots:
crypt: 0.0.2
is-buffer: 1.1.6
- mdn-data@2.0.28: {}
-
- mdn-data@2.0.30: {}
-
media-captions@0.0.18: {}
media-captions@1.0.4: {}
@@ -10526,12 +11311,18 @@ snapshots:
dependencies:
mime-db: 1.52.0
+ mime@3.0.0: {}
+
mimic-fn@2.1.0: {}
min-indent@1.0.1: {}
mini-svg-data-uri@1.4.4: {}
+ minimatch@10.2.5:
+ dependencies:
+ brace-expansion: 5.0.6
+
minimatch@3.1.2:
dependencies:
brace-expansion: 1.1.12
@@ -10546,7 +11337,7 @@ snapshots:
is-plain-obj: 1.1.0
kind-of: 6.0.3
- minimist@1.2.8: {}
+ minipass@7.1.3: {}
mkdirp@2.1.3: {}
@@ -10574,69 +11365,18 @@ snapshots:
nanoid@3.3.12: {}
- napi-postinstall@0.2.4: {}
-
natural-compare-lite@1.4.0: {}
natural-compare@1.4.0: {}
neo-async@2.6.2: {}
- next-pwa@5.6.0(@babel/core@7.27.4)(@types/babel__core@7.20.5)(next@15.5.18(@babel/core@7.27.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(webpack@5.99.9):
+ node-exports-info@1.6.0:
dependencies:
- babel-loader: 8.4.1(@babel/core@7.27.4)(webpack@5.99.9)
- clean-webpack-plugin: 4.0.0(webpack@5.99.9)
- globby: 11.1.0
- next: 15.5.18(@babel/core@7.27.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- terser-webpack-plugin: 5.3.14(webpack@5.99.9)
- workbox-webpack-plugin: 6.6.0(@types/babel__core@7.20.5)(webpack@5.99.9)
- workbox-window: 6.6.0
- transitivePeerDependencies:
- - '@babel/core'
- - '@swc/core'
- - '@types/babel__core'
- - esbuild
- - supports-color
- - uglify-js
- - webpack
-
- next-router-mock@0.9.13(next@15.5.18(@babel/core@7.27.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3):
- dependencies:
- next: 15.5.18(@babel/core@7.27.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- react: 19.2.3
-
- next-themes@0.4.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
- dependencies:
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
-
- next@15.5.18(@babel/core@7.27.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
- dependencies:
- '@next/env': 15.5.18
- '@swc/helpers': 0.5.15
- caniuse-lite: 1.0.30001741
- postcss: 8.4.31
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
- styled-jsx: 5.1.6(@babel/core@7.27.4)(react@19.2.3)
- optionalDependencies:
- '@next/swc-darwin-arm64': 15.5.18
- '@next/swc-darwin-x64': 15.5.18
- '@next/swc-linux-arm64-gnu': 15.5.18
- '@next/swc-linux-arm64-musl': 15.5.18
- '@next/swc-linux-x64-gnu': 15.5.18
- '@next/swc-linux-x64-musl': 15.5.18
- '@next/swc-win32-arm64-msvc': 15.5.18
- '@next/swc-win32-x64-msvc': 15.5.18
- sharp: 0.34.5
- transitivePeerDependencies:
- - '@babel/core'
- - babel-plugin-macros
-
- no-case@3.0.4:
- dependencies:
- lower-case: 2.0.2
- tslib: 2.8.1
+ array.prototype.flatmap: 1.3.3
+ es-errors: 1.3.0
+ object.entries: 1.1.9
+ semver: 6.3.1
node-int64@0.4.0: {}
@@ -10644,6 +11384,8 @@ snapshots:
node-releases@2.0.20: {}
+ node-releases@2.0.46: {}
+
normalize-package-data@2.5.0:
dependencies:
hosted-git-info: 2.8.9
@@ -10666,10 +11408,6 @@ snapshots:
dependencies:
path-key: 3.1.1
- nth-check@2.1.1:
- dependencies:
- boolbase: 1.0.0
-
nwsapi@2.2.20: {}
object-assign@4.1.1: {}
@@ -10678,7 +11416,7 @@ snapshots:
object-is@1.1.6:
dependencies:
- call-bind: 1.0.8
+ call-bind: 1.0.9
define-properties: 1.2.1
object-keys@1.1.1: {}
@@ -10706,12 +11444,6 @@ snapshots:
es-abstract: 1.24.0
es-object-atoms: 1.1.1
- object.groupby@1.0.3:
- dependencies:
- call-bind: 1.0.8
- define-properties: 1.2.1
- es-abstract: 1.24.0
-
object.values@1.2.1:
dependencies:
call-bind: 1.0.8
@@ -10719,6 +11451,8 @@ snapshots:
define-properties: 1.2.1
es-object-atoms: 1.1.1
+ on-exit-leak-free@2.1.2: {}
+
once@1.4.0:
dependencies:
wrappy: 1.0.2
@@ -10773,8 +11507,6 @@ snapshots:
dependencies:
p-limit: 3.1.0
- p-map@2.1.0: {}
-
p-map@4.0.0:
dependencies:
aggregate-error: 3.1.0
@@ -10798,12 +11530,17 @@ snapshots:
path-is-absolute@1.0.1: {}
- path-is-inside@1.0.2: {}
-
path-key@3.1.1: {}
path-parse@1.0.7: {}
+ path-scurry@2.0.2:
+ dependencies:
+ lru-cache: 11.5.0
+ minipass: 7.1.3
+
+ path-to-regexp@8.4.2: {}
+
path-type@4.0.0: {}
picocolors@1.1.1: {}
@@ -10812,17 +11549,29 @@ snapshots:
picomatch@4.0.2: {}
+ picomatch@4.0.4: {}
+
pidtree@0.5.0: {}
- pify@2.3.0: {}
-
- pify@4.0.1: {}
-
- pinkie-promise@2.0.1:
+ pino-abstract-transport@3.0.0:
dependencies:
- pinkie: 2.0.4
+ split2: 4.2.0
- pinkie@2.0.4: {}
+ pino-std-serializers@7.1.0: {}
+
+ pino@10.3.1:
+ dependencies:
+ '@pinojs/redact': 0.4.0
+ atomic-sleep: 1.0.0
+ on-exit-leak-free: 2.1.2
+ pino-abstract-transport: 3.0.0
+ pino-std-serializers: 7.1.0
+ process-warning: 5.0.0
+ quick-format-unescaped: 4.0.4
+ real-require: 0.2.0
+ safe-stable-stringify: 2.5.0
+ sonic-boom: 4.2.1
+ thread-stream: 4.2.0
pirates@4.0.7: {}
@@ -10842,12 +11591,6 @@ snapshots:
postcss-value-parser@4.2.0: {}
- postcss@8.4.31:
- dependencies:
- nanoid: 3.3.11
- picocolors: 1.1.1
- source-map-js: 1.2.1
-
postcss@8.5.15:
dependencies:
nanoid: 3.3.12
@@ -10872,17 +11615,17 @@ snapshots:
pretty-bytes@5.6.0: {}
+ pretty-bytes@6.1.1: {}
+
pretty-format@27.5.1:
dependencies:
ansi-regex: 5.0.1
ansi-styles: 5.2.0
react-is: 17.0.2
- pretty-format@30.0.0:
- dependencies:
- '@jest/schemas': 30.0.0
- ansi-styles: 5.2.0
- react-is: 18.3.1
+ process-warning@4.0.1: {}
+
+ process-warning@5.0.0: {}
process@0.11.10: {}
@@ -10909,6 +11652,8 @@ snapshots:
queue-microtask@1.2.3: {}
+ quick-format-unescaped@4.0.4: {}
+
quick-lru@4.0.1: {}
randombytes@2.1.0:
@@ -10957,7 +11702,19 @@ snapshots:
react-is@17.0.2: {}
- react-is@18.3.1: {}
+ react-router-dom@7.15.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
+ dependencies:
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ react-router: 7.15.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+
+ react-router@7.15.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
+ dependencies:
+ cookie: 1.1.1
+ react: 19.2.3
+ set-cookie-parser: 2.7.2
+ optionalDependencies:
+ react-dom: 19.2.3(react@19.2.3)
react-stately@3.46.0(react@19.2.3):
dependencies:
@@ -10999,6 +11756,10 @@ snapshots:
string_decoder: 1.3.0
util-deprecate: 1.0.2
+ real-require@0.2.0: {}
+
+ real-require@1.0.0: {}
+
redent@3.0.0:
dependencies:
indent-string: 4.0.0
@@ -11030,6 +11791,10 @@ snapshots:
dependencies:
regenerate: 1.4.2
+ regenerate-unicode-properties@10.2.2:
+ dependencies:
+ regenerate: 1.4.2
+
regenerate@1.4.2: {}
regexp.prototype.flags@1.5.4:
@@ -11050,12 +11815,25 @@ snapshots:
unicode-match-property-ecmascript: 2.0.0
unicode-match-property-value-ecmascript: 2.2.0
+ regexpu-core@6.4.0:
+ dependencies:
+ regenerate: 1.4.2
+ regenerate-unicode-properties: 10.2.2
+ regjsgen: 0.8.0
+ regjsparser: 0.13.1
+ unicode-match-property-ecmascript: 2.0.0
+ unicode-match-property-value-ecmascript: 2.2.1
+
regjsgen@0.8.0: {}
regjsparser@0.12.0:
dependencies:
jsesc: 3.0.2
+ regjsparser@0.13.1:
+ dependencies:
+ jsesc: 3.1.0
+
require-directory@2.1.1: {}
require-from-string@2.0.2: {}
@@ -11074,8 +11852,6 @@ snapshots:
dependencies:
global-dirs: 0.1.1
- resolve-pkg-maps@1.0.0: {}
-
resolve.exports@1.1.1: {}
resolve@1.22.10:
@@ -11084,9 +11860,19 @@ snapshots:
path-parse: 1.0.7
supports-preserve-symlinks-flag: 1.0.0
- resolve@2.0.0-next.5:
+ resolve@1.22.12:
dependencies:
- is-core-module: 2.16.1
+ es-errors: 1.3.0
+ is-core-module: 2.16.2
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+
+ resolve@2.0.0-next.7:
+ dependencies:
+ es-errors: 1.3.0
+ is-core-module: 2.16.2
+ node-exports-info: 1.6.0
+ object-keys: 1.1.1
path-parse: 1.0.7
supports-preserve-symlinks-flag: 1.0.0
@@ -11095,21 +11881,40 @@ snapshots:
onetime: 5.1.2
signal-exit: 3.0.7
+ ret@0.5.0: {}
+
reusify@1.1.0: {}
rfdc@1.4.1: {}
- rimraf@2.7.1:
- dependencies:
- glob: 7.2.3
-
rimraf@3.0.2:
dependencies:
glob: 7.2.3
+ rolldown@1.0.2:
+ dependencies:
+ '@oxc-project/types': 0.132.0
+ '@rolldown/pluginutils': 1.0.1
+ optionalDependencies:
+ '@rolldown/binding-android-arm64': 1.0.2
+ '@rolldown/binding-darwin-arm64': 1.0.2
+ '@rolldown/binding-darwin-x64': 1.0.2
+ '@rolldown/binding-freebsd-x64': 1.0.2
+ '@rolldown/binding-linux-arm-gnueabihf': 1.0.2
+ '@rolldown/binding-linux-arm64-gnu': 1.0.2
+ '@rolldown/binding-linux-arm64-musl': 1.0.2
+ '@rolldown/binding-linux-ppc64-gnu': 1.0.2
+ '@rolldown/binding-linux-s390x-gnu': 1.0.2
+ '@rolldown/binding-linux-x64-gnu': 1.0.2
+ '@rolldown/binding-linux-x64-musl': 1.0.2
+ '@rolldown/binding-openharmony-arm64': 1.0.2
+ '@rolldown/binding-wasm32-wasi': 1.0.2
+ '@rolldown/binding-win32-arm64-msvc': 1.0.2
+ '@rolldown/binding-win32-x64-msvc': 1.0.2
+
rollup-plugin-terser@7.0.2(rollup@2.79.2):
dependencies:
- '@babel/code-frame': 7.27.1
+ '@babel/code-frame': 7.29.7
jest-worker: 26.6.2
rollup: 2.79.2
serialize-javascript: 4.0.0
@@ -11148,6 +11953,12 @@ snapshots:
es-errors: 1.3.0
is-regex: 1.2.1
+ safe-regex2@5.1.1:
+ dependencies:
+ ret: 0.5.0
+
+ safe-stable-stringify@2.5.0: {}
+
safer-buffer@2.1.2: {}
saxes@5.0.1:
@@ -11156,12 +11967,6 @@ snapshots:
scheduler@0.27.0: {}
- schema-utils@2.7.1:
- dependencies:
- '@types/json-schema': 7.0.15
- ajv: 6.12.6
- ajv-keywords: 3.5.2(ajv@6.12.6)
-
schema-utils@4.3.2:
dependencies:
'@types/json-schema': 7.0.15
@@ -11169,6 +11974,8 @@ snapshots:
ajv-formats: 2.1.1(ajv@8.17.1)
ajv-keywords: 5.1.0(ajv@8.17.1)
+ secure-json-parse@4.1.0: {}
+
semver@5.7.2: {}
semver@6.3.1: {}
@@ -11189,6 +11996,8 @@ snapshots:
dependencies:
randombytes: 2.1.0
+ set-cookie-parser@2.7.2: {}
+
set-function-length@1.2.2:
dependencies:
define-data-property: 1.1.4
@@ -11211,37 +12020,7 @@ snapshots:
es-errors: 1.3.0
es-object-atoms: 1.1.1
- sharp@0.34.5:
- dependencies:
- '@img/colour': 1.1.0
- detect-libc: 2.1.2
- semver: 7.8.0
- optionalDependencies:
- '@img/sharp-darwin-arm64': 0.34.5
- '@img/sharp-darwin-x64': 0.34.5
- '@img/sharp-libvips-darwin-arm64': 1.2.4
- '@img/sharp-libvips-darwin-x64': 1.2.4
- '@img/sharp-libvips-linux-arm': 1.2.4
- '@img/sharp-libvips-linux-arm64': 1.2.4
- '@img/sharp-libvips-linux-ppc64': 1.2.4
- '@img/sharp-libvips-linux-riscv64': 1.2.4
- '@img/sharp-libvips-linux-s390x': 1.2.4
- '@img/sharp-libvips-linux-x64': 1.2.4
- '@img/sharp-libvips-linuxmusl-arm64': 1.2.4
- '@img/sharp-libvips-linuxmusl-x64': 1.2.4
- '@img/sharp-linux-arm': 0.34.5
- '@img/sharp-linux-arm64': 0.34.5
- '@img/sharp-linux-ppc64': 0.34.5
- '@img/sharp-linux-riscv64': 0.34.5
- '@img/sharp-linux-s390x': 0.34.5
- '@img/sharp-linux-x64': 0.34.5
- '@img/sharp-linuxmusl-arm64': 0.34.5
- '@img/sharp-linuxmusl-x64': 0.34.5
- '@img/sharp-wasm32': 0.34.5
- '@img/sharp-win32-arm64': 0.34.5
- '@img/sharp-win32-ia32': 0.34.5
- '@img/sharp-win32-x64': 0.34.5
- optional: true
+ setprototypeof@1.2.0: {}
shebang-command@2.0.0:
dependencies:
@@ -11300,10 +12079,9 @@ snapshots:
ansi-styles: 6.2.1
is-fullwidth-code-point: 4.0.0
- snake-case@3.0.4:
+ sonic-boom@4.2.1:
dependencies:
- dot-case: 3.0.4
- tslib: 2.8.1
+ atomic-sleep: 1.0.0
source-list-map@2.0.1: {}
@@ -11346,14 +12124,16 @@ snapshots:
dependencies:
readable-stream: 3.6.2
- sprintf-js@1.0.3: {}
+ split2@4.2.0: {}
- stable-hash@0.0.5: {}
+ sprintf-js@1.0.3: {}
stack-utils@2.0.6:
dependencies:
escape-string-regexp: 2.0.0
+ statuses@2.0.2: {}
+
stop-iteration-iterator@1.1.0:
dependencies:
es-errors: 1.3.0
@@ -11380,12 +12160,6 @@ snapshots:
emoji-regex: 9.2.2
strip-ansi: 7.1.0
- string.prototype.includes@2.0.1:
- dependencies:
- call-bind: 1.0.8
- define-properties: 1.2.1
- es-abstract: 1.24.0
-
string.prototype.matchall@4.0.12:
dependencies:
call-bind: 1.0.8
@@ -11452,8 +12226,6 @@ snapshots:
dependencies:
ansi-regex: 6.1.0
- strip-bom@3.0.0: {}
-
strip-bom@4.0.0: {}
strip-comments@2.0.1: {}
@@ -11466,13 +12238,6 @@ snapshots:
strip-json-comments@3.1.1: {}
- styled-jsx@5.1.6(@babel/core@7.27.4)(react@19.2.3):
- dependencies:
- client-only: 0.0.1
- react: 19.2.3
- optionalDependencies:
- '@babel/core': 7.27.4
-
supports-color@7.2.0:
dependencies:
has-flag: 4.0.0
@@ -11490,18 +12255,6 @@ snapshots:
supports-preserve-symlinks-flag@1.0.0: {}
- svg-parser@2.0.4: {}
-
- svgo@3.3.2:
- dependencies:
- '@trysound/sax': 0.2.0
- commander: 7.2.0
- css-select: 5.1.0
- css-tree: 2.3.1
- css-what: 6.1.0
- csso: 5.0.5
- picocolors: 1.1.1
-
swiper@11.2.8: {}
symbol-tree@3.2.4: {}
@@ -11532,14 +12285,16 @@ snapshots:
ansi-escapes: 4.3.2
supports-hyperlinks: 2.3.0
- terser-webpack-plugin@5.3.14(webpack@5.99.9):
+ terser-webpack-plugin@5.3.14(esbuild@0.28.0)(webpack@5.99.9(esbuild@0.28.0)):
dependencies:
- '@jridgewell/trace-mapping': 0.3.25
+ '@jridgewell/trace-mapping': 0.3.31
jest-worker: 27.5.1
schema-utils: 4.3.2
serialize-javascript: 6.0.2
terser: 5.43.1
- webpack: 5.99.9
+ webpack: 5.99.9(esbuild@0.28.0)
+ optionalDependencies:
+ esbuild: 0.28.0
terser@5.43.1:
dependencies:
@@ -11558,6 +12313,10 @@ snapshots:
text-table@0.2.0: {}
+ thread-stream@4.2.0:
+ dependencies:
+ real-require: 1.0.0
+
throat@6.0.2: {}
through2@4.0.2:
@@ -11571,12 +12330,21 @@ snapshots:
fdir: 6.4.6(picomatch@4.0.2)
picomatch: 4.0.2
+ tinyglobby@0.2.16:
+ dependencies:
+ fdir: 6.5.0(picomatch@4.0.4)
+ picomatch: 4.0.4
+
tmpl@1.0.5: {}
to-regex-range@5.0.1:
dependencies:
is-number: 7.0.0
+ toad-cache@3.7.1: {}
+
+ toidentifier@1.0.1: {}
+
tough-cookie@4.1.4:
dependencies:
psl: 1.15.0
@@ -11631,13 +12399,6 @@ snapshots:
yn: 3.1.1
optional: true
- tsconfig-paths@3.15.0:
- dependencies:
- '@types/json5': 0.0.29
- json5: 1.0.2
- minimist: 1.2.8
- strip-bom: 3.0.0
-
tslib@1.14.1: {}
tslib@2.5.0: {}
@@ -11649,6 +12410,12 @@ snapshots:
tslib: 1.14.1
typescript: 5.9.3
+ tsx@4.22.3:
+ dependencies:
+ esbuild: 0.28.0
+ optionalDependencies:
+ fsevents: 2.3.3
+
tw-animate-css@1.4.0: {}
type-check@0.3.2:
@@ -11727,6 +12494,8 @@ snapshots:
undici-types@7.8.0: {}
+ undici@8.3.0: {}
+
unicode-canonical-property-names-ecmascript@2.0.1: {}
unicode-match-property-ecmascript@2.0.0:
@@ -11736,6 +12505,8 @@ snapshots:
unicode-match-property-value-ecmascript@2.2.0: {}
+ unicode-match-property-value-ecmascript@2.2.1: {}
+
unicode-property-aliases-ecmascript@2.1.0: {}
unique-string@2.0.0:
@@ -11746,30 +12517,6 @@ snapshots:
universalify@2.0.1: {}
- unrs-resolver@1.9.0:
- dependencies:
- napi-postinstall: 0.2.4
- optionalDependencies:
- '@unrs/resolver-binding-android-arm-eabi': 1.9.0
- '@unrs/resolver-binding-android-arm64': 1.9.0
- '@unrs/resolver-binding-darwin-arm64': 1.9.0
- '@unrs/resolver-binding-darwin-x64': 1.9.0
- '@unrs/resolver-binding-freebsd-x64': 1.9.0
- '@unrs/resolver-binding-linux-arm-gnueabihf': 1.9.0
- '@unrs/resolver-binding-linux-arm-musleabihf': 1.9.0
- '@unrs/resolver-binding-linux-arm64-gnu': 1.9.0
- '@unrs/resolver-binding-linux-arm64-musl': 1.9.0
- '@unrs/resolver-binding-linux-ppc64-gnu': 1.9.0
- '@unrs/resolver-binding-linux-riscv64-gnu': 1.9.0
- '@unrs/resolver-binding-linux-riscv64-musl': 1.9.0
- '@unrs/resolver-binding-linux-s390x-gnu': 1.9.0
- '@unrs/resolver-binding-linux-x64-gnu': 1.9.0
- '@unrs/resolver-binding-linux-x64-musl': 1.9.0
- '@unrs/resolver-binding-wasm32-wasi': 1.9.0
- '@unrs/resolver-binding-win32-arm64-msvc': 1.9.0
- '@unrs/resolver-binding-win32-ia32-msvc': 1.9.0
- '@unrs/resolver-binding-win32-x64-msvc': 1.9.0
-
upath@1.2.0: {}
update-browserslist-db@1.1.3(browserslist@4.25.0):
@@ -11784,6 +12531,12 @@ snapshots:
escalade: 3.2.0
picocolors: 1.1.1
+ update-browserslist-db@1.2.3(browserslist@4.28.2):
+ dependencies:
+ browserslist: 4.28.2
+ escalade: 3.2.0
+ picocolors: 1.1.1
+
uri-js@4.4.1:
dependencies:
punycode: 2.3.1
@@ -11832,6 +12585,32 @@ snapshots:
media-captions: 0.0.18
type-fest: 3.13.1
+ vite-plugin-pwa@1.3.0(vite@8.0.14(@types/node@24.0.3)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.43.1)(tsx@4.22.3))(workbox-build@6.6.0(@types/babel__core@7.20.5))(workbox-window@6.6.0):
+ dependencies:
+ debug: 4.4.1(supports-color@9.4.0)
+ pretty-bytes: 6.1.1
+ tinyglobby: 0.2.14
+ vite: 8.0.14(@types/node@24.0.3)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.43.1)(tsx@4.22.3)
+ workbox-build: 6.6.0(@types/babel__core@7.20.5)
+ workbox-window: 6.6.0
+ transitivePeerDependencies:
+ - supports-color
+
+ vite@8.0.14(@types/node@24.0.3)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.43.1)(tsx@4.22.3):
+ dependencies:
+ lightningcss: 1.32.0
+ picomatch: 4.0.4
+ postcss: 8.5.15
+ rolldown: 1.0.2
+ tinyglobby: 0.2.16
+ optionalDependencies:
+ '@types/node': 24.0.3
+ esbuild: 0.28.0
+ fsevents: 2.3.3
+ jiti: 2.7.0
+ terser: 5.43.1
+ tsx: 4.22.3
+
w3c-hr-time@1.0.2:
dependencies:
browser-process-hrtime: 1.0.0
@@ -11855,20 +12634,15 @@ snapshots:
webidl-conversions@6.1.0: {}
- webpack-obfuscator@3.5.1(javascript-obfuscator@4.1.1)(webpack@5.99.9):
+ webpack-obfuscator@3.5.1(javascript-obfuscator@4.1.1)(webpack@5.99.9(esbuild@0.28.0)):
dependencies:
javascript-obfuscator: 4.1.1
loader-utils: 2.0.4
multi-stage-sourcemap: 0.3.1
multimatch: 5.0.0
- webpack: 5.99.9
+ webpack: 5.99.9(esbuild@0.28.0)
webpack-sources: 2.3.1
- webpack-sources@1.4.3:
- dependencies:
- source-list-map: 2.0.1
- source-map: 0.6.1
-
webpack-sources@2.3.1:
dependencies:
source-list-map: 2.0.1
@@ -11876,7 +12650,7 @@ snapshots:
webpack-sources@3.3.3: {}
- webpack@5.99.9:
+ webpack@5.99.9(esbuild@0.28.0):
dependencies:
'@types/eslint-scope': 3.7.7
'@types/estree': 1.0.8
@@ -11899,7 +12673,7 @@ snapshots:
neo-async: 2.6.2
schema-utils: 4.3.2
tapable: 2.3.3
- terser-webpack-plugin: 5.3.14(webpack@5.99.9)
+ terser-webpack-plugin: 5.3.14(esbuild@0.28.0)(webpack@5.99.9(esbuild@0.28.0))
watchpack: 2.4.4
webpack-sources: 3.3.3
transitivePeerDependencies:
@@ -11984,10 +12758,10 @@ snapshots:
workbox-build@6.6.0(@types/babel__core@7.20.5):
dependencies:
'@apideck/better-ajv-errors': 0.3.6(ajv@8.17.1)
- '@babel/core': 7.27.4
- '@babel/preset-env': 7.27.2(@babel/core@7.27.4)
+ '@babel/core': 7.29.7
+ '@babel/preset-env': 7.27.2(@babel/core@7.29.7)
'@babel/runtime': 7.27.6
- '@rollup/plugin-babel': 5.3.1(@babel/core@7.27.4)(@types/babel__core@7.20.5)(rollup@2.79.2)
+ '@rollup/plugin-babel': 5.3.1(@babel/core@7.29.7)(@types/babel__core@7.20.5)(rollup@2.79.2)
'@rollup/plugin-node-resolve': 11.2.1(rollup@2.79.2)
'@rollup/plugin-replace': 2.4.2(rollup@2.79.2)
'@surma/rollup-plugin-off-main-thread': 2.2.3
@@ -12080,18 +12854,6 @@ snapshots:
workbox-sw@6.6.0: {}
- workbox-webpack-plugin@6.6.0(@types/babel__core@7.20.5)(webpack@5.99.9):
- dependencies:
- fast-json-stable-stringify: 2.1.0
- pretty-bytes: 5.6.0
- upath: 1.2.0
- webpack: 5.99.9
- webpack-sources: 1.4.3
- workbox-build: 6.6.0(@types/babel__core@7.20.5)
- transitivePeerDependencies:
- - '@types/babel__core'
- - supports-color
-
workbox-window@6.6.0:
dependencies:
'@types/trusted-types': 2.0.7
@@ -12162,4 +12924,8 @@ snapshots:
yocto-queue@0.1.0: {}
+ zod-validation-error@4.0.2(zod@3.25.67):
+ dependencies:
+ zod: 3.25.67
+
zod@3.25.67: {}
diff --git a/production-final.js b/production-final.js
deleted file mode 100644
index c88faed..0000000
--- a/production-final.js
+++ /dev/null
@@ -1,176 +0,0 @@
-/**
- * 最终的生产环境启动文件
- * 分离Next.js和WebSocket服务器,避免任何冲突
- */
-process.env.NODE_ENV = 'production';
-
-const path = require('path');
-const http = require('http');
-
-// 调用 generate-manifest.js 生成 manifest.json
-function generateManifest() {
- console.log('Generating manifest.json for Docker deployment...');
-
- try {
- const generateManifestScript = path.join(
- __dirname,
- 'scripts',
- 'generate-manifest.js'
- );
- require(generateManifestScript);
- } catch (error) {
- console.error('❌ Error calling generate-manifest.js:', error);
- throw error;
- }
-}
-
-// 生成manifest
-generateManifest();
-
-// 启动独立的WebSocket服务器
-const { createStandaloneWebSocketServer, getOnlineUsers, sendMessageToUsers } = require('./standalone-websocket');
-const wsPort = process.env.WS_PORT || 3001;
-const wss = createStandaloneWebSocketServer(wsPort);
-
-// 将WebSocket函数存储到全局对象,供API路由使用
-global.getOnlineUsers = getOnlineUsers;
-global.sendMessageToUsers = sendMessageToUsers;
-
-// 启动Next.js standalone服务器
-console.log('Starting Next.js production server...');
-const nextServerPath = path.join(__dirname, 'server.js');
-
-// 检查是否存在standalone server.js
-const fs = require('fs');
-if (fs.existsSync(nextServerPath)) {
- // Docker环境,使用standalone server
- require(nextServerPath);
-} else {
- // 非Docker环境,使用标准Next.js启动
- const { createServer } = require('http');
- const { parse } = require('url');
- const next = require('next');
-
- const hostname = process.env.HOSTNAME || '0.0.0.0';
- const port = process.env.PORT || 3000;
-
- const app = next({
- dev: false,
- hostname,
- port
- });
-
- const handle = app.getRequestHandler();
-
- app.prepare().then(() => {
- const server = createServer(async (req, res) => {
- try {
- const parsedUrl = parse(req.url, true);
- await handle(req, res, parsedUrl);
- } catch (err) {
- console.error('处理请求时出错:', req.url, err);
- res.statusCode = 500;
- res.end('内部服务器错误');
- }
- });
-
- server.listen(port, (err) => {
- if (err) throw err;
- console.log(`> Next.js服务已启动: http://${hostname}:${port}`);
- setupServerTasks();
- });
- });
-}
-
-// 设置服务器启动后的任务
-function setupServerTasks() {
- const httpPort = process.env.PORT || 3000;
- const hostname = process.env.HOSTNAME || 'localhost';
-
- // 每1秒轮询一次,直到请求成功
- const TARGET_URL = `http://${hostname}:${httpPort}/login`;
-
- const intervalId = setInterval(() => {
- console.log(`Fetching ${TARGET_URL} ...`);
-
- const req = http.get(TARGET_URL, (res) => {
- // 当返回2xx状态码时认为成功,然后停止轮询
- if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
- console.log('Server is up, stop polling.');
- clearInterval(intervalId);
-
- setTimeout(() => {
- // 服务器启动后,立即执行一次cron任务
- executeCronJob();
- }, 3000);
-
- // 然后设置每小时执行一次cron任务
- setInterval(() => {
- executeCronJob();
- }, 60 * 60 * 1000); // 每小时执行一次
-
- // 显示服务状态
- console.log('====================================');
- console.log(`✅ Next.js服务运行在: http://${hostname}:${httpPort}`);
- console.log(`✅ WebSocket服务运行在: ws://${hostname}:${wsPort}`);
- console.log('====================================');
- }
- });
-
- req.setTimeout(2000, () => {
- req.destroy();
- });
-
- req.on('error', () => {
- // 忽略连接错误,继续轮询
- });
- }, 1000);
-}
-
-// 执行cron任务的函数
-function executeCronJob() {
- const httpPort = process.env.PORT || 3000;
- const hostname = process.env.HOSTNAME || 'localhost';
- const cronUrl = `http://${hostname}:${httpPort}/api/cron`;
-
- console.log(`Executing cron job: ${cronUrl}`);
-
- const req = http.get(cronUrl, (res) => {
- let data = '';
-
- res.on('data', (chunk) => {
- data += chunk;
- });
-
- res.on('end', () => {
- if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
- console.log('Cron job executed successfully:', data);
- } else {
- console.error('Cron job failed:', res.statusCode, data);
- }
- });
- });
-
- req.on('error', (err) => {
- console.error('Error executing cron job:', err);
- });
-
- req.setTimeout(30000, () => {
- console.error('Cron job timeout');
- req.destroy();
- });
-}
-
-// 如果直接运行此文件,设置任务
-if (require.main === module) {
- // 延迟启动任务,等待服务器完全启动
- setTimeout(() => {
- setupServerTasks();
- }, 5000);
-}
-
-
-
-
-
-
diff --git a/production.js b/production.js
deleted file mode 100644
index b99fb50..0000000
--- a/production.js
+++ /dev/null
@@ -1,178 +0,0 @@
-/**
- * 生产模式下的服务器入口
- * 使用 NODE_ENV=production node production.js 来启动
- */
-process.env.NODE_ENV = 'production';
-
-const { createServer } = require('http');
-const { parse } = require('url');
-const next = require('next');
-const path = require('path');
-const http = require('http');
-const { createWebSocketServer } = require('./websocket');
-
-// 调用 generate-manifest.js 生成 manifest.json
-function generateManifest() {
- console.log('Generating manifest.json for Docker deployment...');
-
- try {
- const generateManifestScript = path.join(
- __dirname,
- 'scripts',
- 'generate-manifest.js'
- );
- require(generateManifestScript);
- } catch (error) {
- console.error('❌ Error calling generate-manifest.js:', error);
- throw error;
- }
-}
-
-// 生成manifest
-generateManifest();
-
-const hostname = process.env.HOSTNAME || '0.0.0.0';
-const port = process.env.PORT || 3000;
-
-// 在生产模式下初始化 Next.js
-const app = next({
- dev: false,
- hostname,
- port
-});
-
-const handle = app.getRequestHandler();
-
-app.prepare().then(() => {
- const server = createServer(async (req, res) => {
- try {
- // 检查是否是WebSocket升级请求,如果是则跳过Next.js处理
- const upgrade = req.headers.upgrade;
- if (upgrade && upgrade.toLowerCase() === 'websocket') {
- // 不处理WebSocket升级请求,让upgrade事件处理器处理
- return;
- }
-
- // 使用Next.js处理所有非WebSocket请求
- const parsedUrl = parse(req.url, true);
- await handle(req, res, parsedUrl);
- } catch (err) {
- console.error('处理请求时出错:', req.url, err);
- res.statusCode = 500;
- res.end('内部服务器错误');
- }
- });
-
- // 初始化 WebSocket 服务器
- const wss = createWebSocketServer();
-
- // 将 WebSocket 服务器实例存储到全局对象中,供 API 路由使用
- global.wss = wss;
-
- // 使用WeakSet来跟踪已处理的socket,避免重复处理
- const handledSockets = new WeakSet();
-
- // 处理 WebSocket 升级请求
- server.on('upgrade', (request, socket, head) => {
- // 如果socket已经被处理过,直接返回
- if (handledSockets.has(socket)) {
- return;
- }
-
- const pathname = parse(request.url).pathname;
-
- if (pathname === '/ws') {
- console.log('处理 WebSocket 升级请求:', pathname);
-
- // 标记socket已被处理
- handledSockets.add(socket);
-
- // 处理WebSocket连接
- try {
- wss.handleUpgrade(request, socket, head, (ws) => {
- wss.emit('connection', ws, request);
- });
- } catch (error) {
- console.error('WebSocket升级错误:', error);
- socket.destroy();
- }
- } else {
- console.log('未知的升级请求路径:', pathname);
- // 不销毁socket,让它自然关闭
- }
- });
-
- // 启动服务器
- server.listen(port, (err) => {
- if (err) throw err;
- console.log(`> 服务已启动 (生产模式): http://${hostname}:${port}`);
- console.log(`> WebSocket 服务已启动: ws://${hostname}:${port}/ws`);
-
- // 设置服务器启动后的任务
- setupServerTasks();
- });
-});
-
-// 设置服务器启动后的任务
-function setupServerTasks() {
- // 每 1 秒轮询一次,直到请求成功
- const TARGET_URL = `http://${process.env.HOSTNAME || 'localhost'}:${process.env.PORT || 3000}/login`;
-
- const intervalId = setInterval(() => {
- console.log(`Fetching ${TARGET_URL} ...`);
-
- const req = http.get(TARGET_URL, (res) => {
- // 当返回 2xx 状态码时认为成功,然后停止轮询
- if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
- console.log('Server is up, stop polling.');
- clearInterval(intervalId);
-
- setTimeout(() => {
- // 服务器启动后,立即执行一次 cron 任务
- executeCronJob();
- }, 3000);
-
- // 然后设置每小时执行一次 cron 任务
- setInterval(() => {
- executeCronJob();
- }, 60 * 60 * 1000); // 每小时执行一次
- }
- });
-
- req.setTimeout(2000, () => {
- req.destroy();
- });
- }, 1000);
-}
-
-// 执行 cron 任务的函数
-function executeCronJob() {
- const cronUrl = `http://${process.env.HOSTNAME || 'localhost'}:${process.env.PORT || 3000}/api/cron`;
-
- console.log(`Executing cron job: ${cronUrl}`);
-
- const req = http.get(cronUrl, (res) => {
- let data = '';
-
- res.on('data', (chunk) => {
- data += chunk;
- });
-
- res.on('end', () => {
- if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
- console.log('Cron job executed successfully:', data);
- } else {
- console.error('Cron job failed:', res.statusCode, data);
- }
- });
- });
-
- req.on('error', (err) => {
- console.error('Error executing cron job:', err);
- });
-
- req.setTimeout(30000, () => {
- console.error('Cron job timeout');
- req.destroy();
- });
-}
diff --git a/public/sw.js b/public/sw.js
deleted file mode 100644
index c0fcd05..0000000
--- a/public/sw.js
+++ /dev/null
@@ -1 +0,0 @@
-if(!self.define){let e,a={};const s=(s,c)=>(s=new URL(s+".js",c).href,a[s]||new Promise(a=>{if("document"in self){const e=document.createElement("script");e.src=s,e.onload=a,document.head.appendChild(e)}else e=s,importScripts(s),a()}).then(()=>{let e=a[s];if(!e)throw new Error(`Module ${s} didn’t register its module`);return e}));self.define=(c,i)=>{const t=e||("document"in self?document.currentScript.src:"")||location.href;if(a[t])return;let n={};const r=e=>s(e,t),u={module:{uri:t},exports:n,require:r};a[t]=Promise.all(c.map(e=>u[e]||r(e))).then(e=>(i(...e),n))}}define(["./workbox-e9849328"],function(e){"use strict";importScripts(),self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"/_next/app-build-manifest.json",revision:"7e017214d7c68ca4aa9bbdb7879859e9"},{url:"/_next/static/SVgE5GKtb0zjUpb0Z6Iu5/_buildManifest.js",revision:"4740a4478df99a73dadc7052247a6d6d"},{url:"/_next/static/SVgE5GKtb0zjUpb0Z6Iu5/_ssgManifest.js",revision:"b6652df95db52feb4daf4eca35380933"},{url:"/_next/static/chunks/1214-239f55f0a9968ae6.js",revision:"239f55f0a9968ae6"},{url:"/_next/static/chunks/212-c92804cd5c36ccfe.js",revision:"c92804cd5c36ccfe"},{url:"/_next/static/chunks/260-96a9f42b8688c71a.js",revision:"96a9f42b8688c71a"},{url:"/_next/static/chunks/394-ed74bf23acf690cd.js",revision:"ed74bf23acf690cd"},{url:"/_next/static/chunks/4707-a33a49083c72c92d.js",revision:"a33a49083c72c92d"},{url:"/_next/static/chunks/5688-7cf3621a969b7c92.js",revision:"7cf3621a969b7c92"},{url:"/_next/static/chunks/569-6ef1a7bcb3c35760.js",revision:"6ef1a7bcb3c35760"},{url:"/_next/static/chunks/6247-0803ce791127ffc4.js",revision:"0803ce791127ffc4"},{url:"/_next/static/chunks/6837-0542749c23ed2959.js",revision:"0542749c23ed2959"},{url:"/_next/static/chunks/7422-b8e062ed75f815a0.js",revision:"b8e062ed75f815a0"},{url:"/_next/static/chunks/7678-2c39a82db7ab4d79.js",revision:"2c39a82db7ab4d79"},{url:"/_next/static/chunks/7809-e061e97228be14bd.js",revision:"e061e97228be14bd"},{url:"/_next/static/chunks/7870.7199854d4bfb7214.js",revision:"7199854d4bfb7214"},{url:"/_next/static/chunks/835-1311a5ac1bc1a551.js",revision:"1311a5ac1bc1a551"},{url:"/_next/static/chunks/861965c9-56382d4621d981d6.js",revision:"56382d4621d981d6"},{url:"/_next/static/chunks/8964-a123ccc1aaa9f25e.js",revision:"a123ccc1aaa9f25e"},{url:"/_next/static/chunks/app/_not-found/page-eaf37efff24851e5.js",revision:"eaf37efff24851e5"},{url:"/_next/static/chunks/app/admin/page-0f29387e2be4272e.js",revision:"0f29387e2be4272e"},{url:"/_next/static/chunks/app/api/admin/category/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/admin/config/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/admin/config_file/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/admin/config_subscription/fetch/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/admin/data_migration/export/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/admin/data_migration/import/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/admin/live/refresh/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/admin/live/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/admin/reset/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/admin/site/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/admin/source/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/admin/source/validate/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/admin/theme/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/admin/user/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/avatar/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/change-password/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/chat/conversations/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/chat/friend-requests/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/chat/friends/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/chat/messages/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/chat/online-users/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/chat/search-users/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/chat/send-message/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/cron/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/danmu/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/detail/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/douban/categories/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/douban/recommends/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/douban/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/favorites/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/health/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/image-proxy/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/live/channels/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/live/epg/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/live/precheck/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/live/sources/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/login/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/logout/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/machine-code/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/playrecords/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/proxy/key/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/proxy/logo/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/proxy/m3u8/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/proxy/segment/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/proxy/video/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/proxy/video/test/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/search/one/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/search/resources/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/search/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/search/suggestions/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/search/ws/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/searchhistory/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/server-config/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/shortdrama/categories/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/shortdrama/latest/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/shortdrama/list/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/shortdrama/parse/all/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/shortdrama/parse/batch/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/shortdrama/parse/single/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/shortdrama/recommend/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/shortdrama/search/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/skipconfigs/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/api/websocket/route-86f2c28a81077b9d.js",revision:"86f2c28a81077b9d"},{url:"/_next/static/chunks/app/douban/page-f54a581a7ad3f486.js",revision:"f54a581a7ad3f486"},{url:"/_next/static/chunks/app/layout-91dc4f35c822836a.js",revision:"91dc4f35c822836a"},{url:"/_next/static/chunks/app/live/page-5317e86b4e682269.js",revision:"5317e86b4e682269"},{url:"/_next/static/chunks/app/login/page-4cea8d8ecc9cdf94.js",revision:"4cea8d8ecc9cdf94"},{url:"/_next/static/chunks/app/page-7972ca67735ea7d5.js",revision:"7972ca67735ea7d5"},{url:"/_next/static/chunks/app/play/page-f7b5e4a15ca70bf8.js",revision:"f7b5e4a15ca70bf8"},{url:"/_next/static/chunks/app/search/page-2d08139976f3568c.js",revision:"2d08139976f3568c"},{url:"/_next/static/chunks/app/shortdrama/page-103d01c7dd76fc57.js",revision:"103d01c7dd76fc57"},{url:"/_next/static/chunks/app/warning/page-7e49052845300dc2.js",revision:"7e49052845300dc2"},{url:"/_next/static/chunks/deb030d4-c5209a2ceb93feb3.js",revision:"c5209a2ceb93feb3"},{url:"/_next/static/chunks/framework-38d00379d7a41d4e.js",revision:"38d00379d7a41d4e"},{url:"/_next/static/chunks/main-80d1b284ea08d4a6.js",revision:"80d1b284ea08d4a6"},{url:"/_next/static/chunks/main-app-2a0dd42e958c98cd.js",revision:"2a0dd42e958c98cd"},{url:"/_next/static/chunks/pages/_app-31f2fea9e30ebfdd.js",revision:"31f2fea9e30ebfdd"},{url:"/_next/static/chunks/pages/_error-55c33958c98286e9.js",revision:"55c33958c98286e9"},{url:"/_next/static/chunks/polyfills-42372ed130431b0a.js",revision:"846118c33b2c0e922d7b3a7676f81f6f"},{url:"/_next/static/chunks/webpack-4638d3f2b0151932.js",revision:"4638d3f2b0151932"},{url:"/_next/static/css/086a977ee2ee8597.css",revision:"086a977ee2ee8597"},{url:"/_next/static/css/ccce47fdcedd91d2.css",revision:"ccce47fdcedd91d2"},{url:"/favicon.ico",revision:"27cf5167605c37fe0dc1624590c96b7a"},{url:"/icons/icon-192x192.png",revision:"e214d3db80d2eb6ef7a911b3f9433b81"},{url:"/icons/icon-256x256.png",revision:"a5cd7490191373b684033f1b33c9d9da"},{url:"/icons/icon-384x384.png",revision:"8540e29a41812989d2d5bf8f61e1e755"},{url:"/icons/icon-512x512.png",revision:"3e5597604f2c5d99d7ab62b02f6863d3"},{url:"/logo.png",revision:"3da704450f5c0807a0c8ad9840461521"},{url:"/manifest.json",revision:"46f3847d5e244fb9c639fa86902e15db"},{url:"/robots.txt",revision:"0483b37fb6cf7455cefe516197e39241"},{url:"/screenshot1.png",revision:"d7de3a25686c5b9c9d8c8675bc6109fc"},{url:"/screenshot2.png",revision:"b0b715a3018d2f02aba5d94762473bb6"},{url:"/screenshot3.png",revision:"7e454c28e110e291ee12f494fb3cf40c"}],{ignoreURLParametersMatching:[]}),e.cleanupOutdatedCaches(),e.registerRoute("/",new e.NetworkFirst({cacheName:"start-url",plugins:[{cacheWillUpdate:async({request:e,response:a,event:s,state:c})=>a&&"opaqueredirect"===a.type?new Response(a.body,{status:200,statusText:"OK",headers:a.headers}):a}]}),"GET"),e.registerRoute(/^https:\/\/fonts\.(?:gstatic)\.com\/.*/i,new e.CacheFirst({cacheName:"google-fonts-webfonts",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:31536e3})]}),"GET"),e.registerRoute(/^https:\/\/fonts\.(?:googleapis)\.com\/.*/i,new e.StaleWhileRevalidate({cacheName:"google-fonts-stylesheets",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:604800})]}),"GET"),e.registerRoute(/\.(?:eot|otf|ttc|ttf|woff|woff2|font.css)$/i,new e.StaleWhileRevalidate({cacheName:"static-font-assets",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:604800})]}),"GET"),e.registerRoute(/\.(?:jpg|jpeg|gif|png|svg|ico|webp)$/i,new e.StaleWhileRevalidate({cacheName:"static-image-assets",plugins:[new e.ExpirationPlugin({maxEntries:64,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\/_next\/image\?url=.+$/i,new e.StaleWhileRevalidate({cacheName:"next-image",plugins:[new e.ExpirationPlugin({maxEntries:64,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:mp3|wav|ogg)$/i,new e.CacheFirst({cacheName:"static-audio-assets",plugins:[new e.RangeRequestsPlugin,new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:mp4)$/i,new e.CacheFirst({cacheName:"static-video-assets",plugins:[new e.RangeRequestsPlugin,new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:js)$/i,new e.StaleWhileRevalidate({cacheName:"static-js-assets",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:css|less)$/i,new e.StaleWhileRevalidate({cacheName:"static-style-assets",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\/_next\/data\/.+\/.+\.json$/i,new e.StaleWhileRevalidate({cacheName:"next-data",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:json|xml|csv)$/i,new e.NetworkFirst({cacheName:"static-data-assets",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(({url:e})=>{if(!(self.origin===e.origin))return!1;const a=e.pathname;return!a.startsWith("/api/auth/")&&!!a.startsWith("/api/")},new e.NetworkFirst({cacheName:"apis",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:16,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(({url:e})=>{if(!(self.origin===e.origin))return!1;return!e.pathname.startsWith("/api/")},new e.NetworkFirst({cacheName:"others",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(({url:e})=>!(self.origin===e.origin),new e.NetworkFirst({cacheName:"cross-origin",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:3600})]}),"GET")});
diff --git a/public/workbox-e9849328.js b/public/workbox-e9849328.js
deleted file mode 100644
index 788fd6c..0000000
--- a/public/workbox-e9849328.js
+++ /dev/null
@@ -1 +0,0 @@
-define(["exports"],function(t){"use strict";try{self["workbox:core:6.5.4"]&&_()}catch(t){}const e=(t,...e)=>{let s=t;return e.length>0&&(s+=` :: ${JSON.stringify(e)}`),s};class s extends Error{constructor(t,s){super(e(t,s)),this.name=t,this.details=s}}try{self["workbox:routing:6.5.4"]&&_()}catch(t){}const n=t=>t&&"object"==typeof t?t:{handle:t};class r{constructor(t,e,s="GET"){this.handler=n(e),this.match=t,this.method=s}setCatchHandler(t){this.catchHandler=n(t)}}class i extends r{constructor(t,e,s){super(({url:e})=>{const s=t.exec(e.href);if(s&&(e.origin===location.origin||0===s.index))return s.slice(1)},e,s)}}class a{constructor(){this.t=new Map,this.i=new Map}get routes(){return this.t}addFetchListener(){self.addEventListener("fetch",t=>{const{request:e}=t,s=this.handleRequest({request:e,event:t});s&&t.respondWith(s)})}addCacheListener(){self.addEventListener("message",t=>{if(t.data&&"CACHE_URLS"===t.data.type){const{payload:e}=t.data,s=Promise.all(e.urlsToCache.map(e=>{"string"==typeof e&&(e=[e]);const s=new Request(...e);return this.handleRequest({request:s,event:t})}));t.waitUntil(s),t.ports&&t.ports[0]&&s.then(()=>t.ports[0].postMessage(!0))}})}handleRequest({request:t,event:e}){const s=new URL(t.url,location.href);if(!s.protocol.startsWith("http"))return;const n=s.origin===location.origin,{params:r,route:i}=this.findMatchingRoute({event:e,request:t,sameOrigin:n,url:s});let a=i&&i.handler;const o=t.method;if(!a&&this.i.has(o)&&(a=this.i.get(o)),!a)return;let c;try{c=a.handle({url:s,request:t,event:e,params:r})}catch(t){c=Promise.reject(t)}const h=i&&i.catchHandler;return c instanceof Promise&&(this.o||h)&&(c=c.catch(async n=>{if(h)try{return await h.handle({url:s,request:t,event:e,params:r})}catch(t){t instanceof Error&&(n=t)}if(this.o)return this.o.handle({url:s,request:t,event:e});throw n})),c}findMatchingRoute({url:t,sameOrigin:e,request:s,event:n}){const r=this.t.get(s.method)||[];for(const i of r){let r;const a=i.match({url:t,sameOrigin:e,request:s,event:n});if(a)return r=a,(Array.isArray(r)&&0===r.length||a.constructor===Object&&0===Object.keys(a).length||"boolean"==typeof a)&&(r=void 0),{route:i,params:r}}return{}}setDefaultHandler(t,e="GET"){this.i.set(e,n(t))}setCatchHandler(t){this.o=n(t)}registerRoute(t){this.t.has(t.method)||this.t.set(t.method,[]),this.t.get(t.method).push(t)}unregisterRoute(t){if(!this.t.has(t.method))throw new s("unregister-route-but-not-found-with-method",{method:t.method});const e=this.t.get(t.method).indexOf(t);if(!(e>-1))throw new s("unregister-route-route-not-registered");this.t.get(t.method).splice(e,1)}}let o;const c=()=>(o||(o=new a,o.addFetchListener(),o.addCacheListener()),o);function h(t,e,n){let a;if("string"==typeof t){const s=new URL(t,location.href);a=new r(({url:t})=>t.href===s.href,e,n)}else if(t instanceof RegExp)a=new i(t,e,n);else if("function"==typeof t)a=new r(t,e,n);else{if(!(t instanceof r))throw new s("unsupported-route-type",{moduleName:"workbox-routing",funcName:"registerRoute",paramName:"capture"});a=t}return c().registerRoute(a),a}try{self["workbox:strategies:6.5.4"]&&_()}catch(t){}const u={cacheWillUpdate:async({response:t})=>200===t.status||0===t.status?t:null},l={googleAnalytics:"googleAnalytics",precache:"precache-v2",prefix:"workbox",runtime:"runtime",suffix:"undefined"!=typeof registration?registration.scope:""},f=t=>[l.prefix,t,l.suffix].filter(t=>t&&t.length>0).join("-"),w=t=>t||f(l.precache),d=t=>t||f(l.runtime);function p(t,e){const s=new URL(t);for(const t of e)s.searchParams.delete(t);return s.href}class y{constructor(){this.promise=new Promise((t,e)=>{this.resolve=t,this.reject=e})}}const g=new Set;function m(t){return"string"==typeof t?new Request(t):t}class v{constructor(t,e){this.h={},Object.assign(this,e),this.event=e.event,this.u=t,this.l=new y,this.p=[],this.m=[...t.plugins],this.v=new Map;for(const t of this.m)this.v.set(t,{});this.event.waitUntil(this.l.promise)}async fetch(t){const{event:e}=this;let n=m(t);if("navigate"===n.mode&&e instanceof FetchEvent&&e.preloadResponse){const t=await e.preloadResponse;if(t)return t}const r=this.hasCallback("fetchDidFail")?n.clone():null;try{for(const t of this.iterateCallbacks("requestWillFetch"))n=await t({request:n.clone(),event:e})}catch(t){if(t instanceof Error)throw new s("plugin-error-request-will-fetch",{thrownErrorMessage:t.message})}const i=n.clone();try{let t;t=await fetch(n,"navigate"===n.mode?void 0:this.u.fetchOptions);for(const s of this.iterateCallbacks("fetchDidSucceed"))t=await s({event:e,request:i,response:t});return t}catch(t){throw r&&await this.runCallbacks("fetchDidFail",{error:t,event:e,originalRequest:r.clone(),request:i.clone()}),t}}async fetchAndCachePut(t){const e=await this.fetch(t),s=e.clone();return this.waitUntil(this.cachePut(t,s)),e}async cacheMatch(t){const e=m(t);let s;const{cacheName:n,matchOptions:r}=this.u,i=await this.getCacheKey(e,"read"),a=Object.assign(Object.assign({},r),{cacheName:n});s=await caches.match(i,a);for(const t of this.iterateCallbacks("cachedResponseWillBeUsed"))s=await t({cacheName:n,matchOptions:r,cachedResponse:s,request:i,event:this.event})||void 0;return s}async cachePut(t,e){const n=m(t);var r;await(r=0,new Promise(t=>setTimeout(t,r)));const i=await this.getCacheKey(n,"write");if(!e)throw new s("cache-put-with-no-response",{url:(a=i.url,new URL(String(a),location.href).href.replace(new RegExp(`^${location.origin}`),""))});var a;const o=await this.R(e);if(!o)return!1;const{cacheName:c,matchOptions:h}=this.u,u=await self.caches.open(c),l=this.hasCallback("cacheDidUpdate"),f=l?await async function(t,e,s,n){const r=p(e.url,s);if(e.url===r)return t.match(e,n);const i=Object.assign(Object.assign({},n),{ignoreSearch:!0}),a=await t.keys(e,i);for(const e of a)if(r===p(e.url,s))return t.match(e,n)}(u,i.clone(),["__WB_REVISION__"],h):null;try{await u.put(i,l?o.clone():o)}catch(t){if(t instanceof Error)throw"QuotaExceededError"===t.name&&await async function(){for(const t of g)await t()}(),t}for(const t of this.iterateCallbacks("cacheDidUpdate"))await t({cacheName:c,oldResponse:f,newResponse:o.clone(),request:i,event:this.event});return!0}async getCacheKey(t,e){const s=`${t.url} | ${e}`;if(!this.h[s]){let n=t;for(const t of this.iterateCallbacks("cacheKeyWillBeUsed"))n=m(await t({mode:e,request:n,event:this.event,params:this.params}));this.h[s]=n}return this.h[s]}hasCallback(t){for(const e of this.u.plugins)if(t in e)return!0;return!1}async runCallbacks(t,e){for(const s of this.iterateCallbacks(t))await s(e)}*iterateCallbacks(t){for(const e of this.u.plugins)if("function"==typeof e[t]){const s=this.v.get(e),n=n=>{const r=Object.assign(Object.assign({},n),{state:s});return e[t](r)};yield n}}waitUntil(t){return this.p.push(t),t}async doneWaiting(){let t;for(;t=this.p.shift();)await t}destroy(){this.l.resolve(null)}async R(t){let e=t,s=!1;for(const t of this.iterateCallbacks("cacheWillUpdate"))if(e=await t({request:this.request,response:e,event:this.event})||void 0,s=!0,!e)break;return s||e&&200!==e.status&&(e=void 0),e}}class R{constructor(t={}){this.cacheName=d(t.cacheName),this.plugins=t.plugins||[],this.fetchOptions=t.fetchOptions,this.matchOptions=t.matchOptions}handle(t){const[e]=this.handleAll(t);return e}handleAll(t){t instanceof FetchEvent&&(t={event:t,request:t.request});const e=t.event,s="string"==typeof t.request?new Request(t.request):t.request,n="params"in t?t.params:void 0,r=new v(this,{event:e,request:s,params:n}),i=this.q(r,s,e);return[i,this.D(i,r,s,e)]}async q(t,e,n){let r;await t.runCallbacks("handlerWillStart",{event:n,request:e});try{if(r=await this.U(e,t),!r||"error"===r.type)throw new s("no-response",{url:e.url})}catch(s){if(s instanceof Error)for(const i of t.iterateCallbacks("handlerDidError"))if(r=await i({error:s,event:n,request:e}),r)break;if(!r)throw s}for(const s of t.iterateCallbacks("handlerWillRespond"))r=await s({event:n,request:e,response:r});return r}async D(t,e,s,n){let r,i;try{r=await t}catch(i){}try{await e.runCallbacks("handlerDidRespond",{event:n,request:s,response:r}),await e.doneWaiting()}catch(t){t instanceof Error&&(i=t)}if(await e.runCallbacks("handlerDidComplete",{event:n,request:s,response:r,error:i}),e.destroy(),i)throw i}}function b(t){t.then(()=>{})}function q(){return q=Object.assign?Object.assign.bind():function(t){for(var e=1;e(t[e]=s,!0),has:(t,e)=>t instanceof IDBTransaction&&("done"===e||"store"===e)||e in t};function O(t){return t!==IDBDatabase.prototype.transaction||"objectStoreNames"in IDBTransaction.prototype?(U||(U=[IDBCursor.prototype.advance,IDBCursor.prototype.continue,IDBCursor.prototype.continuePrimaryKey])).includes(t)?function(...e){return t.apply(B(this),e),k(x.get(this))}:function(...e){return k(t.apply(B(this),e))}:function(e,...s){const n=t.call(B(this),e,...s);return I.set(n,e.sort?e.sort():[e]),k(n)}}function T(t){return"function"==typeof t?O(t):(t instanceof IDBTransaction&&function(t){if(L.has(t))return;const e=new Promise((e,s)=>{const n=()=>{t.removeEventListener("complete",r),t.removeEventListener("error",i),t.removeEventListener("abort",i)},r=()=>{e(),n()},i=()=>{s(t.error||new DOMException("AbortError","AbortError")),n()};t.addEventListener("complete",r),t.addEventListener("error",i),t.addEventListener("abort",i)});L.set(t,e)}(t),e=t,(D||(D=[IDBDatabase,IDBObjectStore,IDBIndex,IDBCursor,IDBTransaction])).some(t=>e instanceof t)?new Proxy(t,N):t);var e}function k(t){if(t instanceof IDBRequest)return function(t){const e=new Promise((e,s)=>{const n=()=>{t.removeEventListener("success",r),t.removeEventListener("error",i)},r=()=>{e(k(t.result)),n()},i=()=>{s(t.error),n()};t.addEventListener("success",r),t.addEventListener("error",i)});return e.then(e=>{e instanceof IDBCursor&&x.set(e,t)}).catch(()=>{}),E.set(e,t),e}(t);if(C.has(t))return C.get(t);const e=T(t);return e!==t&&(C.set(t,e),E.set(e,t)),e}const B=t=>E.get(t);const P=["get","getKey","getAll","getAllKeys","count"],M=["put","add","delete","clear"],W=new Map;function j(t,e){if(!(t instanceof IDBDatabase)||e in t||"string"!=typeof e)return;if(W.get(e))return W.get(e);const s=e.replace(/FromIndex$/,""),n=e!==s,r=M.includes(s);if(!(s in(n?IDBIndex:IDBObjectStore).prototype)||!r&&!P.includes(s))return;const i=async function(t,...e){const i=this.transaction(t,r?"readwrite":"readonly");let a=i.store;return n&&(a=a.index(e.shift())),(await Promise.all([a[s](...e),r&&i.done]))[0]};return W.set(e,i),i}N=(t=>q({},t,{get:(e,s,n)=>j(e,s)||t.get(e,s,n),has:(e,s)=>!!j(e,s)||t.has(e,s)}))(N);try{self["workbox:expiration:6.5.4"]&&_()}catch(t){}const S="cache-entries",K=t=>{const e=new URL(t,location.href);return e.hash="",e.href};class A{constructor(t){this._=null,this.L=t}I(t){const e=t.createObjectStore(S,{keyPath:"id"});e.createIndex("cacheName","cacheName",{unique:!1}),e.createIndex("timestamp","timestamp",{unique:!1})}C(t){this.I(t),this.L&&function(t,{blocked:e}={}){const s=indexedDB.deleteDatabase(t);e&&s.addEventListener("blocked",t=>e(t.oldVersion,t)),k(s).then(()=>{})}(this.L)}async setTimestamp(t,e){const s={url:t=K(t),timestamp:e,cacheName:this.L,id:this.N(t)},n=(await this.getDb()).transaction(S,"readwrite",{durability:"relaxed"});await n.store.put(s),await n.done}async getTimestamp(t){const e=await this.getDb(),s=await e.get(S,this.N(t));return null==s?void 0:s.timestamp}async expireEntries(t,e){const s=await this.getDb();let n=await s.transaction(S).store.index("timestamp").openCursor(null,"prev");const r=[];let i=0;for(;n;){const s=n.value;s.cacheName===this.L&&(t&&s.timestamp=e?r.push(n.value):i++),n=await n.continue()}const a=[];for(const t of r)await s.delete(S,t.id),a.push(t.url);return a}N(t){return this.L+"|"+K(t)}async getDb(){return this._||(this._=await function(t,e,{blocked:s,upgrade:n,blocking:r,terminated:i}={}){const a=indexedDB.open(t,e),o=k(a);return n&&a.addEventListener("upgradeneeded",t=>{n(k(a.result),t.oldVersion,t.newVersion,k(a.transaction),t)}),s&&a.addEventListener("blocked",t=>s(t.oldVersion,t.newVersion,t)),o.then(t=>{i&&t.addEventListener("close",()=>i()),r&&t.addEventListener("versionchange",t=>r(t.oldVersion,t.newVersion,t))}).catch(()=>{}),o}("workbox-expiration",1,{upgrade:this.C.bind(this)})),this._}}class F{constructor(t,e={}){this.O=!1,this.T=!1,this.k=e.maxEntries,this.B=e.maxAgeSeconds,this.P=e.matchOptions,this.L=t,this.M=new A(t)}async expireEntries(){if(this.O)return void(this.T=!0);this.O=!0;const t=this.B?Date.now()-1e3*this.B:0,e=await this.M.expireEntries(t,this.k),s=await self.caches.open(this.L);for(const t of e)await s.delete(t,this.P);this.O=!1,this.T&&(this.T=!1,b(this.expireEntries()))}async updateTimestamp(t){await this.M.setTimestamp(t,Date.now())}async isURLExpired(t){if(this.B){const e=await this.M.getTimestamp(t),s=Date.now()-1e3*this.B;return void 0===e||er||e&&e<0)throw new s("range-not-satisfiable",{size:r,end:n,start:e});let i,a;return void 0!==e&&void 0!==n?(i=e,a=n+1):void 0!==e&&void 0===n?(i=e,a=r):void 0!==n&&void 0===e&&(i=r-n,a=r),{start:i,end:a}}(i,r.start,r.end),o=i.slice(a.start,a.end),c=o.size,h=new Response(o,{status:206,statusText:"Partial Content",headers:e.headers});return h.headers.set("Content-Length",String(c)),h.headers.set("Content-Range",`bytes ${a.start}-${a.end-1}/${i.size}`),h}catch(t){return new Response("",{status:416,statusText:"Range Not Satisfiable"})}}function $(t,e){const s=e();return t.waitUntil(s),s}try{self["workbox:precaching:6.5.4"]&&_()}catch(t){}function z(t){if(!t)throw new s("add-to-cache-list-unexpected-type",{entry:t});if("string"==typeof t){const e=new URL(t,location.href);return{cacheKey:e.href,url:e.href}}const{revision:e,url:n}=t;if(!n)throw new s("add-to-cache-list-unexpected-type",{entry:t});if(!e){const t=new URL(n,location.href);return{cacheKey:t.href,url:t.href}}const r=new URL(n,location.href),i=new URL(n,location.href);return r.searchParams.set("__WB_REVISION__",e),{cacheKey:r.href,url:i.href}}class G{constructor(){this.updatedURLs=[],this.notUpdatedURLs=[],this.handlerWillStart=async({request:t,state:e})=>{e&&(e.originalRequest=t)},this.cachedResponseWillBeUsed=async({event:t,state:e,cachedResponse:s})=>{if("install"===t.type&&e&&e.originalRequest&&e.originalRequest instanceof Request){const t=e.originalRequest.url;s?this.notUpdatedURLs.push(t):this.updatedURLs.push(t)}return s}}}class V{constructor({precacheController:t}){this.cacheKeyWillBeUsed=async({request:t,params:e})=>{const s=(null==e?void 0:e.cacheKey)||this.W.getCacheKeyForURL(t.url);return s?new Request(s,{headers:t.headers}):t},this.W=t}}let J,Q;async function X(t,e){let n=null;if(t.url){n=new URL(t.url).origin}if(n!==self.location.origin)throw new s("cross-origin-copy-response",{origin:n});const r=t.clone(),i={headers:new Headers(r.headers),status:r.status,statusText:r.statusText},a=e?e(i):i,o=function(){if(void 0===J){const t=new Response("");if("body"in t)try{new Response(t.body),J=!0}catch(t){J=!1}J=!1}return J}()?r.body:await r.blob();return new Response(o,a)}class Y extends R{constructor(t={}){t.cacheName=w(t.cacheName),super(t),this.j=!1!==t.fallbackToNetwork,this.plugins.push(Y.copyRedirectedCacheableResponsesPlugin)}async U(t,e){const s=await e.cacheMatch(t);return s||(e.event&&"install"===e.event.type?await this.S(t,e):await this.K(t,e))}async K(t,e){let n;const r=e.params||{};if(!this.j)throw new s("missing-precache-entry",{cacheName:this.cacheName,url:t.url});{const s=r.integrity,i=t.integrity,a=!i||i===s;n=await e.fetch(new Request(t,{integrity:"no-cors"!==t.mode?i||s:void 0})),s&&a&&"no-cors"!==t.mode&&(this.A(),await e.cachePut(t,n.clone()))}return n}async S(t,e){this.A();const n=await e.fetch(t);if(!await e.cachePut(t,n.clone()))throw new s("bad-precaching-response",{url:t.url,status:n.status});return n}A(){let t=null,e=0;for(const[s,n]of this.plugins.entries())n!==Y.copyRedirectedCacheableResponsesPlugin&&(n===Y.defaultPrecacheCacheabilityPlugin&&(t=s),n.cacheWillUpdate&&e++);0===e?this.plugins.push(Y.defaultPrecacheCacheabilityPlugin):e>1&&null!==t&&this.plugins.splice(t,1)}}Y.defaultPrecacheCacheabilityPlugin={cacheWillUpdate:async({response:t})=>!t||t.status>=400?null:t},Y.copyRedirectedCacheableResponsesPlugin={cacheWillUpdate:async({response:t})=>t.redirected?await X(t):t};class Z{constructor({cacheName:t,plugins:e=[],fallbackToNetwork:s=!0}={}){this.F=new Map,this.H=new Map,this.$=new Map,this.u=new Y({cacheName:w(t),plugins:[...e,new V({precacheController:this})],fallbackToNetwork:s}),this.install=this.install.bind(this),this.activate=this.activate.bind(this)}get strategy(){return this.u}precache(t){this.addToCacheList(t),this.G||(self.addEventListener("install",this.install),self.addEventListener("activate",this.activate),this.G=!0)}addToCacheList(t){const e=[];for(const n of t){"string"==typeof n?e.push(n):n&&void 0===n.revision&&e.push(n.url);const{cacheKey:t,url:r}=z(n),i="string"!=typeof n&&n.revision?"reload":"default";if(this.F.has(r)&&this.F.get(r)!==t)throw new s("add-to-cache-list-conflicting-entries",{firstEntry:this.F.get(r),secondEntry:t});if("string"!=typeof n&&n.integrity){if(this.$.has(t)&&this.$.get(t)!==n.integrity)throw new s("add-to-cache-list-conflicting-integrities",{url:r});this.$.set(t,n.integrity)}if(this.F.set(r,t),this.H.set(r,i),e.length>0){const t=`Workbox is precaching URLs without revision info: ${e.join(", ")}\nThis is generally NOT safe. Learn more at https://bit.ly/wb-precache`;console.warn(t)}}}install(t){return $(t,async()=>{const e=new G;this.strategy.plugins.push(e);for(const[e,s]of this.F){const n=this.$.get(s),r=this.H.get(e),i=new Request(e,{integrity:n,cache:r,credentials:"same-origin"});await Promise.all(this.strategy.handleAll({params:{cacheKey:s},request:i,event:t}))}const{updatedURLs:s,notUpdatedURLs:n}=e;return{updatedURLs:s,notUpdatedURLs:n}})}activate(t){return $(t,async()=>{const t=await self.caches.open(this.strategy.cacheName),e=await t.keys(),s=new Set(this.F.values()),n=[];for(const r of e)s.has(r.url)||(await t.delete(r),n.push(r.url));return{deletedURLs:n}})}getURLsToCacheKeys(){return this.F}getCachedURLs(){return[...this.F.keys()]}getCacheKeyForURL(t){const e=new URL(t,location.href);return this.F.get(e.href)}getIntegrityForCacheKey(t){return this.$.get(t)}async matchPrecache(t){const e=t instanceof Request?t.url:t,s=this.getCacheKeyForURL(e);if(s){return(await self.caches.open(this.strategy.cacheName)).match(s)}}createHandlerBoundToURL(t){const e=this.getCacheKeyForURL(t);if(!e)throw new s("non-precached-url",{url:t});return s=>(s.request=new Request(t),s.params=Object.assign({cacheKey:e},s.params),this.strategy.handle(s))}}const tt=()=>(Q||(Q=new Z),Q);class et extends r{constructor(t,e){super(({request:s})=>{const n=t.getURLsToCacheKeys();for(const r of function*(t,{ignoreURLParametersMatching:e=[/^utm_/,/^fbclid$/],directoryIndex:s="index.html",cleanURLs:n=!0,urlManipulation:r}={}){const i=new URL(t,location.href);i.hash="",yield i.href;const a=function(t,e=[]){for(const s of[...t.searchParams.keys()])e.some(t=>t.test(s))&&t.searchParams.delete(s);return t}(i,e);if(yield a.href,s&&a.pathname.endsWith("/")){const t=new URL(a.href);t.pathname+=s,yield t.href}if(n){const t=new URL(a.href);t.pathname+=".html",yield t.href}if(r){const t=r({url:i});for(const e of t)yield e.href}}(s.url,e)){const e=n.get(r);if(e){return{cacheKey:e,integrity:t.getIntegrityForCacheKey(e)}}}},t.strategy)}}t.CacheFirst=class extends R{async U(t,e){let n,r=await e.cacheMatch(t);if(!r)try{r=await e.fetchAndCachePut(t)}catch(t){t instanceof Error&&(n=t)}if(!r)throw new s("no-response",{url:t.url,error:n});return r}},t.ExpirationPlugin=class{constructor(t={}){this.cachedResponseWillBeUsed=async({event:t,request:e,cacheName:s,cachedResponse:n})=>{if(!n)return null;const r=this.V(n),i=this.J(s);b(i.expireEntries());const a=i.updateTimestamp(e.url);if(t)try{t.waitUntil(a)}catch(t){}return r?n:null},this.cacheDidUpdate=async({cacheName:t,request:e})=>{const s=this.J(t);await s.updateTimestamp(e.url),await s.expireEntries()},this.X=t,this.B=t.maxAgeSeconds,this.Y=new Map,t.purgeOnQuotaError&&function(t){g.add(t)}(()=>this.deleteCacheAndMetadata())}J(t){if(t===d())throw new s("expire-custom-caches-only");let e=this.Y.get(t);return e||(e=new F(t,this.X),this.Y.set(t,e)),e}V(t){if(!this.B)return!0;const e=this.Z(t);if(null===e)return!0;return e>=Date.now()-1e3*this.B}Z(t){if(!t.headers.has("date"))return null;const e=t.headers.get("date"),s=new Date(e).getTime();return isNaN(s)?null:s}async deleteCacheAndMetadata(){for(const[t,e]of this.Y)await self.caches.delete(t),await e.delete();this.Y=new Map}},t.NetworkFirst=class extends R{constructor(t={}){super(t),this.plugins.some(t=>"cacheWillUpdate"in t)||this.plugins.unshift(u),this.tt=t.networkTimeoutSeconds||0}async U(t,e){const n=[],r=[];let i;if(this.tt){const{id:s,promise:a}=this.et({request:t,logs:n,handler:e});i=s,r.push(a)}const a=this.st({timeoutId:i,request:t,logs:n,handler:e});r.push(a);const o=await e.waitUntil((async()=>await e.waitUntil(Promise.race(r))||await a)());if(!o)throw new s("no-response",{url:t.url});return o}et({request:t,logs:e,handler:s}){let n;return{promise:new Promise(e=>{n=setTimeout(async()=>{e(await s.cacheMatch(t))},1e3*this.tt)}),id:n}}async st({timeoutId:t,request:e,logs:s,handler:n}){let r,i;try{i=await n.fetchAndCachePut(e)}catch(t){t instanceof Error&&(r=t)}return t&&clearTimeout(t),!r&&i||(i=await n.cacheMatch(e)),i}},t.RangeRequestsPlugin=class{constructor(){this.cachedResponseWillBeUsed=async({request:t,cachedResponse:e})=>e&&t.headers.has("range")?await H(t,e):e}},t.StaleWhileRevalidate=class extends R{constructor(t={}){super(t),this.plugins.some(t=>"cacheWillUpdate"in t)||this.plugins.unshift(u)}async U(t,e){const n=e.fetchAndCachePut(t).catch(()=>{});e.waitUntil(n);let r,i=await e.cacheMatch(t);if(i);else try{i=await n}catch(t){t instanceof Error&&(r=t)}if(!i)throw new s("no-response",{url:t.url,error:r});return i}},t.cleanupOutdatedCaches=function(){self.addEventListener("activate",t=>{const e=w();t.waitUntil((async(t,e="-precache-")=>{const s=(await self.caches.keys()).filter(s=>s.includes(e)&&s.includes(self.registration.scope)&&s!==t);return await Promise.all(s.map(t=>self.caches.delete(t))),s})(e).then(t=>{}))})},t.clientsClaim=function(){self.addEventListener("activate",()=>self.clients.claim())},t.precacheAndRoute=function(t,e){!function(t){tt().precache(t)}(t),function(t){const e=tt();h(new et(e,t))}(e)},t.registerRoute=h});
diff --git a/scripts/__tests__/dev-with-redis.test.js b/scripts/__tests__/dev-with-redis.test.js
index 3aa0402..8961a4a 100644
--- a/scripts/__tests__/dev-with-redis.test.js
+++ b/scripts/__tests__/dev-with-redis.test.js
@@ -31,7 +31,7 @@ describe('dev-with-redis helpers', () => {
});
});
- test('builds the Redis URL passed to the Next.js dev process', () => {
+ test('builds the Redis URL passed to the local dev process', () => {
expect(buildRedisUrl('6380')).toBe('redis://localhost:6380');
});
diff --git a/scripts/build-server.js b/scripts/build-server.js
new file mode 100644
index 0000000..0d59670
--- /dev/null
+++ b/scripts/build-server.js
@@ -0,0 +1,23 @@
+/* eslint-disable no-console */
+const esbuild = require('esbuild');
+
+async function main() {
+ await esbuild.build({
+ entryPoints: ['src/server/index.ts'],
+ outfile: 'dist/server/index.js',
+ bundle: true,
+ platform: 'node',
+ target: 'node24',
+ format: 'cjs',
+ sourcemap: true,
+ packages: 'external',
+ alias: {
+ '@': './src',
+ },
+ });
+}
+
+main().catch((error) => {
+ console.error(error);
+ process.exit(1);
+});
diff --git a/scripts/dev-with-redis.js b/scripts/dev-with-redis.js
index d12ca0a..c25d354 100644
--- a/scripts/dev-with-redis.js
+++ b/scripts/dev-with-redis.js
@@ -38,7 +38,7 @@ function isPortAvailable(port) {
});
}
-async function assertDevPortsAvailable(ports = [3000, 3001]) {
+async function assertDevPortsAvailable(ports = [3000]) {
const checks = await Promise.all(
ports.map(async (port) => ({
port,
@@ -136,16 +136,16 @@ function ensureRedis(config = getRedisConfig()) {
}
}
-function startNextDev(config = getRedisConfig()) {
+function startFastifyDev(config = getRedisConfig()) {
const redisUrl = buildRedisUrl(config.port);
const env = {
...process.env,
- NEXT_PUBLIC_STORAGE_TYPE: 'redis',
+ VITE_STORAGE_TYPE: 'redis',
REDIS_URL: redisUrl,
};
console.log(`Using Redis storage: ${redisUrl}`);
- console.log('Starting OrangeTV dev server...');
+ console.log('Starting OrangeTV Fastify/Vite dev server...');
const child = spawn('pnpm', ['dev'], {
env,
@@ -172,7 +172,7 @@ async function main() {
const config = getRedisConfig();
await assertDevPortsAvailable();
ensureRedis(config);
- startNextDev(config);
+ startFastifyDev(config);
} catch (error) {
console.error(error.message);
process.exit(1);
@@ -190,4 +190,5 @@ module.exports = {
getRedisConfig,
isPortAvailable,
resolveRedisAction,
+ startFastifyDev,
};
diff --git a/scripts/generate-manifest.js b/scripts/generate-manifest.js
index 9a3fc2e..fff7794 100644
--- a/scripts/generate-manifest.js
+++ b/scripts/generate-manifest.js
@@ -1,6 +1,6 @@
#!/usr/bin/env node
/* eslint-disable */
-// 根据 NEXT_PUBLIC_SITE_NAME 动态生成 manifest.json
+// 根据 VITE_SITE_NAME 动态生成 manifest.json
const fs = require('fs');
const path = require('path');
@@ -11,7 +11,7 @@ const publicDir = path.join(projectRoot, 'public');
const manifestPath = path.join(publicDir, 'manifest.json');
// 从环境变量获取站点名称
-const siteName = process.env.NEXT_PUBLIC_SITE_NAME || 'OrangeTV';
+const siteName = process.env.VITE_SITE_NAME || 'OrangeTV';
// manifest.json 模板
const manifestTemplate = {
diff --git a/server.js b/server.js
deleted file mode 100644
index 69b7caf..0000000
--- a/server.js
+++ /dev/null
@@ -1,70 +0,0 @@
-const { createServer } = require('http');
-const { parse } = require('url');
-const next = require('next');
-const { createWebSocketServer } = require('./websocket');
-
-const dev = process.env.NODE_ENV !== 'production';
-const hostname = 'localhost';
-const port = process.env.PORT || 3000;
-
-// 当使用Next.js时,需要预准备应用程序
-const app = next({ dev, hostname, port });
-const handle = app.getRequestHandler();
-
-app.prepare().then(() => {
- const server = createServer(async (req, res) => {
- try {
- // 使用Next.js处理所有请求
- const parsedUrl = parse(req.url, true);
- await handle(req, res, parsedUrl);
- } catch (err) {
- console.error('Error occurred handling', req.url, err);
- res.statusCode = 500;
- res.end('internal server error');
- }
- });
-
- // 初始化 WebSocket 服务器
- const wss = createWebSocketServer(server);
-
- // 将 WebSocket 服务器实例及相关方法存储到全局对象中,供 API 路由使用
- global.wss = wss;
-
- // 使用一个标志确保每个连接只被处理一次
- const upgradedSockets = new WeakSet();
-
- // 直接处理 WebSocket 升级请求
- server.on('upgrade', (request, socket, head) => {
- // 如果这个 socket 已经被处理过,就忽略它
- if (upgradedSockets.has(socket)) {
- return;
- }
-
- const pathname = parse(request.url).pathname;
-
- if (pathname === '/ws') {
- console.log('处理 WebSocket 升级请求:', pathname);
- try {
- // 标记这个 socket 已经被处理
- upgradedSockets.add(socket);
-
- wss.handleUpgrade(request, socket, head, (ws) => {
- wss.emit('connection', ws, request);
- });
- } catch (error) {
- console.error('WebSocket 升级处理错误:', error);
- socket.write('HTTP/1.1 500 Internal Server Error\r\n\r\n');
- socket.destroy();
- }
- } else {
- console.log('非 WebSocket 升级请求:', pathname);
- // Next.js 会自己处理这些请求,无需销毁 socket
- }
- });
-
- server.listen(port, (err) => {
- if (err) throw err;
- console.log(`> Ready on http://${hostname}:${port}`);
- console.log(`> WebSocket server ready on ws://${hostname}:${port}/ws`);
- });
-});
\ No newline at end of file
diff --git a/simple-dev.js b/simple-dev.js
deleted file mode 100644
index 622c72f..0000000
--- a/simple-dev.js
+++ /dev/null
@@ -1,54 +0,0 @@
-const { createServer } = require('http');
-const { parse } = require('url');
-const next = require('next');
-
-const dev = process.env.NODE_ENV !== 'production';
-const hostname = 'localhost';
-const port = 3000;
-const wsPort = 3001;
-
-// 启动独立WebSocket服务器
-console.log('🔌 启动 WebSocket 服务器...');
-const { createStandaloneWebSocketServer } = require('./standalone-websocket');
-createStandaloneWebSocketServer(wsPort);
-
-// 启动Next.js
-const app = next({ dev, hostname, port });
-const handle = app.getRequestHandler();
-
-app.prepare().then(() => {
- const server = createServer(async (req, res) => {
- try {
- const parsedUrl = parse(req.url, true);
- await handle(req, res, parsedUrl);
- } catch (err) {
- console.error('Error occurred handling', req.url, err);
- res.statusCode = 500;
- res.end('internal server error');
- }
- });
-
- server.listen(port, (err) => {
- if (err) throw err;
- console.log(`🌐 Next.js ready on http://${hostname}:${port}`);
- console.log(`🔌 WebSocket ready on ws://${hostname}:${wsPort}/ws`);
- console.log('\n✅ 开发环境已启动!按 Ctrl+C 停止服务器');
- });
-
- // 优雅关闭
- const cleanup = () => {
- console.log('\n🛑 正在关闭服务器...');
- server.close(() => {
- process.exit(0);
- });
- };
-
- process.on('SIGINT', cleanup);
- process.on('SIGTERM', cleanup);
-});
-
-
-
-
-
-
diff --git a/src/app/api/health/route.ts b/src/app/api/health/route.ts
deleted file mode 100644
index 68edb1d..0000000
--- a/src/app/api/health/route.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import { NextResponse } from 'next/server';
-
-export async function GET() {
- return NextResponse.json({
- status: 'ok',
- timestamp: new Date().toISOString(),
- message: 'Next.js server is running'
- });
-}
-
-
-
-
-
-
diff --git a/src/app/api/search/resources/route.ts b/src/app/api/search/resources/route.ts
deleted file mode 100644
index a4eb218..0000000
--- a/src/app/api/search/resources/route.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-/* eslint-disable no-console */
-
-import { NextRequest, NextResponse } from 'next/server';
-
-import { getAvailableApiSites } from '@/lib/config';
-
-export const runtime = 'nodejs';
-
-// OrionTV 兼容接口
-export async function GET(request: NextRequest) {
- console.log('request', request.url);
- try {
- const apiSites = await getAvailableApiSites();
-
- return NextResponse.json(apiSites);
- } catch (error) {
- return NextResponse.json({ error: '获取资源失败' }, { status: 500 });
- }
-}
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
deleted file mode 100644
index a4c2614..0000000
--- a/src/app/layout.tsx
+++ /dev/null
@@ -1,185 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-
-import type { Metadata, Viewport } from 'next';
-
-import './globals.css';
-
-import { getConfig } from '@/lib/config';
-
-import { GlobalErrorIndicator } from '../components/GlobalErrorIndicator';
-import { SiteProvider } from '../components/SiteProvider';
-import { ThemeProvider } from '../components/ThemeProvider';
-import { ToastProvider } from '../components/Toast';
-import GlobalThemeLoader from '../components/GlobalThemeLoader';
-
-export const dynamic = 'force-dynamic';
-
-// 动态生成 metadata,支持配置更新后的标题变化
-export async function generateMetadata(): Promise {
- const storageType = process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage';
- const config = await getConfig();
- let siteName = process.env.NEXT_PUBLIC_SITE_NAME || 'OrangeTV';
- if (storageType !== 'localstorage') {
- siteName = config.SiteConfig.SiteName;
- }
-
- return {
- title: siteName,
- description: '影视聚合',
- manifest: '/manifest.json',
- };
-}
-
-export const viewport: Viewport = {
- viewportFit: 'cover',
-};
-
-export default async function RootLayout({
- children,
-}: {
- children: React.ReactNode;
-}) {
- const storageType = process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage';
-
- let siteName = process.env.NEXT_PUBLIC_SITE_NAME || 'OrangeTV';
- let announcement =
- process.env.ANNOUNCEMENT ||
- '本网站仅提供影视信息搜索服务,所有内容均来自第三方网站。本站不存储任何视频资源,不对任何内容的准确性、合法性、完整性负责。';
-
- let doubanProxyType = process.env.NEXT_PUBLIC_DOUBAN_PROXY_TYPE || 'cmliussss-cdn-tencent';
- let doubanProxy = process.env.NEXT_PUBLIC_DOUBAN_PROXY || '';
- let doubanImageProxyType =
- process.env.NEXT_PUBLIC_DOUBAN_IMAGE_PROXY_TYPE || 'cmliussss-cdn-tencent';
- let doubanImageProxy = process.env.NEXT_PUBLIC_DOUBAN_IMAGE_PROXY || '';
- let disableYellowFilter =
- process.env.NEXT_PUBLIC_DISABLE_YELLOW_FILTER === 'true';
- let fluidSearch = process.env.NEXT_PUBLIC_FLUID_SEARCH !== 'false';
- let requireDeviceCode = process.env.NEXT_PUBLIC_REQUIRE_DEVICE_CODE !== 'false';
- let customCategories = [] as {
- name: string;
- type: 'movie' | 'tv';
- query: string;
- }[];
- if (storageType !== 'localstorage') {
- const config = await getConfig();
- siteName = config.SiteConfig.SiteName;
- announcement = config.SiteConfig.Announcement;
-
- doubanProxyType = config.SiteConfig.DoubanProxyType;
- doubanProxy = config.SiteConfig.DoubanProxy;
- doubanImageProxyType = config.SiteConfig.DoubanImageProxyType;
- doubanImageProxy = config.SiteConfig.DoubanImageProxy;
- disableYellowFilter = config.SiteConfig.DisableYellowFilter;
- customCategories = config.CustomCategories.filter(
- (category) => !category.disabled
- ).map((category) => ({
- name: category.name || '',
- type: category.type,
- query: category.query,
- }));
- fluidSearch = config.SiteConfig.FluidSearch;
- requireDeviceCode = config.SiteConfig.RequireDeviceCode;
- }
-
- // 将运行时配置注入到全局 window 对象,供客户端在运行时读取
- const runtimeConfig = {
- STORAGE_TYPE: process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage',
- DOUBAN_PROXY_TYPE: doubanProxyType,
- DOUBAN_PROXY: doubanProxy,
- DOUBAN_IMAGE_PROXY_TYPE: doubanImageProxyType,
- DOUBAN_IMAGE_PROXY: doubanImageProxy,
- DISABLE_YELLOW_FILTER: disableYellowFilter,
- CUSTOM_CATEGORIES: customCategories,
- FLUID_SEARCH: fluidSearch,
- REQUIRE_DEVICE_CODE: requireDeviceCode,
- };
-
- return (
-
-
-
-
- {/* 将配置序列化后直接写入脚本,浏览器端可通过 window.RUNTIME_CONFIG 获取 */}
- {/* eslint-disable-next-line @next/next/no-sync-scripts */}
-
-
- {/* 立即从缓存应用主题,避免闪烁 */}
- {/* eslint-disable-next-line @next/next/no-sync-scripts */}
-
-
-
-
-
-
-
-
- {children}
-
-
-
-
-
-
- );
-}
diff --git a/src/app/warning/page.tsx b/src/app/warning/page.tsx
deleted file mode 100644
index aad1339..0000000
--- a/src/app/warning/page.tsx
+++ /dev/null
@@ -1,11 +0,0 @@
-import { Metadata } from 'next';
-import WarningClient from './warning-client';
-
-export const metadata: Metadata = {
- title: '安全警告 - OrangeTV',
- description: '站点安全配置警告',
-};
-
-export default function WarningPage() {
- return ;
-}
diff --git a/src/client/AppImage.tsx b/src/client/AppImage.tsx
new file mode 100644
index 0000000..27d0156
--- /dev/null
+++ b/src/client/AppImage.tsx
@@ -0,0 +1,39 @@
+import type { ImgHTMLAttributes } from 'react';
+
+type AppImageProps = ImgHTMLAttributes & {
+ fill?: boolean;
+ priority?: boolean;
+ quality?: number;
+ onLoadingComplete?: (image: HTMLImageElement) => void;
+};
+
+export default function AppImage({
+ fill,
+ priority: _priority,
+ quality: _quality,
+ onLoadingComplete,
+ onLoad,
+ style,
+ ...props
+}: AppImageProps) {
+ return (
+
{
+ onLoad?.(event);
+ onLoadingComplete?.(event.currentTarget);
+ }}
+ style={{
+ ...(fill
+ ? {
+ position: 'absolute',
+ inset: 0,
+ width: '100%',
+ height: '100%',
+ }
+ : null),
+ ...style,
+ }}
+ />
+ );
+}
diff --git a/src/client/__tests__/module-interop.test.ts b/src/client/__tests__/module-interop.test.ts
new file mode 100644
index 0000000..f7dabab
--- /dev/null
+++ b/src/client/__tests__/module-interop.test.ts
@@ -0,0 +1,10 @@
+import { getDefaultExport } from '../module-interop';
+
+describe('getDefaultExport', () => {
+ it('unwraps nested default exports produced by bundled CommonJS modules', () => {
+ function Artplayer() {}
+ const module = { default: { default: Artplayer } };
+
+ expect(getDefaultExport(module)).toBe(Artplayer);
+ });
+});
diff --git a/src/app/globals.css b/src/client/globals.css
similarity index 95%
rename from src/app/globals.css
rename to src/client/globals.css
index 11224f4..25a031a 100644
--- a/src/app/globals.css
+++ b/src/client/globals.css
@@ -1,6 +1,6 @@
@import "tailwindcss";
-@config "../../tailwind.config.ts";
@import "@heroui/styles";
+@config "../../tailwind.config.ts";
:root {
color-scheme: light;
@@ -257,7 +257,21 @@ body {
}
.theme-input {
- @apply rounded-xl border border-border bg-field px-3 py-2 text-foreground placeholder:text-muted focus:border-accent focus:outline-none focus:ring-2 focus:ring-accent/20;
+ border: 1px solid rgb(var(--color-border));
+ border-radius: 0.75rem;
+ background: rgb(var(--color-surface));
+ color: rgb(var(--color-foreground));
+ padding: 0.5rem 0.75rem;
+ }
+
+ .theme-input::placeholder {
+ color: rgb(var(--color-muted));
+ }
+
+ .theme-input:focus {
+ border-color: rgb(var(--color-accent));
+ box-shadow: 0 0 0 2px rgb(var(--color-accent) / 0.2);
+ outline: none;
}
.video-card-hover {
diff --git a/src/client/main.tsx b/src/client/main.tsx
new file mode 100644
index 0000000..5ce616a
--- /dev/null
+++ b/src/client/main.tsx
@@ -0,0 +1,69 @@
+import '@/client/globals.css';
+
+import React, { Suspense } from 'react';
+import { createRoot } from 'react-dom/client';
+import { BrowserRouter, Route, Routes } from 'react-router-dom';
+
+import AdminPage from '@/pages/admin';
+import DoubanPage from '@/pages/douban';
+import HomePage from '@/pages/home';
+import LivePage from '@/pages/live';
+import LoginPage from '@/pages/login';
+import PlayPage from '@/pages/play';
+import SearchPage from '@/pages/search';
+import ShortDramaPage from '@/pages/shortdrama';
+import WarningPage from '@/pages/warning';
+import { GlobalErrorIndicator } from '@/components/GlobalErrorIndicator';
+import GlobalThemeLoader from '@/components/GlobalThemeLoader';
+import { SiteProvider } from '@/components/SiteProvider';
+import { ThemeProvider } from '@/components/ThemeProvider';
+import { ToastProvider } from '@/components/Toast';
+
+function Providers({ children }: { children: React.ReactNode }) {
+ const runtimeConfig = window.RUNTIME_CONFIG;
+
+ return (
+
+
+
+
+ {children}
+
+
+
+
+ );
+}
+
+function App() {
+ return (
+
+
+
+
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+
+
+
+
+ );
+}
+
+createRoot(document.getElementById('root')!).render();
diff --git a/src/client/module-interop.ts b/src/client/module-interop.ts
new file mode 100644
index 0000000..79b307b
--- /dev/null
+++ b/src/client/module-interop.ts
@@ -0,0 +1,14 @@
+export function getDefaultExport(module: unknown): T {
+ let value = module as { default?: unknown };
+
+ while (
+ value &&
+ typeof value === 'object' &&
+ 'default' in value &&
+ value.default
+ ) {
+ value = value.default as { default?: unknown };
+ }
+
+ return value as T;
+}
diff --git a/src/client/router.ts b/src/client/router.ts
new file mode 100644
index 0000000..163f45a
--- /dev/null
+++ b/src/client/router.ts
@@ -0,0 +1,27 @@
+import { useLocation, useNavigate, useSearchParams as useRRSearchParams } from 'react-router-dom';
+
+export function useRouter() {
+ const navigate = useNavigate();
+
+ return {
+ push: (href: string) => navigate(href),
+ replace: (href: string) => navigate(href, { replace: true }),
+ back: () => window.history.back(),
+ forward: () => window.history.forward(),
+ refresh: () => window.location.reload(),
+ };
+}
+
+export function usePathname() {
+ return useLocation().pathname;
+}
+
+export function useSearchParams() {
+ const [searchParams] = useRRSearchParams();
+ return searchParams;
+}
+
+export function redirect(href: string): never {
+ window.location.href = href;
+ throw new Error(`Redirected to ${href}`);
+}
diff --git a/src/client/runtime.d.ts b/src/client/runtime.d.ts
new file mode 100644
index 0000000..98d85c7
--- /dev/null
+++ b/src/client/runtime.d.ts
@@ -0,0 +1,19 @@
+export {};
+
+declare global {
+ interface Window {
+ RUNTIME_CONFIG?: {
+ STORAGE_TYPE?: string;
+ SITE_NAME?: string;
+ ANNOUNCEMENT?: string;
+ DOUBAN_PROXY_TYPE?: string;
+ DOUBAN_PROXY?: string;
+ DOUBAN_IMAGE_PROXY_TYPE?: string;
+ DOUBAN_IMAGE_PROXY?: string;
+ DISABLE_YELLOW_FILTER?: boolean;
+ CUSTOM_CATEGORIES?: { name: string; type: 'movie' | 'tv'; query: string }[];
+ FLUID_SEARCH?: boolean;
+ REQUIRE_DEVICE_CODE?: boolean;
+ };
+ }
+}
diff --git a/src/client/theme-provider.tsx b/src/client/theme-provider.tsx
new file mode 100644
index 0000000..00dd520
--- /dev/null
+++ b/src/client/theme-provider.tsx
@@ -0,0 +1,84 @@
+'use client';
+
+import * as React from 'react';
+
+type Theme = 'light' | 'dark' | 'system' | string;
+
+type ThemeContextValue = {
+ theme: Theme;
+ resolvedTheme: 'light' | 'dark';
+ setTheme: (theme: Theme) => void;
+};
+
+type ThemeProviderProps = {
+ children: React.ReactNode;
+ defaultTheme?: Theme;
+ enableSystem?: boolean;
+ attribute?: 'class' | string;
+ disableTransitionOnChange?: boolean;
+};
+
+const ThemeContext = React.createContext(null);
+const STORAGE_KEY = 'theme';
+
+export function ThemeProvider({
+ children,
+ defaultTheme = 'system',
+ enableSystem = true,
+ attribute = 'class',
+}: ThemeProviderProps) {
+ const [theme, setThemeState] = React.useState(() => {
+ if (typeof window === 'undefined') return defaultTheme;
+ return localStorage.getItem(STORAGE_KEY) || defaultTheme;
+ });
+ const [systemTheme, setSystemTheme] = React.useState<'light' | 'dark'>(() =>
+ getSystemTheme()
+ );
+ const resolvedTheme =
+ theme === 'system' && enableSystem ? systemTheme : theme === 'dark' ? 'dark' : 'light';
+
+ React.useEffect(() => {
+ if (!enableSystem) return;
+
+ const media = window.matchMedia('(prefers-color-scheme: dark)');
+ const onChange = () => setSystemTheme(media.matches ? 'dark' : 'light');
+ onChange();
+ media.addEventListener('change', onChange);
+ return () => media.removeEventListener('change', onChange);
+ }, [enableSystem]);
+
+ React.useEffect(() => {
+ const root = document.documentElement;
+ root.classList.remove('light', 'dark');
+ if (attribute === 'class') {
+ root.classList.add(resolvedTheme);
+ } else {
+ root.setAttribute(attribute, resolvedTheme);
+ }
+ root.style.colorScheme = resolvedTheme;
+ }, [attribute, resolvedTheme]);
+
+ const setTheme = React.useCallback((nextTheme: Theme) => {
+ localStorage.setItem(STORAGE_KEY, nextTheme);
+ setThemeState(nextTheme);
+ }, []);
+
+ return (
+
+ {children}
+
+ );
+}
+
+export function useTheme() {
+ const context = React.useContext(ThemeContext);
+ if (!context) {
+ throw new Error('useTheme must be used within ThemeProvider');
+ }
+ return context;
+}
+
+function getSystemTheme(): 'light' | 'dark' {
+ if (typeof window === 'undefined') return 'light';
+ return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
+}
diff --git a/src/components/EpisodeSelector.tsx b/src/components/EpisodeSelector.tsx
index 43e8945..8257142 100644
--- a/src/components/EpisodeSelector.tsx
+++ b/src/components/EpisodeSelector.tsx
@@ -1,6 +1,6 @@
-/* eslint-disable @next/next/no-img-element */
+/* eslint-disable react/no-unknown-property */
-import { useRouter } from 'next/navigation';
+import { useRouter } from '@/client/router';
import { Button, Chip, Spinner } from '@heroui/react';
import React, {
useCallback,
diff --git a/src/components/MobileActionSheet.tsx b/src/components/MobileActionSheet.tsx
index 3c5a720..292e4aa 100644
--- a/src/components/MobileActionSheet.tsx
+++ b/src/components/MobileActionSheet.tsx
@@ -1,5 +1,5 @@
import { Radio } from 'lucide-react';
-import Image from 'next/image';
+import Image from '@/client/AppImage';
import React from 'react';
import { Card, Chip } from '@heroui/react';
diff --git a/src/components/MobileBottomNav.tsx b/src/components/MobileBottomNav.tsx
index b1eb879..181b650 100644
--- a/src/components/MobileBottomNav.tsx
+++ b/src/components/MobileBottomNav.tsx
@@ -4,7 +4,7 @@
import { Clover, Film, Home, Star, Tv } from 'lucide-react';
import { Button, Card, ScrollShadow } from '@heroui/react';
-import { usePathname, useRouter } from 'next/navigation';
+import { usePathname, useRouter } from '@/client/router';
import { useEffect, useState } from 'react';
interface MobileBottomNavProps {
diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx
index db7db44..a74d8c2 100644
--- a/src/components/Sidebar.tsx
+++ b/src/components/Sidebar.tsx
@@ -12,8 +12,8 @@ import {
Star,
Tv,
} from 'lucide-react';
-import Image from 'next/image';
-import { usePathname, useRouter, useSearchParams } from 'next/navigation';
+import Image from '@/client/AppImage';
+import { usePathname, useRouter, useSearchParams } from '@/client/router';
import { Button, Card, Link as HeroLink, Separator, Tooltip } from '@heroui/react';
import {
createContext,
diff --git a/src/components/ThemeProvider.tsx b/src/components/ThemeProvider.tsx
index 4ec0be5..80a7a02 100644
--- a/src/components/ThemeProvider.tsx
+++ b/src/components/ThemeProvider.tsx
@@ -1,18 +1 @@
-'use client';
-
-import type { ThemeProviderProps } from 'next-themes';
-import { ThemeProvider as NextThemesProvider } from 'next-themes';
-import * as React from 'react';
-
-export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
- return (
-
- {children}
-
- );
-}
+export { ThemeProvider, useTheme } from '@/client/theme-provider';
diff --git a/src/components/ThemeToggle.tsx b/src/components/ThemeToggle.tsx
index 40d2da8..6d89d66 100644
--- a/src/components/ThemeToggle.tsx
+++ b/src/components/ThemeToggle.tsx
@@ -3,8 +3,8 @@
'use client';
import { Moon, Sun } from 'lucide-react';
-import { usePathname } from 'next/navigation';
-import { useTheme } from 'next-themes';
+import { usePathname } from '@/client/router';
+import { useTheme } from '@/client/theme-provider';
import { useEffect, useState } from 'react';
import { AppIconButton } from './ui/HeroPrimitives';
diff --git a/src/components/UserMenu.tsx b/src/components/UserMenu.tsx
index 3fb0052..241330c 100644
--- a/src/components/UserMenu.tsx
+++ b/src/components/UserMenu.tsx
@@ -23,8 +23,8 @@ import {
User,
Upload,
} from 'lucide-react';
-import Image from 'next/image';
-import { useRouter } from 'next/navigation';
+import Image from '@/client/AppImage';
+import { useRouter } from '@/client/router';
import { useEffect, useRef, useState } from 'react';
import ReactCrop, { Crop, PercentCrop, PixelCrop } from 'react-image-crop';
import 'react-image-crop/dist/ReactCrop.css';
diff --git a/src/components/VideoCard.tsx b/src/components/VideoCard.tsx
index 352f845..a6e9a0e 100644
--- a/src/components/VideoCard.tsx
+++ b/src/components/VideoCard.tsx
@@ -9,7 +9,6 @@ import {
Trash2,
} from 'lucide-react';
import {
- Badge,
Button,
Card,
Chip,
@@ -17,8 +16,8 @@ import {
ProgressBar,
Tooltip,
} from '@heroui/react';
-import Image from 'next/image';
-import { useRouter } from 'next/navigation';
+import Image from '@/client/AppImage';
+import { useRouter } from '@/client/router';
import React, {
forwardRef,
memo,
@@ -478,6 +477,14 @@ const VideoCard = forwardRef(
return configs[from] || configs.search;
}, [from, isAggregate, douban_id, rate]);
+ const coverBadgeClass =
+ 'pointer-events-none inline-flex h-7 min-w-11 max-w-[calc(100%-1rem)] items-center justify-center rounded-full border border-white/20 bg-black/70 px-2.5 text-[12px] font-semibold leading-none tracking-normal text-white shadow-[0_6px_18px_rgba(0,0,0,0.35)] backdrop-blur-md';
+ const hasYearBadge =
+ config.showYear &&
+ actualYear &&
+ actualYear !== 'unknown' &&
+ actualYear.trim() !== '';
+
// 移动端操作菜单配置
const mobileActions = useMemo(() => {
const actions = [];
@@ -835,14 +842,9 @@ const VideoCard = forwardRef(
)}
{/* 年份徽章 */}
- {config.showYear &&
- actualYear &&
- actualYear !== 'unknown' &&
- actualYear.trim() !== '' && (
- (
return false;
}}
>
- {actualYear}
-
+ {actualYear}
+
)}
{/* 徽章 */}
{config.showRating && rate && (
- (
return false;
}}
>
- {rate}
-
+ {rate}
+
)}
{actualEpisodes && actualEpisodes > 1 && (
- (
return false;
}}
>
-
- {currentEpisode
- ? `${currentEpisode}/${actualEpisodes}`
- : actualEpisodes}
-
-
+ {currentEpisode
+ ? `${currentEpisode}/${actualEpisodes}`
+ : actualEpisodes}
+
)}
{/* 豆瓣链接 */}
@@ -920,7 +915,7 @@ const VideoCard = forwardRef(
target='_blank'
rel='noopener noreferrer'
onClick={(e) => e.stopPropagation()}
- className='absolute top-2 left-2 opacity-0 -translate-x-2 transition-all duration-300 ease-in-out delay-100 sm:group-hover:opacity-100 sm:group-hover:translate-x-0'
+ className={`absolute left-2 ${hasYearBadge ? 'top-11' : 'top-2'} opacity-0 -translate-x-2 transition-all duration-300 ease-in-out delay-100 sm:group-hover:opacity-100 sm:group-hover:translate-x-0`}
style={
{
WebkitUserSelect: 'none',
@@ -980,10 +975,8 @@ const VideoCard = forwardRef(
} as React.CSSProperties
}
>
- (
return false;
}}
>
- {sourceCount}
-
+ {sourceCount}
+
{/* 播放源详情悬浮框 */}
{(() => {
diff --git a/src/components/__tests__/HiddenFeOptions.test.tsx b/src/components/__tests__/HiddenFeOptions.test.tsx
index 828e3f7..4557407 100644
--- a/src/components/__tests__/HiddenFeOptions.test.tsx
+++ b/src/components/__tests__/HiddenFeOptions.test.tsx
@@ -4,15 +4,15 @@ import MobileBottomNav from '../MobileBottomNav';
import Sidebar from '../Sidebar';
import { ThemeToggle } from '../ThemeToggle';
-const push = jest.fn();
+const mockPush = jest.fn();
-jest.mock('next/navigation', () => ({
+jest.mock('@/client/router', () => ({
usePathname: () => '/',
- useRouter: () => ({ push }),
+ useRouter: () => ({ push: mockPush }),
useSearchParams: () => new URLSearchParams(),
}));
-jest.mock('next-themes', () => ({
+jest.mock('@/client/theme-provider', () => ({
useTheme: () => ({
resolvedTheme: 'dark',
setTheme: jest.fn(),
@@ -25,7 +25,7 @@ jest.mock('../ChatModal', () => ({
describe('hidden front-end options', () => {
beforeEach(() => {
- push.mockClear();
+ mockPush.mockClear();
localStorage.clear();
});
diff --git a/src/lib/auth.ts b/src/lib/auth.ts
index c3c244d..6333572 100644
--- a/src/lib/auth.ts
+++ b/src/lib/auth.ts
@@ -1,7 +1,7 @@
-import { NextRequest } from 'next/server';
+import type { AppRequest } from '@/server/web';
// 从cookie获取认证信息 (服务端使用)
-export function getAuthInfoFromCookie(request: NextRequest): {
+export function getAuthInfoFromCookie(request: AppRequest): {
password?: string;
username?: string;
signature?: string;
diff --git a/src/lib/config.ts b/src/lib/config.ts
index 43e9119..3d70d8d 100644
--- a/src/lib/config.ts
+++ b/src/lib/config.ts
@@ -225,25 +225,25 @@ async function getInitConfig(configFile: string, subConfig: {
ConfigFile: configFile,
ConfigSubscribtion: subConfig,
SiteConfig: {
- SiteName: process.env.NEXT_PUBLIC_SITE_NAME || 'OrangeTV',
+ SiteName: process.env.VITE_SITE_NAME || 'OrangeTV',
Announcement:
process.env.ANNOUNCEMENT ||
'本网站仅提供影视信息搜索服务,所有内容均来自第三方网站。本站不存储任何视频资源,不对任何内容的准确性、合法性、完整性负责。',
SearchDownstreamMaxPage:
- Number(process.env.NEXT_PUBLIC_SEARCH_MAX_PAGE) || 5,
+ Number(process.env.VITE_SEARCH_MAX_PAGE) || 5,
SiteInterfaceCacheTime: cfgFile.cache_time || 7200,
DoubanProxyType:
- process.env.NEXT_PUBLIC_DOUBAN_PROXY_TYPE || 'cmliussss-cdn-tencent',
- DoubanProxy: process.env.NEXT_PUBLIC_DOUBAN_PROXY || '',
+ process.env.VITE_DOUBAN_PROXY_TYPE || 'cmliussss-cdn-tencent',
+ DoubanProxy: process.env.VITE_DOUBAN_PROXY || '',
DoubanImageProxyType:
- process.env.NEXT_PUBLIC_DOUBAN_IMAGE_PROXY_TYPE || 'cmliussss-cdn-tencent',
- DoubanImageProxy: process.env.NEXT_PUBLIC_DOUBAN_IMAGE_PROXY || '',
+ process.env.VITE_DOUBAN_IMAGE_PROXY_TYPE || 'cmliussss-cdn-tencent',
+ DoubanImageProxy: process.env.VITE_DOUBAN_IMAGE_PROXY || '',
DisableYellowFilter:
- process.env.NEXT_PUBLIC_DISABLE_YELLOW_FILTER === 'true',
+ process.env.VITE_DISABLE_YELLOW_FILTER === 'true',
FluidSearch:
- process.env.NEXT_PUBLIC_FLUID_SEARCH !== 'false',
+ process.env.VITE_FLUID_SEARCH !== 'false',
RequireDeviceCode:
- process.env.NEXT_PUBLIC_REQUIRE_DEVICE_CODE !== 'false',
+ process.env.VITE_REQUIRE_DEVICE_CODE !== 'false',
},
UserConfig: {
Users: [],
@@ -360,23 +360,23 @@ export function configSelfCheck(adminConfig: AdminConfig): AdminConfig {
// 确保 SiteConfig 及其属性存在
if (!adminConfig.SiteConfig) {
adminConfig.SiteConfig = {
- SiteName: process.env.NEXT_PUBLIC_SITE_NAME || 'OrangeTV',
+ SiteName: process.env.VITE_SITE_NAME || 'OrangeTV',
Announcement: process.env.ANNOUNCEMENT || '本网站仅提供影视信息搜索服务,所有内容均来自第三方网站。本站不存储任何视频资源,不对任何内容的准确性、合法性、完整性负责。',
- SearchDownstreamMaxPage: Number(process.env.NEXT_PUBLIC_SEARCH_MAX_PAGE) || 5,
+ SearchDownstreamMaxPage: Number(process.env.VITE_SEARCH_MAX_PAGE) || 5,
SiteInterfaceCacheTime: 7200,
- DoubanProxyType: process.env.NEXT_PUBLIC_DOUBAN_PROXY_TYPE || 'cmliussss-cdn-tencent',
- DoubanProxy: process.env.NEXT_PUBLIC_DOUBAN_PROXY || '',
- DoubanImageProxyType: process.env.NEXT_PUBLIC_DOUBAN_IMAGE_PROXY_TYPE || 'cmliussss-cdn-tencent',
- DoubanImageProxy: process.env.NEXT_PUBLIC_DOUBAN_IMAGE_PROXY || '',
- DisableYellowFilter: process.env.NEXT_PUBLIC_DISABLE_YELLOW_FILTER === 'true',
- FluidSearch: process.env.NEXT_PUBLIC_FLUID_SEARCH !== 'false',
- RequireDeviceCode: process.env.NEXT_PUBLIC_REQUIRE_DEVICE_CODE !== 'false',
+ DoubanProxyType: process.env.VITE_DOUBAN_PROXY_TYPE || 'cmliussss-cdn-tencent',
+ DoubanProxy: process.env.VITE_DOUBAN_PROXY || '',
+ DoubanImageProxyType: process.env.VITE_DOUBAN_IMAGE_PROXY_TYPE || 'cmliussss-cdn-tencent',
+ DoubanImageProxy: process.env.VITE_DOUBAN_IMAGE_PROXY || '',
+ DisableYellowFilter: process.env.VITE_DISABLE_YELLOW_FILTER === 'true',
+ FluidSearch: process.env.VITE_FLUID_SEARCH !== 'false',
+ RequireDeviceCode: process.env.VITE_REQUIRE_DEVICE_CODE !== 'false',
};
}
// 确保 RequireDeviceCode 属性存在
if (adminConfig.SiteConfig.RequireDeviceCode === undefined) {
- adminConfig.SiteConfig.RequireDeviceCode = process.env.NEXT_PUBLIC_REQUIRE_DEVICE_CODE !== 'false';
+ adminConfig.SiteConfig.RequireDeviceCode = process.env.VITE_REQUIRE_DEVICE_CODE !== 'false';
}
// 确保 ThemeConfig 存在
diff --git a/src/lib/db.ts b/src/lib/db.ts
index 82dffcb..1a77c20 100644
--- a/src/lib/db.ts
+++ b/src/lib/db.ts
@@ -8,7 +8,7 @@ import { UpstashRedisStorage } from './upstash.db';
// storage type 常量: 'localstorage' | 'redis' | 'upstash',默认 'localstorage'
const STORAGE_TYPE =
- (process.env.NEXT_PUBLIC_STORAGE_TYPE as
+ (process.env.VITE_STORAGE_TYPE as
| 'localstorage'
| 'redis'
| 'upstash'
diff --git a/src/middleware.ts b/src/middleware.ts
deleted file mode 100644
index b672d79..0000000
--- a/src/middleware.ts
+++ /dev/null
@@ -1,138 +0,0 @@
-/* eslint-disable no-console */
-
-import { NextRequest, NextResponse } from 'next/server';
-
-import { getAuthInfoFromCookie } from '@/lib/auth';
-
-export async function middleware(request: NextRequest) {
- const { pathname } = request.nextUrl;
-
- // 跳过不需要认证的路径
- if (shouldSkipAuth(pathname)) {
- return NextResponse.next();
- }
-
- const storageType = process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage';
-
- if (!process.env.PASSWORD) {
- // 如果没有设置密码,重定向到警告页面
- const warningUrl = new URL('/warning', request.url);
- return NextResponse.redirect(warningUrl);
- }
-
- // 从cookie获取认证信息
- const authInfo = getAuthInfoFromCookie(request);
-
- if (!authInfo) {
- return handleAuthFailure(request, pathname);
- }
-
- // localstorage模式:在middleware中完成验证
- if (storageType === 'localstorage') {
- if (!authInfo.password || authInfo.password !== process.env.PASSWORD) {
- return handleAuthFailure(request, pathname);
- }
- return NextResponse.next();
- }
-
- // 其他模式:只验证签名
- // 检查是否有用户名(非localStorage模式下密码不存储在cookie中)
- if (!authInfo.username || !authInfo.signature) {
- return handleAuthFailure(request, pathname);
- }
-
- // 验证签名(如果存在)
- if (authInfo.signature) {
- const isValidSignature = await verifySignature(
- authInfo.username,
- authInfo.signature,
- process.env.PASSWORD || ''
- );
-
- // 签名验证通过即可
- if (isValidSignature) {
- return NextResponse.next();
- }
- }
-
- // 签名验证失败或不存在签名
- return handleAuthFailure(request, pathname);
-}
-
-// 验证签名
-async function verifySignature(
- data: string,
- signature: string,
- secret: string
-): Promise {
- const encoder = new TextEncoder();
- const keyData = encoder.encode(secret);
- const messageData = encoder.encode(data);
-
- try {
- // 导入密钥
- const key = await crypto.subtle.importKey(
- 'raw',
- keyData,
- { name: 'HMAC', hash: 'SHA-256' },
- false,
- ['verify']
- );
-
- // 将十六进制字符串转换为Uint8Array
- const signatureBuffer = new Uint8Array(
- signature.match(/.{1,2}/g)?.map((byte) => parseInt(byte, 16)) || []
- );
-
- // 验证签名
- return await crypto.subtle.verify(
- 'HMAC',
- key,
- signatureBuffer,
- messageData
- );
- } catch (error) {
- console.error('签名验证失败:', error);
- return false;
- }
-}
-
-// 处理认证失败的情况
-function handleAuthFailure(
- request: NextRequest,
- pathname: string
-): NextResponse {
- // 如果是 API 路由,返回 401 状态码
- if (pathname.startsWith('/api')) {
- return new NextResponse('Unauthorized', { status: 401 });
- }
-
- // 否则重定向到登录页面
- const loginUrl = new URL('/login', request.url);
- // 保留完整的URL,包括查询参数
- const fullUrl = `${pathname}${request.nextUrl.search}`;
- loginUrl.searchParams.set('redirect', fullUrl);
- return NextResponse.redirect(loginUrl);
-}
-
-// 判断是否需要跳过认证的路径
-function shouldSkipAuth(pathname: string): boolean {
- const skipPaths = [
- '/_next',
- '/favicon.ico',
- '/robots.txt',
- '/manifest.json',
- '/icons/',
- '/logo.png',
- '/screenshot.png',
- ];
-
- return skipPaths.some((path) => pathname.startsWith(path));
-}
-
-// 配置middleware匹配规则
-export const config = {
- matcher: [
- '/((?!_next/static|_next/image|favicon.ico|login|warning|api/login|api/register|api/logout|api/cron|api/server-config).*)',
- ],
-};
diff --git a/src/app/admin/page.tsx b/src/pages/admin.tsx
similarity index 99%
rename from src/app/admin/page.tsx
rename to src/pages/admin.tsx
index 816d84f..268c3a3 100644
--- a/src/app/admin/page.tsx
+++ b/src/pages/admin.tsx
@@ -42,7 +42,7 @@ import { GripVertical, Palette } from 'lucide-react';
import { Alert, Avatar, Button, Card, Checkbox, Chip, Input, Label, Skeleton, Switch, Table, TextArea, TextField } from '@heroui/react';
import { Suspense, useCallback, useEffect, useMemo, useRef, useState } from 'react';
-import { AdminConfig, AdminConfigResult } from '../../lib/admin.types';
+import { AdminConfig, AdminConfigResult } from '@/lib/admin.types';
import { getAuthInfoFromBrowserCookie } from '@/lib/auth';
import DataMigration from '@/components/DataMigration';
diff --git a/src/app/douban/page.tsx b/src/pages/douban.tsx
similarity index 99%
rename from src/app/douban/page.tsx
rename to src/pages/douban.tsx
index 028fbce..7abe38c 100644
--- a/src/app/douban/page.tsx
+++ b/src/pages/douban.tsx
@@ -2,7 +2,7 @@
'use client';
-import { useSearchParams } from 'next/navigation';
+import { useSearchParams } from '@/client/router';
import { Card, EmptyState, Spinner } from '@heroui/react';
import { Suspense } from 'react';
import { useCallback, useEffect, useRef, useState } from 'react';
diff --git a/src/app/page.tsx b/src/pages/home.tsx
similarity index 100%
rename from src/app/page.tsx
rename to src/pages/home.tsx
diff --git a/src/app/live/page.tsx b/src/pages/live.tsx
similarity index 99%
rename from src/app/live/page.tsx
rename to src/pages/live.tsx
index 4de21cd..7a93c40 100644
--- a/src/app/live/page.tsx
+++ b/src/pages/live.tsx
@@ -1,4 +1,4 @@
-/* eslint-disable @typescript-eslint/ban-ts-comment, @typescript-eslint/no-explicit-any, react-hooks/exhaustive-deps, no-console, @next/next/no-img-element */
+/* eslint-disable @typescript-eslint/ban-ts-comment, @typescript-eslint/no-explicit-any, react-hooks/exhaustive-deps, no-console, react/no-unknown-property */
'use client';
@@ -6,7 +6,7 @@ import Artplayer from 'artplayer';
import Hls from 'hls.js';
import { Heart, Radio, Tv } from 'lucide-react';
import { Alert, Button, Card, Chip, EmptyState, ProgressBar, ScrollShadow, Spinner, Tabs } from '@heroui/react';
-import { useRouter, useSearchParams } from 'next/navigation';
+import { useRouter, useSearchParams } from '@/client/router';
import { Suspense, useEffect, useRef, useState } from 'react';
import {
diff --git a/src/app/login/page.tsx b/src/pages/login.tsx
similarity index 99%
rename from src/app/login/page.tsx
rename to src/pages/login.tsx
index 05e82c8..8ad1a59 100644
--- a/src/app/login/page.tsx
+++ b/src/pages/login.tsx
@@ -4,7 +4,7 @@
import { AlertCircle, CheckCircle, Shield } from 'lucide-react';
import { Alert, Checkbox, Form, Input, Label, Link, TextField } from '@heroui/react';
-import { useRouter, useSearchParams } from 'next/navigation';
+import { useRouter, useSearchParams } from '@/client/router';
import { Suspense, useEffect, useState } from 'react';
import { CURRENT_VERSION } from '@/lib/version';
diff --git a/src/app/play/page.tsx b/src/pages/play.tsx
similarity index 99%
rename from src/app/play/page.tsx
rename to src/pages/play.tsx
index 448fc19..d33ae65 100644
--- a/src/app/play/page.tsx
+++ b/src/pages/play.tsx
@@ -1,13 +1,14 @@
-/* eslint-disable @typescript-eslint/ban-ts-comment, @typescript-eslint/no-explicit-any, react-hooks/exhaustive-deps, no-console, @next/next/no-img-element */
+/* eslint-disable @typescript-eslint/ban-ts-comment, @typescript-eslint/no-explicit-any, react-hooks/exhaustive-deps, no-console, react/no-unknown-property */
'use client';
// Artplayer 和 Hls 以及弹幕插件将动态加载
import { Heart } from 'lucide-react';
import { Alert, Button, Card, Chip, ProgressBar, Spinner } from '@heroui/react';
-import { useRouter, useSearchParams } from 'next/navigation';
+import { useRouter, useSearchParams } from '@/client/router';
import { Suspense, useEffect, useRef, useState } from 'react';
+import { getDefaultExport } from '@/client/module-interop';
import {
deleteFavorite,
deletePlayRecord,
@@ -161,9 +162,9 @@ function PlayPageClient() {
if (mounted) {
setDynamicDeps({
- Artplayer: ArtplayerModule.default,
- Hls: HlsModule.default,
- artplayerPluginDanmuku: DanmakuModule.default
+ Artplayer: getDefaultExport(ArtplayerModule),
+ Hls: getDefaultExport(HlsModule),
+ artplayerPluginDanmuku: getDefaultExport(DanmakuModule)
});
}
} catch (error) {
@@ -2409,7 +2410,7 @@ function PlayPageClient() {
artPlayerRef.current.on('video:timeupdate', () => {
const now = Date.now();
let interval = 5000;
- if (process.env.NEXT_PUBLIC_STORAGE_TYPE === 'upstash') {
+ if (window.RUNTIME_CONFIG?.STORAGE_TYPE === 'upstash') {
interval = 20000;
}
if (now - lastSaveTimeRef.current > interval) {
diff --git a/src/app/search/page.tsx b/src/pages/search.tsx
similarity index 98%
rename from src/app/search/page.tsx
rename to src/pages/search.tsx
index 55f35e4..ecae575 100644
--- a/src/app/search/page.tsx
+++ b/src/pages/search.tsx
@@ -12,7 +12,7 @@ import {
Switch,
Tooltip,
} from '@heroui/react';
-import { useRouter, useSearchParams } from 'next/navigation';
+import { useRouter, useSearchParams } from '@/client/router';
import React, { startTransition, Suspense, useEffect, useMemo, useRef, useState } from 'react';
import {
@@ -1092,7 +1092,7 @@ function SearchPageClient() {
搜索结果
{totalSources > 0 && useFluidSearch && (
- {completedSources}/{totalSources}
+ 来源 {completedSources}/{totalSources}
)}
{isLoading && useFluidSearch && (
@@ -1238,19 +1238,17 @@ function SearchPageClient() {
>
{item}
- {/* 删除按钮 */}
-
+
+
))}
diff --git a/src/app/shortdrama/page.tsx b/src/pages/shortdrama.tsx
similarity index 100%
rename from src/app/shortdrama/page.tsx
rename to src/pages/shortdrama.tsx
diff --git a/src/app/warning/warning-client.tsx b/src/pages/warning-client.tsx
similarity index 100%
rename from src/app/warning/warning-client.tsx
rename to src/pages/warning-client.tsx
diff --git a/src/pages/warning.tsx b/src/pages/warning.tsx
new file mode 100644
index 0000000..0fcceb8
--- /dev/null
+++ b/src/pages/warning.tsx
@@ -0,0 +1,5 @@
+import WarningClient from './warning-client';
+
+export default function WarningPage() {
+ return ;
+}
diff --git a/src/server/__tests__/env.test.ts b/src/server/__tests__/env.test.ts
new file mode 100644
index 0000000..0bc3d49
--- /dev/null
+++ b/src/server/__tests__/env.test.ts
@@ -0,0 +1,40 @@
+import fs from 'node:fs';
+import os from 'node:os';
+import path from 'node:path';
+
+import { loadEnvFiles } from '../env';
+
+describe('loadEnvFiles', () => {
+ const originalEnv = process.env;
+
+ beforeEach(() => {
+ jest.resetModules();
+ process.env = { ...originalEnv };
+ });
+
+ afterEach(() => {
+ process.env = originalEnv;
+ });
+
+ it('loads local env defaults without overriding existing process env', () => {
+ const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'orangetv-env-'));
+ fs.writeFileSync(
+ path.join(tmp, '.env.local'),
+ [
+ 'USERNAME=admin',
+ 'PASSWORD=orangetv-local-dev',
+ 'VITE_STORAGE_TYPE=localstorage',
+ ].join('\n')
+ );
+
+ delete process.env.USERNAME;
+ delete process.env.PASSWORD;
+ process.env.VITE_STORAGE_TYPE = 'redis';
+
+ loadEnvFiles({ cwd: tmp, nodeEnv: 'development' });
+
+ expect(process.env.USERNAME).toBe('admin');
+ expect(process.env.PASSWORD).toBe('orangetv-local-dev');
+ expect(process.env.VITE_STORAGE_TYPE).toBe('redis');
+ });
+});
diff --git a/src/server/__tests__/fastify-app.test.ts b/src/server/__tests__/fastify-app.test.ts
new file mode 100644
index 0000000..b694464
--- /dev/null
+++ b/src/server/__tests__/fastify-app.test.ts
@@ -0,0 +1,81 @@
+/**
+ * @jest-environment node
+ */
+
+import type { createApp as createAppType } from '@/server/app';
+
+describe('Fastify app shell', () => {
+ let createApp: typeof createAppType;
+
+ beforeAll(async () => {
+ const { Blob, File } = await import('node:buffer');
+ const { ReadableStream, TransformStream } = await import('node:stream/web');
+ const { MessageChannel, MessagePort } = await import('node:worker_threads');
+ Object.assign(globalThis, {
+ Blob,
+ DOMException: class DOMException extends Error {
+ constructor(message?: string, public name = 'DOMException') {
+ super(message);
+ }
+ },
+ File,
+ MessageChannel,
+ MessagePort,
+ ReadableStream,
+ TransformStream,
+ });
+ const { FormData, Headers, Request, Response } = await import('undici');
+ Object.assign(globalThis, { FormData, Headers, Request, Response });
+ const appModule = await import('@/server/app');
+ createApp = appModule.createApp;
+ });
+
+ beforeEach(() => {
+ process.env.PASSWORD = 'secret';
+ process.env.USERNAME = 'owner';
+ process.env.VITE_STORAGE_TYPE = 'redis';
+ process.env.REDIS_URL = 'redis://localhost:6379';
+ });
+
+ it('serves health and runtime config without authentication', async () => {
+ const app = await createApp({ dev: false, clientDist: null });
+
+ const health = await app.inject('/api/health');
+ expect(health.statusCode).toBe(200);
+ expect(health.json()).toMatchObject({
+ status: 'ok',
+ timestamp: expect.any(String),
+ });
+
+ const runtimeConfig = await app.inject('/runtime-config.js');
+ expect(runtimeConfig.statusCode).toBe(200);
+ expect(runtimeConfig.headers['content-type']).toContain('application/javascript');
+ expect(runtimeConfig.body).toContain('window.RUNTIME_CONFIG');
+ expect(runtimeConfig.body).toContain('"STORAGE_TYPE":"redis"');
+
+ await app.close();
+ });
+
+ it('redirects protected browser routes to login and serves the SPA when authenticated', async () => {
+ process.env.VITE_STORAGE_TYPE = 'localstorage';
+ const app = await createApp({ dev: false, clientDist: null });
+ const auth = encodeURIComponent(JSON.stringify({ password: 'secret', role: 'user' }));
+
+ const unauthenticated = await app.inject('/admin');
+ expect(unauthenticated.statusCode).toBe(302);
+ expect(unauthenticated.headers.location).toBe('/login?redirect=%2Fadmin');
+
+ const authenticated = await app.inject({
+ method: 'GET',
+ url: '/play?id=abc',
+ headers: {
+ cookie: `auth=${auth}`,
+ },
+ });
+ expect(authenticated.statusCode).toBe(200);
+ expect(authenticated.headers['content-type']).toContain('text/html');
+ expect(authenticated.body).toContain('');
+
+ await app.close();
+ });
+});
diff --git a/src/server/app.ts b/src/server/app.ts
new file mode 100644
index 0000000..b8ee319
--- /dev/null
+++ b/src/server/app.ts
@@ -0,0 +1,105 @@
+import fs from 'node:fs';
+import path from 'node:path';
+
+import fastifyCookie from '@fastify/cookie';
+import fastifyMiddie from '@fastify/middie';
+import fastifyStatic from '@fastify/static';
+import Fastify from 'fastify';
+import type { ViteDevServer } from 'vite';
+
+import { isAuthenticated, shouldSkipAuth } from './auth';
+import { renderRuntimeConfigScript } from './runtime-config';
+import { apiRoutes } from './routes';
+import { registerWebRouteModule } from './web-route';
+
+export interface CreateAppOptions {
+ dev?: boolean;
+ clientDist?: string | null;
+}
+
+export async function createApp(options: CreateAppOptions = {}) {
+ const app = Fastify({ logger: true });
+ const dev = options.dev ?? process.env.NODE_ENV !== 'production';
+ const clientDist =
+ options.clientDist === undefined
+ ? path.resolve(process.cwd(), 'dist/client')
+ : options.clientDist;
+ let vite: ViteDevServer | null = null;
+
+ await app.register(fastifyCookie);
+ await app.register(fastifyMiddie);
+
+ app.addHook('onRequest', async (request, reply) => {
+ const pathname = new URL(request.url, 'http://localhost').pathname;
+ if (shouldSkipAuth(pathname)) return;
+ if (await isAuthenticated(request)) return;
+
+ if (pathname.startsWith('/api')) {
+ reply.code(401).send('Unauthorized');
+ return reply;
+ }
+
+ const redirect = `${pathname}${new URL(request.url, 'http://localhost').search}`;
+ reply.redirect(`/login?redirect=${encodeURIComponent(redirect)}`);
+ return reply;
+ });
+
+ app.get('/runtime-config.js', async (_request, reply) => {
+ reply.type('application/javascript; charset=utf-8');
+ return renderRuntimeConfigScript();
+ });
+
+ for (const route of apiRoutes) {
+ registerWebRouteModule(app, route.path, route.module);
+ }
+
+ if (dev) {
+ const { createServer } = await import('vite');
+ vite = await createServer({
+ server: { middlewareMode: true },
+ appType: 'spa',
+ });
+ app.use((request, response, next) => {
+ const requestUrl = request.url || '/';
+ if (
+ requestUrl.startsWith('/api/') ||
+ requestUrl.startsWith('/runtime-config.js')
+ ) {
+ next();
+ return;
+ }
+ vite!.middlewares(request, response, next);
+ });
+ } else if (clientDist && fs.existsSync(clientDist)) {
+ await app.register(fastifyStatic, {
+ root: clientDist,
+ wildcard: false,
+ });
+ }
+
+ app.setNotFoundHandler(async (request, reply) => {
+ if (request.url.startsWith('/api/')) {
+ reply.code(404).send({ error: 'Not Found' });
+ return;
+ }
+
+ reply.type('text/html; charset=utf-8');
+
+ if (dev && vite) {
+ const template = fs.readFileSync(path.resolve(process.cwd(), 'index.html'), 'utf-8');
+ return vite.transformIndexHtml(request.url, template);
+ }
+
+ const indexPath =
+ clientDist && fs.existsSync(path.join(clientDist, 'index.html'))
+ ? path.join(clientDist, 'index.html')
+ : path.resolve(process.cwd(), 'index.html');
+ return fs.readFileSync(indexPath, 'utf-8');
+ });
+
+ app.addHook('onClose', async () => {
+ await vite?.close();
+ });
+
+ return app;
+}
diff --git a/src/server/auth-context.ts b/src/server/auth-context.ts
new file mode 100644
index 0000000..6130ab7
--- /dev/null
+++ b/src/server/auth-context.ts
@@ -0,0 +1,7 @@
+import type { FastifyRequest } from 'fastify';
+
+import { getAuthCookie } from './auth';
+
+export function getAuthContext(request: FastifyRequest) {
+ return getAuthCookie(request);
+}
diff --git a/src/server/auth.ts b/src/server/auth.ts
new file mode 100644
index 0000000..d9df29d
--- /dev/null
+++ b/src/server/auth.ts
@@ -0,0 +1,86 @@
+import type { FastifyRequest } from 'fastify';
+
+type AuthInfo = {
+ password?: string;
+ username?: string;
+ signature?: string;
+ timestamp?: number;
+ role?: 'owner' | 'admin' | 'user';
+};
+
+const PUBLIC_PREFIXES = [
+ '/api/login',
+ '/api/logout',
+ '/api/cron',
+ '/api/server-config',
+ '/api/health',
+ '/runtime-config.js',
+ '/assets/',
+ '/icons/',
+ '/favicon.ico',
+ '/robots.txt',
+ '/manifest.json',
+ '/logo.png',
+ '/screenshot.png',
+ '/sw.js',
+ '/workbox-',
+ '/login',
+ '/warning',
+];
+
+export function shouldSkipAuth(pathname: string) {
+ return PUBLIC_PREFIXES.some((prefix) => pathname.startsWith(prefix));
+}
+
+export function getAuthCookie(request: FastifyRequest): AuthInfo | null {
+ const authCookie = request.cookies?.auth;
+ if (!authCookie) return null;
+
+ try {
+ return JSON.parse(decodeURIComponent(authCookie));
+ } catch {
+ return null;
+ }
+}
+
+export async function isAuthenticated(request: FastifyRequest) {
+ if (!process.env.PASSWORD) return false;
+
+ const authInfo = getAuthCookie(request);
+ if (!authInfo) return false;
+
+ const storageType = process.env.VITE_STORAGE_TYPE || 'localstorage';
+ if (storageType === 'localstorage') {
+ return authInfo.password === process.env.PASSWORD;
+ }
+
+ if (!authInfo.username || !authInfo.signature) return false;
+ return verifySignature(
+ authInfo.username,
+ authInfo.signature,
+ process.env.PASSWORD
+ );
+}
+
+async function verifySignature(data: string, signature: string, secret: string) {
+ const encoder = new TextEncoder();
+ const keyData = encoder.encode(secret);
+ const messageData = encoder.encode(data);
+
+ try {
+ const key = await crypto.subtle.importKey(
+ 'raw',
+ keyData,
+ { name: 'HMAC', hash: 'SHA-256' },
+ false,
+ ['verify']
+ );
+ const signatureBuffer = new Uint8Array(
+ signature.match(/.{1,2}/g)?.map((byte) => parseInt(byte, 16)) || []
+ );
+
+ return crypto.subtle.verify('HMAC', key, signatureBuffer, messageData);
+ } catch {
+ return false;
+ }
+}
diff --git a/src/server/env.ts b/src/server/env.ts
new file mode 100644
index 0000000..535b66a
--- /dev/null
+++ b/src/server/env.ts
@@ -0,0 +1,60 @@
+import fs from 'node:fs';
+import path from 'node:path';
+
+type LoadEnvOptions = {
+ cwd?: string;
+ nodeEnv?: string;
+};
+
+export function loadEnvFiles(options: LoadEnvOptions = {}) {
+ const cwd = options.cwd || process.cwd();
+ const nodeEnv = options.nodeEnv || process.env.NODE_ENV || 'development';
+ const files = [
+ `.env.${nodeEnv}.local`,
+ nodeEnv === 'test' ? null : '.env.local',
+ `.env.${nodeEnv}`,
+ '.env',
+ ].filter(Boolean) as string[];
+
+ for (const file of files) {
+ loadEnvFile(path.join(cwd, file));
+ }
+}
+
+function loadEnvFile(filePath: string) {
+ if (!fs.existsSync(filePath)) return;
+
+ const content = fs.readFileSync(filePath, 'utf8');
+ for (const rawLine of content.split(/\r?\n/)) {
+ const parsed = parseEnvLine(rawLine);
+ if (!parsed) continue;
+
+ const [key, value] = parsed;
+ if (process.env[key] === undefined) {
+ process.env[key] = value;
+ }
+ }
+}
+
+function parseEnvLine(line: string): [string, string] | null {
+ const trimmed = line.trim();
+ if (!trimmed || trimmed.startsWith('#')) return null;
+
+ const match = trimmed.match(/^(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/);
+ if (!match) return null;
+
+ return [match[1], parseEnvValue(match[2])];
+}
+
+function parseEnvValue(value: string) {
+ const trimmed = value.trim();
+ if (
+ (trimmed.startsWith('"') && trimmed.endsWith('"')) ||
+ (trimmed.startsWith("'") && trimmed.endsWith("'"))
+ ) {
+ return trimmed.slice(1, -1);
+ }
+
+ const commentIndex = trimmed.indexOf(' #');
+ return commentIndex === -1 ? trimmed : trimmed.slice(0, commentIndex).trim();
+}
diff --git a/src/server/http.ts b/src/server/http.ts
new file mode 100644
index 0000000..39f23af
--- /dev/null
+++ b/src/server/http.ts
@@ -0,0 +1,11 @@
+import { AppResponse } from './web';
+
+export { AppResponse, type AppRequest } from './web';
+
+export function json(data: unknown, init: ResponseInit = {}) {
+ return AppResponse.json(data, init);
+}
+
+export function error(message: string, status = 500) {
+ return AppResponse.json({ error: message }, { status });
+}
diff --git a/src/server/index.ts b/src/server/index.ts
new file mode 100644
index 0000000..2115c77
--- /dev/null
+++ b/src/server/index.ts
@@ -0,0 +1,19 @@
+import { loadEnvFiles } from './env';
+
+loadEnvFiles();
+
+async function main() {
+ const { createApp } = await import('./app');
+ const app = await createApp({
+ dev: process.env.NODE_ENV !== 'production',
+ });
+ const port = Number(process.env.PORT || 3000);
+ const host = process.env.HOSTNAME || '0.0.0.0';
+
+ await app.listen({ port, host });
+}
+
+main().catch((error) => {
+ console.error(error);
+ process.exit(1);
+});
diff --git a/src/server/route-auth.ts b/src/server/route-auth.ts
new file mode 100644
index 0000000..31c1447
--- /dev/null
+++ b/src/server/route-auth.ts
@@ -0,0 +1,15 @@
+import { getAuthInfoFromCookie } from '@/lib/auth';
+
+import type { AppRequest } from './web';
+
+export function getRouteUsername(request: AppRequest) {
+ const authInfo = getAuthInfoFromCookie(request);
+ if (!authInfo) return null;
+
+ return (
+ authInfo.username ||
+ process.env.USERNAME ||
+ process.env.ADMIN_USERNAME ||
+ 'admin'
+ );
+}
diff --git a/src/app/api/admin/category/route.ts b/src/server/routes/api/admin/category/route.ts
similarity index 79%
rename from src/app/api/admin/category/route.ts
rename to src/server/routes/api/admin/category/route.ts
index 6fc2226..70a6a48 100644
--- a/src/app/api/admin/category/route.ts
+++ b/src/server/routes/api/admin/category/route.ts
@@ -1,12 +1,11 @@
/* eslint-disable @typescript-eslint/no-explicit-any,no-console */
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { getAuthInfoFromCookie } from '@/lib/auth';
import { getConfig } from '@/lib/config';
import { db } from '@/lib/db';
-export const runtime = 'nodejs';
// 支持的操作类型
type Action = 'add' | 'disable' | 'enable' | 'delete' | 'sort';
@@ -15,10 +14,10 @@ interface BaseBody {
action?: Action;
}
-export async function POST(request: NextRequest) {
- const storageType = process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage';
+export async function POST(request: AppRequest) {
+ const storageType = process.env.VITE_STORAGE_TYPE || 'localstorage';
if (storageType === 'localstorage') {
- return NextResponse.json(
+ return AppResponse.json(
{
error: '不支持本地存储进行管理员配置',
},
@@ -32,14 +31,14 @@ export async function POST(request: NextRequest) {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
+ return AppResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const username = authInfo.username;
// 基础校验
const ACTIONS: Action[] = ['add', 'disable', 'enable', 'delete', 'sort'];
if (!username || !action || !ACTIONS.includes(action)) {
- return NextResponse.json({ error: '参数格式错误' }, { status: 400 });
+ return AppResponse.json({ error: '参数格式错误' }, { status: 400 });
}
// 获取配置与存储
@@ -51,7 +50,7 @@ export async function POST(request: NextRequest) {
(u) => u.username === username
);
if (!userEntry || userEntry.role !== 'admin' || userEntry.banned) {
- return NextResponse.json({ error: '权限不足' }, { status: 401 });
+ return AppResponse.json({ error: '权限不足' }, { status: 401 });
}
}
@@ -63,7 +62,7 @@ export async function POST(request: NextRequest) {
query?: string;
};
if (!name || !type || !query) {
- return NextResponse.json({ error: '缺少必要参数' }, { status: 400 });
+ return AppResponse.json({ error: '缺少必要参数' }, { status: 400 });
}
// 检查是否已存在相同的查询和类型组合
if (
@@ -71,7 +70,7 @@ export async function POST(request: NextRequest) {
(c) => c.query === query && c.type === type
)
) {
- return NextResponse.json({ error: '该分类已存在' }, { status: 400 });
+ return AppResponse.json({ error: '该分类已存在' }, { status: 400 });
}
adminConfig.CustomCategories.push({
name,
@@ -88,7 +87,7 @@ export async function POST(request: NextRequest) {
type?: 'movie' | 'tv';
};
if (!query || !type)
- return NextResponse.json(
+ return AppResponse.json(
{ error: '缺少 query 或 type 参数' },
{ status: 400 }
);
@@ -96,7 +95,7 @@ export async function POST(request: NextRequest) {
(c) => c.query === query && c.type === type
);
if (!entry)
- return NextResponse.json({ error: '分类不存在' }, { status: 404 });
+ return AppResponse.json({ error: '分类不存在' }, { status: 404 });
entry.disabled = true;
break;
}
@@ -106,7 +105,7 @@ export async function POST(request: NextRequest) {
type?: 'movie' | 'tv';
};
if (!query || !type)
- return NextResponse.json(
+ return AppResponse.json(
{ error: '缺少 query 或 type 参数' },
{ status: 400 }
);
@@ -114,7 +113,7 @@ export async function POST(request: NextRequest) {
(c) => c.query === query && c.type === type
);
if (!entry)
- return NextResponse.json({ error: '分类不存在' }, { status: 404 });
+ return AppResponse.json({ error: '分类不存在' }, { status: 404 });
entry.disabled = false;
break;
}
@@ -124,7 +123,7 @@ export async function POST(request: NextRequest) {
type?: 'movie' | 'tv';
};
if (!query || !type)
- return NextResponse.json(
+ return AppResponse.json(
{ error: '缺少 query 或 type 参数' },
{ status: 400 }
);
@@ -132,10 +131,10 @@ export async function POST(request: NextRequest) {
(c) => c.query === query && c.type === type
);
if (idx === -1)
- return NextResponse.json({ error: '分类不存在' }, { status: 404 });
+ return AppResponse.json({ error: '分类不存在' }, { status: 404 });
const entry = adminConfig.CustomCategories[idx];
if (entry.from === 'config') {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '该分类不可删除' },
{ status: 400 }
);
@@ -146,7 +145,7 @@ export async function POST(request: NextRequest) {
case 'sort': {
const { order } = body as { order?: string[] };
if (!Array.isArray(order)) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '排序列表格式错误' },
{ status: 400 }
);
@@ -170,13 +169,13 @@ export async function POST(request: NextRequest) {
break;
}
default:
- return NextResponse.json({ error: '未知操作' }, { status: 400 });
+ return AppResponse.json({ error: '未知操作' }, { status: 400 });
}
// 持久化到存储
await db.saveAdminConfig(adminConfig);
- return NextResponse.json(
+ return AppResponse.json(
{ ok: true },
{
headers: {
@@ -186,7 +185,7 @@ export async function POST(request: NextRequest) {
);
} catch (error) {
console.error('分类管理操作失败:', error);
- return NextResponse.json(
+ return AppResponse.json(
{
error: '分类管理操作失败',
details: (error as Error).message,
diff --git a/src/app/api/admin/config/route.ts b/src/server/routes/api/admin/config/route.ts
similarity index 86%
rename from src/app/api/admin/config/route.ts
rename to src/server/routes/api/admin/config/route.ts
index 846bab7..0bdb726 100644
--- a/src/app/api/admin/config/route.ts
+++ b/src/server/routes/api/admin/config/route.ts
@@ -1,17 +1,16 @@
/* eslint-disable no-console */
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { AdminConfigResult } from '@/lib/admin.types';
import { getAuthInfoFromCookie } from '@/lib/auth';
import { getConfig } from '@/lib/config';
-export const runtime = 'nodejs';
-export async function GET(request: NextRequest) {
- const storageType = process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage';
+export async function GET(request: AppRequest) {
+ const storageType = process.env.VITE_STORAGE_TYPE || 'localstorage';
if (storageType === 'localstorage') {
- return NextResponse.json(
+ return AppResponse.json(
{
error: '不支持本地存储进行管理员配置',
},
@@ -55,7 +54,7 @@ export async function GET(request: NextRequest) {
Config: config,
};
- return NextResponse.json(result, {
+ return AppResponse.json(result, {
headers: {
'Cache-Control': 'no-store', // 管理员配置不缓存
},
@@ -77,7 +76,7 @@ export async function GET(request: NextRequest) {
};
console.log('返回公开配置给', userRole, ',包含主题配置:', !!publicConfig.ThemeConfig);
- return NextResponse.json(result, {
+ return AppResponse.json(result, {
headers: {
'Cache-Control': 'public, max-age=60', // 公开配置可以缓存1分钟
},
@@ -85,7 +84,7 @@ export async function GET(request: NextRequest) {
}
} catch (error) {
console.error('获取配置失败:', error);
- return NextResponse.json(
+ return AppResponse.json(
{
error: '获取配置失败',
details: (error as Error).message,
diff --git a/src/app/api/admin/config_file/route.ts b/src/server/routes/api/admin/config_file/route.ts
similarity index 81%
rename from src/app/api/admin/config_file/route.ts
rename to src/server/routes/api/admin/config_file/route.ts
index 26e6c35..a71ea46 100644
--- a/src/app/api/admin/config_file/route.ts
+++ b/src/server/routes/api/admin/config_file/route.ts
@@ -1,17 +1,16 @@
/* eslint-disable no-console,@typescript-eslint/no-explicit-any */
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { getAuthInfoFromCookie } from '@/lib/auth';
import { getConfig, refineConfig } from '@/lib/config';
import { db } from '@/lib/db';
-export const runtime = 'nodejs';
-export async function POST(request: NextRequest) {
- const storageType = process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage';
+export async function POST(request: AppRequest) {
+ const storageType = process.env.VITE_STORAGE_TYPE || 'localstorage';
if (storageType === 'localstorage') {
- return NextResponse.json(
+ return AppResponse.json(
{
error: '不支持本地存储进行管理员配置',
},
@@ -21,7 +20,7 @@ export async function POST(request: NextRequest) {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
+ return AppResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const username = authInfo.username;
@@ -31,7 +30,7 @@ export async function POST(request: NextRequest) {
// 仅站长可以修改配置文件
if (username !== process.env.USERNAME) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '权限不足,只有站长可以修改配置文件' },
{ status: 401 }
);
@@ -42,7 +41,7 @@ export async function POST(request: NextRequest) {
const { configFile, subscriptionUrl, autoUpdate, lastCheckTime } = body;
if (!configFile || typeof configFile !== 'string') {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '配置文件内容不能为空' },
{ status: 400 }
);
@@ -52,7 +51,7 @@ export async function POST(request: NextRequest) {
try {
JSON.parse(configFile);
} catch (e) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '配置文件格式错误,请检查 JSON 语法' },
{ status: 400 }
);
@@ -79,13 +78,13 @@ export async function POST(request: NextRequest) {
adminConfig = refineConfig(adminConfig);
// 更新配置文件
await db.saveAdminConfig(adminConfig);
- return NextResponse.json({
+ return AppResponse.json({
success: true,
message: '配置文件更新成功',
});
} catch (error) {
console.error('更新配置文件失败:', error);
- return NextResponse.json(
+ return AppResponse.json(
{
error: '更新配置文件失败',
details: (error as Error).message,
diff --git a/src/app/api/admin/config_subscription/fetch/route.ts b/src/server/routes/api/admin/config_subscription/fetch/route.ts
similarity index 76%
rename from src/app/api/admin/config_subscription/fetch/route.ts
rename to src/server/routes/api/admin/config_subscription/fetch/route.ts
index 1480691..de8c11c 100644
--- a/src/app/api/admin/config_subscription/fetch/route.ts
+++ b/src/server/routes/api/admin/config_subscription/fetch/route.ts
@@ -1,21 +1,20 @@
/* eslint-disable no-console */
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { getAuthInfoFromCookie } from '@/lib/auth';
-export const runtime = 'nodejs';
-export async function POST(request: NextRequest) {
+export async function POST(request: AppRequest) {
try {
// 权限检查:仅站长可以拉取配置订阅
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
+ return AppResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
if (authInfo.username !== process.env.USERNAME) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '权限不足,只有站长可以拉取配置订阅' },
{ status: 401 }
);
@@ -24,14 +23,14 @@ export async function POST(request: NextRequest) {
const { url } = await request.json();
if (!url) {
- return NextResponse.json({ error: '缺少URL参数' }, { status: 400 });
+ return AppResponse.json({ error: '缺少URL参数' }, { status: 400 });
}
// 直接 fetch URL 获取配置内容
const response = await fetch(url);
if (!response.ok) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: `请求失败: ${response.status} ${response.statusText}` },
{ status: response.status }
);
@@ -50,7 +49,7 @@ export async function POST(request: NextRequest) {
throw decodeError;
}
- return NextResponse.json({
+ return AppResponse.json({
success: true,
configContent: decodedContent,
message: '配置拉取成功'
@@ -58,7 +57,7 @@ export async function POST(request: NextRequest) {
} catch (error) {
console.error('拉取配置失败:', error);
- return NextResponse.json(
+ return AppResponse.json(
{ error: '拉取配置失败' },
{ status: 500 }
);
diff --git a/src/app/api/admin/data_migration/export/route.ts b/src/server/routes/api/admin/data_migration/export/route.ts
similarity index 85%
rename from src/app/api/admin/data_migration/export/route.ts
rename to src/server/routes/api/admin/data_migration/export/route.ts
index f813586..6bb99a9 100644
--- a/src/app/api/admin/data_migration/export/route.ts
+++ b/src/server/routes/api/admin/data_migration/export/route.ts
@@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any,no-console */
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { promisify } from 'util';
import { gzip } from 'zlib';
@@ -9,16 +9,15 @@ import { SimpleCrypto } from '@/lib/crypto';
import { db } from '@/lib/db';
import { CURRENT_VERSION } from '@/lib/version';
-export const runtime = 'nodejs';
const gzipAsync = promisify(gzip);
-export async function POST(req: NextRequest) {
+export async function POST(req: AppRequest) {
try {
// 检查存储类型
- const storageType = process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage';
+ const storageType = process.env.VITE_STORAGE_TYPE || 'localstorage';
if (storageType === 'localstorage') {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '不支持本地存储进行数据迁移' },
{ status: 400 }
);
@@ -27,23 +26,23 @@ export async function POST(req: NextRequest) {
// 验证身份和权限
const authInfo = getAuthInfoFromCookie(req);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: '未登录' }, { status: 401 });
+ return AppResponse.json({ error: '未登录' }, { status: 401 });
}
// 检查用户权限(只有站长可以导出数据)
if (authInfo.username !== process.env.USERNAME) {
- return NextResponse.json({ error: '权限不足,只有站长可以导出数据' }, { status: 401 });
+ return AppResponse.json({ error: '权限不足,只有站长可以导出数据' }, { status: 401 });
}
const config = await db.getAdminConfig();
if (!config) {
- return NextResponse.json({ error: '无法获取配置' }, { status: 500 });
+ return AppResponse.json({ error: '无法获取配置' }, { status: 500 });
}
// 解析请求体获取密码
const { password } = await req.json();
if (!password || typeof password !== 'string') {
- return NextResponse.json({ error: '请提供加密密码' }, { status: 400 });
+ return AppResponse.json({ error: '请提供加密密码' }, { status: 400 });
}
// 收集所有数据
@@ -100,7 +99,7 @@ export async function POST(req: NextRequest) {
const filename = `OrangeTV-backup-${timestamp}.dat`;
// 返回加密的数据作为文件下载
- return new NextResponse(encryptedData, {
+ return new AppResponse(encryptedData, {
status: 200,
headers: {
'Content-Type': 'application/octet-stream',
@@ -111,7 +110,7 @@ export async function POST(req: NextRequest) {
} catch (error) {
console.error('数据导出失败:', error);
- return NextResponse.json(
+ return AppResponse.json(
{ error: error instanceof Error ? error.message : '导出失败' },
{ status: 500 }
);
diff --git a/src/app/api/admin/data_migration/import/route.ts b/src/server/routes/api/admin/data_migration/import/route.ts
similarity index 80%
rename from src/app/api/admin/data_migration/import/route.ts
rename to src/server/routes/api/admin/data_migration/import/route.ts
index e6b19bb..a0b6cd3 100644
--- a/src/app/api/admin/data_migration/import/route.ts
+++ b/src/server/routes/api/admin/data_migration/import/route.ts
@@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any,no-console */
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { promisify } from 'util';
import { gunzip } from 'zlib';
@@ -9,16 +9,15 @@ import { configSelfCheck, setCachedConfig } from '@/lib/config';
import { SimpleCrypto } from '@/lib/crypto';
import { db } from '@/lib/db';
-export const runtime = 'nodejs';
const gunzipAsync = promisify(gunzip);
-export async function POST(req: NextRequest) {
+export async function POST(req: AppRequest) {
try {
// 检查存储类型
- const storageType = process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage';
+ const storageType = process.env.VITE_STORAGE_TYPE || 'localstorage';
if (storageType === 'localstorage') {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '不支持本地存储进行数据迁移' },
{ status: 400 }
);
@@ -27,12 +26,12 @@ export async function POST(req: NextRequest) {
// 验证身份和权限
const authInfo = getAuthInfoFromCookie(req);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: '未登录' }, { status: 401 });
+ return AppResponse.json({ error: '未登录' }, { status: 401 });
}
// 检查用户权限(只有站长可以导入数据)
if (authInfo.username !== process.env.USERNAME) {
- return NextResponse.json({ error: '权限不足,只有站长可以导入数据' }, { status: 401 });
+ return AppResponse.json({ error: '权限不足,只有站长可以导入数据' }, { status: 401 });
}
// 解析表单数据
@@ -41,11 +40,11 @@ export async function POST(req: NextRequest) {
const password = formData.get('password') as string;
if (!file) {
- return NextResponse.json({ error: '请选择备份文件' }, { status: 400 });
+ return AppResponse.json({ error: '请选择备份文件' }, { status: 400 });
}
if (!password) {
- return NextResponse.json({ error: '请提供解密密码' }, { status: 400 });
+ return AppResponse.json({ error: '请提供解密密码' }, { status: 400 });
}
// 读取文件内容
@@ -56,7 +55,7 @@ export async function POST(req: NextRequest) {
try {
decryptedData = SimpleCrypto.decrypt(encryptedData, password);
} catch (error) {
- return NextResponse.json({ error: '解密失败,请检查密码是否正确' }, { status: 400 });
+ return AppResponse.json({ error: '解密失败,请检查密码是否正确' }, { status: 400 });
}
// 解压缩数据
@@ -69,12 +68,12 @@ export async function POST(req: NextRequest) {
try {
importData = JSON.parse(decompressedData);
} catch (error) {
- return NextResponse.json({ error: '备份文件格式错误' }, { status: 400 });
+ return AppResponse.json({ error: '备份文件格式错误' }, { status: 400 });
}
// 验证数据格式
if (!importData.data || !importData.data.adminConfig || !importData.data.userData) {
- return NextResponse.json({ error: '备份文件格式无效' }, { status: 400 });
+ return AppResponse.json({ error: '备份文件格式无效' }, { status: 400 });
}
// 开始导入数据 - 先清空现有数据
@@ -127,7 +126,7 @@ export async function POST(req: NextRequest) {
}
}
- return NextResponse.json({
+ return AppResponse.json({
message: '数据导入成功',
importedUsers: Object.keys(userData).length,
timestamp: importData.timestamp,
@@ -136,7 +135,7 @@ export async function POST(req: NextRequest) {
} catch (error) {
console.error('数据导入失败:', error);
- return NextResponse.json(
+ return AppResponse.json(
{ error: error instanceof Error ? error.message : '导入失败' },
{ status: 500 }
);
diff --git a/src/app/api/admin/live/refresh/route.ts b/src/server/routes/api/admin/live/refresh/route.ts
similarity index 83%
rename from src/app/api/admin/live/refresh/route.ts
rename to src/server/routes/api/admin/live/refresh/route.ts
index 82497fb..0e57bd8 100644
--- a/src/app/api/admin/live/refresh/route.ts
+++ b/src/server/routes/api/admin/live/refresh/route.ts
@@ -1,15 +1,14 @@
/* eslint-disable no-console */
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { getAuthInfoFromCookie } from '@/lib/auth';
import { getConfig } from '@/lib/config';
import { db } from '@/lib/db';
import { refreshLiveChannels } from '@/lib/live';
-export const runtime = 'nodejs';
-export async function POST(request: NextRequest) {
+export async function POST(request: AppRequest) {
try {
// 权限检查
const authInfo = getAuthInfoFromCookie(request);
@@ -21,7 +20,7 @@ export async function POST(request: NextRequest) {
(u) => u.username === username
);
if (!user || user.role !== 'admin' || user.banned) {
- return NextResponse.json({ error: '权限不足' }, { status: 401 });
+ return AppResponse.json({ error: '权限不足' }, { status: 401 });
}
}
@@ -43,13 +42,13 @@ export async function POST(request: NextRequest) {
// 保存配置
await db.saveAdminConfig(config);
- return NextResponse.json({
+ return AppResponse.json({
success: true,
message: '直播源刷新成功',
});
} catch (error) {
console.error('直播源刷新失败:', error);
- return NextResponse.json(
+ return AppResponse.json(
{ error: error instanceof Error ? error.message : '刷新失败' },
{ status: 500 }
);
diff --git a/src/app/api/admin/live/route.ts b/src/server/routes/api/admin/live/route.ts
similarity index 77%
rename from src/app/api/admin/live/route.ts
rename to src/server/routes/api/admin/live/route.ts
index b173205..8a278c8 100644
--- a/src/app/api/admin/live/route.ts
+++ b/src/server/routes/api/admin/live/route.ts
@@ -1,15 +1,14 @@
/* eslint-disable no-console,no-case-declarations */
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { getAuthInfoFromCookie } from '@/lib/auth';
import { getConfig } from '@/lib/config';
import { db } from '@/lib/db';
import { deleteCachedLiveChannels, refreshLiveChannels } from '@/lib/live';
-export const runtime = 'nodejs';
-export async function POST(request: NextRequest) {
+export async function POST(request: AppRequest) {
try {
// 权限检查
const authInfo = getAuthInfoFromCookie(request);
@@ -21,7 +20,7 @@ export async function POST(request: NextRequest) {
(u) => u.username === username
);
if (!user || user.role !== 'admin' || user.banned) {
- return NextResponse.json({ error: '权限不足' }, { status: 401 });
+ return AppResponse.json({ error: '权限不足' }, { status: 401 });
}
}
@@ -29,7 +28,7 @@ export async function POST(request: NextRequest) {
const { action, key, name, url, ua, epg } = body;
if (!config) {
- return NextResponse.json({ error: '配置不存在' }, { status: 404 });
+ return AppResponse.json({ error: '配置不存在' }, { status: 404 });
}
// 确保 LiveConfig 存在
@@ -41,7 +40,7 @@ export async function POST(request: NextRequest) {
case 'add':
// 检查是否已存在相同的 key
if (config.LiveConfig.some((l) => l.key === key)) {
- return NextResponse.json({ error: '直播源 key 已存在' }, { status: 400 });
+ return AppResponse.json({ error: '直播源 key 已存在' }, { status: 400 });
}
const liveInfo = {
@@ -71,12 +70,12 @@ export async function POST(request: NextRequest) {
// 删除直播源
const deleteIndex = config.LiveConfig.findIndex((l) => l.key === key);
if (deleteIndex === -1) {
- return NextResponse.json({ error: '直播源不存在' }, { status: 404 });
+ return AppResponse.json({ error: '直播源不存在' }, { status: 404 });
}
const liveSource = config.LiveConfig[deleteIndex];
if (liveSource.from === 'config') {
- return NextResponse.json({ error: '不能删除配置文件中的直播源' }, { status: 400 });
+ return AppResponse.json({ error: '不能删除配置文件中的直播源' }, { status: 400 });
}
deleteCachedLiveChannels(key);
@@ -88,7 +87,7 @@ export async function POST(request: NextRequest) {
// 启用直播源
const enableSource = config.LiveConfig.find((l) => l.key === key);
if (!enableSource) {
- return NextResponse.json({ error: '直播源不存在' }, { status: 404 });
+ return AppResponse.json({ error: '直播源不存在' }, { status: 404 });
}
enableSource.disabled = false;
break;
@@ -97,7 +96,7 @@ export async function POST(request: NextRequest) {
// 禁用直播源
const disableSource = config.LiveConfig.find((l) => l.key === key);
if (!disableSource) {
- return NextResponse.json({ error: '直播源不存在' }, { status: 404 });
+ return AppResponse.json({ error: '直播源不存在' }, { status: 404 });
}
disableSource.disabled = true;
break;
@@ -106,12 +105,12 @@ export async function POST(request: NextRequest) {
// 编辑直播源
const editSource = config.LiveConfig.find((l) => l.key === key);
if (!editSource) {
- return NextResponse.json({ error: '直播源不存在' }, { status: 404 });
+ return AppResponse.json({ error: '直播源不存在' }, { status: 404 });
}
// 配置文件中的直播源不允许编辑
if (editSource.from === 'config') {
- return NextResponse.json({ error: '不能编辑配置文件中的直播源' }, { status: 400 });
+ return AppResponse.json({ error: '不能编辑配置文件中的直播源' }, { status: 400 });
}
// 更新字段(除了 key 和 from)
@@ -134,7 +133,7 @@ export async function POST(request: NextRequest) {
// 排序直播源
const { order } = body;
if (!Array.isArray(order)) {
- return NextResponse.json({ error: '排序数据格式错误' }, { status: 400 });
+ return AppResponse.json({ error: '排序数据格式错误' }, { status: 400 });
}
// 创建新的排序后的数组
@@ -157,15 +156,15 @@ export async function POST(request: NextRequest) {
break;
default:
- return NextResponse.json({ error: '未知操作' }, { status: 400 });
+ return AppResponse.json({ error: '未知操作' }, { status: 400 });
}
// 保存配置
await db.saveAdminConfig(config);
- return NextResponse.json({ success: true });
+ return AppResponse.json({ success: true });
} catch (error) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: error instanceof Error ? error.message : '操作失败' },
{ status: 500 }
);
diff --git a/src/app/api/admin/reset/route.ts b/src/server/routes/api/admin/reset/route.ts
similarity index 63%
rename from src/app/api/admin/reset/route.ts
rename to src/server/routes/api/admin/reset/route.ts
index 7524160..4283939 100644
--- a/src/app/api/admin/reset/route.ts
+++ b/src/server/routes/api/admin/reset/route.ts
@@ -1,16 +1,15 @@
/* eslint-disable no-console */
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { getAuthInfoFromCookie } from '@/lib/auth';
import { resetConfig } from '@/lib/config';
-export const runtime = 'nodejs';
-export async function GET(request: NextRequest) {
- const storageType = process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage';
+export async function GET(request: AppRequest) {
+ const storageType = process.env.VITE_STORAGE_TYPE || 'localstorage';
if (storageType === 'localstorage') {
- return NextResponse.json(
+ return AppResponse.json(
{
error: '不支持本地存储进行管理员配置',
},
@@ -20,18 +19,18 @@ export async function GET(request: NextRequest) {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
+ return AppResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const username = authInfo.username;
if (username !== process.env.USERNAME) {
- return NextResponse.json({ error: '仅支持站长重置配置' }, { status: 401 });
+ return AppResponse.json({ error: '仅支持站长重置配置' }, { status: 401 });
}
try {
await resetConfig();
- return NextResponse.json(
+ return AppResponse.json(
{ ok: true },
{
headers: {
@@ -40,7 +39,7 @@ export async function GET(request: NextRequest) {
}
);
} catch (error) {
- return NextResponse.json(
+ return AppResponse.json(
{
error: '重置管理员配置失败',
details: (error as Error).message,
diff --git a/src/app/api/admin/site/route.ts b/src/server/routes/api/admin/site/route.ts
similarity index 84%
rename from src/app/api/admin/site/route.ts
rename to src/server/routes/api/admin/site/route.ts
index ce69f8a..cd19cf2 100644
--- a/src/app/api/admin/site/route.ts
+++ b/src/server/routes/api/admin/site/route.ts
@@ -1,17 +1,16 @@
/* eslint-disable @typescript-eslint/no-explicit-any,no-console */
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { getAuthInfoFromCookie } from '@/lib/auth';
import { getConfig } from '@/lib/config';
import { db } from '@/lib/db';
-export const runtime = 'nodejs';
-export async function POST(request: NextRequest) {
- const storageType = process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage';
+export async function POST(request: AppRequest) {
+ const storageType = process.env.VITE_STORAGE_TYPE || 'localstorage';
if (storageType === 'localstorage') {
- return NextResponse.json(
+ return AppResponse.json(
{
error: '不支持本地存储进行管理员配置',
},
@@ -24,7 +23,7 @@ export async function POST(request: NextRequest) {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
+ return AppResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const username = authInfo.username;
@@ -77,7 +76,7 @@ export async function POST(request: NextRequest) {
typeof CustomTheme.customCSS !== 'string'
))
) {
- return NextResponse.json({ error: '参数格式错误' }, { status: 400 });
+ return AppResponse.json({ error: '参数格式错误' }, { status: 400 });
}
const adminConfig = await getConfig();
@@ -89,7 +88,7 @@ export async function POST(request: NextRequest) {
(u) => u.username === username
);
if (!user || user.role !== 'admin' || user.banned) {
- return NextResponse.json({ error: '权限不足' }, { status: 401 });
+ return AppResponse.json({ error: '权限不足' }, { status: 401 });
}
}
@@ -112,7 +111,7 @@ export async function POST(request: NextRequest) {
// 写入数据库
await db.saveAdminConfig(adminConfig);
- return NextResponse.json(
+ return AppResponse.json(
{ ok: true },
{
headers: {
@@ -122,7 +121,7 @@ export async function POST(request: NextRequest) {
);
} catch (error) {
console.error('更新站点配置失败:', error);
- return NextResponse.json(
+ return AppResponse.json(
{
error: '更新站点配置失败',
details: (error as Error).message,
diff --git a/src/app/api/admin/source/route.ts b/src/server/routes/api/admin/source/route.ts
similarity index 80%
rename from src/app/api/admin/source/route.ts
rename to src/server/routes/api/admin/source/route.ts
index 4c75850..6916159 100644
--- a/src/app/api/admin/source/route.ts
+++ b/src/server/routes/api/admin/source/route.ts
@@ -1,12 +1,11 @@
/* eslint-disable @typescript-eslint/no-explicit-any,no-console */
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { getAuthInfoFromCookie } from '@/lib/auth';
import { getConfig } from '@/lib/config';
import { db } from '@/lib/db';
-export const runtime = 'nodejs';
// 支持的操作类型
type Action = 'add' | 'disable' | 'enable' | 'delete' | 'edit' | 'sort' | 'batch_disable' | 'batch_enable' | 'batch_delete';
@@ -15,10 +14,10 @@ interface BaseBody {
action?: Action;
}
-export async function POST(request: NextRequest) {
- const storageType = process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage';
+export async function POST(request: AppRequest) {
+ const storageType = process.env.VITE_STORAGE_TYPE || 'localstorage';
if (storageType === 'localstorage') {
- return NextResponse.json(
+ return AppResponse.json(
{
error: '不支持本地存储进行管理员配置',
},
@@ -32,14 +31,14 @@ export async function POST(request: NextRequest) {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
+ return AppResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const username = authInfo.username;
// 基础校验
const ACTIONS: Action[] = ['add', 'disable', 'enable', 'delete', 'edit', 'sort', 'batch_disable', 'batch_enable', 'batch_delete'];
if (!username || !action || !ACTIONS.includes(action)) {
- return NextResponse.json({ error: '参数格式错误' }, { status: 400 });
+ return AppResponse.json({ error: '参数格式错误' }, { status: 400 });
}
// 获取配置与存储
@@ -51,7 +50,7 @@ export async function POST(request: NextRequest) {
(u) => u.username === username
);
if (!userEntry || userEntry.role !== 'admin' || userEntry.banned) {
- return NextResponse.json({ error: '权限不足' }, { status: 401 });
+ return AppResponse.json({ error: '权限不足' }, { status: 401 });
}
}
@@ -64,10 +63,10 @@ export async function POST(request: NextRequest) {
detail?: string;
};
if (!key || !name || !api) {
- return NextResponse.json({ error: '缺少必要参数' }, { status: 400 });
+ return AppResponse.json({ error: '缺少必要参数' }, { status: 400 });
}
if (adminConfig.SourceConfig.some((s) => s.key === key)) {
- return NextResponse.json({ error: '该源已存在' }, { status: 400 });
+ return AppResponse.json({ error: '该源已存在' }, { status: 400 });
}
adminConfig.SourceConfig.push({
key,
@@ -82,20 +81,20 @@ export async function POST(request: NextRequest) {
case 'disable': {
const { key } = body as { key?: string };
if (!key)
- return NextResponse.json({ error: '缺少 key 参数' }, { status: 400 });
+ return AppResponse.json({ error: '缺少 key 参数' }, { status: 400 });
const entry = adminConfig.SourceConfig.find((s) => s.key === key);
if (!entry)
- return NextResponse.json({ error: '源不存在' }, { status: 404 });
+ return AppResponse.json({ error: '源不存在' }, { status: 404 });
entry.disabled = true;
break;
}
case 'enable': {
const { key } = body as { key?: string };
if (!key)
- return NextResponse.json({ error: '缺少 key 参数' }, { status: 400 });
+ return AppResponse.json({ error: '缺少 key 参数' }, { status: 400 });
const entry = adminConfig.SourceConfig.find((s) => s.key === key);
if (!entry)
- return NextResponse.json({ error: '源不存在' }, { status: 404 });
+ return AppResponse.json({ error: '源不存在' }, { status: 404 });
entry.disabled = false;
break;
}
@@ -107,11 +106,11 @@ export async function POST(request: NextRequest) {
detail?: string;
};
if (!key || !name || !api) {
- return NextResponse.json({ error: '缺少必要参数' }, { status: 400 });
+ return AppResponse.json({ error: '缺少必要参数' }, { status: 400 });
}
const entry = adminConfig.SourceConfig.find((s) => s.key === key);
if (!entry) {
- return NextResponse.json({ error: '源不存在' }, { status: 404 });
+ return AppResponse.json({ error: '源不存在' }, { status: 404 });
}
// 更新字段(除了 key 和 from)
entry.name = name;
@@ -122,13 +121,13 @@ export async function POST(request: NextRequest) {
case 'delete': {
const { key } = body as { key?: string };
if (!key)
- return NextResponse.json({ error: '缺少 key 参数' }, { status: 400 });
+ return AppResponse.json({ error: '缺少 key 参数' }, { status: 400 });
const idx = adminConfig.SourceConfig.findIndex((s) => s.key === key);
if (idx === -1)
- return NextResponse.json({ error: '源不存在' }, { status: 404 });
+ return AppResponse.json({ error: '源不存在' }, { status: 404 });
const entry = adminConfig.SourceConfig[idx];
if (entry.from === 'config') {
- return NextResponse.json({ error: '该源不可删除' }, { status: 400 });
+ return AppResponse.json({ error: '该源不可删除' }, { status: 400 });
}
adminConfig.SourceConfig.splice(idx, 1);
@@ -153,7 +152,7 @@ export async function POST(request: NextRequest) {
case 'batch_disable': {
const { keys } = body as { keys?: string[] };
if (!Array.isArray(keys) || keys.length === 0) {
- return NextResponse.json({ error: '缺少 keys 参数或为空' }, { status: 400 });
+ return AppResponse.json({ error: '缺少 keys 参数或为空' }, { status: 400 });
}
keys.forEach(key => {
const entry = adminConfig.SourceConfig.find((s) => s.key === key);
@@ -166,7 +165,7 @@ export async function POST(request: NextRequest) {
case 'batch_enable': {
const { keys } = body as { keys?: string[] };
if (!Array.isArray(keys) || keys.length === 0) {
- return NextResponse.json({ error: '缺少 keys 参数或为空' }, { status: 400 });
+ return AppResponse.json({ error: '缺少 keys 参数或为空' }, { status: 400 });
}
keys.forEach(key => {
const entry = adminConfig.SourceConfig.find((s) => s.key === key);
@@ -179,7 +178,7 @@ export async function POST(request: NextRequest) {
case 'batch_delete': {
const { keys } = body as { keys?: string[] };
if (!Array.isArray(keys) || keys.length === 0) {
- return NextResponse.json({ error: '缺少 keys 参数或为空' }, { status: 400 });
+ return AppResponse.json({ error: '缺少 keys 参数或为空' }, { status: 400 });
}
// 过滤掉 from=config 的源,但不报错
const keysToDelete = keys.filter(key => {
@@ -218,7 +217,7 @@ export async function POST(request: NextRequest) {
case 'sort': {
const { order } = body as { order?: string[] };
if (!Array.isArray(order)) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '排序列表格式错误' },
{ status: 400 }
);
@@ -240,13 +239,13 @@ export async function POST(request: NextRequest) {
break;
}
default:
- return NextResponse.json({ error: '未知操作' }, { status: 400 });
+ return AppResponse.json({ error: '未知操作' }, { status: 400 });
}
// 持久化到存储
await db.saveAdminConfig(adminConfig);
- return NextResponse.json(
+ return AppResponse.json(
{ ok: true },
{
headers: {
@@ -256,7 +255,7 @@ export async function POST(request: NextRequest) {
);
} catch (error) {
console.error('视频源管理操作失败:', error);
- return NextResponse.json(
+ return AppResponse.json(
{
error: '视频源管理操作失败',
details: (error as Error).message,
diff --git a/src/app/api/admin/source/validate/route.ts b/src/server/routes/api/admin/source/validate/route.ts
similarity index 96%
rename from src/app/api/admin/source/validate/route.ts
rename to src/server/routes/api/admin/source/validate/route.ts
index bb4ad9d..d74045d 100644
--- a/src/app/api/admin/source/validate/route.ts
+++ b/src/server/routes/api/admin/source/validate/route.ts
@@ -1,17 +1,16 @@
/* eslint-disable @typescript-eslint/no-explicit-any,no-console */
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { getAuthInfoFromCookie } from '@/lib/auth';
import { getConfig } from '@/lib/config';
import { API_CONFIG } from '@/lib/config';
-export const runtime = 'nodejs';
-export async function GET(request: NextRequest) {
+export async function GET(request: AppRequest) {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
+ return AppResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const { searchParams } = new URL(request.url);
diff --git a/src/app/api/admin/theme/route.ts b/src/server/routes/api/admin/theme/route.ts
similarity index 76%
rename from src/app/api/admin/theme/route.ts
rename to src/server/routes/api/admin/theme/route.ts
index 2ed07f5..4e45b15 100644
--- a/src/app/api/admin/theme/route.ts
+++ b/src/server/routes/api/admin/theme/route.ts
@@ -1,18 +1,18 @@
-import { NextResponse } from 'next/server';
+import { AppResponse } from '@/server/web';
import { getAuthInfoFromCookie } from '@/lib/auth';
import { db } from '@/lib/db';
import { AdminConfig } from '@/lib/admin.types';
-import { headers, cookies } from 'next/headers';
+import { headers, cookies } from '@/server/web';
import { getConfig, setCachedConfig, clearCachedConfig } from '@/lib/config';
export async function GET() {
try {
- // 创建一个模拟的NextRequest对象来使用getAuthInfoFromCookie
+ // 创建一个模拟的AppRequest对象来使用getAuthInfoFromCookie
const cookieStore = await cookies();
const authCookie = cookieStore.get('auth');
if (!authCookie) {
- return NextResponse.json({ error: '未授权' }, { status: 401 });
+ return AppResponse.json({ error: '未授权' }, { status: 401 });
}
let authData;
@@ -20,19 +20,19 @@ export async function GET() {
const decoded = decodeURIComponent(authCookie.value);
authData = JSON.parse(decoded);
} catch (error) {
- return NextResponse.json({ error: '认证信息无效' }, { status: 401 });
+ return AppResponse.json({ error: '认证信息无效' }, { status: 401 });
}
const config = await getConfig();
const themeConfig = config.ThemeConfig;
- return NextResponse.json({
+ return AppResponse.json({
success: true,
data: themeConfig,
});
} catch (error) {
console.error('获取主题配置失败:', error);
- return NextResponse.json(
+ return AppResponse.json(
{ error: '获取主题配置失败' },
{ status: 500 }
);
@@ -46,7 +46,7 @@ export async function POST(request: Request) {
const authCookie = cookieStore.get('auth');
if (!authCookie) {
- return NextResponse.json({ error: '未授权' }, { status: 401 });
+ return AppResponse.json({ error: '未授权' }, { status: 401 });
}
let authData;
@@ -54,12 +54,12 @@ export async function POST(request: Request) {
const decoded = decodeURIComponent(authCookie.value);
authData = JSON.parse(decoded);
} catch (error) {
- return NextResponse.json({ error: '认证信息无效' }, { status: 401 });
+ return AppResponse.json({ error: '认证信息无效' }, { status: 401 });
}
// 检查是否为管理员
if (authData.role !== 'admin' && authData.role !== 'owner') {
- return NextResponse.json({ error: '权限不足,仅管理员可设置全局主题' }, { status: 403 });
+ return AppResponse.json({ error: '权限不足,仅管理员可设置全局主题' }, { status: 403 });
}
const body = await request.json();
@@ -68,7 +68,7 @@ export async function POST(request: Request) {
// 验证主题名称
const validThemes = ['default', 'minimal', 'warm', 'fresh'];
if (!validThemes.includes(defaultTheme)) {
- return NextResponse.json({ error: '无效的主题名称' }, { status: 400 });
+ return AppResponse.json({ error: '无效的主题名称' }, { status: 400 });
}
// 获取当前配置
@@ -86,7 +86,7 @@ export async function POST(request: Request) {
console.log('=== 保存主题配置 ===');
console.log('请求参数:', { defaultTheme, customCSS, allowUserCustomization });
- console.log('当前存储类型:', process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage');
+ console.log('当前存储类型:', process.env.VITE_STORAGE_TYPE || 'localstorage');
console.log('待保存配置:', updatedConfig.ThemeConfig);
console.log('完整配置对象:', JSON.stringify(updatedConfig, null, 2));
@@ -101,14 +101,14 @@ export async function POST(request: Request) {
const cachedConfig = await getConfig();
console.log('保存后验证缓存中的配置:', cachedConfig.ThemeConfig);
- return NextResponse.json({
+ return AppResponse.json({
success: true,
message: '主题配置已更新',
data: updatedConfig.ThemeConfig,
});
} catch (error) {
console.error('更新主题配置失败:', error);
- return NextResponse.json(
+ return AppResponse.json(
{ error: '更新主题配置失败', details: error instanceof Error ? error.message : '未知错误' },
{ status: 500 }
);
diff --git a/src/app/api/admin/user/route.ts b/src/server/routes/api/admin/user/route.ts
similarity index 84%
rename from src/app/api/admin/user/route.ts
rename to src/server/routes/api/admin/user/route.ts
index 9473f25..fdf0542 100644
--- a/src/app/api/admin/user/route.ts
+++ b/src/server/routes/api/admin/user/route.ts
@@ -1,12 +1,11 @@
/* eslint-disable @typescript-eslint/no-explicit-any,no-console,@typescript-eslint/no-non-null-assertion */
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { getAuthInfoFromCookie } from '@/lib/auth';
import { getConfig } from '@/lib/config';
import { db } from '@/lib/db';
-export const runtime = 'nodejs';
// 支持的操作类型
const ACTIONS = [
@@ -23,10 +22,10 @@ const ACTIONS = [
'batchUpdateUserGroups',
] as const;
-export async function POST(request: NextRequest) {
- const storageType = process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage';
+export async function POST(request: AppRequest) {
+ const storageType = process.env.VITE_STORAGE_TYPE || 'localstorage';
if (storageType === 'localstorage') {
- return NextResponse.json(
+ return AppResponse.json(
{
error: '不支持本地存储进行管理员配置',
},
@@ -39,7 +38,7 @@ export async function POST(request: NextRequest) {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
+ return AppResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const username = authInfo.username;
@@ -54,12 +53,12 @@ export async function POST(request: NextRequest) {
};
if (!action || !ACTIONS.includes(action)) {
- return NextResponse.json({ error: '参数格式错误' }, { status: 400 });
+ return AppResponse.json({ error: '参数格式错误' }, { status: 400 });
}
// 用户组操作和批量操作不需要targetUsername
if (!targetUsername && !['userGroup', 'batchUpdateUserGroups'].includes(action)) {
- return NextResponse.json({ error: '缺少目标用户名' }, { status: 400 });
+ return AppResponse.json({ error: '缺少目标用户名' }, { status: 400 });
}
if (
@@ -71,7 +70,7 @@ export async function POST(request: NextRequest) {
action !== 'batchUpdateUserGroups' &&
username === targetUsername
) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '无法对自己进行此操作' },
{ status: 400 }
);
@@ -89,7 +88,7 @@ export async function POST(request: NextRequest) {
(u) => u.username === username
);
if (!userEntry || userEntry.role !== 'admin' || userEntry.banned) {
- return NextResponse.json({ error: '权限不足' }, { status: 401 });
+ return AppResponse.json({ error: '权限不足' }, { status: 401 });
}
operatorRole = 'admin';
}
@@ -108,7 +107,7 @@ export async function POST(request: NextRequest) {
targetEntry.role === 'owner' &&
!['changePassword', 'updateUserApis', 'updateUserGroups'].includes(action)
) {
- return NextResponse.json({ error: '无法操作站长' }, { status: 400 });
+ return AppResponse.json({ error: '无法操作站长' }, { status: 400 });
}
// 权限校验逻辑
@@ -118,10 +117,10 @@ export async function POST(request: NextRequest) {
switch (action) {
case 'add': {
if (targetEntry) {
- return NextResponse.json({ error: '用户已存在' }, { status: 400 });
+ return AppResponse.json({ error: '用户已存在' }, { status: 400 });
}
if (!targetPassword) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '缺少目标用户密码' },
{ status: 400 }
);
@@ -151,7 +150,7 @@ export async function POST(request: NextRequest) {
}
case 'ban': {
if (!targetEntry) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '目标用户不存在' },
{ status: 404 }
);
@@ -159,7 +158,7 @@ export async function POST(request: NextRequest) {
if (isTargetAdmin) {
// 目标是管理员
if (operatorRole !== 'owner') {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '仅站长可封禁管理员' },
{ status: 401 }
);
@@ -170,14 +169,14 @@ export async function POST(request: NextRequest) {
}
case 'unban': {
if (!targetEntry) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '目标用户不存在' },
{ status: 404 }
);
}
if (isTargetAdmin) {
if (operatorRole !== 'owner') {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '仅站长可操作管理员' },
{ status: 401 }
);
@@ -188,19 +187,19 @@ export async function POST(request: NextRequest) {
}
case 'setAdmin': {
if (!targetEntry) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '目标用户不存在' },
{ status: 404 }
);
}
if (targetEntry.role === 'admin') {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '该用户已是管理员' },
{ status: 400 }
);
}
if (operatorRole !== 'owner') {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '仅站长可设置管理员' },
{ status: 401 }
);
@@ -210,19 +209,19 @@ export async function POST(request: NextRequest) {
}
case 'cancelAdmin': {
if (!targetEntry) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '目标用户不存在' },
{ status: 404 }
);
}
if (targetEntry.role !== 'admin') {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '目标用户不是管理员' },
{ status: 400 }
);
}
if (operatorRole !== 'owner') {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '仅站长可取消管理员' },
{ status: 401 }
);
@@ -232,18 +231,18 @@ export async function POST(request: NextRequest) {
}
case 'changePassword': {
if (!targetEntry) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '目标用户不存在' },
{ status: 404 }
);
}
if (!targetPassword) {
- return NextResponse.json({ error: '缺少新密码' }, { status: 400 });
+ return AppResponse.json({ error: '缺少新密码' }, { status: 400 });
}
// 权限检查:不允许修改站长密码
if (targetEntry.role === 'owner') {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '无法修改站长密码' },
{ status: 401 }
);
@@ -254,7 +253,7 @@ export async function POST(request: NextRequest) {
operatorRole !== 'owner' &&
username !== targetUsername
) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '仅站长可修改其他管理员密码' },
{ status: 401 }
);
@@ -265,7 +264,7 @@ export async function POST(request: NextRequest) {
}
case 'deleteUser': {
if (!targetEntry) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '目标用户不存在' },
{ status: 404 }
);
@@ -273,14 +272,14 @@ export async function POST(request: NextRequest) {
// 权限检查:站长可删除所有用户(除了自己),管理员可删除普通用户
if (username === targetUsername) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '不能删除自己' },
{ status: 400 }
);
}
if (isTargetAdmin && operatorRole !== 'owner') {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '仅站长可删除管理员' },
{ status: 401 }
);
@@ -300,7 +299,7 @@ export async function POST(request: NextRequest) {
}
case 'updateUserApis': {
if (!targetEntry) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '目标用户不存在' },
{ status: 404 }
);
@@ -314,7 +313,7 @@ export async function POST(request: NextRequest) {
operatorRole !== 'owner' &&
username !== targetUsername
) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '仅站长可配置其他管理员的采集源' },
{ status: 401 }
);
@@ -346,7 +345,7 @@ export async function POST(request: NextRequest) {
case 'add': {
// 检查用户组是否已存在
if (adminConfig.UserConfig.Tags.find(t => t.name === groupName)) {
- return NextResponse.json({ error: '用户组已存在' }, { status: 400 });
+ return AppResponse.json({ error: '用户组已存在' }, { status: 400 });
}
adminConfig.UserConfig.Tags.push({
name: groupName,
@@ -357,7 +356,7 @@ export async function POST(request: NextRequest) {
case 'edit': {
const groupIndex = adminConfig.UserConfig.Tags.findIndex(t => t.name === groupName);
if (groupIndex === -1) {
- return NextResponse.json({ error: '用户组不存在' }, { status: 404 });
+ return AppResponse.json({ error: '用户组不存在' }, { status: 404 });
}
adminConfig.UserConfig.Tags[groupIndex].enabledApis = enabledApis || [];
break;
@@ -365,7 +364,7 @@ export async function POST(request: NextRequest) {
case 'delete': {
const groupIndex = adminConfig.UserConfig.Tags.findIndex(t => t.name === groupName);
if (groupIndex === -1) {
- return NextResponse.json({ error: '用户组不存在' }, { status: 404 });
+ return AppResponse.json({ error: '用户组不存在' }, { status: 404 });
}
// 查找使用该用户组的所有用户
@@ -391,13 +390,13 @@ export async function POST(request: NextRequest) {
break;
}
default:
- return NextResponse.json({ error: '未知的用户组操作' }, { status: 400 });
+ return AppResponse.json({ error: '未知的用户组操作' }, { status: 400 });
}
break;
}
case 'updateUserGroups': {
if (!targetEntry) {
- return NextResponse.json({ error: '目标用户不存在' }, { status: 404 });
+ return AppResponse.json({ error: '目标用户不存在' }, { status: 404 });
}
const { userGroups } = body as { userGroups: string[] };
@@ -408,7 +407,7 @@ export async function POST(request: NextRequest) {
operatorRole !== 'owner' &&
username !== targetUsername
) {
- return NextResponse.json({ error: '仅站长可配置其他管理员的用户组' }, { status: 400 });
+ return AppResponse.json({ error: '仅站长可配置其他管理员的用户组' }, { status: 400 });
}
// 更新用户的用户组
@@ -425,7 +424,7 @@ export async function POST(request: NextRequest) {
const { usernames, userGroups } = body as { usernames: string[]; userGroups: string[] };
if (!usernames || !Array.isArray(usernames) || usernames.length === 0) {
- return NextResponse.json({ error: '缺少用户名列表' }, { status: 400 });
+ return AppResponse.json({ error: '缺少用户名列表' }, { status: 400 });
}
// 权限检查:站长可批量配置所有人的用户组,管理员只能批量配置普通用户
@@ -433,7 +432,7 @@ export async function POST(request: NextRequest) {
for (const targetUsername of usernames) {
const targetUser = adminConfig.UserConfig.Users.find(u => u.username === targetUsername);
if (targetUser && targetUser.role === 'admin' && targetUsername !== username) {
- return NextResponse.json({ error: `管理员无法操作其他管理员 ${targetUsername}` }, { status: 400 });
+ return AppResponse.json({ error: `管理员无法操作其他管理员 ${targetUsername}` }, { status: 400 });
}
}
}
@@ -454,13 +453,13 @@ export async function POST(request: NextRequest) {
break;
}
default:
- return NextResponse.json({ error: '未知操作' }, { status: 400 });
+ return AppResponse.json({ error: '未知操作' }, { status: 400 });
}
// 将更新后的配置写入数据库
await db.saveAdminConfig(adminConfig);
- return NextResponse.json(
+ return AppResponse.json(
{ ok: true },
{
headers: {
@@ -470,7 +469,7 @@ export async function POST(request: NextRequest) {
);
} catch (error) {
console.error('用户管理操作失败:', error);
- return NextResponse.json(
+ return AppResponse.json(
{
error: '用户管理操作失败',
details: (error as Error).message,
diff --git a/src/app/api/avatar/route.ts b/src/server/routes/api/avatar/route.ts
similarity index 62%
rename from src/app/api/avatar/route.ts
rename to src/server/routes/api/avatar/route.ts
index b6ea89c..1232071 100644
--- a/src/app/api/avatar/route.ts
+++ b/src/server/routes/api/avatar/route.ts
@@ -1,16 +1,15 @@
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { getAuthInfoFromCookie } from '@/lib/auth';
import { db } from '@/lib/db';
-export const runtime = 'nodejs';
// 获取用户头像
-export async function GET(request: NextRequest) {
+export async function GET(request: AppRequest) {
try {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
+ return AppResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const { searchParams } = new URL(request.url);
@@ -23,41 +22,41 @@ export async function GET(request: NextRequest) {
const avatar = await db.getUserAvatar(targetUser);
if (!avatar) {
- return NextResponse.json({ avatar: null });
+ return AppResponse.json({ avatar: null });
}
- return NextResponse.json({ avatar });
+ return AppResponse.json({ avatar });
} catch (error) {
console.error('获取头像失败:', error);
- return NextResponse.json({ error: '获取头像失败' }, { status: 500 });
+ return AppResponse.json({ error: '获取头像失败' }, { status: 500 });
}
}
// 上传用户头像
-export async function POST(request: NextRequest) {
+export async function POST(request: AppRequest) {
try {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
+ return AppResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const body = await request.json();
const { avatar, targetUser } = body;
if (!avatar) {
- return NextResponse.json({ error: '头像数据不能为空' }, { status: 400 });
+ return AppResponse.json({ error: '头像数据不能为空' }, { status: 400 });
}
// 验证Base64格式
if (!avatar.startsWith('data:image/')) {
- return NextResponse.json({ error: '无效的图片格式' }, { status: 400 });
+ return AppResponse.json({ error: '无效的图片格式' }, { status: 400 });
}
// 检查文件大小(Base64编码后大约增加33%,2MB的限制)
const base64Data = avatar.split(',')[1];
const sizeInBytes = (base64Data.length * 3) / 4;
if (sizeInBytes > 2 * 1024 * 1024) {
- return NextResponse.json({ error: '图片大小不能超过2MB' }, { status: 400 });
+ return AppResponse.json({ error: '图片大小不能超过2MB' }, { status: 400 });
}
const userToUpdate = targetUser || authInfo.username;
@@ -68,24 +67,24 @@ export async function POST(request: NextRequest) {
authInfo.role === 'owner';
if (!canUpdate) {
- return NextResponse.json({ error: 'Permission denied' }, { status: 403 });
+ return AppResponse.json({ error: 'Permission denied' }, { status: 403 });
}
await db.setUserAvatar(userToUpdate, avatar);
- return NextResponse.json({ success: true, message: '头像上传成功' });
+ return AppResponse.json({ success: true, message: '头像上传成功' });
} catch (error) {
console.error('上传头像失败:', error);
- return NextResponse.json({ error: '上传头像失败' }, { status: 500 });
+ return AppResponse.json({ error: '上传头像失败' }, { status: 500 });
}
}
// 删除用户头像
-export async function DELETE(request: NextRequest) {
+export async function DELETE(request: AppRequest) {
try {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
+ return AppResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const { searchParams } = new URL(request.url);
@@ -97,14 +96,14 @@ export async function DELETE(request: NextRequest) {
authInfo.role === 'owner';
if (!canDelete) {
- return NextResponse.json({ error: 'Permission denied' }, { status: 403 });
+ return AppResponse.json({ error: 'Permission denied' }, { status: 403 });
}
await db.deleteUserAvatar(targetUser);
- return NextResponse.json({ success: true, message: '头像删除成功' });
+ return AppResponse.json({ success: true, message: '头像删除成功' });
} catch (error) {
console.error('删除头像失败:', error);
- return NextResponse.json({ error: '删除头像失败' }, { status: 500 });
+ return AppResponse.json({ error: '删除头像失败' }, { status: 500 });
}
}
diff --git a/src/app/api/change-password/route.ts b/src/server/routes/api/change-password/route.ts
similarity index 68%
rename from src/app/api/change-password/route.ts
rename to src/server/routes/api/change-password/route.ts
index c9534f8..d6eea08 100644
--- a/src/app/api/change-password/route.ts
+++ b/src/server/routes/api/change-password/route.ts
@@ -1,18 +1,17 @@
/* eslint-disable no-console*/
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { getAuthInfoFromCookie } from '@/lib/auth';
import { db } from '@/lib/db';
-export const runtime = 'nodejs';
-export async function POST(request: NextRequest) {
- const storageType = process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage';
+export async function POST(request: AppRequest) {
+ const storageType = process.env.VITE_STORAGE_TYPE || 'localstorage';
// 不支持 localstorage 模式
if (storageType === 'localstorage') {
- return NextResponse.json(
+ return AppResponse.json(
{
error: '不支持本地存储模式修改密码',
},
@@ -27,19 +26,19 @@ export async function POST(request: NextRequest) {
// 获取认证信息
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
+ return AppResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
// 验证新密码
if (!newPassword || typeof newPassword !== 'string') {
- return NextResponse.json({ error: '新密码不得为空' }, { status: 400 });
+ return AppResponse.json({ error: '新密码不得为空' }, { status: 400 });
}
const username = authInfo.username;
// 不允许站长修改密码(站长用户名等于 process.env.USERNAME)
if (username === process.env.USERNAME) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '站长不能通过此接口修改密码' },
{ status: 403 }
);
@@ -48,10 +47,10 @@ export async function POST(request: NextRequest) {
// 修改密码
await db.changePassword(username, newPassword);
- return NextResponse.json({ ok: true });
+ return AppResponse.json({ ok: true });
} catch (error) {
console.error('修改密码失败:', error);
- return NextResponse.json(
+ return AppResponse.json(
{
error: '修改密码失败',
details: (error as Error).message,
diff --git a/src/app/api/chat/conversations/route.ts b/src/server/routes/api/chat/conversations/route.ts
similarity index 61%
rename from src/app/api/chat/conversations/route.ts
rename to src/server/routes/api/chat/conversations/route.ts
index 50c9325..5cafcc0 100644
--- a/src/app/api/chat/conversations/route.ts
+++ b/src/server/routes/api/chat/conversations/route.ts
@@ -1,34 +1,34 @@
-import { NextRequest, NextResponse } from 'next/server';
-import { db } from '../../../../lib/db';
-import { Conversation } from '../../../../lib/types';
-import { getAuthInfoFromCookie } from '../../../../lib/auth';
+import { AppRequest, AppResponse } from '@/server/web';
+import { db } from '@/lib/db';
+import { Conversation } from '@/lib/types';
+import { getAuthInfoFromCookie } from '@/lib/auth';
-export async function GET(request: NextRequest) {
+export async function GET(request: AppRequest) {
try {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: '未授权' }, { status: 401 });
+ return AppResponse.json({ error: '未授权' }, { status: 401 });
}
const conversations = await db.getConversations(authInfo.username);
- return NextResponse.json(conversations);
+ return AppResponse.json(conversations);
} catch (error) {
console.error('Error loading conversations:', error);
- return NextResponse.json({ error: '获取对话列表失败' }, { status: 500 });
+ return AppResponse.json({ error: '获取对话列表失败' }, { status: 500 });
}
}
-export async function POST(request: NextRequest) {
+export async function POST(request: AppRequest) {
try {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: '未授权' }, { status: 401 });
+ return AppResponse.json({ error: '未授权' }, { status: 401 });
}
const { participants, name, type } = await request.json();
if (!participants || !Array.isArray(participants) || participants.length === 0) {
- return NextResponse.json({ error: '参与者列表不能为空' }, { status: 400 });
+ return AppResponse.json({ error: '参与者列表不能为空' }, { status: 400 });
}
// 确保当前用户在参与者列表中
@@ -51,9 +51,9 @@ export async function POST(request: NextRequest) {
};
await db.createConversation(conversation);
- return NextResponse.json(conversation, { status: 201 });
+ return AppResponse.json(conversation, { status: 201 });
} catch (error) {
console.error('Error creating conversation:', error);
- return NextResponse.json({ error: '创建对话失败' }, { status: 500 });
+ return AppResponse.json({ error: '创建对话失败' }, { status: 500 });
}
}
diff --git a/src/app/api/chat/friend-requests/route.ts b/src/server/routes/api/chat/friend-requests/route.ts
similarity index 64%
rename from src/app/api/chat/friend-requests/route.ts
rename to src/server/routes/api/chat/friend-requests/route.ts
index fc95ba4..42e8ff3 100644
--- a/src/app/api/chat/friend-requests/route.ts
+++ b/src/server/routes/api/chat/friend-requests/route.ts
@@ -1,47 +1,47 @@
-import { NextRequest, NextResponse } from 'next/server';
-import { db } from '../../../../lib/db';
-import { FriendRequest, Friend } from '../../../../lib/types';
-import { getAuthInfoFromCookie } from '../../../../lib/auth';
+import { AppRequest, AppResponse } from '@/server/web';
+import { db } from '@/lib/db';
+import { FriendRequest, Friend } from '@/lib/types';
+import { getAuthInfoFromCookie } from '@/lib/auth';
-export async function GET(request: NextRequest) {
+export async function GET(request: AppRequest) {
try {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: '未授权' }, { status: 401 });
+ return AppResponse.json({ error: '未授权' }, { status: 401 });
}
const friendRequests = await db.getFriendRequests(authInfo.username);
- return NextResponse.json(friendRequests);
+ return AppResponse.json(friendRequests);
} catch (error) {
console.error('Error loading friend requests:', error);
- return NextResponse.json({ error: '获取好友申请失败' }, { status: 500 });
+ return AppResponse.json({ error: '获取好友申请失败' }, { status: 500 });
}
}
-export async function POST(request: NextRequest) {
+export async function POST(request: AppRequest) {
try {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: '未授权' }, { status: 401 });
+ return AppResponse.json({ error: '未授权' }, { status: 401 });
}
const { to_user, message } = await request.json();
if (!to_user) {
- return NextResponse.json({ error: '目标用户不能为空' }, { status: 400 });
+ return AppResponse.json({ error: '目标用户不能为空' }, { status: 400 });
}
// 检查目标用户是否存在
const userExists = await db.checkUserExist(to_user);
if (!userExists) {
- return NextResponse.json({ error: '目标用户不存在' }, { status: 404 });
+ return AppResponse.json({ error: '目标用户不存在' }, { status: 404 });
}
// 检查是否已经是好友
const friends = await db.getFriends(authInfo.username);
const isAlreadyFriend = friends.some(friend => friend.username === to_user);
if (isAlreadyFriend) {
- return NextResponse.json({ error: '已经是好友' }, { status: 400 });
+ return AppResponse.json({ error: '已经是好友' }, { status: 400 });
}
// 检查是否已经有pending的申请
@@ -50,7 +50,7 @@ export async function POST(request: NextRequest) {
req => req.from_user === authInfo.username && req.status === 'pending'
);
if (hasPendingRequest) {
- return NextResponse.json({ error: '已有待处理的好友申请' }, { status: 400 });
+ return AppResponse.json({ error: '已有待处理的好友申请' }, { status: 400 });
}
const friendRequest: FriendRequest = {
@@ -64,24 +64,24 @@ export async function POST(request: NextRequest) {
};
await db.createFriendRequest(friendRequest);
- return NextResponse.json(friendRequest, { status: 201 });
+ return AppResponse.json(friendRequest, { status: 201 });
} catch (error) {
console.error('Error creating friend request:', error);
- return NextResponse.json({ error: '发送好友申请失败' }, { status: 500 });
+ return AppResponse.json({ error: '发送好友申请失败' }, { status: 500 });
}
}
-export async function PUT(request: NextRequest) {
+export async function PUT(request: AppRequest) {
try {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: '未授权' }, { status: 401 });
+ return AppResponse.json({ error: '未授权' }, { status: 401 });
}
const { requestId, status } = await request.json();
if (!requestId || !status || !['accepted', 'rejected'].includes(status)) {
- return NextResponse.json({ error: '请求参数无效' }, { status: 400 });
+ return AppResponse.json({ error: '请求参数无效' }, { status: 400 });
}
// 获取申请信息
@@ -89,11 +89,11 @@ export async function PUT(request: NextRequest) {
const friendRequest = allRequests.find(req => req.id === requestId && req.to_user === authInfo.username);
if (!friendRequest) {
- return NextResponse.json({ error: '好友申请不存在' }, { status: 404 });
+ return AppResponse.json({ error: '好友申请不存在' }, { status: 404 });
}
if (friendRequest.status !== 'pending') {
- return NextResponse.json({ error: '申请已处理' }, { status: 400 });
+ return AppResponse.json({ error: '申请已处理' }, { status: 400 });
}
// 更新申请状态
@@ -122,9 +122,9 @@ export async function PUT(request: NextRequest) {
]);
}
- return NextResponse.json({ success: true });
+ return AppResponse.json({ success: true });
} catch (error) {
console.error('Error handling friend request:', error);
- return NextResponse.json({ error: '处理好友申请失败' }, { status: 500 });
+ return AppResponse.json({ error: '处理好友申请失败' }, { status: 500 });
}
}
diff --git a/src/app/api/chat/friends/route.ts b/src/server/routes/api/chat/friends/route.ts
similarity index 54%
rename from src/app/api/chat/friends/route.ts
rename to src/server/routes/api/chat/friends/route.ts
index 095ca26..7969bdb 100644
--- a/src/app/api/chat/friends/route.ts
+++ b/src/server/routes/api/chat/friends/route.ts
@@ -1,47 +1,47 @@
-import { NextRequest, NextResponse } from 'next/server';
-import { db } from '../../../../lib/db';
-import { Friend } from '../../../../lib/types';
-import { getAuthInfoFromCookie } from '../../../../lib/auth';
+import { AppRequest, AppResponse } from '@/server/web';
+import { db } from '@/lib/db';
+import { Friend } from '@/lib/types';
+import { getAuthInfoFromCookie } from '@/lib/auth';
-export async function GET(request: NextRequest) {
+export async function GET(request: AppRequest) {
try {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: '未授权' }, { status: 401 });
+ return AppResponse.json({ error: '未授权' }, { status: 401 });
}
const friends = await db.getFriends(authInfo.username);
- return NextResponse.json(friends);
+ return AppResponse.json(friends);
} catch (error) {
console.error('Error loading friends:', error);
- return NextResponse.json({ error: '获取好友列表失败' }, { status: 500 });
+ return AppResponse.json({ error: '获取好友列表失败' }, { status: 500 });
}
}
-export async function POST(request: NextRequest) {
+export async function POST(request: AppRequest) {
try {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: '未授权' }, { status: 401 });
+ return AppResponse.json({ error: '未授权' }, { status: 401 });
}
const { username, nickname } = await request.json();
if (!username) {
- return NextResponse.json({ error: '用户名不能为空' }, { status: 400 });
+ return AppResponse.json({ error: '用户名不能为空' }, { status: 400 });
}
// 检查用户是否存在
const userExists = await db.checkUserExist(username);
if (!userExists) {
- return NextResponse.json({ error: '用户不存在' }, { status: 404 });
+ return AppResponse.json({ error: '用户不存在' }, { status: 404 });
}
// 检查是否已经是好友
const friends = await db.getFriends(authInfo.username);
const isAlreadyFriend = friends.some(friend => friend.username === username);
if (isAlreadyFriend) {
- return NextResponse.json({ error: '已经是好友' }, { status: 400 });
+ return AppResponse.json({ error: '已经是好友' }, { status: 400 });
}
const friend: Friend = {
@@ -53,31 +53,31 @@ export async function POST(request: NextRequest) {
};
await db.addFriend(authInfo.username, friend);
- return NextResponse.json(friend, { status: 201 });
+ return AppResponse.json(friend, { status: 201 });
} catch (error) {
console.error('Error adding friend:', error);
- return NextResponse.json({ error: '添加好友失败' }, { status: 500 });
+ return AppResponse.json({ error: '添加好友失败' }, { status: 500 });
}
}
-export async function DELETE(request: NextRequest) {
+export async function DELETE(request: AppRequest) {
try {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: '未授权' }, { status: 401 });
+ return AppResponse.json({ error: '未授权' }, { status: 401 });
}
const { searchParams } = new URL(request.url);
const friendId = searchParams.get('friendId');
if (!friendId) {
- return NextResponse.json({ error: '好友 ID 不能为空' }, { status: 400 });
+ return AppResponse.json({ error: '好友 ID 不能为空' }, { status: 400 });
}
await db.removeFriend(authInfo.username, friendId);
- return NextResponse.json({ success: true });
+ return AppResponse.json({ success: true });
} catch (error) {
console.error('Error removing friend:', error);
- return NextResponse.json({ error: '删除好友失败' }, { status: 500 });
+ return AppResponse.json({ error: '删除好友失败' }, { status: 500 });
}
}
diff --git a/src/app/api/chat/messages/route.ts b/src/server/routes/api/chat/messages/route.ts
similarity index 69%
rename from src/app/api/chat/messages/route.ts
rename to src/server/routes/api/chat/messages/route.ts
index 92cac13..501f958 100644
--- a/src/app/api/chat/messages/route.ts
+++ b/src/server/routes/api/chat/messages/route.ts
@@ -1,14 +1,14 @@
-import { NextRequest, NextResponse } from 'next/server';
-import { db } from '../../../../lib/db';
-import { ChatMessage } from '../../../../lib/types';
-import { getAuthInfoFromCookie } from '../../../../lib/auth';
+import { AppRequest, AppResponse } from '@/server/web';
+import { db } from '@/lib/db';
+import { ChatMessage } from '@/lib/types';
+import { getAuthInfoFromCookie } from '@/lib/auth';
-export async function GET(request: NextRequest) {
+export async function GET(request: AppRequest) {
try {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
console.log('未授权访问消息API:', authInfo);
- return NextResponse.json({ error: '未授权' }, { status: 401 });
+ return AppResponse.json({ error: '未授权' }, { status: 401 });
}
const { searchParams } = new URL(request.url);
@@ -18,7 +18,7 @@ export async function GET(request: NextRequest) {
if (!conversationId) {
console.log('缺少对话ID参数');
- return NextResponse.json({ error: '对话 ID 不能为空' }, { status: 400 });
+ return AppResponse.json({ error: '对话 ID 不能为空' }, { status: 400 });
}
console.log('加载消息 - 用户:', authInfo.username, '对话ID:', conversationId);
@@ -30,7 +30,7 @@ export async function GET(request: NextRequest) {
console.log('对话查询结果:', conversation ? '找到对话' : '对话不存在');
} catch (dbError) {
console.error('数据库查询对话失败:', dbError);
- return NextResponse.json({
+ return AppResponse.json({
error: '数据库查询失败',
details: process.env.NODE_ENV === 'development' ? (dbError as Error).message : undefined
}, { status: 500 });
@@ -38,21 +38,21 @@ export async function GET(request: NextRequest) {
if (!conversation) {
console.log('对话不存在:', conversationId);
- return NextResponse.json({ error: '对话不存在' }, { status: 404 });
+ return AppResponse.json({ error: '对话不存在' }, { status: 404 });
}
if (!conversation.participants.includes(authInfo.username)) {
console.log('用户无权限访问对话:', authInfo.username, '参与者:', conversation.participants);
- return NextResponse.json({ error: '无权限访问此对话' }, { status: 403 });
+ return AppResponse.json({ error: '无权限访问此对话' }, { status: 403 });
}
try {
const messages = await db.getMessages(conversationId, limit, offset);
console.log(`成功加载 ${messages.length} 条消息`);
- return NextResponse.json(messages);
+ return AppResponse.json(messages);
} catch (dbError) {
console.error('数据库查询消息失败:', dbError);
- return NextResponse.json({
+ return AppResponse.json({
error: '获取消息失败',
details: process.env.NODE_ENV === 'development' ? (dbError as Error).message : undefined
}, { status: 500 });
@@ -60,30 +60,30 @@ export async function GET(request: NextRequest) {
} catch (error) {
console.error('加载消息API发生未知错误:', error);
- return NextResponse.json({
+ return AppResponse.json({
error: '获取消息失败',
details: process.env.NODE_ENV === 'development' ? (error as Error).message : undefined
}, { status: 500 });
}
}
-export async function POST(request: NextRequest) {
+export async function POST(request: AppRequest) {
try {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: '未授权' }, { status: 401 });
+ return AppResponse.json({ error: '未授权' }, { status: 401 });
}
const messageData = await request.json();
if (!messageData.conversation_id || !messageData.content) {
- return NextResponse.json({ error: '对话 ID 和消息内容不能为空' }, { status: 400 });
+ return AppResponse.json({ error: '对话 ID 和消息内容不能为空' }, { status: 400 });
}
// 验证用户是否有权限发送消息到此对话
const conversation = await db.getConversation(messageData.conversation_id);
if (!conversation || !conversation.participants.includes(authInfo.username)) {
- return NextResponse.json({ error: '无权限发送消息到此对话' }, { status: 403 });
+ return AppResponse.json({ error: '无权限发送消息到此对话' }, { status: 403 });
}
const message: ChatMessage = {
@@ -105,30 +105,30 @@ export async function POST(request: NextRequest) {
updated_at: Date.now(),
});
- return NextResponse.json(message, { status: 201 });
+ return AppResponse.json(message, { status: 201 });
} catch (error) {
console.error('Error sending message:', error);
- return NextResponse.json({ error: '发送消息失败' }, { status: 500 });
+ return AppResponse.json({ error: '发送消息失败' }, { status: 500 });
}
}
-export async function PUT(request: NextRequest) {
+export async function PUT(request: AppRequest) {
try {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: '未授权' }, { status: 401 });
+ return AppResponse.json({ error: '未授权' }, { status: 401 });
}
const { messageId } = await request.json();
if (!messageId) {
- return NextResponse.json({ error: '消息 ID 不能为空' }, { status: 400 });
+ return AppResponse.json({ error: '消息 ID 不能为空' }, { status: 400 });
}
await db.markMessageAsRead(messageId);
- return NextResponse.json({ success: true });
+ return AppResponse.json({ success: true });
} catch (error) {
console.error('Error marking message as read:', error);
- return NextResponse.json({ error: '标记消息已读失败' }, { status: 500 });
+ return AppResponse.json({ error: '标记消息已读失败' }, { status: 500 });
}
}
diff --git a/src/app/api/chat/online-users/route.ts b/src/server/routes/api/chat/online-users/route.ts
similarity index 63%
rename from src/app/api/chat/online-users/route.ts
rename to src/server/routes/api/chat/online-users/route.ts
index a64bff8..a77320b 100644
--- a/src/app/api/chat/online-users/route.ts
+++ b/src/server/routes/api/chat/online-users/route.ts
@@ -1,5 +1,5 @@
-import { NextRequest, NextResponse } from 'next/server';
-import { getAuthInfoFromCookie } from '../../../../lib/auth';
+import { AppRequest, AppResponse } from '@/server/web';
+import { getAuthInfoFromCookie } from '@/lib/auth';
// 从全局对象获取WebSocket实例相关方法
function getOnlineUsers(): string[] {
@@ -16,17 +16,17 @@ function getOnlineUsers(): string[] {
}
// 获取在线用户列表
-export async function GET(request: NextRequest) {
+export async function GET(request: AppRequest) {
try {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: '未授权' }, { status: 401 });
+ return AppResponse.json({ error: '未授权' }, { status: 401 });
}
const onlineUsers = getOnlineUsers();
- return NextResponse.json({ onlineUsers });
+ return AppResponse.json({ onlineUsers });
} catch (error) {
console.error('获取在线用户失败:', error);
- return NextResponse.json({ error: '获取在线用户失败' }, { status: 500 });
+ return AppResponse.json({ error: '获取在线用户失败' }, { status: 500 });
}
}
diff --git a/src/app/api/chat/search-users/route.ts b/src/server/routes/api/chat/search-users/route.ts
similarity index 61%
rename from src/app/api/chat/search-users/route.ts
rename to src/server/routes/api/chat/search-users/route.ts
index 3d7f74a..287c8b0 100644
--- a/src/app/api/chat/search-users/route.ts
+++ b/src/server/routes/api/chat/search-users/route.ts
@@ -1,19 +1,19 @@
-import { NextRequest, NextResponse } from 'next/server';
-import { db } from '../../../../lib/db';
-import { getAuthInfoFromCookie } from '../../../../lib/auth';
+import { AppRequest, AppResponse } from '@/server/web';
+import { db } from '@/lib/db';
+import { getAuthInfoFromCookie } from '@/lib/auth';
-export async function GET(request: NextRequest) {
+export async function GET(request: AppRequest) {
try {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: '未授权' }, { status: 401 });
+ return AppResponse.json({ error: '未授权' }, { status: 401 });
}
const { searchParams } = new URL(request.url);
const query = searchParams.get('q');
if (!query || query.trim().length < 2) {
- return NextResponse.json({ error: '搜索关键词至少需要2个字符' }, { status: 400 });
+ return AppResponse.json({ error: '搜索关键词至少需要2个字符' }, { status: 400 });
}
// 获取所有用户并进行模糊匹配
@@ -31,9 +31,9 @@ export async function GET(request: NextRequest) {
added_at: 0,
}));
- return NextResponse.json(userResults);
+ return AppResponse.json(userResults);
} catch (error) {
console.error('Error searching users:', error);
- return NextResponse.json({ error: '搜索用户失败' }, { status: 500 });
+ return AppResponse.json({ error: '搜索用户失败' }, { status: 500 });
}
}
diff --git a/src/app/api/chat/send-message/route.ts b/src/server/routes/api/chat/send-message/route.ts
similarity index 75%
rename from src/app/api/chat/send-message/route.ts
rename to src/server/routes/api/chat/send-message/route.ts
index 8c3786e..07a2d7f 100644
--- a/src/app/api/chat/send-message/route.ts
+++ b/src/server/routes/api/chat/send-message/route.ts
@@ -1,6 +1,6 @@
-import { NextRequest, NextResponse } from 'next/server';
-import { getAuthInfoFromCookie } from '../../../../lib/auth';
-import { WebSocketMessage } from '../../../../lib/types';
+import { AppRequest, AppResponse } from '@/server/web';
+import { getAuthInfoFromCookie } from '@/lib/auth';
+import { WebSocketMessage } from '@/lib/types';
// 从全局对象获取WebSocket实例相关方法
function sendMessageToUsers(userIds: string[], message: WebSocketMessage): boolean {
@@ -17,11 +17,11 @@ function sendMessageToUsers(userIds: string[], message: WebSocketMessage): boole
}
// 发送消息的备用 API 路由,在 WebSocket 不可用时使用
-export async function POST(request: NextRequest) {
+export async function POST(request: AppRequest) {
try {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: '未授权' }, { status: 401 });
+ return AppResponse.json({ error: '未授权' }, { status: 401 });
}
const message: WebSocketMessage = await request.json();
@@ -52,18 +52,18 @@ export async function POST(request: NextRequest) {
break;
default:
- return NextResponse.json({ error: '不支持的消息类型' }, { status: 400 });
+ return AppResponse.json({ error: '不支持的消息类型' }, { status: 400 });
}
// 通过 WebSocket 发送消息
const sent = sendMessageToUsers(targetUsers, message);
- return NextResponse.json({
+ return AppResponse.json({
success: true,
delivered: sent
});
} catch (error) {
console.error('通过 API 发送消息失败:', error);
- return NextResponse.json({ error: '发送消息失败' }, { status: 500 });
+ return AppResponse.json({ error: '发送消息失败' }, { status: 500 });
}
}
diff --git a/src/app/api/cron/route.ts b/src/server/routes/api/cron/route.ts
similarity index 97%
rename from src/app/api/cron/route.ts
rename to src/server/routes/api/cron/route.ts
index aca9a32..a73b455 100644
--- a/src/app/api/cron/route.ts
+++ b/src/server/routes/api/cron/route.ts
@@ -1,6 +1,6 @@
/* eslint-disable no-console,@typescript-eslint/no-explicit-any */
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { getConfig, refineConfig } from '@/lib/config';
import { db } from '@/lib/db';
@@ -8,16 +8,15 @@ import { fetchVideoDetail } from '@/lib/fetchVideoDetail';
import { refreshLiveChannels } from '@/lib/live';
import { SearchResult } from '@/lib/types';
-export const runtime = 'nodejs';
-export async function GET(request: NextRequest) {
+export async function GET(request: AppRequest) {
console.log(request.url);
try {
console.log('Cron job triggered:', new Date().toISOString());
cronJob();
- return NextResponse.json({
+ return AppResponse.json({
success: true,
message: 'Cron job executed successfully',
timestamp: new Date().toISOString(),
@@ -25,7 +24,7 @@ export async function GET(request: NextRequest) {
} catch (error) {
console.error('Cron job failed:', error);
- return NextResponse.json(
+ return AppResponse.json(
{
success: false,
message: 'Cron job failed',
diff --git a/src/app/api/danmu/route.ts b/src/server/routes/api/danmu/route.ts
similarity index 59%
rename from src/app/api/danmu/route.ts
rename to src/server/routes/api/danmu/route.ts
index e706647..7de4312 100644
--- a/src/app/api/danmu/route.ts
+++ b/src/server/routes/api/danmu/route.ts
@@ -1,18 +1,17 @@
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { getAuthInfoFromCookie } from '@/lib/auth';
import { db } from '@/lib/db';
-export const runtime = 'nodejs';
// 获取弹幕
-export async function GET(request: NextRequest) {
+export async function GET(request: AppRequest) {
try {
const { searchParams } = new URL(request.url);
const videoId = searchParams.get('videoId');
if (!videoId) {
- return NextResponse.json({ error: '视频ID不能为空' }, { status: 400 });
+ return AppResponse.json({ error: '视频ID不能为空' }, { status: 400 });
}
const danmuList = await db.getDanmu(videoId);
@@ -27,38 +26,38 @@ export async function GET(request: NextRequest) {
size: 25
}));
- return NextResponse.json(formattedDanmu);
+ return AppResponse.json(formattedDanmu);
} catch (error) {
console.error('获取弹幕失败:', error);
- return NextResponse.json({ error: '获取弹幕失败' }, { status: 500 });
+ return AppResponse.json({ error: '获取弹幕失败' }, { status: 500 });
}
}
// 发送弹幕
-export async function POST(request: NextRequest) {
+export async function POST(request: AppRequest) {
try {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
+ return AppResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const body = await request.json();
const { videoId, text, color, mode, time } = body;
if (!videoId || !text) {
- return NextResponse.json({ error: '视频ID和弹幕内容不能为空' }, { status: 400 });
+ return AppResponse.json({ error: '视频ID和弹幕内容不能为空' }, { status: 400 });
}
// 验证弹幕内容长度
if (text.length > 100) {
- return NextResponse.json({ error: '弹幕内容不能超过100个字符' }, { status: 400 });
+ return AppResponse.json({ error: '弹幕内容不能超过100个字符' }, { status: 400 });
}
// 过滤敏感内容(可以扩展)
const sensitiveWords = ['垃圾', '傻逼', '草泥马', '操你妈']; // 示例敏感词
const hasSensitiveWord = sensitiveWords.some(word => text.includes(word));
if (hasSensitiveWord) {
- return NextResponse.json({ error: '弹幕内容包含敏感词汇' }, { status: 400 });
+ return AppResponse.json({ error: '弹幕内容包含敏感词汇' }, { status: 400 });
}
const danmuData = {
@@ -71,24 +70,24 @@ export async function POST(request: NextRequest) {
await db.saveDanmu(videoId, authInfo.username, danmuData);
- return NextResponse.json({ success: true, message: '弹幕发送成功' });
+ return AppResponse.json({ success: true, message: '弹幕发送成功' });
} catch (error) {
console.error('发送弹幕失败:', error);
- return NextResponse.json({ error: '发送弹幕失败' }, { status: 500 });
+ return AppResponse.json({ error: '发送弹幕失败' }, { status: 500 });
}
}
// 删除弹幕(管理员功能)
-export async function DELETE(request: NextRequest) {
+export async function DELETE(request: AppRequest) {
try {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
+ return AppResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
// 只有管理员和站长可以删除弹幕
if (authInfo.role !== 'admin' && authInfo.role !== 'owner') {
- return NextResponse.json({ error: 'Permission denied' }, { status: 403 });
+ return AppResponse.json({ error: 'Permission denied' }, { status: 403 });
}
const { searchParams } = new URL(request.url);
@@ -96,14 +95,14 @@ export async function DELETE(request: NextRequest) {
const danmuId = searchParams.get('danmuId');
if (!videoId || !danmuId) {
- return NextResponse.json({ error: '视频ID和弹幕ID不能为空' }, { status: 400 });
+ return AppResponse.json({ error: '视频ID和弹幕ID不能为空' }, { status: 400 });
}
await db.deleteDanmu(videoId, danmuId);
- return NextResponse.json({ success: true, message: '弹幕删除成功' });
+ return AppResponse.json({ success: true, message: '弹幕删除成功' });
} catch (error) {
console.error('删除弹幕失败:', error);
- return NextResponse.json({ error: '删除弹幕失败' }, { status: 500 });
+ return AppResponse.json({ error: '删除弹幕失败' }, { status: 500 });
}
}
diff --git a/src/app/api/detail/route.ts b/src/server/routes/api/detail/route.ts
similarity index 68%
rename from src/app/api/detail/route.ts
rename to src/server/routes/api/detail/route.ts
index 59dba3b..ff81e3d 100644
--- a/src/app/api/detail/route.ts
+++ b/src/server/routes/api/detail/route.ts
@@ -1,15 +1,14 @@
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { getAuthInfoFromCookie } from '@/lib/auth';
import { getAvailableApiSites, getCacheTime } from '@/lib/config';
import { getDetailFromApi } from '@/lib/downstream';
-export const runtime = 'nodejs';
-export async function GET(request: NextRequest) {
+export async function GET(request: AppRequest) {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
+ return AppResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const { searchParams } = new URL(request.url);
@@ -17,11 +16,11 @@ export async function GET(request: NextRequest) {
const sourceCode = searchParams.get('source');
if (!id || !sourceCode) {
- return NextResponse.json({ error: '缺少必要参数' }, { status: 400 });
+ return AppResponse.json({ error: '缺少必要参数' }, { status: 400 });
}
if (!/^[\w-]+$/.test(id)) {
- return NextResponse.json({ error: '无效的视频ID格式' }, { status: 400 });
+ return AppResponse.json({ error: '无效的视频ID格式' }, { status: 400 });
}
try {
@@ -29,13 +28,13 @@ export async function GET(request: NextRequest) {
const apiSite = apiSites.find((site) => site.key === sourceCode);
if (!apiSite) {
- return NextResponse.json({ error: '无效的API来源' }, { status: 400 });
+ return AppResponse.json({ error: '无效的API来源' }, { status: 400 });
}
const result = await getDetailFromApi(apiSite, id);
const cacheTime = await getCacheTime();
- return NextResponse.json(result, {
+ return AppResponse.json(result, {
headers: {
'Cache-Control': `public, max-age=${cacheTime}, s-maxage=${cacheTime}`,
'CDN-Cache-Control': `public, s-maxage=${cacheTime}`,
@@ -44,7 +43,7 @@ export async function GET(request: NextRequest) {
},
});
} catch (error) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: (error as Error).message },
{ status: 500 }
);
diff --git a/src/app/api/douban/categories/route.ts b/src/server/routes/api/douban/categories/route.ts
similarity index 90%
rename from src/app/api/douban/categories/route.ts
rename to src/server/routes/api/douban/categories/route.ts
index 3af8b6f..0b317bb 100644
--- a/src/app/api/douban/categories/route.ts
+++ b/src/server/routes/api/douban/categories/route.ts
@@ -1,4 +1,4 @@
-import { NextResponse } from 'next/server';
+import { AppResponse } from '@/server/web';
import { getCacheTime } from '@/lib/config';
import { fetchDoubanData } from '@/lib/douban';
@@ -20,7 +20,6 @@ interface DoubanCategoryApiResponse {
}>;
}
-export const runtime = 'nodejs';
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
@@ -34,28 +33,28 @@ export async function GET(request: Request) {
// 验证参数
if (!kind || !category || !type) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '缺少必要参数: kind 或 category 或 type' },
{ status: 400 }
);
}
if (!['tv', 'movie'].includes(kind)) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'kind 参数必须是 tv 或 movie' },
{ status: 400 }
);
}
if (pageLimit < 1 || pageLimit > 100) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'pageSize 必须在 1-100 之间' },
{ status: 400 }
);
}
if (pageStart < 0) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'pageStart 不能小于 0' },
{ status: 400 }
);
@@ -83,7 +82,7 @@ export async function GET(request: Request) {
};
const cacheTime = await getCacheTime();
- return NextResponse.json(response, {
+ return AppResponse.json(response, {
headers: {
'Cache-Control': `public, max-age=${cacheTime}, s-maxage=${cacheTime}`,
'CDN-Cache-Control': `public, s-maxage=${cacheTime}`,
@@ -92,7 +91,7 @@ export async function GET(request: Request) {
},
});
} catch (error) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '获取豆瓣数据失败', details: (error as Error).message },
{ status: 500 }
);
diff --git a/src/app/api/douban/recommends/route.ts b/src/server/routes/api/douban/recommends/route.ts
similarity index 92%
rename from src/app/api/douban/recommends/route.ts
rename to src/server/routes/api/douban/recommends/route.ts
index 34f16c5..49c9a69 100644
--- a/src/app/api/douban/recommends/route.ts
+++ b/src/server/routes/api/douban/recommends/route.ts
@@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any,no-console */
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { getCacheTime } from '@/lib/config';
import { fetchDoubanData } from '@/lib/douban';
@@ -23,9 +23,8 @@ interface DoubanRecommendApiResponse {
}>;
}
-export const runtime = 'nodejs';
-export async function GET(request: NextRequest) {
+export async function GET(request: AppRequest) {
const { searchParams } = new URL(request.url);
// 获取参数
@@ -47,7 +46,7 @@ export async function GET(request: NextRequest) {
searchParams.get('label') === 'all' ? '' : searchParams.get('label');
if (!kind) {
- return NextResponse.json({ error: '缺少必要参数: kind' }, { status: 400 });
+ return AppResponse.json({ error: '缺少必要参数: kind' }, { status: 400 });
}
const selectedCategories = { 类型: category } as any;
@@ -113,7 +112,7 @@ export async function GET(request: NextRequest) {
};
const cacheTime = await getCacheTime();
- return NextResponse.json(response, {
+ return AppResponse.json(response, {
headers: {
'Cache-Control': `public, max-age=${cacheTime}, s-maxage=${cacheTime}`,
'CDN-Cache-Control': `public, s-maxage=${cacheTime}`,
@@ -122,7 +121,7 @@ export async function GET(request: NextRequest) {
},
});
} catch (error) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '获取豆瓣数据失败', details: (error as Error).message },
{ status: 500 }
);
diff --git a/src/app/api/douban/route.ts b/src/server/routes/api/douban/route.ts
similarity index 93%
rename from src/app/api/douban/route.ts
rename to src/server/routes/api/douban/route.ts
index 8cf24fb..2855626 100644
--- a/src/app/api/douban/route.ts
+++ b/src/server/routes/api/douban/route.ts
@@ -1,4 +1,4 @@
-import { NextResponse } from 'next/server';
+import { AppResponse } from '@/server/web';
import { getCacheTime } from '@/lib/config';
import { fetchDoubanData } from '@/lib/douban';
@@ -13,7 +13,6 @@ interface DoubanApiResponse {
}>;
}
-export const runtime = 'nodejs';
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
@@ -26,28 +25,28 @@ export async function GET(request: Request) {
// 验证参数
if (!type || !tag) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '缺少必要参数: type 或 tag' },
{ status: 400 }
);
}
if (!['tv', 'movie'].includes(type)) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'type 参数必须是 tv 或 movie' },
{ status: 400 }
);
}
if (pageSize < 1 || pageSize > 100) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'pageSize 必须在 1-100 之间' },
{ status: 400 }
);
}
if (pageStart < 0) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'pageStart 不能小于 0' },
{ status: 400 }
);
@@ -79,7 +78,7 @@ export async function GET(request: Request) {
};
const cacheTime = await getCacheTime();
- return NextResponse.json(response, {
+ return AppResponse.json(response, {
headers: {
'Cache-Control': `public, max-age=${cacheTime}, s-maxage=${cacheTime}`,
'CDN-Cache-Control': `public, s-maxage=${cacheTime}`,
@@ -88,7 +87,7 @@ export async function GET(request: Request) {
},
});
} catch (error) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '获取豆瓣数据失败', details: (error as Error).message },
{ status: 500 }
);
@@ -155,7 +154,7 @@ function handleTop250(pageStart: number) {
};
const cacheTime = await getCacheTime();
- return NextResponse.json(apiResponse, {
+ return AppResponse.json(apiResponse, {
headers: {
'Cache-Control': `public, max-age=${cacheTime}, s-maxage=${cacheTime}`,
'CDN-Cache-Control': `public, s-maxage=${cacheTime}`,
@@ -166,7 +165,7 @@ function handleTop250(pageStart: number) {
})
.catch((error) => {
clearTimeout(timeoutId);
- return NextResponse.json(
+ return AppResponse.json(
{
error: '获取豆瓣 Top250 数据失败',
details: (error as Error).message,
diff --git a/src/app/api/favorites/route.ts b/src/server/routes/api/favorites/route.ts
similarity index 74%
rename from src/app/api/favorites/route.ts
rename to src/server/routes/api/favorites/route.ts
index 4bd7724..aa17e40 100644
--- a/src/app/api/favorites/route.ts
+++ b/src/server/routes/api/favorites/route.ts
@@ -1,13 +1,12 @@
/* eslint-disable no-console */
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { getAuthInfoFromCookie } from '@/lib/auth';
import { getConfig } from '@/lib/config';
import { db } from '@/lib/db';
import { Favorite } from '@/lib/types';
-export const runtime = 'nodejs';
/**
* GET /api/favorites
@@ -16,12 +15,12 @@ export const runtime = 'nodejs';
* 1. 不带 query,返回全部收藏列表(Record)。
* 2. 带 key=source+id,返回单条收藏(Favorite | null)。
*/
-export async function GET(request: NextRequest) {
+export async function GET(request: AppRequest) {
try {
// 从 cookie 获取用户信息
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
+ return AppResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const config = await getConfig();
@@ -31,10 +30,10 @@ export async function GET(request: NextRequest) {
(u) => u.username === authInfo.username
);
if (!user) {
- return NextResponse.json({ error: '用户不存在' }, { status: 401 });
+ return AppResponse.json({ error: '用户不存在' }, { status: 401 });
}
if (user.banned) {
- return NextResponse.json({ error: '用户已被封禁' }, { status: 401 });
+ return AppResponse.json({ error: '用户已被封禁' }, { status: 401 });
}
}
@@ -45,21 +44,21 @@ export async function GET(request: NextRequest) {
if (key) {
const [source, id] = key.split('+');
if (!source || !id) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'Invalid key format' },
{ status: 400 }
);
}
const fav = await db.getFavorite(authInfo.username, source, id);
- return NextResponse.json(fav, { status: 200 });
+ return AppResponse.json(fav, { status: 200 });
}
// 查询全部收藏
const favorites = await db.getAllFavorites(authInfo.username);
- return NextResponse.json(favorites, { status: 200 });
+ return AppResponse.json(favorites, { status: 200 });
} catch (err) {
console.error('获取收藏失败', err);
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'Internal Server Error' },
{ status: 500 }
);
@@ -70,12 +69,12 @@ export async function GET(request: NextRequest) {
* POST /api/favorites
* body: { key: string; favorite: Favorite }
*/
-export async function POST(request: NextRequest) {
+export async function POST(request: AppRequest) {
try {
// 从 cookie 获取用户信息
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
+ return AppResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const config = await getConfig();
@@ -85,10 +84,10 @@ export async function POST(request: NextRequest) {
(u) => u.username === authInfo.username
);
if (!user) {
- return NextResponse.json({ error: '用户不存在' }, { status: 401 });
+ return AppResponse.json({ error: '用户不存在' }, { status: 401 });
}
if (user.banned) {
- return NextResponse.json({ error: '用户已被封禁' }, { status: 401 });
+ return AppResponse.json({ error: '用户已被封禁' }, { status: 401 });
}
}
@@ -96,7 +95,7 @@ export async function POST(request: NextRequest) {
const { key, favorite }: { key: string; favorite: Favorite } = body;
if (!key || !favorite) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'Missing key or favorite' },
{ status: 400 }
);
@@ -104,7 +103,7 @@ export async function POST(request: NextRequest) {
// 验证必要字段
if (!favorite.title || !favorite.source_name) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'Invalid favorite data' },
{ status: 400 }
);
@@ -112,7 +111,7 @@ export async function POST(request: NextRequest) {
const [source, id] = key.split('+');
if (!source || !id) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'Invalid key format' },
{ status: 400 }
);
@@ -125,10 +124,10 @@ export async function POST(request: NextRequest) {
await db.saveFavorite(authInfo.username, source, id, finalFavorite);
- return NextResponse.json({ success: true }, { status: 200 });
+ return AppResponse.json({ success: true }, { status: 200 });
} catch (err) {
console.error('保存收藏失败', err);
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'Internal Server Error' },
{ status: 500 }
);
@@ -141,12 +140,12 @@ export async function POST(request: NextRequest) {
* 1. 不带 query -> 清空全部收藏
* 2. 带 key=source+id -> 删除单条收藏
*/
-export async function DELETE(request: NextRequest) {
+export async function DELETE(request: AppRequest) {
try {
// 从 cookie 获取用户信息
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
+ return AppResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const config = await getConfig();
@@ -156,10 +155,10 @@ export async function DELETE(request: NextRequest) {
(u) => u.username === authInfo.username
);
if (!user) {
- return NextResponse.json({ error: '用户不存在' }, { status: 401 });
+ return AppResponse.json({ error: '用户不存在' }, { status: 401 });
}
if (user.banned) {
- return NextResponse.json({ error: '用户已被封禁' }, { status: 401 });
+ return AppResponse.json({ error: '用户已被封禁' }, { status: 401 });
}
}
@@ -171,7 +170,7 @@ export async function DELETE(request: NextRequest) {
// 删除单条
const [source, id] = key.split('+');
if (!source || !id) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'Invalid key format' },
{ status: 400 }
);
@@ -188,10 +187,10 @@ export async function DELETE(request: NextRequest) {
);
}
- return NextResponse.json({ success: true }, { status: 200 });
+ return AppResponse.json({ success: true }, { status: 200 });
} catch (err) {
console.error('删除收藏失败', err);
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'Internal Server Error' },
{ status: 500 }
);
diff --git a/src/server/routes/api/health/route.ts b/src/server/routes/api/health/route.ts
new file mode 100644
index 0000000..e16d532
--- /dev/null
+++ b/src/server/routes/api/health/route.ts
@@ -0,0 +1,9 @@
+import { AppResponse } from '@/server/web';
+
+export async function GET() {
+ return AppResponse.json({
+ status: 'ok',
+ timestamp: new Date().toISOString(),
+ message: 'Fastify server is running'
+ });
+}
diff --git a/src/app/api/image-proxy/route.ts b/src/server/routes/api/image-proxy/route.ts
similarity index 85%
rename from src/app/api/image-proxy/route.ts
rename to src/server/routes/api/image-proxy/route.ts
index 2bf73b3..07ddd25 100644
--- a/src/app/api/image-proxy/route.ts
+++ b/src/server/routes/api/image-proxy/route.ts
@@ -1,6 +1,5 @@
-import { NextResponse } from 'next/server';
+import { AppResponse } from '@/server/web';
-export const runtime = 'nodejs';
// OrionTV 兼容接口
export async function GET(request: Request) {
@@ -8,7 +7,7 @@ export async function GET(request: Request) {
const imageUrl = searchParams.get('url');
if (!imageUrl) {
- return NextResponse.json({ error: 'Missing image URL' }, { status: 400 });
+ return AppResponse.json({ error: 'Missing image URL' }, { status: 400 });
}
try {
@@ -21,7 +20,7 @@ export async function GET(request: Request) {
});
if (!imageResponse.ok) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: imageResponse.statusText },
{ status: imageResponse.status }
);
@@ -30,7 +29,7 @@ export async function GET(request: Request) {
const contentType = imageResponse.headers.get('content-type');
if (!imageResponse.body) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'Image response has no body' },
{ status: 500 }
);
@@ -54,7 +53,7 @@ export async function GET(request: Request) {
headers,
});
} catch (error) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'Error fetching image' },
{ status: 500 }
);
diff --git a/src/app/api/live/channels/route.ts b/src/server/routes/api/live/channels/route.ts
similarity index 54%
rename from src/app/api/live/channels/route.ts
rename to src/server/routes/api/live/channels/route.ts
index fc2b20f..d12d89e 100644
--- a/src/app/api/live/channels/route.ts
+++ b/src/server/routes/api/live/channels/route.ts
@@ -1,30 +1,29 @@
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { getCachedLiveChannels } from '@/lib/live';
-export const runtime = 'nodejs';
-export async function GET(request: NextRequest) {
+export async function GET(request: AppRequest) {
try {
const { searchParams } = new URL(request.url);
const sourceKey = searchParams.get('source');
if (!sourceKey) {
- return NextResponse.json({ error: '缺少直播源参数' }, { status: 400 });
+ return AppResponse.json({ error: '缺少直播源参数' }, { status: 400 });
}
const channelData = await getCachedLiveChannels(sourceKey);
if (!channelData) {
- return NextResponse.json({ error: '频道信息未找到' }, { status: 404 });
+ return AppResponse.json({ error: '频道信息未找到' }, { status: 404 });
}
- return NextResponse.json({
+ return AppResponse.json({
success: true,
data: channelData.channels
});
} catch (error) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '获取频道信息失败' },
{ status: 500 }
);
diff --git a/src/app/api/live/epg/route.ts b/src/server/routes/api/live/epg/route.ts
similarity index 69%
rename from src/app/api/live/epg/route.ts
rename to src/server/routes/api/live/epg/route.ts
index 62c6560..732fe37 100644
--- a/src/app/api/live/epg/route.ts
+++ b/src/server/routes/api/live/epg/route.ts
@@ -1,28 +1,27 @@
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { getCachedLiveChannels } from '@/lib/live';
-export const runtime = 'nodejs';
-export async function GET(request: NextRequest) {
+export async function GET(request: AppRequest) {
try {
const { searchParams } = new URL(request.url);
const sourceKey = searchParams.get('source');
const tvgId = searchParams.get('tvgId');
if (!sourceKey) {
- return NextResponse.json({ error: '缺少直播源参数' }, { status: 400 });
+ return AppResponse.json({ error: '缺少直播源参数' }, { status: 400 });
}
if (!tvgId) {
- return NextResponse.json({ error: '缺少频道tvg-id参数' }, { status: 400 });
+ return AppResponse.json({ error: '缺少频道tvg-id参数' }, { status: 400 });
}
const channelData = await getCachedLiveChannels(sourceKey);
if (!channelData) {
// 频道信息未找到时返回空的节目单数据
- return NextResponse.json({
+ return AppResponse.json({
success: true,
data: {
tvgId,
@@ -36,7 +35,7 @@ export async function GET(request: NextRequest) {
// 从epgs字段中获取对应tvgId的节目单信息
const epgData = channelData.epgs[tvgId] || [];
- return NextResponse.json({
+ return AppResponse.json({
success: true,
data: {
tvgId,
@@ -46,7 +45,7 @@ export async function GET(request: NextRequest) {
}
});
} catch (error) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '获取节目单信息失败' },
{ status: 500 }
);
diff --git a/src/app/api/live/precheck/route.ts b/src/server/routes/api/live/precheck/route.ts
similarity index 58%
rename from src/app/api/live/precheck/route.ts
rename to src/server/routes/api/live/precheck/route.ts
index 57f6fc1..6ff5cae 100644
--- a/src/app/api/live/precheck/route.ts
+++ b/src/server/routes/api/live/precheck/route.ts
@@ -1,23 +1,22 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { getConfig } from '@/lib/config';
-export const runtime = 'nodejs';
-export async function GET(request: NextRequest) {
+export async function GET(request: AppRequest) {
const { searchParams } = new URL(request.url);
const url = searchParams.get('url');
const source = searchParams.get('OrangeTV-source');
if (!url) {
- return NextResponse.json({ error: 'Missing url' }, { status: 400 });
+ return AppResponse.json({ error: 'Missing url' }, { status: 400 });
}
const config = await getConfig();
const liveSource = config.LiveConfig?.find((s: any) => s.key === source);
if (!liveSource) {
- return NextResponse.json({ error: 'Source not found' }, { status: 404 });
+ return AppResponse.json({ error: 'Source not found' }, { status: 404 });
}
const ua = liveSource.ua || 'AptvPlayer/1.4.10';
@@ -34,7 +33,7 @@ export async function GET(request: NextRequest) {
});
if (!response.ok) {
- return NextResponse.json({ error: 'Failed to fetch', message: response.statusText }, { status: 500 });
+ return AppResponse.json({ error: 'Failed to fetch', message: response.statusText }, { status: 500 });
}
const contentType = response.headers.get('Content-Type');
@@ -42,13 +41,13 @@ export async function GET(request: NextRequest) {
response.body.cancel();
}
if (contentType?.includes('video/mp4')) {
- return NextResponse.json({ success: true, type: 'mp4' }, { status: 200 });
+ return AppResponse.json({ success: true, type: 'mp4' }, { status: 200 });
}
if (contentType?.includes('video/x-flv')) {
- return NextResponse.json({ success: true, type: 'flv' }, { status: 200 });
+ return AppResponse.json({ success: true, type: 'flv' }, { status: 200 });
}
- return NextResponse.json({ success: true, type: 'm3u8' }, { status: 200 });
+ return AppResponse.json({ success: true, type: 'm3u8' }, { status: 200 });
} catch (error) {
- return NextResponse.json({ error: 'Failed to fetch', message: error }, { status: 500 });
+ return AppResponse.json({ error: 'Failed to fetch', message: error }, { status: 500 });
}
}
\ No newline at end of file
diff --git a/src/app/api/live/sources/route.ts b/src/server/routes/api/live/sources/route.ts
similarity index 64%
rename from src/app/api/live/sources/route.ts
rename to src/server/routes/api/live/sources/route.ts
index 1bd17b8..7f5fb73 100644
--- a/src/app/api/live/sources/route.ts
+++ b/src/server/routes/api/live/sources/route.ts
@@ -1,30 +1,29 @@
/* eslint-disable no-console */
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { getConfig } from '@/lib/config';
-export const runtime = 'nodejs';
-export async function GET(request: NextRequest) {
+export async function GET(request: AppRequest) {
console.log(request.url)
try {
const config = await getConfig();
if (!config) {
- return NextResponse.json({ error: '配置未找到' }, { status: 404 });
+ return AppResponse.json({ error: '配置未找到' }, { status: 404 });
}
// 过滤出所有非 disabled 的直播源
const liveSources = (config.LiveConfig || []).filter(source => !source.disabled);
- return NextResponse.json({
+ return AppResponse.json({
success: true,
data: liveSources
});
} catch (error) {
console.error('获取直播源失败:', error);
- return NextResponse.json(
+ return AppResponse.json(
{ error: '获取直播源失败' },
{ status: 500 }
);
diff --git a/src/app/api/login/route.ts b/src/server/routes/api/login/route.ts
similarity index 85%
rename from src/app/api/login/route.ts
rename to src/server/routes/api/login/route.ts
index a0d27b3..d6883ee 100644
--- a/src/app/api/login/route.ts
+++ b/src/server/routes/api/login/route.ts
@@ -1,14 +1,13 @@
/* eslint-disable no-console,@typescript-eslint/no-explicit-any */
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { getConfig } from '@/lib/config';
import { db } from '@/lib/db';
-export const runtime = 'nodejs';
// 读取存储类型环境变量,默认 localstorage
const STORAGE_TYPE =
- (process.env.NEXT_PUBLIC_STORAGE_TYPE as
+ (process.env.VITE_STORAGE_TYPE as
| 'localstorage'
| 'redis'
| 'upstash'
@@ -67,7 +66,7 @@ async function generateAuthCookie(
return encodeURIComponent(JSON.stringify(authData));
}
-export async function POST(req: NextRequest) {
+export async function POST(req: AppRequest) {
try {
// 本地 / localStorage 模式——仅校验固定密码
if (STORAGE_TYPE === 'localstorage') {
@@ -75,7 +74,7 @@ export async function POST(req: NextRequest) {
// 未配置 PASSWORD 时直接放行
if (!envPassword) {
- const response = NextResponse.json({ ok: true });
+ const response = AppResponse.json({ ok: true });
// 清除可能存在的认证cookie
response.cookies.set('auth', '', {
@@ -91,18 +90,18 @@ export async function POST(req: NextRequest) {
const { password } = await req.json();
if (typeof password !== 'string') {
- return NextResponse.json({ error: '密码不能为空' }, { status: 400 });
+ return AppResponse.json({ error: '密码不能为空' }, { status: 400 });
}
if (password !== envPassword) {
- return NextResponse.json(
+ return AppResponse.json(
{ ok: false, error: '密码错误' },
{ status: 401 }
);
}
// 验证成功,设置认证cookie
- const response = NextResponse.json({ ok: true });
+ const response = AppResponse.json({ ok: true });
const cookieValue = await generateAuthCookie(
undefined,
password,
@@ -127,10 +126,10 @@ export async function POST(req: NextRequest) {
const { username, password, machineCode } = await req.json();
if (!username || typeof username !== 'string') {
- return NextResponse.json({ error: '用户名不能为空' }, { status: 400 });
+ return AppResponse.json({ error: '用户名不能为空' }, { status: 400 });
}
if (!password || typeof password !== 'string') {
- return NextResponse.json({ error: '密码不能为空' }, { status: 400 });
+ return AppResponse.json({ error: '密码不能为空' }, { status: 400 });
}
// 可能是站长,直接读环境变量
@@ -139,7 +138,7 @@ export async function POST(req: NextRequest) {
password === process.env.PASSWORD
) {
// 验证成功,设置认证cookie
- const response = NextResponse.json({ ok: true });
+ const response = AppResponse.json({ ok: true });
const cookieValue = await generateAuthCookie(
username,
password,
@@ -159,20 +158,20 @@ export async function POST(req: NextRequest) {
return response;
} else if (username === process.env.USERNAME) {
- return NextResponse.json({ error: '用户名或密码错误' }, { status: 401 });
+ return AppResponse.json({ error: '用户名或密码错误' }, { status: 401 });
}
const config = await getConfig();
const user = config.UserConfig.Users.find((u) => u.username === username);
if (user && user.banned) {
- return NextResponse.json({ error: '用户被封禁' }, { status: 401 });
+ return AppResponse.json({ error: '用户被封禁' }, { status: 401 });
}
// 校验用户密码
try {
const pass = await db.verifyUser(username, password);
if (!pass) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: '用户名或密码错误' },
{ status: 401 }
);
@@ -184,14 +183,14 @@ export async function POST(req: NextRequest) {
if (boundMachineCode) {
// 用户已绑定机器码,需要验证
if (!machineCode) {
- return NextResponse.json({
+ return AppResponse.json({
error: '该账户已绑定设备,请提供机器码',
requireMachineCode: true
}, { status: 403 });
}
if (machineCode.toUpperCase() !== boundMachineCode.toUpperCase()) {
- return NextResponse.json({
+ return AppResponse.json({
error: '机器码不匹配,此账户只能在绑定的设备上使用',
machineCodeMismatch: true
}, { status: 403 });
@@ -200,7 +199,7 @@ export async function POST(req: NextRequest) {
// 用户未绑定机器码,但提供了机器码,检查是否被其他用户绑定
const codeOwner = await db.isMachineCodeBound(machineCode);
if (codeOwner && codeOwner !== username) {
- return NextResponse.json({
+ return AppResponse.json({
error: `该机器码已被用户 ${codeOwner} 绑定`,
machineCodeTaken: true
}, { status: 409 });
@@ -208,7 +207,7 @@ export async function POST(req: NextRequest) {
}
// 验证成功,设置认证cookie
- const response = NextResponse.json({
+ const response = AppResponse.json({
ok: true,
machineCodeBound: !!boundMachineCode,
username: username
@@ -233,10 +232,10 @@ export async function POST(req: NextRequest) {
return response;
} catch (err) {
console.error('数据库验证失败', err);
- return NextResponse.json({ error: '数据库错误' }, { status: 500 });
+ return AppResponse.json({ error: '数据库错误' }, { status: 500 });
}
} catch (error) {
console.error('登录接口异常', error);
- return NextResponse.json({ error: '服务器错误' }, { status: 500 });
+ return AppResponse.json({ error: '服务器错误' }, { status: 500 });
}
}
diff --git a/src/app/api/logout/route.ts b/src/server/routes/api/logout/route.ts
similarity index 70%
rename from src/app/api/logout/route.ts
rename to src/server/routes/api/logout/route.ts
index 8bfa015..b2a7078 100644
--- a/src/app/api/logout/route.ts
+++ b/src/server/routes/api/logout/route.ts
@@ -1,9 +1,8 @@
-import { NextResponse } from 'next/server';
+import { AppResponse } from '@/server/web';
-export const runtime = 'nodejs';
export async function POST() {
- const response = NextResponse.json({ ok: true });
+ const response = AppResponse.json({ ok: true });
// 清除认证cookie
response.cookies.set('auth', '', {
diff --git a/src/app/api/machine-code/route.ts b/src/server/routes/api/machine-code/route.ts
similarity index 68%
rename from src/app/api/machine-code/route.ts
rename to src/server/routes/api/machine-code/route.ts
index 095ab4f..8222f96 100644
--- a/src/app/api/machine-code/route.ts
+++ b/src/server/routes/api/machine-code/route.ts
@@ -1,16 +1,15 @@
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { getAuthInfoFromCookie } from '@/lib/auth';
import { db } from '@/lib/db';
-export const runtime = 'nodejs';
// 获取用户机器码信息
-export async function GET(request: NextRequest) {
+export async function GET(request: AppRequest) {
try {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
+ return AppResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const { searchParams } = new URL(request.url);
@@ -19,28 +18,28 @@ export async function GET(request: NextRequest) {
// 管理员获取所有用户的机器码信息
if (action === 'list' && (authInfo.role === 'admin' || authInfo.role === 'owner')) {
const machineCodeUsers = await db.getMachineCodeUsers();
- return NextResponse.json({ users: machineCodeUsers });
+ return AppResponse.json({ users: machineCodeUsers });
}
// 获取当前用户的机器码
const userMachineCode = await db.getUserMachineCode(authInfo.username);
- return NextResponse.json({
+ return AppResponse.json({
machineCode: userMachineCode,
isBound: !!userMachineCode
});
} catch (error) {
console.error('获取机器码信息失败:', error);
- return NextResponse.json({ error: '获取机器码信息失败' }, { status: 500 });
+ return AppResponse.json({ error: '获取机器码信息失败' }, { status: 500 });
}
}
// 绑定机器码
-export async function POST(request: NextRequest) {
+export async function POST(request: AppRequest) {
try {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
+ return AppResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const body = await request.json();
@@ -50,22 +49,22 @@ export async function POST(request: NextRequest) {
if (action === 'unbind' && (authInfo.role === 'admin' || authInfo.role === 'owner')) {
const { targetUser } = body;
if (!targetUser) {
- return NextResponse.json({ error: '目标用户不能为空' }, { status: 400 });
+ return AppResponse.json({ error: '目标用户不能为空' }, { status: 400 });
}
await db.deleteUserMachineCode(targetUser);
- return NextResponse.json({ success: true, message: '机器码解绑成功' });
+ return AppResponse.json({ success: true, message: '机器码解绑成功' });
}
// 用户绑定机器码
if (!machineCode) {
- return NextResponse.json({ error: '机器码不能为空' }, { status: 400 });
+ return AppResponse.json({ error: '机器码不能为空' }, { status: 400 });
}
// 检查机器码是否已被绑定
const boundUser = await db.isMachineCodeBound(machineCode);
if (boundUser && boundUser !== authInfo.username) {
- return NextResponse.json({
+ return AppResponse.json({
error: `该机器码已被用户 ${boundUser} 绑定,请联系管理员处理`,
boundUser
}, { status: 409 });
@@ -74,7 +73,7 @@ export async function POST(request: NextRequest) {
// 检查用户是否已绑定其他机器码
const existingMachineCode = await db.getUserMachineCode(authInfo.username);
if (existingMachineCode && existingMachineCode !== machineCode) {
- return NextResponse.json({
+ return AppResponse.json({
error: '您已绑定其他设备,如需更换请联系管理员',
currentMachineCode: existingMachineCode
}, { status: 409 });
@@ -83,40 +82,40 @@ export async function POST(request: NextRequest) {
// 绑定机器码
await db.setUserMachineCode(authInfo.username, machineCode, deviceInfo);
- return NextResponse.json({
+ return AppResponse.json({
success: true,
message: '机器码绑定成功',
machineCode
});
} catch (error) {
console.error('绑定机器码失败:', error);
- return NextResponse.json({ error: '绑定机器码失败' }, { status: 500 });
+ return AppResponse.json({ error: '绑定机器码失败' }, { status: 500 });
}
}
// 解绑机器码(用户自己解绑)
-export async function DELETE(request: NextRequest) {
+export async function DELETE(request: AppRequest) {
try {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
+ return AppResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
// 检查是否有绑定的机器码
const existingMachineCode = await db.getUserMachineCode(authInfo.username);
if (!existingMachineCode) {
- return NextResponse.json({ error: '您还未绑定任何机器码' }, { status: 400 });
+ return AppResponse.json({ error: '您还未绑定任何机器码' }, { status: 400 });
}
// 解绑机器码
await db.deleteUserMachineCode(authInfo.username);
- return NextResponse.json({
+ return AppResponse.json({
success: true,
message: '机器码解绑成功'
});
} catch (error) {
console.error('解绑机器码失败:', error);
- return NextResponse.json({ error: '解绑机器码失败' }, { status: 500 });
+ return AppResponse.json({ error: '解绑机器码失败' }, { status: 500 });
}
}
diff --git a/src/app/api/playrecords/route.ts b/src/server/routes/api/playrecords/route.ts
similarity index 72%
rename from src/app/api/playrecords/route.ts
rename to src/server/routes/api/playrecords/route.ts
index 181ad0a..acc9ec1 100644
--- a/src/app/api/playrecords/route.ts
+++ b/src/server/routes/api/playrecords/route.ts
@@ -1,20 +1,19 @@
/* eslint-disable no-console */
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { getAuthInfoFromCookie } from '@/lib/auth';
import { getConfig } from '@/lib/config';
import { db } from '@/lib/db';
import { PlayRecord } from '@/lib/types';
-export const runtime = 'nodejs';
-export async function GET(request: NextRequest) {
+export async function GET(request: AppRequest) {
try {
// 从 cookie 获取用户信息
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
+ return AppResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const config = await getConfig();
@@ -24,30 +23,30 @@ export async function GET(request: NextRequest) {
(u) => u.username === authInfo.username
);
if (!user) {
- return NextResponse.json({ error: '用户不存在' }, { status: 401 });
+ return AppResponse.json({ error: '用户不存在' }, { status: 401 });
}
if (user.banned) {
- return NextResponse.json({ error: '用户已被封禁' }, { status: 401 });
+ return AppResponse.json({ error: '用户已被封禁' }, { status: 401 });
}
}
const records = await db.getAllPlayRecords(authInfo.username);
- return NextResponse.json(records, { status: 200 });
+ return AppResponse.json(records, { status: 200 });
} catch (err) {
console.error('获取播放记录失败', err);
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'Internal Server Error' },
{ status: 500 }
);
}
}
-export async function POST(request: NextRequest) {
+export async function POST(request: AppRequest) {
try {
// 从 cookie 获取用户信息
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
+ return AppResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const config = await getConfig();
@@ -57,10 +56,10 @@ export async function POST(request: NextRequest) {
(u) => u.username === authInfo.username
);
if (!user) {
- return NextResponse.json({ error: '用户不存在' }, { status: 401 });
+ return AppResponse.json({ error: '用户不存在' }, { status: 401 });
}
if (user.banned) {
- return NextResponse.json({ error: '用户已被封禁' }, { status: 401 });
+ return AppResponse.json({ error: '用户已被封禁' }, { status: 401 });
}
}
@@ -68,7 +67,7 @@ export async function POST(request: NextRequest) {
const { key, record }: { key: string; record: PlayRecord } = body;
if (!key || !record) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'Missing key or record' },
{ status: 400 }
);
@@ -76,7 +75,7 @@ export async function POST(request: NextRequest) {
// 验证播放记录数据
if (!record.title || !record.source_name || record.index < 1) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'Invalid record data' },
{ status: 400 }
);
@@ -85,7 +84,7 @@ export async function POST(request: NextRequest) {
// 从key中解析source和id
const [source, id] = key.split('+');
if (!source || !id) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'Invalid key format' },
{ status: 400 }
);
@@ -98,22 +97,22 @@ export async function POST(request: NextRequest) {
await db.savePlayRecord(authInfo.username, source, id, finalRecord);
- return NextResponse.json({ success: true }, { status: 200 });
+ return AppResponse.json({ success: true }, { status: 200 });
} catch (err) {
console.error('保存播放记录失败', err);
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'Internal Server Error' },
{ status: 500 }
);
}
}
-export async function DELETE(request: NextRequest) {
+export async function DELETE(request: AppRequest) {
try {
// 从 cookie 获取用户信息
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
+ return AppResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const config = await getConfig();
@@ -123,10 +122,10 @@ export async function DELETE(request: NextRequest) {
(u) => u.username === authInfo.username
);
if (!user) {
- return NextResponse.json({ error: '用户不存在' }, { status: 401 });
+ return AppResponse.json({ error: '用户不存在' }, { status: 401 });
}
if (user.banned) {
- return NextResponse.json({ error: '用户已被封禁' }, { status: 401 });
+ return AppResponse.json({ error: '用户已被封禁' }, { status: 401 });
}
}
@@ -138,7 +137,7 @@ export async function DELETE(request: NextRequest) {
// 如果提供了 key,删除单条播放记录
const [source, id] = key.split('+');
if (!source || !id) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'Invalid key format' },
{ status: 400 }
);
@@ -157,10 +156,10 @@ export async function DELETE(request: NextRequest) {
);
}
- return NextResponse.json({ success: true }, { status: 200 });
+ return AppResponse.json({ success: true }, { status: 200 });
} catch (err) {
console.error('删除播放记录失败', err);
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'Internal Server Error' },
{ status: 500 }
);
diff --git a/src/app/api/proxy/key/route.ts b/src/server/routes/api/proxy/key/route.ts
similarity index 73%
rename from src/app/api/proxy/key/route.ts
rename to src/server/routes/api/proxy/key/route.ts
index a22d508..699aabf 100644
--- a/src/app/api/proxy/key/route.ts
+++ b/src/server/routes/api/proxy/key/route.ts
@@ -1,23 +1,22 @@
/* eslint-disable no-console,@typescript-eslint/no-explicit-any */
-import { NextResponse } from "next/server";
+import { AppResponse } from '@/server/web';
import { getConfig } from "@/lib/config";
-export const runtime = 'nodejs';
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const url = searchParams.get('url');
const source = searchParams.get('OrangeTV-source');
if (!url) {
- return NextResponse.json({ error: 'Missing url' }, { status: 400 });
+ return AppResponse.json({ error: 'Missing url' }, { status: 400 });
}
const config = await getConfig();
const liveSource = config.LiveConfig?.find((s: any) => s.key === source);
if (!liveSource) {
- return NextResponse.json({ error: 'Source not found' }, { status: 404 });
+ return AppResponse.json({ error: 'Source not found' }, { status: 404 });
}
const ua = liveSource.ua || 'AptvPlayer/1.4.10';
@@ -30,7 +29,7 @@ export async function GET(request: Request) {
},
});
if (!response.ok) {
- return NextResponse.json({ error: 'Failed to fetch key' }, { status: 500 });
+ return AppResponse.json({ error: 'Failed to fetch key' }, { status: 500 });
}
const keyData = await response.arrayBuffer();
return new Response(keyData, {
@@ -42,6 +41,6 @@ export async function GET(request: Request) {
},
});
} catch (error) {
- return NextResponse.json({ error: 'Failed to fetch key' }, { status: 500 });
+ return AppResponse.json({ error: 'Failed to fetch key' }, { status: 500 });
}
}
\ No newline at end of file
diff --git a/src/app/api/proxy/logo/route.ts b/src/server/routes/api/proxy/logo/route.ts
similarity index 85%
rename from src/app/api/proxy/logo/route.ts
rename to src/server/routes/api/proxy/logo/route.ts
index 6202def..dc06224 100644
--- a/src/app/api/proxy/logo/route.ts
+++ b/src/server/routes/api/proxy/logo/route.ts
@@ -1,10 +1,9 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
-import { NextResponse } from 'next/server';
+import { AppResponse } from '@/server/web';
import { getConfig } from '@/lib/config';
-export const runtime = 'nodejs';
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
@@ -12,7 +11,7 @@ export async function GET(request: Request) {
const source = searchParams.get('OrangeTV-source');
if (!imageUrl) {
- return NextResponse.json({ error: 'Missing image URL' }, { status: 400 });
+ return AppResponse.json({ error: 'Missing image URL' }, { status: 400 });
}
const config = await getConfig();
@@ -31,7 +30,7 @@ export async function GET(request: Request) {
});
if (!imageResponse.ok) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: imageResponse.statusText },
{ status: imageResponse.status }
);
@@ -40,7 +39,7 @@ export async function GET(request: Request) {
const contentType = imageResponse.headers.get('content-type');
if (!imageResponse.body) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'Image response has no body' },
{ status: 500 }
);
@@ -61,7 +60,7 @@ export async function GET(request: Request) {
headers,
});
} catch (error) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'Error fetching image' },
{ status: 500 }
);
diff --git a/src/app/api/proxy/m3u8/route.ts b/src/server/routes/api/proxy/m3u8/route.ts
similarity index 93%
rename from src/app/api/proxy/m3u8/route.ts
rename to src/server/routes/api/proxy/m3u8/route.ts
index 5e35250..de7e646 100644
--- a/src/app/api/proxy/m3u8/route.ts
+++ b/src/server/routes/api/proxy/m3u8/route.ts
@@ -1,11 +1,10 @@
/* eslint-disable no-console,@typescript-eslint/no-explicit-any */
-import { NextResponse } from "next/server";
+import { AppResponse } from '@/server/web';
import { getConfig } from "@/lib/config";
import { getBaseUrl, resolveUrl } from "@/lib/live";
-export const runtime = 'nodejs';
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
@@ -13,13 +12,13 @@ export async function GET(request: Request) {
const allowCORS = searchParams.get('allowCORS') === 'true';
const source = searchParams.get('OrangeTV-source');
if (!url) {
- return NextResponse.json({ error: 'Missing url' }, { status: 400 });
+ return AppResponse.json({ error: 'Missing url' }, { status: 400 });
}
const config = await getConfig();
const liveSource = config.LiveConfig?.find((s: any) => s.key === source);
if (!liveSource) {
- return NextResponse.json({ error: 'Source not found' }, { status: 404 });
+ return AppResponse.json({ error: 'Source not found' }, { status: 404 });
}
const ua = liveSource.ua || 'AptvPlayer/1.4.10';
@@ -39,7 +38,7 @@ export async function GET(request: Request) {
});
if (!response.ok) {
- return NextResponse.json({ error: 'Failed to fetch m3u8' }, { status: 500 });
+ return AppResponse.json({ error: 'Failed to fetch m3u8' }, { status: 500 });
}
const contentType = response.headers.get('Content-Type') || '';
@@ -80,7 +79,7 @@ export async function GET(request: Request) {
headers,
});
} catch (error) {
- return NextResponse.json({ error: 'Failed to fetch m3u8' }, { status: 500 });
+ return AppResponse.json({ error: 'Failed to fetch m3u8' }, { status: 500 });
} finally {
// 确保 response 被正确关闭以释放资源
if (response && !responseUsed) {
diff --git a/src/app/api/proxy/segment/route.ts b/src/server/routes/api/proxy/segment/route.ts
similarity index 89%
rename from src/app/api/proxy/segment/route.ts
rename to src/server/routes/api/proxy/segment/route.ts
index 781978a..139b21c 100644
--- a/src/app/api/proxy/segment/route.ts
+++ b/src/server/routes/api/proxy/segment/route.ts
@@ -1,23 +1,22 @@
/* eslint-disable no-console,@typescript-eslint/no-explicit-any */
-import { NextResponse } from "next/server";
+import { AppResponse } from '@/server/web';
import { getConfig } from "@/lib/config";
-export const runtime = 'nodejs';
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const url = searchParams.get('url');
const source = searchParams.get('OrangeTV-source');
if (!url) {
- return NextResponse.json({ error: 'Missing url' }, { status: 400 });
+ return AppResponse.json({ error: 'Missing url' }, { status: 400 });
}
const config = await getConfig();
const liveSource = config.LiveConfig?.find((s: any) => s.key === source);
if (!liveSource) {
- return NextResponse.json({ error: 'Source not found' }, { status: 404 });
+ return AppResponse.json({ error: 'Source not found' }, { status: 404 });
}
const ua = liveSource.ua || 'AptvPlayer/1.4.10';
@@ -32,7 +31,7 @@ export async function GET(request: Request) {
},
});
if (!response.ok) {
- return NextResponse.json({ error: 'Failed to fetch segment' }, { status: 500 });
+ return AppResponse.json({ error: 'Failed to fetch segment' }, { status: 500 });
}
const headers = new Headers();
@@ -137,6 +136,6 @@ export async function GET(request: Request) {
}
}
- return NextResponse.json({ error: 'Failed to fetch segment' }, { status: 500 });
+ return AppResponse.json({ error: 'Failed to fetch segment' }, { status: 500 });
}
}
\ No newline at end of file
diff --git a/src/app/api/proxy/video/route.ts b/src/server/routes/api/proxy/video/route.ts
similarity index 86%
rename from src/app/api/proxy/video/route.ts
rename to src/server/routes/api/proxy/video/route.ts
index 1ba51f8..a9e71b9 100644
--- a/src/app/api/proxy/video/route.ts
+++ b/src/server/routes/api/proxy/video/route.ts
@@ -1,8 +1,7 @@
/* eslint-disable no-console,@typescript-eslint/no-explicit-any */
-import { NextResponse } from 'next/server';
+import { AppResponse } from '@/server/web';
-export const runtime = 'nodejs';
function buildCorsHeaders(contentType?: string, extra?: Record) {
const headers = new Headers();
@@ -47,7 +46,7 @@ export async function HEAD(request: Request) {
try {
const { searchParams } = new URL(request.url);
const url = searchParams.get('url');
- if (!url) return NextResponse.json({ error: 'Missing url' }, { status: 400 });
+ if (!url) return AppResponse.json({ error: 'Missing url' }, { status: 400 });
const upstream = await forwardRequest(url, 'HEAD', request.headers);
const headers = buildCorsHeaders(upstream.headers.get('Content-Type') || undefined, {
@@ -58,7 +57,7 @@ export async function HEAD(request: Request) {
const status = upstream.status === 206 ? 206 : upstream.status;
return new Response(null, { status, headers });
} catch (e) {
- return NextResponse.json({ error: 'Proxy HEAD failed' }, { status: 500 });
+ return AppResponse.json({ error: 'Proxy HEAD failed' }, { status: 500 });
}
}
@@ -66,11 +65,11 @@ export async function GET(request: Request) {
try {
const { searchParams } = new URL(request.url);
const url = searchParams.get('url');
- if (!url) return NextResponse.json({ error: 'Missing url' }, { status: 400 });
+ if (!url) return AppResponse.json({ error: 'Missing url' }, { status: 400 });
const upstream = await forwardRequest(url, 'GET', request.headers);
if (!upstream.ok && upstream.status !== 206) {
- return NextResponse.json({ error: `Upstream error ${upstream.status}` }, { status: upstream.status });
+ return AppResponse.json({ error: `Upstream error ${upstream.status}` }, { status: upstream.status });
}
const contentType = upstream.headers.get('Content-Type') || 'application/octet-stream';
@@ -87,7 +86,7 @@ export async function GET(request: Request) {
return new Response(upstream.body, { status, headers });
} catch (e) {
console.error('Proxy video failed:', e);
- return NextResponse.json({ error: 'Proxy failed' }, { status: 500 });
+ return AppResponse.json({ error: 'Proxy failed' }, { status: 500 });
}
}
diff --git a/src/app/api/proxy/video/test/route.ts b/src/server/routes/api/proxy/video/test/route.ts
similarity index 95%
rename from src/app/api/proxy/video/test/route.ts
rename to src/server/routes/api/proxy/video/test/route.ts
index 982ae93..49b64fe 100644
--- a/src/app/api/proxy/video/test/route.ts
+++ b/src/server/routes/api/proxy/video/test/route.ts
@@ -1,6 +1,6 @@
// /* eslint-disable no-console */
-// import { NextResponse } from "next/server";
+// import { AppResponse } from '@/server/web';
// export const runtime = 'nodejs';
@@ -10,7 +10,7 @@
// const url = searchParams.get('url');
// if (!url) {
-// return NextResponse.json({ error: 'Missing url parameter' }, { status: 400 });
+// return AppResponse.json({ error: 'Missing url parameter' }, { status: 400 });
// }
// try {
@@ -87,7 +87,7 @@
// }
// }
-// return NextResponse.json({
+// return AppResponse.json({
// url: decodedUrl,
// testResults: results,
// timestamp: new Date().toISOString(),
@@ -101,7 +101,7 @@
// } catch (error) {
// console.error('Test URL error:', error);
-// return NextResponse.json({
+// return AppResponse.json({
// error: 'Failed to test URL',
// details: error instanceof Error ? error.message : String(error)
// }, {
diff --git a/src/app/api/search/one/route.ts b/src/server/routes/api/search/one/route.ts
similarity index 79%
rename from src/app/api/search/one/route.ts
rename to src/server/routes/api/search/one/route.ts
index 61a4c30..4063c4d 100644
--- a/src/app/api/search/one/route.ts
+++ b/src/server/routes/api/search/one/route.ts
@@ -1,17 +1,16 @@
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
+import { getRouteUsername } from '@/server/route-auth';
-import { getAuthInfoFromCookie } from '@/lib/auth';
import { getAvailableApiSites, getCacheTime, getConfig } from '@/lib/config';
import { searchFromApi } from '@/lib/downstream';
import { yellowWords } from '@/lib/yellow';
-export const runtime = 'nodejs';
// OrionTV 兼容接口
-export async function GET(request: NextRequest) {
- const authInfo = getAuthInfoFromCookie(request);
- if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
+export async function GET(request: AppRequest) {
+ const username = getRouteUsername(request);
+ if (!username) {
+ return AppResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const { searchParams } = new URL(request.url);
@@ -20,7 +19,7 @@ export async function GET(request: NextRequest) {
if (!query || !resourceId) {
const cacheTime = await getCacheTime();
- return NextResponse.json(
+ return AppResponse.json(
{ result: null, error: '缺少必要参数: q 或 resourceId' },
{
headers: {
@@ -34,13 +33,13 @@ export async function GET(request: NextRequest) {
}
const config = await getConfig();
- const apiSites = await getAvailableApiSites(authInfo.username);
+ const apiSites = await getAvailableApiSites(username);
try {
// 根据 resourceId 查找对应的 API 站点
const targetSite = apiSites.find((site) => site.key === resourceId);
if (!targetSite) {
- return NextResponse.json(
+ return AppResponse.json(
{
error: `未找到指定的视频源: ${resourceId}`,
result: null,
@@ -60,7 +59,7 @@ export async function GET(request: NextRequest) {
const cacheTime = await getCacheTime();
if (result.length === 0) {
- return NextResponse.json(
+ return AppResponse.json(
{
error: '未找到结果',
result: null,
@@ -68,7 +67,7 @@ export async function GET(request: NextRequest) {
{ status: 404 }
);
} else {
- return NextResponse.json(
+ return AppResponse.json(
{ results: result },
{
headers: {
@@ -81,7 +80,7 @@ export async function GET(request: NextRequest) {
);
}
} catch (error) {
- return NextResponse.json(
+ return AppResponse.json(
{
error: '搜索失败',
result: null,
diff --git a/src/server/routes/api/search/resources/route.ts b/src/server/routes/api/search/resources/route.ts
new file mode 100644
index 0000000..1fc1ea7
--- /dev/null
+++ b/src/server/routes/api/search/resources/route.ts
@@ -0,0 +1,18 @@
+/* eslint-disable no-console */
+
+import { AppRequest, AppResponse } from '@/server/web';
+
+import { getAvailableApiSites } from '@/lib/config';
+
+
+// OrionTV 兼容接口
+export async function GET(request: AppRequest) {
+ console.log('request', request.url);
+ try {
+ const apiSites = await getAvailableApiSites();
+
+ return AppResponse.json(apiSites);
+ } catch (error) {
+ return AppResponse.json({ error: '获取资源失败' }, { status: 500 });
+ }
+}
diff --git a/src/app/api/search/route.ts b/src/server/routes/api/search/route.ts
similarity index 87%
rename from src/app/api/search/route.ts
rename to src/server/routes/api/search/route.ts
index 6e30d0b..d602cac 100644
--- a/src/app/api/search/route.ts
+++ b/src/server/routes/api/search/route.ts
@@ -1,8 +1,8 @@
/* eslint-disable @typescript-eslint/no-explicit-any,no-console */
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
+import { getRouteUsername } from '@/server/route-auth';
-import { getAuthInfoFromCookie } from '@/lib/auth';
import { getAvailableApiSites, getCacheTime, getConfig } from '@/lib/config';
import { searchFromApi } from '@/lib/downstream';
import { yellowWords } from '@/lib/yellow';
@@ -59,12 +59,11 @@ async function searchShortDrama(query: string, page = 1, limit = 20): Promise
@@ -129,10 +128,10 @@ export async function GET(request: NextRequest) {
if (flattenedResults.length === 0) {
// no cache if empty
- return NextResponse.json({ results: [] }, { status: 200 });
+ return AppResponse.json({ results: [] }, { status: 200 });
}
- return NextResponse.json(
+ return AppResponse.json(
{ results: flattenedResults },
{
headers: {
@@ -144,6 +143,6 @@ export async function GET(request: NextRequest) {
}
);
} catch (error) {
- return NextResponse.json({ error: '搜索失败' }, { status: 500 });
+ return AppResponse.json({ error: '搜索失败' }, { status: 500 });
}
}
diff --git a/src/app/api/search/suggestions/route.ts b/src/server/routes/api/search/suggestions/route.ts
similarity index 86%
rename from src/app/api/search/suggestions/route.ts
rename to src/server/routes/api/search/suggestions/route.ts
index 88e97b4..efb08d9 100644
--- a/src/app/api/search/suggestions/route.ts
+++ b/src/server/routes/api/search/suggestions/route.ts
@@ -1,21 +1,20 @@
/* eslint-disable @typescript-eslint/no-explicit-any,no-console */
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
+import { getRouteUsername } from '@/server/route-auth';
import { AdminConfig } from '@/lib/admin.types';
-import { getAuthInfoFromCookie } from '@/lib/auth';
import { getAvailableApiSites, getConfig } from '@/lib/config';
import { searchFromApi } from '@/lib/downstream';
import { yellowWords } from '@/lib/yellow';
-export const runtime = 'nodejs';
-export async function GET(request: NextRequest) {
+export async function GET(request: AppRequest) {
try {
// 从 cookie 获取用户信息
- const authInfo = getAuthInfoFromCookie(request);
- if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
+ const username = getRouteUsername(request);
+ if (!username) {
+ return AppResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const config = await getConfig();
@@ -23,16 +22,16 @@ export async function GET(request: NextRequest) {
const query = searchParams.get('q')?.trim();
if (!query) {
- return NextResponse.json({ suggestions: [] });
+ return AppResponse.json({ suggestions: [] });
}
// 生成建议
- const suggestions = await generateSuggestions(config, query, authInfo.username);
+ const suggestions = await generateSuggestions(config, query, username);
// 从配置中获取缓存时间,如果没有配置则使用默认值300秒(5分钟)
const cacheTime = config.SiteConfig.SiteInterfaceCacheTime || 300;
- return NextResponse.json(
+ return AppResponse.json(
{ suggestions },
{
headers: {
@@ -45,7 +44,7 @@ export async function GET(request: NextRequest) {
);
} catch (error) {
console.error('获取搜索建议失败', error);
- return NextResponse.json({ error: '获取搜索建议失败' }, { status: 500 });
+ return AppResponse.json({ error: '获取搜索建议失败' }, { status: 500 });
}
}
diff --git a/src/server/routes/api/search/ws/route.test.ts b/src/server/routes/api/search/ws/route.test.ts
new file mode 100644
index 0000000..9c75eae
--- /dev/null
+++ b/src/server/routes/api/search/ws/route.test.ts
@@ -0,0 +1,203 @@
+/**
+ * @jest-environment node
+ */
+
+import type { AppRequest } from '@/server/web';
+
+const mockGetAvailableApiSites = jest.fn();
+const mockGetConfig = jest.fn();
+const mockSearchFromApi = jest.fn();
+
+jest.mock('@/server/route-auth', () => ({
+ getRouteUsername: () => 'owner',
+}));
+
+jest.mock('@/lib/config', () => ({
+ getAvailableApiSites: mockGetAvailableApiSites,
+ getConfig: mockGetConfig,
+}));
+
+jest.mock('@/lib/downstream', () => ({
+ searchFromApi: mockSearchFromApi,
+}));
+
+jest.mock('@/lib/yellow', () => ({
+ yellowWords: [],
+}));
+
+type SsePayload = {
+ type: string;
+ totalSources?: number;
+ completedSources?: number;
+ source?: string;
+ results?: unknown[];
+};
+
+describe('/api/search/ws', () => {
+ beforeAll(async () => {
+ const { Blob, File } = await import('node:buffer');
+ const { ReadableStream, TransformStream } = await import('node:stream/web');
+ const { MessageChannel, MessagePort } = await import('node:worker_threads');
+ Object.assign(globalThis, {
+ Blob,
+ DOMException: class DOMException extends Error {
+ constructor(message?: string, public name = 'DOMException') {
+ super(message);
+ }
+ },
+ File,
+ MessageChannel,
+ MessagePort,
+ ReadableStream,
+ TransformStream,
+ });
+ const { FormData, Headers, Request, Response } = await import('undici');
+ Object.assign(globalThis, { FormData, Headers, Request, Response });
+ });
+
+ beforeEach(() => {
+ jest.clearAllMocks();
+ mockGetConfig.mockResolvedValue({
+ SiteConfig: {
+ DisableYellowFilter: false,
+ },
+ });
+ global.fetch = jest.fn().mockResolvedValue(
+ new Response(
+ JSON.stringify({
+ list: [
+ {
+ id: 'sd-1',
+ name: '短剧结果',
+ cover: 'https://example.com/cover.jpg',
+ update_time: '2026-01-01T00:00:00Z',
+ },
+ ],
+ }),
+ { status: 200 }
+ )
+ ) as unknown as typeof fetch;
+ });
+
+ it('completes when shortdrama is the only counted search source', async () => {
+ mockGetAvailableApiSites.mockResolvedValue([]);
+
+ const response = await callSearchWs('歌手2026');
+ const events = await readSseEvents(response);
+
+ expect(events[0]).toMatchObject({ type: 'start', totalSources: 1 });
+ expect(events).toContainEqual(
+ expect.objectContaining({
+ type: 'source_result',
+ source: 'shortdrama',
+ results: expect.any(Array),
+ })
+ );
+ expect(events.at(-1)).toMatchObject({
+ type: 'complete',
+ completedSources: 1,
+ });
+ });
+
+ it('emits one source event for each counted source before completing', async () => {
+ mockGetAvailableApiSites.mockResolvedValue([
+ { key: 'alpha', name: 'Alpha Source' },
+ ]);
+ mockSearchFromApi.mockResolvedValue([
+ {
+ id: 'alpha-1',
+ title: '歌手2026',
+ poster: 'https://example.com/poster.jpg',
+ episodes: ['episode-1'],
+ source: 'alpha',
+ source_name: 'Alpha Source',
+ year: '2026',
+ type_name: '综艺',
+ douban_id: 0,
+ },
+ ]);
+
+ const response = await callSearchWs('歌手2026');
+ const events = await readSseEvents(response);
+ const sourceEvents = events.filter(
+ (event) => event.type === 'source_result' || event.type === 'source_error'
+ );
+
+ expect(events[0]).toMatchObject({ type: 'start', totalSources: 2 });
+ expect(sourceEvents).toHaveLength(2);
+ expect(sourceEvents.map((event) => event.source).sort()).toEqual([
+ 'alpha',
+ 'shortdrama',
+ ]);
+ expect(events.at(-1)).toMatchObject({
+ type: 'complete',
+ completedSources: 2,
+ });
+ });
+});
+
+async function callSearchWs(query: string) {
+ const route = await import('./route');
+ const request = new Request(
+ `http://localhost:3000/api/search/ws?q=${encodeURIComponent(query)}`
+ ) as AppRequest;
+ Object.assign(request, {
+ cookies: {
+ get: () => undefined,
+ },
+ });
+ return route.GET(request);
+}
+
+async function readSseEvents(response: Response) {
+ const reader = response.body?.getReader();
+ if (!reader) throw new Error('Expected SSE response body');
+
+ const decoder = new TextDecoder();
+ const events: SsePayload[] = [];
+ let buffer = '';
+ let doneReading = false;
+
+ try {
+ while (!doneReading) {
+ const result = await Promise.race([
+ reader.read(),
+ new Promise<'timeout'>((resolve) => {
+ setTimeout(() => resolve('timeout'), 500);
+ }),
+ ]);
+
+ if (result === 'timeout') {
+ throw new Error(
+ `Timed out waiting for SSE completion after ${events.length} events`
+ );
+ }
+
+ if (result.done) {
+ doneReading = true;
+ break;
+ }
+ buffer += decoder.decode(result.value, { stream: true });
+
+ let separatorIndex = buffer.indexOf('\n\n');
+ while (separatorIndex >= 0) {
+ const rawEvent = buffer.slice(0, separatorIndex);
+ buffer = buffer.slice(separatorIndex + 2);
+ const dataLine = rawEvent
+ .split('\n')
+ .find((line) => line.startsWith('data: '));
+ if (dataLine) {
+ events.push(JSON.parse(dataLine.slice(6)));
+ }
+ separatorIndex = buffer.indexOf('\n\n');
+ }
+
+ if (events.at(-1)?.type === 'complete') break;
+ }
+ } catch (error) {
+ await reader.cancel().catch(() => undefined);
+ throw error;
+ }
+
+ return events;
+}
diff --git a/src/app/api/search/ws/route.ts b/src/server/routes/api/search/ws/route.ts
similarity index 79%
rename from src/app/api/search/ws/route.ts
rename to src/server/routes/api/search/ws/route.ts
index cdeb96f..cb3a2fb 100644
--- a/src/app/api/search/ws/route.ts
+++ b/src/server/routes/api/search/ws/route.ts
@@ -1,8 +1,8 @@
/* eslint-disable @typescript-eslint/no-explicit-any,no-console */
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
+import { getRouteUsername } from '@/server/route-auth';
-import { getAuthInfoFromCookie } from '@/lib/auth';
import { getAvailableApiSites, getConfig } from '@/lib/config';
import { searchFromApi } from '@/lib/downstream';
import { yellowWords } from '@/lib/yellow';
@@ -59,12 +59,11 @@ async function searchShortDrama(query: string, page = 1, limit = 20): Promise {
try {
- if (streamClosed || (!controller.desiredSize && controller.desiredSize !== 0)) {
+ if (streamClosed) {
// 流已标记为关闭或控制器已关闭
return false;
}
@@ -114,7 +114,7 @@ export async function GET(request: NextRequest) {
const startEvent = `data: ${JSON.stringify({
type: 'start',
query,
- totalSources: apiSites.length + 1, // +1 for short drama search
+ totalSources: expectedSources,
timestamp: Date.now()
})}\n\n`;
@@ -124,8 +124,31 @@ export async function GET(request: NextRequest) {
// 记录已完成的源数量
let completedSources = 0;
+ let completeSent = false;
const allResults: any[] = [];
+ const sendCompleteIfDone = () => {
+ if (streamClosed || completeSent || completedSources !== expectedSources) {
+ return;
+ }
+
+ completeSent = true;
+ const completeEvent = `data: ${JSON.stringify({
+ type: 'complete',
+ totalResults: allResults.length,
+ completedSources,
+ timestamp: Date.now()
+ })}\n\n`;
+
+ if (safeEnqueue(encoder.encode(completeEvent))) {
+ try {
+ controller.close();
+ } catch (error) {
+ console.warn('Failed to close controller:', error);
+ }
+ }
+ };
+
// 为每个源创建搜索 Promise
const searchPromises = [...apiSites.map(async (site) => {
try {
@@ -195,27 +218,7 @@ export async function GET(request: NextRequest) {
}
}
- // 检查是否所有源都已完成 (包括短剧搜索)
- if (completedSources === apiSites.length + 1) {
- if (!streamClosed) {
- // 发送最终完成事件
- const completeEvent = `data: ${JSON.stringify({
- type: 'complete',
- totalResults: allResults.length,
- completedSources,
- timestamp: Date.now()
- })}\n\n`;
-
- if (safeEnqueue(encoder.encode(completeEvent))) {
- // 只有在成功发送完成事件后才关闭流
- try {
- controller.close();
- } catch (error) {
- console.warn('Failed to close controller:', error);
- }
- }
- }
- }
+ sendCompleteIfDone();
}),
// 短剧搜索Promise
(async () => {
@@ -270,27 +273,8 @@ export async function GET(request: NextRequest) {
}
}
- // 检查是否所有源都已完成
- if (completedSources === apiSites.length + 1) {
- if (!streamClosed) {
- // 发送最终完成事件
- const completeEvent = `data: ${JSON.stringify({
- type: 'complete',
- totalResults: allResults.length,
- completedSources,
- timestamp: Date.now()
- })}\n\n`;
-
- if (safeEnqueue(encoder.encode(completeEvent))) {
- try {
- controller.close();
- } catch (error) {
- console.warn('Failed to close controller:', error);
- }
- }
- }
- }
- })];
+ sendCompleteIfDone();
+ })()];
// 等待所有搜索完成
await Promise.allSettled(searchPromises);
diff --git a/src/app/api/searchhistory/route.ts b/src/server/routes/api/searchhistory/route.ts
similarity index 69%
rename from src/app/api/searchhistory/route.ts
rename to src/server/routes/api/searchhistory/route.ts
index 9a9e717..11dc658 100644
--- a/src/app/api/searchhistory/route.ts
+++ b/src/server/routes/api/searchhistory/route.ts
@@ -1,12 +1,11 @@
/* eslint-disable no-console */
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { getAuthInfoFromCookie } from '@/lib/auth';
import { getConfig } from '@/lib/config';
import { db } from '@/lib/db';
-export const runtime = 'nodejs';
// 最大保存条数(与客户端保持一致)
const HISTORY_LIMIT = 20;
@@ -15,12 +14,12 @@ const HISTORY_LIMIT = 20;
* GET /api/searchhistory
* 返回 string[]
*/
-export async function GET(request: NextRequest) {
+export async function GET(request: AppRequest) {
try {
// 从 cookie 获取用户信息
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
+ return AppResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const config = await getConfig();
@@ -30,18 +29,18 @@ export async function GET(request: NextRequest) {
(u) => u.username === authInfo.username
);
if (!user) {
- return NextResponse.json({ error: '用户不存在' }, { status: 401 });
+ return AppResponse.json({ error: '用户不存在' }, { status: 401 });
}
if (user.banned) {
- return NextResponse.json({ error: '用户已被封禁' }, { status: 401 });
+ return AppResponse.json({ error: '用户已被封禁' }, { status: 401 });
}
}
const history = await db.getSearchHistory(authInfo.username);
- return NextResponse.json(history, { status: 200 });
+ return AppResponse.json(history, { status: 200 });
} catch (err) {
console.error('获取搜索历史失败', err);
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'Internal Server Error' },
{ status: 500 }
);
@@ -52,12 +51,12 @@ export async function GET(request: NextRequest) {
* POST /api/searchhistory
* body: { keyword: string }
*/
-export async function POST(request: NextRequest) {
+export async function POST(request: AppRequest) {
try {
// 从 cookie 获取用户信息
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
+ return AppResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const config = await getConfig();
@@ -67,10 +66,10 @@ export async function POST(request: NextRequest) {
(u) => u.username === authInfo.username
);
if (!user) {
- return NextResponse.json({ error: '用户不存在' }, { status: 401 });
+ return AppResponse.json({ error: '用户不存在' }, { status: 401 });
}
if (user.banned) {
- return NextResponse.json({ error: '用户已被封禁' }, { status: 401 });
+ return AppResponse.json({ error: '用户已被封禁' }, { status: 401 });
}
}
@@ -78,7 +77,7 @@ export async function POST(request: NextRequest) {
const keyword: string = body.keyword?.trim();
if (!keyword) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'Keyword is required' },
{ status: 400 }
);
@@ -88,10 +87,10 @@ export async function POST(request: NextRequest) {
// 再次获取最新列表,确保客户端与服务端同步
const history = await db.getSearchHistory(authInfo.username);
- return NextResponse.json(history.slice(0, HISTORY_LIMIT), { status: 200 });
+ return AppResponse.json(history.slice(0, HISTORY_LIMIT), { status: 200 });
} catch (err) {
console.error('添加搜索历史失败', err);
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'Internal Server Error' },
{ status: 500 }
);
@@ -104,12 +103,12 @@ export async function POST(request: NextRequest) {
* 1. 不带 keyword -> 清空全部搜索历史
* 2. 带 keyword= -> 删除单条关键字
*/
-export async function DELETE(request: NextRequest) {
+export async function DELETE(request: AppRequest) {
try {
// 从 cookie 获取用户信息
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
+ return AppResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const config = await getConfig();
@@ -119,10 +118,10 @@ export async function DELETE(request: NextRequest) {
(u) => u.username === authInfo.username
);
if (!user) {
- return NextResponse.json({ error: '用户不存在' }, { status: 401 });
+ return AppResponse.json({ error: '用户不存在' }, { status: 401 });
}
if (user.banned) {
- return NextResponse.json({ error: '用户已被封禁' }, { status: 401 });
+ return AppResponse.json({ error: '用户已被封禁' }, { status: 401 });
}
}
@@ -131,10 +130,10 @@ export async function DELETE(request: NextRequest) {
await db.deleteSearchHistory(authInfo.username, kw || undefined);
- return NextResponse.json({ success: true }, { status: 200 });
+ return AppResponse.json({ success: true }, { status: 200 });
} catch (err) {
console.error('删除搜索历史失败', err);
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'Internal Server Error' },
{ status: 500 }
);
diff --git a/src/app/api/server-config/route.ts b/src/server/routes/api/server-config/route.ts
similarity index 55%
rename from src/app/api/server-config/route.ts
rename to src/server/routes/api/server-config/route.ts
index 011a0ff..d9b51fe 100644
--- a/src/app/api/server-config/route.ts
+++ b/src/server/routes/api/server-config/route.ts
@@ -1,20 +1,19 @@
/* eslint-disable no-console */
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { getConfig } from '@/lib/config';
import { CURRENT_VERSION } from '@/lib/version'
-export const runtime = 'nodejs';
-export async function GET(request: NextRequest) {
+export async function GET(request: AppRequest) {
console.log('server-config called: ', request.url);
const config = await getConfig();
const result = {
SiteName: config.SiteConfig.SiteName,
- StorageType: process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage',
+ StorageType: process.env.VITE_STORAGE_TYPE || 'localstorage',
Version: CURRENT_VERSION,
};
- return NextResponse.json(result);
+ return AppResponse.json(result);
}
diff --git a/src/app/api/shortdrama/categories/route.ts b/src/server/routes/api/shortdrama/categories/route.ts
similarity index 86%
rename from src/app/api/shortdrama/categories/route.ts
rename to src/server/routes/api/shortdrama/categories/route.ts
index 875eb06..4487a0f 100644
--- a/src/app/api/shortdrama/categories/route.ts
+++ b/src/server/routes/api/shortdrama/categories/route.ts
@@ -1,7 +1,7 @@
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { API_CONFIG } from '@/lib/config';
-export async function GET(_request: NextRequest) {
+export async function GET(_request: AppRequest) {
try {
// 先尝试调用外部API
const controller = new AbortController();
@@ -17,7 +17,7 @@ export async function GET(_request: NextRequest) {
if (response.ok) {
const data = await response.json();
- return NextResponse.json(data);
+ return AppResponse.json(data);
} else {
throw new Error(`External API failed: ${response.status}`);
}
@@ -25,7 +25,7 @@ export async function GET(_request: NextRequest) {
console.error('Short drama categories API error:', error);
// 如果外部API失败,返回默认分类数据作为备用
- return NextResponse.json({
+ return AppResponse.json({
categories: [
{ type_id: 1, type_name: '古装' },
{ type_id: 2, type_name: '现代' },
diff --git a/src/app/api/shortdrama/latest/route.ts b/src/server/routes/api/shortdrama/latest/route.ts
similarity index 94%
rename from src/app/api/shortdrama/latest/route.ts
rename to src/server/routes/api/shortdrama/latest/route.ts
index 02241f4..6110e7e 100644
--- a/src/app/api/shortdrama/latest/route.ts
+++ b/src/server/routes/api/shortdrama/latest/route.ts
@@ -1,4 +1,4 @@
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { API_CONFIG } from '@/lib/config';
// 转换外部API数据格式到内部格式 - 最新剧集API使用vod_id作为实际视频ID
@@ -16,7 +16,7 @@ function transformExternalData(externalItem: any) {
};
}
-export async function GET(request: NextRequest) {
+export async function GET(request: AppRequest) {
try {
const { searchParams } = new URL(request.url);
const page = searchParams.get('page') || '1';
@@ -44,7 +44,7 @@ export async function GET(request: NextRequest) {
// 处理外部API响应格式
if (externalData && externalData.list && Array.isArray(externalData.list)) {
const transformedData = externalData.list.map(transformExternalData);
- return NextResponse.json(transformedData);
+ return AppResponse.json(transformedData);
} else {
throw new Error('Invalid response format from external API');
}
@@ -76,6 +76,6 @@ export async function GET(request: NextRequest) {
});
// 确保返回数组
- return NextResponse.json(mockData);
+ return AppResponse.json(mockData);
}
}
diff --git a/src/app/api/shortdrama/list/route.ts b/src/server/routes/api/shortdrama/list/route.ts
similarity index 92%
rename from src/app/api/shortdrama/list/route.ts
rename to src/server/routes/api/shortdrama/list/route.ts
index b01eac4..98f62a4 100644
--- a/src/app/api/shortdrama/list/route.ts
+++ b/src/server/routes/api/shortdrama/list/route.ts
@@ -1,4 +1,4 @@
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { API_CONFIG } from '@/lib/config';
// 转换外部API数据格式到内部格式 - 分类热搜API直接使用id作为视频ID
@@ -16,14 +16,14 @@ function transformExternalData(externalItem: any) {
};
}
-export async function GET(request: NextRequest) {
+export async function GET(request: AppRequest) {
try {
const { searchParams } = new URL(request.url);
const categoryId = searchParams.get('categoryId');
const page = searchParams.get('page') || '1';
if (!categoryId) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'categoryId is required' },
{ status: 400 }
);
@@ -53,7 +53,7 @@ export async function GET(request: NextRequest) {
// 处理外部API响应格式
if (externalData && externalData.list && Array.isArray(externalData.list)) {
const transformedList = externalData.list.map(transformExternalData);
- return NextResponse.json({
+ return AppResponse.json({
total: externalData.total || 0,
totalPages: externalData.totalPages || externalData.pagecount || 1,
currentPage: externalData.currentPage || externalData.page || 1,
@@ -87,10 +87,10 @@ export async function GET(request: NextRequest) {
};
});
- return NextResponse.json({
+ return AppResponse.json({
total: 100,
totalPages: 4,
- currentPage: parseInt(request.nextUrl.searchParams.get('page') || '1'),
+ currentPage: parseInt(new URL(request.url).searchParams.get('page') || '1'),
list: mockData,
});
}
diff --git a/src/app/api/shortdrama/parse/all/route.ts b/src/server/routes/api/shortdrama/parse/all/route.ts
similarity index 97%
rename from src/app/api/shortdrama/parse/all/route.ts
rename to src/server/routes/api/shortdrama/parse/all/route.ts
index eae1946..423dd8f 100644
--- a/src/app/api/shortdrama/parse/all/route.ts
+++ b/src/server/routes/api/shortdrama/parse/all/route.ts
@@ -1,14 +1,14 @@
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { API_CONFIG } from '@/lib/config';
-export async function GET(request: NextRequest) {
+export async function GET(request: AppRequest) {
try {
const { searchParams } = new URL(request.url);
const id = searchParams.get('id');
if (!id) {
console.error('🚫 [短剧API] 缺少必需的ID参数');
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'id parameter is required' },
{ status: 400 }
);
@@ -209,7 +209,7 @@ export async function GET(request: NextRequest) {
}
});
- return NextResponse.json(processedData);
+ return AppResponse.json(processedData);
} catch (error) {
const { searchParams: errorSearchParams } = new URL(request.url);
const errorId = errorSearchParams.get('id');
@@ -283,7 +283,7 @@ export async function GET(request: NextRequest) {
hasFallbackData: true
});
- return NextResponse.json(mockData, {
+ return AppResponse.json(mockData, {
headers: {
'X-Fallback-Data': 'true',
'X-Error-Category': errorCategory,
diff --git a/src/app/api/shortdrama/parse/batch/route.ts b/src/server/routes/api/shortdrama/parse/batch/route.ts
similarity index 83%
rename from src/app/api/shortdrama/parse/batch/route.ts
rename to src/server/routes/api/shortdrama/parse/batch/route.ts
index ab07f37..5c77826 100644
--- a/src/app/api/shortdrama/parse/batch/route.ts
+++ b/src/server/routes/api/shortdrama/parse/batch/route.ts
@@ -1,14 +1,14 @@
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { API_CONFIG } from '@/lib/config';
-export async function GET(request: NextRequest) {
+export async function GET(request: AppRequest) {
try {
const { searchParams } = new URL(request.url);
const id = searchParams.get('id');
const episodes = searchParams.get('episodes');
if (!id) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'id parameter is required' },
{ status: 400 }
);
@@ -30,12 +30,12 @@ export async function GET(request: NextRequest) {
const data = await response.json();
- return NextResponse.json(data);
+ return AppResponse.json(data);
} catch (error) {
console.error('Short drama batch parse API error:', error);
// 返回默认数据作为备用
- return NextResponse.json({
+ return AppResponse.json({
code: 500,
message: 'Failed to parse episodes',
data: null,
diff --git a/src/app/api/shortdrama/parse/single/route.ts b/src/server/routes/api/shortdrama/parse/single/route.ts
similarity index 83%
rename from src/app/api/shortdrama/parse/single/route.ts
rename to src/server/routes/api/shortdrama/parse/single/route.ts
index c748ec3..451fb48 100644
--- a/src/app/api/shortdrama/parse/single/route.ts
+++ b/src/server/routes/api/shortdrama/parse/single/route.ts
@@ -1,14 +1,14 @@
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { API_CONFIG } from '@/lib/config';
-export async function GET(request: NextRequest) {
+export async function GET(request: AppRequest) {
try {
const { searchParams } = new URL(request.url);
const id = searchParams.get('id');
const episode = searchParams.get('episode');
if (!id) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'id parameter is required' },
{ status: 400 }
);
@@ -30,12 +30,12 @@ export async function GET(request: NextRequest) {
const data = await response.json();
- return NextResponse.json(data);
+ return AppResponse.json(data);
} catch (error) {
console.error('Short drama single parse API error:', error);
// 返回默认数据作为备用
- return NextResponse.json({
+ return AppResponse.json({
code: 500,
message: 'Failed to parse episode',
data: null,
diff --git a/src/app/api/shortdrama/recommend/route.ts b/src/server/routes/api/shortdrama/recommend/route.ts
similarity index 94%
rename from src/app/api/shortdrama/recommend/route.ts
rename to src/server/routes/api/shortdrama/recommend/route.ts
index 338af67..15f37e0 100644
--- a/src/app/api/shortdrama/recommend/route.ts
+++ b/src/server/routes/api/shortdrama/recommend/route.ts
@@ -1,4 +1,4 @@
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { API_CONFIG } from '@/lib/config';
// 转换外部API数据格式到内部格式 - 推荐API通常和分类热搜格式相同
@@ -16,7 +16,7 @@ function transformExternalData(externalItem: any) {
};
}
-export async function GET(request: NextRequest) {
+export async function GET(request: AppRequest) {
const { searchParams } = new URL(request.url);
const categoryId = searchParams.get('categoryId');
const size = searchParams.get('size') || '25';
@@ -54,7 +54,7 @@ export async function GET(request: NextRequest) {
total: externalData.total || transformedItems.length,
items: transformedItems,
};
- return NextResponse.json(recommendResponse);
+ return AppResponse.json(recommendResponse);
} else {
throw new Error('Invalid response format from external API');
}
@@ -82,6 +82,6 @@ export async function GET(request: NextRequest) {
items: mockItems,
};
- return NextResponse.json(mockResponse);
+ return AppResponse.json(mockResponse);
}
}
diff --git a/src/app/api/shortdrama/search/route.ts b/src/server/routes/api/shortdrama/search/route.ts
similarity index 85%
rename from src/app/api/shortdrama/search/route.ts
rename to src/server/routes/api/shortdrama/search/route.ts
index 5aaa6f7..6480d70 100644
--- a/src/app/api/shortdrama/search/route.ts
+++ b/src/server/routes/api/shortdrama/search/route.ts
@@ -1,14 +1,14 @@
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { API_CONFIG } from '@/lib/config';
-export async function GET(request: NextRequest) {
+export async function GET(request: AppRequest) {
const { searchParams } = new URL(request.url);
const name = searchParams.get('name');
try {
if (!name) {
- return NextResponse.json(
+ return AppResponse.json(
{ error: 'name parameter is required' },
{ status: 400 }
);
@@ -28,7 +28,7 @@ export async function GET(request: NextRequest) {
const data = await response.json();
- return NextResponse.json(data);
+ return AppResponse.json(data);
} catch (error) {
console.error('Short drama search API error:', error);
@@ -41,7 +41,7 @@ export async function GET(request: NextRequest) {
score: Math.floor(Math.random() * 3) + 8, // 8-10的随机分数
}));
- return NextResponse.json({
+ return AppResponse.json({
total: mockData.length,
totalPages: 1,
currentPage: 1,
diff --git a/src/app/api/skipconfigs/route.ts b/src/server/routes/api/skipconfigs/route.ts
similarity index 67%
rename from src/app/api/skipconfigs/route.ts
rename to src/server/routes/api/skipconfigs/route.ts
index 3762c4a..d0ccc00 100644
--- a/src/app/api/skipconfigs/route.ts
+++ b/src/server/routes/api/skipconfigs/route.ts
@@ -1,19 +1,18 @@
/* eslint-disable no-console */
-import { NextRequest, NextResponse } from 'next/server';
+import { AppRequest, AppResponse } from '@/server/web';
import { getAuthInfoFromCookie } from '@/lib/auth';
import { getConfig } from '@/lib/config';
import { db } from '@/lib/db';
import { SkipConfig } from '@/lib/types';
-export const runtime = 'nodejs';
-export async function GET(request: NextRequest) {
+export async function GET(request: AppRequest) {
try {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: '未登录' }, { status: 401 });
+ return AppResponse.json({ error: '未登录' }, { status: 401 });
}
const config = await getConfig();
@@ -23,10 +22,10 @@ export async function GET(request: NextRequest) {
(u) => u.username === authInfo.username
);
if (!user) {
- return NextResponse.json({ error: '用户不存在' }, { status: 401 });
+ return AppResponse.json({ error: '用户不存在' }, { status: 401 });
}
if (user.banned) {
- return NextResponse.json({ error: '用户已被封禁' }, { status: 401 });
+ return AppResponse.json({ error: '用户已被封禁' }, { status: 401 });
}
}
@@ -37,26 +36,26 @@ export async function GET(request: NextRequest) {
if (source && id) {
// 获取单个配置
const config = await db.getSkipConfig(authInfo.username, source, id);
- return NextResponse.json(config);
+ return AppResponse.json(config);
} else {
// 获取所有配置
const configs = await db.getAllSkipConfigs(authInfo.username);
- return NextResponse.json(configs);
+ return AppResponse.json(configs);
}
} catch (error) {
console.error('获取跳过片头片尾配置失败:', error);
- return NextResponse.json(
+ return AppResponse.json(
{ error: '获取跳过片头片尾配置失败' },
{ status: 500 }
);
}
}
-export async function POST(request: NextRequest) {
+export async function POST(request: AppRequest) {
try {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: '未登录' }, { status: 401 });
+ return AppResponse.json({ error: '未登录' }, { status: 401 });
}
const adminConfig = await getConfig();
@@ -66,10 +65,10 @@ export async function POST(request: NextRequest) {
(u) => u.username === authInfo.username
);
if (!user) {
- return NextResponse.json({ error: '用户不存在' }, { status: 401 });
+ return AppResponse.json({ error: '用户不存在' }, { status: 401 });
}
if (user.banned) {
- return NextResponse.json({ error: '用户已被封禁' }, { status: 401 });
+ return AppResponse.json({ error: '用户已被封禁' }, { status: 401 });
}
}
@@ -77,13 +76,13 @@ export async function POST(request: NextRequest) {
const { key, config } = body;
if (!key || !config) {
- return NextResponse.json({ error: '缺少必要参数' }, { status: 400 });
+ return AppResponse.json({ error: '缺少必要参数' }, { status: 400 });
}
// 解析key为source和id
const [source, id] = key.split('+');
if (!source || !id) {
- return NextResponse.json({ error: '无效的key格式' }, { status: 400 });
+ return AppResponse.json({ error: '无效的key格式' }, { status: 400 });
}
// 验证配置格式
@@ -95,21 +94,21 @@ export async function POST(request: NextRequest) {
await db.setSkipConfig(authInfo.username, source, id, skipConfig);
- return NextResponse.json({ success: true });
+ return AppResponse.json({ success: true });
} catch (error) {
console.error('保存跳过片头片尾配置失败:', error);
- return NextResponse.json(
+ return AppResponse.json(
{ error: '保存跳过片头片尾配置失败' },
{ status: 500 }
);
}
}
-export async function DELETE(request: NextRequest) {
+export async function DELETE(request: AppRequest) {
try {
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
- return NextResponse.json({ error: '未登录' }, { status: 401 });
+ return AppResponse.json({ error: '未登录' }, { status: 401 });
}
const adminConfig = await getConfig();
@@ -119,10 +118,10 @@ export async function DELETE(request: NextRequest) {
(u) => u.username === authInfo.username
);
if (!user) {
- return NextResponse.json({ error: '用户不存在' }, { status: 401 });
+ return AppResponse.json({ error: '用户不存在' }, { status: 401 });
}
if (user.banned) {
- return NextResponse.json({ error: '用户已被封禁' }, { status: 401 });
+ return AppResponse.json({ error: '用户已被封禁' }, { status: 401 });
}
}
@@ -130,21 +129,21 @@ export async function DELETE(request: NextRequest) {
const key = searchParams.get('key');
if (!key) {
- return NextResponse.json({ error: '缺少必要参数' }, { status: 400 });
+ return AppResponse.json({ error: '缺少必要参数' }, { status: 400 });
}
// 解析key为source和id
const [source, id] = key.split('+');
if (!source || !id) {
- return NextResponse.json({ error: '无效的key格式' }, { status: 400 });
+ return AppResponse.json({ error: '无效的key格式' }, { status: 400 });
}
await db.deleteSkipConfig(authInfo.username, source, id);
- return NextResponse.json({ success: true });
+ return AppResponse.json({ success: true });
} catch (error) {
console.error('删除跳过片头片尾配置失败:', error);
- return NextResponse.json(
+ return AppResponse.json(
{ error: '删除跳过片头片尾配置失败' },
{ status: 500 }
);
diff --git a/src/app/api/websocket/route.ts b/src/server/routes/api/websocket/route.ts
similarity index 87%
rename from src/app/api/websocket/route.ts
rename to src/server/routes/api/websocket/route.ts
index 95fe46f..f2c2baa 100644
--- a/src/app/api/websocket/route.ts
+++ b/src/server/routes/api/websocket/route.ts
@@ -1,7 +1,7 @@
-import { NextRequest } from 'next/server';
+import { AppRequest } from '@/server/web';
// 这个端点主要用于 WebSocket 升级,实际的 WebSocket 处理在自定义服务器中进行
-export async function GET(request: NextRequest) {
+export async function GET(request: AppRequest) {
// 如果运行在自定义服务器环境下,WebSocket 连接应该已经被处理
// 这里主要是为了提供一个回退响应
diff --git a/src/server/routes/index.ts b/src/server/routes/index.ts
new file mode 100644
index 0000000..e16f05d
--- /dev/null
+++ b/src/server/routes/index.ts
@@ -0,0 +1,129 @@
+import * as route0 from './api/admin/category/route';
+import * as route1 from './api/admin/config/route';
+import * as route2 from './api/admin/config_file/route';
+import * as route3 from './api/admin/config_subscription/fetch/route';
+import * as route4 from './api/admin/data_migration/export/route';
+import * as route5 from './api/admin/data_migration/import/route';
+import * as route6 from './api/admin/live/route';
+import * as route7 from './api/admin/live/refresh/route';
+import * as route8 from './api/admin/reset/route';
+import * as route9 from './api/admin/site/route';
+import * as route10 from './api/admin/source/route';
+import * as route11 from './api/admin/source/validate/route';
+import * as route12 from './api/admin/theme/route';
+import * as route13 from './api/admin/user/route';
+import * as route14 from './api/avatar/route';
+import * as route15 from './api/change-password/route';
+import * as route16 from './api/chat/conversations/route';
+import * as route17 from './api/chat/friend-requests/route';
+import * as route18 from './api/chat/friends/route';
+import * as route19 from './api/chat/messages/route';
+import * as route20 from './api/chat/online-users/route';
+import * as route21 from './api/chat/search-users/route';
+import * as route22 from './api/chat/send-message/route';
+import * as route23 from './api/cron/route';
+import * as route24 from './api/danmu/route';
+import * as route25 from './api/detail/route';
+import * as route26 from './api/douban/route';
+import * as route27 from './api/douban/categories/route';
+import * as route28 from './api/douban/recommends/route';
+import * as route29 from './api/favorites/route';
+import * as route30 from './api/health/route';
+import * as route31 from './api/image-proxy/route';
+import * as route32 from './api/live/channels/route';
+import * as route33 from './api/live/epg/route';
+import * as route34 from './api/live/precheck/route';
+import * as route35 from './api/live/sources/route';
+import * as route36 from './api/login/route';
+import * as route37 from './api/logout/route';
+import * as route38 from './api/machine-code/route';
+import * as route39 from './api/playrecords/route';
+import * as route40 from './api/proxy/key/route';
+import * as route41 from './api/proxy/logo/route';
+import * as route42 from './api/proxy/m3u8/route';
+import * as route43 from './api/proxy/segment/route';
+import * as route44 from './api/proxy/video/route';
+import * as route45 from './api/proxy/video/test/route';
+import * as route46 from './api/search/route';
+import * as route47 from './api/search/one/route';
+import * as route48 from './api/search/resources/route';
+import * as route49 from './api/search/suggestions/route';
+import * as route50 from './api/search/ws/route';
+import * as route51 from './api/searchhistory/route';
+import * as route52 from './api/server-config/route';
+import * as route53 from './api/shortdrama/categories/route';
+import * as route54 from './api/shortdrama/latest/route';
+import * as route55 from './api/shortdrama/list/route';
+import * as route56 from './api/shortdrama/parse/all/route';
+import * as route57 from './api/shortdrama/parse/batch/route';
+import * as route58 from './api/shortdrama/parse/single/route';
+import * as route59 from './api/shortdrama/recommend/route';
+import * as route60 from './api/shortdrama/search/route';
+import * as route61 from './api/skipconfigs/route';
+import * as route62 from './api/websocket/route';
+
+export const apiRoutes = [
+ { path: '/api/admin/category', module: route0 },
+ { path: '/api/admin/config', module: route1 },
+ { path: '/api/admin/config_file', module: route2 },
+ { path: '/api/admin/config_subscription/fetch', module: route3 },
+ { path: '/api/admin/data_migration/export', module: route4 },
+ { path: '/api/admin/data_migration/import', module: route5 },
+ { path: '/api/admin/live', module: route6 },
+ { path: '/api/admin/live/refresh', module: route7 },
+ { path: '/api/admin/reset', module: route8 },
+ { path: '/api/admin/site', module: route9 },
+ { path: '/api/admin/source', module: route10 },
+ { path: '/api/admin/source/validate', module: route11 },
+ { path: '/api/admin/theme', module: route12 },
+ { path: '/api/admin/user', module: route13 },
+ { path: '/api/avatar', module: route14 },
+ { path: '/api/change-password', module: route15 },
+ { path: '/api/chat/conversations', module: route16 },
+ { path: '/api/chat/friend-requests', module: route17 },
+ { path: '/api/chat/friends', module: route18 },
+ { path: '/api/chat/messages', module: route19 },
+ { path: '/api/chat/online-users', module: route20 },
+ { path: '/api/chat/search-users', module: route21 },
+ { path: '/api/chat/send-message', module: route22 },
+ { path: '/api/cron', module: route23 },
+ { path: '/api/danmu', module: route24 },
+ { path: '/api/detail', module: route25 },
+ { path: '/api/douban', module: route26 },
+ { path: '/api/douban/categories', module: route27 },
+ { path: '/api/douban/recommends', module: route28 },
+ { path: '/api/favorites', module: route29 },
+ { path: '/api/health', module: route30 },
+ { path: '/api/image-proxy', module: route31 },
+ { path: '/api/live/channels', module: route32 },
+ { path: '/api/live/epg', module: route33 },
+ { path: '/api/live/precheck', module: route34 },
+ { path: '/api/live/sources', module: route35 },
+ { path: '/api/login', module: route36 },
+ { path: '/api/logout', module: route37 },
+ { path: '/api/machine-code', module: route38 },
+ { path: '/api/playrecords', module: route39 },
+ { path: '/api/proxy/key', module: route40 },
+ { path: '/api/proxy/logo', module: route41 },
+ { path: '/api/proxy/m3u8', module: route42 },
+ { path: '/api/proxy/segment', module: route43 },
+ { path: '/api/proxy/video', module: route44 },
+ { path: '/api/proxy/video/test', module: route45 },
+ { path: '/api/search', module: route46 },
+ { path: '/api/search/one', module: route47 },
+ { path: '/api/search/resources', module: route48 },
+ { path: '/api/search/suggestions', module: route49 },
+ { path: '/api/search/ws', module: route50 },
+ { path: '/api/searchhistory', module: route51 },
+ { path: '/api/server-config', module: route52 },
+ { path: '/api/shortdrama/categories', module: route53 },
+ { path: '/api/shortdrama/latest', module: route54 },
+ { path: '/api/shortdrama/list', module: route55 },
+ { path: '/api/shortdrama/parse/all', module: route56 },
+ { path: '/api/shortdrama/parse/batch', module: route57 },
+ { path: '/api/shortdrama/parse/single', module: route58 },
+ { path: '/api/shortdrama/recommend', module: route59 },
+ { path: '/api/shortdrama/search', module: route60 },
+ { path: '/api/skipconfigs', module: route61 },
+ { path: '/api/websocket', module: route62 },
+];
diff --git a/src/server/runtime-config.ts b/src/server/runtime-config.ts
new file mode 100644
index 0000000..2898d72
--- /dev/null
+++ b/src/server/runtime-config.ts
@@ -0,0 +1,61 @@
+import { getConfig } from '@/lib/config';
+
+export async function getRuntimeConfig() {
+ const storageType = process.env.VITE_STORAGE_TYPE || 'localstorage';
+ let siteName = process.env.VITE_SITE_NAME || 'OrangeTV';
+ let announcement =
+ process.env.ANNOUNCEMENT ||
+ '本网站仅提供影视信息搜索服务,所有内容均来自第三方网站。本站不存储任何视频资源,不对任何内容的准确性、合法性、完整性负责。';
+ let doubanProxyType =
+ process.env.VITE_DOUBAN_PROXY_TYPE || 'cmliussss-cdn-tencent';
+ let doubanProxy = process.env.VITE_DOUBAN_PROXY || '';
+ let doubanImageProxyType =
+ process.env.VITE_DOUBAN_IMAGE_PROXY_TYPE || 'cmliussss-cdn-tencent';
+ let doubanImageProxy = process.env.VITE_DOUBAN_IMAGE_PROXY || '';
+ let disableYellowFilter =
+ process.env.VITE_DISABLE_YELLOW_FILTER === 'true';
+ let fluidSearch = process.env.VITE_FLUID_SEARCH !== 'false';
+ let requireDeviceCode =
+ process.env.VITE_REQUIRE_DEVICE_CODE !== 'false';
+ let customCategories: { name: string; type: 'movie' | 'tv'; query: string }[] =
+ [];
+
+ if (storageType !== 'localstorage') {
+ const config = await getConfig();
+ siteName = config.SiteConfig.SiteName;
+ announcement = config.SiteConfig.Announcement;
+ doubanProxyType = config.SiteConfig.DoubanProxyType;
+ doubanProxy = config.SiteConfig.DoubanProxy;
+ doubanImageProxyType = config.SiteConfig.DoubanImageProxyType;
+ doubanImageProxy = config.SiteConfig.DoubanImageProxy;
+ disableYellowFilter = config.SiteConfig.DisableYellowFilter;
+ fluidSearch = config.SiteConfig.FluidSearch;
+ requireDeviceCode = config.SiteConfig.RequireDeviceCode;
+ customCategories = config.CustomCategories.filter(
+ (category) => !category.disabled
+ ).map((category) => ({
+ name: category.name || '',
+ type: category.type,
+ query: category.query,
+ }));
+ }
+
+ return {
+ STORAGE_TYPE: storageType,
+ SITE_NAME: siteName,
+ ANNOUNCEMENT: announcement,
+ DOUBAN_PROXY_TYPE: doubanProxyType,
+ DOUBAN_PROXY: doubanProxy,
+ DOUBAN_IMAGE_PROXY_TYPE: doubanImageProxyType,
+ DOUBAN_IMAGE_PROXY: doubanImageProxy,
+ DISABLE_YELLOW_FILTER: disableYellowFilter,
+ CUSTOM_CATEGORIES: customCategories,
+ FLUID_SEARCH: fluidSearch,
+ REQUIRE_DEVICE_CODE: requireDeviceCode,
+ };
+}
+
+export async function renderRuntimeConfigScript() {
+ const config = await getRuntimeConfig();
+ return `window.RUNTIME_CONFIG = ${JSON.stringify(config)};`;
+}
diff --git a/src/server/web-route.ts b/src/server/web-route.ts
new file mode 100644
index 0000000..5251ce2
--- /dev/null
+++ b/src/server/web-route.ts
@@ -0,0 +1,66 @@
+import { Readable } from 'node:stream';
+import type { ReadableStream as NodeReadableStream } from 'node:stream/web';
+
+import type { FastifyInstance, FastifyReply } from 'fastify';
+
+import type { AppRequest } from './web';
+import { createAppRequest, runWithRequestContext } from './web';
+
+type RouteModule = Record;
+type RouteHandler = (request: AppRequest) => Promise | Response;
+
+const METHODS = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'] as const;
+
+export function registerWebRouteModule(
+ app: FastifyInstance,
+ path: string,
+ routeModule: RouteModule
+) {
+ for (const method of METHODS) {
+ const handler = routeModule[method] as RouteHandler | undefined;
+ if (!handler) continue;
+
+ app.route({
+ method,
+ url: path,
+ exposeHeadRoute: method === 'GET' ? false : undefined,
+ handler: async (request, reply) => {
+ const appRequest = createAppRequest(request);
+ const response = await runWithRequestContext(request, appRequest, () =>
+ handler(appRequest)
+ );
+ return sendWebResponse(reply, response);
+ },
+ });
+ }
+}
+
+function sendWebResponse(reply: FastifyReply, response: Response) {
+ reply.status(response.status);
+
+ const setCookies = getSetCookies(response.headers);
+ response.headers.forEach((value, key) => {
+ if (key.toLowerCase() !== 'set-cookie') {
+ reply.header(key, value);
+ }
+ });
+ for (const cookie of setCookies) {
+ reply.header('set-cookie', cookie);
+ }
+
+ if (!response.body) {
+ return reply.send();
+ }
+
+ return reply.send(
+ Readable.fromWeb(response.body as unknown as NodeReadableStream)
+ );
+}
+
+function getSetCookies(headers: Headers) {
+ const maybeHeaders = headers as Headers & { getSetCookie?: () => string[] };
+ const cookies = maybeHeaders.getSetCookie?.();
+ if (cookies?.length) return cookies;
+ const single = headers.get('set-cookie');
+ return single ? [single] : [];
+}
diff --git a/src/server/web.ts b/src/server/web.ts
new file mode 100644
index 0000000..a792a62
--- /dev/null
+++ b/src/server/web.ts
@@ -0,0 +1,136 @@
+import { AsyncLocalStorage } from 'node:async_hooks';
+
+import type { FastifyRequest } from 'fastify';
+
+export type AppRequest = Request & {
+ cookies: {
+ get(name: string): { name: string; value: string } | undefined;
+ };
+};
+
+type CookieOptions = {
+ path?: string;
+ expires?: Date;
+ maxAge?: number;
+ sameSite?: 'strict' | 'lax' | 'none' | boolean;
+ httpOnly?: boolean;
+ secure?: boolean;
+};
+
+type RequestContext = {
+ request: FastifyRequest;
+ appRequest: AppRequest;
+};
+
+const requestContext = new AsyncLocalStorage();
+
+export class AppResponse extends Response {
+ cookies = {
+ set: (name: string, value: string, options: CookieOptions = {}) => {
+ this.headers.append('set-cookie', serializeCookie(name, value, options));
+ },
+ };
+
+ static json(data: unknown, init: ResponseInit = {}) {
+ const headers = new Headers(init.headers);
+ if (!headers.has('content-type')) {
+ headers.set('content-type', 'application/json');
+ }
+ return new AppResponse(JSON.stringify(data), {
+ ...init,
+ headers,
+ });
+ }
+}
+
+export function createAppRequest(request: FastifyRequest): AppRequest {
+ const protocol = request.headers['x-forwarded-proto'] || 'http';
+ const host = request.headers.host || 'localhost:3000';
+ const url = `${protocol}://${host}${request.url}`;
+ const headers = new Headers();
+
+ for (const [key, value] of Object.entries(request.headers)) {
+ if (Array.isArray(value)) {
+ headers.set(key, value.join(', '));
+ } else if (value !== undefined) {
+ headers.set(key, String(value));
+ }
+ }
+
+ const method = request.method.toUpperCase();
+ const body =
+ method === 'GET' || method === 'HEAD'
+ ? undefined
+ : serializeBody(request.body, headers);
+
+ const webRequest = new Request(url, { method, headers, body });
+ return Object.assign(webRequest, {
+ cookies: cookieReader(request),
+ });
+}
+
+export function runWithRequestContext(
+ request: FastifyRequest,
+ appRequest: AppRequest,
+ callback: () => T
+) {
+ return requestContext.run({ request, appRequest }, callback);
+}
+
+export async function cookies() {
+ const context = getRequestContext();
+ return {
+ get: (name: string) => context.appRequest.cookies.get(name),
+ };
+}
+
+export async function headers() {
+ const context = getRequestContext();
+ return context.appRequest.headers;
+}
+
+function getRequestContext() {
+ const context = requestContext.getStore();
+ if (!context) {
+ throw new Error('Request context is unavailable');
+ }
+ return context;
+}
+
+function cookieReader(request: FastifyRequest) {
+ return {
+ get: (name: string) => {
+ const value = request.cookies?.[name];
+ return value === undefined ? undefined : { name, value };
+ },
+ };
+}
+
+function serializeBody(body: unknown, headers: Headers) {
+ if (body === undefined || body === null) return undefined;
+ if (typeof body === 'string' || body instanceof FormData) return body;
+ if (body instanceof ArrayBuffer || body instanceof Uint8Array) {
+ return body as BodyInit;
+ }
+ if (!headers.has('content-type')) headers.set('content-type', 'application/json');
+ return JSON.stringify(body);
+}
+
+function serializeCookie(name: string, value: string, options: CookieOptions) {
+ const parts = [`${name}=${value}`];
+ if (options.maxAge !== undefined) parts.push(`Max-Age=${options.maxAge}`);
+ if (options.expires) parts.push(`Expires=${options.expires.toUTCString()}`);
+ if (options.path) parts.push(`Path=${options.path}`);
+ if (options.httpOnly) parts.push('HttpOnly');
+ if (options.secure) parts.push('Secure');
+ if (options.sameSite) {
+ const sameSite =
+ typeof options.sameSite === 'string'
+ ? options.sameSite
+ : options.sameSite === true
+ ? 'strict'
+ : undefined;
+ if (sameSite) parts.push(`SameSite=${sameSite}`);
+ }
+ return parts.join('; ');
+}
diff --git a/standalone-websocket.js b/standalone-websocket.js
index ed507d3..e4653ce 100644
--- a/standalone-websocket.js
+++ b/standalone-websocket.js
@@ -1,6 +1,6 @@
/**
* 独立的WebSocket服务器
- * 完全独立于Next.js,避免任何冲突
+ * 完全独立于主应用服务器,避免任何冲突
*/
const WebSocket = require('ws');
diff --git a/start.js b/start.js
deleted file mode 100644
index 5561a53..0000000
--- a/start.js
+++ /dev/null
@@ -1,90 +0,0 @@
-#!/usr/bin/env node
-
-/* eslint-disable no-console,@typescript-eslint/no-var-requires */
-const http = require('http');
-const path = require('path');
-
-// 调用 generate-manifest.js 生成 manifest.json
-function generateManifest() {
- console.log('Generating manifest.json for Docker deployment...');
-
- try {
- const generateManifestScript = path.join(
- __dirname,
- 'scripts',
- 'generate-manifest.js'
- );
- require(generateManifestScript);
- } catch (error) {
- console.error('❌ Error calling generate-manifest.js:', error);
- throw error;
- }
-}
-
-generateManifest();
-
-// 直接在当前进程中启动 standalone Server(`server.js`)
-require('./server.js');
-
-// 每 1 秒轮询一次,直到请求成功
-const TARGET_URL = `http://${process.env.HOSTNAME || 'localhost'}:${process.env.PORT || 3000
- }/login`;
-
-const intervalId = setInterval(() => {
- console.log(`Fetching ${TARGET_URL} ...`);
-
- const req = http.get(TARGET_URL, (res) => {
- // 当返回 2xx 状态码时认为成功,然后停止轮询
- if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
- console.log('Server is up, stop polling.');
- clearInterval(intervalId);
-
- setTimeout(() => {
- // 服务器启动后,立即执行一次 cron 任务
- executeCronJob();
- }, 3000);
-
- // 然后设置每小时执行一次 cron 任务
- setInterval(() => {
- executeCronJob();
- }, 60 * 60 * 1000); // 每小时执行一次
- }
- });
-
- req.setTimeout(2000, () => {
- req.destroy();
- });
-}, 1000);
-
-// 执行 cron 任务的函数
-function executeCronJob() {
- const cronUrl = `http://${process.env.HOSTNAME || 'localhost'}:${process.env.PORT || 3000
- }/api/cron`;
-
- console.log(`Executing cron job: ${cronUrl}`);
-
- const req = http.get(cronUrl, (res) => {
- let data = '';
-
- res.on('data', (chunk) => {
- data += chunk;
- });
-
- res.on('end', () => {
- if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
- console.log('Cron job executed successfully:', data);
- } else {
- console.error('Cron job failed:', res.statusCode, data);
- }
- });
- });
-
- req.on('error', (err) => {
- console.error('Error executing cron job:', err);
- });
-
- req.setTimeout(30000, () => {
- console.error('Cron job timeout');
- req.destroy();
- });
-}
diff --git a/tailwind.config.ts b/tailwind.config.ts
index 42666e7..78a0f72 100644
--- a/tailwind.config.ts
+++ b/tailwind.config.ts
@@ -6,7 +6,7 @@ const config: Config = {
content: [
'./src/pages/**/*.{js,ts,jsx,tsx,mdx}',
'./src/components/**/*.{js,ts,jsx,tsx,mdx}',
- './src/app/**/*.{js,ts,jsx,tsx,mdx}',
+ './src/pages/**/*.{js,ts,jsx,tsx,mdx}',
],
theme: {
extend: {
diff --git a/tsconfig.json b/tsconfig.json
index 5717967..b497569 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -16,7 +16,7 @@
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
- "jsx": "preserve",
+ "jsx": "react-jsx",
"baseUrl": ".",
"paths": {
"@/*": [
@@ -27,17 +27,16 @@
]
},
"incremental": true,
- "plugins": [
- {
- "name": "next"
- }
+ "types": [
+ "node",
+ "jest",
+ "@testing-library/jest-dom",
+ "vite/client"
]
},
"include": [
- "next-env.d.ts",
"**/*.ts",
- "**/*.tsx",
- ".next/types/**/*.ts"
+ "**/*.tsx"
],
"exclude": [
"node_modules"
diff --git a/vite.config.ts b/vite.config.ts
new file mode 100644
index 0000000..ab5dad2
--- /dev/null
+++ b/vite.config.ts
@@ -0,0 +1,33 @@
+import path from 'node:path';
+
+import babel from '@rolldown/plugin-babel';
+import react, { reactCompilerPreset } from '@vitejs/plugin-react';
+import { defineConfig } from 'vite';
+import { VitePWA } from 'vite-plugin-pwa';
+
+export default defineConfig({
+ plugins: [
+ react(),
+ babel({
+ presets: [reactCompilerPreset()],
+ }),
+ VitePWA({
+ registerType: 'autoUpdate',
+ manifest: false,
+ workbox: {
+ globPatterns: ['**/*.{js,css,html,ico,png,svg,webmanifest}'],
+ maximumFileSizeToCacheInBytes: 8 * 1024 * 1024,
+ },
+ }),
+ ],
+ resolve: {
+ alias: {
+ '@': path.resolve(__dirname, 'src'),
+ '~': path.resolve(__dirname, 'public'),
+ },
+ },
+ build: {
+ outDir: 'dist/client',
+ emptyOutDir: true,
+ },
+});