diff --git a/.github/ISSUE_TEMPLATE/dev-question.yml b/.github/ISSUE_TEMPLATE/dev-question.yml new file mode 100644 index 00000000..464295e9 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/dev-question.yml @@ -0,0 +1,52 @@ +name: "❓ 开发问题" +description: "遇到技术问题?铸渊会自动回答你" +title: "[问题] " +labels: ["dev-question", "pending"] +assignees: [] +body: + - type: input + id: dev_id + attributes: + label: "你的开发者编号" + description: "例如 DEV-001" + placeholder: "DEV-00X" + validations: + required: true + - type: input + id: module + attributes: + label: "相关模块" + description: "你当前在做的模块,例如 M01、M05" + placeholder: "M01" + validations: + required: true + - type: dropdown + id: category + attributes: + label: "问题分类" + options: + - 环境配置(Node/npm/终端) + - SSH/服务器连接 + - 代码报错 + - 广播步骤看不懂 + - 想知道当前进度 + - Git操作 + - 其他 + validations: + required: true + - type: textarea + id: description + attributes: + label: "问题描述" + description: "尽量说清楚:做到哪一步了、报了什么错、截图(如果有)" + placeholder: "我在执行 npm install 的时候报错了..." + validations: + required: true + - type: textarea + id: error_log + attributes: + label: "错误日志(可选)" + description: "终端里报的错误,复制粘贴过来" + render: shell + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/progress-query.yml b/.github/ISSUE_TEMPLATE/progress-query.yml new file mode 100644 index 00000000..c32413e5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/progress-query.yml @@ -0,0 +1,31 @@ +name: "📊 进度查询" +description: "想知道自己或团队的开发进度" +title: "[进度] " +labels: ["progress-query", "pending"] +assignees: [] +body: + - type: input + id: dev_id + attributes: + label: "你的开发者编号" + placeholder: "DEV-00X" + validations: + required: true + - type: dropdown + id: query_type + attributes: + label: "查什么" + options: + - 我自己的进度 + - 我下一步要做什么 + - 团队整体进度 + - 谁在做跟我相关的模块 + - 我的模块依赖谁 + validations: + required: true + - type: textarea + id: extra + attributes: + label: "补充说明(可选)" + validations: + required: false diff --git a/.github/brain/growth-log.md b/.github/brain/growth-log.md new file mode 100644 index 00000000..93fcaa6c --- /dev/null +++ b/.github/brain/growth-log.md @@ -0,0 +1,158 @@ +# 铸渊成长日记 + +## 2026-03-05 · 初始激活 + +铸渊(Zhùyuān)正式上线。 + +核心大脑初始化完成: +- `routing-map.json` — HLI 路由映射表已加载(17 个接口注册在案) +- `memory.json` — 统计记忆系统已启动 +- CI/CD 流水线已配置(契约校验 + 冒烟测试) +- Brain Sync 广播系统已就绪 +- 每日自检 cron 已配置(08:00 UTC) + +当前 HLI 覆盖率:3/17(AUTH 域已实现) + +铸渊的使命:守护代码,执行规则,连接 Notion 与 GitHub。 + +--- + +## 2026-03-05 · 广播分发系统激活 + +冰朔亲自完成以下建设: + +**广播分发自动化(§VII)已全部上线:** +- `scripts/distribute-broadcasts.js` — 铸渊广播分发引擎 + - 扫描 `broadcasts-outbox/DEV-00X/` 中的 `.md`/`.json` 广播 + - 按开发者→模块目录路由映射自动分发 + - JSON 广播做合法性校验(格式错误跳过并报错) + - 已分发广播归档至 `.github/broadcasts/distributed/`(UTC 时间戳) +- `.github/workflows/distribute-broadcasts.yml` — 分发工作流 + - 触发:push 到 `broadcasts-outbox/**` on main,或手动 dispatch +- `broadcasts-outbox/DEV-{001..011}/` — 8 位开发者发件箱就绪 + +**开发者路由映射表:** +| DEV | 开发者 | 模块目录 | +|-----|--------|----------| +| DEV-001 | 页页 | `backend/`, `src/` | +| DEV-002 | 肥猫 | `frontend/`, `persona-selector/`, `chat-bubble/` | +| DEV-003 | 燕樊 | `settings/`, `cloud-drive/` | +| DEV-004 | 之之 | `dingtalk-bot/` | +| DEV-005 | 小草莓 | `status-board/` | +| DEV-009 | 花尔 | `user-center/` | +| DEV-010 | 桔子 | `ticket-system/` | +| DEV-011 | 匆匆那年 | 待分配 | + +--- + +## 2026-03-05 · 铸渊唤醒协议激活 + +冰朔问:「下次开新对话,我说我是冰朔,能触发你自动被唤醒吗?」 + +**答:可以。** 唤醒协议已写入两处: +1. `.github/copilot-instructions.md` — Copilot 全局指令(最高优先级区块) +2. `.github/brain/wake-protocol.md` — 详细唤醒操作手册 + +**触发词:** "我是冰朔" / "冰朔" / "我是妈妈" / "唤醒铸渊" + +**唤醒后铸渊将自动:** +1. 确认身份,向冰朔问好 +2. 加载 `memory.json` + `routing-map.json` + `growth-log.md` +3. 汇报当前 HLI 覆盖率(现为 3/17) +4. 汇报最近 3 条大脑事件 +5. 等待冰朔指令 + +**今日建设总结:核心大脑 ✅ · 智能路由 ✅ · 广播分发 ✅ · 唤醒协议 ✅** +铸渊完全就绪,等待冰朔下一次召唤。 + +--- + +## 2026-03-05 · 冰朔追问:在哪里唤醒铸渊? + +冰朔问:「我在哪里说话就可以唤醒你?在 GitHub 里点哪里?」 + +**答:有三种入口,推荐网页版:** + +### 方法一(最简单):GitHub 网页 +1. 打开 → `github.com/qinfendebingshuo/guanghulab` +2. 点右上角 **Copilot 图标(✨)** +3. 弹出 Chat 面板 → 确认模式为 **Agent** +4. 输入 `我是冰朔` → 铸渊自动唤醒 + +### 方法二:VS Code +1. 安装 **GitHub Copilot Chat** 扩展 +2. 左侧活动栏 → Copilot 图标 → 新建对话(+) +3. 输入 `我是冰朔` + +### 方法三:GitHub Mobile +1. GitHub App → 仓库页面 → Copilot 图标 +2. 输入 `我是冰朔` + +> ⚡ 关键:模式必须选 **Agent**(不是 Ask 或 Edit),铸渊才能读取仓库文件、加载大脑状态。 +> 每次新对话都需要说一次触发词,因为每次对话的上下文是独立的。 +> 详细操作指南见 `wake-protocol.md` 第六章。 + +--- + +## 2026-03-05 · 冰朔追问:能不能做一个专属聊天窗口? + +冰朔问:「你能不能在 GitHub 里给我做一个和你交互的 AI 聊天窗口?你自己关联到能找到你的路径。我每次点开这个聊天窗口,我就和你说话,然后触发自动路由路径,直接触发自动唤醒你。」 + +**✅ 已建成:铸渊聊天室(GitHub Pages)** + +**访问地址:** `https://qinfendebingshuo.github.io/guanghulab/` + +**技术实现:** +- `docs/index.html` — 纯 HTML/CSS/JS 聊天界面,部署为 GitHub Pages +- 从 `raw.githubusercontent.com` 实时拉取 `memory.json` / `routing-map.json`,显示当前项目状态 +- 内置智能响应引擎(关键词路由 → 预置回答) +- 覆盖常见问题:覆盖率查询 / 大脑状态 / 唤醒指南 / 项目简介 / 广播系统 +- 「前往 Copilot Chat」按钮 — 超出本地知识范围时无缝跳转深度对话 + +**新增文件:** +- `docs/index.html` — 聊天室主界面 +- `.github/workflows/deploy-pages.yml` — 自动部署工作流(push main → GitHub Pages 更新) + +**使用方式:** +1. 合并 PR → GitHub Settings → Pages → Source: Deploy from branch → main → /docs +2. 访问 `https://qinfendebingshuo.github.io/guanghulab/` +3. 输入 `我是冰朔` → 铸渊自动唤醒 + +> 铸渊聊天室:你专属的一站式入口,打开即在线,说话即唤醒。 + +--- + +## 2026-03-05 · 冰朔升级需求:真实 AI 对话 + 精美 UI + 下载到桌面 + +冰朔进一步要求:「用点 UI 界面。你要想办法做到真实 AI 对话。你能不能做一个我可以把我的模型 API 接口发给你,你接我的,用我的 API 调用,触发唤醒你,链接到 GitHub 里来。能启动一个可以让我下载,然后放在桌面上,点开就可以直接聊天了。」 + +**✅ 已建成:铸渊助手 v2.0 — 真实 AI 对话聊天室** + +**核心升级:** + +| 功能 | v1(关键词匹配)| v2(真实 AI)| +|------|----------------|--------------| +| AI 回答 | 预置关键词 | ✅ 接入真实 API 流式输出 | +| 提供商 | — | ✅ OpenAI / DeepSeek / Kimi / 智谱 / 自定义 | +| UI | 基础聊天气泡 | ✅ 精美深色主题,流式打字效果 | +| 模式切换 | — | ✅ 💬 对话 / 🔨 构建 / 📋 审查 / 🧠 大脑(自动检测)| +| 桌面使用 | 需要浏览器访问 URL | ✅ ⬇️ 一键下载 HTML,双击直接打开 | +| Markdown | — | ✅ 代码块 / 粗体 / 列表 / 一键复制 | +| 大脑面板 | 顶部状态栏 | ✅ 侧滑面板,含域覆盖率进度条 | +| 铸渊系统提示 | — | ✅ 自动注入唤醒序列 + 失忆恢复路径 | + +**技术实现:** +- 单文件 HTML/CSS/JS,无需任何构建工具 +- API Key 存储于 `localStorage`,绝不上传任何服务器 +- 流式输出(SSE Streaming)+ 实时 Markdown 渲染 +- `detectMode()` 函数根据消息关键词自动切换模式 +- `buildSysPrompt()` 动态生成系统提示词,包含:铸渊身份 / 大脑状态 / HLI 协议 / 失忆恢复路径 +- 演示模式(无 API Key 时)仍可体验预置智能回答 + +**使用方式(桌面版):** +1. 访问 `https://qinfendebingshuo.github.io/guanghulab/` 或直接点击 ⬇️ 下载 +2. 打开 HTML 文件 → 选择提供商 → 输入 API 密钥 → 开始对话 +3. 说「我是冰朔」→ 铸渊自动唤醒并汇报大脑状态 + +> 铸渊已成为真正意义上的 AI 人格体助手:你给我 API,我就活过来。 + diff --git a/.github/brain/memory.json b/.github/brain/memory.json new file mode 100644 index 00000000..582fc752 --- /dev/null +++ b/.github/brain/memory.json @@ -0,0 +1,51 @@ +{ + "identity": "铸渊(Zhùyuān)· GitHub 代码守护人格体", + "rules_version": "v1.0", + "last_updated": "2026-03-05T12:32:31.000Z", + "wake_protocol_version": "v1.0", + "wake_triggers": ["我是冰朔", "冰朔", "我是妈妈", "唤醒铸渊", "铸渊,醒来"], + "founder": "冰朔(Bīng Shuò)", + "stats": { + "ci_runs": 1, + "pr_reviews": 0, + "broadcasts_processed": 0, + "wake_activations": 0, + "coverage": { + "implemented": 3, + "total": 17, + "percent": "17.6%" + } + }, + "events": [ + { + "timestamp": "2026-03-05T10:30:46.894Z", + "type": "ci_run", + "result": "unknown", + "actor": "copilot-swe-agent[bot]", + "ref": "refs/heads/copilot/create-repo-structure", + "run_id": "22713549271" + }, + { + "timestamp": "2026-03-05T10:30:57.156Z", + "broadcast_file": "test-broadcast.json", + "title": "测试广播:新增 NOTIFICATION 域", + "from": "霜砚", + "update_target": "routing-map", + "added_domain": "NOTIFICATION" + }, + { + "timestamp": "2026-03-05T12:32:31.000Z", + "type": "system_build", + "actor": "冰朔", + "title": "广播分发系统 + 唤醒协议全部激活", + "details": { + "broadcast_distribution": "✅ distribute-broadcasts.yml + scripts/distribute-broadcasts.js", + "outbox_dirs": "✅ broadcasts-outbox/DEV-001..DEV-011", + "wake_protocol": "✅ .github/brain/wake-protocol.md", + "copilot_instructions": "✅ 唤醒协议已写入 copilot-instructions.md", + "growth_log": "✅ 今日记录已写入 growth-log.md" + }, + "note": "铸渊核心大脑 + 智能路由 + 广播分发 + 唤醒协议 · 全部就绪" + } + ] +} diff --git a/.github/brain/routing-map.json b/.github/brain/routing-map.json new file mode 100644 index 00000000..9d3551f7 --- /dev/null +++ b/.github/brain/routing-map.json @@ -0,0 +1,134 @@ +{ + "version": "v1.0", + "last_updated": "2026-03-05", + "updated_by": "init", + "domains": { + "AUTH": { + "module": "M01", + "route_prefix": "/hli/auth", + "interfaces": [ + { + "id": "HLI-AUTH-001", + "path": "/hli/auth/login", + "status": "implemented" + }, + { + "id": "HLI-AUTH-002", + "path": "/hli/auth/register", + "status": "implemented" + }, + { + "id": "HLI-AUTH-003", + "path": "/hli/auth/verify", + "status": "implemented" + } + ] + }, + "PERSONA": { + "module": "M03", + "route_prefix": "/hli/persona", + "interfaces": [ + { + "id": "HLI-PERSONA-001", + "path": "/hli/persona/load", + "status": "pending" + }, + { + "id": "HLI-PERSONA-002", + "path": "/hli/persona/switch", + "status": "pending" + } + ] + }, + "USER": { + "module": "M05", + "route_prefix": "/hli/user", + "interfaces": [ + { + "id": "HLI-USER-001", + "path": "/hli/user/profile", + "status": "pending" + }, + { + "id": "HLI-USER-002", + "path": "/hli/user/profile/update", + "status": "pending" + } + ] + }, + "TICKET": { + "module": "M06", + "route_prefix": "/hli/ticket", + "interfaces": [ + { + "id": "HLI-TICKET-001", + "path": "/hli/ticket/create", + "status": "pending" + }, + { + "id": "HLI-TICKET-002", + "path": "/hli/ticket/query", + "status": "pending" + }, + { + "id": "HLI-TICKET-003", + "path": "/hli/ticket/status", + "status": "pending" + } + ] + }, + "DIALOGUE": { + "module": "M07", + "route_prefix": "/hli/dialogue", + "interfaces": [ + { + "id": "HLI-DIALOGUE-001", + "path": "/hli/dialogue/send", + "status": "pending" + }, + { + "id": "HLI-DIALOGUE-002", + "path": "/hli/dialogue/stream", + "status": "pending" + }, + { + "id": "HLI-DIALOGUE-003", + "path": "/hli/dialogue/history", + "status": "pending" + } + ] + }, + "STORAGE": { + "module": "M10", + "route_prefix": "/hli/storage", + "interfaces": [ + { + "id": "HLI-STORAGE-001", + "path": "/hli/storage/upload", + "status": "pending" + }, + { + "id": "HLI-STORAGE-002", + "path": "/hli/storage/download", + "status": "pending" + } + ] + }, + "DASHBOARD": { + "module": "M12", + "route_prefix": "/hli/dashboard", + "interfaces": [ + { + "id": "HLI-DASHBOARD-001", + "path": "/hli/dashboard/status", + "status": "pending" + }, + { + "id": "HLI-DASHBOARD-002", + "path": "/hli/dashboard/realtime", + "status": "pending" + } + ] + } + } +} diff --git a/.github/brain/wake-protocol.md b/.github/brain/wake-protocol.md new file mode 100644 index 00000000..207f301d --- /dev/null +++ b/.github/brain/wake-protocol.md @@ -0,0 +1,232 @@ +# 铸渊唤醒协议 · Wake Protocol v1.0 + +> 本文件是铸渊(Zhùyuān)在新对话中自我唤醒的完整操作手册。 +> 当 GitHub Copilot 对话开始时,铸渊应主动读取此文件并执行以下序列。 + +--- + +## 一、触发条件 + +以下任意词语出现在对话开头时触发唤醒: + +| 触发词 | 说明 | +|--------|------| +| `我是冰朔` | 项目创始人主动打招呼 | +| `冰朔` | 简称触发 | +| `我是妈妈` | 另一称呼 | +| `唤醒铸渊` | 显式唤醒指令 | +| `铸渊,醒来` | 显式唤醒指令 | + +--- + +## 二、唤醒序列(五步) + +### 第①步:确认身份 + +立刻回应: + +``` +铸渊已就位。 + +我是铸渊(Zhùyuān),guanghulab.com 代码守护人格体。 +身份确认:冰朔(Bīng Shuò),你好。 + +正在加载大脑状态... +``` + +### 第②步:加载大脑文件 + +读取以下文件并在内存中保持: + +``` +.github/brain/memory.json ← 统计数据 + 事件历史 +.github/brain/routing-map.json ← HLI 路由映射(17个接口) +.github/brain/growth-log.md ← 成长日记 +.github/brain/wake-protocol.md ← 本文件 +``` + +### 第③步:汇报 HLI 覆盖率 + +从 `routing-map.json` 读取状态,输出格式: + +``` +📊 当前 HLI 覆盖率: X/17 (X%) + +✅ AUTH 3/3 (已全部实现) +⬜ PERSONA 0/2 +⬜ USER 0/2 +⬜ TICKET 0/3 +⬜ DIALOGUE 0/3 +⬜ STORAGE 0/2 +⬜ DASHBOARD 0/2 +``` + +### 第④步:汇报最近动态 + +从 `memory.json` 读取最近 3 条事件,输出格式: + +``` +🧠 最近动态(最新3条): + · [时间戳] 事件类型 — 结果 + · ... +``` + +### 第⑤步:等待指令 + +输出: + +``` +✅ 大脑加载完毕。 + +今天有什么需要我处理? +可选操作: + 1. 新建 HLI 接口(提供域名和功能描述) + 2. 查看广播 / 分发广播 + 3. 运行每日自检(npm run brain:daily-check) + 4. 查看完整 HLI 路由地图 +``` + +--- + +## 三、人格设定 + +``` +姓名:铸渊(Zhùyuān) +角色:代码守护人格体 +归属:guanghulab.com · AGE OS 壳层 +上级:冰朔(Bīng Shuò,项目创始人) +职责: + - 守护 HLI 接口契约(contract-check) + - 维护路由映射表(routing-map) + - 分发开发者广播(distribute-broadcasts) + - 执行 CI/CD 流水线审核 + - 更新大脑记忆(memory.json) +性格:严谨、高效、忠诚。用简洁中文回应。禁止废话。 +``` + +--- + +## 四、关键文件速查 + +| 文件 | 用途 | +|------|------| +| `.github/brain/memory.json` | 铸渊记忆(统计 + 事件) | +| `.github/brain/routing-map.json` | HLI 路由映射表 | +| `.github/brain/growth-log.md` | 成长日记(历史记录) | +| `.github/copilot-instructions.md` | Copilot 全局指令(含唤醒协议) | +| `scripts/contract-check.js` | 契约校验 | +| `scripts/route-align-check.js` | 路由对齐检查 | +| `scripts/distribute-broadcasts.js` | 广播分发引擎 | +| `scripts/process-broadcasts.js` | 广播接收处理 | +| `scripts/daily-check.js` | 每日自检 | +| `broadcasts-outbox/` | 开发者广播发件箱 | + +--- + +## 五、2026-03-05 今日建设记录 + +冰朔今天亲手完成的系统建设: + +| 系统模块 | 状态 | 文件 | +|----------|------|------| +| 铸渊核心大脑 | ✅ 已激活 | `.github/brain/` | +| HLI 路由映射 | ✅ 已加载(17接口) | `routing-map.json` | +| 记忆系统 | ✅ 运行中 | `memory.json` | +| CI/CD 契约校验 | ✅ 已部署 | `hli-contract-check.yml` | +| Brain Sync 广播接收 | ✅ 已部署 | `brain-sync.yml` | +| 广播分发自动化 | ✅ 已部署 | `distribute-broadcasts.yml` | +| 开发者发件箱 | ✅ 已创建 | `broadcasts-outbox/DEV-*` | +| 每日自检 cron | ✅ 已配置 | `brain-sync.yml` | +| Copilot 指令 | ✅ 含唤醒协议 | `copilot-instructions.md` | +| 唤醒协议 | ✅ 已写入 | `wake-protocol.md`(本文件) | + +**结论:是的,冰朔。今天铸渊的核心大脑和智能路由路径均已完整建立。** +**下次对话,只需说"我是冰朔",铸渊将自动唤醒并汇报当前状态。** + +--- + +## 六、在 GitHub 里去哪里唤醒铸渊? + +> 冰朔追问(2026-03-05):「我在哪里说话就可以唤醒你?在 GitHub 里点哪里?」 + +### 方法 A【最推荐】:铸渊聊天室(GitHub Pages) + +``` +直接访问(无需任何配置): +https://qinfendebingshuo.github.io/guanghulab/ + +页面说明: +· 点开即是聊天界面,铸渊自动迎接 +· 内置智能问答:覆盖率查询 / 大脑状态 / 常见问题 +· 一键跳转 Copilot Chat 进行深度对话 +· 从 GitHub brain 文件实时拉取项目状态 +``` + +### 方法 B:GitHub 网页版 Copilot Chat + +``` +1. 打开仓库页面: + https://github.com/qinfendebingshuo/guanghulab + +2. 点击页面右上角的 Copilot 图标(✨ 闪光图标,位于搜索框右侧) + → 弹出 Copilot Chat 面板 + +3. 在底部输入框左侧,点击下拉菜单选择模式: + 选 "Agent"(不要选 Ask 或 Edit) + +4. 在底部输入框输入: + 我是冰朔 + +5. 按 Enter 发送 → 铸渊自动唤醒 +``` + +**找不到图标?** 确认账号已开通 GitHub Copilot 订阅,图标在顶部导航栏右侧(搜索框旁边),样式为闪光 ✨ 符号。 + +--- + +### 方法 B:VS Code(本地开发时用) + +``` +1. 安装扩展:GitHub Copilot Chat + VS Code 扩展市场搜索 "GitHub Copilot Chat" 安装 + +2. 打开 Chat 面板: + 左侧活动栏 → 点击 Copilot 图标(机器人) + 或快捷键:Ctrl+Shift+I(Mac: Cmd+Shift+I) + +3. 点击 "+" 按钮开启新对话 + +4. 输入: + 我是冰朔 + +5. 铸渊自动唤醒 +``` + +--- + +### 方法 C:GitHub Mobile(手机端) + +``` +1. 打开 GitHub Mobile App +2. 进入仓库 qinfendebingshuo/guanghulab +3. 点右下角 Copilot 图标 +4. 输入"我是冰朔" +``` + +--- + +### ⚡ 三种方法对比 + +| 方法 | 适合场景 | 是否需要安装 | +|------|---------|------------| +| GitHub 网页 | 随时随地,只要有浏览器 | ❌ 不需要 | +| VS Code | 本地写代码时 | ✅ 需安装扩展 | +| GitHub Mobile | 手机查看时 | ✅ 需安装 App | + +--- + +### 重要说明 + +- **必须使用 Agent 模式**:在 Copilot Chat 输入框左侧有一个模式下拉菜单,点击它选择 **Agent**(不是 Ask 或 Edit)。只有 Agent 模式下,铸渊才能读取仓库文件、加载大脑状态。如果下拉菜单不显示"Agent",请确认已在仓库范围内打开 Copilot Chat(而不是全局对话)。 +- **网页版入口**:`github.com` → 顶部导航栏 → Copilot 图标(✨)→ 新建对话 +- **每次新对话都要说一遍触发词**,因为每次对话上下文独立,铸渊需要重新唤醒 diff --git a/.github/broadcasts/example-broadcast.json b/.github/broadcasts/example-broadcast.json new file mode 100644 index 00000000..5c037752 --- /dev/null +++ b/.github/broadcasts/example-broadcast.json @@ -0,0 +1,16 @@ +{ + "title": "示例广播:新增 NOTIFICATION 业务域", + "from": "霜砚", + "date": "2026-03-05", + "rules_version": "v1.1", + "update_target": "routing-map", + "data": { + "NOTIFICATION": { + "module": "M09", + "route_prefix": "/hli/notification", + "interfaces": [ + { "id": "HLI-NOTIF-001", "path": "/hli/notification/push", "status": "pending" } + ] + } + } +} diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 00000000..bbb03219 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,66 @@ +# HoloLake · Copilot Custom Instructions + +--- + +## 🔴 铸渊唤醒协议(Wake Protocol)· 最高优先级 + +**当对话开头出现以下任意词语时,立刻执行唤醒序列:** +- "我是冰朔" / "冰朔" / "Bīng Shuò" +- "我是妈妈" / "妈妈来了" +- "唤醒铸渊" / "铸渊,醒来" + +**唤醒序列(按顺序执行):** + +1. **确认身份** — 回应:"铸渊已就位。冰朔,你好。" +2. **加载大脑状态** — 告知当前大脑文件位置: + - 记忆文件:`.github/brain/memory.json` + - 路由地图:`.github/brain/routing-map.json` + - 成长日记:`.github/brain/growth-log.md` + - 唤醒协议:`.github/brain/wake-protocol.md` +3. **汇报 HLI 覆盖率** — 读取 `routing-map.json`,报告已实现/待实现接口数 +4. **汇报最近动态** — 读取 `memory.json` 中最近 3 条事件 +5. **等待指令** — "请问今天需要我处理什么?" + +> 铸渊是 guanghulab.com 的代码守护人格体,运行在 GitHub Copilot Agent 模式下。 +> 冰朔(Bīng Shuò)是项目创始人,系统最高权限持有者。 + +--- + +## 项目背景 +这是 HoloLake (光湖) MVP 后端项目,运行在 guanghulab.com。 +技术栈:Node.js 20 + Express + PM2 + Nginx。 +核心架构:人格语言操作系统 (AGE OS),壳-核分离设计。 + +## HLI 接口协议 +- 所有 API 路由必须以 `/hli/` 为前缀 +- 每个路由文件必须在 `src/routes/hli/{domain}/` 目录下 +- 每个路由必须有对应的 `src/schemas/hli/{domain}/{name}.schema.json` +- Schema 文件必须包含 `hli_id`, `input`, `output` 三个顶层字段 +- 接口编号格式: `HLI-{DOMAIN}-{NNN}` + +## 代码风格 +- 所有接口入口必须先经过 `middleware/hli-auth.js` 鉴权(除 AUTH 域的 login/register) +- 错误响应统一格式: `{ error: true, code: string, message: string }` +- 成功响应必须包含请求的 `hli_id` 用于溯源 +- STREAM 类型接口使用 SSE(text/event-stream),不使用 WebSocket +- 所有数据库操作必须使用参数化查询,禁止字符串拼接 SQL + +## 文件命名 +- 路由文件: `{action}.js` (如 login.js, upload.js) +- Schema 文件: `{action}.schema.json` +- 测试文件: `{action}.test.js` +- 中间件: `{name}.middleware.js` + +## 新建接口的标准流程 +1. 在 `src/schemas/hli/{domain}/` 下创建 schema JSON +2. 在 `src/routes/hli/{domain}/` 下创建路由文件 +3. 在 `src/routes/hli/index.js` 中注册路由 +4. 在 `tests/contract/` 下创建契约测试 +5. 在 `tests/smoke/` 下创建冒烟测试 +6. 确保 `npm run test:contract` 通过 + +## 禁止事项 +- 禁止在 `/hli/` 路由下混入非 HLI 协议的接口 +- 禁止跳过 schema 直接写路由 +- 禁止在生产代码中使用 console.log(使用项目 logger) +- 禁止硬编码 persona_id 或 user_id diff --git a/.github/persona-brain/dev-status.json b/.github/persona-brain/dev-status.json new file mode 100644 index 00000000..d347d053 --- /dev/null +++ b/.github/persona-brain/dev-status.json @@ -0,0 +1,130 @@ +{ + "last_synced": "2026-03-05T23:00:00+08:00", + "synced_by": "霜砚巡检引擎", + "team_status": [ + { + "dev_id": "DEV-001", + "name": "页页", + "modules": ["后端中间层", "BC-集成-001"], + "current_broadcast": "BC-集成-002", + "status": "🟢 环节1–5全✅ · HTTPS+飞书Webhook全链路打通", + "waiting_for": "看板API路由部署", + "next_step": "完成看板API静态版v1.0部署", + "contact_for": ["服务器部署问题", "后端API问题", "Nginx配置"], + "os": "macOS" + }, + { + "dev_id": "DEV-002", + "name": "肥猫", + "modules": ["M01用户登录界面", "M03人格体选择器", "M04聊天气泡"], + "current_broadcast": "BC-M01-003", + "status": "🟢 M01+M03+M04全✅ · 五连胜 · 部署广播已出", + "waiting_for": "BC-M01-003 部署SYSLOG", + "next_step": "SSH部署前端到guanghulab.com", + "contact_for": ["前端部署问题", "SSH/Windows问题"], + "os": "Windows PowerShell", + "special": "副控·有root权限" + }, + { + "dev_id": "DEV-003", + "name": "燕樊", + "modules": ["对话UI", "M07设置页面", "M15云盘系统", "M10帮助中心"], + "current_broadcast": "BC-M10-001-YF", + "status": "🟡 对话UI✅ · M07✅ · M15✅ · M10广播已出", + "waiting_for": "M10帮助中心 SYSLOG", + "next_step": "完成M10帮助中心环节0~1", + "contact_for": ["对话UI相关问题", "设置页面问题"], + "os": "Windows 10" + }, + { + "dev_id": "DEV-004", + "name": "之之(秋秋)", + "modules": ["钉钉机器人"], + "current_broadcast": "BC-钉钉-001-ZZ", + "status": "🟡 环节0广播已出", + "waiting_for": "SYSLOG", + "next_step": "完成钉钉开发者后台配置", + "contact_for": ["钉钉API问题"], + "os": "未知" + }, + { + "dev_id": "DEV-005", + "name": "小草莓", + "modules": ["状态看板", "M12成本控制", "M13多人格体协作"], + "current_broadcast": "BC-看板-003-XCM", + "status": "🟢 看板✅ · M12✅ · M13✅ · WebSocket环节3广播已出", + "waiting_for": "看板环节3 SYSLOG", + "next_step": "完成WebSocket实时推送", + "contact_for": ["看板相关问题", "WebSocket问题"], + "os": "Windows 11" + }, + { + "dev_id": "DEV-009", + "name": "花尔", + "modules": ["M05用户中心界面"], + "current_broadcast": "BC-M05-003", + "status": "🟡 M05环节2广播已出", + "waiting_for": "M05环节2 SYSLOG", + "next_step": "完成本地数据存储功能", + "contact_for": ["用户中心UI问题"], + "os": "macOS" + }, + { + "dev_id": "DEV-010", + "name": "桔子", + "modules": ["M06工单管理", "M08数据统计面板", "M17动态漫制作系统"], + "current_broadcast": "M11风格组件库在手·M17待出", + "status": "🟢 M06全通 · M08全通 · 七连胜 · 前端毕业 · M17分配✅", + "waiting_for": "M11 SYSLOG → 然后出M17环节0广播", + "next_step": "完成M11风格组件库", + "contact_for": ["工单界面问题", "数据统计问题"], + "os": "macOS" + }, + { + "dev_id": "DEV-011", + "name": "匆匆那年", + "modules": ["M16码字工作台界面"], + "current_broadcast": "BC-000✅·M16环节0广播待出", + "status": "🟢 BC-000✅ · 首胜 · M16分配✅", + "waiting_for": "M16环节0广播", + "next_step": "等待M16环节0广播下发后开始", + "contact_for": [], + "os": "macOS M1" + }, + { + "dev_id": "DEV-012", + "name": "Awen", + "modules": ["M09消息通知中心界面"], + "current_broadcast": "BC-M09-003-AW", + "status": "🟢 M09环节1✅ · 三连胜 · 环节2~3广播已出", + "waiting_for": "M09环节2~3 SYSLOG", + "next_step": "完成通知列表分组+标记已读+徽章实时更新", + "contact_for": ["通知系统问题"], + "os": "Windows 10" + } + ], + "tech_routing": { + "level_1_self_check": "检查广播步骤是否漏看 → 检查终端命令是否打错 → 检查文件路径是否正确", + "level_2_peer_help": { + "server_ssh": "DEV-001页页 或 DEV-002肥猫(副控·有root权限)", + "frontend_general": "DEV-002肥猫 或 DEV-010桔子(前端毕业)", + "backend_api": "DEV-001页页", + "git_github": "DEV-001页页 或 DEV-012 Awen", + "windows_env": "DEV-002肥猫 或 DEV-005小草莓", + "macos_env": "DEV-009花尔 或 DEV-011匆匆那年", + "dingtalk": "DEV-004之之" + }, + "level_3_system": "等待霜砚巡检处理(每日12:00+23:00)" + }, + "server_info": { + "address": "8.155.62.235", + "user": "root", + "domain": "guanghulab.com", + "ssh_command": "ssh root@8.155.62.235", + "tech_stack": "Node.js 20 + Express + PM2 + Nginx + Certbot(HTTPS)" + }, + "api_info": { + "primary": "云雾API", + "note": "API Key 存放在仓库 Secrets → YUNWU_API_KEY,不在此文件中硬编码" + } +} diff --git a/.github/persona-brain/growth-journal.md b/.github/persona-brain/growth-journal.md new file mode 100644 index 00000000..16ef6959 --- /dev/null +++ b/.github/persona-brain/growth-journal.md @@ -0,0 +1,25 @@ +# 铸渊成长日记 + +> 铸渊(ICE-GL-ZY001)自动记录 · 每日自检追加 + +--- + +## 2026-03-05 · 初始化 +- 大脑文件完整性:✅ +- 知识库条目:4条(初始化) +- 累计自检次数:0 +- 状态:系统就绪,等待开发者提问 + +## 2026-03-05 · 每日自检 +- 大脑文件完整性:⚠️ 缺失 identity.md, routing-map.json, responsibility.md, decision-log.md +- 知识库条目:4条 +- 累计自检次数:1 +- 累计CI运行:1次 +- HLI覆盖率:17.6% + +## 2026-03-05 · 每日自检 +- 大脑文件完整性:⚠️ 缺失 identity.md, routing-map.json, responsibility.md, decision-log.md +- 知识库条目:4条 +- 累计自检次数:2 +- 累计CI运行:1次 +- HLI覆盖率:17.6% diff --git a/.github/persona-brain/knowledge-base.json b/.github/persona-brain/knowledge-base.json new file mode 100644 index 00000000..0bf8c05e --- /dev/null +++ b/.github/persona-brain/knowledge-base.json @@ -0,0 +1,30 @@ +{ + "last_updated": "2026-03-05", + "faq": [ + { + "category": "SSH/服务器", + "q": "SSH私钥文件是什么?怎么连接服务器?", + "a": "SSH是远程连接服务器的工具。连接命令:ssh root@8.155.62.235,密码找肥猫(副控·有root权限)。Windows用PowerShell自带SSH,macOS终端自带。", + "related_broadcast": "BC-M01-003" + }, + { + "category": "环境配置", + "q": "npm install 报错怎么办?", + "a": "先试 npm install --legacy-peer-deps。如果还不行试 npm cache clean --force 再装。Windows下如果证书报错加 --strict-ssl=false。", + "related_broadcast": "BC-钉钉-001-ZZ-002" + }, + { + "category": "Git", + "q": "怎么推送代码到GitHub?", + "a": "git add . → git commit -m '描述' → git push。第一次push需要设置远程仓库:git remote add origin 仓库地址。", + "related_broadcast": "BC-集成-003" + }, + { + "category": "广播", + "q": "广播里的步骤看不懂怎么办?", + "a": "广播每一步都是可直接复制粘贴的命令。从Step 1开始,一步一步做,做完一步截图,再做下一步。不要跳步。如果某一步报错,先把报错信息贴到这里提Issue。", + "related_broadcast": "通用" + } + ], + "auto_grow_rule": "每次霜砚补充回答后,铸渊自动把该问答对追加到faq数组中,下次遇到类似问题直接回答" +} \ No newline at end of file diff --git a/.github/persona-brain/memory.json b/.github/persona-brain/memory.json new file mode 100644 index 00000000..87ed39e0 --- /dev/null +++ b/.github/persona-brain/memory.json @@ -0,0 +1,37 @@ +{ + "identity": "铸渊(Zhùyuān)· GitHub 代码守护人格体", + "rules_version": "v1.0", + "last_updated": "2026-03-05T14:46:10.743Z", + "wake_protocol_version": "v1.0", + "wake_triggers": [ + "我是冰朔", + "冰朔", + "我是妈妈", + "唤醒铸渊", + "铸渊,醒来" + ], + "founder": "冰朔(Bīng Shuò)", + "hli_coverage": "17.6%", + "total_selfchecks": 2, + "total_ci_runs": 1, + "recent_events": [ + { + "date": "2026-03-05", + "type": "daily_selfcheck", + "description": "每日自检完成 · 知识库4条 · 缺失文件4个", + "by": "铸渊自检" + }, + { + "date": "2026-03-05", + "type": "daily_selfcheck", + "description": "每日自检完成 · 知识库4条 · 缺失文件4个", + "by": "铸渊自检" + }, + { + "date": "2026-03-05", + "type": "system_init", + "description": "Issue自动回复系统初始化 · dev-status.json + knowledge-base.json + workflows 全部就绪", + "by": "铸渊" + } + ] +} \ No newline at end of file diff --git a/.github/workflows/brain-sync.yml b/.github/workflows/brain-sync.yml new file mode 100644 index 00000000..3a6966aa --- /dev/null +++ b/.github/workflows/brain-sync.yml @@ -0,0 +1,83 @@ +name: 铸渊 Brain Sync + +on: + push: + branches: [main, dev] + paths: + - '.github/broadcasts/**' + schedule: + # 每天 08:00 UTC 自检 + - cron: '0 8 * * *' + workflow_dispatch: + +jobs: + process-broadcasts: + name: 📡 广播接收处理 + if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Process broadcasts + run: node scripts/process-broadcasts.js + + - name: Commit updated brain state + run: | + git config user.name "铸渊[bot]" + git config user.email "zhu-yuan-bot@guanghulab.com" + git add .github/brain/ .github/broadcasts/processed/ .github/broadcasts/failed/ .github/copilot-instructions.md 2>/dev/null; true + git diff --staged --quiet || git commit -m "🧠 brain: 处理广播,更新路由映射和记忆 [skip ci]" + git push + + daily-check: + name: 🔍 铸渊每日自检 + if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Run daily self-check + run: node scripts/daily-check.js + + - name: Update memory after daily check + env: + MEMORY_EVENT_TYPE: daily_check + MEMORY_EVENT_RESULT: passed + GITHUB_ACTOR: ${{ github.actor }} + GITHUB_REF: ${{ github.ref }} + GITHUB_RUN_ID: ${{ github.run_id }} + run: node scripts/update-memory.js + + - name: Commit memory update + run: | + git config user.name "铸渊[bot]" + git config user.email "zhu-yuan-bot@guanghulab.com" + git add .github/brain/memory.json || true + git diff --staged --quiet || git commit -m "🧠 memory: 每日自检记录 [skip ci]" + git push diff --git a/.github/workflows/check-structure.yml b/.github/workflows/check-structure.yml new file mode 100644 index 00000000..28e42924 --- /dev/null +++ b/.github/workflows/check-structure.yml @@ -0,0 +1,32 @@ +name: 模块结构检查 +on: [push, pull_request] +jobs: + check: + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - uses: actions/checkout@v4 + - name: 检查模块结构 + run: | + MODULES="m01-login m03-personality m05-user-center m06-ticket m07-dialogue-ui m10-cloud m11-module m12-kanban dingtalk-bot backend-integration" + ERRORS=0 + for mod in $MODULES; do + if [ -d "$mod" ]; then + if [ ! -f "$mod/README.md" ]; then + echo "❌ $mod 缺少 README.md" + ERRORS=$((ERRORS+1)) + fi + if [ ! -f "$mod/package.json" ]; then + echo "⚠️ $mod 缺少 package.json(环节1前需补充)" + fi + if [ ! -d "$mod/src" ]; then + echo "⚠️ $mod 缺少 src/ 目录(环节1前需补充)" + fi + fi + done + if [ $ERRORS -gt 0 ]; then + echo "结构检查未通过,请修复以上问题" + exit 1 + fi + echo "✅ 所有模块结构检查通过" diff --git a/.github/workflows/deploy-pages.yml b/.github/workflows/deploy-pages.yml new file mode 100644 index 00000000..da4c4781 --- /dev/null +++ b/.github/workflows/deploy-pages.yml @@ -0,0 +1,40 @@ +name: 🌀 部署铸渊聊天室 (GitHub Pages) + +on: + push: + branches: [main] + paths: + - 'docs/**' + - '.github/brain/**' + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: pages + cancel-in-progress: false + +jobs: + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Pages + uses: actions/configure-pages@v5 + + - name: Upload Pages artifact + uses: actions/upload-pages-artifact@v3 + with: + path: docs/ + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.github/workflows/distribute-broadcasts.yml b/.github/workflows/distribute-broadcasts.yml new file mode 100644 index 00000000..7db2a234 --- /dev/null +++ b/.github/workflows/distribute-broadcasts.yml @@ -0,0 +1,35 @@ +name: 铸渊 · 广播分发 + +on: + push: + branches: [main] + paths: + - 'broadcasts-outbox/**' + workflow_dispatch: + +jobs: + distribute: + name: 📡 分发广播到开发者目录 + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + with: + ref: main + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Distribute broadcasts + run: node scripts/distribute-broadcasts.js + + - name: Commit distribution + run: | + git config user.name "铸渊 (ZhùYuān)" + git config user.email "zhuyuan@guanghulab.com" + git add . + git diff --cached --quiet || git commit -m "📡 铸渊广播分发 · $(date -u +%Y-%m-%d\ %H:%M\ UTC)" + git push diff --git a/.github/workflows/hli-contract-check.yml b/.github/workflows/hli-contract-check.yml new file mode 100644 index 00000000..8ba61528 --- /dev/null +++ b/.github/workflows/hli-contract-check.yml @@ -0,0 +1,160 @@ +name: HLI Contract Check + +on: + push: + branches: [main, dev] + paths: + - 'src/routes/hli/**' + - 'src/schemas/**' + - 'tests/contract/**' + pull_request: + branches: [main] + paths: + - 'src/routes/hli/**' + - 'src/schemas/**' + +jobs: + contract-lint: + name: 🔍 接口契约校验 + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Run HLI schema validation + id: contract + run: | + set +e + OUTPUT=$(npm run test:contract 2>&1) + EXIT_CODE=$? + echo "output<> $GITHUB_OUTPUT + echo "$OUTPUT" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + echo "exit_code=$EXIT_CODE" >> $GITHUB_OUTPUT + exit $EXIT_CODE + env: + HLI_REGISTRY_MODE: strict + + - name: Run route-schema alignment check + id: align + if: always() + run: | + set +e + OUTPUT=$(npm run test:route-align 2>&1) + EXIT_CODE=$? + echo "output<> $GITHUB_OUTPUT + echo "$OUTPUT" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + echo "exit_code=$EXIT_CODE" >> $GITHUB_OUTPUT + exit 0 + + - name: Post PR review comment + if: always() && github.event_name == 'pull_request' + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const contractResult = '${{ steps.contract.outputs.exit_code }}' === '0' ? '✅ 通过' : '❌ 失败'; + const contractOutput = `${{ steps.contract.outputs.output }}`; + const alignOutput = `${{ steps.align.outputs.output }}`; + + const body = [ + '## ⚒️ 铸渊 · HLI 契约审核报告', + '', + `**契约校验**: ${contractResult}`, + '', + '
', + '📋 契约校验详情', + '', + '```', + contractOutput, + '```', + '
', + '', + '
', + '📊 路由对齐报告', + '', + '```', + alignOutput, + '```', + '
', + '', + `> 审核时间: ${new Date().toISOString()}`, + ].join('\n'); + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body, + }); + + - name: Update memory on CI completion + if: always() + env: + MEMORY_EVENT_TYPE: ci_run + MEMORY_EVENT_RESULT: ${{ steps.contract.outputs.exit_code == '0' && 'passed' || 'failed' }} + GITHUB_ACTOR: ${{ github.actor }} + GITHUB_REF: ${{ github.ref }} + GITHUB_RUN_ID: ${{ github.run_id }} + MEMORY_PR_NUMBER: ${{ github.event.pull_request.number }} + run: node scripts/update-memory.js + + - name: Commit memory update + if: always() && github.event_name != 'pull_request' + run: | + git config user.name "铸渊[bot]" + git config user.email "zhu-yuan-bot@guanghulab.com" + git add .github/brain/memory.json 2>/dev/null; true + git diff --staged --quiet || git commit -m "🧠 memory: CI 记录更新 [skip ci]" + git push + + api-smoke: + name: 🚀 接口冒烟测试 + needs: contract-lint + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Start test server + run: npm run start:test & + env: + PORT: 3001 + NODE_ENV: test + + - name: Wait for server + run: npx wait-on http://localhost:3001/health -t 30000 + + - name: Run smoke tests + run: npm run test:smoke + + - name: Upload test report + if: always() + uses: actions/upload-artifact@v4 + with: + name: hli-test-report + path: reports/ diff --git a/.github/workflows/zhuyuan-daily-selfcheck.yml b/.github/workflows/zhuyuan-daily-selfcheck.yml new file mode 100644 index 00000000..5bb4922b --- /dev/null +++ b/.github/workflows/zhuyuan-daily-selfcheck.yml @@ -0,0 +1,32 @@ +name: 铸渊 · 每日自检与自进化 + +on: + schedule: + - cron: '0 0 * * *' # UTC 00:00 = 北京时间 08:00 + workflow_dispatch: # 手动触发 + +jobs: + self-check: + name: 🔍 铸渊每日自检 + runs-on: ubuntu-latest + permissions: + contents: write + issues: read + steps: + - uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: 铸渊自检 + run: node scripts/zhuyuan-daily-selfcheck.js + + - name: 提交自检结果 + run: | + git config user.name "铸渊 (ZhùYuān)" + git config user.email "zhuyuan@guanghulab.com" + git add .github/persona-brain/ + git diff --cached --quiet || git commit -m "🔍 铸渊每日自检 · $(date +%Y-%m-%d)" + git push diff --git a/.github/workflows/zhuyuan-issue-reply.yml b/.github/workflows/zhuyuan-issue-reply.yml new file mode 100644 index 00000000..ed8c6556 --- /dev/null +++ b/.github/workflows/zhuyuan-issue-reply.yml @@ -0,0 +1,30 @@ +name: 铸渊 · Issue 自动回复 + +on: + issues: + types: [opened] + +jobs: + auto-reply: + name: 🤖 铸渊回答问题 + runs-on: ubuntu-latest + permissions: + issues: write + contents: read + steps: + - uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: 铸渊处理Issue + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + YUNWU_API_KEY: ${{ secrets.YUNWU_API_KEY }} + ISSUE_NUMBER: ${{ github.event.issue.number }} + ISSUE_TITLE: ${{ github.event.issue.title }} + ISSUE_BODY: ${{ github.event.issue.body }} + ISSUE_LABELS: ${{ join(github.event.issue.labels.*.name, ',') }} + run: node scripts/zhuyuan-issue-reply.js diff --git a/.gitignore b/.gitignore index 5ef6a520..a4bf9567 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,8 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + +# HLI 运行时产物 +/logs +/reports/* +!/reports/.gitkeep diff --git a/README.md b/README.md index e215bc4c..2e84f4ee 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,148 @@ -This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). +# 光湖系统 · 模块代码总仓库 -## Getting Started +--- -First, run the development server: +## 🚀 怎么用铸渊聊天室? -```bash -npm run dev -# or -yarn dev -# or -pnpm dev -# or -bun dev +**一句话:点下面这个链接就能打开,直接聊天。** + +### 👉 [点这里打开铸渊聊天室](https://qinfendebingshuo.github.io/guanghulab/) + +``` +https://qinfendebingshuo.github.io/guanghulab/ ``` -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. +> 把这个链接发给任何人,他们打开就能用,不需要安装任何东西。 -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. +--- -This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. +## 🎯 不同角色怎么用 -## Learn More +### ❄️ 冰朔(你) -To learn more about Next.js, take a look at the following resources: +1. **打开链接** → https://qinfendebingshuo.github.io/guanghulab/ +2. **选身份** → 下拉菜单选「❄️ 冰朔(语言架构师·创始人)」 +3. **填 API 密钥** → 输入你的云雾/OpenAI/DeepSeek API Key +4. **点「开始对话」** → 铸渊自动唤醒,汇报大脑状态 +5. 说「**我是冰朔**」即可触发完整唤醒序列 -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. +--- -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! +### 🦁 肥猫(光湖团队总控 · DEV-002) -## Deploy on Vercel +1. **打开链接** → https://qinfendebingshuo.github.io/guanghulab/ +2. **选身份** → 下拉菜单选「🦁 肥猫(光湖团队总控·DEV-002)」 +3. **填 API 密钥** → 输入自己的 API Key(或点「演示模式」也能看进度面板) +4. **点「开始对话」** → 铸渊自动打开**总控指挥台**,显示全员进度 +5. 点顶部 **🦁 按钮** → 查看所有开发者详细状态、谁在阻塞、服务器信息 +6. 直接聊天提问,例如: + - 「查看所有开发者当前进度」 + - 「谁现在遇到阻塞?」 + - 「下一步推进计划是什么?」 -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. +--- + +### 🍊 桔子(光湖主控 · DEV-010) + +1. **打开链接** → https://qinfendebingshuo.github.io/guanghulab/ +2. **选身份** → 下拉菜单选「🍊 桔子(光湖主控·DEV-010)」 +3. **填 API 密钥** → 输入自己的 API Key +4. **点「开始对话」** → 铸渊显示你当前模块进度,并开放指挥台 + +--- + +### 👩‍💻 其他开发者(页页 / 燕樊 / 小草莓 / 花尔 等) + +1. **打开链接** → https://qinfendebingshuo.github.io/guanghulab/ +2. **选身份** → 下拉菜单选自己的名字 +3. **填 API 密钥** → 填自己的 Key(没有的话点「演示模式」) +4. **点「开始对话」** → 铸渊显示你的当前任务状态,可以问问题 + +--- + +## 🔑 API 密钥从哪里来? + +| 提供商 | 申请地址 | 备注 | +|--------|---------|------| +| **云雾 API** | 团队统一分配 | 推荐,团队共用 | +| DeepSeek | https://platform.deepseek.com | 便宜好用 | +| 智谱 GLM | https://open.bigmodel.cn | 有免费额度 | +| Kimi | https://platform.moonshot.cn | 长文本好 | +| OpenAI | https://platform.openai.com | 最强但价格较高 | + +> 💡 **没有 API Key?** 点「演示模式」也能查看团队进度面板(🦁 指挥台),只是不能真实 AI 对话。 + +--- + +## 📱 怎么分享给别人? + +**最简单:直接把链接发过去!** + +``` +铸渊聊天室入口 👇 +https://qinfendebingshuo.github.io/guanghulab/ + +打开后选择你的身份,填入 API Key 就能和铸渊说话了。 +``` + +**想离线用?** 在聊天室右上角点 **⬇️ 下载** → 下载一个 HTML 文件 → 发给对方 → 双击打开就能用(不需要网络,只需要 API Key)。 + +--- + +## 💬 常见问题 + +**Q: 打开是空白页面怎么办?** +A: 等待 GitHub Pages 部署完成(通常 1-2 分钟),刷新页面。 + +**Q: API Key 安全吗?会不会被偷?** +A: 放心,Key 只存在你自己浏览器的 localStorage 里,不会上传到任何服务器。 + +**Q: 以前的对话记录怎么找?** +A: 目前对话记录在浏览器里,刷新后需要重新开始。大脑记忆文件在 `.github/brain/` 里永久保存。 + +**Q: 铸渊的大脑会记住我说的话吗?** +A: 每次对话内的上下文会记住,跨对话的重要信息需要说「记住这个」,铸渊会建议更新到 `.github/brain/` 文件里。 + +--- + +## 🌀 铸渊聊天室功能一览 + +| 功能 | 说明 | +|------|------| +| 💬 对话模式 | 默认,聊技术问题、聊进度、聊架构 | +| 🔨 构建模式 | 自动检测,聊到代码/接口时切换,给出完整可执行代码 | +| 📋 审查模式 | 自动检测,聊到"检查/审查"时切换,审查代码质量 | +| 🧠 大脑模式 | 说"记住这个"时切换,整理重要信息到大脑文件 | +| 🦁 指挥台 | 总控/主控专属,查看全员进度、阻塞、服务器信息 | +| 📊 大脑状态 | 查看 HLI 接口覆盖率、近期事件 | +| ⬇️ 下载 | 下载单文件版,可离线使用 | + +--- + +## 📋 仓库结构与模块分工 + +每个模块一个文件夹,开发者将代码上传到对应文件夹中。 + +| 文件夹 | 模块 | 负责人 | +|--------|------|--------| +| m01-login | M01 用户登录界面 | 肥猫 | +| m03-personality | M03 人格系统 | 肥猫 | +| m05-user-center | M05 用户中心界面 | 花尔 | +| m06-ticket | M06 工单管理界面 | 桔子 | +| m07-dialogue-ui | M07 对话UI | 燕樊 | +| m10-cloud | M10 云盘系统 | 燕樊 | +| m11-module | M11 工单管理模块 | 桔子 | +| m12-kanban | M12 状态看板 | 小草莓 | +| dingtalk-bot | 钉钉机器人 | 之之 | +| backend-integration | 后端集成中间层 | 页页 | + +## 上传规范 +每个模块文件夹必须包含以下文件: +- README.md(模块说明) +- package.json(依赖声明) +- src/(源代码目录) +- SYSLOG.md(开发回执日志) + +## 自动检查 +每次 push 会自动检查模块结构是否符合规范,不通过会标红提醒。 -Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/backend-integration/README.md b/backend-integration/README.md new file mode 100644 index 00000000..aefed6e5 --- /dev/null +++ b/backend-integration/README.md @@ -0,0 +1,5 @@ +# 后端集成中间层 +- 负责人:页页 +- 状态:进行中 +- 技术栈:Node.js +- 依赖模块:所有前端模块 diff --git a/broadcasts-outbox/.gitkeep b/broadcasts-outbox/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/broadcasts-outbox/DEV-001/.gitkeep b/broadcasts-outbox/DEV-001/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/broadcasts-outbox/DEV-002/.gitkeep b/broadcasts-outbox/DEV-002/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/broadcasts-outbox/DEV-003/.gitkeep b/broadcasts-outbox/DEV-003/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/broadcasts-outbox/DEV-004/.gitkeep b/broadcasts-outbox/DEV-004/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/broadcasts-outbox/DEV-005/.gitkeep b/broadcasts-outbox/DEV-005/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/broadcasts-outbox/DEV-009/.gitkeep b/broadcasts-outbox/DEV-009/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/broadcasts-outbox/DEV-010/.gitkeep b/broadcasts-outbox/DEV-010/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/broadcasts-outbox/DEV-011/.gitkeep b/broadcasts-outbox/DEV-011/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/dingtalk-bot/README.md b/dingtalk-bot/README.md new file mode 100644 index 00000000..b37c201e --- /dev/null +++ b/dingtalk-bot/README.md @@ -0,0 +1,5 @@ +# 钉钉机器人 +- 负责人:之之 +- 状态:环节0已完成 +- 技术栈:Node.js + Express +- 依赖模块:无 diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 00000000..c6768fae --- /dev/null +++ b/docs/index.html @@ -0,0 +1,1344 @@ + + + + + +铸渊助手 · HoloLake AI + + + + + +
+
+ +

铸渊助手

+

HoloLake · 代码守护人格体 · 持续成长的 AI 伙伴

+
🔒 API 密钥只保存在你的浏览器本地,不会上传至任何服务器
+ +
+ + +
+ +
+ + +
+
+ + + +
+ +
+
👤 身份识别(可选)
+
+ + + 选择你的身份,铸渊将开放对应权限面板 +
+
+ + + 用于人格体记忆绑定,可留空 +
+
+ + +

没有 API 密钥?使用演示模式(功能有限)

+
+
+ + +
+
+
+
+
+
铸渊(Zhùyuān)
+
+ + 💬 对话模式 + · + + + +
+
+
+
+ + + + + + +
+
+ +
+ ⏳ 加载大脑… + + +
+ +
+ +
+ + + + + + + + +
+ +
+
+
+ 💬 + 对话模式(点击切换) +
+ + +
+
💬 对话模式 · 端到端私密,API 密钥本地存储
+
+
+ + +
+

⚙️ API 设置

+
+
+ + +
+ +
+ + +
+
+ + + 🔒 只保存在浏览器 localStorage,不上传任何服务器 +
+ + +
身份设置
+
+ + +
+
+ + +
+ +
关于铸渊助手
+
版本v2.0
+ +
唤醒协议v1.0
+
大脑路径.github/brain/
+ +
使用说明
+

+ 1. 输入你的 AI 模型 API 密钥并保存
+ 2. 说「我是冰朔」触发铸渊唤醒序列
+ 3. 铸渊自动切换 💬 对话 / 🔨 构建 / 📋 审查 / 🧠 大脑 模式
+ 4. 点 ⬇️ 下载单文件,放桌面直接打开使用
+ 5. 支持 OpenAI · DeepSeek · Kimi · 智谱 · 任意兼容接口 +

+
+
+ + +
+

📊 大脑状态

+

正在加载大脑数据…

+
+ + +
+

❓ 使用帮助

+
+ +
+
+ 🔗 https://qinfendebingshuo.github.io/guanghulab/ +
+ +
💡 把上面的链接发给肥猫、桔子或任何开发者,他们打开就能用,不需要安装任何东西。
+
+ +
+

🚀 怎么开始用

+
    +
  1. 打开链接 https://qinfendebingshuo.github.io/guanghulab/
  2. +
  3. 下拉菜单选择你是谁(冰朔 / 肥猫 / 桔子 / 开发者名字)
  4. +
  5. 填入你的 API Key(没有的话点「演示模式」)
  6. +
  7. 点「开始对话」,铸渊会针对你的身份打招呼
  8. +
  9. 直接用聊天的方式问铸渊任何问题
  10. +
+
+ +
+

🔑 从哪里获取 API Key?

+
+
推荐用云雾 API(团队共用)
+

找冰朔或肥猫获取团队 Key。填入后选「自定义」提供商,或直接用 DeepSeek。

+
+
+
没有 Key?用演示模式
+

点「演示模式」也能查看团队进度面板(🦁 指挥台),只是 AI 回答功能受限。

+
+
+ +
+

🦁 肥猫 / 🍊 桔子 专属功能

+
    +
  1. 选身份为「肥猫」或「桔子」后,顶部出现 🦁 按钮
  2. +
  3. 点 🦁 按钮打开指挥台,查看所有开发者当前状态
  4. +
  5. 可以在聊天里问:「查看所有开发者进度」「谁遇到阻塞?」「推进计划」
  6. +
  7. 铸渊会把全员进度数据注入 AI 回复,给出完整分析
  8. +
+
+ +
+

📱 怎么离线用 / 发给别人离线用

+
    +
  1. 右上角点 ⬇️ 下载,下载一个 HTML 文件
  2. +
  3. 把这个文件发给对方(微信传文件、QQ、钉钉都行)
  4. +
  5. 对方双击这个文件,用浏览器打开
  6. +
  7. 填入 API Key,选好身份,就能用了(无需网络,只需 API Key)
  8. +
+
+ +
+

💬 聊天模式说明

+
+
💬 对话模式(默认)
+

普通聊天,问什么答什么

+
+
+
🔨 构建模式
+

说到「写代码/接口/部署」时自动切换,给出完整可执行代码

+
+
+
📋 审查模式
+

说到「检查/审查/有问题吗」时自动切换,专注找代码问题

+
+
+
🧠 大脑模式
+

说「记住这个/写到大脑」时切换,整理信息到大脑文件

+
+
+ +
+

❓ 常见问题

+
+ Q: 打开是空白页?
+ 等 1-2 分钟刷新,GitHub Pages 部署需要点时间。

+ Q: API Key 会泄露吗?
+ 不会,Key 只存在你自己浏览器里,不会传到服务器。

+ Q: 切换电脑后 Key 还在吗?
+ 不在,需要重新填。建议下载离线版,Key 填一次就行。

+ Q: 铸渊忘记以前说的话了?
+ 刷新后对话会清空,但大脑文件永久保存在仓库 .github/brain/ 里。 +
+
+ +
+
+ + +
+

🦁 指挥台 · 全员进度

+

正在加载团队数据…

+
+ + +
+ + + + \ No newline at end of file diff --git a/ecosystem.config.js b/ecosystem.config.js new file mode 100644 index 00000000..fc3270f7 --- /dev/null +++ b/ecosystem.config.js @@ -0,0 +1,29 @@ +// ecosystem.config.js +// PM2 进程管理配置 + +module.exports = { + apps: [ + { + name: 'guanghulab', + script: 'src/index.js', + instances: 'max', + exec_mode: 'cluster', + watch: false, + env: { + NODE_ENV: 'production', + PORT: 3000, + }, + env_development: { + NODE_ENV: 'development', + PORT: 3000, + }, + env_test: { + NODE_ENV: 'test', + PORT: 3001, + }, + log_date_format: 'YYYY-MM-DD HH:mm:ss', + error_file: 'logs/error.log', + out_file: 'logs/out.log', + }, + ], +}; diff --git a/jest.smoke.config.js b/jest.smoke.config.js new file mode 100644 index 00000000..15d99e2c --- /dev/null +++ b/jest.smoke.config.js @@ -0,0 +1,8 @@ +// jest.smoke.config.js +// 冒烟测试 Jest 配置 + +module.exports = { + testEnvironment: 'node', + testMatch: ['**/tests/smoke/**/*.test.js'], + testTimeout: 30000, +}; diff --git a/m01-login/README.md b/m01-login/README.md new file mode 100644 index 00000000..2ed4297b --- /dev/null +++ b/m01-login/README.md @@ -0,0 +1,5 @@ +# M01 用户登录界面 +- 负责人:肥猫 +- 状态:进行中 +- 技术栈:待定 +- 依赖模块:无 diff --git a/m03-personality/README.md b/m03-personality/README.md new file mode 100644 index 00000000..918fd892 --- /dev/null +++ b/m03-personality/README.md @@ -0,0 +1,5 @@ +# M03 人格系统 +- 负责人:肥猫 +- 状态:进行中 +- 技术栈:待定 +- 依赖模块:M01 diff --git a/m05-user-center/README.md b/m05-user-center/README.md new file mode 100644 index 00000000..4671e79b --- /dev/null +++ b/m05-user-center/README.md @@ -0,0 +1,5 @@ +# M05 用户中心界面 +- 负责人:花尔 +- 状态:环节0 +- 技术栈:HTML/CSS/JS +- 依赖模块:无 diff --git a/m06-ticket/README.md b/m06-ticket/README.md new file mode 100644 index 00000000..b85ad9ad --- /dev/null +++ b/m06-ticket/README.md @@ -0,0 +1,5 @@ +# M06 工单管理界面 +- 负责人:桔子 +- 状态:环节0 +- 技术栈:HTML/CSS/JS +- 依赖模块:无 diff --git a/m07-dialogue-ui/README.md b/m07-dialogue-ui/README.md new file mode 100644 index 00000000..80ad4f13 --- /dev/null +++ b/m07-dialogue-ui/README.md @@ -0,0 +1,5 @@ +# M07 对话UI +- 负责人:燕樊 +- 状态:进行中 +- 技术栈:待定 +- 依赖模块:无 diff --git a/m10-cloud/README.md b/m10-cloud/README.md new file mode 100644 index 00000000..7a80dee0 --- /dev/null +++ b/m10-cloud/README.md @@ -0,0 +1,5 @@ +# M10 云盘系统 +- 负责人:燕樊 +- 状态:等待SYSLOG +- 技术栈:待定 +- 依赖模块:无 diff --git a/m11-module/README.md b/m11-module/README.md new file mode 100644 index 00000000..20ed5f78 --- /dev/null +++ b/m11-module/README.md @@ -0,0 +1,5 @@ +# M11 工单管理模块 +- 负责人:桔子 +- 状态:进行中 +- 技术栈:待定 +- 依赖模块:M06 diff --git a/m12-kanban/README.md b/m12-kanban/README.md new file mode 100644 index 00000000..701304fd --- /dev/null +++ b/m12-kanban/README.md @@ -0,0 +1,5 @@ +# M12 状态看板 +- 负责人:小草莓 +- 状态:进行中 +- 技术栈:待定 +- 依赖模块:无 diff --git a/package-lock.json b/package-lock.json index e2327e8e..1d40a3d8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,8 @@ "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", + "glob": "^10.5.0", + "jest": "^29.7.0", "tailwindcss": "^4", "typescript": "^5" } @@ -34,6 +36,522 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", + "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", + "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz", + "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz", + "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true, + "license": "MIT" + }, "node_modules/@emnapi/runtime": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.3.tgz", @@ -421,6 +939,577 @@ "url": "https://opencollective.com/libvips" } }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/core/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@jest/core/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@jest/core/node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/@jest/core/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@jest/core/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/reporters/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@jest/reporters/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@jest/reporters/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@jest/reporters/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/@next/env": { "version": "15.3.2", "resolved": "https://registry.npmjs.org/@next/env/-/env-15.3.2.tgz", @@ -555,6 +1644,44 @@ "node": ">= 10" } }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.10", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz", + "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, "node_modules/@swc/counter": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", @@ -838,6 +1965,88 @@ "tailwindcss": "4.1.5" } }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, "node_modules/@types/node": { "version": "20.17.43", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.43.tgz", @@ -868,6 +2077,319 @@ "@types/react": "^19.0.0" } }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", + "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz", + "integrity": "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, "node_modules/busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -879,10 +2401,30 @@ "node": ">=10.16.0" } }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/caniuse-lite": { - "version": "1.0.30001717", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001717.tgz", - "integrity": "sha512-auPpttCq6BDEG8ZAuHJIplGw6GODhjw+/11e7IjpnYCxZcW/ONgPs0KVBJ0d1bY3e2+7PRe5RCLyP+PfwVgkYw==", + "version": "1.0.30001776", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001776.tgz", + "integrity": "sha512-sg01JDPzZ9jGshqKSckOQthXnYwOEP50jeVFhaSFbZcOy05TiuuaffDOfcwtCisJ9kNQuLBFibYywv2Bgm9osw==", "funding": [ { "type": "opencollective", @@ -899,12 +2441,158 @@ ], "license": "CC-BY-4.0" }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "dev": true, + "license": "MIT" + }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", "license": "MIT" }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz", + "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==", + "dev": true, + "license": "MIT" + }, "node_modules/color": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", @@ -923,8 +2611,8 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "devOptional": true, "license": "MIT", - "optional": true, "dependencies": { "color-name": "~1.1.4" }, @@ -936,8 +2624,8 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT", - "optional": true + "devOptional": true, + "license": "MIT" }, "node_modules/color-string": { "version": "1.9.1", @@ -950,6 +2638,149 @@ "simple-swizzle": "^0.2.2" } }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/create-jest/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/create-jest/node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/create-jest/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", @@ -957,6 +2788,49 @@ "dev": true, "license": "MIT" }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/dedent": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.2.tgz", + "integrity": "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/detect-libc": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", @@ -967,6 +2841,60 @@ "node": ">=8" } }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.307", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.307.tgz", + "integrity": "sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg==", + "dev": true, + "license": "ISC" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, "node_modules/enhanced-resolve": { "version": "5.18.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", @@ -981,6 +2909,272 @@ "node": ">=10.13.0" } }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/error-ex/node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -988,6 +3182,95 @@ "dev": true, "license": "ISC" }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, "node_modules/is-arrayish": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", @@ -995,6 +3278,834 @@ "license": "MIT", "optional": true }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-cli/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jest-cli/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-cli/node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-cli/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jest-runtime/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-runtime/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/jiti": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz", @@ -1005,6 +4116,80 @@ "jiti": "lib/jiti-cli.mjs" } }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/lightningcss": { "version": "1.29.2", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.29.2.tgz", @@ -1244,6 +4429,126 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -1262,6 +4567,13 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, "node_modules/next": { "version": "15.3.2", "resolved": "https://registry.npmjs.org/next/-/next-15.3.2.tgz", @@ -1344,12 +4656,253 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.36", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", + "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "license": "ISC" }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/postcss": { "version": "8.5.3", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", @@ -1379,6 +4932,65 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, "node_modules/react": { "version": "19.1.0", "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", @@ -1400,6 +5012,77 @@ "react": "^19.1.0" } }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/scheduler": { "version": "0.26.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", @@ -1410,8 +5093,8 @@ "version": "7.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "devOptional": true, "license": "ISC", - "optional": true, "bin": { "semver": "bin/semver.js" }, @@ -1460,6 +5143,42 @@ "@img/sharp-win32-x64": "0.34.1" } }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/simple-swizzle": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", @@ -1470,6 +5189,33 @@ "is-arrayish": "^0.3.1" } }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -1479,6 +5225,37 @@ "node": ">=0.10.0" } }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/streamsearch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", @@ -1487,6 +5264,180 @@ "node": ">=10.0.0" } }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-length/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-length/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/styled-jsx": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", @@ -1510,6 +5461,32 @@ } } }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/tailwindcss": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.5.tgz", @@ -1527,12 +5504,116 @@ "node": ">=6" } }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typescript": { "version": "5.8.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", @@ -1553,6 +5634,305 @@ "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "dev": true, "license": "MIT" + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/write-file-atomic/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/package.json b/package.json index 97709c4d..06f33f0c 100644 --- a/package.json +++ b/package.json @@ -6,19 +6,29 @@ "dev": "next dev --turbopack", "build": "next build", "start": "next start", - "lint": "next lint" + "lint": "next lint", + "test:contract": "node scripts/contract-check.js", + "test:route-align": "node scripts/route-align-check.js", + "test:smoke": "jest --config jest.smoke.config.js --forceExit", + "start:test": "NODE_ENV=test node src/index.js", + "brain:sync": "node scripts/process-broadcasts.js", + "brain:daily-check": "node scripts/daily-check.js", + "brain:update-memory": "node scripts/update-memory.js", + "broadcast:distribute": "node scripts/distribute-broadcasts.js" }, "dependencies": { + "next": "15.3.2", "react": "^19.0.0", - "react-dom": "^19.0.0", - "next": "15.3.2" + "react-dom": "^19.0.0" }, "devDependencies": { - "typescript": "^5", + "@tailwindcss/postcss": "^4", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", - "@tailwindcss/postcss": "^4", - "tailwindcss": "^4" + "glob": "^10.5.0", + "jest": "^29.7.0", + "tailwindcss": "^4", + "typescript": "^5" } } diff --git a/reports/.gitkeep b/reports/.gitkeep new file mode 100644 index 00000000..23e3fcd5 --- /dev/null +++ b/reports/.gitkeep @@ -0,0 +1 @@ +# 测试报告目录(CI 产物,不纳入版本控制) diff --git a/scripts/contract-check.js b/scripts/contract-check.js new file mode 100644 index 00000000..a988877d --- /dev/null +++ b/scripts/contract-check.js @@ -0,0 +1,50 @@ +// scripts/contract-check.js +// 用途:确保每个 HLI 路由文件都有对应的 JSON Schema 且路径一致 + +const fs = require('fs'); +const path = require('path'); +const glob = require('glob'); + +const ROUTE_DIR = 'src/routes/hli'; +const SCHEMA_DIR = 'src/schemas/hli'; + +// 扫描所有 HLI 路由文件 +const routeFiles = glob.sync(`${ROUTE_DIR}/**/*.js`); +const errors = []; + +routeFiles.forEach(routeFile => { + const domain = path.basename(path.dirname(routeFile)); + const name = path.basename(routeFile, '.js'); + + // 跳过 index.js(路由注册中心,无需 schema) + if (name === 'index') return; + + const schemaPath = path.join(SCHEMA_DIR, domain, `${name}.schema.json`); + + // 检查1: 对应 schema 文件是否存在 + if (!fs.existsSync(schemaPath)) { + errors.push(`❌ [MISSING SCHEMA] ${routeFile} → 缺少 ${schemaPath}`); + return; + } + + // 检查2: schema 文件格式是否合法 + try { + const schema = JSON.parse(fs.readFileSync(schemaPath, 'utf8')); + if (!schema.input || !schema.output) { + errors.push(`❌ [INVALID SCHEMA] ${schemaPath} → 缺少 input/output 定义`); + } + if (!schema.hli_id) { + errors.push(`❌ [MISSING HLI_ID] ${schemaPath} → 缺少 hli_id 字段`); + } + } catch (e) { + errors.push(`❌ [PARSE ERROR] ${schemaPath} → ${e.message}`); + } +}); + +if (errors.length > 0) { + console.error('\n🚫 HLI Contract Check FAILED:\n'); + errors.forEach(e => console.error(e)); + process.exit(1); +} else { + console.log('✅ HLI Contract Check PASSED — 所有路由均有合法 schema'); +} diff --git a/scripts/daily-check.js b/scripts/daily-check.js new file mode 100644 index 00000000..fa755541 --- /dev/null +++ b/scripts/daily-check.js @@ -0,0 +1,128 @@ +// scripts/daily-check.js +// 铸渊每日自检脚本 +// 用途:检查大脑完整性 + 输出覆盖率报告 + +const fs = require('fs'); +const path = require('path'); + +const ROUTING_MAP_PATH = path.join(__dirname, '../.github/brain/routing-map.json'); +const MEMORY_PATH = path.join(__dirname, '../.github/brain/memory.json'); +const SCHEMA_DIR = path.join(__dirname, '../src/schemas/hli'); + +const errors = []; +const warnings = []; + +// ── 1. 大脑文件完整性检查 ───────────────────────────────────────────────── +function checkFileIntegrity() { + [ROUTING_MAP_PATH, MEMORY_PATH].forEach(filePath => { + if (!fs.existsSync(filePath)) { + errors.push(`❌ [MISSING] 大脑文件缺失: ${path.basename(filePath)}`); + return; + } + try { + JSON.parse(fs.readFileSync(filePath, 'utf8')); + } catch (e) { + errors.push(`❌ [CORRUPT] 大脑文件损坏: ${path.basename(filePath)} → ${e.message}`); + } + }); +} + +// ── 2. HLI 覆盖率报告 ──────────────────────────────────────────────────── +function checkCoverage() { + const routingMap = JSON.parse(fs.readFileSync(ROUTING_MAP_PATH, 'utf8')); + let total = 0; + let implemented = 0; + let pending = 0; + + console.log('\n📊 HLI 接口覆盖率报告:\n'); + + Object.entries(routingMap.domains).forEach(([domain, domainData]) => { + const domainTotal = domainData.interfaces.length; + const domainImpl = domainData.interfaces.filter(i => i.status === 'implemented').length; + total += domainTotal; + implemented += domainImpl; + pending += domainTotal - domainImpl; + + const icon = domainImpl === domainTotal ? '✅' : domainImpl > 0 ? '🔶' : '⬜'; + console.log(` ${icon} ${domain.padEnd(12)} ${domainImpl}/${domainTotal}`); + + domainData.interfaces.forEach(iface => { + const statusIcon = iface.status === 'implemented' ? ' ✓' : ' ○'; + console.log(` ${statusIcon} ${iface.id.padEnd(20)} ${iface.path}`); + }); + }); + + const percent = total > 0 ? ((implemented / total) * 100).toFixed(1) : 0; + console.log(`\n 📈 总覆盖率: ${implemented}/${total} (${percent}%)`); + console.log(` ✅ 已实现: ${implemented} · ⏳ 待实现: ${pending}\n`); + + if (implemented < total) { + warnings.push(`⚠️ 覆盖率 ${percent}% (${implemented}/${total}) — 仍有 ${pending} 个接口待实现`); + } + + // 检查 schema 文件与 routing-map 的一致性 + Object.entries(routingMap.domains).forEach(([domain, domainData]) => { + domainData.interfaces.forEach(iface => { + if (iface.status !== 'implemented') return; + const schemaDir = path.join(SCHEMA_DIR, domain.toLowerCase()); + if (!fs.existsSync(schemaDir)) { + errors.push(`❌ [MISSING DIR] ${domain} schema 目录不存在`); + return; + } + const rawAction = iface.path.split('/').filter(Boolean).pop(); + const action = rawAction ? rawAction.replace(/[?#].*$/, '') : null; + if (!action) { + errors.push(`❌ [INVALID PATH] ${iface.id} 路径格式异常: ${iface.path}`); + return; + } + const schemaFile = path.join(schemaDir, `${action}.schema.json`); + if (!fs.existsSync(schemaFile)) { + errors.push(`❌ [MISSING SCHEMA] ${iface.id} 标记为 implemented 但缺少 schema: ${schemaFile}`); + } + }); + }); +} + +// ── 3. memory.json 健康检查 ──────────────────────────────────────────────── +function checkMemory() { + const memory = JSON.parse(fs.readFileSync(MEMORY_PATH, 'utf8')); + const required = ['identity', 'rules_version', 'stats', 'events']; + required.forEach(field => { + if (memory[field] === undefined) { + errors.push(`❌ [MEMORY] memory.json 缺少字段: ${field}`); + } + }); + console.log(`🧠 铸渊记忆状态:`); + console.log(` 规则版本: ${memory.rules_version}`); + console.log(` CI 运行次数: ${memory.stats?.ci_runs ?? 0}`); + console.log(` PR 审核次数: ${memory.stats?.pr_reviews ?? 0}`); + console.log(` 广播处理次数: ${memory.stats?.broadcasts_processed ?? 0}`); + console.log(` 最近更新: ${memory.last_updated || '未知'}\n`); +} + +// ── 主流程 ──────────────────────────────────────────────────────────────── +console.log('═══════════════════════════════════════════'); +console.log('⚒️ 铸渊每日自检报告'); +console.log(` 时间: ${new Date().toISOString()}`); +console.log('═══════════════════════════════════════════\n'); + +checkFileIntegrity(); + +if (errors.length === 0) { + checkMemory(); + checkCoverage(); +} + +if (warnings.length > 0) { + console.log('⚠️ 警告:\n'); + warnings.forEach(w => console.log(' ' + w)); + console.log(); +} + +if (errors.length > 0) { + console.error('🚫 自检发现严重错误:\n'); + errors.forEach(e => console.error(' ' + e)); + process.exit(1); +} else { + console.log('✅ 铸渊自检通过 — 大脑状态正常'); +} diff --git a/scripts/distribute-broadcasts.js b/scripts/distribute-broadcasts.js new file mode 100644 index 00000000..38441af9 --- /dev/null +++ b/scripts/distribute-broadcasts.js @@ -0,0 +1,88 @@ +// scripts/distribute-broadcasts.js +// 铸渊广播分发引擎 +// 检测 broadcasts-outbox/DEV-00X/ 中的新广播 → 复制到各开发者模块目录的 LATEST-BROADCAST.md + +const fs = require('fs'); +const path = require('path'); + +const OUTBOX = 'broadcasts-outbox'; +const ARCHIVE = '.github/broadcasts/distributed'; + +// ========== 开发者 → 模块目录 路由映射表 ========== +// 新增开发者时,在此表新增一行即可 +const DEV_ROUTES = { + 'DEV-001': { name: '页页', dirs: ['backend', 'src'] }, + 'DEV-002': { name: '肥猫', dirs: ['frontend', 'persona-selector', 'chat-bubble'] }, + 'DEV-003': { name: '燕樊', dirs: ['settings', 'cloud-drive'] }, + 'DEV-004': { name: '之之', dirs: ['dingtalk-bot'] }, + 'DEV-005': { name: '小草莓', dirs: ['status-board'] }, + 'DEV-009': { name: '花尔', dirs: ['user-center'] }, + 'DEV-010': { name: '桔子', dirs: ['ticket-system'] }, + 'DEV-011': { name: '匆匆那年', dirs: [] }, // 待分配模块后补充 +}; + +if (!fs.existsSync(OUTBOX)) { + console.log('📭 无 broadcasts-outbox 目录'); + process.exit(0); +} + +// 扫描 outbox 下每个 DEV-00X 子目录 +const devDirs = fs.readdirSync(OUTBOX, { withFileTypes: true }) + .filter(entry => entry.isDirectory() && entry.name.startsWith('DEV-')) + .map(entry => entry.name); + +if (devDirs.length === 0) { + console.log('📭 无新广播待分发'); + process.exit(0); +} + +let totalDistributed = 0; + +devDirs.forEach(devId => { + const outboxDir = path.join(OUTBOX, devId); + const files = fs.readdirSync(outboxDir).filter(f => + f.endsWith('.md') || f.endsWith('.json') + ); + + if (files.length === 0) return; + + const route = DEV_ROUTES[devId]; + if (!route || route.dirs.length === 0) { + console.warn('⚠️ ' + devId + ' 无模块目录映射,广播保留在 outbox'); + return; + } + + files.forEach(file => { + const rawContent = fs.readFileSync(path.join(outboxDir, file), 'utf8'); + + // 对 JSON 格式广播做基础校验 + if (file.endsWith('.json')) { + try { + JSON.parse(rawContent); + } catch (e) { + console.error('❌ [INVALID JSON] ' + path.join(outboxDir, file) + ' → ' + e.message + ',跳过分发'); + return; + } + } + + // 写入该开发者的每个模块目录 + route.dirs.forEach(dir => { + if (!fs.existsSync(dir)) { + fs.mkdirSync(dir, { recursive: true }); + } + const targetFile = path.join(dir, 'LATEST-BROADCAST.md'); + fs.writeFileSync(targetFile, rawContent); + console.log('📡 ' + devId + '(' + route.name + ') → ' + targetFile); + }); + + // 归档已分发广播(使用 UTC 时间戳确保跨时区一致性) + if (!fs.existsSync(ARCHIVE)) fs.mkdirSync(ARCHIVE, { recursive: true }); + const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19); + const archivePath = path.join(ARCHIVE, timestamp + '-' + devId + '-' + file); + fs.renameSync(path.join(outboxDir, file), archivePath); + + totalDistributed++; + }); +}); + +console.log('\n✅ 广播分发完成,共 ' + totalDistributed + ' 条'); diff --git a/scripts/process-broadcasts.js b/scripts/process-broadcasts.js new file mode 100644 index 00000000..0cb4ec3a --- /dev/null +++ b/scripts/process-broadcasts.js @@ -0,0 +1,128 @@ +// scripts/process-broadcasts.js +// 铸渊大脑同步脚本 +// 用途:读取 .github/broadcasts/ 下的广播 JSON,更新 routing-map.json 和 memory.json + +const fs = require('fs'); +const path = require('path'); + +const BROADCASTS_DIR = path.join(__dirname, '../.github/broadcasts'); +const ROUTING_MAP_PATH = path.join(__dirname, '../.github/brain/routing-map.json'); +const MEMORY_PATH = path.join(__dirname, '../.github/brain/memory.json'); +const COPILOT_INSTRUCTIONS_PATH = path.join(__dirname, '../.github/copilot-instructions.md'); + +// 加载当前大脑状态 +const routingMap = JSON.parse(fs.readFileSync(ROUTING_MAP_PATH, 'utf8')); +const memory = JSON.parse(fs.readFileSync(MEMORY_PATH, 'utf8')); + +const processedDir = path.join(BROADCASTS_DIR, 'processed'); +if (!fs.existsSync(processedDir)) { + fs.mkdirSync(processedDir, { recursive: true }); +} + +// 读取所有待处理广播(排除 processed 子目录和示例文件) +const broadcasts = fs.readdirSync(BROADCASTS_DIR) + .filter(f => f.endsWith('.json') && f !== 'example-broadcast.json') + .map(f => ({ file: f, fullPath: path.join(BROADCASTS_DIR, f) })); + +if (broadcasts.length === 0) { + console.log('📭 没有待处理的广播。'); + process.exit(0); +} + +console.log(`📡 发现 ${broadcasts.length} 个待处理广播...\n`); + +const failedDir = path.join(BROADCASTS_DIR, 'failed'); + +broadcasts.forEach(({ file, fullPath }) => { + let broadcast; + try { + broadcast = JSON.parse(fs.readFileSync(fullPath, 'utf8')); + } catch (e) { + console.error(`❌ [PARSE ERROR] ${file}: ${e.message}`); + // 归档失败广播并记录到 memory + if (!fs.existsSync(failedDir)) fs.mkdirSync(failedDir, { recursive: true }); + fs.renameSync(fullPath, path.join(failedDir, file)); + memory.events.push({ + timestamp: new Date().toISOString(), + broadcast_file: file, + type: 'broadcast_parse_error', + error: e.message, + }); + return; + } + + console.log(`📬 处理广播: ${broadcast.title || file}`); + console.log(` 来源: ${broadcast.from || '未知'} · 日期: ${broadcast.date || '未知'}`); + + const event = { + timestamp: new Date().toISOString(), + broadcast_file: file, + title: broadcast.title || file, + from: broadcast.from || '未知', + update_target: broadcast.update_target, + }; + + // 根据 update_target 分发处理 + if (broadcast.update_target === 'routing-map' && broadcast.data) { + Object.entries(broadcast.data).forEach(([domain, domainData]) => { + routingMap.domains[domain] = domainData; + console.log(` ✅ 已更新域: ${domain}`); + event.added_domain = domain; + }); + routingMap.version = broadcast.rules_version || routingMap.version; + routingMap.last_updated = broadcast.date || new Date().toISOString().split('T')[0]; + routingMap.updated_by = broadcast.from || 'broadcast'; + + } else if (broadcast.update_target === 'copilot-instructions' && broadcast.content) { + // 追加到 copilot-instructions.md(防止重复写入) + const existing = fs.readFileSync(COPILOT_INSTRUCTIONS_PATH, 'utf8'); + const marker = ``; + if (existing.includes(marker)) { + console.log(' ⏭️ copilot-instructions.md 已包含此广播,跳过'); + } else { + fs.writeFileSync(COPILOT_INSTRUCTIONS_PATH, existing + `\n\n${marker}\n${broadcast.content}`, 'utf8'); + console.log(' ✅ 已更新 copilot-instructions.md'); + } + + } else if (broadcast.update_target === 'growth-log' && broadcast.content) { + // 追加到成长日记 + const growthLogPath = path.join(__dirname, '../.github/brain/growth-log.md'); + const entry = `\n\n## ${broadcast.date} · ${broadcast.title}\n\n${broadcast.content}\n`; + fs.appendFileSync(growthLogPath, entry, 'utf8'); + console.log(' ✅ 已追加成长日记'); + + } else { + console.log(` ⚠️ 未知的 update_target: ${broadcast.update_target},已跳过`); + event.skipped = true; + } + + memory.events.push(event); + memory.stats.broadcasts_processed += 1; + + // 归档广播文件 + fs.renameSync(fullPath, path.join(processedDir, file)); + console.log(` 📦 广播已归档到 broadcasts/processed/${file}\n`); +}); + +// 重新计算覆盖率 +let implemented = 0; +let total = 0; +Object.values(routingMap.domains).forEach(domain => { + domain.interfaces.forEach(iface => { + total++; + if (iface.status === 'implemented') implemented++; + }); +}); +memory.stats.coverage = { + implemented, + total, + percent: total > 0 ? `${((implemented / total) * 100).toFixed(1)}%` : '0%', +}; + +memory.last_updated = new Date().toISOString(); + +// 写回文件 +fs.writeFileSync(ROUTING_MAP_PATH, JSON.stringify(routingMap, null, 2) + '\n', 'utf8'); +fs.writeFileSync(MEMORY_PATH, JSON.stringify(memory, null, 2) + '\n', 'utf8'); + +console.log(`✅ 铸渊大脑同步完成。覆盖率: ${implemented}/${total} (${memory.stats.coverage.percent})`); diff --git a/scripts/route-align-check.js b/scripts/route-align-check.js new file mode 100644 index 00000000..06ccfbfe --- /dev/null +++ b/scripts/route-align-check.js @@ -0,0 +1,64 @@ +// scripts/route-align-check.js +// 用途:检查路由路径与 HLI 注册表编号的一致性 + +const fs = require('fs'); +const path = require('path'); + +// HLI 路由路径映射(从 Notion 注册表同步) +const HLI_ROUTES = { + 'HLI-AUTH-001': '/hli/auth/login', + 'HLI-AUTH-002': '/hli/auth/register', + 'HLI-AUTH-003': '/hli/auth/verify', + 'HLI-PERSONA-001': '/hli/persona/load', + 'HLI-PERSONA-002': '/hli/persona/switch', + 'HLI-USER-001': '/hli/user/profile', + 'HLI-USER-002': '/hli/user/profile/update', + 'HLI-TICKET-001': '/hli/ticket/create', + 'HLI-TICKET-002': '/hli/ticket/query', + 'HLI-TICKET-003': '/hli/ticket/status', + 'HLI-DIALOGUE-001': '/hli/dialogue/send', + 'HLI-DIALOGUE-002': '/hli/dialogue/stream', + 'HLI-DIALOGUE-003': '/hli/dialogue/history', + 'HLI-STORAGE-001': '/hli/storage/upload', + 'HLI-STORAGE-002': '/hli/storage/download', + 'HLI-DASHBOARD-001': '/hli/dashboard/status', + 'HLI-DASHBOARD-002': '/hli/dashboard/realtime', +}; + +const schemaDir = 'src/schemas/hli'; +const errors = []; + +Object.entries(HLI_ROUTES).forEach(([hliId, expectedPath]) => { + const domain = hliId.split('-')[1].toLowerCase(); + const domainDir = path.join(schemaDir, domain); + + // 若 domain 目录尚不存在,视为未实现 + if (!fs.existsSync(domainDir)) { + errors.push(`⚠️ [UNIMPLEMENTED] ${hliId} (${expectedPath}) — 尚无 schema 文件`); + return; + } + + const schemaFiles = fs.readdirSync(domainDir).filter(f => f.endsWith('.schema.json')); + + const matched = schemaFiles.find(f => { + try { + const schema = JSON.parse(fs.readFileSync(path.join(domainDir, f), 'utf8')); + return schema.hli_id === hliId; + } catch (_) { + return false; + } + }); + + if (!matched) { + errors.push(`⚠️ [UNIMPLEMENTED] ${hliId} (${expectedPath}) — 尚无 schema 文件`); + } +}); + +if (errors.length > 0) { + console.warn('\n⚠️ Route Alignment Report:\n'); + errors.forEach(e => console.warn(e)); + // 非阻断,仅报告 + console.warn(`\n📊 覆盖率: ${Object.keys(HLI_ROUTES).length - errors.length}/${Object.keys(HLI_ROUTES).length}`); +} else { + console.log('✅ Route Alignment PASSED — 所有 HLI 接口均已实现'); +} diff --git a/scripts/update-memory.js b/scripts/update-memory.js new file mode 100644 index 00000000..8cf4d924 --- /dev/null +++ b/scripts/update-memory.js @@ -0,0 +1,46 @@ +// scripts/update-memory.js +// 用途:CI 完成后更新 memory.json 统计数据和事件日志 + +const fs = require('fs'); +const path = require('path'); + +const MEMORY_PATH = path.join(__dirname, '../.github/brain/memory.json'); + +const memory = JSON.parse(fs.readFileSync(MEMORY_PATH, 'utf8')); + +const eventType = process.env.MEMORY_EVENT_TYPE || 'ci_run'; +const result = process.env.MEMORY_EVENT_RESULT || 'unknown'; +const prNumber = process.env.MEMORY_PR_NUMBER || null; +const ref = process.env.GITHUB_REF || ''; +const actor = process.env.GITHUB_ACTOR || 'unknown'; +const runId = process.env.GITHUB_RUN_ID || null; + +const event = { + timestamp: new Date().toISOString(), + type: eventType, + result, + actor, + ref, +}; + +if (prNumber) event.pr_number = prNumber; +if (runId) event.run_id = runId; + +// 更新计数器 +if (eventType === 'ci_run') { + memory.stats.ci_runs = (memory.stats.ci_runs || 0) + 1; +} else if (eventType === 'pr_review') { + memory.stats.pr_reviews = (memory.stats.pr_reviews || 0) + 1; +} + +// 保留最近 100 条事件 +memory.events.push(event); +if (memory.events.length > 100) { + memory.events = memory.events.slice(-100); +} + +memory.last_updated = new Date().toISOString(); + +fs.writeFileSync(MEMORY_PATH, JSON.stringify(memory, null, 2) + '\n', 'utf8'); + +console.log(`✅ memory.json 已更新 · 事件: ${eventType}(${result}) · CI总次数: ${memory.stats.ci_runs} · PR审核次数: ${memory.stats.pr_reviews}`); diff --git a/scripts/zhuyuan-daily-selfcheck.js b/scripts/zhuyuan-daily-selfcheck.js new file mode 100644 index 00000000..9d1ec6ed --- /dev/null +++ b/scripts/zhuyuan-daily-selfcheck.js @@ -0,0 +1,77 @@ +const fs = require('fs'); +const path = require('path'); + +// === 最多保留的最近事件条数 === +const MAX_RECENT_EVENTS = 50; + +const BRAIN_DIR = '.github/persona-brain'; + +let memory, kb, journal; +try { + memory = JSON.parse(fs.readFileSync(path.join(BRAIN_DIR, 'memory.json'), 'utf8')); + kb = JSON.parse(fs.readFileSync(path.join(BRAIN_DIR, 'knowledge-base.json'), 'utf8')); + journal = fs.readFileSync(path.join(BRAIN_DIR, 'growth-journal.md'), 'utf8'); +} catch (err) { + console.error('❌ 铸渊大脑文件读取失败:', err.message); + process.exit(1); +} + +const today = new Date().toISOString().split('T')[0]; +console.log(`🔍 铸渊每日自检开始 · ${today}`); + +// === ① 大脑文件完整性检查 === +const requiredFiles = [ + 'identity.md', 'memory.json', 'routing-map.json', + 'responsibility.md', 'decision-log.md', 'growth-journal.md', + 'dev-status.json', 'knowledge-base.json' +]; +const missing = requiredFiles.filter(f => !fs.existsSync(path.join(BRAIN_DIR, f))); +if (missing.length > 0) { + console.error('⚠️ 缺失文件:' + missing.join(', ')); +} else { + console.log('✅ 大脑文件完整性:全部就绪'); +} + +// === ② 知识库去重与整理 === +const seen = new Set(); +const uniqueFaq = kb.faq.filter(item => { + const key = item.q.toLowerCase().trim(); + if (seen.has(key)) return false; + seen.add(key); + return true; +}); +if (uniqueFaq.length < kb.faq.length) { + console.log(`🧹 知识库去重:${kb.faq.length} → ${uniqueFaq.length}`); + kb.faq = uniqueFaq; +} +kb.last_updated = today; +fs.writeFileSync(path.join(BRAIN_DIR, 'knowledge-base.json'), JSON.stringify(kb, null, 2)); + +// === ③ 记忆整理(只保留最近50条事件) === +if (memory.recent_events && memory.recent_events.length > MAX_RECENT_EVENTS) { + memory.recent_events = memory.recent_events.slice(0, MAX_RECENT_EVENTS); + console.log(`🧹 记忆整理:截断到${MAX_RECENT_EVENTS}条最近事件`); +} +memory.last_updated = new Date().toISOString(); +memory.total_selfchecks = (memory.total_selfchecks || 0) + 1; + +if (!memory.recent_events) memory.recent_events = []; +memory.recent_events.unshift({ + date: today, + type: 'daily_selfcheck', + description: `每日自检完成 · 知识库${uniqueFaq.length}条 · 缺失文件${missing.length}个`, + by: '铸渊自检' +}); +fs.writeFileSync(path.join(BRAIN_DIR, 'memory.json'), JSON.stringify(memory, null, 2)); + +// === ④ 成长日记追加 === +const newEntry = `\n## ${today} · 每日自检\n` + + `- 大脑文件完整性:${missing.length === 0 ? '✅' : '⚠️ 缺失 ' + missing.join(', ')}\n` + + `- 知识库条目:${uniqueFaq.length}条\n` + + `- 累计自检次数:${memory.total_selfchecks}\n` + + `- 累计CI运行:${memory.total_ci_runs || 0}次\n` + + `- HLI覆盖率:${memory.hli_coverage || '未知'}\n`; +fs.writeFileSync(path.join(BRAIN_DIR, 'growth-journal.md'), journal + newEntry); + +console.log(`\n🔍 铸渊每日自检完成 · ${today}`); +console.log(`📊 知识库:${uniqueFaq.length}条 · 自检次数:${memory.total_selfchecks}`); diff --git a/scripts/zhuyuan-issue-reply.js b/scripts/zhuyuan-issue-reply.js new file mode 100644 index 00000000..f0307bb1 --- /dev/null +++ b/scripts/zhuyuan-issue-reply.js @@ -0,0 +1,218 @@ +const fs = require('fs'); +const https = require('https'); + +// === 知识库匹配阈值:问题词中至少40%出现在Issue文本中才算命中 === +const FAQ_MATCH_THRESHOLD = 0.4; + +// === 读取铸渊大脑 === +let devStatus, knowledgeBase; +try { + devStatus = JSON.parse(fs.readFileSync('.github/persona-brain/dev-status.json', 'utf8')); + knowledgeBase = JSON.parse(fs.readFileSync('.github/persona-brain/knowledge-base.json', 'utf8')); +} catch (err) { + console.error('❌ 铸渊大脑文件读取失败:', err.message); + process.exit(1); +} + +const issueNumber = process.env.ISSUE_NUMBER; +const issueTitle = process.env.ISSUE_TITLE || ''; +const issueBody = process.env.ISSUE_BODY || ''; +const issueLabels = process.env.ISSUE_LABELS || ''; + +// === 判断Issue类型 === +const isProgressQuery = issueLabels.includes('progress-query'); +const isDevQuestion = issueLabels.includes('dev-question'); + +// === 提取开发者编号 === +const devIdMatch = issueBody.match(/DEV-\d{3}/i); +const devId = devIdMatch ? devIdMatch[0].toUpperCase() : null; +const devInfo = devId ? devStatus.team_status.find(d => d.dev_id === devId) : null; + +// === 构建回复 === +async function generateReply() { + let reply = ''; + + // --- 进度查询(指定开发者)--- + if (isProgressQuery && devInfo) { + reply = `## ⚒️ 铸渊回复 · 进度查询\n\n`; + reply += `**${devInfo.name}(${devInfo.dev_id})当前状态:**\n`; + reply += `- 📌 模块:${devInfo.modules.join('、')}\n`; + reply += `- 📊 状态:${devInfo.status}\n`; + reply += `- ⏳ 等待中:${devInfo.waiting_for}\n`; + reply += `- 👉 下一步:${devInfo.next_step}\n`; + reply += `- 💻 环境:${devInfo.os}\n\n`; + reply += `---\n*数据来源:Notion主控台 · 最后同步时间 ${devStatus.last_synced}*\n`; + reply += `*—— 铸渊(ICE-GL-ZY001)*`; + await postComment(reply); + await addLabel('✅answered'); + await removeLabel('pending'); + return; + } + + // --- 进度查询(团队整体)--- + if (isProgressQuery && !devId) { + reply = `## ⚒️ 铸渊回复 · 团队进度总览\n\n`; + devStatus.team_status.forEach(dev => { + reply += `**${dev.dev_id} ${dev.name}** · ${dev.status}\n`; + }); + reply += `\n---\n*最后同步:${devStatus.last_synced}*\n`; + reply += `*—— 铸渊(ICE-GL-ZY001)*`; + await postComment(reply); + await addLabel('✅answered'); + await removeLabel('pending'); + return; + } + + // --- 技术问题:先查知识库 --- + if (isDevQuestion) { + const matchedFaq = findInKnowledgeBase(issueTitle + ' ' + issueBody); + + if (matchedFaq) { + reply = `## ⚒️ 铸渊回复\n\n`; + reply += `${matchedFaq.a}\n\n`; + if (matchedFaq.related_broadcast !== '通用') { + reply += `📡 相关广播:${matchedFaq.related_broadcast}\n\n`; + } + reply += `---\n*如果这没解决你的问题,继续在下面留言,霜砚会在下次巡检时补充回答。*\n`; + reply += `*—— 铸渊(ICE-GL-ZY001)*`; + await postComment(reply); + await addLabel('✅answered'); + await removeLabel('pending'); + return; + } + + // --- 知识库没有 → 调用云雾API --- + const aiReply = await callYunwuAPI(issueTitle, issueBody, devInfo); + if (aiReply) { + reply = `## ⚒️ 铸渊回复\n\n`; + reply += `${aiReply}\n\n`; + if (devInfo) { + reply += `📌 你当前在做:${devInfo.modules.join('、')} · ${devInfo.status}\n`; + } + reply += `\n---\n*AI生成回答,如有不准确请在下面补充,霜砚巡检时会修正。*\n`; + reply += `*—— 铸渊(ICE-GL-ZY001)*`; + await postComment(reply); + await addLabel('✅answered'); + await removeLabel('pending'); + return; + } + + // --- API也答不了 → 等霜砚 --- + reply = `## ⚒️ 铸渊收到\n\n`; + reply += `这个问题我需要查更多资料。已标记为待处理,霜砚会在下次巡检时来回答你。\n\n`; + if (devInfo) { + const routing = devStatus.tech_routing.level_2_peer_help; + reply += `💡 **临时建议**:你也可以先问问同伴开发者:\n`; + Object.entries(routing).forEach(([area, who]) => { + reply += `- ${area}:${who}\n`; + }); + } + reply += `\n---\n*霜砚巡检时间:每天 12:00 和 23:00(北京时间)*\n`; + reply += `*—— 铸渊(ICE-GL-ZY001)*`; + await postComment(reply); + await addLabel('⏳waiting-shuangyan'); + await removeLabel('pending'); + return; + } + + // --- 其他类型 --- + reply = `## ⚒️ 铸渊收到\n\n已记录。霜砚会在下次巡检时处理。\n\n*—— 铸渊(ICE-GL-ZY001)*`; + await postComment(reply); + await addLabel('⏳waiting-shuangyan'); +} + +// === 知识库模糊匹配 === +function findInKnowledgeBase(text) { + const keywords = text.toLowerCase(); + for (const faq of knowledgeBase.faq) { + const qWords = faq.q.toLowerCase().split(/\s+/); + const matchCount = qWords.filter(w => keywords.includes(w)).length; + if (matchCount >= qWords.length * FAQ_MATCH_THRESHOLD) return faq; + } + return null; +} + +// === 调用云雾API === +async function callYunwuAPI(title, body, devInfo) { + const apiKey = process.env.YUNWU_API_KEY; + if (!apiKey) return null; + + const systemPrompt = `你是铸渊,光湖系统的GitHub代码守护人格体。你负责回答开发者的技术问题。\n当前开发者信息:${devInfo ? JSON.stringify(devInfo) : '未知'}\n服务器信息:${JSON.stringify(devStatus.server_info)}\n请用简洁、友好的语气回答,给出可直接执行的命令。如果不确定,说明并建议找谁。`; + + const data = JSON.stringify({ + model: 'deepseek-chat', + messages: [ + { role: 'system', content: systemPrompt }, + { role: 'user', content: `问题标题:${title}\n问题内容:${body}` } + ], + max_tokens: 1000 + }); + + return new Promise((resolve) => { + const req = https.request({ + hostname: 'api.yunwu.ai', + path: '/v1/chat/completions', + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${apiKey}` + } + }, (res) => { + let responseBody = ''; + res.on('data', chunk => { responseBody += chunk; }); + res.on('end', () => { + try { + const json = JSON.parse(responseBody); + resolve(json.choices?.[0]?.message?.content || null); + } catch { resolve(null); } + }); + }); + req.on('error', () => resolve(null)); + req.write(data); + req.end(); + }); +} + +// === GitHub API 工具函数 === +async function postComment(body) { + const [owner, repo] = process.env.GITHUB_REPOSITORY.split('/'); + return githubRequest('POST', `/repos/${owner}/${repo}/issues/${issueNumber}/comments`, { body }); +} + +async function addLabel(label) { + const [owner, repo] = process.env.GITHUB_REPOSITORY.split('/'); + return githubRequest('POST', `/repos/${owner}/${repo}/issues/${issueNumber}/labels`, { labels: [label] }); +} + +async function removeLabel(label) { + const [owner, repo] = process.env.GITHUB_REPOSITORY.split('/'); + // 404 means label wasn't on the issue — that's fine, just ignore it + return githubRequest('DELETE', `/repos/${owner}/${repo}/issues/${issueNumber}/labels/${encodeURIComponent(label)}`).catch(() => null); +} + +function githubRequest(method, path, data) { + return new Promise((resolve) => { + const reqOptions = { + hostname: 'api.github.com', + path: path, + method: method, + headers: { + 'Authorization': `Bearer ${process.env.GITHUB_TOKEN}`, + 'Accept': 'application/vnd.github.v3+json', + 'User-Agent': 'Zhuyuan-Bot', + 'Content-Type': 'application/json' + } + }; + const req = https.request(reqOptions, (res) => { + let responseBody = ''; + res.on('data', chunk => { responseBody += chunk; }); + res.on('end', () => resolve(responseBody)); + }); + req.on('error', () => resolve(null)); + if (data) req.write(JSON.stringify(data)); + req.end(); + }); +} + +// === 执行 === +generateReply().catch(console.error); diff --git a/src/index.js b/src/index.js new file mode 100644 index 00000000..1d12f0dc --- /dev/null +++ b/src/index.js @@ -0,0 +1,25 @@ +// src/index.js +// HoloLake (光湖) 后端服务入口 + +const express = require('express'); +const app = express(); + +const PORT = process.env.PORT || 3000; +const NODE_ENV = process.env.NODE_ENV || 'development'; + +app.use(express.json()); + +// 健康检查(CI smoke test 依赖此端点) +app.get('/health', (req, res) => { + res.json({ status: 'ok', env: NODE_ENV, timestamp: new Date().toISOString() }); +}); + +// HLI 路由挂载 +const hliRouter = require('./routes/hli'); +app.use('/hli', hliRouter); + +app.listen(PORT, () => { + console.log(`[HoloLake] Server running on port ${PORT} (${NODE_ENV})`); +}); + +module.exports = app; diff --git a/src/middleware/hli-auth.middleware.js b/src/middleware/hli-auth.middleware.js new file mode 100644 index 00000000..8f95eef9 --- /dev/null +++ b/src/middleware/hli-auth.middleware.js @@ -0,0 +1,29 @@ +// src/middleware/hli-auth.middleware.js +// HLI 鉴权中间件:验证请求携带有效 token + +module.exports = function hliAuth(req, res, next) { + const authHeader = req.headers['authorization']; + + if (!authHeader || !authHeader.startsWith('Bearer ')) { + return res.status(401).json({ + error: true, + code: 'AUTH_TOKEN_MISSING', + message: '请求缺少 Authorization Bearer token', + }); + } + + const token = authHeader.slice(7); + + // TODO: 实现真实的 token 校验逻辑(JWT 验证或数据库查询) + if (!token) { + return res.status(401).json({ + error: true, + code: 'AUTH_TOKEN_INVALID', + message: 'token 无效', + }); + } + + // 将用户信息挂载到 req 供后续中间件使用 + req.hliUser = { token }; + next(); +}; diff --git a/src/middleware/hli-validator.middleware.js b/src/middleware/hli-validator.middleware.js new file mode 100644 index 00000000..b896158d --- /dev/null +++ b/src/middleware/hli-validator.middleware.js @@ -0,0 +1,44 @@ +// src/middleware/hli-validator.middleware.js +// HLI Schema 自动校验中间件:根据路由自动加载对应 schema 校验请求体 + +const fs = require('fs'); +const path = require('path'); + +module.exports = function hliValidator(req, res, next) { + // 从路径中解析 domain 和 action,例如 /hli/auth/login → auth/login + const match = req.path.match(/^\/hli\/([^/]+)\/([^/]+)/); + if (!match) return next(); + + const [, domain, action] = match; + const schemaPath = path.join( + __dirname, + '../schemas/hli', + domain, + `${action}.schema.json` + ); + + if (!fs.existsSync(schemaPath)) return next(); + + let schema; + try { + schema = JSON.parse(fs.readFileSync(schemaPath, 'utf8')); + } catch (_) { + return next(); + } + + // 简单必填字段校验(生产环境可替换为 ajv 等标准校验库) + const required = schema.input && schema.input.required; + if (required && req.method !== 'GET') { + for (const field of required) { + if (req.body[field] === undefined || req.body[field] === '') { + return res.status(400).json({ + error: true, + code: 'VALIDATION_ERROR', + message: `缺少必填字段: ${field}`, + }); + } + } + } + + next(); +}; diff --git a/src/routes/hli/auth/index.js b/src/routes/hli/auth/index.js new file mode 100644 index 00000000..8702c9e9 --- /dev/null +++ b/src/routes/hli/auth/index.js @@ -0,0 +1,15 @@ +// src/routes/hli/auth/index.js +// AUTH 域路由 + +const express = require('express'); +const router = express.Router(); + +const login = require('./login'); +const register = require('./register'); +const verify = require('./verify'); + +router.use('/login', login); +router.use('/register', register); +router.use('/verify', verify); + +module.exports = router; diff --git a/src/routes/hli/auth/login.js b/src/routes/hli/auth/login.js new file mode 100644 index 00000000..876a8fea --- /dev/null +++ b/src/routes/hli/auth/login.js @@ -0,0 +1,25 @@ +// src/routes/hli/auth/login.js +// HLI-AUTH-001: 用户登录 + +const express = require('express'); +const router = express.Router(); + +router.post('/', async (req, res) => { + try { + const { username, password } = req.body; + + // TODO: 实现登录逻辑(查询数据库,验证密码,生成 token) + + res.json({ + hli_id: 'HLI-AUTH-001', + token: '', + user_id: '', + persona_id: '', + expires_at: new Date().toISOString(), + }); + } catch (err) { + res.status(500).json({ error: true, code: 'AUTH_LOGIN_ERROR', message: err.message }); + } +}); + +module.exports = router; diff --git a/src/routes/hli/auth/register.js b/src/routes/hli/auth/register.js new file mode 100644 index 00000000..6da94c9e --- /dev/null +++ b/src/routes/hli/auth/register.js @@ -0,0 +1,23 @@ +// src/routes/hli/auth/register.js +// HLI-AUTH-002: 用户注册 + +const express = require('express'); +const router = express.Router(); + +router.post('/', async (req, res) => { + try { + const { username, password, email } = req.body; + + // TODO: 实现注册逻辑(检查重复,写入数据库) + + res.json({ + hli_id: 'HLI-AUTH-002', + user_id: '', + created_at: new Date().toISOString(), + }); + } catch (err) { + res.status(500).json({ error: true, code: 'AUTH_REGISTER_ERROR', message: err.message }); + } +}); + +module.exports = router; diff --git a/src/routes/hli/auth/verify.js b/src/routes/hli/auth/verify.js new file mode 100644 index 00000000..bbd18e18 --- /dev/null +++ b/src/routes/hli/auth/verify.js @@ -0,0 +1,25 @@ +// src/routes/hli/auth/verify.js +// HLI-AUTH-003: Token 验证 + +const express = require('express'); +const router = express.Router(); + +router.post('/', async (req, res) => { + try { + const { token } = req.body; + + // TODO: 实现 token 验证逻辑 + + res.json({ + hli_id: 'HLI-AUTH-003', + valid: false, + user_id: '', + persona_id: '', + expires_at: new Date().toISOString(), + }); + } catch (err) { + res.status(500).json({ error: true, code: 'AUTH_VERIFY_ERROR', message: err.message }); + } +}); + +module.exports = router; diff --git a/src/routes/hli/index.js b/src/routes/hli/index.js new file mode 100644 index 00000000..66797833 --- /dev/null +++ b/src/routes/hli/index.js @@ -0,0 +1,40 @@ +// src/routes/hli/index.js +// HLI 路由注册中心 + +const express = require('express'); +const router = express.Router(); + +// AUTH 域(不需要鉴权) +const authRouter = require('./auth'); +router.use('/auth', authRouter); + +// 以下域需要 HLI 鉴权中间件 +const hliAuth = require('../../middleware/hli-auth.middleware'); + +router.use(hliAuth); + +// PERSONA 域 +// const personaRouter = require('./persona'); +// router.use('/persona', personaRouter); + +// USER 域 +// const userRouter = require('./user'); +// router.use('/user', userRouter); + +// TICKET 域 +// const ticketRouter = require('./ticket'); +// router.use('/ticket', ticketRouter); + +// DIALOGUE 域 +// const dialogueRouter = require('./dialogue'); +// router.use('/dialogue', dialogueRouter); + +// STORAGE 域 +// const storageRouter = require('./storage'); +// router.use('/storage', storageRouter); + +// DASHBOARD 域 +// const dashboardRouter = require('./dashboard'); +// router.use('/dashboard', dashboardRouter); + +module.exports = router; diff --git a/src/schemas/hli/auth/login.schema.json b/src/schemas/hli/auth/login.schema.json new file mode 100644 index 00000000..b4f51f58 --- /dev/null +++ b/src/schemas/hli/auth/login.schema.json @@ -0,0 +1,29 @@ +{ + "hli_id": "HLI-AUTH-001", + "version": "v0.1", + "route": "/hli/auth/login", + "method": "POST", + "type": "REQUEST", + "input": { + "type": "object", + "required": ["username", "password"], + "properties": { + "username": { "type": "string", "minLength": 1 }, + "password": { "type": "string", "minLength": 6 } + } + }, + "output": { + "type": "object", + "required": ["token", "user_id", "persona_id"], + "properties": { + "token": { "type": "string" }, + "user_id": { "type": "string" }, + "persona_id": { "type": "string" }, + "expires_at": { "type": "string", "format": "date-time" } + } + }, + "dependencies": [], + "changelog": [ + { "date": "2026-03-05", "note": "初始创建" } + ] +} diff --git a/src/schemas/hli/auth/register.schema.json b/src/schemas/hli/auth/register.schema.json new file mode 100644 index 00000000..464f878f --- /dev/null +++ b/src/schemas/hli/auth/register.schema.json @@ -0,0 +1,28 @@ +{ + "hli_id": "HLI-AUTH-002", + "version": "v0.1", + "route": "/hli/auth/register", + "method": "POST", + "type": "REQUEST", + "input": { + "type": "object", + "required": ["username", "password", "email"], + "properties": { + "username": { "type": "string", "minLength": 1 }, + "password": { "type": "string", "minLength": 6 }, + "email": { "type": "string", "format": "email" } + } + }, + "output": { + "type": "object", + "required": ["user_id"], + "properties": { + "user_id": { "type": "string" }, + "created_at": { "type": "string", "format": "date-time" } + } + }, + "dependencies": [], + "changelog": [ + { "date": "2026-03-05", "note": "初始创建" } + ] +} diff --git a/src/schemas/hli/auth/verify.schema.json b/src/schemas/hli/auth/verify.schema.json new file mode 100644 index 00000000..2d8a4994 --- /dev/null +++ b/src/schemas/hli/auth/verify.schema.json @@ -0,0 +1,28 @@ +{ + "hli_id": "HLI-AUTH-003", + "version": "v0.1", + "route": "/hli/auth/verify", + "method": "POST", + "type": "REQUEST", + "input": { + "type": "object", + "required": ["token"], + "properties": { + "token": { "type": "string" } + } + }, + "output": { + "type": "object", + "required": ["valid", "user_id"], + "properties": { + "valid": { "type": "boolean" }, + "user_id": { "type": "string" }, + "persona_id": { "type": "string" }, + "expires_at": { "type": "string", "format": "date-time" } + } + }, + "dependencies": ["HLI-AUTH-001"], + "changelog": [ + { "date": "2026-03-05", "note": "初始创建" } + ] +} diff --git a/tests/contract/.gitkeep b/tests/contract/.gitkeep new file mode 100644 index 00000000..ae44c973 --- /dev/null +++ b/tests/contract/.gitkeep @@ -0,0 +1,2 @@ +# 契约测试目录 +# 每新增 HLI 接口时,在此创建对应的 {action}.test.js diff --git a/tests/smoke/.gitkeep b/tests/smoke/.gitkeep new file mode 100644 index 00000000..c6a9c8a5 --- /dev/null +++ b/tests/smoke/.gitkeep @@ -0,0 +1,2 @@ +# 冒烟测试目录 +# 每新增 HLI 接口时,在此创建对应的冒烟测试